Seal live dashboard event gaps

This commit is contained in:
Thanakorn S
2026-05-25 17:02:52 +07:00
parent 3c9475f3fa
commit 5c0166ae73
13 changed files with 147 additions and 17 deletions
@@ -1,5 +1,8 @@
<?php
require_once __DIR__ . '/../db_helpers.php';
require_once __DIR__ . '/../notify_node.php';
/**
* StockManager
*
@@ -856,6 +859,11 @@ class StockManager {
(int)$inbound_row['id'], $inbound_row['source'] ?? '', (int)($inbound_row['source_id'] ?? 0), $inbound_row['date'] ?? '');
}
}
$notify_company_id = $this->company_id;
db_after_commit(function() use ($warehouse_id, $type, $notify_company_id) {
notify_node("stock_updated", ["warehouse_id" => $warehouse_id, "type" => $type], $notify_company_id);
});
}
}
+29 -2
View File
@@ -69,17 +69,43 @@ function db_check($sth, &$answer, $options = []) {
// Run a callback after the surrounding dbTransaction() commits. If no managed
// transaction is active, run immediately. Used for non-authoritative side effects
// such as live dashboard notifications.
function db_after_commit(callable $callback): void {
if (!isset($GLOBALS['_db_after_commit_stack']) || empty($GLOBALS['_db_after_commit_stack'])) {
$callback();
return;
}
$idx = count($GLOBALS['_db_after_commit_stack']) - 1;
$GLOBALS['_db_after_commit_stack'][$idx][] = $callback;
}
// transaction wrapper with retry logic for deadlocks
function dbTransaction($pdo, $callback, $maxRetries = 3) {
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
$GLOBALS['_db_after_commit_stack'][] = [];
try {
$pdo->beginTransaction();
$result = $callback($pdo);
$pdo->commit();
$callbacks = array_pop($GLOBALS['_db_after_commit_stack']);
foreach ($callbacks as $after_commit) {
try {
$after_commit();
} catch (Throwable $e) {
error_log("[AFTER COMMIT ERROR] " . $e->getMessage() . " | " . $e->getFile() . ":" . $e->getLine());
}
}
return $result;
} catch (PDOException $e) {
$pdo->rollBack();
if ($pdo->inTransaction()) $pdo->rollBack();
array_pop($GLOBALS['_db_after_commit_stack']);
if ($e->getCode() == '40001' && $attempt < $maxRetries - 1) {
usleep(600000 * ($attempt + 1));
@@ -90,7 +116,8 @@ function dbTransaction($pdo, $callback, $maxRetries = 3) {
throw $e;
} catch (Exception $e) {
$pdo->rollBack();
if ($pdo->inTransaction()) $pdo->rollBack();
array_pop($GLOBALS['_db_after_commit_stack']);
error_log("[ERROR] " . $e->getMessage() . " | " . $e->getFile() . ":" . $e->getLine());
throw $e;
}
+20
View File
@@ -34,3 +34,23 @@ function notify_node(string $event, array $data, int $company_id): void
curl_exec($ch);
curl_close($ch);
}
function gl_posted_payload(string $doc_type, int $id, string $action, array $lines): array
{
$has_revenue = false;
$has_expense = false;
foreach ($lines as $line) {
$code = (int)($line['account_code'] ?? 0);
if ($code >= 4000 && $code < 5000) $has_revenue = true;
if ($code >= 5000) $has_expense = true;
}
return [
'doc_type' => $doc_type,
'id' => $id,
'action' => $action,
'has_revenue' => $has_revenue,
'has_expense' => $has_expense,
];
}