Skip to content

Commit

Permalink
Merge pull request #7881 from ever-co/fix/organization-team-timer-sta…
Browse files Browse the repository at this point in the history
…tistics

[Fix] Organization Team Members Timer Statistics
  • Loading branch information
rahul-rocket authored Jun 17, 2024
2 parents 623ffd2 + b151097 commit d63bfff
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 68 deletions.
52 changes: 26 additions & 26 deletions packages/common/src/utils/shared-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,32 +163,32 @@ export function chunks(items: any[], size: number): any[] {
* @returns {boolean} - A boolean representation of the given input.
*/
export const parseToBoolean = (value: any): boolean => {
if (value === undefined || value === null) {
return false; // Return false for undefined or null
}

try {
const parsed = JSON.parse(value); // Attempt to parse as JSON
if (typeof parsed === 'boolean') {
return parsed; // Return if it's already a boolean
}

// Convert numbers: 0 is false, other numbers are true
if (typeof parsed === 'number') {
return parsed !== 0;
}

// Convert common truthy/falsy strings
if (typeof parsed === 'string') {
const lowerCase = parsed.toLowerCase().trim();
return lowerCase === 'true' || lowerCase === '1'; // Consider 'true' and '1' as true
}

return Boolean(parsed); // Fallback to Boolean conversion
} catch (error) {
// Handle JSON parse errors
return false; // Return false on parsing errors
}
if (value === undefined || value === null) {
return false; // Return false for undefined or null
}

try {
const parsed = JSON.parse(value); // Attempt to parse as JSON
if (typeof parsed === 'boolean') {
return parsed; // Return if it's already a boolean
}

// Convert numbers: 0 is false, other numbers are true
if (typeof parsed === 'number') {
return parsed !== 0;
}

// Convert common truthy/falsy strings
if (typeof parsed === 'string') {
const lowerCase = parsed.toLowerCase().trim();
return lowerCase === 'true' || lowerCase === '1'; // Consider 'true' and '1' as true
}

return Boolean(parsed); // Fallback to Boolean conversion
} catch (error) {
// Handle JSON parse errors
return false; // Return false on parsing errors
}
};

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
import { ApiPropertyOptional, IntersectionType } from '@nestjs/swagger';
import { IsOptional } from 'class-validator';
import { Transform, TransformFnParams } from 'class-transformer';
import {
IDateRangePicker,
IOrganizationTeamStatisticInput
} from '@gauzy/contracts';
import { IDateRangePicker, IOrganizationTeamStatisticInput } from '@gauzy/contracts';
import { parseToBoolean } from '@gauzy/common';
import { DateRangeQueryDTO, RelationsQueryDTO } from './../../shared/dto';

/**
* DTO for handling requests related to organization team statistics.
* Combines date range and relations query features.
*/
export class OrganizationTeamStatisticDTO extends IntersectionType(
DateRangeQueryDTO,
RelationsQueryDTO
) implements IOrganizationTeamStatisticInput, IDateRangePicker {
export class OrganizationTeamStatisticDTO
extends IntersectionType(DateRangeQueryDTO, RelationsQueryDTO)
implements IOrganizationTeamStatisticInput, IDateRangePicker
{
/**
* Indicates whether the last worked task row should be included in the entity result.
* Default value is set to false.
*/
@ApiPropertyOptional({ type: Boolean, default: false })
@IsOptional()
@Transform(({ value }: TransformFnParams) => value ? parseToBoolean(value) : false)
@Transform(({ value }: TransformFnParams) => (value ? parseToBoolean(value) : false))
readonly withLastWorkedTask: boolean;
}
75 changes: 42 additions & 33 deletions packages/core/src/organization-team/organization-team.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
*/
async getOrganizationTeamStatistic(input: GetOrganizationTeamStatisticQuery): Promise<IOrganizationTeam> {
try {
console.time('Get Organization Team ID Query');
const { organizationTeamId, query } = input;
const { withLastWorkedTask } = query;

Expand All @@ -86,7 +85,6 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
);
}

console.timeEnd('Get Organization Team ID Query');
return organizationTeam;
} catch (error) {
throw new BadRequestException(error);
Expand Down Expand Up @@ -220,15 +218,10 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
// If not included, add the employeeId to the managerIds array
managerIds.push(employeeId);
}
} catch (error) { }
} catch (error) {}

// Retrieves a collection of employees based on specified criteria.
const employees = await this.retrieveEmployees(
memberIds,
managerIds,
organizationId,
tenantId
);
const employees = await this.retrieveEmployees(memberIds, managerIds, organizationId, tenantId);

