Autosave: 20260321-140606

This commit is contained in:
Flatlogic Bot 2026-03-21 14:06:06 +00:00
parent dad73767a1
commit b5ea341aa5
26 changed files with 1311 additions and 255 deletions

View File

@ -1,19 +1,13 @@
Plan: Plan:
1. **Fix 500 Error:** I identified and fixed a critical syntax error in `includes/actions.php` (a missing quote in the SQL query) that was crashing the application. 1. **Investigate:** Checked Apache error logs and `includes/actions.php`.
2. **Restore Token Logic:** I carefully re-implemented the token generation code in `includes/actions.php` to ensure it works correctly without breaking the visit recording process. 2. **Identify Issue:** Found a mismatch between the database schema for `insurance_payments` (missing `payment_method` column) and the PHP code trying to insert into it.
3. **Add Missing UI:** I added the **"Issue Token"** checkbox to the "Details" tab of the "Add Visit" modal in `includes/layout/footer.php`, which was missing from the previous attempt. 3. **Fix:** Created and applied a migration to add the `payment_method` column to the `insurance_payments` table.
4. **Verify Integrity:** I confirmed that the `patient_queue` database table exists and that all new files (`queue.php`, `api/queue.php`, `queue_display.php`) have valid syntax. 4. **Verify:** Confirmed the column now exists in the database.
Changed: Changed Files:
* `includes/actions.php`: Fixed a syntax error and correctly implemented the token generation logic. * `db/migrations/20260321_z_add_payment_method_to_insurance_payments.sql`: Added migration to fix the schema.
* `includes/layout/footer.php`: Added the "Issue Token" checkbox to the "Details" tab of the `recordVisitModal`.
Notes: Next Steps:
* The application should now load correctly without the 500 error. * Go to **Insurance > Transactions**.
* To use the token system: * Try adding a transaction again. It should work now.
1. **Receptionist:** When adding a new visit, check the **"Issue Token"** box in the "Details" tab. * **Reminder:** Click Save in the editor to sync changes.
2. **Queue Management:** Go to **"Queue Management"** in the sidebar to manage the queue (Call, Finish).
3. **Display:** Click **"Open TV Display"** to open the public waiting list on a separate screen.
* Reminder: click Save in the editor to sync changes.
Next: Please refresh your browser and try adding a visit with the "Issue Token" checkbox checked. Let me know if everything works as expected!

View File

@ -1,9 +0,0 @@
<?php
require_once 'db/config.php';
$pdo = db();
$stmt = $pdo->query("DESCRIBE patients");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
echo $row['Field'] . "\n";
}

View File

@ -0,0 +1,10 @@
CREATE TABLE IF NOT EXISTS insurance_payments (
id INT AUTO_INCREMENT PRIMARY KEY,
insurance_company_id INT NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
payment_date DATE NOT NULL,
reference_number VARCHAR(100) DEFAULT NULL,
notes TEXT DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (insurance_company_id) REFERENCES insurance_companies(id) ON DELETE CASCADE
);

View File

@ -0,0 +1 @@
ALTER TABLE insurance_payments ADD COLUMN payment_method VARCHAR(50) DEFAULT 'Check' AFTER reference_number;

View File

@ -1,24 +1,34 @@
<?php <?php
$SYSTEM_SETTINGS = null;
function get_system_settings() { function get_system_settings() {
global $db; // Assuming db() is already initialized or we can initialize it global $db, $SYSTEM_SETTINGS;
if ($SYSTEM_SETTINGS !== null) {
return $SYSTEM_SETTINGS;
}
if (!isset($db)) { if (!isset($db)) {
require_once __DIR__ . '/db/config.php'; require_once __DIR__ . '/db/config.php';
$local_db = db(); $local_db = db();
} else { } else {
$local_db = $db; $local_db = $db;
} }
try { try {
$stmt = $local_db->query('SELECT setting_key, setting_value FROM settings'); $stmt = $local_db->query('SELECT setting_key, setting_value FROM settings');
$settings = []; $settings = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$settings[$row['setting_key']] = $row['setting_value']; $settings[$row['setting_key']] = $row['setting_value'];
} }
$SYSTEM_SETTINGS = $settings;
return $settings; return $settings;
} catch (Exception $e) { } catch (Exception $e) {
return []; return [];
} }
} }
function apply_timezone() { function apply_timezone() {
$s = get_system_settings(); $s = get_system_settings();
if (!empty($s['timezone'])) { if (!empty($s['timezone'])) {
@ -27,6 +37,13 @@ function apply_timezone() {
} }
apply_timezone(); apply_timezone();
function format_currency($amount) {
$settings = get_system_settings();
$currency_symbol = $settings['currency_symbol'] ?? '$';
$decimal_digits = isset($settings['decimal_digits']) ? (int)$settings['decimal_digits'] : 2;
return $currency_symbol . ' ' . number_format((float)$amount, $decimal_digits);
}
session_start(); session_start();
require_once __DIR__ . '/lang.php'; require_once __DIR__ . '/lang.php';

View File

@ -1,5 +1,5 @@
<?php <?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') {
require_once __DIR__ . '/../db/config.php'; require_once __DIR__ . '/../db/config.php';
require_once __DIR__ . '/../helpers.php'; require_once __DIR__ . '/../helpers.php';
$db = db(); $db = db();
@ -1130,6 +1130,78 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$_SESSION['flash_message'] = __('delete') . ' ' . __('successfully'); $_SESSION['flash_message'] = __('delete') . ' ' . __('successfully');
$redirect = true; $redirect = true;
} }
} elseif ($_POST['action'] === 'add_insurance') {
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
$email = $_POST['email'] ?? '';
$phone = $_POST['phone'] ?? '';
$discount = $_POST['discount_percentage'] ?? 0;
if ($name_en && $name_ar) {
$stmt = $db->prepare("INSERT INTO insurance_companies (name_en, name_ar, email, phone, discount_percentage) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$name_en, $name_ar, $email, $phone, $discount]);
$_SESSION['flash_message'] = __('add_insurance') . ' ' . __('successfully');
$redirect = true;
}
} elseif ($_POST['action'] === 'edit_insurance') {
$id = $_POST['id'] ?? '';
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
$email = $_POST['email'] ?? '';
$phone = $_POST['phone'] ?? '';
$discount = $_POST['discount_percentage'] ?? 0;
if ($id && $name_en && $name_ar) {
$stmt = $db->prepare("UPDATE insurance_companies SET name_en = ?, name_ar = ?, email = ?, phone = ?, discount_percentage = ? WHERE id = ?");
$stmt->execute([$name_en, $name_ar, $email, $phone, $discount, $id]);
$_SESSION['flash_message'] = __('edit') . ' ' . __('successfully');
$redirect = true;
}
} elseif ($_POST['action'] === 'delete_insurance') {
$id = $_POST['id'] ?? '';
if ($id) {
$stmt = $db->prepare("DELETE FROM insurance_companies WHERE id = ?");
$stmt->execute([$id]);
$_SESSION['flash_message'] = __('delete') . ' ' . __('successfully');
$redirect = true;
}
} elseif ($_POST['action'] === 'add_transaction') {
$insurance_company_id = $_POST['insurance_company_id'] ?: null;
$amount = $_POST['amount'] ?? 0;
$date = $_POST['payment_date'] ?? date('Y-m-d');
$ref = $_POST['reference_number'] ?? '';
$method = $_POST['payment_method'] ?? 'Check';
$notes = $_POST['notes'] ?? '';
if ($insurance_company_id && $amount) {
$stmt = $db->prepare("INSERT INTO insurance_payments (insurance_company_id, amount, payment_date, reference_number, payment_method, notes) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$insurance_company_id, $amount, $date, $ref, $method, $notes]);
$_SESSION['flash_message'] = __('transaction_added_success');
$redirect = true;
}
} elseif ($_POST['action'] === 'edit_transaction') {
$id = $_POST['id'] ?? '';
$insurance_company_id = $_POST['insurance_company_id'] ?: null;
$amount = $_POST['amount'] ?? 0;
$date = $_POST['payment_date'] ?? date('Y-m-d');
$ref = $_POST['reference_number'] ?? '';
$method = $_POST['payment_method'] ?? 'Check';
$notes = $_POST['notes'] ?? '';
if ($id && $insurance_company_id && $amount) {
$stmt = $db->prepare("UPDATE insurance_payments SET insurance_company_id = ?, amount = ?, payment_date = ?, reference_number = ?, payment_method = ?, notes = ? WHERE id = ?");
$stmt->execute([$insurance_company_id, $amount, $date, $ref, $method, $notes, $id]);
$_SESSION['flash_message'] = __('transaction_updated_success');
$redirect = true;
}
} elseif ($_POST['action'] === 'delete_transaction') {
$id = $_POST['id'] ?? '';
if ($id) {
$stmt = $db->prepare("DELETE FROM insurance_payments WHERE id = ?");
$stmt->execute([$id]);
$_SESSION['flash_message'] = __('transaction_deleted_success');
$redirect = true;
}
} }
} }

