Skip to content

Commit

Permalink
fix: issue type should be created from global type
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul-rocket committed Feb 15, 2024
1 parent d4dd97d commit f828020
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@ import { TenantIssueTypeBulkCreateCommand } from '../tenant-issue-type-bulk-crea
import { IssueTypeService } from '../../issue-type.service';

@CommandHandler(TenantIssueTypeBulkCreateCommand)
export class TenantIssueTypeBulkCreateHandler
implements ICommandHandler<TenantIssueTypeBulkCreateCommand>
{
constructor(private readonly issueTypeService: IssueTypeService) {}
export class TenantIssueTypeBulkCreateHandler implements ICommandHandler<TenantIssueTypeBulkCreateCommand> {

constructor(
private readonly issueTypeService: IssueTypeService
) { }

/**
*
* @param command
* @returns
*/
public async execute(
command: TenantIssueTypeBulkCreateCommand
): Promise<IIssueType[]> {
const { tenants } = command;

// Create issue types of the tenant.
return await this.issueTypeService.bulkCreateTenantsIssueTypes(tenants);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ export class IssueTypeController extends CrudFactory<
async findAllIssueTypes(
@Query() params: IssueTypeQuerDTO
): Promise<IPagination<IIssueType>> {
return await this.issueTypeService.findAllIssueTypes(params);
return await this.issueTypeService.fetchAll(params);
}
}
164 changes: 83 additions & 81 deletions packages/core/src/tasks/issue-type/issue-type.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { DeleteResult, SelectQueryBuilder } from 'typeorm';
import { Knex as KnexConnection } from 'knex';
Expand Down Expand Up @@ -47,20 +47,18 @@ export class IssueTypeService extends TaskStatusPrioritySizeService<IssueType> {
}

/**
* GET issue types by filters
* If parameters not match, retrieve global issue types
* Fetches issue types based on specified parameters.
*
* @param params
* @returns
* @param params - Parameters for finding issue types (IIssueTypeFindInput).
* @returns A Promise resolving to an object with items (array of issue types) and total count.
* @throws Error if no records are found or an error occurs during the query.
*/
async findAllIssueTypes(
params: IIssueTypeFindInput
): Promise<IPagination<IIssueType>> {
public async fetchAll(params: IIssueTypeFindInput): Promise<IPagination<IIssueType>> {
try {
/**
* Find at least one record or get global records
*/
const cqb = this.repository.createQueryBuilder(this.alias);
const cqb = this.typeOrmIssueTypeRepository.createQueryBuilder(this.alias);
cqb.where((qb: SelectQueryBuilder<IssueType>) => {
this.getFilterQuery(qb, params);
});
Expand All @@ -69,11 +67,7 @@ export class IssueTypeService extends TaskStatusPrioritySizeService<IssueType> {
/**
* Find task issue types for given params
*/
const query = this.repository.createQueryBuilder(this.alias).setFindOptions({
relations: {
image: true
}
});
const query = this.typeOrmIssueTypeRepository.createQueryBuilder(this.alias);
query.where((qb: SelectQueryBuilder<IssueType>) => {
this.getFilterQuery(qb, params);
});
Expand All @@ -85,31 +79,44 @@ export class IssueTypeService extends TaskStatusPrioritySizeService<IssueType> {
}

/**
* Create bulk issue type for tenants
* Create or fetch issue types for a list of tenants.
*
* @param tenants '
* @param tenants The list of tenants.
* @returns A promise resolving to an array of created or fetched issue types.
*/
async bulkCreateTenantsIssueTypes(
tenants: ITenant[]
): Promise<IIssueType[]> {
async bulkCreateTenantsIssueTypes(tenants: ITenant[]): Promise<IIssueType[]> {
try {
const issueTypes: IIssueType[] = [];

for (const tenant of tenants) {
for (const issueType of DEFAULT_GLOBAL_ISSUE_TYPES) {
const create = this.repository.create({
...issueType,
icon: `ever-icons/${issueType.icon}`,
tenant,
isSystem: false,
});
issueTypes.push(create);
}
}
// Fetch existing issue types
const { items = [], total } = await super.fetchAll({});

// Define default issue types
const defaultIssueTypes = DEFAULT_GLOBAL_ISSUE_TYPES.map((issueType: IIssueType) => ({
...issueType,
icon: `ever-icons/${issueType.icon}`,
isSystem: false
}));

// Function to generate issue types based on a source array
const generateIssueTypes = (source: IIssueType[]) => tenants.flatMap((tenant) =>
source.map(({ name, value, description, icon, color, imageId = null }: IIssueType) => ({
name,
value,
description,
icon,
color,
imageId,
tenant,
isSystem: false
}))
);

// Generate the array of issue types based on existing or default values
const issueTypes: IIssueType[] = total > 0 ? generateIssueTypes(items) : generateIssueTypes(defaultIssueTypes);

// Save the created or fetched issue types to the repository and return the result.
return await this.repository.save(issueTypes);
} catch (error) {
throw new BadRequestException(error);
throw new HttpException('Invalid request parameter: Some required parameters are missing or incorrect.', HttpStatus.BAD_REQUEST);
}
}

Expand All @@ -118,73 +125,68 @@ export class IssueTypeService extends TaskStatusPrioritySizeService<IssueType> {
*
* @param organization
*/
async bulkCreateOrganizationIssueType(
organization: IOrganization
): Promise<IIssueType[]> {
async bulkCreateOrganizationIssueType(organization: IOrganization): Promise<IIssueType[]> {
try {
const tenantId = RequestContext.currentTenantId();
const { items = [] } = await super.fetchAll({ tenantId });

const issueTypes: IIssueType[] = [];
const { items = [] } = await this.findAllIssueTypes({ tenantId });

for (const item of items) {
const { name, value, description, icon, color } = item;

const create = this.repository.create({
// Use map to generate issue types for each item.
const issueTypes: IIssueType[] = items.map((item: IIssueType) => (
new IssueType({
tenantId,
name,
value,
description,
icon,
color,
name: item.name,
value: item.value,
description: item.description,
icon: item.icon,
color: item.color,
imageId: item.imageId,
organization,
isSystem: false,
});
issueTypes.push(create);
}
isSystem: false
})
));
return await this.repository.save(issueTypes);
} catch (error) {
throw new BadRequestException(error);
throw new HttpException('Invalid request parameter: Some required parameters are missing or incorrect.', HttpStatus.BAD_REQUEST);
}
}

/**
* Create bulk issue type for specific organization entity
* Create bulk issue types for a specific organization entity.
*
* @param entity
* @returns
* @param entity - Partial input for creating issue types (Partial<IIssueTypeCreateInput>).
* @returns A Promise resolving to an array of created issue types (IIssueType[]).
* @throws HttpException if an error occurs during the creation process.
*/
async createBulkIssueTypeByEntity(
entity: Partial<IIssueTypeCreateInput>
): Promise<IIssueType[]> {
async createBulkIssueTypeByEntity(entity: Partial<IIssueTypeCreateInput>): Promise<IIssueType[]> {
try {
const { organizationId } = entity;
const tenantId = RequestContext.currentTenantId();

const { items = [] } = await this.findAllIssueTypes({
tenantId,
organizationId
});

const issueTypes: IIssueType[] = [];
for (const item of items) {
const { name, value, description, icon, color } = item;

const issueType = await this.create({
...entity,
name,
value,
description,
icon,
color,
isSystem: false,
});
issueTypes.push(issueType);
}

// Fetch items based on tenant and organizationId
const { items = [] } = await super.fetchAll({ tenantId, organizationId });

// Use Promise.all to concurrently create issue types for each item
// Wait for all issue types to be created and resolve the promises
const issueTypes = await Promise.all(
items.map(async (item: IIssueType) => {
const { name, value, description, icon, color, imageId } = item;
// Create and return the issue type
return await this.create({
...entity,
name,
value,
description,
icon,
color,
imageId,
isSystem: false
});
})
);
return issueTypes;
} catch (error) {
throw new BadRequestException(error);
// If an error occurs, throw an HttpException with a more specific message.
throw new HttpException('Failed to create bulk issue types for the organization entity.', HttpStatus.BAD_REQUEST);
}
}
}
14 changes: 12 additions & 2 deletions packages/core/src/tasks/task-status-priority-size.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import { Brackets, Repository, SelectQueryBuilder, WhereExpressionBuilder } from
import { Knex as KnexConnection } from 'knex';
import { EntityRepository } from '@mikro-orm/core';
import {
FileStorageProviderEnum,
IIssueTypeFindInput,
IPagination,
ITaskPriorityFindInput,
ITaskSizeFindInput,
ITaskStatusFindInput,
ITaskVersionFindInput
} from '@gauzy/contracts';
import { TenantBaseEntity } from '../core/entities/internal';
import { FileStorage } from '../core/file-storage';
import { RequestContext } from '../core/context';
import { TenantAwareCrudService } from '../core/crud';
import { TenantBaseEntity } from '../core/entities/internal';
import { prepareSQLQuery as p } from './../database/database.helper';

export type IFindEntityByParams = | ITaskStatusFindInput | ITaskPriorityFindInput | ITaskSizeFindInput | IIssueTypeFindInput | ITaskVersionFindInput;
Expand All @@ -35,7 +37,7 @@ export class TaskStatusPrioritySizeService<BaseEntity extends TenantBaseEntity>
*/
async fetchAllByKnex(input: IFindEntityByParams): Promise<IPagination<BaseEntity>> {
try {
// Attempt to get at least one record that matches the specified parameters
// Ensure at least one record matches the specified parameters
const first = await this.getOneOrFailByKnex(this.knexConnection, input);

// If no record is found, throw an error
Expand All @@ -46,6 +48,14 @@ export class TaskStatusPrioritySizeService<BaseEntity extends TenantBaseEntity>
// Perform the Knex query to fetch entities and their count
const items = await this.getManyAndCountByKnex(this.knexConnection, input);

// Fetch fullIconUrl for items with an icon
await Promise.all(items.map(async (item: any) => {
if (item.icon) {
const store = new FileStorage().setProvider(FileStorageProviderEnum.LOCAL);
item.fullIconUrl = await store.getProviderInstance().url(item.icon);
}
}));

// Calculate the total count of items
const total = items.length;

Expand Down

0 comments on commit f828020

Please sign in to comment.