214 lines
10 KiB
PHP
214 lines
10 KiB
PHP
<?php
|
|
$page = $_GET['page'] ?? 1;
|
|
$limit = 20;
|
|
$offset = ($page - 1) * $limit;
|
|
|
|
// Count total
|
|
$count_stmt = $db->query("SELECT COUNT(*) FROM pharmacy_sales");
|
|
$total_rows = $count_stmt->fetchColumn();
|
|
$total_pages = ceil($total_rows / $limit);
|
|
|
|
// Fetch Sales
|
|
$sql = "SELECT s.*, p.name as patient_name
|
|
FROM pharmacy_sales s
|
|
LEFT JOIN patients p ON s.patient_id = p.id
|
|
ORDER BY s.created_at DESC
|
|
LIMIT $limit OFFSET $offset";
|
|
$stmt = $db->query($sql);
|
|
$sales = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
?>
|
|
|
|
<div class="container-fluid">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h2 class="fw-bold text-primary"><i class="bi bi-receipt me-2"></i> <?php echo __('sales_history'); ?></h2>
|
|
<a href="pharmacy_pos.php" class="btn btn-primary">
|
|
<i class="bi bi-cart-plus me-2"></i> <?php echo __('new_sale'); ?>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th><?php echo __('date'); ?></th>
|
|
<th><?php echo __('patient'); ?></th>
|
|
<th><?php echo __('items'); ?></th>
|
|
<th><?php echo __('total_amount'); ?></th>
|
|
<th><?php echo __('payment_method'); ?></th>
|
|
<th><?php echo __('status'); ?></th>
|
|
<th><?php echo __('actions'); ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($sales)): ?>
|
|
<tr>
|
|
<td colspan="8" class="text-center py-4 text-muted">
|
|
<i class="bi bi-inbox fs-1 d-block mb-2"></i>
|
|
<?php echo __('no_data_found'); ?>
|
|
</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php foreach ($sales as $sale): ?>
|
|
<tr>
|
|
<td><?php echo $sale['id']; ?></td>
|
|
<td><?php echo date('Y-m-d H:i', strtotime($sale['created_at'])); ?></td>
|
|
<td>
|
|
<?php if ($sale['patient_name']): ?>
|
|
<a href="patients.php?action=view&id=<?php echo $sale['patient_id']; ?>" class="text-decoration-none">
|
|
<?php echo htmlspecialchars($sale['patient_name']); ?>
|
|
</a>
|
|
<?php else: ?>
|
|
<span class="text-muted"><?php echo __('walk_in'); ?></span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php
|
|
// Fetch item count or summary (quick query)
|
|
$item_count_stmt = $db->prepare("SELECT COUNT(*) FROM pharmacy_sale_items WHERE sale_id = ?");
|
|
$item_count_stmt->execute([$sale['id']]);
|
|
echo $item_count_stmt->fetchColumn() . ' ' . __('items');
|
|
?>
|
|
</td>
|
|
<td class="fw-bold"><?php echo number_format($sale['total_amount'], 2); ?></td>
|
|
<td>
|
|
<span class="badge bg-light text-dark border">
|
|
<?php echo ucfirst($sale['payment_method']); ?>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-success"><?php echo ucfirst($sale['status']); ?></span>
|
|
</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="viewReceipt(<?php echo $sale['id']; ?>)">
|
|
<i class="bi bi-receipt"></i> <?php echo __('receipt'); ?>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
<?php if ($total_pages > 1): ?>
|
|
<nav aria-label="Page navigation" class="mt-4">
|
|
<ul class="pagination justify-content-center">
|
|
<li class="page-item <?php echo $page <= 1 ? 'disabled' : ''; ?>">
|
|
<a class="page-link" href="?page=<?php echo $page - 1; ?>"><?php echo __('previous'); ?></a>
|
|
</li>
|
|
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
|
|
<li class="page-item <?php echo $page == $i ? 'active' : ''; ?>">
|
|
<a class="page-link" href="?page=<?php echo $i; ?>"><?php echo $i; ?></a>
|
|
</li>
|
|
<?php endfor; ?>
|
|
<li class="page-item <?php echo $page >= $total_pages ? 'disabled' : ''; ?>">
|
|
<a class="page-link" href="?page=<?php echo $page + 1; ?>"><?php echo __('next'); ?></a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Receipt Modal -->
|
|
<div class="modal fade" id="receiptModal" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title"><?php echo __('receipt'); ?></h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body" id="receiptBody">
|
|
<!-- Content via JS -->
|
|
</div>
|
|
<div class="modal-footer">
|
|
<a href="#" id="formalReceiptBtn" target="_blank" class="btn btn-outline-primary"><i class="bi bi-file-earmark-text"></i> <?php echo __('formal_receipt'); ?></a>
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('close'); ?></button>
|
|
<button type="button" class="btn btn-primary" onclick="printReceiptContent()"><i class="bi bi-printer"></i> <?php echo __('print'); ?></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function viewReceipt(saleId) {
|
|
const modal = new bootstrap.Modal(document.getElementById('receiptModal'));
|
|
const body = document.getElementById('receiptBody');
|
|
document.getElementById('formalReceiptBtn').href = 'print_pharmacy_receipt.php?sale_id=' + saleId;
|
|
body.innerHTML = '<div class="text-center py-4"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
|
|
modal.show();
|
|
|
|
fetch('api/pharmacy.php?action=get_sale_details&sale_id=' + saleId)
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
if (data.error) {
|
|
body.innerHTML = '<div class="text-danger">' + data.error + '</div>';
|
|
return;
|
|
}
|
|
|
|
let html = `
|
|
<div class="text-center mb-4">
|
|
<h5><?php echo htmlspecialchars($site_name); ?></h5>
|
|
<p class="mb-0 text-muted">Receipt #${data.id}</p>
|
|
<small class="text-muted">${data.created_at}</small>
|
|
</div>
|
|
<div class="mb-3 d-flex justify-content-between">
|
|
<span><strong>Patient:</strong> ${data.patient_name || 'Walk-in'}</span>
|
|
<span><strong>Method:</strong> ${data.payment_method}</span>
|
|
</div>
|
|
<table class="table table-sm border-top border-bottom">
|
|
<thead><tr><th>Item</th><th class="text-end">Qty</th><th class="text-end">Price</th><th class="text-end">Total</th></tr></thead>
|
|
<tbody>
|
|
`;
|
|
|
|
data.items.forEach(item => {
|
|
html += `
|
|
<tr>
|
|
<td>${item.drug_name}</td>
|
|
<td class="text-end">${item.quantity}</td>
|
|
<td class="text-end">${parseFloat(item.unit_price).toFixed(2)}</td>
|
|
<td class="text-end">${parseFloat(item.total_price).toFixed(2)}</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
|
|
html += `
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="fw-bold">
|
|
<td colspan="3" class="text-end pt-3">Total Amount</td>
|
|
<td class="text-end pt-3 fs-5">${parseFloat(data.total_amount).toFixed(2)}</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
<div class="text-center mt-4 text-muted small">
|
|
<p>Thank you for your visit!</p>
|
|
</div>
|
|
`;
|
|
|
|
body.innerHTML = html;
|
|
})
|
|
.catch(e => {
|
|
console.error(e);
|
|
body.innerHTML = '<div class="text-danger">Error loading receipt</div>';
|
|
});
|
|
}
|
|
|
|
function printReceiptContent() {
|
|
const content = document.getElementById('receiptBody').innerHTML;
|
|
const win = window.open('', '', 'height=600,width=800');
|
|
win.document.write('<html><head><title>Print Receipt</title>');
|
|
win.document.write('<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">');
|
|
win.document.write('</head><body><div class="p-4" style="max-width: 400px; margin: 0 auto;">');
|
|
win.document.write(content);
|
|
win.document.write('</div></body></html>');
|
|
win.document.close();
|
|
win.focus();
|
|
setTimeout(() => { win.print(); win.close(); }, 500);
|
|
}
|
|
</script>
|