add school year and security fix
API CI/CD / Validate (composer + pint) (push) Successful in 3m14s
API CI/CD / Test (PHPUnit) (push) Failing after 3m28s
API CI/CD / Build frontend assets (push) Successful in 1m2s
API CI/CD / Security audit (push) Failing after 56s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped

This commit is contained in:
root
2026-07-06 00:55:01 -04:00
parent 99782c2a3c
commit 39228168c8
40 changed files with 20370 additions and 70 deletions
@@ -628,51 +628,16 @@ class SchoolYearClosureService
private function buildParentBalanceRows(string $fromSchoolYear, string $toSchoolYear): array
{
$invoices = DB::table('invoices')
$invoiceBalances = DB::table('invoices')
->where('school_year', $fromSchoolYear)
->whereNotIn(DB::raw('LOWER(COALESCE(status, ""))'), ['void', 'voided', 'cancelled', 'canceled'])
->whereNotIn(DB::raw("LOWER(COALESCE(status, ''))"), ['void', 'voided', 'cancelled', 'canceled'])
->select('parent_id')
->selectRaw('ROUND(SUM(COALESCE(balance, 0)), 2) as net_balance')
->selectRaw('COUNT(CASE WHEN COALESCE(balance, 0) > 0.01 THEN 1 END) as unpaid_invoice_count')
->groupBy('parent_id')
->havingRaw('ABS(SUM(COALESCE(balance, 0))) > 0.01')
->get();
$byParent = [];
foreach ($invoices as $invoice) {
$parentId = (int) ($invoice->parent_id ?? 0);
if ($parentId <= 0) {
continue;
}
$balance = $invoice->balance !== null
? (float) $invoice->balance
: (float) ($invoice->total_amount ?? 0) - (float) ($invoice->paid_amount ?? 0);
if (! isset($byParent[$parentId])) {
$existing = ParentBalanceTransfer::query()
->where('parent_id', $parentId)
->where('from_school_year', $fromSchoolYear)
->where('to_school_year', $toSchoolYear)
->first();
$byParent[$parentId] = [
'parent_id' => $parentId,
'parent_name' => $this->resolveParentName($parentId),
'student_names' => $this->resolveStudentNames($parentId, $fromSchoolYear),
'unpaid_invoice_count' => 0,
'old_unpaid_balance' => 0.0,
'credit_balance' => 0.0,
'net_balance' => 0.0,
'amount_to_transfer' => 0.0,
'transfer_status' => $existing?->status,
'existing_transfer_id' => $existing?->id,
'source_invoice_ids' => [],
];
}
$byParent[$parentId]['source_invoice_ids'][] = (int) $invoice->id;
$byParent[$parentId]['net_balance'] += $balance;
if ($balance > 0) {
$byParent[$parentId]['unpaid_invoice_count']++;
}
}
$rows = [];
$summary = [
'parents_with_non_zero_balance' => 0,
@@ -683,16 +648,46 @@ class SchoolYearClosureService
'net_balance_to_transfer' => 0.0,
];
foreach ($byParent as $row) {
$net = round((float) $row['net_balance'], 2);
foreach ($invoiceBalances as $balanceRow) {
$parentId = (int) ($balanceRow->parent_id ?? 0);
if ($parentId <= 0) {
continue;
}
$net = round((float) ($balanceRow->net_balance ?? 0), 2);
if (abs($net) < 0.01) {
continue;
}
$row['old_unpaid_balance'] = $net > 0 ? $net : 0.0;
$row['credit_balance'] = $net < 0 ? abs($net) : 0.0;
$row['amount_to_transfer'] = $net;
$row['transfer_status'] = $row['transfer_status'] ?? ($net > 0 ? 'pending' : 'credit_pending');
$existing = ParentBalanceTransfer::query()
->where('parent_id', $parentId)
->where('from_school_year', $fromSchoolYear)
->where('to_school_year', $toSchoolYear)
->first();
$sourceInvoiceIds = DB::table('invoices')
->where('parent_id', $parentId)
->where('school_year', $fromSchoolYear)
->whereRaw('ABS(COALESCE(balance, 0)) > 0.01')
->whereNotIn(DB::raw("LOWER(COALESCE(status, ''))"), ['void', 'voided', 'cancelled', 'canceled'])
->pluck('id')
->map(fn ($id) => (int) $id)
->all();
$row = [
'parent_id' => $parentId,
'parent_name' => $this->resolveParentName($parentId),
'student_names' => $this->resolveStudentNames($parentId, $fromSchoolYear),
'unpaid_invoice_count' => (int) ($balanceRow->unpaid_invoice_count ?? 0),
'old_unpaid_balance' => $net > 0 ? $net : 0.0,
'credit_balance' => $net < 0 ? abs($net) : 0.0,
'net_balance' => $net,
'amount_to_transfer' => $net,
'transfer_status' => $existing?->status ?? ($net > 0 ? 'pending' : 'credit_pending'),
'existing_transfer_id' => $existing?->id,
'source_invoice_ids' => $sourceInvoiceIds,
];
$rows[] = $row;
$summary['parents_with_non_zero_balance']++;