@platform-modules/civil-aviation-authority 2.3.294 → 2.3.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.
@@ -77,7 +77,6 @@ export type RequestApprovedAssignedWorkflowParams = {
77
77
  employeeId: string | number;
78
78
  assigneeLabel?: 'user' | 'technician';
79
79
  };
80
- /** Parse legacy English-only assignment comments used as workflow log suffixes. */
81
80
  export declare function tryParseRequestAssignedComment(comment?: string | null): Omit<RequestApprovedAssignedWorkflowParams, 'roleArabicName'> | null;
82
81
  /** Bilingual workflow content for approved assignment steps (HR, IT, Tender, etc.). */
83
82
  export declare function buildRequestApprovedAssignedWorkflowFields(params: RequestApprovedAssignedWorkflowParams): BilingualText;
@@ -178,10 +178,19 @@ function buildSynchronizedWorkflowMessage(ctx) {
178
178
  return actorEn
179
179
  ? renderSynchronizedWorkflowMessage('request_approval_pending_from', { name: actorEn }, { name: actorAr })
180
180
  : workflowTemplate('request_approval_pending');
181
- case 'approved':
181
+ case 'approved': {
182
+ const assignment = tryParseRequestAssignedComment(ctx.comment);
183
+ if (assignment) {
184
+ return buildRequestApprovedAssignedWorkflowFields({
185
+ ...assignment,
186
+ roleName: ctx.roleName?.trim() || assignment.roleName,
187
+ roleArabicName: ctx.roleArabicName,
188
+ });
189
+ }
182
190
  return actorEn
183
191
  ? renderSynchronizedWorkflowMessage('request_approved_by', { name: actorEn, comment: commentWf }, { name: actorAr, comment: commentWf })
184
192
  : renderSynchronizedWorkflowMessage('request_approved', { comment: commentWf }, { comment: commentWf });
193
+ }
185
194
  case 'rejected':
186
195
  return actorEn
187
196
  ? renderSynchronizedWorkflowMessage('request_rejected_by', { name: actorEn, comment: commentWf }, { name: actorAr, comment: commentWf })
@@ -236,11 +245,11 @@ function buildSynchronizedChatMessage(ctx) {
236
245
  }
237
246
  }
238
247
  /** Parse legacy English-only assignment comments used as workflow log suffixes. */
