refactor(deposits): remove inline installment creation

This commit is contained in:
2026-07-13 14:02:00 +08:00
parent 0515e6ed27
commit 04ef5c42d9
4 changed files with 23 additions and 32 deletions

View File

@@ -16,7 +16,7 @@ import { Student } from '../entities/student.entity';
import { DepositsService } from './deposits.service';
import { NotificationsService } from '../notifications/notifications.service';
import { NotificationType } from '../entities/notification.entity';
import { CreateDepositDto, RefundDepositDto, CreateDepositWithInstallmentsDto } from './dto/deposit.dto';
import { CreateDepositDto, RefundDepositDto } from './dto/deposit.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { OperationLogsService } from '../operation-logs/operation-logs.service';
import { extractRequestInfo } from '../common/request-utils';
@@ -61,7 +61,7 @@ export class DepositsController {
@Post()
@RequirePermission('deposit:create')
async create(@Body() dto: CreateDepositDto | CreateDepositWithInstallmentsDto, @Request() req: any) {
async create(@Body() dto: CreateDepositDto, @Request() req: any) {
const { ipAddress, userAgent } = extractRequestInfo(req);
const result = await this.service.create(dto, req.user?.id);
await this.logService.log({

View File

@@ -5,7 +5,7 @@ import { Deposit } from '../entities/deposit.entity';
import { Student } from '../entities/student.entity';
import { DepositInstallment } from '../entities/deposit-installment.entity';
import { CreateDepositDto, RefundDepositDto, CreateDepositWithInstallmentsDto } from './dto/deposit.dto';
import { CreateDepositDto, RefundDepositDto } from './dto/deposit.dto';
@Injectable()
export class DepositsService {
@@ -55,17 +55,6 @@ export class DepositsService {
recordedBy: userId,
});
if (dto instanceof CreateDepositWithInstallmentsDto && dto.installments?.length) {
deposit.installments = dto.installments.map((i) => {
const inst = this.installmentRepo.create({
amount: i.amount,
dueDate: i.dueDate,
status: 'pending',
});
return inst;
});
}
return this.repo.save(deposit);
}

View File

@@ -0,0 +1,19 @@
import 'reflect-metadata';
import { validate } from 'class-validator';
import { CreateDepositDto } from './deposit.dto';
describe('CreateDepositDto boundaries', () => {
it('removes inline installments because they are managed after deposit creation', async () => {
const dto = Object.assign(new CreateDepositDto(), {
studentId: 1,
amount: 500,
paidDate: '2026-07-13',
installments: [{ amount: 250, dueDate: '2026-08-01' }],
});
await validate(dto, { whitelist: true });
expect(dto).toMatchObject({ studentId: 1, amount: 500, paidDate: '2026-07-13' });
expect(dto).not.toHaveProperty('installments');
});
});

View File

@@ -1,5 +1,4 @@
import { IsInt, IsNumber, IsString, IsOptional, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
import { IsInt, IsNumber, IsString, IsOptional } from 'class-validator';
export class CreateDepositDto {
@IsInt()
@@ -16,16 +15,6 @@ export class CreateDepositDto {
notes?: string;
}
export class CreateInstallmentDto {
@IsNumber()
amount: number;
@IsString()
dueDate: string;
}
export class RefundDepositDto {
@IsString()
refundDate: string;
@@ -42,9 +31,3 @@ export class RefundDepositDto {
@IsString()
notes?: string;
}
export class CreateDepositWithInstallmentsDto extends CreateDepositDto {
@IsOptional()
@ValidateNested({ each: true })
@Type(() => CreateInstallmentDto)
installments?: CreateInstallmentDto[];
}