Skip to content

Commit

Permalink
Merge pull request #6923 from ever-co/feat/6909-active-archived-softD…
Browse files Browse the repository at this point in the history
…elete-records

Feat/6909 active archived soft delete records
  • Loading branch information
rahul-rocket authored Oct 4, 2023
2 parents b2642bd + f638b06 commit 81509be
Show file tree
Hide file tree
Showing 28 changed files with 5,547 additions and 150 deletions.
31 changes: 19 additions & 12 deletions packages/contracts/src/base-entity.model.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import { ITenant } from './tenant.model';
import { IOrganization } from './organization.model';

// Common properties for entities with relations
export interface IBaseRelationsEntityModel {
readonly relations?: string[];
relations?: string[]; // List of related entities
}

// Common properties for soft delete entities
export interface IBaseSoftDeleteEntityModel {
deletedAt?: Date;
deletedAt?: Date; // Indicates if the record is soft deleted
}

export interface IBaseEntityModel extends IBaseSoftDeleteEntityModel {
id?: string;
// Common properties for entities
export interface IBaseEntityModel extends IBaseSoftDeleteEntityModel {
id?: string; // Unique identifier

readonly createdAt?: Date;
readonly updatedAt?: Date;
readonly createdAt?: Date; // Date when the record was created
readonly updatedAt?: Date; // Date when the record was last updated

isActive?: boolean; // Indicates if the record is currently active
isArchived?: boolean; // Indicates if the record is archived
}

// Common properties for entities associated with a tenant
export interface IBasePerTenantEntityModel extends IBaseEntityModel {
tenantId?: string;
tenant?: ITenant;
tenantId?: ITenant['id']; // Identifier of the associated tenant
tenant?: ITenant; // Reference to the associated tenant
}

export interface IBasePerTenantAndOrganizationEntityModel
extends IBasePerTenantEntityModel {
organizationId?: string;
organization?: IOrganization;
// Common properties for entities associated with both tenant and organization
export interface IBasePerTenantAndOrganizationEntityModel extends IBasePerTenantEntityModel {
organizationId?: IOrganization['id']; // Identifier of the associated organization
organization?: IOrganization; // Reference to the associated organization
}
20 changes: 6 additions & 14 deletions packages/contracts/src/candidate-interview.model.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import { IBasePerTenantAndOrganizationEntityModel } from './base-entity.model';
import { ICandidate } from './candidate.model';
import { IRelationalCandidate } from './candidate.model';
import { ICandidateFeedback } from './candidate-feedback.model';
import { ICandidateInterviewers } from './candidate-interviewers.model';
import { ICandidatePersonalQualities } from './candidate-personal-qualities.model';
import { ICandidateTechnologies } from './candidate-technologies.model';
import { IEmployee } from './employee.model';

export interface IRelationalCandidateInterview {
readonly interview?: ICandidateInterview;
readonly interviewId?: ICandidateInterview['id'];
readonly interview?: ICandidateInterview;
readonly interviewId?: ICandidateInterview['id'];
}

export interface ICandidateInterview
extends IBasePerTenantAndOrganizationEntityModel {
export interface ICandidateInterview extends IBasePerTenantAndOrganizationEntityModel, IRelationalCandidate {
title: string;
candidateId?: string;
candidate?: ICandidate;
interviewers?: ICandidateInterviewers[];
location?: string;
startTime: Date;
Expand All @@ -26,13 +23,10 @@ export interface ICandidateInterview
technologies?: ICandidateTechnologies[];
personalQualities?: ICandidatePersonalQualities[];
rating?: number;
isArchived?: boolean;
}

export interface ICandidateInterviewFindInput
extends IBasePerTenantAndOrganizationEntityModel {
export interface ICandidateInterviewFindInput extends IBasePerTenantAndOrganizationEntityModel, IRelationalCandidate {
title?: string;
candidateId?: string;
interviewers?: ICandidateInterviewers[];
location?: string;
startTime?: Date;
Expand All @@ -43,10 +37,8 @@ export interface ICandidateInterviewFindInput
personalQualities?: ICandidatePersonalQualities[];
}

export interface ICandidateInterviewCreateInput
extends IBasePerTenantAndOrganizationEntityModel {
export interface ICandidateInterviewCreateInput extends IBasePerTenantAndOrganizationEntityModel, IRelationalCandidate {
title: string;
candidateId?: string;
interviewers?: ICandidateInterviewers[];
location?: string;
note?: string;
Expand Down
5 changes: 2 additions & 3 deletions packages/contracts/src/candidate.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { ITag } from './tag.model';
import { IEmployee, PayPeriodEnum } from './employee.model';

export interface IRelationalCandidate {
readonly candidate?: ICandidate;
readonly candidateId?: ICandidate['id'];
candidate?: ICandidate;
candidateId?: ICandidate['id'];
}

export interface ICandidate extends IBasePerTenantAndOrganizationEntityModel {
Expand Down Expand Up @@ -47,7 +47,6 @@ export interface ICandidate extends IBasePerTenantAndOrganizationEntityModel {
cvUrl?: string;
feedbacks?: ICandidateFeedback[];
rating?: number;
isArchived?: boolean;
interview?: ICandidateInterview[];
contact?: IContact;
contactId?: IContact['id'];
Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/email.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export interface IEmailHistory extends IBasePerTenantAndOrganizationEntityModel,
name: string;
content: string;
email: string;
isArchived?: boolean;
}

export interface IEmailUpdateInput extends IBasePerTenantAndOrganizationEntityModel, IRelationalUser, Partial<IRelationalEmailTemplate> {
Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/employee.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export interface IEmployee extends IBasePerTenantAndOrganizationEntityModel {
user: IUser;
userId: string;
valueDate?: Date;
isActive: boolean;
short_description?: string;
description?: string;
teams?: IOrganizationTeam[];
Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/event-type.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export interface IEventType extends IBasePerTenantAndOrganizationEntityModel {
description?: string;
duration: number;
durationUnit: string;
isActive: boolean;
employeeId?: string;
employee?: IEmployee;
tags?: ITag[];
Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/invoice.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export interface IInvoice extends IBasePerTenantAndOrganizationEntityModel {
amountDue?: number;
hasRemainingAmountInvoiced?: boolean;
token?: string;
isArchived?: boolean;
}

export interface IInvoiceCreateInput
Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/organization-sprint.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export interface IOrganizationSprint
endDate?: Date;
dayStart?: number; // Enum ((Sunday-Saturday) => (0-7))
project?: IOrganizationProject;
isActive?: boolean;
tasks?: ITask[];
}

Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/organization.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export interface IOrganization
overview: string;
skills: ISkill[];
currency: string;
isActive: boolean;
defaultValueDateType: DefaultValueDateTypeEnum;
defaultAlignmentType?: string;
dateFormat?: string;
Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/pipeline.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export interface IPipeline extends IBasePerTenantAndOrganizationEntityModel {
stages: IPipelineStage[];
description: string;
name: string;
isActive: boolean;
}

export type IPipelineFindInput = Partial<
Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/time-off.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export interface ITimeOff extends IBasePerTenantAndOrganizationEntityModel {
documentUrl?: string;
fullName?: string;
imageUrl?: string;
isArchived?: boolean;
}

export interface ITimeOffFindInput
Expand Down
1 change: 0 additions & 1 deletion packages/contracts/src/user-organization.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export interface IUserOrganization
extends IBasePerTenantAndOrganizationEntityModel {
userId: string;
isDefault: boolean;
isActive: boolean;
user?: IUser;
}

Expand Down
2 changes: 0 additions & 2 deletions packages/contracts/src/user.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ export interface IUser extends IBasePerTenantEntityModel, IRelationalImageAsset
organizations?: IUserOrganization[];
isImporting?: boolean;
sourceId?: string;
isActive?: boolean;
isArchived?: boolean;
code?: string;
codeExpireAt?: Date;
emailVerifiedAt?: Date;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ export class CandidateInterview extends TenantOrganizationBaseEntity
@Column({ nullable: true })
note?: string;

@ApiPropertyOptional({ type: () => Boolean, default: false })
@Column({ nullable: true, default: false })
isArchived?: boolean;

@ApiPropertyOptional({ type: () => Number })
@Column({
Expand All @@ -55,10 +52,10 @@ export class CandidateInterview extends TenantOrganizationBaseEntity
rating?: number;

/*
|--------------------------------------------------------------------------
| @OneToMany
|--------------------------------------------------------------------------
*/
|--------------------------------------------------------------------------
| @OneToMany
|--------------------------------------------------------------------------
*/
@ApiProperty({ type: () => CandidateFeedback })
@OneToMany(() => CandidateFeedback, (feedback) => feedback.interview, {
onDelete: 'SET NULL'
Expand Down Expand Up @@ -88,10 +85,10 @@ export class CandidateInterview extends TenantOrganizationBaseEntity
interviewers?: ICandidateInterviewers[];

/*
|--------------------------------------------------------------------------
| @ManyToOne
|--------------------------------------------------------------------------
*/
|--------------------------------------------------------------------------
| @ManyToOne
|--------------------------------------------------------------------------
*/

/**
* Candidate
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/candidate/candidate.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,6 @@ export class Candidate extends TenantOrganizationBaseEntity implements ICandidat
@Column({ nullable: true })
cvUrl?: string;

@ApiPropertyOptional({ type: () => Boolean, default: false })
@Column({ nullable: true, default: false })
isArchived?: boolean;

ratings?: number;
alreadyHired?: boolean;
Expand Down
23 changes: 22 additions & 1 deletion packages/core/src/core/entities/base.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import {
PrimaryGeneratedColumn,
UpdateDateColumn,
CreateDateColumn
CreateDateColumn,
Column,
Index
} from 'typeorm';
import { ApiPropertyOptional } from '@nestjs/swagger';
import { BaseEntityModel as IBaseEntityModel } from '@gauzy/contracts';
import { IsBoolean, IsOptional } from 'class-validator';

export abstract class Model {
constructor(input?: any) {
Expand All @@ -25,6 +28,7 @@ export abstract class BaseEntity extends Model implements IBaseEntityModel {
@PrimaryGeneratedColumn('uuid')
id?: string;

// Date when the record was created
@ApiPropertyOptional({
type: 'string',
format: 'date-time',
Expand All @@ -33,11 +37,28 @@ export abstract class BaseEntity extends Model implements IBaseEntityModel {
@CreateDateColumn()
createdAt?: Date;

// Date when the record was last updated
@ApiPropertyOptional({
type: 'string',
format: 'date-time',
example: '2018-11-21T06:20:32.232Z'
})
@UpdateDateColumn()
updatedAt?: Date;

// Indicates if record is active now
@ApiPropertyOptional({ type: Boolean, default: true })
@IsOptional()
@IsBoolean()
@Index()
@Column({ nullable: false, default: true })
isActive?: boolean;

// Indicate if record is archived
@ApiPropertyOptional({ type: Boolean, default: false })
@IsOptional()
@IsBoolean()
@Index()
@Column({ nullable: false, default: false })
isArchived?: boolean;
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
import { MigrationInterface, QueryRunner, SelectQueryBuilder } from "typeorm";
import { createDefaultEmailTemplates } from "./../../email-template/email-template.seed";
import { EmailTemplate } from "./../../core/entities/internal";
import { MigrationInterface, QueryRunner } from "typeorm";
import * as chalk from 'chalk';
import { EmailTemplateEnum } from "@gauzy/contracts";
import { EmailTemplateUtils } from "email-template/utils";

export class MigrateEmailTemplatesData1643809486960 implements MigrationInterface {

name = 'MigrateEmailTemplatesData1643809486960';

/**
* Up Migration
*
* @param queryRunner
*/
public async up(queryRunner: QueryRunner): Promise<any> {
/**
* Removed default gauzy email templates, again seed them with new one
*/
const query = queryRunner.connection.createQueryBuilder(EmailTemplate, 'email_template');
query.where((qb: SelectQueryBuilder<EmailTemplate>) => {
qb.andWhere(`"${qb.alias}"."organizationId" IS NULL`);
qb.andWhere(`"${qb.alias}"."tenantId" IS NULL`);
});
const emailTemplates = await query.getMany();
await queryRunner.connection.getRepository(EmailTemplate).remove(emailTemplates);

/**
* Reseed all new default email templates
*/
await createDefaultEmailTemplates(queryRunner.connection);
console.log(chalk.yellow(`MigrateEmailTemplatesData1643809486960 start running!`));
const templates = Object.values(EmailTemplateEnum);
await Promise.all(
templates.map(
async (template: EmailTemplateEnum) => {
try {
await EmailTemplateUtils.migrateEmailTemplates(queryRunner, template);
} catch (error) {
console.log(`Error while migrating missing email templates for ${template}`, error);
}
}
)
);
}

public async down(queryRunner: QueryRunner): Promise<any> {}
}
public async down(queryRunner: QueryRunner): Promise<any> { }
}
Loading

0 comments on commit 81509be

Please sign in to comment.