@platform-modules/civil-aviation-authority 2.3.312 → 2.3.314

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 (74) hide show
  1. package/dist/data-source.js +2 -0
  2. package/dist/helpers/cancellation-bilingual-persist.helper.d.ts +37 -0
  3. package/dist/helpers/cancellation-bilingual-persist.helper.js +77 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +1 -0
  6. package/dist/models/IconsModel.d.ts +7 -0
  7. package/dist/models/IconsModel.js +39 -0
  8. package/dist/models/SlaApprovalsViewModel.js +54 -54
  9. package/dist/models/importantLinksModel.d.ts +1 -0
  10. package/dist/models/importantLinksModel.js +5 -0
  11. package/package.json +1 -1
  12. package/scripts/sync-sla-reports-sql.js +92 -92
  13. package/sql/README.md +21 -21
  14. package/sql/add_important_links_icon_id.sql +17 -0
  15. package/sql/create_icons.sql +21 -0
  16. package/sql/sla_reports_admin_procedures.sql +322 -323
  17. package/sql/sla_reports_approvals_workbook.sql +427 -430
  18. package/sql/sla_reports_procedures.sql +883 -886
  19. package/sql/vw_sla_approvals.sql +115 -115
  20. package/sql/vw_sla_my_requests.sql +58 -58
  21. package/src/data-source.ts +2 -0
  22. package/src/index.ts +1 -0
  23. package/src/models/AccessCardRequestModel.ts +135 -135
  24. package/src/models/AirportEntryPermitModel.ts +276 -276
  25. package/src/models/AnnualTrainingPlanRequestModel.ts +153 -153
  26. package/src/models/DocumentDriveModel.ts +28 -28
  27. package/src/models/DocumentFolderModel.ts +45 -45
  28. package/src/models/HotelApprovalModel.ts +83 -83
  29. package/src/models/HousingContractCancelApprovalModel.ts +64 -64
  30. package/src/models/HousingContractRenewalApprovalModel.ts +64 -64
  31. package/src/models/ITRequestAttachmentModel.ts +73 -73
  32. package/src/models/IconsModel.ts +21 -0
  33. package/src/models/ItApprovalsModel.ts +84 -84
  34. package/src/models/LegalConsultationApprovalModel.ts +65 -65
  35. package/src/models/MissionTravelPassportExpiryNotificationConfigModel.ts +36 -36
  36. package/src/models/NotificationModel.ts +89 -89
  37. package/src/models/ResidentialUnitRentalApprovalModel.ts +143 -143
  38. package/src/models/ServiceExtensionAfter60ApprovalModel.ts +87 -87
  39. package/src/models/ServiceSlaApprovalModel.ts +64 -64
  40. package/src/models/ServicesNotificationConfigModel.ts +55 -55
  41. package/src/models/SlaApprovalsViewModel.ts +142 -142
  42. package/src/models/StudyLeaveRequestModel.ts +144 -144
  43. package/src/models/TrainingRequestModel.ts +164 -164
  44. package/src/models/TrainingRoomBookingRequestModel.ts +142 -142
  45. package/src/models/TrainingRoomNotificationConfigModel.ts +30 -30
  46. package/src/models/importantLinksModel.ts +4 -0
  47. package/src/models/role.ts +34 -34
  48. package/src/sla/sla-table-sync.service.ts +90 -90
  49. package/dist/models/DocumentMetadataModel.d.ts +0 -45
  50. package/dist/models/DocumentMetadataModel.js +0 -171
  51. package/dist/models/DocumentationDepartmentsModel.d.ts +0 -13
  52. package/dist/models/DocumentationDepartmentsModel.js +0 -53
  53. package/dist/models/FolderModel.d.ts +0 -16
  54. package/dist/models/FolderModel.js +0 -85
  55. package/dist/models/ImportExportMaterialModels.d.ts +0 -92
  56. package/dist/models/ImportExportMaterialModels.js +0 -307
  57. package/dist/models/PermissionModel.d.ts +0 -18
  58. package/dist/models/PermissionModel.js +0 -68
  59. package/dist/models/SecurityAccessApprovalModel.d.ts +0 -23
  60. package/dist/models/SecurityAccessApprovalModel.js +0 -82
  61. package/dist/models/SecurityAccessAttachmentModel.d.ts +0 -12
  62. package/dist/models/SecurityAccessAttachmentModel.js +0 -56
  63. package/dist/models/SecurityAccessChatModel.d.ts +0 -12
  64. package/dist/models/SecurityAccessChatModel.js +0 -56
  65. package/dist/models/SecurityAccessRequestModel.d.ts +0 -25
  66. package/dist/models/SecurityAccessRequestModel.js +0 -80
  67. package/dist/models/SecurityAccessWorkflowModel.d.ts +0 -24
  68. package/dist/models/SecurityAccessWorkflowModel.js +0 -84
  69. package/dist/models/ServiceExtensionAfterAge60Models.d.ts +0 -93
  70. package/dist/models/ServiceExtensionAfterAge60Models.js +0 -312
  71. package/dist/models/UUIDBaseModel.d.ts +0 -14
  72. package/dist/models/UUIDBaseModel.js +0 -66
  73. package/dist/models/WorkingHoursExtensionModels.d.ts +0 -88
  74. package/dist/models/WorkingHoursExtensionModels.js +0 -295
