From b89863b4d3d86717ded4f1ae5dd41900762baae0 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 3 May 2026 03:29:51 +0000 Subject: [PATCH] Autosave: 20260503-032951 --- index.php | 331 +------------------------------- pages/sales_purchases_logic.php | 130 +++++++++++++ pages/sales_purchases_view.php | 204 ++++++++++++++++++++ 3 files changed, 336 insertions(+), 329 deletions(-) create mode 100644 pages/sales_purchases_logic.php create mode 100644 pages/sales_purchases_view.php diff --git a/index.php b/index.php index 0c25abb..e8c89ec 100644 --- a/index.php +++ b/index.php @@ -4071,134 +4071,7 @@ switch ($page) { break; case 'sales': case 'purchases': - $type = ($page === 'sales') ? 'sale' : 'purchase'; - $table = ($type === 'purchase') ? 'purchases' : 'invoices'; - $cust_supplier_col = ($type === 'purchase') ? 'supplier_id' : 'customer_id'; - $cust_supplier_table = ($type === 'purchase') ? 'suppliers' : 'customers'; - - $where = ["1=1"]; - $params = []; - - $referenceSearchColumn = db_column_exists($table, 'transaction_no') ? 'transaction_no' : null; - if (!empty($_GET['search'])) { - $s = trim((string)$_GET['search']); - $clean_id = preg_replace('/[^0-9]/', '', $s); - $searchClauses = ["CAST(v.id AS CHAR) LIKE ?", "c.name LIKE ?"]; - $searchParams = ["%$s%", "%$s%"]; - - if ($referenceSearchColumn !== null) { - $searchClauses[] = "v.$referenceSearchColumn LIKE ?"; - $searchParams[] = "%$s%"; - } - - if ($clean_id !== '') { - $searchClauses[] = "v.id = ?"; - $searchParams[] = $clean_id; - } - - $where[] = '(' . implode(' OR ', $searchClauses) . ')'; - $params = array_merge($params, $searchParams); - } - - if (!empty($_GET['customer_id'])) { - $where[] = "v.$cust_supplier_col = ?"; - $params[] = $_GET['customer_id']; - } - - if (!empty($_GET['start_date'])) { - $where[] = "v.invoice_date >= ?"; - $params[] = $_GET['start_date']; - } - - if (!empty($_GET['end_date'])) { - $where[] = "v.invoice_date <= ?"; - $params[] = $_GET['end_date']; - } - - $tableHasOutlet = db_column_exists($table, 'outlet_id'); - $oid = current_outlet_id(); - if ($tableHasOutlet && $oid !== -1) { - $where[] = "(v.outlet_id = ? OR v.outlet_id IS NULL)"; - $params[] = $oid; - } - - $whereSql = implode(" AND ", $where); - - $countStmt = db()->prepare("SELECT COUNT(*) FROM $table v LEFT JOIN $cust_supplier_table c ON v.$cust_supplier_col = c.id WHERE $whereSql"); - $countStmt->execute($params); - $total_records = (int)$countStmt->fetchColumn(); - $data['total_pages'] = ceil($total_records / $limit); - $data['current_page'] = $page_num; - - $customerTaxColumn = entity_tax_column($cust_supplier_table); - $customerTaxSelect = $customerTaxColumn !== null ? "c.$customerTaxColumn" : "''"; - $outletSelectSql = "'' AS outlet_name"; - $outletJoinSql = ''; - if ($tableHasOutlet && db_table_exists('outlets')) { - $outletSelectSql = "o.name AS outlet_name"; - $outletJoinSql = "LEFT JOIN outlets o ON v.outlet_id = o.id"; - } - $stmt = db()->prepare("SELECT v.*, c.name as customer_name, $customerTaxSelect as customer_tax_id, c.phone as customer_phone, $outletSelectSql - FROM $table v - LEFT JOIN $cust_supplier_table c ON v.$cust_supplier_col = c.id - $outletJoinSql - WHERE $whereSql - ORDER BY v.id DESC LIMIT $limit OFFSET $offset"); - $stmt->execute($params); - $data['invoices'] = $stmt->fetchAll(); - $documentPrefix = ($type === 'purchase') ? 'PUR' : 'INV'; - foreach ($data['invoices'] as &$inv) { - $inv['due_date'] = $inv['due_date'] ?? null; - $transactionNo = trim((string)($inv['transaction_no'] ?? '')); - $partyFallback = ($type === 'sale' && !empty($inv['is_pos'])) ? 'Walk-in Customer' : '---'; - $normalizedPaymentType = strtolower(str_replace([' ', '-'], '_', (string)($inv['payment_type'] ?? 'cash'))); - $paymentTypeLabel = 'Cash'; - - if ($normalizedPaymentType === 'bank_transfer') { - $paymentTypeLabel = 'Bank Transfer'; - } elseif (in_array($normalizedPaymentType, ['card', 'credit_card'], true)) { - $paymentTypeLabel = 'Card'; - } elseif ($normalizedPaymentType === 'credit') { - $paymentTypeLabel = 'Credit'; - } - - $inv['party_name'] = trim((string)($inv['customer_name'] ?? '')) !== '' ? (string)$inv['customer_name'] : $partyFallback; - $inv['document_no'] = ($type === 'sale' && $transactionNo !== '') ? $transactionNo : $documentPrefix . '-' . str_pad((string)$inv['id'], 5, '0', STR_PAD_LEFT); - $inv['type'] = $type; - $inv['payment_type'] = $normalizedPaymentType; - $inv['payment_type_label'] = $paymentTypeLabel; - $inv['total_with_vat'] = (float)($inv['total_with_vat'] ?? (($inv['total_amount'] ?? 0) + ($inv['vat_amount'] ?? 0))); - $inv['paid_amount'] = (float)($inv['paid_amount'] ?? 0); - $inv['balance_amount'] = max($inv['total_with_vat'] - $inv['paid_amount'], 0); - $inv['total_in_words'] = numberToWordsOMR($inv['total_with_vat']); - - if ($type === 'sale') { - $item_stmt = db()->prepare("SELECT ii.*, i.name_en, i.name_ar, i.vat_rate FROM invoice_items ii LEFT JOIN stock_items i ON ii.item_id = i.id WHERE ii.invoice_id = ?"); - $item_stmt->execute([$inv['id']]); - $inv['items'] = $item_stmt->fetchAll(PDO::FETCH_ASSOC); - } else { - $item_stmt = db()->prepare("SELECT pi.*, i.name_en, i.name_ar, i.vat_rate FROM purchase_items pi LEFT JOIN stock_items i ON pi.item_id = i.id WHERE pi.purchase_id = ?"); - $item_stmt->execute([$inv['id']]); - $inv['items'] = $item_stmt->fetchAll(PDO::FETCH_ASSOC); - } - } - unset($inv); - - $oid = current_outlet_id(); $items_list_raw = db()->query("SELECT i.id, i.name_en, i.name_ar, i.sale_price, i.purchase_price, i.stock_quantity, i.vat_rate, i.is_promotion, i.promotion_start, i.promotion_end, i.promotion_percent FROM stock_items i ORDER BY i.name_en ASC")->fetchAll(PDO::FETCH_ASSOC); - foreach ($items_list_raw as &$item) { - $item['sale_price'] = getPromotionalPrice($item); - } - $data['items_list'] = $items_list_raw; - $data['customers_list'] = db()->query("SELECT id, name FROM $cust_supplier_table ORDER BY name ASC")->fetchAll(); - - $oid = current_outlet_id(); - $outlet_sql = ($oid !== -1) ? "WHERE outlet_id = $oid" : ""; - - if ($type === 'sale') { - $data['sales_invoices'] = db()->query("SELECT id, invoice_date, total_with_vat FROM invoices $outlet_sql ORDER BY id DESC")->fetchAll(); - } else { - $data['purchase_invoices'] = db()->query("SELECT id, invoice_date, total_with_vat FROM purchases $outlet_sql ORDER BY id DESC")->fetchAll(); - } + require 'pages/sales_purchases_logic.php'; break; case 'sales_returns': @@ -7960,207 +7833,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; -
- - - -
-
-
- - Export to Excel - - - - -
-
- - -
-
- - - -
- - -
-
- - -
-
- - -
-
- - - - - Clear - -
-
-
-
- - - - - - - - - - - - - - - - prepare("SELECT ii.*, i.name_en, i.name_ar, i.vat_rate - FROM $itemTable ii - JOIN stock_items i ON ii.item_id = i.id - WHERE ii.$fkCol = ?"); - $items->execute([$inv['id']]); - $inv['items'] = $items->fetchAll(PDO::FETCH_ASSOC); - $isOverdue = !empty($inv['due_date']) && strtotime((string)$inv['due_date']) < time() && ($inv['status'] ?? '') !== 'paid'; - ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Invoice #DatesPaymentStatusTotalPaidBalanceActions
-
- -
- -
-
-
- - - - - - - -
-
- - - OMR OMR OMR -
- - - - - - - -
- - -
-
-
No invoices found
TotalsOMR OMR OMR
-
- - - -
+
diff --git a/pages/sales_purchases_logic.php b/pages/sales_purchases_logic.php new file mode 100644 index 0000000..e47a240 --- /dev/null +++ b/pages/sales_purchases_logic.php @@ -0,0 +1,130 @@ += ?"; + $params[] = $_GET['start_date']; + } + + if (!empty($_GET['end_date'])) { + $where[] = "v.invoice_date <= ?"; + $params[] = $_GET['end_date']; + } + + $tableHasOutlet = db_column_exists($table, 'outlet_id'); + $oid = current_outlet_id(); + if ($tableHasOutlet && $oid !== -1) { + $where[] = "(v.outlet_id = ? OR v.outlet_id IS NULL)"; + $params[] = $oid; + } + + $whereSql = implode(" AND ", $where); + + $countStmt = db()->prepare("SELECT COUNT(*) FROM $table v LEFT JOIN $cust_supplier_table c ON v.$cust_supplier_col = c.id WHERE $whereSql"); + $countStmt->execute($params); + $total_records = (int)$countStmt->fetchColumn(); + $data['total_pages'] = ceil($total_records / $limit); + $data['current_page'] = $page_num; + + $customerTaxColumn = entity_tax_column($cust_supplier_table); + $customerTaxSelect = $customerTaxColumn !== null ? "c.$customerTaxColumn" : "''"; + $outletSelectSql = "'' AS outlet_name"; + $outletJoinSql = ''; + if ($tableHasOutlet && db_table_exists('outlets')) { + $outletSelectSql = "o.name AS outlet_name"; + $outletJoinSql = "LEFT JOIN outlets o ON v.outlet_id = o.id"; + } + $stmt = db()->prepare("SELECT v.*, c.name as customer_name, $customerTaxSelect as customer_tax_id, c.phone as customer_phone, $outletSelectSql + FROM $table v + LEFT JOIN $cust_supplier_table c ON v.$cust_supplier_col = c.id + $outletJoinSql + WHERE $whereSql + ORDER BY v.id DESC LIMIT $limit OFFSET $offset"); + $stmt->execute($params); + $data['invoices'] = $stmt->fetchAll(); + $documentPrefix = ($type === 'purchase') ? 'PUR' : 'INV'; + foreach ($data['invoices'] as &$inv) { + $inv['due_date'] = $inv['due_date'] ?? null; + $transactionNo = trim((string)($inv['transaction_no'] ?? '')); + $partyFallback = ($type === 'sale' && !empty($inv['is_pos'])) ? 'Walk-in Customer' : '---'; + $normalizedPaymentType = strtolower(str_replace([' ', '-'], '_', (string)($inv['payment_type'] ?? 'cash'))); + $paymentTypeLabel = 'Cash'; + + if ($normalizedPaymentType === 'bank_transfer') { + $paymentTypeLabel = 'Bank Transfer'; + } elseif (in_array($normalizedPaymentType, ['card', 'credit_card'], true)) { + $paymentTypeLabel = 'Card'; + } elseif ($normalizedPaymentType === 'credit') { + $paymentTypeLabel = 'Credit'; + } + + $inv['party_name'] = trim((string)($inv['customer_name'] ?? '')) !== '' ? (string)$inv['customer_name'] : $partyFallback; + $inv['document_no'] = ($type === 'sale' && $transactionNo !== '') ? $transactionNo : $documentPrefix . '-' . str_pad((string)$inv['id'], 5, '0', STR_PAD_LEFT); + $inv['type'] = $type; + $inv['payment_type'] = $normalizedPaymentType; + $inv['payment_type_label'] = $paymentTypeLabel; + $inv['total_with_vat'] = (float)($inv['total_with_vat'] ?? (($inv['total_amount'] ?? 0) + ($inv['vat_amount'] ?? 0))); + $inv['paid_amount'] = (float)($inv['paid_amount'] ?? 0); + $inv['balance_amount'] = max($inv['total_with_vat'] - $inv['paid_amount'], 0); + $inv['total_in_words'] = numberToWordsOMR($inv['total_with_vat']); + + if ($type === 'sale') { + $item_stmt = db()->prepare("SELECT ii.*, i.name_en, i.name_ar, i.vat_rate FROM invoice_items ii LEFT JOIN stock_items i ON ii.item_id = i.id WHERE ii.invoice_id = ?"); + $item_stmt->execute([$inv['id']]); + $inv['items'] = $item_stmt->fetchAll(PDO::FETCH_ASSOC); + } else { + $item_stmt = db()->prepare("SELECT pi.*, i.name_en, i.name_ar, i.vat_rate FROM purchase_items pi LEFT JOIN stock_items i ON pi.item_id = i.id WHERE pi.purchase_id = ?"); + $item_stmt->execute([$inv['id']]); + $inv['items'] = $item_stmt->fetchAll(PDO::FETCH_ASSOC); + } + } + unset($inv); + + $oid = current_outlet_id(); $items_list_raw = db()->query("SELECT i.id, i.name_en, i.name_ar, i.sale_price, i.purchase_price, i.stock_quantity, i.vat_rate, i.is_promotion, i.promotion_start, i.promotion_end, i.promotion_percent FROM stock_items i ORDER BY i.name_en ASC")->fetchAll(PDO::FETCH_ASSOC); + foreach ($items_list_raw as &$item) { + $item['sale_price'] = getPromotionalPrice($item); + } + $data['items_list'] = $items_list_raw; + $data['customers_list'] = db()->query("SELECT id, name FROM $cust_supplier_table ORDER BY name ASC")->fetchAll(); + + $oid = current_outlet_id(); + $outlet_sql = ($oid !== -1) ? "WHERE outlet_id = $oid" : ""; + + if ($type === 'sale') { + $data['sales_invoices'] = db()->query("SELECT id, invoice_date, total_with_vat FROM invoices $outlet_sql ORDER BY id DESC")->fetchAll(); + } else { + $data['purchase_invoices'] = db()->query("SELECT id, invoice_date, total_with_vat FROM purchases $outlet_sql ORDER BY id DESC")->fetchAll(); + } diff --git a/pages/sales_purchases_view.php b/pages/sales_purchases_view.php new file mode 100644 index 0000000..f6f23e9 --- /dev/null +++ b/pages/sales_purchases_view.php @@ -0,0 +1,204 @@ + +
+ + + +
+
+
+ + Export to Excel + + + + +
+
+ + +
+
+ + + +
+ + +
+
+ + +
+
+ + +
+
+ + + + + Clear + +
+
+
+
+ + + + + + + + + + + + + + + + prepare("SELECT ii.*, i.name_en, i.name_ar, i.vat_rate + FROM $itemTable ii + JOIN stock_items i ON ii.item_id = i.id + WHERE ii.$fkCol = ?"); + $items->execute([$inv['id']]); + $inv['items'] = $items->fetchAll(PDO::FETCH_ASSOC); + $isOverdue = !empty($inv['due_date']) && strtotime((string)$inv['due_date']) < time() && ($inv['status'] ?? '') !== 'paid'; + ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Invoice #DatesPaymentStatusTotalPaidBalanceActions
+
+ +
+ +
+
+
+ + + + + + + +
+
+ + + OMR OMR OMR +
+ + + + + + + +
+ + +
+
+
No invoices found
TotalsOMR OMR OMR
+
+ + + +