cost/price/margin

This commit is contained in:
Thanakorn S
2026-05-06 09:37:28 +07:00
parent 6501d326ca
commit d8131a01b7
10 changed files with 130 additions and 27 deletions
+29 -4
View File
@@ -39,10 +39,21 @@
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<div class="col-md-3 mb-3">
<label for="price" class="form-label">Price</label>
<input type="number" class="form-control" id="price" placeholder="0.00" step="0.01" required>
</div>
<div class="col-md-2 mb-3">
<label for="cost_price" class="form-label">Cost Price <span class="text-muted fw-normal">(COGS)</span></label>
<input type="number" class="form-control" id="cost_price" placeholder="0.00" step="0.01" min="0">
</div>
<div class="col-md-2 mb-3">
<label class="form-label">Margin</label>
<div class="input-group">
<input type="text" class="form-control" id="margin_display" placeholder="—" disabled>
<span class="input-group-text">%</span>
</div>
</div>
<div class="col-md-2 mb-3">
<label for="uom" class="form-label">UOM</label>
<input type="text" class="form-control" id="uom" placeholder="pcs"
@@ -62,7 +73,7 @@
<option value="bottle">
</datalist>
</div>
<div class="col-md-3 mb-3">
<div class="col-md-2 mb-3">
<label for="min_stock" class="form-label">Min Stock</label>
<input type="number" class="form-control" id="min_stock" placeholder="0" min="0" required>
<div class="invalid-feedback" id="min_stock_error"></div>
@@ -138,6 +149,7 @@
}
formData.append('keep_files', $('#current_file_label').val())
formData.append('cost_price', $('#cost_price').val() || 0)
formData.append('uom', $('#uom').val() || 'pcs')
return ajax_request({
@@ -209,8 +221,8 @@
});
$(`button[type=submit]`).text('Update');
$(`button[type=reset]`).hide();
update_margin();
}
});
@@ -267,9 +279,22 @@
// Live feedback as the user types
$('#min_stock, #reorder_point').on('input', validate_stock_thresholds);
function update_margin() {
var price = parseFloat($('#price').val()) || 0;
var cost_price = parseFloat($('#cost_price').val()) || 0;
if (price > 0) {
var margin = (price - cost_price) / price * 100;
$('#margin_display').val(margin.toFixed(2));
} else {
$('#margin_display').val('');
}
}
$('#price, #cost_price').on('input', update_margin);
</script>
</body>
</html>
</html>
+15 -2
View File
@@ -197,6 +197,8 @@
<th width="75px"></th>
<th>Product</th>
<th>SKU</th>
<th style="text-align: right;">Price / Cost</th>
<th style="text-align: right;">Margin</th>
<th>UOM</th>
<th style="text-align: right;">Current Stock</th>
<th style="text-align: right;">Min Stock</th>
@@ -345,7 +347,7 @@
if (filtered.length === 0) {
$("table#product > tbody").html(
'<tr><td colspan="9" class="text-center py-5 text-muted">No products match your search.</td></tr>'
'<tr><td colspan="11" class="text-center py-5 text-muted">No products match your search.</td></tr>'
);
return;
}
@@ -362,6 +364,17 @@
</td>
<td class="py-3">${item['product_name']}</td>
<td class="py-3">${item['sku']}</td>
<td class="py-3 text-end">
<div>${format_number(item['price'], 2)}</div>
<small class="text-muted">${format_number(item['cost_price'], 2)}</small>
</td>
<td class="py-3 text-end">
${(item['price'] > 0 && item['cost_price'] > 0)
? `<span class="${((item['price'] - item['cost_price']) / item['price'] * 100) >= 0 ? 'text-success' : 'text-danger'} fw-semibold">
${format_number((item['price'] - item['cost_price']) / item['price'] * 100, 1)}%
</span>`
: '<span class="text-muted">—</span>'}
</td>
<td class="py-3"><span class="badge bg-light text-secondary border">${item['uom'] || 'pcs'}</span></td>
<td class="py-3">
<div class="d-flex justify-content-end align-items-baseline gap-1">
@@ -472,4 +485,4 @@
</body>
</html>
</html>