Autosave: 20260420-172034
This commit is contained in:
parent
2f1d29f034
commit
554fd02f89
81
debts.php
81
debts.php
@ -4,9 +4,10 @@ $user = require_auth();
|
|||||||
|
|
||||||
$activeNav = 'debts';
|
$activeNav = 'debts';
|
||||||
$pageTitle = tr('الديون والفواتير الآجلة', 'Debts & Unpaid Bills');
|
$pageTitle = tr('الديون والفواتير الآجلة', 'Debts & Unpaid Bills');
|
||||||
require_once 'includes/header.php';
|
|
||||||
|
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
$debtsLoadError = '';
|
||||||
|
$unpaidSales = [];
|
||||||
|
$debtsByCustomer = [];
|
||||||
|
|
||||||
// Handle Mark as Paid
|
// Handle Mark as Paid
|
||||||
if (isset($_GET['mark_paid'])) {
|
if (isset($_GET['mark_paid'])) {
|
||||||
@ -20,17 +21,67 @@ if (isset($_GET['mark_paid'])) {
|
|||||||
redirect_to('debts.php');
|
redirect_to('debts.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all unpaid sales
|
try {
|
||||||
$sqlUnpaid = "SELECT s.*, c.name as c_name, c.phone as c_phone
|
$salesColumns = [];
|
||||||
FROM sales_orders s
|
foreach ($pdo->query('SHOW COLUMNS FROM sales_orders')->fetchAll(PDO::FETCH_ASSOC) as $column) {
|
||||||
LEFT JOIN customers c ON s.customer_id = c.id
|
$salesColumns[$column['Field']] = true;
|
||||||
WHERE s.payment_status = 'unpaid'
|
}
|
||||||
ORDER BY s.sale_date DESC";
|
|
||||||
$stmtUnpaid = $pdo->query($sqlUnpaid);
|
$hasCustomersTable = false;
|
||||||
$unpaidSales = $stmtUnpaid->fetchAll(PDO::FETCH_ASSOC);
|
$customerColumns = [];
|
||||||
|
$customersTable = $pdo->query("SHOW TABLES LIKE 'customers'");
|
||||||
|
if ($customersTable && $customersTable->fetchColumn()) {
|
||||||
|
$hasCustomersTable = true;
|
||||||
|
foreach ($pdo->query('SHOW COLUMNS FROM customers')->fetchAll(PDO::FETCH_ASSOC) as $column) {
|
||||||
|
$customerColumns[$column['Field']] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$selectParts = [
|
||||||
|
's.id',
|
||||||
|
's.receipt_no',
|
||||||
|
's.sale_date',
|
||||||
|
's.total_amount',
|
||||||
|
isset($salesColumns['customer_id']) ? 's.customer_id' : 'NULL AS customer_id',
|
||||||
|
isset($salesColumns['customer_name']) ? 's.customer_name' : 'NULL AS customer_name',
|
||||||
|
'NULL AS c_name',
|
||||||
|
'NULL AS c_phone',
|
||||||
|
];
|
||||||
|
|
||||||
|
$joinSql = '';
|
||||||
|
if ($hasCustomersTable && isset($salesColumns['customer_id']) && isset($customerColumns['id'])) {
|
||||||
|
$joinSql = ' LEFT JOIN customers c ON s.customer_id = c.id ';
|
||||||
|
if (isset($customerColumns['name'])) {
|
||||||
|
$selectParts[6] = 'c.name AS c_name';
|
||||||
|
}
|
||||||
|
if (isset($customerColumns['phone'])) {
|
||||||
|
$selectParts[7] = 'c.phone AS c_phone';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($salesColumns['payment_status'])) {
|
||||||
|
$whereSql = " WHERE s.payment_status = 'unpaid'";
|
||||||
|
} elseif (isset($salesColumns['payment_method'])) {
|
||||||
|
$whereSql = " WHERE s.payment_method = 'pay_later'";
|
||||||
|
} else {
|
||||||
|
$whereSql = ' WHERE 1 = 0';
|
||||||
|
}
|
||||||
|
|
||||||
|
$sqlUnpaid = 'SELECT ' . implode(', ', $selectParts)
|
||||||
|
. ' FROM sales_orders s'
|
||||||
|
. $joinSql
|
||||||
|
. $whereSql
|
||||||
|
. ' ORDER BY s.sale_date DESC';
|
||||||
|
$stmtUnpaid = $pdo->query($sqlUnpaid);
|
||||||
|
$unpaidSales = $stmtUnpaid ? $stmtUnpaid->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$debtsLoadError = tr(
|
||||||
|
'تعذر تحميل صفحة الديون بسبب اختلاف في هيكل قاعدة البيانات. احفظ التعديلات ثم أنشئ نسخة جديدة وأعد التحديث.',
|
||||||
|
'The debts page could not load because the deployed database schema is older than the current code. Save these changes, create a new version, then refresh the page.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Aggregate by customer
|
// Aggregate by customer
|
||||||
$debtsByCustomer = [];
|
|
||||||
foreach ($unpaidSales as $sale) {
|
foreach ($unpaidSales as $sale) {
|
||||||
$cId = $sale['customer_id'] ?? 'unknown';
|
$cId = $sale['customer_id'] ?? 'unknown';
|
||||||
if (!isset($debtsByCustomer[$cId])) {
|
if (!isset($debtsByCustomer[$cId])) {
|
||||||
@ -47,12 +98,20 @@ foreach ($unpaidSales as $sale) {
|
|||||||
|
|
||||||
// Sort by highest debt
|
// Sort by highest debt
|
||||||
uasort($debtsByCustomer, fn($a, $b) => $b['total'] <=> $a['total']);
|
uasort($debtsByCustomer, fn($a, $b) => $b['total'] <=> $a['total']);
|
||||||
|
|
||||||
|
require_once 'includes/header.php';
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<h1 class="h3 mb-0 text-gray-800"><?= h($pageTitle) ?></h1>
|
<h1 class="h3 mb-0 text-gray-800"><?= h($pageTitle) ?></h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if ($debtsLoadError !== ''): ?>
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
<?= h($debtsLoadError) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- Debts by Customer -->
|
<!-- Debts by Customer -->
|
||||||
<div class="col-lg-4 mb-4">
|
<div class="col-lg-4 mb-4">
|
||||||
|
|||||||
@ -28,6 +28,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$error = tr('اختر فرعاً صالحاً لهذه الصلاحية.', 'Choose a valid branch for this role.');
|
$error = tr('اختر فرعاً صالحاً لهذه الصلاحية.', 'Choose a valid branch for this role.');
|
||||||
} elseif (!in_array($paymentMethod, ['cash', 'card', 'transfer', 'pay_later'], true)) {
|
} elseif (!in_array($paymentMethod, ['cash', 'card', 'transfer', 'pay_later'], true)) {
|
||||||
$error = tr('اختر طريقة دفع صحيحة.', 'Choose a valid payment method.');
|
$error = tr('اختر طريقة دفع صحيحة.', 'Choose a valid payment method.');
|
||||||
|
} elseif ($saleStatus === 'order' && !$customerId) {
|
||||||
|
$error = tr('يجب اختيار عميل للطلب المسبق.', 'You must select a customer for a pre-order.');
|
||||||
} elseif ($paymentMethod === 'pay_later' && !$customerId) {
|
} elseif ($paymentMethod === 'pay_later' && !$customerId) {
|
||||||
$error = tr('يجب اختيار عميل مسجل للدفع الآجل.', 'You must select a registered customer for pay later.');
|
$error = tr('يجب اختيار عميل مسجل للدفع الآجل.', 'You must select a registered customer for pay later.');
|
||||||
} elseif (!is_array($items) || $items === []) {
|
} elseif (!is_array($items) || $items === []) {
|
||||||
@ -732,10 +734,14 @@ function updateTotals(total, vat) {
|
|||||||
// Intercept form submission to check if items exist
|
// Intercept form submission to check if items exist
|
||||||
document.getElementById('smart-sale-form').addEventListener('submit', function(e) {
|
document.getElementById('smart-sale-form').addEventListener('submit', function(e) {
|
||||||
const paymentMethod = document.querySelector('select[name="payment_method"]').value;
|
const paymentMethod = document.querySelector('select[name="payment_method"]').value;
|
||||||
|
const saleStatus = document.querySelector('select[name="sale_status"]').value;
|
||||||
const customerId = document.getElementById('formCustomerId').value;
|
const customerId = document.getElementById('formCustomerId').value;
|
||||||
if (Object.keys(invoiceItems).length === 0) {
|
if (Object.keys(invoiceItems).length === 0) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Swal.fire({icon: 'warning', text: '<?= h(tr('الرجاء إضافة أصناف للفاتورة أولاً.', 'Please add items to the invoice first.')) ?>'});
|
Swal.fire({icon: 'warning', text: '<?= h(tr('الرجاء إضافة أصناف للفاتورة أولاً.', 'Please add items to the invoice first.')) ?>'});
|
||||||
|
} else if (saleStatus === 'order' && !customerId) {
|
||||||
|
e.preventDefault();
|
||||||
|
Swal.fire({icon: 'warning', text: '<?= h(tr('يجب اختيار عميل للطلب المسبق.', 'You must select a customer for a pre-order.')) ?>'});
|
||||||
} else if (paymentMethod === 'pay_later' && !customerId) {
|
} else if (paymentMethod === 'pay_later' && !customerId) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Swal.fire({icon: 'warning', text: '<?= h(tr('يجب اختيار عميل مسجل للدفع الآجل.', 'You must select a registered customer for pay later.')) ?>'});
|
Swal.fire({icon: 'warning', text: '<?= h(tr('يجب اختيار عميل مسجل للدفع الآجل.', 'You must select a registered customer for pay later.')) ?>'});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user