rez_core 2.2.18 → 2.2.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "2.2.18",
3
+ "version": "2.2.21",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -54,15 +54,23 @@ export class OtpController {
54
54
  return { message: 'OTP verified successfully!', success: true };
55
55
  }
56
56
 
57
- @Get('send-mail')
57
+ @Post('send-mail')
58
58
  @HttpCode(HttpStatus.OK)
59
- async sendMail(@Query('email') email: string) {
59
+ async sendMail(
60
+ @Body()
61
+ body: {
62
+ to: string;
63
+ subject: string;
64
+ templateCode: number;
65
+ payload: any;
66
+ },
67
+ ) {
60
68
  // return await this.emailService.sendEmail(email, 'Harry', '123456');
61
69
  return await this.emailService.sendEmailWithDynamicTemplate(
62
- email,
63
- 'Sample OTP',
64
- '<div style="font-family: Arial, sans-serif; padding: 20px; background-color: #f7f9fc; color: #333;"> <div style="max-width: 600px; margin: auto; background-color: #ffffff; padding: 30px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);"> <h2 style="color: #2c3e50;">Hello {{name}},</h2> <p style="font-size: 16px; line-height: 1.6;"> We received a request to verify your email address using a one-time password (OTP). </p> <p style="font-size: 16px; line-height: 1.6;"> Please use the following OTP to complete your action: </p> <div style="text-align: center; margin: 20px 0;"> <span style="font-size: 24px; font-weight: bold; color: #2e86de;">{{otp}}</span> </div> <p style="font-size: 16px; line-height: 1.6;"> This OTP is valid for the next 10 minutes. If you did not request this, please ignore this email. </p> <p style="font-size: 16px; line-height: 1.6;"> Regards,<br/> <strong>Your Company Team</strong> </p> <hr style="margin-top: 30px;"/> <p style="font-size: 12px; color: #999;"> This is an automated message, please do not reply to this email. </p> </div> </div>',
65
- { name: 'Harsh', otp: '123456' },
70
+ body.to,
71
+ body.subject,
72
+ body.templateCode,
73
+ body.payload,
66
74
  );
67
75
  }
68
76
  }
@@ -1,10 +1,14 @@
1
1
  import { Injectable } from '@nestjs/common';
2
2
  import { MailerService } from '@nestjs-modules/mailer';
3
3
  import * as Handlebars from 'handlebars';
4
+ import { DataSource } from 'typeorm';
4
5
 
5
6
  @Injectable()
