chore: strengthen backend eslint profile
This commit is contained in:
@@ -1,9 +1,3 @@
|
||||
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,
|
||||
@@ -28,7 +22,14 @@ import {
|
||||
ValidateIf,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
|
||||
import { MoneyDto } from '../../../../common/money.dto';
|
||||
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';
|
||||
|
||||
export const DEFAULT_BANK_PAGE_SIZE = 50;
|
||||
const MAX_BANK_PAGE_SIZE = 100;
|
||||
@@ -41,6 +42,7 @@ export class RubMoneyInputDto {
|
||||
@ApiProperty({ enum: ['RUB'] }) @IsIn(['RUB']) declare currency: string;
|
||||
@ApiProperty({ pattern: '^-?[0-9]+(\\.[0-9]{1,2})?$' })
|
||||
@IsString()
|
||||
// eslint-disable-next-line security/detect-unsafe-regex -- Anchored decimal grammar: the literal decimal point separates disjoint digit runs; backtracking is linear.
|
||||
@Matches(/^-?\d+(\.\d{1,2})?$/)
|
||||
declare value: string;
|
||||
}
|
||||
@@ -52,6 +54,7 @@ export class CreateBankCardDto {
|
||||
@MinLength(1)
|
||||
@MaxLength(MAX_CARD_NAME_LENGTH)
|
||||
declare name: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
type: String,
|
||||
nullable: true,
|
||||
@@ -61,20 +64,24 @@ export class CreateBankCardDto {
|
||||
@Transform(trim)
|
||||
@IsString()
|
||||
@MaxLength(MAX_CARD_NAME_LENGTH)
|
||||
bankName?: string | null;
|
||||
bankName?: null | string;
|
||||
|
||||
@ApiPropertyOptional({ type: String, nullable: true, pattern: '^[0-9]{4}$' })
|
||||
@IsOptional()
|
||||
@Matches(/^[0-9]{4}$/)
|
||||
lastFour?: string | null;
|
||||
@Matches(/^\d{4}$/)
|
||||
lastFour?: null | string;
|
||||
|
||||
@ApiPropertyOptional({ enum: bankPaymentSystems, nullable: true })
|
||||
@IsOptional()
|
||||
@IsIn(bankPaymentSystems)
|
||||
paymentSystem?: string | null;
|
||||
paymentSystem?: null | string;
|
||||
|
||||
@ApiProperty({ type: RubMoneyInputDto })
|
||||
@IsDefined()
|
||||
@ValidateNested()
|
||||
@Type(() => RubMoneyInputDto)
|
||||
declare openingBalance: MoneyDto;
|
||||
|
||||
@ApiProperty({ format: 'date' })
|
||||
@IsString()
|
||||
@Matches(/^\d{4}-\d{2}-\d{2}$/)
|
||||
@@ -106,28 +113,34 @@ export class CreateBankOperationDto {
|
||||
@ApiProperty({ enum: bankOperationKinds })
|
||||
@IsIn(bankOperationKinds)
|
||||
declare kind: BankOperationKind;
|
||||
|
||||
@ApiProperty({ format: 'uuid' }) @IsUUID() declare cardId: string;
|
||||
@ApiPropertyOptional({ format: 'uuid' })
|
||||
@ValidateIf((_object, value: unknown) => value !== undefined)
|
||||
@IsUUID()
|
||||
targetCardId?: string;
|
||||
|
||||
@ApiPropertyOptional({ format: 'uuid' })
|
||||
@ValidateIf((_object, value: unknown) => value !== undefined)
|
||||
@IsUUID()
|
||||
categoryId?: string;
|
||||
|
||||
@ApiPropertyOptional({ format: 'uuid' })
|
||||
@ValidateIf((_object, value: unknown) => value !== undefined)
|
||||
@IsUUID()
|
||||
originalExpenseId?: string;
|
||||
|
||||
@ApiProperty({ type: RubMoneyInputDto })
|
||||
@IsDefined()
|
||||
@ValidateNested()
|
||||
@Type(() => RubMoneyInputDto)
|
||||
declare amount: MoneyDto;
|
||||
|
||||
@ApiProperty({ format: 'date' })
|
||||
@IsString()
|
||||
@Matches(/^\d{4}-\d{2}-\d{2}$/)
|
||||
declare date: string;
|
||||
|
||||
@ApiPropertyOptional({ maxLength: MAX_OPERATION_DESCRIPTION_LENGTH })
|
||||
@ValidateIf((_object, value: unknown) => value !== undefined)
|
||||
@IsString()
|
||||
@@ -153,6 +166,7 @@ export class BankPageQueryDto {
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
page?: number;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
minimum: 1,
|
||||
maximum: MAX_BANK_PAGE_SIZE,
|
||||
@@ -173,6 +187,7 @@ export class BankPeriodQueryDto {
|
||||
@IsOptional()
|
||||
@Matches(/^\d{4}-(0[1-9]|1[0-2])$/)
|
||||
month?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
format: 'date',
|
||||
description: 'Inclusive start date; requires to.',
|
||||
@@ -180,6 +195,7 @@ export class BankPeriodQueryDto {
|
||||
@IsOptional()
|
||||
@Matches(/^\d{4}-\d{2}-\d{2}$/)
|
||||
from?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
format: 'date',
|
||||
description: 'Inclusive end date; requires from.',
|
||||
@@ -215,16 +231,20 @@ export class BankCardDto {
|
||||
@ApiProperty({ type: String }) declare id: string;
|
||||
@ApiProperty({ type: String }) declare name: string;
|
||||
@ApiProperty({ type: String, nullable: true }) declare bankName:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ type: String, nullable: true }) declare lastFour:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ enum: bankPaymentSystems, nullable: true })
|
||||
declare paymentSystem: string | null;
|
||||
declare paymentSystem: null | string;
|
||||
|
||||
@ApiProperty({ type: MoneyDto }) declare openingBalance: MoneyDto;
|
||||
@ApiProperty({ type: String }) declare openingDate: string;
|
||||
@ApiProperty({ type: MoneyDto }) declare balance: MoneyDto;
|
||||
@ApiProperty({ type: String, nullable: true }) declare archivedAt:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ type: Number }) declare version: number;
|
||||
}
|
||||
export class BankOperationDto {
|
||||
@@ -233,27 +253,35 @@ export class BankOperationDto {
|
||||
@ApiProperty({ type: String }) declare cardId: string;
|
||||
@ApiProperty({ type: String }) declare cardName: string;
|
||||
@ApiProperty({ type: String, nullable: true }) declare targetCardId:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ type: String, nullable: true }) declare targetCardName:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ type: String, nullable: true }) declare categoryId:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ type: String, nullable: true }) declare categoryName:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ type: String, nullable: true }) declare originalExpenseId:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ type: MoneyDto }) declare amount: MoneyDto;
|
||||
@ApiProperty({ type: MoneyDto, nullable: true })
|
||||
declare availableRefund: MoneyDto | null;
|
||||
|
||||
@ApiProperty({ type: String }) declare date: string;
|
||||
@ApiProperty({ type: String, nullable: true }) declare description:
|
||||
string | null;
|
||||
null | string;
|
||||
|
||||
@ApiProperty({ type: Number }) declare version: number;
|
||||
@ApiProperty({ type: String }) declare createdAt: string;
|
||||
}
|
||||
export class BankOperationsPageDto {
|
||||
@ApiProperty({ type: BankOperationDto, isArray: true })
|
||||
declare items: BankOperationDto[];
|
||||
|
||||
@ApiProperty({ type: Number }) declare page: number;
|
||||
@ApiProperty({ type: Number }) declare total: number;
|
||||
@ApiProperty({ type: Boolean }) declare hasNext: boolean;
|
||||
@@ -269,7 +297,7 @@ export class BankSummaryDto {
|
||||
@ApiPropertyOptional({ type: String }) month?: string;
|
||||
@ApiPropertyOptional({ format: 'date' }) from?: string;
|
||||
@ApiPropertyOptional({ format: 'date' }) to?: string;
|
||||
@ApiProperty({ type: String, nullable: true }) declare cardId: string | null;
|
||||
@ApiProperty({ type: String, nullable: true }) declare cardId: null | string;
|
||||
@ApiProperty({ type: MoneyDto }) declare expenses: MoneyDto;
|
||||
@ApiProperty({ type: MoneyDto }) declare refunds: MoneyDto;
|
||||
@ApiProperty({ type: MoneyDto }) declare net: MoneyDto;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { Request } from 'express';
|
||||
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
@@ -21,12 +23,16 @@ import {
|
||||
ApiTags,
|
||||
getSchemaPath,
|
||||
} from '@nestjs/swagger';
|
||||
import type { Request } from 'express';
|
||||
|
||||
import {
|
||||
ApiProblemResponses,
|
||||
ProblemDetailsDto,
|
||||
} from '../../../../common/decorators/api-safe-error-response.decorator';
|
||||
import { AccessPayload, JwtAuthGuard } from '../../../auth/auth.api';
|
||||
import { BankCardsService } from '../application/bank-cards.service';
|
||||
import { BankOperationsService } from '../application/bank-operations.service';
|
||||
import { ExpenseCategoriesService } from '../application/expense-categories.service';
|
||||
import { GetBankSummaryUseCase } from '../application/get-bank-summary.use-case';
|
||||
import {
|
||||
BankCardDto,
|
||||
BankCardsQueryDto,
|
||||
@@ -45,10 +51,6 @@ import {
|
||||
UpdateBankOperationDto,
|
||||
UpdateExpenseCategoryDto,
|
||||
} from './bank-card.dto';
|
||||
import { BankCardsService } from '../application/bank-cards.service';
|
||||
import { BankOperationsService } from '../application/bank-operations.service';
|
||||
import { ExpenseCategoriesService } from '../application/expense-categories.service';
|
||||
import { GetBankSummaryUseCase } from '../application/get-bank-summary.use-case';
|
||||
type AuthRequest = Request & { user: AccessPayload };
|
||||
@ApiResponse({
|
||||
status: 409,
|
||||
@@ -82,26 +84,31 @@ export class BankCardsController {
|
||||
private readonly expenseCategories: ExpenseCategoriesService,
|
||||
private readonly bankSummary: GetBankSummaryUseCase,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@ApiOkResponse({ type: BankCardDto, isArray: true })
|
||||
list(@Req() req: AuthRequest, @Query() query: BankCardsQueryDto) {
|
||||
return this.cards.list(req.user.sub, query.includeArchived === 'true');
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiCreatedResponse({ type: BankCardDto })
|
||||
create(@Req() req: AuthRequest, @Body() body: CreateBankCardDto) {
|
||||
return this.cards.createCard(req.user.sub, body);
|
||||
}
|
||||
|
||||
@Get('categories')
|
||||
@ApiOkResponse({ type: ExpenseCategoryDto, isArray: true })
|
||||
categories(@Req() req: AuthRequest) {
|
||||
return this.expenseCategories.categories(req.user.sub);
|
||||
}
|
||||
|
||||
@Post('categories')
|
||||
@ApiCreatedResponse({ type: ExpenseCategoryDto })
|
||||
createCategory(@Req() req: AuthRequest, @Body() body: CategoryNameDto) {
|
||||
return this.expenseCategories.createCategory(req.user.sub, body.name);
|
||||
}
|
||||
|
||||
@Patch('categories/:id')
|
||||
@ApiOkResponse({ type: ExpenseCategoryDto })
|
||||
updateCategory(
|
||||
@@ -116,11 +123,13 @@ export class BankCardsController {
|
||||
body.version,
|
||||
);
|
||||
}
|
||||
|
||||
@Get('summary')
|
||||
@ApiOkResponse({ type: BankSummaryDto })
|
||||
summary(@Req() req: AuthRequest, @Query() query: BankSummaryQueryDto) {
|
||||
return this.bankSummary.execute(req.user.sub, query);
|
||||
}
|
||||
|
||||
@Post('operations')
|
||||
@ApiCreatedResponse({ type: BankOperationDto })
|
||||
createOperation(
|
||||
@@ -129,11 +138,13 @@ export class BankCardsController {
|
||||
) {
|
||||
return this.operations.createOperation(req.user.sub, body);
|
||||
}
|
||||
|
||||
@Get('operations/:id')
|
||||
@ApiOkResponse({ type: BankOperationDto })
|
||||
operation(@Req() req: AuthRequest, @Param('id') id: string) {
|
||||
return this.operations.getOperation(req.user.sub, id);
|
||||
}
|
||||
|
||||
@Patch('operations/:id')
|
||||
@ApiOkResponse({ type: BankOperationDto })
|
||||
updateOperation(
|
||||
@@ -143,6 +154,7 @@ export class BankCardsController {
|
||||
) {
|
||||
return this.operations.updateOperation(req.user.sub, id, body);
|
||||
}
|
||||
|
||||
@Delete('operations/:id')
|
||||
@HttpCode(HttpStatus.NO_CONTENT)
|
||||
@ApiNoContentResponse()
|
||||
@@ -153,6 +165,7 @@ export class BankCardsController {
|
||||
) {
|
||||
return this.operations.deleteOperation(req.user.sub, id, query.version);
|
||||
}
|
||||
|
||||
@Get(':id/operations')
|
||||
@ApiOkResponse({ type: BankOperationsPageDto })
|
||||
history(
|
||||
@@ -162,6 +175,7 @@ export class BankCardsController {
|
||||
) {
|
||||
return this.operations.history(req.user.sub, id, query);
|
||||
}
|
||||
|
||||
@Get(':id/expenses')
|
||||
@ApiOkResponse({ type: BankOperationsPageDto })
|
||||
expenses(
|
||||
@@ -171,11 +185,13 @@ export class BankCardsController {
|
||||
) {
|
||||
return this.operations.history(req.user.sub, id, query, true);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOkResponse({ type: BankCardDto })
|
||||
get(@Req() req: AuthRequest, @Param('id') id: string) {
|
||||
return this.cards.get(req.user.sub, id);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
@ApiOkResponse({ type: BankCardDto })
|
||||
update(
|
||||
|
||||
Reference in New Issue
Block a user