rez_core 2.2.81 → 2.2.83
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/dist/module/workflow/repository/activity-log.repository.d.ts +1 -1
- package/dist/module/workflow/repository/activity-log.repository.js +7 -3
- package/dist/module/workflow/repository/activity-log.repository.js.map +1 -1
- package/dist/module/workflow/repository/stage-group.repository.js +2 -17
- package/dist/module/workflow/repository/stage-group.repository.js.map +1 -1
- package/dist/module/workflow/service/activity-log.service.js +23 -15
- package/dist/module/workflow/service/activity-log.service.js.map +1 -1
- package/dist/module/workflow/service/stage-group.service.d.ts +4 -1
- package/dist/module/workflow/service/stage-group.service.js +38 -8
- package/dist/module/workflow/service/stage-group.service.js.map +1 -1
- package/dist/module/workflow/service/task.service.js +25 -19
- package/dist/module/workflow/service/task.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/src/module/workflow/repository/activity-log.repository.ts +7 -3
- package/src/module/workflow/repository/stage-group.repository.ts +2 -22
- package/src/module/workflow/service/activity-log.service.ts +27 -17
- package/src/module/workflow/service/stage-group.service.ts +60 -10
- package/src/module/workflow/service/task.service.ts +35 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rez_core",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.83",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "",
|
|
6
6
|
"private": false,
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"exceljs": "^4.4.0",
|
|
45
45
|
"handlebars": "^4.7.8",
|
|
46
46
|
"moment": "^2.30.1",
|
|
47
|
+
"moment-timezone": "^0.6.0",
|
|
47
48
|
"multer": "^1.4.5-lts.2",
|
|
48
49
|
"mysql2": "^3.12.0",
|
|
49
50
|
"nodemailer": "^7.0.5",
|
|
@@ -2,7 +2,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|
|
2
2
|
import { MediaDataService } from 'src/module/meta/service/media-data.service';
|
|
3
3
|
import { ActivityLog } from '../entity/activity-log.entity';
|
|
4
4
|
import { Repository } from 'typeorm';
|
|
5
|
-
import * as moment from 'moment
|
|
5
|
+
import * as moment from 'moment';
|
|
6
6
|
|
|
7
7
|
export const ACTIVITY_CATEGORIES = {
|
|
8
8
|
ASSIGN: 'ASSIGN',
|
|
@@ -15,7 +15,7 @@ export const ACTIVITY_CATEGORIES = {
|
|
|
15
15
|
STATUS: 'STATUS',
|
|
16
16
|
TASK: 'TASK',
|
|
17
17
|
LEAD: 'LEAD',
|
|
18
|
-
STAGEGROUP: '
|
|
18
|
+
STAGEGROUP: 'STAGE_GROUP',
|
|
19
19
|
} as const;
|
|
20
20
|
|
|
21
21
|
export type ActivityCategoryType = keyof typeof ACTIVITY_CATEGORIES;
|
|
@@ -104,8 +104,12 @@ export class ActivityLogRepository {
|
|
|
104
104
|
|
|
105
105
|
.getRawMany();
|
|
106
106
|
return result.map((row) => {
|
|
107
|
+
const formattedLabel = row.category
|
|
108
|
+
.toLowerCase() // stage_group
|
|
109
|
+
.replace(/_/g, ' ') // stage group
|
|
110
|
+
.replace(/\b\w/g, (char) => char.toUpperCase()); // Stage Group
|
|
107
111
|
return {
|
|
108
|
-
label:
|
|
112
|
+
label: formattedLabel,
|
|
109
113
|
value: row.category,
|
|
110
114
|
};
|
|
111
115
|
});
|
|
@@ -64,12 +64,8 @@ export class StageGroupRepository {
|
|
|
64
64
|
const stagesRaw = await this.dataSource.query(
|
|
65
65
|
`
|
|
66
66
|
SELECT
|
|
67
|
-
cr_wf_stage
|
|
68
|
-
eth_user_profile.name AS created_by_name,
|
|
69
|
-
eth_user_profile.profile_image AS profile_image
|
|
67
|
+
cr_wf_stage.*
|
|
70
68
|
FROM cr_wf_stage
|
|
71
|
-
LEFT JOIN eth_user_profile
|
|
72
|
-
ON cr_wf_stage.created_by = eth_user_profile.parent_id
|
|
73
69
|
WHERE cr_wf_stage.stage_group_id IN (${stageGroupIds.map(() => '?').join(',')})
|
|
74
70
|
AND cr_wf_stage.organization_id = ?
|
|
75
71
|
ORDER BY cr_wf_stage.sequence ASC
|
|
@@ -131,26 +127,10 @@ export class StageGroupRepository {
|
|
|
131
127
|
);
|
|
132
128
|
|
|
133
129
|
// Step 4: Add counts & profile to each stage
|
|
134
|
-
const stages = await Promise.all(
|
|
135
|
-
stagesRaw.map(async (stage) => {
|
|
136
|
-
const profileImageId = stage.profile_image;
|
|
137
|
-
let profile: any = null;
|
|
138
|
-
if (profileImageId) {
|
|
139
|
-
profile = await this.mediaDataService.getMediaDownloadUrl(
|
|
140
|
-
profileImageId,
|
|
141
|
-
loggedInUser,
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
return {
|
|
145
|
-
...stage,
|
|
146
|
-
profile, // enriched profile object
|
|
147
|
-
};
|
|
148
|
-
}),
|
|
149
|
-
);
|
|
150
130
|
|
|
151
131
|
// Step 5: Group stages by stage_group_id
|
|
152
132
|
const stageMap = new Map<number, any[]>();
|
|
153
|
-
for (const stage of
|
|
133
|
+
for (const stage of stagesRaw) {
|
|
154
134
|
const stageId = Number(stage.id); // ensure number
|
|
155
135
|
|
|
156
136
|
stage.task_count = taskCountMap.get(stageId) || 0;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Injectable } from '@nestjs/common';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ACTIVITY_CATEGORIES,
|
|
4
|
+
ActivityLogRepository,
|
|
5
|
+
} from '../repository/activity-log.repository';
|
|
3
6
|
import { ActivityLog } from '../entity/activity-log.entity';
|
|
4
7
|
import { log } from 'console';
|
|
5
8
|
import { EntityServiceImpl } from 'src/module/meta/service/entity-service-impl.service';
|
|
@@ -7,43 +10,50 @@ import { UserData } from 'src/module/user/entity/user.entity';
|
|
|
7
10
|
|
|
8
11
|
function enrichData(category: string, logData: any): any {
|
|
9
12
|
switch (category) {
|
|
10
|
-
case
|
|
11
|
-
logData.color = '#
|
|
13
|
+
case ACTIVITY_CATEGORIES.STAGE:
|
|
14
|
+
logData.color = '#06aed4';
|
|
12
15
|
logData.icon = 'stage';
|
|
13
16
|
break;
|
|
14
|
-
case
|
|
17
|
+
case ACTIVITY_CATEGORIES.INTERACTION:
|
|
15
18
|
logData.color = '#7a5af8';
|
|
16
19
|
logData.icon = 'interaction';
|
|
17
20
|
break;
|
|
18
|
-
case
|
|
21
|
+
case ACTIVITY_CATEGORIES.FORM:
|
|
19
22
|
logData.color = '#eaaa08';
|
|
20
23
|
logData.icon = 'form';
|
|
21
24
|
break;
|
|
22
|
-
case
|
|
25
|
+
case ACTIVITY_CATEGORIES.ASSIGN:
|
|
23
26
|
logData.color = '#16b364';
|
|
24
27
|
logData.icon = 'assign';
|
|
25
28
|
break;
|
|
26
|
-
case
|
|
27
|
-
logData.color = '#
|
|
29
|
+
case ACTIVITY_CATEGORIES.MEETING:
|
|
30
|
+
logData.color = '#7a5af8';
|
|
28
31
|
logData.icon = 'meeting';
|
|
29
32
|
break;
|
|
30
|
-
case
|
|
31
|
-
logData.color = '#
|
|
33
|
+
case ACTIVITY_CATEGORIES.PROCESS:
|
|
34
|
+
logData.color = '#06aed4';
|
|
32
35
|
logData.icon = 'process';
|
|
33
36
|
break;
|
|
34
|
-
case
|
|
35
|
-
logData.color = '#
|
|
37
|
+
case ACTIVITY_CATEGORIES.STATUS:
|
|
38
|
+
logData.color = '#06aed4';
|
|
36
39
|
logData.icon = 'status';
|
|
37
40
|
break;
|
|
38
|
-
case
|
|
39
|
-
logData.color = '#
|
|
41
|
+
case ACTIVITY_CATEGORIES.TASK:
|
|
42
|
+
logData.color = '#f63d68';
|
|
40
43
|
logData.icon = 'task';
|
|
41
44
|
break;
|
|
42
|
-
case
|
|
43
|
-
logData.color = '#
|
|
45
|
+
case ACTIVITY_CATEGORIES.LEAD:
|
|
46
|
+
logData.color = '#16b364';
|
|
44
47
|
logData.icon = 'lead';
|
|
45
48
|
break;
|
|
46
|
-
|
|
49
|
+
case ACTIVITY_CATEGORIES.ASSESSMENT:
|
|
50
|
+
logData.color = '#f63d68';
|
|
51
|
+
logData.icon = 'assessment';
|
|
52
|
+
break;
|
|
53
|
+
case ACTIVITY_CATEGORIES.STAGEGROUP:
|
|
54
|
+
logData.color = '#06aed4';
|
|
55
|
+
logData.icon = 'stage_group';
|
|
56
|
+
break;
|
|
47
57
|
default:
|
|
48
58
|
logData.color = '#ff0000';
|
|
49
59
|
logData.icon = 'DEFAULT';
|
|
@@ -8,7 +8,8 @@ import { DataSource, Repository } from 'typeorm';
|
|
|
8
8
|
import { WorkflowLevelMappingEntity } from '../entity/workflow-level-mapping.entity';
|
|
9
9
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
10
10
|
import { StageMovementData } from '../entity/stage-movement-data.entity';
|
|
11
|
-
import * as moment from 'moment
|
|
11
|
+
import * as moment from 'moment';
|
|
12
|
+
import { MediaDataService } from 'src/module/meta/service/media-data.service';
|
|
12
13
|
|
|
13
14
|
@Injectable()
|
|
14
15
|
export class StageGroupService extends EntityServiceImpl {
|
|
@@ -21,6 +22,7 @@ export class StageGroupService extends EntityServiceImpl {
|
|
|
21
22
|
private readonly workflowLevelMappingRepo: Repository<WorkflowLevelMappingEntity>,
|
|
22
23
|
@InjectRepository(StageMovementData)
|
|
23
24
|
private readonly stageMovementRepo: Repository<StageMovementData>,
|
|
25
|
+
private readonly mediaDataService: MediaDataService,
|
|
24
26
|
) {
|
|
25
27
|
super();
|
|
26
28
|
}
|
|
@@ -55,22 +57,21 @@ export class StageGroupService extends EntityServiceImpl {
|
|
|
55
57
|
|
|
56
58
|
if (!workflowLevelMapping) return null;
|
|
57
59
|
|
|
58
|
-
// 3
|
|
60
|
+
// 3) Lead status (parameterized)
|
|
59
61
|
let leadStatus: string | null = null;
|
|
60
62
|
const leadData = await this.dataSource.query(
|
|
61
|
-
`SELECT lead_status FROM crm_lead WHERE id =
|
|
63
|
+
`SELECT lead_status FROM crm_lead WHERE id = ?`,
|
|
64
|
+
[lead_id],
|
|
62
65
|
);
|
|
63
|
-
|
|
64
|
-
if (leadData.length > 0) {
|
|
66
|
+
if (leadData.length > 0 && leadData[0].lead_status != null) {
|
|
65
67
|
const leadStatusResolved = await this.dataSource.query(
|
|
66
|
-
`SELECT name FROM cr_list_master_items WHERE id =
|
|
68
|
+
`SELECT name FROM cr_list_master_items WHERE id = ? AND organization_id = ?`,
|
|
69
|
+
[leadData[0].lead_status, loggedInUser.organization_id],
|
|
67
70
|
);
|
|
68
|
-
|
|
69
71
|
if (leadStatusResolved.length > 0) {
|
|
70
72
|
leadStatus = leadStatusResolved[0].name;
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
|
-
|
|
74
75
|
// 4. Fetch stage groups & hierarchy
|
|
75
76
|
const stageGroupAndStageHierarchy =
|
|
76
77
|
(await this.stageGroupRepository.getAllStageGroupAndStageHierarchy(
|
|
@@ -108,9 +109,14 @@ export class StageGroupService extends EntityServiceImpl {
|
|
|
108
109
|
|
|
109
110
|
let foundInProgressGroup = false;
|
|
110
111
|
|
|
112
|
+
const userCache = new Map<
|
|
113
|
+
number,
|
|
114
|
+
{ created_by_name: string | null; profile: any }
|
|
115
|
+
>();
|
|
116
|
+
|
|
111
117
|
// 7. Loop & apply IST conversions
|
|
112
118
|
for (const group of stageGroupAndStageHierarchy) {
|
|
113
|
-
|
|
119
|
+
const stagePromises = (group.stages || []).map(async (stage) => {
|
|
114
120
|
const movement = stageMovementMap.get(Number(stage.id));
|
|
115
121
|
|
|
116
122
|
if (movement) {
|
|
@@ -129,6 +135,17 @@ export class StageGroupService extends EntityServiceImpl {
|
|
|
129
135
|
movement.start_date,
|
|
130
136
|
movement.end_date ?? new Date(),
|
|
131
137
|
);
|
|
138
|
+
|
|
139
|
+
if (movement.current_user_id) {
|
|
140
|
+
if (!userCache.has(movement.current_user_id)) {
|
|
141
|
+
const user = await this.getUserNameAndProfilePic(
|
|
142
|
+
movement.current_user_id,
|
|
143
|
+
loggedInUser,
|
|
144
|
+
);
|
|
145
|
+
userCache.set(movement.current_user_id, user);
|
|
146
|
+
}
|
|
147
|
+
Object.assign(stage, userCache.get(movement.current_user_id));
|
|
148
|
+
}
|
|
132
149
|
} else {
|
|
133
150
|
stage.is_current = false;
|
|
134
151
|
stage.is_done = false;
|
|
@@ -136,12 +153,15 @@ export class StageGroupService extends EntityServiceImpl {
|
|
|
136
153
|
stage.end_time = null;
|
|
137
154
|
stage.time_spent = null;
|
|
138
155
|
stage.created_by_name = null;
|
|
156
|
+
stage.profile = null;
|
|
139
157
|
}
|
|
140
158
|
|
|
141
159
|
if (leadStatus) {
|
|
142
160
|
stage.lead_status = leadStatus;
|
|
143
161
|
}
|
|
144
|
-
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
await Promise.all(stagePromises);
|
|
145
165
|
|
|
146
166
|
if (group.stages.length === 0) {
|
|
147
167
|
group.stage_group_status = 'TODO';
|
|
@@ -166,6 +186,36 @@ export class StageGroupService extends EntityServiceImpl {
|
|
|
166
186
|
return stageGroupAndStageHierarchy;
|
|
167
187
|
}
|
|
168
188
|
|
|
189
|
+
async getUserNameAndProfilePic(
|
|
190
|
+
userId: number,
|
|
191
|
+
loggedInUser: UserData,
|
|
192
|
+
): Promise<any> {
|
|
193
|
+
const user = await this.dataSource.query(
|
|
194
|
+
`SELECT eth_user_profile.name AS created_by_name,
|
|
195
|
+
eth_user_profile.profile_image AS profile_image
|
|
196
|
+
FROM eth_user_profile
|
|
197
|
+
WHERE eth_user_profile.id = ?;`,
|
|
198
|
+
[userId],
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
if (user.length === 0) return null;
|
|
202
|
+
|
|
203
|
+
let profileImageId = user[0].profile_image;
|
|
204
|
+
let profile: any = null;
|
|
205
|
+
|
|
206
|
+
if (profileImageId) {
|
|
207
|
+
profile = await this.mediaDataService.getMediaDownloadUrl(
|
|
208
|
+
profileImageId,
|
|
209
|
+
loggedInUser,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
created_by_name: user[0].created_by_name,
|
|
215
|
+
profile: profile,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
169
219
|
async calculateTimeSpent(
|
|
170
220
|
start: Date | string,
|
|
171
221
|
end?: Date | string,
|
|
@@ -85,8 +85,17 @@ export class TaskService extends EntityServiceImpl {
|
|
|
85
85
|
entityData.is_completed = isCompletedStatus;
|
|
86
86
|
entityData.is_done = isCompletedStatus;
|
|
87
87
|
|
|
88
|
+
const isMandatory =
|
|
89
|
+
String(entityData.is_mandatory).toLowerCase() === 'true' ||
|
|
90
|
+
entityData.is_mandatory === true ||
|
|
91
|
+
entityData.is_mandatory === 1 ||
|
|
92
|
+
entityData.is_mandatory === '1';
|
|
93
|
+
|
|
88
94
|
const updatedEntity = await super.updateEntity(
|
|
89
|
-
|
|
95
|
+
{
|
|
96
|
+
...entityData,
|
|
97
|
+
is_mandatory: isMandatory,
|
|
98
|
+
},
|
|
90
99
|
loggedInUser,
|
|
91
100
|
appcode,
|
|
92
101
|
);
|
|
@@ -213,33 +222,36 @@ export class TaskService extends EntityServiceImpl {
|
|
|
213
222
|
LEFT JOIN cr_user u ON t.created_by = u.id
|
|
214
223
|
LEFT JOIN cr_user u2 ON t.task_owner = u2.id
|
|
215
224
|
WHERE ${whereClauses.join(' AND ')}
|
|
216
|
-
ORDER BY t.
|
|
225
|
+
ORDER BY t.created_date DESC
|
|
217
226
|
`;
|
|
218
227
|
|
|
219
228
|
const taskData = await this.dataSource.query(sql, params);
|
|
220
229
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
230
|
+
if (taskData.length === 0) {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Fetch all TKST statuses in a single query
|
|
235
|
+
const taskStatusQuery = `
|
|
236
|
+
SELECT id, name
|
|
237
|
+
FROM cr_list_master_items
|
|
238
|
+
WHERE organization_id = ?
|
|
239
|
+
AND listtype = 'TKST'
|
|
240
|
+
`;
|
|
241
|
+
const taskAllStatus = await this.dataSource.query(taskStatusQuery, [
|
|
242
|
+
loggedInUser.organization_id,
|
|
243
|
+
]);
|
|
227
244
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
task.status,
|
|
239
|
-
loggedInUser.organization_id,
|
|
240
|
-
]);
|
|
241
|
-
|
|
242
|
-
task.task_status = statusRow?.name || null;
|
|
245
|
+
// Build a hash map { id → name }
|
|
246
|
+
const statusMap = new Map(
|
|
247
|
+
taskAllStatus.map((row) => [String(row.id), row.name]),
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
// Assign task_status using the map
|
|
251
|
+
for (const task of taskData) {
|
|
252
|
+
task.task_status = task.status
|
|
253
|
+
? statusMap.get(String(task.status)) || null
|
|
254
|
+
: null;
|
|
243
255
|
}
|
|
244
256
|
|
|
245
257
|
// Normalize is_mandatory to '0'/'1' as string
|