From f99cd026a04f4c63b8fca4471d9b8fe0d01e661b Mon Sep 17 00:00:00 2001 From: Birloi Florian Date: Thu, 3 Oct 2024 12:11:52 +0300 Subject: [PATCH] feat: update archive entity and tracking for contracts --- .../_mobile/news/presenters/news.presenter.ts | 6 +-- ...79738-AddOrganizationIdToActionsArchive.ts | 54 +++++++++++++++++++ .../actions-archive/actions-archive.facade.ts | 2 + .../entities/actions-archive.entity.ts | 14 +++-- .../enums/action-resource-types.enum.ts | 2 + .../events/actions-archive-event.listener.ts | 1 + .../models/actions-archive.model.ts | 24 ++++++--- .../actions-archive.repository.ts | 7 ++- .../modules/user/models/base-user.model.ts | 23 ++++++++ .../approve-access-request.usecase.ts | 1 + .../delete-access-request.usecase.ts | 1 + .../reject-access-request.usecase.ts | 1 + .../approve-activity-log.usecase.ts | 1 + .../create-activity-log-by-admin.usecase.ts | 1 + ...te-activity-log-by-regular-user.usecase.ts | 1 + .../reject-activity-log.usecase.ts | 1 + .../activate-activity-type.usecase.ts | 1 + .../archive-activity-type.usecase.ts | 1 + .../create-activity-type.usecase.ts | 1 + .../update-activity-type.usecase.ts | 1 + .../create-announcement.usecase.ts | 1 + .../delete-announcement.usecase.ts | 1 + .../update-announcement.usecase.ts | 1 + .../documents/create-contract.usecase.ts | 1 + .../create-document-contract.usecase.ts | 1 + .../create-document-template.usecase.ts | 1 + .../delete-document-contract.usecase.ts | 1 + .../delete-document-template.usecase.ts | 1 + ...t-document-contact-by-volunteer.usecase.ts | 30 ++++++++--- ...reject-document-contract-by-ngo.usecase.ts | 1 + .../sign-document-contract-by-ngo.usecase.ts | 1 + ...-document-contract-by-volunteer.usecase.ts | 17 +++++- .../update-document-template.usecase.ts | 1 + ...lidate-document-contract-by-ngo.usecase.ts | 1 + .../documents/reject-contract.usecase.ts | 1 + .../sign-and-confirm-contract.usecase.ts | 1 + .../usecases/event/archive-event.usecase.ts | 1 + .../usecases/event/create-event.usecase.ts | 1 + .../usecases/event/delete-event.usecase.ts | 1 + .../usecases/event/publish-event.usecase.ts | 1 + .../usecases/event/update-event.usecase.ts | 1 + .../create-organization-structure.usecase.ts | 1 + .../delete-organization-structure.usecase.ts | 1 + .../update-organization-structure.usecase.ts | 1 + ...update-organization-description.usecase.ts | 1 + .../volunteer/activate-volunteer.usecase.ts | 1 + .../volunteer/archive-volunteer.usescase.ts | 1 + .../volunteer/block-volunteer.usecase.ts | 1 + .../update-volunteer-profile.usecase.ts | 1 + .../common/utils/actions-archive.mappings.tsx | 6 +++ 50 files changed, 198 insertions(+), 26 deletions(-) create mode 100644 backend/src/migrations/1727938379738-AddOrganizationIdToActionsArchive.ts diff --git a/backend/src/api/_mobile/news/presenters/news.presenter.ts b/backend/src/api/_mobile/news/presenters/news.presenter.ts index 1ef912037..5a3dd5211 100644 --- a/backend/src/api/_mobile/news/presenters/news.presenter.ts +++ b/backend/src/api/_mobile/news/presenters/news.presenter.ts @@ -7,12 +7,12 @@ import { ActivityLogStatus } from 'src/modules/activity-log/enums/activity-log-s export class NewsPresenter { constructor(item: IActionArchiveModel) { this.id = item.id; - this.organizationLogo = item.author.organization.logo; - this.organizationName = item.author.organization.name; + this.organizationLogo = item.organization.logo; + this.organizationName = item.organization.name; this.activityLogId = (item.eventData as never)['activityLogId']; this.contractId = (item.eventData as never)['documentContractId']; this.accessRequestId = (item.eventData as never)['accessRequestId']; - this.organizationId = item.author.organization.id; + this.organizationId = item.organization.id; this.eventName = item.eventName; this.newStatus = (item.eventData as never)['newStatus']; } diff --git a/backend/src/migrations/1727938379738-AddOrganizationIdToActionsArchive.ts b/backend/src/migrations/1727938379738-AddOrganizationIdToActionsArchive.ts new file mode 100644 index 000000000..558b222a3 --- /dev/null +++ b/backend/src/migrations/1727938379738-AddOrganizationIdToActionsArchive.ts @@ -0,0 +1,54 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddOrganizationIdToActionsArchive1727938379738 + implements MigrationInterface +{ + name = 'AddOrganizationIdToActionsArchive1727938379738'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "actions_archive" ADD "organization_id" uuid`, + ); + await queryRunner.query( + `ALTER TABLE "actions_archive" ADD CONSTRAINT "FK_fa13764b4b3b3f7064046a76d49" FOREIGN KEY ("organization_id") REFERENCES "organization"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); + + const actionsArchive = await queryRunner.query(` + SELECT + actions_archive.*, + COALESCE( + "user".organization_id, + (actions_archive.event_data->>'organizationId')::uuid, + volunteer.organization_id + ) AS organization_id + FROM actions_archive + LEFT JOIN "user" ON actions_archive.author_id = "user".id + LEFT JOIN volunteer ON (actions_archive.event_data->>'volunteerId')::uuid = volunteer.id + `); + + for (const action of actionsArchive) { + if (action.organization_id) { + await queryRunner.query( + `UPDATE actions_archive + SET organization_id = $1 + WHERE id = $2`, + [action.organization_id, action.id], + ); + } + } + + await queryRunner.query( + `ALTER TABLE "actions_archive" ALTER COLUMN "organization_id" SET NOT NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "actions_archive" DROP CONSTRAINT "FK_fa13764b4b3b3f7064046a76d49"`, + ); + await queryRunner.query( + `ALTER TABLE "actions_archive" DROP COLUMN "organization_id"`, + ); + } +} diff --git a/backend/src/modules/actions-archive/actions-archive.facade.ts b/backend/src/modules/actions-archive/actions-archive.facade.ts index 09b3738cc..7ee4f750c 100644 --- a/backend/src/modules/actions-archive/actions-archive.facade.ts +++ b/backend/src/modules/actions-archive/actions-archive.facade.ts @@ -24,6 +24,7 @@ export class ActionsArchiveFacade { eventName: EventName, eventData: TrackedEventData[EventName], author: IAdminUserModel | IRegularUserModel, + organizationId: string, changes?: unknown, ): void { const event: CreateActionArchiveOptions = { @@ -31,6 +32,7 @@ export class ActionsArchiveFacade { eventData, author, changes, + organizationId, }; this.eventEmitter.emit(TRACK_ACTION_EVENT, event); } diff --git a/backend/src/modules/actions-archive/entities/actions-archive.entity.ts b/backend/src/modules/actions-archive/entities/actions-archive.entity.ts index 2e3b67c33..e71304068 100644 --- a/backend/src/modules/actions-archive/entities/actions-archive.entity.ts +++ b/backend/src/modules/actions-archive/entities/actions-archive.entity.ts @@ -1,5 +1,5 @@ import { BaseEntity } from 'src/infrastructure/base/base-entity'; -import { AdminUserEntity } from 'src/modules/user/entities/user.entity'; +import { UserEntity } from 'src/modules/user/entities/user.entity'; import { Column, Entity, @@ -11,6 +11,7 @@ import { TrackedEventData, TrackedEventName, } from '../enums/action-resource-types.enum'; +import { OrganizationEntity } from 'src/modules/organization/entities/organization.entity'; @Entity({ name: 'actions_archive' }) export class ActionsArchiveEntity extends BaseEntity { @@ -29,7 +30,14 @@ export class ActionsArchiveEntity extends BaseEntity { @Column({ type: 'text', name: 'author_id' }) authorId: string; - @ManyToOne(() => AdminUserEntity) + @ManyToOne(() => UserEntity) @JoinColumn({ name: 'author_id' }) - author: AdminUserEntity; + author: UserEntity; + + @Column({ type: 'text', name: 'organization_id' }) + organizationId: string; + + @ManyToOne(() => OrganizationEntity) + @JoinColumn({ name: 'organization_id' }) + organization: OrganizationEntity; } diff --git a/backend/src/modules/actions-archive/enums/action-resource-types.enum.ts b/backend/src/modules/actions-archive/enums/action-resource-types.enum.ts index d1daa555f..11f2b3a33 100644 --- a/backend/src/modules/actions-archive/enums/action-resource-types.enum.ts +++ b/backend/src/modules/actions-archive/enums/action-resource-types.enum.ts @@ -61,6 +61,7 @@ export enum TrackedEventName { REJECT_DOCUMENT_CONTRACT_BY_NGO = 'REJECT_DOCUMENT_CONTRACT_BY_NGO', REJECT_DOCUMENT_CONTRACT_BY_VOLUNTEER = 'REJECT_DOCUMENT_CONTRACT_BY_VOLUNTEER', DELETE_DOCUMENT_CONTRACT = 'DELETE_DOCUMENT_CONTRACT', + EXPIRE_DOCUMENT_CONTRACT = 'EXPIRE_DOCUMENT_CONTRACT', // New Templates CREATE_DOCUMENT_TEMPLATE = 'CREATE_DOCUMENT_TEMPLATE', @@ -238,4 +239,5 @@ export interface TrackedEventData { [TrackedEventName.CREATE_DOCUMENT_TEMPLATE]: BaseDocumentTemplateActionsArchiveEvent; [TrackedEventName.UPDATE_DOCUMENT_TEMPLATE]: BaseDocumentTemplateActionsArchiveEvent; [TrackedEventName.DELETE_DOCUMENT_TEMPLATE]: BaseDocumentTemplateActionsArchiveEvent; + [TrackedEventName.EXPIRE_DOCUMENT_CONTRACT]: BaseDocumentContractActionsArchiveEvent; } diff --git a/backend/src/modules/actions-archive/events/actions-archive-event.listener.ts b/backend/src/modules/actions-archive/events/actions-archive-event.listener.ts index aa06f484b..c081cd79e 100644 --- a/backend/src/modules/actions-archive/events/actions-archive-event.listener.ts +++ b/backend/src/modules/actions-archive/events/actions-archive-event.listener.ts @@ -29,6 +29,7 @@ export class ActionsArchiveEventListener { eventData: event.eventData, author: event.author, changes: event.changes, + organizationId: event.organizationId, }), ); } catch (err) { diff --git a/backend/src/modules/actions-archive/models/actions-archive.model.ts b/backend/src/modules/actions-archive/models/actions-archive.model.ts index 6b77a1eef..0fe155967 100644 --- a/backend/src/modules/actions-archive/models/actions-archive.model.ts +++ b/backend/src/modules/actions-archive/models/actions-archive.model.ts @@ -1,9 +1,6 @@ import { IBaseModel } from 'src/common/interfaces/base.model'; import { IBasePaginationFilterModel } from 'src/infrastructure/base/base-pagination-filter.model'; -import { - AdminUserTransformer, - IAdminUserModel, -} from 'src/modules/user/models/admin-user.model'; +import { IAdminUserModel } from 'src/modules/user/models/admin-user.model'; import { ActionsArchiveEntity } from '../entities/actions-archive.entity'; import { TrackedEventData, @@ -11,13 +8,21 @@ import { } from '../enums/action-resource-types.enum'; import { IRegularUserModel } from 'src/modules/user/models/regular-user.model'; import { NewsType } from '../enums/news-type.enum'; +import { + BaseUserTransformer, + ICommonUserModel, +} from 'src/modules/user/models/base-user.model'; +import { + IOrganizationModel, + OrganizationTransformer, +} from 'src/modules/organization/models/organization.model'; export const TRACK_ACTION_EVENT = 'track.action'; export interface IActionArchiveModel extends IBaseModel { id: string; - author: IAdminUserModel; - + author: ICommonUserModel; + organization: IOrganizationModel; eventName: TrackedEventName; eventData: TrackedEventData[TrackedEventName]; @@ -29,6 +34,7 @@ export type CreateActionArchiveOptions = Pick< 'eventName' | 'eventData' | 'changes' > & { author: IRegularUserModel | IAdminUserModel; + organizationId: string; }; export type FindManyActionsArchiveOptions = { @@ -51,7 +57,9 @@ export class ActionsArchiveTransformer { return { id: entity.id, - author: AdminUserTransformer.fromEntity(entity.author), + author: BaseUserTransformer.fromEntity(entity.author), + + organization: OrganizationTransformer.fromEntity(entity.organization), eventName: entity.eventName, eventData: entity.eventData, @@ -71,6 +79,8 @@ export class ActionsArchiveTransformer { entity.authorId = action.author.id; + entity.organizationId = action.organizationId; + entity.changes = action.changes; return entity; diff --git a/backend/src/modules/actions-archive/repositories/actions-archive.repository.ts b/backend/src/modules/actions-archive/repositories/actions-archive.repository.ts index 2b79ab1f4..9521d332a 100644 --- a/backend/src/modules/actions-archive/repositories/actions-archive.repository.ts +++ b/backend/src/modules/actions-archive/repositories/actions-archive.repository.ts @@ -41,8 +41,7 @@ export class ActionsArchiveRepository 'author', ) .select() - // TODO: Instead of filtering organization by author, add organizationId in the entity because otherwise we can't track volunteer actions - .where('author.organizationId = :organizationId', { + .where('actionsArchive.organizationId = :organizationId', { organizationId: findOptions.organizationId, }) .orderBy( @@ -101,8 +100,8 @@ export class ActionsArchiveRepository 'author', ) .leftJoinAndMapOne( - 'author.organization', - 'author.organization', + 'actionsArchive.organization', + 'actionsArchive.organization', 'organization', ) .select() diff --git a/backend/src/modules/user/models/base-user.model.ts b/backend/src/modules/user/models/base-user.model.ts index a59fc3cb1..e5802a963 100644 --- a/backend/src/modules/user/models/base-user.model.ts +++ b/backend/src/modules/user/models/base-user.model.ts @@ -1,3 +1,6 @@ +import { AdminUserEntity, UserEntity } from '../entities/user.entity'; +import { UserType } from '../enums/user.enum'; + export interface IUserModel { id: string; cognitoId: string; @@ -6,3 +9,23 @@ export interface IUserModel { phone: string; // type: UserType; } + +export interface ICommonUserModel extends IUserModel { + type: UserType; +} + +export class BaseUserTransformer { + static fromEntity(entity: UserEntity): ICommonUserModel { + if (!entity) return null; + + return { + id: entity.id, + cognitoId: entity.cognitoId, + email: entity.email, + type: + entity instanceof AdminUserEntity ? UserType.ADMIN : UserType.REGULAR, + name: entity.name, + phone: entity.phone, + }; + } +} diff --git a/backend/src/usecases/access-request/approve-access-request.usecase.ts b/backend/src/usecases/access-request/approve-access-request.usecase.ts index e7b0919e1..48d30707f 100644 --- a/backend/src/usecases/access-request/approve-access-request.usecase.ts +++ b/backend/src/usecases/access-request/approve-access-request.usecase.ts @@ -85,6 +85,7 @@ export class ApproveAccessRequestUseCase volunteerId: volunteer.id, }, admin, + accessRequest.organizationId, ); return updated; diff --git a/backend/src/usecases/access-request/delete-access-request.usecase.ts b/backend/src/usecases/access-request/delete-access-request.usecase.ts index 81c25eee1..e9f4ea9f4 100644 --- a/backend/src/usecases/access-request/delete-access-request.usecase.ts +++ b/backend/src/usecases/access-request/delete-access-request.usecase.ts @@ -43,6 +43,7 @@ export class DeleteAccessRequestUseCase implements IUseCaseService { userId: accessRequest.requestedBy?.id, }, admin, + admin.organizationId, ); return deleted; diff --git a/backend/src/usecases/access-request/reject-access-request.usecase.ts b/backend/src/usecases/access-request/reject-access-request.usecase.ts index 0ea47ee5c..f39191ac5 100644 --- a/backend/src/usecases/access-request/reject-access-request.usecase.ts +++ b/backend/src/usecases/access-request/reject-access-request.usecase.ts @@ -79,6 +79,7 @@ export class RejectAccessRequestUseCase userId: accessRequest.requestedBy?.id, }, admin, + admin.organizationId, ); return updated; diff --git a/backend/src/usecases/activity-log/approve-activity-log.usecase.ts b/backend/src/usecases/activity-log/approve-activity-log.usecase.ts index 55774b539..22d6644d7 100644 --- a/backend/src/usecases/activity-log/approve-activity-log.usecase.ts +++ b/backend/src/usecases/activity-log/approve-activity-log.usecase.ts @@ -68,6 +68,7 @@ export class ApproveActivityLogUsecase newStatus: approved.status, }, admin, + admin.organizationId, ); return approved; diff --git a/backend/src/usecases/activity-log/create-activity-log-by-admin.usecase.ts b/backend/src/usecases/activity-log/create-activity-log-by-admin.usecase.ts index 14801aad9..9f03c7e8a 100644 --- a/backend/src/usecases/activity-log/create-activity-log-by-admin.usecase.ts +++ b/backend/src/usecases/activity-log/create-activity-log-by-admin.usecase.ts @@ -118,6 +118,7 @@ export class CreateActivityLogByAdmin volunteerName: volunteer.user?.name, }, admin, + admin.organizationId, ); return created; diff --git a/backend/src/usecases/activity-log/create-activity-log-by-regular-user.usecase.ts b/backend/src/usecases/activity-log/create-activity-log-by-regular-user.usecase.ts index d74d89ec5..c50b4c332 100644 --- a/backend/src/usecases/activity-log/create-activity-log-by-regular-user.usecase.ts +++ b/backend/src/usecases/activity-log/create-activity-log-by-regular-user.usecase.ts @@ -92,6 +92,7 @@ export class CreateActivityLogByRegularUser volunteerName: volunteer.user?.name, }, user, + user.activeOrganization.id, ); return created; diff --git a/backend/src/usecases/activity-log/reject-activity-log.usecase.ts b/backend/src/usecases/activity-log/reject-activity-log.usecase.ts index 366f86b9f..126d4d133 100644 --- a/backend/src/usecases/activity-log/reject-activity-log.usecase.ts +++ b/backend/src/usecases/activity-log/reject-activity-log.usecase.ts @@ -71,6 +71,7 @@ export class RejectActivityLogUsecase newStatus: rejected.status, }, admin, + admin.organizationId, ); return rejected; diff --git a/backend/src/usecases/activity-type/activate-activity-type.usecase.ts b/backend/src/usecases/activity-type/activate-activity-type.usecase.ts index 296d980f9..23bc728b4 100644 --- a/backend/src/usecases/activity-type/activate-activity-type.usecase.ts +++ b/backend/src/usecases/activity-type/activate-activity-type.usecase.ts @@ -48,6 +48,7 @@ export class ActivateActivityTypeUseCase newStatus: updated.status, }, admin, + admin.organizationId, ); return updated; diff --git a/backend/src/usecases/activity-type/archive-activity-type.usecase.ts b/backend/src/usecases/activity-type/archive-activity-type.usecase.ts index 4fcb2bf5e..0d3213765 100644 --- a/backend/src/usecases/activity-type/archive-activity-type.usecase.ts +++ b/backend/src/usecases/activity-type/archive-activity-type.usecase.ts @@ -48,6 +48,7 @@ export class ArchiveActivityTypeUseCase newStatus: updated.status, }, admin, + admin.organizationId, ); return updated; diff --git a/backend/src/usecases/activity-type/create-activity-type.usecase.ts b/backend/src/usecases/activity-type/create-activity-type.usecase.ts index a2ef7343e..402518ec0 100644 --- a/backend/src/usecases/activity-type/create-activity-type.usecase.ts +++ b/backend/src/usecases/activity-type/create-activity-type.usecase.ts @@ -74,6 +74,7 @@ export class CreateActivityTypeUseCase activityTypeName: created.name, }, admin, + admin.organizationId, ); return created; diff --git a/backend/src/usecases/activity-type/update-activity-type.usecase.ts b/backend/src/usecases/activity-type/update-activity-type.usecase.ts index ba25b2c8c..c6f10bef0 100644 --- a/backend/src/usecases/activity-type/update-activity-type.usecase.ts +++ b/backend/src/usecases/activity-type/update-activity-type.usecase.ts @@ -87,6 +87,7 @@ export class UpdateActivityTypeUseCase activityTypeName: updated.name, }, admin, + admin.organizationId, ObjectDiff.diff(toUpdate, updated), ); diff --git a/backend/src/usecases/announcement/create-announcement.usecase.ts b/backend/src/usecases/announcement/create-announcement.usecase.ts index 06bea1bde..fe9fcc0c6 100644 --- a/backend/src/usecases/announcement/create-announcement.usecase.ts +++ b/backend/src/usecases/announcement/create-announcement.usecase.ts @@ -111,6 +111,7 @@ export class CreateAnnouncementUseCase status: newAnouncement.status, }, admin, + admin.organizationId, ); return newAnouncement; diff --git a/backend/src/usecases/announcement/delete-announcement.usecase.ts b/backend/src/usecases/announcement/delete-announcement.usecase.ts index 71abb14fb..3e6aa1044 100644 --- a/backend/src/usecases/announcement/delete-announcement.usecase.ts +++ b/backend/src/usecases/announcement/delete-announcement.usecase.ts @@ -37,6 +37,7 @@ export class DeleteAnnouncementUseCase implements IUseCaseService { announcementTitle: announcement.name, }, admin, + admin.organizationId, ); return deleted; diff --git a/backend/src/usecases/announcement/update-announcement.usecase.ts b/backend/src/usecases/announcement/update-announcement.usecase.ts index bbc19078d..898991fff 100644 --- a/backend/src/usecases/announcement/update-announcement.usecase.ts +++ b/backend/src/usecases/announcement/update-announcement.usecase.ts @@ -133,6 +133,7 @@ export class UpdateAnnouncementUseCase announcementTitle: updatedAnnouncement.name, }, admin, + admin.organizationId, ); } diff --git a/backend/src/usecases/documents/create-contract.usecase.ts b/backend/src/usecases/documents/create-contract.usecase.ts index 9ade0b7de..909e24cf2 100644 --- a/backend/src/usecases/documents/create-contract.usecase.ts +++ b/backend/src/usecases/documents/create-contract.usecase.ts @@ -118,6 +118,7 @@ export class CreateContractUsecase implements IUseCaseService { contractNumber: contract.contractNumber, }, admin, + organization.id, ); return contract; diff --git a/backend/src/usecases/documents/new_contracts/create-document-contract.usecase.ts b/backend/src/usecases/documents/new_contracts/create-document-contract.usecase.ts index b1c5fdad9..7e74057cd 100644 --- a/backend/src/usecases/documents/new_contracts/create-document-contract.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/create-document-contract.usecase.ts @@ -181,6 +181,7 @@ export class CreateDocumentContractUsecase implements IUseCaseService { documentTemplateName: template.name, }, admin, + admin.organizationId, ); return contract.id; diff --git a/backend/src/usecases/documents/new_contracts/create-document-template.usecase.ts b/backend/src/usecases/documents/new_contracts/create-document-template.usecase.ts index 8164e8741..d0882e617 100644 --- a/backend/src/usecases/documents/new_contracts/create-document-template.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/create-document-template.usecase.ts @@ -38,6 +38,7 @@ export class CreateDocumentTemplateUsecase documentTemplateName: newTemplate.name, }, admin, + admin.organizationId, ); return newTemplate; diff --git a/backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts b/backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts index b53642e75..3b33cf28b 100644 --- a/backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/delete-document-contract.usecase.ts @@ -97,6 +97,7 @@ export class DeleteDocumentContractUsecase implements IUseCaseService { documentContractNumber: contract.documentNumber, }, admin, + admin.organizationId, ); } catch (error) { if (error?.status === 400) { diff --git a/backend/src/usecases/documents/new_contracts/delete-document-template.usecase.ts b/backend/src/usecases/documents/new_contracts/delete-document-template.usecase.ts index 28e86e7eb..d139982f9 100644 --- a/backend/src/usecases/documents/new_contracts/delete-document-template.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/delete-document-template.usecase.ts @@ -53,6 +53,7 @@ export class DeleteDocumentTemplateUsecase implements IUseCaseService { documentTemplateName: deleted.name, }, admin, + admin.organizationId, ); return deleted.name; diff --git a/backend/src/usecases/documents/new_contracts/reject-document-contact-by-volunteer.usecase.ts b/backend/src/usecases/documents/new_contracts/reject-document-contact-by-volunteer.usecase.ts index e884ceefd..198bdd616 100644 --- a/backend/src/usecases/documents/new_contracts/reject-document-contact-by-volunteer.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/reject-document-contact-by-volunteer.usecase.ts @@ -5,7 +5,8 @@ import { DocumentContractStatus } from 'src/modules/documents/enums/contract-sta import { ContractExceptionMessages } from 'src/modules/documents/exceptions/contract.exceptions'; import { DocumentContractFacade } from 'src/modules/documents/services/document-contract.facade'; import { VolunteerFacade } from 'src/modules/volunteer/services/volunteer.facade'; - +import { ActionsArchiveFacade } from 'src/modules/actions-archive/actions-archive.facade'; +import { TrackedEventName } from 'src/modules/actions-archive/enums/action-resource-types.enum'; // ┌─────────────────────────────────────────────────────────────────────────┐ // │ Business Rules for RejectDocumentContractByVolunteerUsecase: │ // │ │ @@ -62,6 +63,7 @@ export class RejectDocumentContractByVolunteerUsecase private readonly documentContractFacade: DocumentContractFacade, private readonly volunteerFacade: VolunteerFacade, private readonly exceptionService: ExceptionsService, + private readonly actionsArchiveFacade: ActionsArchiveFacade, ) {} public async execute({ @@ -124,11 +126,12 @@ export class RejectDocumentContractByVolunteerUsecase * │ 1. Update the contract status to REJECTED_VOLUNTEER. │ * └─────────────────────────────────────────────────────────────────────┘ */ - await this.documentContractFacade.rejectDocumentContractByVolunteer( - contractId, - rejectionReason, - userId, - ); + const contract = + await this.documentContractFacade.rejectDocumentContractByVolunteer( + contractId, + rejectionReason, + userId, + ); /* ┌─────────────────────────────────────────────────────────────────────┐ * │ Audit trail logging: │ @@ -137,8 +140,19 @@ export class RejectDocumentContractByVolunteerUsecase * │ with the rejection reason. │ * └─────────────────────────────────────────────────────────────────────┘ */ - // TODO: Implement audit trail logging - console.log('rejectionReason', rejectionReason); + this.actionsArchiveFacade.trackEvent( + TrackedEventName.REJECT_DOCUMENT_CONTRACT_BY_VOLUNTEER, + { + documentContractId: contract.id, + documentContractNumber: contract.documentNumber, + volunteerId: volunteer.id, + volunteerName: volunteer.user.name, + rejectionReason, + organizationId, + }, + volunteer.user, + organizationId, + ); // TODO: Implement notification to relevant parties diff --git a/backend/src/usecases/documents/new_contracts/reject-document-contract-by-ngo.usecase.ts b/backend/src/usecases/documents/new_contracts/reject-document-contract-by-ngo.usecase.ts index 3bb7b97bb..1d8dca3e8 100644 --- a/backend/src/usecases/documents/new_contracts/reject-document-contract-by-ngo.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/reject-document-contract-by-ngo.usecase.ts @@ -88,6 +88,7 @@ export class RejectDocumentContractByNgoUsecase documentContractNumber: updatedContract.documentNumber, }, admin, + admin.organizationId, ); // get volunteer data to build the mail/notification subject/body diff --git a/backend/src/usecases/documents/new_contracts/sign-document-contract-by-ngo.usecase.ts b/backend/src/usecases/documents/new_contracts/sign-document-contract-by-ngo.usecase.ts index 00afa5e7a..b974ce6fc 100644 --- a/backend/src/usecases/documents/new_contracts/sign-document-contract-by-ngo.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/sign-document-contract-by-ngo.usecase.ts @@ -76,6 +76,7 @@ export class SignDocumentContractByNgoUsecase implements IUseCaseService { volunteerName: contract.volunteerData.name, }, admin, + admin.organizationId, ); // get volunteer data to build the mail/notification subject/body diff --git a/backend/src/usecases/documents/new_contracts/sign-document-contract-by-volunteer.usecase.ts b/backend/src/usecases/documents/new_contracts/sign-document-contract-by-volunteer.usecase.ts index 2d5d2f9e3..2a2fe7c69 100644 --- a/backend/src/usecases/documents/new_contracts/sign-document-contract-by-volunteer.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/sign-document-contract-by-volunteer.usecase.ts @@ -7,6 +7,8 @@ import { DocumentContractFacade } from 'src/modules/documents/services/document- import { DocumentSignatureFacade } from 'src/modules/documents/services/document-signature.facade'; import { DocumentPDFGenerator } from 'src/modules/documents/services/document-pdf-generator'; import { VolunteerFacade } from 'src/modules/volunteer/services/volunteer.facade'; +import { ActionsArchiveFacade } from 'src/modules/actions-archive/actions-archive.facade'; +import { TrackedEventName } from 'src/modules/actions-archive/enums/action-resource-types.enum'; // ┌─────────────────────────────────────────────────────────────────────────┐ // │ Business Rules for SignDocumentContractByVolunteerUsecase: │ @@ -73,6 +75,7 @@ export class SignDocumentContractByVolunteerUsecase private readonly volunteerFacade: VolunteerFacade, private readonly exceptionService: ExceptionsService, private readonly documentPDFGenerator: DocumentPDFGenerator, + private readonly actionsArchiveFacade: ActionsArchiveFacade, ) {} public async execute({ @@ -159,7 +162,7 @@ export class SignDocumentContractByVolunteerUsecase // │ This ensures that the contract is updated with the signatures and │ // │ ready for further processing. │ // └─────────────────────────────────────────────────────────────────────┘ - await this.documentContractFacade.update(contractId, { + const contract = await this.documentContractFacade.update(contractId, { status: DocumentContractStatus.PENDING_APPROVAL_NGO, volunteerSignatureId: volunteerSignatureId, legalGuardianSignatureId: legalGuardianSignatureId, @@ -168,6 +171,18 @@ export class SignDocumentContractByVolunteerUsecase await this.documentPDFGenerator.generateContractPDF(contractId); // Track event in Actions Archive + this.actionsArchiveFacade.trackEvent( + TrackedEventName.SIGN_DOCUMENT_CONTRACT_BY_VOLUNTEER, + { + documentContractId: contract.id, + documentContractNumber: contract.documentNumber, + volunteerId: volunteer.id, + volunteerName: volunteer.user.name, + organizationId, + }, + volunteer.user, + organizationId, + ); return; } diff --git a/backend/src/usecases/documents/new_contracts/update-document-template.usecase.ts b/backend/src/usecases/documents/new_contracts/update-document-template.usecase.ts index 42193fa1d..8acf0e093 100644 --- a/backend/src/usecases/documents/new_contracts/update-document-template.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/update-document-template.usecase.ts @@ -60,6 +60,7 @@ export class UpdateDocumentTemplateUsecase implements IUseCaseService { documentTemplateName: template.name, }, admin, + admin.organizationId, ObjectDiff.diff(template, updated), ); } catch (error) { diff --git a/backend/src/usecases/documents/new_contracts/validate-document-contract-by-ngo.usecase.ts b/backend/src/usecases/documents/new_contracts/validate-document-contract-by-ngo.usecase.ts index 3bf0f789e..222b5f5c3 100644 --- a/backend/src/usecases/documents/new_contracts/validate-document-contract-by-ngo.usecase.ts +++ b/backend/src/usecases/documents/new_contracts/validate-document-contract-by-ngo.usecase.ts @@ -57,6 +57,7 @@ export class ValidateDocumentContractByNgoUsecase { volunteerName: contract.volunteerData.name, }, admin, + admin.organizationId, ); } } diff --git a/backend/src/usecases/documents/reject-contract.usecase.ts b/backend/src/usecases/documents/reject-contract.usecase.ts index 821c61b4e..b4a944940 100644 --- a/backend/src/usecases/documents/reject-contract.usecase.ts +++ b/backend/src/usecases/documents/reject-contract.usecase.ts @@ -77,6 +77,7 @@ export class RejectContractUsecase implements IUseCaseService { contractNumber: contract.contractNumber, }, admin, + organization.id, ); // 4. generate contract diff --git a/backend/src/usecases/documents/sign-and-confirm-contract.usecase.ts b/backend/src/usecases/documents/sign-and-confirm-contract.usecase.ts index 4784a74af..5cce67ec6 100644 --- a/backend/src/usecases/documents/sign-and-confirm-contract.usecase.ts +++ b/backend/src/usecases/documents/sign-and-confirm-contract.usecase.ts @@ -79,6 +79,7 @@ export class SignAndConfirmContractUsecase contractNumber: contract.contractNumber, }, admin, + organization.id, ); // 4. generate contract diff --git a/backend/src/usecases/event/archive-event.usecase.ts b/backend/src/usecases/event/archive-event.usecase.ts index d7d0e4016..56850887f 100644 --- a/backend/src/usecases/event/archive-event.usecase.ts +++ b/backend/src/usecases/event/archive-event.usecase.ts @@ -44,6 +44,7 @@ export class ArchiveEventUseCase implements IUseCaseService { newStatus: updated.status, }, admin, + admin.organizationId, ); return updated; diff --git a/backend/src/usecases/event/create-event.usecase.ts b/backend/src/usecases/event/create-event.usecase.ts index 577b9d8e2..b621926c8 100644 --- a/backend/src/usecases/event/create-event.usecase.ts +++ b/backend/src/usecases/event/create-event.usecase.ts @@ -132,6 +132,7 @@ export class CreateEventUseCase implements IUseCaseService { status: created.status, }, admin, + organization.id, ); return created; diff --git a/backend/src/usecases/event/delete-event.usecase.ts b/backend/src/usecases/event/delete-event.usecase.ts index e103f02e7..c00c7e8a8 100644 --- a/backend/src/usecases/event/delete-event.usecase.ts +++ b/backend/src/usecases/event/delete-event.usecase.ts @@ -68,6 +68,7 @@ export class DeleteEventUseCase implements IUseCaseService { eventName: toBeDeleted.name, }, admin, + admin.organizationId, ); return deleted; diff --git a/backend/src/usecases/event/publish-event.usecase.ts b/backend/src/usecases/event/publish-event.usecase.ts index 464eedd54..151732511 100644 --- a/backend/src/usecases/event/publish-event.usecase.ts +++ b/backend/src/usecases/event/publish-event.usecase.ts @@ -75,6 +75,7 @@ export class PublishEventUseCase implements IUseCaseService { newStatus: updated.status, }, admin, + organization.id, ); return updated; diff --git a/backend/src/usecases/event/update-event.usecase.ts b/backend/src/usecases/event/update-event.usecase.ts index d211918b0..50233224e 100644 --- a/backend/src/usecases/event/update-event.usecase.ts +++ b/backend/src/usecases/event/update-event.usecase.ts @@ -116,6 +116,7 @@ export class UpdateEventUseCase implements IUseCaseService { eventName: updated.name, }, admin, + admin.organizationId, ObjectDiff.diff(event, updated), ); diff --git a/backend/src/usecases/organization/organization-structure/create-organization-structure.usecase.ts b/backend/src/usecases/organization/organization-structure/create-organization-structure.usecase.ts index e5faecd01..ae5275375 100644 --- a/backend/src/usecases/organization/organization-structure/create-organization-structure.usecase.ts +++ b/backend/src/usecases/organization/organization-structure/create-organization-structure.usecase.ts @@ -46,6 +46,7 @@ export class CreateOrganizationStructureUseCase organizationStructureType: created.type, }, admin, + admin.organizationId, ); return created; diff --git a/backend/src/usecases/organization/organization-structure/delete-organization-structure.usecase.ts b/backend/src/usecases/organization/organization-structure/delete-organization-structure.usecase.ts index 16bad222e..0a952c0eb 100644 --- a/backend/src/usecases/organization/organization-structure/delete-organization-structure.usecase.ts +++ b/backend/src/usecases/organization/organization-structure/delete-organization-structure.usecase.ts @@ -40,6 +40,7 @@ export class DeleteOrganizationStructureUseCase organizationStructureType: toRemove.type, }, admin, + admin.organizationId, ); return removed; diff --git a/backend/src/usecases/organization/organization-structure/update-organization-structure.usecase.ts b/backend/src/usecases/organization/organization-structure/update-organization-structure.usecase.ts index 0d01e4794..c9a7cf543 100644 --- a/backend/src/usecases/organization/organization-structure/update-organization-structure.usecase.ts +++ b/backend/src/usecases/organization/organization-structure/update-organization-structure.usecase.ts @@ -60,6 +60,7 @@ export class UpdateOrganizationStructureUseCase organizationStructureType: updated.type, }, admin, + admin.organizationId, ObjectDiff.diff(toUpdate, updated), ); diff --git a/backend/src/usecases/organization/update-organization-description.usecase.ts b/backend/src/usecases/organization/update-organization-description.usecase.ts index 24cb1a023..2287fad32 100644 --- a/backend/src/usecases/organization/update-organization-description.usecase.ts +++ b/backend/src/usecases/organization/update-organization-description.usecase.ts @@ -42,6 +42,7 @@ export class UpdateOrganizationDescriptionUseCaseService organizationName: toUpdate.name, }, admin, + admin.organizationId, ObjectDiff.diff(toUpdate, updated), ); diff --git a/backend/src/usecases/volunteer/activate-volunteer.usecase.ts b/backend/src/usecases/volunteer/activate-volunteer.usecase.ts index 55645c8ed..9fd3a8c8e 100644 --- a/backend/src/usecases/volunteer/activate-volunteer.usecase.ts +++ b/backend/src/usecases/volunteer/activate-volunteer.usecase.ts @@ -54,6 +54,7 @@ export class ActivateVolunteerUsecase newStatus: activated.status, }, admin, + volunteer.organization.id, ); return activated; diff --git a/backend/src/usecases/volunteer/archive-volunteer.usescase.ts b/backend/src/usecases/volunteer/archive-volunteer.usescase.ts index 123443a84..992c3254e 100644 --- a/backend/src/usecases/volunteer/archive-volunteer.usescase.ts +++ b/backend/src/usecases/volunteer/archive-volunteer.usescase.ts @@ -74,6 +74,7 @@ export class ArchiveVolunteerUsecase newStatus: archived.status, }, admin, + volunteer.organization.id, ); return archived; diff --git a/backend/src/usecases/volunteer/block-volunteer.usecase.ts b/backend/src/usecases/volunteer/block-volunteer.usecase.ts index 3f253aa35..0214da7ea 100644 --- a/backend/src/usecases/volunteer/block-volunteer.usecase.ts +++ b/backend/src/usecases/volunteer/block-volunteer.usecase.ts @@ -43,6 +43,7 @@ export class BlockVolunteerUsecase implements IUseCaseService { newStatus: blocked.status, }, admin, + admin.organizationId, ); return blocked; diff --git a/backend/src/usecases/volunteer/update-volunteer-profile.usecase.ts b/backend/src/usecases/volunteer/update-volunteer-profile.usecase.ts index f06ce4e01..84a5f0ec0 100644 --- a/backend/src/usecases/volunteer/update-volunteer-profile.usecase.ts +++ b/backend/src/usecases/volunteer/update-volunteer-profile.usecase.ts @@ -51,6 +51,7 @@ export class UpdateVolunteerProfileUsecase volunteerName: volunteer.user?.name, }, user, + volunteer.organization.id, ObjectDiff.diff(volunteer.volunteerProfile, updated.volunteerProfile), ); diff --git a/frontend/src/common/utils/actions-archive.mappings.tsx b/frontend/src/common/utils/actions-archive.mappings.tsx index ec8c996bf..07c927f46 100644 --- a/frontend/src/common/utils/actions-archive.mappings.tsx +++ b/frontend/src/common/utils/actions-archive.mappings.tsx @@ -405,6 +405,12 @@ export const mapEventDataToActionDescription = ( content={eventData.volunteerName} /> ), + inlineContractLink: ( + + ), }} /> );