From 0b78e9d257e67068f36517403ee97f43d72a5c42 Mon Sep 17 00:00:00 2001 From: samuelmbabhazi Date: Mon, 10 Feb 2025 23:20:57 +0200 Subject: [PATCH 1/8] Fix: project module actions button --- .../organization-project-module.controller.ts | 2 ++ .../organization-project-module.entity.ts | 3 +++ .../project-module-table.module.ts | 13 +++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.controller.ts b/packages/core/src/lib/organization-project-module/organization-project-module.controller.ts index e6661c96cd1..0b9df867484 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.controller.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.controller.ts @@ -170,6 +170,8 @@ export class OrganizationProjectModuleController extends CrudController { + console.log('Voici les data:', entity); + return await this.commandBus.execute(new OrganizationProjectModuleCreateCommand(entity)); } diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.entity.ts b/packages/core/src/lib/organization-project-module/organization-project-module.entity.ts index 35aae835e99..cca11c45ac9 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.entity.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.entity.ts @@ -181,6 +181,9 @@ export class OrganizationProjectModule extends TenantOrganizationBaseEntity impl /** * Task */ + @ApiPropertyOptional({ type: () => Array, isArray: true, description: 'List of task IDs' }) + @IsOptional() + @IsArray() @MultiORMManyToMany(() => Task, (it) => it.modules, { /** Defines the database action to perform on update. */ onUpdate: 'CASCADE', diff --git a/packages/ui-core/shared/src/lib/project-module/project-module-table/project-module-table.module.ts b/packages/ui-core/shared/src/lib/project-module/project-module-table/project-module-table.module.ts index 99980c410e4..3a131a9235c 100644 --- a/packages/ui-core/shared/src/lib/project-module/project-module-table/project-module-table.module.ts +++ b/packages/ui-core/shared/src/lib/project-module/project-module-table/project-module-table.module.ts @@ -1,13 +1,22 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { NbSpinnerModule } from '@nebular/theme'; +import { NbButtonModule, NbIconModule, NbSpinnerModule } from '@nebular/theme'; import { SmartDataViewLayoutModule } from '../../smart-data-layout'; import { ProjectModuleTableComponent } from './project-module-table.component'; import { ProjectModuleMutationModule } from '../project-module-mutation/project-module-mutation.module'; +import { TranslateModule } from '@ngx-translate/core'; @NgModule({ declarations: [ProjectModuleTableComponent], exports: [ProjectModuleTableComponent], - imports: [CommonModule, NbSpinnerModule, ProjectModuleMutationModule, SmartDataViewLayoutModule] + imports: [ + CommonModule, + NbSpinnerModule, + NbButtonModule, + NbIconModule, + TranslateModule.forChild(), + ProjectModuleMutationModule, + SmartDataViewLayoutModule + ] }) export class ProjectModuleTableModule {} From e134e61d751602b02a1ce9d0c68e71ecbbc70a0c Mon Sep 17 00:00:00 2001 From: samuelmbabhazi Date: Wed, 12 Feb 2025 21:09:56 +0200 Subject: [PATCH 2/8] Fix:Foreign Key Constraint Violation in project_module_task During Project Module Creation --- .../organization-project-module.module.ts | 2 + .../organization-project-module.service.ts | 235 ++++++++++++------ 2 files changed, 164 insertions(+), 73 deletions(-) diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.module.ts b/packages/core/src/lib/organization-project-module/organization-project-module.module.ts index 57cc834872c..549b714e4df 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.module.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.module.ts @@ -12,6 +12,7 @@ import { RoleModule } from '../role/role.module'; import { EmployeeModule } from '../employee/employee.module'; import { OrganizationProjectModuleEmployee } from './organization-project-module-employee.entity'; import { TypeOrmOrganizationProjectModuleEmployeeRepository } from './repository/type-orm-organization-project-module-employee.repository'; +import { TaskModule } from '../tasks'; @Module({ imports: [ @@ -21,6 +22,7 @@ import { TypeOrmOrganizationProjectModuleEmployeeRepository } from './repository RolePermissionModule, RoleModule, EmployeeModule, + TaskModule, CqrsModule ], controllers: [OrganizationProjectModuleController], diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts index 00e02b68dc8..a6c36617c8e 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts @@ -1,5 +1,5 @@ import { BadRequestException, HttpException, HttpStatus, Injectable } from '@nestjs/common'; -import { Brackets, FindManyOptions, SelectQueryBuilder, UpdateResult, WhereExpressionBuilder } from 'typeorm'; +import { Brackets, FindManyOptions, In, SelectQueryBuilder, UpdateResult, WhereExpressionBuilder } from 'typeorm'; import { BaseEntityEnum, ActorTypeEnum, @@ -13,7 +13,8 @@ import { ProjectModuleStatusEnum, ActionTypeEnum, RolesEnum, - IEmployee + IEmployee, + ITask } from '@gauzy/contracts'; import { isEmpty, isNotEmpty } from '@gauzy/utils'; import { isPostgres } from '@gauzy/config'; @@ -29,6 +30,7 @@ import { EmployeeService } from '../employee/employee.service'; import { OrganizationProjectModuleEmployee } from './organization-project-module-employee.entity'; import { TypeOrmOrganizationProjectModuleEmployeeRepository } from './repository/type-orm-organization-project-module-employee.repository'; import { MikroOrmOrganizationProjectModuleEmployeeRepository } from './repository/mikro-orm-organization-project-module-employee.repository'; +import { TaskService } from '../tasks'; @Injectable() export class OrganizationProjectModuleService extends TenantAwareCrudService { @@ -39,7 +41,8 @@ export class OrganizationProjectModuleService extends TenantAwareCrudService { - // If the employee is a manager, assign the existing manager with the latest assignedAt date - const isManager = managerIdsSet.has(employeeId); - const assignedAt = new Date(); - - return new OrganizationProjectModuleEmployee({ - employeeId, - organizationId, - tenantId, - isManager, - assignedAt, - role: isManager ? managerRole : null - }); - }); + const existingTasks = await this.getExistingTasks(tasks); + const members = await this.buildModuleMembers(employees, managerIds, organizationId, tenantId); const projectModule = await super.create({ ...input, @@ -110,21 +80,16 @@ export class OrganizationProjectModuleService extends TenantAwareCrudService( - BaseEntityEnum.OrganizationProjectModule, + await this.assignTasksToModule(existingTasks, projectModule); + + this.logModuleActivity( ActionTypeEnum.Created, - ActorTypeEnum.User, - projectModule.id, - projectModule.name, projectModule, - organizationId, - tenantId + undefined, // No previous module (creation case) + entity ); - return projectModule; } catch (error) { - // Handle errors and return an appropriate error response throw new HttpException( `Failed to create organization project module: ${error.message}`, HttpStatus.BAD_REQUEST @@ -146,23 +111,22 @@ export class OrganizationProjectModuleService extends TenantAwareCrudService task.id)); + const newTasks = tasks.filter((task) => !existingTaskIds.has(task.id)); + + // Determine tasks to remove + const tasksToRemove = existingProjectModule.tasks.filter( + (task) => !tasks.some((updatedTask) => updatedTask.id === task.id) + ); + + // Add new tasks + for (const task of newTasks) { + task.modules = [...(task.modules || []), existingProjectModule]; + await this._taskService.update(task.id, task); + } + + // Remove tasks + for (const task of tasksToRemove) { + task.modules = task.modules?.filter((module) => module.id !== existingProjectModule.id) || []; + await this._taskService.update(task.id, task); + } + } + + // Update the project module with new values const updatedProjectModule = await super.create({ ...entity, id }); // Generate the activity log + this.logModuleActivity(ActionTypeEnum.Updated, updatedProjectModule, existingProjectModule, entity); - this.activityLogService.logActivity( - BaseEntityEnum.OrganizationProjectModule, - ActionTypeEnum.Updated, - ActorTypeEnum.User, - updatedProjectModule.id, - updatedProjectModule.name, - updatedProjectModule, - organizationId, - tenantId, - existingProjectModule, - entity - ); - - // return updated Module + // Return updated module return updatedProjectModule; } catch (error) { throw new BadRequestException(error); @@ -594,4 +572,115 @@ export class OrganizationProjectModuleService extends TenantAwareCrudService { + try { + const currentRole = await this._roleService.findOneByIdString(currentRoleId, { + where: { name: RolesEnum.EMPLOYEE } + }); + if (currentRole && !managerIds.includes(employeeId)) { + managerIds.push(employeeId); + } + } catch { + // Role is not "EMPLOYEE" or no action needed. + } + } + + /** + * Fetch existing tasks related to the project module. + * @param tasks List of tasks to check. + * @returns A list of existing tasks found in the database. + */ + private async getExistingTasks(tasks: ITask[]): Promise { + const taskIds = tasks.map((task) => task.id); + return this._taskService.find({ + where: { id: In(taskIds) }, + relations: { modules: true } + }); + } + + /** + * Build module members from employees and assign manager roles. + * @param employees List of employees to assign as members. + * @param managerIds List of manager IDs. + * @param organizationId The ID of the organization. + * @param tenantId The ID of the tenant. + * @returns A list of organization project module members. + */ + private async buildModuleMembers( + employees: IEmployee[], + managerIds: string[], + organizationId: string, + tenantId: string + ): Promise { + const managerRole = await this._roleService.findOneByWhereOptions({ name: RolesEnum.MANAGER }); + const managerIdsSet = new Set(managerIds); + + return employees.map(({ id: employeeId }) => { + const isManager = managerIdsSet.has(employeeId); + return new OrganizationProjectModuleEmployee({ + employeeId, + organizationId, + tenantId, + isManager, + assignedAt: new Date(), + role: isManager ? managerRole : null + }); + }); + } + + /** + * Assign tasks to the project module. + * @param tasks List of tasks to associate with the module. + * @param projectModule The project module to assign tasks to. + */ + private async assignTasksToModule(tasks: ITask[], projectModule: IOrganizationProjectModule): Promise { + const taskUpdates = tasks.map((task) => { + if (!task.modules) { + task.modules = []; + } + task.modules.push(projectModule); + return this._taskService.update(task.id, { ...task }); + }); + await Promise.all(taskUpdates); + } + + /** + * Log activity for a project module. + * @param projectModule The project module to log. + * @param organizationId The ID of the organization. + * @param tenantId The ID of the tenant. + */ + private logModuleActivity( + action: ActionTypeEnum, + updatedModule: IOrganizationProjectModule, + existingModule?: IOrganizationProjectModule, + changes?: Partial + ): void { + const tenantId = RequestContext.currentTenantId(); + const organizationId = updatedModule.organizationId; + + this.activityLogService.logActivity( + BaseEntityEnum.OrganizationProjectModule, + action, + ActorTypeEnum.User, + updatedModule.id, + updatedModule.name, + updatedModule, + organizationId, + tenantId, + existingModule, + changes + ); + } } From f37918a94b4d06e5d94618277d9da218a3e745a9 Mon Sep 17 00:00:00 2001 From: samuelmbabhazi Date: Wed, 12 Feb 2025 21:30:46 +0200 Subject: [PATCH 3/8] Remove console log --- .../organization-project-module.controller.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.controller.ts b/packages/core/src/lib/organization-project-module/organization-project-module.controller.ts index 0b9df867484..e6661c96cd1 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.controller.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.controller.ts @@ -170,8 +170,6 @@ export class OrganizationProjectModuleController extends CrudController { - console.log('Voici les data:', entity); - return await this.commandBus.execute(new OrganizationProjectModuleCreateCommand(entity)); } From d067e19d841f393545808d83927597e1487dd805 Mon Sep 17 00:00:00 2001 From: samuelmbabhazi Date: Thu, 13 Feb 2025 09:31:57 +0200 Subject: [PATCH 4/8] Fix:Deep scan --- .../organization-project-module.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts index a6c36617c8e..1a322ea8587 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts @@ -138,8 +138,8 @@ export class OrganizationProjectModuleService extends TenantAwareCrudService Date: Fri, 14 Feb 2025 09:37:39 +0200 Subject: [PATCH 5/8] Fix: full import --- .../organization-project-module.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts index 1a322ea8587..e05f79f003f 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts @@ -30,7 +30,7 @@ import { EmployeeService } from '../employee/employee.service'; import { OrganizationProjectModuleEmployee } from './organization-project-module-employee.entity'; import { TypeOrmOrganizationProjectModuleEmployeeRepository } from './repository/type-orm-organization-project-module-employee.repository'; import { MikroOrmOrganizationProjectModuleEmployeeRepository } from './repository/mikro-orm-organization-project-module-employee.repository'; -import { TaskService } from '../tasks'; +import { TaskService } from '../tasks/task.service'; @Injectable() export class OrganizationProjectModuleService extends TenantAwareCrudService { From 5003514ece3a817deb4b38c8739b02f522c73cbb Mon Sep 17 00:00:00 2001 From: samuelmbabhazi Date: Sat, 15 Feb 2025 10:19:17 +0200 Subject: [PATCH 6/8] Fix: format --- .../organization-project-module.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts index e05f79f003f..d5a16a38ce9 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts @@ -138,8 +138,8 @@ export class OrganizationProjectModuleService extends TenantAwareCrudService Date: Sat, 15 Feb 2025 12:06:09 +0200 Subject: [PATCH 7/8] Integration of coderabbit ai suggestions --- .../organization-project-module.service.ts | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts index d5a16a38ce9..f94fb97679c 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts @@ -1,5 +1,14 @@ import { BadRequestException, HttpException, HttpStatus, Injectable } from '@nestjs/common'; -import { Brackets, FindManyOptions, In, SelectQueryBuilder, UpdateResult, WhereExpressionBuilder } from 'typeorm'; +import { InjectDataSource } from '@nestjs/typeorm'; +import { + Brackets, + DataSource, + FindManyOptions, + In, + SelectQueryBuilder, + UpdateResult, + WhereExpressionBuilder +} from 'typeorm'; import { BaseEntityEnum, ActorTypeEnum, @@ -35,6 +44,7 @@ import { TaskService } from '../tasks/task.service'; @Injectable() export class OrganizationProjectModuleService extends TenantAwareCrudService { constructor( + @InjectDataSource() private readonly dataSource: DataSource, readonly typeOrmProjectModuleRepository: TypeOrmOrganizationProjectModuleRepository, readonly mikroOrmProjectModuleRepository: MikroOrmOrganizationProjectModuleRepository, readonly typeOrmOrganizationProjectModuleEmployeeRepository: TypeOrmOrganizationProjectModuleEmployeeRepository, @@ -61,15 +71,20 @@ export class OrganizationProjectModuleService extends TenantAwareCrudService Date: Mon, 17 Feb 2025 11:49:53 +0530 Subject: [PATCH 8/8] fix: updated organization project module activity log --- .../organization-project-module.module.ts | 4 ++-- .../organization-project-module.service.ts | 22 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.module.ts b/packages/core/src/lib/organization-project-module/organization-project-module.module.ts index 549b714e4df..f310e7d71ac 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.module.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.module.ts @@ -6,13 +6,13 @@ import { CommandHandlers } from './commands/handlers'; import { OrganizationProjectModuleService } from './organization-project-module.service'; import { OrganizationProjectModuleController } from './organization-project-module.controller'; import { OrganizationProjectModule } from './organization-project-module.entity'; -import { TypeOrmOrganizationProjectModuleRepository } from './repository/type-orm-organization-project-module.repository'; import { RolePermissionModule } from '../role-permission/role-permission.module'; import { RoleModule } from '../role/role.module'; import { EmployeeModule } from '../employee/employee.module'; +import { TaskModule } from '../tasks/task.module'; import { OrganizationProjectModuleEmployee } from './organization-project-module-employee.entity'; +import { TypeOrmOrganizationProjectModuleRepository } from './repository/type-orm-organization-project-module.repository'; import { TypeOrmOrganizationProjectModuleEmployeeRepository } from './repository/type-orm-organization-project-module-employee.repository'; -import { TaskModule } from '../tasks'; @Module({ imports: [ diff --git a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts index f94fb97679c..cc536eda771 100644 --- a/packages/core/src/lib/organization-project-module/organization-project-module.service.ts +++ b/packages/core/src/lib/organization-project-module/organization-project-module.service.ts @@ -28,7 +28,7 @@ import { import { isEmpty, isNotEmpty } from '@gauzy/utils'; import { isPostgres } from '@gauzy/config'; import { PaginationParams, TenantAwareCrudService } from './../core/crud'; -import { RequestContext } from '../core/context'; +import { RequestContext } from '../core/context/request-context'; import { OrganizationProjectModule } from './organization-project-module.entity'; import { prepareSQLQuery as p } from './../database/database.helper'; import { ActivityLogService } from '../activity-log/activity-log.service'; @@ -49,7 +49,7 @@ export class OrganizationProjectModuleService extends TenantAwareCrudService ): void { - const tenantId = RequestContext.currentTenantId(); + const tenantId = RequestContext.currentTenantId() ?? updatedModule.tenantId; const organizationId = updatedModule.organizationId; - this.activityLogService.logActivity( + this._activityLogService.logActivity( BaseEntityEnum.OrganizationProjectModule, action, ActorTypeEnum.User,