@platform-modules/civil-aviation-authority 2.3.281 → 2.3.282

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.
@@ -91,8 +91,10 @@ export declare function buildApprovalChatMessage(params: {
91
91
  }): BilingualText;
92
92
  export declare function resolveWorkflowStatusAr(status: string | null | undefined): string | null;
93
93
  export declare function resolveChatStatusAr(status: string | null | undefined): string | null;
94
- export declare function resolveWorkflowContentAr(content: string | null | undefined): string | null;
95
- export declare function resolveChatMessageAr(message: string | null | undefined): string | null;
94
+ /** Pull bilingual actor fields from joined relations on workflow/chat rows. */
95
+ export declare function extractBilingualActorsFromRecord(record: Record<string, unknown>): BilingualActorNames;
96
+ export declare function resolveWorkflowContentAr(content: string | null | undefined, actors?: BilingualActorNames): string | null;
97
+ export declare function resolveChatMessageAr(message: string | null | undefined, actors?: BilingualActorNames): string | null;
96
98
  /** Generic workflow log enricher — use in all module repositories. */
97
99
  export declare function enrichWorkflowLog(log: Record<string, unknown>): Record<string, unknown>;
98
100
  /** Generic chat enricher — use in all module repositories. */
@@ -25,6 +25,7 @@ exports.buildHumanApprovalWorkflowContent = buildHumanApprovalWorkflowContent;
25
25
  exports.buildApprovalChatMessage = buildApprovalChatMessage;
26
26
  exports.resolveWorkflowStatusAr = resolveWorkflowStatusAr;
27
27
  exports.resolveChatStatusAr = resolveChatStatusAr;
28
+ exports.extractBilingualActorsFromRecord = extractBilingualActorsFromRecord;
28
29
  exports.resolveWorkflowContentAr = resolveWorkflowContentAr;
29
30
  exports.resolveChatMessageAr = resolveChatMessageAr;
30
31
  exports.enrichWorkflowLog = enrichWorkflowLog;
@@ -257,7 +258,47 @@ function resolveChatStatusAr(status) {
257
258
  return CHAT_STATUS_LABELS[status] ?? status;
258
259
  }
259
260
  // ─── Legacy row enrichment (read API) ────────────────────────────────────────
