Skip to content

Commit da540ed

Browse files
fix: [Contracts] Delete file from S3 when the contract is deleted, invalidate query in FE
1 parent 2b4d21e commit da540ed

4 files changed

Lines changed: 45 additions & 0 deletions

File tree

backend/src/modules/documents/repositories/document-signature.repository.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ export class DocumentSignatureRepository {
1919
return signature.id;
2020
}
2121

22+
async delete(id: string): Promise<void> {
23+
await this.signatureRepository.delete({ id });
24+
}
25+
2226
async findOne(
2327
options: FindOneSignatureOptions,
2428
): Promise<DocumentSignatureEntity> {

backend/src/modules/documents/services/document-signature.facade.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@ export class DocumentSignatureFacade {
1111
async create(newSignature: CreateSignatureOptions): Promise<string> {
1212
return this.documentSignatureRepository.create(newSignature);
1313
}
14+
15+
async delete(id: string): Promise<void> {
16+
return this.documentSignatureRepository.delete(id);
17+
}
1418
}

backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ import { Injectable, Logger } from '@nestjs/common';
22
import { JSONStringifyError } from 'src/common/helpers/utils';
33
import { IUseCaseService } from 'src/common/interfaces/use-case-service.interface';
44
import { ExceptionsService } from 'src/infrastructure/exceptions/exceptions.service';
5+
import { S3Service } from 'src/infrastructure/providers/s3/module/s3.service';
56
import { ActionsArchiveFacade } from 'src/modules/actions-archive/actions-archive.facade';
67
import { TrackedEventName } from 'src/modules/actions-archive/enums/action-resource-types.enum';
78
import { DocumentContractStatus } from 'src/modules/documents/enums/contract-status.enum';
89
import { ContractExceptionMessages } from 'src/modules/documents/exceptions/contract.exceptions';
910
import { DocumentContractFacade } from 'src/modules/documents/services/document-contract.facade';
1011
import { IAdminUserModel } from 'src/modules/user/models/admin-user.model';
12+
import * as Sentry from '@sentry/nestjs';
13+
import { DocumentSignatureFacade } from 'src/modules/documents/services/document-signature.facade';
1114

1215
@Injectable()
1316
export class DeleteDocumentContractUsecase implements IUseCaseService<string> {
@@ -16,6 +19,8 @@ export class DeleteDocumentContractUsecase implements IUseCaseService<string> {
1619
private readonly documentContractFacade: DocumentContractFacade,
1720
private readonly exceptionService: ExceptionsService,
1821
private readonly actionsArchiveFacade: ActionsArchiveFacade,
22+
private readonly signatureService: DocumentSignatureFacade,
23+
private readonly s3Service: S3Service,
1924
) {}
2025

2126
public async execute(id: string, admin: IAdminUserModel): Promise<void> {
@@ -53,6 +58,34 @@ export class DeleteDocumentContractUsecase implements IUseCaseService<string> {
5358
throw new Error('Could not delete contract from DB');
5459
}
5560

61+
// Delete file from S3
62+
try {
63+
if (contract.filePath) {
64+
await this.s3Service.deleteFile(contract.filePath);
65+
}
66+
} catch (error) {
67+
Sentry.captureException(error);
68+
this.logger.error('Error deleting contract file from S3: ', error);
69+
}
70+
71+
// Delete signatures
72+
try {
73+
if (contract.volunteerSignatureId) {
74+
await this.signatureService.delete(contract.volunteerSignatureId);
75+
}
76+
if (contract.legalGuardianSignatureId) {
77+
await this.signatureService.delete(contract.legalGuardianSignatureId);
78+
}
79+
if (contract.ngoLegalRepresentativeSignatureId) {
80+
await this.signatureService.delete(
81+
contract.ngoLegalRepresentativeSignatureId,
82+
);
83+
}
84+
} catch (error) {
85+
Sentry.captureException(error);
86+
this.logger.error('Error while deleting contract signatures');
87+
}
88+
5689
// 10. Track event
5790
this.actionsArchiveFacade.trackEvent(
5891
TrackedEventName.DELETE_DOCUMENT_CONTRACT,

frontend/src/components/DocumentContractsTable.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import ConfirmationModal from './ConfirmationModal';
4747
import { useErrorToast, useSuccessToast } from '../hooks/useToast';
4848
import { InternalErrors } from '../common/errors/internal-errors.class';
4949
import { ContractsStatistics } from './ContractsStatistics';
50+
import { useQueryClient } from 'react-query';
5051

5152
interface StatusOption {
5253
key: string;
@@ -122,6 +123,8 @@ export interface DocumentContractsTableQueryProps extends IPaginationQueryParams
122123
type DocumentContractsTableBasicProps = IHOCQueryProps<DocumentContractsTableQueryProps>;
123124

124125
const DocumentContractsTable = ({ query, setQuery }: DocumentContractsTableBasicProps) => {
126+
const queryClient = useQueryClient();
127+
125128
// selected contract id
126129
const [selectedContract, setSelectedContract] = useState<string>();
127130
const [selectedVolunteer, setSelectedVolunteer] = useState<ListItem>();
@@ -187,6 +190,7 @@ const DocumentContractsTable = ({ query, setQuery }: DocumentContractsTableBasic
187190
onSuccess: () => {
188191
useSuccessToast(t('contract.submit.delete'));
189192
setSelectedDeleteContract(null);
193+
queryClient.invalidateQueries({ queryKey: ['contracts-statistics'] });
190194
refetch();
191195
},
192196
// eslint-disable-next-line @typescript-eslint/no-explicit-any

0 commit comments

Comments
 (0)