@@ -1,323 +1,322 @@
1
- -- Admin SLA reports + approvals Excel export
2
- -- Prerequisites: sla_reports_procedures.sql, vw_sla_my_requests.sql, vw_sla_approvals.sql
3
- -- Applied via: npm run sync:sla-sql (after sla_reports_procedures.sql in manifest)
4
-
5
- CREATE OR REPLACE FUNCTION sla_filtered_request_fields(p_request_obj JSONB)
6
- RETURNS JSONB
7
- LANGUAGE sql
8
- IMMUTABLE
9
- AS $$
10
- SELECT
11
- COALESCE(p_request_obj, '{}'::jsonb)
12
- - 'id' - 'status' - 'role_id' - 'user_id' - 'createdBy' - 'created_at'
13
- - 'updated_by' - 'updated_at' - 'req_user_department_id' - 'workflow_execution_id'
14
- - 'department_id' - 'req_user_section_id' - 'service_type_id' - 'service_type'
15
- - 'created_by' - 'service_id' - 'sub_service_id' - 'attachments'
16
- - 'is_deleted' - 'sla_request' - 'sla_request_id';
17
- $$;
18
-
19
- -- Admin list views: served by Reports_Service TypeORM (sla-my-requests-view.query.ts, sla-approvals-view.query.ts)
20
-
21
- -- ---------------------------------------------------------------------------
22
- -- ADMIN — my requests Excel (optional p_target_user_ids INT[])
23
- -- Per sub-service Requests + Approvals sheets (same as user my-requests download)
24
- -- ---------------------------------------------------------------------------
25
- DROP FUNCTION IF EXISTS sp_sla_admin_my_requests_excel_export(INT, INT[], INT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT);
26
- DROP FUNCTION IF EXISTS sp_sla_admin_my_requests_excel_export(INT, INT[], INT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT, TEXT);
27
- DROP FUNCTION IF EXISTS sp_sla_admin_my_requests_excel_export(INT[], INT[], INT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT, TEXT);
28
-
29
- CREATE OR REPLACE FUNCTION sp_sla_admin_my_requests_excel_export(
30
- p_target_user_ids INT[] DEFAULT NULL,
31
- p_service_ids INT[] DEFAULT NULL,
32
- p_sub_service_ids INT[] DEFAULT NULL,
33
- p_statuses TEXT[] DEFAULT ARRAY['Pending','In Progress','Approved','Rejected'],
34
- p_from_date DATE DEFAULT NULL,
35
- p_to_date DATE DEFAULT NULL,
36
- p_search_text TEXT DEFAULT NULL,
37
- p_sort_by TEXT DEFAULT 'created_at',
38
- p_sort_order TEXT DEFAULT 'DESC',
39
- p_extra_filter_sql TEXT DEFAULT 'TRUE'
40
- )
41
- RETURNS TABLE (
42
- sheet_order INT,
43
- sub_service_id INT,
44
- sub_service_name TEXT,
45
- sheet_name TEXT,
46
- headers JSONB,
47
- rows JSONB
48
- )
49
- LANGUAGE plpgsql
50
- STABLE
51
- AS $$
52
- DECLARE
53
- v_sort_col TEXT;
54
- v_sort_dir TEXT;
55
- v_sub RECORD;
56
- v_row RECORD;
57
- v_dyn_keys TEXT[];
58
- v_dyn_labels TEXT[];
59
- v_common_labels TEXT[] := ARRAY[
60
- 'SLA Request ID', 'Request ID', 'User', 'Status', 'Created At',
61
- 'Created By', 'Department', 'Section'
62
- ];
63
- v_headers_labels TEXT[];
64
- v_headers_json JSONB;
65
- v_cells TEXT[];
66
- v_all_rows JSONB;
67
- v_k TEXT;
68
- v_sheet_order INT := 0;
69
- v_user_filter TEXT;
70
- v_user_scope TEXT;
71
- BEGIN
72
- IF p_target_user_ids IS NULL OR cardinality(p_target_user_ids) = 0 THEN
73
- v_user_scope := 'TRUE';
74
- ELSE
75
- -- Validated positive ints from app; format as int array literal for ANY()
76
- v_user_scope := format(
77
- 'v.user_id = ANY (ARRAY[%s]::int[])',
78
- array_to_string(p_target_user_ids, ',')
79
- );
80
- END IF;
81
-
82
- v_user_filter := format(
83
- '(%s) AND (%s)',
84
- v_user_scope,
85
- COALESCE(NULLIF(trim(p_extra_filter_sql), ''), 'TRUE')
86
- );
87
-
88
- v_sort_col := CASE lower(trim(p_sort_by))
89
- WHEN 'updated_at' THEN 'v.created_at'
90
- WHEN 'id' THEN 'v.sla_request_id'
91
- WHEN 'status' THEN 'v.status'
92
- WHEN 'request_id' THEN 'v.request_id'
93
- ELSE 'v.created_at'
94
- END;
95
- v_sort_dir := CASE WHEN upper(trim(p_sort_order)) = 'ASC' THEN 'ASC' ELSE 'DESC' END;
96
-
97
- FOR v_sub IN
98
- EXECUTE format($q$
99
- SELECT DISTINCT
100
- COALESCE(sr.sub_service_id, 0) AS sub_service_id_num,
101
- COALESCE(NULLIF(trim(subsvc.sub_service_name), ''), NULLIF(trim(v.sub_service_name), ''), 'Uncategorized') AS sub_service_name
102
- FROM vw_sla_my_requests v
103
- INNER JOIN sla_requests sr ON sr.id = v.sla_request_id AND COALESCE(sr.is_deleted, false) = false
104
- LEFT JOIN caa_sub_services subsvc ON subsvc.id = sr.sub_service_id
105
- WHERE %s
106
- AND v.status = ANY($1)
107
- AND ($2 IS NULL OR cardinality($2) = 0 OR sr.service_id = ANY($2))
108
- AND ($3 IS NULL OR cardinality($3) = 0 OR sr.sub_service_id = ANY($3))
109
- AND ($4 IS NULL OR v.created_at::date >= $4)
110
- AND ($5 IS NULL OR v.created_at::date <= $5)
111
- AND ($6 IS NULL OR trim($6) = '' OR CAST(v.request_id AS TEXT) ILIKE '%%' || trim($6) || '%%')
112
- ORDER BY sub_service_name ASC
113
- $q$, v_user_filter)
114
- USING p_statuses, p_service_ids, p_sub_service_ids, p_from_date, p_to_date, p_search_text
115
- LOOP
116
- v_sheet_order := v_sheet_order + 1;
117
-
118
- EXECUTE format($q$
119
- SELECT COALESCE(array_agg(DISTINCT keys.k ORDER BY keys.k), ARRAY[]::TEXT[])
120
- FROM vw_sla_my_requests v
121
- INNER JOIN sla_requests sr ON sr.id = v.sla_request_id AND COALESCE(sr.is_deleted, false) = false
122
- CROSS JOIN LATERAL jsonb_object_keys(COALESCE(v.request_fields, '{}'::jsonb)) AS keys(k)
123
- WHERE %s
124
- AND v.status = ANY($1)
125
- AND ($2 IS NULL OR cardinality($2) = 0 OR sr.service_id = ANY($2))
126
- AND ($3 IS NULL OR cardinality($3) = 0 OR sr.sub_service_id = ANY($3))
127
- AND ($4 IS NULL OR v.created_at::date >= $4)
128
- AND ($5 IS NULL OR v.created_at::date <= $5)
129
- AND ($6 IS NULL OR trim($6) = '' OR CAST(v.request_id AS TEXT) ILIKE '%%' || trim($6) || '%%')
130
- AND COALESCE(sr.sub_service_id, 0) = %s
131
- $q$, v_user_filter, v_sub.sub_service_id_num)
132
- INTO v_dyn_keys
133
- USING p_statuses, p_service_ids, p_sub_service_ids, p_from_date, p_to_date, p_search_text;
134
-
135
- v_dyn_labels := ARRAY[]::TEXT[];
136
- IF v_dyn_keys IS NOT NULL THEN
137
- FOREACH v_k IN ARRAY v_dyn_keys LOOP
138
- v_dyn_labels := array_append(v_dyn_labels, sla_excel_header_label(v_k));
139
- END LOOP;
140
- END IF;
141
-
142
- v_headers_labels := ARRAY(
143
- SELECT sla_excel_header_label(lbl)
144
- FROM unnest(v_common_labels || COALESCE(v_dyn_labels, ARRAY[]::TEXT[])) AS u(lbl)
145
- );
146
- v_headers_json := to_jsonb(v_headers_labels);
147
- v_all_rows := '[]'::jsonb;
148
-
149
- FOR v_row IN
150
- EXECUTE format($q$
151
- SELECT
152
- v.sla_request_id, v.request_id, v.status, v.created_at, v.created_by,
153
- v.req_user_department_id, v.req_user_section_id, v.request_fields,
154
- TRIM(COALESCE(u.employee_name, '')) AS user_name
155
- FROM vw_sla_my_requests v
156
- INNER JOIN sla_requests sr ON sr.id = v.sla_request_id AND COALESCE(sr.is_deleted, false) = false
157
- LEFT JOIN users u ON u.id = v.user_id AND COALESCE(u.is_deleted, false) = false
158
- WHERE %s
159
- AND v.status = ANY($1)
160
- AND ($2 IS NULL OR cardinality($2) = 0 OR sr.service_id = ANY($2))
161
- AND ($3 IS NULL OR cardinality($3) = 0 OR sr.sub_service_id = ANY($3))
162
- AND ($4 IS NULL OR v.created_at::date >= $4)
163
- AND ($5 IS NULL OR v.created_at::date <= $5)
164
- AND ($6 IS NULL OR trim($6) = '' OR CAST(v.request_id AS TEXT) ILIKE '%%' || trim($6) || '%%')
165
- AND COALESCE(sr.sub_service_id, 0) = %s
166
- ORDER BY %s %s, v.sla_request_id ASC
167
- $q$, v_user_filter, v_sub.sub_service_id_num, v_sort_col, v_sort_dir)
168
- USING p_statuses, p_service_ids, p_sub_service_ids, p_from_date, p_to_date, p_search_text
169
- LOOP
170
- v_cells := ARRAY[
171
- COALESCE(v_row.sla_request_id::TEXT, ''),
172
- COALESCE(v_row.request_id::TEXT, ''),
173
- COALESCE(v_row.user_name, ''),
174
- COALESCE(v_row.status, ''),
175
- COALESCE(to_char(v_row.created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS'), ''),
176
- COALESCE(v_row.created_by, ''),
177
- COALESCE(v_row.req_user_department_id, ''),
178
- COALESCE(v_row.req_user_section_id, '')
179
- ];
180
- IF v_dyn_keys IS NOT NULL THEN
181
- FOREACH v_k IN ARRAY v_dyn_keys LOOP
182
- v_cells := array_append(v_cells, COALESCE(sla_request_field_cell(v_row.request_fields, v_k), ''));
183
- END LOOP;
184
- END IF;
185
- v_all_rows := v_all_rows || jsonb_build_array(to_jsonb(v_cells));
186
- END LOOP;
187
-
188
- sheet_order := v_sheet_order;
189
- sub_service_id := NULLIF(v_sub.sub_service_id_num, 0);
190
- sub_service_name := v_sub.sub_service_name;
191
- sheet_name := sla_excel_sheet_name(v_sub.sub_service_name);
192
- headers := v_headers_json;
193
- rows := v_all_rows;
194
- RETURN NEXT;
195
- END LOOP;
196
-
197
- RETURN QUERY
198
- SELECT *
199
- FROM sla_my_requests_approvals_excel_sheet(
200
- v_user_filter,
201
- p_statuses,
202
- p_service_ids,
203
- p_sub_service_ids,
204
- p_from_date,
205
- p_to_date,
206
- p_search_text,
207
- v_sheet_order + 1
208
- );
209
-
210
- RETURN;
211
- END;
212
- $$;
213
-
214
- -- ---------------------------------------------------------------------------
215
- -- APPROVALS Excel export (approver-scoped; user download)
216
- -- Workbook: per sub-service Requests + Approvals (see sla_reports_approvals_workbook.sql)
217
- -- ---------------------------------------------------------------------------
218
- DROP FUNCTION IF EXISTS sp_sla_approvals_excel_export_internal(
219
- TEXT, BOOLEAN, INT, INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT
220
- );
221
-
222
- DROP FUNCTION IF EXISTS sp_sla_approvals_excel_export(
223
- INT, INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT
224
- );
225
-
226
- CREATE OR REPLACE FUNCTION sp_sla_approvals_excel_export(
227
- p_approver_user_id INT,
228
- p_service_ids INT[] DEFAULT NULL,
229
- p_sub_service_ids INT[] DEFAULT NULL,
230
- p_request_statuses TEXT[] DEFAULT ARRAY['Pending','In Progress','Approved','Rejected'],
231
- p_approval_statuses TEXT[] DEFAULT ARRAY['In Progress','Approved','Rejected'],
232
- p_from_date DATE DEFAULT NULL,
233
- p_to_date DATE DEFAULT NULL,
234
- p_search_text TEXT DEFAULT NULL,
235
- p_sort_by TEXT DEFAULT 'created_at',
236
- p_sort_order TEXT DEFAULT 'DESC',
237
- p_extra_filter_sql TEXT DEFAULT 'TRUE'
238
- )
239
- RETURNS TABLE (
240
- sheet_order INT, sub_service_id INT, sub_service_name TEXT, sheet_name TEXT, headers JSONB, rows JSONB
241
- )
242
- LANGUAGE plpgsql
243
- STABLE
244
- AS $$
245
- DECLARE
246
- v_exists TEXT := sla_approval_queue_exists_sql(p_approver_user_id);
247
- v_own TEXT := format(
248
- '(%s) AND (%s)',
249
- format('sr.user_id != %s', p_approver_user_id),
250
- COALESCE(NULLIF(trim(p_extra_filter_sql), ''), 'TRUE')
251
- );
252
- BEGIN
253
- RETURN QUERY
254
- SELECT * FROM sp_sla_approvals_workbook_excel_export(
255
- v_exists,
256
- v_own,
257
- p_service_ids,
258
- p_sub_service_ids,
259
- p_request_statuses,
260
- p_approval_statuses,
261
- p_from_date,
262
- p_to_date,
263
- p_search_text,
264
- p_sort_by,
265
- p_sort_order
266
- );
267
- END;
268
- $$;
269
-
270
- -- ---------------------------------------------------------------------------
271
- -- ADMIN approvals Excel
272
- -- Per sub-service Requests + Approvals; optional approver user id(s) (NULL/empty = all queues)
273
- -- Does not exclude own requests (unlike user approvals download)
274
- -- ---------------------------------------------------------------------------
275
- DROP FUNCTION IF EXISTS sp_sla_admin_approvals_excel_export(
276
- INT, INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT
277
- );
278
- DROP FUNCTION IF EXISTS sp_sla_admin_approvals_excel_export(
279
- INT, INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT, TEXT
280
- );
281
- DROP FUNCTION IF EXISTS sp_sla_admin_approvals_excel_export(
282
- INT[], INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT, TEXT
283
- );
284
-
285
- CREATE OR REPLACE FUNCTION sp_sla_admin_approvals_excel_export(
286
- p_target_approver_user_ids INT[] DEFAULT NULL,
287
- p_service_ids INT[] DEFAULT NULL,
288
- p_sub_service_ids INT[] DEFAULT NULL,
289
- p_request_statuses TEXT[] DEFAULT ARRAY['Pending','In Progress','Approved','Rejected'],
290
- p_approval_statuses TEXT[] DEFAULT ARRAY['In Progress','Approved','Rejected'],
291
- p_from_date DATE DEFAULT NULL,
292
- p_to_date DATE DEFAULT NULL,
293
- p_search_text TEXT DEFAULT NULL,
294
- p_sort_by TEXT DEFAULT 'created_at',
295
- p_sort_order TEXT DEFAULT 'DESC',
296
- p_extra_filter_sql TEXT DEFAULT 'TRUE'
297
- )
298
- RETURNS TABLE (
299
- sheet_order INT, sub_service_id INT, sub_service_name TEXT, sheet_name TEXT, headers JSONB, rows JSONB
300
- )
301
- LANGUAGE plpgsql
302
- STABLE
303
- AS $$
304
- DECLARE
305
- v_exists TEXT := sla_approval_queue_exists_sql_any(p_target_approver_user_ids);
306
- v_own TEXT := COALESCE(NULLIF(trim(p_extra_filter_sql), ''), 'TRUE');
307
- BEGIN
308
- RETURN QUERY
309
- SELECT * FROM sp_sla_approvals_workbook_excel_export(
310
- v_exists,
311
- v_own,
312
- p_service_ids,
313
- p_sub_service_ids,
314
- p_request_statuses,
315
- p_approval_statuses,
316
- p_from_date,
317
- p_to_date,
318
- p_search_text,
319
- p_sort_by,
320
- p_sort_order
321
- );
322
- END;
323
- $$;
1
+ -- Admin SLA reports + approvals Excel export
2
+ -- Prerequisites: sla_reports_procedures.sql, vw_sla_my_requests.sql, vw_sla_approvals.sql
3
+ -- Applied via: npm run sync:sla-sql (after sla_reports_procedures.sql in manifest)
4
+
5
+ CREATE OR REPLACE FUNCTION sla_filtered_request_fields(p_request_obj JSONB)
6
+ RETURNS JSONB
7
+ LANGUAGE sql
8
+ IMMUTABLE
9
+ AS $$
10
+ SELECT
11
+ COALESCE(p_request_obj, '{}'::jsonb)
12
+ - 'id' - 'status' - 'role_id' - 'user_id' - 'createdBy' - 'created_at'
13
+ - 'updated_by' - 'updated_at' - 'req_user_department_id' - 'workflow_execution_id'
14
+ - 'department_id' - 'req_user_section_id' - 'service_type_id' - 'service_type'
15
+ - 'created_by' - 'service_id' - 'sub_service_id' - 'attachments'
16
+ - 'is_deleted' - 'sla_request' - 'sla_request_id';
17
+ $$;
18
+
19
+ -- Admin list views: served by Reports_Service TypeORM (sla-my-requests-view.query.ts, sla-approvals-view.query.ts)
20
+
21
+ -- ---------------------------------------------------------------------------
22
+ -- ADMIN — my requests Excel (optional p_target_user_ids INT[])
23
+ -- Per sub-service Requests + Approvals sheets (same as user my-requests download)
24
+ -- ---------------------------------------------------------------------------
25
+ DROP FUNCTION IF EXISTS sp_sla_admin_my_requests_excel_export(INT, INT[], INT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT);
26
+ DROP FUNCTION IF EXISTS sp_sla_admin_my_requests_excel_export(INT, INT[], INT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT, TEXT);
27
+ DROP FUNCTION IF EXISTS sp_sla_admin_my_requests_excel_export(INT[], INT[], INT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT, TEXT);
28
+
29
+ CREATE OR REPLACE FUNCTION sp_sla_admin_my_requests_excel_export(
30
+ p_target_user_ids INT[] DEFAULT NULL,
31
+ p_service_ids INT[] DEFAULT NULL,
32
+ p_sub_service_ids INT[] DEFAULT NULL,
33
+ p_statuses TEXT[] DEFAULT ARRAY['Pending','In Progress','Approved','Rejected'],
34
+ p_from_date DATE DEFAULT NULL,
35
+ p_to_date DATE DEFAULT NULL,
36
+ p_search_text TEXT DEFAULT NULL,
37
+ p_sort_by TEXT DEFAULT 'created_at',
38
+ p_sort_order TEXT DEFAULT 'DESC',
39
+ p_extra_filter_sql TEXT DEFAULT 'TRUE'
40
+ )
41
+ RETURNS TABLE (
42
+ sheet_order INT,
43
+ sub_service_id INT,
44
+ sub_service_name TEXT,
45
+ sheet_name TEXT,
46
+ headers JSONB,
47
+ rows JSONB
48
+ )
49
+ LANGUAGE plpgsql
50
+ STABLE
51
+ AS $$
52
+ DECLARE
53
+ v_sort_col TEXT;
54
+ v_sort_dir TEXT;
55
+ v_sub RECORD;
56
+ v_row RECORD;
57
+ v_dyn_keys TEXT[];
58
+ v_dyn_labels TEXT[];
59
+ v_common_labels TEXT[] := ARRAY[
60
+ 'Request ID', 'User', 'Status', 'Created At',
61
+ 'Created By', 'Department', 'Section'
62
+ ];
63
+ v_headers_labels TEXT[];
64
+ v_headers_json JSONB;
65
+ v_cells TEXT[];
66
+ v_all_rows JSONB;
67
+ v_k TEXT;
68
+ v_sheet_order INT := 0;
69
+ v_user_filter TEXT;
70
+ v_user_scope TEXT;
71
+ BEGIN
72
+ IF p_target_user_ids IS NULL OR cardinality(p_target_user_ids) = 0 THEN
73
+ v_user_scope := 'TRUE';
74
+ ELSE
75
+ -- Validated positive ints from app; format as int array literal for ANY()
76
+ v_user_scope := format(
77
+ 'v.user_id = ANY (ARRAY[%s]::int[])',
78
+ array_to_string(p_target_user_ids, ',')
79
+ );
80
+ END IF;
81
+
82
+ v_user_filter := format(
83
+ '(%s) AND (%s)',
84
+ v_user_scope,
85
+ COALESCE(NULLIF(trim(p_extra_filter_sql), ''), 'TRUE')
86
+ );
87
+
88
+ v_sort_col := CASE lower(trim(p_sort_by))
89
+ WHEN 'updated_at' THEN 'v.created_at'
90
+ WHEN 'id' THEN 'v.sla_request_id'
91
+ WHEN 'status' THEN 'v.status'
92
+ WHEN 'request_id' THEN 'v.request_id'
93
+ ELSE 'v.created_at'
94
+ END;
95
+ v_sort_dir := CASE WHEN upper(trim(p_sort_order)) = 'ASC' THEN 'ASC' ELSE 'DESC' END;
96
+
97
+ FOR v_sub IN
98
+ EXECUTE format($q$
99
+ SELECT DISTINCT
100
+ COALESCE(sr.sub_service_id, 0) AS sub_service_id_num,
101
+ COALESCE(NULLIF(trim(subsvc.sub_service_name), ''), NULLIF(trim(v.sub_service_name), ''), 'Uncategorized') AS sub_service_name
102
+ FROM vw_sla_my_requests v
103
+ INNER JOIN sla_requests sr ON sr.id = v.sla_request_id AND COALESCE(sr.is_deleted, false) = false
104
+ LEFT JOIN caa_sub_services subsvc ON subsvc.id = sr.sub_service_id
105
+ WHERE %s
106
+ AND v.status = ANY($1)
107
+ AND ($2 IS NULL OR cardinality($2) = 0 OR sr.service_id = ANY($2))
108
+ AND ($3 IS NULL OR cardinality($3) = 0 OR sr.sub_service_id = ANY($3))
109
+ AND ($4 IS NULL OR v.created_at::date >= $4)
110
+ AND ($5 IS NULL OR v.created_at::date <= $5)
111
+ AND ($6 IS NULL OR trim($6) = '' OR CAST(v.request_id AS TEXT) ILIKE '%%' || trim($6) || '%%')
112
+ ORDER BY sub_service_name ASC
113
+ $q$, v_user_filter)
114
+ USING p_statuses, p_service_ids, p_sub_service_ids, p_from_date, p_to_date, p_search_text
115
+ LOOP
116
+ v_sheet_order := v_sheet_order + 1;
117
+
118
+ EXECUTE format($q$
119
+ SELECT COALESCE(array_agg(DISTINCT keys.k ORDER BY keys.k), ARRAY[]::TEXT[])
120
+ FROM vw_sla_my_requests v
121
+ INNER JOIN sla_requests sr ON sr.id = v.sla_request_id AND COALESCE(sr.is_deleted, false) = false
122
+ CROSS JOIN LATERAL jsonb_object_keys(COALESCE(v.request_fields, '{}'::jsonb)) AS keys(k)
123
+ WHERE %s
124
+ AND v.status = ANY($1)
125
+ AND ($2 IS NULL OR cardinality($2) = 0 OR sr.service_id = ANY($2))
126
+ AND ($3 IS NULL OR cardinality($3) = 0 OR sr.sub_service_id = ANY($3))
127
+ AND ($4 IS NULL OR v.created_at::date >= $4)
128
+ AND ($5 IS NULL OR v.created_at::date <= $5)
129
+ AND ($6 IS NULL OR trim($6) = '' OR CAST(v.request_id AS TEXT) ILIKE '%%' || trim($6) || '%%')
130
+ AND COALESCE(sr.sub_service_id, 0) = %s
131
+ $q$, v_user_filter, v_sub.sub_service_id_num)
132
+ INTO v_dyn_keys
133
+ USING p_statuses, p_service_ids, p_sub_service_ids, p_from_date, p_to_date, p_search_text;
134
+
135
+ v_dyn_labels := ARRAY[]::TEXT[];
136
+ IF v_dyn_keys IS NOT NULL THEN
137
+ FOREACH v_k IN ARRAY v_dyn_keys LOOP
138
+ v_dyn_labels := array_append(v_dyn_labels, sla_excel_header_label(v_k));
139
+ END LOOP;
140
+ END IF;
141
+
142
+ v_headers_labels := ARRAY(
143
+ SELECT sla_excel_header_label(lbl)
144
+ FROM unnest(v_common_labels || COALESCE(v_dyn_labels, ARRAY[]::TEXT[])) AS u(lbl)
145
+ );
146
+ v_headers_json := to_jsonb(v_headers_labels);
147
+ v_all_rows := '[]'::jsonb;
148
+
149
+ FOR v_row IN
150
+ EXECUTE format($q$
151
+ SELECT
152
+ v.sla_request_id, v.request_id, v.status, v.created_at, v.created_by,
153
+ v.req_user_department_id, v.req_user_section_id, v.request_fields,
154
+ TRIM(COALESCE(u.employee_name, '')) AS user_name
155
+ FROM vw_sla_my_requests v
156
+ INNER JOIN sla_requests sr ON sr.id = v.sla_request_id AND COALESCE(sr.is_deleted, false) = false
157
+ LEFT JOIN users u ON u.id = v.user_id AND COALESCE(u.is_deleted, false) = false
158
+ WHERE %s
159
+ AND v.status = ANY($1)
160
+ AND ($2 IS NULL OR cardinality($2) = 0 OR sr.service_id = ANY($2))
161
+ AND ($3 IS NULL OR cardinality($3) = 0 OR sr.sub_service_id = ANY($3))
162
+ AND ($4 IS NULL OR v.created_at::date >= $4)
163
+ AND ($5 IS NULL OR v.created_at::date <= $5)
164
+ AND ($6 IS NULL OR trim($6) = '' OR CAST(v.request_id AS TEXT) ILIKE '%%' || trim($6) || '%%')
165
+ AND COALESCE(sr.sub_service_id, 0) = %s
166
+ ORDER BY %s %s, v.sla_request_id ASC
167
+ $q$, v_user_filter, v_sub.sub_service_id_num, v_sort_col, v_sort_dir)
168
+ USING p_statuses, p_service_ids, p_sub_service_ids, p_from_date, p_to_date, p_search_text
169
+ LOOP
170
+ v_cells := ARRAY[
171
+ COALESCE(v_row.request_id::TEXT, ''),
172
+ COALESCE(v_row.user_name, ''),
173
+ COALESCE(v_row.status, ''),
174
+ COALESCE(to_char(v_row.created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS'), ''),
175
+ COALESCE(v_row.created_by, ''),
176
+ COALESCE(v_row.req_user_department_id, ''),
177
+ COALESCE(v_row.req_user_section_id, '')
178
+ ];
179
+ IF v_dyn_keys IS NOT NULL THEN
180
+ FOREACH v_k IN ARRAY v_dyn_keys LOOP
181
+ v_cells := array_append(v_cells, COALESCE(sla_request_field_cell(v_row.request_fields, v_k), ''));
182
+ END LOOP;
183
+ END IF;
184
+ v_all_rows := v_all_rows || jsonb_build_array(to_jsonb(v_cells));
185
+ END LOOP;
186
+
187
+ sheet_order := v_sheet_order;
188
+ sub_service_id := NULLIF(v_sub.sub_service_id_num, 0);
189
+ sub_service_name := v_sub.sub_service_name;
190
+ sheet_name := sla_excel_sheet_name(v_sub.sub_service_name);
191
+ headers := v_headers_json;
192
+ rows := v_all_rows;
193
+ RETURN NEXT;
194
+ END LOOP;
195
+
196
+ RETURN QUERY
197
+ SELECT *
198
+ FROM sla_my_requests_approvals_excel_sheet(
199
+ v_user_filter,
200
+ p_statuses,
201
+ p_service_ids,
202
+ p_sub_service_ids,
203
+ p_from_date,
204
+ p_to_date,
205
+ p_search_text,
206
+ v_sheet_order + 1
207
+ );
208
+
209
+ RETURN;
210
+ END;
211
+ $$;
212
+
213
+ -- ---------------------------------------------------------------------------
214
+ -- APPROVALS — Excel export (approver-scoped; user download)
215
+ -- Workbook: per sub-service Requests + Approvals (see sla_reports_approvals_workbook.sql)
216
+ -- ---------------------------------------------------------------------------
217
+ DROP FUNCTION IF EXISTS sp_sla_approvals_excel_export_internal(
218
+ TEXT, BOOLEAN, INT, INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT
219
+ );
220
+
221
+ DROP FUNCTION IF EXISTS sp_sla_approvals_excel_export(
222
+ INT, INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT
223
+ );
224
+
225
+ CREATE OR REPLACE FUNCTION sp_sla_approvals_excel_export(
226
+ p_approver_user_id INT,
227
+ p_service_ids INT[] DEFAULT NULL,
228
+ p_sub_service_ids INT[] DEFAULT NULL,
229
+ p_request_statuses TEXT[] DEFAULT ARRAY['Pending','In Progress','Approved','Rejected'],
230
+ p_approval_statuses TEXT[] DEFAULT ARRAY['In Progress','Approved','Rejected'],
231
+ p_from_date DATE DEFAULT NULL,
232
+ p_to_date DATE DEFAULT NULL,
233
+ p_search_text TEXT DEFAULT NULL,
234
+ p_sort_by TEXT DEFAULT 'created_at',
235
+ p_sort_order TEXT DEFAULT 'DESC',
236
+ p_extra_filter_sql TEXT DEFAULT 'TRUE'
237
+ )
238
+ RETURNS TABLE (
239
+ sheet_order INT, sub_service_id INT, sub_service_name TEXT, sheet_name TEXT, headers JSONB, rows JSONB
240
+ )
241
+ LANGUAGE plpgsql
242
+ STABLE
243
+ AS $$
244
+ DECLARE
245
+ v_exists TEXT := sla_approval_queue_exists_sql(p_approver_user_id);
246
+ v_own TEXT := format(
247
+ '(%s) AND (%s)',
248
+ format('sr.user_id != %s', p_approver_user_id),
249
+ COALESCE(NULLIF(trim(p_extra_filter_sql), ''), 'TRUE')
250
+ );
251
+ BEGIN
252
+ RETURN QUERY
253
+ SELECT * FROM sp_sla_approvals_workbook_excel_export(
254
+ v_exists,
255
+ v_own,
256
+ p_service_ids,
257
+ p_sub_service_ids,
258
+ p_request_statuses,
259
+ p_approval_statuses,
260
+ p_from_date,
261
+ p_to_date,
262
+ p_search_text,
263
+ p_sort_by,
264
+ p_sort_order
265
+ );
266
+ END;
267
+ $$;
268
+
269
+ -- ---------------------------------------------------------------------------
270
+ -- ADMIN — approvals Excel
271
+ -- Per sub-service Requests + Approvals; optional approver user id(s) (NULL/empty = all queues)
272
+ -- Does not exclude own requests (unlike user approvals download)
273
+ -- ---------------------------------------------------------------------------
274
+ DROP FUNCTION IF EXISTS sp_sla_admin_approvals_excel_export(
275
+ INT, INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT
276
+ );
277
+ DROP FUNCTION IF EXISTS sp_sla_admin_approvals_excel_export(
278
+ INT, INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT, TEXT
279
+ );
280
+ DROP FUNCTION IF EXISTS sp_sla_admin_approvals_excel_export(
281
+ INT[], INT[], INT[], TEXT[], TEXT[], DATE, DATE, TEXT, TEXT, TEXT, TEXT
282
+ );
283
+
284
+ CREATE OR REPLACE FUNCTION sp_sla_admin_approvals_excel_export(
285
+ p_target_approver_user_ids INT[] DEFAULT NULL,
286
+ p_service_ids INT[] DEFAULT NULL,
287
+ p_sub_service_ids INT[] DEFAULT NULL,
288
+ p_request_statuses TEXT[] DEFAULT ARRAY['Pending','In Progress','Approved','Rejected'],
289
+ p_approval_statuses TEXT[] DEFAULT ARRAY['In Progress','Approved','Rejected'],
290
+ p_from_date DATE DEFAULT NULL,
291
+ p_to_date DATE DEFAULT NULL,
292
+ p_search_text TEXT DEFAULT NULL,
293
+ p_sort_by TEXT DEFAULT 'created_at',
294
+ p_sort_order TEXT DEFAULT 'DESC',
295
+ p_extra_filter_sql TEXT DEFAULT 'TRUE'
296
+ )
297
+ RETURNS TABLE (
298
+ sheet_order INT, sub_service_id INT, sub_service_name TEXT, sheet_name TEXT, headers JSONB, rows JSONB
299
+ )
300
+ LANGUAGE plpgsql
301
+ STABLE
302
+ AS $$
303
+ DECLARE
304
+ v_exists TEXT := sla_approval_queue_exists_sql_any(p_target_approver_user_ids);
305
+ v_own TEXT := COALESCE(NULLIF(trim(p_extra_filter_sql), ''), 'TRUE');
306
+ BEGIN
307
+ RETURN QUERY
308
+ SELECT * FROM sp_sla_approvals_workbook_excel_export(
309
+ v_exists,
310
+ v_own,
311
+ p_service_ids,
312
+ p_sub_service_ids,
313
+ p_request_statuses,
314
+ p_approval_statuses,
315
+ p_from_date,
316
+ p_to_date,
317
+ p_search_text,
318
+ p_sort_by,
319
+ p_sort_order
320
+ );
321
+ END;
322
+ $$;