update pos

This commit is contained in:
Flatlogic Bot 2026-03-02 13:43:08 +00:00
parent 3f1e18552b
commit 275baf63cd
2 changed files with 99 additions and 10 deletions

View File

@ -14,6 +14,7 @@ $customer_id = $input['customer_id'] ?: null;
$items = $input['items'] ?? [];
$vat_total = (float)($input['vat_total'] ?? 0);
$total_price = (float)($input['total_price'] ?? 0);
$payment_method = $input['payment_method'] ?? null;
$branch_id = $_SESSION['branch_id'];
$user_id = $_SESSION['user_id'];
@ -26,10 +27,12 @@ try {
$pdo = db();
$pdo->beginTransaction();
$payment_status = ($payment_method && $payment_method !== 'pay_later') ? 'paid' : 'unpaid';
if ($order_id) {
// Update existing order
$stmt = $pdo->prepare("UPDATE orders SET customer_id = ?, total_price = ?, vat_total = ? WHERE id = ? AND branch_id = ?");
$stmt->execute([$customer_id, $total_price, $vat_total, $order_id, $branch_id]);
$stmt = $pdo->prepare("UPDATE orders SET customer_id = ?, total_price = ?, vat_total = ?, payment_status = ? WHERE id = ? AND branch_id = ?");
$stmt->execute([$customer_id, $total_price, $vat_total, $payment_status, $order_id, $branch_id]);
// Remove existing items
$stmt = $pdo->prepare("DELETE FROM order_items WHERE order_id = ?");
@ -37,8 +40,8 @@ try {
} else {
// Create new order
$stmt = $pdo->prepare("INSERT INTO orders (branch_id, customer_id, user_id, order_number, total_price, vat_total, status, payment_status)
VALUES (?, ?, ?, NULL, ?, ?, 'received', 'unpaid')");
$stmt->execute([$branch_id, $customer_id, $user_id, $total_price, $vat_total]);
VALUES (?, ?, ?, NULL, ?, ?, 'received', ?)");
$stmt->execute([$branch_id, $customer_id, $user_id, $total_price, $vat_total, $payment_status]);
$order_id = $pdo->lastInsertId();
// Get branch prefix
@ -49,14 +52,12 @@ try {
$prefix = strtoupper(str_pad($prefix, 3, 'X'));
// Determine the next serial number for this branch
// We look at existing order numbers for this branch that follow the XXX-###### format
$stmt_max = $pdo->prepare("SELECT order_number FROM orders WHERE branch_id = ? AND order_number LIKE ? ORDER BY id DESC LIMIT 100");
$stmt_max->execute([$branch_id, "$prefix-%"]);
$existing_orders = $stmt_max->fetchAll(PDO::FETCH_COLUMN);
$max_serial = 0;
foreach ($existing_orders as $onum) {
// Format is XXX-######.
if (preg_match('/' . preg_quote($prefix) . '-(\d{6})/', $onum, $matches)) {
$serial = (int)$matches[1];
if ($serial > $max_serial) $max_serial = $serial;
@ -88,6 +89,12 @@ try {
]);
}
// Handle Payment recording
if ($payment_method && $payment_method !== 'pay_later') {
$stmt_payment = $pdo->prepare("INSERT INTO payments (order_id, amount, payment_method) VALUES (?, ?, ?)");
$stmt_payment->execute([$order_id, $total_price, $payment_method]);
}
$pdo->commit();
echo json_encode(['success' => true, 'order_id' => $order_id]);
} catch (Exception $e) {

90
pos.php
View File

@ -288,6 +288,48 @@ $pageTitle = $edit_order ? ($lang == 'en' ? 'Edit Order #' . $edit_order['order_
</div>
</div>
<!-- Payment Modal -->
<div class="modal fade" id="paymentModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-0 rounded-4 shadow-lg">
<div class="modal-header border-0 pb-0">
<h5 class="modal-title fw-bold"><?= $lang == 'en' ? 'Payment' : 'الدفع' ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-4">
<div class="text-center mb-4">
<h3 class="fw-bold text-primary mb-1" id="paymentTotalAmount">0.000</h3>
<div class="text-muted small"><?= $lang == 'en' ? 'Total Amount' : 'المبلغ الإجمالي' ?></div>
</div>
<div class="row g-3">
<div class="col-6">
<button class="btn btn-outline-primary w-100 py-3 rounded-3 d-flex flex-column align-items-center" onclick="completeCheckout('cash')">
<i class="bi bi-cash-stack mb-1 fs-4"></i>
<span class="small fw-bold"><?= $lang == 'en' ? 'Cash' : 'نقداً' ?></span>
</button>
</div>
<div class="col-6">
<button class="btn btn-outline-primary w-100 py-3 rounded-3 d-flex flex-column align-items-center" onclick="completeCheckout('card')">
<i class="bi bi-credit-card mb-1 fs-4"></i>
<span class="small fw-bold"><?= $lang == 'en' ? 'Card' : 'بطاقة' ?></span>
</button>
</div>
<div class="col-12">
<button class="btn btn-outline-secondary w-100 py-3 rounded-3 d-flex flex-column align-items-center" onclick="completeCheckout('pay_later')">
<i class="bi bi-clock-history mb-1 fs-4"></i>
<span class="small fw-bold"><?= $lang == 'en' ? 'Pay Later' : 'الدفع لاحقاً' ?></span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Hidden Iframe for Printing -->
<iframe id="printFrame" style="display:none;"></iframe>
<script>
const itemsData = <?= json_encode((object)$items) ?>;
const lang = '<?= $lang ?>';
@ -296,6 +338,7 @@ const decimalPrecision = <?= decimals() ?>;
const editOrderId = <?= $edit_order_id ?: 'null' ?>;
let cart = <?= json_encode($edit_items) ?>;
let selectionModal;
let paymentModal;
// If not editing, try to load from local storage
if (!editOrderId) {
@ -312,6 +355,9 @@ document.addEventListener('DOMContentLoaded', () => {
if (typeof bootstrap !== 'undefined') {
const modalEl = document.getElementById('selectionModal');
if (modalEl) selectionModal = new bootstrap.Modal(modalEl);
const payModalEl = document.getElementById('paymentModal');
if (payModalEl) paymentModal = new bootstrap.Modal(payModalEl);
}
// Category filtering
@ -527,14 +573,25 @@ function clearCart() {
}
}
async function checkout() {
function checkout() {
if (cart.length === 0) return;
let total = 0;
cart.forEach(item => {
const itemSubtotal = item.price * item.qty;
total += itemSubtotal + (itemSubtotal * ((item.vat_percent || 15) / 100));
});
document.getElementById('paymentTotalAmount').innerText = total.toFixed(decimalPrecision) + ' ' + currencyLabel;
if (paymentModal) paymentModal.show();
}
async function completeCheckout(paymentMethod) {
const cid = document.getElementById('customerId').value;
let subtotal = 0;
let totalVat = 0;
// Map cart items to the keys expected by checkout.php
const itemsToSubmit = cart.map(item => {
const itemSubtotal = item.price * item.qty;
const itemVat = itemSubtotal * ((item.vat_percent || 15) / 100);
@ -552,6 +609,8 @@ async function checkout() {
};
});
const totalPrice = subtotal + totalVat;
try {
const response = await fetch('api/checkout.php', {
method: 'POST',
@ -561,20 +620,43 @@ async function checkout() {
customer_id: cid,
items: itemsToSubmit,
vat_total: totalVat,
total_price: subtotal + totalVat
total_price: totalPrice,
payment_method: paymentMethod
})
});
const res = await response.json();
if (res.success) {
const orderId = res.order_id || editOrderId;
// Direct Print
printReceipt(orderId);
if (!editOrderId) {
cart = [];
updateCart();
localStorage.removeItem('pos_cart');
}
window.location.href = 'order_details.php?id=' + (res.order_id || editOrderId);
if (paymentModal) paymentModal.hide();
// Wait a bit for print dialog to start then redirect
setTimeout(() => {
window.location.href = 'pos.php';
}, 2000);
} else alert(res.error);
} catch (e) { alert('Error'); }
}
function printReceipt(orderId) {
const iframe = document.getElementById('printFrame');
iframe.src = 'receipt.php?id=' + orderId;
iframe.onload = function() {
iframe.contentWindow.focus();
iframe.contentWindow.print();
};
}
async function saveCustomer() {
const form = document.getElementById('addCustomerForm');
if (!form) return;