Commit 5287a41a authored by Mahmoud Aglan's avatar Mahmoud Aglan

Fix fine distribution: proportionally split across subscription rows per year

Previously the year-level fine (e.g. 897 EGP) was stamped identically on
every row in the year, tripling the displayed fine. Now distributes
proportionally based on each row's total_amount relative to the year total.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 194da186
......@@ -31,12 +31,9 @@ final class OverdueFineApplicator
foreach ($calc['details'] as $detail) {
if (($detail['in_grace'] ?? false)) continue;
if (bccomp($detail['fine_amount'], '0', 2) <= 0) continue;
$db->query(
"UPDATE subscriptions SET fine_amount = ?, status = 'overdue', updated_at = NOW()
WHERE member_id = ? AND financial_year = ? AND status IN ('pending','overdue')",
[$detail['fine_amount'], $memberId, $detail['financial_year']]
);
self::distributeFineForYear($db, $memberId, $detail['financial_year'], $detail['fine_amount']);
}
if (bccomp($calc['total_fine'], '0', 2) > 0) {
......@@ -81,16 +78,44 @@ final class OverdueFineApplicator
if ($detail['in_grace'] ?? false) continue;
if (bccomp($detail['fine_amount'], '0', 2) <= 0) continue;
$db->query(
"UPDATE subscriptions SET fine_amount = ?, status = 'overdue', updated_at = NOW()
WHERE member_id = ? AND financial_year = ? AND status IN ('pending','overdue')",
[$detail['fine_amount'], $memberId, $detail['financial_year']]
);
self::distributeFineForYear($db, $memberId, $detail['financial_year'], $detail['fine_amount']);
}
return $calc;
}
private static function distributeFineForYear($db, int $memberId, string $financialYear, string $totalFine): void
{
$rows = $db->select(
"SELECT id, total_amount FROM subscriptions WHERE member_id = ? AND financial_year = ? AND status IN ('pending','overdue')",
[$memberId, $financialYear]
);
if (empty($rows)) return;
$yearTotal = '0.00';
foreach ($rows as $r) {
$yearTotal = bcadd($yearTotal, $r['total_amount'], 2);
}
$fineDistributed = '0.00';
$lastIdx = count($rows) - 1;
foreach ($rows as $idx => $r) {
if ($idx === $lastIdx) {
$rowFine = bcsub($totalFine, $fineDistributed, 2);
} else {
$rowFine = (bccomp($yearTotal, '0', 2) > 0)
? bcdiv(bcmul($r['total_amount'], $totalFine, 4), $yearTotal, 2)
: '0.00';
}
$fineDistributed = bcadd($fineDistributed, $rowFine, 2);
$db->query(
"UPDATE subscriptions SET fine_amount = ?, status = 'overdue', updated_at = NOW() WHERE id = ?",
[$rowFine, (int) $r['id']]
);
}
}
public static function expireReinstatements(): array
{
$db = App::getInstance()->db();
......
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