@@ -661,6 +661,7 @@ class RefundController extends BaseController
|
||||
|
||||
$payoutId = $this->refundPayoutModel->insert([
|
||||
'refund_id' => $refundId,
|
||||
'school_year' => (string)($lockedRefund['school_year'] ?? ''),
|
||||
'amount_cents' => $newPaidCents,
|
||||
'currency' => (string)($lockedRefund['currency'] ?? 'USD') ?: 'USD',
|
||||
'payout_type' => 'cash_out',
|
||||
@@ -830,6 +831,7 @@ class RefundController extends BaseController
|
||||
|
||||
$reversalId = $this->refundPayoutModel->insert([
|
||||
'refund_id' => $refundId,
|
||||
'school_year' => (string)($refund['school_year'] ?? ''),
|
||||
'amount_cents' => $reverseCents,
|
||||
'currency' => (string)($payout['currency'] ?? $refund['currency'] ?? 'USD') ?: 'USD',
|
||||
'payout_type' => 'reversal',
|
||||
|
||||
@@ -22,6 +22,11 @@ class CreateInvoiceLines extends Migration
|
||||
'unsigned' => true,
|
||||
'null' => false,
|
||||
],
|
||||
'school_year' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 9,
|
||||
'null' => false,
|
||||
],
|
||||
'line_type' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 50,
|
||||
@@ -101,6 +106,7 @@ class CreateInvoiceLines extends Migration
|
||||
$this->forge->createTable('invoice_lines', true);
|
||||
}
|
||||
|
||||
$this->ensureSchoolYearColumn();
|
||||
$this->backfillLegacyInvoiceLines();
|
||||
}
|
||||
|
||||
@@ -125,7 +131,7 @@ class CreateInvoiceLines extends Migration
|
||||
$existing = array_fill_keys(array_map(static fn ($row) => (int) ($row['invoice_id'] ?? 0), $existingRows), true);
|
||||
|
||||
$invoices = $this->db->table('invoices')
|
||||
->select('id, total_amount, invoice_number, created_at, updated_at')
|
||||
->select('id, total_amount, invoice_number, school_year, created_at, updated_at')
|
||||
->orderBy('id', 'ASC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
@@ -143,6 +149,7 @@ class CreateInvoiceLines extends Migration
|
||||
|
||||
$this->db->table('invoice_lines')->insert([
|
||||
'invoice_id' => $invoiceId,
|
||||
'school_year' => (string)($invoice['school_year'] ?? ''),
|
||||
'line_type' => 'legacy_invoice_total',
|
||||
'source_type' => 'legacy_invoice',
|
||||
'source_id' => $invoiceId,
|
||||
@@ -164,4 +171,33 @@ class CreateInvoiceLines extends Migration
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function ensureSchoolYearColumn(): void
|
||||
{
|
||||
if (!$this->db->tableExists('invoice_lines')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->db->fieldExists('school_year', 'invoice_lines')) {
|
||||
$this->forge->addColumn('invoice_lines', [
|
||||
'school_year' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 9,
|
||||
'null' => true,
|
||||
'after' => 'invoice_id',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->db->tableExists('invoices')) {
|
||||
$this->db->query(
|
||||
"UPDATE invoice_lines il
|
||||
INNER JOIN invoices i ON i.id = il.invoice_id
|
||||
SET il.school_year = i.school_year
|
||||
WHERE il.school_year IS NULL OR TRIM(il.school_year) = ''"
|
||||
);
|
||||
}
|
||||
|
||||
$this->db->query("ALTER TABLE invoice_lines MODIFY school_year VARCHAR(9) NOT NULL");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class AddRefundSourcesAndPayouts extends Migration
|
||||
{
|
||||
$this->ensureRefundSourceColumns();
|
||||
$this->ensureRefundPayoutsTable();
|
||||
$this->ensureRefundPayoutSchoolYearColumn();
|
||||
$this->ensureRefundPayoutFingerprintColumns();
|
||||
$this->backfillRefundSources();
|
||||
$this->backfillLegacyPayouts();
|
||||
@@ -67,6 +68,7 @@ class AddRefundSourcesAndPayouts extends Migration
|
||||
$this->forge->addField([
|
||||
'id' => ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
|
||||
'refund_id' => ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'null' => false],
|
||||
'school_year' => ['type' => 'VARCHAR', 'constraint' => 9, 'null' => false],
|
||||
'amount_cents' => ['type' => 'INT', 'constraint' => 11, 'null' => false],
|
||||
'currency' => ['type' => 'CHAR', 'constraint' => 3, 'null' => false, 'default' => 'USD'],
|
||||
'payout_type' => ['type' => 'VARCHAR', 'constraint' => 30, 'null' => false, 'default' => 'cash_out'],
|
||||
@@ -94,6 +96,35 @@ class AddRefundSourcesAndPayouts extends Migration
|
||||
$this->forge->createTable('refund_payouts', true);
|
||||
}
|
||||
|
||||
private function ensureRefundPayoutSchoolYearColumn(): void
|
||||
{
|
||||
if (!$this->db->tableExists('refund_payouts')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->db->fieldExists('school_year', 'refund_payouts')) {
|
||||
$this->forge->addColumn('refund_payouts', [
|
||||
'school_year' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 9,
|
||||
'null' => true,
|
||||
'after' => 'refund_id',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->db->tableExists('refunds')) {
|
||||
$this->db->query(
|
||||
"UPDATE refund_payouts rp
|
||||
INNER JOIN refunds r ON r.id = rp.refund_id
|
||||
SET rp.school_year = r.school_year
|
||||
WHERE rp.school_year IS NULL OR TRIM(rp.school_year) = ''"
|
||||
);
|
||||
}
|
||||
|
||||
$this->db->query("ALTER TABLE refund_payouts MODIFY school_year VARCHAR(9) NOT NULL");
|
||||
}
|
||||
|
||||
private function ensureRefundPayoutFingerprintColumns(): void
|
||||
{
|
||||
if (!$this->db->tableExists('refund_payouts')) {
|
||||
@@ -161,7 +192,7 @@ class AddRefundSourcesAndPayouts extends Migration
|
||||
}
|
||||
|
||||
$refunds = $this->db->table('refunds')
|
||||
->select('id, refund_paid_amount, currency, refund_method, check_nbr, check_file, refunded_at, updated_by, created_at, updated_at')
|
||||
->select('id, refund_paid_amount, currency, refund_method, check_nbr, check_file, school_year, refunded_at, updated_by, created_at, updated_at')
|
||||
->where('refund_paid_amount >', 0)
|
||||
->get()
|
||||
->getResultArray();
|
||||
@@ -182,6 +213,7 @@ class AddRefundSourcesAndPayouts extends Migration
|
||||
|
||||
$this->db->table('refund_payouts')->insert([
|
||||
'refund_id' => $refundId,
|
||||
'school_year' => (string)($refund['school_year'] ?? ''),
|
||||
'amount_cents' => (int) round(((float) ($refund['refund_paid_amount'] ?? 0)) * 100),
|
||||
'currency' => (string) ($refund['currency'] ?? 'USD') ?: 'USD',
|
||||
'payout_type' => 'cash_out',
|
||||
|
||||
@@ -69,6 +69,8 @@ class FinancialReimbursementPoHardening extends Migration
|
||||
|
||||
private function ensurePurchaseOrderInvariants(): void
|
||||
{
|
||||
$this->ensurePurchaseOrderSchoolYearColumns();
|
||||
|
||||
if (!$this->db->tableExists('purchase_order_items')) {
|
||||
return;
|
||||
}
|
||||
@@ -108,6 +110,63 @@ class FinancialReimbursementPoHardening extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
private function ensurePurchaseOrderSchoolYearColumns(): void
|
||||
{
|
||||
foreach (['purchase_orders' => 'status', 'purchase_order_items' => 'purchase_order_id'] as $table => $after) {
|
||||
if (!$this->db->tableExists($table)) {
|
||||
continue;
|
||||
}
|
||||
if (!$this->db->fieldExists('school_year', $table)) {
|
||||
$this->forge->addColumn($table, [
|
||||
'school_year' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 9,
|
||||
'null' => true,
|
||||
'after' => $after,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->db->tableExists('purchase_orders')) {
|
||||
$currentYear = $this->currentSchoolYear();
|
||||
$this->db->query(
|
||||
'UPDATE purchase_orders SET school_year = ? WHERE school_year IS NULL OR TRIM(school_year) = ?',
|
||||
[$currentYear, '']
|
||||
);
|
||||
$this->db->query('ALTER TABLE purchase_orders MODIFY school_year VARCHAR(9) NOT NULL');
|
||||
}
|
||||
|
||||
if ($this->db->tableExists('purchase_orders') && $this->db->tableExists('purchase_order_items')) {
|
||||
$this->db->query(
|
||||
"UPDATE purchase_order_items poi
|
||||
INNER JOIN purchase_orders po ON po.id = poi.purchase_order_id
|
||||
SET poi.school_year = po.school_year
|
||||
WHERE poi.school_year IS NULL OR TRIM(poi.school_year) = ''"
|
||||
);
|
||||
$this->db->query('ALTER TABLE purchase_order_items MODIFY school_year VARCHAR(9) NOT NULL');
|
||||
}
|
||||
}
|
||||
|
||||
private function currentSchoolYear(): string
|
||||
{
|
||||
if ($this->db->tableExists('school_years')) {
|
||||
$row = $this->db->table('school_years')
|
||||
->select('name')
|
||||
->where('status', 'active')
|
||||
->orderBy('id', 'DESC')
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
$name = trim((string)($row['name'] ?? ''));
|
||||
if (preg_match('/^\d{4}-\d{4}$/', $name) === 1) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
$year = (int)date('Y');
|
||||
return $year . '-' . ($year + 1);
|
||||
}
|
||||
|
||||
private function createIndexIfMissing(string $table, string $indexName, string $sql): void
|
||||
{
|
||||
if (!$this->db->tableExists($table)) {
|
||||
|
||||
@@ -9,6 +9,7 @@ class CreatePaymentCorrections extends Migration
|
||||
public function up()
|
||||
{
|
||||
if ($this->db->tableExists('payment_corrections')) {
|
||||
$this->ensureSchoolYearColumn();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,6 +18,7 @@ class CreatePaymentCorrections extends Migration
|
||||
'payment_id' => ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'null' => false],
|
||||
'invoice_id' => ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'null' => false],
|
||||
'parent_id' => ['type' => 'INT', 'constraint' => 11, 'unsigned' => true, 'null' => false],
|
||||
'school_year' => ['type' => 'VARCHAR', 'constraint' => 9, 'null' => false],
|
||||
'correction_type' => ['type' => 'VARCHAR', 'constraint' => 50, 'null' => false],
|
||||
'approved_refundable_cents' => ['type' => 'INT', 'constraint' => 11, 'null' => false],
|
||||
'status' => ['type' => 'VARCHAR', 'constraint' => 30, 'null' => false],
|
||||
@@ -31,7 +33,9 @@ class CreatePaymentCorrections extends Migration
|
||||
|
||||
$this->db->query('CREATE INDEX idx_payment_corrections_payment_status ON payment_corrections (payment_id, status)');
|
||||
$this->db->query('CREATE INDEX idx_payment_corrections_invoice_status ON payment_corrections (invoice_id, status)');
|
||||
$this->db->query('CREATE INDEX idx_payment_corrections_year_status ON payment_corrections (school_year, status)');
|
||||
$this->assertIndexExists('payment_corrections', 'idx_payment_corrections_payment_status');
|
||||
$this->assertIndexExists('payment_corrections', 'idx_payment_corrections_year_status');
|
||||
}
|
||||
|
||||
public function down()
|
||||
@@ -52,4 +56,45 @@ class CreatePaymentCorrections extends Migration
|
||||
|
||||
throw new \RuntimeException("Required index {$indexName} was not created on {$table}.");
|
||||
}
|
||||
|
||||
private function ensureSchoolYearColumn(): void
|
||||
{
|
||||
if (!$this->db->fieldExists('school_year', 'payment_corrections')) {
|
||||
$this->forge->addColumn('payment_corrections', [
|
||||
'school_year' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 9,
|
||||
'null' => true,
|
||||
'after' => 'parent_id',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->db->tableExists('invoices')) {
|
||||
$this->db->query(
|
||||
"UPDATE payment_corrections pc
|
||||
INNER JOIN invoices i ON i.id = pc.invoice_id
|
||||
SET pc.school_year = i.school_year
|
||||
WHERE pc.school_year IS NULL OR TRIM(pc.school_year) = ''"
|
||||
);
|
||||
}
|
||||
|
||||
$this->db->query("ALTER TABLE payment_corrections MODIFY school_year VARCHAR(9) NOT NULL");
|
||||
if (!$this->indexExists('payment_corrections', 'idx_payment_corrections_year_status')) {
|
||||
$this->db->query('CREATE INDEX idx_payment_corrections_year_status ON payment_corrections (school_year, status)');
|
||||
}
|
||||
$this->assertIndexExists('payment_corrections', 'idx_payment_corrections_year_status');
|
||||
}
|
||||
|
||||
private function indexExists(string $table, string $indexName): bool
|
||||
{
|
||||
$indexes = $this->db->query('SHOW INDEX FROM ' . $this->db->escapeIdentifiers($table))->getResultArray();
|
||||
foreach ($indexes as $index) {
|
||||
if (($index['Key_name'] ?? '') === $indexName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class EnsureFinancialModelSchoolYears extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->ensureColumn('invoice_lines', 'invoice_id');
|
||||
$this->backfillFromParent('invoice_lines', 'invoices', 'invoice_id');
|
||||
|
||||
$this->ensureColumn('refund_payouts', 'refund_id');
|
||||
$this->backfillFromParent('refund_payouts', 'refunds', 'refund_id');
|
||||
|
||||
$this->ensureColumn('payment_corrections', 'parent_id');
|
||||
$this->backfillFromParent('payment_corrections', 'invoices', 'invoice_id');
|
||||
|
||||
$this->ensureColumn('reimbursement_batch_admin_files', 'batch_id');
|
||||
$this->backfillFromParent('reimbursement_batch_admin_files', 'reimbursement_batches', 'batch_id');
|
||||
|
||||
$this->ensureColumn('purchase_orders', 'status');
|
||||
$this->backfillCurrentYear('purchase_orders');
|
||||
|
||||
$this->ensureColumn('purchase_order_items', 'purchase_order_id');
|
||||
$this->backfillFromParent('purchase_order_items', 'purchase_orders', 'purchase_order_id');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
// school_year is now part of the financial model contract; do not drop it.
|
||||
}
|
||||
|
||||
private function ensureColumn(string $table, string $after): void
|
||||
{
|
||||
if (!$this->db->tableExists($table)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->db->fieldExists('school_year', $table)) {
|
||||
$this->forge->addColumn($table, [
|
||||
'school_year' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 9,
|
||||
'null' => true,
|
||||
'after' => $after,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function backfillFromParent(string $childTable, string $parentTable, string $foreignKey): void
|
||||
{
|
||||
if (
|
||||
!$this->db->tableExists($childTable)
|
||||
|| !$this->db->tableExists($parentTable)
|
||||
|| !$this->db->fieldExists('school_year', $childTable)
|
||||
|| !$this->db->fieldExists('school_year', $parentTable)
|
||||
|| !$this->db->fieldExists($foreignKey, $childTable)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->db->query(sprintf(
|
||||
"UPDATE %s child
|
||||
INNER JOIN %s parent ON parent.id = child.%s
|
||||
SET child.school_year = parent.school_year
|
||||
WHERE child.school_year IS NULL OR TRIM(child.school_year) = ''",
|
||||
$this->db->escapeIdentifiers($childTable),
|
||||
$this->db->escapeIdentifiers($parentTable),
|
||||
$this->db->escapeIdentifiers($foreignKey)
|
||||
));
|
||||
|
||||
$this->backfillCurrentYear($childTable);
|
||||
}
|
||||
|
||||
private function backfillCurrentYear(string $table): void
|
||||
{
|
||||
if (!$this->db->tableExists($table) || !$this->db->fieldExists('school_year', $table)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->db->query(
|
||||
sprintf(
|
||||
'UPDATE %s SET school_year = ? WHERE school_year IS NULL OR TRIM(school_year) = ?',
|
||||
$this->db->escapeIdentifiers($table)
|
||||
),
|
||||
[$this->currentSchoolYear(), '']
|
||||
);
|
||||
|
||||
$this->db->query(sprintf(
|
||||
'ALTER TABLE %s MODIFY school_year VARCHAR(9) NOT NULL',
|
||||
$this->db->escapeIdentifiers($table)
|
||||
));
|
||||
|
||||
$this->ensureIndex($table);
|
||||
}
|
||||
|
||||
private function ensureIndex(string $table): void
|
||||
{
|
||||
$indexName = 'idx_' . $table . '_school_year';
|
||||
if (strlen($indexName) > 64) {
|
||||
$indexName = 'idx_' . substr(hash('sha256', $table . '_school_year'), 0, 24);
|
||||
}
|
||||
|
||||
$indexes = $this->db->query('SHOW INDEX FROM ' . $this->db->escapeIdentifiers($table))->getResultArray();
|
||||
foreach ($indexes as $index) {
|
||||
if (($index['Key_name'] ?? '') === $indexName) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->query(sprintf(
|
||||
'CREATE INDEX %s ON %s (school_year)',
|
||||
$this->db->escapeIdentifiers($indexName),
|
||||
$this->db->escapeIdentifiers($table)
|
||||
));
|
||||
}
|
||||
|
||||
private function currentSchoolYear(): string
|
||||
{
|
||||
if ($this->db->tableExists('school_years')) {
|
||||
$row = $this->db->table('school_years')
|
||||
->select('name')
|
||||
->where('status', 'active')
|
||||
->orderBy('id', 'DESC')
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
|
||||
$name = trim((string)($row['name'] ?? ''));
|
||||
if (preg_match('/^\d{4}-\d{4}$/', $name) === 1) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
$year = (int)date('Y');
|
||||
|
||||
return $year . '-' . ($year + 1);
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,7 @@ class InvoiceAdjustmentService
|
||||
$now = utc_now();
|
||||
$lineId = $this->invoiceLineModel->insert([
|
||||
'invoice_id' => $invoiceId,
|
||||
'school_year' => (string)$invoice['school_year'],
|
||||
'line_type' => $amountCents > 0 ? 'additional_charge' : 'additional_deduction',
|
||||
'source_type' => 'additional_charge',
|
||||
'source_id' => $chargeId,
|
||||
@@ -139,6 +140,7 @@ class InvoiceAdjustmentService
|
||||
$now = utc_now();
|
||||
$lineId = $this->invoiceLineModel->insert([
|
||||
'invoice_id' => $invoiceId,
|
||||
'school_year' => (string)$invoice['school_year'],
|
||||
'line_type' => $reverseAmountCents > 0 ? 'additional_charge_reversal' : 'additional_deduction_reversal',
|
||||
'source_type' => 'additional_charge_reversal',
|
||||
'source_id' => $chargeId,
|
||||
|
||||
@@ -388,6 +388,7 @@ class InvoiceLedgerService
|
||||
): array {
|
||||
return [
|
||||
'invoice_id' => $invoiceId,
|
||||
'school_year' => (string)($metadata['school_year'] ?? ''),
|
||||
'line_type' => $lineType,
|
||||
'source_type' => $sourceType,
|
||||
'source_id' => $sourceId,
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
use App\Models\Concerns\SchoolYearAutoFillTrait;
|
||||
|
||||
class InvoiceLineModel extends Model
|
||||
{
|
||||
use SchoolYearAutoFillTrait;
|
||||
|
||||
protected $table = 'invoice_lines';
|
||||
protected $primaryKey = 'id';
|
||||
protected $returnType = 'array';
|
||||
@@ -13,6 +16,7 @@ class InvoiceLineModel extends Model
|
||||
|
||||
protected $allowedFields = [
|
||||
'invoice_id',
|
||||
'school_year',
|
||||
'line_type',
|
||||
'source_type',
|
||||
'source_id',
|
||||
@@ -31,6 +35,7 @@ class InvoiceLineModel extends Model
|
||||
|
||||
protected $validationRules = [
|
||||
'invoice_id' => 'required|integer',
|
||||
'school_year' => 'required|string|max_length[9]',
|
||||
'line_type' => 'required|max_length[50]',
|
||||
'description' => 'required|max_length[255]',
|
||||
'quantity' => 'required|decimal',
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
use App\Models\Concerns\SchoolYearAutoFillTrait;
|
||||
|
||||
class PaymentCorrectionModel extends Model
|
||||
{
|
||||
use SchoolYearAutoFillTrait;
|
||||
|
||||
protected $table = 'payment_corrections';
|
||||
protected $primaryKey = 'id';
|
||||
protected $returnType = 'array';
|
||||
@@ -15,6 +18,7 @@ class PaymentCorrectionModel extends Model
|
||||
'payment_id',
|
||||
'invoice_id',
|
||||
'parent_id',
|
||||
'school_year',
|
||||
'correction_type',
|
||||
'approved_refundable_cents',
|
||||
'status',
|
||||
@@ -24,4 +28,14 @@ class PaymentCorrectionModel extends Model
|
||||
'created_at',
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
protected $validationRules = [
|
||||
'payment_id' => 'required|integer',
|
||||
'invoice_id' => 'required|integer',
|
||||
'parent_id' => 'required|integer',
|
||||
'school_year' => 'required|string|max_length[9]',
|
||||
'correction_type' => 'required|max_length[50]',
|
||||
'approved_refundable_cents' => 'required|integer|greater_than[0]',
|
||||
'status' => 'required|max_length[30]',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,17 +3,21 @@
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
use App\Models\Concerns\SchoolYearAutoFillTrait;
|
||||
|
||||
class PurchaseOrderItemModel extends Model
|
||||
{
|
||||
use SchoolYearAutoFillTrait;
|
||||
|
||||
protected $table = 'purchase_order_items';
|
||||
protected $primaryKey = 'id';
|
||||
protected $allowedFields = ['purchase_order_id','supply_id','description','quantity','received_qty','unit_cost'];
|
||||
protected $allowedFields = ['purchase_order_id','supply_id','school_year','description','quantity','received_qty','unit_cost'];
|
||||
protected $useTimestamps = true;
|
||||
|
||||
protected $validationRules = [
|
||||
'purchase_order_id' => 'required|is_natural_no_zero',
|
||||
'supply_id' => 'required|is_natural_no_zero',
|
||||
'school_year' => 'required|string|max_length[9]',
|
||||
'quantity' => 'required|is_natural_no_zero',
|
||||
'received_qty' => 'if_exist|integer|greater_than_equal_to[0]',
|
||||
'unit_cost' => 'required|decimal|greater_than_equal_to[0]',
|
||||
|
||||
@@ -3,18 +3,22 @@
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
use App\Models\Concerns\SchoolYearAutoFillTrait;
|
||||
|
||||
class PurchaseOrderModel extends Model
|
||||
{
|
||||
use SchoolYearAutoFillTrait;
|
||||
|
||||
protected $table = 'purchase_orders';
|
||||
protected $primaryKey = 'id';
|
||||
protected $allowedFields = ['po_number','supplier_id','status','order_date','expected_date','subtotal','tax','total','notes'];
|
||||
protected $allowedFields = ['po_number','supplier_id','status','school_year','order_date','expected_date','subtotal','tax','total','notes'];
|
||||
protected $useTimestamps = true;
|
||||
protected $useSoftDeletes = true;
|
||||
|
||||
protected $validationRules = [
|
||||
'po_number' => 'required|max_length[60]|is_unique[purchase_orders.po_number,id,{id}]',
|
||||
'supplier_id' => 'required|is_natural_no_zero',
|
||||
'school_year' => 'required|string|max_length[9]',
|
||||
'status' => 'in_list[draft,ordered,received,canceled]',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
use App\Models\Concerns\SchoolYearAutoFillTrait;
|
||||
|
||||
class RefundPayoutModel extends Model
|
||||
{
|
||||
use SchoolYearAutoFillTrait;
|
||||
|
||||
protected $table = 'refund_payouts';
|
||||
protected $primaryKey = 'id';
|
||||
protected $returnType = 'array';
|
||||
@@ -13,6 +16,7 @@ class RefundPayoutModel extends Model
|
||||
|
||||
protected $allowedFields = [
|
||||
'refund_id',
|
||||
'school_year',
|
||||
'amount_cents',
|
||||
'currency',
|
||||
'payout_type',
|
||||
@@ -36,6 +40,7 @@ class RefundPayoutModel extends Model
|
||||
|
||||
protected $validationRules = [
|
||||
'refund_id' => 'required|integer',
|
||||
'school_year' => 'required|string|max_length[9]',
|
||||
'amount_cents' => 'required|integer|greater_than[0]',
|
||||
'currency' => 'required|exact_length[3]',
|
||||
'payout_type' => 'required|in_list[cash_out,account_credit,reversal]',
|
||||
|
||||
@@ -301,12 +301,12 @@
|
||||
/app/Controllers/View/PaymentNotificationController.php:333 matches /Paid/i
|
||||
/app/Controllers/View/PaymentNotificationController.php:333 matches /Unpaid/i
|
||||
/app/Controllers/View/PaymentNotificationController.php:93 matches /balance\s*=/i
|
||||
/app/Controllers/View/RefundController.php:1007 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1014 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1015 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1028 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1028 matches /refund_paid_amount/i
|
||||
/app/Controllers/View/RefundController.php:1214 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1009 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1016 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1017 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1030 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:1030 matches /refund_paid_amount/i
|
||||
/app/Controllers/View/RefundController.php:1216 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:164 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:168 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:178 matches /Paid/i
|
||||
@@ -333,14 +333,14 @@
|
||||
/app/Controllers/View/RefundController.php:631 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:636 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:660 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:664 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:698 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:698 matches /refund_paid_amount/i
|
||||
/app/Controllers/View/RefundController.php:858 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:862 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:865 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:865 matches /refund_paid_amount/i
|
||||
/app/Controllers/View/RefundController.php:665 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:699 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:699 matches /refund_paid_amount/i
|
||||
/app/Controllers/View/RefundController.php:860 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:864 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:867 matches /Paid/i
|
||||
/app/Controllers/View/RefundController.php:867 matches /refund_paid_amount/i
|
||||
/app/Controllers/View/RefundController.php:869 matches /Paid/i
|
||||
/app/Controllers/View/ReimbursementController.php:1204 matches /Paid/i
|
||||
/app/Controllers/View/ReimbursementController.php:1288 matches /Paid/i
|
||||
/app/Controllers/View/ReimbursementController.php:2038 matches /Paid/i
|
||||
|
||||
@@ -14,6 +14,7 @@ class PaymentModelTest extends ModelCrudTestCase
|
||||
|
||||
if ($model instanceof PaymentModel) {
|
||||
$overrides['transaction_id'] = uniqid('PAY-TEST-', true);
|
||||
$overrides['request_fingerprint_hash'] = hash('sha256', uniqid('payment-model-test-', true));
|
||||
$overrides['payment_method'] = 'cash';
|
||||
$overrides['status'] = 'recorded';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user