update reciept
This commit is contained in:
parent
329da3e5d5
commit
97ae4ba490
@ -5,15 +5,29 @@ require_once __DIR__ . '/../ai/LocalAIApi.php';
|
|||||||
// Get JSON input
|
// Get JSON input
|
||||||
$input = json_decode(file_get_contents('php://input'), true);
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
|
|
||||||
$target = $input['target'] ?? 'treatment_plan'; // symptoms, diagnosis, treatment_plan
|
$target = $input['target'] ?? 'treatment_plan'; // symptoms, diagnosis, treatment_plan, translate
|
||||||
$symptoms = $input['symptoms'] ?? '';
|
$symptoms = $input['symptoms'] ?? '';
|
||||||
$diagnosis = $input['diagnosis'] ?? '';
|
$diagnosis = $input['diagnosis'] ?? '';
|
||||||
$currentValue = $input['current_value'] ?? ''; // For expanding symptoms
|
$currentValue = $input['current_value'] ?? ''; // For expanding symptoms or translation text
|
||||||
|
|
||||||
$systemPrompt = 'You are a professional medical assistant.';
|
$systemPrompt = 'You are a professional medical assistant.';
|
||||||
$userPrompt = "";
|
$userPrompt = "";
|
||||||
|
|
||||||
switch ($target) {
|
switch ($target) {
|
||||||
|
case 'translate':
|
||||||
|
$text = $input['text'] ?? '';
|
||||||
|
$from = $input['from'] ?? 'English';
|
||||||
|
$to = $input['to'] ?? 'Arabic';
|
||||||
|
|
||||||
|
if (empty($text)) {
|
||||||
|
echo json_encode(['success' => false, 'error' => 'No text provided for translation.']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$systemPrompt = "You are a professional translator specializing in medical terminology.";
|
||||||
|
$userPrompt = "Translate the following text from $from to $to. Return only the translated text without any explanations or extra characters.\n\nText: $text";
|
||||||
|
break;
|
||||||
|
|
||||||
case 'symptoms':
|
case 'symptoms':
|
||||||
if (empty($currentValue)) {
|
if (empty($currentValue)) {
|
||||||
$userPrompt = "Generate a list of common clinical symptoms for a general checkup in a professional medical format (HTML lists).";
|
$userPrompt = "Generate a list of common clinical symptoms for a general checkup in a professional medical format (HTML lists).";
|
||||||
@ -57,7 +71,7 @@ try {
|
|||||||
|
|
||||||
if (!empty($response['success'])) {
|
if (!empty($response['success'])) {
|
||||||
$text = LocalAIApi::extractText($response);
|
$text = LocalAIApi::extractText($response);
|
||||||
echo json_encode(['success' => true, 'report' => $text]);
|
echo json_encode(['success' => true, 'report' => trim($text)]);
|
||||||
} else {
|
} else {
|
||||||
echo json_encode(['success' => false, 'error' => $response['error'] ?? 'AI generation failed.']);
|
echo json_encode(['success' => false, 'error' => $response['error'] ?? 'AI generation failed.']);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -192,6 +192,14 @@ try {
|
|||||||
|
|
||||||
if (empty($input['items'])) throw new Exception("No items in sale");
|
if (empty($input['items'])) throw new Exception("No items in sale");
|
||||||
|
|
||||||
|
// Check Settings
|
||||||
|
$allow_negative = false;
|
||||||
|
try {
|
||||||
|
$settingStmt = $pdo->prepare("SELECT setting_value FROM settings WHERE setting_key = 'allow_negative_stock'");
|
||||||
|
$settingStmt->execute();
|
||||||
|
$allow_negative = (bool)$settingStmt->fetchColumn();
|
||||||
|
} catch (Exception $e) { /* ignore */ }
|
||||||
|
|
||||||
$pdo->beginTransaction();
|
$pdo->beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -235,9 +243,15 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($qty_remaining > 0) {
|
if ($qty_remaining > 0) {
|
||||||
|
if ($allow_negative) {
|
||||||
|
// Record sale for remaining quantity without batch
|
||||||
|
$item_stmt = $pdo->prepare("INSERT INTO pharmacy_sale_items (sale_id, drug_id, batch_id, quantity, unit_price, total_price) VALUES (?, ?, ?, ?, ?, ?)");
|
||||||
|
$item_stmt->execute([$sale_id, $drug_id, null, $qty_remaining, $unit_price, $qty_remaining * $unit_price]);
|
||||||
|
} else {
|
||||||
throw new Exception("Insufficient stock for drug ID: $drug_id");
|
throw new Exception("Insufficient stock for drug ID: $drug_id");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$pdo->commit();
|
$pdo->commit();
|
||||||
echo json_encode(['success' => true, 'sale_id' => $sale_id]);
|
echo json_encode(['success' => true, 'sale_id' => $sale_id]);
|
||||||
|
|||||||
1
db/migrations/20260322_add_image_to_drugs.sql
Normal file
1
db/migrations/20260322_add_image_to_drugs.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE drugs ADD COLUMN image VARCHAR(255) NULL;
|
||||||
@ -804,10 +804,11 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
|
|||||||
$price = $_POST['price'] ?? 0;
|
$price = $_POST['price'] ?? 0;
|
||||||
$expiry_date = $_POST['expiry_date'] ?: null;
|
$expiry_date = $_POST['expiry_date'] ?: null;
|
||||||
$supplier_id = $_POST['supplier_id'] ?: null;
|
$supplier_id = $_POST['supplier_id'] ?: null;
|
||||||
|
$image = upload_file($_FILES['image'] ?? [], 0, "assets/uploads/drugs/");
|
||||||
|
|
||||||
if ($name_en && $name_ar) {
|
if ($name_en && $name_ar) {
|
||||||
$stmt = $db->prepare("INSERT INTO drugs (name_en, name_ar, group_id, description_en, description_ar, default_dosage, default_instructions, price, expiry_date, supplier_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = $db->prepare("INSERT INTO drugs (name_en, name_ar, group_id, description_en, description_ar, default_dosage, default_instructions, price, expiry_date, supplier_id, image) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$name_en, $name_ar, $group_id, $desc_en, $desc_ar, $dosage, $instructions, $price, $expiry_date, $supplier_id]);
|
$stmt->execute([$name_en, $name_ar, $group_id, $desc_en, $desc_ar, $dosage, $instructions, $price, $expiry_date, $supplier_id, $image]);
|
||||||
$_SESSION['flash_message'] = __('add_drug') . ' ' . __('successfully');
|
$_SESSION['flash_message'] = __('add_drug') . ' ' . __('successfully');
|
||||||
$redirect = true;
|
$redirect = true;
|
||||||
}
|
}
|
||||||
@ -823,10 +824,16 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
|
|||||||
$price = $_POST['price'] ?? 0;
|
$price = $_POST['price'] ?? 0;
|
||||||
$expiry_date = $_POST['expiry_date'] ?: null;
|
$expiry_date = $_POST['expiry_date'] ?: null;
|
||||||
$supplier_id = $_POST['supplier_id'] ?: null;
|
$supplier_id = $_POST['supplier_id'] ?: null;
|
||||||
|
$image = upload_file($_FILES['image'] ?? [], 0, "assets/uploads/drugs/");
|
||||||
|
|
||||||
if ($id && $name_en && $name_ar) {
|
if ($id && $name_en && $name_ar) {
|
||||||
|
if ($image) {
|
||||||
|
$stmt = $db->prepare("UPDATE drugs SET name_en = ?, name_ar = ?, group_id = ?, description_en = ?, description_ar = ?, default_dosage = ?, default_instructions = ?, price = ?, expiry_date = ?, supplier_id = ?, image = ? WHERE id = ?");
|
||||||
|
$stmt->execute([$name_en, $name_ar, $group_id, $desc_en, $desc_ar, $dosage, $instructions, $price, $expiry_date, $supplier_id, $image, $id]);
|
||||||
|
} else {
|
||||||
$stmt = $db->prepare("UPDATE drugs SET name_en = ?, name_ar = ?, group_id = ?, description_en = ?, description_ar = ?, default_dosage = ?, default_instructions = ?, price = ?, expiry_date = ?, supplier_id = ? WHERE id = ?");
|
$stmt = $db->prepare("UPDATE drugs SET name_en = ?, name_ar = ?, group_id = ?, description_en = ?, description_ar = ?, default_dosage = ?, default_instructions = ?, price = ?, expiry_date = ?, supplier_id = ? WHERE id = ?");
|
||||||
$stmt->execute([$name_en, $name_ar, $group_id, $desc_en, $desc_ar, $dosage, $instructions, $price, $expiry_date, $supplier_id, $id]);
|
$stmt->execute([$name_en, $name_ar, $group_id, $desc_en, $desc_ar, $dosage, $instructions, $price, $expiry_date, $supplier_id, $id]);
|
||||||
|
}
|
||||||
$_SESSION['flash_message'] = __('edit_drug') . ' ' . __('successfully');
|
$_SESSION['flash_message'] = __('edit_drug') . ' ' . __('successfully');
|
||||||
$redirect = true;
|
$redirect = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,7 +57,7 @@ if (isset($_GET['ajax_search'])) {
|
|||||||
if (empty($drugs)):
|
if (empty($drugs)):
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="7" class="text-center py-5 text-muted">
|
<td colspan="8" class="text-center py-5 text-muted">
|
||||||
<i class="bi bi-capsule display-4 d-block mb-3"></i>
|
<i class="bi bi-capsule display-4 d-block mb-3"></i>
|
||||||
<?php echo __('no_drugs_found'); ?>
|
<?php echo __('no_drugs_found'); ?>
|
||||||
</td>
|
</td>
|
||||||
@ -67,10 +67,16 @@ if (isset($_GET['ajax_search'])) {
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="px-4 fw-medium text-secondary"><?php echo $drug['id']; ?></td>
|
<td class="px-4 fw-medium text-secondary"><?php echo $drug['id']; ?></td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex align-items-center">
|
<?php if (!empty($drug['image'])): ?>
|
||||||
<div class="bg-primary bg-opacity-10 text-primary p-2 rounded-circle me-3 flex-shrink-0">
|
<img src="<?php echo htmlspecialchars($drug['image']); ?>" class="rounded" style="width: 40px; height: 40px; object-fit: cover;">
|
||||||
<i class="bi bi-capsule fs-5"></i>
|
<?php else: ?>
|
||||||
|
<div class="bg-light rounded d-flex align-items-center justify-content-center text-muted" style="width: 40px; height: 40px;">
|
||||||
|
<i class="bi bi-image"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
<div class="text-wrap" style="word-break: break-word;">
|
<div class="text-wrap" style="word-break: break-word;">
|
||||||
<div class="fw-semibold text-dark"><?php echo htmlspecialchars($drug['name_'.$lang]); ?></div>
|
<div class="fw-semibold text-dark"><?php echo htmlspecialchars($drug['name_'.$lang]); ?></div>
|
||||||
<small class="text-muted d-block"><?php echo htmlspecialchars($drug['name_'.($lang == 'en' ? 'ar' : 'en')]); ?></small>
|
<small class="text-muted d-block"><?php echo htmlspecialchars($drug['name_'.($lang == 'en' ? 'ar' : 'en')]); ?></small>
|
||||||
@ -205,6 +211,7 @@ if (isset($_GET['ajax_search'])) {
|
|||||||
<thead class="table-light text-secondary">
|
<thead class="table-light text-secondary">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-4 py-3">#</th>
|
<th class="px-4 py-3">#</th>
|
||||||
|
<th class="py-3" style="width: 50px;"><?php echo __('image'); ?></th>
|
||||||
<th class="py-3" style="width: 30%; min-width: 200px;"><?php echo __('drug_name'); ?></th>
|
<th class="py-3" style="width: 30%; min-width: 200px;"><?php echo __('drug_name'); ?></th>
|
||||||
<th class="py-3"><?php echo __('drug_group'); ?></th>
|
<th class="py-3"><?php echo __('drug_group'); ?></th>
|
||||||
<th class="py-3"><?php echo __('expiry_date'); ?></th>
|
<th class="py-3"><?php echo __('expiry_date'); ?></th>
|
||||||
@ -216,7 +223,7 @@ if (isset($_GET['ajax_search'])) {
|
|||||||
<tbody id="drugsTableBody">
|
<tbody id="drugsTableBody">
|
||||||
<?php if (empty($drugs)): ?>
|
<?php if (empty($drugs)): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="7" class="text-center py-5 text-muted">
|
<td colspan="8" class="text-center py-5 text-muted">
|
||||||
<i class="bi bi-capsule display-4 d-block mb-3"></i>
|
<i class="bi bi-capsule display-4 d-block mb-3"></i>
|
||||||
<?php echo __('no_drugs_found'); ?>
|
<?php echo __('no_drugs_found'); ?>
|
||||||
</td>
|
</td>
|
||||||
@ -226,10 +233,16 @@ if (isset($_GET['ajax_search'])) {
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="px-4 fw-medium text-secondary"><?php echo $drug['id']; ?></td>
|
<td class="px-4 fw-medium text-secondary"><?php echo $drug['id']; ?></td>
|
||||||
<td>
|
<td>
|
||||||
<div class="d-flex align-items-center">
|
<?php if (!empty($drug['image'])): ?>
|
||||||
<div class="bg-primary bg-opacity-10 text-primary p-2 rounded-circle me-3 flex-shrink-0">
|
<img src="<?php echo htmlspecialchars($drug['image']); ?>" class="rounded" style="width: 40px; height: 40px; object-fit: cover;">
|
||||||
<i class="bi bi-capsule fs-5"></i>
|
<?php else: ?>
|
||||||
|
<div class="bg-light rounded d-flex align-items-center justify-content-center text-muted" style="width: 40px; height: 40px;">
|
||||||
|
<i class="bi bi-image"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
<div class="text-wrap" style="word-break: break-word;">
|
<div class="text-wrap" style="word-break: break-word;">
|
||||||
<div class="fw-semibold text-dark"><?php echo htmlspecialchars($drug['name_'.$lang]); ?></div>
|
<div class="fw-semibold text-dark"><?php echo htmlspecialchars($drug['name_'.$lang]); ?></div>
|
||||||
<small class="text-muted d-block"><?php echo htmlspecialchars($drug['name_'.($lang == 'en' ? 'ar' : 'en')]); ?></small>
|
<small class="text-muted d-block"><?php echo htmlspecialchars($drug['name_'.($lang == 'en' ? 'ar' : 'en')]); ?></small>
|
||||||
@ -337,18 +350,28 @@ if (isset($_GET['ajax_search'])) {
|
|||||||
<h5 class="modal-title" id="drugModalTitle"><?php echo __('add_drug'); ?></h5>
|
<h5 class="modal-title" id="drugModalTitle"><?php echo __('add_drug'); ?></h5>
|
||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<form method="POST" action="">
|
<form method="POST" action="" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="action" id="drugAction" value="add_drug">
|
<input type="hidden" name="action" id="drugAction" value="add_drug">
|
||||||
<input type="hidden" name="id" id="drugId">
|
<input type="hidden" name="id" id="drugId">
|
||||||
<div class="modal-body p-4">
|
<div class="modal-body p-4">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label"><?php echo __('name_en'); ?> <span class="text-danger">*</span></label>
|
<label class="form-label"><?php echo __('name_en'); ?> <span class="text-danger">*</span></label>
|
||||||
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" name="name_en" id="drugNameEn" required>
|
<input type="text" class="form-control" name="name_en" id="drugNameEn" required>
|
||||||
|
<button type="button" class="btn btn-outline-secondary" onclick="translateDrug('en', 'ar')" title="<?php echo __('auto_translate'); ?>">
|
||||||
|
<i class="bi bi-translate"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label"><?php echo __('name_ar'); ?> <span class="text-danger">*</span></label>
|
<label class="form-label"><?php echo __('name_ar'); ?> <span class="text-danger">*</span></label>
|
||||||
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" name="name_ar" id="drugNameAr" required>
|
<input type="text" class="form-control" name="name_ar" id="drugNameAr" required>
|
||||||
|
<button type="button" class="btn btn-outline-secondary" onclick="translateDrug('ar', 'en')" title="<?php echo __('auto_translate'); ?>">
|
||||||
|
<i class="bi bi-translate"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@ -395,6 +418,12 @@ if (isset($_GET['ajax_search'])) {
|
|||||||
<input type="text" class="form-control" name="default_instructions" id="drugInstructions">
|
<input type="text" class="form-control" name="default_instructions" id="drugInstructions">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label"><?php echo __('image'); ?></label>
|
||||||
|
<input type="file" class="form-control" name="image" accept="image/*" onchange="previewImage(this)">
|
||||||
|
<div id="drugImagePreview" class="mt-2"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label class="form-label"><?php echo __('description_en'); ?></label>
|
<label class="form-label"><?php echo __('description_en'); ?></label>
|
||||||
<textarea class="form-control" name="description_en" id="drugDescEn" rows="2"></textarea>
|
<textarea class="form-control" name="description_en" id="drugDescEn" rows="2"></textarea>
|
||||||
@ -485,6 +514,8 @@ function resetDrugModal() {
|
|||||||
document.getElementById('drugDescAr').value = '';
|
document.getElementById('drugDescAr').value = '';
|
||||||
document.getElementById('drugExpiry').value = '';
|
document.getElementById('drugExpiry').value = '';
|
||||||
document.getElementById('drugSupplierId').value = '';
|
document.getElementById('drugSupplierId').value = '';
|
||||||
|
document.getElementById('drugImagePreview').innerHTML = '';
|
||||||
|
document.querySelector('input[name="image"]').value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function showEditDrugModal(drug) {
|
function showEditDrugModal(drug) {
|
||||||
@ -503,6 +534,13 @@ function showEditDrugModal(drug) {
|
|||||||
document.getElementById('drugExpiry').value = drug.expiry_date || '';
|
document.getElementById('drugExpiry').value = drug.expiry_date || '';
|
||||||
document.getElementById('drugSupplierId').value = drug.supplier_id || '';
|
document.getElementById('drugSupplierId').value = drug.supplier_id || '';
|
||||||
|
|
||||||
|
const preview = document.getElementById('drugImagePreview');
|
||||||
|
if (drug.image) {
|
||||||
|
preview.innerHTML = `<img src="${drug.image}" class="rounded shadow-sm" style="max-height: 100px;">`;
|
||||||
|
} else {
|
||||||
|
preview.innerHTML = '';
|
||||||
|
}
|
||||||
|
|
||||||
var modal = new bootstrap.Modal(document.getElementById('addDrugModal'));
|
var modal = new bootstrap.Modal(document.getElementById('addDrugModal'));
|
||||||
modal.show();
|
modal.show();
|
||||||
}
|
}
|
||||||
@ -513,6 +551,52 @@ function showDeleteDrugModal(id) {
|
|||||||
modal.show();
|
modal.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function previewImage(input) {
|
||||||
|
const preview = document.getElementById('drugImagePreview');
|
||||||
|
if (input.files && input.files[0]) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function(e) {
|
||||||
|
preview.innerHTML = `<img src="${e.target.result}" class="rounded shadow-sm" style="max-height: 100px;">`;
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(input.files[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function translateDrug(source, target) {
|
||||||
|
const text = document.getElementById(source === 'en' ? 'drugNameEn' : 'drugNameAr').value;
|
||||||
|
if (!text) return;
|
||||||
|
|
||||||
|
const btn = event.currentTarget;
|
||||||
|
const originalContent = btn.innerHTML;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span>';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('api/ai_report.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({
|
||||||
|
target: 'translate',
|
||||||
|
text: text,
|
||||||
|
from: source === 'en' ? 'English' : 'Arabic',
|
||||||
|
to: target === 'en' ? 'English' : 'Arabic'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.success) {
|
||||||
|
document.getElementById(target === 'en' ? 'drugNameEn' : 'drugNameAr').value = data.report;
|
||||||
|
} else {
|
||||||
|
alert('Translation failed: ' + (data.error || 'Unknown error'));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
alert('Network error');
|
||||||
|
} finally {
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.innerHTML = originalContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const searchInput = document.getElementById('drugSearchInput');
|
const searchInput = document.getElementById('drugSearchInput');
|
||||||
const tableBody = document.getElementById('drugsTableBody');
|
const tableBody = document.getElementById('drugsTableBody');
|
||||||
|
|||||||
@ -1,3 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
// Fetch Allow Negative Stock setting
|
||||||
|
$allowNegativeStock = 0;
|
||||||
|
try {
|
||||||
|
$stmt = $db->prepare("SELECT setting_value FROM settings WHERE setting_key = 'allow_negative_stock'");
|
||||||
|
$stmt->execute();
|
||||||
|
if ($row = $stmt->fetch()) {
|
||||||
|
$allowNegativeStock = (int)$row['setting_value'];
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// defaults to 0
|
||||||
|
}
|
||||||
|
?>
|
||||||
<div class="container-fluid h-100">
|
<div class="container-fluid h-100">
|
||||||
<div class="row h-100">
|
<div class="row h-100">
|
||||||
<!-- Left Panel: Product Search -->
|
<!-- Left Panel: Product Search -->
|
||||||
@ -10,9 +23,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0 overflow-auto" style="max-height: calc(100vh - 200px);">
|
<div class="card-body p-0 overflow-auto" style="max-height: calc(100vh - 200px);">
|
||||||
<div id="drugList" class="list-group list-group-flush">
|
<div id="drugList" class="row row-cols-1 row-cols-md-3 row-cols-lg-4 g-3 p-3">
|
||||||
<!-- Populated by JS -->
|
<!-- Populated by JS -->
|
||||||
<div class="text-center py-5 text-muted">
|
<div class="col-12 text-center py-5 text-muted">
|
||||||
<div class="spinner-border text-primary" role="status">
|
<div class="spinner-border text-primary" role="status">
|
||||||
<span class="visually-hidden">Loading...</span>
|
<span class="visually-hidden">Loading...</span>
|
||||||
</div>
|
</div>
|
||||||
@ -115,6 +128,7 @@
|
|||||||
<script>
|
<script>
|
||||||
let cart = [];
|
let cart = [];
|
||||||
let debounceTimer;
|
let debounceTimer;
|
||||||
|
const allowNegativeStock = <?php echo $allowNegativeStock; ?>;
|
||||||
|
|
||||||
const searchInput = document.getElementById('drugSearch');
|
const searchInput = document.getElementById('drugSearch');
|
||||||
const drugList = document.getElementById('drugList');
|
const drugList = document.getElementById('drugList');
|
||||||
@ -134,7 +148,7 @@ function fetchDrugs(query = '') {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
drugList.innerHTML = '';
|
drugList.innerHTML = '';
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
drugList.innerHTML = '<div class="list-group-item text-center text-muted"><?php echo __('no_drugs_found'); ?></div>';
|
drugList.innerHTML = '<div class="col-12 text-center text-muted py-5"><?php echo __('no_drugs_found'); ?></div>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,37 +156,44 @@ function fetchDrugs(query = '') {
|
|||||||
const stock = parseFloat(drug.stock);
|
const stock = parseFloat(drug.stock);
|
||||||
// Use batch price if available (current active price), otherwise default
|
// Use batch price if available (current active price), otherwise default
|
||||||
const price = parseFloat(drug.batch_price || drug.default_price || 0);
|
const price = parseFloat(drug.batch_price || drug.default_price || 0);
|
||||||
const isOutOfStock = stock <= 0;
|
const isOutOfStock = stock <= 0 && !allowNegativeStock;
|
||||||
|
let skuHtml = drug.sku ? `<span class="badge bg-secondary me-1">${drug.sku}</span>` : '';
|
||||||
|
|
||||||
const item = document.createElement('a');
|
const col = document.createElement('div');
|
||||||
item.className = `list-group-item list-group-item-action d-flex justify-content-between align-items-center ${isOutOfStock ? 'disabled bg-light' : ''}`;
|
col.className = 'col';
|
||||||
|
|
||||||
let skuHtml = drug.sku ? `<span class="badge bg-secondary me-2">${drug.sku}</span>` : '';
|
const card = document.createElement('div');
|
||||||
|
card.className = `card h-100 shadow-sm ${isOutOfStock ? 'bg-light opacity-75' : 'cursor-pointer border-0 hover-shadow'}`;
|
||||||
|
if (!isOutOfStock) {
|
||||||
|
card.style.cursor = 'pointer';
|
||||||
|
card.onclick = () => addToCart(drug);
|
||||||
|
}
|
||||||
|
|
||||||
item.innerHTML = `
|
const imgHtml = drug.image
|
||||||
<div>
|
? `<img src="${drug.image}" class="card-img-top" alt="${drug.name_en}" style="height: 120px; object-fit: cover;">`
|
||||||
<div class="fw-bold">${drug.name_en}</div>
|
: `<div class="card-img-top bg-light d-flex align-items-center justify-content-center text-muted" style="height: 120px;"><i class="bi bi-capsule fs-1"></i></div>`;
|
||||||
<small class="text-muted">${skuHtml}${drug.name_ar || ''}</small>
|
|
||||||
</div>
|
card.innerHTML = `
|
||||||
<div class="text-end">
|
${imgHtml}
|
||||||
<div class="fw-bold text-primary">${formatCurrency(price)}</div>
|
<div class="card-body p-2">
|
||||||
<small class="${isOutOfStock ? 'text-danger' : 'text-success'}">
|
<h6 class="card-title text-truncate mb-1 fw-bold" title="${drug.name_en}">${drug.name_en}</h6>
|
||||||
${isOutOfStock ? '<?php echo __('out_of_stock'); ?>' : '<?php echo __('stock'); ?>: ' + stock}
|
<small class="text-muted d-block text-truncate mb-2">${skuHtml}${drug.name_ar || ''}</small>
|
||||||
|
<div class="d-flex justify-content-between align-items-center mt-auto">
|
||||||
|
<span class="fw-bold text-primary">${formatCurrency(price)}</span>
|
||||||
|
<small class="${isOutOfStock ? 'text-danger fw-bold' : 'text-success'}">
|
||||||
|
${stock <= 0 ? '<?php echo __('out_of_stock'); ?>' : '<?php echo __('stock'); ?>: ' + stock}
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
if (!isOutOfStock) {
|
col.appendChild(card);
|
||||||
item.onclick = () => addToCart(drug);
|
drugList.appendChild(col);
|
||||||
item.style.cursor = 'pointer';
|
|
||||||
}
|
|
||||||
|
|
||||||
drugList.appendChild(item);
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
drugList.innerHTML = '<div class="list-group-item text-center text-danger">Error loading items</div>';
|
drugList.innerHTML = '<div class="col-12 text-center text-danger py-5">Error loading items</div>';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +216,7 @@ searchInput.addEventListener('input', function() {
|
|||||||
function addToCart(drug) {
|
function addToCart(drug) {
|
||||||
const existing = cart.find(i => i.id === drug.id);
|
const existing = cart.find(i => i.id === drug.id);
|
||||||
if (existing) {
|
if (existing) {
|
||||||
if (existing.quantity >= drug.stock) {
|
if (!allowNegativeStock && existing.quantity >= drug.stock) {
|
||||||
alert('<?php echo __('insufficient_stock'); ?>');
|
alert('<?php echo __('insufficient_stock'); ?>');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -218,7 +239,7 @@ function updateQty(id, change) {
|
|||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
const newQty = item.quantity + change;
|
const newQty = item.quantity + change;
|
||||||
if (newQty > item.max_stock) {
|
if (!allowNegativeStock && newQty > item.max_stock) {
|
||||||
alert('<?php echo __('insufficient_stock'); ?>');
|
alert('<?php echo __('insufficient_stock'); ?>');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,50 +11,72 @@
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="card shadow-sm border-0">
|
<div class="card shadow-sm border-0">
|
||||||
<div class="card-header py-3 d-flex align-items-center">
|
<div class="card-header bg-white">
|
||||||
<i class="bi bi-info-circle me-2"></i>
|
<ul class="nav nav-tabs card-header-tabs" id="settingsTabs" role="tablist">
|
||||||
<h5 class="mb-0 fw-bold"><?php echo __('company_details'); ?></h5>
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link active" id="general-tab" data-bs-toggle="tab" data-bs-target="#general" type="button" role="tab" aria-controls="general" aria-selected="true">
|
||||||
|
<i class="bi bi-info-circle me-2"></i><?php echo __('general_settings'); ?>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="system-tab" data-bs-toggle="tab" data-bs-target="#system" type="button" role="tab" aria-controls="system" aria-selected="false">
|
||||||
|
<i class="bi bi-gear me-2"></i><?php echo __('system_settings'); ?>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="email-tab" data-bs-toggle="tab" data-bs-target="#email" type="button" role="tab" aria-controls="email" aria-selected="false">
|
||||||
|
<i class="bi bi-envelope me-2"></i><?php echo __('email_settings'); ?>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<form action="settings.php" method="POST" enctype="multipart/form-data">
|
<form action="settings.php" method="POST" enctype="multipart/form-data">
|
||||||
|
<div class="tab-content" id="settingsTabsContent">
|
||||||
|
|
||||||
|
<!-- Tab 1: General Settings -->
|
||||||
|
<div class="tab-pane fade show active" id="general" role="tabpanel" aria-labelledby="general-tab">
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
|
<div class="col-12 mb-2">
|
||||||
|
<h6 class="fw-bold text-dark"><i class="bi bi-building me-2"></i> <?php echo __('company_details'); ?></h6>
|
||||||
|
</div>
|
||||||
<!-- Basic Information -->
|
<!-- Basic Information -->
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="company_name" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_name'); ?></label>
|
<label for="company_name" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('company_name'); ?></label>
|
||||||
<input type="text" class="form-control" id="company_name" name="company_name" value="<?php echo htmlspecialchars($settings['company_name'] ?? ''); ?>" required>
|
<input type="text" class="form-control" id="company_name" name="company_name" value="<?php echo htmlspecialchars($settings['company_name'] ?? ''); ?>" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="company_email" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_email'); ?></label>
|
<label for="company_email" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('company_email'); ?></label>
|
||||||
<input type="email" class="form-control" id="company_email" name="company_email" value="<?php echo htmlspecialchars($settings['company_email'] ?? ''); ?>">
|
<input type="email" class="form-control" id="company_email" name="company_email" value="<?php echo htmlspecialchars($settings['company_email'] ?? ''); ?>">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="company_phone" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_phone'); ?></label>
|
<label for="company_phone" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('company_phone'); ?></label>
|
||||||
<input type="text" class="form-control" id="company_phone" name="company_phone" value="<?php echo htmlspecialchars($settings['company_phone'] ?? ''); ?>">
|
<input type="text" class="form-control" id="company_phone" name="company_phone" value="<?php echo htmlspecialchars($settings['company_phone'] ?? ''); ?>">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="company_address" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_address'); ?></label>
|
<label for="company_address" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('company_address'); ?></label>
|
||||||
<input type="text" class="form-control" id="company_address" name="company_address" value="<?php echo htmlspecialchars($settings['company_address'] ?? ''); ?>">
|
<input type="text" class="form-control" id="company_address" name="company_address" value="<?php echo htmlspecialchars($settings['company_address'] ?? ''); ?>">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Registration Details -->
|
<!-- Registration Details -->
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="company_ctr_no" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('ctr_no'); ?></label>
|
<label for="company_ctr_no" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('ctr_no'); ?></label>
|
||||||
<input type="text" class="form-control" id="company_ctr_no" name="company_ctr_no" value="<?php echo htmlspecialchars($settings['company_ctr_no'] ?? ''); ?>">
|
<input type="text" class="form-control" id="company_ctr_no" name="company_ctr_no" value="<?php echo htmlspecialchars($settings['company_ctr_no'] ?? ''); ?>">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="company_registration_no" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('registration_no'); ?></label>
|
<label for="company_registration_no" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('registration_no'); ?></label>
|
||||||
<input type="text" class="form-control" id="company_registration_no" name="company_registration_no" value="<?php echo htmlspecialchars($settings['company_registration_no'] ?? ''); ?>">
|
<input type="text" class="form-control" id="company_registration_no" name="company_registration_no" value="<?php echo htmlspecialchars($settings['company_registration_no'] ?? ''); ?>">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="company_vat_no" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('vat_no'); ?></label>
|
<label for="company_vat_no" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('vat_no'); ?></label>
|
||||||
<input type="text" class="form-control" id="company_vat_no" name="company_vat_no" value="<?php echo htmlspecialchars($settings['company_vat_no'] ?? ''); ?>">
|
<input type="text" class="form-control" id="company_vat_no" name="company_vat_no" value="<?php echo htmlspecialchars($settings['company_vat_no'] ?? ''); ?>">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Timezone & Working Hours -->
|
<!-- Timezone & Working Hours -->
|
||||||
<div class="col-12 mt-4"><hr></div>
|
<div class="col-12 mt-4"><hr></div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="timezone" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('timezone'); ?></label>
|
<label for="timezone" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('timezone'); ?></label>
|
||||||
<select class="form-select" id="timezone" name="timezone">
|
<select class="form-select" id="timezone" name="timezone">
|
||||||
<?php
|
<?php
|
||||||
$timezones = DateTimeZone::listIdentifiers();
|
$timezones = DateTimeZone::listIdentifiers();
|
||||||
@ -67,16 +89,41 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="working_hours_start" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('working_hours_start'); ?></label>
|
<label for="working_hours_start" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('working_hours_start'); ?></label>
|
||||||
<input type="time" class="form-control" id="working_hours_start" name="working_hours_start" value="<?php echo htmlspecialchars($settings['working_hours_start'] ?? '08:00'); ?>">
|
<input type="time" class="form-control" id="working_hours_start" name="working_hours_start" value="<?php echo htmlspecialchars($settings['working_hours_start'] ?? '08:00'); ?>">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="working_hours_end" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('working_hours_end'); ?></label>
|
<label for="working_hours_end" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('working_hours_end'); ?></label>
|
||||||
<input type="time" class="form-control" id="working_hours_end" name="working_hours_end" value="<?php echo htmlspecialchars($settings['working_hours_end'] ?? '17:00'); ?>">
|
<input type="time" class="form-control" id="working_hours_end" name="working_hours_end" value="<?php echo htmlspecialchars($settings['working_hours_end'] ?? '17:00'); ?>">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Visit Settings -->
|
<!-- Branding -->
|
||||||
<div class="col-12 mt-4"><hr></div>
|
<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">
|
||||||
|
<img src="<?php echo htmlspecialchars($settings['company_logo']); ?>" alt="Logo" class="img-thumbnail" style="max-height: 80px;">
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<input type="file" class="form-control" id="company_logo" name="company_logo" accept="image/*">
|
||||||
|
</div>
|
||||||
|
<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">
|
||||||
|
<img src="<?php echo htmlspecialchars($settings['company_favicon']); ?>" alt="Favicon" class="img-thumbnail" style="max-height: 32px;">
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<input type="file" class="form-control" id="company_favicon" name="company_favicon" accept="image/x-icon,image/png">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab 2: System Settings -->
|
||||||
|
<div class="tab-pane fade" id="system" role="tabpanel" aria-labelledby="system-tab">
|
||||||
|
<div class="row g-4">
|
||||||
|
<!-- Visit Settings -->
|
||||||
<div class="col-12 mb-2">
|
<div class="col-12 mb-2">
|
||||||
<h6 class="fw-bold text-dark"><i class="bi bi-gear me-2"></i> <?php echo __('visit_settings'); ?></h6>
|
<h6 class="fw-bold text-dark"><i class="bi bi-gear me-2"></i> <?php echo __('visit_settings'); ?></h6>
|
||||||
</div>
|
</div>
|
||||||
@ -84,8 +131,8 @@
|
|||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input type="hidden" name="disable_visit_edit_24h" value="0">
|
<input type="hidden" name="disable_visit_edit_24h" value="0">
|
||||||
<input class="form-check-input" type="checkbox" id="disable_visit_edit_24h" name="disable_visit_edit_24h" value="1" <?php echo !empty($settings['disable_visit_edit_24h']) ? 'checked' : ''; ?>>
|
<input class="form-check-input" type="checkbox" id="disable_visit_edit_24h" name="disable_visit_edit_24h" value="1" <?php echo !empty($settings['disable_visit_edit_24h']) ? 'checked' : ''; ?>>
|
||||||
<label class="form-check-label" for="disable_visit_edit_24h"><?php echo __('disable_visit_edit_24h'); ?></label>
|
<label class="form-check-label" for="disable_visit_edit_24h"> <?php echo __('disable_visit_edit_24h'); ?></label>
|
||||||
<div class="form-text text-muted"><?php echo __('disable_visit_edit_24h_desc'); ?></div>
|
<div class="form-text text-muted"> <?php echo __('disable_visit_edit_24h_desc'); ?></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -95,33 +142,83 @@
|
|||||||
<h6 class="fw-bold text-dark"><i class="bi bi-cash-coin me-2"></i> <?php echo __('currency_settings'); ?></h6>
|
<h6 class="fw-bold text-dark"><i class="bi bi-cash-coin me-2"></i> <?php echo __('currency_settings'); ?></h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="currency_symbol" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('currency_symbol'); ?></label>
|
<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="$">
|
<input type="text" class="form-control" id="currency_symbol" name="currency_symbol" value="<?php echo htmlspecialchars($settings['currency_symbol'] ?? '$'); ?>" placeholder="$">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="decimal_digits" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('decimal_digits'); ?></label>
|
<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">
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- Branding -->
|
<!-- Pharmacy Settings -->
|
||||||
<div class="col-12 mt-4"><hr></div>
|
<div class="col-12 mt-4"><hr></div>
|
||||||
<div class="col-md-6 mt-2">
|
<div class="col-12 mb-2">
|
||||||
<label for="company_logo" class="form-label fw-semibold text-muted small text-uppercase"><?php echo __('company_logo'); ?></label>
|
<h6 class="fw-bold text-dark"><i class="bi bi-capsule me-2"></i> <?php echo __('pharmacy_settings'); ?></h6>
|
||||||
<?php if (!empty($settings['company_logo'])): ?>
|
|
||||||
<div class="mb-2">
|
|
||||||
<img src="<?php echo htmlspecialchars($settings['company_logo']); ?>" alt="Logo" class="img-thumbnail" style="max-height: 80px;">
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<div class="col-12">
|
||||||
<input type="file" class="form-control" id="company_logo" name="company_logo" accept="image/*">
|
<div class="form-check form-switch">
|
||||||
|
<input type="hidden" name="allow_negative_stock" value="0">
|
||||||
|
<input class="form-check-input" type="checkbox" id="allow_negative_stock" name="allow_negative_stock" value="1" <?php echo !empty($settings['allow_negative_stock']) ? 'checked' : ''; ?>>
|
||||||
|
<label class="form-check-label" for="allow_negative_stock"> <?php echo __('allow_negative_stock'); ?></label>
|
||||||
|
<div class="form-text text-muted"> <?php echo __('allow_negative_stock_desc'); ?></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab 3: Email Settings -->
|
||||||
|
<div class="tab-pane fade" id="email" role="tabpanel" aria-labelledby="email-tab">
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-12 mb-2">
|
||||||
|
<h6 class="fw-bold text-dark"><i class="bi bi-envelope me-2"></i> <?php echo __('email_settings'); ?></h6>
|
||||||
|
<div class="alert alert-info py-2 small">
|
||||||
|
<i class="bi bi-info-circle me-1"></i> Use these settings to configure outgoing emails.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-8">
|
||||||
|
<label for="smtp_host" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('smtp_host'); ?></label>
|
||||||
|
<input type="text" class="form-control" id="smtp_host" name="smtp_host" value="<?php echo htmlspecialchars($settings['smtp_host'] ?? ''); ?>" placeholder="smtp.example.com">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="smtp_port" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('smtp_port'); ?></label>
|
||||||
|
<input type="number" class="form-control" id="smtp_port" name="smtp_port" value="<?php echo htmlspecialchars($settings['smtp_port'] ?? '587'); ?>" placeholder="587">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="smtp_user" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('smtp_user'); ?></label>
|
||||||
|
<input type="text" class="form-control" id="smtp_user" name="smtp_user" value="<?php echo htmlspecialchars($settings['smtp_user'] ?? ''); ?>" placeholder="user@example.com">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="smtp_pass" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('smtp_pass'); ?></label>
|
||||||
|
<input type="password" class="form-control" id="smtp_pass" name="smtp_pass" value="<?php echo htmlspecialchars($settings['smtp_pass'] ?? ''); ?>" placeholder="********">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="smtp_secure" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('smtp_secure'); ?></label>
|
||||||
|
<select class="form-select" id="smtp_secure" name="smtp_secure">
|
||||||
|
<option value="tls" <?php echo ($settings['smtp_secure'] ?? '') === 'tls' ? 'selected' : ''; ?>><?php echo __('tls'); ?></option>
|
||||||
|
<option value="ssl" <?php echo ($settings['smtp_secure'] ?? '') === 'ssl' ? 'selected' : ''; ?>><?php echo __('ssl'); ?></option>
|
||||||
|
<option value="" <?php echo ($settings['smtp_secure'] ?? '') === '' ? 'selected' : ''; ?>><?php echo __('none'); ?></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 mt-4"><hr></div>
|
||||||
|
<div class="col-12 mb-2">
|
||||||
|
<h6 class="fw-bold text-dark"><i class="bi bi-person-badge me-2"></i> <?php echo __('smtp_from_name'); ?> & <?php echo __('email'); ?></h6>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="smtp_from_email" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('smtp_from_email'); ?></label>
|
||||||
|
<input type="email" class="form-control" id="smtp_from_email" name="smtp_from_email" value="<?php echo htmlspecialchars($settings['smtp_from_email'] ?? ''); ?>" placeholder="noreply@example.com">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="smtp_from_name" class="form-label fw-semibold text-muted small text-uppercase"> <?php echo __('smtp_from_name'); ?></label>
|
||||||
|
<input type="text" class="form-control" id="smtp_from_name" name="smtp_from_name" value="<?php echo htmlspecialchars($settings['smtp_from_name'] ?? ''); ?>" placeholder="My Hospital">
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<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">
|
|
||||||
<img src="<?php echo htmlspecialchars($settings['company_favicon']); ?>" alt="Favicon" class="img-thumbnail" style="max-height: 32px;">
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
|
||||||
<input type="file" class="form-control" id="company_favicon" name="company_favicon" accept="image/x-icon,image/png">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 mt-5 text-end">
|
<div class="col-12 mt-5 text-end">
|
||||||
@ -129,7 +226,6 @@
|
|||||||
<i class="bi bi-check2-circle me-2"></i> <?php echo __('save_changes'); ?>
|
<i class="bi bi-check2-circle me-2"></i> <?php echo __('save_changes'); ?>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
326
lang.php
326
lang.php
@ -382,6 +382,55 @@ $translations = array (
|
|||||||
'wait_time' => 'Wait Time',
|
'wait_time' => 'Wait Time',
|
||||||
'call' => 'Call',
|
'call' => 'Call',
|
||||||
'finish' => 'Finish',
|
'finish' => 'Finish',
|
||||||
|
'drug_group' => 'Drug Group',
|
||||||
|
'select_group' => 'Select Group',
|
||||||
|
'select_supplier' => 'Select Supplier',
|
||||||
|
'import_drugs' => 'Import Drugs',
|
||||||
|
'upload_file' => 'Upload File',
|
||||||
|
'csv_format_drugs' => 'Format: Name (EN), Name (AR), Group, Price, Expiry, Supplier',
|
||||||
|
'delete_drug' => 'Delete Drug',
|
||||||
|
'auto_translate' => 'Auto Translate',
|
||||||
|
'translate' => 'Translate',
|
||||||
|
'image' => 'Image',
|
||||||
|
'all' => 'All',
|
||||||
|
'are_you_sure_delete' => 'Are you sure you want to delete?',
|
||||||
|
'no_drugs_found' => 'No drugs found',
|
||||||
|
'insufficient_stock' => 'Insufficient stock',
|
||||||
|
'cart_is_empty' => 'Cart is empty',
|
||||||
|
'payment_method' => 'Payment Method',
|
||||||
|
'cash' => 'Cash',
|
||||||
|
'card' => 'Card',
|
||||||
|
'total_amount' => 'Total Amount',
|
||||||
|
'confirm_payment' => 'Confirm Payment',
|
||||||
|
'cart' => 'Cart',
|
||||||
|
'checkout' => 'Checkout',
|
||||||
|
'search_patient' => 'Search Patient',
|
||||||
|
'cart_empty' => 'Cart is empty',
|
||||||
|
'stock' => 'Stock',
|
||||||
|
'default_dosage' => 'Default Dosage',
|
||||||
|
'default_instructions' => 'Default Instructions',
|
||||||
|
'import' => 'Import',
|
||||||
|
'description_en' => 'Description (English)',
|
||||||
|
'description_ar' => 'Description (Arabic)',
|
||||||
|
'general_settings' => 'General Settings',
|
||||||
|
'system_settings' => 'System Settings',
|
||||||
|
'email_settings' => 'Email Settings',
|
||||||
|
'pharmacy_settings' => 'Pharmacy Settings',
|
||||||
|
'allow_negative_stock' => 'Allow Negative Stock Sales',
|
||||||
|
'allow_negative_stock_desc' => 'If enabled, the POS will allow sales even if the system shows zero stock.',
|
||||||
|
'smtp_host' => 'SMTP Host',
|
||||||
|
'smtp_port' => 'SMTP Port',
|
||||||
|
'smtp_user' => 'SMTP User',
|
||||||
|
'smtp_pass' => 'SMTP Password',
|
||||||
|
'smtp_secure' => 'SMTP Encryption',
|
||||||
|
'smtp_from_email' => 'From Email',
|
||||||
|
'smtp_from_name' => 'From Name',
|
||||||
|
'smtp_test' => 'Test SMTP Connection',
|
||||||
|
'smtp_test_success' => 'SMTP Connection Successful',
|
||||||
|
'smtp_test_failed' => 'SMTP Connection Failed',
|
||||||
|
'none' => 'None',
|
||||||
|
'ssl' => 'SSL',
|
||||||
|
'tls' => 'TLS'
|
||||||
),
|
),
|
||||||
'ar' =>
|
'ar' =>
|
||||||
array (
|
array (
|
||||||
@ -643,127 +692,176 @@ $translations = array (
|
|||||||
'add_ad' => 'إضافة إعلان',
|
'add_ad' => 'إضافة إعلان',
|
||||||
'edit_ad' => 'تعديل إعلان',
|
'edit_ad' => 'تعديل إعلان',
|
||||||
'delete_ad' => 'حذف إعلان',
|
'delete_ad' => 'حذف إعلان',
|
||||||
'ad_text_en' => 'نص الإعلان (إنجليزي)',
|
'ad_text_en' => 'Ad Text (English)',
|
||||||
'ad_text_ar' => 'نص الإعلان (عربي)',
|
'ad_text_ar' => 'Ad Text (Arabic)',
|
||||||
'no_ads_found' => 'لا توجد إعلانات',
|
'no_ads_found' => 'No ads found',
|
||||||
'scheduled' => 'مجدولة',
|
'scheduled' => 'Scheduled',
|
||||||
'completed' => 'مكتملة',
|
'completed' => 'Completed',
|
||||||
'cancelled' => 'ملغاة',
|
'cancelled' => 'Cancelled',
|
||||||
'no_address_provided' => 'لم يتم تقديم عنوان',
|
'no_address_provided' => 'No address provided',
|
||||||
'provider' => 'المقدم',
|
'provider' => 'Provider',
|
||||||
'unassigned' => 'غير معين',
|
'unassigned' => 'Unassigned',
|
||||||
'reason_label' => 'السبب',
|
'reason_label' => 'Reason',
|
||||||
'complete' => 'إكمال',
|
'complete' => 'Complete',
|
||||||
'complete_home_visit' => 'إكمال الزيارة المنزلية',
|
'complete_home_visit' => 'Complete Home Visit',
|
||||||
'notes_treatment' => 'ملاحظات / العلاج',
|
'notes_treatment' => 'Notes / Treatment',
|
||||||
'create_bill' => 'إنشاء فاتورة',
|
'create_bill' => 'Create Bill',
|
||||||
'save_complete' => 'حفظ وإكمال',
|
'save_complete' => 'Save & Complete',
|
||||||
'no_appointments_found' => 'لا توجد مواعيد',
|
'no_appointments_found' => 'No appointments found',
|
||||||
'doctor_is_on_holiday_on_this_date' => 'الطبيب المحدد في إجازة في هذا التاريخ.',
|
'doctor_is_on_holiday_on_this_date' => 'Selected doctor is on holiday on this date.',
|
||||||
'edit_appointment' => 'تعديل موعد',
|
'edit_appointment' => 'Edit Appointment',
|
||||||
'appointment_details' => 'تفاصيل الموعد',
|
'appointment_details' => 'Appointment Details',
|
||||||
'print_daily_list' => 'طباعة القائمة اليومية',
|
'print_daily_list' => 'Print Daily List',
|
||||||
'appointments_list' => 'قائمة المواعيد',
|
'appointments_list' => 'Appointments List',
|
||||||
'back' => 'رجوع',
|
'back' => 'Back',
|
||||||
'no_appointments' => 'لم يتم العثور على مواعيد',
|
'no_appointments' => 'No appointments found',
|
||||||
'printed_on' => 'تم الطباعة في',
|
'printed_on' => 'Printed on',
|
||||||
'fill_all_fields' => 'يرجى ملء جميع الحقول',
|
'fill_all_fields' => 'Please fill in all fields',
|
||||||
'invalid_credentials' => 'البريد الإلكتروني أو كلمة المرور غير صحيحة',
|
'invalid_credentials' => 'Invalid email or password',
|
||||||
'login_to_continue' => 'قم بتسجيل الدخول للمتابعة',
|
'login_to_continue' => 'Login to continue to your account',
|
||||||
'forgot_password' => 'هل نسيت كلمة المرور؟',
|
'forgot_password' => 'Forgot Password?',
|
||||||
'user_profile' => 'الملف الشخصي',
|
'user_profile' => 'User Profile',
|
||||||
'profile_picture' => 'الصورة الشخصية',
|
'profile_picture' => 'Profile Picture',
|
||||||
'edit_profile' => 'تعديل الملف الشخصي',
|
'edit_profile' => 'Edit Profile',
|
||||||
'change_avatar' => 'تغيير الصورة',
|
'change_avatar' => 'Change Avatar',
|
||||||
'choose_file' => 'اختر ملف',
|
'choose_file' => 'Choose file',
|
||||||
'allowed_file_types' => 'أنواع الملفات المسموحة',
|
'allowed_file_types' => 'Allowed file types',
|
||||||
'change_password' => 'تغيير كلمة المرور',
|
'change_password' => 'Change Password',
|
||||||
'leave_blank_to_keep_current' => 'اتركه فارغاً للاحتفاظ بكلمة المرور الحالية',
|
'leave_blank_to_keep_current' => 'Leave blank to keep current password',
|
||||||
'new_password' => 'كلمة المرور الجديدة',
|
'new_password' => 'New Password',
|
||||||
'confirm_password' => 'تأكيد كلمة المرور',
|
'confirm_password' => 'Confirm Password',
|
||||||
'name_required' => 'الاسم مطلوب',
|
'name_required' => 'Name is required',
|
||||||
'email_required' => 'البريد الإلكتروني مطلوب',
|
'email_required' => 'Email is required',
|
||||||
'email_already_taken' => 'البريد الإلكتروني مسجل مسبقاً',
|
'email_already_taken' => 'Email is already taken',
|
||||||
'password_min_length' => 'يجب أن تتكون كلمة المرور من 6 أحرف على الأقل',
|
'password_min_length' => 'Password must be at least 6 characters',
|
||||||
'passwords_do_not_match' => 'كلمات المرور غير متطابقة',
|
'passwords_do_not_match' => 'Passwords do not match',
|
||||||
'invalid_file_type' => 'نوع الملف غير صالح. مسموح فقط بـ JPG, PNG, GIF.',
|
'invalid_file_type' => 'Invalid file type. Only JPG, PNG and GIF are allowed.',
|
||||||
'upload_failed' => 'فشل تحميل الملف',
|
'upload_failed' => 'File upload failed',
|
||||||
'profile_updated_successfully' => 'تم تحديث الملف الشخصي بنجاح',
|
'profile_updated_successfully' => 'Profile updated successfully',
|
||||||
'error_updating_profile' => 'خطأ في تحديث الملف الشخصي',
|
'error_updating_profile' => 'Error updating profile',
|
||||||
'settings_updated_successfully' => 'تم تحديث الإعدادات بنجاح.',
|
'settings_updated_successfully' => 'Settings updated successfully.',
|
||||||
'company_details' => 'تفاصيل الشركة',
|
'company_details' => 'Company Details',
|
||||||
'company_name' => 'اسم الشركة',
|
'company_name' => 'Company Name',
|
||||||
'company_email' => 'البريد الإلكتروني للشركة',
|
'company_email' => 'Company Email',
|
||||||
'company_phone' => 'هاتف الشركة',
|
'company_phone' => 'Company Phone',
|
||||||
'company_address' => 'عنوان الشركة',
|
'company_address' => 'Company Address',
|
||||||
'ctr_no' => 'رقم السجل التجاري',
|
'ctr_no' => 'CR No.',
|
||||||
'registration_no' => 'رقم التسجيل',
|
'registration_no' => 'Registration No.',
|
||||||
'vat_no' => 'الرقم الضريبي',
|
'vat_no' => 'VAT No.',
|
||||||
'timezone' => 'المنطقة الزمنية',
|
'timezone' => 'Timezone',
|
||||||
'working_hours_start' => 'بداية ساعات العمل',
|
'working_hours_start' => 'Working Hours Start',
|
||||||
'working_hours_end' => 'نهاية ساعات العمل',
|
'working_hours_end' => 'Working Hours End',
|
||||||
'currency_settings' => 'إعدادات العملة',
|
'currency_settings' => 'Currency Settings',
|
||||||
'currency_symbol' => 'رمز العملة',
|
'currency_symbol' => 'Currency Symbol',
|
||||||
'decimal_digits' => 'الخانات العشرية',
|
'decimal_digits' => 'Decimal Digits',
|
||||||
'company_logo' => 'شعار الشركة',
|
'company_logo' => 'Company Logo',
|
||||||
'company_favicon' => 'أيقونة الموقع',
|
'company_favicon' => 'Company Favicon',
|
||||||
'civil_id' => 'الرقم المدني',
|
'civil_id' => 'Civil ID',
|
||||||
'nationality' => 'الجنسية',
|
'nationality' => 'Nationality',
|
||||||
'dob' => 'تاريخ الميلاد',
|
'dob' => 'Date of Birth',
|
||||||
'gender' => 'الجنس',
|
'gender' => 'Gender',
|
||||||
'blood_group' => 'فصيلة الدم',
|
'blood_group' => 'Blood Group',
|
||||||
'insurance_company' => 'شركة التأمين',
|
'insurance_company' => 'Insurance Company',
|
||||||
'address' => 'العنوان',
|
'address' => 'Address',
|
||||||
'male' => 'ذكر',
|
'male' => 'Male',
|
||||||
'female' => 'أنثى',
|
'female' => 'Female',
|
||||||
'other' => 'آخر',
|
'other' => 'Other',
|
||||||
'edit_patient' => 'تعديل مريض',
|
'edit_patient' => 'Edit Patient',
|
||||||
'delete_patient' => 'حذف مريض',
|
'delete_patient' => 'Delete Patient',
|
||||||
'confirm_delete' => 'هل أنت متأكد من حذف',
|
'confirm_delete' => 'Are you sure you want to delete',
|
||||||
'add_doctor' => 'إضافة طبيب',
|
'add_doctor' => 'Add Doctor',
|
||||||
'edit_doctor' => 'تعديل طبيب',
|
'edit_doctor' => 'Edit Doctor',
|
||||||
'specialization_en' => 'التخصص (إنجليزي)',
|
'specialization_en' => 'Specialization (English)',
|
||||||
'specialization_ar' => 'التخصص (عربي)',
|
'specialization_ar' => 'Specialization (Arabic)',
|
||||||
'hr_management' => 'إدارة الموارد البشرية',
|
'hr_management' => 'HR Management',
|
||||||
'attendance' => 'الحضور والانصراف',
|
'attendance' => 'Attendance',
|
||||||
'leave_requests' => 'طلبات الإجازة',
|
'leave_requests' => 'Leave Requests',
|
||||||
'add_employee' => 'إضافة موظف',
|
'add_employee' => 'Add Employee',
|
||||||
'edit_employee' => 'تعديل موظف',
|
'edit_employee' => 'Edit Employee',
|
||||||
'delete_employee' => 'حذف موظف',
|
'delete_employee' => 'Delete Employee',
|
||||||
'select_position' => 'اختر المسمى الوظيفي',
|
'select_position' => 'Select Position',
|
||||||
'no_employees_found' => 'لم يتم العثور على موظفين',
|
'no_employees_found' => 'No employees found',
|
||||||
'visit_settings' => 'Visit Settings',
|
'visit_settings' => 'Visit Settings',
|
||||||
'disable_visit_edit_24h' => 'Disable editing visits after 24 hours',
|
'disable_visit_edit_24h' => 'Disable editing visits after 24 hours',
|
||||||
'disable_visit_edit_24h_desc' => 'If enabled, visits cannot be edited 24 hours after their creation.',
|
'disable_visit_edit_24h_desc' => 'If enabled, visits cannot be edited 24 hours after their creation.',
|
||||||
'details' => 'التفاصيل',
|
'details' => 'Details',
|
||||||
'vitals' => 'المؤشرات الحيوية',
|
'vitals' => 'Vitals',
|
||||||
'symptoms_diagnosis' => 'الأعراض والتشخيص',
|
'symptoms_diagnosis' => 'Symptoms & Diagnosis',
|
||||||
'treatment_plan' => 'خطة العلاج',
|
'treatment_plan' => 'Treatment Plan',
|
||||||
'prescriptions' => 'الوصفات الطبية',
|
'prescriptions' => 'Prescriptions',
|
||||||
'weight' => 'الوزن',
|
'weight' => 'Weight',
|
||||||
'blood_pressure' => 'ضغط الدم',
|
'blood_pressure' => 'Blood Pressure',
|
||||||
'heart_rate' => 'معدل ضربات القلب',
|
'heart_rate' => 'Heart Rate',
|
||||||
'temperature' => 'درجة الحرارة',
|
'temperature' => 'Temperature',
|
||||||
'symptoms' => 'الأعراض',
|
'symptoms' => 'Symptoms',
|
||||||
'diagnosis' => 'التشخيص',
|
'diagnosis' => 'Diagnosis',
|
||||||
'drug_name' => 'اسم الدواء',
|
'drug_name' => 'Drug Name',
|
||||||
'dosage' => 'الجرعة',
|
'dosage' => 'Dosage',
|
||||||
'instructions' => 'التعليمات',
|
'instructions' => 'Instructions',
|
||||||
'add_drug' => 'إضافة دواء',
|
'add_drug' => 'Add Drug',
|
||||||
'nursing_notes' => 'ملاحظات التمريض',
|
'nursing_notes' => 'Nursing Notes',
|
||||||
'issue_new_token' => 'إصدار تذكرة جديدة',
|
'issue_new_token' => 'Issue New Token',
|
||||||
'select_patient' => 'اختر المريض',
|
'select_patient' => 'Select Patient',
|
||||||
'showing_last_50_patients' => 'عرض آخر 50 مريض مسجل',
|
'showing_last_50_patients' => 'Showing last 50 registered patients',
|
||||||
'doctor_optional' => 'الطبيب (اختياري)',
|
'doctor_optional' => 'Doctor (Optional)',
|
||||||
'any_doctor' => 'أي طبيب',
|
'any_doctor' => 'Any Doctor',
|
||||||
'waiting' => 'انتظار',
|
'waiting' => 'Waiting',
|
||||||
'serving' => 'تحت الخدمة',
|
'serving' => 'Serving',
|
||||||
'all_statuses' => 'كل الحالات',
|
'all_statuses' => 'All Statuses',
|
||||||
'refresh' => 'تحديث',
|
'refresh' => 'تحديث',
|
||||||
'no_tokens_found' => 'لا توجد تذاكر',
|
'no_tokens_found' => 'لا توجد تذاكر',
|
||||||
'token' => 'التذكرة',
|
'token' => 'التذكرة',
|
||||||
'wait_time' => 'وقت الانتظار',
|
'wait_time' => 'وقت الانتظار',
|
||||||
'call' => 'نداء',
|
'call' => 'نداء',
|
||||||
'finish' => 'إنهاء',
|
'finish' => 'إنهاء',
|
||||||
),
|
'drug_group' => 'مجموعة الدواء',
|
||||||
|
'select_group' => 'اختر المجموعة',
|
||||||
|
'select_supplier' => 'اختر المورد',
|
||||||
|
'import_drugs' => 'استيراد الأدوية',
|
||||||
|
'upload_file' => 'رفع ملف',
|
||||||
|
'csv_format_drugs' => 'التنسيق: الاسم (إنجليزي), الاسم (عربي), المجموعة, السعر, انتهاء الصلاحية, المورد',
|
||||||
|
'delete_drug' => 'حذف الدواء',
|
||||||
|
'auto_translate' => 'ترجمة تلقائية',
|
||||||
|
'translate' => 'ترجمة',
|
||||||
|
'image' => 'صورة',
|
||||||
|
'all' => 'الكل',
|
||||||
|
'are_you_sure_delete' => 'هل أنت متأكد من الحذف؟',
|
||||||
|
'no_drugs_found' => 'لم يتم العثور على أدوية',
|
||||||
|
'insufficient_stock' => 'المخزون غير كاف',
|
||||||
|
'cart_is_empty' => 'السلة فارغة',
|
||||||
|
'payment_method' => 'طريقة الدفع',
|
||||||
|
'cash' => 'نقد',
|
||||||
|
'card' => 'بطاقة',
|
||||||
|
'total_amount' => 'المبلغ الإجمالي',
|
||||||
|
'confirm_payment' => 'تأكيد الدفع',
|
||||||
|
'cart' => 'السلة',
|
||||||
|
'checkout' => 'دفع',
|
||||||
|
'search_patient' => 'بحث عن مريض',
|
||||||
|
'cart_empty' => 'السلة فارغة',
|
||||||
|
'stock' => 'المخزون',
|
||||||
|
'default_dosage' => 'الجرعة الافتراضية',
|
||||||
|
'default_instructions' => 'التعليمات الافتراضية',
|
||||||
|
'import' => 'استيراد',
|
||||||
|
'description_en' => 'الوصف (إنجليزي)',
|
||||||
|
'description_ar' => 'الوصف (عربي)',
|
||||||
|
'general_settings' => 'الإعدادات العامة',
|
||||||
|
'system_settings' => 'إعدادات النظام',
|
||||||
|
'email_settings' => 'إعدادات البريد الإلكتروني',
|
||||||
|
'pharmacy_settings' => 'إعدادات الصيدلية',
|
||||||
|
'allow_negative_stock' => 'السماح بالبيع بالسالب',
|
||||||
|
'allow_negative_stock_desc' => 'في حالة التفعيل، سيسمح نظام نقاط البيع بإتمام عملية البيع حتى لو كان الرصيد صفراً.',
|
||||||
|
'smtp_host' => 'خادم SMTP',
|
||||||
|
'smtp_port' => 'منفذ SMTP',
|
||||||
|
'smtp_user' => 'اسم مستخدم SMTP',
|
||||||
|
'smtp_pass' => 'كلمة مرور SMTP',
|
||||||
|
'smtp_secure' => 'تشفير SMTP',
|
||||||
|
'smtp_from_email' => 'البريد الإلكتروني للمرسل',
|
||||||
|
'smtp_from_name' => 'اسم المرسل',
|
||||||
|
'smtp_test' => 'اختبار اتصال SMTP',
|
||||||
|
'smtp_test_success' => 'نجح الاتصال بخادم SMTP',
|
||||||
|
'smtp_test_failed' => 'فشل الاتصال بخادم SMTP',
|
||||||
|
'none' => 'بدون',
|
||||||
|
'ssl' => 'SSL',
|
||||||
|
'tls' => 'TLS'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
@ -1,16 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
// Mail configuration sourced from environment variables.
|
// Mail configuration sourced from environment variables or Database Settings.
|
||||||
// No secrets are stored here; the file just maps env -> config array for MailService.
|
|
||||||
|
|
||||||
function env_val(string $key, $default = null) {
|
if (!function_exists('env_val')) {
|
||||||
|
function env_val(string $key, $default = null) {
|
||||||
$v = getenv($key);
|
$v = getenv($key);
|
||||||
return ($v === false || $v === null || $v === '') ? $default : $v;
|
return ($v === false || $v === null || $v === '') ? $default : $v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: if critical vars are missing from process env, try to parse executor/.env
|
// Fallback: if critical vars are missing from process env, try to parse executor/.env
|
||||||
// This helps in web/Apache contexts where .env is not exported.
|
if (!function_exists('load_dotenv_if_needed')) {
|
||||||
// Supports simple KEY=VALUE lines; ignores quotes and comments.
|
function load_dotenv_if_needed(array $keys): void {
|
||||||
function load_dotenv_if_needed(array $keys): void {
|
|
||||||
$missing = array_filter($keys, fn($k) => getenv($k) === false || getenv($k) === '');
|
$missing = array_filter($keys, fn($k) => getenv($k) === false || getenv($k) === '');
|
||||||
if (empty($missing)) return;
|
if (empty($missing)) return;
|
||||||
static $loaded = false;
|
static $loaded = false;
|
||||||
@ -22,15 +22,14 @@ function load_dotenv_if_needed(array $keys): void {
|
|||||||
if ($line[0] === '#' || trim($line) === '') continue;
|
if ($line[0] === '#' || trim($line) === '') continue;
|
||||||
if (!str_contains($line, '=')) continue;
|
if (!str_contains($line, '=')) continue;
|
||||||
[$k, $v] = array_map('trim', explode('=', $line, 2));
|
[$k, $v] = array_map('trim', explode('=', $line, 2));
|
||||||
// Strip potential surrounding quotes
|
$v = trim($v, "' ");
|
||||||
$v = trim($v, "\"' ");
|
|
||||||
// Do not override existing env
|
|
||||||
if ($k !== '' && (getenv($k) === false || getenv($k) === '')) {
|
if ($k !== '' && (getenv($k) === false || getenv($k) === '')) {
|
||||||
putenv("{$k}={$v}");
|
putenv("{$k}={$v}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$loaded = true;
|
$loaded = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
load_dotenv_if_needed([
|
load_dotenv_if_needed([
|
||||||
@ -39,6 +38,7 @@ load_dotenv_if_needed([
|
|||||||
'DKIM_DOMAIN','DKIM_SELECTOR','DKIM_PRIVATE_KEY_PATH'
|
'DKIM_DOMAIN','DKIM_SELECTOR','DKIM_PRIVATE_KEY_PATH'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 1. Defaults from Environment
|
||||||
$transport = env_val('MAIL_TRANSPORT', 'smtp');
|
$transport = env_val('MAIL_TRANSPORT', 'smtp');
|
||||||
$smtp_host = env_val('SMTP_HOST');
|
$smtp_host = env_val('SMTP_HOST');
|
||||||
$smtp_port = (int) env_val('SMTP_PORT', 587);
|
$smtp_port = (int) env_val('SMTP_PORT', 587);
|
||||||
@ -54,6 +54,35 @@ $dkim_domain = env_val('DKIM_DOMAIN');
|
|||||||
$dkim_selector = env_val('DKIM_SELECTOR');
|
$dkim_selector = env_val('DKIM_SELECTOR');
|
||||||
$dkim_private_key_path = env_val('DKIM_PRIVATE_KEY_PATH');
|
$dkim_private_key_path = env_val('DKIM_PRIVATE_KEY_PATH');
|
||||||
|
|
||||||
|
// 2. Override from Database (if available)
|
||||||
|
if (file_exists(__DIR__ . '/../db/config.php')) {
|
||||||
|
require_once __DIR__ . '/../db/config.php';
|
||||||
|
if (function_exists('db')) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
// Check if settings table exists to avoid errors during fresh install/migration
|
||||||
|
$checkTable = $pdo->query("SHOW TABLES LIKE 'settings'");
|
||||||
|
if ($checkTable->rowCount() > 0) {
|
||||||
|
$stmt = $pdo->query("SELECT setting_key, setting_value FROM settings WHERE setting_key LIKE 'smtp_%'");
|
||||||
|
$db_settings = [];
|
||||||
|
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
$db_settings[$row['setting_key']] = $row['setting_value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($db_settings['smtp_host'])) $smtp_host = $db_settings['smtp_host'];
|
||||||
|
if (!empty($db_settings['smtp_port'])) $smtp_port = (int)$db_settings['smtp_port'];
|
||||||
|
if (isset($db_settings['smtp_user'])) $smtp_user = $db_settings['smtp_user'];
|
||||||
|
if (isset($db_settings['smtp_pass'])) $smtp_pass = $db_settings['smtp_pass'];
|
||||||
|
if (isset($db_settings['smtp_secure'])) $smtp_secure = $db_settings['smtp_secure'];
|
||||||
|
if (!empty($db_settings['smtp_from_email'])) $from_email = $db_settings['smtp_from_email'];
|
||||||
|
if (!empty($db_settings['smtp_from_name'])) $from_name = $db_settings['smtp_from_name'];
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Ignore DB errors (e.g. connection issues or during installation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'transport' => $transport,
|
'transport' => $transport,
|
||||||
|
|
||||||
|
|||||||
@ -62,169 +62,238 @@ try {
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en" dir="ltr">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Receipt #<?php echo $sale_id; ?></title>
|
<title>Receipt #<?php echo $sale_id; ?></title>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
||||||
<style>
|
<style>
|
||||||
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #333; }
|
|
||||||
.receipt-header { border-bottom: 2px solid #333; padding-bottom: 20px; margin-bottom: 20px; }
|
|
||||||
.receipt-footer { border-top: 1px dashed #333; padding-top: 20px; margin-top: 30px; }
|
|
||||||
.company-logo { max-height: 80px; }
|
|
||||||
.receipt-title { font-size: 1.8rem; font-weight: bold; text-transform: uppercase; }
|
|
||||||
|
|
||||||
.table thead th { border-bottom: 2px solid #333; background-color: #f8f9fa; font-size: 0.9rem; }
|
|
||||||
.table-bordered td, .table-bordered th { border-color: #dee2e6; }
|
|
||||||
|
|
||||||
.bilingual { display: flex; flex-direction: column; line-height: 1.2; }
|
|
||||||
.text-ar { font-family: Tahoma, sans-serif; font-size: 0.9em; direction: rtl; }
|
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
.no-print { display: none !important; }
|
@page {
|
||||||
body { padding: 0; margin: 0; background: white; }
|
size: 80mm auto; /* Force 80mm width */
|
||||||
.container { max-width: 100%; width: 100%; padding: 0; }
|
margin: 0; /* No margins from printer driver */
|
||||||
.card { border: none !important; box-shadow: none !important; }
|
}
|
||||||
|
html, body {
|
||||||
|
width: 80mm;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.no-print {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
width: 100% !important;
|
||||||
|
padding: 1mm 2mm !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Courier New', Courier, monospace; /* Monospace for alignment */
|
||||||
|
font-size: 11px;
|
||||||
|
color: #000;
|
||||||
|
background: #fff;
|
||||||
|
width: 78mm; /* Screen preview width */
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.logo {
|
||||||
|
max-width: 40px;
|
||||||
|
max-height: 40px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
.company-name {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.company-info {
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
.divider {
|
||||||
|
border-top: 1px dashed #000;
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
.receipt-details {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 10px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
.items-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-size: 10px;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
.items-table th {
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px dashed #000;
|
||||||
|
padding: 2px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.items-table td {
|
||||||
|
padding: 2px 0;
|
||||||
|
vertical-align: top;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ar-text {
|
||||||
|
display: block;
|
||||||
|
direction: rtl;
|
||||||
|
font-family: Tahoma, sans-serif; /* Better for Arabic */
|
||||||
|
font-size: 9px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-section {
|
||||||
|
margin-top: 5px;
|
||||||
|
border-top: 1px dashed #000;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 5px 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
.btn-secondary { background: #6c757d; }
|
||||||
|
.no-print {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border: 1px solid #ddd;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body onload="window.print()">
|
<body onload="window.print()">
|
||||||
|
|
||||||
<div class="container my-4" style="max-width: 800px;">
|
<div class="no-print">
|
||||||
<div class="no-print mb-4 text-end">
|
<button onclick="window.print()" class="btn">Print 80mm</button>
|
||||||
<button onclick="window.print()" class="btn btn-primary"><i class="bi bi-printer"></i> Print</button>
|
|
||||||
<button onclick="window.close()" class="btn btn-secondary">Close</button>
|
<button onclick="window.close()" class="btn btn-secondary">Close</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card p-4">
|
<div class="container">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="receipt-header">
|
<div class="header">
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col-8">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<?php if (!empty($settings['company_logo'])): ?>
|
<?php if (!empty($settings['company_logo'])): ?>
|
||||||
<img src="<?php echo htmlspecialchars($settings['company_logo']); ?>" alt="Logo" class="company-logo me-3">
|
<img src="<?php echo htmlspecialchars($settings['company_logo']); ?>" alt="Logo" class="logo">
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<div>
|
<div class="company-name"><?php echo htmlspecialchars($settings['company_name'] ?? 'Pharmacy'); ?></div>
|
||||||
<h4 class="fw-bold m-0"><?php echo htmlspecialchars($settings['company_name'] ?? 'Pharmacy Name'); ?></h4>
|
<div class="company-info">
|
||||||
<div class="small text-muted mt-1">
|
|
||||||
<?php echo htmlspecialchars($settings['company_address'] ?? ''); ?><br>
|
<?php echo htmlspecialchars($settings['company_address'] ?? ''); ?><br>
|
||||||
<?php echo htmlspecialchars($settings['company_phone'] ?? ''); ?>
|
<?php echo htmlspecialchars($settings['company_phone'] ?? ''); ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<!-- Receipt Meta -->
|
||||||
|
<div class="receipt-details">
|
||||||
|
<span>#<?php echo $sale_id; ?></span>
|
||||||
|
<span style="direction: ltr;"><?php echo date('Y-m-d H:i', strtotime($sale['created_at'])); ?></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="receipt-details">
|
||||||
<div class="col-4 text-end">
|
<span>رقم الإيصال</span>
|
||||||
<div class="receipt-title">RECEIPT</div>
|
<span>التاريخ</span>
|
||||||
<div class="text-ar">إيصال استلام</div>
|
|
||||||
<div class="mt-2">
|
|
||||||
<strong>#<?php echo str_pad($sale_id, 6, '0', STR_PAD_LEFT); ?></strong>
|
|
||||||
</div>
|
|
||||||
<div class="small text-muted">
|
|
||||||
<?php echo date('d/m/Y h:i A', strtotime($sale['created_at'])); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Patient Info (if applicable) -->
|
|
||||||
<?php if ($sale['patient_id']): ?>
|
<?php if ($sale['patient_id']): ?>
|
||||||
<div class="row mb-4 border-bottom pb-3">
|
<div class="divider"></div>
|
||||||
<div class="col-12">
|
<div class="receipt-details">
|
||||||
<span class="fw-bold">Patient / المريض:</span>
|
<span>Patient / المريض:</span>
|
||||||
<?php echo htmlspecialchars($sale['patient_name']); ?>
|
|
||||||
<?php if($sale['patient_phone']) echo ' (' . htmlspecialchars($sale['patient_phone']) . ')'; ?>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div style="font-weight: bold; font-size: 11px;">
|
||||||
|
<?php echo htmlspecialchars($sale['patient_name']); ?>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<!-- Items Table -->
|
<div class="divider"></div>
|
||||||
<table class="table table-bordered mb-4">
|
|
||||||
|
<!-- Items -->
|
||||||
|
<table class="items-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="text-center" width="50">#</th>
|
<th style="width: 45%;">Item / الصنف</th>
|
||||||
<th>
|
<th style="width: 15%; text-align: center;">Qty<br>العدد</th>
|
||||||
<div class="d-flex justify-content-between">
|
<th style="width: 20%; text-align: right;">Price<br>السعر</th>
|
||||||
<span>Item Description</span>
|
<th style="width: 20%; text-align: right;">Total<br>الإجمالي</th>
|
||||||
<span class="text-ar">الصنف</span>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<th class="text-center" width="80">
|
|
||||||
<div class="d-flex justify-content-between px-1">
|
|
||||||
<span>Qty</span>
|
|
||||||
<span class="text-ar">العدد</span>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<th class="text-end" width="120">
|
|
||||||
<div class="d-flex justify-content-between px-1">
|
|
||||||
<span>Price</span>
|
|
||||||
<span class="text-ar">السعر</span>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<th class="text-end" width="120">
|
|
||||||
<div class="d-flex justify-content-between px-1">
|
|
||||||
<span>Total</span>
|
|
||||||
<span class="text-ar">الإجمالي</span>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php $i = 1; foreach ($items as $item): ?>
|
<?php foreach ($items as $item): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center"><?php echo $i++; ?></td>
|
|
||||||
<td>
|
<td>
|
||||||
<div class="fw-bold"><?php echo htmlspecialchars($item['drug_name_en']); ?></div>
|
<?php echo htmlspecialchars($item['drug_name_en']); ?>
|
||||||
<?php if($item['drug_name_ar']): ?>
|
<?php if(!empty($item['drug_name_ar'])): ?>
|
||||||
<div class="text-ar small text-muted"><?php echo htmlspecialchars($item['drug_name_ar']); ?></div>
|
<br><span class="ar-text"><?php echo htmlspecialchars($item['drug_name_ar']); ?></span>
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($item['sku']): ?>
|
|
||||||
<div class="small text-muted" style="font-size: 0.75rem;">SKU: <?php echo htmlspecialchars($item['sku']); ?></div>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center"><?php echo $item['quantity']; ?></td>
|
<td style="text-align: center;"><?php echo $item['quantity']; ?></td>
|
||||||
<td class="text-end"><?php echo format_currency($item['unit_price']); ?></td>
|
<td style="text-align: right;"><?php echo number_format($item['unit_price'], 2); ?></td>
|
||||||
<td class="text-end"><?php echo format_currency($item['total_price']); ?></td>
|
<td style="text-align: right;"><?php echo number_format($item['total_price'], 2); ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td colspan="4" class="text-end fw-bold">
|
|
||||||
TOTAL / الإجمالي
|
|
||||||
</td>
|
|
||||||
<td class="text-end fw-bold fs-5">
|
|
||||||
<?php echo format_currency($sale['total_amount']); ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- Payment Info -->
|
<!-- Totals -->
|
||||||
<div class="row">
|
<div class="total-section">
|
||||||
<div class="col-6">
|
<div style="display: flex; justify-content: space-between; font-weight: bold; font-size: 13px;">
|
||||||
<div class="small">
|
<div>TOTAL <span style="font-size: 11px; font-weight: normal;">الإجمالي</span></div>
|
||||||
<strong>Payment Method / طريقة الدفع:</strong><br>
|
<div><?php echo format_currency($sale['total_amount']); ?></div>
|
||||||
<span class="text-uppercase"><?php echo htmlspecialchars($sale['payment_method']); ?></span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div style="display: flex; justify-content: space-between; margin-top: 5px; font-size: 10px;">
|
||||||
|
<div>Paid Via <span style="font-size: 9px;">طريقة الدفع</span></div>
|
||||||
|
<div style="text-transform: uppercase;">
|
||||||
|
<?php echo htmlspecialchars($sale['payment_method']); ?>
|
||||||
|
<?php
|
||||||
|
$methods_ar = ['cash' => 'نقد', 'card' => 'بطاقة', 'insurance' => 'تأمين'];
|
||||||
|
if(isset($methods_ar[strtolower($sale['payment_method'])])) {
|
||||||
|
echo ' / ' . $methods_ar[strtolower($sale['payment_method'])];
|
||||||
|
}
|
||||||
|
?>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 text-end">
|
|
||||||
<!--
|
|
||||||
<br>
|
|
||||||
<div class="border-top border-dark d-inline-block pt-1" style="width: 200px; text-align: center;">
|
|
||||||
<span class="small">Signature / التوقيع</span>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<div class="receipt-footer text-center small text-muted">
|
<div class="footer">
|
||||||
<p class="mb-1">Thank you for your visit! / !شكراً لزيارتكم</p>
|
Thank You! / شكراً لكم<br>
|
||||||
<p>Get Well Soon / تمنياتنا بالشفاء العاجل</p>
|
Get Well Soon / بالشفاء العاجل
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Cut space -->
|
||||||
|
<div style="height: 10mm;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user