@platform-modules/civil-aviation-authority 2.3.274 → 2.3.277

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/.env CHANGED
@@ -1,8 +1,8 @@
1
- # DB_HOST=164.52.222.169
2
- # DB_PORT=5432
3
- # DB_USER=postgres_admin_user
4
- # DB_PASS=pg_admin_user_pwd_caa_fa_$%^&OIukhjgcvbn
5
- # DB_NAME=CAA
1
+ DB_HOST=164.52.222.169
2
+ DB_PORT=5432
3
+ DB_USER=postgres_admin_user
4
+ DB_PASS=pg_admin_user_pwd_caa_fa_$%^&OIukhjgcvbn
5
+ DB_NAME=CAA
6
6
 
7
7
 
8
8
  # DB_HOST=localhost
@@ -11,8 +11,8 @@
11
11
  # DB_PASS=stevejobs
12
12
  # DB_NAME=CAA
13
13
 
14
- DB_HOST=10.44.3.201
15
- DB_PORT=5432
16
- DB_USER=appuser
17
- DB_PASS=HamaCaa7489
18
- DB_NAME=caa_prd_db
14
+ # DB_HOST=10.44.3.201
15
+ # DB_PORT=5432
16
+ # DB_USER=appuser
17
+ # DB_PASS=HamaCaa7489
18
+ # DB_NAME=caa_prd_db
@@ -0,0 +1,40 @@
1
+ export type BilingualText = {
2
+ en: string;
3
+ ar: string;
4
+ };
5
+ type WorkflowChatI18nCatalog = {
6
+ workflowTemplates: Record<string, BilingualText>;
7
+ chatTemplates: Record<string, BilingualText>;
8
+ workflowStatusLabels: Record<string, string>;
9
+ chatStatusLabels: Record<string, string>;
10
+ };
11
+ /** Read-only view of the shared workflow/chat translation catalog. */
12
+ export declare function getWorkflowChatI18nCatalog(): WorkflowChatI18nCatalog;
13
+ export declare function buildBilingualFromTemplate(templateCatalog: Record<string, BilingualText>, key: string, params?: Record<string, string>): BilingualText;
14
+ export declare function workflowTemplate(key: string, params?: Record<string, string>): BilingualText;
15
+ export declare function chatTemplate(key: string, params?: Record<string, string>): BilingualText;
16
+ export declare function resolveWorkflowStatusAr(status: string | null | undefined): string | null;
17
+ export declare function resolveChatStatusAr(status: string | null | undefined): string | null;
18
+ export declare function pickLocalizedName(englishName?: string | null, arabicName?: string | null, fallback?: string): string;
19
+ export declare function buildApprovalWorkflowContent(params: {
20
+ status: 'Approved' | 'Rejected' | 'Pending' | string;
21
+ roleName?: string | null;
22
+ roleArabicName?: string | null;
23
+ comment?: string | null;
24
+ }): BilingualText;
25
+ export declare function buildHumanApprovalWorkflowContent(params: {
26
+ isFirst: boolean;
27
+ roleName?: string | null;
28
+ roleArabicName?: string | null;
29
+ deptSectionEn?: string | null;
30
+ deptSectionAr?: string | null;
31
+ }): BilingualText;
32
+ export declare function buildApprovalChatMessage(params: {
33
+ status: 'Approved' | 'Rejected' | string;
34
+ roleName?: string | null;
35
+ roleArabicName?: string | null;
36
+ comment?: string | null;
37
+ }): BilingualText;
38
+ export declare function enrichCancellationWorkflowLog(log: Record<string, unknown>): Record<string, unknown>;
39
+ export declare function enrichCancellationChatMessage(chat: Record<string, unknown>): Record<string, unknown>;
40
+ export {};
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getWorkflowChatI18nCatalog = getWorkflowChatI18nCatalog;
7
+ exports.buildBilingualFromTemplate = buildBilingualFromTemplate;
8
+ exports.workflowTemplate = workflowTemplate;
9
+ exports.chatTemplate = chatTemplate;
10
+ exports.resolveWorkflowStatusAr = resolveWorkflowStatusAr;
11
+ exports.resolveChatStatusAr = resolveChatStatusAr;
12
+ exports.pickLocalizedName = pickLocalizedName;
13
+ exports.buildApprovalWorkflowContent = buildApprovalWorkflowContent;
14
+ exports.buildHumanApprovalWorkflowContent = buildHumanApprovalWorkflowContent;
15
+ exports.buildApprovalChatMessage = buildApprovalChatMessage;
16
+ exports.enrichCancellationWorkflowLog = enrichCancellationWorkflowLog;
17
+ exports.enrichCancellationChatMessage = enrichCancellationChatMessage;
18
+ const workflow_chat_i18n_json_1 = __importDefault(require("./workflow-chat-i18n.json"));
19
+ const WORKFLOW_TEMPLATES = workflow_chat_i18n_json_1.default.workflowTemplates;
20
+ const CHAT_TEMPLATES = workflow_chat_i18n_json_1.default.chatTemplates;
21
+ const WORKFLOW_STATUS_LABELS = workflow_chat_i18n_json_1.default.workflowStatusLabels;
22
+ const CHAT_STATUS_LABELS = workflow_chat_i18n_json_1.default.chatStatusLabels;
23
+ /** Read-only view of the shared workflow/chat translation catalog. */
24
+ function getWorkflowChatI18nCatalog() {
25
+ return workflow_chat_i18n_json_1.default;
26
+ }
27
+ function interpolate(template, params = {}) {
28
+ return template.replace(/\{\{(\w+)\}\}/g, (_, key) => params[key] ?? '');
29
+ }
30
+ function buildBilingualFromTemplate(templateCatalog, key, params = {}) {
31
+ const tpl = templateCatalog[key];
32
+ if (!tpl) {
33
+ return { en: key, ar: key };
34
+ }
35
+ return {
36
+ en: interpolate(tpl.en, params),
37
+ ar: interpolate(tpl.ar, params),
38
+ };
39
+ }
40
+ function workflowTemplate(key, params = {}) {
41
+ return buildBilingualFromTemplate(WORKFLOW_TEMPLATES, key, params);
42
+ }
43
+ function chatTemplate(key, params = {}) {
44
+ return buildBilingualFromTemplate(CHAT_TEMPLATES, key, params);
45
+ }
46
+ function resolveWorkflowStatusAr(status) {
47
+ if (status == null || status === '')
48
+ return null;
49
+ return WORKFLOW_STATUS_LABELS[status] ?? status;
50
+ }
51
+ function resolveChatStatusAr(status) {
52
+ if (status == null || status === '')
53
+ return null;
54
+ return CHAT_STATUS_LABELS[status] ?? status;
55
+ }
56
+ function pickLocalizedName(englishName, arabicName, fallback = '') {
57
+ const ar = arabicName?.trim();
58
+ if (ar)
59
+ return ar;
60
+ const en = englishName?.trim();
61
+ if (en)
62
+ return en;
63
+ return fallback;
64
+ }
65
+ function buildApprovalWorkflowContent(params) {
66
+ const nameEn = params.roleName?.trim() || '';
67
+ const nameAr = pickLocalizedName(params.roleName, params.roleArabicName, nameEn || 'Unknown');
68
+ let base;
69
+ if (params.status === 'Approved') {
70
+ base = nameEn
71
+ ? workflowTemplate('request_approved_by', { name: nameEn })
72
+ : workflowTemplate('request_approved');
73
+ if (nameEn) {
74
+ base.ar = workflowTemplate('request_approved_by', { name: nameAr }).ar;
75
+ }
76
+ }
77
+ else if (params.status === 'Rejected') {
78
+ base = nameEn
79
+ ? workflowTemplate('request_rejected_by', { name: nameEn })
80
+ : workflowTemplate('request_rejected');
81
+ if (nameEn) {
82
+ base.ar = workflowTemplate('request_rejected_by', { name: nameAr }).ar;
83
+ }
84
+ }
85
+ else {
86
+ base = nameEn
87
+ ? workflowTemplate('request_approval_pending_from', { name: nameEn })
88
+ : workflowTemplate('request_approval_pending');
89
+ if (nameEn) {
90
+ base.ar = workflowTemplate('request_approval_pending_from', { name: nameAr }).ar;
91
+ }
92
+ }
93
+ const comment = params.comment?.trim();
94
+ if (!comment)
95
+ return base;
96
+ return {
97
+ en: `${base.en}: ${comment}`,
98
+ ar: `${base.ar}: ${comment}`,
99
+ };
100
+ }
101
+ function buildHumanApprovalWorkflowContent(params) {
102
+ const nameEn = params.roleName?.trim() || params.deptSectionEn?.trim() || '';
103
+ const nameAr = params.roleName
104
+ ? pickLocalizedName(params.roleName, params.roleArabicName, nameEn)
105
+ : params.deptSectionAr?.trim() || params.deptSectionEn?.trim() || nameEn;
106
+ if (nameEn) {
107
+ const key = params.isFirst ? 'request_approval_in_progress_from' : 'request_approval_pending_from';
108
+ return {
109
+ en: workflowTemplate(key, { name: nameEn }).en,
110
+ ar: workflowTemplate(key, { name: nameAr || nameEn }).ar,
111
+ };
112
+ }
113
+ return params.isFirst
114
+ ? workflowTemplate('request_approval_in_progress')
115
+ : workflowTemplate('request_approval_pending');
116
+ }
117
+ function buildApprovalChatMessage(params) {
118
+ const roleEn = params.roleName?.trim() || 'Unknown Role';
119
+ const roleAr = pickLocalizedName(params.roleName, params.roleArabicName, roleEn);
120
+ const commentSuffix = params.comment?.trim() ? ` - ${params.comment.trim()}` : '';
121
+ const key = params.status === 'Approved' ? 'request_approved_by_role' : 'request_rejected_by_role';
122
+ return {
123
+ en: chatTemplate(key, { roleName: roleEn, comment: commentSuffix }).en,
124
+ ar: chatTemplate(key, { roleName: roleAr, comment: commentSuffix }).ar,
125
+ };
126
+ }
127
+ function enrichCancellationWorkflowLog(log) {
128
+ const status = log.status != null ? String(log.status) : null;
129
+ return {
130
+ ...log,
131
+ status_ar: log.status_ar ?? resolveWorkflowStatusAr(status),
132
+ };
133
+ }
134
+ function enrichCancellationChatMessage(chat) {
135
+ const status = chat.status != null ? String(chat.status) : null;
136
+ return {
137
+ ...chat,
138
+ status_ar: chat.status_ar ?? resolveChatStatusAr(status),
139
+ };
140
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "workflowTemplates": {
3
+ "request_submitted": {
4
+ "en": "Request Submitted",
5
+ "ar": "تم تقديم الطلب"
6
+ },
7
+ "notification_sent_pending": {
8
+ "en": "Notification sent Pending",
9
+ "ar": "في انتظار إرسال الإشعار"
10
+ },
11
+ "notification_sent_successfully": {
12
+ "en": "Notification sent successfully",
13
+ "ar": "تم إرسال الإشعار بنجاح"
14
+ },
15
+ "request_approval_in_progress": {
16
+ "en": "Request Approval In Progress",
17
+ "ar": "الموافقة على الطلب قيد التنفيذ"
18
+ },
19
+ "request_approval_pending": {
20
+ "en": "Request Approval Pending",
21
+ "ar": "في انتظار الموافقة على الطلب"
22
+ },
23
+ "request_approval_in_progress_from": {
24
+ "en": "Request Approval In Progress from {{name}}",
25
+ "ar": "الموافقة على الطلب قيد التنفيذ من {{name}}"
26
+ },
27
+ "request_approval_pending_from": {
28
+ "en": "Request Approval Pending from {{name}}",
29
+ "ar": "في انتظار موافقة {{name}}"
30
+ },
31
+ "request_approved_by": {
32
+ "en": "Request Approved by {{name}}",
33
+ "ar": "تمت الموافقة على الطلب من قبل {{name}}"
34
+ },
35
+ "request_rejected_by": {
36
+ "en": "Request Rejected by {{name}}",
37
+ "ar": "تم رفض الطلب من قبل {{name}}"
38
+ },
39
+ "request_approved": {
40
+ "en": "Request Approved",
41
+ "ar": "تمت الموافقة على الطلب"
42
+ },
43
+ "request_rejected": {
44
+ "en": "Request Rejected",
45
+ "ar": "تم رفض الطلب"
46
+ }
47
+ },
48
+ "chatTemplates": {
49
+ "cancellation_submitted_by": {
50
+ "en": "Cancellation request submitted by {{userName}} ({{employeeId}})",
51
+ "ar": "تم تقديم طلب الإلغاء بواسطة {{userName}} ({{employeeId}})"
52
+ },
53
+ "request_received": {
54
+ "en": "Request Received",
55
+ "ar": "تم استلام الطلب"
56
+ },
57
+ "request_approved_by_role": {
58
+ "en": "Request Approved by: {{roleName}}{{comment}}",
59
+ "ar": "تمت الموافقة على الطلب من قبل: {{roleName}}{{comment}}"
60
+ },
61
+ "request_rejected_by_role": {
62
+ "en": "Request Rejected by: {{roleName}}{{comment}}",
63
+ "ar": "تم رفض الطلب من قبل: {{roleName}}{{comment}}"
64
+ }
65
+ },
66
+ "workflowStatusLabels": {
67
+ "Completed": "مكتمل",
68
+ "Pending": "قيد الانتظار",
69
+ "Not Yet Started": "لم يبدأ بعد"
70
+ },
71
+ "chatStatusLabels": {
72
+ "Submitted": "تم التقديم",
73
+ "Received": "تم الاستلام",
74
+ "Approved": "موافق عليه",
75
+ "Rejected": "مرفوض",
76
+ "Pending": "قيد الانتظار"
77
+ }
78
+ }
package/dist/index.d.ts CHANGED
@@ -415,3 +415,4 @@ export * from './models/SlaApprovalsViewModel';
415
415
  export * from './models/ServiceSlaApprovalModel';
