Files
root 0ac3a8375e
Deploy to Shared Hosting / Shared hosting deploy (push) Failing after 31s
Tests / PHPUnit (push) Failing after 55s
Fix semester context, attendance rosters, and billing workflows
- load global semester helpers consistently and use date-based semester defaults
- fix grading and daily attendance duplicate student/section rows
- keep attendance violations scoped to the current semester by default
- update invoice, refund, discount, payment, and financial aid flows
- add configuration cleanup migrations for duplicate calendar/semester keys
- refresh parent registration/report-card and print request handling
- update related models, services, views, cron notes, and test coverage
2026-08-16 17:41:11 -04:00

108 lines
3.0 KiB
PHP

<?php
namespace App\Models;
use CodeIgniter\Database\ConnectionInterface;
use CodeIgniter\Model;
use App\Models\Concerns\SchoolYearAutoFillTrait;
use CodeIgniter\Validation\ValidationInterface;
class RefundModel extends Model
{
use SchoolYearAutoFillTrait;
protected $table = 'refunds';
protected $primaryKey = 'id';
protected $allowedFields = [
'parent_id',
'school_year',
'invoice_id',
'refund_amount',
'requested_amount_cents',
'approved_amount_cents',
'reconciliation_status',
'reconciliation_reason',
'reconciliation_required_at',
'currency',
'requested_at',
'approved_at',
'refunded_at',
'status',
'reason',
'refund_paid_amount',
'request',
'source_type',
'source_id',
'note',
'semester',
'school_year',
'approved_by',
'updated_by',
'refund_method',
'check_nbr',
'check_file'
];
protected $validationRules = [
'school_year' => 'required|string|max_length[9]',
];
protected $useTimestamps = true;
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
private array $refundColumns = [];
public function __construct(?ConnectionInterface $db = null, ?ValidationInterface $validation = null)
{
parent::__construct($db, $validation);
$this->refundColumns = $this->getTableColumns($this->table);
$this->allowedFields = array_values(array_filter(
$this->allowedFields,
fn (string $field): bool => in_array($field, $this->refundColumns, true)
));
foreach (array_keys($this->validationRules) as $field) {
if (!in_array($field, $this->allowedFields, true)) {
unset($this->validationRules[$field]);
}
}
}
private function getTableColumns(string $table): array
{
try {
return $this->db->getFieldNames($table);
} catch (\Throwable $e) {
log_message('error', '[RefundModel] Could not read table columns for {table}: {error}', [
'table' => $table,
'error' => $e->getMessage(),
]);
return [];
}
}
/**
* Get total approved refund for a parent in a specific school year.
*
* @param int $parentId
* @param string $schoolYear
* @return float
*/
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;
}
}