diff --git a/assets/css/custom.css b/assets/css/custom.css index 1cece62..118ef2f 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -504,8 +504,10 @@ body:not(.theme-default) .form-select:focus { /* Thermal Receipt Styles */ .thermal-receipt { width: 80mm; + max-width: 100%; margin: 0 auto; padding: 10px; + box-sizing: border-box; font-family: 'Courier New', Courier, monospace; font-size: 12px; line-height: 1.4; @@ -527,11 +529,14 @@ body:not(.theme-default) .form-select:focus { } .thermal-receipt table { width: 100%; + table-layout: fixed; + border-collapse: collapse; } .thermal-receipt table th { text-align: left; border-bottom: 1px dashed #000; font-size: 10px; + word-break: break-word; } .thermal-receipt.rtl table th { text-align: right; @@ -539,6 +544,7 @@ body:not(.theme-default) .form-select:focus { .thermal-receipt table td { padding: 5px 0; font-size: 11px; + word-break: break-word; } .thermal-receipt .total-row { font-weight: bold; @@ -547,9 +553,11 @@ body:not(.theme-default) .form-select:focus { @media print { .thermal-receipt-print { - width: 80mm !important; - margin: 0 !important; - padding: 5mm !important; + width: 76mm !important; + max-width: 76mm !important; + margin: 0 auto !important; + padding: 2mm !important; + box-sizing: border-box !important; } body.printing-receipt * { visibility: hidden; @@ -560,12 +568,21 @@ body:not(.theme-default) .form-select:focus { } body.printing-receipt #posPrintArea { visibility: visible !important; - display: block !important; + display: flex !important; + justify-content: center !important; + align-items: flex-start !important; + position: fixed !important; + inset: 0 !important; + width: 100% !important; + margin: 0 !important; + padding: 0 !important; + z-index: 9999 !important; + background: #fff !important; } body.printing-receipt .thermal-receipt-print { - position: absolute; - left: 0; - top: 0; + position: static !important; + left: auto !important; + top: auto !important; display: block !important; } } diff --git a/includes/quantity_helper.php b/includes/quantity_helper.php new file mode 100644 index 0000000..a4fc165 --- /dev/null +++ b/includes/quantity_helper.php @@ -0,0 +1,34 @@ +prepare("UPDATE stock_items SET stock_quantity = stock_quantity + ? WHERE id = ?"); - $stmt->execute([$qty, $item_id]); + $stmt->execute([$normalizedQty, $item_id]); } } diff --git a/index.php b/index.php index 47d3759..66cdf7a 100644 --- a/index.php +++ b/index.php @@ -467,6 +467,7 @@ if (!function_exists('register_wablas_helper_fallback')) { runtime_debug_boot_mark('boot:loading_core_dependencies'); require_once __DIR__ . '/db/config.php'; require_once __DIR__ . '/includes/SimpleXLSX.php'; +require_once __DIR__ . '/includes/quantity_helper.php'; require_once __DIR__ . '/includes/stock_helper.php'; $wablasHelperPath = __DIR__ . '/includes/wablas_helper.php'; if (is_file($wablasHelperPath)) { @@ -1860,7 +1861,7 @@ if (isset($_GET['action']) || isset($_POST['action'])) { // Render Card HTML ?> -
+
<?= htmlspecialchars($p['name_en']) ?> @@ -1883,7 +1884,7 @@ if (isset($_GET['action']) || isset($_POST['action'])) { OMR
- left + left
'This item cannot use price-based scale barcodes because its sale price is zero.']); exit; } - $qty = round(((float)$weightBarcode['value']) / (float)$p['sale_price'], 3); + $qty = normalize_quantity(((float)$weightBarcode['value']) / (float)$p['sale_price']); } else { - $qty = round((float)$weightBarcode['value'], 3); + $qty = normalize_quantity((float)$weightBarcode['value']); } if ($qty <= 0) { @@ -2003,6 +2004,12 @@ if (isset($_GET['action']) || isset($_POST['action'])) { $customer_id = !empty($_POST['customer_id']) ? (int)$_POST['customer_id'] : null; $payments = json_decode($_POST['payments'] ?? '[]', true); $items = json_decode($_POST['items'] ?? '[]', true); + if (!is_array($items)) { + $items = []; + } + foreach ($items as $itemIndex => $item) { + $items[$itemIndex]['qty'] = normalize_quantity($item['qty'] ?? 0); + } $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; @@ -2833,8 +2840,8 @@ function getPromotionalPrice($item) { } $sale_price = (float)($_POST['sale_price'] ?? 0); $purchase_price = (float)($_POST['purchase_price'] ?? 0); - $stock_quantity = (float)($_POST['stock_quantity'] ?? 0); - $min_stock_level = (float)($_POST['min_stock_level'] ?? 0); + $stock_quantity = normalize_quantity($_POST['stock_quantity'] ?? 0); + $min_stock_level = normalize_quantity($_POST['min_stock_level'] ?? 0); $vat_rate = (float)($_POST['vat_rate'] ?? 0); $expiry_date = !empty($_POST['expiry_date']) ? $_POST['expiry_date'] : null; $is_promotion = isset($_POST['is_promotion']) ? 1 : 0; @@ -2869,8 +2876,8 @@ function getPromotionalPrice($item) { } $sale_price = (float)($_POST['sale_price'] ?? 0); $purchase_price = (float)($_POST['purchase_price'] ?? 0); - $stock_quantity = (float)($_POST['stock_quantity'] ?? 0); - $min_stock_level = (float)($_POST['min_stock_level'] ?? 0); + $stock_quantity = normalize_quantity($_POST['stock_quantity'] ?? 0); + $min_stock_level = normalize_quantity($_POST['min_stock_level'] ?? 0); $vat_rate = (float)($_POST['vat_rate'] ?? 0); $expiry_date = !empty($_POST['expiry_date']) ? $_POST['expiry_date'] : null; $is_promotion = isset($_POST['is_promotion']) ? 1 : 0; @@ -3014,7 +3021,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3045,7 +3052,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3080,7 +3087,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3103,7 +3110,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3145,7 +3152,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3177,7 +3184,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3213,7 +3220,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3235,7 +3242,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3303,7 +3310,7 @@ function getPromotionalPrice($item) { $name_ar = trim((string)($row[2] ?? '')); $sale_price = (float)($row[3] ?? 0); $purchase_price = (float)($row[4] ?? 0); - $qty = (float)($row[5] ?? 0); + $qty = normalize_quantity($row[5] ?? 0); $vat_rate = (float)($row[6] ?? 0); $check = db()->prepare("SELECT id FROM stock_items WHERE sku = ? AND outlet_id = ?"); @@ -3580,7 +3587,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3612,7 +3619,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3651,7 +3658,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3673,7 +3680,7 @@ function getPromotionalPrice($item) { foreach ($items as $i => $item_id) { if (!$item_id) continue; - $qty = (float)$qtys[$i]; + $qty = normalize_quantity($qtys[$i] ?? 0); $price = (float)$prices[$i]; $subtotal = $qty * $price; @@ -3889,7 +3896,7 @@ if (isset($_POST['add_hr_department'])) { $total_return = 0; foreach ($quantities as $i => $qty) { - $total_return += (float)$qty * (float)$prices[$i]; + $total_return += normalize_quantity($qty) * (float)$prices[$i]; } // Insert Sales Return @@ -3911,7 +3918,7 @@ if (isset($_POST['add_hr_department'])) { // $stmtStock = $db->prepare("UPDATE stock_items SET stock_quantity = stock_quantity + ? WHERE id = ?"); foreach ($item_ids as $i => $item_id) { - $qty = (float)$quantities[$i]; + $qty = normalize_quantity($quantities[$i] ?? 0); if ($qty > 0) { $price = (float)$prices[$i]; $line_total = $qty * $price; @@ -3949,7 +3956,7 @@ if (isset($_POST['add_hr_department'])) { $total_return = 0; foreach ($quantities as $i => $qty) { - $total_return += (float)$qty * (float)$prices[$i]; + $total_return += normalize_quantity($qty) * (float)$prices[$i]; } // Insert Purchase Return @@ -3971,7 +3978,7 @@ if (isset($_POST['add_hr_department'])) { // $stmtStock = $db->prepare("UPDATE stock_items SET stock_quantity = stock_quantity - ? WHERE id = ?"); foreach ($item_ids as $i => $item_id) { - $qty = (float)$quantities[$i]; + $qty = normalize_quantity($quantities[$i] ?? 0); if ($qty > 0) { $price = (float)$prices[$i]; $line_total = $qty * $price; @@ -7333,8 +7340,8 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]);
- -
Min:
+ +
Min:
Low Stock @@ -7385,7 +7392,7 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]); Category Supplier Sale PriceOMR - Stock Level + Stock Level VAT Rate%
@@ -7420,8 +7427,8 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]);
-
-
+
+

Promotion Details
@@ -7498,7 +7505,7 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]);
- + @@ -7555,10 +7562,10 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]); - + - + @@ -7697,7 +7704,7 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]);
-
+
<?= htmlspecialchars($p['name_en']) ?> @@ -7720,7 +7727,7 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]); OMR
- left + left
@@ -7746,7 +7753,7 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]);
- +
- +
OMR @@ -8745,8 +8752,8 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]);
@@ -8760,7 +8767,7 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]); @@ -11680,8 +11687,8 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]);
-
-
+
+
@@ -11970,9 +11977,72 @@ runtime_debug_mark('page:rendering', ['page' => (string)$page]);