Files
backend/src/modules/banking/bank-cards/presentation/bank-cards.controller.ts
T
codex-bot 02e0d560c8
Backend verify / commits (push) Skipped
Backend verify / security (push) Successful in 1m12s
Backend verify / verify (push) Failing after 7m27s
refactor(api): describe bank operation create body as oneOf by kind (WealthLedger/backend#172) (#173)
2026-11-04 17:47:36 +03:00

219 lines
5.7 KiB
TypeScript

import type { Request } from 'express';
import {
Body,
Controller,
Delete,
Get,
HttpCode,
HttpStatus,
Param,
Patch,
Post,
Query,
Req,
UseGuards,
} from '@nestjs/common';
import {
ApiBearerAuth,
ApiBody,
ApiCreatedResponse,
ApiExtraModels,
ApiNoContentResponse,
ApiOkResponse,
ApiResponse,
ApiTags,
getSchemaPath,
} from '@nestjs/swagger';
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,
BankOperationDto,
BankOperationsPageDto,
BankOperationsQueryDto,
BankPageQueryDto,
BankSummaryDto,
BankSummaryQueryDto,
BankVersionQueryDto,
CategoryNameDto,
CreateBankCardDto,
CreateBankOperationDto,
createBankOperationSchema,
CreateExpenseOperationDto,
CreateRefundOperationDto,
CreateTopupOperationDto,
CreateTransferOperationDto,
ExpenseCategoryDto,
UpdateBankCardDto,
UpdateBankOperationDto,
UpdateExpenseCategoryDto,
} from './bank-card.dto';
type AuthRequest = Request & { user: AccessPayload };
@ApiResponse({
status: 409,
description:
'BANK_CARD_ARCHIVED, BANK_VERSION_CONFLICT, BANK_INTENT_CONFLICT, BANK_REFUND_LIMIT, BANK_DEPENDENT_REFUNDS, BANK_DUPLICATE_CATEGORY or BANK_WRITE_CONFLICT',
content: {
'application/problem+json': {
schema: { $ref: getSchemaPath(ProblemDetailsDto) },
},
},
})
@ApiResponse({
status: 410,
description:
'BANK_OPERATION_DELETED: creation replay refers to a deleted operation',
content: {
'application/problem+json': {
schema: { $ref: getSchemaPath(ProblemDetailsDto) },
},
},
})
@ApiTags('bank-cards')
@ApiExtraModels(
CreateExpenseOperationDto,
CreateTopupOperationDto,
CreateTransferOperationDto,
CreateRefundOperationDto,
)
@ApiBearerAuth()
@ApiProblemResponses()
@UseGuards(JwtAuthGuard)
@Controller('bank-cards')
export class BankCardsController {
constructor(
private readonly cards: BankCardsService,
private readonly operations: BankOperationsService,
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(
@Req() req: AuthRequest,
@Param('id') id: string,
@Body() body: UpdateExpenseCategoryDto,
) {
return this.expenseCategories.updateCategory(
req.user.sub,
id,
body.name,
body.version,
);
}
@Get('summary')
@ApiOkResponse({ type: BankSummaryDto })
summary(@Req() req: AuthRequest, @Query() query: BankSummaryQueryDto) {
return this.bankSummary.execute(req.user.sub, query);
}
@Post('operations')
@ApiBody({ schema: createBankOperationSchema })
@ApiCreatedResponse({ type: BankOperationDto })
createOperation(
@Req() req: AuthRequest,
@Body() body: CreateBankOperationDto,
) {
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(
@Req() req: AuthRequest,
@Param('id') id: string,
@Body() body: UpdateBankOperationDto,
) {
return this.operations.updateOperation(req.user.sub, id, body);
}
@Delete('operations/:id')
@HttpCode(HttpStatus.NO_CONTENT)
@ApiNoContentResponse()
deleteOperation(
@Req() req: AuthRequest,
@Param('id') id: string,
@Query() query: BankVersionQueryDto,
) {
return this.operations.deleteOperation(req.user.sub, id, query.version);
}
@Get(':id/operations')
@ApiOkResponse({ type: BankOperationsPageDto })
history(
@Req() req: AuthRequest,
@Param('id') id: string,
@Query() query: BankOperationsQueryDto,
) {
return this.operations.history(req.user.sub, id, query);
}
@Get(':id/expenses')
@ApiOkResponse({ type: BankOperationsPageDto })
expenses(
@Req() req: AuthRequest,
@Param('id') id: string,
@Query() query: BankPageQueryDto,
) {
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(
@Req() req: AuthRequest,
@Param('id') id: string,
@Body() body: UpdateBankCardDto,
) {
return this.cards.updateCard(req.user.sub, id, body);
}
}