239
- function tryParseRequestAssignedComment(comment) {
240
- const text = comment?.trim();
241
- if (!text)
248
+ function parseRequestAssignedCommentText(text) {
249
+ const normalized = text.trim();
250
+ if (!normalized)
242
251
  return null;
243
- const technicianMatch = text.match(/^Request assigned to technician (.+?) by (.+?) \((.+?) - (.+?)\)$/);
252
+ const technicianMatch = normalized.match(/^request assigned to technician (.+?) by (.+?) \((.+?) - (.+?)\)$/i);
244
253
  if (technicianMatch) {
245
254
  return {
246
255
  assignedUserName: technicianMatch[1].trim(),
@@ -250,7 +259,7 @@ function tryParseRequestAssignedComment(comment) {
250
259
  assigneeLabel: 'technician',
251
260
  };
252
261
  }
253
- const userMatch = text.match(/^Request assigned to (.+?) by (.+?) \((.+?) - (.+?)\)$/);
262
+ const userMatch = normalized.match(/^request assigned to (.+?) by (.+?) \((.+?) - (.+?)\)$/i);
254
263
  if (userMatch) {
255
264
  return {
256
265
  assignedUserName: userMatch[1].trim(),
@@ -262,6 +271,36 @@ function tryParseRequestAssignedComment(comment) {
262
271
  }
263
272
  return null;
264
273
  }
274
+ function tryParseRequestAssignedComment(comment) {
275
+ let text = comment?.trim();
276
+ if (!text)
277
+ return null;
278
+ if (text.startsWith(':')) {
279
+ text = text.replace(/^:\s*/, '').trim();
280
+ }
281
+ const direct = parseRequestAssignedCommentText(text);
282
+ if (direct)
283
+ return direct;
284
+ const colonIdx = text.indexOf(': ');
285
+ if (colonIdx >= 0) {
286
+ const afterColon = text.slice(colonIdx + 2).trim();
287
+ const parsedAfterColon = parseRequestAssignedCommentText(afterColon);
288
+ if (parsedAfterColon)
289
+ return parsedAfterColon;
290
+ }
291
+ const assignMatch = text.match(/request assigned to/i);
292
+ if (assignMatch && assignMatch.index != null && assignMatch.index >= 0) {
293
+ return parseRequestAssignedCommentText(text.slice(assignMatch.index).trim());
294
+ }
295
+ return null;
296
+ }
297
+ function buildAssignmentWorkflowFieldsFromActors(assignment, actors) {
298
+ return buildRequestApprovedAssignedWorkflowFields({
299
+ ...assignment,
300
+ roleName: actors?.roleName?.trim() || assignment.roleName,
301
+ roleArabicName: actors?.roleArabicName ?? null,
302
+ });
303
+ }
265
304
  /** Bilingual workflow content for approved assignment steps (HR, IT, Tender, etc.). */
266
305
  function buildRequestApprovedAssignedWorkflowFields(params) {
267
306
  const assignedUserEn = params.assignedUserName?.trim() || 'User';
@@ -286,7 +325,8 @@ function buildRequestApprovedAssignedWorkflowFields(params) {
286
325
  }
287
326
  /** Standard workflow log UPDATE fields for all CAA module repositories. */
288
327
  function buildWorkflowLogUpdateFields(params) {
289
- if (params.approvalStatus === 'Approved') {
328
+ const isApprovedLike = params.approvalStatus === 'Approved' || params.approvalStatus === 'Assigned';
329
+ if (isApprovedLike) {
290
330
  const assignment = tryParseRequestAssignedComment(params.comment);
291
331
  if (assignment) {
292
332
  const bilingual = buildRequestApprovedAssignedWorkflowFields({
@@ -303,7 +343,7 @@ function buildWorkflowLogUpdateFields(params) {
303
343
  }
304
344
  }
305
345
  let action;
306
- if (params.approvalStatus === 'Approved')
346
+ if (params.approvalStatus === 'Approved' || params.approvalStatus === 'Assigned')
307
347
  action = 'approved';
308
348
  else if (params.approvalStatus === 'Rejected')
309
349
  action = 'rejected';
@@ -880,6 +920,10 @@ function resolveWorkflowContentAr(content, actors) {
880
920
  if (content == null || content.trim() === '')
881
921
  return null;
882
922
  const normalized = content.trim();
923
+ const embeddedAssignment = tryParseRequestAssignedComment(normalized);
924
+ if (embeddedAssignment) {
925
+ return buildAssignmentWorkflowFieldsFromActors(embeddedAssignment, actors).ar;
926
+ }
883
927
  for (const tpl of Object.values(WORKFLOW_TEMPLATES)) {
884
928
  if (tpl.en === normalized || tpl.en.toLowerCase() === normalized.toLowerCase())
885
929
  return tpl.ar;
@@ -896,6 +940,10 @@ function resolveWorkflowContentAr(content, actors) {
896
940
  if (commentIdx > 0) {
897
941
  const baseEn = normalized.slice(0, commentIdx).trim();
898
942
  const commentText = normalized.slice(commentIdx + 2).trim();
943
+ const assignment = tryParseRequestAssignedComment(commentText);
944
+ if (assignment) {
945
+ return buildAssignmentWorkflowFieldsFromActors(assignment, actors).ar;
946
+ }
899
947
  const commentSuffix = formatWorkflowCommentSuffix(commentText);
900
948
  for (const tpl of Object.values(WORKFLOW_TEMPLATES)) {
901
949
  if (!tpl.en.includes('{{comment}}'))
@@ -999,7 +1047,7 @@ function enrichWorkflowLog(log) {
999
1047
  existingAr &&
1000
1048
  resolvedAr &&
1001
1049
  existingAr !== resolvedAr &&
1002
- /Request assigned to/i.test(existingAr)) {
1050
+ (/request assigned to/i.test(content) || /request assigned to/i.test(existingAr))) {
1003
1051
  content_ar = resolvedAr;
1004
1052
  }
1005
1053
  if (content &&
@@ -80,12 +80,7 @@ __decorate([
80
80
  __metadata("design:type", String)
81
81
  ], FollowUpReportRequests.prototype, "subject", void 0);
82
82
  __decorate([
83
- (0, typeorm_1.Column)({
84
- type: 'enum',
85
- enum: FollowUpReportSubjectClassification,
86
- enumName: 'maintenance_subject_classification_en',
87
- nullable: false,
88
- }),
83
+ (0, typeorm_1.Column)({ type: 'varchar', length: 100, nullable: false }),
89
84
  __metadata("design:type", String)
90
85
  ], FollowUpReportRequests.prototype, "subject_classification", void 0);
91
86
  __decorate([
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@platform-modules/civil-aviation-authority",
3
- "version": "2.3.294",
3
+ "version": "2.3.296",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
7
7
  "build": "tsc && node -e \"require('fs').mkdirSync('dist/i18n',{recursive:true}); require('fs').copyFileSync('src/i18n/workflow-chat-i18n.json','dist/i18n/workflow-chat-i18n.json')\"",
8
8
  "dev": "ts-node src/scripts.ts",
9
+ "fix:enum": "node scripts/run-enum-fix.js",
9
10
  "sync:sla-sql": "node scripts/sync-sla-reports-sql.js"
10
11
  },
11
12
  "publishConfig": {
@@ -0,0 +1,30 @@
1
+ require('dotenv').config();
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const { Client } = require('pg');
5
+
6
+ async function main() {
7
+ const sqlPath = path.join(__dirname, '..', 'sql', 'fix_maintenance_subject_classification_enum_2026_07.sql');
8
+ const sql = fs.readFileSync(sqlPath, 'utf8');
9
+
10
+ const client = new Client({
11
+ host: process.env.DB_HOST,
12
+ port: Number(process.env.DB_PORT || 5432),
13
+ user: process.env.DB_USER,
14
+ password: process.env.DB_PASS,
15
+ database: process.env.DB_NAME,
16
+ });
17
+
18
+ await client.connect();
19
+ try {
20
+ await client.query(sql);
21
+ console.log('✅ Enum repair SQL applied successfully.');
22
+ } finally {
23
+ await client.end();
24
+ }
25
+ }
26
+
27
+ main().catch((error) => {
28
+ console.error('❌ Enum repair failed:', error.message);
29
+ process.exit(1);
30
+ });
@@ -31,51 +31,29 @@ ALTER TABLE cyber_security_risk_management_risks
31
31
  ADD COLUMN IF NOT EXISTS treatment TEXT,
32
32
  ADD COLUMN IF NOT EXISTS action TEXT;
33
33
 
34
- -- 7. Follow-up report: subject_classification enum values
35
- ALTER TYPE maintenance_subject_classification_en ADD VALUE IF NOT EXISTS 'Important';
36
- ALTER TYPE maintenance_subject_classification_en ADD VALUE IF NOT EXISTS 'Highly Confidential';
37
- ALTER TYPE maintenance_subject_classification_en ADD VALUE IF NOT EXISTS 'Restricted';
38
- ALTER TYPE maintenance_subject_classification_en ADD VALUE IF NOT EXISTS 'Limited';
34
+ -- 7. Follow-up report: subject_classification as varchar (avoids TypeORM PG enum sync failures)
35
+ ALTER TABLE followup_report_items
36
+ ALTER COLUMN subject_classification TYPE VARCHAR(100)
37
+ USING subject_classification::text;
39
38
 
40
- -- 7b. Repair failed TypeORM enum swap (items column can remain on _old type)
41
- DO $$
42
- BEGIN
43
- IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'maintenance_subject_classification_en_old') THEN
44
- IF EXISTS (
45
- SELECT 1
46
- FROM information_schema.columns
47
- WHERE table_schema = 'public'
48
- AND table_name = 'followup_report_items'
49
- AND column_name = 'subject_classification'
50
- AND udt_name = 'maintenance_subject_classification_en_old'
51
- ) THEN
52
- ALTER TABLE followup_report_items
53
- ALTER COLUMN subject_classification TYPE maintenance_subject_classification_en
54
- USING subject_classification::text::maintenance_subject_classification_en;
55
- END IF;
39
+ ALTER TABLE followup_report_requests
40
+ ALTER COLUMN subject_classification TYPE VARCHAR(100)
41
+ USING subject_classification::text;
56
42
 
57
- IF EXISTS (
58
- SELECT 1
59
- FROM information_schema.columns
60
- WHERE table_schema = 'public'
61
- AND table_name = 'followup_report_requests'
62
- AND column_name = 'subject_classification'
63
- AND udt_name = 'maintenance_subject_classification_en_old'
64
- ) THEN
65
- ALTER TABLE followup_report_requests
66
- ALTER COLUMN subject_classification TYPE maintenance_subject_classification_en
67
- USING subject_classification::text::maintenance_subject_classification_en;
68
- END IF;
43
+ DROP TYPE IF EXISTS maintenance_subject_classification_en_old;
69
44
 
70
- DROP TYPE maintenance_subject_classification_en_old;
45
+ DO $$
46
+ BEGIN
47
+ IF NOT EXISTS (
48
+ SELECT 1
49
+ FROM information_schema.columns
50
+ WHERE table_schema = 'public'
51
+ AND udt_name = 'maintenance_subject_classification_en'
52
+ ) THEN
53
+ DROP TYPE IF EXISTS maintenance_subject_classification_en;
71
54
  END IF;
72
55
  END $$;
73
56
 
74
- -- 7c. Report items use varchar (nullable) so TypeORM sync does not fight shared PG enum on two tables
75
- ALTER TABLE followup_report_items
76
- ALTER COLUMN subject_classification TYPE VARCHAR(100)
77
- USING subject_classification::text;
78
-
79
57
  -- 8. Contract service request: notes, company phone, contract documents table
80
58
  ALTER TABLE contract_service_requests
81
59
  ADD COLUMN IF NOT EXISTS notes TEXT,
@@ -1,48 +1,28 @@
1
- -- Run this BEFORE shared_models synchronize if you see:
2
- -- cannot drop type maintenance_subject_classification_en_old because other objects depend on it
3
- --
1
+ -- Repair stuck TypeORM enum swap for follow-up report subject_classification.
4
2
  -- Safe to re-run.
5
3
 
6
- -- Add new enum values on the live type (no-op if already present)
7
- ALTER TYPE maintenance_subject_classification_en ADD VALUE IF NOT EXISTS 'Important';
8
- ALTER TYPE maintenance_subject_classification_en ADD VALUE IF NOT EXISTS 'Highly Confidential';
9
- ALTER TYPE maintenance_subject_classification_en ADD VALUE IF NOT EXISTS 'Restricted';
10
- ALTER TYPE maintenance_subject_classification_en ADD VALUE IF NOT EXISTS 'Limited';
4
+ -- 1) Move report items off PG enum (_old or live) -> varchar
5
+ ALTER TABLE followup_report_items
6
+ ALTER COLUMN subject_classification TYPE VARCHAR(100)
7
+ USING subject_classification::text;
11
8
 
12
- DO $$
13
- BEGIN
14
- IF EXISTS (SELECT 1 FROM pg_type WHERE typname = 'maintenance_subject_classification_en_old') THEN
15
- IF EXISTS (
16
- SELECT 1
17
- FROM information_schema.columns
18
- WHERE table_schema = 'public'
19
- AND table_name = 'followup_report_items'
20
- AND column_name = 'subject_classification'
21
- AND udt_name = 'maintenance_subject_classification_en_old'
22
- ) THEN
23
- ALTER TABLE followup_report_items
24
- ALTER COLUMN subject_classification TYPE maintenance_subject_classification_en
25
- USING subject_classification::text::maintenance_subject_classification_en;
26
- END IF;
9
+ -- 2) Move requests off PG enum (_old or live) -> varchar
10
+ ALTER TABLE followup_report_requests
11
+ ALTER COLUMN subject_classification TYPE VARCHAR(100)
12
+ USING subject_classification::text;
27
13
 
28
- IF EXISTS (
29
- SELECT 1
30
- FROM information_schema.columns
31
- WHERE table_schema = 'public'
32
- AND table_name = 'followup_report_requests'
33
- AND column_name = 'subject_classification'
34
- AND udt_name = 'maintenance_subject_classification_en_old'
35
- ) THEN
36
- ALTER TABLE followup_report_requests
37
- ALTER COLUMN subject_classification TYPE maintenance_subject_classification_en
38
- USING subject_classification::text::maintenance_subject_classification_en;
39
- END IF;
14
+ -- 3) Drop leftover TypeORM enum type if nothing depends on it
15
+ DROP TYPE IF EXISTS maintenance_subject_classification_en_old;
40
16
 
41
- DROP TYPE maintenance_subject_classification_en_old;
17
+ -- 4) Drop orphaned live enum only when no column uses it anymore
18
+ DO $$
19
+ BEGIN
20
+ IF NOT EXISTS (
21
+ SELECT 1
22
+ FROM information_schema.columns
23
+ WHERE table_schema = 'public'
24
+ AND udt_name = 'maintenance_subject_classification_en'
25
+ ) THEN
26
+ DROP TYPE IF EXISTS maintenance_subject_classification_en;
42
27
  END IF;
43
28
  END $$;
44
-
45
- -- Items column: varchar avoids TypeORM multi-table PG enum sync failures
46
- ALTER TABLE followup_report_items
47
- ALTER COLUMN subject_classification TYPE VARCHAR(100)
48
- USING subject_classification::text;
@@ -237,7 +237,15 @@ export function buildSynchronizedWorkflowMessage(ctx: WorkflowMessageContext): B
237
237
  { name: actorAr },
238
238
  )
239
239
  : workflowTemplate('request_approval_pending');
240
- case 'approved':
240
+ case 'approved': {
241
+ const assignment = tryParseRequestAssignedComment(ctx.comment);
242
+ if (assignment) {
243
+ return buildRequestApprovedAssignedWorkflowFields({
244
+ ...assignment,
245
+ roleName: ctx.roleName?.trim() || assignment.roleName,
246
+ roleArabicName: ctx.roleArabicName,
247
+ });
248
+ }
241
249
  return actorEn
242
250
  ? renderSynchronizedWorkflowMessage(
243
251
  'request_approved_by',
@@ -249,6 +257,7 @@ export function buildSynchronizedWorkflowMessage(ctx: WorkflowMessageContext): B
249
257
  { comment: commentWf },
250
258
  { comment: commentWf },
251
259
  );
260
+ }
252
261
  case 'rejected':
253
262
  return actorEn
254
263
  ? renderSynchronizedWorkflowMessage(
@@ -354,14 +363,14 @@ export type RequestApprovedAssignedWorkflowParams = {
354
363
  };
355
364
 
356
365
  /** Parse legacy English-only assignment comments used as workflow log suffixes. */
357
- export function tryParseRequestAssignedComment(
358
- comment?: string | null,
366
+ function parseRequestAssignedCommentText(
367
+ text: string,
359
368
  ): Omit<RequestApprovedAssignedWorkflowParams, 'roleArabicName'> | null {
360
- const text = comment?.trim();
361
- if (!text) return null;
369
+ const normalized = text.trim();
370
+ if (!normalized) return null;
362
371
 
363
- const technicianMatch = text.match(
364
- /^Request assigned to technician (.+?) by (.+?) \((.+?) - (.+?)\)$/,
372
+ const technicianMatch = normalized.match(
373
+ /^request assigned to technician (.+?) by (.+?) \((.+?) - (.+?)\)$/i,
365
374
  );
366
375
  if (technicianMatch) {
367
376
  return {
@@ -373,7 +382,7 @@ export function tryParseRequestAssignedComment(
373
382
  };
374
383
  }
375
384
 
376
- const userMatch = text.match(/^Request assigned to (.+?) by (.+?) \((.+?) - (.+?)\)$/);
385
+ const userMatch = normalized.match(/^request assigned to (.+?) by (.+?) \((.+?) - (.+?)\)$/i);
377
386
  if (userMatch) {
378
387
  return {
379
388
  assignedUserName: userMatch[1].trim(),
@@ -387,6 +396,45 @@ export function tryParseRequestAssignedComment(
387
396
  return null;
388
397
  }
389
398
 
399
+ export function tryParseRequestAssignedComment(
400
+ comment?: string | null,
401
+ ): Omit<RequestApprovedAssignedWorkflowParams, 'roleArabicName'> | null {
402
+ let text = comment?.trim();
403
+ if (!text) return null;
404
+
405
+ if (text.startsWith(':')) {
406
+ text = text.replace(/^:\s*/, '').trim();
407
+ }
408
+
409
+ const direct = parseRequestAssignedCommentText(text);
410
+ if (direct) return direct;
411
+
412
+ const colonIdx = text.indexOf(': ');
413
+ if (colonIdx >= 0) {
414
+ const afterColon = text.slice(colonIdx + 2).trim();
415
+ const parsedAfterColon = parseRequestAssignedCommentText(afterColon);
416
+ if (parsedAfterColon) return parsedAfterColon;
417
+ }
418
+
419
+ const assignMatch = text.match(/request assigned to/i);
420
+ if (assignMatch && assignMatch.index != null && assignMatch.index >= 0) {
421
+ return parseRequestAssignedCommentText(text.slice(assignMatch.index).trim());
422
+ }
423
+
424
+ return null;
425
+ }
426
+
427
+ function buildAssignmentWorkflowFieldsFromActors(
428
+ assignment: Omit<RequestApprovedAssignedWorkflowParams, 'roleArabicName'>,
429
+ actors?: BilingualActorNames,
430
+ ): BilingualText {
431
+ return buildRequestApprovedAssignedWorkflowFields({
432
+ ...assignment,
433
+ roleName: actors?.roleName?.trim() || assignment.roleName,
434
+ roleArabicName: actors?.roleArabicName ?? null,
435
+ });
436
+ }
437
+
390
438
  /** Bilingual workflow content for approved assignment steps (HR, IT, Tender, etc.). */
391
439
  export function buildRequestApprovedAssignedWorkflowFields(
392
440
  params: RequestApprovedAssignedWorkflowParams,
@@ -427,7 +475,10 @@ export function buildWorkflowLogUpdateFields(params: {
427
475
  roleArabicName?: string | null;
428
476
  comment?: string | null;
429
477
  }): { content: string; content_ar: string; status: string; status_ar: string | null } {
430
- if (params.approvalStatus === 'Approved') {
478
+ const isApprovedLike =
479
+ params.approvalStatus === 'Approved' || params.approvalStatus === 'Assigned';
480
+
481
+ if (isApprovedLike) {
431
482
  const assignment = tryParseRequestAssignedComment(params.comment);
432
483
  if (assignment) {
433
484
  const bilingual = buildRequestApprovedAssignedWorkflowFields({
@@ -445,7 +496,7 @@ export function buildWorkflowLogUpdateFields(params: {
445
496
  }
446
497
 
447
498
  let action: WorkflowMessageAction;
448
- if (params.approvalStatus === 'Approved') action = 'approved';
499
+ if (params.approvalStatus === 'Approved' || params.approvalStatus === 'Assigned') action = 'approved';
449
500
  else if (params.approvalStatus === 'Rejected') action = 'rejected';
450
501
  else if (params.approvalStatus === 'Returned for Modification') action = 'returned_for_modification';
451
502
  else action = 'approval_pending_update';
@@ -1368,6 +1419,11 @@ export function resolveWorkflowContentAr(
1368
1419
  if (content == null || content.trim() === '') return null;
1369
1420
  const normalized = content.trim();
1370
1421
 
1422
+ const embeddedAssignment = tryParseRequestAssignedComment(normalized);
1423
+ if (embeddedAssignment) {
1424
+ return buildAssignmentWorkflowFieldsFromActors(embeddedAssignment, actors).ar;
1425
+ }
1426
+
1371
1427
  for (const tpl of Object.values(WORKFLOW_TEMPLATES)) {
1372
1428
  if (tpl.en === normalized || tpl.en.toLowerCase() === normalized.toLowerCase()) return tpl.ar;
1373
1429
  }
@@ -1383,6 +1439,10 @@ export function resolveWorkflowContentAr(
1383
1439
  if (commentIdx > 0) {
1384
1440
  const baseEn = normalized.slice(0, commentIdx).trim();
1385
1441
  const commentText = normalized.slice(commentIdx + 2).trim();
1442
+ const assignment = tryParseRequestAssignedComment(commentText);
1443
+ if (assignment) {
1444
+ return buildAssignmentWorkflowFieldsFromActors(assignment, actors).ar;
1445
+ }
1386
1446
  const commentSuffix = formatWorkflowCommentSuffix(commentText);
1387
1447
 
1388
1448
  for (const tpl of Object.values(WORKFLOW_TEMPLATES)) {
@@ -1502,7 +1562,7 @@ export function enrichWorkflowLog(log: Record<string, unknown>): Record<string,
1502
1562
  existingAr &&
1503
1563
  resolvedAr &&
1504
1564
  existingAr !== resolvedAr &&
1505
- /Request assigned to/i.test(existingAr)
1565
+ (/request assigned to/i.test(content) || /request assigned to/i.test(existingAr))
1506
1566
  ) {
1507
1567
  content_ar = resolvedAr;
1508
1568
  }
@@ -62,12 +62,7 @@ export class FollowUpReportRequests extends BaseModel {
62
62
  @Column({ type: 'varchar', length: 500, nullable: false })
63
63
  subject: string;
64
64
 
65
- @Column({
66
- type: 'enum',
67
- enum: FollowUpReportSubjectClassification,
68
- enumName: 'maintenance_subject_classification_en',
69
- nullable: false,
70
- })
65
+ @Column({ type: 'varchar', length: 100, nullable: false })
71
66
  subject_classification: FollowUpReportSubjectClassification;
72
67
 
73
68
  @Column({ type: 'text', nullable: false })