fix(mobile): add auto-search on typing in stock audit and remove copyright footer

This commit is contained in:
DevSoftTech Server 2026-10-27 00:41:59 +05:30
parent c26b5bf01e
commit 40ce7b7a0f
2 changed files with 105 additions and 17 deletions

View File

@ -15979,11 +15979,15 @@ class Medical extends BaseController
$shelf = trim((string)($this->request->getGet('shelf') ?? ''));
$q = trim((string)($this->request->getGet('q') ?? ''));
if ($rack === '' && $shelf === '' && $q === '') {
return $this->response->setJSON(['status' => 1, 'items' => []]);
}
$builder = $this->db->table('purchase_invoice_item p');
$builder->select('
p.id AS batch_id,
p.item_code,
m.item_name,
COALESCE(NULLIF(m.item_name, ""), p.Item_name, "Medicine") AS item_name,
m.formulation,
p.packing,
p.batch_no,
@ -15994,11 +15998,15 @@ class Medical extends BaseController
p.selling_unit_rate,
IFNULL(NULLIF(p.rack_no, ""), m.rack_no) AS rack_no,
IFNULL(NULLIF(p.shelf_no, ""), m.shelf_no) AS shelf_no,
(p.total_unit - p.total_sale_unit + p.total_return_unit - p.total_lost_unit) AS system_qty
(IFNULL(p.total_unit, 0) - IFNULL(p.total_sale_unit, 0) + IFNULL(p.total_return_unit, 0) - IFNULL(p.total_lost_unit, 0)) AS system_qty
', false);
$builder->join('med_product_master m', 'm.id = p.item_code');
$builder->join('med_product_master m', 'm.id = p.item_code', 'left');
$builder->where('p.item_code >', 0);
if ($this->db->fieldExists('remove_item', 'purchase_invoice_item')) {
$builder->where('p.remove_item', 0);
}
if ($rack !== '') {
$builder->groupStart();
$builder->where('p.rack_no', $rack);
@ -16016,7 +16024,18 @@ class Medical extends BaseController
if ($q !== '') {
$builder->groupStart();
$builder->like('m.item_name', $q);
$builder->orLike('p.Item_name', $q);
$builder->orLike('p.batch_no', $q);
if ($this->db->fieldExists('genericname', 'med_product_master')) {
$builder->orLike('m.genericname', $q);
}
if (is_numeric($q)) {
$builder->orWhere('p.item_code', (int)$q);
$builder->orWhere('p.id', (int)$q);
}
if ($this->db->fieldExists('barcode', 'purchase_invoice_item')) {
$builder->orLike('p.barcode', $q);
}
$builder->groupEnd();
}

View File

@ -337,19 +337,24 @@
<div class="col-7">
<label class="form-label small fw-bold text-muted mb-0">Select / Type Rack</label>
<div class="input-group input-group-sm">
<input type="text" class="form-control form-control-sm" id="audit_rack_input" placeholder="e.g. Rack A" list="rack_datalist">
<input type="text" class="form-control form-control-sm" id="audit_rack_input" placeholder="e.g. Rack A" list="rack_datalist" autocomplete="off">
<datalist id="rack_datalist"></datalist>
<button class="btn btn-outline-secondary" type="button" onclick="clearAuditRack();" title="Clear Rack / Shelf"><i class="bi bi-x"></i></button>
</div>
</div>
<div class="col-5">
<label class="form-label small fw-bold text-muted mb-0">Shelf No.</label>
<input type="text" class="form-control form-control-sm" id="audit_shelf_input" placeholder="e.g. 1">
<input type="text" class="form-control form-control-sm" id="audit_shelf_input" placeholder="e.g. 1" autocomplete="off">
</div>
</div>
<div class="input-group input-group-sm mb-2">
<input type="text" class="form-control" id="audit_search_q" placeholder="Or search medicine / batch...">
<button class="btn btn-primary" type="button" onclick="loadAuditItems();">
<span class="input-group-text bg-white text-muted"><i class="bi bi-search"></i></span>
<input type="text" class="form-control" id="audit_search_q" placeholder="Search medicine name or batch no..." autocomplete="off">
<button class="btn btn-outline-secondary" type="button" id="btn_clear_audit_q" onclick="clearAuditSearch();" title="Clear Search" style="display:none;">
<i class="bi bi-x-lg"></i>
</button>
<button class="btn btn-primary" type="button" id="btn_audit_load" onclick="loadAuditItems();">
<i class="bi bi-arrow-clockwise"></i> Load
</button>
</div>
@ -360,7 +365,7 @@
<div id="audit_items_container">
<div class="text-center py-4 text-muted">
<i class="bi bi-boxes fs-1 text-secondary opacity-50 d-block mb-2"></i>
<span>Select a rack or click Load to start shelf counting.</span>
<span>Select a rack or type medicine/batch name to start shelf counting.</span>
</div>
</div>
@ -384,13 +389,6 @@
</div>
<!-- System & License Footer -->
<footer class="text-center py-3 mt-4 mb-4 text-muted" style="font-size: 11px; border-top: 1px solid #e2e8f0;">
&copy; 2017 - 2026 <strong><a href="https://www.e-atria.in" target="_blank" rel="noopener" class="text-decoration-none text-primary">E-Atria</a></strong>. All Rights Reserved |
<a href="<?= base_url('software-use-license.html') ?>" target="_blank" rel="noopener" class="text-decoration-none text-secondary">Software Use License</a> |
Version: <?= esc($footerVersion ?? '26.117') ?>
</footer>
</div>
<!-- Floating Bottom Bar for Basket -->
@ -899,13 +897,81 @@
}
loadRacksDatalist();
function clearAuditSearch() {
jQuery('#audit_search_q').val('').focus();
jQuery('#btn_clear_audit_q').hide();
loadAuditItems();
}
function clearAuditRack() {
jQuery('#audit_rack_input').val('');
jQuery('#audit_shelf_input').val('');
loadAuditItems();
}
var auditSearchTimer = null;
jQuery('#audit_search_q').on('input', function() {
clearTimeout(auditSearchTimer);
var q = jQuery(this).val().trim();
if (q.length > 0) {
jQuery('#btn_clear_audit_q').show();
} else {
jQuery('#btn_clear_audit_q').hide();
}
var rack = jQuery('#audit_rack_input').val().trim();
var shelf = jQuery('#audit_shelf_input').val().trim();
if (q.length === 0 && rack === '' && shelf === '') {
jQuery('#audit_items_container').html(
'<div class="text-center py-4 text-muted">' +
'<i class="bi bi-boxes fs-1 text-secondary opacity-50 d-block mb-2"></i>' +
'<span>Select a rack or type medicine/batch name to start shelf counting.</span>' +
'</div>'
);
return;
}
auditSearchTimer = setTimeout(loadAuditItems, 300);
});
jQuery('#audit_rack_input, #audit_shelf_input').on('change input', function() {
clearTimeout(auditSearchTimer);
auditSearchTimer = setTimeout(loadAuditItems, 350);
});
jQuery('#audit_search_q, #audit_rack_input, #audit_shelf_input').on('keydown', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
clearTimeout(auditSearchTimer);
loadAuditItems();
}
});
function loadAuditItems() {
var rack = jQuery('#audit_rack_input').val().trim();
var shelf = jQuery('#audit_shelf_input').val().trim();
var q = jQuery('#audit_search_q').val().trim();
if (q.length > 0) {
jQuery('#btn_clear_audit_q').show();
} else {
jQuery('#btn_clear_audit_q').hide();
}
var container = jQuery('#audit_items_container');
container.html('<div class="text-center py-4 text-muted"><div class="spinner-border spinner-border-sm text-primary"></div> Loading shelf batches...</div>');
if (q === '' && rack === '' && shelf === '') {
container.html(
'<div class="text-center py-4 text-muted">' +
'<i class="bi bi-boxes fs-1 text-secondary opacity-50 d-block mb-2"></i>' +
'<span>Select a rack or type medicine/batch name to start shelf counting.</span>' +
'</div>'
);
return;
}
container.html('<div class="text-center py-4 text-muted"><div class="spinner-border spinner-border-sm text-primary"></div> Searching shelf batches...</div>');
jQuery.ajax({
url: baseUrl + 'Medical/mobile_audit_items',
@ -914,7 +980,10 @@
dataType: 'json',
success: function(res) {
if (!res.items || res.items.length === 0) {
container.html('<div class="text-center py-4 text-muted"><i class="bi bi-inbox fs-3 d-block mb-1"></i> No batches found in this rack / shelf.</div>');
var notFoundMsg = q
? ('No medicines or batches found matching "' + escapeHtml(q) + '"' + (rack ? ' in rack ' + escapeHtml(rack) : '') + '.')
: ('No batches found in rack "' + escapeHtml(rack) + '"' + (shelf ? ' / shelf ' + escapeHtml(shelf) : '') + '.');
container.html('<div class="text-center py-4 text-muted"><i class="bi bi-inbox fs-3 d-block mb-1"></i> ' + notFoundMsg + '</div>');
return;
}