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
185 lines
5.1 KiB
PHP
185 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class Payment extends BaseModel
|
|
{
|
|
protected $table = 'payments';
|
|
|
|
protected $fillable = [
|
|
'parent_id',
|
|
'invoice_id',
|
|
'total_amount',
|
|
'paid_amount',
|
|
'balance',
|
|
'number_of_installments',
|
|
'transaction_id',
|
|
'check_file',
|
|
'check_number',
|
|
'payment_method',
|
|
'payment_date',
|
|
'semester',
|
|
'school_year',
|
|
'status',
|
|
'updated_by',
|
|
];
|
|
|
|
protected $casts = [
|
|
'parent_id' => 'integer',
|
|
'invoice_id' => 'integer',
|
|
'number_of_installments' => 'integer',
|
|
'updated_by' => 'integer',
|
|
|
|
'total_amount' => 'decimal:2',
|
|
'paid_amount' => 'decimal:2',
|
|
'balance' => 'decimal:2',
|
|
|
|
'payment_date' => 'date',
|
|
'created_at' => 'datetime',
|
|
'updated_at' => 'datetime',
|
|
];
|
|
|
|
protected $attributes = [
|
|
'paid_amount' => '0.00',
|
|
'balance' => '0.00',
|
|
'payment_method' => 'Unknown',
|
|
'status' => 'Pending',
|
|
];
|
|
|
|
/* Optional relationships */
|
|
|
|
public function invoice()
|
|
{
|
|
return $this->belongsTo(Invoice::class, 'invoice_id');
|
|
}
|
|
|
|
public function parent()
|
|
{
|
|
return $this->belongsTo(User::class, 'parent_id');
|
|
}
|
|
|
|
/* =========================
|
|
* legacy method equivalents
|
|
* ========================= */
|
|
|
|
public static function getPaymentsByParentId(int $parentId): array
|
|
{
|
|
return static::query()
|
|
->where('parent_id', $parentId)
|
|
->orderByDesc('payment_date')
|
|
->get()
|
|
->toArray();
|
|
}
|
|
|
|
public static function getTotalPaidByParentId(int $parentId, string $schoolYear): float
|
|
{
|
|
$total = DB::table('payments')
|
|
->where('parent_id', $parentId)
|
|
->where('school_year', $schoolYear)
|
|
->sum('paid_amount');
|
|
|
|
return (float) $total;
|
|
}
|
|
|
|
public static function updateBalance(int $paymentId, float $amountPaid): bool
|
|
{
|
|
/** @var self|null $payment */
|
|
$payment = static::query()->find($paymentId);
|
|
|
|
if (! $payment) {
|
|
return false;
|
|
}
|
|
|
|
$newPaidAmount = round((float) $payment->paid_amount + $amountPaid, 2);
|
|
$newBalance = round((float) $payment->balance - $amountPaid, 2);
|
|
|
|
$affected = static::query()
|
|
->whereKey($paymentId)
|
|
->update([
|
|
'paid_amount' => $newPaidAmount,
|
|
'balance' => $newBalance,
|
|
]);
|
|
|
|
return $affected > 0;
|
|
}
|
|
|
|
public static function getPaymentsByYear(string $schoolYear): array
|
|
{
|
|
return static::query()
|
|
->where('school_year', $schoolYear)
|
|
->orderByDesc('payment_date')
|
|
->get()
|
|
->toArray();
|
|
}
|
|
|
|
/**
|
|
* Generate a new transaction ID: YYYY-000001
|
|
*/
|
|
public static function generateNewTransactionId(): string
|
|
{
|
|
$currentYear = date('Y');
|
|
$prefix = $currentYear . '-';
|
|
|
|
$latest = static::query()
|
|
->where('transaction_id', 'like', $prefix . '%')
|
|
->orderByDesc('transaction_id')
|
|
->first();
|
|
|
|
if ($latest && ! empty($latest->transaction_id)) {
|
|
$lastNumber = (int) str_replace($prefix, '', (string) $latest->transaction_id);
|
|
$newNumber = $lastNumber + 1;
|
|
} else {
|
|
$newNumber = 1;
|
|
}
|
|
|
|
return $prefix . str_pad((string) $newNumber, 6, '0', STR_PAD_LEFT);
|
|
}
|
|
|
|
/**
|
|
* Get latest payment date/amount/status per invoice for given invoice IDs.
|
|
* Statuses included: Full, Paid, Partially Paid.
|
|
*/
|
|
public static function getPaymentsByInvoice($invoiceIds): array
|
|
{
|
|
if (! is_array($invoiceIds)) {
|
|
$invoiceIds = [$invoiceIds];
|
|
}
|
|
|
|
$invoiceIds = array_values(array_unique(array_map(
|
|
'intval',
|
|
array_filter($invoiceIds)
|
|
)));
|
|
|
|
if (empty($invoiceIds)) {
|
|
return [];
|
|
}
|
|
|
|
$latestSub = DB::table('payments')
|
|
->selectRaw('invoice_id, MAX(payment_date) AS max_date')
|
|
->whereIn('invoice_id', $invoiceIds)
|
|
->whereIn('status', ['Full', 'Paid', 'Partially Paid'])
|
|
->groupBy('invoice_id');
|
|
|
|
$rows = DB::table('payments as p')
|
|
->joinSub($latestSub, 'latest', function ($join) {
|
|
$join->on('latest.invoice_id', '=', 'p.invoice_id')
|
|
->on('latest.max_date', '=', 'p.payment_date');
|
|
})
|
|
->whereIn('p.invoice_id', $invoiceIds)
|
|
->whereIn('p.status', ['Full', 'Paid', 'Partially Paid'])
|
|
->select([
|
|
'p.invoice_id',
|
|
DB::raw('p.paid_amount AS last_paid_amount'),
|
|
DB::raw('p.balance AS balance'),
|
|
DB::raw('p.balance AS balance_after_payment'),
|
|
DB::raw('p.payment_date AS last_payment_date'),
|
|
DB::raw('p.status AS last_payment_status'),
|
|
])
|
|
->get();
|
|
|
|
return $rows->map(fn ($row) => (array) $row)->all();
|
|
}
|
|
}
|