Commit 6beb4544 authored by Mahmoud Aglan's avatar Mahmoud Aglan

feat(installments): business-intelligence show page + recalculate action

- Complete rewrite of show.php: 6 KPI cards (original amount, down payment,
  remaining balance, interest, monthly payment, member's outstanding balance),
  progress bar showing paid vs total installments, financial breakdown panels
  (paid vs remaining split), grand total formula ribbon, overdue alerts,
  next-due-date card with countdown, enhanced schedule table with status
  highlighting and per-row pay forms
- Add recalculate() action to InstallmentController: corrects pending-only
  installment rows to flat simple-interest formula without touching paid rows
- Register POST /installments/{id}/recalculate route
Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
parent 58084696
...@@ -173,6 +173,107 @@ class InstallmentController extends Controller ...@@ -173,6 +173,107 @@ class InstallmentController extends Controller
); );
} }
/**
* Recalculate pending installments using the correct flat simple-interest formula.
* Paid rows are left untouched; only pending rows and plan header are corrected.
*/
public function recalculate(Request $request, string $id): Response
{
$this->authorize('installment.create_plan');
$db = App::getInstance()->db();
$plan = $db->selectOne("SELECT * FROM installment_plans WHERE id = ?", [(int) $id]);
if (!$plan) return $this->redirect('/installments')->withError('الخطة غير موجودة');
if ($plan['status'] === 'completed') {
return $this->redirect("/installments/{$id}")->withError('الخطة مكتملة — لا يمكن إعادة الحساب');
}
$totalAmount = $plan['total_amount'];
$downPayment = $plan['down_payment'];
$remaining = bcsub($totalAmount, $downPayment, 2);
$months = (int) $plan['number_of_months'];
$rate = $plan['interest_rate'];
if (bccomp($remaining, '0', 2) <= 0 || $months < 1) {
return $this->redirect("/installments/{$id}")->withError('بيانات الخطة غير صالحة للحساب');
}
// Flat simple interest: remaining × (rate/100) × (months/12)
$correctTotalInterest = bcmul(
bcmul($remaining, bcdiv($rate, '100', 10), 10),
bcdiv((string) $months, '12', 10),
2
);
$correctTotalWI = bcadd($remaining, $correctTotalInterest, 2);
$flatMonthly = bcdiv($correctTotalWI, (string) $months, 2);
$flatPrincipal = bcdiv($remaining, (string) $months, 2);
$flatInterest = bcdiv($correctTotalInterest, (string) $months, 2);
$pendingRows = $db->select(
"SELECT id, installment_number FROM installment_schedule
WHERE installment_plan_id = ? AND status = 'pending'
ORDER BY installment_number ASC",
[(int) $id]
);
if (empty($pendingRows)) {
return $this->redirect("/installments/{$id}")->withError('لا توجد أقساط معلقة لإعادة حسابها');
}
// Compute running balance after all paid rows
$paidPrincipalSum = $db->selectOne(
"SELECT COALESCE(SUM(principal), 0) as s FROM installment_schedule
WHERE installment_plan_id = ? AND status = 'paid'",
[(int) $id]
);
$runningBalance = bcsub($remaining, (string) ($paidPrincipalSum['s'] ?? '0'), 2);
if (bccomp($runningBalance, '0', 2) < 0) $runningBalance = '0.00';
$db->beginTransaction();
try {
$pendingCount = count($pendingRows);
foreach ($pendingRows as $idx => $row) {
$isLast = ($idx === $pendingCount - 1);
$principal = $isLast ? $runningBalance : $flatPrincipal;
// Last row absorbs rounding in interest too
$interest = $isLast
? bcsub($correctTotalInterest, bcmul($flatInterest, (string) ($pendingCount - 1), 2), 2)
: $flatInterest;
if (bccomp($interest, '0', 2) < 0) $interest = '0.00';
$amount = bcadd($principal, $interest, 2);
$runningBalance = bcsub($runningBalance, $principal, 2);
if (bccomp($runningBalance, '0', 2) < 0) $runningBalance = '0.00';
$db->update('installment_schedule', [
'amount' => $amount,
'principal' => $principal,
'interest' => $interest,
'remaining_after' => $runningBalance,
'updated_at' => date('Y-m-d H:i:s'),
], '`id` = ?', [(int) $row['id']]);
}
// Update plan header
$db->update('installment_plans', [
'remaining_balance' => bcsub($remaining, (string) ($paidPrincipalSum['s'] ?? '0'), 2),
'total_interest' => $correctTotalInterest,
'total_with_interest' => $correctTotalWI,
'monthly_payment' => $flatMonthly,
'updated_at' => date('Y-m-d H:i:s'),
], '`id` = ?', [(int) $id]);
$db->commit();
} catch (\Throwable $e) {
$db->rollBack();
return $this->redirect("/installments/{$id}")->withError('خطأ أثناء إعادة الحساب: ' . $e->getMessage());
}
return $this->redirect("/installments/{$id}")->withSuccess(
'تمت إعادة الحساب — ' . $pendingCount . ' قسط تم تصحيحه | القسط الشهري الصحيح: ' . money($flatMonthly)
);
}
public function payInstallment(Request $request, string $planId, string $scheduleId): Response public function payInstallment(Request $request, string $planId, string $scheduleId): Response
{ {
$db = App::getInstance()->db(); $db = App::getInstance()->db();
......
...@@ -7,6 +7,7 @@ return [ ...@@ -7,6 +7,7 @@ return [
['POST', '/installments/store/{memberId}', 'Installments\Controllers\InstallmentController@store', ['auth', 'csrf'], 'installment.create_plan'], ['POST', '/installments/store/{memberId}', 'Installments\Controllers\InstallmentController@store', ['auth', 'csrf'], 'installment.create_plan'],
['GET', '/installments/{id}', 'Installments\Controllers\InstallmentController@show', ['auth'], 'installment.view'], ['GET', '/installments/{id}', 'Installments\Controllers\InstallmentController@show', ['auth'], 'installment.view'],
['POST', '/installments/{planId}/pay/{scheduleId}', 'Installments\Controllers\InstallmentController@payInstallment', ['auth', 'csrf'], 'installment.pay'], ['POST', '/installments/{planId}/pay/{scheduleId}', 'Installments\Controllers\InstallmentController@payInstallment', ['auth', 'csrf'], 'installment.pay'],
['POST', '/installments/{id}/recalculate', 'Installments\Controllers\InstallmentController@recalculate', ['auth', 'csrf'], 'installment.create_plan'],
// Cheque uploads // Cheque uploads
['GET', '/installments/{planId}/cheques', 'Installments\Controllers\ChequeController@index', ['auth'], 'installment.view'], ['GET', '/installments/{planId}/cheques', 'Installments\Controllers\ChequeController@index', ['auth'], 'installment.view'],
......
<?php $__template->layout('Layout.main'); ?> <?php $__template->layout('Layout.main'); ?>
<?php $__template->section('title'); ?>خطة تقسيط #<?= (int) $plan['id'] ?><?php $__template->endSection(); ?> <?php $__template->section('title'); ?>خطة تقسيط #<?= (int) $plan['id'] ?><?php $__template->endSection(); ?>
<?php $__template->section('page_actions'); ?> <?php $__template->section('page_actions'); ?>
<a href="/installments/<?= (int) $plan['id'] ?>/cheques" class="btn btn-primary"><i data-lucide="file-check" style="width:16px;height:16px;vertical-align:middle;margin-left:4px;"></i> شيكات الأقساط</a> <?php if (can('installment.create_plan') && $plan['status'] === 'active'): ?>
<form method="POST" action="/installments/<?= (int) $plan['id'] ?>/recalculate" style="display:inline;">
<?= csrf_field() ?>
<button type="submit" class="btn btn-outline"
style="border-color:#D97706;color:#D97706;"
onclick="return confirm('إعادة حساب الأقساط المعلقة بالصيغة الصحيحة (فائدة بسيطة مسطحة)؟')">
🔄 إعادة الحساب
</button>
</form>
<?php endif; ?>
<a href="/installments/<?= (int) $plan['id'] ?>/cheques" class="btn btn-primary">
<i data-lucide="file-check" style="width:16px;height:16px;vertical-align:middle;margin-left:4px;"></i> شيكات الأقساط
</a>
<a href="/members/<?= (int) $plan['member_id'] ?>" class="btn btn-outline">← العضو</a> <a href="/members/<?= (int) $plan['member_id'] ?>" class="btn btn-outline">← العضو</a>
<a href="/installments" class="btn btn-outline">← كل الأقساط</a> <a href="/installments" class="btn btn-outline">← كل الأقساط</a>
<?php $__template->endSection(); ?> <?php $__template->endSection(); ?>
<?php $__template->section('content'); ?> <?php $__template->section('content'); ?>
<!-- Plan Summary --> <?php
<div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));gap:15px;margin-bottom:20px;"> // ─── Derived KPIs ────────────────────────────────────────────────────────────
<div class="card" style="padding:15px;text-align:center;border-right:4px solid #0D7377;"> $totalAmount = (float) $plan['total_amount'];
<div style="font-size:20px;font-weight:700;color:#0D7377;"><?= money($plan['total_amount']) ?></div> $downPayment = (float) $plan['down_payment'];
<div style="font-size:11px;color:#6B7280;">المبلغ الأصلي</div> $remainingBalance = (float) $plan['remaining_balance']; // total - down
$interestRate = (float) $plan['interest_rate'];
$months = (int) $plan['number_of_months'];
$totalInterest = (float) $plan['total_interest'];
$totalWithInterest = (float) $plan['total_with_interest'];
$monthlyPayment = (float) $plan['monthly_payment'];
// Recompute correct flat formula for display verification
$correctInterest = round($remainingBalance * ($interestRate / 100) * ($months / 12), 2);
$correctTotalWI = round($remainingBalance + $correctInterest, 2);
$correctMonthly = $months > 0 ? round($correctTotalWI / $months, 2) : 0;
// Schedule aggregates
$paidCount = 0;
$pendingCount = 0;
$overdueCount = 0;
$paidPrincipal = 0.0;
$paidInterest = 0.0;
$paidTotal = 0.0;
$nextDueDate = null;
$nextDueAmount = null;
$today = date('Y-m-d');
foreach ($schedule as $s) {
if ($s['status'] === 'paid') {
$paidCount++;
$paidPrincipal += (float) $s['principal'];
$paidInterest += (float) $s['interest'];
$paidTotal += (float) $s['paid_amount'];
} else {
$pendingCount++;
if ($s['due_date'] < $today) {
$overdueCount++;
}
if ($nextDueDate === null) {
$nextDueDate = $s['due_date'];
$nextDueAmount = (float) $s['amount'];
}
}
}
$progressPct = $months > 0 ? round($paidCount / $months * 100) : 0;
$remainingPrincipal = round($remainingBalance - $paidPrincipal, 2);
$remainingInstallAmt = round(max(0, $correctTotalWI - $paidTotal), 2);
$totalPaidIncDownPmt = round($downPayment + $paidTotal, 2);
$grandTotalFinanced = round($downPayment + $correctTotalWI, 2);
$memberOwes = round($grandTotalFinanced - $totalPaidIncDownPmt, 2);
$statusColor = match($plan['status']) {
'active' => '#059669',
'completed' => '#0284C7',
default => '#6B7280',
};
$statusLabel = match($plan['status']) {
'active' => '● نشط',
'completed' => '✅ مكتمل',
default => e($plan['status']),
};
?>
<!-- ═══ ROW 1: Plan identity + progress ══════════════════════════════════════ -->
<div style="display:grid;grid-template-columns:1fr auto;gap:16px;margin-bottom:16px;align-items:start;">
<div class="card" style="padding:18px 22px;">
<div style="display:flex;align-items:center;gap:16px;flex-wrap:wrap;">
<div>
<div style="font-size:13px;color:#6B7280;margin-bottom:2px;">العضو</div>
<div style="font-size:17px;font-weight:700;color:#111827;"><?= e($plan['member_name']) ?></div>
<div style="font-size:12px;color:#6B7280;"><?= e($plan['membership_number'] ?? '—') ?></div>
</div> </div>
<div class="card" style="padding:15px;text-align:center;border-right:4px solid #059669;"> <div style="width:1px;height:48px;background:#E5E7EB;"></div>
<div style="font-size:20px;font-weight:700;color:#059669;"><?= money($plan['down_payment']) ?></div> <div>
<div style="font-size:11px;color:#6B7280;">المقدم</div> <div style="font-size:13px;color:#6B7280;margin-bottom:2px;">تاريخ البداية</div>
<div style="font-size:15px;font-weight:600;"><?= e($plan['start_date']) ?></div>
</div> </div>
<div class="card" style="padding:15px;text-align:center;border-right:4px solid #D97706;"> <div style="width:1px;height:48px;background:#E5E7EB;"></div>
<div style="font-size:20px;font-weight:700;color:#D97706;"><?= money($plan['total_interest']) ?></div> <div>
<div style="font-size:11px;color:#6B7280;">الفائدة (<?= e($plan['interest_rate']) ?>%)</div> <div style="font-size:13px;color:#6B7280;margin-bottom:2px;">المدة</div>
<div style="font-size:15px;font-weight:600;"><?= $months ?> شهر</div>
</div> </div>
<div class="card" style="padding:15px;text-align:center;border-right:4px solid #0284C7;"> <div style="width:1px;height:48px;background:#E5E7EB;"></div>
<div style="font-size:20px;font-weight:700;color:#0284C7;"><?= money($plan['monthly_payment']) ?></div> <div>
<div style="font-size:11px;color:#6B7280;">القسط الشهري</div> <div style="font-size:13px;color:#6B7280;margin-bottom:2px;">الحالة</div>
<div style="font-size:15px;font-weight:700;color:<?= $statusColor ?>;"><?= $statusLabel ?></div>
</div> </div>
<div class="card" style="padding:15px;text-align:center;border-right:4px solid <?= $plan['status'] === 'active' ? '#059669' : '#6B7280' ?>;"> <?php if ($overdueCount > 0): ?>
<div style="font-size:20px;font-weight:700;color:<?= $plan['status'] === 'active' ? '#059669' : '#6B7280' ?>;"> <div style="width:1px;height:48px;background:#E5E7EB;"></div>
<?= $plan['status'] === 'active' ? '● نشط' : ($plan['status'] === 'completed' ? '✅ مكتمل' : $plan['status']) ?> <div style="background:#FEF2F2;border:1px solid #FECACA;border-radius:8px;padding:8px 14px;">
<div style="font-size:12px;color:#DC2626;font-weight:700;">⚠️ <?= $overdueCount ?> قسط متأخر</div>
<div style="font-size:11px;color:#991B1B;">يستوجب السداد فوراً</div>
</div> </div>
<div style="font-size:11px;color:#6B7280;">الحالة</div> <?php endif; ?>
</div>
<!-- Progress bar -->
<div style="margin-top:14px;">
<div style="display:flex;justify-content:space-between;font-size:12px;color:#6B7280;margin-bottom:5px;">
<span>التقدم: <?= $paidCount ?> / <?= $months ?> قسط مدفوع</span>
<span style="font-weight:700;color:<?= $statusColor ?>;"><?= $progressPct ?>%</span>
</div>
<div style="background:#E5E7EB;border-radius:99px;height:10px;overflow:hidden;">
<div style="height:100%;background:<?= $progressPct === 100 ? '#0284C7' : ($overdueCount > 0 ? '#DC2626' : '#059669') ?>;width:<?= $progressPct ?>%;transition:width 0.4s;border-radius:99px;"></div>
</div>
</div>
</div>
<?php if ($nextDueDate && $plan['status'] === 'active'): ?>
<div class="card" style="padding:18px 22px;text-align:center;border-top:4px solid <?= $overdueCount > 0 ? '#DC2626' : '#0284C7' ?>;min-width:170px;">
<div style="font-size:11px;color:#6B7280;margin-bottom:4px;">القسط التالي</div>
<div style="font-size:22px;font-weight:800;color:<?= $overdueCount > 0 ? '#DC2626' : '#0284C7' ?>;"><?= money($nextDueAmount) ?></div>
<div style="font-size:13px;color:#374151;margin-top:4px;font-weight:600;"><?= e($nextDueDate) ?></div>
<?php if ($nextDueDate < $today): ?>
<div style="font-size:11px;color:#DC2626;margin-top:4px;font-weight:700;">⚠️ متأخر</div>
<?php else: ?>
<?php $daysLeft = (int) round((strtotime($nextDueDate) - strtotime($today)) / 86400); ?>
<div style="font-size:11px;color:#6B7280;margin-top:4px;"><?= $daysLeft ?> يوم متبقي</div>
<?php endif; ?>
</div> </div>
<?php endif; ?>
</div> </div>
<!-- Schedule Table --> <!-- ═══ ROW 2: 6 KPI cards ═══════════════════════════════════════════════════ -->
<div style="display:grid;grid-template-columns:repeat(6,1fr);gap:12px;margin-bottom:16px;">
<div class="card" style="padding:14px 16px;text-align:center;border-right:4px solid #0D7377;">
<div style="font-size:11px;color:#6B7280;margin-bottom:4px;">المبلغ الأصلي</div>
<div style="font-size:17px;font-weight:800;color:#0D7377;"><?= money($totalAmount) ?></div>
</div>
<div class="card" style="padding:14px 16px;text-align:center;border-right:4px solid #059669;">
<div style="font-size:11px;color:#6B7280;margin-bottom:4px;">المقدم</div>
<div style="font-size:17px;font-weight:800;color:#059669;"><?= money($downPayment) ?></div>
</div>
<div class="card" style="padding:14px 16px;text-align:center;border-right:4px solid #7C3AED;">
<div style="font-size:11px;color:#6B7280;margin-bottom:4px;">المبلغ المتبقي بعد المقدم</div>
<div style="font-size:17px;font-weight:800;color:#7C3AED;"><?= money($remainingBalance) ?></div>
<div style="font-size:10px;color:#9CA3AF;margin-top:2px;"><?= money($totalAmount) ?><?= money($downPayment) ?></div>
</div>
<div class="card" style="padding:14px 16px;text-align:center;border-right:4px solid #D97706;">
<div style="font-size:11px;color:#6B7280;margin-bottom:4px;">الفائدة (<?= $interestRate ?>% × <?= $months ?> شهر)</div>
<div style="font-size:17px;font-weight:800;color:#D97706;"><?= money($correctInterest) ?></div>
<div style="font-size:10px;color:#9CA3AF;margin-top:2px;"><?= money($remainingBalance) ?> × <?= $interestRate ?>% × <?= $months ?>/12</div>
</div>
<div class="card" style="padding:14px 16px;text-align:center;border-right:4px solid #0284C7;">
<div style="font-size:11px;color:#6B7280;margin-bottom:4px;">القسط الشهري</div>
<div style="font-size:17px;font-weight:800;color:#0284C7;"><?= money($correctMonthly) ?></div>
<div style="font-size:10px;color:#9CA3AF;margin-top:2px;"><?= money($correctTotalWI) ?> ÷ <?= $months ?></div>
</div>
<div class="card" style="padding:14px 16px;text-align:center;border-right:4px solid <?= $memberOwes > 0 ? '#DC2626' : '#059669' ?>;">
<div style="font-size:11px;color:#6B7280;margin-bottom:4px;">المتبقي على العضو</div>
<div style="font-size:17px;font-weight:800;color:<?= $memberOwes > 0 ? '#DC2626' : '#059669' ?>;"><?= money($memberOwes) ?></div>
<div style="font-size:10px;color:#9CA3AF;margin-top:2px;"><?= $pendingCount ?> قسط متبقي</div>
</div>
</div>
<!-- ═══ ROW 3: Financial breakdown ═══════════════════════════════════════════ -->
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px;">
<!-- Paid summary -->
<div class="card" style="padding:16px 20px;">
<div style="font-size:13px;font-weight:700;color:#374151;margin-bottom:12px;border-bottom:1px solid #F3F4F6;padding-bottom:8px;">
✅ ما تم سداده
</div>
<table style="width:100%;font-size:13px;border-collapse:collapse;">
<tr style="border-bottom:1px solid #F9FAFB;">
<td style="padding:5px 0;color:#6B7280;">المقدم</td>
<td style="text-align:left;font-weight:600;"><?= money($downPayment) ?></td>
</tr>
<tr style="border-bottom:1px solid #F9FAFB;">
<td style="padding:5px 0;color:#6B7280;">أصل الدين المسدد (<?= $paidCount ?> قسط)</td>
<td style="text-align:left;font-weight:600;"><?= money($paidPrincipal) ?></td>
</tr>
<tr style="border-bottom:1px solid #F9FAFB;">
<td style="padding:5px 0;color:#6B7280;">فوائد مسددة</td>
<td style="text-align:left;font-weight:600;color:#D97706;"><?= money($paidInterest) ?></td>
</tr>
<tr>
<td style="padding:5px 0;font-weight:700;color:#111827;">إجمالي المسدد</td>
<td style="text-align:left;font-weight:800;color:#059669;font-size:15px;"><?= money($totalPaidIncDownPmt) ?></td>
</tr>
</table>
</div>
<!-- Remaining summary -->
<div class="card" style="padding:16px 20px;">
<div style="font-size:13px;font-weight:700;color:#374151;margin-bottom:12px;border-bottom:1px solid #F3F4F6;padding-bottom:8px;">
⏳ ما تبقى
</div>
<table style="width:100%;font-size:13px;border-collapse:collapse;">
<tr style="border-bottom:1px solid #F9FAFB;">
<td style="padding:5px 0;color:#6B7280;">أصل الدين المتبقي</td>
<td style="text-align:left;font-weight:600;"><?= money($remainingPrincipal) ?></td>
</tr>
<tr style="border-bottom:1px solid #F9FAFB;">
<td style="padding:5px 0;color:#6B7280;">عدد الأقساط المتبقية</td>
<td style="text-align:left;font-weight:600;"><?= $pendingCount ?> قسط</td>
</tr>
<?php if ($overdueCount > 0): ?>
<tr style="border-bottom:1px solid #F9FAFB;">
<td style="padding:5px 0;color:#DC2626;font-weight:700;">أقساط متأخرة</td>
<td style="text-align:left;font-weight:700;color:#DC2626;"><?= $overdueCount ?> قسط ⚠️</td>
</tr>
<?php endif; ?>
<tr>
<td style="padding:5px 0;font-weight:700;color:#111827;">إجمالي المتبقي</td>
<td style="text-align:left;font-weight:800;color:#DC2626;font-size:15px;"><?= money($memberOwes) ?></td>
</tr>
</table>
</div>
</div>
<!-- ═══ ROW 4: Grand total ribbon ════════════════════════════════════════════ -->
<div class="card" style="padding:14px 22px;margin-bottom:16px;background:linear-gradient(135deg,#EFF6FF,#F0FDF4);border:1px solid #93C5FD;">
<div style="display:flex;flex-wrap:wrap;gap:24px;align-items:center;justify-content:space-between;font-size:13px;">
<span><?= money($totalAmount) ?> <span style="color:#6B7280;">سعر العضوية</span></span>
<span style="color:#6B7280;"></span>
<span><?= money($downPayment) ?> <span style="color:#6B7280;">مقدم</span></span>
<span style="color:#6B7280;">+</span>
<span><?= money($correctInterest) ?> <span style="color:#D97706;">فائدة <?= $interestRate ?>% / <?= $months ?> شهر</span></span>
<span style="color:#6B7280;">=</span>
<span style="font-size:16px;font-weight:800;color:#1E40AF;"><?= money($grandTotalFinanced) ?> <span style="font-size:12px;font-weight:400;color:#6B7280;">إجمالي التمويل</span></span>
</div>
</div>
<!-- ═══ Schedule Table ════════════════════════════════════════════════════════ -->
<div class="card"> <div class="card">
<div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;"> <div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;display:flex;justify-content:space-between;align-items:center;">
<h3 style="margin:0;color:#0D7377;">📅 جدول الأقساط (<?= (int) $plan['number_of_months'] ?> شهر)</h3> <h3 style="margin:0;color:#0D7377;">
📅 جدول الأقساط (<?= $months ?> شهر)
</h3>
<div style="font-size:12px;color:#6B7280;">
<span style="display:inline-block;width:10px;height:10px;background:#F0FDF4;border:1px solid #86EFAC;border-radius:2px;margin-left:4px;"></span>مدفوع
<span style="display:inline-block;width:10px;height:10px;background:#FEF2F2;border:1px solid #FECACA;border-radius:2px;margin-right:8px;margin-left:4px;"></span>متأخر
</div>
</div> </div>
<div class="table-responsive"> <div class="table-responsive">
<table class="data-table"> <table class="data-table">
<thead> <thead>
<tr><th>#</th><th>تاريخ الاستحقاق</th><th>المبلغ</th><th>أصل الدين</th><th>الفائدة</th><th>المتبقي</th><th>الحالة</th><th>الإجراءات</th></tr> <tr>
<th>#</th>
<th>تاريخ الاستحقاق</th>
<th>المبلغ</th>
<th>أصل الدين</th>
<th>الفائدة</th>
<th>المتبقي بعده</th>
<th>الحالة</th>
<th>الإجراءات</th>
</tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($schedule as $s): ?> <?php foreach ($schedule as $s): ?>
<?php <?php
$isOverdue = ($s['status'] === 'pending' && $s['due_date'] < date('Y-m-d')); $isOverdue = ($s['status'] === 'pending' && $s['due_date'] < $today);
$isPaid = ($s['status'] === 'paid'); $isPaid = ($s['status'] === 'paid');
$rowBg = $isPaid ? 'background:#F0FDF4;' : ($isOverdue ? 'background:#FEF2F2;' : '');
?> ?>
<tr style="<?= $isOverdue ? 'background:#FEF2F2;' : '' ?><?= $isPaid ? 'background:#F0FDF4;' : '' ?>"> <tr style="<?= $rowBg ?>">
<td style="font-weight:600;"><?= (int) $s['installment_number'] ?></td> <td style="font-weight:600;"><?= (int) $s['installment_number'] ?></td>
<td style="white-space:nowrap;<?= $isOverdue ? 'color:#DC2626;font-weight:700;' : '' ?>"><?= e($s['due_date']) ?></td> <td style="white-space:nowrap;<?= $isOverdue ? 'color:#DC2626;font-weight:700;' : '' ?>">
<?= e($s['due_date']) ?>
</td>
<td style="font-weight:600;"><?= money($s['amount']) ?></td> <td style="font-weight:600;"><?= money($s['amount']) ?></td>
<td style="font-size:13px;"><?= money($s['principal']) ?></td> <td style="font-size:13px;"><?= money($s['principal']) ?></td>
<td style="font-size:13px;color:#D97706;"><?= money($s['interest']) ?></td> <td style="font-size:13px;color:#D97706;"><?= money($s['interest']) ?></td>
<td style="font-size:13px;"><?= money($s['remaining_after']) ?></td> <td style="font-size:13px;color:#6B7280;"><?= money($s['remaining_after']) ?></td>
<td> <td>
<?php if ($isPaid): ?> <?php if ($isPaid): ?>
<span style="color:#059669;font-weight:700;">✅ مدفوع</span> <span style="color:#059669;font-weight:700;">✅ مدفوع</span>
...@@ -73,9 +309,12 @@ ...@@ -73,9 +309,12 @@
<input type="hidden" name="amount" value="<?= e($s['amount']) ?>"> <input type="hidden" name="amount" value="<?= e($s['amount']) ?>">
<select name="payment_method" class="form-select" style="width:auto;font-size:11px;padding:3px 6px;"> <select name="payment_method" class="form-select" style="width:auto;font-size:11px;padding:3px 6px;">
<option value="cash">نقدي</option> <option value="cash">نقدي</option>
<option value="check">شيك</option>
<option value="visa">فيزا</option> <option value="visa">فيزا</option>
<option value="bank_transfer">تحويل</option>
</select> </select>
<button type="submit" class="btn btn-sm btn-primary" onclick="return confirm('دفع قسط <?= money($s['amount']) ?>؟')">💰 ادفع</button> <button type="submit" class="btn btn-sm btn-primary"
onclick="return confirm('دفع قسط <?= money($s['amount']) ?>؟')">💰 ادفع</button>
</form> </form>
<?php elseif ($isPaid): ?> <?php elseif ($isPaid): ?>
<span style="font-size:11px;color:#9CA3AF;"></span> <span style="font-size:11px;color:#9CA3AF;"></span>
...@@ -84,6 +323,15 @@ ...@@ -84,6 +323,15 @@
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
<tfoot>
<tr style="background:#F9FAFB;font-weight:700;font-size:13px;">
<td colspan="2" style="padding:8px 12px;color:#374151;">الإجماليات</td>
<td style="padding:8px 12px;"><?= money(array_sum(array_column($schedule, 'amount'))) ?></td>
<td style="padding:8px 12px;"><?= money(array_sum(array_column($schedule, 'principal'))) ?></td>
<td style="padding:8px 12px;color:#D97706;"><?= money(array_sum(array_column($schedule, 'interest'))) ?></td>
<td colspan="3"></td>
</tr>
</tfoot>
</table> </table>
</div> </div>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment