Skip to content

Commit

Permalink
feat: [Contracts] API - Delete template and reject contract by NGO
Browse files Browse the repository at this point in the history
  • Loading branch information
radulescuandrew committed Sep 16, 2024
1 parent 5ff75d5 commit 78cf3e0
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 7 deletions.
20 changes: 18 additions & 2 deletions backend/src/api/documents/document-contract.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import {
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';
import { SignDocumentContractByNGO } from 'src/usecases/documents/new_contracts/sign-document-contract-by-ngo.usecase';
import { SignDocumentContractByNgoUsecase } from 'src/usecases/documents/new_contracts/sign-document-contract-by-ngo.usecase';
import { RejectDocumentContractByNgoUsecase } from 'src/usecases/documents/new_contracts/reject-document-contract-by-ngo.usecase';
import { RejectDocumentContractByNgoDTO } from './dto/reject-document-contract.dto';

@ApiBearerAuth()
@UseGuards(WebJwtAuthGuard)
Expand All @@ -34,7 +36,8 @@ export class DocumentContractController {
private readonly createDocumentContractUsecase: CreateDocumentContractUsecase,
private readonly getManyDocumentContractsUsecase: GetManyDocumentContractsUsecase,
private readonly approveDocumentContractByNgoUsecase: ApproveDocumentContractByNgoUsecase,
private readonly signDocumentContractByNGO: SignDocumentContractByNGO,
private readonly rejectDocumentContractByNgoUsecase: RejectDocumentContractByNgoUsecase,
private readonly signDocumentContractByNGO: SignDocumentContractByNgoUsecase,
) {}

@Post()
Expand Down Expand Up @@ -85,4 +88,17 @@ export class DocumentContractController {
): Promise<void> {
await this.signDocumentContractByNGO.execute(id, organizationId);
}

@Patch(':id/reject')
async rejectDocumentContract(
@Param('id', UuidValidationPipe) id: string,
@ExtractUser() { organizationId }: IAdminUserModel,
@Body() { rejectionReason }: RejectDocumentContractByNgoDTO,
): Promise<void> {
await this.rejectDocumentContractByNgoUsecase.execute({
documentContractId: id,
organizationId,
rejectionReason: rejectionReason,
});
}
}
12 changes: 12 additions & 0 deletions backend/src/api/documents/document-template.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Expand All @@ -23,6 +24,7 @@ import {
ApiPaginatedResponse,
PaginatedPresenter,
} from 'src/infrastructure/presenters/generic-paginated.presenter';
import { DeleteDocumentTemplateUsecase } from 'src/usecases/documents/new_contracts/delete-document-template.usecase';

@ApiBearerAuth()
@UseGuards(WebJwtAuthGuard)
Expand All @@ -32,6 +34,7 @@ export class DocumentTemplateController {
private readonly createDocumentTemplateUsecase: CreateDocumentTemplateUsecase,
private readonly getOneDocumentTemplateUsecase: GetOneDocumentTemplateUseCase,
private readonly getManyDocumentTemplatesUsecase: GetManyDocumentTemplatesUsecase,
private readonly deleteDocumentTemplateUsecase: DeleteDocumentTemplateUsecase,
) {}

@ApiBody({ type: CreateDocumentTemplateDto })
Expand Down Expand Up @@ -63,6 +66,15 @@ export class DocumentTemplateController {
return new DocumentTemplatePresenter(documentTemplate);
}

@ApiParam({ name: 'id', type: 'string' })
@Delete(':id')
async delete(
@Param('id', UuidValidationPipe) id: string,
@ExtractUser() { organizationId }: IAdminUserModel,
): Promise<string> {
return this.deleteDocumentTemplateUsecase.execute(id, organizationId);
}

@Get()
@ApiPaginatedResponse(DocumentTemplateListViewItemPresenter)
async getMany(
Expand Down
7 changes: 7 additions & 0 deletions backend/src/api/documents/dto/reject-document-contract.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IsOptional, IsString } from 'class-validator';

export class RejectDocumentContractByNgoDTO {
@IsString()
@IsOptional()
rejectionReason: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export type UpdateDocumentContractOptions = {
export type FindOneDocumentContractOptions = Partial<
Pick<
IDocumentContractModel,
'id' | 'volunteerId' | 'organizationId' | 'status'
'id' | 'volunteerId' | 'organizationId' | 'status' | 'documentTemplateId'
>
>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export type FindOneDocumentTemplateOptions = Partial<
Pick<IDocumentTemplateModel, 'id' | 'organizationId'>
>;

export type DeleteOneDocumentTemplateOptions = {
id: string;
organizationId: string;
};

export class DocumentTemplateTransformer {
static fromEntity(entity: DocumentTemplateEntity): IDocumentTemplateModel {
if (!entity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { DocumentTemplateEntity } from '../entities/document-template.entity';
import { IDocumentTemplateRepository } from '../interfaces/document-template-repository.interface';
import {
CreateDocumentTemplateOptions,
DeleteOneDocumentTemplateOptions,
DocumentTemplateTransformer,
FindOneDocumentTemplateOptions,
IDocumentTemplateModel,
Expand Down Expand Up @@ -43,4 +44,15 @@ export class DocumentTemplateRepositoryService

return DocumentTemplateTransformer.fromEntity(documentTemplate);
}

async delete(options: DeleteOneDocumentTemplateOptions): Promise<string> {
const template = await this.documentTemplateRepository.findOneBy(options);

if (template) {
await this.documentTemplateRepository.remove(template);
return options.id;
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
import { DocumentTemplateRepositoryService } from '../repositories/document-template.repository';
import {
CreateDocumentTemplateOptions,
DeleteOneDocumentTemplateOptions,
FindOneDocumentTemplateOptions,
IDocumentTemplateModel,
} from '../models/document-template.model';
Expand Down Expand Up @@ -36,4 +37,8 @@ export class DocumentTemplateFacade {
): Promise<Pagination<IDocumentTemplateListViewModel>> {
return this.documentTemplateListViewRepository.findMany(findOptions);
}

async delete(options: DeleteOneDocumentTemplateOptions): Promise<string> {
return this.documentTemplateRepository.delete(options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Injectable, Logger } from '@nestjs/common';
import { JSONStringifyError } from 'src/common/helpers/utils';
import { IUseCaseService } from 'src/common/interfaces/use-case-service.interface';
import { ExceptionsService } from 'src/infrastructure/exceptions/exceptions.service';
import { DocumentTemplateExceptionMessages } from 'src/modules/documents/exceptions/documente-template.exceptions';
import { DocumentContractFacade } from 'src/modules/documents/services/document-contract.facade';
import { DocumentTemplateFacade } from 'src/modules/documents/services/document-template.facade';

@Injectable()
export class DeleteDocumentTemplateUsecase implements IUseCaseService<string> {
private readonly logger = new Logger(DeleteDocumentTemplateUsecase.name);
constructor(
private readonly documentTemplateFacade: DocumentTemplateFacade,
private readonly documentContractFacade: DocumentContractFacade,
private readonly exceptionService: ExceptionsService,
) {}

public async execute(id: string, organizationId: string): Promise<string> {
try {
// 1. Templates can be deleted if are not linked with a contract
const isUsed = await this.documentContractFacade.exists({
documentTemplateId: id,
organizationId: organizationId,
});

if (isUsed) {
this.exceptionService.badRequestException({
message: 'Used templates cannot be deleted',
code_error: 'DELETE_DOCUMENT_TEMPLATE_USED',
});
}

// 2. Try to delete it
const deleted = await this.documentTemplateFacade.delete({
id,
organizationId,
});

if (!deleted) {
this.exceptionService.badRequestException({
message:
'The template does not exist or is not part of your organization',
code_error: 'DELETE_TEMPLATE_ERR',
});
}

return deleted;
} catch (error) {
if (error.code_error) {
// Rethrow errors that we've thrown above, and catch the others
throw error;
}

this.logger.error({
...DocumentTemplateExceptionMessages.TEMPLATE_002,
error: JSONStringifyError(error),
});
this.exceptionService.internalServerErrorException({
message: 'Could not delete the template',
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { ContractExceptionMessages } from 'src/modules/documents/exceptions/cont
import { DocumentContractFacade } from 'src/modules/documents/services/document-contract.facade';

@Injectable()
export class RejectDocumentContractByNGO implements IUseCaseService<void> {
export class RejectDocumentContractByNgoUsecase
implements IUseCaseService<void>
{
constructor(
private readonly documentContractFacade: DocumentContractFacade,
private readonly exceptionService: ExceptionsService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ContractExceptionMessages } from 'src/modules/documents/exceptions/cont
import { DocumentContractFacade } from 'src/modules/documents/services/document-contract.facade';

@Injectable()
export class SignDocumentContractByNGO implements IUseCaseService<void> {
export class SignDocumentContractByNgoUsecase implements IUseCaseService<void> {
constructor(
private readonly documentContractFacade: DocumentContractFacade,
private readonly exceptionService: ExceptionsService,
Expand Down
8 changes: 6 additions & 2 deletions backend/src/usecases/use-case.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ import { GeneratePDFsUseCase } from './documents/new_contracts/generate-pdfs.use
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';
import { SignDocumentContractByNGO } from './documents/new_contracts/sign-document-contract-by-ngo.usecase';
import { SignDocumentContractByNgoUsecase } from './documents/new_contracts/sign-document-contract-by-ngo.usecase';
import { DeleteDocumentTemplateUsecase } from './documents/new_contracts/delete-document-template.usecase';
import { RejectDocumentContractByNgoUsecase } from './documents/new_contracts/reject-document-contract-by-ngo.usecase';

const providers = [
// Organization
Expand Down Expand Up @@ -281,6 +283,7 @@ const providers = [
CreateDocumentTemplateUsecase,
GetOneDocumentTemplateUseCase,
GetManyDocumentTemplatesUsecase,
DeleteDocumentTemplateUsecase,
// Contracts
CreateContractUsecase,
GetManyContractsUsecase,
Expand All @@ -303,7 +306,8 @@ const providers = [
GetManyDocumentContractsByVolunteerUsecase,
GetOneDocumentContractForVolunteerUsecase,
ApproveDocumentContractByNgoUsecase,
SignDocumentContractByNGO,
SignDocumentContractByNgoUsecase,
RejectDocumentContractByNgoUsecase,
// Notifications
UpdateSettingsUsecase,
// Testing PDFs
Expand Down

0 comments on commit 78cf3e0

Please sign in to comment.