import { create } from 'domain'; import { CommTemplate } from './../entity/comm-template.entity'; import { ActionCategory } from './../entity/action-category.entity'; import { DataSource } from 'typeorm'; import { PopulateMetaService } from './../../meta/service/populate-meta.service'; import { Inject, Injectable } from '@nestjs/common'; import { EntityServiceImpl } from 'src/module/meta/service/entity-service-impl.service'; import { WorkflowService } from './workflow.service'; import { UserData } from 'src/module/user/entity/user.entity'; import { StageGroupService } from './stage-group.service'; import { StageService } from './stage.service'; import { ActionService } from './action.service'; @Injectable() export class PopulateWorkflowService extends EntityServiceImpl { constructor( private readonly populateMetaService: PopulateMetaService, private readonly dataSource: DataSource, @Inject('WorkflowService') private readonly workflowService: WorkflowService, @Inject('StageGroupService') private readonly stageGroupService: StageGroupService, @Inject('StageService') private readonly stageService: StageService, @Inject('ActionService') private readonly actionService: ActionService, ) { super(); } async populateWorkflowData(organization_id: number, loggedInUser: UserData) { const listMasterItemsRepo = this.reflectionHelper.getRepoService('ListMasterItems'); if (!listMasterItemsRepo) return; let statusRow = await listMasterItemsRepo.findOne({ where: { code: 'STATUS_ACTIVE', organization_id: organization_id }, }); if (!statusRow) { statusRow = await listMasterItemsRepo.findOne({ where: { code: 'STATUS_ACTIVE', organization_id: -1 }, }); } const statusValue = statusRow?.id; // template populate // Step 1: Fetch default frm_wf_comm_template const commTemplateRepo = this.reflectionHelper.getRepoService('CommTemplate'); if (!commTemplateRepo) return; const defaultCommTemplates = await commTemplateRepo.find({ where: { organization_id: -1, level_type: 'ORG', level_id: -1, }, }); if (defaultCommTemplates.length > 0) { // Step 2: Insert default communication templates for the new organization for (const template of defaultCommTemplates) { const { id, created_date, modified_date, ...rest } = template; await super.createEntity( { ...rest, organization_id, enterprise_id: organization_id, level_id: organization_id, entity_type: 'TEM', status: statusValue, created_date: new Date(), modified_date: new Date(), }, loggedInUser, ); } } const workflowTables = [ { table: 'frm_wf_master', entityType: 'WRFW', service: 'workflowService', }, { table: 'frm_wf_stage_group', entityType: 'WFSG', service: 'stageGroupService', }, { table: 'frm_wf_stage', entityType: 'WFS', service: 'stageService' }, { table: 'frm_wf_action', entityType: 'WFAC', service: 'actionService' }, ]; const workFlowRepo = this.reflectionHelper.getRepoService('Workflow'); const stageGroupRepo = this.reflectionHelper.getRepoService('StageGroup'); const stageRepo = this.reflectionHelper.getRepoService('Stage'); const actionRepo = this.reflectionHelper.getRepoService('ActionEntity'); const stageActionMappingRepo = this.reflectionHelper.getRepoService('StageActionMapping'); const workflowLevelMappingRepo = this.reflectionHelper.getRepoService( 'WorkflowLevelMappingEntity', ); const listMasterRepo = this.reflectionHelper.getRepoService('ListMasterData'); const actionCategoryRepo = this.reflectionHelper.getRepoService('ActionCategory'); const viewMasterRepo = this.reflectionHelper.getRepoService('ViewMaster'); // Fetch all base data // === 1. Workflow mapping const workflowIdMap: Record = {}; let transformRepo; transformRepo = workFlowRepo; const workflows = await transformRepo?.find({ where: { organization_id: -1, level_type: 'ORG', level_id: -1, }, }); for (const row of workflows) { const { id, ...rest } = row; const newWf = await this.workflowService.createEntity( { ...rest, organization_id, enterprise_id: organization_id, level_id: organization_id, entity_type: 'WRFW', status: statusValue, }, loggedInUser, ); // adding new entry for workflow level mapping if (!workflowLevelMappingRepo) continue; const newMapping = workflowLevelMappingRepo.create({ workflow_id: Number(newWf.id), mapped_level_id: organization_id.toString(), mapped_level_type: 'ORG', }); await workflowLevelMappingRepo.save(newMapping); workflowIdMap[id] = newWf.id; } // === 2. StageGroup mapping (and save workflow ref from template data!) const stageGroupIdMap: Record = {}; // Include mapping from old stageGroupId to old workflowId to help with stage->workflow logic later: const stageGroupToWorkflowMap: Record = {}; transformRepo = stageGroupRepo; const stageGroups = await transformRepo?.find({ where: { organization_id: -1, level_type: 'ORG', level_id: -1, }, }); for (const row of stageGroups) { const { id, workflow_id, ...rest } = row; const newSg = await this.stageGroupService.createEntity( { ...rest, workflow_id: workflowIdMap[workflow_id], organization_id, enterprise_id: organization_id, level_id: organization_id, entity_type: 'WFSG', status: statusValue, }, loggedInUser, ); stageGroupIdMap[id] = newSg.id; stageGroupToWorkflowMap[id] = workflow_id; } // === 3. Stage mapping — point to stageGroup and workflow const stageIdMap: Record = {}; const stageToStageGroupMap: Record = {}; transformRepo = stageRepo; const stages = await transformRepo?.find({ where: { organization_id: -1, level_type: 'ORG', level_id: -1, }, }); for (const row of stages) { const { id, stage_group_id, ...rest } = row; // Find the original parent workflow_id using the stageGroupToWorkflowMap const originalWorkflowId = stageGroupToWorkflowMap[stage_group_id]; const newStage = await this.stageService.createEntity( { ...rest, stage_group_id: stageGroupIdMap[stage_group_id], workflow_id: workflowIdMap[originalWorkflowId], // New workflow id! organization_id, enterprise_id: organization_id, level_id: organization_id, entity_type: 'WFS', status: statusValue, }, loggedInUser, ); stageIdMap[id] = newStage.id; stageToStageGroupMap[id] = stage_group_id; // maintain // step 1 find old stage_id in stage_action_mapper and get all actions_ids // step 2 search action in frm_wf_action table with those action_ids // step 3 create new action with new stage_id and new workflow_id // step 4 save new action if (!stageActionMappingRepo) continue; const stageIds = await stageActionMappingRepo.find({ where: { stage_id: id, }, }); const actionIds = stageIds.map((item) => item.action_id); let actions = [] as any[]; if (actionIds.length > 0) { if (!actionRepo) continue; actions = await actionRepo?.findByIds(actionIds); } else { // No actions to query actions = []; } console.log( `Found ${actions.length} actions for stage ${id} in workflow ${originalWorkflowId}`, ); // === 4. Action mapping — point to stage, stageGroup, workflow correctly for (const row of actions as any[]) { const { id, created_date, modified_date, workflow_id, ...rest } = row; const newWorkflowId = workflowIdMap[workflow_id]; // Step 1: Get the code of the old is_mandatory field const [oldIsMandatory] = await listMasterItemsRepo.find({ where: { id: rest.action_requirement }, }); // Step 2: Get all new 'ACRQ' list master items for the organization const newIsMandatoryList = await listMasterItemsRepo.find({ where: { organization_id: organization_id, listtype: 'ACRQ' }, }); console.log( `Populating action for stage ${newStage.id} in workflow ${newWorkflowId}`, ); console.log(`Old is_mandatory code: ${oldIsMandatory?.code}`); console.log(`New is_mandatory list:`, newIsMandatoryList); // Step 3: Find the matching new item with the same code const matchedNewMandatory = newIsMandatoryList.find( (item) => item.code === oldIsMandatory?.code, ); console.log(`Matched new mandatory item:`, matchedNewMandatory); if (!actionCategoryRepo) continue; const formActionCategory = await actionCategoryRepo.find({ where: { id: row.action_category, is_form: true }, }); //get view master form if (!viewMasterRepo) continue; const formViewMaster = await viewMasterRepo.find({ where: { code: 'LEAD_FORM', organization_id: organization_id }, }); // Step 4: Use the matched new item's id (if found) await this.actionService.createEntity( { ...rest, stage_id: newStage.id, workflow_id: newWorkflowId, organization_id, enterprise_id: organization_id, action_requirement: matchedNewMandatory?.id ?? null, level_id: organization_id, entity_type: 'WFA', form: formActionCategory.length > 0 ? formViewMaster[0]?.id : null, status: statusValue, }, loggedInUser, ); } } return { message: 'Workflow data populated successfully', status: 'success', }; } }