260
- function resolveWorkflowContentAr(content) {
261
+ /** Pull bilingual actor fields from joined relations on workflow/chat rows. */
262
+ function extractBilingualActorsFromRecord(record) {
263
+ const role = (record.approver_role ?? record.role);
264
+ const user = (record.approver_user ?? record.user);
265
+ const dept = (record.approver_department ?? record.department);
266
+ const section = (record.approver_section ?? record.section);
267
+ return {
268
+ roleName: role?.name != null ? String(role.name) : null,
269
+ roleArabicName: role?.arabic_name != null ? String(role.arabic_name) : null,
270
+ deptName: dept?.department_name != null ? String(dept.department_name) : null,
271
+ deptArabicName: dept?.department_arabic_name != null ? String(dept.department_arabic_name) : null,
272
+ sectionName: section?.section_name != null ? String(section.section_name) : null,
273
+ sectionArabicName: section?.section_arabic_name != null ? String(section.section_arabic_name) : null,
274
+ userName: user?.employee_name != null ? String(user.employee_name) : null,
275
+ userArabicName: user?.employee_arabic_name != null ? String(user.employee_arabic_name) : null,
276
+ employeeId: user?.employee_id != null ? String(user.employee_id) : null,
277
+ };
278
+ }
279
+ /** Arabic actor label for workflow templates (role, dept+section, or user). */
280
+ function resolveArabicWorkflowActorName(actors, parsedEnglishName) {
281
+ if (actors) {
282
+ const { ar } = resolveActorDisplayNames(actors);
283
+ if (ar)
284
+ return ar;
285
+ if (actors.userName?.trim()) {
286
+ return resolveBilingualName(actors.userName, actors.userArabicName);
287
+ }
288
+ }
289
+ return parsedEnglishName?.trim() || '';
290
+ }
291
+ /** Arabic role/user label for chat templates. */
292
+ function resolveArabicChatRoleName(actors, parsedEnglishRole) {
293
+ if (actors?.roleName?.trim()) {
294
+ return resolveBilingualName(actors.roleName, actors.roleArabicName);
295
+ }
296
+ if (actors?.userName?.trim()) {
297
+ return resolveBilingualName(actors.userName, actors.userArabicName);
298
+ }
299
+ return resolveBilingualName(parsedEnglishRole, actors?.roleArabicName);
300
+ }
301
+ function resolveWorkflowContentAr(content, actors) {
261
302
  if (content == null || content.trim() === '')
262
303
  return null;
263
304
  const normalized = content.trim();
@@ -277,8 +318,9 @@ function resolveWorkflowContentAr(content) {
277
318
  if (withoutComment.includes('{{name}}')) {
278
319
  const staticPrefix = withoutComment.replace('{{name}}', '').trim();
279
320
  if (baseEn.startsWith(staticPrefix)) {
280
- const namePart = baseEn.slice(staticPrefix.length).trim();
281
- return interpolate(tpl.ar, { name: namePart, comment: commentSuffix });
321
+ const namePartEn = baseEn.slice(staticPrefix.length).trim();
322
+ const nameAr = resolveArabicWorkflowActorName(actors, namePartEn);
323
+ return interpolate(tpl.ar, { name: nameAr, comment: commentSuffix });
282
324
  }
283
325
  }
284
326
  else if (withoutComment.trim() === baseEn) {
@@ -288,17 +330,19 @@ function resolveWorkflowContentAr(content) {
288
330
  }
289
331
  const inProgressPrefix = WORKFLOW_TEMPLATES.request_approval_in_progress_from?.en.split('{{name}}')[0].trim();
290
332
  if (inProgressPrefix && normalized.startsWith(inProgressPrefix)) {
291
- const namePart = normalized.slice(inProgressPrefix.length).trim();
292
- return interpolate(WORKFLOW_TEMPLATES.request_approval_in_progress_from.ar, { name: namePart });
333
+ const namePartEn = normalized.slice(inProgressPrefix.length).trim();
334
+ const nameAr = resolveArabicWorkflowActorName(actors, namePartEn);
335
+ return interpolate(WORKFLOW_TEMPLATES.request_approval_in_progress_from.ar, { name: nameAr });
293
336
  }
294
337
  const pendingPrefix = WORKFLOW_TEMPLATES.request_approval_pending_from?.en.split('{{name}}')[0].trim();
295
338
  if (pendingPrefix && normalized.startsWith(pendingPrefix)) {
296
- const namePart = normalized.slice(pendingPrefix.length).trim();
297
- return interpolate(WORKFLOW_TEMPLATES.request_approval_pending_from.ar, { name: namePart });
339
+ const namePartEn = normalized.slice(pendingPrefix.length).trim();
340
+ const nameAr = resolveArabicWorkflowActorName(actors, namePartEn);
341
+ return interpolate(WORKFLOW_TEMPLATES.request_approval_pending_from.ar, { name: nameAr });
298
342
  }
299
343
  return null;
300
344
  }
301
- function resolveChatMessageAr(message) {
345
+ function resolveChatMessageAr(message, actors) {
302
346
  if (message == null || message.trim() === '')
303
347
  return null;
304
348
  const normalized = message.trim();
@@ -306,6 +350,22 @@ function resolveChatMessageAr(message) {
306
350
  if (tpl.en === normalized)
307
351
  return tpl.ar;
308
352
  }
353
+ const submittedTpl = CHAT_TEMPLATES.cancellation_submitted_by;
354
+ if (submittedTpl) {
355
+ const prefix = submittedTpl.en.split('{{userName}}')[0];
356
+ if (normalized.startsWith(prefix)) {
357
+ const afterPrefix = normalized.slice(prefix.length);
358
+ const parenMatch = afterPrefix.match(/^(.+?) \((.+)\)$/);
359
+ if (parenMatch) {
360
+ const userEn = parenMatch[1].trim();
361
+ const employeeId = parenMatch[2].trim();
362
+ const userAr = actors?.userName?.trim()
363
+ ? resolveBilingualName(actors.userName, actors.userArabicName)
364
+ : resolveBilingualName(userEn, actors?.userArabicName);
365
+ return interpolate(submittedTpl.ar, { userName: userAr, employeeId });
366
+ }
367
+ }
368
+ }
309
369
  for (const tpl of Object.values(CHAT_TEMPLATES)) {
310
370
  if (!tpl.en.includes('{{roleName}}'))
311
371
  continue;
@@ -314,13 +374,10 @@ function resolveChatMessageAr(message) {
314
374
  continue;
315
375
  const rest = normalized.slice(prefix.length);
316
376
  const commentIdx = rest.lastIndexOf(' - ');
317
- if (commentIdx >= 0) {
318
- return interpolate(tpl.ar, {
319
- roleName: rest.slice(0, commentIdx),
320
- comment: rest.slice(commentIdx),
321
- });
322
- }
323
- return interpolate(tpl.ar, { roleName: rest, comment: '' });
377
+ const roleNameEn = commentIdx >= 0 ? rest.slice(0, commentIdx) : rest;
378
+ const commentSuffix = commentIdx >= 0 ? rest.slice(commentIdx) : '';
379
+ const roleNameAr = resolveArabicChatRoleName(actors, roleNameEn.trim());
380
+ return interpolate(tpl.ar, { roleName: roleNameAr, comment: commentSuffix });
324
381
  }
325
382
  return null;
326
383
  }
@@ -328,9 +385,10 @@ function resolveChatMessageAr(message) {
328
385
  function enrichWorkflowLog(log) {
329
386
  const status = log.status != null ? String(log.status) : null;
330
387
  const content = log.content != null ? String(log.content) : null;
388
+ const actors = extractBilingualActorsFromRecord(log);
331
389
  return {
332
390
  ...log,
333
- content_ar: log.content_ar ?? resolveWorkflowContentAr(content),
391
+ content_ar: log.content_ar ?? resolveWorkflowContentAr(content, actors),
334
392
  status_ar: log.status_ar ?? resolveWorkflowStatusAr(status),
335
393
  };
336
394
  }
@@ -338,9 +396,10 @@ function enrichWorkflowLog(log) {
338
396
  function enrichChatMessage(chat) {
339
397
  const status = chat.status != null ? String(chat.status) : null;
340
398
  const message = chat.message != null ? String(chat.message) : null;
399
+ const actors = extractBilingualActorsFromRecord(chat);
341
400
  return {
342
401
  ...chat,
343
- message_ar: chat.message_ar ?? resolveChatMessageAr(message),
402
+ message_ar: chat.message_ar ?? resolveChatMessageAr(message, actors),
344
403
  status_ar: chat.status_ar ?? resolveChatStatusAr(status),
345
404
  };
346
405
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platform-modules/civil-aviation-authority",
3
- "version": "2.3.281",
3
+ "version": "2.3.282",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
@@ -404,7 +404,61 @@ export function resolveChatStatusAr(status: string | null | undefined): string |
404
404
 
405
405
  // ─── Legacy row enrichment (read API) ────────────────────────────────────────
406
406
 
407
- export function resolveWorkflowContentAr(content: string | null | undefined): string | null {
407
+ /** Pull bilingual actor fields from joined relations on workflow/chat rows. */
408
+ export function extractBilingualActorsFromRecord(
409
+ record: Record<string, unknown>,
410
+ ): BilingualActorNames {
411
+ const role = (record.approver_role ?? record.role) as Record<string, unknown> | undefined;
412
+ const user = (record.approver_user ?? record.user) as Record<string, unknown> | undefined;
413
+ const dept = (record.approver_department ?? record.department) as Record<string, unknown> | undefined;
414
+ const section = (record.approver_section ?? record.section) as Record<string, unknown> | undefined;
415
+
416
+ return {
417
+ roleName: role?.name != null ? String(role.name) : null,
418
+ roleArabicName: role?.arabic_name != null ? String(role.arabic_name) : null,
419
+ deptName: dept?.department_name != null ? String(dept.department_name) : null,
420
+ deptArabicName: dept?.department_arabic_name != null ? String(dept.department_arabic_name) : null,
421
+ sectionName: section?.section_name != null ? String(section.section_name) : null,
422
+ sectionArabicName: section?.section_arabic_name != null ? String(section.section_arabic_name) : null,
423
+ userName: user?.employee_name != null ? String(user.employee_name) : null,
424
+ userArabicName: user?.employee_arabic_name != null ? String(user.employee_arabic_name) : null,
425
+ employeeId: user?.employee_id != null ? String(user.employee_id) : null,
426
+ };
427
+ }
428
+
429
+ /** Arabic actor label for workflow templates (role, dept+section, or user). */
430
+ function resolveArabicWorkflowActorName(
431
+ actors: BilingualActorNames | undefined,
432
+ parsedEnglishName?: string,
433
+ ): string {
434
+ if (actors) {
435
+ const { ar } = resolveActorDisplayNames(actors);
436
+ if (ar) return ar;
437
+ if (actors.userName?.trim()) {
438
+ return resolveBilingualName(actors.userName, actors.userArabicName);
439
+ }
440
+ }
441
+ return parsedEnglishName?.trim() || '';
442
+ }
443
+
444
+ /** Arabic role/user label for chat templates. */
445
+ function resolveArabicChatRoleName(
446
+ actors: BilingualActorNames | undefined,
447
+ parsedEnglishRole?: string,
448
+ ): string {
449
+ if (actors?.roleName?.trim()) {
450
+ return resolveBilingualName(actors.roleName, actors.roleArabicName);
451
+ }
452
+ if (actors?.userName?.trim()) {
453
+ return resolveBilingualName(actors.userName, actors.userArabicName);
454
+ }
455
+ return resolveBilingualName(parsedEnglishRole, actors?.roleArabicName);
456
+ }
457
+
458
+ export function resolveWorkflowContentAr(
459
+ content: string | null | undefined,
460
+ actors?: BilingualActorNames,
461
+ ): string | null {
408
462
  if (content == null || content.trim() === '') return null;
409
463
  const normalized = content.trim();
410
464
 
@@ -424,8 +478,9 @@ export function resolveWorkflowContentAr(content: string | null | undefined): st
424
478
  if (withoutComment.includes('{{name}}')) {
425
479
  const staticPrefix = withoutComment.replace('{{name}}', '').trim();
426
480
  if (baseEn.startsWith(staticPrefix)) {
427
- const namePart = baseEn.slice(staticPrefix.length).trim();
428
- return interpolate(tpl.ar, { name: namePart, comment: commentSuffix });
481
+ const namePartEn = baseEn.slice(staticPrefix.length).trim();
482
+ const nameAr = resolveArabicWorkflowActorName(actors, namePartEn);
483
+ return interpolate(tpl.ar, { name: nameAr, comment: commentSuffix });
429
484
  }
430
485
  } else if (withoutComment.trim() === baseEn) {
431
486
  return interpolate(tpl.ar, { comment: commentSuffix });
@@ -435,19 +490,24 @@ export function resolveWorkflowContentAr(content: string | null | undefined): st
435
490
 
436
491
  const inProgressPrefix = WORKFLOW_TEMPLATES.request_approval_in_progress_from?.en.split('{{name}}')[0].trim();
437
492
  if (inProgressPrefix && normalized.startsWith(inProgressPrefix)) {
438
- const namePart = normalized.slice(inProgressPrefix.length).trim();
439
- return interpolate(WORKFLOW_TEMPLATES.request_approval_in_progress_from.ar, { name: namePart });
493
+ const namePartEn = normalized.slice(inProgressPrefix.length).trim();
494
+ const nameAr = resolveArabicWorkflowActorName(actors, namePartEn);
495
+ return interpolate(WORKFLOW_TEMPLATES.request_approval_in_progress_from.ar, { name: nameAr });
440
496
  }
441
497
  const pendingPrefix = WORKFLOW_TEMPLATES.request_approval_pending_from?.en.split('{{name}}')[0].trim();
442
498
  if (pendingPrefix && normalized.startsWith(pendingPrefix)) {
443
- const namePart = normalized.slice(pendingPrefix.length).trim();
444
- return interpolate(WORKFLOW_TEMPLATES.request_approval_pending_from.ar, { name: namePart });
499
+ const namePartEn = normalized.slice(pendingPrefix.length).trim();
500
+ const nameAr = resolveArabicWorkflowActorName(actors, namePartEn);
501
+ return interpolate(WORKFLOW_TEMPLATES.request_approval_pending_from.ar, { name: nameAr });
445
502
  }
446
503
 
447
504
  return null;
448
505
  }
449
506
 
450
- export function resolveChatMessageAr(message: string | null | undefined): string | null {
507
+ export function resolveChatMessageAr(
508
+ message: string | null | undefined,
509
+ actors?: BilingualActorNames,
510
+ ): string | null {
451
511
  if (message == null || message.trim() === '') return null;
452
512
  const normalized = message.trim();
453
513
 
@@ -455,19 +515,33 @@ export function resolveChatMessageAr(message: string | null | undefined): string
455
515
  if (tpl.en === normalized) return tpl.ar;
456
516
  }
457
517
 
518
+ const submittedTpl = CHAT_TEMPLATES.cancellation_submitted_by;
519
+ if (submittedTpl) {
520
+ const prefix = submittedTpl.en.split('{{userName}}')[0];
521
+ if (normalized.startsWith(prefix)) {
522
+ const afterPrefix = normalized.slice(prefix.length);
523
+ const parenMatch = afterPrefix.match(/^(.+?) \((.+)\)$/);
524
+ if (parenMatch) {
525
+ const userEn = parenMatch[1].trim();
526
+ const employeeId = parenMatch[2].trim();
527
+ const userAr = actors?.userName?.trim()
528
+ ? resolveBilingualName(actors.userName, actors.userArabicName)
529
+ : resolveBilingualName(userEn, actors?.userArabicName);
530
+ return interpolate(submittedTpl.ar, { userName: userAr, employeeId });
531
+ }
532
+ }
533
+ }
534
+
458
535
  for (const tpl of Object.values(CHAT_TEMPLATES)) {
459
536
  if (!tpl.en.includes('{{roleName}}')) continue;
460
537
  const prefix = tpl.en.split('{{roleName}}')[0];
461
538
  if (!normalized.startsWith(prefix)) continue;
462
539
  const rest = normalized.slice(prefix.length);
463
540
  const commentIdx = rest.lastIndexOf(' - ');
464
- if (commentIdx >= 0) {
465
- return interpolate(tpl.ar, {
466
- roleName: rest.slice(0, commentIdx),
467
- comment: rest.slice(commentIdx),
468
- });
469
- }
470
- return interpolate(tpl.ar, { roleName: rest, comment: '' });
541
+ const roleNameEn = commentIdx >= 0 ? rest.slice(0, commentIdx) : rest;
542
+ const commentSuffix = commentIdx >= 0 ? rest.slice(commentIdx) : '';
543
+ const roleNameAr = resolveArabicChatRoleName(actors, roleNameEn.trim());
544
+ return interpolate(tpl.ar, { roleName: roleNameAr, comment: commentSuffix });
471
545
  }
472
546
 
473
547
  return null;
@@ -477,9 +551,10 @@ export function resolveChatMessageAr(message: string | null | undefined): string
477
551
  export function enrichWorkflowLog(log: Record<string, unknown>): Record<string, unknown> {
478
552
  const status = log.status != null ? String(log.status) : null;
479
553
  const content = log.content != null ? String(log.content) : null;
554
+ const actors = extractBilingualActorsFromRecord(log);
480
555
  return {
481
556
  ...log,
482
- content_ar: log.content_ar ?? resolveWorkflowContentAr(content),
557
+ content_ar: log.content_ar ?? resolveWorkflowContentAr(content, actors),
483
558
  status_ar: log.status_ar ?? resolveWorkflowStatusAr(status),
484
559
  };
485
560
  }
@@ -488,9 +563,10 @@ export function enrichWorkflowLog(log: Record<string, unknown>): Record<string,
488
563
  export function enrichChatMessage(chat: Record<string, unknown>): Record<string, unknown> {
489
564
  const status = chat.status != null ? String(chat.status) : null;
490
565
  const message = chat.message != null ? String(chat.message) : null;
566
+ const actors = extractBilingualActorsFromRecord(chat);
491
567
  return {
492
568
  ...chat,
493
- message_ar: chat.message_ar ?? resolveChatMessageAr(message),
569
+ message_ar: chat.message_ar ?? resolveChatMessageAr(message, actors),
494
570
  status_ar: chat.status_ar ?? resolveChatStatusAr(status),
495
571
  };
496
572
  }