416
416
  export * from './sla/sla-table-sync.service';
417
417
  export * from './sla/sla-approval-mirror';
418
+ export * from './i18n/workflow-chat-i18n';
package/dist/index.js CHANGED
@@ -604,3 +604,4 @@ __exportStar(require("./models/SlaApprovalsViewModel"), exports);
604
604
  __exportStar(require("./models/ServiceSlaApprovalModel"), exports);
605
605
  __exportStar(require("./sla/sla-table-sync.service"), exports);
606
606
  __exportStar(require("./sla/sla-approval-mirror"), exports);
607
+ __exportStar(require("./i18n/workflow-chat-i18n"), exports);
@@ -13,6 +13,8 @@ export declare class CancellationRequestChat extends BaseModel {
13
13
  user_id: number;
14
14
  role_id: number | null;
15
15
  message: string;
16
+ message_ar: string | null;
16
17
  messageType: CancellationMessageType;
17
18
  status: string | null;
19
+ status_ar: string | null;
18
20
  }
@@ -47,6 +47,10 @@ __decorate([
47
47
  (0, typeorm_1.Column)({ type: "text", nullable: false }),
48
48
  __metadata("design:type", String)
49
49
  ], CancellationRequestChat.prototype, "message", void 0);
50
+ __decorate([
51
+ (0, typeorm_1.Column)({ type: "text", nullable: true }),
52
+ __metadata("design:type", Object)
53
+ ], CancellationRequestChat.prototype, "message_ar", void 0);
50
54
  __decorate([
51
55
  (0, typeorm_1.Column)({
52
56
  type: "enum",
@@ -60,6 +64,10 @@ __decorate([
60
64
  (0, typeorm_1.Column)({ type: "text", nullable: true }),
61
65
  __metadata("design:type", Object)
62
66
  ], CancellationRequestChat.prototype, "status", void 0);
67
+ __decorate([
68
+ (0, typeorm_1.Column)({ type: "varchar", length: 100, nullable: true }),
69
+ __metadata("design:type", Object)
70
+ ], CancellationRequestChat.prototype, "status_ar", void 0);
63
71
  exports.CancellationRequestChat = CancellationRequestChat = __decorate([
64
72
  (0, typeorm_1.Entity)({ name: "cancellation_chats" })
65
73
  ], CancellationRequestChat);
@@ -9,7 +9,9 @@ export declare class CancellationWorkFlow extends BaseModel {
9
9
  service_id: number | null;
10
10
  sub_service_id: number | null;
11
11
  content: string;
12
+ content_ar: string | null;
12
13
  status: CancellationWorkFlowStatus;
14
+ status_ar: string | null;
13
15
  user_id: number | null;
14
16
  role_id: number | null;
15
17
  department_id: number | null;
@@ -37,10 +37,18 @@ __decorate([
37
37
  (0, typeorm_1.Column)({ type: "varchar", length: 500, nullable: false }),
38
38
  __metadata("design:type", String)
39
39
  ], CancellationWorkFlow.prototype, "content", void 0);
40
+ __decorate([
41
+ (0, typeorm_1.Column)({ type: "varchar", length: 500, nullable: true }),
42
+ __metadata("design:type", Object)
43
+ ], CancellationWorkFlow.prototype, "content_ar", void 0);
40
44
  __decorate([
41
45
  (0, typeorm_1.Column)({ type: "enum", enum: CancellationWorkFlowStatus, default: CancellationWorkFlowStatus.NOT_YET_STARTED, nullable: false }),
42
46
  __metadata("design:type", String)
43
47
  ], CancellationWorkFlow.prototype, "status", void 0);
48
+ __decorate([
49
+ (0, typeorm_1.Column)({ type: "varchar", length: 100, nullable: true }),
50
+ __metadata("design:type", Object)
51
+ ], CancellationWorkFlow.prototype, "status_ar", void 0);
44
52
  __decorate([
45
53
  (0, typeorm_1.Column)({ type: "integer", nullable: true }),
46
54
  __metadata("design:type", Object)
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@platform-modules/civil-aviation-authority",
3
- "version": "2.3.274",
3
+ "version": "2.3.277",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
- "scripts": {
7
- "build": "tsc",
6
+ "scripts": {
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
9
  "sync:sla-sql": "node scripts/sync-sla-reports-sql.js"
10
10
  },
@@ -0,0 +1,10 @@
1
+ -- Pilot: Arabic columns for cancellation workflow and chat tables (CAA).
2
+ -- Run once per environment before deploying updated services.
3
+
4
+ ALTER TABLE IF EXISTS cancellation_workflows
5
+ ADD COLUMN IF NOT EXISTS content_ar VARCHAR(500) NULL,
6
+ ADD COLUMN IF NOT EXISTS status_ar VARCHAR(100) NULL;
7
+
8
+ ALTER TABLE IF EXISTS cancellation_chats
9
+ ADD COLUMN IF NOT EXISTS message_ar TEXT NULL,
10
+ ADD COLUMN IF NOT EXISTS status_ar VARCHAR(100) NULL;
@@ -0,0 +1,78 @@
1
+ {
2
+ "workflowTemplates": {
3
+ "request_submitted": {
4
+ "en": "Request Submitted",
5
+ "ar": "تم تقديم الطلب"
6
+ },
7
+ "notification_sent_pending": {
8
+ "en": "Notification sent Pending",
9
+ "ar": "في انتظار إرسال الإشعار"
10
+ },
11
+ "notification_sent_successfully": {
12
+ "en": "Notification sent successfully",
13
+ "ar": "تم إرسال الإشعار بنجاح"
14
+ },
15
+ "request_approval_in_progress": {
16
+ "en": "Request Approval In Progress",
17
+ "ar": "الموافقة على الطلب قيد التنفيذ"
18
+ },
19
+ "request_approval_pending": {
20
+ "en": "Request Approval Pending",
21
+ "ar": "في انتظار الموافقة على الطلب"
22
+ },
23
+ "request_approval_in_progress_from": {
24
+ "en": "Request Approval In Progress from {{name}}",
25
+ "ar": "الموافقة على الطلب قيد التنفيذ من {{name}}"
26
+ },
27
+ "request_approval_pending_from": {
28
+ "en": "Request Approval Pending from {{name}}",
29
+ "ar": "في انتظار موافقة {{name}}"
30
+ },
31
+ "request_approved_by": {
32
+ "en": "Request Approved by {{name}}",
33
+ "ar": "تمت الموافقة على الطلب من قبل {{name}}"
34
+ },
35
+ "request_rejected_by": {
36
+ "en": "Request Rejected by {{name}}",
37
+ "ar": "تم رفض الطلب من قبل {{name}}"
38
+ },
39
+ "request_approved": {
40
+ "en": "Request Approved",
41
+ "ar": "تمت الموافقة على الطلب"
42
+ },
43
+ "request_rejected": {
44
+ "en": "Request Rejected",
45
+ "ar": "تم رفض الطلب"
46
+ }
47
+ },
48
+ "chatTemplates": {
49
+ "cancellation_submitted_by": {
50
+ "en": "Cancellation request submitted by {{userName}} ({{employeeId}})",
51
+ "ar": "تم تقديم طلب الإلغاء بواسطة {{userName}} ({{employeeId}})"
52
+ },
53
+ "request_received": {
54
+ "en": "Request Received",
55
+ "ar": "تم استلام الطلب"
56
+ },
57
+ "request_approved_by_role": {
58
+ "en": "Request Approved by: {{roleName}}{{comment}}",
59
+ "ar": "تمت الموافقة على الطلب من قبل: {{roleName}}{{comment}}"
60
+ },
61
+ "request_rejected_by_role": {
62
+ "en": "Request Rejected by: {{roleName}}{{comment}}",
63
+ "ar": "تم رفض الطلب من قبل: {{roleName}}{{comment}}"
64
+ }
65
+ },
66
+ "workflowStatusLabels": {
67
+ "Completed": "مكتمل",
68
+ "Pending": "قيد الانتظار",
69
+ "Not Yet Started": "لم يبدأ بعد"
70
+ },
71
+ "chatStatusLabels": {
72
+ "Submitted": "تم التقديم",
73
+ "Received": "تم الاستلام",
74
+ "Approved": "موافق عليه",
75
+ "Rejected": "مرفوض",
76
+ "Pending": "قيد الانتظار"
77
+ }
78
+ }
@@ -0,0 +1,169 @@
1
+ import catalog from './workflow-chat-i18n.json';
2
+
3
+ export type BilingualText = { en: string; ar: string };
4
+
5
+ type WorkflowChatI18nCatalog = {
6
+ workflowTemplates: Record<string, BilingualText>;
7
+ chatTemplates: Record<string, BilingualText>;
8
+ workflowStatusLabels: Record<string, string>;
9
+ chatStatusLabels: Record<string, string>;
10
+ };
11
+
12
+ const WORKFLOW_TEMPLATES = catalog.workflowTemplates as Record<string, BilingualText>;
13
+ const CHAT_TEMPLATES = catalog.chatTemplates as Record<string, BilingualText>;
14
+ const WORKFLOW_STATUS_LABELS = catalog.workflowStatusLabels as Record<string, string>;
15
+ const CHAT_STATUS_LABELS = catalog.chatStatusLabels as Record<string, string>;
16
+
17
+ /** Read-only view of the shared workflow/chat translation catalog. */
18
+ export function getWorkflowChatI18nCatalog(): WorkflowChatI18nCatalog {
19
+ return catalog as WorkflowChatI18nCatalog;
20
+ }
21
+
22
+ function interpolate(template: string, params: Record<string, string> = {}): string {
23
+ return template.replace(/\{\{(\w+)\}\}/g, (_, key: string) => params[key] ?? '');
24
+ }
25
+
26
+ export function buildBilingualFromTemplate(
27
+ templateCatalog: Record<string, BilingualText>,
28
+ key: string,
29
+ params: Record<string, string> = {}
30
+ ): BilingualText {
31
+ const tpl = templateCatalog[key];
32
+ if (!tpl) {
33
+ return { en: key, ar: key };
34
+ }
35
+ return {
36
+ en: interpolate(tpl.en, params),
37
+ ar: interpolate(tpl.ar, params),
38
+ };
39
+ }
40
+
41
+ export function workflowTemplate(key: string, params: Record<string, string> = {}): BilingualText {
42
+ return buildBilingualFromTemplate(WORKFLOW_TEMPLATES, key, params);
43
+ }
44
+
45
+ export function chatTemplate(key: string, params: Record<string, string> = {}): BilingualText {
46
+ return buildBilingualFromTemplate(CHAT_TEMPLATES, key, params);
47
+ }
48
+
49
+ export function resolveWorkflowStatusAr(status: string | null | undefined): string | null {
50
+ if (status == null || status === '') return null;
51
+ return WORKFLOW_STATUS_LABELS[status] ?? status;
52
+ }
53
+
54
+ export function resolveChatStatusAr(status: string | null | undefined): string | null {
55
+ if (status == null || status === '') return null;
56
+ return CHAT_STATUS_LABELS[status] ?? status;
57
+ }
58
+
59
+ export function pickLocalizedName(
60
+ englishName?: string | null,
61
+ arabicName?: string | null,
62
+ fallback = ''
63
+ ): string {
64
+ const ar = arabicName?.trim();
65
+ if (ar) return ar;
66
+ const en = englishName?.trim();
67
+ if (en) return en;
68
+ return fallback;
69
+ }
70
+
71
+ export function buildApprovalWorkflowContent(params: {
72
+ status: 'Approved' | 'Rejected' | 'Pending' | string;
73
+ roleName?: string | null;
74
+ roleArabicName?: string | null;
75
+ comment?: string | null;
76
+ }): BilingualText {
77
+ const nameEn = params.roleName?.trim() || '';
78
+ const nameAr = pickLocalizedName(params.roleName, params.roleArabicName, nameEn || 'Unknown');
79
+
80
+ let base: BilingualText;
81
+ if (params.status === 'Approved') {
82
+ base = nameEn
83
+ ? workflowTemplate('request_approved_by', { name: nameEn })
84
+ : workflowTemplate('request_approved');
85
+ if (nameEn) {
86
+ base.ar = workflowTemplate('request_approved_by', { name: nameAr }).ar;
87
+ }
88
+ } else if (params.status === 'Rejected') {
89
+ base = nameEn
90
+ ? workflowTemplate('request_rejected_by', { name: nameEn })
91
+ : workflowTemplate('request_rejected');
92
+ if (nameEn) {
93
+ base.ar = workflowTemplate('request_rejected_by', { name: nameAr }).ar;
94
+ }
95
+ } else {
96
+ base = nameEn
97
+ ? workflowTemplate('request_approval_pending_from', { name: nameEn })
98
+ : workflowTemplate('request_approval_pending');
99
+ if (nameEn) {
100
+ base.ar = workflowTemplate('request_approval_pending_from', { name: nameAr }).ar;
101
+ }
102
+ }
103
+
104
+ const comment = params.comment?.trim();
105
+ if (!comment) return base;
106
+
107
+ return {
108
+ en: `${base.en}: ${comment}`,
109
+ ar: `${base.ar}: ${comment}`,
110
+ };
111
+ }
112
+
113
+ export function buildHumanApprovalWorkflowContent(params: {
114
+ isFirst: boolean;
115
+ roleName?: string | null;
116
+ roleArabicName?: string | null;
117
+ deptSectionEn?: string | null;
118
+ deptSectionAr?: string | null;
119
+ }): BilingualText {
120
+ const nameEn = params.roleName?.trim() || params.deptSectionEn?.trim() || '';
121
+ const nameAr = params.roleName
122
+ ? pickLocalizedName(params.roleName, params.roleArabicName, nameEn)
123
+ : params.deptSectionAr?.trim() || params.deptSectionEn?.trim() || nameEn;
124
+
125
+ if (nameEn) {
126
+ const key = params.isFirst ? 'request_approval_in_progress_from' : 'request_approval_pending_from';
127
+ return {
128
+ en: workflowTemplate(key, { name: nameEn }).en,
129
+ ar: workflowTemplate(key, { name: nameAr || nameEn }).ar,
130
+ };
131
+ }
132
+
133
+ return params.isFirst
134
+ ? workflowTemplate('request_approval_in_progress')
135
+ : workflowTemplate('request_approval_pending');
136
+ }
137
+
138
+ export function buildApprovalChatMessage(params: {
139
+ status: 'Approved' | 'Rejected' | string;
140
+ roleName?: string | null;
141
+ roleArabicName?: string | null;
142
+ comment?: string | null;
143
+ }): BilingualText {
144
+ const roleEn = params.roleName?.trim() || 'Unknown Role';
145
+ const roleAr = pickLocalizedName(params.roleName, params.roleArabicName, roleEn);
146
+ const commentSuffix = params.comment?.trim() ? ` - ${params.comment.trim()}` : '';
147
+ const key = params.status === 'Approved' ? 'request_approved_by_role' : 'request_rejected_by_role';
148
+
149
+ return {
150
+ en: chatTemplate(key, { roleName: roleEn, comment: commentSuffix }).en,
151
+ ar: chatTemplate(key, { roleName: roleAr, comment: commentSuffix }).ar,
152
+ };
153
+ }
154
+
155
+ export function enrichCancellationWorkflowLog(log: Record<string, unknown>): Record<string, unknown> {
156
+ const status = log.status != null ? String(log.status) : null;
157
+ return {
158
+ ...log,
159
+ status_ar: log.status_ar ?? resolveWorkflowStatusAr(status),
160
+ };
161
+ }
162
+
163
+ export function enrichCancellationChatMessage(chat: Record<string, unknown>): Record<string, unknown> {
164
+ const status = chat.status != null ? String(chat.status) : null;
165
+ return {
166
+ ...chat,
167
+ status_ar: chat.status_ar ?? resolveChatStatusAr(status),
168
+ };
169
+ }
package/src/index.ts CHANGED
@@ -503,4 +503,5 @@ export * from './models/SlaMyRequestsViewModel';
503
503
  export * from './models/SlaApprovalsViewModel';
504
504
  export * from './models/ServiceSlaApprovalModel';
505
505
  export * from './sla/sla-table-sync.service';
506
- export * from './sla/sla-approval-mirror';
506
+ export * from './sla/sla-approval-mirror';
507
+ export * from './i18n/workflow-chat-i18n';
@@ -29,6 +29,9 @@ export class CancellationRequestChat extends BaseModel {
29
29
  @Column({ type: "text", nullable: false })
30
30
  message: string;
31
31
 
32
+ @Column({ type: "text", nullable: true })
33
+ message_ar: string | null;
34
+
32
35
  @Column({
33
36
  type: "enum",
34
37
  enum: CancellationMessageType,
@@ -39,4 +42,7 @@ export class CancellationRequestChat extends BaseModel {
39
42
 
40
43
  @Column({ type: "text", nullable: true })
41
44
  status: string | null;
45
+
46
+ @Column({ type: "varchar", length: 100, nullable: true })
47
+ status_ar: string | null;
42
48
  }
@@ -21,9 +21,15 @@ export class CancellationWorkFlow extends BaseModel {
21
21
  @Column({ type: "varchar", length: 500, nullable: false })
22
22
  content: string;
23
23
 
24
+ @Column({ type: "varchar", length: 500, nullable: true })
25
+ content_ar: string | null;
26
+
24
27
  @Column({ type: "enum", enum: CancellationWorkFlowStatus, default: CancellationWorkFlowStatus.NOT_YET_STARTED, nullable: false })
25
28
  status: CancellationWorkFlowStatus;
26
29
 
30
+ @Column({ type: "varchar", length: 100, nullable: true })
31
+ status_ar: string | null;
32
+
27
33
  @Column({ type: "integer", nullable: true })
28
34
  user_id: number | null;
29
35
 
package/tsconfig.json CHANGED
@@ -5,6 +5,7 @@
5
5
  "declaration": true,
6
6
  "outDir": "./dist",
7
7
  "strict": true,
8
+ "resolveJsonModule": true,
8
9
  "esModuleInterop": true,
9
10
  "skipLibCheck": true,
10
11
  "strictPropertyInitialization": false,