Lot, Serial, ExpiryDate

This commit is contained in:
Thanakorn S
2026-04-25 14:37:00 +07:00
parent 92d116fd21
commit 3cc5baba3f
35 changed files with 3518 additions and 1890 deletions
+94 -2
View File
@@ -44,7 +44,23 @@
<input type="number" class="form-control" id="quantity" placeholder="Enter quantity" required>
</div>
<!-- Lot Number -->
<div class="mb-3 col-lg-6">
<label for="lot_number" class="form-label">Lot Number <span class="text-muted fw-normal">(optional)</span></label>
<input type="text" class="form-control lot_search" id="lot_number" placeholder="Type to search or enter new lot..." autocomplete="off">
</div>
<!-- Expiry Date (only relevant when lot_number is set) -->
<div class="mb-3 col-lg-6">
<label for="expiry_date" class="form-label">Expiry Date <span class="text-muted fw-normal">(optional)</span></label>
<input type="text" class="form-control" id="expiry_date" placeholder="DD/MM/YYYY" autocomplete="off">
</div>
<!-- Serial Number -->
<div class="mb-3 col-lg-6">
<label for="serial_number" class="form-label">Serial Number <span class="text-muted fw-normal">(optional)</span></label>
<input type="text" class="form-control" id="serial_number" placeholder="Enter serial number">
</div>
<!-- Warehouse -->
<div class="mb-3 col-lg-6">
@@ -79,7 +95,6 @@
<input type="text" class="form-control contact_search" id="contact" placeholder="Enter contact name">
</div>
<!-- Notes / Description -->
<div class="mb-3 col-lg-12">
<label for="description" class="form-label">Notes / Description</label>
@@ -111,7 +126,10 @@
checkRequired: 1,
debugMode: 0,
data: {
"contact_id": $("#contact").attr('data-id')
"contact_id": $("#contact").attr('data-id'),
"lot_number": $("#lot_number").val(),
"expiry_date": $("#expiry_date").val(),
"serial_number": $("#serial_number").val()
},
action: 'manage',
onSuccess: function(res) {
@@ -271,6 +289,16 @@
.attr('data-id', data.contact_id);
$('#product_name').val(data.product_name);
$('#lot_number').val(data.lot_number || '');
$('#serial_number').val(data.serial_number || '');
if (data.lot_number) {
if (expiryPicker) { expiryPicker.setDate(data.expiry_date || '', true, 'Y-m-d'); }
$('#expiry_date').prop('disabled', true).attr('title', 'Expiry date is locked for existing lots')
.val(data.expiry_date);
if (expiryPicker && expiryPicker.altInput) { expiryPicker.altInput.disabled = true; }
} else {
if (expiryPicker) { expiryPicker.clear(); }
}
$('#product_sku').attr('secondary', data.product_sku);
$('#product_sku,#quantity').prop('disabled', true);
@@ -291,16 +319,80 @@
}
// ── Prefill for restock flow (coming from low-stock-products.php) ────
function prefill_from_restock() {
var params = new URLSearchParams(window.location.search);
var sku = params.get('sku');
var name = params.get('name');
var qty = params.get('qty');
var wh = params.get('wh');
// Not a restock flow — nothing to prefill
if (!sku) return false;
// Product fields (locked — the point of restock is this specific SKU)
$('#product_sku')
.val(sku)
.attr('secondary', sku)
.prop('disabled', true);
$('#product_name')
.val(name || '')
.attr('secondary', name || '');
// already disabled in markup
// Suggested quantity (prefilled value only; user can still edit)
if (qty) {
$('#quantity').val(qty);
}
// Warehouse: lock it (can't restock to a different warehouse than the one that's low)
if (wh) {
$('#warehouse').val(wh).prop('disabled', true);
// Chain-load location selects for the locked warehouse.
// Unlike edit mode, we DON'T preselect zone/aisle/rack — the user picks.
retrieve_zone('to', function() {
retrieve_aisle('to', function() {
retrieve_rack('to');
});
});
}
return true;
}
$(async function() {
try {
await retrieve_warehouse('to');
await retrieve_for_edit();
<?php if(!empty($_GET["sku"])){ ?>
prefill_from_restock();
<?php } ?>
} catch (e) {
console.log(e);
}
});
// ── Flatpickr: display dd/mm/yyyy, send yyyy-mm-dd to API ──────────
var expiryPicker = flatpickr("#expiry_date", {
dateFormat: "Y-m-d", // actual value stored in input (sent to API)
altInput: true, // show a separate visible input
altFormat: "d/m/Y", // visible format: 28/04/2026
allowInput: true,
onReady: function(_, __, fp) {
// Apply Bootstrap form-control class to the alt input
fp.altInput.classList.add("form-control");
},
onChange: function(_, dateStr) {
// If lot is new (not existing), keep expiry_date unlocked
}
});
<?php if(empty($_GET["id"])){ ?>
$("select#warehouse").change(function() {
retrieve_zone('to');