import moment from 'moment'; import { Column, CreateDateColumn, DeleteDateColumn, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; import { Guardian } from '~/guardian/entities/guradian.entity'; import { Junior } from '~/junior/entities'; import { AllowanceFrequency, AllowanceType } from '../enums'; import { AllowanceChangeRequest } from './allowance-change-request.entity'; @Entity('allowances') export class Allowance { @PrimaryGeneratedColumn('uuid') id!: string; @Column({ type: 'varchar', length: 255, name: 'name' }) name!: string; @Column({ type: 'decimal', precision: 10, scale: 2, name: 'amount', transformer: { to: (value: number) => value, from: (value: string) => parseFloat(value) }, }) amount!: number; @Column({ type: 'varchar', length: 255, name: 'frequency' }) frequency!: AllowanceFrequency; @Column({ type: 'varchar', length: 255, name: 'type' }) type!: AllowanceType; @Column({ type: 'timestamp with time zone', name: 'start_date' }) startDate!: Date; @Column({ type: 'timestamp with time zone', name: 'end_date', nullable: true }) endDate?: Date; @Column({ type: 'int', name: 'number_of_transactions', nullable: true }) numberOfTransactions?: number; @Column({ type: 'uuid', name: 'guardian_id' }) guardianId!: string; @Column({ type: 'uuid', name: 'junior_id' }) juniorId!: string; @ManyToOne(() => Guardian, (guardian) => guardian.allowances) @JoinColumn({ name: 'guardian_id' }) guardian!: Guardian; @ManyToOne(() => Junior, (junior) => junior.allowances) @JoinColumn({ name: 'junior_id' }) junior!: Junior; @OneToMany(() => AllowanceChangeRequest, (changeRequest) => changeRequest.allowance) changeRequests!: AllowanceChangeRequest[]; @CreateDateColumn({ name: 'created_at', type: 'timestamp with time zone', default: () => 'CURRENT_TIMESTAMP' }) createdAt!: Date; @UpdateDateColumn({ name: 'updated_at', type: 'timestamp with time zone', default: () => 'CURRENT_TIMESTAMP' }) updatedAt!: Date; @DeleteDateColumn({ name: 'deleted_at', type: 'timestamp with time zone', nullable: true }) deletedAt?: Date; get nextPaymentDate(): Date | null { const startDate = moment(this.startDate).clone().startOf('day'); const endDate = this.endDate ? moment(this.endDate).endOf('day') : null; const now = moment().startOf('day'); if (endDate && moment().isAfter(endDate)) { return null; } const calculateNextDate = (unit: moment.unitOfTime.Diff) => { const diff = now.diff(startDate, unit); const nextDate = startDate.clone().add(diff, unit); const adjustedDate = nextDate.isSameOrAfter(now) ? nextDate : nextDate.add('1', unit); if (endDate && adjustedDate.isAfter(endDate)) { return null; } return adjustedDate.toDate(); }; switch (this.frequency) { case AllowanceFrequency.DAILY: return calculateNextDate('days'); case AllowanceFrequency.WEEKLY: return calculateNextDate('weeks'); case AllowanceFrequency.MONTHLY: return calculateNextDate('months'); default: return null; } } }