Files
alrahma_sunday_school_api/app/Models/Payment.php
T
2026-06-09 01:03:53 -04:00

172 lines
5.1 KiB
PHP

<?php
namespace App\Models;
use App\Models\BaseModel;
use Illuminate\Support\Facades\DB;
class Payment extends BaseModel
{
protected $table = 'payments';
/**
* legacy: useTimestamps = false because DB handles created_at/updated_at (defaults/triggers).
* Keep OFF in Laravel too.
*/
public $timestamps = false;
protected $fillable = [
'parent_id',
'invoice_id',
'total_amount',
'paid_amount',
'balance',
'number_of_installments',
'transaction_id',
'check_file',
'check_number',
'payment_method',
'payment_date',
'school_year',
'semester',
'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' => 'datetime',
];
/* 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;
$newBalance = (float)$payment->balance - (float)$amountPaid;
// keep precision stable
$paidAmount = (float)$payment->paid_amount + (float)$amountPaid;
$affected = static::query()
->whereKey($paymentId)
->update([
'paid_amount' => $paidAmount,
'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.
* Matches your legacy logic: statuses in ['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 [];
// Subquery: latest payment_date per invoice (Full/Partial only)
$latestSub = DB::table('payments')
->selectRaw('invoice_id, MAX(payment_date) AS max_date')
->whereIn('status', ['Full', 'Paid', 'Partially Paid'])
->groupBy('invoice_id');
// Main query: join payments to the latest per invoice
$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.payment_date AS last_payment_date'),
DB::raw('p.status AS last_payment_status'),
])
->get();
return $rows->map(fn ($r) => (array) $r)->all();
}
}