@platform-modules/foreign-ministry 1.3.341 → 1.3.350

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 (87) hide show
  1. package/.env +4 -4
  2. package/dist/helpers/employee-evaluation-request.utils.d.ts +6 -0
  3. package/dist/helpers/employee-evaluation-request.utils.js +83 -5
  4. package/dist/helpers/sla-request-status.helper.d.ts +3 -0
  5. package/dist/helpers/sla-request-status.helper.js +36 -0
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.js +4 -3
  8. package/dist/models/EmbassyEvaluationDepartmentSettingModel.d.ts +14 -0
  9. package/dist/models/EmbassyEvaluationDepartmentSettingModel.js +56 -0
  10. package/dist/models/EmployeeEvaluationRequestModel.d.ts +1 -0
  11. package/dist/models/EmployeeEvaluationRequestModel.js +4 -0
  12. package/dist/models/EvaluationMastersModel.d.ts +16 -0
  13. package/dist/models/EvaluationMastersModel.js +67 -0
  14. package/dist/models/EvaluationQuestionMasterModel.d.ts +10 -0
  15. package/dist/models/EvaluationQuestionMasterModel.js +42 -0
  16. package/dist/models/EvaluationSectionMasterModel.d.ts +7 -0
  17. package/dist/models/EvaluationSectionMasterModel.js +36 -0
  18. package/dist/models/EvaluationWorkflowModel.d.ts +60 -0
  19. package/dist/models/EvaluationWorkflowModel.js +215 -0
  20. package/dist/models/IneligibleForEvaluationModel.d.ts +8 -0
  21. package/dist/models/IneligibleForEvaluationModel.js +44 -0
  22. package/dist/models/MissionTravelClassConfigModel.d.ts +10 -0
  23. package/dist/models/MissionTravelClassConfigModel.js +50 -0
  24. package/dist/models/MissionTravelPerdiemModel.d.ts +10 -0
  25. package/dist/models/MissionTravelPerdiemModel.js +54 -0
  26. package/dist/models/MounringLeaveRelationModel.d.ts +1 -0
  27. package/dist/models/MounringLeaveRelationModel.js +4 -0
  28. package/dist/models/SlaApprovalsViewModel.js +47 -47
  29. package/dist/models/SlaMyRequestsViewModel.js +52 -52
  30. package/dist/models/UuidAuditModel.d.ts +9 -0
  31. package/dist/models/UuidAuditModel.js +41 -0
  32. package/package.json +1 -1
  33. package/scripts/check-column-types.js +38 -38
  34. package/scripts/check-service-tables.js +42 -42
  35. package/scripts/sync-sla-reports-sql.js +92 -92
  36. package/sql/add_employee_evaluation_requests_is_draft.sql +2 -0
  37. package/sql/add_mounring_leave_relation_arabic.sql +2 -0
  38. package/sql/sla-reports-sync.manifest.json +9 -9
  39. package/sql/sla_reports_admin_procedures.sql +304 -304
  40. package/sql/sla_reports_approvals_workbook.sql +383 -383
  41. package/sql/sla_reports_procedures.sql +886 -886
  42. package/sql/sla_requests_status_to_varchar.sql +28 -28
  43. package/sql/vw_sla_approvals.sql +108 -108
  44. package/sql/vw_sla_my_requests.sql +55 -55
  45. package/src/data-source.ts +686 -686
  46. package/src/helpers/employee-evaluation-request.utils.ts +87 -7
  47. package/src/helpers/evaluation-eligibility.utils.ts +126 -126
  48. package/src/index.ts +1 -0
  49. package/src/models/DiplomaticAcademyRequestModel.ts +80 -80
  50. package/src/models/DocumentationFileModel.ts +40 -40
  51. package/src/models/EmbassyEvaluationCycleModel.ts +45 -45
  52. package/src/models/EmbassyEvaluationRequestModel.ts +59 -59
  53. package/src/models/EmployeeEvaluationAnswerModel.ts +26 -26
  54. package/src/models/EmployeeEvaluationRequestModel.ts +3 -0
  55. package/src/models/EvaluationEligibilitySettingModel.ts +51 -51
  56. package/src/models/EvaluationFormModel.ts +44 -44
  57. package/src/models/LanguageCourseRequestModel.ts +67 -67
  58. package/src/models/LeaveApprovalsModel.ts +66 -66
  59. package/src/models/LeaveConfigModel.ts +71 -71
  60. package/src/models/MissionTravelApprovalModel.ts +101 -101
  61. package/src/models/MissionTravelAttachmentModel.ts +56 -56
  62. package/src/models/MissionTravelChatModel.ts +52 -52
  63. package/src/models/MissionTravelPersonModel.ts +105 -105
  64. package/src/models/MissionTravelWorkflowModel.ts +54 -54
  65. package/src/models/MounringLeaveRelationModel.ts +3 -0
  66. package/src/models/ProjectContactsModel.ts +51 -51
  67. package/src/models/ProjectFaqModel.ts +36 -36
  68. package/src/models/ProjectInvoicesModel.ts +41 -41
  69. package/src/models/ProjectModel.ts +75 -75
  70. package/src/models/ProjectTasksModel.ts +75 -75
  71. package/src/models/ServiceSlaApprovalModel.ts +63 -63
  72. package/src/models/ServicesNotificationConfigsModel.ts +55 -55
  73. package/src/models/SlaApprovalsViewModel.ts +135 -135
  74. package/src/models/SlaMyRequestsViewModel.ts +172 -172
  75. package/src/models/SlaRequestModel.ts +57 -57
  76. package/src/sla-report-views.ts +3 -3
  77. package/dist/auth/authenticate-jwt-session.d.ts +0 -19
  78. package/dist/auth/authenticate-jwt-session.js +0 -35
  79. package/dist/auth/jwt-token.helper.d.ts +0 -18
  80. package/dist/auth/jwt-token.helper.js +0 -58
  81. package/dist/auth/user-session-validation.d.ts +0 -42
  82. package/dist/auth/user-session-validation.js +0 -95
  83. package/dist/i18n/workflow-chat-i18n.d.ts +0 -5
  84. package/dist/i18n/workflow-chat-i18n.js +0 -21
  85. package/dist/i18n/workflow-chat-i18n.json +0 -320
  86. package/dist/i18n/workflow-chat-message.builder.d.ts +0 -325
  87. package/dist/i18n/workflow-chat-message.builder.js +0 -924
