298 lines
15 KiB
PHP
298 lines
15 KiB
PHP
<?php
|
|
// ACTION HANDLING FIRST
|
|
require_once __DIR__ . '/db/config.php';
|
|
require_once __DIR__ . '/includes/lang.php';
|
|
require_once __DIR__ . '/includes/whatsapp.php';
|
|
|
|
$order_id = $_GET['id'] ?? null;
|
|
if (!$order_id) {
|
|
header('Location: orders.php');
|
|
exit;
|
|
}
|
|
|
|
$stmt = db()->prepare("SELECT o.*, c.name_en as customer_name_en, c.name_ar as customer_name_ar, c.phone as customer_phone, c.address_en as customer_address_en, c.address_ar as customer_address_ar
|
|
FROM orders o
|
|
LEFT JOIN customers c ON o.customer_id = c.id
|
|
WHERE o.id = ?");
|
|
$stmt->execute([$order_id]);
|
|
$order = $stmt->fetch();
|
|
|
|
if (!$order) {
|
|
echo "Order not found";
|
|
exit;
|
|
}
|
|
|
|
// Handle status updates
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
|
if ($_POST['action'] === 'update_status') {
|
|
$new_status = $_POST['status'];
|
|
$stmt = db()->prepare("UPDATE orders SET status = ? WHERE id = ?");
|
|
$stmt->execute([$new_status, $order_id]);
|
|
|
|
// WhatsApp Notification for Order Ready
|
|
try {
|
|
if ($new_status === 'ready' && get_setting('whatsapp_enabled') === '1' && !empty($order['customer_phone'])) {
|
|
$template = get_setting('msg_order_ready_ar');
|
|
if (!empty($template)) {
|
|
$message = str_replace(
|
|
['{customer_name}', '{order_number}'],
|
|
[$order['customer_name_ar'], $order['order_number']],
|
|
$template
|
|
);
|
|
send_whatsapp_message($order['customer_phone'], $message);
|
|
}
|
|
}
|
|
} catch (Exception $e) {}
|
|
|
|
header("Location: order_details.php?id=$order_id");
|
|
exit;
|
|
} elseif ($_POST['action'] === 'add_payment') {
|
|
$amount = (float)$_POST['amount'];
|
|
$method = $_POST['payment_method'];
|
|
$stmt = db()->prepare("INSERT INTO payments (order_id, amount, payment_method) VALUES (?, ?, ?)");
|
|
$stmt->execute([$order_id, $amount, $method]);
|
|
|
|
$stmt = db()->prepare("SELECT SUM(amount) as total_paid FROM payments WHERE order_id = ?");
|
|
$stmt->execute([$order_id]);
|
|
$total_paid = $stmt->fetch()['total_paid'] ?? 0;
|
|
|
|
$payment_status = $total_paid >= ($order['total_price'] - $order['loyalty_discount']) ? 'paid' : ($total_paid > 0 ? 'partially_paid' : 'unpaid');
|
|
$stmt = db()->prepare("UPDATE orders SET payment_status = ? WHERE id = ?");
|
|
$stmt->execute([$payment_status, $order_id]);
|
|
|
|
// WhatsApp Notification for Payment Received
|
|
try {
|
|
if (get_setting('whatsapp_enabled') === '1' && !empty($order['customer_phone'])) {
|
|
$remaining_now = ((float)$order['total_price'] - (float)$order['loyalty_discount']) - (float)$total_paid;
|
|
$template = get_setting('msg_payment_ar');
|
|
if (!empty($template)) {
|
|
$message = str_replace(
|
|
['{customer_name}', '{order_number}', '{amount}', '{remaining_balance}'],
|
|
[$order['customer_name_ar'], $order['order_number'], $amount, max(0, $remaining_now)],
|
|
$template
|
|
);
|
|
send_whatsapp_message($order['customer_phone'], $message);
|
|
}
|
|
}
|
|
} catch (Exception $e) {}
|
|
|
|
header("Location: order_details.php?id=$order_id");
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// NOW Include header
|
|
$title = 'order_details';
|
|
require_once __DIR__ . '/includes/header.php';
|
|
if ($current_role === 'limited_viewer') { header('Location: admin.php'); exit; }
|
|
|
|
$stmt = db()->prepare("SELECT oi.*, i.name_en as item_en, i.name_ar as item_ar,
|
|
s.name_en as service_en, s.name_ar as service_ar
|
|
FROM order_items oi
|
|
JOIN items i ON oi.item_id = i.id
|
|
JOIN services s ON oi.service_id = s.id
|
|
WHERE oi.order_id = ?");
|
|
$stmt->execute([$order_id]);
|
|
$order_items = $stmt->fetchAll();
|
|
|
|
$stmt = db()->prepare("SELECT * FROM payments WHERE order_id = ?");
|
|
$stmt->execute([$order_id]);
|
|
$payments = $stmt->fetchAll();
|
|
|
|
?>
|
|
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<div class="card p-4 mb-4" style="border-radius: 25px; border: none; shadow: 0 10px 30px rgba(0,0,0,0.05);">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h5 class="fw-bold mb-0"><?= __('order') ?> #<?= $order['order_number'] ?></h5>
|
|
<div class="d-flex gap-2">
|
|
<span class="badge bg-<?= getStatusColor($order['status']) ?> fs-6 px-3 py-2" style="border-radius: 12px;"><?= __($order['status']) ?></span>
|
|
<span class="badge badge-soft-<?= getPaymentStatusColor($order['payment_status']) ?> fs-6 px-3 py-2" style="border-radius: 12px;"><?= __($order['payment_status']) ?></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-responsive mb-4">
|
|
<table class="table align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th><?= __('item') ?></th>
|
|
<th><?= __('service') ?></th>
|
|
<th><?= __('quantity') ?></th>
|
|
<th class="text-end"><?= __('price') ?></th>
|
|
<th class="text-end"><?= __('vat') ?></th>
|
|
<th class="text-end"><?= __('subtotal') ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$subtotal_sum = 0;
|
|
foreach($order_items as $item):
|
|
$subtotal_sum += $item['subtotal'];
|
|
?>
|
|
<tr>
|
|
<td>
|
|
<strong><?= $lang === 'ar' ? ($item['item_ar'] ?: $item['item_en']) : $item['item_en'] ?></strong>
|
|
</td>
|
|
<td><?= $lang === 'ar' ? ($item['service_ar'] ?: $item['service_en']) : $item['service_en'] ?></td>
|
|
<td><?= $item['quantity'] ?></td>
|
|
<td class="text-end"><?= format_amount($item['unit_price']) ?></td>
|
|
<td class="text-end"><?= format_amount($item['vat_amount'] * $item['quantity']) ?></td>
|
|
<td class="text-end fw-bold"><?= format_amount($item['subtotal'] + ($item['vat_amount'] * $item['quantity'])) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<th colspan="5" class="text-end text-muted small"><?= __('subtotal') ?></th>
|
|
<th class="text-end"><?= format_amount($subtotal_sum) ?></th>
|
|
</tr>
|
|
<tr>
|
|
<th colspan="5" class="text-end text-muted small"><?= __('vat_total') ?? 'VAT Total' ?></th>
|
|
<th class="text-end"><?= format_amount($order['vat_total']) ?></th>
|
|
</tr>
|
|
<?php if ($order['loyalty_discount'] > 0): ?>
|
|
<tr>
|
|
<th colspan="5" class="text-end text-success small"><?= __('loyalty_discount') ?? 'Loyalty Discount' ?></th>
|
|
<th class="text-end text-success fw-bold">-<?= format_amount($order['loyalty_discount']) ?></th>
|
|
</tr>
|
|
<?php endif; ?>
|
|
<tr>
|
|
<th colspan="5" class="text-end fs-5 fw-bold"><?= __('total') ?></th>
|
|
<th class="text-end fs-5 fw-bold text-primary"><?= format_amount($order['total_price'] - $order['loyalty_discount']) ?></th>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="row mt-4 p-4 bg-light mx-1" style="border-radius: 20px;">
|
|
<div class="col-md-6">
|
|
<h6 class="fw-bold text-muted small mb-3"><?= __('customer_details') ?></h6>
|
|
<p class="mb-1 fw-bold"><?= $lang === 'ar' ? ($order['customer_name_ar'] ?: $order['customer_name_en']) : $order['customer_name_en'] ?></p>
|
|
<p class="mb-1"><?= $order['customer_phone'] ?></p>
|
|
<p class="mb-0 text-muted small"><?= $lang === 'ar' ? ($order['customer_address_ar'] ?: $order['customer_address_en']) : $order['customer_address_en'] ?></p>
|
|
</div>
|
|
<div class="col-md-6 text-md-end mt-4 mt-md-0">
|
|
<h6 class="fw-bold text-muted small mb-3"><?= __('order_date') ?></h6>
|
|
<p class="mb-0 fw-bold"><?= date('d M Y', strtotime($order['created_at'])) ?></p>
|
|
<p class="mb-0 text-muted"><?= date('h:i A', strtotime($order['created_at'])) ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card p-4 border-0 shadow-sm mb-4" style="border-radius: 25px;">
|
|
<h5 class="fw-bold mb-4"><?= __('payments') ?></h5>
|
|
<div class="table-responsive">
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr class="text-muted small">
|
|
<th><?= __('date') ?></th>
|
|
<th><?= __('method') ?></th>
|
|
<th class="text-end"><?= __('amount') ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach($payments as $p): ?>
|
|
<tr>
|
|
<td><?= date('d M Y, h:i A', strtotime($p['created_at'])) ?></td>
|
|
<td><span class="badge bg-light text-dark px-3 py-2 rounded-pill"><?= __($p['payment_method']) ?></span></td>
|
|
<td class="text-end fw-bold"><?= format_amount($p['amount']) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php if (empty($payments)): ?>
|
|
<tr>
|
|
<td colspan="3" class="text-center text-muted py-4"><?= __('no_payments') ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="card p-4 mb-4 border-0 shadow-sm" style="border-radius: 25px;">
|
|
<h5 class="fw-bold mb-4"><?= __('actions') ?></h5>
|
|
<form method="POST" class="mb-4">
|
|
<input type="hidden" name="action" value="update_status">
|
|
<label class="form-label small fw-bold text-muted"><?= __('update_status') ?></label>
|
|
<div class="input-group shadow-sm" style="border-radius: 12px; overflow: hidden;">
|
|
<select name="status" class="form-select border-0 bg-light">
|
|
<option value="received" <?= $order['status'] == 'received' ? 'selected' : '' ?>><?= __('received') ?></option>
|
|
<option value="processing" <?= $order['status'] == 'processing' ? 'selected' : '' ?>><?= __('processing') ?></option>
|
|
<option value="ready" <?= $order['status'] == 'ready' ? 'selected' : '' ?>><?= __('ready') ?></option>
|
|
<option value="delivered" <?= $order['status'] == 'delivered' ? 'selected' : '' ?>><?= __('delivered') ?></option>
|
|
<option value="cancelled" <?= $order['status'] == 'cancelled' ? 'selected' : '' ?>><?= __('cancelled') ?></option>
|
|
</select>
|
|
<button type="submit" class="btn btn-primary px-3 fw-bold"><?= __('update') ?></button>
|
|
</div>
|
|
</form>
|
|
<hr class="my-4 opacity-10">
|
|
<?php
|
|
$stmt = db()->prepare("SELECT SUM(amount) as total_paid FROM payments WHERE order_id = ?");
|
|
$stmt->execute([$order_id]);
|
|
$total_paid = $stmt->fetch()['total_paid'] ?? 0;
|
|
$remaining = ((float)$order['total_price'] - (float)$order['loyalty_discount']) - (float)$total_paid;
|
|
?>
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<span class="text-muted fw-bold small"><?= __('remaining_amount') ?></span>
|
|
<span class="fs-5 fw-bold <?= $remaining <= 0.001 ? 'text-success' : 'text-danger' ?>">
|
|
<?= format_amount(max(0, $remaining)) ?>
|
|
</span>
|
|
</div>
|
|
|
|
<?php if ($remaining > 0.001): ?>
|
|
<form method="POST">
|
|
<input type="hidden" name="action" value="add_payment">
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold text-muted"><?= __('amount') ?></label>
|
|
<input type="number" step="0.001" name="amount" class="form-control bg-light border-0" value="<?= round($remaining, 3) ?>" required style="border-radius: 12px;">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label small fw-bold text-muted"><?= __('payment_method') ?></label>
|
|
<select name="payment_method" class="form-select bg-light border-0" style="border-radius: 12px;">
|
|
<option value="cash"><?= __('cash') ?></option>
|
|
<option value="card"><?= __('card') ?></option>
|
|
<option value="transfer"><?= __('transfer') ?></option>
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="btn btn-success w-100 py-3 fw-bold shadow-sm" style="border-radius: 15px;"><?= __('add_payment') ?></button>
|
|
</form>
|
|
<?php endif; ?>
|
|
|
|
<div class="row mt-4">
|
|
<div class="col-6">
|
|
<button class="btn btn-outline-dark w-100 py-3 fw-bold shadow-sm" style="border-radius: 15px;" onclick="window.print()">
|
|
<i class="bi bi-printer me-2"></i> <?= __('print_invoice') ?>
|
|
</button>
|
|
</div>
|
|
<div class="col-6">
|
|
<a href="receipt.php?id=<?= $order_id ?>" target="_blank" class="btn btn-dark w-100 py-3 fw-bold shadow-sm" style="border-radius: 15px;">
|
|
<i class="bi bi-receipt me-2"></i> <?= __('thermal_receipt') ?? 'Thermal Receipt' ?>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php
|
|
if (!function_exists('getStatusColor')) { function getStatusColor($status) {
|
|
return [
|
|
'received' => 'secondary',
|
|
'processing' => 'primary',
|
|
'ready' => 'success',
|
|
'delivered' => 'dark',
|
|
'cancelled' => 'danger',
|
|
][$status] ?? 'info';
|
|
}}
|
|
function getPaymentStatusColor($status) {
|
|
return [
|
|
'unpaid' => 'danger',
|
|
'partially_paid' => 'warning',
|
|
'paid' => 'success',
|
|
][$status] ?? 'info';
|
|
}
|
|
require_once __DIR__ . '/includes/footer.php';
|
|
?>
|