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); } }