rez_core 2.2.148 → 2.2.150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/extensions.json +5 -0
- package/dist/module/meta/controller/view-master.controller.d.ts +3 -1
- package/dist/module/meta/controller/view-master.controller.js +4 -2
- package/dist/module/meta/controller/view-master.controller.js.map +1 -1
- package/dist/module/workflow/entity/action.entity.d.ts +1 -0
- package/dist/module/workflow/entity/action.entity.js +4 -0
- package/dist/module/workflow/entity/action.entity.js.map +1 -1
- package/dist/module/workflow/repository/stage-movement.repository.js +1 -1
- package/dist/module/workflow/service/task.service.js +2 -2
- package/dist/module/workflow/service/task.service.js.map +1 -1
- package/dist/module/workflow/service/workflow-meta.service.d.ts +5 -1
- package/dist/module/workflow/service/workflow-meta.service.js +168 -2
- package/dist/module/workflow/service/workflow-meta.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/meta/controller/view-master.controller.ts +4 -0
- package/src/module/workflow/entity/action.entity.ts +3 -0
- package/src/module/workflow/repository/stage-movement.repository.ts +1 -1
- package/src/module/workflow/service/task.service.ts +3 -3
- package/src/module/workflow/service/workflow-meta.service.ts +286 -0
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { log } from 'console';
|
|
1
2
|
import {
|
|
2
3
|
Controller,
|
|
3
4
|
Get,
|
|
@@ -24,7 +25,10 @@ export class ViewMasterController {
|
|
|
24
25
|
@Query('entity_type') entityType: string,
|
|
25
26
|
@Query('type') type: string,
|
|
26
27
|
@Res() res: Response,
|
|
28
|
+
@Req() req: Request & { user: any },
|
|
27
29
|
) {
|
|
30
|
+
const loggedInUser = req.user.userData;
|
|
31
|
+
|
|
28
32
|
try {
|
|
29
33
|
if (!entityType || !type) {
|
|
30
34
|
return res.status(HttpStatus.BAD_REQUEST).json({
|
|
@@ -189,7 +189,7 @@ export class StageMovementRepository {
|
|
|
189
189
|
ac.code AS action_category_code,
|
|
190
190
|
arm.form_id
|
|
191
191
|
FROM cr_wf_action a
|
|
192
|
-
|
|
192
|
+
LEFT JOIN cr_wf_stage_action_mapping m ON a.id = m.action_id
|
|
193
193
|
LEFT JOIN cr_wf_action_category ac ON a.action_category = ac.id
|
|
194
194
|
LEFT JOIN cr_wf_action_resources_mapping arm ON m.id = arm.stg_act_mapping_id
|
|
195
195
|
WHERE m.stage_id = ?
|
|
@@ -341,11 +341,11 @@ export class TaskService extends EntityServiceImpl {
|
|
|
341
341
|
body.action_id,
|
|
342
342
|
);
|
|
343
343
|
|
|
344
|
-
if (body.reason_code
|
|
344
|
+
if (body.reason_code || body.remark) {
|
|
345
345
|
await this.createSystemNote(
|
|
346
346
|
{
|
|
347
|
-
reason_code: body.reason_code
|
|
348
|
-
remark: body.remark,
|
|
347
|
+
reason_code: body.reason_code!,
|
|
348
|
+
remark: body.remark || '',
|
|
349
349
|
mapped_entity_id: body.mapped_entity_id,
|
|
350
350
|
stage_id: body.stage_id,
|
|
351
351
|
action_id: body.action_id,
|
|
@@ -10,6 +10,7 @@ import { ActionDataService } from './action-data.service';
|
|
|
10
10
|
import { TaskService } from './task.service';
|
|
11
11
|
import { ACTIVITY_CATEGORIES } from '../repository/activity-log.repository';
|
|
12
12
|
import { ActivityLogService } from './activity-log.service';
|
|
13
|
+
import { EntityModificationService } from './entity-modification.service';
|
|
13
14
|
|
|
14
15
|
@Injectable()
|
|
15
16
|
export class WorkflowMetaService extends EntityServiceImpl {
|
|
@@ -23,6 +24,8 @@ export class WorkflowMetaService extends EntityServiceImpl {
|
|
|
23
24
|
private readonly taskService: TaskService,
|
|
24
25
|
@Inject('ActivityLogService')
|
|
25
26
|
private readonly activityLogService: ActivityLogService,
|
|
27
|
+
@Inject('EntityModificationService')
|
|
28
|
+
private readonly modificationService: EntityModificationService,
|
|
26
29
|
) {
|
|
27
30
|
super();
|
|
28
31
|
}
|
|
@@ -151,6 +154,18 @@ export class WorkflowMetaService extends EntityServiceImpl {
|
|
|
151
154
|
mapped_entity_type,
|
|
152
155
|
);
|
|
153
156
|
|
|
157
|
+
await this.taskService.createSystemNote(
|
|
158
|
+
{
|
|
159
|
+
reason_code: firstStage.reason_code,
|
|
160
|
+
remark: firstStage.remark,
|
|
161
|
+
mapped_entity_id,
|
|
162
|
+
stage_id: firstStage.id,
|
|
163
|
+
action_id: firstStage.id,
|
|
164
|
+
stage_group_id: stageGroup.id,
|
|
165
|
+
},
|
|
166
|
+
loggedInUser,
|
|
167
|
+
);
|
|
168
|
+
|
|
154
169
|
return `Initialized workflow with first stage (Stage ID: ${firstStage.id}).`;
|
|
155
170
|
}
|
|
156
171
|
|
|
@@ -257,6 +272,16 @@ export class WorkflowMetaService extends EntityServiceImpl {
|
|
|
257
272
|
return 'No actions found for this stage.';
|
|
258
273
|
}
|
|
259
274
|
|
|
275
|
+
// check whether first action's action_category is owner_assignment and assignment_type is AUTO_ASSIGN
|
|
276
|
+
const firstAction = actions[0];
|
|
277
|
+
let actionCategory = await this.dataSource.query(
|
|
278
|
+
`SELECT code FROM cr_wf_action_category WHERE id = ${Number(firstAction.action_category)}`,
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
let assignmentType = await this.dataSource.query(
|
|
282
|
+
`SELECT value FROM cr_list_master_items WHERE id = ${Number(firstAction.assignment_type)}`,
|
|
283
|
+
);
|
|
284
|
+
|
|
260
285
|
// save in action data
|
|
261
286
|
await this.actionDataService.saveActionData(
|
|
262
287
|
actions,
|
|
@@ -272,5 +297,266 @@ export class WorkflowMetaService extends EntityServiceImpl {
|
|
|
272
297
|
mapped_entity_id,
|
|
273
298
|
mapped_entity_type,
|
|
274
299
|
);
|
|
300
|
+
|
|
301
|
+
if (
|
|
302
|
+
actionCategory[0]?.code == 'OWAS' &&
|
|
303
|
+
assignmentType[0]?.value == 'round_robin'
|
|
304
|
+
) {
|
|
305
|
+
console.log('Auto-assigning owner based on round-robin assignment type');
|
|
306
|
+
await this.assignLead(
|
|
307
|
+
loggedInUser,
|
|
308
|
+
mapped_entity_id,
|
|
309
|
+
mapped_entity_type,
|
|
310
|
+
stage_id,
|
|
311
|
+
actions,
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async updateLeadOwner(entityData, loggedInUser) {
|
|
317
|
+
let { lead_id, lead_owner, stage_id, entity_type } = entityData;
|
|
318
|
+
let updatedData = {
|
|
319
|
+
id: lead_id,
|
|
320
|
+
lead_owner: lead_owner,
|
|
321
|
+
entity_type: entity_type,
|
|
322
|
+
};
|
|
323
|
+
entityData = updatedData;
|
|
324
|
+
|
|
325
|
+
this.modificationService.logModification(
|
|
326
|
+
{
|
|
327
|
+
entity_type: 'ENMD',
|
|
328
|
+
mapped_entity_type: entity_type,
|
|
329
|
+
mapped_entity_id: lead_id,
|
|
330
|
+
attribute_key: 'lead_owner',
|
|
331
|
+
new_value: lead_owner,
|
|
332
|
+
old_value: entityData.lead_owner,
|
|
333
|
+
remarks: entityData.remarks,
|
|
334
|
+
reason_code: entityData.reason_code,
|
|
335
|
+
stage_id: stage_id,
|
|
336
|
+
action_id: entityData.action_id,
|
|
337
|
+
},
|
|
338
|
+
loggedInUser,
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
const leadData: any = await this.getEntityData(
|
|
342
|
+
'LEAD',
|
|
343
|
+
lead_id,
|
|
344
|
+
loggedInUser,
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
const unassignedListMasterItemData = await this.dataSource.query(
|
|
348
|
+
`SELECT name, id
|
|
349
|
+
FROM cr_list_master_items
|
|
350
|
+
WHERE listtype = "LEST" AND organization_id = ?
|
|
351
|
+
AND value IN (?, ?)`,
|
|
352
|
+
[loggedInUser.organization_id, 'unassigned', 'active'],
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
// Find the IDs explicitly
|
|
356
|
+
const unassignedId = unassignedListMasterItemData.find(
|
|
357
|
+
(item) => item.name.toLowerCase() === 'unassigned',
|
|
358
|
+
)?.id;
|
|
359
|
+
|
|
360
|
+
const activeId = unassignedListMasterItemData.find(
|
|
361
|
+
(item) => item.name.toLowerCase() === 'active',
|
|
362
|
+
)?.id;
|
|
363
|
+
|
|
364
|
+
// Use unassignedId for comparison
|
|
365
|
+
if (leadData?.lead_status === unassignedId) {
|
|
366
|
+
leadData.lead_status = activeId;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const result = await super.updateEntity(
|
|
370
|
+
{
|
|
371
|
+
...entityData,
|
|
372
|
+
status: leadData?.lead_status,
|
|
373
|
+
lead_status: leadData?.lead_status,
|
|
374
|
+
},
|
|
375
|
+
loggedInUser,
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
await this.dataSource.query(
|
|
379
|
+
`UPDATE cr_wf_action_data SET user_id =?
|
|
380
|
+
WHERE mapped_entity_id=?
|
|
381
|
+
AND mapped_entity_type = ?
|
|
382
|
+
AND stage_id = ?
|
|
383
|
+
AND (is_current = 'Y' OR is_current IS NULL)
|
|
384
|
+
`,
|
|
385
|
+
[lead_owner, lead_id, entity_type, stage_id],
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
await this.dataSource.query(
|
|
389
|
+
`UPDATE cr_lead_meeting SET user_id=?
|
|
390
|
+
WHERE stage_id = ?
|
|
391
|
+
AND lead_id = ?
|
|
392
|
+
AND (status='scheduled' OR status='rescheduled')
|
|
393
|
+
`,
|
|
394
|
+
[lead_owner, stage_id, lead_id],
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
const taskRows = await this.dataSource.query(
|
|
398
|
+
`SELECT id,status FROM cr_wf_task_data
|
|
399
|
+
WHERE mapped_entity_id = ?
|
|
400
|
+
AND mapped_entity_type = ?
|
|
401
|
+
AND stage_id = ?`,
|
|
402
|
+
[lead_id, entity_type, stage_id],
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
for (const task of taskRows) {
|
|
406
|
+
const statusRows = await this.dataSource.query(
|
|
407
|
+
`SELECT value FROM cr_list_master_items
|
|
408
|
+
WHERE id = ? AND organization_id = ?`,
|
|
409
|
+
[task.status, loggedInUser.organization_id],
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
const statusName = statusRows[0]?.value?.toLowerCase() || '';
|
|
413
|
+
if (
|
|
414
|
+
['todo', 'in_progress'].includes(statusName) ||
|
|
415
|
+
statusName === 'todo'
|
|
416
|
+
) {
|
|
417
|
+
await this.dataSource.query(
|
|
418
|
+
`UPDATE cr_wf_task_data SET user_id = ?, task_owner = ? WHERE id = ?`,
|
|
419
|
+
[lead_owner, lead_owner, task.id],
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const leadOwnerName = await this.dataSource.query(
|
|
425
|
+
`SELECT name FROM cr_user WHERE id = ?`,
|
|
426
|
+
[entityData?.lead_owner],
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
try {
|
|
430
|
+
const logData = {
|
|
431
|
+
mapped_entity_id: lead_id,
|
|
432
|
+
mapped_entity_type: 'LEAD',
|
|
433
|
+
title: 'Owner Assigned',
|
|
434
|
+
description: leadData?.lead_owner
|
|
435
|
+
? `${leadOwnerName[0]?.name} reassigned as Lead owner.`
|
|
436
|
+
: `${leadOwnerName[0]?.name} assigned as Lead owner.`,
|
|
437
|
+
action: 'assign',
|
|
438
|
+
category: ACTIVITY_CATEGORIES.ASSIGN,
|
|
439
|
+
appcode: loggedInUser.appcode,
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
await this.activityLogService.logActivity(logData, loggedInUser);
|
|
443
|
+
} catch (error) {
|
|
444
|
+
console.error(
|
|
445
|
+
'Failed to log activity for meeting:',
|
|
446
|
+
error?.message || error,
|
|
447
|
+
);
|
|
448
|
+
// Logging should not block main flow
|
|
449
|
+
}
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
async assignLead(
|
|
454
|
+
loggedInUser: UserData,
|
|
455
|
+
mapped_entity_id: number,
|
|
456
|
+
mapped_entity_type: string,
|
|
457
|
+
stage_id: number,
|
|
458
|
+
actions: any[],
|
|
459
|
+
): Promise<number> {
|
|
460
|
+
const { organization_id, level_id, level_type } = loggedInUser;
|
|
461
|
+
|
|
462
|
+
// 1) Get eligible owners (distinct + stable ordering)
|
|
463
|
+
const owners: Array<{ id: number }> = await this.dataSource.query(
|
|
464
|
+
`
|
|
465
|
+
SELECT DISTINCT u.id
|
|
466
|
+
FROM cr_user u
|
|
467
|
+
JOIN cr_user_role_mapping urm ON u.id = urm.user_id
|
|
468
|
+
JOIN cr_role r ON urm.role_id = r.id
|
|
469
|
+
JOIN cr_module_access ma ON ma.role_code = r.code
|
|
470
|
+
WHERE urm.organization_id = ?
|
|
471
|
+
AND urm.level_id = ?
|
|
472
|
+
AND urm.level_type = ?
|
|
473
|
+
AND urm.appcode = 'CRM'
|
|
474
|
+
AND ma.appcode = 'CRM'
|
|
475
|
+
AND ma.module_code = 'lead_crm_sch'
|
|
476
|
+
AND ma.access_flag = 1
|
|
477
|
+
AND ma.action_type = 'LEAD_OWNER'
|
|
478
|
+
ORDER BY u.id ASC
|
|
479
|
+
`,
|
|
480
|
+
[organization_id, Number(level_id), level_type],
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
if (!owners?.length) throw new Error('No eligible users found');
|
|
484
|
+
const userIds = owners.map((o) => Number(o.id)); // normalize to numbers
|
|
485
|
+
|
|
486
|
+
// 2) Find the last assigned *eligible* owner (use IN (...))
|
|
487
|
+
const placeholders = userIds.map(() => '?').join(',');
|
|
488
|
+
const lastRow: Array<{ lead_owner: number }> = await this.dataSource.query(
|
|
489
|
+
`
|
|
490
|
+
SELECT lead_owner
|
|
491
|
+
FROM crm_lead
|
|
492
|
+
WHERE organization_id = ?
|
|
493
|
+
AND level_id = ?
|
|
494
|
+
AND level_type = ?
|
|
495
|
+
AND lead_owner IN (${placeholders})
|
|
496
|
+
ORDER BY created_date DESC
|
|
497
|
+
LIMIT 1
|
|
498
|
+
`,
|
|
499
|
+
[organization_id, Number(level_id), level_type, ...userIds],
|
|
500
|
+
);
|
|
501
|
+
|
|
502
|
+
const lastAssigned = lastRow.length ? Number(lastRow[0].lead_owner) : null;
|
|
503
|
+
|
|
504
|
+
// 3) Compute next user in round-robin
|
|
505
|
+
const lastIdx = lastAssigned != null ? userIds.indexOf(lastAssigned) : -1;
|
|
506
|
+
const nextIdx = (lastIdx + 1) % userIds.length;
|
|
507
|
+
const nextUser = userIds[nextIdx];
|
|
508
|
+
|
|
509
|
+
//4) Update lead owner in the lead table
|
|
510
|
+
await this.dataSource.query(
|
|
511
|
+
`
|
|
512
|
+
UPDATE crm_lead
|
|
513
|
+
SET lead_owner = ?
|
|
514
|
+
WHERE organization_id = ?
|
|
515
|
+
AND level_id = ?
|
|
516
|
+
AND level_type = ?
|
|
517
|
+
AND lead_owner IS NULL
|
|
518
|
+
ORDER BY created_date ASC
|
|
519
|
+
LIMIT 1
|
|
520
|
+
`,
|
|
521
|
+
[nextUser, organization_id, Number(level_id), level_type],
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
console.log(`Assigning lead to user ID: ${nextUser}`);
|
|
525
|
+
|
|
526
|
+
const firstAction = actions[0];
|
|
527
|
+
|
|
528
|
+
// move task
|
|
529
|
+
await this.taskService.moveTask(loggedInUser, {
|
|
530
|
+
mapped_entity_type,
|
|
531
|
+
mapped_entity_id,
|
|
532
|
+
stage_id,
|
|
533
|
+
action_id: firstAction.id,
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// if it has only one action then move next stage
|
|
537
|
+
if (actions.length == 1) {
|
|
538
|
+
console.log(
|
|
539
|
+
'Only one action present and it is owner assignment. Moving to next stage.',
|
|
540
|
+
);
|
|
541
|
+
await this.moveToNextStage(
|
|
542
|
+
mapped_entity_type,
|
|
543
|
+
mapped_entity_id,
|
|
544
|
+
loggedInUser,
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// update lead owner status
|
|
549
|
+
await this.updateLeadOwner(
|
|
550
|
+
{
|
|
551
|
+
lead_id: mapped_entity_id,
|
|
552
|
+
lead_owner: nextUser,
|
|
553
|
+
stage_id: stage_id,
|
|
554
|
+
entity_type: mapped_entity_type,
|
|
555
|
+
action_id: firstAction.id,
|
|
556
|
+
},
|
|
557
|
+
loggedInUser,
|
|
558
|
+
);
|
|
559
|
+
|
|
560
|
+
return nextUser;
|
|
275
561
|
}
|
|
276
562
|
}
|