// Find the manager role
const managerRole = await this.roleService.findOneByWhereOptions({ name: RolesEnum.MANAGER });
Expand All @@ -237,18 +230,29 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
const managerIdsSet = new Set(managerIds);

// Use destructuring to directly extract 'id' from 'employee'
const members = employees.map(({ id: employeeId }) => new OrganizationTeamEmployee({
employee: { id: employeeId },
organization: { id: organizationId },
tenant: { id: tenantId },
role: managerIdsSet.has(employeeId) ? managerRole : null
}));
const members = employees.map(
({ id: employeeId }) =>
new OrganizationTeamEmployee({
employee: { id: employeeId },
organization: { id: organizationId },
tenant: { id: tenantId },
role: managerIdsSet.has(employeeId) ? managerRole : null
})
);

// Create the organization team with the prepared members
return await super.create({
organization: { id: organizationId },
tenant: { id: tenantId },
tags, name, prefix, members, profile_link, public: input.public, logo, imageId, projects
tags,
name,
prefix,
members,
profile_link,
public: input.public,
logo,
imageId,
projects
});
} catch (error) {
throw new BadRequestException(`Failed to create a team: ${error}`);
Expand Down Expand Up @@ -304,12 +308,7 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
});

// Retrieves a collection of employees based on specified criteria.
const employees = await this.retrieveEmployees(
memberIds,
managerIds,
organizationId,
tenantId
);
const employees = await this.retrieveEmployees(memberIds, managerIds, organizationId, tenantId);

// Update nested entity
await this.organizationTeamEmployeeService.updateOrganizationTeam(
Expand Down Expand Up @@ -419,7 +418,9 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization

// Execute the raw SQL query and get the results
const rawResults: OrganizationTeamEmployee[] = (await knex.raw(sqlQuery.toString())).rows || [];
const organizationTeamIds = rawResults.map((entry: OrganizationTeamEmployee) => entry.organizationTeamId);
const organizationTeamIds = rawResults.map(
(entry: OrganizationTeamEmployee) => entry.organizationTeamId
);

// Convert to string for the subquery
return organizationTeamIds || [];
Expand All @@ -446,7 +447,9 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
}

// Converts TypeORM find options to a format compatible with MikroORM for a given entity.
const { where, mikroOptions } = parseTypeORMFindToMikroOrm<OrganizationTeam>(options as FindManyOptions);
const { where, mikroOptions } = parseTypeORMFindToMikroOrm<OrganizationTeam>(
options as FindManyOptions
);
// Retrieve the items and total count
const [entities, totalEntities] = await this.mikroOrmOrganizationTeamRepository.findAndCount(
enhanceWhereWithTenantId(tenantId, where), // Add a condition for the tenant ID
Expand Down Expand Up @@ -477,7 +480,9 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
// Apply the organization filter if available
if (options?.where?.organizationId) {
const { organizationId } = options.where;
subQuery.andWhere(p(`"${subQuery.alias}"."organizationId" = :organizationId`), { organizationId });
subQuery.andWhere(p(`"${subQuery.alias}"."organizationId" = :organizationId`), {
organizationId
});
}

// Additional conditions
Expand All @@ -498,13 +503,17 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
if (isNotEmpty(members) && isNotEmpty(members['employeeId'])) {
const employeeId = members['employeeId'];
// Sub query to get only employee assigned teams
typeOrmQueryBuilder.andWhere((cb: SelectQueryBuilder<OrganizationTeam>) => subQueryBuilder(cb, employeeId));
typeOrmQueryBuilder.andWhere((cb: SelectQueryBuilder<OrganizationTeam>) =>
subQueryBuilder(cb, employeeId)
);
}
} else {
// If employee has login and doesn't have permission to change employee
const employeeId = RequestContext.currentEmployeeId();
// Sub query to get only employee assigned teams
typeOrmQueryBuilder.andWhere((cb: SelectQueryBuilder<OrganizationTeam>) => subQueryBuilder(cb, employeeId));
typeOrmQueryBuilder.andWhere((cb: SelectQueryBuilder<OrganizationTeam>) =>
subQueryBuilder(cb, employeeId)
);
}

// Set query options
Expand Down Expand Up @@ -555,13 +564,13 @@ export class OrganizationTeamService extends TenantAwareCrudService<Organization
organizationId,
...(!RequestContext.hasPermission(PermissionsEnum.CHANGE_SELECTED_EMPLOYEE)
? {
members: {
employeeId: RequestContext.currentEmployeeId(),
role: {
name: RolesEnum.MANAGER
members: {
employeeId: RequestContext.currentEmployeeId(),
role: {
name: RolesEnum.MANAGER
}
}
}
}
}
: {})
}
});
Expand Down

0 comments on commit d63bfff

Please sign in to comment.