599 lines
27 KiB
PHP
599 lines
27 KiB
PHP
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h4 class="mb-0 text-primary fw-bold"><i class="bi bi-basket2 me-2"></i> <?php echo __('purchases'); ?></h4>
|
|
<button type="button" class="btn btn-primary" onclick="openCreatePurchaseModal()">
|
|
<i class="bi bi-plus-lg me-2"></i> <?php echo __('create_purchase'); ?>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="card shadow-sm border-0">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle" id="purchaseTable">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>#</th>
|
|
<th><?php echo __('purchase_date'); ?></th>
|
|
<th><?php echo __('supplier'); ?></th>
|
|
<th><?php echo __('total_amount'); ?></th>
|
|
<th><?php echo __('status'); ?></th>
|
|
<th><?php echo __('actions'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="purchaseTableBody">
|
|
<tr><td colspan="6" class="text-center py-4"><div class="spinner-border text-primary" role="status"></div></td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<!-- Pagination -->
|
|
<nav id="paginationContainer" class="mt-3" aria-label="Page navigation"></nav>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create Purchase Modal -->
|
|
<div class="modal fade" id="createPurchaseModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-xl">
|
|
<form id="createPurchaseForm" onsubmit="submitPurchase(event)">
|
|
<div class="modal-content border-0 shadow">
|
|
<div class="modal-header bg-primary text-white">
|
|
<h5 class="modal-title fw-bold"><i class="bi bi-plus-circle me-2"></i> <?php echo __('create_purchase'); ?></h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body bg-light">
|
|
<div class="card mb-3 border-0 shadow-sm">
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-bold"><?php echo __('supplier'); ?></label>
|
|
<select name="supplier_id" id="purchase_supplier_id" class="form-select select2-modal" required>
|
|
<option value=""><?php echo __('select_supplier'); ?>...</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label fw-bold"><?php echo __('purchase_date'); ?></label>
|
|
<input type="date" name="lpo_date" id="purchase_date" class="form-control" value="<?php echo date('Y-m-d'); ?>" required>
|
|
</div>
|
|
<div class="col-md-12">
|
|
<label class="form-label"><?php echo __('notes'); ?></label>
|
|
<textarea name="notes" id="purchase_notes" class="form-control" rows="2"></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-header bg-white py-3">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<h6 class="mb-0 fw-bold text-primary"><?php echo __('items'); ?></h6>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="addPurchaseItemRow()">
|
|
<i class="bi bi-plus-lg me-1"></i> <?php echo __('add_item'); ?>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered mb-0" id="purchaseItemsTable">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th style="width: 25%;"><?php echo __('drug_name'); ?></th>
|
|
<th style="width: 15%;"><?php echo __('batch_number'); ?></th>
|
|
<th style="width: 15%;"><?php echo __('expiry_date'); ?></th>
|
|
<th style="width: 10%;"><?php echo __('quantity'); ?></th>
|
|
<th style="width: 15%;"><?php echo __('cost_price'); ?></th>
|
|
<th style="width: 15%;"><?php echo __('total_cost'); ?></th>
|
|
<th style="width: 5%;"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="purchaseItemsBody">
|
|
<!-- Dynamic Rows -->
|
|
</tbody>
|
|
<tfoot class="table-light">
|
|
<tr>
|
|
<td colspan="5" class="text-end fw-bold"><?php echo __('total_amount'); ?>:</td>
|
|
<td class="fw-bold text-primary fs-5" id="purchaseTotalDisplay">0.00</td>
|
|
<td></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer bg-white">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('cancel'); ?></button>
|
|
<button type="submit" class="btn btn-primary px-4"><i class="bi bi-save me-2"></i> <?php echo __('save'); ?></button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Receive Purchase Modal -->
|
|
<div class="modal fade" id="receivePurchaseModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-xl">
|
|
<div class="modal-content border-0 shadow">
|
|
<div class="modal-header bg-success text-white">
|
|
<h5 class="modal-title fw-bold"><i class="bi bi-check-circle me-2"></i> <?php echo __('receive_purchase'); ?></h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body bg-light">
|
|
<div class="alert alert-warning">
|
|
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
|
<?php echo __('receive_warning_msg'); ?>
|
|
<?php echo __('ensure_batch_expiry_msg'); ?>
|
|
</div>
|
|
|
|
<input type="hidden" id="receive_purchase_id">
|
|
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th><?php echo __('drug_name'); ?></th>
|
|
<th><?php echo __('batch_number'); ?> <span class="text-danger">*</span></th>
|
|
<th><?php echo __('expiry_date'); ?> <span class="text-danger">*</span></th>
|
|
<th><?php echo __('quantity'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="receivePurchaseItemsBody"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer bg-white">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('cancel'); ?></button>
|
|
<button type="button" class="btn btn-success px-4" onclick="confirmReceivePurchase()"><i class="bi bi-box-seam me-2"></i> <?php echo __('confirm_received'); ?></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- View Purchase Modal -->
|
|
<div class="modal fade" id="viewPurchaseModal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content border-0 shadow">
|
|
<div class="modal-header bg-primary text-white">
|
|
<h5 class="modal-title fw-bold"><i class="bi bi-eye me-2"></i> <?php echo __('view_purchase'); ?> #<span id="view_purchase_id"></span></h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<p class="mb-1 text-muted small"><?php echo __('supplier'); ?></p>
|
|
<h6 class="fw-bold" id="view_purchase_supplier"></h6>
|
|
</div>
|
|
<div class="col-md-6 text-end">
|
|
<p class="mb-1 text-muted small"><?php echo __('date'); ?></p>
|
|
<h6 class="fw-bold" id="view_purchase_date"></h6>
|
|
<span class="badge bg-secondary" id="view_purchase_status"></span>
|
|
</div>
|
|
</div>
|
|
|
|
<h6 class="border-bottom pb-2 mb-3 fw-bold text-primary"><?php echo __('items'); ?></h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered table-sm">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th><?php echo __('drug_name'); ?></th>
|
|
<th><?php echo __('batch_number'); ?></th>
|
|
<th><?php echo __('expiry_date'); ?></th>
|
|
<th class="text-center"><?php echo __('quantity'); ?></th>
|
|
<th class="text-end"><?php echo __('cost_price'); ?></th>
|
|
<th class="text-end"><?php echo __('total_cost'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="viewPurchaseItemsBody"></tbody>
|
|
<tfoot class="table-light">
|
|
<tr>
|
|
<td colspan="5" class="text-end fw-bold"><?php echo __('total_amount'); ?></td>
|
|
<td class="text-end fw-bold text-primary" id="view_purchase_total"></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="mt-3">
|
|
<p class="mb-1 text-muted small"><?php echo __('notes'); ?></p>
|
|
<p class="bg-light p-2 rounded" id="view_purchase_notes"></p>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer bg-light">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('close'); ?></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let allDrugs = [];
|
|
let allSuppliers = [];
|
|
let currentPage = 1;
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
loadPurchases(1);
|
|
fetchSuppliers();
|
|
fetchDrugs();
|
|
|
|
// Calculate total when inputs change in the table
|
|
document.getElementById('purchaseItemsBody').addEventListener('input', function(e) {
|
|
if (e.target.classList.contains('purchase-qty') || e.target.classList.contains('purchase-price')) {
|
|
calculateRowTotal(e.target.closest('tr'));
|
|
calculateGrandTotal();
|
|
}
|
|
});
|
|
|
|
// Re-initialize Select2 when modal is shown
|
|
$('#createPurchaseModal').on('shown.bs.modal', function () {
|
|
$('.select2-modal').select2({
|
|
dropdownParent: $('#createPurchaseModal'),
|
|
width: '100%'
|
|
});
|
|
});
|
|
});
|
|
|
|
function loadPurchases(page = 1) {
|
|
currentPage = page;
|
|
fetch('api/pharmacy_lpo.php?action=get_lpos&page=' + page)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
const tbody = document.getElementById('purchaseTableBody');
|
|
const paginationContainer = document.getElementById('paginationContainer');
|
|
tbody.innerHTML = '';
|
|
|
|
const purchases = data.data || (Array.isArray(data) ? data : []);
|
|
const totalPages = data.pages || 1;
|
|
|
|
if (purchases.length === 0) {
|
|
tbody.innerHTML = '<tr><td colspan="6" class="text-center py-4 text-muted"><?php echo __('no_data_found'); ?></td></tr>';
|
|
paginationContainer.innerHTML = '';
|
|
return;
|
|
}
|
|
|
|
purchases.forEach(p => {
|
|
const tr = document.createElement('tr');
|
|
let statusBadge = '';
|
|
switch(p.status) {
|
|
case 'Draft': statusBadge = '<span class="badge bg-secondary">Draft</span>'; break;
|
|
case 'Sent': statusBadge = '<span class="badge bg-primary">Sent</span>'; break;
|
|
case 'Received': statusBadge = '<span class="badge bg-success">Received</span>'; break;
|
|
case 'Cancelled': statusBadge = '<span class="badge bg-danger">Cancelled</span>'; break;
|
|
default: statusBadge = `<span class="badge bg-info">${p.status}</span>`;
|
|
}
|
|
|
|
tr.innerHTML = `
|
|
<td>${p.id}</td>
|
|
<td>${p.lpo_date}</td>
|
|
<td>${p.supplier_name || '-'}</td>
|
|
<td class="fw-bold text-success">$${parseFloat(p.total_amount).toFixed(2)}</td>
|
|
<td>${statusBadge}</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewPurchase(${p.id}, '${p.supplier_name}', '${p.lpo_date}', '${p.total_amount}', '${p.status}', '${p.notes || ''}')">
|
|
<i class="bi bi-eye"></i>
|
|
</button>
|
|
${p.status === 'Draft' ? `<button class="btn btn-sm btn-outline-success ms-1" onclick="updateStatus(${p.id}, 'Sent')" title="Mark as Sent"><i class="bi bi-send"></i></button>` : ''}
|
|
${p.status === 'Sent' ? `<button class="btn btn-sm btn-success ms-1" onclick="openReceiveModal(${p.id})" title="Receive Items"><i class="bi bi-box-seam"></i></button>` : ''}
|
|
</td>
|
|
`;
|
|
tbody.appendChild(tr);
|
|
});
|
|
|
|
renderPagination(currentPage, totalPages);
|
|
})
|
|
.catch(err => {
|
|
console.error(err);
|
|
document.getElementById('purchaseTableBody').innerHTML = '<tr><td colspan="6" class="text-center text-danger">Error loading data</td></tr>';
|
|
});
|
|
}
|
|
|
|
function renderPagination(current, total) {
|
|
const container = document.getElementById('paginationContainer');
|
|
if (total <= 1) {
|
|
container.innerHTML = '';
|
|
return;
|
|
}
|
|
|
|
let html = '<ul class="pagination justify-content-center">';
|
|
html += `<li class="page-item ${current <= 1 ? 'disabled' : ''}"><a class="page-link" href="#" onclick="event.preventDefault(); loadPurchases(${current - 1})"><?php echo __('previous'); ?></a></li>`;
|
|
|
|
let start = Math.max(1, current - 2);
|
|
let end = Math.min(total, start + 4);
|
|
if (end - start < 4) start = Math.max(1, end - 4);
|
|
|
|
for (let i = start; i <= end; i++) {
|
|
html += `<li class="page-item ${current === i ? 'active' : ''}"><a class="page-link" href="#" onclick="event.preventDefault(); loadPurchases(${i})">${i}</a></li>`;
|
|
}
|
|
|
|
html += `<li class="page-item ${current >= total ? 'disabled' : ''}"><a class="page-link" href="#" onclick="event.preventDefault(); loadPurchases(${current + 1})"><?php echo __('next'); ?></a></li>`;
|
|
html += '</ul>';
|
|
container.innerHTML = html;
|
|
}
|
|
|
|
function fetchSuppliers() {
|
|
fetch('api/pharmacy_lpo.php?action=get_suppliers')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
allSuppliers = data;
|
|
const select = document.getElementById('purchase_supplier_id');
|
|
select.innerHTML = '<option value=""><?php echo __('select_supplier'); ?>...</option>';
|
|
data.forEach(s => {
|
|
select.innerHTML += `<option value="${s.id}">${s.name_en} / ${s.name_ar}</option>`;
|
|
});
|
|
});
|
|
}
|
|
|
|
function fetchDrugs() {
|
|
fetch('api/pharmacy_lpo.php?action=get_drugs')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
allDrugs = data;
|
|
});
|
|
}
|
|
|
|
function openCreatePurchaseModal() {
|
|
document.getElementById('createPurchaseForm').reset();
|
|
$('#purchase_supplier_id').val('').trigger('change');
|
|
document.getElementById('purchaseItemsBody').innerHTML = '';
|
|
document.getElementById('purchaseTotalDisplay').innerText = '0.00';
|
|
addPurchaseItemRow();
|
|
|
|
var modal = new bootstrap.Modal(document.getElementById('createPurchaseModal'));
|
|
modal.show();
|
|
}
|
|
|
|
function addPurchaseItemRow() {
|
|
const tbody = document.getElementById('purchaseItemsBody');
|
|
const tr = document.createElement('tr');
|
|
|
|
let drugOptions = '<option value="">Select Drug...</option>';
|
|
allDrugs.forEach(d => {
|
|
drugOptions += `<option value="${d.id}" data-price="${d.price}">${d.name_en} (${d.sku || '-'})</option>`;
|
|
});
|
|
|
|
tr.innerHTML = `
|
|
<td>
|
|
<select name="items[drug_id][]" class="form-select select2-modal-row purchase-drug" onchange="drugSelected(this)" required>
|
|
${drugOptions}
|
|
</select>
|
|
</td>
|
|
<td><input type="text" name="items[batch_number][]" class="form-control" placeholder="Optional"></td>
|
|
<td><input type="date" name="items[expiry_date][]" class="form-control"></td>
|
|
<td><input type="number" name="items[quantity][]" class="form-control purchase-qty" min="1" value="1" required></td>
|
|
<td><input type="number" name="items[cost_price][]" class="form-control purchase-price" step="0.01" min="0" value="0.00" required></td>
|
|
<td><input type="text" class="form-control purchase-total" readonly value="0.00"></td>
|
|
<td class="text-center">
|
|
<button type="button" class="btn btn-sm btn-outline-danger" onclick="removePurchaseRow(this)"><i class="bi bi-trash"></i></button>
|
|
</td>
|
|
`;
|
|
tbody.appendChild(tr);
|
|
|
|
$(tr).find('.select2-modal-row').select2({
|
|
dropdownParent: $('#createPurchaseModal'),
|
|
width: '100%'
|
|
});
|
|
}
|
|
|
|
function removePurchaseRow(btn) {
|
|
const tbody = document.getElementById('purchaseItemsBody');
|
|
if (tbody.children.length > 1) {
|
|
btn.closest('tr').remove();
|
|
calculateGrandTotal();
|
|
}
|
|
}
|
|
|
|
function drugSelected(select) {
|
|
// Optional: Pre-fill last cost price if available (requires API change to fetch history)
|
|
}
|
|
|
|
function calculateRowTotal(row) {
|
|
const qty = parseFloat(row.querySelector('.purchase-qty').value) || 0;
|
|
const price = parseFloat(row.querySelector('.purchase-price').value) || 0;
|
|
const total = qty * price;
|
|
row.querySelector('.purchase-total').value = total.toFixed(2);
|
|
}
|
|
|
|
function calculateGrandTotal() {
|
|
let total = 0;
|
|
document.querySelectorAll('.purchase-total').forEach(input => {
|
|
total += parseFloat(input.value) || 0;
|
|
});
|
|
document.getElementById('purchaseTotalDisplay').innerText = total.toFixed(2);
|
|
}
|
|
|
|
function submitPurchase(e) {
|
|
e.preventDefault();
|
|
|
|
const supplierId = document.getElementById('purchase_supplier_id').value;
|
|
const date = document.getElementById('purchase_date').value;
|
|
const notes = document.getElementById('purchase_notes').value;
|
|
const totalAmount = document.getElementById('purchaseTotalDisplay').innerText;
|
|
|
|
const items = [];
|
|
document.querySelectorAll('#purchaseItemsBody tr').forEach(row => {
|
|
const drugId = $(row).find('.purchase-drug').val();
|
|
const quantity = row.querySelector('.purchase-qty').value;
|
|
const costPrice = row.querySelector('.purchase-price').value;
|
|
const totalCost = row.querySelector('.purchase-total').value;
|
|
const batchNumber = row.querySelector('input[name="items[batch_number][]"]').value;
|
|
const expiryDate = row.querySelector('input[name="items[expiry_date][]"]').value;
|
|
|
|
if (drugId) {
|
|
items.push({
|
|
drug_id: drugId,
|
|
quantity: quantity,
|
|
cost_price: costPrice,
|
|
total_cost: totalCost,
|
|
batch_number: batchNumber,
|
|
expiry_date: expiryDate
|
|
});
|
|
}
|
|
});
|
|
|
|
if (items.length === 0) {
|
|
alert('Please add at least one item.');
|
|
return;
|
|
}
|
|
|
|
fetch('api/pharmacy_lpo.php?action=create_lpo', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ supplier_id: supplierId, lpo_date: date, notes: notes, total_amount: totalAmount, items: items })
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
bootstrap.Modal.getInstance(document.getElementById('createPurchaseModal')).hide();
|
|
loadPurchases();
|
|
} else {
|
|
alert('Error: ' + (data.error || 'Unknown error'));
|
|
}
|
|
});
|
|
}
|
|
|
|
function viewPurchase(id, supplier, date, total, status, notes) {
|
|
document.getElementById('view_purchase_id').innerText = id;
|
|
document.getElementById('view_purchase_supplier').innerText = supplier;
|
|
document.getElementById('view_purchase_date').innerText = date;
|
|
document.getElementById('view_purchase_total').innerText = '$' + parseFloat(total).toFixed(2);
|
|
document.getElementById('view_purchase_status').innerText = status;
|
|
document.getElementById('view_purchase_notes').innerText = notes;
|
|
|
|
const tbody = document.getElementById('viewPurchaseItemsBody');
|
|
tbody.innerHTML = '<tr><td colspan="6" class="text-center">Loading...</td></tr>';
|
|
|
|
var modal = new bootstrap.Modal(document.getElementById('viewPurchaseModal'));
|
|
modal.show();
|
|
|
|
fetch('api/pharmacy_lpo.php?action=get_lpo_details&id=' + id)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
tbody.innerHTML = '';
|
|
data.forEach(item => {
|
|
tbody.innerHTML += `
|
|
<tr>
|
|
<td>${item.drug_name} <small class="text-muted">(${item.sku || '-'})</small></td>
|
|
<td>${item.batch_number || '-'}</td>
|
|
<td>${item.expiry_date || '-'}</td>
|
|
<td class="text-center">${item.quantity}</td>
|
|
<td class="text-end">$${parseFloat(item.cost_price).toFixed(2)}</td>
|
|
<td class="text-end">$${parseFloat(item.total_cost).toFixed(2)}</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
});
|
|
}
|
|
|
|
function updateStatus(id, newStatus) {
|
|
if (!confirm('Are you sure?')) return;
|
|
|
|
fetch('api/pharmacy_lpo.php?action=update_status', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ id: id, status: newStatus })
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) loadPurchases();
|
|
else alert('Error updating status');
|
|
});
|
|
}
|
|
|
|
// Receive Flow
|
|
let currentReceiveId = 0;
|
|
|
|
function openReceiveModal(id) {
|
|
currentReceiveId = id;
|
|
document.getElementById('receive_purchase_id').value = id;
|
|
|
|
const tbody = document.getElementById('receivePurchaseItemsBody');
|
|
tbody.innerHTML = '<tr><td colspan="4" class="text-center">Loading items...</td></tr>';
|
|
|
|
var modal = new bootstrap.Modal(document.getElementById('receivePurchaseModal'));
|
|
modal.show();
|
|
|
|
fetch('api/pharmacy_lpo.php?action=get_lpo_details&id=' + id)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
tbody.innerHTML = '';
|
|
data.forEach(item => {
|
|
const batchVal = item.batch_number || '';
|
|
const expiryVal = item.expiry_date || '';
|
|
|
|
// If missing, generate default suggestion (e.g. current date + 1 year) or empty?
|
|
// Let's leave empty to force user check, or prefill if available.
|
|
|
|
tbody.innerHTML += `
|
|
<tr data-item-id="${item.id}">
|
|
<td>
|
|
${item.drug_name}
|
|
<div class="small text-muted">SKU: ${item.sku || '-'}</div>
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control receive-batch" value="${batchVal}" required>
|
|
</td>
|
|
<td>
|
|
<input type="date" class="form-control receive-expiry" value="${expiryVal}" required>
|
|
</td>
|
|
<td class="text-center align-middle">${item.quantity}</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
});
|
|
}
|
|
|
|
function confirmReceivePurchase() {
|
|
const id = document.getElementById('receive_purchase_id').value;
|
|
const items = [];
|
|
let valid = true;
|
|
|
|
document.querySelectorAll('#receivePurchaseItemsBody tr').forEach(row => {
|
|
const itemId = row.getAttribute('data-item-id');
|
|
const batch = row.querySelector('.receive-batch').value.trim();
|
|
const expiry = row.querySelector('.receive-expiry').value;
|
|
|
|
if (!batch || !expiry) {
|
|
valid = false;
|
|
row.querySelector('.receive-batch').classList.add('is-invalid');
|
|
row.querySelector('.receive-expiry').classList.add('is-invalid');
|
|
} else {
|
|
row.querySelector('.receive-batch').classList.remove('is-invalid');
|
|
row.querySelector('.receive-expiry').classList.remove('is-invalid');
|
|
}
|
|
|
|
items.push({
|
|
id: itemId,
|
|
batch_number: batch,
|
|
expiry_date: expiry
|
|
});
|
|
});
|
|
|
|
if (!valid) {
|
|
alert('Please fill in Batch Number and Expiry Date for all items.');
|
|
return;
|
|
}
|
|
|
|
if (!confirm('Are you sure you want to mark this purchase as Received? Stock will be updated.')) return;
|
|
|
|
fetch('api/pharmacy_lpo.php?action=update_status', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
id: id,
|
|
status: 'Received',
|
|
items: items
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
bootstrap.Modal.getInstance(document.getElementById('receivePurchaseModal')).hide();
|
|
loadPurchases();
|
|
} else {
|
|
alert('Error: ' + (data.error || 'Unknown error'));
|
|
}
|
|
})
|
|
.catch(err => {
|
|
console.error(err);
|
|
alert('Failed to receive purchase');
|
|
});
|
|
}
|
|
</script>
|