rez_core 5.0.295 → 5.0.296

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.
Files changed (26) hide show
  1. package/dist/module/meta/service/media-data.service.js +108 -38
  2. package/dist/module/meta/service/media-data.service.js.map +1 -1
  3. package/dist/module/workflow-automation/service/schedule-handler.service.d.ts +2 -2
  4. package/dist/module/workflow-automation/service/schedule-handler.service.js +18 -22
  5. package/dist/module/workflow-automation/service/schedule-handler.service.js.map +1 -1
  6. package/dist/module/workflow-schedule/interfaces/schedule-job-data.interface.d.ts +7 -8
  7. package/dist/module/workflow-schedule/processors/schedule.processor.d.ts +2 -0
  8. package/dist/module/workflow-schedule/processors/schedule.processor.js +115 -19
  9. package/dist/module/workflow-schedule/processors/schedule.processor.js.map +1 -1
  10. package/dist/module/workflow-schedule/service/workflow-schedule.service.js +14 -16
  11. package/dist/module/workflow-schedule/service/workflow-schedule.service.js.map +1 -1
  12. package/dist/tsconfig.build.tsbuildinfo +1 -1
  13. package/package.json +1 -1
  14. package/src/module/meta/service/media-data.service.ts +142 -40
  15. package/src/module/workflow-automation/service/schedule-handler.service.ts +19 -27
  16. package/src/module/workflow-schedule/interfaces/schedule-job-data.interface.ts +7 -8
  17. package/src/module/workflow-schedule/processors/schedule.processor.ts +156 -156
  18. package/src/module/workflow-schedule/service/workflow-schedule.service.ts +14 -16
  19. package/src/resources/dev.properties.yaml +0 -31
  20. package/src/resources/local.properties.yaml +0 -27
  21. package/src/resources/uat.properties.yaml +0 -31
  22. package/.idea/250218_ether_core.iml +0 -12
  23. package/.idea/codeStyles/Project.xml +0 -59
  24. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  25. package/.idea/modules.xml +0 -8
  26. package/.idea/vcs.xml +0 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "5.0.295",
