From b1a016903b20cd326a1687ce5ec348d7b2264327 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 19 Apr 2026 16:03:44 +0000 Subject: [PATCH] Autosave: 20260419-160352 --- api/place_order.php | 97 +++++++++++ includes/app.php | 28 ++- includes/footer.php | 14 ++ includes/header.php | 27 ++- index.php | 373 ++++++++++++++++++++++++++++++++------- online_orders.php | 159 +++++++++++++++++ outlets.php | 240 +++++++++++++++++++++++++ patch_stock.py | 44 +++++ purchases.php | 2 +- reports.php | 16 +- sales.php | 2 +- shop.php | 413 ++++++++++++++++++++++++++++++++++++++++++++ stock.php | 23 ++- 13 files changed, 1354 insertions(+), 84 deletions(-) create mode 100644 api/place_order.php create mode 100644 online_orders.php create mode 100644 outlets.php create mode 100644 patch_stock.py create mode 100644 shop.php diff --git a/api/place_order.php b/api/place_order.php new file mode 100644 index 0000000..d12316f --- /dev/null +++ b/api/place_order.php @@ -0,0 +1,97 @@ + false, 'error' => 'Invalid method']); + exit; +} + +$input = json_decode(file_get_contents('php://input'), true); +if (!$input || empty($input['items'])) { + echo json_encode(['success' => false, 'error' => 'Cart is empty']); + exit; +} + +$name = trim($input['name'] ?? ''); +$phone = trim($input['phone'] ?? ''); +$address = trim($input['address'] ?? ''); + +if ($name === '' || $phone === '' || $address === '') { + echo json_encode(['success' => false, 'error' => 'Missing customer details']); + exit; +} + +$items = $input['items']; +$total = 0; + +// Recalculate total for security +$db = db(); +$processedItems = []; +foreach ($items as $id => $item) { + $qty = (int)$item['qty']; + if ($qty <= 0) continue; + + // get price from DB + $stmt = $db->prepare("SELECT sku, name, price FROM items WHERE id = ?"); + $stmt->execute([$id]); + $dbItem = $stmt->fetch(); + if ($dbItem) { + $price = (float)$dbItem['price']; + $total += ($price * $qty); + $processedItems[] = [ + 'id' => $id, + 'sku' => $dbItem['sku'], + 'name' => $dbItem['name'], + 'price' => $price, + 'qty' => $qty + ]; + } +} + +if (empty($processedItems)) { + echo json_encode(['success' => false, 'error' => 'Invalid items']); + exit; +} + +try { + $stmt = $db->prepare("INSERT INTO online_orders (customer_name, customer_phone, customer_address, items_json, total_amount) VALUES (?, ?, ?, ?, ?)"); + $stmt->execute([ + $name, + $phone, + $address, + json_encode($processedItems, JSON_UNESCAPED_UNICODE), + $total + ]); + + // Optional: send telegram notification if configured + try { + // require_once __DIR__ . '/telegram_webhook.php'; // wait, it might not be a function but a script. Let's just do simple notification + $orderId = $db->lastInsertId(); + $msg = "🛒 *New Online Order #{$orderId}*\n\n"; + $msg .= "👤 {$name}\n📞 {$phone}\n📍 {$address}\n\n"; + $msg .= "💰 Total: " . currency($total) . "\n"; + // To send, we'd need to call telegram api directly if token is set. + $botToken = getenv('TELEGRAM_BOT_TOKEN') ?: get_setting('telegram_bot_token'); + $chatId = getenv('TELEGRAM_CHAT_ID') ?: get_setting('telegram_chat_id'); + if ($botToken && $chatId) { + $url = "https://api.telegram.org/bot{$botToken}/sendMessage"; + $data = ['chat_id' => $chatId, 'text' => $msg, 'parse_mode' => 'Markdown']; + $options = [ + 'http' => [ + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'method' => 'POST', + 'content' => http_build_query($data) + ] + ]; + $context = stream_context_create($options); + @file_get_contents($url, false, $context); + } + } catch (Exception $e) { + // ignore notification errors + } + + echo json_encode(['success' => true]); +} catch (Exception $e) { + echo json_encode(['success' => false, 'error' => 'Database error']); +} diff --git a/includes/app.php b/includes/app.php index 25c4104..84a6e83 100644 --- a/includes/app.php +++ b/includes/app.php @@ -98,6 +98,20 @@ function pull_flash(): ?array function branches(): array { + try { + $db = db(); + $stmt = $db->query("SELECT * FROM branches"); + $res = $stmt->fetchAll(PDO::FETCH_ASSOC); + if ($res) { + $arr = []; + foreach ($res as $row) { + $arr[$row['code']] = $row; + } + return $arr; + } + } catch (Exception $e) { + // Table might not exist yet + } return [ 'muscat' => ['code' => 'muscat', 'name_ar' => 'فرع مسقط', 'name_en' => 'Muscat Branch', 'city_ar' => 'مسقط', 'city_en' => 'Muscat'], 'sohar' => ['code' => 'sohar', 'name_ar' => 'فرع صحار', 'name_en' => 'Sohar Branch', 'city_ar' => 'صحار', 'city_en' => 'Sohar'], @@ -208,7 +222,7 @@ function catalog(): array "cost_price" => (float)($item["cost_price"] ?? 0), "base_stock" => (int)$item["base_stock"], "vat" => (float)$item["vat"], - "category_id" => $item["category_id"], + "category_id" => $item["category_id"], "in_catalog" => (int)($item["in_catalog"] ?? 0), "supplier_id" => $item["supplier_id"], "image_url" => $item["image_url"], "unit_id" => $item["unit_id"], @@ -414,6 +428,7 @@ function report_metrics(): array $branchTotals = []; $paymentTotals = []; $productTotals = []; + $monthlyTotals = []; $gross = 0.0; $totalVat = 0.0; @@ -423,7 +438,10 @@ function report_metrics(): array $payment = $sale['payment_method']; $paymentTotals[$payment] = ($paymentTotals[$payment] ?? 0.0) + (float) $sale['total_amount']; $gross += (float) $sale['total_amount']; - $totalVat += (float) $sale['vat_amount']; + $totalVat += (float) $sale['vat_amount']; + + $month = substr((string)$sale['sale_date'], 0, 7); + $monthlyTotals[$month] = ($monthlyTotals[$month] ?? 0.0) + (float) $sale['total_amount']; foreach ($sale['items'] as $item) { $sku = (string) ($item['sku'] ?? ''); $qty = (int) ($item['qty'] ?? 0); @@ -433,14 +451,16 @@ function report_metrics(): array arsort($branchTotals); arsort($paymentTotals); - arsort($productTotals); + arsort($productTotals); + ksort($monthlyTotals); return [ 'gross' => $gross, 'total_vat' => $totalVat, 'branch_totals' => $branchTotals, 'payment_totals' => $paymentTotals, - 'product_totals' => $productTotals, + 'product_totals' => $productTotals, + 'monthly_totals' => $monthlyTotals, 'sales_count' => count($sales), ]; } diff --git a/includes/footer.php b/includes/footer.php index 69a9e57..84fd362 100644 --- a/includes/footer.php +++ b/includes/footer.php @@ -6,6 +6,20 @@ $isPublic = !isset($user) || !$user; + + + + + diff --git a/includes/header.php b/includes/header.php index a860e12..ff9dd6e 100644 --- a/includes/header.php +++ b/includes/header.php @@ -11,7 +11,7 @@ $flash = pull_flash(); $assetVersion = date('YmdHi'); // Determine if we are on a public page (like login) -$isPublic = !isset($user) || !$user; +$isPublic = !empty($forcePublic) || !isset($user) || !$user; ?> @@ -138,6 +138,9 @@ $isPublic = !isset($user) || !$user; + + + @@ -153,16 +156,29 @@ $isPublic = !isset($user) || !$user; - - - + +
+ + +
+
+
+ +
-
+