Add Asset Management app

Assets from purchase invoice lines, straight-line depreciation/amortization with salvage value, disposals, and [Asset Mgmt] sources in Batch GL Entries. Green third workspace with an app access guard.
This commit is contained in:
Thanakorn
2026-09-15 09:50:55 +07:00
parent 9512d440dd
commit c957280aa5
46 changed files with 4316 additions and 131 deletions
+70 -1
View File
@@ -4,6 +4,8 @@
require '../include_header.php';
$invoice_id = (int)($_GET['id'] ?? 0);
// Users with Asset Management can turn issued invoice lines into assets.
$pi_asset_access = in_array($_SESSION['login_app_access'] ?? 'wms', ['all', 'asset'], true);
?>
<body>
@@ -73,6 +75,30 @@
</div>
</div>
</div>
<!-- Assets created from this invoice (Asset Management) -->
<div class="card mt-5 d-none" id="asset_card">
<div class="card-body p-5">
<h2 class="fs-5 mb-4">
<span class="badge bg-success text-white me-2"><i class="ti ti-building-warehouse me-1"></i>Asset Management</span>
Assets from this invoice
</h2>
<div class="table-responsive">
<table class="table mb-0 table-hover">
<thead class="table-light">
<tr>
<th>Asset No.</th>
<th>Name</th>
<th class="text-end">Cost</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody id="asset_tbody"></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Right: Info + actions -->
@@ -160,6 +186,44 @@
var invoice_id = <?php echo $invoice_id; ?>;
var invoice_data = null;
var show_asset_actions = <?php echo $pi_asset_access ? 'true' : 'false'; ?>;
var ASSET_STATUS_BADGE = {
'0': '<span class="badge bg-secondary">Draft</span>',
'1': '<span class="badge bg-success">Active</span>',
'2': '<span class="badge bg-info text-white">Fully depreciated</span>',
'3': '<span class="badge bg-dark">Disposed</span>',
'4': '<span class="badge bg-light text-dark">Void</span>',
};
function load_invoice_assets() {
return ajax_request({
url: '<?php echo $server_url?>asset/api/engine/asset.php',
autoPrepare: true,
checkRequired: 0,
action: 'read',
queueLock: false,
noLoading: true,
noAlert: true,
data: { invoice_id: invoice_id },
onSuccess: function(res) {
var rows = res.output || [];
if (!rows.length) { $('#asset_card').addClass('d-none'); return; }
var html = '';
$.each(rows, function(i, a) {
html += `<tr>
<td>${escape_html(a.asset_number)}</td>
<td>${escape_html(a.asset_name)}</td>
<td class="text-end">${format_number(a.cost, 2)}</td>
<td>${ASSET_STATUS_BADGE[String(a.status)] || '—'}</td>
<td><a href="<?php echo $server_url?>asset/manage_asset.php?id=${a.id}"><i class="ti ti-eye fs-5"></i></a></td>
</tr>`;
});
$('#asset_tbody').html(html);
$('#asset_card').removeClass('d-none');
}
});
}
function doc_type_badge(doc_type) {
const map = {
@@ -245,10 +309,14 @@
}
// Items
var can_capitalize = show_asset_actions && inv.doc_type === 'purchase_invoice' && [1, 2].includes(parseInt(inv.status));
var tbody = '';
$.each(inv.items || [], function(i, item) {
var asset_link = can_capitalize
? `<div><a class="small link-success" href="<?php echo $server_url?>asset/manage_asset.php?invoice_id=${invoice_id}&item_id=${item.id}"><i class="ti ti-building-warehouse me-1"></i>Create asset</a></div>`
: '';
tbody += `<tr>
<td>${escape_html(item.product_name || item.product_sku)}</td>
<td>${escape_html(item.product_name || item.product_sku)}${asset_link}</td>
<td class="text-end">${format_number(item.quantity, 2)}</td>
<td class="text-end">${format_number(item.unit_price, 2)}</td>
<td class="text-end">${format_number(item.tax_rate, 2)}</td>
@@ -310,6 +378,7 @@
$('#btn_save_formula').prop('disabled', parseInt(inv.status) === 4);
set_mode(inv);
if (show_asset_actions && inv.doc_type === 'purchase_invoice') load_invoice_assets();
}
});
}