Commit cb2f1384 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix(retroactive): dispatch payment events to treasury and skip zero-amount installments

Retroactive payments now fire payment.completed event so DailyCashMovementService
records them in daily_cash_movements (treasury). Zero-amount installments (from
bad data where down_payment = total_amount) no longer create empty payment records.
Also simplifies overdue subscriptions section on member profile to a warning banner.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 28433036
...@@ -53,6 +53,7 @@ final class DailyCashMovementService ...@@ -53,6 +53,7 @@ final class DailyCashMovementService
if (bccomp($amount, '0', 2) <= 0) return; if (bccomp($amount, '0', 2) <= 0) return;
self::record([ self::record([
'movement_date' => $data['payment_date'] ?? date('Y-m-d'),
'movement_type' => 'collection', 'movement_type' => 'collection',
'direction' => 'in', 'direction' => 'in',
'amount' => $amount, 'amount' => $amount,
......
...@@ -526,6 +526,16 @@ final class RetroactiveMembershipService ...@@ -526,6 +526,16 @@ final class RetroactiveMembershipService
$db->update('payments', ['receipt_id' => $receiptId], '`id` = ?', [$paymentId]); $db->update('payments', ['receipt_id' => $receiptId], '`id` = ?', [$paymentId]);
EventBus::dispatch('payment.completed', [
'payment_id' => $paymentId,
'member_id' => $memberId,
'amount' => (string) $data['amount'],
'payment_type' => $data['payment_type'],
'payment_method' => $data['payment_method'] ?? 'cash',
'payment_date' => $paymentDate,
'receipt_number' => $receiptNumber,
]);
return $paymentId; return $paymentId;
} }
...@@ -627,6 +637,7 @@ final class RetroactiveMembershipService ...@@ -627,6 +637,7 @@ final class RetroactiveMembershipService
if ($isPaid) { if ($isPaid) {
$status = 'paid'; $status = 'paid';
$paidCount++; $paidCount++;
if (bccomp($item['amount'], '0', 2) > 0) {
$paymentId = self::createRetroactivePayment($memberId, [ $paymentId = self::createRetroactivePayment($memberId, [
'payment_type' => 'installment', 'payment_type' => 'installment',
'amount' => $item['amount'], 'amount' => $item['amount'],
...@@ -637,6 +648,7 @@ final class RetroactiveMembershipService ...@@ -637,6 +648,7 @@ final class RetroactiveMembershipService
'check_date' => $paid['check_date'] ?? null, 'check_date' => $paid['check_date'] ?? null,
'description' => "قسط رقم {$item['number']} — إدخال بأثر رجعي", 'description' => "قسط رقم {$item['number']} — إدخال بأثر رجعي",
]); ]);
}
} elseif (strtotime($item['due_date']) < time()) { } elseif (strtotime($item['due_date']) < time()) {
$status = 'overdue'; $status = 'overdue';
} }
......
...@@ -150,29 +150,12 @@ $canEdit = can('member.edit') && (!$isLocked || ($isSuperAdmin ?? false)); ...@@ -150,29 +150,12 @@ $canEdit = can('member.edit') && (!$isLocked || ($isSuperAdmin ?? false));
<!-- OVERDUE SUBSCRIPTIONS WARNING --> <!-- OVERDUE SUBSCRIPTIONS WARNING -->
<!-- ═══════════════════════════════════════════════ --> <!-- ═══════════════════════════════════════════════ -->
<?php if (!empty($overdueSubscriptions)): ?> <?php if (!empty($overdueSubscriptions)): ?>
<div class="card" style="margin-bottom:20px;padding:20px;background:#FEF2F2;border:1px solid #FECACA;"> <div class="card" style="margin-bottom:20px;padding:16px 20px;background:#FEF2F2;border:1px solid #FECACA;display:flex;align-items:center;justify-content:space-between;">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;"> <div style="display:flex;align-items:center;gap:10px;">
<span style="font-size:20px;">⚠️</span> <span style="font-size:18px;">⚠️</span>
<h3 style="margin:0;color:#DC2626;font-size:15px;">اشتراكات متأخرة — يجب السداد للتجديد</h3> <span style="font-weight:700;color:#DC2626;font-size:14px;">يوجد اشتراكات متأخرة يجب سدادها</span>
</div> </div>
<table style="width:100%;font-size:13px;border-collapse:collapse;"> <a href="/members/<?= (int) $member->id ?>/subscriptions" class="btn btn-sm" style="background:#DC2626;color:#fff;padding:6px 14px;border-radius:6px;font-size:12px;font-weight:600;text-decoration:none;">عرض الاشتراكات</a>
<thead><tr style="background:#FEE2E2;"><th style="padding:8px;text-align:right;">السنة المالية</th><th style="padding:8px;text-align:right;">المبلغ</th><th style="padding:8px;text-align:right;">المدفوع</th><th style="padding:8px;text-align:right;">الغرامة</th><th style="padding:8px;text-align:right;">المتبقي</th></tr></thead>
<tbody>
<?php $totalDue = '0.00'; foreach ($overdueSubscriptions as $sub):
$remaining = bcsub(bcadd($sub['total_amount'], $sub['fine_amount'] ?? '0', 2), $sub['paid_amount'] ?? '0', 2);
$totalDue = bcadd($totalDue, $remaining, 2);
?>
<tr>
<td style="padding:6px 8px;font-weight:600;"><?= e($sub['financial_year']) ?></td>
<td style="padding:6px 8px;"><?= number_format((float) $sub['total_amount'], 2) ?></td>
<td style="padding:6px 8px;"><?= number_format((float) ($sub['paid_amount'] ?? 0), 2) ?></td>
<td style="padding:6px 8px;color:#DC2626;"><?= number_format((float) ($sub['fine_amount'] ?? 0), 2) ?></td>
<td style="padding:6px 8px;font-weight:700;color:#DC2626;"><?= number_format((float) $remaining, 2) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot><tr style="border-top:2px solid #DC2626;"><td colspan="4" style="padding:8px;font-weight:700;">إجمالي المطلوب للتجديد</td><td style="padding:8px;font-weight:800;font-size:16px;color:#DC2626;"><?= number_format((float) $totalDue, 2) ?> ج.م</td></tr></tfoot>
</table>
</div> </div>
<?php endif; ?> <?php endif; ?>
......
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