Skip to content

Commit

Permalink
Merge branch 'feature/contracts' of github.com:code4romania/teo into …
Browse files Browse the repository at this point in the history
…feature/contracts
  • Loading branch information
dragos1195 committed Sep 30, 2024
2 parents 8fad7fb + 8f93b62 commit f13e27c
Show file tree
Hide file tree
Showing 27 changed files with 332 additions and 45 deletions.
23 changes: 13 additions & 10 deletions backend/src/api/documents/document-template.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,17 @@ export class DocumentTemplateController {
@Post()
async create(
@Body() payload: CreateDocumentTemplateDto,
@ExtractUser() { organizationId, id: adminId }: IAdminUserModel,
@ExtractUser() admin: IAdminUserModel,
): Promise<DocumentTemplatePresenter> {
const newDocumentTemplate =
await this.createDocumentTemplateUsecase.execute({
...payload,
createdByAdminId: adminId,
organizationId,
});
await this.createDocumentTemplateUsecase.execute(
{
...payload,
createdByAdminId: admin.id,
organizationId: admin.organizationId,
},
admin,
);
return new DocumentTemplatePresenter(newDocumentTemplate);
}

Expand All @@ -74,21 +77,21 @@ export class DocumentTemplateController {
async update(
@Param('id', UuidValidationPipe) id: string,
@Body() payload: CreateDocumentTemplateDto,
@ExtractUser() { organizationId }: IAdminUserModel,
@ExtractUser() admin: IAdminUserModel,
): Promise<void> {
return this.updateDocumentTemplateUsecase.execute(
{ id, ...payload },
organizationId,
admin,
);
}

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

@Get()
Expand Down
2 changes: 1 addition & 1 deletion backend/src/instrument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Sentry.init({

debug: process.env.NODE_ENV === 'local',

enabled: true,
enabled: process.env.NODE_ENV !== 'local',

environment: process.env.NODE_ENV,

Expand Down
35 changes: 35 additions & 0 deletions backend/src/migrations/1727684897827-AddTemplateActionsArchive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class Migrations1727684897827 implements MigrationInterface {
name = 'Migrations1727684897827';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TYPE "public"."actions_archive_event_name_enum" RENAME TO "actions_archive_event_name_enum_old"`,
);
await queryRunner.query(
`CREATE TYPE "public"."actions_archive_event_name_enum" AS ENUM('UPDATE_ORGANIZATION_PROFILE', 'CREATE_ORGANIZATION_STRUCTURE', 'UPDATE_ORGANIZATION_STRUCTURE', 'DELETE_ORGANIZATION_STRUCTURE', 'APPROVE_ACCESS_REQUEST', 'REJECT_ACCESS_REQUEST', 'DELETE_ACCESS_REQUEST', 'CHANGE_VOLUNTEER_STATUS', 'UPDATE_VOLUNTEER_PROFILE', 'REGISTER_ACTIVITY_LOG', 'CHANGE_ACTIVITY_LOG_STATUS', 'CREATE_ACTIVITY_TYPE', 'UPDATE_ACTIVITY_TYPE', 'CHANGE_ACTIVITY_TYPE_STATUS', 'CREATE_EVENT', 'UPDATE_EVENT', 'DELETE_EVENT', 'CHANGE_EVENT_STATUS', 'CREATE_ANNOUNCEMENT', 'DELETE_ANNOUNCEMENT', 'PUBLISH_ANNOUNCEMENT', 'CREATE_CONTRACT', 'APPROVE_CONTRACT', 'REJECT_CONTRACT', 'CREATE_DOCUMENT_CONTRACT', 'VALIDATE_DOCUMENT_CONTRACT', 'SIGN_DOCUMENT_CONTRACT_BY_NGO', 'SIGN_DOCUMENT_CONTRACT_BY_VOLUNTEER', 'REJECT_DOCUMENT_CONTRACT_BY_NGO', 'REJECT_DOCUMENT_CONTRACT_BY_VOLUNTEER', 'DELETE_DOCUMENT_CONTRACT', 'CREATE_DOCUMENT_TEMPLATE', 'UPDATE_DOCUMENT_TEMPLATE', 'DELETE_DOCUMENT_TEMPLATE')`,
);
await queryRunner.query(
`ALTER TABLE "actions_archive" ALTER COLUMN "event_name" TYPE "public"."actions_archive_event_name_enum" USING "event_name"::"text"::"public"."actions_archive_event_name_enum"`,
);
await queryRunner.query(
`DROP TYPE "public"."actions_archive_event_name_enum_old"`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."actions_archive_event_name_enum_old" AS ENUM('UPDATE_ORGANIZATION_PROFILE', 'CREATE_ORGANIZATION_STRUCTURE', 'UPDATE_ORGANIZATION_STRUCTURE', 'DELETE_ORGANIZATION_STRUCTURE', 'APPROVE_ACCESS_REQUEST', 'REJECT_ACCESS_REQUEST', 'DELETE_ACCESS_REQUEST', 'CHANGE_VOLUNTEER_STATUS', 'UPDATE_VOLUNTEER_PROFILE', 'REGISTER_ACTIVITY_LOG', 'CHANGE_ACTIVITY_LOG_STATUS', 'CREATE_ACTIVITY_TYPE', 'UPDATE_ACTIVITY_TYPE', 'CHANGE_ACTIVITY_TYPE_STATUS', 'CREATE_EVENT', 'UPDATE_EVENT', 'DELETE_EVENT', 'CHANGE_EVENT_STATUS', 'CREATE_ANNOUNCEMENT', 'DELETE_ANNOUNCEMENT', 'PUBLISH_ANNOUNCEMENT', 'CREATE_CONTRACT', 'APPROVE_CONTRACT', 'REJECT_CONTRACT', 'CREATE_DOCUMENT_CONTRACT', 'VALIDATE_DOCUMENT_CONTRACT', 'SIGN_DOCUMENT_CONTRACT_BY_NGO', 'SIGN_DOCUMENT_CONTRACT_BY_VOLUNTEER', 'REJECT_DOCUMENT_CONTRACT_BY_NGO', 'REJECT_DOCUMENT_CONTRACT_BY_VOLUNTEER', 'DELETE_DOCUMENT_CONTRACT')`,
);
await queryRunner.query(
`ALTER TABLE "actions_archive" ALTER COLUMN "event_name" TYPE "public"."actions_archive_event_name_enum_old" USING "event_name"::"text"::"public"."actions_archive_event_name_enum_old"`,
);
await queryRunner.query(
`DROP TYPE "public"."actions_archive_event_name_enum"`,
);
await queryRunner.query(
`ALTER TYPE "public"."actions_archive_event_name_enum_old" RENAME TO "actions_archive_event_name_enum"`,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { ContractStatus } from 'src/modules/documents/enums/contract-status.enum
import { EventStatus } from 'src/modules/event/enums/event-status.enum';
import { OrganizationStructureType } from 'src/modules/organization/enums/organization-structure-type.enum';
import { VolunteerStatus } from 'src/modules/volunteer/enums/volunteer-status.enum';
import { BaseDocumentContractActionsArchiveEvent } from '../interfaces/document-contract-actions-archive-event.type';
import {
BaseDocumentContractActionsArchiveEvent,
BaseDocumentTemplateActionsArchiveEvent,
} from '../interfaces/document-contract-actions-archive-event.type';

export enum TrackedEventName {
// Organization Profile
Expand Down Expand Up @@ -60,9 +63,9 @@ export enum TrackedEventName {
DELETE_DOCUMENT_CONTRACT = 'DELETE_DOCUMENT_CONTRACT',

// New Templates
// CREATE_DOCUMENT_TEMPLATE = 'CREATE_DOCUMENT_TEMPLATE',
// UPDATE_DOCUMENT_TEMPLATE = 'UPDATE_DOCUMENT_TEMPLATE',
// DELETE_DOCUMENT_TEMPLATE = 'DELETE_DOCUMENT_TEMPLATE',
CREATE_DOCUMENT_TEMPLATE = 'CREATE_DOCUMENT_TEMPLATE',
UPDATE_DOCUMENT_TEMPLATE = 'UPDATE_DOCUMENT_TEMPLATE',
DELETE_DOCUMENT_TEMPLATE = 'DELETE_DOCUMENT_TEMPLATE',
}

export interface TrackedEventData {
Expand Down Expand Up @@ -230,4 +233,9 @@ export interface TrackedEventData {
rejectionReason: string;
};
[TrackedEventName.DELETE_DOCUMENT_CONTRACT]: BaseDocumentContractActionsArchiveEvent;

// New Templates
[TrackedEventName.CREATE_DOCUMENT_TEMPLATE]: BaseDocumentTemplateActionsArchiveEvent;
[TrackedEventName.UPDATE_DOCUMENT_TEMPLATE]: BaseDocumentTemplateActionsArchiveEvent;
[TrackedEventName.DELETE_DOCUMENT_TEMPLATE]: BaseDocumentTemplateActionsArchiveEvent;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ export type BaseDocumentContractActionsArchiveEvent = {
volunteerId: string;
volunteerName: string;
};

export type BaseDocumentTemplateActionsArchiveEvent = {
organizationId: string;
documentTemplateId: string;
documentTemplateName: string;
};
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,14 @@ export class DocumentTemplateRepositoryService
return DocumentTemplateTransformer.fromEntity(documentTemplate);
}

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

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

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ export class DocumentTemplateFacade {
return this.documentTemplateListViewRepository.findMany(findOptions);
}

async delete(options: DeleteOneDocumentTemplateOptions): Promise<string> {
async delete(
options: DeleteOneDocumentTemplateOptions,
): Promise<{ name: string }> {
return this.documentTemplateRepository.delete(options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ export class CreateDocumentContractUsecase implements IUseCaseService<string> {

// 8. Generate the PDF
try {
// TODO: Make it async, so we can return the contract id immediately
await this.documentPDFGenerator.generateContractPDF(contract.id);
} catch (error) {
this.logger.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ 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 { ActionsArchiveFacade } from 'src/modules/actions-archive/actions-archive.facade';
import { TrackedEventName } from 'src/modules/actions-archive/enums/action-resource-types.enum';
import { DocumentTemplateExceptionMessages } from 'src/modules/documents/exceptions/documente-template.exceptions';
import {
CreateDocumentTemplateOptions,
IDocumentTemplateModel,
} from 'src/modules/documents/models/document-template.model';
import { DocumentTemplateFacade } from 'src/modules/documents/services/document-template.facade';
import { IAdminUserModel } from 'src/modules/user/models/admin-user.model';

@Injectable()
export class CreateDocumentTemplateUsecase
Expand All @@ -17,14 +20,26 @@ export class CreateDocumentTemplateUsecase
constructor(
private readonly documentTemplateFacade: DocumentTemplateFacade,
private readonly exceptionService: ExceptionsService,
private readonly actionsArchiveFacade: ActionsArchiveFacade,
) {}

public async execute(
options: CreateDocumentTemplateOptions,
admin: IAdminUserModel,
): Promise<IDocumentTemplateModel> {
try {
const newTemplate = await this.documentTemplateFacade.create(options);

this.actionsArchiveFacade.trackEvent(
TrackedEventName.CREATE_DOCUMENT_TEMPLATE,
{
organizationId: newTemplate.organizationId,
documentTemplateId: newTemplate.id,
documentTemplateName: newTemplate.name,
},
admin,
);

return newTemplate;
} catch (error) {
this.logger.error({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ 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 { ActionsArchiveFacade } from 'src/modules/actions-archive/actions-archive.facade';
import { TrackedEventName } from 'src/modules/actions-archive/enums/action-resource-types.enum';
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';
import { IAdminUserModel } from 'src/modules/user/models/admin-user.model';

@Injectable()
export class DeleteDocumentTemplateUsecase implements IUseCaseService<string> {
Expand All @@ -13,14 +16,15 @@ export class DeleteDocumentTemplateUsecase implements IUseCaseService<string> {
private readonly documentTemplateFacade: DocumentTemplateFacade,
private readonly documentContractFacade: DocumentContractFacade,
private readonly exceptionService: ExceptionsService,
private readonly actionsArchiveFacade: ActionsArchiveFacade,
) {}

public async execute(id: string, organizationId: string): Promise<string> {
public async execute(id: string, admin: IAdminUserModel): 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,
organizationId: admin.organizationId,
});

if (isUsed) {
Expand All @@ -32,7 +36,7 @@ export class DeleteDocumentTemplateUsecase implements IUseCaseService<string> {
// 2. Try to delete it
const deleted = await this.documentTemplateFacade.delete({
id,
organizationId,
organizationId: admin.organizationId,
});

if (!deleted) {
Expand All @@ -41,7 +45,17 @@ export class DeleteDocumentTemplateUsecase implements IUseCaseService<string> {
);
}

return deleted;
this.actionsArchiveFacade.trackEvent(
TrackedEventName.DELETE_DOCUMENT_TEMPLATE,
{
organizationId: admin.organizationId,
documentTemplateId: id,
documentTemplateName: deleted.name,
},
admin,
);

return deleted.name;
} catch (error) {
if (error?.status === 400) {
// Rethrow errors that we've thrown above, and catch the others
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Injectable, Logger } from '@nestjs/common';
import { ObjectDiff } from 'src/common/helpers/object-diff';
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 { ActionsArchiveFacade } from 'src/modules/actions-archive/actions-archive.facade';
import { TrackedEventName } from 'src/modules/actions-archive/enums/action-resource-types.enum';
import { DocumentTemplateExceptionMessages } from 'src/modules/documents/exceptions/documente-template.exceptions';
import { UpdateDocumentTemplateOptions } from 'src/modules/documents/models/document-template.model';
import { DocumentContractFacade } from 'src/modules/documents/services/document-contract.facade';
import { DocumentTemplateFacade } from 'src/modules/documents/services/document-template.facade';
import { IAdminUserModel } from 'src/modules/user/models/admin-user.model';

@Injectable()
export class UpdateDocumentTemplateUsecase implements IUseCaseService<string> {
Expand All @@ -14,17 +18,18 @@ export class UpdateDocumentTemplateUsecase implements IUseCaseService<string> {
private readonly documentTemplateFacade: DocumentTemplateFacade,
private readonly documentContractFacade: DocumentContractFacade,
private readonly exceptionService: ExceptionsService,
private readonly actionsArchiveFacade: ActionsArchiveFacade,
) {}

public async execute(
updates: UpdateDocumentTemplateOptions,
organizationId: string,
admin: IAdminUserModel,
): Promise<void> {
try {
// 1. Does the template exists in the callers' organization?
const template = await this.documentTemplateFacade.exists({
const template = await this.documentTemplateFacade.findOne({
id: updates.id,
organizationId,
organizationId: admin.organizationId,
});

if (!template) {
Expand All @@ -36,7 +41,7 @@ export class UpdateDocumentTemplateUsecase implements IUseCaseService<string> {
// 2. Templates can be deleted if are not linked with a contract
const isUsed = await this.documentContractFacade.exists({
documentTemplateId: updates.id,
organizationId: organizationId,
organizationId: admin.organizationId,
});

if (isUsed) {
Expand All @@ -45,7 +50,18 @@ export class UpdateDocumentTemplateUsecase implements IUseCaseService<string> {
);
}

await this.documentTemplateFacade.update(updates);
const updated = await this.documentTemplateFacade.update(updates);

this.actionsArchiveFacade.trackEvent(
TrackedEventName.UPDATE_DOCUMENT_TEMPLATE,
{
organizationId: admin.organizationId,
documentTemplateId: updates.id,
documentTemplateName: template.name,
},
admin,
ObjectDiff.diff(template, updated),
);
} catch (error) {
if (error?.status === 400) {
// Rethrow errors that we've thrown above, and catch the others
Expand Down
14 changes: 13 additions & 1 deletion frontend/src/assets/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,18 @@
"DELETE_DOCUMENT_CONTRACT": {
"label": "Delete Contract",
"description": "Contract number <inlineContractLink>{{contractNumber}}</inlineContractLink> for <inlineLink>{{volunteerName}}</inlineLink> has been deleted"
},
"CREATE_DOCUMENT_TEMPLATE": {
"label": "Create Template",
"description": "A new template has been created with the name <inlineLink>{{documentTemplateName}}</inlineLink>"
},
"UPDATE_DOCUMENT_TEMPLATE": {
"label": "Update Template",
"description": "Template with the name <inlineLink>{{documentTemplateName}}</inlineLink> has been modified."
},
"DELETE_DOCUMENT_TEMPLATE": {
"label": "Delete Template",
"description": "Template with the name <inlineLink>{{documentTemplateName}}</inlineLink> has been deleted."
}
},
"dashboard": {
Expand Down Expand Up @@ -1300,4 +1312,4 @@
"clear": "Clear",
"apply_all": "Apply to all"
}
}
}
12 changes: 12 additions & 0 deletions frontend/src/assets/locales/ro/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,18 @@
"DELETE_DOCUMENT_CONTRACT": {
"label": "Șterge Contract",
"description": "Contractul cu numărul <inlineContractLink>{{contractNumber}}</inlineContractLink> pentru <inlineLink>{{volunteerName}}</inlineLink> a fost șters"
},
"CREATE_DOCUMENT_TEMPLATE": {
"label": "Creează Template",
"description": "A fost creat un nou template cu numele <inlineLink>{{documentTemplateName}}</inlineLink>"
},
"UPDATE_DOCUMENT_TEMPLATE": {
"label": "Actualizează Template",
"description": "Template-ul cu numele <inlineLink>{{documentTemplateName}}</inlineLink> a fost modificat."
},
"DELETE_DOCUMENT_TEMPLATE": {
"label": "Șterge Template",
"description": "Template-ul cu numele <inlineLink>{{documentTemplateName}}</inlineLink> a fost șters."
}
},
"dashboard": {
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/common/enums/actions.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@ export enum TrackedEventName {
REJECT_DOCUMENT_CONTRACT_BY_NGO = 'REJECT_DOCUMENT_CONTRACT_BY_NGO', // done
REJECT_DOCUMENT_CONTRACT_BY_VOLUNTEER = 'REJECT_DOCUMENT_CONTRACT_BY_VOLUNTEER', // cannot do it
DELETE_DOCUMENT_CONTRACT = 'DELETE_DOCUMENT_CONTRACT',

// New templates
CREATE_DOCUMENT_TEMPLATE = 'CREATE_DOCUMENT_TEMPLATE',
UPDATE_DOCUMENT_TEMPLATE = 'UPDATE_DOCUMENT_TEMPLATE',
DELETE_DOCUMENT_TEMPLATE = 'DELETE_DOCUMENT_TEMPLATE',
}
Loading

0 comments on commit f13e27c

Please sign in to comment.