reconstruction of the project

This commit is contained in:
root
2026-03-08 16:33:24 -04:00
parent 23b7db1107
commit c8de5f7edc
9157 changed files with 77877 additions and 1073823 deletions
+139 -18
View File
@@ -2,12 +2,14 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use App\Models\BaseModel;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Refund extends BaseModel
{
protected $table = 'refunds';
protected $primaryKey = 'id';
protected $fillable = [
'parent_id',
'school_year',
@@ -30,27 +32,146 @@ class Refund extends BaseModel
'updated_at',
'semester',
];
public $timestamps = true;
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at';
protected $casts = [
'parent_id' => 'integer',
'invoice_id' => 'integer',
'approved_by' => 'integer',
'updated_by' => 'integer',
'refund_amount' => 'decimal:2',
'refund_paid_amount' => 'decimal:2',
'requested_at' => 'datetime',
'approved_at' => 'datetime',
'refunded_at' => 'datetime',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/* ============================================================
* Status (enum-like)
* ============================================================
*/
public const STATUS_PENDING = 'Pending';
public const STATUS_APPROVED = 'Approved';
public const STATUS_PARTIAL = 'Partial';
public const STATUS_PAID = 'Paid';
public const STATUS_REJECTED = 'Rejected';
public const STATUS_CANCELED = 'Canceled';
public static function paidOutStatuses(): array
{
// matches your CI whereIn(['Partial','Paid'])
return [self::STATUS_PARTIAL, self::STATUS_PAID];
}
/* ============================================================
* Relationships (optional)
* ============================================================
*/
public function parent(): BelongsTo
{
return $this->belongsTo(ParentModel::class, 'parent_id'); // rename to your real model, e.g. ParentUser/Guardian/Customer
}
public function invoice(): BelongsTo
{
return $this->belongsTo(Invoice::class, 'invoice_id');
}
/* ============================================================
* Scopes
* ============================================================
*/
public function scopeForParent(Builder $q, int $parentId): Builder
{
return $q->where('parent_id', $parentId);
}
public function scopeForSchoolYear(Builder $q, string $schoolYear): Builder
{
return $q->where('school_year', $schoolYear);
}
public function scopePaidOut(Builder $q): Builder
{
return $q->whereIn('status', self::paidOutStatuses());
}
/* ============================================================
* Business: totals
* ============================================================
*/
/**
* Get total approved refund for a parent in a specific school year.
*
* @param int $parentId
* @param string $schoolYear
* @return float
* Total paid-out refunds for a parent in a specific school year (Partial + Paid).
* Mirrors the CI behavior and returns 0.00 if none.
*/
public static function totalApprovedPaidOutForParentAndYear(int $parentId, string $schoolYear): float
{
$sum = static::query()
->forParent($parentId)
->forSchoolYear($schoolYear)
->paidOut()
->sum('refund_paid_amount');
return (float) $sum;
}
/**
* Instance-style method if you want to keep a similar calling style to CI.
*/
public function getTotalApprovedRefundByParentIdAndSchoolYear(int $parentId, string $schoolYear): float
{
// Sum refunds that have been at least partially paid out to the parent
$result = $this->selectSum('refund_paid_amount', 'total_paid')
->where('parent_id', $parentId)
->where('school_year', $schoolYear)
->whereIn('status', ['Partial', 'Paid'])
->get()
->getRowArray();
return $result && isset($result['total_paid']) ? (float) $result['total_paid'] : 0.00;
return static::totalApprovedPaidOutForParentAndYear($parentId, $schoolYear);
}
}
/* ============================================================
* Validation rules (optional helper for controllers/FormRequests)
* ============================================================
*/
public static function rules(?int $id = null): array
{
return [
'parent_id' => ['required', 'integer', 'min:1', 'exists:parents,id'], // adjust table name
'school_year' => ['required', 'string', 'max:20'],
'invoice_id' => ['nullable', 'integer', 'exists:invoices,id'],
'refund_amount' => ['required', 'numeric', 'min:0'],
'refund_paid_amount' => ['nullable', 'numeric', 'min:0'],
'requested_at' => ['nullable', 'date'],
'approved_at' => ['nullable', 'date', 'after_or_equal:requested_at'],
'refunded_at' => ['nullable', 'date', 'after_or_equal:approved_at'],
'status' => ['required', 'string', 'in:' . implode(',', [
self::STATUS_PENDING,
self::STATUS_APPROVED,
self::STATUS_PARTIAL,
self::STATUS_PAID,
self::STATUS_REJECTED,
self::STATUS_CANCELED,
])],
'reason' => ['nullable', 'string', 'max:2000'],
'request' => ['nullable', 'string'],
'note' => ['nullable', 'string', 'max:5000'],
'semester' => ['nullable', 'string', 'max:20'],
'approved_by' => ['nullable', 'integer'],
'updated_by' => ['nullable', 'integer'],
'refund_method' => ['nullable', 'string', 'max:50'], // cash/check/cc/etc.
'check_nbr' => ['nullable', 'string', 'max:80'],
'check_file' => ['nullable', 'string', 'max:255'],
];
}
}