Autosave: 20260321-140606
This commit is contained in:
parent
dad73767a1
commit
b5ea341aa5
@ -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.
|
||||
@ -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";
|
||||
}
|
||||
|
||||
10
db/migrations/20260321_create_insurance_payments.sql
Normal file
10
db/migrations/20260321_create_insurance_payments.sql
Normal 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
|
||||
);
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE insurance_payments ADD COLUMN payment_method VARCHAR(50) DEFAULT 'Check' AFTER reference_number;
|
||||
19
helpers.php
19
helpers.php
@ -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';
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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']); ?>
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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">«</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">»</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">«</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">»</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>
|
||||
@ -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>
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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>
|
||||
`;
|
||||
});
|
||||
|
||||
@ -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>
|
||||
`;
|
||||
});
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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']): ?>
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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';
|
||||
53
lang.php
53
lang.php
@ -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' => 'الشركات'
|
||||
]
|
||||
];
|
||||
@ -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>
|
||||
|
||||
191
print_insurance_statement.php
Normal file
191
print_insurance_statement.php
Normal 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>
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
11
settings.php
11
settings.php
@ -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]);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user