Files
wms-app/app/order/api/engine/issue_invoice.php
T
Thanakorn SandClaude Sonnet 4.6 b8798bc02d Wire targeted toast notifications to document status transitions
Adds emit_notification_user() to 7 endpoints so the acting user and
all admins/owners receive a real-time toast on key document actions:
confirm/cancel order, issue/void invoice, confirm return, confirm PO,
receive PO goods. Other staff and viewers are not notified.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:44:55 +07:00

83 lines
3.5 KiB
PHP

<?php
session_start();
require_once '../../../assets/utils/db_auth.php';
require_role($user_role, ['owner', 'admin', 'staff']);
require_once '../../../assets/utils/classes/InvoiceManager.php';
$id = (int)($data['id'] ?? ($data['invoice_id'] ?? 0));
$due_date = trim((string)($data['due_date'] ?? ''));
if (!$id) {
$answer['message'] = 'Invalid ID.';
http_response_code(400);
exit(json_encode($answer));
}
$posting_map = [
'invoice' => 'InvoicePosting',
'credit_note' => 'CreditNotePosting',
'purchase_invoice' => 'PurchaseInvoicePosting',
'supplier_credit_note' => 'SupplierCreditNotePosting',
];
try {
dbTransaction($pdo2, function($pdo) use ($id, $due_date, $company_id, $logging) {
$inv = new InvoiceManager($pdo, $company_id);
$inv->issueInvoice($id, $logging, $due_date ?: null);
});
$answer['success'] = 1;
$answer['message'] = 'Invoice issued.';
require_once '../../../assets/utils/notify_node.php';
emit_notification_user($company_id, $user_id, 'Invoice Issued', 'The invoice has been issued.', 'success');
// Auto-post GL for this document
$sth = $pdo2->prepare("SELECT doc_type, formula_id FROM td_invoice WHERE company_id = :cid AND id = :id LIMIT 1");
$sth->execute([':cid' => $company_id, ':id' => $id]);
$doc = $sth->fetch(PDO::FETCH_ASSOC);
if ($doc && isset($posting_map[$doc['doc_type']])) {
try {
$class_name = $posting_map[$doc['doc_type']];
require_once '../../../assets/utils/classes_ac/posting/BasePosting.php';
require_once '../../../assets/utils/classes_ac/posting/' . $class_name . '.php';
require_once '../../../assets/utils/notify_node.php';
$posting = new $class_name($pdo2, $company_id);
$built = $posting->build($id, $doc['formula_id'] ?: null);
$guard = new PostingWindowGuard($pdo1, $company_id);
$gl = new GlManager($pdo2, $company_id, $guard);
$meta = ['journal_date' => $built['doc_date'] ?? null];
$existing = $gl->getBySource($doc['doc_type'], $id);
$pdo2->beginTransaction();
if ($existing) {
$gl->replace($doc['doc_type'], $id, $built['formula_id'], $built['period'], $built['lines'], $meta);
} else {
$gl->post($doc['doc_type'], $id, $built['formula_id'], $built['period'], $built['lines'], $meta);
}
$pdo2->commit();
notify_node('gl_posted', gl_posted_payload((string)$doc['doc_type'], (int)$id, $existing ? 'replaced' : 'posted', $built['lines'] ?? []), $company_id);
$answer['gl_posted'] = true;
} catch (Exception $e) {
if ($pdo2->inTransaction()) $pdo2->rollBack();
$answer['gl_posted'] = false;
$answer['gl_message'] = $e->getMessage();
error_log("auto_gl [{$doc['doc_type']}#{$id}]: " . $e->getMessage());
}
}
} catch (PDOException $e) {
$answer['message'] = 'Database error, please try again.';
http_response_code(500);
} catch (Exception $e) {
$answer['message'] = $e->getMessage();
http_response_code(400);
}
exit(json_encode($answer));
?>