6
7
  export class EmailService {
7
- constructor(private readonly mailerService: MailerService) {}
8
+ constructor(
9
+ private readonly mailerService: MailerService,
10
+ private readonly datasource: DataSource,
11
+ ) {}
8
12
 
9
13
  async sendEmail(email, name: string, otp: string) {
10
14
  this.mailerService
@@ -24,9 +28,22 @@ export class EmailService {
24
28
  async sendEmailWithDynamicTemplate(
25
29
  email: string,
26
30
  subject: string,
27
- templateString: string,
31
+ templateCode: number,
28
32
  context?: any,
29
33
  ) {
34
+ // retrieve the rich_text from the database table cr_wf_comm_template for the given templateCode
35
+
36
+ const template = await this.datasource
37
+ .getRepository('cr_wf_comm_template')
38
+ .findOne({ where: { code: templateCode } });
39
+
40
+ if (!template) {
41
+ throw new Error(`Template with code ${templateCode} not found`);
42
+ }
43
+
44
+ // Compile the template string with Handlebars
45
+ const templateString = template.rich_text || '';
46
+
30
47
  const compiled = Handlebars.compile(templateString);
31
48
  const htmlContent = compiled(context);
32
49
 
@@ -20,4 +20,7 @@ export class ActionResourcesMapping extends BaseEntity {
20
20
 
21
21
  @Column({ type: 'varchar', nullable: true })
22
22
  form_id: string;
23
+
24
+ @Column({ type: 'int', nullable: true })
25
+ stg_act_mapping_id: number;
23
26
  }
@@ -26,13 +26,23 @@ export class ActionService extends EntityServiceImpl {
26
26
  return null;
27
27
  }
28
28
 
29
- const template = await this.dataSource.query(
30
- `SELECT template_code FROM cr_wf_action_template_mapping WHERE stg_act_mapping_id =
29
+ const result = await this.dataSource.query(
30
+ `SELECT template_code, form_id FROM cr_wf_action_resources_mapping WHERE stg_act_mapping_id =
31
31
  (SELECT id FROM cr_wf_stage_action_mapping WHERE action_id = ? AND entity_type = 'STGM')`,
32
32
  [actionData.id],
33
33
  );
34
34
 
35
- return { ...actionData, template: template.map((t) => t.template_code) };
35
+ const templates = result
36
+ .filter((t) => t.template_code !== null)
37
+ .map((t) => t.template_code);
38
+
39
+ const form = result.find((f) => f.form_id !== null);
40
+
41
+ return {
42
+ ...actionData,
43
+ template: templates,
44
+ form: form?.form_id ?? null,
45
+ };
36
46
  }
37
47
 
38
48
  async createEntity(
@@ -61,21 +71,9 @@ export class ActionService extends EntityServiceImpl {
61
71
  // Step 3: Template mapping (existing)
62
72
  if (Array.isArray(actionData.template) && actionData.template.length > 0) {
63
73
  for (const templateCode of actionData.template) {
64
- const actionTemplateMapping = {
65
- stg_act_mapping_id: stageActionMappingData.id,
66
- template_code: templateCode,
67
- entity_type: 'ATMP',
68
- } as any;
69
-
70
- await super.createEntity(
71
- actionTemplateMapping,
72
- loggedInUser,
73
- manager,
74
- appcode,
75
- );
76
-
77
74
  // ➕ Step 4: Resource mapping for template
78
75
  const resourceMapping = {
76
+ stg_act_mapping_id: stageActionMappingData.id,
79
77
  template_code: templateCode,
80
78
  type: 'template',
81
79
  entity_type: 'ARMS',
@@ -89,6 +87,7 @@ export class ActionService extends EntityServiceImpl {
89
87
  if (actionData.form && actionData.form.length > 0) {
90
88
  for (const formId of actionData.form) {
91
89
  const resourceMapping = {
90
+ stg_act_mapping_id: stageActionMappingData.id,
92
91
  form_id: formId,
93
92
  type: 'form',
94
93
  entity_type: 'ARMS',
@@ -108,10 +107,12 @@ export class ActionService extends EntityServiceImpl {
108
107
  console.log('entityData', entityData);
109
108
 
110
109
  // Extract template from entityData, keep the rest for ActionEntity
111
- const { template, stage_id, ...actionData } = entityData as ActionEntity & {
112
- template?: number[];
113
- stage_id?: string;
114
- };
110
+ const { template, stage_id, form, ...actionData } =
111
+ entityData as ActionEntity & {
112
+ template?: number[];
113
+ stage_id?: string;
114
+ form?: number;
115
+ };
115
116
 
116
117
  // Pass only actionData (without template) to super.updateEntity
117
118
  let action = await super.updateEntity({ ...actionData }, loggedInUser);
@@ -140,7 +141,7 @@ export class ActionService extends EntityServiceImpl {
140
141
 
141
142
  // delete existing template mappings for this action
142
143
  await this.dataSource.query(
143
- `DELETE FROM cr_wf_action_template_mapping WHERE stg_act_mapping_id = ?`,
144
+ `DELETE FROM cr_wf_action_resources_mapping WHERE stg_act_mapping_id = ? AND type = 'template'`,
144
145
  [stageActionMappingData.id],
145
146
  );
146
147
 
@@ -150,16 +151,32 @@ export class ActionService extends EntityServiceImpl {
150
151
  const templateCode = template[i];
151
152
 
152
153
  // Create Action-Template Mapping
153
- const actionTemplateMapping = {
154
+ const resourceMapping = {
154
155
  stg_act_mapping_id: stageActionMappingData.id,
155
156
  template_code: templateCode,
156
- entity_type: 'ATMP',
157
+ type: 'template',
158
+ entity_type: 'ARMS',
157
159
  } as any;
158
160
 
159
- await super.createEntity(actionTemplateMapping, loggedInUser);
161
+ await super.createEntity(resourceMapping, loggedInUser);
160
162
  }
161
163
  }
162
164
 
165
+ await this.dataSource.query(
166
+ `DELETE FROM cr_wf_action_resources_mapping WHERE stg_act_mapping_id = ? AND type = 'form'`,
167
+ [stageActionMappingData.id],
168
+ );
169
+
170
+ if (form) {
171
+ const resourceMapping = {
172
+ stg_act_mapping_id: stageActionMappingData.id,
173
+ form_id: form,
174
+ type: 'form',
175
+ entity_type: 'ARMS',
176
+ } as any;
177
+
178
+ await super.createEntity(resourceMapping, loggedInUser);
179
+ }
163
180
  return action; // Return the action entity instead of actionData
164
181
  }
165
182
 
@@ -138,6 +138,13 @@ export class PopulateWorkflowService extends EntityServiceImpl {
138
138
  },
139
139
  loggedInUser,
140
140
  );
141
+
142
+ // adding new entry for workflow level mapping
143
+ await this.dataSource.query(
144
+ `INSERT INTO cr_workflow_level_mapping (workflow_id, mapped_level_id, mapped_level_type) VALUES (?, ?, ?)`,
145
+ [newWf.id, organization_id, 'ORG'],
146
+ );
147
+
141
148
  workflowIdMap[id] = newWf.id;
142
149
  }
143
150
 
@@ -205,18 +212,50 @@ export class PopulateWorkflowService extends EntityServiceImpl {
205
212
  actions = [];
206
213
  }
207
214
 
215
+ console.log(
216
+ `Found ${actions.length} actions for stage ${id} in workflow ${originalWorkflowId}`,
217
+ );
218
+
208
219
  // === 4. Action mapping — point to stage, stageGroup, workflow correctly
209
220
  for (const row of actions as any[]) {
210
221
  const { id, created_date, modified_date, workflow_id, ...rest } = row;
211
222
 
212
223
  const newWorkflowId = workflowIdMap[workflow_id];
213
224
 
225
+ // Step 1: Get the code of the old is_mandatory field
226
+ const [oldIsMandatory] = await this.dataSource.query(
227
+ `SELECT code FROM cr_list_master_items WHERE id = ?`,
228
+ [rest.action_requirement],
229
+ );
230
+
231
+ // Step 2: Get all new 'ACRQ' list master items for the organization
232
+ const newIsMandatoryList = await this.dataSource.query(
233
+ `SELECT id, code FROM cr_list_master_items WHERE organization_id = ? AND listtype = 'ACRQ'`,
234
+ [organization_id],
235
+ );
236
+
237
+ console.log(
238
+ `Populating action for stage ${newStage.id} in workflow ${newWorkflowId}`,
239
+ );
240
+
241
+ console.log(`Old is_mandatory code: ${oldIsMandatory?.code}`);
242
+ console.log(`New is_mandatory list:`, newIsMandatoryList);
243
+
244
+ // Step 3: Find the matching new item with the same code
245
+ const matchedNewMandatory = newIsMandatoryList.find(
246
+ (item) => item.code === oldIsMandatory?.code,
247
+ );
248
+
249
+ console.log(`Matched new mandatory item:`, matchedNewMandatory);
250
+
251
+ // Step 4: Use the matched new item's id (if found)
214
252
  await this.actionService.createEntity(
215
253
  {
216
254
  ...rest,
217
255
  stage_id: newStage.id,
218
256
  workflow_id: newWorkflowId,
219
257
  organization_id,
258
+ action_requirement: matchedNewMandatory?.id ?? null,
220
259
  level_id: organization_id,
221
260
  entity_type: 'ACTN',
222
261
  },