refactor: centralize domain values and enforce numeric lint

This commit is contained in:
2026-09-13 14:37:39 +03:00
parent 8ba005346d
commit 8637ad2f34
44 changed files with 543 additions and 174 deletions
@@ -1,3 +1,9 @@
import {
MAX_CARD_NAME_LENGTH,
MAX_CATEGORY_NAME_LENGTH,
MAX_OPERATION_DESCRIPTION_LENGTH,
} from '../domain/bank-card-limits';
import { BankOperationKind } from '../domain/bank-operation-kind';
import {
ApiProperty,
ApiPropertyOptional,
@@ -24,16 +30,13 @@ import {
} from 'class-validator';
import { MoneyDto } from '../../../../common/money.dto';
export const DEFAULT_BANK_PAGE_SIZE = 50;
const MAX_BANK_PAGE_SIZE = 100;
const trim = ({ value }: { value: unknown }) =>
typeof value === 'string' ? value.trim() : value;
export const bankPaymentSystems = ['mir', 'visa', 'mastercard'] as const;
export const bankOperationKinds = [
'expense',
'topup',
'transfer',
'refund',
] as const;
export type BankOperationKind = (typeof bankOperationKinds)[number];
const bankOperationKinds = Object.values(BankOperationKind);
export class RubMoneyInputDto {
@ApiProperty({ enum: ['RUB'] }) @IsIn(['RUB']) declare currency: string;
@ApiProperty({ pattern: '^-?[0-9]+(\\.[0-9]{1,2})?$' })
@@ -43,17 +46,21 @@ export class RubMoneyInputDto {
}
export class CreateBankCardDto {
@ApiProperty({ format: 'uuid' }) @IsUUID() declare id: string;
@ApiProperty({ minLength: 1, maxLength: 100 })
@ApiProperty({ minLength: 1, maxLength: MAX_CARD_NAME_LENGTH })
@Transform(trim)
@IsString()
@MinLength(1)
@MaxLength(100)
@MaxLength(MAX_CARD_NAME_LENGTH)
declare name: string;
@ApiPropertyOptional({ type: String, nullable: true, maxLength: 100 })
@ApiPropertyOptional({
type: String,
nullable: true,
maxLength: MAX_CARD_NAME_LENGTH,
})
@IsOptional()
@Transform(trim)
@IsString()
@MaxLength(100)
@MaxLength(MAX_CARD_NAME_LENGTH)
bankName?: string | null;
@ApiPropertyOptional({ type: String, nullable: true, pattern: '^[0-9]{4}$' })
@IsOptional()
@@ -84,11 +91,11 @@ export class UpdateBankCardDto extends PartialType(
archived?: boolean;
}
export class CategoryNameDto {
@ApiProperty({ minLength: 1, maxLength: 80 })
@ApiProperty({ minLength: 1, maxLength: MAX_CATEGORY_NAME_LENGTH })
@Transform(trim)
@IsString()
@MinLength(1)
@MaxLength(80)
@MaxLength(MAX_CATEGORY_NAME_LENGTH)
declare name: string;
}
export class UpdateExpenseCategoryDto extends CategoryNameDto {
@@ -121,10 +128,10 @@ export class CreateBankOperationDto {
@IsString()
@Matches(/^\d{4}-\d{2}-\d{2}$/)
declare date: string;
@ApiPropertyOptional({ maxLength: 500 })
@ApiPropertyOptional({ maxLength: MAX_OPERATION_DESCRIPTION_LENGTH })
@ValidateIf((_object, value: unknown) => value !== undefined)
@IsString()
@MaxLength(500)
@MaxLength(MAX_OPERATION_DESCRIPTION_LENGTH)
description?: string;
}
export class UpdateBankOperationDto extends PartialType(
@@ -146,12 +153,16 @@ export class BankPageQueryDto {
@IsInt()
@Min(1)
page?: number;
@ApiPropertyOptional({ minimum: 1, maximum: 100, default: 50 })
@ApiPropertyOptional({
minimum: 1,
maximum: MAX_BANK_PAGE_SIZE,
default: DEFAULT_BANK_PAGE_SIZE,
})
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
@Max(100)
@Max(MAX_BANK_PAGE_SIZE)
limit?: number;
}
export class BankPeriodQueryDto {
@@ -4,6 +4,7 @@ import {
Delete,
Get,
HttpCode,
HttpStatus,
Param,
Patch,
Post,
@@ -143,7 +144,7 @@ export class BankCardsController {
return this.operations.updateOperation(req.user.sub, id, body);
}
@Delete('operations/:id')
@HttpCode(204)
@HttpCode(HttpStatus.NO_CONTENT)
@ApiNoContentResponse()
deleteOperation(
@Req() req: AuthRequest,