updating labels price
This commit is contained in:
parent
e3240af16d
commit
552d635c19
BIN
assets/pasted-20260219-104108-ada41fa8.png
Normal file
BIN
assets/pasted-20260219-104108-ada41fa8.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
16
db/migrations/20260219_add_vat_to_pos_items.sql
Normal file
16
db/migrations/20260219_add_vat_to_pos_items.sql
Normal file
@ -0,0 +1,16 @@
|
||||
-- Add VAT columns to pos_items
|
||||
ALTER TABLE pos_items ADD COLUMN vat_rate DECIMAL(5,2) DEFAULT 0.00 AFTER unit_price;
|
||||
ALTER TABLE pos_items ADD COLUMN vat_amount DECIMAL(15,3) DEFAULT 0.000 AFTER vat_rate;
|
||||
|
||||
-- Update existing pos_items if possible (optional, but good for consistency)
|
||||
-- This might not be accurate if items changed their vat rate after transaction,
|
||||
-- but it's better than nothing.
|
||||
UPDATE pos_items pi
|
||||
JOIN stock_items si ON pi.product_id = si.id
|
||||
SET pi.vat_rate = si.vat_rate;
|
||||
|
||||
UPDATE pos_items SET vat_amount = subtotal * (vat_rate / (100 + vat_rate));
|
||||
|
||||
-- Update pos_transactions to ensure tax_amount is populated for old transactions
|
||||
UPDATE pos_transactions pt
|
||||
SET tax_amount = (SELECT SUM(vat_amount) FROM pos_items WHERE transaction_id = pt.id);
|
||||
1
debug_sessions.log
Normal file
1
debug_sessions.log
Normal file
@ -0,0 +1 @@
|
||||
Where: 1=1 Params: []
|
||||
@ -90,7 +90,7 @@ $translations = [
|
||||
'walk_in_customer' => 'Walk-in Customer',
|
||||
'currency' => 'ر.ع / OMR',
|
||||
'cash' => 'Cash',
|
||||
'card' => 'Card',
|
||||
'card' => 'Credit Card',
|
||||
'credit' => 'Credit',
|
||||
],
|
||||
'ar' => [
|
||||
@ -183,7 +183,7 @@ $translations = [
|
||||
'walk_in_customer' => 'عميل نقدي',
|
||||
'currency' => 'ر.ع / OMR',
|
||||
'cash' => 'نقد',
|
||||
'card' => 'بطاقة',
|
||||
'card' => 'بطاقة ائتمان',
|
||||
'credit' => 'آجل',
|
||||
]
|
||||
];
|
||||
|
||||
231
index.php
231
index.php
@ -258,6 +258,7 @@ if (isset($_GET['action']) || isset($_POST['action'])) {
|
||||
$payments = json_decode($_POST['payments'] ?? '[]', true);
|
||||
$items = json_decode($_POST['items'] ?? '[]', true);
|
||||
$total_amount = (float)($_POST['total_amount'] ?? 0);
|
||||
$tax_amount = (float)($_POST['tax_amount'] ?? 0);
|
||||
$discount_code_id = !empty($_POST['discount_code_id']) ? (int)$_POST['discount_code_id'] : null;
|
||||
$discount_amount = (float)($_POST['discount_amount'] ?? 0);
|
||||
$loyalty_redeemed = (float)($_POST['loyalty_redeemed'] ?? 0);
|
||||
@ -266,18 +267,30 @@ if (isset($_GET['action']) || isset($_POST['action'])) {
|
||||
$transaction_no = 'POS-' . time() . rand(10, 99);
|
||||
$session_id = $_SESSION['register_session_id'] ?? null;
|
||||
|
||||
if (!$session_id) {
|
||||
// Fallback: try to find an open session for this user
|
||||
$check_session = $db->prepare("SELECT id FROM register_sessions WHERE user_id = ? AND status = 'open' LIMIT 1");
|
||||
$check_session->execute([$_SESSION['user_id']]);
|
||||
$session_id = $check_session->fetchColumn() ?: null;
|
||||
if ($session_id) {
|
||||
$_SESSION['register_session_id'] = $session_id;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert Transaction
|
||||
$stmt = $db->prepare("INSERT INTO pos_transactions (transaction_no, customer_id, total_amount, discount_code_id, discount_amount, loyalty_points_redeemed, net_amount, register_session_id, created_by, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'completed')");
|
||||
$stmt->execute([$transaction_no, $customer_id, $total_amount, $discount_code_id, $discount_amount, $loyalty_redeemed, $net_amount, $session_id, $_SESSION['user_id']]);
|
||||
$stmt = $db->prepare("INSERT INTO pos_transactions (transaction_no, customer_id, total_amount, tax_amount, discount_code_id, discount_amount, loyalty_points_redeemed, net_amount, register_session_id, created_by, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'completed')");
|
||||
$stmt->execute([$transaction_no, $customer_id, $total_amount, $tax_amount, $discount_code_id, $discount_amount, $loyalty_redeemed, $net_amount, $session_id, $_SESSION['user_id']]);
|
||||
$transaction_id = (int)$db->lastInsertId();
|
||||
|
||||
// Insert Items & Update Stock
|
||||
$stmtItem = $db->prepare("INSERT INTO pos_items (transaction_id, product_id, quantity, unit_price, subtotal) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmtItem = $db->prepare("INSERT INTO pos_items (transaction_id, product_id, quantity, unit_price, vat_rate, vat_amount, subtotal) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmtStock = $db->prepare("UPDATE stock_items SET stock_quantity = stock_quantity - ? WHERE id = ?");
|
||||
|
||||
foreach ($items as $item) {
|
||||
$sub = (float)$item['price'] * (float)$item['qty'];
|
||||
$stmtItem->execute([$transaction_id, $item['id'], $item['qty'], $item['price'], $sub]);
|
||||
$vr = (float)($item['vat_rate'] ?? 0);
|
||||
$va = (float)($item['vat_amount'] ?? 0);
|
||||
$stmtItem->execute([$transaction_id, $item['id'], $item['qty'], $item['price'], $vr, $va, $sub]);
|
||||
$stmtStock->execute([$item['qty'], $item['id']]);
|
||||
}
|
||||
|
||||
@ -1911,10 +1924,30 @@ switch ($page) {
|
||||
case 'register_sessions':
|
||||
$where = ["1=1"];
|
||||
$params = [];
|
||||
|
||||
// Filter by user if provided and user has permission
|
||||
if (isset($_GET['user_id']) && !empty($_GET['user_id'])) {
|
||||
if (can('users_view')) {
|
||||
$where[] = "s.user_id = ?";
|
||||
$params[] = $_GET['user_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!can('users_view')) {
|
||||
$where[] = "s.user_id = ?";
|
||||
$params[] = $_SESSION['user_id'];
|
||||
}
|
||||
|
||||
// Filter by date range
|
||||
if (isset($_GET['date_from']) && !empty($_GET['date_from'])) {
|
||||
$where[] = "s.opened_at >= ?";
|
||||
$params[] = $_GET['date_from'] . ' 00:00:00';
|
||||
}
|
||||
if (isset($_GET['date_to']) && !empty($_GET['date_to'])) {
|
||||
$where[] = "s.opened_at <= ?";
|
||||
$params[] = $_GET['date_to'] . ' 23:59:59';
|
||||
}
|
||||
|
||||
$whereSql = implode(" AND ", $where);
|
||||
$stmt = db()->prepare("SELECT s.*, r.name as register_name, u.username
|
||||
FROM register_sessions s
|
||||
@ -1925,6 +1958,7 @@ switch ($page) {
|
||||
$stmt->execute($params);
|
||||
$data['sessions'] = $stmt->fetchAll();
|
||||
$data['cash_registers'] = db()->query("SELECT * FROM cash_registers WHERE status = 'active'")->fetchAll();
|
||||
$data['users'] = db()->query("SELECT id, username FROM users ORDER BY username ASC")->fetchAll();
|
||||
break;
|
||||
default:
|
||||
$data['customers'] = db()->query("SELECT * FROM customers WHERE type = 'customer' ORDER BY id DESC LIMIT 5")->fetchAll();
|
||||
@ -2802,7 +2836,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<tbody>
|
||||
<?php foreach ($data['items'] as $item): ?>
|
||||
<tr>
|
||||
<td><input type="checkbox" class="form-check-input item-checkbox" data-id="<?= $item['id'] ?>" data-sku="<?= htmlspecialchars($item['sku']) ?>" data-name="<?= htmlspecialchars($item['name_en']) ?>" data-price="<?= number_format((float)$item['sale_price'], 3) ?>"></td>
|
||||
<td><input type="checkbox" class="form-check-input item-checkbox" data-id="<?= $item['id'] ?>" data-sku="<?= htmlspecialchars($item['sku']) ?>" data-name="<?= htmlspecialchars($item['name_en'] . ' - ' . $item['name_ar']) ?>" data-price="<?= number_format((float)$item['sale_price'] * (1 + (float)($item['vat_rate'] ?? 5) / 100), 3) ?>"></td>
|
||||
<td>
|
||||
<?php if ($item['image_path']): ?>
|
||||
<img src="<?= htmlspecialchars($item['image_path']) ?>" alt="item" style="width: 40px; height: 40px; object-fit: cover;" class="rounded">
|
||||
@ -2839,7 +2873,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button class="btn btn-outline-info" title="View" data-bs-toggle="modal" data-bs-target="#viewItemModal<?= $item['id'] ?>"><i class="bi bi-eye"></i></button>
|
||||
<button class="btn btn-outline-primary" title="Edit" data-bs-toggle="modal" data-bs-target="#editItemModal<?= $item['id'] ?>"><i class="bi bi-pencil"></i></button>
|
||||
<button class="btn btn-outline-dark" title="Barcode" onclick="printItemBarcode('<?= htmlspecialchars($item['sku']) ?>', '<?= htmlspecialchars($item['name_en']) ?>', '<?= number_format((float)$item['sale_price'], 3) ?>')"><i class="bi bi-upc"></i></button>
|
||||
<button class="btn btn-outline-dark" title="Barcode" onclick="printItemBarcode('<?= htmlspecialchars($item['sku']) ?>', '<?= htmlspecialchars($item['name_en'] . ' - ' . $item['name_ar']) ?>', '<?= number_format((float)$item['sale_price'] * (1 + (float)($item['vat_rate'] ?? 5) / 100), 3) ?>')"><i class="bi bi-upc"></i></button>
|
||||
<form method="POST" class="d-inline" onsubmit="return confirm('Are you sure?')">
|
||||
<input type="hidden" name="id" value="<?= $item['id'] ?>">
|
||||
<button type="submit" name="delete_item" class="btn btn-outline-danger" title="Delete"><i class="bi bi-trash"></i></button>
|
||||
@ -2874,7 +2908,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-outline-dark" onclick="printItemBarcode('<?= htmlspecialchars($item['sku']) ?>', '<?= htmlspecialchars($item['name_en']) ?>', '<?= number_format((float)$item['sale_price'], 3) ?>')"><i class="bi bi-printer"></i> Print Barcode</button>
|
||||
<button class="btn btn-outline-dark" onclick="printItemBarcode('<?= htmlspecialchars($item['sku']) ?>', '<?= htmlspecialchars($item['name_en'] . ' - ' . $item['name_ar']) ?>', '<?= number_format((float)$item['sale_price'] * (1 + (float)($item['vat_rate'] ?? 5) / 100), 3) ?>')"><i class="bi bi-printer"></i> Print Barcode</button>
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -3376,7 +3410,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
const totalVat = this.items.reduce((sum, item) => {
|
||||
const price = parseFloat(item.price) || 0;
|
||||
const qty = parseFloat(item.qty) || 0;
|
||||
const vatRate = item.vatRate || 5;
|
||||
const vatRate = (item.vatRate !== undefined && item.vatRate !== null) ? item.vatRate : 5;
|
||||
return sum + (price * qty * (vatRate / (100 + vatRate)));
|
||||
}, 0);
|
||||
let discountAmount = 0;
|
||||
@ -3395,7 +3429,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
items: this.items.map(i => {
|
||||
const price = parseFloat(i.price) || 0;
|
||||
const qty = parseFloat(i.qty) || 0;
|
||||
const vatRate = i.vatRate || 5;
|
||||
const vatRate = (i.vatRate !== undefined && i.vatRate !== null) ? i.vatRate : 5;
|
||||
const vatAmount = price * qty * (vatRate / (100 + vatRate));
|
||||
return {
|
||||
name: (document.documentElement.lang === 'ar' ? (i.nameAr || i.nameEn) : (i.nameEn || i.nameAr)) || 'Unknown Item',
|
||||
@ -3680,7 +3714,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
const qty = parseFloat(item.qty) || 0;
|
||||
const itemTotal = price * qty;
|
||||
subtotal += itemTotal;
|
||||
const vatRate = item.vatRate || 5;
|
||||
const vatRate = (item.vatRate !== undefined && item.vatRate !== null) ? item.vatRate : 5;
|
||||
const itemVat = itemTotal * (vatRate / (100 + vatRate));
|
||||
totalVat += itemVat;
|
||||
const displayName = (lang === 'ar' ? (item.nameAr || item.nameEn) : (item.nameEn || item.nameAr)) || 'Unknown Item';
|
||||
@ -3850,10 +3884,16 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
},
|
||||
renderPayments() {
|
||||
const container = document.getElementById('paymentList');
|
||||
const methodLabels = {
|
||||
'cash': 'Cash',
|
||||
'card': 'Credit Card',
|
||||
'credit': 'Credit',
|
||||
'transfer': 'Bank Transfer'
|
||||
};
|
||||
container.innerHTML = this.payments.map((p, i) => `
|
||||
<div class="payment-line">
|
||||
<div>
|
||||
<span class="method">${p.method}</span>
|
||||
<span class="method">${methodLabels[p.method] || p.method}</span>
|
||||
<span class="ms-2 badge bg-secondary small"><?= __('currency') ?> ${p.amount.toFixed(3)}</span>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-outline-danger border-0" onclick="cart.removePaymentLine(${i})">
|
||||
@ -3937,6 +3977,10 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
btn.innerText = 'PROCESSING...';
|
||||
|
||||
const subtotal = this.items.reduce((sum, item) => sum + (parseFloat(item.price) * item.qty), 0);
|
||||
const totalVat = this.items.reduce((sum, item) => {
|
||||
const vatRate = (item.vatRate !== undefined && item.vatRate !== null) ? item.vatRate : 5;
|
||||
return sum + ((parseFloat(item.price) * item.qty) * (vatRate / (100 + vatRate)));
|
||||
}, 0);
|
||||
let discountAmount = 0;
|
||||
if (this.discount) {
|
||||
discountAmount = this.discount.type === 'percentage' ? subtotal * (parseFloat(this.discount.value) / 100) : parseFloat(this.discount.value);
|
||||
@ -3949,10 +3993,15 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
formData.append('customer_id', customerId);
|
||||
formData.append('payments', JSON.stringify(this.payments));
|
||||
formData.append('total_amount', subtotal);
|
||||
formData.append('tax_amount', totalVat);
|
||||
formData.append('discount_code_id', this.discount ? this.discount.id : '');
|
||||
formData.append('discount_amount', discountAmount);
|
||||
formData.append('loyalty_redeemed', loyaltyRedeemed);
|
||||
formData.append('items', JSON.stringify(this.items.map(i => ({id: i.id, qty: i.qty, price: i.price}))));
|
||||
formData.append('items', JSON.stringify(this.items.map(i => {
|
||||
const vr = (i.vatRate !== undefined && i.vatRate !== null) ? i.vatRate : 5;
|
||||
const va = (parseFloat(i.price) * i.qty) * (vr / (100 + vr));
|
||||
return {id: i.id, qty: i.qty, price: i.price, vat_rate: vr, vat_amount: va};
|
||||
})));
|
||||
|
||||
try {
|
||||
const resp = await fetch('index.php', { method: 'POST', body: formData });
|
||||
@ -3987,8 +4036,8 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
const customerName = (customerSelect && customerSelect.selectedIndex >= 0 && customerSelect.value !== '') ? customerSelect.options[customerSelect.selectedIndex].text : '<?= $translations['ar']['walk_in_customer'] ?> / <?= $translations['en']['walk_in_customer'] ?>';
|
||||
const paymentsHtml = this.payments.map(p => {
|
||||
let m = p.method.toLowerCase();
|
||||
let methodAr = m === 'cash' ? 'نقد' : (m === 'card' ? 'بطاقة' : (m === 'credit' ? 'آجل' : m));
|
||||
let methodEn = m.charAt(0).toUpperCase() + m.slice(1);
|
||||
let methodAr = m === 'cash' ? 'نقد' : (m === 'card' ? 'بطاقة ائتمان' : (m === 'credit' ? 'آجل' : (m === 'transfer' ? 'تحويل بنكي' : m)));
|
||||
let methodEn = m === 'cash' ? 'Cash' : (m === 'card' ? 'Credit Card' : (m === 'credit' ? 'Credit' : (m === 'transfer' ? 'Bank Transfer' : m.charAt(0).toUpperCase() + m.slice(1))));
|
||||
return `
|
||||
<div class="d-flex justify-content-between small">
|
||||
<span class="text-uppercase">${methodAr} / ${methodEn}</span>
|
||||
@ -4000,7 +4049,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
|
||||
let itemsHtml = this.items.map(item => {
|
||||
const itemTotal = item.price * item.qty;
|
||||
const vatRate = item.vatRate || 5; // Default to 5 if not set
|
||||
const vatRate = (item.vatRate !== undefined && item.vatRate !== null) ? item.vatRate : 5; // Default to 5 if not set
|
||||
const vatAmount = itemTotal * (vatRate / (100 + vatRate));
|
||||
const exclVat = itemTotal - vatAmount;
|
||||
return `
|
||||
@ -4018,7 +4067,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
|
||||
const subtotal = this.items.reduce((sum, item) => sum + (item.price * item.qty), 0);
|
||||
const totalVat = this.items.reduce((sum, item) => {
|
||||
const vatRate = item.vatRate || 5;
|
||||
const vatRate = (item.vatRate !== undefined && item.vatRate !== null) ? item.vatRate : 5;
|
||||
return sum + ((item.price * item.qty) * (vatRate / (100 + vatRate)));
|
||||
}, 0);
|
||||
const total = subtotal - discountAmount - loyaltyRedeemed;
|
||||
@ -6995,7 +7044,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<div class="card p-4 rounded-4 shadow-sm border-0 mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h5 class="m-0 fw-bold text-primary" data-en="Register Sessions" data-ar="جلسات الكاشير">Register Sessions</h5>
|
||||
<h5 class="m-0 fw-bold text-primary"><span data-en="Register Sessions" data-ar="جلسات الكاشير">Register Sessions</span> (<?= count($data['sessions']) ?>)</h5>
|
||||
<p class="text-muted small mb-0">Manage daily opening and closing of cash registers.</p>
|
||||
</div>
|
||||
<div>
|
||||
@ -7030,6 +7079,50 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Filter Form -->
|
||||
<div class="card border-0 bg-light rounded-4 mb-4">
|
||||
<div class="card-body">
|
||||
<form action="index.php" method="GET" class="row g-3 align-items-end">
|
||||
<input type="hidden" name="page" value="register_sessions">
|
||||
|
||||
<?php if (can('users_view')): ?>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small fw-bold" data-en="Cashier" data-ar="الكاشير">Cashier</label>
|
||||
<select name="user_id" class="form-select rounded-3">
|
||||
<option value="" data-en="All Cashiers" data-ar="كل الكاشير">All Cashiers</option>
|
||||
<?php foreach ($data['users'] as $u): ?>
|
||||
<option value="<?= $u['id'] ?>" <?= (isset($_GET['user_id']) && $_GET['user_id'] == $u['id']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($u['username']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small fw-bold" data-en="Date From" data-ar="من تاريخ">Date From</label>
|
||||
<input type="date" name="date_from" class="form-control rounded-3" value="<?= htmlspecialchars($_GET['date_from'] ?? '') ?>">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small fw-bold" data-en="Date To" data-ar="إلى تاريخ">Date To</label>
|
||||
<input type="date" name="date_to" class="form-control rounded-3" value="<?= htmlspecialchars($_GET['date_to'] ?? '') ?>">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary rounded-3 w-100">
|
||||
<i class="bi bi-filter me-1"></i> <span data-en="Filter" data-ar="تصفية">Filter</span>
|
||||
</button>
|
||||
<a href="index.php?page=register_sessions" class="btn btn-outline-secondary rounded-3 w-100">
|
||||
<i class="bi bi-x-circle me-1"></i> <span data-en="Clear" data-ar="مسح">Clear</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
@ -7040,14 +7133,11 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<th data-en="Opened At" data-ar="وقت الفتح">Opened At</th>
|
||||
<th data-en="Closed At" data-ar="وقت الإغلاق">Closed At</th>
|
||||
<th data-en="Opening Bal." data-ar="رصيد الافتتاح">Opening Bal.</th>
|
||||
<th data-en="Cash Sales" data-ar="مبيعات نقدية">Cash Sales</th>
|
||||
<th data-en="Card Sales" data-ar="مبيعات الشبكة">Card Sales</th>
|
||||
<th data-en="Transfer" data-ar="تحويل">Transfer</th>
|
||||
<th data-en="Cash Sale" data-ar="مبيعات نقدية">Cash Sale</th>
|
||||
<th data-en="Credit Card" data-ar="بطاقة ائتمان">Credit Card</th>
|
||||
<th data-en="Credit" data-ar="آجل">Credit</th>
|
||||
<th data-en="Total Sales" data-ar="إجمالي المبيعات">Total Sales</th>
|
||||
<th data-en="Expected Cash" data-ar="النقد المتوقع">Expected Cash</th>
|
||||
<th data-en="Actual Cash" data-ar="النقد الفعلي">Actual Cash</th>
|
||||
<th data-en="Shortage" data-ar="النقص/الزيادة">Shortage</th>
|
||||
<th data-en="Total Sale" data-ar="إجمالي المبيعات">Total Sale</th>
|
||||
<th data-en="Balance" data-ar="الرصيد">Balance</th>
|
||||
<th data-en="Status" data-ar="الحالة">Status</th>
|
||||
<th class="text-end" data-en="Report" data-ar="تقرير">Report</th>
|
||||
</tr>
|
||||
@ -7082,11 +7172,8 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
?>
|
||||
<td>OMR <?= number_format($c_total, 3) ?></td>
|
||||
<td>OMR <?= number_format($cd_total, 3) ?></td>
|
||||
<td>OMR <?= number_format($tr_total, 3) ?></td>
|
||||
<td>OMR <?= number_format($cr_total, 3) ?></td>
|
||||
<td class="fw-bold">OMR <?= number_format($t_sales, 3) ?></td>
|
||||
<td>OMR <?= number_format($row_expected_cash, 3) ?></td>
|
||||
<td>OMR <?= number_format((float)($s['cash_in_hand'] ?? 0), 3) ?></td>
|
||||
<td>
|
||||
<?php if ($s['status'] === 'closed'):
|
||||
$diff = (float)($s['cash_in_hand'] ?? 0) - $row_expected_cash;
|
||||
@ -7100,11 +7187,21 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<?= ucfirst($s['status']) ?>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="text-end">
|
||||
<button class="btn btn-sm btn-light rounded-circle" data-bs-toggle="modal" data-bs-target="#sessionReportModal<?= $s['id'] ?>"><i class="bi bi-file-earmark-text text-primary"></i></button>
|
||||
|
||||
<!-- Session Report Modal -->
|
||||
<div class="modal fade" id="sessionReportModal<?= $s['id'] ?>" tabindex="-1">
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals outside loop for better structure -->
|
||||
<?php foreach ($data['sessions'] as $s): ?>
|
||||
<!-- Session Report Modal -->
|
||||
<div class="modal fade" id="sessionReportModal<?= $s['id'] ?>" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header">
|
||||
@ -7162,12 +7259,26 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<span>Opening Balance:</span>
|
||||
<span class="fw-bold">OMR <?= number_format((float)$s['opening_balance'], 3) ?></span>
|
||||
</div>
|
||||
<?php
|
||||
// Additional totals
|
||||
$extra_stmt = db()->prepare("SELECT SUM(tax_amount) as total_tax, SUM(discount_amount) as total_discount, SUM(net_amount) as total_net FROM pos_transactions WHERE register_session_id = ? AND status = 'completed'");
|
||||
$extra_stmt->execute([$s['id']]);
|
||||
$extra = $extra_stmt->fetch();
|
||||
?>
|
||||
<div class="d-flex justify-content-between mb-2 small text-muted">
|
||||
<span>Tax Amount:</span>
|
||||
<span>OMR <?= number_format((float)($extra['total_tax'] ?? 0), 3) ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2 small text-muted">
|
||||
<span>Discount:</span>
|
||||
<span>OMR <?= number_format((float)($extra['total_discount'] ?? 0), 3) ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span>Cash Sales:</span>
|
||||
<span>Cash Sale:</span>
|
||||
<span class="fw-bold">OMR <?= number_format($cash_sales, 3) ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span>Credit Card Sales:</span>
|
||||
<span>Credit Card:</span>
|
||||
<span class="fw-bold">OMR <?= number_format($card_sales, 3) ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
@ -7179,7 +7290,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<span class="fw-bold">OMR <?= number_format($bank_transfer_sales, 3) ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2 border-top pt-2 mt-2 h6 text-primary">
|
||||
<span>Total Sales:</span>
|
||||
<span>Total Sale:</span>
|
||||
<span class="fw-bold">OMR <?= number_format($total_sales, 3) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
@ -7193,7 +7304,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<span>OMR <?= number_format((float)$s['opening_balance'], 3) ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span>(+) Cash Sales:</span>
|
||||
<span>(+) Cash Sale:</span>
|
||||
<span>OMR <?= number_format($cash_sales, 3) ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-2 border-top pt-2 mt-2 h6">
|
||||
@ -7210,10 +7321,11 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
$shortage_class = $shortage < 0 ? 'text-danger' : ($shortage > 0 ? 'text-info' : 'text-success');
|
||||
?>
|
||||
<div class="d-flex justify-content-between mb-0 h5 mt-2 <?= $shortage_class ?>">
|
||||
<span>Shortage / Overage:</span>
|
||||
<span>Balance:</span>
|
||||
<span class="fw-bold">OMR <?= number_format($shortage, 3) ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -7225,9 +7337,10 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>Order #</th>
|
||||
<th>Customer</th>
|
||||
<th>Method</th>
|
||||
<th>Order #</th>
|
||||
<th>Customer</th>
|
||||
<th>Items</th>
|
||||
<th>Method</th>
|
||||
<th class="text-end">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -7240,9 +7353,19 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
?>
|
||||
<tr>
|
||||
<td><?= date('H:i', strtotime($tx['created_at'])) ?></td>
|
||||
<td><?= htmlspecialchars($tx['transaction_no']) ?></td>
|
||||
<td><?= htmlspecialchars($tx['customer_name'] ?: 'Walk-in') ?></td>
|
||||
<td class="text-capitalize small"><?= htmlspecialchars($tx['methods'] ?: '---') ?></td>
|
||||
<td><?= htmlspecialchars($tx['transaction_no']) ?></td>
|
||||
<td><?= htmlspecialchars($tx['customer_name'] ?: 'Walk-in') ?></td>
|
||||
<td>
|
||||
<?php
|
||||
$items_stmt = db()->prepare("SELECT i.name_en, ti.quantity FROM pos_items ti JOIN stock_items i ON ti.item_id = i.id WHERE ti.transaction_id = ?");
|
||||
$items_stmt->execute([$tx['id']]);
|
||||
$items = $items_stmt->fetchAll();
|
||||
foreach ($items as $item) {
|
||||
echo "<small class='d-block'>" . htmlspecialchars($item['name_en']) . " x " . (float)$item['quantity'] . "</small>";
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="text-capitalize small"><?= htmlspecialchars($tx['methods'] ?: '---') ?></td>
|
||||
<td class="text-end"><?= number_format($tx['net_amount'], 3) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; if(empty($txs)): ?>
|
||||
@ -7272,13 +7395,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<!-- Open Register Modal -->
|
||||
<div class="modal fade" id="openRegisterModal" tabindex="-1">
|
||||
@ -9273,7 +9390,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
<label class="form-label fw-bold" data-en="Payment Type" data-ar="طريقة الدفع">Payment Type</label>
|
||||
<select name="payment_type" class="form-select">
|
||||
<option value="cash">Cash</option>
|
||||
<option value="card">Card</option>
|
||||
<option value="card">Credit Card</option>
|
||||
<option value="bank_transfer">Bank Transfer</option>
|
||||
<option value="credit">Credit</option>
|
||||
</select>
|
||||
@ -9373,7 +9490,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
<label class="form-label fw-bold" data-en="Payment Type" data-ar="طريقة الدفع">Payment Type</label>
|
||||
<select name="payment_type" id="edit_payment_type" class="form-select">
|
||||
<option value="cash">Cash</option>
|
||||
<option value="card">Card</option>
|
||||
<option value="card">Credit Card</option>
|
||||
<option value="bank_transfer">Bank Transfer</option>
|
||||
<option value="credit">Credit</option>
|
||||
</select>
|
||||
@ -9900,7 +10017,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
<label class="form-label fw-bold" data-en="Payment Method" data-ar="طريقة الدفع">Payment Method</label>
|
||||
<select name="payment_method" class="form-select select2" required>
|
||||
<option value="Cash">Cash</option>
|
||||
<option value="Card">Card</option>
|
||||
<option value="Card">Credit Card</option>
|
||||
<option value="Bank Transfer">Bank Transfer</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -10044,7 +10161,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
</div>
|
||||
<div class="payment-method-btn" data-method="card" onclick="cart.selectMethod('card', this)">
|
||||
<i class="bi bi-credit-card"></i>
|
||||
<span class="small fw-bold">Card</span>
|
||||
<span class="small fw-bold">Credit Card</span>
|
||||
</div>
|
||||
<div class="payment-method-btn" data-method="credit" onclick="cart.selectMethod('credit', this)">
|
||||
<i class="bi bi-person-badge"></i>
|
||||
@ -10052,7 +10169,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
</div>
|
||||
<div class="payment-method-btn" data-method="transfer" onclick="cart.selectMethod('transfer', this)">
|
||||
<i class="bi bi-bank"></i>
|
||||
<span class="small fw-bold">Transfer</span>
|
||||
<span class="small fw-bold">Bank Transfer</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -10385,7 +10502,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const uniqueId = Math.random().toString(36).substr(2, 9);
|
||||
const svgId = `bc-${sku}-${uniqueId}`;
|
||||
label.innerHTML = `
|
||||
<div style="font-size: 10px; font-weight: bold; margin-bottom: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 100%;">${name}</div>
|
||||
<div style="font-size: 9px; font-weight: bold; margin-bottom: 2px; line-height: 1.1; overflow: hidden; text-overflow: ellipsis; width: 100%;">${name}</div>
|
||||
<svg id="${svgId}"></svg>
|
||||
<div style="font-size: 11px; font-weight: bold; margin-top: 2px;">OMR ${price}</div>
|
||||
`;
|
||||
@ -10493,7 +10610,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
padding: 1mm;
|
||||
}
|
||||
.label-container:last-child { page-break-after: avoid; }
|
||||
.label-name { font-size: 10px; font-weight: bold; margin-bottom: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
|
||||
.label-name { font-size: 9px; font-weight: bold; margin-bottom: 2px; line-height: 1.1; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
|
||||
.label-price { font-size: 12px; font-weight: bold; margin-top: 2px; }
|
||||
svg { max-width: 100%; height: auto; max-height: 70%; display: block; }
|
||||
</style>
|
||||
@ -10629,7 +10746,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const container = document.getElementById('posReceiptContent');
|
||||
const itemsHtml = inv.items.map(item => {
|
||||
const itemTotal = item.unit_price * item.quantity;
|
||||
const vatRate = parseFloat(item.vat_rate || 5);
|
||||
const vatRate = parseFloat(item.vat_rate !== undefined && item.vat_rate !== null ? item.vat_rate : 5);
|
||||
const vatAmount = itemTotal * (vatRate / (100 + vatRate));
|
||||
return `
|
||||
<tr>
|
||||
@ -10642,7 +10759,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
const totalVat = inv.items.reduce((sum, item) => {
|
||||
const itemTotal = item.unit_price * item.quantity;
|
||||
const vatRate = parseFloat(item.vat_rate || 5);
|
||||
const vatRate = parseFloat(item.vat_rate !== undefined && item.vat_rate !== null ? item.vat_rate : 5);
|
||||
return sum + (itemTotal * (vatRate / (100 + vatRate)));
|
||||
}, 0);
|
||||
const subtotal = inv.items.reduce((sum, item) => sum + (item.unit_price * item.quantity), 0);
|
||||
|
||||
@ -74,3 +74,18 @@
|
||||
2026-02-19 07:58:34 - POST: {"open_register":"1","register_id":"1","opening_balance":"11"}
|
||||
2026-02-19 07:58:46 - POST: {"action":"save_pos_transaction","customer_id":"","payments":"[{\"method\":\"cash\",\"amount\":0.845}]","total_amount":"0.8450000000000001","discount_code_id":"","discount_amount":"0","loyalty_redeemed":"0","items":"[{\"id\":1,\"qty\":1,\"price\":0.3825},{\"id\":3,\"qty\":1,\"price\":0.25},{\"id\":2,\"qty\":1,\"price\":0.2125}]"}
|
||||
2026-02-19 07:59:08 - POST: {"close_register":"1","session_id":"7","cash_in_hand":"13","notes":""}
|
||||
2026-02-19 08:20:34 - POST: {"open_register":"1","register_id":"1","opening_balance":"12"}
|
||||
2026-02-19 08:20:44 - POST: {"action":"save_pos_transaction","customer_id":"","payments":"[{\"method\":\"cash\",\"amount\":0.845}]","total_amount":"0.8450000000000001","discount_code_id":"","discount_amount":"0","loyalty_redeemed":"0","items":"[{\"id\":1,\"qty\":1,\"price\":0.3825},{\"id\":3,\"qty\":1,\"price\":0.25},{\"id\":2,\"qty\":1,\"price\":0.2125}]"}
|
||||
2026-02-19 08:20:57 - POST: {"close_register":"1","session_id":"8","cash_in_hand":"14","notes":""}
|
||||
2026-02-19 10:20:51 - POST: {"open_register":"1","register_id":"1","opening_balance":"22"}
|
||||
2026-02-19 10:21:00 - POST: {"action":"save_pos_transaction","customer_id":"","payments":"[{\"method\":\"cash\",\"amount\":0.845}]","total_amount":"0.8450000000000001","discount_code_id":"","discount_amount":"0","loyalty_redeemed":"0","items":"[{\"id\":1,\"qty\":1,\"price\":0.3825},{\"id\":3,\"qty\":1,\"price\":0.25},{\"id\":2,\"qty\":1,\"price\":0.2125}]"}
|
||||
2026-02-19 10:21:15 - POST: {"close_register":"1","session_id":"9","cash_in_hand":"10","notes":""}
|
||||
2026-02-19 10:50:12 - POST: {"open_register":"1","register_id":"2","opening_balance":"10"}
|
||||
2026-02-19 10:50:49 - POST: {"action":"save_pos_transaction","customer_id":"","payments":"[{\"method\":\"cash\",\"amount\":0.845}]","total_amount":"0.8450000000000001","discount_code_id":"","discount_amount":"0","loyalty_redeemed":"0","items":"[{\"id\":1,\"qty\":1,\"price\":0.3825},{\"id\":3,\"qty\":1,\"price\":0.25},{\"id\":2,\"qty\":1,\"price\":0.2125}]"}
|
||||
2026-02-19 10:51:45 - POST: {"id":"3","name_en":"Tissue","name_ar":"\u0645\u062d\u0627\u0631\u0645 \u0648\u0631\u0642\u064a\u0629","category_id":"2","unit_id":"2","supplier_id":"6","sale_price":"0.25","purchase_price":"0.2","stock_quantity":"-4","min_stock_level":"0","sku":"760115926272","vat_rate":"0","promotion_start":"","promotion_end":"","promotion_percent":"0","edit_item":""}
|
||||
2026-02-19 10:52:25 - POST: {"action":"save_pos_transaction","customer_id":"","payments":"[{\"method\":\"cash\",\"amount\":0.845}]","total_amount":"0.8450000000000001","discount_code_id":"","discount_amount":"0","loyalty_redeemed":"0","items":"[{\"id\":1,\"qty\":1,\"price\":0.3825},{\"id\":3,\"qty\":1,\"price\":0.25},{\"id\":2,\"qty\":1,\"price\":0.2125}]"}
|
||||
2026-02-19 10:54:21 - POST: {"open_register":"1","register_id":"1","opening_balance":"5"}
|
||||
2026-02-19 10:54:24 - POST: {"open_register":"1","register_id":"1","opening_balance":"5"}
|
||||
2026-02-19 10:54:25 - POST: {"open_register":"1","register_id":"2","opening_balance":"5"}
|
||||
2026-02-19 10:54:25 - POST: {"open_register":"1","register_id":"2","opening_balance":"5"}
|
||||
2026-02-19 10:54:26 - POST: {"open_register":"1","register_id":"2","opening_balance":"5"}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user