diff --git a/app/accounting/api/engine/get_gl_by_source.php b/app/accounting/api/engine/get_gl_by_source.php
new file mode 100644
index 0000000..b116304
--- /dev/null
+++ b/app/accounting/api/engine/get_gl_by_source.php
@@ -0,0 +1,34 @@
+getBySource($doc_type, $source_id);
+
+ if (!$entry) {
+ $answer['success'] = 1;
+ $answer['output'] = null;
+ exit(json_encode($answer));
+ }
+
+ $query = new GlQueryManager($pdo2, $company_id);
+ $detail = $query->getJournalDetail((int)$entry['id']);
+
+ $answer['success'] = 1;
+ $answer['output'] = $detail;
+} catch (Exception $e) {
+ $answer['message'] = $e->getMessage();
+}
+
+exit(json_encode($answer));
diff --git a/app/assets/utils/classes_ac/GlQueryManager.php b/app/assets/utils/classes_ac/GlQueryManager.php
index 3510a10..553dc42 100644
--- a/app/assets/utils/classes_ac/GlQueryManager.php
+++ b/app/assets/utils/classes_ac/GlQueryManager.php
@@ -201,7 +201,7 @@ class GlQueryManager
) AS product_mapping_missing"
: ", 0 AS product_mapping_missing";
- $where = ['i.company_id = :cid', 'i.doc_type = :doc_type', 'i.status != 4'];
+ $where = ['i.company_id = :cid', 'i.doc_type = :doc_type', 'i.status NOT IN (0, 4)'];
$params = [':cid' => $this->companyId, ':doc_type' => $doc_type, ':source_type' => $doc_type];
if ($date_from) { $where[] = 'i.issued_date >= :date_from'; $params[':date_from'] = $date_from; }
if ($date_to) { $where[] = 'i.issued_date <= :date_to'; $params[':date_to'] = $date_to; }
diff --git a/app/expense/purchase_invoice.php b/app/expense/purchase_invoice.php
index 46bec59..4bf0ecf 100644
--- a/app/expense/purchase_invoice.php
+++ b/app/expense/purchase_invoice.php
@@ -345,10 +345,16 @@
${inv.due_date ? format_date(inv.due_date) : '—'} |
${formula_name} |
${invoice_status_badge(inv.status, inv.due_date)} |
-
-
+ |
+
+
+
+
+
+
+
|
`;
});
@@ -387,10 +393,16 @@
${format_number(scn.grand_total, 2)} |
${formula_name} |
${invoice_status_badge(scn.status, null)} |
-
-
+ |
+
+
+
+
+
+
+
|
`;
});
@@ -410,7 +422,83 @@
await retrieve_invoices();
}
});
+
+ function delete_invoice(id, doc_number) {
+ bootbox.confirm({
+ message: 'Delete ' + escape_html(doc_number) + '?
This cannot be undone. The document number will be freed for reuse.',
+ buttons: {
+ confirm: { label: 'Delete', className: 'btn-danger' },
+ cancel: { label: 'Back', className: 'btn-secondary' }
+ },
+ callback: function(result) {
+ if (!result) return;
+ ajax_request({
+ url: server_url + 'order/api/engine/delete_invoice.php',
+ autoPrepare: true, checkRequired: 0, action: 'delete',
+ data: { id: id },
+ onSuccess: function() { retrieve_invoices(); }
+ });
+ }
+ });
+ }
+
+ var _GL_SOURCE_LABELS = { invoice:'Invoice', credit_note:'Credit Note', purchase_invoice:'Purchase Invoice', supplier_credit_note:'Supplier Credit Note', receipt:'Receipt', payment:'Payment', manual:'Manual', reversal:'Reversal' };
+ var _GL_SOURCE_BADGE = { invoice:'bg-success-subtle text-success', credit_note:'bg-warning-subtle text-warning', purchase_invoice:'bg-primary-subtle text-primary', supplier_credit_note:'bg-secondary-subtle text-secondary', receipt:'bg-info-subtle text-info', payment:'bg-danger-subtle text-danger', manual:'bg-dark-subtle text-dark', reversal:'bg-danger-subtle text-danger' };
+ function _gl_source_badge(t) { return '' + (_GL_SOURCE_LABELS[t]||t) + ''; }
+
+ function show_gl_modal(doc_type, source_id) {
+ $('#gl-modal-body').html('Loading…
');
+ $('#glModal').modal('show');
+ ajax_request({
+ url: server_url + 'accounting/api/engine/get_gl_by_source.php',
+ autoPrepare: true, checkRequired: 0, noLoading: true, action: 'read',
+ data: { doc_type: doc_type, source_id: source_id },
+ onSuccess: function(res) {
+ if (!res.output) { $('#gl-modal-body').html('No GL entry posted for this document.
'); return; }
+ var h = res.output.header, lines = res.output.lines || [];
+ var total_debit = 0, total_credit = 0, lines_html = '';
+ $.each(lines, function(i, l) {
+ total_debit += parseFloat(l.debit) || 0;
+ total_credit += parseFloat(l.credit) || 0;
+ var dept = l.dept_code ? escape_html(l.dept_code + (l.dept_name ? ' - ' + l.dept_name : '')) : '—';
+ lines_html += '| ' + escape_html(l.account_code) + ' | ' + escape_html(l.account_name) + ' | ' + dept + ' | ' +
+ '' + (parseFloat(l.debit) ? format_number(l.debit, 2) : '—') + ' | ' +
+ '' + (parseFloat(l.credit) ? format_number(l.credit, 2) : '—') + ' | ' +
+ '' + escape_html(l.description || '—') + ' |
';
+ });
+ lines_html += '| Total | ' + format_number(total_debit, 2) + ' | ' + format_number(total_credit, 2) + ' | |
';
+ var balanced = Math.abs(total_debit - total_credit) < 0.01;
+ var bal_badge = balanced ? 'Balanced' : 'Unbalanced';
+ $('#gl-modal-body').html(
+ '' +
+ '
Source
' + _gl_source_badge(h.source_type) + '
' +
+ '
Period
' + escape_html(h.period) + '
' +
+ '
Formula
' + escape_html(h.formula_name || '—') + '
' +
+ '
Posted At
' + escape_html(h.posted_at) + '
' +
+ '
Updated At
' + escape_html(h.updated_at_fmt) + '
' +
+ '
Journal Lines' + bal_badge + '
' +
+ '| Account Code | Account Name | Department | Debit | Credit | Description |
' + lines_html + '
'
+ );
+ }
+ });
+ }
+
+
+