Files
alrahma_sunday_school_api/app/Services/Invoices/InvoicePaymentService.php
T
root 02ba2fe6b6
API CI/CD / Validate (composer + pint) (push) Successful in 3m8s
API CI/CD / Build frontend assets (push) Successful in 1m2s
API CI/CD / Test (PHPUnit) (push) Failing after 6m5s
API CI/CD / Security audit (push) Failing after 52s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
fix parent pages and teachers and admin
2026-07-09 13:56:22 -04:00

146 lines
5.4 KiB
PHP

<?php
namespace App\Services\Invoices;
use App\Models\Invoice;
use App\Models\Payment;
use Illuminate\Support\Facades\DB;
class InvoicePaymentService
{
public function __construct(private InvoiceConfigService $config) {}
public function getParentInvoiceSummary(int $parentId, ?string $schoolYear): array
{
$currentSchoolYear = $this->config->getSchoolYear();
$schoolYears = DB::table('invoices')
->select('school_year')
->distinct()
->where('parent_id', $parentId)
->orderBy('school_year', 'DESC')
->get()
->map(fn ($r) => (array) $r)
->all();
$selectedYear = $schoolYear ?: null;
if (! $selectedYear) {
$hasCurrentYear = in_array($currentSchoolYear, array_column($schoolYears, 'school_year'), true);
$selectedYear = $hasCurrentYear ? $currentSchoolYear : (! empty($schoolYears) ? $schoolYears[0]['school_year'] : null);
}
$invoices = [];
if ($selectedYear) {
$invoices = Invoice::getInvoicesByParentId($parentId, $selectedYear);
}
$invoiceIds = array_column($invoices, 'id');
$payments = [];
$discounts = [];
$refunds = [];
if (! empty($invoiceIds)) {
$paymentTotals = DB::table('payments')
->selectRaw('invoice_id, COALESCE(SUM(paid_amount),0) as paid_amount')
->whereIn('invoice_id', $invoiceIds)
->where(function ($query) {
$query->whereNotIn(DB::raw('LOWER(status)'), [
'pending',
'void',
'voided',
'cancelled',
'canceled',
'failed',
'rejected',
'refunded',
'chargeback',
'declined',
'reversed',
])->orWhereNull('status');
})
->groupBy('invoice_id')
->get()
->map(fn ($r) => (array) $r)
->all();
foreach ($paymentTotals as $row) {
$payments[$row['invoice_id']] = (float) ($row['paid_amount'] ?? 0);
}
$discountResults = DB::table('discount_usages')
->selectRaw('invoice_id, COALESCE(SUM(discount_amount),0) as discount_amount')
->whereIn('invoice_id', $invoiceIds)
->groupBy('invoice_id')
->get()
->map(fn ($r) => (array) $r)
->all();
foreach ($discountResults as $row) {
$discounts[$row['invoice_id']] = (float) ($row['discount_amount'] ?? 0);
}
$refundResults = DB::table('refunds')
->selectRaw('invoice_id, COALESCE(SUM(refund_paid_amount),0) as refund_paid_amount')
->whereIn('invoice_id', $invoiceIds)
->whereIn('status', ['Partial', 'Paid'])
->groupBy('invoice_id')
->get()
->map(fn ($r) => (array) $r)
->all();
foreach ($refundResults as $row) {
$refunds[$row['invoice_id']] = (float) ($row['refund_paid_amount'] ?? 0);
}
}
$lastPayments = [];
if (! empty($invoiceIds)) {
$paymentResults = Payment::getPaymentsByInvoice($invoiceIds);
foreach ($paymentResults as $payment) {
$lastPayments[$payment['invoice_id']] = [
'last_paid_amount' => (float) ($payment['last_paid_amount'] ?? 0),
'last_payment_date' => $payment['last_payment_date'] ?? null,
];
}
}
foreach ($invoices as &$invoice) {
$invoiceId = (int) ($invoice['id'] ?? 0);
$totalAmount = round((float) ($invoice['total_amount'] ?? 0), 2);
$paidAmount = round((float) ($payments[$invoiceId] ?? $invoice['paid_amount'] ?? 0), 2);
$discountAmount = round((float) ($discounts[$invoiceId] ?? $invoice['discount'] ?? 0), 2);
$refundAmount = round((float) ($refunds[$invoiceId] ?? 0), 2);
$balance = max(0.0, round($totalAmount - $paidAmount - $discountAmount - $refundAmount, 2));
$invoice['paid_amount'] = $paidAmount;
$invoice['discount'] = $discountAmount;
$invoice['refund_amount'] = $refundAmount;
$invoice['balance'] = $balance;
$invoice['status'] = $this->deriveInvoiceStatus($invoice['status'] ?? null, $paidAmount, $balance);
$invoice['last_paid_amount'] = $lastPayments[$invoiceId]['last_paid_amount'] ?? 0.0;
$invoice['last_payment_date'] = $lastPayments[$invoiceId]['last_payment_date'] ?? null;
}
unset($invoice);
return [
'invoices' => $invoices,
'schoolYears' => $schoolYears,
'selectedYear' => $selectedYear,
'currentSchoolYear' => $currentSchoolYear,
'dueDate' => $this->config->getDueDate(),
];
}
private function deriveInvoiceStatus(?string $storedStatus, float $paidAmount, float $balance): string
{
if ($balance <= 0.00001) {
return 'Paid';
}
if ($paidAmount > 0) {
return 'Partially Paid';
}
return $storedStatus ?: 'Unpaid';
}
}