import { Injectable, Logger } from '@nestjs/common'; import { BaseEntity } from 'src/module/meta/entity/base-entity.entity'; import { EntityServiceImpl } from 'src/module/meta/service/entity-service-impl.service'; import { UserData } from 'src/module/user/entity/user.entity'; import { LayoutPreferenceRepository } from '../repository/layout_preference.repository'; import { DataSource } from 'typeorm'; @Injectable() export class LayoutPreferenceService extends EntityServiceImpl { private readonly logger = new Logger(LayoutPreferenceService.name); constructor( private layoutPreferenceRepository: LayoutPreferenceRepository, private readonly dataSource: DataSource, ) { super(); } async createEntity(entityData: BaseEntity, loggedInUser: UserData) { const { mapped_entity_type, type } = entityData as any; const userId = loggedInUser?.id; if (userId === undefined) { throw new Error('User ID is required to create layout preference.'); } const existingLayoutPreference = await this.layoutPreferenceRepository.findByEntityUserId( mapped_entity_type, loggedInUser.level_id, loggedInUser.level_type, userId, type, ); if (existingLayoutPreference) { return await super.updateEntity( { ...entityData, id: existingLayoutPreference.id }, loggedInUser, ); } return await super.createEntity( { ...entityData, user_id: userId, mapped_level_id: loggedInUser.level_id, mapped_level_type: loggedInUser.level_type, } as any, loggedInUser, ); } async getLayoutPreferenceByUserID( user_id, mapped_entity_type, mapped_level_id, mapped_level_type, type, ) { const layoutPreference = await this.layoutPreferenceRepository.findByEntityUserId( mapped_entity_type, mapped_level_id, mapped_level_type, user_id, type, ); if (layoutPreference) { return layoutPreference; } return { mapped_json: {}, }; } async getColumnValue( entity_type: string, column: string, sort_by: string, loggedInUser: UserData, ): Promise<{ label: string; value: string }[]> { try { const getTableMeta = await this.entityTableService.findByEntityTypeAndListTypeAndDisplayType( entity_type, entity_type, 'LIST', loggedInUser?.enterprise_id, ); const tableName = getTableMeta?.data_source; if (!tableName) { throw new Error('Invalid or missing table name in metadata'); } // Query DB to get distinct column values and counts const rawData: { column_value: string; count: number }[] = await this.dataSource .createQueryBuilder() .select(`${column} AS column_value`) .addSelect(`COUNT(*) AS count`) .from(tableName, tableName) .where(`${column} IS NOT NULL`) .andWhere(`enterprise_id = :enterprise_id`, { enterprise_id: loggedInUser?.enterprise_id, }) .andWhere(`level_id = :levelId`, { levelId: loggedInUser?.level_id }) .andWhere(`level_type = :levelType`, { levelType: loggedInUser?.level_type, }) .groupBy(column) .getRawMany(); if (!rawData.length) { return []; } // Prepare payload for resolver const payloadBeforeResolved = rawData.map((row) => ({ [column]: row?.column_value, })); // Resolve column values using resolverService const resolvedEntityList = await Promise.all( payloadBeforeResolved.map((row) => this.resolverService.getResolvedData(loggedInUser, row, entity_type), ), ); // Merge resolved names with counts const resolvedWithCounts = rawData.map((row, index) => { const resolvedValue = resolvedEntityList[index]?.[column] || row.column_value; return { label: resolvedValue, // Human-readable label value: row.column_value, // Original DB value count: Number(row.count), }; }); // Sort based on sort_by parameter switch (sort_by) { case 'asc': resolvedWithCounts.sort((a, b) => a.label.localeCompare(b.label)); break; case 'dsc': resolvedWithCounts.sort((a, b) => b.label.localeCompare(a.label)); break; case 'count_asc': resolvedWithCounts.sort((a, b) => a.count - b.count); break; case 'count_dsc': resolvedWithCounts.sort((a, b) => b.count - a.count); break; default: break; } // Clean and return only label/value pairs return resolvedWithCounts .filter( (item) => item.label !== null && item.label !== undefined && item.label.toString().trim() !== '', ) .map((item) => ({ label: item.label, value: item.value, })); } catch (error) { this.logger.error(`getColumnValue ERROR: ${error.message}`, error.stack); return []; } } async getEntityLayoutAttributes( entity_type: string, query_payload: any, loggedInUser: UserData, ): Promise { return this.layoutPreferenceRepository.getEntityLayoutAttributes( entity_type, query_payload, loggedInUser, ); } }