@@ -85,6 +85,81 @@ export function normalizeEmployeeSubmissions(raw: unknown): {
85
85
  return { employees };
86
86
  }
87
87
 
88
+ /** Relaxed validation for draft saves — employees/answers may be empty or partial. */
89
+ export function normalizeEmployeeDraftSubmissions(raw: unknown): {
90
+ employees: NormalizedEmployeeSubmission[];
91
+ error?: string;
92
+ } {
93
+ if (raw == null || raw === undefined) {
94
+ return { employees: [] };
95
+ }
96
+ if (!Array.isArray(raw)) {
97
+ return { employees: [], error: 'employees must be an array when provided' };
98
+ }
99
+ if (raw.length === 0) {
100
+ return { employees: [] };
101
+ }
102
+ const seen = new Set<number>();
103
+ const employees: NormalizedEmployeeSubmission[] = [];
104
+ for (const item of raw) {
105
+ if (item == null || typeof item !== 'object') {
106
+ return { employees: [], error: 'Each employee entry must be an object' };
107
+ }
108
+ const o = item as Record<string, unknown>;
109
+ const user_id = Number(o.user_id ?? o.employee_id);
110
+ if (!Number.isFinite(user_id) || user_id <= 0) {
111
+ return { employees: [], error: 'Each employee must have a valid user_id' };
112
+ }
113
+ if (seen.has(user_id)) {
114
+ return { employees: [], error: `Duplicate user_id ${user_id} in employees list` };
115
+ }
116
+ seen.add(user_id);
117
+ const answersRaw = o.answers;
118
+ const answers: EmployeeEvaluationSubmitAnswer[] = [];
119
+ if (answersRaw != null) {
120
+ if (!Array.isArray(answersRaw)) {
121
+ return { employees: [], error: `Employee ${user_id} answers must be an array when provided` };
122
+ }
123
+ const qSeen = new Set<number>();
124
+ for (const a of answersRaw) {
125
+ if (a == null || typeof a !== 'object') continue;
126
+ const ar = a as Record<string, unknown>;
127
+ const section_id = Number(ar.section_id);
128
+ const question_id = Number(ar.question_id);
129
+ const score = Number(ar.score);
130
+ if (!Number.isFinite(section_id) || !Number.isFinite(question_id)) {
131
+ return {
132
+ employees: [],
133
+ error: `section_id and question_id required for employee ${user_id} when answer is provided`,
134
+ };
135
+ }
136
+ if (!Number.isFinite(score) || score < 0) {
137
+ return {
138
+ employees: [],
139
+ error: `score must be a non-negative number for employee ${user_id}, question ${question_id}`,
140
+ };
141
+ }
142
+ if (qSeen.has(question_id)) {
143
+ return { employees: [], error: `Duplicate question_id ${question_id} for employee ${user_id}` };
144
+ }
145
+ qSeen.add(question_id);
146
+ answers.push({
147
+ section_id,
148
+ question_id,
149
+ score,
150
+ remarks: ar.remarks != null ? String(ar.remarks) : null,
151
+ });
152
+ }
153
+ }
154
+ employees.push({
155
+ user_id,
156
+ is_rca: o.is_rca !== undefined ? Boolean(o.is_rca) : false,
157
+ answers,
158
+ });
159
+ }
160
+ return { employees };
161
+ }
162
+
88
163
  /** Resolve max employees from active exception cycle for the evaluation month. */
