P2-14: Deposit installment tracking + refund approval flow

- Add DepositInstallment entity (id, depositId, amount, dueDate, paidDate, status, createdAt)
- Add installments OneToMany relation to Deposit entity with cascade+eager
- Add refund approval fields: refundStatus, refundRequestedAt, refundApprovedBy, refundApprovedAt
- Add installment DTOs (CreateInstallmentDto, UpdateInstallmentDto)
- Add refund approval DTOs (ApproveRefundDto, CreateDepositWithInstallmentsDto)
- Service: add/create/update/delete installments, requestRefund, approveRefund, findPendingRefunds
- Controller: GET deposits/:id, GET pending-refunds, POST :id/installments, PUT installments/:id, DELETE installments/:id, POST :id/request-refund, PUT :id/approve-refund
- Frontend: detail modal with installment list, refund request button, pending refunds tab with approve actions
This commit is contained in:
2026-07-05 20:46:05 +08:00
parent 5df70a8af0
commit ab4adf1174
8 changed files with 645 additions and 82 deletions

View File

@@ -4,9 +4,11 @@ import {
Column,
CreateDateColumn,
ManyToOne,
OneToMany,
JoinColumn,
} from 'typeorm';
import { Student } from './student.entity';
import { DepositInstallment } from './deposit-installment.entity';
@Entity('deposits')
export class Deposit {
@@ -44,10 +46,26 @@ export class Deposit {
@Column({ name: 'recorded_by', nullable: true })
recordedBy: number;
@Column({ name: 'refund_status', length: 30, nullable: true })
refundStatus: string | null; // pending | head_teacher_approved | finance_approved | refunded
@Column({ name: 'refund_requested_at', nullable: true })
refundRequestedAt: Date | null;
@Column({ name: 'refund_approved_by', type: 'integer', nullable: true })
refundApprovedBy: number | null;
@Column({ name: 'refund_approved_at', nullable: true })
refundApprovedAt: Date | null;
@OneToMany(() => DepositInstallment, (i) => i.deposit, { cascade: true, eager: true })
installments: DepositInstallment[];
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@ManyToOne(() => Student, { eager: true })
@JoinColumn({ name: 'student_id' })
student: Student;
}