3
+ "version": "5.0.296",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -46,6 +46,24 @@ export class MediaDataService extends EntityServiceImpl {
46
46
  if (!fileName || !mappedAttributeKey) {
47
47
  return null;
48
48
  }
49
+
50
+ // Validate AWS configuration
51
+ if (!this.s3AccessKeyID || !this.s3AccessKeySecret) {
52
+ throw new Error(
53
+ 'AWS credentials not configured. Please check AWS_ACCESS_KEY_ID and AWS_SECRET_KEY in configuration.',
54
+ );
55
+ }
56
+ if (!this.bucketName) {
57
+ throw new Error(
58
+ 'S3 bucket name not configured. Please check BUCKET_NAME in configuration.',
59
+ );
60
+ }
61
+ if (!this.s3Region) {
62
+ throw new Error(
63
+ 'AWS region not configured. Please check AWS_REGION in configuration.',
64
+ );
65
+ }
66
+
49
67
  const ext = fileName.split('.').pop()?.toLowerCase() ?? '';
50
68
 
51
69
  const id = uuidv4();
@@ -61,32 +79,45 @@ export class MediaDataService extends EntityServiceImpl {
61
79
 
62
80
  const s3Key = `${s3Path}/${id}.${ext}`;
63
81
 
64
- const uploadUrl = await this.s3.getSignedUrlPromise('putObject', {
65
- Bucket: this.bucketName,
66
- Key: s3Key,
67
- Expires: 60 * 5, // URL valid for 5 mins
68
- ContentType: this.getContentType(ext),
69
- });
82
+ try {
83
+ const uploadUrl = await this.s3.getSignedUrlPromise('putObject', {
84
+ Bucket: this.bucketName,
85
+ Key: s3Key,
86
+ Expires: 60 * 5, // URL valid for 5 mins
87
+ ContentType: this.getContentType(ext),
88
+ });
70
89
 
71
- const mediaData = new MediaData();
72
- mediaData.file_name = fileName;
73
- mediaData.mapped_attribute_key = mappedAttributeKey;
74
- mediaData.status = STATUS_PENDING;
75
- if (mappedEntityType) {
76
- mediaData.mapped_entity_type = mappedEntityType;
77
- }
78
- if (mappedEntityId) {
79
- mediaData.mapped_entity_id = mappedEntityId;
80
- }
81
- mediaData.media_url = s3Key;
90
+ const mediaData = new MediaData();
91
+ mediaData.file_name = fileName;
92
+ mediaData.mapped_attribute_key = mappedAttributeKey;
93
+ mediaData.status = STATUS_PENDING;
94
+ if (mappedEntityType) {
95
+ mediaData.mapped_entity_type = mappedEntityType;
96
+ }
97
+ if (mappedEntityId) {
98
+ mediaData.mapped_entity_id = mappedEntityId;
99
+ }
100
+ mediaData.media_url = s3Key;
82
101
 
83
- //INSERT RECORD IN DOC TABLE
84
- const savedEntity = await super.createEntity(mediaData, loggedInUser);
102
+ //INSERT RECORD IN DOC TABLE
103
+ const savedEntity = await super.createEntity(mediaData, loggedInUser);
85
104
 
86
- if (savedEntity) {
87
- return { id: savedEntity.id, path: s3Key, uploadUrl };
105
+ if (savedEntity) {
106
+ return { id: savedEntity.id, path: s3Key, uploadUrl };
107
+ }
108
+ return null;
109
+ } catch (error) {
110
+ console.error('Error generating upload URL:', error);
111
+ console.error('Error details:', {
112
+ message: error.message,
113
+ code: error.code,
114
+ statusCode: error.statusCode,
115
+ bucketName: this.bucketName,
116
+ region: this.s3Region,
117
+ hasCredentials: !!(this.s3AccessKeyID && this.s3AccessKeySecret),
118
+ });
119
+ throw new Error(`Failed to generate upload URL: ${error.message}`);
88
120
  }
89
- return null;
90
121
  }
91
122
 
92
123
  async findByAttributeKeyAndMappedEntityIdAndMappedEntityType(
@@ -147,21 +178,51 @@ export class MediaDataService extends EntityServiceImpl {
147
178
  // New method to get the signed URL for the media (download link)
148
179
  async getMediaDownloadUrl(id: number, loggedInUser, expiresIn?: number) {
149
180
  try {
181
+ // Validate AWS configuration
182
+ if (!this.s3AccessKeyID || !this.s3AccessKeySecret) {
183
+ throw new Error(
184
+ 'AWS credentials not configured. Please check AWS_ACCESS_KEY_ID and AWS_SECRET_KEY in configuration.',
185
+ );
186
+ }
187
+ if (!this.bucketName) {
188
+ throw new Error(
189
+ 'S3 bucket name not configured. Please check BUCKET_NAME in configuration.',
190
+ );
191
+ }
192
+ if (!this.s3Region) {
193
+ throw new Error(
194
+ 'AWS region not configured. Please check AWS_REGION in configuration.',
195
+ );
196
+ }
197
+
150
198
  const entityData = await this.getEntityData(
151
199
  ENTITYTYPE_MEDIA,
152
200
  id,
153
201
  loggedInUser,
154
202
  );
155
203
  const mediaData = entityData as MediaData;
204
+
205
+ if (!mediaData || !mediaData.media_url) {
206
+ throw new Error(`Media data not found or invalid for id: ${id}`);
207
+ }
208
+
156
209
  let fileSize: number | undefined;
157
210
  if (this.bucketName) {
158
- const head = await this.s3
159
- .headObject({
160
- Bucket: this.bucketName,
161
- Key: mediaData.media_url,
162
- })
163
- .promise();
164
- fileSize = head.ContentLength;
211
+ try {
212
+ const head = await this.s3
213
+ .headObject({
214
+ Bucket: this.bucketName,
215
+ Key: mediaData.media_url,
216
+ })
217
+ .promise();
218
+ fileSize = head.ContentLength;
219
+ } catch (headError) {
220
+ console.error(
221
+ `Error checking file in S3 bucket '${this.bucketName}' with key '${mediaData.media_url}':`,
222
+ headError.message,
223
+ );
224
+ // Continue even if headObject fails - the file might still be accessible
225
+ }
165
226
  }
166
227
 
167
228
  const signedUrl = await this.s3.getSignedUrlPromise('getObject', {
@@ -179,12 +240,37 @@ export class MediaDataService extends EntityServiceImpl {
179
240
  };
180
241
  } catch (error) {
181
242
  console.error('Error generating signed URL for media:', error);
182
- throw new Error('Failed to generate signed URL');
243
+ console.error('Error details:', {
244
+ message: error.message,
245
+ code: error.code,
246
+ statusCode: error.statusCode,
247
+ bucketName: this.bucketName,
248
+ region: this.s3Region,
249
+ hasCredentials: !!(this.s3AccessKeyID && this.s3AccessKeySecret),
250
+ });
251
+ throw new Error(`Failed to generate signed URL: ${error.message}`);
183
252
  }
184
253
  }
185
254
 
186
255
  async getMediaInlineUrl(id: number, loggedInUser, expiresIn?: number) {
187
256
  try {
257
+ // Validate AWS configuration
258
+ if (!this.s3AccessKeyID || !this.s3AccessKeySecret) {
259
+ throw new Error(
260
+ 'AWS credentials not configured. Please check AWS_ACCESS_KEY_ID and AWS_SECRET_KEY in configuration.',
261
+ );
262
+ }
263
+ if (!this.bucketName) {
264
+ throw new Error(
265
+ 'S3 bucket name not configured. Please check BUCKET_NAME in configuration.',
266
+ );
267
+ }
268
+ if (!this.s3Region) {
269
+ throw new Error(
270
+ 'AWS region not configured. Please check AWS_REGION in configuration.',
271
+ );
272
+ }
273
+
188
274
  const entityData = await this.getEntityData(
189
275
  ENTITYTYPE_MEDIA,
190
276
  id,
@@ -193,20 +279,28 @@ export class MediaDataService extends EntityServiceImpl {
193
279
  const mediaData = entityData as MediaData;
194
280
  let fileSize: number | undefined;
195
281
 
196
- if (!mediaData) {
197
- throw new Error('Media not found');
282
+ if (!mediaData || !mediaData.media_url) {
283
+ throw new Error(`Media data not found or invalid for id: ${id}`);
198
284
  }
199
285
 
200
286
  const ext = mediaData.file_name.split('.').pop()?.toLowerCase() || '';
201
287
 
202
288
  if (this.bucketName) {
203
- const head = await this.s3
204
- .headObject({
205
- Bucket: this.bucketName,
206
- Key: mediaData.media_url,
207
- })
208
- .promise();
209
- fileSize = head.ContentLength;
289
+ try {
290
+ const head = await this.s3
291
+ .headObject({
292
+ Bucket: this.bucketName,
293
+ Key: mediaData.media_url,
294
+ })
295
+ .promise();
296
+ fileSize = head.ContentLength;
297
+ } catch (headError) {
298
+ console.error(
299
+ `Error checking file in S3 bucket '${this.bucketName}' with key '${mediaData.media_url}':`,
300
+ headError.message,
301
+ );
302
+ // Continue even if headObject fails - the file might still be accessible
303
+ }
210
304
  }
211
305
 
212
306
  const signedUrl = await this.s3.getSignedUrlPromise('getObject', {
@@ -233,7 +327,15 @@ export class MediaDataService extends EntityServiceImpl {
233
327
  };
234
328
  } catch (error) {
235
329
  console.error('Error generating inline URL:', error);
236
- throw new Error('Failed to generate inline URL');
330
+ console.error('Error details:', {
331
+ message: error.message,
332
+ code: error.code,
333
+ statusCode: error.statusCode,
334
+ bucketName: this.bucketName,
335
+ region: this.s3Region,
336
+ hasCredentials: !!(this.s3AccessKeyID && this.s3AccessKeySecret),
337
+ });
338
+ throw new Error(`Failed to generate inline URL: ${error.message}`);
237
339
  }
238
340
  }
239
341
 
@@ -23,35 +23,35 @@ export class ScheduleHandlerService {
23
23
  private readonly listMasterRepo: Repository<ListMasterData>,
24
24
  ) {}
25
25
 
26
- async scheduleQueryBuilder(workflow_id: number, jobData: any) {
26
+ async scheduleQueryBuilder(workflowId: number, jobData: any) {
27
27
  // 1️⃣ Fetch workflow automation config
28
28
  const workflow = await this.workflowAutomation.findOne({
29
29
  where: {
30
- id: workflow_id,
31
- organization_id: jobData.organization_id,
30
+ id: workflowId,
31
+ organization_id: jobData.organizationId,
32
32
  },
33
33
  });
34
34
 
35
- if (!workflow) throw new Error(`Workflow with ID ${workflow_id} not found`);
35
+ if (!workflow) throw new Error(`Workflow with ID ${workflowId} not found`);
36
36
 
37
37
  const scheduleJson =
38
38
  typeof workflow.schedule === 'string'
39
39
  ? JSON.parse(workflow.schedule)
40
40
  : workflow.schedule;
41
-
41
+
42
42
  const entityType = workflow.applicable_entity_type;
43
43
 
44
44
  // 2️⃣ Get table name from frm_entity_master
45
45
  const entity = await this.entityMasterRepository.findOne({
46
46
  where: {
47
47
  mapped_entity_type: entityType,
48
- organization_id: jobData.organization_id,
48
+ organization_id: jobData.organizationId,
49
49
  },
50
- select: ['db_table_name'],
50
+ select: ['data_source'],
51
51
  });
52
- if (!entity?.db_table_name) throw new Error(`Entity ${entityType} not found`);
52
+ if (!entity?.data_source) throw new Error(`Entity ${entityType} not found`);
53
53
 
54
- const tableName = entity.db_table_name;
54
+ const tableName = entity.data_source;
55
55
 
56
56
  // 3️⃣ Resolve executionDate (list master item name)
57
57
  const executionDateItem = await this.listMasterRepo.findOne({
@@ -88,19 +88,11 @@ export class ScheduleHandlerService {
88
88
 
89
89
  const qb = this.dataSource
90
90
  .createQueryBuilder()
91
- .from(tableName, 'e')
92
- .innerJoin(
93
- 'frm_wf_stage_movement_data',
94
- 'sm',
95
- `
96
- sm.mapped_entity_id = e.id
97
- AND sm.is_current = 'Y'
98
- `,
99
- )
100
- .select('e.*')
91
+ .from(tableName, tableName)
92
+ .select('*')
101
93
  .where(comparisonDateCondition)
102
- .andWhere('e.organization_id = :orgId', {
103
- orgId: jobData.organization_id,
94
+ .andWhere(`${tableName}.organization_id = :orgId`, {
95
+ orgId: jobData.organizationId,
104
96
  });
105
97
 
106
98
  this.logger.debug(`Executing Scheduler Query: ${qb.getSql()}`);
@@ -115,19 +107,19 @@ export class ScheduleHandlerService {
115
107
  }
116
108
 
117
109
  // ⚙️ Step 2: Handle scheduled automation (main entry point)
118
- async handleScheduledWorkflow(workflow_id: number, jobData: any) {
110
+ async handleScheduledWorkflow(workflowId: number, jobData: any) {
119
111
  const { results, workflow, tableName } = await this.scheduleQueryBuilder(
120
- workflow_id,
112
+ workflowId,
121
113
  jobData,
122
114
  );
123
115
 
124
116
  if (!results?.length) {
125
- this.logger.warn(`No records found for scheduled workflow ${workflow_id}`);
117
+ this.logger.warn(`No records found for scheduled workflow ${workflowId}`);
126
118
  return;
127
119
  }
128
120
 
129
121
  this.logger.log(
130
- `Processing ${results.length} records for workflow ${workflow_id}`,
122
+ `Processing ${results.length} records for workflow ${workflowId}`,
131
123
  );
132
124
 
133
125
  // Parse the workflow event JSON again to get filter/action info
@@ -157,7 +149,7 @@ export class ScheduleHandlerService {
157
149
 
158
150
  // 🧮 Step 3: Execute workflow actions for matched entities
159
151
  if (!matchedEntities.length) {
160
- this.logger.log(`No records passed criteria for workflow ${workflow_id}`);
152
+ this.logger.log(`No records passed criteria for workflow ${workflowId}`);
161
153
  return;
162
154
  }
163
155
 
@@ -167,7 +159,7 @@ export class ScheduleHandlerService {
167
159
 
168
160
  for (const entity of matchedEntities) {
169
161
  await this.workflowAutomationEngineService.executeActions(
170
- workflow_id,
162
+ workflowId,
171
163
  entity,
172
164
  jobData,
173
165
  );
@@ -5,14 +5,13 @@
5
5
  import { UserData } from "src/module/user/entity/user.entity";
6
6
 
7
7
  export interface ScheduleJobData {
8
- id: number;
9
- schedule_id: number;
10
- workflow_id: number;
11
- workflow_name: string;
12
- organization_id: number;
13
- enterprise_id: number;
14
- level_id?: string;
15
- level_type?: string;
8
+ scheduleId: number;
9
+ workflowId: number;
10
+ workflowName: string;
11
+ organizationId: number;
12
+ enterpriseId: number;
13
+ levelId?: string;
14
+ levelType?: string;
16
15
  appcode?: string;
17
16
  createdBy: number;
18
17
  triggeredBy: 'SCHEDULE' | 'MANUAL';