import { Inject, Injectable } from '@nestjs/common'; import { FieldMapperRepository } from '../repository/field-mapper.repository'; import { FieldMapperDto } from '../dto/field-mapper.dto'; import { EntityServiceImpl } from '../../meta/service/entity-service-impl.service'; import { UserData } from '../../user/entity/user.entity'; import { FieldLovsRepository } from '../repository/field-lovs.repository'; import { BaseEntity } from '../../meta/entity/base-entity.entity'; import { LoggingService } from 'src/utils/service/loggingUtil.service'; import { FilterService } from '../../filter/service/filter.service'; @Injectable() export class FieldMapperService extends EntityServiceImpl { constructor( private readonly fieldMapperRepository: FieldMapperRepository, private readonly fieldLovsRepository: FieldLovsRepository, private readonly filterService: FilterService, @Inject() protected readonly loggingService: LoggingService, ) { super(); } async createEntity(dto: FieldMapperDto, loggedInUser: UserData) { let savedEntity = await super.createEntity(dto, loggedInUser); if (dto.field_lovs) { for (const lov of dto.field_lovs) { lov.mapper_field_id = savedEntity.id; lov.entity_type = 'FLOV'; } await this.fieldLovsRepository.saveBulk(dto.field_lovs); } return savedEntity; } async updateEntity(dto: FieldMapperDto, loggedInUser: UserData) { return super.updateEntity(dto, loggedInUser); } async createFieldMappers(dtos: FieldMapperDto[], loggedInUser: UserData) { let mapperId = dtos[0].mapper_id; let existingMappers = await this.fieldMapperRepository.findByMapperId(mapperId); for (const mapper of existingMappers) { await this.fieldLovsRepository.deleteByMapperFieldId(mapper.id); } await this.fieldMapperRepository.deleteByMapperId(mapperId); let result: BaseEntity[] = []; for (const dto of dtos) { const fieldMapper = await this.createEntity(dto, loggedInUser); result.push(fieldMapper); } return result; } async updateFieldMappers(dtos: FieldMapperDto[], loggedInUser: UserData) { let result: BaseEntity[] = []; for (const dto of dtos) { const fieldMapper = await super.updateEntity(dto, loggedInUser); result.push(fieldMapper); } return result; } async getMapperFields(mapperId: number, mapper_entity_type: string) { let fieldMappers = await this.fieldMapperRepository.findByMapperIdAndMapperEntityType( mapperId, mapper_entity_type, ); const fieldMapperDtos = fieldMappers as unknown as FieldMapperDto[]; for (const fieldMapper of fieldMapperDtos) { fieldMapper.field_lovs = await this.fieldLovsRepository.findByMapperFieldId(fieldMapper.id); } return fieldMapperDtos; } async getFieldLovs(mapperFieldId: number) { return await this.fieldLovsRepository.findByMapperFieldId(mapperFieldId); } async resolveData( mapper_id: number, action: 'LOOKUP' | 'LOAD', parent_type: string, parent_id: number, userData: UserData, inputJson?: Record, mappedEntities?: Record, overwrite?: boolean, entity_data?: any, ) { // Fetch field mappings for this mapper const fieldMappers = await this.fieldMapperRepository.findByMapperId(mapper_id); // Initialize the final response (generic) let result: any; if (action === 'LOOKUP') result = new Map(); else if (action === 'LOAD') result = { entity_type: parent_type, mappedEntities: {}, }; const inMemory: Record> = {}; // cache per entity-type + filter for (const field of fieldMappers) { const entityType = field.mapped_entity_type || field.mapper_entity_type; const filterCode = field.filter_code || 'default'; // ---------------------------------------------------------------- // LOOKUP (System → External) // ---------------------------------------------------------------- if (action === 'LOOKUP') { if (!inMemory[entityType]) inMemory[entityType] = {}; if (!inMemory[entityType][filterCode]) { if (field.mapped_entity_type === field.mapper_entity_type) { inMemory[entityType][filterCode] = await super.getResolvedEntityDataByDataSource( entityType, parent_id, userData, ); } else { if ( overwrite && entity_data && entity_data[field.mapped_entity_type] ) { inMemory[entityType][filterCode] = entity_data[field.mapped_entity_type]; } else { const relationDataRepo = this.reflectionHelper.getRepoService('EntityRelationData'); const relations = await relationDataRepo.find({ where: { source_entity_type: parent_type, source_entity_id: parent_id, target_entity_type: field.mapped_entity_type, }, }); const targetEntityIds = relations.map((r) => r.target_entity_id); this.loggingService.log( 'debug', 'fieldMapperService', 'resolveData', `Resolved targetEntityIds: ${targetEntityIds} for entityType: ${entityType}`, [parent_type, parent_id, field.mapped_entity_type], [], ); if (targetEntityIds.length > 0) { if (filterCode && filterCode !== 'default') { let filterResponse = await this.filterService.applyFilterWrapper({ entity_type: entityType, savedFilterCode: filterCode, quickFilter: [ { filter_attribute: 'id', filter_operator: 'equal', filter_value: targetEntityIds, filter_entity_type: entityType, }, ], attributeFilter: [], loggedInUser: userData, queryParams: {}, }); this.loggingService.log( 'debug', 'fieldMapperService', 'resolveData', `Filter response for filterCode: ${filterCode} is ${JSON.stringify( filterResponse, )}`, [entityType, filterCode, targetEntityIds], [], ); inMemory[entityType][filterCode] = filterResponse?.data?.entity_list[0]; } else { let firstId = targetEntityIds[0]; if ( mappedEntities && entityType in mappedEntities && mappedEntities[entityType] ) { firstId = mappedEntities[entityType]; } inMemory[entityType][filterCode] = await super.getResolvedEntityData( entityType, firstId, userData, ); } } else { inMemory[entityType][filterCode] = null; } } } } // Extract and transform values const entityData = inMemory[entityType][filterCode]; if (entityData) { let value = entityData[field.attribute_key]; // Apply LOV mapping (System → External) if (field.is_lov_present) { const fieldLovMapper = await this.fieldLovsRepository.findByMapperFieldIdAndDestinationAttributeValue( field.id, value, ); if (fieldLovMapper) { value = fieldLovMapper.source_attribute_value; } } // Add to result result.set(field.source_attribute, value); } } // ---------------------------------------------------------------- // LOAD (External → System) // ---------------------------------------------------------------- else if (action === 'LOAD' && inputJson) { let value = inputJson[field.source_attribute]; if (field.is_lov_present && value !== undefined && value !== null) { const fieldLovMapper = await this.fieldLovsRepository.findByMapperFieldIdAndSourceAttributeValue( field.id, value, ); if (fieldLovMapper) value = fieldLovMapper.destination_attribute_value; } // If field belongs to main entity type → put at top level if (entityType === parent_type) { result[field.attribute_key] = value; } else { if (!result.mappedEntities[entityType]) result.mappedEntities[entityType] = [{}]; result.mappedEntities[entityType][0][field.attribute_key] = value; } } } if (action === 'LOOKUP') { return Object.fromEntries(result); } return result; } }