Commit 2c199906 authored by Mahmoud Aglan's avatar Mahmoud Aglan

Include development fee in paid_amount for all payment paths

When a subscription year is marked as paid, the member row's paid_amount
must include the 35 EGP dev fee (single flat charge per family). Previously
only total_amount + fine_amount was stored, causing remaining balance to
show dev fee as unpaid despite full payment.

Fixes: SubscriptionController::payYear(), RetroactiveMembershipService
(both createRetroactiveSubscription and processRetroactiveRenewal).
Migration Phase_92_006 corrects existing paid rows in the database.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 462e2218
......@@ -690,10 +690,10 @@ final class RetroactiveMembershipService
// total_amount = base - discount (dev fee is separate, added at invoice level)
$totalAmount = bcsub($baseAmount, $discountAmount, 2);
// paid_amount only set when status is actually paid
// paid_amount only set when status is actually paid (includes dev fee on member row)
$paidAmount = '0.00';
if ($status === 'paid') {
$paidAmount = $totalAmount;
$paidAmount = bcadd($totalAmount, $devFee, 2);
}
$paymentId = null;
......@@ -796,7 +796,13 @@ final class RetroactiveMembershipService
if ($existing) {
$updateData = ['status' => $status, 'updated_at' => date('Y-m-d H:i:s')];
if ($status === 'paid') {
$paidAmount = (string) ($renewal['amount'] ?? $existing['total_amount']);
$devFee = $db->selectOne(
"SELECT development_fee FROM subscriptions WHERE member_id = ? AND financial_year = ? AND development_fee > 0 LIMIT 1",
[$memberId, $financialYear]
);
$rowDevFee = (string) ($devFee['development_fee'] ?? '0.00');
$baseAmount = (string) ($renewal['amount'] ?? $existing['total_amount']);
$paidAmount = bcadd($baseAmount, $rowDevFee, 2);
$paymentId = self::createRetroactivePayment($memberId, [
'payment_type' => 'annual_subscription',
'amount' => $paidAmount,
......
......@@ -150,8 +150,11 @@ class SubscriptionController extends Controller
$ts = date('Y-m-d H:i:s');
foreach ($rows as $r) {
$remaining = bcsub(bcadd($r['total_amount'], $r['fine_amount'], 2), $r['paid_amount'], 2);
// Dev fee is added to the member row's paid_amount (single flat charge per family)
$rowDevFee = (bccomp($r['development_fee'] ?? '0', '0', 2) > 0) ? $r['development_fee'] : '0.00';
$rowPaid = bcadd(bcadd($r['paid_amount'], $remaining, 2), $rowDevFee, 2);
$db->update('subscriptions', [
'paid_amount' => bcadd($r['paid_amount'], $remaining, 2),
'paid_amount' => $rowPaid,
'payment_id' => $result['payment_id'],
'status' => 'paid',
'paid_at' => $ts,
......
<?php
declare(strict_types=1);
/**
* Fix paid subscription rows where development_fee > 0 but paid_amount doesn't include it.
* Only affects the member row (person_type='member') which carries the dev fee.
* paid_amount should = total_amount + fine_amount + development_fee when fully paid.
*/
return function (\App\Core\Database $db): void {
$rows = $db->select(
"SELECT id, total_amount, fine_amount, paid_amount, development_fee
FROM subscriptions
WHERE status = 'paid'
AND development_fee > 0
AND paid_amount <= (total_amount + fine_amount)"
);
$fixed = 0;
foreach ($rows as $r) {
$correctPaid = bcadd(bcadd($r['total_amount'], $r['fine_amount'], 2), $r['development_fee'], 2);
if (bccomp($correctPaid, $r['paid_amount'], 2) !== 0) {
$db->query(
"UPDATE subscriptions SET paid_amount = ?, updated_at = NOW() WHERE id = ?",
[$correctPaid, (int) $r['id']]
);
$fixed++;
}
}
};
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