Autosave: 20260420-172034

This commit is contained in:
Flatlogic Bot 2026-04-20 17:20:25 +00:00
parent 2f1d29f034
commit 554fd02f89
2 changed files with 77 additions and 12 deletions

View File

@ -4,9 +4,10 @@ $user = require_auth();
$activeNav = 'debts';
$pageTitle = tr('الديون والفواتير الآجلة', 'Debts & Unpaid Bills');
require_once 'includes/header.php';
$pdo = db();
$debtsLoadError = '';
$unpaidSales = [];
$debtsByCustomer = [];
// Handle Mark as Paid
if (isset($_GET['mark_paid'])) {
@ -20,17 +21,67 @@ if (isset($_GET['mark_paid'])) {
redirect_to('debts.php');
}
// Fetch all unpaid sales
$sqlUnpaid = "SELECT s.*, c.name as c_name, c.phone as c_phone
FROM sales_orders s
LEFT JOIN customers c ON s.customer_id = c.id
WHERE s.payment_status = 'unpaid'
ORDER BY s.sale_date DESC";
$stmtUnpaid = $pdo->query($sqlUnpaid);
$unpaidSales = $stmtUnpaid->fetchAll(PDO::FETCH_ASSOC);
try {
$salesColumns = [];
foreach ($pdo->query('SHOW COLUMNS FROM sales_orders')->fetchAll(PDO::FETCH_ASSOC) as $column) {
$salesColumns[$column['Field']] = true;
}
$hasCustomersTable = false;
$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
$debtsByCustomer = [];
foreach ($unpaidSales as $sale) {
$cId = $sale['customer_id'] ?? 'unknown';
if (!isset($debtsByCustomer[$cId])) {
@ -47,12 +98,20 @@ foreach ($unpaidSales as $sale) {
// Sort by highest debt
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">
<h1 class="h3 mb-0 text-gray-800"><?= h($pageTitle) ?></h1>
</div>
<?php if ($debtsLoadError !== ''): ?>
<div class="alert alert-warning" role="alert">
<?= h($debtsLoadError) ?>
</div>
<?php endif; ?>
<div class="row">
<!-- Debts by Customer -->
<div class="col-lg-4 mb-4">

View File

@ -28,6 +28,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$error = tr('اختر فرعاً صالحاً لهذه الصلاحية.', 'Choose a valid branch for this role.');
} elseif (!in_array($paymentMethod, ['cash', 'card', 'transfer', 'pay_later'], true)) {
$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) {
$error = tr('يجب اختيار عميل مسجل للدفع الآجل.', 'You must select a registered customer for pay later.');
} elseif (!is_array($items) || $items === []) {
@ -732,10 +734,14 @@ function updateTotals(total, vat) {
// Intercept form submission to check if items exist
document.getElementById('smart-sale-form').addEventListener('submit', function(e) {
const paymentMethod = document.querySelector('select[name="payment_method"]').value;
const saleStatus = document.querySelector('select[name="sale_status"]').value;
const customerId = document.getElementById('formCustomerId').value;
if (Object.keys(invoiceItems).length === 0) {
e.preventDefault();
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) {
e.preventDefault();
Swal.fire({icon: 'warning', text: '<?= h(tr('يجب اختيار عميل مسجل للدفع الآجل.', 'You must select a registered customer for pay later.')) ?>'});
@ -743,4 +749,4 @@ document.getElementById('smart-sale-form').addEventListener('submit', function(e
});
</script>
<?php require __DIR__ . '/footer.php'; ?>
<?php require __DIR__ . '/footer.php'; ?>