import { DataSource } from 'typeorm'; import { BadRequestException, forwardRef, Inject, Injectable, NotFoundException } from '@nestjs/common'; import { ListMasterItemsRepository } from '../repository/list-master-items.repository'; import { EntityServiceImpl } from 'src/module/meta/service/entity-service-impl.service'; import { UserData } from 'src/module/user/entity/user.entity'; import { CodeGeneratorService } from 'src/utils/service/codeGenerator.service'; import { AttributeMasterService } from 'src/module/meta/service/attribute-master.service'; import { ListMasterRepository } from '../repository/list-master.repository'; @Injectable() export class ListMasterItemService extends EntityServiceImpl { constructor( private readonly listItemsRepo: ListMasterItemsRepository, private readonly listMasterRepo: ListMasterRepository, @Inject(forwardRef(() => EntityServiceImpl)) private readonly entityServiceImpl: EntityServiceImpl, protected readonly attributeMasterService: AttributeMasterService, private readonly dataSource: DataSource, ) { super(); } async getListMasterItemsByType( listType: string, enterprise_id: number, search?: string, ) { // this method retrieves all list master items for a specific type and organization return this.listItemsRepo.findAllItemsByListType( listType, 'asc', enterprise_id, search, ); } async createEntity(entityData: any, loggedInUser: UserData): Promise { try { const generatedCode = CodeGeneratorService.generateCode(entityData.name); entityData.code = generatedCode; entityData.value = generatedCode; return await this.entityServiceImpl.createEntity( entityData, loggedInUser, ); } catch (error) { throw error; } } async updateEntity(entityData: any, loggedInUser: UserData): Promise { return await this.entityServiceImpl.updateEntity(entityData, loggedInUser); } async upsertListMasterItem( listType: string, items: any[], loggedInUser, ): Promise { const entId = loggedInUser.enterprise_id; const errors: any[] = []; for (let i = 0; i < items.length; i++) { const item = items[i]; const name = item.name?.trim(); const code = item.code?.trim(); try { if (!name) { throw new BadRequestException(`name is missing at index ${i}`); } if (code) { // Check if code exists const existingItem = await this.listItemsRepo.findOneByCondition({ code, listtype: listType, enterprise_id: entId, }); if (existingItem) { // It's an update — check if name is changing to a used name if (existingItem.name.toLowerCase() !== name.toLowerCase()) { const nameExists = await this.listItemsRepo.findOneByCondition({ name, listtype: listType, enterprise_id: entId, }); if (nameExists && nameExists.id !== existingItem.id) { throw new BadRequestException( `${name} already used by another item`, ); } } // Update the existing item await this.updateEntity( { ...existingItem, ...item, name, listtype: listType, }, loggedInUser, ); continue; } } // Creation path const nameExists = await this.listItemsRepo.findOneByCondition({ name, listtype: listType, enterprise_id: entId, }); if (nameExists) { throw new BadRequestException( `list item with name ${name} already exists`, ); } const finalCode = code || ''; // Could generate code here if needed await this.createEntity( { ...item, name, code: finalCode, listtype: listType, value: '', }, loggedInUser, ); } catch (error) { errors.push({ row: i, errors: [ { field: 'name', message: error.message || 'An error occurred while processing the item', }, ], }); } } const updatedItems = await this.listItemsRepo.findAllItemsByListType( listType, 'asc', entId, ); return { success: errors.length === 0, listType, errors, items: updatedItems, }; } async deleteListMasterItem(listType: string, code: string): Promise { const item = await this.listItemsRepo.findOneByCondition({ code, listtype: listType, }); if (!item) { throw new NotFoundException( `Item with name ${code} not found in type ${listType}`, ); } await this.listItemsRepo.delete({ code, listtype: listType }); return `Item with name ${code} deleted successfully from type ${listType}`; } async getListSourceType( loggedInUser: UserData, source: string, ): Promise { return await this.listMasterRepo.findByEnterpriseIdAndSource(loggedInUser.enterprise_id, source); } // async getResolvedListMasterItems( // loggedInUser: UserData, // entityData: any, // entityType: string, // ): Promise { // const attributeItems = // await this.attributeMasterService.findAttributesByMappedEntityType( // entityType, // loggedInUser, // ); // const masterAttributes = attributeItems.filter( // (attr) => attr.data_source_type === 'master', // ); // const resolvedEntityData = { ...entityData }; // for (const attr of masterAttributes) { // const field = attr.attribute_key; // const codeValue = entityData[field]; // if (!codeValue) continue; // const listItems = await this.listItemsRepo.findById(codeValue); // if (!listItems) continue; // } // return resolvedEntityData; // } // async getResolvedListMasterItems( // loggedInUser: UserData, // entityData: any, // entityType: string, // ): Promise { // // const resolvedEntityData = super.getResolvedData( // // loggedInUser, // // entityData, // // entityType, // // ); // // const attributeItems = // // await this.attributeMasterService.findAttributesByMappedEntityType( // // entityType, // // loggedInUser, // // ); // // const resolvedEntityData = { ...entityData }; // // for (const attr of attributeItems) { // // const field = attr.attribute_key; // // const codeValue = entityData[field]; // // if (!codeValue) continue; // // // ---------- ENTITY data_source_type ---------- // // if (attr.data_source_type === 'entity') { // // if (Array.isArray(codeValue)) { // // const resolvedValues: string[] = []; // // for (const code of codeValue) { // // const item = await super.getEntityData( // // attr.datasource_list, // // code, // // loggedInUser, // // ); // // resolvedValues.push(item?.[attr.data_source_attribute] ?? code); // // } // // resolvedEntityData[field] = resolvedValues; // // } else { // // const item = await super.getEntityData( // // attr.datasource_list, // // codeValue, // // loggedInUser, // // ); // // resolvedEntityData[field] = // // item?.[attr.data_source_attribute] ?? codeValue; // // } // // } // // // ---------- MASTER data_source_type ---------- // // else if (attr.data_source_type === 'master') { // // if (Array.isArray(codeValue)) { // // const resolvedValues: string[] = []; // // for (const code of codeValue) { // // const item = await this.listItemsRepo.findById(code); // // resolvedValues.push(item?.[attr.data_source_attribute] ?? code); // // } // // resolvedEntityData[field] = resolvedValues; // // } else { // // const item = await this.listItemsRepo.findById(codeValue); // // resolvedEntityData[field] = // // item?.[attr.data_source_attribute] ?? codeValue; // // } // // } // // } // // return resolvedEntityData; // } }