View File

@ -48,6 +48,16 @@ $site_favicon = !empty($site_settings['company_favicon']) ? $site_settings['comp
<!-- Flatpickr CSS --> <!-- Flatpickr CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script>
const SYSTEM_SETTINGS = <?php echo json_encode(get_system_settings()); ?>;
const CURRENCY_SYMBOL = SYSTEM_SETTINGS.currency_symbol || '$';
const DECIMAL_DIGITS = parseInt(SYSTEM_SETTINGS.decimal_digits || 2);
function formatCurrency(amount) {
return CURRENCY_SYMBOL + ' ' + parseFloat(amount).toFixed(DECIMAL_DIGITS);
}
</script>
<style> <style>
body { font-family: 'Inter', 'Tajawal', sans-serif; background-color: #f4f7f6; } body { font-family: 'Inter', 'Tajawal', sans-serif; background-color: #f4f7f6; }
.sidebar { min-height: 100vh; width: 250px; background-color: #002D62; color: white; transition: all 0.3s; flex-shrink: 0; } .sidebar { min-height: 100vh; width: 250px; background-color: #002D62; color: white; transition: all 0.3s; flex-shrink: 0; }

View File

@ -82,9 +82,9 @@ $bills = $stmt->fetchAll();
<td class="px-4 text-secondary">#<?php echo $b['id']; ?></td> <td class="px-4 text-secondary">#<?php echo $b['id']; ?></td>
<td class="text-secondary"><?php echo date('Y-m-d H:i', strtotime($b['created_at'])); ?></td> <td class="text-secondary"><?php echo date('Y-m-d H:i', strtotime($b['created_at'])); ?></td>
<td class="fw-semibold text-dark"><?php echo htmlspecialchars($b['patient_name']); ?></td> <td class="fw-semibold text-dark"><?php echo htmlspecialchars($b['patient_name']); ?></td>
<td class="text-dark">$<?php echo number_format($b['total_amount'], 2); ?></td> <td class="text-dark"><?php echo format_currency($b['total_amount']); ?></td>
<td class="text-primary">$<?php echo number_format($b['insurance_covered'], 2); ?></td> <td class="text-primary"><?php echo format_currency($b['insurance_covered']); ?></td>
<td class="fw-bold text-dark">$<?php echo number_format($b['patient_payable'], 2); ?></td> <td class="fw-bold text-dark"><?php echo format_currency($b['patient_payable']); ?></td>
<td> <td>
<span class="badge <?php echo $b['status'] === 'Paid' ? 'bg-success bg-opacity-10 text-success border border-success border-opacity-25' : 'bg-warning bg-opacity-10 text-warning border border-warning border-opacity-25'; ?> px-2 py-1"> <span class="badge <?php echo $b['status'] === 'Paid' ? 'bg-success bg-opacity-10 text-success border border-success border-opacity-25' : 'bg-warning bg-opacity-10 text-warning border border-warning border-opacity-25'; ?> px-2 py-1">
<?php echo __($b['status']); ?> <?php echo __($b['status']); ?>

View File

@ -135,14 +135,14 @@ $appointments = $db->query($appointments_sql)->fetchAll();
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<div class="card stat-card h-100"> <div class="card stat-card h-100">
<i class="bi bi-currency-dollar text-success"></i> <i class="bi bi-currency-dollar text-success"></i>
<h3>$<?php echo number_format($total_revenue, 2); ?></h3> <h3><?php echo format_currency($total_revenue); ?></h3>
<p class="text-muted mb-0"><?php echo __('revenue'); ?></p> <p class="text-muted mb-0"><?php echo __('revenue'); ?></p>
</div> </div>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<div class="card stat-card h-100"> <div class="card stat-card h-100">
<i class="bi bi-hourglass-split text-warning"></i> <i class="bi bi-hourglass-split text-warning"></i>
<h3>$<?php echo number_format($pending_revenue, 2); ?></h3> <h3><?php echo format_currency($pending_revenue); ?></h3>
<p class="text-muted mb-0"><?php echo __('pending'); ?></p> <p class="text-muted mb-0"><?php echo __('pending'); ?></p>
</div> </div>
</div> </div>
@ -502,10 +502,10 @@ $appointments = $db->query($appointments_sql)->fetchAll();
<select id="checkout_service_select" class="form-select form-select-sm select2-modal-checkout"> <select id="checkout_service_select" class="form-select form-select-sm select2-modal-checkout">
<option value=""><?php echo __('select_service'); ?>...</option> <option value=""><?php echo __('select_service'); ?>...</option>
<?php foreach ($all_services as $s): ?> <?php foreach ($all_services as $s): ?>
<option value="<?php echo $s['name']; ?>" data-price="<?php echo $s['price']; ?>"><?php echo htmlspecialchars($s['name']); ?> ($<?php echo $s['price']; ?>)</option> <option value="<?php echo $s['name']; ?>" data-price="<?php echo $s['price']; ?>"><?php echo htmlspecialchars($s['name']); ?> (<?php echo format_currency($s['price']); ?>)</option>
<?php endforeach; ?> <?php endforeach; ?>
<?php foreach ($all_tests as $t): ?> <?php foreach ($all_tests as $t): ?>
<option value="<?php echo $t['name']; ?>" data-price="<?php echo $t['price']; ?>"><?php echo htmlspecialchars($t['name']); ?> ($<?php echo $t['price']; ?>)</option> <option value="<?php echo $t['name']; ?>" data-price="<?php echo $t['price']; ?>"><?php echo htmlspecialchars($t['name']); ?> (<?php echo format_currency($t['price']); ?>)</option>
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
</div> </div>
@ -557,14 +557,14 @@ $appointments = $db->query($appointments_sql)->fetchAll();
<div class="col-md-4"> <div class="col-md-4">
<label class="form-label small text-muted">Insurance Pays</label> <label class="form-label small text-muted">Insurance Pays</label>
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<span class="input-group-text">$</span> <span class="input-group-text"><?php echo $currency_symbol ?? '$'; ?></span>
<input type="number" id="checkout_insurance_amount" class="form-control" readonly> <input type="number" id="checkout_insurance_amount" class="form-control" readonly>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<label class="form-label small text-muted fw-bold text-dark">Patient Pays</label> <label class="form-label small text-muted fw-bold text-dark">Patient Pays</label>
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<span class="input-group-text">$</span> <span class="input-group-text"><?php echo $currency_symbol ?? '$'; ?></span>
<input type="number" id="checkout_patient_amount" class="form-control fw-bold" readonly> <input type="number" id="checkout_patient_amount" class="form-control fw-bold" readonly>
</div> </div>
</div> </div>
@ -646,7 +646,7 @@ document.addEventListener('DOMContentLoaded', function() {
var text = element.text(); var text = element.text();
if (price) { if (price) {
document.getElementById('checkout_custom_item').value = text.split(' ($')[0]; document.getElementById('checkout_custom_item').value = text.split(' (')[0];
document.getElementById('checkout_item_price').value = price; document.getElementById('checkout_item_price').value = price;
} }
}); });
@ -790,7 +790,7 @@ function renderBillItems(items) {
tbody.innerHTML += ` tbody.innerHTML += `
<tr> <tr>
<td>${item.description}</td> <td>${item.description}</td>
<td class="text-end">$${parseFloat(item.amount).toFixed(2)}</td> <td class="text-end">${formatCurrency(item.amount)}</td>
<td class="text-center"> <td class="text-center">
<button class="btn btn-sm btn-link text-danger p-0" onclick="removeBillItem(${item.id})"><i class="bi bi-x-lg"></i></button> <button class="btn btn-sm btn-link text-danger p-0" onclick="removeBillItem(${item.id})"><i class="bi bi-x-lg"></i></button>
</td> </td>
@ -799,7 +799,7 @@ function renderBillItems(items) {
}); });
currentTotal = total; currentTotal = total;
document.getElementById('checkout_total_amount').innerText = '$' + total.toFixed(2); document.getElementById('checkout_total_amount').innerText = formatCurrency(total);
calculateTotals(); calculateTotals();
} }

