From b4bd65dea49e3df6cd5b8001a2f081438d75de8e Mon Sep 17 00:00:00 2001 From: Andrew Radulescu Date: Thu, 12 Sep 2024 15:27:58 +0300 Subject: [PATCH] feat: [Contracts] API - Approve contract by NGO --- .../documents/document-contract.controller.ts | 26 +++++++++--- .../services/document-contract.facade.ts | 9 +++++ ...pprove-document-contract-by-ngo.usecase.ts | 40 +++++++++++++++++++ backend/src/usecases/use-case.module.ts | 2 + 4 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 backend/src/usecases/documents/new_contracts/approve-document-contract-by-ngo.usecase.ts diff --git a/backend/src/api/documents/document-contract.controller.ts b/backend/src/api/documents/document-contract.controller.ts index cffdad15..d2e37b65 100644 --- a/backend/src/api/documents/document-contract.controller.ts +++ b/backend/src/api/documents/document-contract.controller.ts @@ -1,4 +1,13 @@ -import { Body, Controller, Get, Post, Query, UseGuards } from '@nestjs/common'; +import { + Body, + Controller, + Get, + Param, + Patch, + Post, + Query, + UseGuards, +} from '@nestjs/common'; import { CreateDocumentContractUsecase } from 'src/usecases/documents/new_contracts/create-document-contract.usecase'; import { CreateDocumentContractDto } from './dto/create-document-contract.dto'; import { IAdminUserModel } from 'src/modules/user/models/admin-user.model'; @@ -13,6 +22,8 @@ import { PaginatedPresenter, } from 'src/infrastructure/presenters/generic-paginated.presenter'; import { GetManyDocumentContractsDto } from './dto/get-many-document-contracts.dto'; +import { UuidValidationPipe } from 'src/infrastructure/pipes/uuid.pipe'; +import { ApproveDocumentContractByNgoUsecase } from 'src/usecases/documents/new_contracts/approve-document-contract-by-ngo.usecase'; @ApiBearerAuth() @UseGuards(WebJwtAuthGuard) @@ -21,6 +32,7 @@ export class DocumentContractController { constructor( private readonly createDocumentContractUsecase: CreateDocumentContractUsecase, private readonly getManyDocumentContractsUsecase: GetManyDocumentContractsUsecase, + private readonly approveDocumentContractByNgoUsecase: ApproveDocumentContractByNgoUsecase, ) {} @Post() @@ -56,9 +68,11 @@ export class DocumentContractController { }); } - /* TODO: GET /documents/contracts/check?year={year}&documentNumber={documentNumber} - CHECK IF A CONTRACT ALREADY EXISTS FOR THE GIVEN YEAR AND DOCUMENT NUMBER IN THE SAME ORGANIZATION - RETURN TRUE IF IT EXISTS, FALSE OTHERWISE - USED TO PREVENT DUPLICATE DOCUMENT NUMBERS IN THE SAME YEAR - */ + @Patch(':id/approve') + async approveDocumentContract( + @Param('id', UuidValidationPipe) id: string, + @ExtractUser() { organizationId }: IAdminUserModel, + ): Promise { + await this.approveDocumentContractByNgoUsecase.execute(id, organizationId); + } } diff --git a/backend/src/modules/documents/services/document-contract.facade.ts b/backend/src/modules/documents/services/document-contract.facade.ts index 18bedf72..c754b7d8 100644 --- a/backend/src/modules/documents/services/document-contract.facade.ts +++ b/backend/src/modules/documents/services/document-contract.facade.ts @@ -13,6 +13,7 @@ import { IDocumentContractListViewModel, } from '../models/document-contract-list-view.model'; import { Pagination } from 'src/infrastructure/base/repository-with-pagination.class'; +import { DocumentContractStatus } from '../enums/contract-status.enum'; @Injectable() export class DocumentContractFacade { @@ -21,6 +22,14 @@ export class DocumentContractFacade { private readonly documentContractListViewRepository: DocumentContractListViewRepository, ) {} + async approveDocumentContractByNGO( + documentContractId: string, + ): Promise { + return this.documentContractRepository.update(documentContractId, { + status: DocumentContractStatus.PENDING_NGO_REPRESENTATIVE_SIGNATURE, + }); + } + async create( newDocumentContract: CreateDocumentContractOptions, ): Promise { diff --git a/backend/src/usecases/documents/new_contracts/approve-document-contract-by-ngo.usecase.ts b/backend/src/usecases/documents/new_contracts/approve-document-contract-by-ngo.usecase.ts new file mode 100644 index 00000000..43e4c2c1 --- /dev/null +++ b/backend/src/usecases/documents/new_contracts/approve-document-contract-by-ngo.usecase.ts @@ -0,0 +1,40 @@ +import { Injectable } from '@nestjs/common'; +import { ExceptionsService } from 'src/infrastructure/exceptions/exceptions.service'; +import { DocumentContractStatus } from 'src/modules/documents/enums/contract-status.enum'; +import { ContractExceptionMessages } from 'src/modules/documents/exceptions/contract.exceptions'; +import { DocumentContractFacade } from 'src/modules/documents/services/document-contract.facade'; + +@Injectable() +export class ApproveDocumentContractByNgoUsecase { + constructor( + private readonly documentContractFacade: DocumentContractFacade, + private readonly exceptionService: ExceptionsService, + ) {} + + async execute( + documentContractId: string, + organizationId: string, + ): Promise { + const exists = await this.documentContractFacade.exists({ + id: documentContractId, + organizationId, + status: DocumentContractStatus.PENDING_APPROVAL_NGO, + }); + + if (!exists) { + this.exceptionService.notFoundException( + ContractExceptionMessages.CONTRACT_002, + ); + } + try { + await this.documentContractFacade.approveDocumentContractByNGO( + documentContractId, + ); + } catch (error) { + this.exceptionService.internalServerErrorException({ + message: `Error while approving the contract by NGO ${error?.message}`, + code_error: 'APPROVE_DOCUMENT_CONTRACT_BY_NGO_001', + }); + } + } +} diff --git a/backend/src/usecases/use-case.module.ts b/backend/src/usecases/use-case.module.ts index 2cb925f0..b19dd4b6 100644 --- a/backend/src/usecases/use-case.module.ts +++ b/backend/src/usecases/use-case.module.ts @@ -147,6 +147,7 @@ import { RejectDocumentContractByVolunteerUsecase } from './documents/new_contra import { GeneratePDFsUseCase } from './documents/new_contracts/generate-pdfs.usecase'; import { GetManyDocumentContractsByVolunteerUsecase } from './documents/new_contracts/get-many-document-contracts-by-volunteer.usecase'; import { GetOneDocumentContractForVolunteerUsecase } from './documents/new_contracts/get-one-document-contract-for-volunteer.usecase'; +import { ApproveDocumentContractByNgoUsecase } from './documents/new_contracts/approve-document-contract-by-ngo.usecase'; const providers = [ // Organization @@ -300,6 +301,7 @@ const providers = [ RejectDocumentContractByVolunteerUsecase, GetManyDocumentContractsByVolunteerUsecase, GetOneDocumentContractForVolunteerUsecase, + ApproveDocumentContractByNgoUsecase, // Notifications UpdateSettingsUsecase, // Testing PDFs