From 8f311cd7a7b8fb877d203f62c296c0369acef88b Mon Sep 17 00:00:00 2001 From: GloireMutaliko21 Date: Tue, 11 Feb 2025 08:36:45 +0200 Subject: [PATCH 01/16] fix: comment entity employee based and add createdById --- packages/contracts/src/lib/comment.model.ts | 22 ++++++---- packages/contracts/src/lib/mention.model.ts | 4 +- .../contracts/src/lib/screening-task.model.ts | 4 +- packages/contracts/src/lib/task.model.ts | 4 +- packages/contracts/src/lib/user.model.ts | 2 +- .../core/src/lib/comment/comment.entity.ts | 43 ++++++++++++++----- .../core/src/lib/comment/comment.service.ts | 15 ++++--- .../src/lib/comment/dto/create-comment.dto.ts | 4 +- packages/core/src/lib/mention/dto/index.ts | 2 +- ...s.dto.ts => mentioned-employee-ids.dto.ts} | 6 +-- .../core/src/lib/mention/mention.service.ts | 12 +++--- .../commands/handlers/task-create.handler.ts | 6 +-- .../core/src/lib/tasks/dto/create-task.dto.ts | 4 +- .../dto/create-screening-task.dto.ts | 4 +- .../screening-tasks.service.ts | 4 +- packages/core/src/lib/tasks/task.service.ts | 4 +- 16 files changed, 85 insertions(+), 55 deletions(-) rename packages/core/src/lib/mention/dto/{mentioned-user-ids.dto.ts => mentioned-employee-ids.dto.ts} (54%) diff --git a/packages/contracts/src/lib/comment.model.ts b/packages/contracts/src/lib/comment.model.ts index 460db074954..3cfde7b19b2 100644 --- a/packages/contracts/src/lib/comment.model.ts +++ b/packages/contracts/src/lib/comment.model.ts @@ -1,17 +1,15 @@ import { ActorTypeEnum, IBasePerEntityType, IBasePerTenantAndOrganizationEntityModel, ID } from './base-entity.model'; import { IUser } from './user.model'; -import { IEmployee } from './employee.model'; +import { IEmployee, IEmployeeEntityInput } from './employee.model'; import { IOrganizationTeam } from './organization-team.model'; -import { IMentionUserIds } from './mention.model'; +import { IMentionEmployeeIds } from './mention.model'; -export interface IComment extends IBasePerTenantAndOrganizationEntityModel, IBasePerEntityType { +export interface IComment extends IBasePerTenantAndOrganizationEntityModel, IBasePerEntityType, IEmployeeEntityInput { comment: string; - creator?: IUser; - creatorId?: ID; // The comment's user author ID actorType?: ActorTypeEnum; resolved?: boolean; resolvedAt?: Date; - resolvedBy?: IUser; + resolvedBy?: IEmployee; resolvedById?: ID; editedAt?: Date; members?: IEmployee[]; // Indicates members assigned to comment @@ -19,9 +17,15 @@ export interface IComment extends IBasePerTenantAndOrganizationEntityModel, IBas parent?: IComment; parentId?: ID; // Specify the parent comment if current one is a reply replies?: IComment[]; + + createdBy?: IUser; + createdById?: ID; // The comment's user creator ID } -export interface ICommentCreateInput extends IBasePerEntityType, IMentionUserIds { +export interface ICommentCreateInput + extends IBasePerTenantAndOrganizationEntityModel, + IBasePerEntityType, + IMentionEmployeeIds { comment: string; parentId?: ID; members?: IEmployee[]; @@ -29,7 +33,7 @@ export interface ICommentCreateInput extends IBasePerEntityType, IMentionUserIds } export interface ICommentUpdateInput - extends IMentionUserIds, - Partial> {} + extends IMentionEmployeeIds, + Partial> {} export interface ICommentFindInput extends Pick {} diff --git a/packages/contracts/src/lib/mention.model.ts b/packages/contracts/src/lib/mention.model.ts index a50bf067f08..075bd0920ef 100644 --- a/packages/contracts/src/lib/mention.model.ts +++ b/packages/contracts/src/lib/mention.model.ts @@ -12,6 +12,6 @@ export interface IMention extends IBasePerTenantAndOrganizationEntityModel, IBas export interface IMentionCreateInput extends Omit {} -export interface IMentionUserIds { - mentionUserIds?: ID[]; +export interface IMentionEmployeeIds { + mentionEmployeeIds?: ID[]; } diff --git a/packages/contracts/src/lib/screening-task.model.ts b/packages/contracts/src/lib/screening-task.model.ts index 6361cbedc93..52f5d07ad21 100644 --- a/packages/contracts/src/lib/screening-task.model.ts +++ b/packages/contracts/src/lib/screening-task.model.ts @@ -1,5 +1,5 @@ import { IBasePerTenantAndOrganizationEntityModel, ID } from './base-entity.model'; -import { IMentionUserIds } from './mention.model'; +import { IMentionEmployeeIds } from './mention.model'; import { ITask } from './task.model'; import { IUser } from './user.model'; @@ -20,6 +20,6 @@ export enum ScreeningTaskStatusEnum { PENDING = 'pending' } -export interface IScreeningTaskCreateInput extends Omit, IMentionUserIds {} +export interface IScreeningTaskCreateInput extends Omit, IMentionEmployeeIds {} export interface IScreeningTaskUpdateInput extends Omit {} diff --git a/packages/contracts/src/lib/task.model.ts b/packages/contracts/src/lib/task.model.ts index b0f5534d0d4..3c9777a8d3c 100644 --- a/packages/contracts/src/lib/task.model.ts +++ b/packages/contracts/src/lib/task.model.ts @@ -15,7 +15,7 @@ import { ITaskPriority, TaskPriorityEnum } from './task-priority.model'; import { ITaskSize, TaskSizeEnum } from './task-size.model'; import { IOrganizationProjectModule } from './organization-project-module.model'; import { IIssueType, TaskTypeEnum } from './issue-type.model'; -import { IMentionUserIds } from './mention.model'; +import { IMentionEmployeeIds } from './mention.model'; export interface ITask extends IBasePerTenantAndOrganizationEntityModel, @@ -80,7 +80,7 @@ export enum TaskParticipantEnum { TEAMS = 'teams' } -export interface ITaskCreateInput extends ITask, IMentionUserIds {} +export interface ITaskCreateInput extends ITask, IMentionEmployeeIds {} export interface ITaskUpdateInput extends ITaskCreateInput { taskSprintMoveReason?: string; diff --git a/packages/contracts/src/lib/user.model.ts b/packages/contracts/src/lib/user.model.ts index eb47233acf4..bdd16b76dd2 100644 --- a/packages/contracts/src/lib/user.model.ts +++ b/packages/contracts/src/lib/user.model.ts @@ -36,7 +36,7 @@ export type ExcludeCreatorFields = Omit; * Interface representing a relationship with a creator. */ export interface IHasCreator { - creator?: IUser; + creator?: IUser; // TODO : Replace these properties with `createdBy` and `createdById` creatorId?: ID; } diff --git a/packages/core/src/lib/comment/comment.entity.ts b/packages/core/src/lib/comment/comment.entity.ts index 4f260dc1b4a..7d08138f01d 100644 --- a/packages/core/src/lib/comment/comment.entity.ts +++ b/packages/core/src/lib/comment/comment.entity.ts @@ -76,34 +76,34 @@ export class Comment extends TenantOrganizationBaseEntity implements IComment { */ /** - * User comment author + * Employee comment author */ - @ApiPropertyOptional({ type: () => Object }) - @IsOptional() - @MultiORMManyToOne(() => User, { + @MultiORMManyToOne(() => Employee, { /** Indicates if relation column value can be nullable or not. */ nullable: true, + /** Database cascade action on update. */ + onUpdate: 'CASCADE', + /** Database cascade action on delete. */ onDelete: 'CASCADE' }) - @JoinColumn() - creator?: IUser; + employee?: IEmployee; @ApiPropertyOptional({ type: () => String }) @IsOptional() @IsUUID() - @RelationId((it: Comment) => it.creator) + @RelationId((it: Comment) => it.employee) @ColumnIndex() @MultiORMColumn({ nullable: true, relationId: true }) - creatorId?: ID; + employeeId?: ID; /** * User marked comment as resolved */ @ApiPropertyOptional({ type: () => Object }) @IsOptional() - @MultiORMManyToOne(() => User, { + @MultiORMManyToOne(() => Employee, { /** Indicates if relation column value can be nullable or not. */ nullable: true, @@ -111,7 +111,7 @@ export class Comment extends TenantOrganizationBaseEntity implements IComment { onDelete: 'CASCADE' }) @JoinColumn() - resolvedBy?: IUser; + resolvedBy?: IEmployee; @ApiPropertyOptional({ type: () => String }) @IsOptional() @@ -138,6 +138,29 @@ export class Comment extends TenantOrganizationBaseEntity implements IComment { @MultiORMColumn({ nullable: true, relationId: true }) parentId?: ID; + /** + * User comment creator + */ + @ApiPropertyOptional({ type: () => Object }) + @IsOptional() + @MultiORMManyToOne(() => User, { + /** Indicates if relation column value can be nullable or not. */ + nullable: true, + + /** Database cascade action on delete. */ + onDelete: 'CASCADE' + }) + @JoinColumn() + createdBy?: IUser; + + @ApiPropertyOptional({ type: () => String }) + @IsOptional() + @IsUUID() + @RelationId((it: Comment) => it.createdBy) + @ColumnIndex() + @MultiORMColumn({ nullable: true, relationId: true }) + createdById?: ID; + /* |-------------------------------------------------------------------------- | @OneToMany diff --git a/packages/core/src/lib/comment/comment.service.ts b/packages/core/src/lib/comment/comment.service.ts index e131c904846..bdd985763d1 100644 --- a/packages/core/src/lib/comment/comment.service.ts +++ b/packages/core/src/lib/comment/comment.service.ts @@ -39,8 +39,9 @@ export class CommentService extends TenantAwareCrudService { async create(input: ICommentCreateInput): Promise { try { const userId = RequestContext.currentUserId(); + const employeeId = RequestContext.currentEmployeeId(); const tenantId = RequestContext.currentTenantId(); - const { mentionUserIds = [], ...data } = input; + const { mentionEmployeeIds = [], organizationId, ...data } = input; // Employee existence validation const user = await this.userService.findOneByIdString(userId); @@ -51,13 +52,15 @@ export class CommentService extends TenantAwareCrudService { // create comment const comment = await super.create({ ...data, + employeeId, + createdById: user.id, tenantId, - creatorId: user.id + organizationId }); // Apply mentions if needed await Promise.all( - mentionUserIds.map((mentionedUserId) => + mentionEmployeeIds.map((mentionedUserId) => this.mentionService.publishMention({ entity: BaseEntityEnum.Comment, entityId: comment.id, @@ -100,13 +103,13 @@ export class CommentService extends TenantAwareCrudService { */ async update(id: ID, input: ICommentUpdateInput): Promise { try { - const { mentionUserIds = [] } = input; + const { mentionEmployeeIds = [] } = input; const userId = RequestContext.currentUserId(); const comment = await this.findOneByOptions({ where: { id, - creatorId: userId + createdById: userId } }); @@ -123,7 +126,7 @@ export class CommentService extends TenantAwareCrudService { await this.mentionService.updateEntityMentions( BaseEntityEnum.Comment, id, - mentionUserIds, + mentionEmployeeIds, updatedComment.entityId, updatedComment.entity ); diff --git a/packages/core/src/lib/comment/dto/create-comment.dto.ts b/packages/core/src/lib/comment/dto/create-comment.dto.ts index 66780ad4ec5..62fc3035f43 100644 --- a/packages/core/src/lib/comment/dto/create-comment.dto.ts +++ b/packages/core/src/lib/comment/dto/create-comment.dto.ts @@ -1,7 +1,7 @@ import { IntersectionType, OmitType } from '@nestjs/swagger'; import { ICommentCreateInput } from '@gauzy/contracts'; import { TenantOrganizationBaseDTO } from './../../core/dto'; -import { MentionUserIdsDTO } from '../../mention/dto'; +import { MentionEmployeeIdsDTO } from '../../mention/dto'; import { Comment } from '../comment.entity'; /** @@ -10,6 +10,6 @@ import { Comment } from '../comment.entity'; export class CreateCommentDTO extends IntersectionType( TenantOrganizationBaseDTO, - IntersectionType(OmitType(Comment, ['creatorId', 'creator']), MentionUserIdsDTO) + IntersectionType(OmitType(Comment, ['createdById', 'createdBy']), MentionEmployeeIdsDTO) ) implements ICommentCreateInput {} diff --git a/packages/core/src/lib/mention/dto/index.ts b/packages/core/src/lib/mention/dto/index.ts index 40c18c3cc21..a733205ff15 100644 --- a/packages/core/src/lib/mention/dto/index.ts +++ b/packages/core/src/lib/mention/dto/index.ts @@ -1 +1 @@ -export * from './mentioned-user-ids.dto'; +export * from './mentioned-employee-ids.dto'; diff --git a/packages/core/src/lib/mention/dto/mentioned-user-ids.dto.ts b/packages/core/src/lib/mention/dto/mentioned-employee-ids.dto.ts similarity index 54% rename from packages/core/src/lib/mention/dto/mentioned-user-ids.dto.ts rename to packages/core/src/lib/mention/dto/mentioned-employee-ids.dto.ts index 6c9bced5505..20dfcf8610d 100644 --- a/packages/core/src/lib/mention/dto/mentioned-user-ids.dto.ts +++ b/packages/core/src/lib/mention/dto/mentioned-employee-ids.dto.ts @@ -1,10 +1,10 @@ import { ApiPropertyOptional } from '@nestjs/swagger'; import { IsArray, IsOptional } from 'class-validator'; -import { ID, IMentionUserIds } from '@gauzy/contracts'; +import { ID, IMentionEmployeeIds } from '@gauzy/contracts'; -export class MentionUserIdsDTO implements IMentionUserIds { +export class MentionEmployeeIdsDTO implements IMentionEmployeeIds { @ApiPropertyOptional({ type: () => Array }) @IsOptional() @IsArray() - mentionUserIds?: ID[]; + mentionEmployeeIds?: ID[]; } diff --git a/packages/core/src/lib/mention/mention.service.ts b/packages/core/src/lib/mention/mention.service.ts index 4dfda23ee9b..ac15b396d07 100644 --- a/packages/core/src/lib/mention/mention.service.ts +++ b/packages/core/src/lib/mention/mention.service.ts @@ -81,18 +81,18 @@ export class MentionService extends TenantAwareCrudService { * * This method handles adding new mentions and removing outdated mentions * for an entity (e.g., comments, tasks, or projects). It ensures that only - * the specified user mentions (`newMentionUserIds`) are associated with the entity. + * the specified user mentions (`newmentionEmployeeIds`) are associated with the entity. * * @param entity - The type of entity being updated (e.g., Comment, Task, etc.). * @param entityId - The ID of the entity being updated. - * @param mentionUserIds - Array of user IDs to be mentioned in this entity. + * @param mentionEmployeeIds - Array of user IDs to be mentioned in this entity. * @param parentEntityId - (Optional) The ID of the parent entity, if applicable. * @param parentEntityType - (Optional) The type of the parent entity, if applicable. */ async updateEntityMentions( entity: BaseEntityEnum, entityId: ID, - mentionUserIds: ID[], + mentionEmployeeIds: ID[], parentEntityId?: ID, parentEntityType?: BaseEntityEnum ): Promise { @@ -106,13 +106,13 @@ export class MentionService extends TenantAwareCrudService { }); // Extract the IDs of currently mentioned users - const existingMentionUserIds = new Set(existingMentions.map((mention) => mention.mentionedUserId)); + const existingmentionEmployeeIds = new Set(existingMentions.map((mention) => mention.mentionedUserId)); // Determine mentions to add (not present in existing mentions) - const mentionsToAdd = mentionUserIds.filter((id) => !existingMentionUserIds.has(id)); + const mentionsToAdd = mentionEmployeeIds.filter((id) => !existingmentionEmployeeIds.has(id)); // Determine mentions to remove (present in existing mentions but not in mentionsIds) - const mentionsToRemove = [...existingMentionUserIds].filter((id) => !mentionUserIds.includes(id)); + const mentionsToRemove = [...existingmentionEmployeeIds].filter((id) => !mentionEmployeeIds.includes(id)); // Add new mentions if (mentionsToAdd.length > 0) { diff --git a/packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts b/packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts index 0ba74e57250..85bef44bbb6 100644 --- a/packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts +++ b/packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts @@ -47,7 +47,7 @@ export class TaskCreateHandler implements ICommandHandler { try { // Destructure input and triggered event flag from the command const { input, triggeredEvent } = command; - const { organizationId, mentionUserIds = [], members = [], ...data } = input; + const { organizationId, mentionEmployeeIds = [], members = [], ...data } = input; // Retrieve current tenant ID from request context or use input tenant ID const tenantId = RequestContext.currentTenantId() ?? data.tenantId; @@ -89,9 +89,9 @@ export class TaskCreateHandler implements ICommandHandler { } // Apply mentions if needed - if (mentionUserIds.length > 0) { + if (mentionEmployeeIds.length > 0) { await Promise.all( - mentionUserIds.map((mentionedUserId: ID) => + mentionEmployeeIds.map((mentionedUserId: ID) => this.mentionService.publishMention({ entity: BaseEntityEnum.Task, entityId: task.id, diff --git a/packages/core/src/lib/tasks/dto/create-task.dto.ts b/packages/core/src/lib/tasks/dto/create-task.dto.ts index 2f60e916096..a71eca3e9f1 100644 --- a/packages/core/src/lib/tasks/dto/create-task.dto.ts +++ b/packages/core/src/lib/tasks/dto/create-task.dto.ts @@ -1,7 +1,7 @@ import { ITaskCreateInput } from '@gauzy/contracts'; import { IntersectionType, OmitType } from '@nestjs/swagger'; import { TenantOrganizationBaseDTO } from './../../core/dto'; -import { MentionUserIdsDTO } from '../../mention/dto'; +import { MentionEmployeeIdsDTO } from '../../mention/dto'; import { Task } from './../task.entity'; /** @@ -10,6 +10,6 @@ import { Task } from './../task.entity'; export class CreateTaskDTO extends IntersectionType( TenantOrganizationBaseDTO, - IntersectionType(OmitType(Task, ['organizationId', 'organization']), MentionUserIdsDTO) + IntersectionType(OmitType(Task, ['organizationId', 'organization']), MentionEmployeeIdsDTO) ) implements ITaskCreateInput {} diff --git a/packages/core/src/lib/tasks/screening-tasks/dto/create-screening-task.dto.ts b/packages/core/src/lib/tasks/screening-tasks/dto/create-screening-task.dto.ts index ee374310636..c043a3e4e9b 100644 --- a/packages/core/src/lib/tasks/screening-tasks/dto/create-screening-task.dto.ts +++ b/packages/core/src/lib/tasks/screening-tasks/dto/create-screening-task.dto.ts @@ -1,7 +1,7 @@ import { IntersectionType, OmitType } from '@nestjs/swagger'; import { IScreeningTaskCreateInput } from '@gauzy/contracts'; import { TenantOrganizationBaseDTO } from '../../../core/dto'; -import { MentionUserIdsDTO } from '../../../mention/dto'; +import { MentionEmployeeIdsDTO } from '../../../mention/dto'; import { ScreeningTask } from '../screening-task.entity'; /** @@ -10,6 +10,6 @@ import { ScreeningTask } from '../screening-task.entity'; export class CreateScreeningTaskDTO extends IntersectionType( TenantOrganizationBaseDTO, - IntersectionType(OmitType(ScreeningTask, ['status']), MentionUserIdsDTO) + IntersectionType(OmitType(ScreeningTask, ['status']), MentionEmployeeIdsDTO) ) implements IScreeningTaskCreateInput {} diff --git a/packages/core/src/lib/tasks/screening-tasks/screening-tasks.service.ts b/packages/core/src/lib/tasks/screening-tasks/screening-tasks.service.ts index ab67b74ced6..04e92a7dda1 100644 --- a/packages/core/src/lib/tasks/screening-tasks/screening-tasks.service.ts +++ b/packages/core/src/lib/tasks/screening-tasks/screening-tasks.service.ts @@ -49,7 +49,7 @@ export class ScreeningTasksService extends TenantAwareCrudService try { const userId = RequestContext.currentUserId(); const tenantId = RequestContext.currentTenantId() || input.tenantId; - const { organizationId, mentionUserIds = [] } = input; + const { organizationId, mentionEmployeeIds = [] } = input; // Check if projectId is provided, if not use the provided project object from the input. // If neither is provided, set project to null. @@ -94,7 +94,7 @@ export class ScreeningTasksService extends TenantAwareCrudService }); // Apply mentions if needed - const mentionPromises = mentionUserIds.map((mentionedUserId) => + const mentionPromises = mentionEmployeeIds.map((mentionedUserId) => this.mentionService.publishMention({ entity: BaseEntityEnum.Task, entityId: task.id, diff --git a/packages/core/src/lib/tasks/task.service.ts b/packages/core/src/lib/tasks/task.service.ts index 88850bac4a8..d3b274b24ed 100644 --- a/packages/core/src/lib/tasks/task.service.ts +++ b/packages/core/src/lib/tasks/task.service.ts @@ -73,7 +73,7 @@ export class TaskService extends TenantAwareCrudService { try { const tenantId = RequestContext.currentTenantId() || input.tenantId; const userId = RequestContext.currentUserId(); - const { mentionUserIds, ...data } = input; + const { mentionEmployeeIds, ...data } = input; // Find task relations const relations: FindOptionsRelations = { @@ -142,7 +142,7 @@ export class TaskService extends TenantAwareCrudService { // Synchronize mentions if (data.description) { try { - await this.mentionService.updateEntityMentions(BaseEntityEnum.Task, id, mentionUserIds); + await this.mentionService.updateEntityMentions(BaseEntityEnum.Task, id, mentionEmployeeIds); } catch (error) { console.error('Error synchronizing mentions:', error); } From c480b725f2f839f795dd22feb965c0bbe3100db9 Mon Sep 17 00:00:00 2001 From: GloireMutaliko21 Date: Tue, 11 Feb 2025 09:41:11 +0200 Subject: [PATCH 02/16] feat: generate migration for comment table based on employee --- ...362112-AlterCommentTableUsingEmployeeId.ts | 391 ++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 packages/core/src/lib/database/migrations/1739256362112-AlterCommentTableUsingEmployeeId.ts diff --git a/packages/core/src/lib/database/migrations/1739256362112-AlterCommentTableUsingEmployeeId.ts b/packages/core/src/lib/database/migrations/1739256362112-AlterCommentTableUsingEmployeeId.ts new file mode 100644 index 00000000000..ac72a8befdc --- /dev/null +++ b/packages/core/src/lib/database/migrations/1739256362112-AlterCommentTableUsingEmployeeId.ts @@ -0,0 +1,391 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; +import * as chalk from 'chalk'; +import { DatabaseTypeEnum } from '@gauzy/config'; + +export class AlterCommentTableUsingEmployeeId1739256362112 implements MigrationInterface { + name = 'AlterCommentTableUsingEmployeeId1739256362112'; + + /** + * Up Migration + * + * @param queryRunner + */ + public async up(queryRunner: QueryRunner): Promise { + console.log(chalk.yellow(this.name + ' start running!')); + + switch (queryRunner.connection.options.type) { + case DatabaseTypeEnum.sqlite: + case DatabaseTypeEnum.betterSqlite3: + await this.sqliteUpQueryRunner(queryRunner); + break; + case DatabaseTypeEnum.postgres: + await this.postgresUpQueryRunner(queryRunner); + break; + case DatabaseTypeEnum.mysql: + await this.mysqlUpQueryRunner(queryRunner); + break; + default: + throw Error(`Unsupported database: ${queryRunner.connection.options.type}`); + } + } + + /** + * Down Migration + * + * @param queryRunner + */ + public async down(queryRunner: QueryRunner): Promise { + switch (queryRunner.connection.options.type) { + case DatabaseTypeEnum.sqlite: + case DatabaseTypeEnum.betterSqlite3: + await this.sqliteDownQueryRunner(queryRunner); + break; + case DatabaseTypeEnum.postgres: + await this.postgresDownQueryRunner(queryRunner); + break; + case DatabaseTypeEnum.mysql: + await this.mysqlDownQueryRunner(queryRunner); + break; + default: + throw Error(`Unsupported database: ${queryRunner.connection.options.type}`); + } + } + + /** + * PostgresDB Up Migration + * + * @param queryRunner + */ + public async postgresUpQueryRunner(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f"`); + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3"`); + await queryRunner.query(`DROP INDEX "public"."IDX_b6bf60ecb9f6c398e349adff52"`); + await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "creatorId"`); + await queryRunner.query(`ALTER TABLE "comment" ADD "employeeId" uuid`); + await queryRunner.query(`ALTER TABLE "comment" ADD "createdById" uuid`); + await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId") `); + await queryRunner.query(`CREATE INDEX "IDX_63ac916757350d28f05c5a6a4b" ON "comment" ("createdById") `); + await queryRunner.query( + `ALTER TABLE "comment" ADD CONSTRAINT "FK_7a88834dadfa6fe261268bfceef" FOREIGN KEY ("employeeId") REFERENCES "employee"("id") ON DELETE CASCADE ON UPDATE CASCADE` + ); + await queryRunner.query( + `ALTER TABLE "comment" ADD CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "employee"("id") ON DELETE CASCADE ON UPDATE NO ACTION` + ); + await queryRunner.query( + `ALTER TABLE "comment" ADD CONSTRAINT "FK_63ac916757350d28f05c5a6a4ba" FOREIGN KEY ("createdById") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION` + ); + } + + /** + * PostgresDB Down Migration + * + * @param queryRunner + */ + public async postgresDownQueryRunner(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_63ac916757350d28f05c5a6a4ba"`); + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3"`); + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_7a88834dadfa6fe261268bfceef"`); + await queryRunner.query(`DROP INDEX "public"."IDX_63ac916757350d28f05c5a6a4b"`); + await queryRunner.query(`DROP INDEX "public"."IDX_7a88834dadfa6fe261268bfcee"`); + await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "createdById"`); + await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "employeeId"`); + await queryRunner.query(`ALTER TABLE "comment" ADD "creatorId" uuid`); + await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); + await queryRunner.query( + `ALTER TABLE "comment" ADD CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION` + ); + await queryRunner.query( + `ALTER TABLE "comment" ADD CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f" FOREIGN KEY ("creatorId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION` + ); + } + + /** + * SqliteDB and BetterSQlite3DB Up Migration + * + * @param queryRunner + */ + public async sqliteUpQueryRunner(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_b6bf60ecb9f6c398e349adff52"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query( + `CREATE TABLE "temporary_comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "creatorId" varchar, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "temporary_comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "creatorId", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "creatorId", "resolvedById", "parentId" FROM "comment"` + ); + await queryRunner.query(`DROP TABLE "comment"`); + await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`DROP INDEX "IDX_b6bf60ecb9f6c398e349adff52"`); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query( + `CREATE TABLE "temporary_comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "temporary_comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId" FROM "comment"` + ); + await queryRunner.query(`DROP TABLE "comment"`); + await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query( + `CREATE TABLE "temporary_comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, "employeeId" varchar, "createdById" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "temporary_comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId" FROM "comment"` + ); + await queryRunner.query(`DROP TABLE "comment"`); + await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId") `); + await queryRunner.query(`CREATE INDEX "IDX_63ac916757350d28f05c5a6a4b" ON "comment" ("createdById") `); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query(`DROP INDEX "IDX_7a88834dadfa6fe261268bfcee"`); + await queryRunner.query(`DROP INDEX "IDX_63ac916757350d28f05c5a6a4b"`); + await queryRunner.query( + `CREATE TABLE "temporary_comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, "employeeId" varchar, "createdById" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_7a88834dadfa6fe261268bfceef" FOREIGN KEY ("employeeId") REFERENCES "employee" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "employee" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_63ac916757350d28f05c5a6a4ba" FOREIGN KEY ("createdById") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "temporary_comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId", "employeeId", "createdById") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId", "employeeId", "createdById" FROM "comment"` + ); + await queryRunner.query(`DROP TABLE "comment"`); + await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId") `); + await queryRunner.query(`CREATE INDEX "IDX_63ac916757350d28f05c5a6a4b" ON "comment" ("createdById") `); + } + + /** + * SqliteDB and BetterSQlite3DB Down Migration + * + * @param queryRunner + */ + public async sqliteDownQueryRunner(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_63ac916757350d28f05c5a6a4b"`); + await queryRunner.query(`DROP INDEX "IDX_7a88834dadfa6fe261268bfcee"`); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); + await queryRunner.query( + `CREATE TABLE "comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, "employeeId" varchar, "createdById" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId", "employeeId", "createdById") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId", "employeeId", "createdById" FROM "temporary_comment"` + ); + await queryRunner.query(`DROP TABLE "temporary_comment"`); + await queryRunner.query(`CREATE INDEX "IDX_63ac916757350d28f05c5a6a4b" ON "comment" ("createdById") `); + await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId") `); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + await queryRunner.query(`DROP INDEX "IDX_63ac916757350d28f05c5a6a4b"`); + await queryRunner.query(`DROP INDEX "IDX_7a88834dadfa6fe261268bfcee"`); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); + await queryRunner.query( + `CREATE TABLE "comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId" FROM "temporary_comment"` + ); + await queryRunner.query(`DROP TABLE "temporary_comment"`); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); + await queryRunner.query( + `CREATE TABLE "comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "creatorId" varchar, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId" FROM "temporary_comment"` + ); + await queryRunner.query(`DROP TABLE "temporary_comment"`); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_b6bf60ecb9f6c398e349adff52"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); + await queryRunner.query( + `CREATE TABLE "comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "creatorId" varchar, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f" FOREIGN KEY ("creatorId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` + ); + await queryRunner.query( + `INSERT INTO "comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "creatorId", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "creatorId", "resolvedById", "parentId" FROM "temporary_comment"` + ); + await queryRunner.query(`DROP TABLE "temporary_comment"`); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + } + + /** + * MySQL Up Migration + * + * @param queryRunner + */ + public async mysqlUpQueryRunner(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_b6bf60ecb9f6c398e349adff52f\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_c9409c81aa283c1aae70fd5f4c3\``); + await queryRunner.query(`DROP INDEX \`IDX_b6bf60ecb9f6c398e349adff52\` ON \`comment\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`creatorId\``); + await queryRunner.query(`ALTER TABLE \`comment\` ADD \`employeeId\` varchar(255) NULL`); + await queryRunner.query(`ALTER TABLE \`comment\` ADD \`createdById\` varchar(255) NULL`); + await queryRunner.query(`CREATE INDEX \`IDX_7a88834dadfa6fe261268bfcee\` ON \`comment\` (\`employeeId\`)`); + await queryRunner.query(`CREATE INDEX \`IDX_63ac916757350d28f05c5a6a4b\` ON \`comment\` (\`createdById\`)`); + await queryRunner.query( + `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_7a88834dadfa6fe261268bfceef\` FOREIGN KEY (\`employeeId\`) REFERENCES \`employee\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE` + ); + await queryRunner.query( + `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_c9409c81aa283c1aae70fd5f4c3\` FOREIGN KEY (\`resolvedById\`) REFERENCES \`employee\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` + ); + await queryRunner.query( + `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_63ac916757350d28f05c5a6a4ba\` FOREIGN KEY (\`createdById\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` + ); + } + + /** + * MySQL Down Migration + * + * @param queryRunner + */ + public async mysqlDownQueryRunner(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_63ac916757350d28f05c5a6a4ba\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_c9409c81aa283c1aae70fd5f4c3\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_7a88834dadfa6fe261268bfceef\``); + await queryRunner.query(`DROP INDEX \`IDX_63ac916757350d28f05c5a6a4b\` ON \`comment\``); + await queryRunner.query(`DROP INDEX \`IDX_7a88834dadfa6fe261268bfcee\` ON \`comment\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`createdById\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`employeeId\``); + await queryRunner.query(`ALTER TABLE \`comment\` ADD \`creatorId\` varchar(255) NULL`); + await queryRunner.query(`CREATE INDEX \`IDX_b6bf60ecb9f6c398e349adff52\` ON \`comment\` (\`creatorId\`)`); + await queryRunner.query( + `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_c9409c81aa283c1aae70fd5f4c3\` FOREIGN KEY (\`resolvedById\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` + ); + await queryRunner.query( + `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_b6bf60ecb9f6c398e349adff52f\` FOREIGN KEY (\`creatorId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` + ); + } +} From 5a47783d841530ab09c8409c9d5d326ac63eff66 Mon Sep 17 00:00:00 2001 From: GloireMutaliko21 Date: Tue, 11 Feb 2025 09:46:35 +0200 Subject: [PATCH 03/16] fix(typos) cspell errors --- packages/core/src/lib/mention/mention.service.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/lib/mention/mention.service.ts b/packages/core/src/lib/mention/mention.service.ts index ac15b396d07..685401044ef 100644 --- a/packages/core/src/lib/mention/mention.service.ts +++ b/packages/core/src/lib/mention/mention.service.ts @@ -81,7 +81,7 @@ export class MentionService extends TenantAwareCrudService { * * This method handles adding new mentions and removing outdated mentions * for an entity (e.g., comments, tasks, or projects). It ensures that only - * the specified user mentions (`newmentionEmployeeIds`) are associated with the entity. + * the specified user mentions (`newMentionEmployeeIds`) are associated with the entity. * * @param entity - The type of entity being updated (e.g., Comment, Task, etc.). * @param entityId - The ID of the entity being updated. @@ -106,13 +106,13 @@ export class MentionService extends TenantAwareCrudService { }); // Extract the IDs of currently mentioned users - const existingmentionEmployeeIds = new Set(existingMentions.map((mention) => mention.mentionedUserId)); + const existingMentionEmployeeIds = new Set(existingMentions.map((mention) => mention.mentionedUserId)); // Determine mentions to add (not present in existing mentions) - const mentionsToAdd = mentionEmployeeIds.filter((id) => !existingmentionEmployeeIds.has(id)); + const mentionsToAdd = mentionEmployeeIds.filter((id) => !existingMentionEmployeeIds.has(id)); // Determine mentions to remove (present in existing mentions but not in mentionsIds) - const mentionsToRemove = [...existingmentionEmployeeIds].filter((id) => !mentionEmployeeIds.includes(id)); + const mentionsToRemove = [...existingMentionEmployeeIds].filter((id) => !mentionEmployeeIds.includes(id)); // Add new mentions if (mentionsToAdd.length > 0) { From 6a7d7e0ef9f2ccd855003593145efdd0bad748da Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 12 Feb 2025 15:07:40 +0530 Subject: [PATCH 04/16] fix: comment entity employee as author ID --- .../contracts/src/lib/base-entity.model.ts | 1 + packages/contracts/src/lib/comment.model.ts | 17 +- .../core/src/lib/comment/comment.entity.ts | 71 +--- ...362112-AlterCommentTableUsingEmployeeId.ts | 391 ------------------ 4 files changed, 29 insertions(+), 451 deletions(-) delete mode 100644 packages/core/src/lib/database/migrations/1739256362112-AlterCommentTableUsingEmployeeId.ts diff --git a/packages/contracts/src/lib/base-entity.model.ts b/packages/contracts/src/lib/base-entity.model.ts index cf415ddbd75..1462d0fddff 100644 --- a/packages/contracts/src/lib/base-entity.model.ts +++ b/packages/contracts/src/lib/base-entity.model.ts @@ -80,6 +80,7 @@ export enum ActorTypeEnum { User = 'User' // User performed the action } +// BaseEntityEnum defines the type of the entity, used in BaseEntity model export enum BaseEntityEnum { Candidate = 'Candidate', Comment = 'Comment', diff --git a/packages/contracts/src/lib/comment.model.ts b/packages/contracts/src/lib/comment.model.ts index be40498ad88..d44498ce784 100644 --- a/packages/contracts/src/lib/comment.model.ts +++ b/packages/contracts/src/lib/comment.model.ts @@ -1,37 +1,34 @@ import { ActorTypeEnum, IBasePerEntityType, ID } from './base-entity.model'; -import { IUser } from './user.model'; -import { IEmployee, IEmployeeEntityInput } from './employee.model'; +import { IEmployee, IEmployeeEntityInput as ICommentAuthor } from './employee.model'; import { IOrganizationTeam } from './organization-team.model'; import { IMentionEmployeeIds } from './mention.model'; -export interface IComment extends IBasePerEntityType, IEmployeeEntityInput { +export interface IComment extends IBasePerEntityType, ICommentAuthor { comment: string; actorType?: ActorTypeEnum; resolved?: boolean; resolvedAt?: Date; - resolvedBy?: IEmployee; - resolvedById?: ID; editedAt?: Date; members?: IEmployee[]; // Indicates members assigned to comment teams?: IOrganizationTeam[]; // Indicates teams assigned to comment parent?: IComment; parentId?: ID; // Specify the parent comment if current one is a reply replies?: IComment[]; - - createdBy?: IUser; - createdById?: ID; // The comment's user creator ID + resolvedBy?: IEmployee; // Indicates the employee who resolved the comment + resolvedById?: ID; // Indicates the employee ID who resolved the comment } export interface ICommentCreateInput extends IBasePerEntityType, IMentionEmployeeIds { comment: string; entityName?: string; - parentId?: ID; + parent?: IComment; + parentId?: ID; // Specify the parent comment if current one is a reply members?: IEmployee[]; teams?: IOrganizationTeam[]; } export interface ICommentUpdateInput extends IMentionEmployeeIds, - Partial> {} + Partial> {} export interface ICommentFindInput extends Pick {} diff --git a/packages/core/src/lib/comment/comment.entity.ts b/packages/core/src/lib/comment/comment.entity.ts index 50ab1272f5c..4c90607aa12 100644 --- a/packages/core/src/lib/comment/comment.entity.ts +++ b/packages/core/src/lib/comment/comment.entity.ts @@ -2,10 +2,10 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { EntityRepositoryType } from '@mikro-orm/core'; import { JoinColumn, JoinTable, RelationId } from 'typeorm'; -import { IsArray, IsBoolean, IsDate, IsEnum, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator'; +import { IsBoolean, IsDate, IsEnum, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator'; import { Type } from 'class-transformer'; -import { ActorTypeEnum, IComment, ID, IEmployee, IOrganizationTeam, IUser } from '@gauzy/contracts'; -import { BasePerEntityType, Employee, OrganizationTeam, User } from '../core/entities/internal'; +import { ActorTypeEnum, IComment, ID, IEmployee, IOrganizationTeam } from '@gauzy/contracts'; +import { BasePerEntityType, Employee, OrganizationTeam } from '../core/entities/internal'; import { ColumnIndex, MultiORMColumn, @@ -59,22 +59,21 @@ export class Comment extends BasePerEntityType implements IComment { | @ManyToOne |-------------------------------------------------------------------------- */ - /** - * Employee comment author + * Comment author */ @MultiORMManyToOne(() => Employee, { /** Indicates if relation column value can be nullable or not. */ nullable: true, - /** Database cascade action on update. */ - onUpdate: 'CASCADE', - /** Database cascade action on delete. */ onDelete: 'CASCADE' }) employee?: IEmployee; + /** + * Comment author ID + */ @ApiPropertyOptional({ type: () => String }) @IsOptional() @IsUUID() @@ -84,10 +83,8 @@ export class Comment extends BasePerEntityType implements IComment { employeeId?: ID; /** - * User marked comment as resolved + * Resolved by */ - @ApiPropertyOptional({ type: () => Object }) - @IsOptional() @MultiORMManyToOne(() => Employee, { /** Indicates if relation column value can be nullable or not. */ nullable: true, @@ -98,6 +95,9 @@ export class Comment extends BasePerEntityType implements IComment { @JoinColumn() resolvedBy?: IEmployee; + /** + * Resolved by ID + */ @ApiPropertyOptional({ type: () => String }) @IsOptional() @IsUUID() @@ -109,49 +109,30 @@ export class Comment extends BasePerEntityType implements IComment { /** * Comment parent-child relationship */ - @ApiPropertyOptional({ type: () => Comment }) - @IsOptional() @MultiORMManyToOne(() => Comment, (comment) => comment.replies, { - onDelete: 'SET NULL' - }) - parent?: IComment; - - @ApiPropertyOptional({ type: () => String }) - @IsOptional() - @IsUUID() - @ColumnIndex() - @MultiORMColumn({ nullable: true, relationId: true }) - parentId?: ID; - - /** - * User comment creator - */ - @ApiPropertyOptional({ type: () => Object }) - @IsOptional() - @MultiORMManyToOne(() => User, { /** Indicates if relation column value can be nullable or not. */ nullable: true, /** Database cascade action on delete. */ - onDelete: 'CASCADE' + onDelete: 'SET NULL' }) - @JoinColumn() - createdBy?: IUser; + parent?: IComment; + /** + * Parent ID of comment + */ @ApiPropertyOptional({ type: () => String }) @IsOptional() @IsUUID() - @RelationId((it: Comment) => it.createdBy) @ColumnIndex() @MultiORMColumn({ nullable: true, relationId: true }) - createdById?: ID; + parentId?: ID; /* |-------------------------------------------------------------------------- | @OneToMany |-------------------------------------------------------------------------- */ - /** * Replies comments */ @@ -164,11 +145,8 @@ export class Comment extends BasePerEntityType implements IComment { |-------------------------------------------------------------------------- */ /** - * Members + * */ - @ApiPropertyOptional({ type: () => Array, isArray: true }) - @IsOptional() - @IsArray() @MultiORMManyToMany(() => Employee, (employee) => employee.assignedComments, { onUpdate: 'CASCADE', onDelete: 'CASCADE', @@ -177,17 +155,12 @@ export class Comment extends BasePerEntityType implements IComment { joinColumn: 'commentId', inverseJoinColumn: 'employeeId' }) - @JoinTable({ - name: 'comment_employee' - }) + @JoinTable({ name: 'comment_employee' }) members?: IEmployee[]; /** - * OrganizationTeam + * */ - @ApiPropertyOptional({ type: () => Array, isArray: true }) - @IsOptional() - @IsArray() @MultiORMManyToMany(() => OrganizationTeam, (team) => team.assignedComments, { onUpdate: 'CASCADE', onDelete: 'CASCADE', @@ -196,8 +169,6 @@ export class Comment extends BasePerEntityType implements IComment { joinColumn: 'commentId', inverseJoinColumn: 'organizationTeamId' }) - @JoinTable({ - name: 'comment_team' - }) + @JoinTable({ name: 'comment_team' }) teams?: IOrganizationTeam[]; } diff --git a/packages/core/src/lib/database/migrations/1739256362112-AlterCommentTableUsingEmployeeId.ts b/packages/core/src/lib/database/migrations/1739256362112-AlterCommentTableUsingEmployeeId.ts deleted file mode 100644 index ac72a8befdc..00000000000 --- a/packages/core/src/lib/database/migrations/1739256362112-AlterCommentTableUsingEmployeeId.ts +++ /dev/null @@ -1,391 +0,0 @@ -import { MigrationInterface, QueryRunner } from 'typeorm'; -import * as chalk from 'chalk'; -import { DatabaseTypeEnum } from '@gauzy/config'; - -export class AlterCommentTableUsingEmployeeId1739256362112 implements MigrationInterface { - name = 'AlterCommentTableUsingEmployeeId1739256362112'; - - /** - * Up Migration - * - * @param queryRunner - */ - public async up(queryRunner: QueryRunner): Promise { - console.log(chalk.yellow(this.name + ' start running!')); - - switch (queryRunner.connection.options.type) { - case DatabaseTypeEnum.sqlite: - case DatabaseTypeEnum.betterSqlite3: - await this.sqliteUpQueryRunner(queryRunner); - break; - case DatabaseTypeEnum.postgres: - await this.postgresUpQueryRunner(queryRunner); - break; - case DatabaseTypeEnum.mysql: - await this.mysqlUpQueryRunner(queryRunner); - break; - default: - throw Error(`Unsupported database: ${queryRunner.connection.options.type}`); - } - } - - /** - * Down Migration - * - * @param queryRunner - */ - public async down(queryRunner: QueryRunner): Promise { - switch (queryRunner.connection.options.type) { - case DatabaseTypeEnum.sqlite: - case DatabaseTypeEnum.betterSqlite3: - await this.sqliteDownQueryRunner(queryRunner); - break; - case DatabaseTypeEnum.postgres: - await this.postgresDownQueryRunner(queryRunner); - break; - case DatabaseTypeEnum.mysql: - await this.mysqlDownQueryRunner(queryRunner); - break; - default: - throw Error(`Unsupported database: ${queryRunner.connection.options.type}`); - } - } - - /** - * PostgresDB Up Migration - * - * @param queryRunner - */ - public async postgresUpQueryRunner(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f"`); - await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3"`); - await queryRunner.query(`DROP INDEX "public"."IDX_b6bf60ecb9f6c398e349adff52"`); - await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "creatorId"`); - await queryRunner.query(`ALTER TABLE "comment" ADD "employeeId" uuid`); - await queryRunner.query(`ALTER TABLE "comment" ADD "createdById" uuid`); - await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId") `); - await queryRunner.query(`CREATE INDEX "IDX_63ac916757350d28f05c5a6a4b" ON "comment" ("createdById") `); - await queryRunner.query( - `ALTER TABLE "comment" ADD CONSTRAINT "FK_7a88834dadfa6fe261268bfceef" FOREIGN KEY ("employeeId") REFERENCES "employee"("id") ON DELETE CASCADE ON UPDATE CASCADE` - ); - await queryRunner.query( - `ALTER TABLE "comment" ADD CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "employee"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - await queryRunner.query( - `ALTER TABLE "comment" ADD CONSTRAINT "FK_63ac916757350d28f05c5a6a4ba" FOREIGN KEY ("createdById") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - } - - /** - * PostgresDB Down Migration - * - * @param queryRunner - */ - public async postgresDownQueryRunner(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_63ac916757350d28f05c5a6a4ba"`); - await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3"`); - await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_7a88834dadfa6fe261268bfceef"`); - await queryRunner.query(`DROP INDEX "public"."IDX_63ac916757350d28f05c5a6a4b"`); - await queryRunner.query(`DROP INDEX "public"."IDX_7a88834dadfa6fe261268bfcee"`); - await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "createdById"`); - await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "employeeId"`); - await queryRunner.query(`ALTER TABLE "comment" ADD "creatorId" uuid`); - await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); - await queryRunner.query( - `ALTER TABLE "comment" ADD CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - await queryRunner.query( - `ALTER TABLE "comment" ADD CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f" FOREIGN KEY ("creatorId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - } - - /** - * SqliteDB and BetterSQlite3DB Up Migration - * - * @param queryRunner - */ - public async sqliteUpQueryRunner(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); - await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); - await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); - await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); - await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); - await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); - await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); - await queryRunner.query(`DROP INDEX "IDX_b6bf60ecb9f6c398e349adff52"`); - await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); - await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); - await queryRunner.query( - `CREATE TABLE "temporary_comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "creatorId" varchar, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` - ); - await queryRunner.query( - `INSERT INTO "temporary_comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "creatorId", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "creatorId", "resolvedById", "parentId" FROM "comment"` - ); - await queryRunner.query(`DROP TABLE "comment"`); - await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); - await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); - await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); - await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); - await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); - await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); - await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); - await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); - await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); - await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); - await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); - await queryRunner.query(`DROP INDEX "IDX_b6bf60ecb9f6c398e349adff52"`); - await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); - await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); - await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); - await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); - await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); - await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); - await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); - await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); - await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); - await queryRunner.query( - `CREATE TABLE "temporary_comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` - ); - await queryRunner.query( - `INSERT INTO "temporary_comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId" FROM "comment"` - ); - await queryRunner.query(`DROP TABLE "comment"`); - await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); - await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); - await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); - await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); - await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); - await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); - await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); - await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); - await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); - await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); - await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); - await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); - await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); - await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); - await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); - await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); - await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); - await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); - await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); - await queryRunner.query( - `CREATE TABLE "temporary_comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, "employeeId" varchar, "createdById" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` - ); - await queryRunner.query( - `INSERT INTO "temporary_comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId" FROM "comment"` - ); - await queryRunner.query(`DROP TABLE "comment"`); - await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); - await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); - await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); - await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); - await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); - await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); - await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); - await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); - await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); - await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); - await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId") `); - await queryRunner.query(`CREATE INDEX "IDX_63ac916757350d28f05c5a6a4b" ON "comment" ("createdById") `); - await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); - await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); - await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); - await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); - await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); - await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); - await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); - await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); - await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); - await queryRunner.query(`DROP INDEX "IDX_7a88834dadfa6fe261268bfcee"`); - await queryRunner.query(`DROP INDEX "IDX_63ac916757350d28f05c5a6a4b"`); - await queryRunner.query( - `CREATE TABLE "temporary_comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, "employeeId" varchar, "createdById" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_7a88834dadfa6fe261268bfceef" FOREIGN KEY ("employeeId") REFERENCES "employee" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "employee" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_63ac916757350d28f05c5a6a4ba" FOREIGN KEY ("createdById") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)` - ); - await queryRunner.query( - `INSERT INTO "temporary_comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId", "employeeId", "createdById") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId", "employeeId", "createdById" FROM "comment"` - ); - await queryRunner.query(`DROP TABLE "comment"`); - await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); - await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); - await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); - await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); - await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); - await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); - await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); - await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); - await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); - await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); - await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId") `); - await queryRunner.query(`CREATE INDEX "IDX_63ac916757350d28f05c5a6a4b" ON "comment" ("createdById") `); - } - - /** - * SqliteDB and BetterSQlite3DB Down Migration - * - * @param queryRunner - */ - public async sqliteDownQueryRunner(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP INDEX "IDX_63ac916757350d28f05c5a6a4b"`); - await queryRunner.query(`DROP INDEX "IDX_7a88834dadfa6fe261268bfcee"`); - await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); - await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); - await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); - await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); - await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); - await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); - await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); - await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); - await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); - await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); - await queryRunner.query( - `CREATE TABLE "comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, "employeeId" varchar, "createdById" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` - ); - await queryRunner.query( - `INSERT INTO "comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId", "employeeId", "createdById") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId", "employeeId", "createdById" FROM "temporary_comment"` - ); - await queryRunner.query(`DROP TABLE "temporary_comment"`); - await queryRunner.query(`CREATE INDEX "IDX_63ac916757350d28f05c5a6a4b" ON "comment" ("createdById") `); - await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId") `); - await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); - await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); - await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); - await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); - await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); - await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); - await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); - await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); - await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); - await queryRunner.query(`DROP INDEX "IDX_63ac916757350d28f05c5a6a4b"`); - await queryRunner.query(`DROP INDEX "IDX_7a88834dadfa6fe261268bfcee"`); - await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); - await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); - await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); - await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); - await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); - await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); - await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); - await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); - await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); - await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); - await queryRunner.query( - `CREATE TABLE "comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` - ); - await queryRunner.query( - `INSERT INTO "comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId" FROM "temporary_comment"` - ); - await queryRunner.query(`DROP TABLE "temporary_comment"`); - await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); - await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); - await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); - await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); - await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); - await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); - await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); - await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); - await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); - await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); - await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); - await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); - await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); - await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); - await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); - await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); - await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); - await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); - await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); - await queryRunner.query( - `CREATE TABLE "comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "creatorId" varchar, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` - ); - await queryRunner.query( - `INSERT INTO "comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "resolvedById", "parentId" FROM "temporary_comment"` - ); - await queryRunner.query(`DROP TABLE "temporary_comment"`); - await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); - await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); - await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); - await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); - await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); - await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); - await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); - await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); - await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); - await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); - await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); - await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); - await queryRunner.query(`DROP INDEX "IDX_b6bf60ecb9f6c398e349adff52"`); - await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); - await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); - await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); - await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); - await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); - await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); - await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); - await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); - await queryRunner.query( - `CREATE TABLE "comment" ("deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "isActive" boolean DEFAULT (1), "isArchived" boolean DEFAULT (0), "archivedAt" datetime, "tenantId" varchar, "organizationId" varchar, "entity" varchar NOT NULL, "entityId" varchar NOT NULL, "comment" text NOT NULL, "actorType" integer, "resolved" boolean, "resolvedAt" datetime, "editedAt" datetime, "creatorId" varchar, "resolvedById" varchar, "parentId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f" FOREIGN KEY ("creatorId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)` - ); - await queryRunner.query( - `INSERT INTO "comment"("deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "creatorId", "resolvedById", "parentId") SELECT "deletedAt", "id", "createdAt", "updatedAt", "isActive", "isArchived", "archivedAt", "tenantId", "organizationId", "entity", "entityId", "comment", "actorType", "resolved", "resolvedAt", "editedAt", "creatorId", "resolvedById", "parentId" FROM "temporary_comment"` - ); - await queryRunner.query(`DROP TABLE "temporary_comment"`); - await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); - await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); - await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); - await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); - await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); - await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); - await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); - await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); - await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); - await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); - } - - /** - * MySQL Up Migration - * - * @param queryRunner - */ - public async mysqlUpQueryRunner(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_b6bf60ecb9f6c398e349adff52f\``); - await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_c9409c81aa283c1aae70fd5f4c3\``); - await queryRunner.query(`DROP INDEX \`IDX_b6bf60ecb9f6c398e349adff52\` ON \`comment\``); - await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`creatorId\``); - await queryRunner.query(`ALTER TABLE \`comment\` ADD \`employeeId\` varchar(255) NULL`); - await queryRunner.query(`ALTER TABLE \`comment\` ADD \`createdById\` varchar(255) NULL`); - await queryRunner.query(`CREATE INDEX \`IDX_7a88834dadfa6fe261268bfcee\` ON \`comment\` (\`employeeId\`)`); - await queryRunner.query(`CREATE INDEX \`IDX_63ac916757350d28f05c5a6a4b\` ON \`comment\` (\`createdById\`)`); - await queryRunner.query( - `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_7a88834dadfa6fe261268bfceef\` FOREIGN KEY (\`employeeId\`) REFERENCES \`employee\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE` - ); - await queryRunner.query( - `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_c9409c81aa283c1aae70fd5f4c3\` FOREIGN KEY (\`resolvedById\`) REFERENCES \`employee\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` - ); - await queryRunner.query( - `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_63ac916757350d28f05c5a6a4ba\` FOREIGN KEY (\`createdById\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` - ); - } - - /** - * MySQL Down Migration - * - * @param queryRunner - */ - public async mysqlDownQueryRunner(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_63ac916757350d28f05c5a6a4ba\``); - await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_c9409c81aa283c1aae70fd5f4c3\``); - await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_7a88834dadfa6fe261268bfceef\``); - await queryRunner.query(`DROP INDEX \`IDX_63ac916757350d28f05c5a6a4b\` ON \`comment\``); - await queryRunner.query(`DROP INDEX \`IDX_7a88834dadfa6fe261268bfcee\` ON \`comment\``); - await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`createdById\``); - await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`employeeId\``); - await queryRunner.query(`ALTER TABLE \`comment\` ADD \`creatorId\` varchar(255) NULL`); - await queryRunner.query(`CREATE INDEX \`IDX_b6bf60ecb9f6c398e349adff52\` ON \`comment\` (\`creatorId\`)`); - await queryRunner.query( - `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_c9409c81aa283c1aae70fd5f4c3\` FOREIGN KEY (\`resolvedById\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` - ); - await queryRunner.query( - `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_b6bf60ecb9f6c398e349adff52f\` FOREIGN KEY (\`creatorId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` - ); - } -} From c4c5293302956d0b806c372adc2c45ea8ede2d60 Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 12 Feb 2025 15:24:29 +0530 Subject: [PATCH 05/16] fix(cspell): typo spelling :-) --- .../lib/employee-notification/employee-notification.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/lib/employee-notification/employee-notification.service.ts b/packages/core/src/lib/employee-notification/employee-notification.service.ts index 234d6abf1b2..6331c6190db 100644 --- a/packages/core/src/lib/employee-notification/employee-notification.service.ts +++ b/packages/core/src/lib/employee-notification/employee-notification.service.ts @@ -100,7 +100,7 @@ export class EmployeeNotificationService extends TenantAwareCrudService Date: Wed, 12 Feb 2025 15:26:21 +0530 Subject: [PATCH 06/16] fix(cspell): typo spelling :-) --- .../lib/tasks/screening-tasks/dto/create-screening-task.dto.ts | 2 +- .../lib/tasks/screening-tasks/dto/update-screening-task.dto.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/lib/tasks/screening-tasks/dto/create-screening-task.dto.ts b/packages/core/src/lib/tasks/screening-tasks/dto/create-screening-task.dto.ts index c043a3e4e9b..d7f726e9bb1 100644 --- a/packages/core/src/lib/tasks/screening-tasks/dto/create-screening-task.dto.ts +++ b/packages/core/src/lib/tasks/screening-tasks/dto/create-screening-task.dto.ts @@ -5,7 +5,7 @@ import { MentionEmployeeIdsDTO } from '../../../mention/dto'; import { ScreeningTask } from '../screening-task.entity'; /** - * Create Sreening Task data validation request DTO + * Create Screening Task data validation request DTO */ export class CreateScreeningTaskDTO extends IntersectionType( diff --git a/packages/core/src/lib/tasks/screening-tasks/dto/update-screening-task.dto.ts b/packages/core/src/lib/tasks/screening-tasks/dto/update-screening-task.dto.ts index 1ab9cd91392..56fdefba2b2 100644 --- a/packages/core/src/lib/tasks/screening-tasks/dto/update-screening-task.dto.ts +++ b/packages/core/src/lib/tasks/screening-tasks/dto/update-screening-task.dto.ts @@ -4,7 +4,7 @@ import { TenantOrganizationBaseDTO } from '../../../core/dto'; import { ScreeningTask } from '../screening-task.entity'; /** - * Update Sreening Task data validation request DTO + * Update Screening Task data validation request DTO */ export class UpdateScreeningTaskDTO extends IntersectionType(TenantOrganizationBaseDTO, OmitType(ScreeningTask, ['task', 'taskId'])) From a8cac9c21c283ad21d544bda12852f5e2df1d90b Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 12 Feb 2025 15:32:43 +0530 Subject: [PATCH 07/16] fix: missing join column decorator --- .../core/src/lib/comment/comment.entity.ts | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/core/src/lib/comment/comment.entity.ts b/packages/core/src/lib/comment/comment.entity.ts index 4c90607aa12..a400ca5d4ae 100644 --- a/packages/core/src/lib/comment/comment.entity.ts +++ b/packages/core/src/lib/comment/comment.entity.ts @@ -69,6 +69,7 @@ export class Comment extends BasePerEntityType implements IComment { /** Database cascade action on delete. */ onDelete: 'CASCADE' }) + @JoinColumn() employee?: IEmployee; /** @@ -116,6 +117,7 @@ export class Comment extends BasePerEntityType implements IComment { /** Database cascade action on delete. */ onDelete: 'SET NULL' }) + @JoinColumn() parent?: IComment; /** @@ -145,29 +147,29 @@ export class Comment extends BasePerEntityType implements IComment { |-------------------------------------------------------------------------- */ /** - * + * Comment members */ @MultiORMManyToMany(() => Employee, (employee) => employee.assignedComments, { - onUpdate: 'CASCADE', - onDelete: 'CASCADE', - owner: true, - pivotTable: 'comment_employee', - joinColumn: 'commentId', - inverseJoinColumn: 'employeeId' + onUpdate: 'CASCADE', // Cascade action on update + onDelete: 'CASCADE', // Cascade action on delete + owner: true, // Ownership + pivotTable: 'comment_employee', // Table name for pivot table + joinColumn: 'commentId', // Column name for join table + inverseJoinColumn: 'employeeId' // Column name for inverse join table }) @JoinTable({ name: 'comment_employee' }) members?: IEmployee[]; /** - * + * Comment teams */ @MultiORMManyToMany(() => OrganizationTeam, (team) => team.assignedComments, { - onUpdate: 'CASCADE', - onDelete: 'CASCADE', - owner: true, - pivotTable: 'comment_team', - joinColumn: 'commentId', - inverseJoinColumn: 'organizationTeamId' + onUpdate: 'CASCADE', // Cascade action on update + onDelete: 'CASCADE', // Cascade action on delete + owner: true, // Ownership + pivotTable: 'comment_team', // Table name for pivot table + joinColumn: 'commentId', // Column name for join table + inverseJoinColumn: 'organizationTeamId' // Column name for inverse join table }) @JoinTable({ name: 'comment_team' }) teams?: IOrganizationTeam[]; From 9a982f3b0c67fe4ced38c45aa08736a09cb850d8 Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 12 Feb 2025 16:11:48 +0530 Subject: [PATCH 08/16] fix: updated comment entity command/handler --- packages/contracts/src/lib/comment.model.ts | 2 +- .../handlers/comment.create.handler.ts | 23 ++++- .../handlers/comment.update.handler.ts | 28 +++++- .../core/src/lib/comment/comment.module.ts | 4 +- .../core/src/lib/comment/comment.service.ts | 98 +++++++++++-------- .../src/lib/comment/dto/create-comment.dto.ts | 5 +- .../handlers/subscription.create.handler.ts | 31 +++++- .../events/subscription.create.event.ts | 2 +- 8 files changed, 129 insertions(+), 64 deletions(-) diff --git a/packages/contracts/src/lib/comment.model.ts b/packages/contracts/src/lib/comment.model.ts index d44498ce784..01b3b7c8c81 100644 --- a/packages/contracts/src/lib/comment.model.ts +++ b/packages/contracts/src/lib/comment.model.ts @@ -18,7 +18,7 @@ export interface IComment extends IBasePerEntityType, ICommentAuthor { resolvedById?: ID; // Indicates the employee ID who resolved the comment } -export interface ICommentCreateInput extends IBasePerEntityType, IMentionEmployeeIds { +export interface ICommentCreateInput extends IBasePerEntityType, ICommentAuthor, IMentionEmployeeIds { comment: string; entityName?: string; parent?: IComment; diff --git a/packages/core/src/lib/comment/commands/handlers/comment.create.handler.ts b/packages/core/src/lib/comment/commands/handlers/comment.create.handler.ts index e75a595c7d3..1bfae624e92 100644 --- a/packages/core/src/lib/comment/commands/handlers/comment.create.handler.ts +++ b/packages/core/src/lib/comment/commands/handlers/comment.create.handler.ts @@ -1,3 +1,4 @@ +import { BadRequestException } from '@nestjs/common'; import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { IComment } from '@gauzy/contracts'; import { CommentService } from '../../comment.service'; @@ -5,10 +6,26 @@ import { CommentCreateCommand } from '../comment.create.command'; @CommandHandler(CommentCreateCommand) export class CommentCreateHandler implements ICommandHandler { - constructor(private readonly commentService: CommentService) {} + constructor(readonly commentService: CommentService) {} + /** + * Executes the CommentCreateCommand to create a new comment. + * + * This function extracts the input data from the provided command and invokes the comment service + * to create a comment. If an error occurs during the process, it logs the error and throws a + * BadRequestException. + * + * @param {CommentCreateCommand} command - The command containing the input data for creating the comment. + * @returns {Promise} A promise that resolves to the newly created comment. + * @throws {BadRequestException} If the comment creation fails. + */ public async execute(command: CommentCreateCommand): Promise { - const { input } = command; - return await this.commentService.create(input); + try { + const { input } = command; + return await this.commentService.create(input); + } catch (error) { + console.log(`Error while creating comment: ${error.message}`, error); + throw new BadRequestException('Comment post failed', error); + } } } diff --git a/packages/core/src/lib/comment/commands/handlers/comment.update.handler.ts b/packages/core/src/lib/comment/commands/handlers/comment.update.handler.ts index 464bd7f617f..6dc1eb47923 100644 --- a/packages/core/src/lib/comment/commands/handlers/comment.update.handler.ts +++ b/packages/core/src/lib/comment/commands/handlers/comment.update.handler.ts @@ -1,15 +1,33 @@ +import { BadRequestException } from '@nestjs/common'; import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { UpdateResult } from 'typeorm'; +import { IComment } from '@gauzy/contracts'; import { CommentService } from '../../comment.service'; import { CommentUpdateCommand } from '../comment.update.command'; -import { IComment } from '@gauzy/contracts'; @CommandHandler(CommentUpdateCommand) export class CommentUpdateHandler implements ICommandHandler { - constructor(private readonly commentService: CommentService) {} - + constructor(readonly commentService: CommentService) {} + /** + * Executes the CommentUpdateCommand to update an existing comment. + * + * This function extracts the comment ID and the update input from the command, and then invokes the + * comment service's update method to perform the update. It returns a promise that resolves to either + * the updated comment or an update result. + * + * If an error occurs during the update, the error is logged and a BadRequestException is thrown. + * + * @param {CommentUpdateCommand} command - The command containing the comment ID and update data. + * @returns {Promise} A promise that resolves to the updated comment or update result. + * @throws {BadRequestException} If the update process fails. + */ public async execute(command: CommentUpdateCommand): Promise { - const { id, input } = command; - return await this.commentService.update(id, input); + try { + const { id, input } = command; + return await this.commentService.update(id, input); + } catch (error) { + console.log(`Error while updating comment: ${error.message}`, error); + throw new BadRequestException('Comment update failed', error); + } } } diff --git a/packages/core/src/lib/comment/comment.module.ts b/packages/core/src/lib/comment/comment.module.ts index a7253672c0f..b46865b288a 100644 --- a/packages/core/src/lib/comment/comment.module.ts +++ b/packages/core/src/lib/comment/comment.module.ts @@ -4,7 +4,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { MikroOrmModule } from '@mikro-orm/nestjs'; import { MentionModule } from '../mention/mention.module'; import { RolePermissionModule } from '../role-permission/role-permission.module'; -import { UserModule } from '../user/user.module'; +import { EmployeeModule } from '../employee/employee.module'; import { CommandHandlers } from './commands/handlers'; import { CommentService } from './comment.service'; import { CommentController } from './comment.controller'; @@ -16,7 +16,7 @@ import { TypeOrmCommentRepository } from './repository/type-orm.comment.reposito TypeOrmModule.forFeature([Comment]), MikroOrmModule.forFeature([Comment]), RolePermissionModule, - UserModule, + EmployeeModule, MentionModule, CqrsModule ], diff --git a/packages/core/src/lib/comment/comment.service.ts b/packages/core/src/lib/comment/comment.service.ts index aebf1fcd41a..712d064c2d2 100644 --- a/packages/core/src/lib/comment/comment.service.ts +++ b/packages/core/src/lib/comment/comment.service.ts @@ -1,8 +1,6 @@ import { EventBus } from '@nestjs/cqrs'; import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; import { UpdateResult } from 'typeorm'; -import { TenantAwareCrudService } from './../core/crud'; -import { RequestContext } from '../core/context'; import { BaseEntityEnum, IComment, @@ -11,8 +9,10 @@ import { ID, SubscriptionTypeEnum } from '@gauzy/contracts'; +import { TenantAwareCrudService } from './../core/crud'; +import { RequestContext } from '../core/context'; import { CreateSubscriptionEvent } from '../subscription/events'; -import { UserService } from '../user/user.service'; +import { EmployeeService } from '../employee/employee.service'; import { MentionService } from '../mention/mention.service'; import { Comment } from './comment.entity'; import { TypeOrmCommentRepository } from './repository/type-orm.comment.repository'; @@ -24,107 +24,119 @@ export class CommentService extends TenantAwareCrudService { readonly typeOrmCommentRepository: TypeOrmCommentRepository, readonly mikroOrmCommentRepository: MikroOrmCommentRepository, private readonly _eventBus: EventBus, - private readonly userService: UserService, - private readonly mentionService: MentionService + private readonly _employeeService: EmployeeService, + private readonly _mentionService: MentionService ) { super(typeOrmCommentRepository, mikroOrmCommentRepository); } /** - * @description Create / Post comment - Note - * @param {ICommentCreateInput} input - Data to creating comment - * @returns A promise that resolves to the created comment - * @memberof CommentService + * Creates a new comment and handles related actions such as publishing mentions + * and subscribing the creator to the comment's entity. + * + * This function retrieves the current user, employee, and tenant IDs from the RequestContext. + * It validates that the user exists, creates a comment record, publishes any provided mentions, + * and then publishes a subscription event for the creator. If any step fails, a BadRequestException + * is thrown. + * + * @param {ICommentCreateInput} input - The data required to create a comment. + * @returns {Promise} A promise that resolves to the newly created comment. + * @throws {NotFoundException} If the current user is not found. + * @throws {BadRequestException} If the comment creation or related processes fail. */ async create(input: ICommentCreateInput): Promise { try { - const userId = RequestContext.currentUserId(); - const employeeId = RequestContext.currentEmployeeId(); - const tenantId = RequestContext.currentTenantId(); + // Retrieve context-specific IDs. + const tenantId = RequestContext.currentTenantId() ?? input.tenantId; + const employeeId = RequestContext.currentEmployeeId() ?? input.employeeId; const { mentionEmployeeIds = [], organizationId, ...data } = input; - // Employee existence validation - const user = await this.userService.findOneByIdString(userId); - if (!user) { - throw new NotFoundException('User not found'); + // Validate that the user exists. + const employee = await this._employeeService.findOneByIdString(employeeId); + if (!employee) { + throw new NotFoundException(`Employee with id ${employeeId} not found`); } - // create comment + // Create the comment. const comment = await super.create({ ...data, employeeId, - createdById: user.id, tenantId, organizationId }); - // Apply mentions if needed + // Publish mentions for each mentioned employee, if any. await Promise.all( mentionEmployeeIds.map((mentionedUserId) => - this.mentionService.publishMention({ + this._mentionService.publishMention({ entity: BaseEntityEnum.Comment, entityId: comment.id, + entityName: input.entityName, mentionedUserId, - mentionById: user.id, + mentionById: employee.id, parentEntityId: comment.entityId, parentEntityType: comment.entity, organizationId: comment.organizationId, - tenantId, - entityName: input.entityName + tenantId: comment.tenantId }) ) ); - // Subscribe creator to the entity + // Subscribe the comment creator to the entity. this._eventBus.publish( new CreateSubscriptionEvent({ entity: input.entity, entityId: input.entityId, - userId: user.id, type: SubscriptionTypeEnum.COMMENT, organizationId: comment.organizationId, - tenantId + tenantId: comment.tenantId }) ); - // Return created Comment + // Return the newly created comment. return comment; } catch (error) { - console.log(error); // Debug Logging + console.log(`Error while creating comment: ${error.message}`, error); throw new BadRequestException('Comment post failed', error); } } /** - * @description Update comment - Note - * @param id - The comment ID to be updated. - * @param {ICommentUpdateInput} input - Data to update comment. - * @returns A promise that resolves to the updated comment OR Update result. - * @memberof CommentService + * Updates an existing comment based on the provided id and update input. + * + * This function first retrieves the current employee's ID from the request context, + * then attempts to locate the comment matching the provided id and employeeId. + * If the comment is found, it creates an updated version of the comment using the input data. + * Additionally, it synchronizes any mention updates via the _mentionService. + * + * @param {ID} id - The unique identifier of the comment to update. + * @param {ICommentUpdateInput} input - The update data for the comment, including any mention updates. + * @returns {Promise} A promise that resolves to the updated comment or an update result. + * @throws {BadRequestException} If the comment is not found or if the update operation fails. */ async update(id: ID, input: ICommentUpdateInput): Promise { try { + const employeeId = RequestContext.currentEmployeeId(); const { mentionEmployeeIds = [] } = input; - const userId = RequestContext.currentUserId(); - const comment = await this.findOneByOptions({ - where: { - id, - createdById: userId - } + // Find the comment for the current employee with the given id. + const comment = await this.findOneByWhereOptions({ + id, + employeeId }); if (!comment) { - throw new BadRequestException('Comment not found'); + throw new BadRequestException(`Comment with id ${id} not found`); } + // Update the comment with the new input data. const updatedComment = await super.create({ ...input, id }); - // Synchronize mentions - await this.mentionService.updateEntityMentions( + // Synchronize any mention updates for the comment. + await this._mentionService.updateEntityMentions( BaseEntityEnum.Comment, id, mentionEmployeeIds, @@ -134,7 +146,7 @@ export class CommentService extends TenantAwareCrudService { return updatedComment; } catch (error) { - console.log(error); // Debug Logging + console.log(`Error while updating comment: ${error.message}`, error); throw new BadRequestException('Comment update failed', error); } } diff --git a/packages/core/src/lib/comment/dto/create-comment.dto.ts b/packages/core/src/lib/comment/dto/create-comment.dto.ts index fc21bb2b240..8e898c37852 100644 --- a/packages/core/src/lib/comment/dto/create-comment.dto.ts +++ b/packages/core/src/lib/comment/dto/create-comment.dto.ts @@ -9,10 +9,7 @@ import { Comment } from '../comment.entity'; * Create Comment data validation request DTO */ export class CreateCommentDTO - extends IntersectionType( - TenantOrganizationBaseDTO, - IntersectionType(OmitType(Comment, ['createdById', 'createdBy']), MentionEmployeeIdsDTO) - ) + extends IntersectionType(TenantOrganizationBaseDTO, Comment, MentionEmployeeIdsDTO) implements ICommentCreateInput { @ApiPropertyOptional({ type: () => String }) diff --git a/packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts b/packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts index f4ee82c2645..582005130d3 100644 --- a/packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts +++ b/packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts @@ -8,14 +8,35 @@ export class CreateSubscriptionHandler implements IEventHandler} A promise that resolves to the created subscription. + * Extracts subscription details from the event input and uses the command bus to execute a SubscriptionCreateCommand, + * which creates a new subscription for the specified entity. * + * @param {CreateSubscriptionEvent} event - The event containing the input data for subscription creation. + * @returns {Promise} A promise that resolves to the created subscription. + * @throws An error if the subscription creation process fails. */ async handle(event: CreateSubscriptionEvent): Promise { - const { input } = event; - return await this.commandBus.execute(new SubscriptionCreateCommand(input)); + try { + // Retrieve the input data from the event. + const { entity, entityId, userId, type, organizationId, tenantId } = event.input; + + // Execute the subscription creation command. + const subscription = await this.commandBus.execute( + new SubscriptionCreateCommand({ + entity, + entityId, + userId, + type, + organizationId, + tenantId + }) + ); + + return subscription; + } catch (error) { + console.log(`Error while creating subscription: ${error.message}`, error); + } } } diff --git a/packages/core/src/lib/subscription/events/subscription.create.event.ts b/packages/core/src/lib/subscription/events/subscription.create.event.ts index 5b898a178ac..f3f565532a1 100644 --- a/packages/core/src/lib/subscription/events/subscription.create.event.ts +++ b/packages/core/src/lib/subscription/events/subscription.create.event.ts @@ -2,5 +2,5 @@ import { IEvent } from '@nestjs/cqrs'; import { IEntitySubscriptionCreateInput } from '@gauzy/contracts'; export class CreateSubscriptionEvent implements IEvent { - constructor(public readonly input: IEntitySubscriptionCreateInput) {} + constructor(readonly input: IEntitySubscriptionCreateInput) {} } From 2229c0af522678f54de119c6b6d17f1ea171c677 Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Wed, 12 Feb 2025 18:06:51 +0530 Subject: [PATCH 09/16] fix: comment entity resolve comment as employee ID --- packages/contracts/src/lib/comment.model.ts | 4 ++-- .../core/src/lib/comment/comment.entity.ts | 6 +++--- .../core/src/lib/comment/comment.service.ts | 20 +++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/contracts/src/lib/comment.model.ts b/packages/contracts/src/lib/comment.model.ts index 01b3b7c8c81..1c9a42867f7 100644 --- a/packages/contracts/src/lib/comment.model.ts +++ b/packages/contracts/src/lib/comment.model.ts @@ -14,8 +14,8 @@ export interface IComment extends IBasePerEntityType, ICommentAuthor { parent?: IComment; parentId?: ID; // Specify the parent comment if current one is a reply replies?: IComment[]; - resolvedBy?: IEmployee; // Indicates the employee who resolved the comment - resolvedById?: ID; // Indicates the employee ID who resolved the comment + resolvedByEmployee?: IEmployee; // Indicates the employee who resolved the comment + resolvedByEmployeeId?: ID; // Indicates the employee ID who resolved the comment } export interface ICommentCreateInput extends IBasePerEntityType, ICommentAuthor, IMentionEmployeeIds { diff --git a/packages/core/src/lib/comment/comment.entity.ts b/packages/core/src/lib/comment/comment.entity.ts index a400ca5d4ae..ad7e2b795a1 100644 --- a/packages/core/src/lib/comment/comment.entity.ts +++ b/packages/core/src/lib/comment/comment.entity.ts @@ -94,7 +94,7 @@ export class Comment extends BasePerEntityType implements IComment { onDelete: 'CASCADE' }) @JoinColumn() - resolvedBy?: IEmployee; + resolvedByEmployee?: IEmployee; /** * Resolved by ID @@ -102,10 +102,10 @@ export class Comment extends BasePerEntityType implements IComment { @ApiPropertyOptional({ type: () => String }) @IsOptional() @IsUUID() - @RelationId((it: Comment) => it.resolvedBy) + @RelationId((it: Comment) => it.resolvedByEmployee) @ColumnIndex() @MultiORMColumn({ nullable: true, relationId: true }) - resolvedById?: ID; + resolvedByEmployeeId?: ID; /** * Comment parent-child relationship diff --git a/packages/core/src/lib/comment/comment.service.ts b/packages/core/src/lib/comment/comment.service.ts index 712d064c2d2..2430c65ffab 100644 --- a/packages/core/src/lib/comment/comment.service.ts +++ b/packages/core/src/lib/comment/comment.service.ts @@ -31,18 +31,18 @@ export class CommentService extends TenantAwareCrudService { } /** - * Creates a new comment and handles related actions such as publishing mentions - * and subscribing the creator to the comment's entity. + * Creates a new comment with the provided input, handling employee validation, + * publishing mention notifications, and subscribing the comment creator to the related entity. * - * This function retrieves the current user, employee, and tenant IDs from the RequestContext. - * It validates that the user exists, creates a comment record, publishes any provided mentions, - * and then publishes a subscription event for the creator. If any step fails, a BadRequestException - * is thrown. + * This function retrieves context-specific IDs from the RequestContext (tenant, employee) + * and falls back to the values in the input if necessary. It verifies that the employee exists, + * creates the comment, publishes mention notifications for each mentioned employee, and + * triggers a subscription event for the creator. * - * @param {ICommentCreateInput} input - The data required to create a comment. + * @param {ICommentCreateInput} input - The input data required to create a comment, including text, mentions, and organization details. * @returns {Promise} A promise that resolves to the newly created comment. - * @throws {NotFoundException} If the current user is not found. - * @throws {BadRequestException} If the comment creation or related processes fail. + * @throws {NotFoundException} If the employee associated with the comment is not found. + * @throws {BadRequestException} If any error occurs during the creation of the comment. */ async create(input: ICommentCreateInput): Promise { try { @@ -51,7 +51,7 @@ export class CommentService extends TenantAwareCrudService { const employeeId = RequestContext.currentEmployeeId() ?? input.employeeId; const { mentionEmployeeIds = [], organizationId, ...data } = input; - // Validate that the user exists. + // Validate that the employee exists. const employee = await this._employeeService.findOneByIdString(employeeId); if (!employee) { throw new NotFoundException(`Employee with id ${employeeId} not found`); From b5018063c44bfe0c804631e1d6388dfad1707abd Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Thu, 13 Feb 2025 11:23:13 +0530 Subject: [PATCH 10/16] feat(migration): alter comment entity [table] for PostgreSQL --- .../1739364133493-AlterCommentEntityTable.ts | 211 ++++++++++++++++++ .../handlers/subscription.create.handler.ts | 3 + 2 files changed, 214 insertions(+) create mode 100644 packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts diff --git a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts new file mode 100644 index 00000000000..19f0d3d7082 --- /dev/null +++ b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts @@ -0,0 +1,211 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; +import * as chalk from 'chalk'; +import { DatabaseTypeEnum } from '@gauzy/config'; + +export class AlterCommentEntityTable1739364133493 implements MigrationInterface { + name = 'AlterCommentEntityTable1739364133493'; + + /** + * Up Migration + * + * @param queryRunner + */ + public async up(queryRunner: QueryRunner): Promise { + console.log(chalk.yellow(this.name + ' start running!')); + + switch (queryRunner.connection.options.type) { + case DatabaseTypeEnum.sqlite: + case DatabaseTypeEnum.betterSqlite3: + await this.sqliteUpQueryRunner(queryRunner); + break; + case DatabaseTypeEnum.postgres: + await this.postgresUpQueryRunner(queryRunner); + break; + case DatabaseTypeEnum.mysql: + await this.mysqlUpQueryRunner(queryRunner); + break; + default: + throw Error(`Unsupported database: ${queryRunner.connection.options.type}`); + } + } + + /** + * Down Migration + * + * @param queryRunner + */ + public async down(queryRunner: QueryRunner): Promise { + switch (queryRunner.connection.options.type) { + case DatabaseTypeEnum.sqlite: + case DatabaseTypeEnum.betterSqlite3: + await this.sqliteDownQueryRunner(queryRunner); + break; + case DatabaseTypeEnum.postgres: + await this.postgresDownQueryRunner(queryRunner); + break; + case DatabaseTypeEnum.mysql: + await this.mysqlDownQueryRunner(queryRunner); + break; + default: + throw Error(`Unsupported database: ${queryRunner.connection.options.type}`); + } + } + + /** + * PostgresDB Up Migration + * + * @param queryRunner + */ + public async postgresUpQueryRunner(queryRunner: QueryRunner): Promise { + // Step 1: Drop existing foreign keys on "creatorId" and "resolvedById" + console.log('Step 1: Dropping existing foreign keys...'); + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f"`); + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3"`); + + // Step 2: Drop existing indexes on "creatorId" and "resolvedById" + console.log('Step 2: Dropping existing indexes on "creatorId" and "resolvedById"...'); + await queryRunner.query(`DROP INDEX "public"."IDX_b6bf60ecb9f6c398e349adff52"`); + await queryRunner.query(`DROP INDEX "public"."IDX_c9409c81aa283c1aae70fd5f4c"`); + + // Step 3: Add new columns "employeeId" and "resolvedByEmployeeId" + console.log('Step 3: Adding new columns "employeeId" and "resolvedByEmployeeId"...'); + await queryRunner.query(`ALTER TABLE "comment" ADD "employeeId" uuid`); + await queryRunner.query(`ALTER TABLE "comment" ADD "resolvedByEmployeeId" uuid`); + + // Step 4: Copy data from "creatorId" to "employeeId" using the employee mapping + console.log('Step 4: Copying data from "creatorId" to "employeeId" via employee table mapping...'); + await queryRunner.query(` + UPDATE "comment" + SET "employeeId" = e.id + FROM "employee" e + WHERE "comment"."creatorId" = e."userId" + `); + + // Step 5: Copy data from "resolvedById" to "resolvedByEmployeeId" using the employee mapping + console.log('Step 5: Copying data from "resolvedById" to "resolvedByEmployeeId" via employee table mapping...'); + await queryRunner.query(` + UPDATE "comment" + SET "resolvedByEmployeeId" = e.id + FROM "employee" e + WHERE "comment"."resolvedById" = e."userId" + `); + + // Step 6: Drop the old columns "creatorId" and "resolvedById" + console.log('Step 6: Dropping old columns "creatorId" and "resolvedById"...'); + await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "creatorId"`); + await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "resolvedById"`); + + // Step 7: Create indexes on the new columns "employeeId" and "resolvedByEmployeeId" + console.log('Step 7: Creating indexes on "employeeId" and "resolvedByEmployeeId"...'); + await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId")`); + await queryRunner.query(`CREATE INDEX "IDX_35cddb3e66a46587966b68a921" ON "comment" ("resolvedByEmployeeId")`); + + // Step 8: Add foreign key constraint for "employeeId" + console.log('Step 8: Adding foreign key constraint for "employeeId"...'); + await queryRunner.query(` + ALTER TABLE "comment" + ADD CONSTRAINT "FK_7a88834dadfa6fe261268bfceef" + FOREIGN KEY ("employeeId") REFERENCES "employee"("id") ON DELETE CASCADE ON UPDATE NO ACTION + `); + + // Step 9: Add foreign key constraint for "resolvedByEmployeeId" + console.log('Step 9: Adding foreign key constraint for "resolvedByEmployeeId"...'); + await queryRunner.query(` + ALTER TABLE "comment" + ADD CONSTRAINT "FK_35cddb3e66a46587966b68a9217" + FOREIGN KEY ("resolvedByEmployeeId") REFERENCES "employee"("id") ON DELETE CASCADE ON UPDATE NO ACTION + `); + } + + /** + * PostgresDB Down Migration + * + * @param queryRunner + */ + public async postgresDownQueryRunner(queryRunner: QueryRunner): Promise { + // Step 1: Drop foreign key constraints for "resolvedByEmployeeId" and "employeeId" + console.log('Step 1: Dropping foreign key constraints for "resolvedByEmployeeId" and "employeeId"...'); + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_35cddb3e66a46587966b68a9217"`); + await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_7a88834dadfa6fe261268bfceef"`); + + // Step 2: Drop indexes on "resolvedByEmployeeId" and "employeeId" + console.log('Step 2: Dropping indexes on "resolvedByEmployeeId" and "employeeId"...'); + await queryRunner.query(`DROP INDEX "public"."IDX_35cddb3e66a46587966b68a921"`); + await queryRunner.query(`DROP INDEX "public"."IDX_7a88834dadfa6fe261268bfcee"`); + + // Step 3: Re-add the old columns "resolvedById" and "creatorId" + console.log('Step 3: Adding columns "resolvedById" and "creatorId"...'); + await queryRunner.query(`ALTER TABLE "comment" ADD "resolvedById" uuid`); + await queryRunner.query(`ALTER TABLE "comment" ADD "creatorId" uuid`); + + // Step 4: Copy data from "employeeId" to "creatorId" via employee table mapping + console.log('Step 4: Copying data from "employeeId" to "creatorId" via employee table mapping...'); + await queryRunner.query(` + UPDATE "comment" + SET "creatorId" = e."userId" + FROM "employee" e + WHERE "comment"."employeeId" = e.id + `); + + // Step 5: Copy data from "resolvedByEmployeeId" to "resolvedById" via employee table mapping + console.log('Step 5: Copying data from "resolvedByEmployeeId" to "resolvedById" via employee table mapping...'); + await queryRunner.query(` + UPDATE "comment" + SET "resolvedById" = e."userId" + FROM "employee" e + WHERE "comment"."resolvedByEmployeeId" = e.id + `); + + // Step 6: Drop the new columns "resolvedByEmployeeId" and "employeeId" + console.log('Step 6: Dropping columns "resolvedByEmployeeId" and "employeeId"...'); + await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "resolvedByEmployeeId"`); + await queryRunner.query(`ALTER TABLE "comment" DROP COLUMN "employeeId"`); + + // Step 7: Create indexes on the restored columns "resolvedById" and "creatorId" + console.log('Step 7: Creating indexes on "resolvedById" and "creatorId"...'); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById")`); + await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId")`); + + // Step 8: Add foreign key constraint for "resolvedById" referencing "user" + console.log('Step 8: Adding foreign key constraint for "resolvedById" referencing "user"...'); + await queryRunner.query(` + ALTER TABLE "comment" ADD CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" + FOREIGN KEY ("resolvedById") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION + `); + + // Step 9: Add foreign key constraint for "creatorId" referencing "user" + console.log('Step 9: Adding foreign key constraint for "creatorId" referencing "user"...'); + await queryRunner.query(` + ALTER TABLE "comment" ADD CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f" + FOREIGN KEY ("creatorId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION + `); + } + + /** + * SqliteDB and BetterSQlite3DB Up Migration + * + * @param queryRunner + */ + public async sqliteUpQueryRunner(queryRunner: QueryRunner): Promise {} + + /** + * SqliteDB and BetterSQlite3DB Down Migration + * + * @param queryRunner + */ + public async sqliteDownQueryRunner(queryRunner: QueryRunner): Promise {} + + /** + * MySQL Up Migration + * + * @param queryRunner + */ + public async mysqlUpQueryRunner(queryRunner: QueryRunner): Promise {} + + /** + * MySQL Down Migration + * + * @param queryRunner + */ + public async mysqlDownQueryRunner(queryRunner: QueryRunner): Promise {} +} diff --git a/packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts b/packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts index 582005130d3..3bcc00cbc0a 100644 --- a/packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts +++ b/packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts @@ -1,3 +1,4 @@ +import { BadRequestException } from '@nestjs/common'; import { CommandBus, EventsHandler, IEventHandler } from '@nestjs/cqrs'; import { IEntitySubscription } from '@gauzy/contracts'; import { CreateSubscriptionEvent } from '../subscription.create.event'; @@ -37,6 +38,8 @@ export class CreateSubscriptionHandler implements IEventHandler Date: Thu, 13 Feb 2025 14:35:02 +0530 Subject: [PATCH 11/16] feat(migration): alter comment entity [table] for MySQL --- .../src/lib/comment/comment.controller.ts | 34 +++-- .../1739364133493-AlterCommentEntityTable.ts | 126 +++++++++++++++++- 2 files changed, 144 insertions(+), 16 deletions(-) diff --git a/packages/core/src/lib/comment/comment.controller.ts b/packages/core/src/lib/comment/comment.controller.ts index dc9c5297772..98f263cf240 100644 --- a/packages/core/src/lib/comment/comment.controller.ts +++ b/packages/core/src/lib/comment/comment.controller.ts @@ -15,9 +15,9 @@ import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { CommandBus } from '@nestjs/cqrs'; import { DeleteResult } from 'typeorm'; import { IComment, ID, IPagination } from '@gauzy/contracts'; -import { UUIDValidationPipe, UseValidationPipe } from './../shared/pipes'; +import { CrudController, OptionParams, PaginationParams } from '../core/crud'; +import { UUIDValidationPipe, UseValidationPipe } from '../shared/pipes'; import { PermissionGuard, TenantPermissionGuard } from '../shared/guards'; -import { CrudController, OptionParams, PaginationParams } from './../core/crud'; import { Comment } from './comment.entity'; import { CommentService } from './comment.service'; import { CommentCreateCommand, CommentUpdateCommand } from './commands'; @@ -31,9 +31,10 @@ export class CommentController extends CrudController { super(commentService); } - @ApiOperation({ - summary: 'Find all comments filtered by type.' - }) + /** + * Find all comments filtered by type. + */ + @ApiOperation({ summary: 'Find all comments filtered by type.' }) @ApiResponse({ status: HttpStatus.OK, description: 'Found comments', @@ -43,26 +44,33 @@ export class CommentController extends CrudController { status: HttpStatus.NOT_FOUND, description: 'Record not found' }) - @Get() + @Get('/') @UseValidationPipe() async findAll(@Query() params: PaginationParams): Promise> { return await this.commentService.findAll(params); } + /** + * Find by id + */ @ApiOperation({ summary: 'Find by id' }) @ApiResponse({ status: HttpStatus.OK, - description: 'Found one record' /*, type: T*/ + description: 'Found one record' + // You can specify a type here if needed: type: Comment, }) @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Record not found' }) - @Get(':id') + @Get('/:id') async findById(@Param('id', UUIDValidationPipe) id: ID, @Query() params: OptionParams): Promise { return this.commentService.findOneByIdString(id, params); } + /** + * Create/Post a comment + */ @ApiOperation({ summary: 'Create/Post a comment' }) @ApiResponse({ status: HttpStatus.CREATED, @@ -73,12 +81,15 @@ export class CommentController extends CrudController { description: 'Invalid input, The response body may contain clues as to what went wrong' }) @HttpCode(HttpStatus.ACCEPTED) - @Post() + @Post('/') @UseValidationPipe({ whitelist: true }) async create(@Body() entity: CreateCommentDTO): Promise { return await this.commandBus.execute(new CommentCreateCommand(entity)); } + /** + * Update an existing comment + */ @ApiOperation({ summary: 'Update an existing comment' }) @ApiResponse({ status: HttpStatus.CREATED, @@ -93,12 +104,15 @@ export class CommentController extends CrudController { description: 'Invalid input, The response body may contain clues as to what went wrong' }) @HttpCode(HttpStatus.ACCEPTED) - @Put(':id') + @Put('/:id') @UseValidationPipe({ whitelist: true }) async update(@Param('id', UUIDValidationPipe) id: ID, @Body() entity: UpdateCommentDTO): Promise { return await this.commandBus.execute(new CommentUpdateCommand(id, entity)); } + /** + * Delete comment + */ @ApiOperation({ summary: 'Delete comment' }) @ApiResponse({ status: HttpStatus.NO_CONTENT, diff --git a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts index 19f0d3d7082..80e49f97405 100644 --- a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts +++ b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts @@ -78,7 +78,7 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface UPDATE "comment" SET "employeeId" = e.id FROM "employee" e - WHERE "comment"."creatorId" = e."userId" + WHERE "comment"."creatorId" = e."userId" AND "comment"."creatorId" IS NOT NULL `); // Step 5: Copy data from "resolvedById" to "resolvedByEmployeeId" using the employee mapping @@ -87,7 +87,7 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface UPDATE "comment" SET "resolvedByEmployeeId" = e.id FROM "employee" e - WHERE "comment"."resolvedById" = e."userId" + WHERE "comment"."resolvedById" = e."userId" AND "comment"."resolvedById" IS NOT NULL `); // Step 6: Drop the old columns "creatorId" and "resolvedById" @@ -144,7 +144,7 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface UPDATE "comment" SET "creatorId" = e."userId" FROM "employee" e - WHERE "comment"."employeeId" = e.id + WHERE "comment"."employeeId" = e.id AND "comment"."employeeId" IS NOT NULL `); // Step 5: Copy data from "resolvedByEmployeeId" to "resolvedById" via employee table mapping @@ -153,7 +153,7 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface UPDATE "comment" SET "resolvedById" = e."userId" FROM "employee" e - WHERE "comment"."resolvedByEmployeeId" = e.id + WHERE "comment"."resolvedByEmployeeId" = e.id AND "comment"."resolvedByEmployeeId" IS NOT NULL `); // Step 6: Drop the new columns "resolvedByEmployeeId" and "employeeId" @@ -200,12 +200,126 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface * * @param queryRunner */ - public async mysqlUpQueryRunner(queryRunner: QueryRunner): Promise {} + public async mysqlUpQueryRunner(queryRunner: QueryRunner): Promise { + // Step 1: Drop existing foreign keys on "creatorId" and "resolvedById" + console.log('Step 1: Dropping existing foreign keys...'); + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_b6bf60ecb9f6c398e349adff52f\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_c9409c81aa283c1aae70fd5f4c3\``); + + // Step 2: Drop existing indexes on "creatorId" and "resolvedById" + console.log('Step 2: Dropping existing indexes on "creatorId" and "resolvedById"...'); + await queryRunner.query(`DROP INDEX \`IDX_c9409c81aa283c1aae70fd5f4c\` ON \`comment\``); + await queryRunner.query(`DROP INDEX \`IDX_b6bf60ecb9f6c398e349adff52\` ON \`comment\``); + + // Step 3: Add new columns "employeeId" and "resolvedByEmployeeId". + console.log('Step 3: Adding new columns "employeeId" and "resolvedByEmployeeId" to "comment"...'); + await queryRunner.query(`ALTER TABLE \`comment\` ADD \`employeeId\` varchar(255) NULL`); + await queryRunner.query(`ALTER TABLE \`comment\` ADD \`resolvedByEmployeeId\` varchar(255) NULL`); + + // Step 4: Copy data from "creatorId" to "employeeId" using the employee mapping + console.log('Step 4: Copying data from "creatorId" to "employeeId" via employee table mapping...'); + await queryRunner.query(` + UPDATE \`comment\` c + JOIN \`employee\` e ON c.\`creatorId\` = e.\`userId\` + SET c.\`employeeId\` = e.\`id\` + WHERE c.\`creatorId\` IS NOT NULL + `); + + // Step 5: Copy data from "resolvedById" to "resolvedByEmployeeId" using the employee mapping + console.log('Step 5: Copying data from "resolvedById" to "resolvedByEmployeeId" via employee table mapping...'); + await queryRunner.query(` + UPDATE \`comment\` c + JOIN \`employee\` e ON c.\`resolvedById\` = e.\`userId\` + SET c.\`resolvedByEmployeeId\` = e.\`id\` + WHERE c.\`resolvedById\` IS NOT NULL + `); + + // Step 6: Drop the old columns "creatorId" and "resolvedById". + console.log('Step 6: Dropping old columns "creatorId" and "resolvedById"...'); + await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`creatorId\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`resolvedById\``); + + // Step 6: Create indexes on the new columns. + console.log('Step 7: Creating indexes on "employeeId" and "resolvedByEmployeeId"...'); + await queryRunner.query(`CREATE INDEX \`IDX_7a88834dadfa6fe261268bfcee\` ON \`comment\` (\`employeeId\`)`); + await queryRunner.query( + `CREATE INDEX \`IDX_35cddb3e66a46587966b68a921\` ON \`comment\` (\`resolvedByEmployeeId\`)` + ); + + // Step 8: Add foreign key constraint for "employeeId" + console.log('Step 8: Adding foreign key constraint for "employeeId"...'); + await queryRunner.query(` + ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_7a88834dadfa6fe261268bfceef\` + FOREIGN KEY (\`employeeId\`) REFERENCES \`employee\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION + `); + + // Step 9: Add foreign key constraint for "resolvedByEmployeeId" + console.log('Step 9: Adding foreign key constraint for "resolvedByEmployeeId"...'); + await queryRunner.query(` + ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_35cddb3e66a46587966b68a9217\` + FOREIGN KEY (\`resolvedByEmployeeId\`) REFERENCES \`employee\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION + `); + } /** * MySQL Down Migration * * @param queryRunner */ - public async mysqlDownQueryRunner(queryRunner: QueryRunner): Promise {} + public async mysqlDownQueryRunner(queryRunner: QueryRunner): Promise { + // Step 1: Drop foreign key constraints for "resolvedByEmployeeId" and "employeeId" + console.log('Step 1: Dropping foreign key constraints for "resolvedByEmployeeId" and "employeeId"...'); + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_35cddb3e66a46587966b68a9217\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP FOREIGN KEY \`FK_7a88834dadfa6fe261268bfceef\``); + + // Step 2: Drop indexes on "resolvedByEmployeeId" and "employeeId" + console.log('Step 2: Dropping indexes on "resolvedByEmployeeId" and "employeeId"...'); + await queryRunner.query(`DROP INDEX \`IDX_35cddb3e66a46587966b68a921\` ON \`comment\``); + await queryRunner.query(`DROP INDEX \`IDX_7a88834dadfa6fe261268bfcee\` ON \`comment\``); + + // Step 3: Re-add the old columns "resolvedById" and "creatorId" + console.log('Step 3: Adding columns "resolvedById" and "creatorId"...'); + await queryRunner.query(`ALTER TABLE \`comment\` ADD \`resolvedById\` varchar(255) NULL`); + await queryRunner.query(`ALTER TABLE \`comment\` ADD \`creatorId\` varchar(255) NULL`); + + // Step 4: Copy data from "employeeId" to "creatorId" via employee table mapping + console.log('Step 4: Copying data from "employeeId" to "creatorId" via employee table mapping...'); + await queryRunner.query(` + UPDATE \`comment\` c + JOIN \`employee\` e ON c.\`employeeId\` = e.\`id\` + SET c.\`creatorId\` = e.\`userId\` + WHERE c.\`employeeId\` IS NOT NULL + `); + + // Step 5: Copy data from "resolvedByEmployeeId" to "resolvedById" via employee table mapping + console.log('Step 5: Copying data from "resolvedByEmployeeId" to "resolvedById" via employee table mapping...'); + await queryRunner.query(` + UPDATE \`comment\` c + JOIN \`employee\` e ON c.\`resolvedByEmployeeId\` = e.\`id\` + SET c.\`resolvedById\` = e.\`userId\` + WHERE c.\`resolvedByEmployeeId\` IS NOT NULL + `); + + // Step 6: Drop the new columns "resolvedByEmployeeId" and "employeeId" + console.log('Step 6: Dropping columns "resolvedByEmployeeId" and "employeeId"...'); + await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`resolvedByEmployeeId\``); + await queryRunner.query(`ALTER TABLE \`comment\` DROP COLUMN \`employeeId\``); + + // Step 7: Create indexes on the restored columns "resolvedById" and "creatorId" + console.log('Step 7: Creating indexes on "resolvedById" and "creatorId"...'); + await queryRunner.query(`CREATE INDEX \`IDX_b6bf60ecb9f6c398e349adff52\` ON \`comment\` (\`creatorId\`)`); + await queryRunner.query(`CREATE INDEX \`IDX_c9409c81aa283c1aae70fd5f4c\` ON \`comment\` (\`resolvedById\`)`); + + // Step 8: Add foreign key constraint for "resolvedById" referencing "user" + console.log('Step 8: Adding foreign key constraint for "resolvedById" referencing "user"...'); + await queryRunner.query( + `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_c9409c81aa283c1aae70fd5f4c3\` FOREIGN KEY (\`resolvedById\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` + ); + + // Step 9: Add foreign key constraint for "creatorId" referencing "user" + console.log('Step 9: Adding foreign key constraint for "creatorId" referencing "user"...'); + await queryRunner.query( + `ALTER TABLE \`comment\` ADD CONSTRAINT \`FK_b6bf60ecb9f6c398e349adff52f\` FOREIGN KEY (\`creatorId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` + ); + } } From 949b46cc7115e35423bb52fcca842a8525245bd2 Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Thu, 13 Feb 2025 16:33:26 +0530 Subject: [PATCH 12/16] feat(migration): alter comment entity [table] for SQLite --- .../1739364133493-AlterCommentEntityTable.ts | 444 +++++++++++++++++- 1 file changed, 442 insertions(+), 2 deletions(-) diff --git a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts index 80e49f97405..4d22a2d25f8 100644 --- a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts +++ b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts @@ -186,14 +186,454 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface * * @param queryRunner */ - public async sqliteUpQueryRunner(queryRunner: QueryRunner): Promise {} + public async sqliteUpQueryRunner(queryRunner: QueryRunner): Promise { + // Step 1: Drop existing indexes from the current "comment" table. + console.log('Step 1: Dropping existing indexes from "comment"...'); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_b6bf60ecb9f6c398e349adff52"`); + await queryRunner.query(`DROP INDEX "IDX_c9409c81aa283c1aae70fd5f4c"`); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + + // Step 2: Create a temporary table with extra columns. + console.log('Step 2: Creating temporary table "temporary_comment" with new columns...'); + await queryRunner.query(` + CREATE TABLE "temporary_comment" ( + "deletedAt" datetime, + "id" varchar PRIMARY KEY NOT NULL, + "createdAt" datetime NOT NULL DEFAULT (datetime('now')), + "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), + "isActive" boolean DEFAULT (1), + "isArchived" boolean DEFAULT (0), + "archivedAt" datetime, + "tenantId" varchar, + "organizationId" varchar, + "entity" varchar NOT NULL, + "entityId" varchar NOT NULL, + "comment" text NOT NULL, + "actorType" integer, + "resolved" boolean, + "resolvedAt" datetime, + "editedAt" datetime, + "parentId" varchar, + "creatorId" varchar, + "resolvedById" varchar, + "employeeId" varchar, + "resolvedByEmployeeId" varchar, + CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION + ) + `); + + // Step 3: Copy data from the old "comment" table into the temporary table. + console.log('Step 3: Copying data from the existing "comment" table into "temporary_comment"...'); + await queryRunner.query(` + INSERT INTO "temporary_comment" ( + "deletedAt", + "id", + "createdAt", + "updatedAt", + "isActive", + "isArchived", + "archivedAt", + "tenantId", + "organizationId", + "entity", + "entityId", + "comment", + "actorType", + "resolved", + "resolvedAt", + "editedAt", + "parentId", + "creatorId", + "resolvedById" + ) + SELECT + "deletedAt", + "id", + "createdAt", + "updatedAt", + "isActive", + "isArchived", + "archivedAt", + "tenantId", + "organizationId", + "entity", + "entityId", + "comment", + "actorType", + "resolved", + "resolvedAt", + "editedAt", + "parentId", + "creatorId", + "resolvedById" + FROM "comment" + `); + + // Step 4: Copy data from "creatorId" to "employeeId" using the employee mapping + console.log('Step 4: Updating "employeeId" from "creatorId" via employee table mapping...'); + await queryRunner.query(` + UPDATE "temporary_comment" + SET "employeeId" = ( + SELECT e."id" + FROM "employee" e + WHERE e."userId" = "temporary_comment"."creatorId" + LIMIT 1 + ) + WHERE "creatorId" IS NOT NULL + `); + + // Step 5: Copy data from "resolvedById" to "resolvedByEmployeeId" using the employee mapping + console.log('Step 5: Updating "resolvedByEmployeeId" from "resolvedById" via employee table mapping...'); + await queryRunner.query(` + UPDATE "temporary_comment" + SET "resolvedByEmployeeId" = ( + SELECT e."id" + FROM "employee" e + WHERE e."userId" = "temporary_comment"."resolvedById" + LIMIT 1 + ) + WHERE "resolvedById" IS NOT NULL + `); + + // Step 6: Drop the old "comment" table and rename the temporary table to it. + console.log('Step 6: Dropping the old "comment" table and renaming the temporary table to it...'); + await queryRunner.query(`DROP TABLE "comment"`); + await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); + + // Step 7: Recreate the "comment" table without the old columns. + console.log('Step 7: Recreating "comment" table without old columns...'); + await queryRunner.query(` + CREATE TABLE "temporary_comment" ( + "deletedAt" datetime, + "id" varchar PRIMARY KEY NOT NULL, + "createdAt" datetime NOT NULL DEFAULT (datetime('now')), + "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), + "isActive" boolean DEFAULT (1), + "isArchived" boolean DEFAULT (0), + "archivedAt" datetime, + "tenantId" varchar, + "organizationId" varchar, + "entity" varchar NOT NULL, + "entityId" varchar NOT NULL, + "comment" text NOT NULL, + "actorType" integer, + "resolved" boolean, + "resolvedAt" datetime, + "editedAt" datetime, + "parentId" varchar, + "employeeId" varchar, + "resolvedByEmployeeId" varchar, + CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, + CONSTRAINT "FK_7a88834dadfa6fe261268bfceef" FOREIGN KEY ("employeeId") REFERENCES "employee" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_35cddb3e66a46587966b68a9217" FOREIGN KEY ("resolvedByEmployeeId") REFERENCES "employee" ("id") ON DELETE CASCADE ON UPDATE NO ACTION + ) + `); + + // Step 8: Copy data from the temporary table (which now has the new columns) into the new clean table. + console.log('Step 8: Copying data into the new "comment" table without old columns...'); + await queryRunner.query(` + INSERT INTO "temporary_comment" ( + "deletedAt", + "id", + "createdAt", + "updatedAt", + "isActive", + "isArchived", + "archivedAt", + "tenantId", + "organizationId", + "entity", + "entityId", + "comment", + "actorType", + "resolved", + "resolvedAt", + "editedAt", + "parentId", + "employeeId", + "resolvedByEmployeeId" + ) + SELECT + "deletedAt", + "id", + "createdAt", + "updatedAt", + "isActive", + "isArchived", + "archivedAt", + "tenantId", + "organizationId", + "entity", + "entityId", + "comment", + "actorType", + "resolved", + "resolvedAt", + "editedAt", + "parentId", + "employeeId", + "resolvedByEmployeeId" + FROM "temporary_comment" + `); + + // Step 9: Drop the old "comment" table and rename the new clean table. + console.log('Step 9: Dropping old "comment" table and renaming "temporary_comment" to "comment"...'); + await queryRunner.query(`DROP TABLE "comment"`); + await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); + + // Step 10: Create final indexes on the new "comment" table. + console.log('Step 10: Creating indexes on the new "comment" table...'); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive")`); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived")`); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId")`); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId")`); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity")`); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId")`); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType")`); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId")`); + await queryRunner.query(`CREATE INDEX "IDX_7a88834dadfa6fe261268bfcee" ON "comment" ("employeeId")`); + await queryRunner.query(`CREATE INDEX "IDX_35cddb3e66a46587966b68a921" ON "comment" ("resolvedByEmployeeId")`); + } /** * SqliteDB and BetterSQlite3DB Down Migration * * @param queryRunner */ - public async sqliteDownQueryRunner(queryRunner: QueryRunner): Promise {} + public async sqliteDownQueryRunner(queryRunner: QueryRunner): Promise { + // Step 1: Drop existing indexes from the final "comment" table. + console.log('Step 1: Dropping existing indexes from "comment"...'); + await queryRunner.query(`DROP INDEX "IDX_35cddb3e66a46587966b68a921"`); + await queryRunner.query(`DROP INDEX "IDX_7a88834dadfa6fe261268bfcee"`); + await queryRunner.query(`DROP INDEX "IDX_e3aebe2bd1c53467a07109be59"`); + await queryRunner.query(`DROP INDEX "IDX_eecd6e41f9acb6bf59e474d518"`); + await queryRunner.query(`DROP INDEX "IDX_2950cfa146fc50334efa61a70b"`); + await queryRunner.query(`DROP INDEX "IDX_097e339f6cb990306d19880a4c"`); + await queryRunner.query(`DROP INDEX "IDX_a3422826753d4e6b079dea9834"`); + await queryRunner.query(`DROP INDEX "IDX_8f58834bed39f0f9e85f048eaf"`); + await queryRunner.query(`DROP INDEX "IDX_da3cd25ed3a6ce76770f00c3da"`); + await queryRunner.query(`DROP INDEX "IDX_3620aeff4ac5c977176226017e"`); + + // Step 2: Rename the current "comment" table to "temporary_comment". + console.log('Step 2: Renaming "comment" to "temporary_comment"...'); + await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); + + // Step 3: Create a new "comment" table with the old schema. + // This new table includes "creatorId" and "resolvedById" with their foreign key constraints. + console.log('Step 3: Creating new "comment" table with old schema (with "creatorId" and "resolvedById")...'); + await queryRunner.query(` + CREATE TABLE "comment" ( + "deletedAt" datetime, + "id" varchar PRIMARY KEY NOT NULL, + "createdAt" datetime NOT NULL DEFAULT (datetime('now')), + "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), + "isActive" boolean DEFAULT (1), + "isArchived" boolean DEFAULT (0), + "archivedAt" datetime, + "tenantId" varchar, + "organizationId" varchar, + "entity" varchar NOT NULL, + "entityId" varchar NOT NULL, + "comment" text NOT NULL, + "actorType" integer, + "resolved" boolean, + "resolvedAt" datetime, + "editedAt" datetime, + "parentId" varchar, + "creatorId" varchar, + "resolvedById" varchar, + "employeeId" varchar, + "resolvedByEmployeeId" varchar, + CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION + ) + `); + + // Step 4: Copy data from the old "temporary_comment" table into the "comment" table. + console.log('Step 4: Copying data from the existing "temporary_comment" table into "comment"...'); + await queryRunner.query(` + INSERT INTO "comment" ( + "deletedAt", + "id", + "createdAt", + "updatedAt", + "isActive", + "isArchived", + "archivedAt", + "tenantId", + "organizationId", + "entity", + "entityId", + "comment", + "actorType", + "resolved", + "resolvedAt", + "editedAt", + "parentId", + "employeeId", + "resolvedByEmployeeId" + ) + SELECT + "deletedAt", + "id", + "createdAt", + "updatedAt", + "isActive", + "isArchived", + "archivedAt", + "tenantId", + "organizationId", + "entity", + "entityId", + "comment", + "actorType", + "resolved", + "resolvedAt", + "editedAt", + "parentId", + "employeeId", + "resolvedByEmployeeId" + FROM "temporary_comment" + `); + + // Step 5: Update "creatorId" from "employeeId" using employee table mapping + console.log('Step 5: Updating "creatorId" from "employeeId" via employee table mapping...'); + await queryRunner.query(` + UPDATE "comment" + SET "creatorId" = ( + SELECT e."userId" + FROM "employee" e + WHERE e."id" = "comment"."employeeId" + LIMIT 1 + ) + WHERE "employeeId" IS NOT NULL + `); + + // Step 6: Update "resolvedById" from "resolvedByEmployeeId" using employee table mapping + console.log('Step 6: Updating "resolvedById" from "resolvedByEmployeeId" via employee table mapping...'); + await queryRunner.query(` + UPDATE "comment" + SET "resolvedById" = ( + SELECT e."userId" + FROM "employee" e + WHERE e."id" = "comment"."resolvedByEmployeeId" + LIMIT 1 + ) + WHERE "resolvedByEmployeeId" IS NOT NULL + `); + + // Step 7: Drop the old "comment" table and rename the temporary table to it. + console.log('Step 7: Dropping the old "temporary_comment" table and renaming the "comment" table to it...'); + await queryRunner.query(`DROP TABLE "temporary_comment"`); + await queryRunner.query(`ALTER TABLE "comment" RENAME TO "temporary_comment"`); + + // Step 8: Recreating "comment" table with the new columns. + console.log('Step 8: Recreating "comment" table with the new columns...'); + await queryRunner.query(` + CREATE TABLE "comment" ( + "deletedAt" datetime, + "id" varchar PRIMARY KEY NOT NULL, + "createdAt" datetime NOT NULL DEFAULT (datetime('now')), + "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), + "isActive" boolean DEFAULT (1), + "isArchived" boolean DEFAULT (0), + "archivedAt" datetime, + "tenantId" varchar, + "organizationId" varchar, + "entity" varchar NOT NULL, + "entityId" varchar NOT NULL, + "comment" text NOT NULL, + "actorType" integer, + "resolved" boolean, + "resolvedAt" datetime, + "editedAt" datetime, + "creatorId" varchar, + "resolvedById" varchar, + "parentId" varchar, + CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f" FOREIGN KEY ("creatorId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_c9409c81aa283c1aae70fd5f4c3" FOREIGN KEY ("resolvedById") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION + ) + `); + + // Step 9: Copy data from the old "temporary_comment" table into the "comment" table. + console.log('Step 9: Copying data from the existing "temporary_comment" table into "comment"...'); + await queryRunner.query(` + INSERT INTO "comment" ( + "deletedAt", + "id", + "createdAt", + "updatedAt", + "isActive", + "isArchived", + "archivedAt", + "tenantId", + "organizationId", + "entity", + "entityId", + "comment", + "actorType", + "resolved", + "resolvedAt", + "editedAt", + "creatorId", + "resolvedById", + "parentId" + ) + SELECT + "deletedAt", + "id", + "createdAt", + "updatedAt", + "isActive", + "isArchived", + "archivedAt", + "tenantId", + "organizationId", + "entity", + "entityId", + "comment", + "actorType", + "resolved", + "resolvedAt", + "editedAt", + "creatorId", + "resolvedById", + "parentId" + FROM "temporary_comment" + `); + + // Step 10: Dropping the old "temporary_comment" table. + console.log('Step 10: Dropping the old "temporary_comment" table...'); + await queryRunner.query(`DROP TABLE "temporary_comment"`); + + // Step 11: Create final indexes on the new "comment" table. + console.log('Step 11: Creating indexes on the new "comment" table...'); + await queryRunner.query(`CREATE INDEX "IDX_e3aebe2bd1c53467a07109be59" ON "comment" ("parentId") `); + await queryRunner.query(`CREATE INDEX "IDX_c9409c81aa283c1aae70fd5f4c" ON "comment" ("resolvedById") `); + await queryRunner.query(`CREATE INDEX "IDX_b6bf60ecb9f6c398e349adff52" ON "comment" ("creatorId") `); + await queryRunner.query(`CREATE INDEX "IDX_eecd6e41f9acb6bf59e474d518" ON "comment" ("actorType") `); + await queryRunner.query(`CREATE INDEX "IDX_2950cfa146fc50334efa61a70b" ON "comment" ("entityId") `); + await queryRunner.query(`CREATE INDEX "IDX_097e339f6cb990306d19880a4c" ON "comment" ("entity") `); + await queryRunner.query(`CREATE INDEX "IDX_a3422826753d4e6b079dea9834" ON "comment" ("organizationId") `); + await queryRunner.query(`CREATE INDEX "IDX_8f58834bed39f0f9e85f048eaf" ON "comment" ("tenantId") `); + await queryRunner.query(`CREATE INDEX "IDX_da3cd25ed3a6ce76770f00c3da" ON "comment" ("isArchived") `); + await queryRunner.query(`CREATE INDEX "IDX_3620aeff4ac5c977176226017e" ON "comment" ("isActive") `); + } /** * MySQL Up Migration From 649421a1a10b78812e64bc938972afc8aba4aabb Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Thu, 13 Feb 2025 17:26:40 +0530 Subject: [PATCH 13/16] fix: update comment controller methods definition --- .../src/lib/comment/comment.controller.ts | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/core/src/lib/comment/comment.controller.ts b/packages/core/src/lib/comment/comment.controller.ts index 98f263cf240..42259c44d3f 100644 --- a/packages/core/src/lib/comment/comment.controller.ts +++ b/packages/core/src/lib/comment/comment.controller.ts @@ -32,7 +32,10 @@ export class CommentController extends CrudController { } /** - * Find all comments filtered by type. + * Finds all comments filtered by type (or other criteria) with pagination. + * + * @param params - Pagination and filter parameters. + * @returns A promise that resolves with paginated comments. */ @ApiOperation({ summary: 'Find all comments filtered by type.' }) @ApiResponse({ @@ -51,13 +54,16 @@ export class CommentController extends CrudController { } /** - * Find by id + * Finds a comment by its id. + * + * @param id - The id of the comment. + * @param params - Optional parameters (e.g., relations to load). + * @returns The found comment record. */ @ApiOperation({ summary: 'Find by id' }) @ApiResponse({ status: HttpStatus.OK, description: 'Found one record' - // You can specify a type here if needed: type: Comment, }) @ApiResponse({ status: HttpStatus.NOT_FOUND, @@ -69,7 +75,10 @@ export class CommentController extends CrudController { } /** - * Create/Post a comment + * Creates a new comment using the provided DTO. + * + * @param createCommentDto - Data transfer object containing comment data. + * @returns A promise resolving to the created comment. */ @ApiOperation({ summary: 'Create/Post a comment' }) @ApiResponse({ @@ -80,7 +89,7 @@ export class CommentController extends CrudController { status: HttpStatus.BAD_REQUEST, description: 'Invalid input, The response body may contain clues as to what went wrong' }) - @HttpCode(HttpStatus.ACCEPTED) + @HttpCode(HttpStatus.CREATED) @Post('/') @UseValidationPipe({ whitelist: true }) async create(@Body() entity: CreateCommentDTO): Promise { @@ -88,7 +97,12 @@ export class CommentController extends CrudController { } /** - * Update an existing comment + * Updates an existing comment identified by the provided id. + * + * @param id - The unique identifier of the comment. + * @param updateCommentDto - The data transfer object containing update data. + * @returns The updated comment. + * @throws NotFoundException if the comment does not exist. */ @ApiOperation({ summary: 'Update an existing comment' }) @ApiResponse({ @@ -111,7 +125,11 @@ export class CommentController extends CrudController { } /** - * Delete comment + * Deletes a comment identified by the given id. + * + * @param id - The unique identifier of the comment to delete. + * @returns A promise resolving to the result of the delete operation. + * @throws NotFoundException if the comment is not found. */ @ApiOperation({ summary: 'Delete comment' }) @ApiResponse({ From be7c4cb48eef120e6ca11727641e01a410514178 Mon Sep 17 00:00:00 2001 From: "Rahul R." Date: Thu, 13 Feb 2025 19:59:41 +0530 Subject: [PATCH 14/16] feat(migration): alter comment entity [table] for SQLite --- .../1739364133493-AlterCommentEntityTable.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts index 4d22a2d25f8..931d77a6c16 100644 --- a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts +++ b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts @@ -227,7 +227,9 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface "resolvedByEmployeeId" varchar, CONSTRAINT "FK_8f58834bed39f0f9e85f048eafe" FOREIGN KEY ("tenantId") REFERENCES "tenant" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_a3422826753d4e6b079dea98342" FOREIGN KEY ("organizationId") REFERENCES "organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION + CONSTRAINT "FK_e3aebe2bd1c53467a07109be596" FOREIGN KEY ("parentId") REFERENCES "comment" ("id") ON DELETE SET NULL ON UPDATE NO ACTION, + CONSTRAINT "FK_7a88834dadfa6fe261268bfceef" FOREIGN KEY ("employeeId") REFERENCES "employee" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_35cddb3e66a46587966b68a9217" FOREIGN KEY ("resolvedByEmployeeId") REFERENCES "employee" ("id") ON DELETE CASCADE ON UPDATE NO ACTION ) `); @@ -304,15 +306,10 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface WHERE "resolvedById" IS NOT NULL `); - // Step 6: Drop the old "comment" table and rename the temporary table to it. - console.log('Step 6: Dropping the old "comment" table and renaming the temporary table to it...'); - await queryRunner.query(`DROP TABLE "comment"`); - await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); - - // Step 7: Recreate the "comment" table without the old columns. - console.log('Step 7: Recreating "comment" table without old columns...'); + // Step 6: Recreate the "clean_comment" table without the old columns. + console.log('Step 6: Recreating "clean_comment" table without old columns...'); await queryRunner.query(` - CREATE TABLE "temporary_comment" ( + CREATE TABLE "clean_comment" ( "deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), @@ -341,9 +338,9 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface `); // Step 8: Copy data from the temporary table (which now has the new columns) into the new clean table. - console.log('Step 8: Copying data into the new "comment" table without old columns...'); + console.log('Step 8: Copying data into the new "clean_comment" table without old columns...'); await queryRunner.query(` - INSERT INTO "temporary_comment" ( + INSERT INTO "clean_comment" ( "deletedAt", "id", "createdAt", @@ -388,9 +385,12 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface `); // Step 9: Drop the old "comment" table and rename the new clean table. - console.log('Step 9: Dropping old "comment" table and renaming "temporary_comment" to "comment"...'); + console.log( + 'Step 9: Dropping old "comment" table and renaming "clean_comment" to "comment" and dropping "temporary_comment"...' + ); await queryRunner.query(`DROP TABLE "comment"`); - await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); + await queryRunner.query(`ALTER TABLE "clean_comment" RENAME TO "comment"`); + await queryRunner.query(`DROP TABLE "temporary_comment"`); // Step 10: Create final indexes on the new "comment" table. console.log('Step 10: Creating indexes on the new "comment" table...'); From 906c33af1da51bf99f68b00f85e8ef65546723f6 Mon Sep 17 00:00:00 2001 From: RAHUL RATHORE Date: Thu, 13 Feb 2025 22:14:37 +0530 Subject: [PATCH 15/16] feat(migration): alter comment entity [table] for SQLite --- .../1739364133493-AlterCommentEntityTable.ts | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts index 931d77a6c16..05402069c53 100644 --- a/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts +++ b/packages/core/src/lib/database/migrations/1739364133493-AlterCommentEntityTable.ts @@ -306,10 +306,15 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface WHERE "resolvedById" IS NOT NULL `); - // Step 6: Recreate the "clean_comment" table without the old columns. - console.log('Step 6: Recreating "clean_comment" table without old columns...'); + // Step 6: Drop the old "comment" table and rename the temporary table to it. + console.log('Step 6: Dropping the old "comment" table and renaming the temporary table to it...'); + await queryRunner.query(`DROP TABLE "comment"`); + await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); + + // Step 7: Recreate the "temporary_comment" table without the old columns. + console.log('Step 7: Recreating "temporary_comment" table without old columns...'); await queryRunner.query(` - CREATE TABLE "clean_comment" ( + CREATE TABLE "temporary_comment" ( "deletedAt" datetime, "id" varchar PRIMARY KEY NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), @@ -338,9 +343,9 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface `); // Step 8: Copy data from the temporary table (which now has the new columns) into the new clean table. - console.log('Step 8: Copying data into the new "clean_comment" table without old columns...'); + console.log('Step 8: Copying data into the new "temporary_comment" table without old columns...'); await queryRunner.query(` - INSERT INTO "clean_comment" ( + INSERT INTO "temporary_comment" ( "deletedAt", "id", "createdAt", @@ -381,16 +386,13 @@ export class AlterCommentEntityTable1739364133493 implements MigrationInterface "parentId", "employeeId", "resolvedByEmployeeId" - FROM "temporary_comment" + FROM "comment" `); // Step 9: Drop the old "comment" table and rename the new clean table. - console.log( - 'Step 9: Dropping old "comment" table and renaming "clean_comment" to "comment" and dropping "temporary_comment"...' - ); + console.log('Step 9: Dropping old "comment" table and renaming "temporary_comment" to "comment"...'); await queryRunner.query(`DROP TABLE "comment"`); - await queryRunner.query(`ALTER TABLE "clean_comment" RENAME TO "comment"`); - await queryRunner.query(`DROP TABLE "temporary_comment"`); + await queryRunner.query(`ALTER TABLE "temporary_comment" RENAME TO "comment"`); // Step 10: Create final indexes on the new "comment" table. console.log('Step 10: Creating indexes on the new "comment" table...'); From c14968738ec2d5436658cbf567a9876e9ea08b78 Mon Sep 17 00:00:00 2001 From: RAHUL RATHORE Date: Thu, 13 Feb 2025 22:19:18 +0530 Subject: [PATCH 16/16] fix(deepscan): removed unused import :) --- packages/core/src/lib/comment/dto/create-comment.dto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/lib/comment/dto/create-comment.dto.ts b/packages/core/src/lib/comment/dto/create-comment.dto.ts index 8e898c37852..a4fd103ac17 100644 --- a/packages/core/src/lib/comment/dto/create-comment.dto.ts +++ b/packages/core/src/lib/comment/dto/create-comment.dto.ts @@ -1,4 +1,4 @@ -import { ApiPropertyOptional, IntersectionType, OmitType } from '@nestjs/swagger'; +import { ApiPropertyOptional, IntersectionType } from '@nestjs/swagger'; import { IsOptional, IsString } from 'class-validator'; import { ICommentCreateInput } from '@gauzy/contracts'; import { TenantOrganizationBaseDTO } from './../../core/dto';