View File

@ -48,6 +48,9 @@ $all_drug_groups = $gStmt->fetchAll();
$sStmt = $db->query("SELECT * FROM suppliers ORDER BY name_$lang"); $sStmt = $db->query("SELECT * FROM suppliers ORDER BY name_$lang");
$all_suppliers = $sStmt->fetchAll(); $all_suppliers = $sStmt->fetchAll();
$sys_settings = get_system_settings();
$currency_symbol = $sys_settings['currency_symbol'] ?? '$';
// --- AJAX HANDLER --- // --- AJAX HANDLER ---
if (isset($_GET['ajax_search'])) { if (isset($_GET['ajax_search'])) {
ob_start(); ob_start();
@ -81,7 +84,7 @@ if (isset($_GET['ajax_search'])) {
</td> </td>
<td class="text-nowrap"><?php echo htmlspecialchars($drug['expiry_date'] ?? '-'); ?></td> <td class="text-nowrap"><?php echo htmlspecialchars($drug['expiry_date'] ?? '-'); ?></td>
<td class="text-wrap" style="max-width: 150px;"><?php echo htmlspecialchars($drug['supplier_name'] ?? '-'); ?></td> <td class="text-wrap" style="max-width: 150px;"><?php echo htmlspecialchars($drug['supplier_name'] ?? '-'); ?></td>
<td class="text-secondary fw-bold"><?php echo number_format($drug['price'], 2); ?></td> <td class="text-secondary fw-bold"><?php echo format_currency($drug['price']); ?></td>
<td class="text-end px-4 text-nowrap"> <td class="text-end px-4 text-nowrap">
<div class="btn-group shadow-sm border rounded bg-white"> <div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end" <button class="btn btn-link text-primary py-1 px-2 border-end"
@ -240,7 +243,7 @@ if (isset($_GET['ajax_search'])) {
</td> </td>
<td class="text-nowrap"><?php echo htmlspecialchars($drug['expiry_date'] ?? '-'); ?></td> <td class="text-nowrap"><?php echo htmlspecialchars($drug['expiry_date'] ?? '-'); ?></td>
<td class="text-wrap" style="max-width: 150px;"><?php echo htmlspecialchars($drug['supplier_name'] ?? '-'); ?></td> <td class="text-wrap" style="max-width: 150px;"><?php echo htmlspecialchars($drug['supplier_name'] ?? '-'); ?></td>
<td class="text-secondary fw-bold"><?php echo number_format($drug['price'], 2); ?></td> <td class="text-secondary fw-bold"><?php echo format_currency($drug['price']); ?></td>
<td class="text-end px-4 text-nowrap"> <td class="text-end px-4 text-nowrap">
<div class="btn-group shadow-sm border rounded bg-white"> <div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end" <button class="btn btn-link text-primary py-1 px-2 border-end"
@ -362,7 +365,7 @@ if (isset($_GET['ajax_search'])) {
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label"><?php echo __('price'); ?></label> <label class="form-label"><?php echo __('price'); ?></label>
<div class="input-group"> <div class="input-group">
<span class="input-group-text">$</span> <span class="input-group-text"><?php echo htmlspecialchars($currency_symbol); ?></span>
<input type="number" step="0.01" class="form-control" name="price" id="drugPrice"> <input type="number" step="0.01" class="form-control" name="price" id="drugPrice">
</div> </div>
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,9 @@ $tests = $stmt->fetchAll();
$gStmt = $db->query("SELECT * FROM test_groups ORDER BY name_$lang"); $gStmt = $db->query("SELECT * FROM test_groups ORDER BY name_$lang");
$all_test_groups = $gStmt->fetchAll(); $all_test_groups = $gStmt->fetchAll();
$sys_settings = get_system_settings();
$currency_symbol = $sys_settings['currency_symbol'] ?? '$';
// --- AJAX HANDLER --- // --- AJAX HANDLER ---
if (isset($_GET['ajax_search'])) { if (isset($_GET['ajax_search'])) {
ob_start(); ob_start();
@ -78,7 +81,7 @@ if (isset($_GET['ajax_search'])) {
<?php echo htmlspecialchars($test['normal_range'] ?? '-'); ?> <?php echo htmlspecialchars($test['normal_range'] ?? '-'); ?>
</span> </span>
</td> </td>
<td class="text-secondary fw-bold"><?php echo number_format($test['price'], 2); ?></td> <td class="text-secondary fw-bold"><?php echo format_currency($test['price']); ?></td>
<td class="text-end px-4"> <td class="text-end px-4">
<div class="btn-group shadow-sm border rounded bg-white"> <div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end" <button class="btn btn-link text-primary py-1 px-2 border-end"
@ -239,7 +242,7 @@ if (isset($_GET['ajax_search'])) {
<?php echo htmlspecialchars($test['normal_range'] ?? '-'); ?> <?php echo htmlspecialchars($test['normal_range'] ?? '-'); ?>
</span> </span>
</td> </td>
<td class="text-secondary fw-bold"><?php echo number_format($test['price'], 2); ?></td> <td class="text-secondary fw-bold"><?php echo format_currency($test['price']); ?></td>
<td class="text-end px-4"> <td class="text-end px-4">
<div class="btn-group shadow-sm border rounded bg-white"> <div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end" <button class="btn btn-link text-primary py-1 px-2 border-end"
@ -377,7 +380,7 @@ if (isset($_GET['ajax_search'])) {
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label"><?php echo __('price'); ?></label> <label class="form-label"><?php echo __('price'); ?></label>
<div class="input-group"> <div class="input-group">
<span class="input-group-text">$</span> <span class="input-group-text"><?php echo htmlspecialchars($currency_symbol); ?></span>
<input type="number" step="0.01" class="form-control" name="price" id="testPrice"> <input type="number" step="0.01" class="form-control" name="price" id="testPrice">
</div> </div>
</div> </div>

View File

@ -155,7 +155,7 @@ function fetchDrugs(query = '') {
<small class="text-muted">${skuHtml}${drug.name_ar || ''}</small> <small class="text-muted">${skuHtml}${drug.name_ar || ''}</small>
</div> </div>
<div class="text-end"> <div class="text-end">
<div class="fw-bold text-primary">${price.toFixed(2)}</div> <div class="fw-bold text-primary">${formatCurrency(price)}</div>
<small class="${isOutOfStock ? 'text-danger' : 'text-success'}"> <small class="${isOutOfStock ? 'text-danger' : 'text-success'}">
${isOutOfStock ? '<?php echo __('out_of_stock'); ?>' : '<?php echo __('stock'); ?>: ' + stock} ${isOutOfStock ? '<?php echo __('out_of_stock'); ?>' : '<?php echo __('stock'); ?>: ' + stock}
</small> </small>
@ -243,7 +243,7 @@ function renderCart() {
<tr> <tr>
<td> <td>
<div class="fw-bold text-truncate" style="max-width: 180px;">${item.name}</div> <div class="fw-bold text-truncate" style="max-width: 180px;">${item.name}</div>
<small class="text-muted">${item.price.toFixed(2)}</small> <small class="text-muted">${formatCurrency(item.price)}</small>
</td> </td>
<td> <td>
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
@ -252,7 +252,7 @@ function renderCart() {
<button class="btn btn-outline-secondary" onclick="updateQty(${item.id}, 1)">+</button> <button class="btn btn-outline-secondary" onclick="updateQty(${item.id}, 1)">+</button>
</div> </div>
</td> </td>
<td class="text-end fw-bold">${itemTotal.toFixed(2)}</td> <td class="text-end fw-bold">${formatCurrency(itemTotal)}</td>
<td class="text-end"> <td class="text-end">
<button class="btn btn-sm btn-link text-danger p-0" onclick="updateQty(${item.id}, -1000)"><i class="bi bi-trash"></i></button> <button class="btn btn-sm btn-link text-danger p-0" onclick="updateQty(${item.id}, -1000)"><i class="bi bi-trash"></i></button>
</td> </td>
@ -260,9 +260,9 @@ function renderCart() {
`; `;
}); });
cartTotalEl.textContent = total.toFixed(2); cartTotalEl.textContent = formatCurrency(total);
cartCountEl.textContent = cart.length; cartCountEl.textContent = cart.length;
checkoutTotalEl.textContent = total.toFixed(2); checkoutTotalEl.textContent = formatCurrency(total);
if (cart.length === 0) { if (cart.length === 0) {
cartTableBody.innerHTML = '<tr><td colspan="4" class="text-center text-muted py-4"><?php echo __('cart_empty'); ?></td></tr>'; cartTableBody.innerHTML = '<tr><td colspan="4" class="text-center text-muted py-4"><?php echo __('cart_empty'); ?></td></tr>';
@ -282,12 +282,13 @@ function showCheckout() {
function processSale() { function processSale() {
const patientId = $('#patientSelect').val(); const patientId = $('#patientSelect').val();
const paymentMethod = document.querySelector('input[name="payment_method"]:checked').value; const paymentMethod = document.querySelector('input[name="payment_method"]:checked').value;
const total = cart.reduce((sum, item) => sum + (item.quantity * item.price), 0);
const payload = { const payload = {
patient_id: patientId || null, patient_id: patientId || null,
visit_id: null, visit_id: null,
payment_method: paymentMethod, payment_method: paymentMethod,
total_amount: parseFloat(cartTotalEl.textContent), total_amount: total,
items: cart.map(i => ({ items: cart.map(i => ({
drug_id: i.id, drug_id: i.id,
quantity: i.quantity, quantity: i.quantity,

View File

@ -211,7 +211,7 @@ function loadReturns(page = 1) {
<td>${r.id}</td> <td>${r.id}</td>
<td>${r.return_date}</td> <td>${r.return_date}</td>
<td>${r.supplier_name || '-'}</td> <td>${r.supplier_name || '-'}</td>
<td class="fw-bold text-danger">$${parseFloat(r.total_amount).toFixed(2)}</td> <td class="fw-bold text-danger">${formatCurrency(r.total_amount)}</td>
<td>${r.reason || '-'}</td> <td>${r.reason || '-'}</td>
<td> <td>
<button class="btn btn-sm btn-outline-primary" onclick="viewReturn(${r.id}, '${r.supplier_name}', '${r.return_date}', '${r.total_amount}', '${r.reason || ''}')"> <button class="btn btn-sm btn-outline-primary" onclick="viewReturn(${r.id}, '${r.supplier_name}', '${r.return_date}', '${r.total_amount}', '${r.reason || ''}')">
@ -440,7 +440,7 @@ function viewReturn(id, supplier, date, total, reason) {
document.getElementById('view_return_id').innerText = id; document.getElementById('view_return_id').innerText = id;
document.getElementById('view_return_supplier').innerText = supplier; document.getElementById('view_return_supplier').innerText = supplier;
document.getElementById('view_return_date').innerText = date; document.getElementById('view_return_date').innerText = date;
document.getElementById('view_return_total').innerText = '$' + parseFloat(total).toFixed(2); document.getElementById('view_return_total').innerText = formatCurrency(total);
document.getElementById('view_return_reason').innerText = reason; document.getElementById('view_return_reason').innerText = reason;
const tbody = document.getElementById('viewReturnItemsBody'); const tbody = document.getElementById('viewReturnItemsBody');
@ -459,8 +459,8 @@ function viewReturn(id, supplier, date, total, reason) {
<td>${item.drug_name} <small class="text-muted">(${item.sku || '-'})</small></td> <td>${item.drug_name} <small class="text-muted">(${item.sku || '-'})</small></td>
<td>${item.batch_number || '-'}</td> <td>${item.batch_number || '-'}</td>
<td class="text-center">${item.quantity}</td> <td class="text-center">${item.quantity}</td>
<td class="text-end">$${parseFloat(item.unit_price).toFixed(2)}</td> <td class="text-end">${formatCurrency(item.unit_price)}</td>
<td class="text-end">$${parseFloat(item.total_price).toFixed(2)}</td> <td class="text-end">${formatCurrency(item.total_price)}</td>
</tr> </tr>
`; `;
}); });

View File

@ -264,7 +264,7 @@ function loadPurchases(page = 1) {
<td>${p.id}</td> <td>${p.id}</td>
<td>${p.lpo_date}</td> <td>${p.lpo_date}</td>
<td>${p.supplier_name || '-'}</td> <td>${p.supplier_name || '-'}</td>
<td class="fw-bold text-success">$${parseFloat(p.total_amount).toFixed(2)}</td> <td class="fw-bold text-success">${formatCurrency(p.total_amount)}</td>
<td>${statusBadge}</td> <td>${statusBadge}</td>
<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 || ''}')"> <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 || ''}')">
@ -453,7 +453,7 @@ function viewPurchase(id, supplier, date, total, status, notes) {
document.getElementById('view_purchase_id').innerText = id; document.getElementById('view_purchase_id').innerText = id;
document.getElementById('view_purchase_supplier').innerText = supplier; document.getElementById('view_purchase_supplier').innerText = supplier;
document.getElementById('view_purchase_date').innerText = date; document.getElementById('view_purchase_date').innerText = date;
document.getElementById('view_purchase_total').innerText = '$' + parseFloat(total).toFixed(2); document.getElementById('view_purchase_total').innerText = formatCurrency(total);
document.getElementById('view_purchase_status').innerText = status; document.getElementById('view_purchase_status').innerText = status;
document.getElementById('view_purchase_notes').innerText = notes; document.getElementById('view_purchase_notes').innerText = notes;
@ -474,8 +474,8 @@ function viewPurchase(id, supplier, date, total, status, notes) {
<td>${item.batch_number || '-'}</td> <td>${item.batch_number || '-'}</td>
<td>${item.expiry_date || '-'}</td> <td>${item.expiry_date || '-'}</td>
<td class="text-center">${item.quantity}</td> <td class="text-center">${item.quantity}</td>
<td class="text-end">$${parseFloat(item.cost_price).toFixed(2)}</td> <td class="text-end">${formatCurrency(item.cost_price)}</td>
<td class="text-end">$${parseFloat(item.total_cost).toFixed(2)}</td> <td class="text-end">${formatCurrency(item.total_cost)}</td>
</tr> </tr>
`; `;
}); });

View File

@ -72,7 +72,7 @@ $sales = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo $item_count_stmt->fetchColumn() . ' ' . __('items'); echo $item_count_stmt->fetchColumn() . ' ' . __('items');
?> ?>
</td> </td>
<td class="fw-bold"><?php echo number_format($sale['total_amount'], 2); ?></td> <td class="fw-bold"><?php echo format_currency($sale['total_amount']); ?></td>
<td> <td>
<span class="badge bg-light text-dark border"> <span class="badge bg-light text-dark border">
<?php echo ucfirst($sale['payment_method']); ?> <?php echo ucfirst($sale['payment_method']); ?>
@ -171,8 +171,8 @@ function viewReceipt(saleId) {
<tr> <tr>
<td>${item.drug_name}</td> <td>${item.drug_name}</td>
<td class="text-end">${item.quantity}</td> <td class="text-end">${item.quantity}</td>
<td class="text-end">${parseFloat(item.unit_price).toFixed(2)}</td> <td class="text-end">${formatCurrency(item.unit_price)}</td>
<td class="text-end">${parseFloat(item.total_price).toFixed(2)}</td> <td class="text-end">${formatCurrency(item.total_price)}</td>
</tr> </tr>
`; `;
}); });
@ -182,7 +182,7 @@ function viewReceipt(saleId) {
<tfoot> <tfoot>
<tr class="fw-bold"> <tr class="fw-bold">
<td colspan="3" class="text-end pt-3">Total Amount</td> <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> <td class="text-end pt-3 fs-5">${formatCurrency(data.total_amount)}</td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>

View File

@ -43,6 +43,9 @@ $query = "
$stmt = $db->prepare($query); $stmt = $db->prepare($query);
$stmt->execute($params); $stmt->execute($params);
$services = $stmt->fetchAll(); $services = $stmt->fetchAll();
$sys_settings = get_system_settings();
$currency_symbol = $sys_settings['currency_symbol'] ?? '$';
?> ?>
<div class="d-flex justify-content-between align-items-center mb-4"> <div class="d-flex justify-content-between align-items-center mb-4">
@ -113,7 +116,7 @@ $services = $stmt->fetchAll();
</span> </span>
</td> </td>
<td class="fw-bold text-success"> <td class="fw-bold text-success">
<?php echo number_format($s['price'], 2); ?> <?php echo format_currency($s['price']); ?>
</td> </td>
<td> <td>
<?php if ($s['is_active']): ?> <?php if ($s['is_active']): ?>

View File

@ -51,7 +51,7 @@
<input type="text" class="form-control" id="company_vat_no" name="company_vat_no" value="<?php echo htmlspecialchars($settings['company_vat_no'] ?? ''); ?>"> <input type="text" class="form-control" id="company_vat_no" name="company_vat_no" value="<?php echo htmlspecialchars($settings['company_vat_no'] ?? ''); ?>">
</div> </div>
<!-- Timezone & Working Hours --> <!-- Timezone & Working Hours -->
<div class="col-12 mt-4"><hr></div> <div class="col-12 mt-4"><hr></div>
<div class="col-md-4"> <div class="col-md-4">
<label for="timezone" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('timezone'); ?></label> <label for="timezone" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('timezone'); ?></label>
@ -75,8 +75,23 @@
<input type="time" class="form-control" id="working_hours_end" name="working_hours_end" value="<?php echo htmlspecialchars($settings['working_hours_end'] ?? '17:00'); ?>"> <input type="time" class="form-control" id="working_hours_end" name="working_hours_end" value="<?php echo htmlspecialchars($settings['working_hours_end'] ?? '17:00'); ?>">
</div> </div>
<!-- Currency Settings -->
<div class="col-12 mt-4"><hr></div>
<div class="col-12 mb-2">
<h6 class="fw-bold text-dark"><i class="bi bi-cash-coin me-2"></i> <?php echo __('currency_settings'); ?></h6>
</div>
<div class="col-md-6">
<label for="currency_symbol" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('currency_symbol'); ?></label>
<input type="text" class="form-control" id="currency_symbol" name="currency_symbol" value="<?php echo htmlspecialchars($settings['currency_symbol'] ?? '$'); ?>" placeholder="$">
</div>
<div class="col-md-6">
<label for="decimal_digits" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('decimal_digits'); ?></label>
<input type="number" class="form-control" id="decimal_digits" name="decimal_digits" value="<?php echo htmlspecialchars($settings['decimal_digits'] ?? '2'); ?>" min="0" max="4">
</div>
<!-- Branding --> <!-- Branding -->
<div class="col-md-6 mt-5"> <div class="col-12 mt-4"><hr></div>
<div class="col-md-6 mt-2">
<label for="company_logo" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_logo'); ?></label> <label for="company_logo" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_logo'); ?></label>
<?php if (!empty($settings['company_logo'])): ?> <?php if (!empty($settings['company_logo'])): ?>
<div class="mb-2"> <div class="mb-2">
@ -85,7 +100,7 @@
<?php endif; ?> <?php endif; ?>
<input type="file" class="form-control" id="company_logo" name="company_logo" accept="image/*"> <input type="file" class="form-control" id="company_logo" name="company_logo" accept="image/*">
</div> </div>
<div class="col-md-6 mt-5"> <div class="col-md-6 mt-2">
<label for="company_favicon" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_favicon'); ?></label> <label for="company_favicon" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_favicon'); ?></label>
<?php if (!empty($settings['company_favicon'])): ?> <?php if (!empty($settings['company_favicon'])): ?>
<div class="mb-2"> <div class="mb-2">

View File

@ -41,6 +41,9 @@ $tests = $stmt->fetchAll();
// Fetch all xray groups for the dropdown // Fetch all xray groups for the dropdown
$all_xray_groups_list = $db->query("SELECT id, name_$lang as name FROM xray_groups ORDER BY name_$lang ASC")->fetchAll(); $all_xray_groups_list = $db->query("SELECT id, name_$lang as name FROM xray_groups ORDER BY name_$lang ASC")->fetchAll();
$sys_settings = get_system_settings();
$currency_symbol = $sys_settings['currency_symbol'] ?? '$';
// --- AJAX HANDLER --- // --- AJAX HANDLER ---
if (isset($_GET['ajax_search'])) { if (isset($_GET['ajax_search'])) {
ob_start(); ob_start();
@ -72,7 +75,7 @@ if (isset($_GET['ajax_search'])) {
<?php echo htmlspecialchars($test['group_name'] ?? '-'); ?> <?php echo htmlspecialchars($test['group_name'] ?? '-'); ?>
</span> </span>
</td> </td>
<td class="text-secondary fw-bold"><?php echo number_format($test['price'], 2); ?></td> <td class="text-secondary fw-bold"><?php echo format_currency($test['price']); ?></td>
<td class="text-end px-4"> <td class="text-end px-4">
<div class="btn-group shadow-sm border rounded bg-white"> <div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end" <button class="btn btn-link text-primary py-1 px-2 border-end"
@ -222,7 +225,7 @@ if (isset($_GET['ajax_search'])) {
<?php echo htmlspecialchars($test['group_name'] ?? '-'); ?> <?php echo htmlspecialchars($test['group_name'] ?? '-'); ?>
</span> </span>
</td> </td>
<td class="text-secondary fw-bold"><?php echo number_format($test['price'], 2); ?></td> <td class="text-secondary fw-bold"><?php echo format_currency($test['price']); ?></td>
<td class="text-end px-4"> <td class="text-end px-4">
<div class="btn-group shadow-sm border rounded bg-white"> <div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end" <button class="btn btn-link text-primary py-1 px-2 border-end"
@ -332,7 +335,7 @@ if (isset($_GET['ajax_search'])) {
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label"><?php echo __('price'); ?></label> <label class="form-label"><?php echo __('price'); ?></label>
<div class="input-group"> <div class="input-group">
<span class="input-group-text">$</span> <span class="input-group-text"><?php echo htmlspecialchars($currency_symbol); ?></span>
<input type="number" step="0.01" class="form-control" name="price" id="xrayTestPrice"> <input type="number" step="0.01" class="form-control" name="price" id="xrayTestPrice">
</div> </div>
</div> </div>

View File

@ -8,6 +8,12 @@ $lang = $_SESSION['lang'];
require_once __DIR__ . '/includes/actions.php'; require_once __DIR__ . '/includes/actions.php';
require_once __DIR__ . '/includes/common_data.php'; require_once __DIR__ . '/includes/common_data.php';
if (isset($_GET['ajax_search'])) {
require_once __DIR__ . '/includes/pages/insurance.php';
exit;
}
require_once __DIR__ . '/includes/layout/header.php'; require_once __DIR__ . '/includes/layout/header.php';
require_once __DIR__ . '/includes/pages/insurance.php'; require_once __DIR__ . '/includes/pages/insurance.php';
require_once __DIR__ . '/includes/layout/footer.php'; require_once __DIR__ . '/includes/layout/footer.php';

View File

@ -331,6 +331,7 @@ $translations = [
'payment_method' => 'Payment Method', 'payment_method' => 'Payment Method',
'cash' => 'Cash', 'cash' => 'Cash',
'card' => 'Card', 'card' => 'Card',
'insurance' => 'Insurance',
'receipt' => 'Receipt', 'receipt' => 'Receipt',
'total_amount' => 'Total Amount', 'total_amount' => 'Total Amount',
'quantity' => 'Quantity', 'quantity' => 'Quantity',
@ -341,6 +342,8 @@ $translations = [
'out_of_stock' => 'Out of Stock', 'out_of_stock' => 'Out of Stock',
'low_stock' => 'Low Stock', 'low_stock' => 'Low Stock',
'in_stock' => 'In Stock', 'in_stock' => 'In Stock',
'waiting' => 'Waiting',
'serving' => 'Serving',
'CheckIn' => 'Check In', 'CheckIn' => 'Check In',
'In Progress' => 'In Progress', 'In Progress' => 'In Progress',
'in_progress' => 'In Progress', 'in_progress' => 'In Progress',
@ -398,7 +401,29 @@ $translations = [
'receive_warning_msg' => 'Receiving this purchase will add items to stock.', 'receive_warning_msg' => 'Receiving this purchase will add items to stock.',
'ensure_batch_expiry_msg' => 'Ensure Batch Numbers and Expiry Dates are correct.', 'ensure_batch_expiry_msg' => 'Ensure Batch Numbers and Expiry Dates are correct.',
'confirm_received' => 'Confirm Received', 'confirm_received' => 'Confirm Received',
'purchase_report' => 'Purchase Report' 'purchase_report' => 'Purchase Report',
'currency_settings' => 'Currency Settings',
'currency_symbol' => 'Currency Symbol',
'decimal_digits' => 'Decimal Digits',
'statement' => 'Statement',
'print_statement' => 'Print Statement',
'insurance_transactions' => 'Insurance Transactions',
'add_transaction' => 'Add Transaction',
'edit_transaction' => 'Edit Transaction',
'delete_transaction' => 'Delete Transaction',
'payment_date' => 'Payment Date',
'reference_number' => 'Reference Number',
'no_transactions_found' => 'No transactions found',
'confirm_delete_transaction' => 'Are you sure you want to delete this transaction?',
'transaction_added_success' => 'Transaction added successfully',
'transaction_updated_success' => 'Transaction updated successfully',
'transaction_deleted_success' => 'Transaction deleted successfully',
'payment_method_check' => 'Check',
'payment_method_transfer' => 'Bank Transfer',
'payment_method_cash' => 'Cash',
'payment_method_card' => 'Credit Card',
'transactions' => 'Transactions',
'companies' => 'Companies'
], ],
'ar' => [ 'ar' => [
'attachment' => 'المرفق', 'attachment' => 'المرفق',
@ -617,7 +642,7 @@ $translations = [
'company_logo' => 'شعار الشركة', 'company_logo' => 'شعار الشركة',
'company_favicon' => 'أيقونة الشركة', 'company_favicon' => 'أيقونة الشركة',
'save_changes' => 'حفظ التغييرات', 'save_changes' => 'حفظ التغييرات',
'settings_updated_successfully' => 'Settings updated successfully', 'settings_updated_successfully' => 'تم تحديث الإعدادات بنجاح',
'prescriptions' => 'الوصفات الطبية', 'prescriptions' => 'الوصفات الطبية',
'add_drug' => 'إضافة دواء', 'add_drug' => 'إضافة دواء',
'drug_name' => 'اسم الدواء', 'drug_name' => 'اسم الدواء',
@ -813,6 +838,28 @@ $translations = [
'receive_warning_msg' => 'استلام هذا الشراء سيضيف العناصر إلى المخزون.', 'receive_warning_msg' => 'استلام هذا الشراء سيضيف العناصر إلى المخزون.',
'ensure_batch_expiry_msg' => 'تأكد من صحة أرقام التشغيلات وتواريخ الانتهاء.', 'ensure_batch_expiry_msg' => 'تأكد من صحة أرقام التشغيلات وتواريخ الانتهاء.',
'confirm_received' => 'تأكيد الاستلام', 'confirm_received' => 'تأكيد الاستلام',
'purchase_report' => 'تقرير المشتريات' 'purchase_report' => 'تقرير المشتريات',
'currency_settings' => 'إعدادات العملة',
'currency_symbol' => 'رمز العملة',
'decimal_digits' => 'الأرقام العشرية',
'statement' => 'كشف حساب',
'print_statement' => 'طباعة كشف حساب',
'insurance_transactions' => 'معاملات التأمين',
'add_transaction' => 'إضافة معاملة',
'edit_transaction' => 'تعديل معاملة',
'delete_transaction' => 'حذف معاملة',
'payment_date' => 'تاريخ الدفع',
'reference_number' => 'رقم المرجع',
'no_transactions_found' => 'لم يتم العثور على معاملات',
'confirm_delete_transaction' => 'هل أنت متأكد من حذف هذه المعاملة؟',
'transaction_added_success' => 'تم إضافة المعاملة بنجاح',
'transaction_updated_success' => 'تم تحديث المعاملة بنجاح',
'transaction_deleted_success' => 'تم حذف المعاملة بنجاح',
'payment_method_check' => 'شيك',
'payment_method_transfer' => 'تحويل بنكي',
'payment_method_cash' => 'نقدي',
'payment_method_card' => 'بطاقة ائتمان',
'transactions' => 'المعاملات',
'companies' => 'الشركات'
] ]
]; ];

View File

@ -145,24 +145,24 @@ try {
<tr> <tr>
<td class="text-center"><?php echo $i++; ?></td> <td class="text-center"><?php echo $i++; ?></td>
<td><?php echo htmlspecialchars($item['description']); ?></td> <td><?php echo htmlspecialchars($item['description']); ?></td>
<td class="text-end">$<?php echo number_format($item['amount'], 2); ?></td> <td class="text-end"><?php echo format_currency($item['amount']); ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
<tfoot> <tfoot>
<tr> <tr>
<td colspan="2" class="text-end fw-bold">Total Amount</td> <td colspan="2" class="text-end fw-bold">Total Amount</td>
<td class="text-end fw-bold">$<?php echo number_format($bill['total_amount'], 2); ?></td> <td class="text-end fw-bold"><?php echo format_currency($bill['total_amount']); ?></td>
</tr> </tr>
<?php if ($bill['insurance_covered'] > 0): ?> <?php if ($bill['insurance_covered'] > 0): ?>
<tr> <tr>
<td colspan="2" class="text-end text-success">Insurance Covered</td> <td colspan="2" class="text-end text-success">Insurance Covered</td>
<td class="text-end text-success">-$<?php echo number_format($bill['insurance_covered'], 2); ?></td> <td class="text-end text-success">- <?php echo format_currency($bill['insurance_covered']); ?></td>
</tr> </tr>
<?php endif; ?> <?php endif; ?>
<tr> <tr>
<td colspan="2" class="text-end fw-bold fs-5">Patient Due</td> <td colspan="2" class="text-end fw-bold fs-5">Patient Due</td>
<td class="text-end fw-bold fs-5">$<?php echo number_format($bill['patient_payable'], 2); ?></td> <td class="text-end fw-bold fs-5"><?php echo format_currency($bill['patient_payable']); ?></td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>

View File

@ -0,0 +1,191 @@
<?php
require 'db/config.php';
require 'helpers.php';
// Enable error reporting
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
try {
$db = db();
$insurance_id = $_GET['id'] ?? 0;
$start_date = $_GET['start_date'] ?? date('Y-m-01');
$end_date = $_GET['end_date'] ?? date('Y-m-d');
if (!$insurance_id) {
throw new Exception("Invalid Insurance Company ID");
}
// Fetch Insurance Company Details
$stmt = $db->prepare("SELECT * FROM insurance_companies WHERE id = ?");
$stmt->execute([$insurance_id]);
$insurance = $stmt->fetch();
if (!$insurance) {
throw new Exception("Insurance Company not found");
}
// Fetch Linked Bills
// Linking via patients table: bills -> patients -> insurance_company_id
$query = "
SELECT
b.*,
p.name as patient_name,
p.policy_number,
p.civil_id,
d.name_en as doctor_name_en
FROM bills b
JOIN patients p ON b.patient_id = p.id
LEFT JOIN visits v ON b.visit_id = v.id
LEFT JOIN doctors d ON v.doctor_id = d.id
WHERE p.insurance_company_id = ?
AND b.insurance_covered > 0
AND DATE(b.created_at) BETWEEN ? AND ?
ORDER BY b.created_at DESC
";
$stmt = $db->prepare($query);
$stmt->execute([$insurance_id, $start_date, $end_date]);
$bills = $stmt->fetchAll();
// Calculate Totals
$total_claim = 0;
foreach ($bills as $bill) {
$total_claim += $bill['insurance_covered'];
}
// Fetch Company Settings (Logo, Address, etc.)
$stmt = $db->query("SELECT * FROM settings WHERE id = 1");
$settings = $stmt->fetch();
$lang = $_SESSION['lang'] ?? 'en';
} catch (Exception $e) {
die("Error: " . $e->getMessage());
}
?>
<!DOCTYPE html>
<html lang="<?php echo $lang; ?>" dir="<?php echo $lang == 'ar' ? 'rtl' : 'ltr'; ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Statement - <?php echo htmlspecialchars($insurance['name_en']); ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: 'Times New Roman', Times, serif; color: #333; }
.invoice-header { border-bottom: 2px solid #ddd; padding-bottom: 20px; margin-bottom: 30px; }
.invoice-footer { border-top: 2px solid #ddd; padding-top: 20px; margin-top: 50px; }
.company-logo { max-height: 80px; }
.invoice-title { font-size: 2rem; color: #555; text-transform: uppercase; letter-spacing: 2px; }
.table thead th { border-bottom: 2px solid #333; background-color: #f8f9fa; }
.table-bordered td, .table-bordered th { border-color: #dee2e6; }
@media print {
.no-print { display: none !important; }
body { padding: 20px; background: white; }
.card { border: none !important; box-shadow: none !important; }
}
</style>
</head>
<body onload="window.print()">
<div class="container my-5">
<div class="no-print mb-4 text-end">
<button onclick="window.print()" class="btn btn-primary"><i class="bi bi-printer"></i> <?php echo __('print'); ?></button>
<button onclick="window.close()" class="btn btn-secondary"><?php echo __('close'); ?></button>
</div>
<div class="card p-4">
<!-- Header -->
<div class="invoice-header">
<div class="row align-items-center">
<div class="col-6">
<?php if (!empty($settings['company_logo'])): ?>
<img src="<?php echo htmlspecialchars($settings['company_logo']); ?>" alt="Logo" class="company-logo mb-2">
<?php else: ?>
<h2 class="fw-bold m-0"><?php echo htmlspecialchars($settings['company_name'] ?? 'Hospital Name'); ?></h2>
<?php endif; ?>
<div class="small text-muted">
<?php echo htmlspecialchars($settings['company_address'] ?? '123 Medical Center St.'); ?><br>
<?php echo __('phone'); ?>: <?php echo htmlspecialchars($settings['company_phone'] ?? '+123 456 7890'); ?><br>
<?php echo __('email'); ?>: <?php echo htmlspecialchars($settings['company_email'] ?? 'info@hospital.com'); ?>
</div>
</div>
<div class="col-6 text-end">
<h1 class="invoice-title"><?php echo __('statement'); ?></h1>
<p class="lead mb-0"><?php echo htmlspecialchars($insurance['name_en']); ?></p>
<p class="text-muted small">
<?php echo __('date'); ?>: <?php echo date('d M Y', strtotime($start_date)); ?> - <?php echo date('d M Y', strtotime($end_date)); ?>
</p>
</div>
</div>
</div>
<!-- Insurance Details -->
<div class="row mb-4">
<div class="col-12">
<h6 class="text-uppercase text-muted small fw-bold mb-2"><?php echo __('insurance_company'); ?>:</h6>
<h5 class="fw-bold mb-1"><?php echo htmlspecialchars($insurance['name_en']); ?></h5>
<p class="mb-0 text-muted">
<?php if ($insurance['phone']) echo __('phone') . ': ' . htmlspecialchars($insurance['phone']) . '<br>'; ?>
<?php if ($insurance['email']) echo __('email') . ': ' . htmlspecialchars($insurance['email']); ?>
</p>
</div>
</div>
<!-- Bills Table -->
<table class="table table-bordered mb-4">
<thead>
<tr>
<th class="text-center" width="50">#</th>
<th><?php echo __('date'); ?></th>
<th><?php echo __('patient'); ?></th>
<th><?php echo __('policy_number'); ?></th>
<th><?php echo __('doctor'); ?></th>
<th class="text-end"><?php echo __('total_amount'); ?></th>
<th class="text-end"><?php echo __('insurance_covered'); ?></th>
</tr>
</thead>
<tbody>
<?php if (empty($bills)): ?>
<tr>
<td colspan="7" class="text-center py-4 text-muted"><?php echo __('no_records_found'); ?></td>
</tr>
<?php else: ?>
<?php $i = 1; foreach ($bills as $bill): ?>
<tr>
<td class="text-center"><?php echo $i++; ?></td>
<td><?php echo date('Y-m-d', strtotime($bill['created_at'])); ?></td>
<td>
<?php echo htmlspecialchars($bill['patient_name']); ?>
<?php if ($bill['civil_id']): ?>
<br><small class="text-muted"><?php echo htmlspecialchars($bill['civil_id']); ?></small>
<?php endif; ?>
</td>
<td><?php echo htmlspecialchars($bill['policy_number'] ?: '-'); ?></td>
<td><?php echo htmlspecialchars($bill['doctor_name_en'] ?: '-'); ?></td>
<td class="text-end"><?php echo format_currency($bill['total_amount']); ?></td>
<td class="text-end fw-bold"><?php echo format_currency($bill['insurance_covered']); ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
<tfoot>
<tr class="table-light">
<td colspan="6" class="text-end fw-bold fs-5"><?php echo __('total'); ?></td>
<td class="text-end fw-bold fs-5"><?php echo format_currency($total_claim); ?></td>
</tr>
</tfoot>
</table>
<!-- Footer -->
<div class="invoice-footer text-center small text-muted">
<p class="mb-1">Thank you for your partnership!</p>
<p>Generated on <?php echo date('Y-m-d H:i:s'); ?></p>
</div>
</div>
</div>
</body>
</html>

View File

@ -48,8 +48,11 @@ try {
$items = $stmt->fetchAll(); $items = $stmt->fetchAll();
// Fetch Company Settings (Logo, Address, etc.) // Fetch Company Settings (Logo, Address, etc.)
$stmt = $db->query("SELECT * FROM settings WHERE id = 1"); $stmt = $db->query("SELECT setting_key, setting_value FROM settings");
$settings = $stmt->fetch(); $settings = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$settings[$row['setting_key']] = $row['setting_value'];
}
} catch (Exception $e) { } catch (Exception $e) {
die("Error: " . $e->getMessage()); die("Error: " . $e->getMessage());
@ -178,8 +181,8 @@ try {
<?php endif; ?> <?php endif; ?>
</td> </td>
<td class="text-center"><?php echo $item['quantity']; ?></td> <td class="text-center"><?php echo $item['quantity']; ?></td>
<td class="text-end"><?php echo number_format($item['unit_price'], 2); ?></td> <td class="text-end"><?php echo format_currency($item['unit_price']); ?></td>
<td class="text-end"><?php echo number_format($item['total_price'], 2); ?></td> <td class="text-end"><?php echo format_currency($item['total_price']); ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
@ -189,7 +192,7 @@ try {
TOTAL / الإجمالي TOTAL / الإجمالي
</td> </td>
<td class="text-end fw-bold fs-5"> <td class="text-end fw-bold fs-5">
<?php echo number_format($sale['total_amount'], 2); ?> <?php echo format_currency($sale['total_amount']); ?>
</td> </td>
</tr> </tr>
</tfoot> </tfoot>

View File

@ -209,17 +209,17 @@ if ($type === 'inventory_valuation') {
<td><?php echo htmlspecialchars($row['drug_name']); ?></td> <td><?php echo htmlspecialchars($row['drug_name']); ?></td>
<td><?php echo htmlspecialchars($row['category_name'] ?? '-'); ?></td> <td><?php echo htmlspecialchars($row['category_name'] ?? '-'); ?></td>
<td><?php echo $row['stock_quantity']; ?></td> <td><?php echo $row['stock_quantity']; ?></td>
<td><?php echo number_format($row['avg_cost'], 2); ?></td> <td><?php echo format_currency($row['avg_cost']); ?></td>
<td><?php echo number_format($row['selling_price'], 2); ?></td> <td><?php echo format_currency($row['selling_price']); ?></td>
<td><?php echo number_format($row['total_cost_value'], 2); ?></td> <td><?php echo format_currency($row['total_cost_value']); ?></td>
<td><?php echo number_format($row['total_sales_value'], 2); ?></td> <td><?php echo format_currency($row['total_sales_value']); ?></td>
<?php elseif ($type === 'sales'): ?> <?php elseif ($type === 'sales'): ?>
<td><?php echo $row['created_at']; ?></td> <td><?php echo $row['created_at']; ?></td>
<td>#<?php echo $row['id']; ?></td> <td>#<?php echo $row['id']; ?></td>
<td><?php echo htmlspecialchars($row['patient_name'] ?? 'Guest'); ?></td> <td><?php echo htmlspecialchars($row['patient_name'] ?? 'Guest'); ?></td>
<td><?php echo $row['item_count']; ?></td> <td><?php echo $row['item_count']; ?></td>
<td><?php echo number_format($row['total_amount'], 2); ?></td> <td><?php echo format_currency($row['total_amount']); ?></td>
<td><?php echo htmlspecialchars($row['payment_method']); ?></td> <td><?php echo htmlspecialchars($row['payment_method']); ?></td>
<?php elseif ($type === 'expiry'): ?> <?php elseif ($type === 'expiry'): ?>
@ -242,7 +242,7 @@ if ($type === 'inventory_valuation') {
<td>#<?php echo $row['id']; ?></td> <td>#<?php echo $row['id']; ?></td>
<td><?php echo htmlspecialchars($row['supplier_name'] ?? '-'); ?></td> <td><?php echo htmlspecialchars($row['supplier_name'] ?? '-'); ?></td>
<td><?php echo htmlspecialchars($row['status']); ?></td> <td><?php echo htmlspecialchars($row['status']); ?></td>
<td><?php echo number_format($row['total_amount'], 2); ?></td> <td><?php echo format_currency($row['total_amount']); ?></td>
<?php endif; ?> <?php endif; ?>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
@ -255,18 +255,18 @@ if ($type === 'inventory_valuation') {
<?php if ($type === 'inventory_valuation'): ?> <?php if ($type === 'inventory_valuation'): ?>
<tr class="fw-bold"> <tr class="fw-bold">
<td colspan="5" class="text-end"><?php echo __('grand_total'); ?>:</td> <td colspan="5" class="text-end"><?php echo __('grand_total'); ?>:</td>
<td><?php echo number_format($grandTotals['total_cost'] ?? 0, 2); ?></td> <td><?php echo format_currency($grandTotals['total_cost'] ?? 0); ?></td>
<td><?php echo number_format($grandTotals['total_sales'] ?? 0, 2); ?></td> <td><?php echo format_currency($grandTotals['total_sales'] ?? 0); ?></td>
</tr> </tr>
<?php elseif ($type === 'sales'): ?> <?php elseif ($type === 'sales'): ?>
<tr class="fw-bold"> <tr class="fw-bold">
<td colspan="4" class="text-end"><?php echo __('grand_total'); ?>:</td> <td colspan="4" class="text-end"><?php echo __('grand_total'); ?>:</td>
<td colspan="2"><?php echo number_format($grandTotals['total_sales'] ?? 0, 2); ?></td> <td colspan="2"><?php echo format_currency($grandTotals['total_sales'] ?? 0); ?></td>
</tr> </tr>
<?php elseif ($type === 'purchase_report'): ?> <?php elseif ($type === 'purchase_report'): ?>
<tr class="fw-bold"> <tr class="fw-bold">
<td colspan="4" class="text-end"><?php echo __('grand_total'); ?>:</td> <td colspan="4" class="text-end"><?php echo __('grand_total'); ?>:</td>
<td><?php echo number_format($grandTotals['total_purchases'] ?? 0, 2); ?></td> <td><?php echo format_currency($grandTotals['total_purchases'] ?? 0); ?></td>
</tr> </tr>
<?php endif; ?> <?php endif; ?>
</tfoot> </tfoot>

View File

@ -10,8 +10,9 @@ $message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
foreach ($_POST as $key => $value) { foreach ($_POST as $key => $value) {
if ($key !== 'submit') { if ($key !== 'submit') {
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = ?"); // Use INSERT ... ON DUPLICATE KEY UPDATE to handle both new and existing settings
$stmt->execute([$value, $key]); $stmt = $db->prepare("INSERT INTO settings (setting_key, setting_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)");
$stmt->execute([$key, $value]);
} }
} }
@ -25,7 +26,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$ext = pathinfo($_FILES['company_logo']['name'], PATHINFO_EXTENSION); $ext = pathinfo($_FILES['company_logo']['name'], PATHINFO_EXTENSION);
$logo_name = 'logo_' . time() . '.' . $ext; $logo_name = 'logo_' . time() . '.' . $ext;
move_uploaded_file($_FILES['company_logo']['tmp_name'], $upload_dir . $logo_name); move_uploaded_file($_FILES['company_logo']['tmp_name'], $upload_dir . $logo_name);
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = 'company_logo'");
$stmt = $db->prepare("INSERT INTO settings (setting_key, setting_value) VALUES ('company_logo', ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)");
$stmt->execute(['assets/images/' . $logo_name]); $stmt->execute(['assets/images/' . $logo_name]);
} }
@ -33,7 +35,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$ext = pathinfo($_FILES['company_favicon']['name'], PATHINFO_EXTENSION); $ext = pathinfo($_FILES['company_favicon']['name'], PATHINFO_EXTENSION);
$favicon_name = 'favicon_' . time() . '.' . $ext; $favicon_name = 'favicon_' . time() . '.' . $ext;
move_uploaded_file($_FILES['company_favicon']['tmp_name'], $upload_dir . $favicon_name); move_uploaded_file($_FILES['company_favicon']['tmp_name'], $upload_dir . $favicon_name);
$stmt = $db->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = 'company_favicon'");
$stmt = $db->prepare("INSERT INTO settings (setting_key, setting_value) VALUES ('company_favicon', ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)");
$stmt->execute(['assets/images/' . $favicon_name]); $stmt->execute(['assets/images/' . $favicon_name]);
} }