89
164
  export async function resolveMaxEmployeesPerRequest(
90
165
  manager: EntityManager,
@@ -113,9 +188,10 @@ export async function persistEmployeeEvaluationScores(
113
188
  formId: number;
114
189
  createdBy: string;
115
190
  employees: NormalizedEmployeeSubmission[];
191
+ isDraft?: boolean;
116
192
  }
117
193
  ): Promise<{ totalScore: number; averageScore: number; employeeCount: number }> {
118
- const { requestId, formId, createdBy, employees } = opts;
194
+ const { requestId, formId, createdBy, employees, isDraft = false } = opts;
119
195
  let requestTotal = 0;
120
196
 
121
197
  for (const emp of employees) {
@@ -125,14 +201,18 @@ export async function persistEmployeeEvaluationScores(
125
201
  where: { id: ans.question_id, is_deleted: false },
126
202
  });
127
203
  const questionSectionId = qMeta?.form_section_id;
128
- if (!qMeta || questionSectionId == null || questionSectionId !== ans.section_id) {
204
+ if (!isDraft) {
205
+ if (!qMeta || questionSectionId == null || questionSectionId !== ans.section_id) {
206
+ throw new Error(`Invalid question ${ans.question_id} for section ${ans.section_id}`);
207
+ }
208
+ if (qMeta.max_score != null && ans.score > qMeta.max_score) {
209
+ throw new Error(
210
+ `score ${ans.score} exceeds max_score ${qMeta.max_score} for question ${ans.question_id}`
211
+ );
212
+ }
213
+ } else if (qMeta && qMeta.form_section_id != null && qMeta.form_section_id !== ans.section_id) {
129
214
  throw new Error(`Invalid question ${ans.question_id} for section ${ans.section_id}`);
130
215
  }
131
- if (qMeta.max_score != null && ans.score > qMeta.max_score) {
132
- throw new Error(
133
- `score ${ans.score} exceeds max_score ${qMeta.max_score} for question ${ans.question_id}`
134
- );
135
- }
136
216
  personTotal += ans.score;
137
217
  await manager.save(
138
218
  EmployeeEvaluationAnswers,
@@ -1,126 +1,126 @@
1
- /**
2
- * Evaluation exception cycle dates are stored as MM-DD strings (e.g. 01-01, 05-31, 04-12).
3
- */
4
-
5
- export type MmDdInterval = { start: number; end: number };
6
-
7
- /** Validate and normalize MM-DD (e.g. 1-1 → 01-01). */
8
- export function parseMonthDay(value: unknown): string | null {
9
- if (value == null || value === '') return null;
10
- const s = String(value).trim();
11
- const m = /^(\d{1,2})-(\d{1,2})$/.exec(s);
12
- if (!m) return null;
13
- const month = parseInt(m[1], 10);
14
- const day = parseInt(m[2], 10);
15
- if (month < 1 || month > 12 || day < 1 || day > 31) return null;
16
- return `${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
17
- }
18
-
19
- function parseMmDdParts(mmDd: string): { month: number; day: number } | null {
20
- const normalized = parseMonthDay(mmDd);
21
- if (!normalized) return null;
22
- const [month, day] = normalized.split('-').map(Number);
23
- return { month, day };
24
- }
25
-
26
- /** Sortable key for MM-DD overlap checks (month * 100 + day). */
27
- export function mmDdSortKey(mmDd: string): number {
28
- const parts = parseMmDdParts(mmDd);
29
- if (!parts) return 0;
30
- return parts.month * 100 + parts.day;
31
- }
32
-
33
- function expandMmDdWindow(startMmDd: string, endMmDd: string): MmDdInterval[] {
34
- const start = mmDdSortKey(startMmDd);
35
- const end = mmDdSortKey(endMmDd);
36
- if (start <= end) return [{ start, end }];
37
- return [
38
- { start, end: 1231 },
39
- { start: 101, end },
40
- ];
41
- }
42
-
43
- function linearIntervalsOverlap(a: MmDdInterval, b: MmDdInterval): boolean {
44
- return a.start <= b.end && b.start <= a.end;
45
- }
46
-
47
- /** True when two MM-DD windows share any calendar period. */
48
- export function mmDdWindowsOverlap(
49
- startA: string,
50
- endA: string,
51
- startB: string,
52
- endB: string
53
- ): boolean {
54
- const intervalsA = expandMmDdWindow(startA, endA);
55
- const intervalsB = expandMmDdWindow(startB, endB);
56
- for (const ia of intervalsA) {
57
- for (const ib of intervalsB) {
58
- if (linearIntervalsOverlap(ia, ib)) return true;
59
- }
60
- }
61
- return false;
62
- }
63
-
64
- /** Whether calendar month (1–12) falls within the inclusive MM-DD window. */
65
- export function isCalendarMonthInEligibilityRange(
66
- fromMmDd: string,
67
- toMmDd: string,
68
- calendarMonth: number
69
- ): boolean {
70
- const from = parseMmDdParts(fromMmDd);
71
- const to = parseMmDdParts(toMmDd);
72
- if (!from || !to || calendarMonth < 1 || calendarMonth > 12) return false;
73
- const fm = from.month;
74
- const tm = to.month;
75
- if (fm <= tm) return calendarMonth >= fm && calendarMonth <= tm;
76
- return calendarMonth >= fm || calendarMonth <= tm;
77
- }
78
-
79
- /**
80
- * Whether HOD submissions are still open for the active cycle on the reference date.
81
- * Uses the day component of `evaluationEndMmDd` as the last submission day of each month in range.
82
- */
83
- export function isEvaluationEligibilityWindowOpen(
84
- fromMmDd: string,
85
- toMmDd: string,
86
- evaluationEndMmDd: string,
87
- referenceDate: Date = new Date()
88
- ): boolean {
89
- const month = referenceDate.getMonth() + 1;
90
- const day = referenceDate.getDate();
91
- if (!isCalendarMonthInEligibilityRange(fromMmDd, toMmDd, month)) return false;
92
- const endParts = parseMmDdParts(evaluationEndMmDd);
93
- if (!endParts) return false;
94
- return day <= endParts.day;
95
- }
96
-
97
- export function parseEligibilityDateRange(
98
- fromInput: unknown,
99
- toInput: unknown
100
- ): { from_month: string; to_month: string } | null {
101
- const from_month = parseMonthDay(fromInput);
102
- const to_month = parseMonthDay(toInput);
103
- if (!from_month || !to_month) return null;
104
- return { from_month, to_month };
105
- }
106
-
107
- /** @deprecated Use parseMonthDay for MM-DD strings. */
108
- export function parseEvaluationEndDay(input: unknown): number | null {
109
- const mmDd = parseMonthDay(input);
110
- if (!mmDd) return null;
111
- const parts = parseMmDdParts(mmDd);
112
- return parts?.day ?? null;
113
- }
114
-
115
- /** @deprecated Use parseEligibilityDateRange for MM-DD strings. */
116
- export function parseMonthRange(
117
- fromInput: unknown,
118
- toInput: unknown
119
- ): { from_month: number; to_month: number } | null {
120
- const range = parseEligibilityDateRange(fromInput, toInput);
121
- if (!range) return null;
122
- const from = parseMmDdParts(range.from_month);
123
- const to = parseMmDdParts(range.to_month);
124
- if (!from || !to) return null;
125
- return { from_month: from.month, to_month: to.month };
126
- }
1
+ /**
2
+ * Evaluation exception cycle dates are stored as MM-DD strings (e.g. 01-01, 05-31, 04-12).
3
+ */
4
+
5
+ export type MmDdInterval = { start: number; end: number };
6
+
7
+ /** Validate and normalize MM-DD (e.g. 1-1 → 01-01). */
8
+ export function parseMonthDay(value: unknown): string | null {
9
+ if (value == null || value === '') return null;
10
+ const s = String(value).trim();
11
+ const m = /^(\d{1,2})-(\d{1,2})$/.exec(s);
12
+ if (!m) return null;
13
+ const month = parseInt(m[1], 10);
14
+ const day = parseInt(m[2], 10);
15
+ if (month < 1 || month > 12 || day < 1 || day > 31) return null;
16
+ return `${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
17
+ }
18
+
19
+ function parseMmDdParts(mmDd: string): { month: number; day: number } | null {
20
+ const normalized = parseMonthDay(mmDd);
21
+ if (!normalized) return null;
22
+ const [month, day] = normalized.split('-').map(Number);
23
+ return { month, day };
24
+ }
25
+
26
+ /** Sortable key for MM-DD overlap checks (month * 100 + day). */
27
+ export function mmDdSortKey(mmDd: string): number {
28
+ const parts = parseMmDdParts(mmDd);
29
+ if (!parts) return 0;
30
+ return parts.month * 100 + parts.day;
31
+ }
32
+
33
+ function expandMmDdWindow(startMmDd: string, endMmDd: string): MmDdInterval[] {
34
+ const start = mmDdSortKey(startMmDd);
35
+ const end = mmDdSortKey(endMmDd);
36
+ if (start <= end) return [{ start, end }];
37
+ return [
38
+ { start, end: 1231 },
39
+ { start: 101, end },
40
+ ];
41
+ }
42
+
43
+ function linearIntervalsOverlap(a: MmDdInterval, b: MmDdInterval): boolean {
44
+ return a.start <= b.end && b.start <= a.end;
45
+ }
46
+
47
+ /** True when two MM-DD windows share any calendar period. */
48
+ export function mmDdWindowsOverlap(
49
+ startA: string,
50
+ endA: string,
51
+ startB: string,
52
+ endB: string
53
+ ): boolean {
54
+ const intervalsA = expandMmDdWindow(startA, endA);
55
+ const intervalsB = expandMmDdWindow(startB, endB);
56
+ for (const ia of intervalsA) {
57
+ for (const ib of intervalsB) {
58
+ if (linearIntervalsOverlap(ia, ib)) return true;
59
+ }
60
+ }
61
+ return false;
62
+ }
63
+
64
+ /** Whether calendar month (1–12) falls within the inclusive MM-DD window. */
65
+ export function isCalendarMonthInEligibilityRange(
66
+ fromMmDd: string,
67
+ toMmDd: string,
68
+ calendarMonth: number
69
+ ): boolean {
70
+ const from = parseMmDdParts(fromMmDd);
71
+ const to = parseMmDdParts(toMmDd);
72
+ if (!from || !to || calendarMonth < 1 || calendarMonth > 12) return false;
73
+ const fm = from.month;
74
+ const tm = to.month;
75
+ if (fm <= tm) return calendarMonth >= fm && calendarMonth <= tm;
76
+ return calendarMonth >= fm || calendarMonth <= tm;
77
+ }
78
+
79
+ /**
80
+ * Whether HOD submissions are still open for the active cycle on the reference date.
81
+ * Uses the day component of `evaluationEndMmDd` as the last submission day of each month in range.
82
+ */
83
+ export function isEvaluationEligibilityWindowOpen(
84
+ fromMmDd: string,
85
+ toMmDd: string,
86
+ evaluationEndMmDd: string,
87
+ referenceDate: Date = new Date()
88
+ ): boolean {
89
+ const month = referenceDate.getMonth() + 1;
90
+ const day = referenceDate.getDate();
91
+ if (!isCalendarMonthInEligibilityRange(fromMmDd, toMmDd, month)) return false;
92
+ const endParts = parseMmDdParts(evaluationEndMmDd);
93
+ if (!endParts) return false;
94
+ return day <= endParts.day;
95
+ }
96
+
97
+ export function parseEligibilityDateRange(
98
+ fromInput: unknown,
99
+ toInput: unknown
100
+ ): { from_month: string; to_month: string } | null {
101
+ const from_month = parseMonthDay(fromInput);
102
+ const to_month = parseMonthDay(toInput);
103
+ if (!from_month || !to_month) return null;
104
+ return { from_month, to_month };
105
+ }
106
+
107
+ /** @deprecated Use parseMonthDay for MM-DD strings. */
108
+ export function parseEvaluationEndDay(input: unknown): number | null {
109
+ const mmDd = parseMonthDay(input);
110
+ if (!mmDd) return null;
111
+ const parts = parseMmDdParts(mmDd);
112
+ return parts?.day ?? null;
113
+ }
114
+
115
+ /** @deprecated Use parseEligibilityDateRange for MM-DD strings. */
116
+ export function parseMonthRange(
117
+ fromInput: unknown,
118
+ toInput: unknown
119
+ ): { from_month: number; to_month: number } | null {
120
+ const range = parseEligibilityDateRange(fromInput, toInput);
121
+ if (!range) return null;
122
+ const from = parseMmDdParts(range.from_month);
123
+ const to = parseMmDdParts(range.to_month);
124
+ if (!from || !to) return null;
125
+ return { from_month: from.month, to_month: to.month };
126
+ }
package/src/index.ts CHANGED
@@ -459,6 +459,7 @@ export {
459
459
  export {
460
460
  DEFAULT_MAX_EMPLOYEES_PER_REQUEST,
461
461
  normalizeEmployeeSubmissions,
462
+ normalizeEmployeeDraftSubmissions,
462
463
  resolveMaxEmployeesPerRequest,
463
464
  persistEmployeeEvaluationScores,
464
465
  } from './helpers/employee-evaluation-request.utils';
@@ -1,80 +1,80 @@
1
- import { Column, Entity } from "typeorm";
2
- import { BaseModel } from './BaseModel';
3
-
4
- export enum DiplomaticAcademyStatus {
5
- SUBMITTED = "Submitted",
6
- PENDING = "Pending",
7
- ASSIGNED = "Assigned",
8
- IN_PROGRESS = "In Progress",
9
- APPROVED = "Approved",
10
- REJECTED = "Rejected"
11
- }
12
-
13
- @Entity({ name: 'diplomatic_academy_requests' })
14
- export class DiplomaticAcademyRequests extends BaseModel {
15
-
16
- // Common columns
17
- @Column({ type: 'int', nullable: true })
18
- req_user_department_id: number | null;
19
-
20
- @Column({ type: 'int', nullable: true })
21
- req_user_section_id: number | null;
22
-
23
- @Column({ type: 'int', nullable: true })
24
- service_id: number | null;
25
-
26
- @Column({ type: 'int', nullable: true })
27
- sub_service_id: number | null;
28
-
29
- @Column({ type: 'int', nullable: false })
30
- user_id: number;
31
-
32
- // Diplomatic Academy specific columns
33
- @Column({ type: 'varchar', length: 500, nullable: false })
34
- course_name: string;
35
-
36
- @Column({ type: 'jsonb', nullable: true })
37
- cost_details: {
38
- material_price?: number;
39
- transportation?: number;
40
- accommodation?: number;
41
- allowances?: number;
42
- food?: number;
43
- present?: number;
44
- } | null;
45
-
46
- @Column({ type: 'int', nullable: false })
47
- estimated_participants: number;
48
-
49
- @Column({ type: 'date', nullable: false })
50
- timeline_date_from: Date;
51
-
52
- @Column({ type: 'date', nullable: false })
53
- timeline_date_to: Date;
54
-
55
- @Column({ type: 'time', nullable: true })
56
- timeline_time_from: string | null;
57
-
58
- @Column({ type: 'time', nullable: true })
59
- timeline_time_to: string | null;
60
-
61
- @Column({ type: 'jsonb', nullable: false })
62
- participants_details: Array<{
63
- full_name: string;
64
- passport: string;
65
- age: number;
66
- qualifications: string;
67
- experience: string;
68
- institution: string;
69
- }>;
70
-
71
- @Column({ type: 'enum', enum: DiplomaticAcademyStatus, default: DiplomaticAcademyStatus.PENDING, nullable: false })
72
- status: DiplomaticAcademyStatus;
73
-
74
- @Column({ type: 'int', nullable: true })
75
- course_id: number | null;
76
-
77
- @Column({ type: 'varchar', nullable: true })
78
- workflow_execution_id: string | null;
79
-
80
- }
1
+ import { Column, Entity } from "typeorm";
2
+ import { BaseModel } from './BaseModel';
3
+
4
+ export enum DiplomaticAcademyStatus {
5
+ SUBMITTED = "Submitted",
6
+ PENDING = "Pending",
7
+ ASSIGNED = "Assigned",
8
+ IN_PROGRESS = "In Progress",
9
+ APPROVED = "Approved",
10
+ REJECTED = "Rejected"
11
+ }
12
+
13
+ @Entity({ name: 'diplomatic_academy_requests' })
14
+ export class DiplomaticAcademyRequests extends BaseModel {
15
+
16
+ // Common columns
17
+ @Column({ type: 'int', nullable: true })
18
+ req_user_department_id: number | null;
19
+
20
+ @Column({ type: 'int', nullable: true })
21
+ req_user_section_id: number | null;
22
+
23
+ @Column({ type: 'int', nullable: true })
24
+ service_id: number | null;
25
+
26
+ @Column({ type: 'int', nullable: true })
27
+ sub_service_id: number | null;
28
+
29
+ @Column({ type: 'int', nullable: false })
30
+ user_id: number;
31
+
32
+ // Diplomatic Academy specific columns
33
+ @Column({ type: 'varchar', length: 500, nullable: false })
34
+ course_name: string;
35
+
36
+ @Column({ type: 'jsonb', nullable: true })
37
+ cost_details: {
38
+ material_price?: number;
39
+ transportation?: number;
40
+ accommodation?: number;
41
+ allowances?: number;
42
+ food?: number;
43
+ present?: number;
44
+ } | null;
45
+
46
+ @Column({ type: 'int', nullable: false })
47
+ estimated_participants: number;
48
+
49
+ @Column({ type: 'date', nullable: false })
50
+ timeline_date_from: Date;
51
+
52
+ @Column({ type: 'date', nullable: false })
53
+ timeline_date_to: Date;
54
+
55
+ @Column({ type: 'time', nullable: true })
56
+ timeline_time_from: string | null;
57
+
58
+ @Column({ type: 'time', nullable: true })
59
+ timeline_time_to: string | null;
60
+
61
+ @Column({ type: 'jsonb', nullable: false })
62
+ participants_details: Array<{
63
+ full_name: string;
64
+ passport: string;
65
+ age: number;
66
+ qualifications: string;
67
+ experience: string;
68
+ institution: string;
69
+ }>;
70
+
71
+ @Column({ type: 'enum', enum: DiplomaticAcademyStatus, default: DiplomaticAcademyStatus.PENDING, nullable: false })
72
+ status: DiplomaticAcademyStatus;
73
+
74
+ @Column({ type: 'int', nullable: true })
75
+ course_id: number | null;
76
+
77
+ @Column({ type: 'varchar', nullable: true })
78
+ workflow_execution_id: string | null;
79
+
80
+ }
@@ -1,40 +1,40 @@
1
- import { Column, Entity } from 'typeorm';
2
- import { BaseModel } from './BaseModel';
3
-
4
- @Entity({ name: 'documentation_files' })
5
- export class DocumentationFile extends BaseModel {
6
- @Column({ type: 'int', nullable: true })
7
- project_id: number | null;
8
-
9
- @Column({ type: 'int' })
10
- folder_id: number;
11
-
12
- @Column({ type: 'text', nullable: true })
13
- file_path: string;
14
-
15
- @Column({ type: 'varchar', length: 500, nullable: true })
16
- filename: string;
17
-
18
- @Column({ type: 'bigint', nullable: true })
19
- filesize: number;
20
-
21
- @Column({ type: 'varchar', length: 100, nullable: true })
22
- filetype: string;
23
-
24
- constructor(
25
- project_id?: number | null,
26
- folder_id?: number,
27
- file_path?: string,
28
- filename?: string,
29
- filesize?: number,
30
- filetype?: string
31
- ) {
32
- super();
33
- this.project_id = project_id ?? null;
34
- this.folder_id = folder_id ?? 0;
35
- this.file_path = file_path ?? '';
36
- this.filename = filename ?? '';
37
- this.filesize = filesize ?? 0;
38
- this.filetype = filetype ?? '';
39
- }
40
- }
1
+ import { Column, Entity } from 'typeorm';
2
+ import { BaseModel } from './BaseModel';
3
+
4
+ @Entity({ name: 'documentation_files' })
5
+ export class DocumentationFile extends BaseModel {
6
+ @Column({ type: 'int', nullable: true })
7
+ project_id: number | null;
8
+
9
+ @Column({ type: 'int' })
10
+ folder_id: number;
11
+
12
+ @Column({ type: 'text', nullable: true })
13
+ file_path: string;
14
+
15
+ @Column({ type: 'varchar', length: 500, nullable: true })
16
+ filename: string;
17
+
18
+ @Column({ type: 'bigint', nullable: true })
19
+ filesize: number;
20
+
21
+ @Column({ type: 'varchar', length: 100, nullable: true })
22
+ filetype: string;
23
+
24
+ constructor(
25
+ project_id?: number | null,
26
+ folder_id?: number,
27
+ file_path?: string,
28
+ filename?: string,
29
+ filesize?: number,
30
+ filetype?: string
31
+ ) {
32
+ super();
33
+ this.project_id = project_id ?? null;
34
+ this.folder_id = folder_id ?? 0;
35
+ this.file_path = file_path ?? '';
36
+ this.filename = filename ?? '';
37
+ this.filesize = filesize ?? 0;
38
+ this.filetype = filetype ?? '';
39
+ }
40
+ }