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:
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.
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.
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.
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.
1. **Investigate:** Checked Apache error logs and `includes/actions.php`.
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. **Fix:** Created and applied a migration to add the `payment_method` column to the `insurance_payments` table.
4. **Verify:** Confirmed the column now exists in the database.
Changed:
* `includes/actions.php`: Fixed a syntax error and correctly implemented the token generation logic.
* `includes/layout/footer.php`: Added the "Issue Token" checkbox to the "Details" tab of the `recordVisitModal`.
Changed Files:
* `db/migrations/20260321_z_add_payment_method_to_insurance_payments.sql`: Added migration to fix the schema.
Notes:
* The application should now load correctly without the 500 error.
* To use the token system:
1. **Receptionist:** When adding a new visit, check the **"Issue Token"** box in the "Details" tab.
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!
Next Steps:
* Go to **Insurance > Transactions**.
* Try adding a transaction again. It should work now.
* **Reminder:** Click Save in the editor to sync changes.

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
$SYSTEM_SETTINGS = null;
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)) {
require_once __DIR__ . '/db/config.php';
$local_db = db();
} else {
$local_db = $db;
}
try {
$stmt = $local_db->query('SELECT setting_key, setting_value FROM settings');
$settings = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$settings[$row['setting_key']] = $row['setting_value'];
}
$SYSTEM_SETTINGS = $settings;
return $settings;
} catch (Exception $e) {
return [];
}
}
function apply_timezone() {
$s = get_system_settings();
if (!empty($s['timezone'])) {
@ -27,6 +37,13 @@ function 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();
require_once __DIR__ . '/lang.php';

View File

@ -1,5 +1,5 @@
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') {
require_once __DIR__ . '/../db/config.php';
require_once __DIR__ . '/../helpers.php';
$db = db();
@ -1130,6 +1130,78 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$_SESSION['flash_message'] = __('delete') . ' ' . __('successfully');
$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 -->
<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>
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; }

View File

@ -82,9 +82,9 @@ $bills = $stmt->fetchAll();
<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="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-primary">$<?php echo number_format($b['insurance_covered'], 2); ?></td>
<td class="fw-bold text-dark">$<?php echo number_format($b['patient_payable'], 2); ?></td>
<td class="text-dark"><?php echo format_currency($b['total_amount']); ?></td>
<td class="text-primary"><?php echo format_currency($b['insurance_covered']); ?></td>
<td class="fw-bold text-dark"><?php echo format_currency($b['patient_payable']); ?></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">
<?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="card stat-card h-100">
<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>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card stat-card h-100">
<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>
</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">
<option value=""><?php echo __('select_service'); ?>...</option>
<?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 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; ?>
</select>
</div>
@ -557,14 +557,14 @@ $appointments = $db->query($appointments_sql)->fetchAll();
<div class="col-md-4">
<label class="form-label small text-muted">Insurance Pays</label>
<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>
</div>
</div>
<div class="col-md-4">
<label class="form-label small text-muted fw-bold text-dark">Patient Pays</label>
<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>
</div>
</div>
@ -646,7 +646,7 @@ document.addEventListener('DOMContentLoaded', function() {
var text = element.text();
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;
}
});
@ -790,7 +790,7 @@ function renderBillItems(items) {
tbody.innerHTML += `
<tr>
<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">
<button class="btn btn-sm btn-link text-danger p-0" onclick="removeBillItem(${item.id})"><i class="bi bi-x-lg"></i></button>
</td>
@ -799,7 +799,7 @@ function renderBillItems(items) {
});
currentTotal = total;
document.getElementById('checkout_total_amount').innerText = '$' + total.toFixed(2);
document.getElementById('checkout_total_amount').innerText = formatCurrency(total);
calculateTotals();
}

View File

@ -48,6 +48,9 @@ $all_drug_groups = $gStmt->fetchAll();
$sStmt = $db->query("SELECT * FROM suppliers ORDER BY name_$lang");
$all_suppliers = $sStmt->fetchAll();
$sys_settings = get_system_settings();
$currency_symbol = $sys_settings['currency_symbol'] ?? '$';
// --- AJAX HANDLER ---
if (isset($_GET['ajax_search'])) {
ob_start();
@ -81,7 +84,7 @@ if (isset($_GET['ajax_search'])) {
</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-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">
<div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end"
@ -240,7 +243,7 @@ if (isset($_GET['ajax_search'])) {
</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-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">
<div class="btn-group shadow-sm border rounded bg-white">
<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">
<label class="form-label"><?php echo __('price'); ?></label>
<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">
</div>
</div>

View File

@ -1,4 +1,5 @@
<?php
// --- Companies Logic ---
$search_name = $_GET['name'] ?? '';
$search_phone = $_GET['phone'] ?? '';
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1;
@ -18,26 +19,167 @@ if ($search_phone) {
$params[] = "%$search_phone%";
}
// Count Total
// Count Total Companies
$countQuery = "SELECT COUNT(*) FROM insurance_companies $where";
$stmt = $db->prepare($countQuery);
$stmt->execute($params);
$totalInsurance = $stmt->fetchColumn();
$totalPages = ceil($totalInsurance / $limit);
// Fetch Data
// Fetch Companies
$query = "SELECT * FROM insurance_companies $where ORDER BY id DESC LIMIT $limit OFFSET $offset";
$stmt = $db->prepare($query);
$stmt->execute($params);
$insurance_companies = $stmt->fetchAll();
// --- Transactions Logic ---
$trans_page = isset($_GET['trans_page']) && is_numeric($_GET['trans_page']) ? (int)$_GET['trans_page'] : 1;
$trans_limit = 10;
$trans_offset = ($trans_page - 1) * $trans_limit;
$trans_where = "WHERE 1=1";
$trans_params = [];
$trans_company_id = $_GET['trans_company_id'] ?? '';
$trans_start_date = $_GET['trans_start_date'] ?? '';
$trans_end_date = $_GET['trans_end_date'] ?? '';
if ($trans_company_id) {
$trans_where .= " AND t.insurance_company_id = ?";
$trans_params[] = $trans_company_id;
}
if ($trans_start_date) {
$trans_where .= " AND t.payment_date >= ?";
$trans_params[] = $trans_start_date;
}
if ($trans_end_date) {
$trans_where .= " AND t.payment_date <= ?";
$trans_params[] = $trans_end_date;
}
// Count Transactions
$countTransQuery = "SELECT COUNT(*) FROM insurance_payments t $trans_where";
$stmt = $db->prepare($countTransQuery);
$stmt->execute($trans_params);
$totalTrans = $stmt->fetchColumn();
$totalTransPages = ceil($totalTrans / $trans_limit);
// Fetch Transactions
$transQuery = "SELECT t.*, c.name_$lang as company_name
FROM insurance_payments t
LEFT JOIN insurance_companies c ON t.insurance_company_id = c.id
$trans_where
ORDER BY t.payment_date DESC, t.id DESC
LIMIT $trans_limit OFFSET $trans_offset";
$stmt = $db->prepare($transQuery);
$stmt->execute($trans_params);
$transactions = $stmt->fetchAll();
// --- AJAX HANDLER ---
if (isset($_GET['ajax_search'])) {
header('Content-Type: application/json');
ob_start();
if (empty($insurance_companies)):
?>
if (isset($_GET['tab']) && $_GET['tab'] === 'transactions') {
if (empty($transactions)): ?>
<tr>
<td colspan="6" class="text-center py-5 text-muted">
<td colspan="8" class="text-center py-5 text-muted">
<i class="bi bi-cash-stack display-4 d-block mb-3"></i>
<?php echo __('no_transactions_found'); ?>
</td>
</tr>
<?php else: ?>
<?php foreach ($transactions as $t): ?>
<tr>
<td class="px-4 text-secondary">#<?php echo $t['id']; ?></td>
<td class="fw-semibold text-dark"><?php echo date('Y-m-d', strtotime($t['payment_date'])); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($t['company_name']); ?></td>
<td class="text-dark fw-bold"><?php echo format_currency($t['amount']); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($t['reference_number'] ?: '-'); ?></td>
<td class="text-secondary">
<?php
$method_key = 'payment_method_' . strtolower(str_replace(' ', '_', $t['payment_method']));
echo __($method_key) !== $method_key ? __($method_key) : $t['payment_method'];
?>
</td>
<td class="text-muted small text-truncate" style="max-width: 150px;" title="<?php echo htmlspecialchars($t['notes']); ?>">
<?php echo htmlspecialchars($t['notes'] ?: '-'); ?>
</td>
<td class="text-end px-4">
<button class="btn btn-sm btn-light text-primary me-1"
onclick='openEditTransactionModal(<?php echo json_encode($t); ?>)'
title="<?php echo __('edit'); ?>">
<i class="bi bi-pencil"></i>
</button>
<button class="btn btn-sm btn-light text-danger"
onclick="deleteTransaction(<?php echo $t['id']; ?>)"
title="<?php echo __('delete'); ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif;
$table_html = ob_get_clean();
ob_start();
if ($totalTransPages > 1): ?>
<div class="d-flex justify-content-between align-items-center p-3 border-top">
<div class="text-muted small">
<?php echo __('showing'); ?> <?php echo $trans_offset + 1; ?> - <?php echo min($trans_offset + $trans_limit, $totalTrans); ?> <?php echo __('of'); ?> <?php echo $totalTrans; ?>
</div>
<nav aria-label="Page navigation">
<ul class="pagination pagination-sm mb-0">
<li class="page-item <?php echo $trans_page <= 1 ? 'disabled' : ''; ?>">
<a class="page-link" href="#" data-page="<?php echo $trans_page - 1; ?>" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<?php
$range = 2;
$pages_to_show = [];
$pages_to_show[] = 1;
if ($totalTransPages > 1) { $pages_to_show[] = $totalTransPages; }
for ($i = $trans_page - $range; $i <= $trans_page + $range; $i++) {
if ($i > 1 && $i < $totalTransPages) { $pages_to_show[] = $i; }
}
$pages_to_show = array_unique($pages_to_show);
sort($pages_to_show);
$prev_page = 0;
foreach ($pages_to_show as $p):
if ($prev_page > 0 && $p > $prev_page + 1): ?>
<li class="page-item disabled"><span class="page-link">...</span></li>
<?php endif; ?>
<li class="page-item <?php echo $trans_page == $p ? 'active' : ''; ?>">
<a class="page-link" href="#" data-page="<?php echo $p; ?>">
<?php echo $p; ?>
</a>
</li>
<?php
$prev_page = $p;
endforeach;
?>
<li class="page-item <?php echo $trans_page >= $totalTransPages ? 'disabled' : ''; ?>">
<a class="page-link" href="#" data-page="<?php echo $trans_page + 1; ?>" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
</div>
<?php endif;
$pagination_html = ob_get_clean();
echo json_encode(['html' => $table_html, 'pagination' => $pagination_html]);
} else {
// Companies Tab
if (empty($insurance_companies)): ?>
<tr>
<td colspan="7" class="text-center py-5 text-muted">
<i class="bi bi-shield-check display-4 d-block mb-3"></i>
<?php echo __('no_insurance_companies_found'); ?>
</td>
@ -50,7 +192,32 @@ if (isset($_GET['ajax_search'])) {
<td class="text-secondary"><?php echo htmlspecialchars($ic['name_ar']); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($ic['email'] ?: '-'); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($ic['phone'] ?: '-'); ?></td>
<td class="text-end px-4 text-muted"><?php echo date('Y-m-d', strtotime($ic['created_at'])); ?></td>
<td class="text-muted"><?php echo date('Y-m-d', strtotime($ic['created_at'])); ?></td>
<td class="text-end px-4">
<div class="dropdown">
<button class="btn btn-sm btn-light text-secondary" type="button" data-bs-toggle="dropdown">
<i class="bi bi-three-dots-vertical"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end border-0 shadow-sm">
<li>
<a class="dropdown-item" href="#" onclick="openStatementModal(<?php echo $ic['id']; ?>)">
<i class="bi bi-printer me-2"></i> <?php echo __('statement'); ?>
</a>
</li>
<li>
<a class="dropdown-item" href="#" onclick='openEditInsuranceModal(<?php echo json_encode($ic); ?>)'>
<i class="bi bi-pencil me-2"></i> <?php echo __('edit'); ?>
</a>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<a class="dropdown-item text-danger" href="#" onclick="deleteInsurance(<?php echo $ic['id']; ?>)">
<i class="bi bi-trash me-2"></i> <?php echo __('delete'); ?>
</a>
</li>
</ul>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif;
@ -105,18 +272,37 @@ if (isset($_GET['ajax_search'])) {
<?php endif;
$pagination_html = ob_get_clean();
header('Content-Type: application/json');
echo json_encode(['html' => $table_html, 'pagination' => $pagination_html]);
}
exit;
}
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<h3 class="fw-bold text-secondary"><?php echo __('insurance_companies'); ?></h3>
<h3 class="fw-bold text-secondary"><?php echo __('insurance'); ?></h3>
<div>
<button class="btn btn-outline-primary shadow-sm me-2" data-bs-toggle="modal" data-bs-target="#addTransactionModal">
<i class="bi bi-plus-lg me-1"></i> <?php echo __('add_transaction'); ?>
</button>
<button class="btn btn-primary shadow-sm" data-bs-toggle="modal" data-bs-target="#addInsuranceModal">
<i class="bi bi-plus-lg me-1"></i> <?php echo __('add_insurance'); ?>
</button>
</div>
</div>
<ul class="nav nav-tabs mb-4" id="insuranceTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="companies-tab" data-bs-toggle="tab" data-bs-target="#companies" type="button" role="tab" aria-controls="companies" aria-selected="true"><?php echo __('companies'); ?></button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="transactions-tab" data-bs-toggle="tab" data-bs-target="#transactions" type="button" role="tab" aria-controls="transactions" aria-selected="false"><?php echo __('transactions'); ?></button>
</li>
</ul>
<div class="tab-content" id="insuranceTabsContent">
<!-- COMPANIES TAB -->
<div class="tab-pane fade show active" id="companies" role="tabpanel" aria-labelledby="companies-tab">
<!-- Search Bar -->
<div class="card shadow-sm border-0 mb-4">
@ -152,13 +338,14 @@ if (isset($_GET['ajax_search'])) {
<th class="py-3"><?php echo __('name_ar'); ?></th>
<th class="py-3"><?php echo __('email'); ?></th>
<th class="py-3"><?php echo __('phone'); ?></th>
<th class="py-3 text-end px-4"><?php echo __('date'); ?></th>
<th class="py-3"><?php echo __('date'); ?></th>
<th class="py-3 text-end px-4"><?php echo __('actions'); ?></th>
</tr>
</thead>
<tbody id="insuranceTableBody">
<?php if (empty($insurance_companies)): ?>
<tr>
<td colspan="6" class="text-center py-5 text-muted">
<td colspan="7" class="text-center py-5 text-muted">
<i class="bi bi-shield-check display-4 d-block mb-3"></i>
<?php echo __('no_insurance_companies_found'); ?>
</td>
@ -171,7 +358,32 @@ if (isset($_GET['ajax_search'])) {
<td class="text-secondary"><?php echo htmlspecialchars($ic['name_ar']); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($ic['email'] ?: '-'); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($ic['phone'] ?: '-'); ?></td>
<td class="text-end px-4 text-muted"><?php echo date('Y-m-d', strtotime($ic['created_at'])); ?></td>
<td class="text-muted"><?php echo date('Y-m-d', strtotime($ic['created_at'])); ?></td>
<td class="text-end px-4">
<div class="dropdown">
<button class="btn btn-sm btn-light text-secondary" type="button" data-bs-toggle="dropdown">
<i class="bi bi-three-dots-vertical"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end border-0 shadow-sm">
<li>
<a class="dropdown-item" href="#" onclick="openStatementModal(<?php echo $ic['id']; ?>)">
<i class="bi bi-printer me-2"></i> <?php echo __('statement'); ?>
</a>
</li>
<li>
<a class="dropdown-item" href="#" onclick='openEditInsuranceModal(<?php echo json_encode($ic); ?>)'>
<i class="bi bi-pencil me-2"></i> <?php echo __('edit'); ?>
</a>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<a class="dropdown-item text-danger" href="#" onclick="deleteInsurance(<?php echo $ic['id']; ?>)">
<i class="bi bi-trash me-2"></i> <?php echo __('delete'); ?>
</a>
</li>
</ul>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
@ -230,6 +442,149 @@ if (isset($_GET['ajax_search'])) {
</div>
</div>
</div>
</div>
<!-- TRANSACTIONS TAB -->
<div class="tab-pane fade" id="transactions" role="tabpanel" aria-labelledby="transactions-tab">
<!-- Search Bar -->
<div class="card shadow-sm border-0 mb-4">
<div class="card-body">
<form id="transSearchForm" class="row g-3" onsubmit="return false;">
<div class="col-md-4">
<select name="trans_company_id" id="transSearchCompany" class="form-select bg-light border-0">
<option value=""><?php echo __('all'); ?> <?php echo __('insurance_companies'); ?></option>
<?php foreach ($all_insurance as $ic): ?>
<option value="<?php echo $ic['id']; ?>"><?php echo htmlspecialchars($ic['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3">
<input type="date" name="trans_start_date" id="transStartDate" class="form-control bg-light border-0" placeholder="<?php echo __('start_date'); ?>">
</div>
<div class="col-md-3">
<input type="date" name="trans_end_date" id="transEndDate" class="form-control bg-light border-0" placeholder="<?php echo __('end_date'); ?>">
</div>
<div class="col-md-2">
<button type="button" class="btn btn-secondary w-100" onclick="fetchTransactions(1)"><?php echo __('search'); ?></button>
</div>
</form>
</div>
</div>
<div class="card shadow-sm border-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light text-secondary">
<tr>
<th class="px-4 py-3">ID</th>
<th class="py-3"><?php echo __('payment_date'); ?></th>
<th class="py-3"><?php echo __('insurance_company'); ?></th>
<th class="py-3"><?php echo __('amount'); ?></th>
<th class="py-3"><?php echo __('reference_number'); ?></th>
<th class="py-3"><?php echo __('payment_method'); ?></th>
<th class="py-3"><?php echo __('notes'); ?></th>
<th class="py-3 text-end px-4"><?php echo __('actions'); ?></th>
</tr>
</thead>
<tbody id="transTableBody">
<?php if (empty($transactions)): ?>
<tr>
<td colspan="8" class="text-center py-5 text-muted">
<i class="bi bi-cash-stack display-4 d-block mb-3"></i>
<?php echo __('no_transactions_found'); ?>
</td>
</tr>
<?php else: ?>
<?php foreach ($transactions as $t): ?>
<tr>
<td class="px-4 text-secondary">#<?php echo $t['id']; ?></td>
<td class="fw-semibold text-dark"><?php echo date('Y-m-d', strtotime($t['payment_date'])); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($t['company_name']); ?></td>
<td class="text-dark fw-bold"><?php echo format_currency($t['amount']); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($t['reference_number'] ?: '-'); ?></td>
<td class="text-secondary">
<?php
$method_key = 'payment_method_' . strtolower(str_replace(' ', '_', $t['payment_method']));
echo __($method_key) !== $method_key ? __($method_key) : $t['payment_method'];
?>
</td>
<td class="text-muted small text-truncate" style="max-width: 150px;" title="<?php echo htmlspecialchars($t['notes']); ?>">
<?php echo htmlspecialchars($t['notes'] ?: '-'); ?>
</td>
<td class="text-end px-4">
<button class="btn btn-sm btn-light text-primary me-1"
onclick='openEditTransactionModal(<?php echo json_encode($t); ?>)'
title="<?php echo __('edit'); ?>">
<i class="bi bi-pencil"></i>
</button>
<button class="btn btn-sm btn-light text-danger"
onclick="deleteTransaction(<?php echo $t['id']; ?>)"
title="<?php echo __('delete'); ?>">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Pagination -->
<div id="transPagination">
<?php if ($totalTransPages > 1): ?>
<div class="d-flex justify-content-between align-items-center p-3 border-top">
<div class="text-muted small">
<?php echo __('showing'); ?> <?php echo $trans_offset + 1; ?> - <?php echo min($trans_offset + $trans_limit, $totalTrans); ?> <?php echo __('of'); ?> <?php echo $totalTrans; ?>
</div>
<nav aria-label="Page navigation">
<ul class="pagination pagination-sm mb-0">
<li class="page-item <?php echo $trans_page <= 1 ? 'disabled' : ''; ?>">
<a class="page-link" href="#" data-page="<?php echo $trans_page - 1; ?>" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<?php
$range = 2;
$pages_to_show = [];
$pages_to_show[] = 1;
if ($totalTransPages > 1) { $pages_to_show[] = $totalTransPages; }
for ($i = $trans_page - $range; $i <= $trans_page + $range; $i++) {
if ($i > 1 && $i < $totalTransPages) { $pages_to_show[] = $i; }
}
$pages_to_show = array_unique($pages_to_show);
sort($pages_to_show);
$prev_page = 0;
foreach ($pages_to_show as $p):
if ($prev_page > 0 && $p > $prev_page + 1): ?>
<li class="page-item disabled"><span class="page-link">...</span></li>
<?php endif; ?>
<li class="page-item <?php echo $trans_page == $p ? 'active' : ''; ?>">
<a class="page-link" href="#" data-page="<?php echo $p; ?>">
<?php echo $p; ?>
</a>
</li>
<?php
$prev_page = $p;
endforeach;
?>
<li class="page-item <?php echo $trans_page >= $totalTransPages ? 'disabled' : ''; ?>">
<a class="page-link" href="#" data-page="<?php echo $trans_page + 1; ?>" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<!-- Add Insurance Modal -->
<div class="modal fade" id="addInsuranceModal" tabindex="-1" aria-hidden="true">
@ -275,30 +630,241 @@ if (isset($_GET['ajax_search'])) {
</div>
</div>
<!-- Edit Insurance Modal -->
<div class="modal fade" id="editInsuranceModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content border-0 shadow">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title"><?php echo __('edit'); ?></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST" action="">
<input type="hidden" name="action" value="edit_insurance">
<input type="hidden" name="id" id="editInsId">
<div class="modal-body p-4">
<div class="mb-3">
<label class="form-label"><?php echo __('name_en'); ?> <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="name_en" id="editInsNameEn" required>
</div>
<div class="mb-3">
<label class="form-label"><?php echo __('name_ar'); ?> <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="name_ar" id="editInsNameAr" required>
</div>
<div class="mb-3">
<label class="form-label"><?php echo __('email'); ?></label>
<input type="email" class="form-control" name="email" id="editInsEmail">
</div>
<div class="mb-3">
<label class="form-label"><?php echo __('phone'); ?></label>
<input type="text" class="form-control" name="phone" id="editInsPhone">
</div>
<div class="mb-3">
<label class="form-label"><?php echo __('discount_percentage'); ?></label>
<div class="input-group">
<input type="number" class="form-control" name="discount_percentage" id="editInsDiscount" step="0.01" min="0" max="100">
<span class="input-group-text">%</span>
</div>
</div>
</div>
<div class="modal-footer bg-light">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('close'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo __('save_changes'); ?></button>
</div>
</form>
</div>
</div>
</div>
<!-- Add Transaction Modal -->
<div class="modal fade" id="addTransactionModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content border-0 shadow">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title"><?php echo __('add_transaction'); ?></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST" action="">
<input type="hidden" name="action" value="add_transaction">
<div class="modal-body p-4">
<div class="mb-3">
<label class="form-label"><?php echo __('insurance_company'); ?> <span class="text-danger">*</span></label>
<select name="insurance_company_id" class="form-select" required>
<option value=""><?php echo __('select'); ?></option>
<?php foreach ($all_insurance as $ic): ?>
<option value="<?php echo $ic['id']; ?>"><?php echo htmlspecialchars($ic['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label"><?php echo __('amount'); ?> <span class="text-danger">*</span></label>
<div class="input-group">
<span class="input-group-text"><?php echo $_SESSION['currency_symbol'] ?? '$'; ?></span>
<input type="number" class="form-control" name="amount" step="0.001" required>
</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?php echo __('payment_date'); ?> <span class="text-danger">*</span></label>
<input type="date" class="form-control" name="payment_date" value="<?php echo date('Y-m-d'); ?>" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label"><?php echo __('payment_method'); ?></label>
<select name="payment_method" class="form-select">
<option value="Check"><?php echo __('payment_method_check'); ?></option>
<option value="Bank Transfer"><?php echo __('payment_method_transfer'); ?></option>
<option value="Cash"><?php echo __('payment_method_cash'); ?></option>
<option value="Credit Card"><?php echo __('payment_method_card'); ?></option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?php echo __('reference_number'); ?></label>
<input type="text" class="form-control" name="reference_number">
</div>
</div>
<div class="mb-3">
<label class="form-label"><?php echo __('notes'); ?></label>
<textarea class="form-control" name="notes" rows="2"></textarea>
</div>
</div>
<div class="modal-footer bg-light">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('close'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo __('save'); ?></button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Transaction Modal -->
<div class="modal fade" id="editTransactionModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content border-0 shadow">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title"><?php echo __('edit_transaction'); ?></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST" action="">
<input type="hidden" name="action" value="edit_transaction">
<input type="hidden" name="id" id="editTransId">
<div class="modal-body p-4">
<div class="mb-3">
<label class="form-label"><?php echo __('insurance_company'); ?> <span class="text-danger">*</span></label>
<select name="insurance_company_id" id="editTransCompany" class="form-select" required>
<option value=""><?php echo __('select'); ?></option>
<?php foreach ($all_insurance as $ic): ?>
<option value="<?php echo $ic['id']; ?>"><?php echo htmlspecialchars($ic['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label"><?php echo __('amount'); ?> <span class="text-danger">*</span></label>
<div class="input-group">
<span class="input-group-text"><?php echo $_SESSION['currency_symbol'] ?? '$'; ?></span>
<input type="number" class="form-control" name="amount" id="editTransAmount" step="0.001" required>
</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?php echo __('payment_date'); ?> <span class="text-danger">*</span></label>
<input type="date" class="form-control" name="payment_date" id="editTransDate" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label"><?php echo __('payment_method'); ?></label>
<select name="payment_method" id="editTransMethod" class="form-select">
<option value="Check"><?php echo __('payment_method_check'); ?></option>
<option value="Bank Transfer"><?php echo __('payment_method_transfer'); ?></option>
<option value="Cash"><?php echo __('payment_method_cash'); ?></option>
<option value="Credit Card"><?php echo __('payment_method_card'); ?></option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label"><?php echo __('reference_number'); ?></label>
<input type="text" class="form-control" name="reference_number" id="editTransRef">
</div>
</div>
<div class="mb-3">
<label class="form-label"><?php echo __('notes'); ?></label>
<textarea class="form-control" name="notes" id="editTransNotes" rows="2"></textarea>
</div>
</div>
<div class="modal-footer bg-light">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('close'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo __('save_changes'); ?></button>
</div>
</form>
</div>
</div>
</div>
<!-- Statement Modal -->
<div class="modal fade" id="statementModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content border-0 shadow">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title"><?php echo __('print_statement'); ?></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="statementForm" action="print_insurance_statement.php" method="GET" target="_blank">
<input type="hidden" name="id" id="statementInsuranceId">
<div class="modal-body p-4">
<div class="mb-3">
<label class="form-label"><?php echo __('start_date'); ?></label>
<input type="date" class="form-control" name="start_date" id="startDate">
</div>
<div class="mb-3">
<label class="form-label"><?php echo __('end_date'); ?></label>
<input type="date" class="form-control" name="end_date" id="endDate">
</div>
</div>
<div class="modal-footer bg-light">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo __('close'); ?></button>
<button type="submit" class="btn btn-primary">
<i class="bi bi-printer me-1"></i> <?php echo __('print'); ?>
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Form -->
<form id="deleteForm" method="POST" style="display:none;">
<input type="hidden" name="action" id="deleteAction">
<input type="hidden" name="id" id="deleteId">
</form>
<script>
document.addEventListener('DOMContentLoaded', function() {
const searchName = document.getElementById('insSearchName');
const searchPhone = document.getElementById('insSearchPhone');
const paginationContainer = document.getElementById('insurancePagination');
const insPagination = document.getElementById('insurancePagination');
const transSearchCompany = document.getElementById('transSearchCompany');
const transStartDate = document.getElementById('transStartDate');
const transEndDate = document.getElementById('transEndDate');
const transPagination = document.getElementById('transPagination');
let timeout = null;
// Companies Search
if (searchName) {
searchName.addEventListener('input', function() {
clearTimeout(timeout);
timeout = setTimeout(() => fetchInsurance(1), 300);
});
}
if (searchPhone) {
searchPhone.addEventListener('input', function() {
clearTimeout(timeout);
timeout = setTimeout(() => fetchInsurance(1), 300);
});
}
if (paginationContainer) {
paginationContainer.addEventListener('click', function(e) {
if (insPagination) {
insPagination.addEventListener('click', function(e) {
e.preventDefault();
const link = e.target.closest('.page-link');
if (link && !link.parentElement.classList.contains('disabled')) {
@ -307,6 +873,38 @@ document.addEventListener('DOMContentLoaded', function() {
}
});
}
// Transactions Search
if (transSearchCompany) {
transSearchCompany.addEventListener('change', () => fetchTransactions(1));
}
if (transStartDate) {
transStartDate.addEventListener('change', () => fetchTransactions(1));
}
if (transEndDate) {
transEndDate.addEventListener('change', () => fetchTransactions(1));
}
if (transPagination) {
transPagination.addEventListener('click', function(e) {
e.preventDefault();
const link = e.target.closest('.page-link');
if (link && !link.parentElement.classList.contains('disabled')) {
const page = link.getAttribute('data-page');
if (page) fetchTransactions(page);
}
});
}
// Set default dates for statement
const today = new Date();
const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
if(document.getElementById('startDate')) {
document.getElementById('startDate').valueAsDate = firstDay;
}
if(document.getElementById('endDate')) {
document.getElementById('endDate').valueAsDate = today;
}
});
function fetchInsurance(page) {
@ -318,10 +916,12 @@ function fetchInsurance(page) {
if (tableBody) tableBody.style.opacity = '0.5';
const params = new URLSearchParams();
if (name) params.append('name', name);
if (phone) params.append('phone', phone);
params.append('name', name);
params.append('phone', phone);
params.append('page', page);
params.append('ajax_search', '1');
// Tab defaults to companies implicitly in PHP if not specified,
// or we can explicit pass tab=companies
fetch('insurance.php?' + params.toString())
.then(response => response.json())
@ -339,4 +939,87 @@ function fetchInsurance(page) {
if (tableBody) tableBody.style.opacity = '1';
});
}
function fetchTransactions(page) {
const company = document.getElementById('transSearchCompany').value;
const start = document.getElementById('transStartDate').value;
const end = document.getElementById('transEndDate').value;
const tableBody = document.getElementById('transTableBody');
const paginationContainer = document.getElementById('transPagination');
if (tableBody) tableBody.style.opacity = '0.5';
const params = new URLSearchParams();
params.append('trans_company_id', company);
params.append('trans_start_date', start);
params.append('trans_end_date', end);
params.append('trans_page', page);
params.append('ajax_search', '1');
params.append('tab', 'transactions');
fetch('insurance.php?' + params.toString())
.then(response => response.json())
.then(data => {
if (tableBody) {
tableBody.innerHTML = data.html;
tableBody.style.opacity = '1';
}
if (paginationContainer) {
paginationContainer.innerHTML = data.pagination;
}
})
.catch(error => {
console.error('Error fetching transactions:', error);
if (tableBody) tableBody.style.opacity = '1';
});
}
function openStatementModal(id) {
document.getElementById('statementInsuranceId').value = id;
var myModal = new bootstrap.Modal(document.getElementById('statementModal'));
myModal.show();
}
function openEditInsuranceModal(data) {
document.getElementById('editInsId').value = data.id;
document.getElementById('editInsNameEn').value = data.name_en;
document.getElementById('editInsNameAr').value = data.name_ar;
document.getElementById('editInsEmail').value = data.email || '';
document.getElementById('editInsPhone').value = data.phone || '';
document.getElementById('editInsDiscount').value = data.discount_percentage || 0;
var myModal = new bootstrap.Modal(document.getElementById('editInsuranceModal'));
myModal.show();
}
function deleteInsurance(id) {
if(confirm('<?php echo __('confirm_delete'); ?>?')) {
const form = document.getElementById('deleteForm');
document.getElementById('deleteAction').value = 'delete_insurance';
document.getElementById('deleteId').value = id;
form.submit();
}
}
function openEditTransactionModal(data) {
document.getElementById('editTransId').value = data.id;
document.getElementById('editTransCompany').value = data.insurance_company_id;
document.getElementById('editTransAmount').value = data.amount;
document.getElementById('editTransDate').value = data.payment_date;
document.getElementById('editTransMethod').value = data.payment_method;
document.getElementById('editTransRef').value = data.reference_number || '';
document.getElementById('editTransNotes').value = data.notes || '';
var myModal = new bootstrap.Modal(document.getElementById('editTransactionModal'));
myModal.show();
}
function deleteTransaction(id) {
if(confirm('<?php echo __('confirm_delete_transaction'); ?>')) {
const form = document.getElementById('deleteForm');
document.getElementById('deleteAction').value = 'delete_transaction';
document.getElementById('deleteId').value = id;
form.submit();
}
}
</script>

View File

@ -42,6 +42,9 @@ $tests = $stmt->fetchAll();
$gStmt = $db->query("SELECT * FROM test_groups ORDER BY name_$lang");
$all_test_groups = $gStmt->fetchAll();
$sys_settings = get_system_settings();
$currency_symbol = $sys_settings['currency_symbol'] ?? '$';
// --- AJAX HANDLER ---
if (isset($_GET['ajax_search'])) {
ob_start();
@ -78,7 +81,7 @@ if (isset($_GET['ajax_search'])) {
<?php echo htmlspecialchars($test['normal_range'] ?? '-'); ?>
</span>
</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">
<div class="btn-group shadow-sm border rounded bg-white">
<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'] ?? '-'); ?>
</span>
</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">
<div class="btn-group shadow-sm border rounded bg-white">
<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">
<label class="form-label"><?php echo __('price'); ?></label>
<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">
</div>
</div>

View File

@ -155,7 +155,7 @@ function fetchDrugs(query = '') {
<small class="text-muted">${skuHtml}${drug.name_ar || ''}</small>
</div>
<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'}">
${isOutOfStock ? '<?php echo __('out_of_stock'); ?>' : '<?php echo __('stock'); ?>: ' + stock}
</small>
@ -243,7 +243,7 @@ function renderCart() {
<tr>
<td>
<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>
<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>
</div>
</td>
<td class="text-end fw-bold">${itemTotal.toFixed(2)}</td>
<td class="text-end fw-bold">${formatCurrency(itemTotal)}</td>
<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>
</td>
@ -260,9 +260,9 @@ function renderCart() {
`;
});
cartTotalEl.textContent = total.toFixed(2);
cartTotalEl.textContent = formatCurrency(total);
cartCountEl.textContent = cart.length;
checkoutTotalEl.textContent = total.toFixed(2);
checkoutTotalEl.textContent = formatCurrency(total);
if (cart.length === 0) {
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() {
const patientId = $('#patientSelect').val();
const paymentMethod = document.querySelector('input[name="payment_method"]:checked').value;
const total = cart.reduce((sum, item) => sum + (item.quantity * item.price), 0);
const payload = {
patient_id: patientId || null,
visit_id: null,
payment_method: paymentMethod,
total_amount: parseFloat(cartTotalEl.textContent),
total_amount: total,
items: cart.map(i => ({
drug_id: i.id,
quantity: i.quantity,

View File

@ -211,7 +211,7 @@ function loadReturns(page = 1) {
<td>${r.id}</td>
<td>${r.return_date}</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>
<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_supplier').innerText = supplier;
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;
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.batch_number || '-'}</td>
<td class="text-center">${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>
<td class="text-end">${formatCurrency(item.unit_price)}</td>
<td class="text-end">${formatCurrency(item.total_price)}</td>
</tr>
`;
});

View File

@ -264,7 +264,7 @@ function loadPurchases(page = 1) {
<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 class="fw-bold text-success">${formatCurrency(p.total_amount)}</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 || ''}')">
@ -453,7 +453,7 @@ 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_total').innerText = formatCurrency(total);
document.getElementById('view_purchase_status').innerText = status;
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.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>
<td class="text-end">${formatCurrency(item.cost_price)}</td>
<td class="text-end">${formatCurrency(item.total_cost)}</td>
</tr>
`;
});

View File

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

View File

@ -43,6 +43,9 @@ $query = "
$stmt = $db->prepare($query);
$stmt->execute($params);
$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">
@ -113,7 +116,7 @@ $services = $stmt->fetchAll();
</span>
</td>
<td class="fw-bold text-success">
<?php echo number_format($s['price'], 2); ?>
<?php echo format_currency($s['price']); ?>
</td>
<td>
<?php if ($s['is_active']): ?>

View File

@ -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'); ?>">
</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 -->
<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>
<?php if (!empty($settings['company_logo'])): ?>
<div class="mb-2">
@ -85,7 +100,7 @@
<?php endif; ?>
<input type="file" class="form-control" id="company_logo" name="company_logo" accept="image/*">
</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>
<?php if (!empty($settings['company_favicon'])): ?>
<div class="mb-2">

View File

@ -41,6 +41,9 @@ $tests = $stmt->fetchAll();
// 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();
$sys_settings = get_system_settings();
$currency_symbol = $sys_settings['currency_symbol'] ?? '$';
// --- AJAX HANDLER ---
if (isset($_GET['ajax_search'])) {
ob_start();
@ -72,7 +75,7 @@ if (isset($_GET['ajax_search'])) {
<?php echo htmlspecialchars($test['group_name'] ?? '-'); ?>
</span>
</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">
<div class="btn-group shadow-sm border rounded bg-white">
<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'] ?? '-'); ?>
</span>
</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">
<div class="btn-group shadow-sm border rounded bg-white">
<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">
<label class="form-label"><?php echo __('price'); ?></label>
<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">
</div>
</div>

View File

@ -8,6 +8,12 @@ $lang = $_SESSION['lang'];
require_once __DIR__ . '/includes/actions.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/pages/insurance.php';
require_once __DIR__ . '/includes/layout/footer.php';

View File

@ -331,6 +331,7 @@ $translations = [
'payment_method' => 'Payment Method',
'cash' => 'Cash',
'card' => 'Card',
'insurance' => 'Insurance',
'receipt' => 'Receipt',
'total_amount' => 'Total Amount',
'quantity' => 'Quantity',
@ -341,6 +342,8 @@ $translations = [
'out_of_stock' => 'Out of Stock',
'low_stock' => 'Low Stock',
'in_stock' => 'In Stock',
'waiting' => 'Waiting',
'serving' => 'Serving',
'CheckIn' => 'Check In',
'In Progress' => 'In Progress',
'in_progress' => 'In Progress',
@ -398,7 +401,29 @@ $translations = [
'receive_warning_msg' => 'Receiving this purchase will add items to stock.',
'ensure_batch_expiry_msg' => 'Ensure Batch Numbers and Expiry Dates are correct.',
'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' => [
'attachment' => 'المرفق',
@ -617,7 +642,7 @@ $translations = [
'company_logo' => 'شعار الشركة',
'company_favicon' => 'أيقونة الشركة',
'save_changes' => 'حفظ التغييرات',
'settings_updated_successfully' => 'Settings updated successfully',
'settings_updated_successfully' => 'تم تحديث الإعدادات بنجاح',
'prescriptions' => 'الوصفات الطبية',
'add_drug' => 'إضافة دواء',
'drug_name' => 'اسم الدواء',
@ -813,6 +838,28 @@ $translations = [
'receive_warning_msg' => 'استلام هذا الشراء سيضيف العناصر إلى المخزون.',
'ensure_batch_expiry_msg' => 'تأكد من صحة أرقام التشغيلات وتواريخ الانتهاء.',
'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>
<td class="text-center"><?php echo $i++; ?></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>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<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>
<?php if ($bill['insurance_covered'] > 0): ?>
<tr>
<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>
<?php endif; ?>
<tr>
<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>
</tfoot>
</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();
// Fetch Company Settings (Logo, Address, etc.)
$stmt = $db->query("SELECT * FROM settings WHERE id = 1");
$settings = $stmt->fetch();
$stmt = $db->query("SELECT setting_key, setting_value FROM settings");
$settings = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$settings[$row['setting_key']] = $row['setting_value'];
}
} catch (Exception $e) {
die("Error: " . $e->getMessage());
@ -178,8 +181,8 @@ try {
<?php endif; ?>
</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 number_format($item['total_price'], 2); ?></td>
<td class="text-end"><?php echo format_currency($item['unit_price']); ?></td>
<td class="text-end"><?php echo format_currency($item['total_price']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
@ -189,7 +192,7 @@ try {
TOTAL / الإجمالي
</td>
<td class="text-end fw-bold fs-5">
<?php echo number_format($sale['total_amount'], 2); ?>
<?php echo format_currency($sale['total_amount']); ?>
</td>
</tr>
</tfoot>

View File

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

View File

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