@codihaus/odp-app-hr 0.1.0

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 (192) hide show
  1. package/app/components/hr/contact/tab.vue +238 -0
  2. package/app/components/hr/department/card.vue +141 -0
  3. package/app/components/hr/department/form-modal.vue +90 -0
  4. package/app/components/hr/employees/assets/tab.vue +432 -0
  5. package/app/components/hr/employees/compensation.vue +136 -0
  6. package/app/components/hr/employees/contract.vue +77 -0
  7. package/app/components/hr/employees/insurance.vue +164 -0
  8. package/app/components/hr/employees/leave/tab.vue +180 -0
  9. package/app/components/hr/employees/provisioning/form-modal.vue +219 -0
  10. package/app/components/hr/employees/provisioning/tab.vue +187 -0
  11. package/app/components/hr/employees/tab.vue +38 -0
  12. package/app/components/hr/leave/calendar-tab.vue +649 -0
  13. package/app/components/hr/leave/override-modal.vue +62 -0
  14. package/app/components/hr/leave/request-modal.vue +185 -0
  15. package/app/components/hr/leave/requests-tab.vue +289 -0
  16. package/app/components/hr/leave/timeline-tab.vue +259 -0
  17. package/app/components/hr/offboarding/tab.vue +303 -0
  18. package/app/components/hr/person/activity/tab.vue +65 -0
  19. package/app/components/hr/person/activity/timeline.vue +119 -0
  20. package/app/components/hr/person/detail.vue +303 -0
  21. package/app/components/hr/person/document/tab-documents.vue +120 -0
  22. package/app/components/hr/person/document/template-edit-drawer.vue +215 -0
  23. package/app/components/hr/person/document/template-preview-card.vue +39 -0
  24. package/app/components/hr/person/document/trigger-modal.vue +121 -0
  25. package/app/components/hr/person/employee-form-modal.vue +78 -0
  26. package/app/components/hr/person/form-modal.vue +78 -0
  27. package/app/components/hr/person/list-row.vue +40 -0
  28. package/app/components/hr/person/profile/tab.vue +231 -0
  29. package/app/components/hr/settings/automation.vue +113 -0
  30. package/app/components/hr/settings/documents.vue +200 -0
  31. package/app/components/hr/settings/general.vue +87 -0
  32. package/app/components/hr/settings/holidays.vue +171 -0
  33. package/app/components/hr/settings/integrations.vue +185 -0
  34. package/app/components/hr/settings/policies.vue +83 -0
  35. package/app/components/hr/settings/policy/benefit-override-modal.vue +59 -0
  36. package/app/components/hr/settings/policy/editor-eligibility.vue +27 -0
  37. package/app/components/hr/settings/policy/editor-leave-base.vue +37 -0
  38. package/app/components/hr/settings/policy/editor-tenure-bonus.vue +61 -0
  39. package/app/components/hr/settings/recruitment.vue +128 -0
  40. package/app/components/hr/settings/taxonomies.vue +170 -0
  41. package/app/components/hr/shared/row.vue +21 -0
  42. package/app/components/hr/shared/section.vue +20 -0
  43. package/app/components/hr/shared/source-badge.vue +42 -0
  44. package/app/components/hr/shared/stage-badge.vue +24 -0
  45. package/app/components/hr/shared/workflow-timeline.vue +27 -0
  46. package/app/components/hr/talents/app-sidebar.vue +54 -0
  47. package/app/components/hr/talents/application-form-modal.vue +114 -0
  48. package/app/components/hr/talents/pipeline-picker.vue +56 -0
  49. package/app/components/hr/talents/step-detail.vue +133 -0
  50. package/app/components/hr/talents/step-stepper.vue +85 -0
  51. package/app/components/hr/talents/tab.vue +263 -0
  52. package/app/composables/use-departments.ts +59 -0
  53. package/app/composables/use-employee-detail.ts +24 -0
  54. package/app/composables/use-holidays.ts +48 -0
  55. package/app/composables/use-hr-api.ts +210 -0
  56. package/app/composables/use-hr-field-registry.ts +76 -0
  57. package/app/composables/use-hr-policies.ts +66 -0
  58. package/app/composables/use-hr-settings.ts +118 -0
  59. package/app/composables/use-leave.ts +71 -0
  60. package/app/composables/use-offboarding.ts +49 -0
  61. package/app/composables/use-people.ts +149 -0
  62. package/app/composables/use-providers.ts +44 -0
  63. package/app/composables/use-recruitment-workflow.ts +173 -0
  64. package/app/composables/use-templates.ts +44 -0
  65. package/app/composables/use-triggers.ts +26 -0
  66. package/app/config/column-renderers.ts +4 -0
  67. package/app/config/form-layouts.ts +193 -0
  68. package/app/data/hr-schema.ts +2608 -0
  69. package/app/lib/policy-engine.ts +116 -0
  70. package/app/pages/hr/departments.vue +114 -0
  71. package/app/pages/hr/employees/[id]/activity.vue +10 -0
  72. package/app/pages/hr/employees/[id]/assets.vue +14 -0
  73. package/app/pages/hr/employees/[id]/employment.vue +14 -0
  74. package/app/pages/hr/employees/[id]/index.vue +9 -0
  75. package/app/pages/hr/employees/[id]/offboarding.vue +7 -0
  76. package/app/pages/hr/employees/[id]/profile.vue +11 -0
  77. package/app/pages/hr/employees/[id]/provisioning.vue +17 -0
  78. package/app/pages/hr/employees/[id].vue +313 -0
  79. package/app/pages/hr/employees/index.vue +291 -0
  80. package/app/pages/hr/index.vue +3 -0
  81. package/app/pages/hr/leave.vue +79 -0
  82. package/app/pages/hr/settings.vue +43 -0
  83. package/app/pages/hr/setup.vue +3 -0
  84. package/app/pages/hr/talents/[id]/interview/[stepId].vue +231 -0
  85. package/app/pages/hr/talents/[id].vue +52 -0
  86. package/app/pages/hr/talents/index.vue +224 -0
  87. package/app/pages/hr.vue +129 -0
  88. package/app/plugins/hr-contacts-sync.client.ts +3 -0
  89. package/app/plugins/hr-extensions.ts +36 -0
  90. package/app/plugins/hr-setup.ts +5 -0
  91. package/app/plugins/navigations.ts +22 -0
  92. package/app/utils/hr-permissions.ts +27 -0
  93. package/app/utils/hr-policy-seed-step.ts +110 -0
  94. package/i18n/locales/en.json +726 -0
  95. package/i18n/locales/vi.json +688 -0
  96. package/nuxt.config.ts +19 -0
  97. package/package.json +27 -0
  98. package/server/api/hr/departments/[id].delete.ts +12 -0
  99. package/server/api/hr/departments/[id].patch.ts +14 -0
  100. package/server/api/hr/departments/index.get.ts +11 -0
  101. package/server/api/hr/departments/index.post.ts +13 -0
  102. package/server/api/hr/documents/templates/[id]/preview.post.ts +16 -0
  103. package/server/api/hr/documents/templates/[id].delete.ts +14 -0
  104. package/server/api/hr/documents/templates/[id].patch.ts +16 -0
  105. package/server/api/hr/documents/templates/index.get.ts +15 -0
  106. package/server/api/hr/documents/templates/index.post.ts +15 -0
  107. package/server/api/hr/documents/triggers/[id].patch.ts +16 -0
  108. package/server/api/hr/documents/triggers/index.get.ts +13 -0
  109. package/server/api/hr/fields/[collection].get.ts +14 -0
  110. package/server/api/hr/holidays/[id].delete.ts +14 -0
  111. package/server/api/hr/holidays/[id].patch.ts +16 -0
  112. package/server/api/hr/holidays/copy.post.ts +15 -0
  113. package/server/api/hr/holidays/index.get.ts +15 -0
  114. package/server/api/hr/holidays/index.post.ts +15 -0
  115. package/server/api/hr/leave/requests/[id].patch.ts +22 -0
  116. package/server/api/hr/leave/requests.get.ts +15 -0
  117. package/server/api/hr/leave/types.get.ts +13 -0
  118. package/server/api/hr/offboarding/[id]/cancel.post.ts +8 -0
  119. package/server/api/hr/offboarding/[id]/deprovision.post.ts +8 -0
  120. package/server/api/hr/offboarding/[id]/finalize.post.ts +8 -0
  121. package/server/api/hr/offboarding/[id]/return-assets.post.ts +8 -0
  122. package/server/api/hr/offboarding/[id]/settlement.get.ts +8 -0
  123. package/server/api/hr/offboarding/[id]/tasks/[taskId].patch.ts +10 -0
  124. package/server/api/hr/offboarding/[id].get.ts +8 -0
  125. package/server/api/hr/offboarding/[id].patch.ts +9 -0
  126. package/server/api/hr/offboarding/index.get.ts +7 -0
  127. package/server/api/hr/people/[id]/applications/[appId]/interviews/[iid].delete.ts +16 -0
  128. package/server/api/hr/people/[id]/applications/[appId]/interviews/[iid].patch.ts +18 -0
  129. package/server/api/hr/people/[id]/applications/[appId]/interviews/index.get.ts +15 -0
  130. package/server/api/hr/people/[id]/applications/[appId]/interviews/index.post.ts +17 -0
  131. package/server/api/hr/people/[id]/applications/[appId].patch.ts +17 -0
  132. package/server/api/hr/people/[id]/applications/index.get.ts +14 -0
  133. package/server/api/hr/people/[id]/applications/index.post.ts +16 -0
  134. package/server/api/hr/people/[id]/assets/[aid].delete.ts +13 -0
  135. package/server/api/hr/people/[id]/assets/[aid].patch.ts +15 -0
  136. package/server/api/hr/people/[id]/assets/index.get.ts +12 -0
  137. package/server/api/hr/people/[id]/assets/index.post.ts +14 -0
  138. package/server/api/hr/people/[id]/compensations.get.ts +14 -0
  139. package/server/api/hr/people/[id]/compensations.patch.ts +16 -0
  140. package/server/api/hr/people/[id]/contracts.get.ts +14 -0
  141. package/server/api/hr/people/[id]/contracts.patch.ts +16 -0
  142. package/server/api/hr/people/[id]/documents/[did].delete.ts +15 -0
  143. package/server/api/hr/people/[id]/documents/index.get.ts +14 -0
  144. package/server/api/hr/people/[id]/documents/index.post.ts +16 -0
  145. package/server/api/hr/people/[id]/insurances.get.ts +14 -0
  146. package/server/api/hr/people/[id]/insurances.patch.ts +16 -0
  147. package/server/api/hr/people/[id]/leave-balances/[bid].patch.ts +17 -0
  148. package/server/api/hr/people/[id]/leave-balances/index.get.ts +14 -0
  149. package/server/api/hr/people/[id]/leave-requests/index.get.ts +14 -0
  150. package/server/api/hr/people/[id]/leave-requests/index.post.ts +16 -0
  151. package/server/api/hr/people/[id]/link-user.post.ts +16 -0
  152. package/server/api/hr/people/[id]/notes/[nid].delete.ts +15 -0
  153. package/server/api/hr/people/[id]/notes/index.get.ts +14 -0
  154. package/server/api/hr/people/[id]/notes/index.post.ts +16 -0
  155. package/server/api/hr/people/[id]/offboarding/cases.get.ts +12 -0
  156. package/server/api/hr/people/[id]/offboarding.get.ts +12 -0
  157. package/server/api/hr/people/[id]/offboarding.post.ts +14 -0
  158. package/server/api/hr/people/[id]/provisioning/[logId]/retry.post.ts +7 -0
  159. package/server/api/hr/people/[id]/provisioning/index.get.ts +6 -0
  160. package/server/api/hr/people/[id]/provisioning/index.post.ts +7 -0
  161. package/server/api/hr/people/[id]/transition.post.ts +19 -0
  162. package/server/api/hr/people/[id]/transitions.get.ts +14 -0
  163. package/server/api/hr/people/[id].delete.ts +15 -0
  164. package/server/api/hr/people/[id].get.ts +14 -0
  165. package/server/api/hr/people/[id].patch.ts +17 -0
  166. package/server/api/hr/people/index.get.ts +15 -0
  167. package/server/api/hr/people/index.post.ts +19 -0
  168. package/server/api/hr/policies/[id].patch.ts +16 -0
  169. package/server/api/hr/policies/index.get.ts +13 -0
  170. package/server/api/hr/providers/[id]/test.post.ts +6 -0
  171. package/server/api/hr/providers/[id].delete.ts +6 -0
  172. package/server/api/hr/providers/[id].patch.ts +7 -0
  173. package/server/api/hr/providers/index.get.ts +5 -0
  174. package/server/api/hr/providers/index.post.ts +6 -0
  175. package/server/api/hr/settings/employment-types/[id].delete.ts +14 -0
  176. package/server/api/hr/settings/employment-types/[id].patch.ts +16 -0
  177. package/server/api/hr/settings/employment-types/index.get.ts +13 -0
  178. package/server/api/hr/settings/employment-types/index.post.ts +15 -0
  179. package/server/api/hr/settings/index.get.ts +13 -0
  180. package/server/api/hr/settings/index.patch.ts +15 -0
  181. package/server/api/hr/settings/leave-types/[id].delete.ts +14 -0
  182. package/server/api/hr/settings/leave-types/[id].patch.ts +16 -0
  183. package/server/api/hr/settings/leave-types/index.get.ts +13 -0
  184. package/server/api/hr/settings/leave-types/index.post.ts +15 -0
  185. package/shared/types/form-layout.ts +30 -0
  186. package/shared/types/index.ts +2 -0
  187. package/shared/types/integration.ts +41 -0
  188. package/shared/types/leave.ts +53 -0
  189. package/shared/types/offboarding.ts +46 -0
  190. package/shared/types/person.ts +54 -0
  191. package/shared/types/settings.ts +16 -0
  192. package/shared/utils/template-render.ts +155 -0
@@ -0,0 +1,2608 @@
1
+ export const hrSchema: ModuleSchema = {
2
+ module: "hr",
3
+ version: 1,
4
+ label: "HR",
5
+ icon: "i-ph-user-list-light",
6
+ description: "Human Resources — talents, employees, leave, documents, and provisioning.",
7
+ route: {
8
+ prefix: "/hr",
9
+ setupPath: "/hr/setup",
10
+ },
11
+ collections: [
12
+ // ── Label folder ──
13
+ {
14
+ collection: "hr",
15
+ meta: { icon: "i-ph-user-list-light", sort: 1, collapse: "open", type: "label" },
16
+ schema: null,
17
+ },
18
+
19
+ // ── People (talents + employees) ──
20
+ {
21
+ collection: "hr_people",
22
+ meta: { hidden: true, sort: 2, group: "hr", accountability: "all" },
23
+ schema: { name: "hr_people" },
24
+ },
25
+
26
+ // ── Departments ──
27
+ {
28
+ collection: "hr_departments",
29
+ meta: { hidden: true, sort: 3, group: "hr", accountability: "all" },
30
+ schema: { name: "hr_departments" },
31
+ },
32
+
33
+ // ── Employment types (lookup, seeded) ──
34
+ {
35
+ collection: "hr_employment_types",
36
+ meta: { hidden: true, sort: 4, group: "hr", accountability: "all" },
37
+ schema: { name: "hr_employment_types" },
38
+ },
39
+
40
+ // ── Stage transitions (audit trail) ──
41
+ {
42
+ collection: "hr_stage_transitions",
43
+ meta: { hidden: true, sort: 5, group: "hr", accountability: "all" },
44
+ schema: { name: "hr_stage_transitions" },
45
+ },
46
+
47
+ // ── Applications (one per recruitment round per person) ──
48
+ {
49
+ collection: "hr_applications",
50
+ meta: { hidden: true, sort: 6, group: "hr", accountability: "all" },
51
+ schema: { name: "hr_applications" },
52
+ },
53
+
54
+ // ── Interviews (per application) ──
55
+ {
56
+ collection: "hr_interviews",
57
+ meta: { hidden: true, sort: 7, group: "hr", accountability: "all" },
58
+ schema: { name: "hr_interviews" },
59
+ },
60
+
61
+ // ── Offers (1:1 per application) ──
62
+ {
63
+ collection: "hr_offers",
64
+ meta: { hidden: true, sort: 8, group: "hr", accountability: "all" },
65
+ schema: { name: "hr_offers" },
66
+ },
67
+
68
+ // ── Contracts ──
69
+ {
70
+ collection: "hr_contracts",
71
+ meta: { hidden: true, sort: 9, group: "hr", accountability: "all" },
72
+ schema: { name: "hr_contracts" },
73
+ },
74
+
75
+ // ── Compensations ──
76
+ {
77
+ collection: "hr_compensations",
78
+ meta: { hidden: true, sort: 10, group: "hr", accountability: "all" },
79
+ schema: { name: "hr_compensations" },
80
+ },
81
+
82
+ // ── Compensation allowances (O2M per compensation) ──
83
+ {
84
+ collection: "hr_compensation_allowances",
85
+ meta: { hidden: true, sort: 11, group: "hr", accountability: "all" },
86
+ schema: { name: "hr_compensation_allowances" },
87
+ },
88
+
89
+ // ── Insurances ──
90
+ {
91
+ collection: "hr_insurances",
92
+ meta: { hidden: true, sort: 12, group: "hr", accountability: "all" },
93
+ schema: { name: "hr_insurances" },
94
+ },
95
+
96
+ // ── Leave types (lookup, seeded) ──
97
+ {
98
+ collection: "hr_leave_types",
99
+ meta: { hidden: true, sort: 13, group: "hr", accountability: "all" },
100
+ schema: { name: "hr_leave_types" },
101
+ },
102
+
103
+ // ── Leave balances (per person per leave type) ──
104
+ {
105
+ collection: "hr_leave_balances",
106
+ meta: { hidden: true, sort: 14, group: "hr", accountability: "all" },
107
+ schema: { name: "hr_leave_balances" },
108
+ },
109
+
110
+ // ── Leave requests ──
111
+ {
112
+ collection: "hr_leave_requests",
113
+ meta: { hidden: true, sort: 15, group: "hr", accountability: "all" },
114
+ schema: { name: "hr_leave_requests" },
115
+ },
116
+
117
+ // ── Company holidays ──
118
+ {
119
+ collection: "hr_company_holidays",
120
+ meta: { hidden: true, sort: 16, group: "hr", accountability: "all" },
121
+ schema: { name: "hr_company_holidays" },
122
+ },
123
+
124
+ // ── Documents ──
125
+ {
126
+ collection: "hr_documents",
127
+ meta: { hidden: true, sort: 17, group: "hr", accountability: "all" },
128
+ schema: { name: "hr_documents" },
129
+ },
130
+
131
+ // ── Document templates ──
132
+ {
133
+ collection: "hr_document_templates",
134
+ meta: { hidden: true, sort: 18, group: "hr", accountability: "all" },
135
+ schema: { name: "hr_document_templates" },
136
+ },
137
+
138
+ // ── Document triggers ──
139
+ {
140
+ collection: "hr_document_triggers",
141
+ meta: { hidden: true, sort: 19, group: "hr", accountability: "all" },
142
+ schema: { name: "hr_document_triggers" },
143
+ },
144
+
145
+ // ── Trigger-template junction (M2M) ──
146
+ {
147
+ collection: "hr_document_trigger_tpl_jn",
148
+ meta: { hidden: true, sort: 20, group: "hr", accountability: "all" },
149
+ schema: { name: "hr_document_trigger_tpl_jn" },
150
+ },
151
+
152
+ // ── Assets ──
153
+ {
154
+ collection: "hr_assets",
155
+ meta: { hidden: true, sort: 21, group: "hr", accountability: "all" },
156
+ schema: { name: "hr_assets" },
157
+ },
158
+
159
+ // ── Notes (per person) ──
160
+ {
161
+ collection: "hr_notes",
162
+ meta: { hidden: true, sort: 22, group: "hr", accountability: "all" },
163
+ schema: { name: "hr_notes" },
164
+ },
165
+
166
+ // ── Policies (leave, benefit, probation rules) ──
167
+ {
168
+ collection: "hr_policies",
169
+ meta: { hidden: true, sort: 23, group: "hr", accountability: "all" },
170
+ schema: { name: "hr_policies" },
171
+ },
172
+
173
+ // ── Settings (singleton) ──
174
+ {
175
+ collection: "hr_settings",
176
+ meta: { hidden: true, sort: 24, group: "hr", singleton: true, accountability: "all" },
177
+ schema: { name: "hr_settings" },
178
+ },
179
+
180
+ // ── 3rd-party integration providers ──
181
+ {
182
+ collection: "hr_providers",
183
+ meta: { hidden: true, sort: 25, group: "hr", accountability: "all" },
184
+ schema: { name: "hr_providers" },
185
+ },
186
+
187
+ // ── Provisioning logs (audit trail) ──
188
+ {
189
+ collection: "hr_provisioning_logs",
190
+ meta: { hidden: true, sort: 26, group: "hr", accountability: "all" },
191
+ schema: { name: "hr_provisioning_logs" },
192
+ },
193
+
194
+ // ── Off-boarding case ──
195
+ {
196
+ collection: "hr_offboarding",
197
+ meta: { hidden: true, sort: 27, group: "hr", accountability: "all" },
198
+ schema: { name: "hr_offboarding" },
199
+ },
200
+
201
+ // ── Off-boarding clearance tasks ──
202
+ {
203
+ collection: "hr_offboarding_tasks",
204
+ meta: { hidden: true, sort: 28, group: "hr", accountability: "all" },
205
+ schema: { name: "hr_offboarding_tasks" },
206
+ },
207
+ ],
208
+
209
+ fields: [
210
+ // ════════════════════════════════════════
211
+ // hr_people
212
+ // ════════════════════════════════════════
213
+ {
214
+ collection: "hr_people",
215
+ field: "id",
216
+ type: "integer",
217
+ meta: { hidden: true, readonly: true, interface: "input" },
218
+ schema: { is_primary_key: true, has_auto_increment: true },
219
+ },
220
+ {
221
+ collection: "hr_people",
222
+ field: "stage",
223
+ type: "string",
224
+ meta: {
225
+ interface: "select",
226
+ width: "half",
227
+ required: true,
228
+ options: {
229
+ choices: [
230
+ { text: "Talent", value: "talent" },
231
+ { text: "Interviewing", value: "interviewing" },
232
+ { text: "Offer", value: "offer" },
233
+ { text: "Probation", value: "probation" },
234
+ { text: "Active", value: "active" },
235
+ { text: "Resigned", value: "resigned" },
236
+ ],
237
+ },
238
+ },
239
+ schema: { is_nullable: false, default_value: "talent" },
240
+ },
241
+ {
242
+ collection: "hr_people",
243
+ field: "employee_id",
244
+ type: "string",
245
+ meta: { interface: "input", width: "half" },
246
+ schema: { is_unique: true },
247
+ },
248
+ {
249
+ collection: "hr_people",
250
+ field: "first_name",
251
+ type: "string",
252
+ meta: { interface: "input", width: "half", required: true },
253
+ schema: { is_nullable: false },
254
+ },
255
+ {
256
+ collection: "hr_people",
257
+ field: "last_name",
258
+ type: "string",
259
+ meta: { interface: "input", width: "half", required: true },
260
+ schema: { is_nullable: false },
261
+ },
262
+ {
263
+ collection: "hr_people",
264
+ field: "display_name",
265
+ type: "string",
266
+ meta: { interface: "input", width: "full", required: true },
267
+ schema: { is_nullable: false },
268
+ },
269
+ {
270
+ collection: "hr_people",
271
+ field: "email",
272
+ type: "string",
273
+ meta: { interface: "input", width: "half" },
274
+ schema: {},
275
+ },
276
+ {
277
+ collection: "hr_people",
278
+ field: "phone",
279
+ type: "string",
280
+ meta: { interface: "input", width: "half" },
281
+ schema: {},
282
+ },
283
+ {
284
+ collection: "hr_people",
285
+ field: "avatar",
286
+ type: "uuid",
287
+ meta: { interface: "file-image", width: "half" },
288
+ schema: {},
289
+ },
290
+ {
291
+ collection: "hr_people",
292
+ field: "date_of_birth",
293
+ type: "date",
294
+ meta: { interface: "datetime", width: "half" },
295
+ schema: {},
296
+ },
297
+ {
298
+ collection: "hr_people",
299
+ field: "gender",
300
+ type: "string",
301
+ meta: {
302
+ interface: "select",
303
+ width: "half",
304
+ options: {
305
+ choices: [
306
+ { text: "Male", value: "male" },
307
+ { text: "Female", value: "female" },
308
+ { text: "Other", value: "other" },
309
+ ],
310
+ },
311
+ },
312
+ schema: {},
313
+ },
314
+ {
315
+ collection: "hr_people",
316
+ field: "nationality",
317
+ type: "string",
318
+ meta: { interface: "input", width: "half" },
319
+ schema: {},
320
+ },
321
+ {
322
+ collection: "hr_people",
323
+ field: "id_number",
324
+ type: "string",
325
+ meta: { interface: "input", width: "half" },
326
+ schema: {},
327
+ },
328
+ {
329
+ collection: "hr_people",
330
+ field: "address",
331
+ type: "string",
332
+ meta: { interface: "input", width: "full" },
333
+ schema: {},
334
+ },
335
+ {
336
+ collection: "hr_people",
337
+ field: "desired_position",
338
+ type: "string",
339
+ meta: { interface: "input", width: "half" },
340
+ schema: {},
341
+ },
342
+ {
343
+ collection: "hr_people",
344
+ field: "source",
345
+ type: "string",
346
+ meta: { interface: "input", width: "half" },
347
+ schema: {},
348
+ },
349
+ {
350
+ collection: "hr_people",
351
+ field: "department_id",
352
+ type: "integer",
353
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
354
+ schema: {},
355
+ },
356
+ {
357
+ collection: "hr_people",
358
+ field: "employment_type_id",
359
+ type: "integer",
360
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
361
+ schema: {},
362
+ },
363
+ {
364
+ collection: "hr_people",
365
+ field: "user_id",
366
+ type: "uuid",
367
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, note: "Linked ODP user account (for self-service & manager scoping)" },
368
+ schema: {},
369
+ },
370
+ {
371
+ collection: "hr_people",
372
+ field: "job_title",
373
+ type: "string",
374
+ meta: { interface: "input", width: "half" },
375
+ schema: {},
376
+ },
377
+ {
378
+ collection: "hr_people",
379
+ field: "start_date",
380
+ type: "date",
381
+ meta: { interface: "datetime", width: "half" },
382
+ schema: {},
383
+ },
384
+ {
385
+ collection: "hr_people",
386
+ field: "end_date",
387
+ type: "date",
388
+ meta: { interface: "datetime", width: "half" },
389
+ schema: {},
390
+ },
391
+ // O2M alias fields
392
+ {
393
+ collection: "hr_people",
394
+ field: "applications",
395
+ type: "alias",
396
+ meta: { interface: "list-o2m", special: ["o2m"], width: "full" },
397
+ schema: null,
398
+ },
399
+ {
400
+ collection: "hr_people",
401
+ field: "stage_transitions",
402
+ type: "alias",
403
+ meta: { interface: "list-o2m", special: ["o2m"], width: "full" },
404
+ schema: null,
405
+ },
406
+ {
407
+ collection: "hr_people",
408
+ field: "notes",
409
+ type: "alias",
410
+ meta: { interface: "list-o2m", special: ["o2m"], width: "full" },
411
+ schema: null,
412
+ },
413
+ // System fields
414
+ {
415
+ collection: "hr_people",
416
+ field: "date_created",
417
+ type: "timestamp",
418
+ meta: { interface: "datetime", readonly: true, hidden: true, width: "half", special: ["date-created"] },
419
+ schema: {},
420
+ },
421
+ {
422
+ collection: "hr_people",
423
+ field: "date_updated",
424
+ type: "timestamp",
425
+ meta: { interface: "datetime", readonly: true, hidden: true, width: "half", special: ["date-updated"] },
426
+ schema: {},
427
+ },
428
+ {
429
+ collection: "hr_people",
430
+ field: "user_created",
431
+ type: "uuid",
432
+ meta: { interface: "select-dropdown-m2o", special: ["user-created"], readonly: true, hidden: true, width: "half" },
433
+ schema: {},
434
+ },
435
+ {
436
+ collection: "hr_people",
437
+ field: "user_updated",
438
+ type: "uuid",
439
+ meta: { interface: "select-dropdown-m2o", special: ["user-updated"], readonly: true, hidden: true, width: "half" },
440
+ schema: {},
441
+ },
442
+
443
+ // ════════════════════════════════════════
444
+ // hr_departments
445
+ // ════════════════════════════════════════
446
+ {
447
+ collection: "hr_departments",
448
+ field: "id",
449
+ type: "integer",
450
+ meta: { hidden: true, readonly: true, interface: "input" },
451
+ schema: { is_primary_key: true, has_auto_increment: true },
452
+ },
453
+ {
454
+ collection: "hr_departments",
455
+ field: "name",
456
+ type: "string",
457
+ meta: { interface: "input", width: "half", required: true },
458
+ schema: { is_nullable: false },
459
+ },
460
+ {
461
+ collection: "hr_departments",
462
+ field: "code",
463
+ type: "string",
464
+ meta: { interface: "input", width: "half" },
465
+ schema: { is_unique: true },
466
+ },
467
+ {
468
+ collection: "hr_departments",
469
+ field: "head_person_id",
470
+ type: "integer",
471
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
472
+ schema: {},
473
+ },
474
+ {
475
+ collection: "hr_departments",
476
+ field: "parent_department_id",
477
+ type: "integer",
478
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
479
+ schema: {},
480
+ },
481
+ {
482
+ collection: "hr_departments",
483
+ field: "description",
484
+ type: "text",
485
+ meta: { interface: "input-multiline", width: "full" },
486
+ schema: {},
487
+ },
488
+ {
489
+ collection: "hr_departments",
490
+ field: "sort",
491
+ type: "integer",
492
+ meta: { interface: "input", hidden: true },
493
+ schema: {},
494
+ },
495
+ {
496
+ collection: "hr_departments",
497
+ field: "date_created",
498
+ type: "timestamp",
499
+ meta: { interface: "datetime", readonly: true, hidden: true, width: "half", special: ["date-created"] },
500
+ schema: {},
501
+ },
502
+ {
503
+ collection: "hr_departments",
504
+ field: "date_updated",
505
+ type: "timestamp",
506
+ meta: { interface: "datetime", readonly: true, hidden: true, width: "half", special: ["date-updated"] },
507
+ schema: {},
508
+ },
509
+
510
+ // ════════════════════════════════════════
511
+ // hr_employment_types
512
+ // ════════════════════════════════════════
513
+ {
514
+ collection: "hr_employment_types",
515
+ field: "id",
516
+ type: "integer",
517
+ meta: { hidden: true, readonly: true, interface: "input" },
518
+ schema: { is_primary_key: true, has_auto_increment: true },
519
+ },
520
+ {
521
+ collection: "hr_employment_types",
522
+ field: "key",
523
+ type: "string",
524
+ meta: { interface: "input", width: "half", required: true },
525
+ schema: { is_nullable: false, is_unique: true },
526
+ },
527
+ {
528
+ collection: "hr_employment_types",
529
+ field: "label",
530
+ type: "string",
531
+ meta: { interface: "input", width: "half", required: true },
532
+ schema: { is_nullable: false },
533
+ },
534
+ {
535
+ collection: "hr_employment_types",
536
+ field: "sort",
537
+ type: "integer",
538
+ meta: { interface: "input", hidden: true },
539
+ schema: {},
540
+ },
541
+
542
+ // ════════════════════════════════════════
543
+ // hr_stage_transitions
544
+ // ════════════════════════════════════════
545
+ {
546
+ collection: "hr_stage_transitions",
547
+ field: "id",
548
+ type: "integer",
549
+ meta: { hidden: true, readonly: true, interface: "input" },
550
+ schema: { is_primary_key: true, has_auto_increment: true },
551
+ },
552
+ {
553
+ collection: "hr_stage_transitions",
554
+ field: "person_id",
555
+ type: "integer",
556
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
557
+ schema: { is_nullable: false },
558
+ },
559
+ {
560
+ collection: "hr_stage_transitions",
561
+ field: "from_stage",
562
+ type: "string",
563
+ meta: { interface: "input", width: "half", readonly: true },
564
+ schema: {},
565
+ },
566
+ {
567
+ collection: "hr_stage_transitions",
568
+ field: "to_stage",
569
+ type: "string",
570
+ meta: { interface: "input", width: "half", required: true, readonly: true },
571
+ schema: { is_nullable: false },
572
+ },
573
+ {
574
+ collection: "hr_stage_transitions",
575
+ field: "reason",
576
+ type: "string",
577
+ meta: { interface: "input", width: "full" },
578
+ schema: {},
579
+ },
580
+ {
581
+ collection: "hr_stage_transitions",
582
+ field: "performed_by",
583
+ type: "uuid",
584
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half", readonly: true },
585
+ schema: {},
586
+ },
587
+ {
588
+ collection: "hr_stage_transitions",
589
+ field: "date_created",
590
+ type: "timestamp",
591
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
592
+ schema: {},
593
+ },
594
+
595
+ // ════════════════════════════════════════
596
+ // hr_applications
597
+ // ════════════════════════════════════════
598
+ {
599
+ collection: "hr_applications",
600
+ field: "id",
601
+ type: "integer",
602
+ meta: { hidden: true, readonly: true, interface: "input" },
603
+ schema: { is_primary_key: true, has_auto_increment: true },
604
+ },
605
+ {
606
+ collection: "hr_applications",
607
+ field: "person_id",
608
+ type: "integer",
609
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
610
+ schema: { is_nullable: false },
611
+ },
612
+ {
613
+ collection: "hr_applications",
614
+ field: "status",
615
+ type: "string",
616
+ meta: {
617
+ interface: "select",
618
+ width: "half",
619
+ required: true,
620
+ options: {
621
+ choices: [
622
+ { text: "Open", value: "open" },
623
+ { text: "Closed", value: "closed" },
624
+ { text: "Hired", value: "hired" },
625
+ { text: "Rejected", value: "rejected" },
626
+ ],
627
+ },
628
+ },
629
+ schema: { is_nullable: false, default_value: "open" },
630
+ },
631
+ {
632
+ collection: "hr_applications",
633
+ field: "position",
634
+ type: "string",
635
+ meta: { interface: "input", width: "half" },
636
+ schema: {},
637
+ },
638
+ {
639
+ collection: "hr_applications",
640
+ field: "notes",
641
+ type: "text",
642
+ meta: { interface: "input-multiline", width: "full" },
643
+ schema: {},
644
+ },
645
+ {
646
+ collection: "hr_applications",
647
+ field: "workflow_instance_id",
648
+ type: "string",
649
+ meta: { interface: "input", width: "half", hidden: true },
650
+ schema: { is_nullable: true },
651
+ },
652
+ // O2M alias fields
653
+ {
654
+ collection: "hr_applications",
655
+ field: "interviews",
656
+ type: "alias",
657
+ meta: { interface: "list-o2m", special: ["o2m"], width: "full" },
658
+ schema: null,
659
+ },
660
+ {
661
+ collection: "hr_applications",
662
+ field: "date_created",
663
+ type: "timestamp",
664
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
665
+ schema: {},
666
+ },
667
+ {
668
+ collection: "hr_applications",
669
+ field: "date_updated",
670
+ type: "timestamp",
671
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
672
+ schema: {},
673
+ },
674
+
675
+ // ════════════════════════════════════════
676
+ // hr_interviews
677
+ // ════════════════════════════════════════
678
+ {
679
+ collection: "hr_interviews",
680
+ field: "id",
681
+ type: "integer",
682
+ meta: { hidden: true, readonly: true, interface: "input" },
683
+ schema: { is_primary_key: true, has_auto_increment: true },
684
+ },
685
+ {
686
+ collection: "hr_interviews",
687
+ field: "application_id",
688
+ type: "integer",
689
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
690
+ schema: { is_nullable: false },
691
+ },
692
+ {
693
+ collection: "hr_interviews",
694
+ field: "type",
695
+ type: "string",
696
+ meta: {
697
+ interface: "select",
698
+ width: "half",
699
+ options: {
700
+ choices: [
701
+ { text: "HR Screen", value: "hr_screen" },
702
+ { text: "Technical", value: "technical" },
703
+ { text: "Manager", value: "manager" },
704
+ { text: "Final", value: "final" },
705
+ { text: "Other", value: "other" },
706
+ ],
707
+ },
708
+ },
709
+ schema: { default_value: "hr_screen" },
710
+ },
711
+ {
712
+ collection: "hr_interviews",
713
+ field: "status",
714
+ type: "string",
715
+ meta: {
716
+ interface: "select",
717
+ width: "half",
718
+ options: {
719
+ choices: [
720
+ { text: "Scheduled", value: "scheduled" },
721
+ { text: "Done", value: "done" },
722
+ { text: "Cancelled", value: "cancelled" },
723
+ { text: "No Show", value: "no_show" },
724
+ ],
725
+ },
726
+ },
727
+ schema: { default_value: "scheduled" },
728
+ },
729
+ {
730
+ collection: "hr_interviews",
731
+ field: "interviewer",
732
+ type: "uuid",
733
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
734
+ schema: {},
735
+ },
736
+ {
737
+ collection: "hr_interviews",
738
+ field: "score",
739
+ type: "integer",
740
+ meta: { interface: "input", width: "half" },
741
+ schema: {},
742
+ },
743
+ {
744
+ collection: "hr_interviews",
745
+ field: "notes",
746
+ type: "text",
747
+ meta: { interface: "input-multiline", width: "full" },
748
+ schema: {},
749
+ },
750
+ {
751
+ collection: "hr_interviews",
752
+ field: "scheduled_at",
753
+ type: "timestamp",
754
+ meta: { interface: "datetime", width: "half" },
755
+ schema: {},
756
+ },
757
+ {
758
+ collection: "hr_interviews",
759
+ field: "label",
760
+ type: "string",
761
+ meta: { interface: "input", width: "half" },
762
+ schema: { is_nullable: true },
763
+ },
764
+ {
765
+ collection: "hr_interviews",
766
+ field: "workflow_step_id",
767
+ type: "string",
768
+ meta: { interface: "input", width: "half", hidden: true },
769
+ schema: { is_nullable: true },
770
+ },
771
+ {
772
+ collection: "hr_interviews",
773
+ field: "date_created",
774
+ type: "timestamp",
775
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
776
+ schema: {},
777
+ },
778
+ {
779
+ collection: "hr_interviews",
780
+ field: "date_updated",
781
+ type: "timestamp",
782
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
783
+ schema: {},
784
+ },
785
+
786
+ // ════════════════════════════════════════
787
+ // hr_offers
788
+ // ════════════════════════════════════════
789
+ {
790
+ collection: "hr_offers",
791
+ field: "id",
792
+ type: "integer",
793
+ meta: { hidden: true, readonly: true, interface: "input" },
794
+ schema: { is_primary_key: true, has_auto_increment: true },
795
+ },
796
+ {
797
+ collection: "hr_offers",
798
+ field: "application_id",
799
+ type: "integer",
800
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
801
+ schema: { is_nullable: false },
802
+ },
803
+ {
804
+ collection: "hr_offers",
805
+ field: "status",
806
+ type: "string",
807
+ meta: {
808
+ interface: "select",
809
+ width: "half",
810
+ options: {
811
+ choices: [
812
+ { text: "Draft", value: "draft" },
813
+ { text: "Sent", value: "sent" },
814
+ { text: "Accepted", value: "accepted" },
815
+ { text: "Declined", value: "declined" },
816
+ { text: "Expired", value: "expired" },
817
+ ],
818
+ },
819
+ },
820
+ schema: { default_value: "draft" },
821
+ },
822
+ {
823
+ collection: "hr_offers",
824
+ field: "salary",
825
+ type: "decimal",
826
+ meta: { interface: "input", width: "half" },
827
+ schema: {},
828
+ },
829
+ {
830
+ collection: "hr_offers",
831
+ field: "currency",
832
+ type: "string",
833
+ meta: { interface: "input", width: "half" },
834
+ schema: { default_value: "VND" },
835
+ },
836
+ {
837
+ collection: "hr_offers",
838
+ field: "valid_until",
839
+ type: "date",
840
+ meta: { interface: "datetime", width: "half" },
841
+ schema: {},
842
+ },
843
+ {
844
+ collection: "hr_offers",
845
+ field: "decline_reason",
846
+ type: "string",
847
+ meta: { interface: "input", width: "full" },
848
+ schema: {},
849
+ },
850
+ {
851
+ collection: "hr_offers",
852
+ field: "notes",
853
+ type: "text",
854
+ meta: { interface: "input-multiline", width: "full" },
855
+ schema: {},
856
+ },
857
+ {
858
+ collection: "hr_offers",
859
+ field: "date_created",
860
+ type: "timestamp",
861
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
862
+ schema: {},
863
+ },
864
+ {
865
+ collection: "hr_offers",
866
+ field: "date_updated",
867
+ type: "timestamp",
868
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
869
+ schema: {},
870
+ },
871
+
872
+ // ════════════════════════════════════════
873
+ // hr_contracts
874
+ // ════════════════════════════════════════
875
+ {
876
+ collection: "hr_contracts",
877
+ field: "id",
878
+ type: "integer",
879
+ meta: { hidden: true, readonly: true, interface: "input" },
880
+ schema: { is_primary_key: true, has_auto_increment: true },
881
+ },
882
+ {
883
+ collection: "hr_contracts",
884
+ field: "person_id",
885
+ type: "integer",
886
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
887
+ schema: { is_nullable: false },
888
+ },
889
+ {
890
+ collection: "hr_contracts",
891
+ field: "contract_number",
892
+ type: "string",
893
+ meta: { interface: "input", width: "half" },
894
+ schema: { is_unique: true },
895
+ },
896
+ {
897
+ collection: "hr_contracts",
898
+ field: "type",
899
+ type: "string",
900
+ meta: {
901
+ interface: "select",
902
+ width: "half",
903
+ options: {
904
+ choices: [
905
+ { text: "Indefinite", value: "indefinite" },
906
+ { text: "Fixed Term", value: "fixed_term" },
907
+ { text: "Probation", value: "probation" },
908
+ { text: "Freelance", value: "freelance" },
909
+ ],
910
+ },
911
+ },
912
+ schema: {},
913
+ },
914
+ {
915
+ collection: "hr_contracts",
916
+ field: "start_date",
917
+ type: "date",
918
+ meta: { interface: "datetime", width: "half" },
919
+ schema: {},
920
+ },
921
+ {
922
+ collection: "hr_contracts",
923
+ field: "end_date",
924
+ type: "date",
925
+ meta: { interface: "datetime", width: "half" },
926
+ schema: {},
927
+ },
928
+ {
929
+ collection: "hr_contracts",
930
+ field: "probation_end",
931
+ type: "date",
932
+ meta: { interface: "datetime", width: "half" },
933
+ schema: {},
934
+ },
935
+ {
936
+ collection: "hr_contracts",
937
+ field: "renewal_count",
938
+ type: "integer",
939
+ meta: { interface: "input", width: "half" },
940
+ schema: { default_value: 0 },
941
+ },
942
+ {
943
+ collection: "hr_contracts",
944
+ field: "notes",
945
+ type: "text",
946
+ meta: { interface: "input-multiline", width: "full" },
947
+ schema: {},
948
+ },
949
+ {
950
+ collection: "hr_contracts",
951
+ field: "date_created",
952
+ type: "timestamp",
953
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
954
+ schema: {},
955
+ },
956
+ {
957
+ collection: "hr_contracts",
958
+ field: "date_updated",
959
+ type: "timestamp",
960
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
961
+ schema: {},
962
+ },
963
+
964
+ // ════════════════════════════════════════
965
+ // hr_compensations
966
+ // ════════════════════════════════════════
967
+ {
968
+ collection: "hr_compensations",
969
+ field: "id",
970
+ type: "integer",
971
+ meta: { hidden: true, readonly: true, interface: "input" },
972
+ schema: { is_primary_key: true, has_auto_increment: true },
973
+ },
974
+ {
975
+ collection: "hr_compensations",
976
+ field: "person_id",
977
+ type: "integer",
978
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
979
+ schema: { is_nullable: false },
980
+ },
981
+ {
982
+ collection: "hr_compensations",
983
+ field: "base_salary",
984
+ type: "decimal",
985
+ meta: { interface: "input", width: "half" },
986
+ schema: {},
987
+ },
988
+ {
989
+ collection: "hr_compensations",
990
+ field: "currency",
991
+ type: "string",
992
+ meta: { interface: "input", width: "half" },
993
+ schema: { default_value: "VND" },
994
+ },
995
+ {
996
+ collection: "hr_compensations",
997
+ field: "pay_cycle",
998
+ type: "string",
999
+ meta: {
1000
+ interface: "select",
1001
+ width: "half",
1002
+ options: {
1003
+ choices: [
1004
+ { text: "Monthly", value: "monthly" },
1005
+ { text: "Bi-weekly", value: "biweekly" },
1006
+ { text: "Weekly", value: "weekly" },
1007
+ ],
1008
+ },
1009
+ },
1010
+ schema: { default_value: "monthly" },
1011
+ },
1012
+ {
1013
+ collection: "hr_compensations",
1014
+ field: "effective_date",
1015
+ type: "date",
1016
+ meta: { interface: "datetime", width: "half" },
1017
+ schema: {},
1018
+ },
1019
+ // O2M alias for allowances
1020
+ {
1021
+ collection: "hr_compensations",
1022
+ field: "allowances",
1023
+ type: "alias",
1024
+ meta: { interface: "list-o2m", special: ["o2m"], width: "full" },
1025
+ schema: null,
1026
+ },
1027
+ {
1028
+ collection: "hr_compensations",
1029
+ field: "date_created",
1030
+ type: "timestamp",
1031
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
1032
+ schema: {},
1033
+ },
1034
+ {
1035
+ collection: "hr_compensations",
1036
+ field: "date_updated",
1037
+ type: "timestamp",
1038
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
1039
+ schema: {},
1040
+ },
1041
+
1042
+ // ════════════════════════════════════════
1043
+ // hr_compensation_allowances
1044
+ // ════════════════════════════════════════
1045
+ {
1046
+ collection: "hr_compensation_allowances",
1047
+ field: "id",
1048
+ type: "integer",
1049
+ meta: { hidden: true, readonly: true, interface: "input" },
1050
+ schema: { is_primary_key: true, has_auto_increment: true },
1051
+ },
1052
+ {
1053
+ collection: "hr_compensation_allowances",
1054
+ field: "compensation_id",
1055
+ type: "integer",
1056
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
1057
+ schema: { is_nullable: false },
1058
+ },
1059
+ {
1060
+ collection: "hr_compensation_allowances",
1061
+ field: "name",
1062
+ type: "string",
1063
+ meta: { interface: "input", width: "half", required: true },
1064
+ schema: { is_nullable: false },
1065
+ },
1066
+ {
1067
+ collection: "hr_compensation_allowances",
1068
+ field: "amount",
1069
+ type: "decimal",
1070
+ meta: { interface: "input", width: "half" },
1071
+ schema: {},
1072
+ },
1073
+ {
1074
+ collection: "hr_compensation_allowances",
1075
+ field: "taxable",
1076
+ type: "boolean",
1077
+ meta: { interface: "boolean", width: "half" },
1078
+ schema: { default_value: true },
1079
+ },
1080
+ {
1081
+ collection: "hr_compensation_allowances",
1082
+ field: "sort",
1083
+ type: "integer",
1084
+ meta: { interface: "input", hidden: true },
1085
+ schema: {},
1086
+ },
1087
+
1088
+ // ════════════════════════════════════════
1089
+ // hr_insurances
1090
+ // ════════════════════════════════════════
1091
+ {
1092
+ collection: "hr_insurances",
1093
+ field: "id",
1094
+ type: "integer",
1095
+ meta: { hidden: true, readonly: true, interface: "input" },
1096
+ schema: { is_primary_key: true, has_auto_increment: true },
1097
+ },
1098
+ {
1099
+ collection: "hr_insurances",
1100
+ field: "person_id",
1101
+ type: "integer",
1102
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
1103
+ schema: { is_nullable: false },
1104
+ },
1105
+ {
1106
+ collection: "hr_insurances",
1107
+ field: "social_insurance_number",
1108
+ type: "string",
1109
+ meta: { interface: "input", width: "half" },
1110
+ schema: {},
1111
+ },
1112
+ {
1113
+ collection: "hr_insurances",
1114
+ field: "health_insurance_number",
1115
+ type: "string",
1116
+ meta: { interface: "input", width: "half" },
1117
+ schema: {},
1118
+ },
1119
+ {
1120
+ collection: "hr_insurances",
1121
+ field: "eligible",
1122
+ type: "boolean",
1123
+ meta: { interface: "boolean", width: "half" },
1124
+ schema: { default_value: true },
1125
+ },
1126
+ {
1127
+ collection: "hr_insurances",
1128
+ field: "eligible_override",
1129
+ type: "boolean",
1130
+ meta: { interface: "boolean", width: "half", hidden: true },
1131
+ schema: {},
1132
+ },
1133
+ {
1134
+ collection: "hr_insurances",
1135
+ field: "notes",
1136
+ type: "text",
1137
+ meta: { interface: "input-multiline", width: "full" },
1138
+ schema: {},
1139
+ },
1140
+ {
1141
+ collection: "hr_insurances",
1142
+ field: "date_created",
1143
+ type: "timestamp",
1144
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
1145
+ schema: {},
1146
+ },
1147
+ {
1148
+ collection: "hr_insurances",
1149
+ field: "date_updated",
1150
+ type: "timestamp",
1151
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
1152
+ schema: {},
1153
+ },
1154
+
1155
+ // ════════════════════════════════════════
1156
+ // hr_leave_types
1157
+ // ════════════════════════════════════════
1158
+ {
1159
+ collection: "hr_leave_types",
1160
+ field: "id",
1161
+ type: "integer",
1162
+ meta: { hidden: true, readonly: true, interface: "input" },
1163
+ schema: { is_primary_key: true, has_auto_increment: true },
1164
+ },
1165
+ {
1166
+ collection: "hr_leave_types",
1167
+ field: "key",
1168
+ type: "string",
1169
+ meta: { interface: "input", width: "half", required: true },
1170
+ schema: { is_nullable: false, is_unique: true },
1171
+ },
1172
+ {
1173
+ collection: "hr_leave_types",
1174
+ field: "label",
1175
+ type: "string",
1176
+ meta: { interface: "input", width: "half", required: true },
1177
+ schema: { is_nullable: false },
1178
+ },
1179
+ {
1180
+ collection: "hr_leave_types",
1181
+ field: "default_days",
1182
+ type: "integer",
1183
+ meta: { interface: "input", width: "half" },
1184
+ schema: { default_value: 0 },
1185
+ },
1186
+ {
1187
+ collection: "hr_leave_types",
1188
+ field: "paid",
1189
+ type: "boolean",
1190
+ meta: { interface: "boolean", width: "half" },
1191
+ schema: { default_value: true },
1192
+ },
1193
+ {
1194
+ collection: "hr_leave_types",
1195
+ field: "sort",
1196
+ type: "integer",
1197
+ meta: { interface: "input", hidden: true },
1198
+ schema: {},
1199
+ },
1200
+
1201
+ // ════════════════════════════════════════
1202
+ // hr_leave_balances
1203
+ // ════════════════════════════════════════
1204
+ {
1205
+ collection: "hr_leave_balances",
1206
+ field: "id",
1207
+ type: "integer",
1208
+ meta: { hidden: true, readonly: true, interface: "input" },
1209
+ schema: { is_primary_key: true, has_auto_increment: true },
1210
+ },
1211
+ {
1212
+ collection: "hr_leave_balances",
1213
+ field: "person_id",
1214
+ type: "integer",
1215
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
1216
+ schema: { is_nullable: false },
1217
+ },
1218
+ {
1219
+ collection: "hr_leave_balances",
1220
+ field: "leave_type_id",
1221
+ type: "integer",
1222
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half", required: true },
1223
+ schema: { is_nullable: false },
1224
+ },
1225
+ {
1226
+ collection: "hr_leave_balances",
1227
+ field: "year",
1228
+ type: "integer",
1229
+ meta: { interface: "input", width: "half", required: true },
1230
+ schema: { is_nullable: false },
1231
+ },
1232
+ {
1233
+ collection: "hr_leave_balances",
1234
+ field: "allocated",
1235
+ type: "decimal",
1236
+ meta: { interface: "input", width: "half" },
1237
+ schema: { default_value: 0 },
1238
+ },
1239
+ {
1240
+ collection: "hr_leave_balances",
1241
+ field: "used",
1242
+ type: "decimal",
1243
+ meta: { interface: "input", width: "half" },
1244
+ schema: { default_value: 0 },
1245
+ },
1246
+ {
1247
+ collection: "hr_leave_balances",
1248
+ field: "override",
1249
+ type: "decimal",
1250
+ meta: { interface: "input", width: "half", hidden: true },
1251
+ schema: {},
1252
+ },
1253
+ {
1254
+ collection: "hr_leave_balances",
1255
+ field: "date_updated",
1256
+ type: "timestamp",
1257
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
1258
+ schema: {},
1259
+ },
1260
+
1261
+ // ════════════════════════════════════════
1262
+ // hr_leave_requests
1263
+ // ════════════════════════════════════════
1264
+ {
1265
+ collection: "hr_leave_requests",
1266
+ field: "id",
1267
+ type: "integer",
1268
+ meta: { hidden: true, readonly: true, interface: "input" },
1269
+ schema: { is_primary_key: true, has_auto_increment: true },
1270
+ },
1271
+ {
1272
+ collection: "hr_leave_requests",
1273
+ field: "person_id",
1274
+ type: "integer",
1275
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
1276
+ schema: { is_nullable: false },
1277
+ },
1278
+ {
1279
+ collection: "hr_leave_requests",
1280
+ field: "leave_type_id",
1281
+ type: "integer",
1282
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half", required: true },
1283
+ schema: { is_nullable: false },
1284
+ },
1285
+ {
1286
+ collection: "hr_leave_requests",
1287
+ field: "status",
1288
+ type: "string",
1289
+ meta: {
1290
+ interface: "select",
1291
+ width: "half",
1292
+ options: {
1293
+ choices: [
1294
+ { text: "Pending", value: "pending" },
1295
+ { text: "Approved", value: "approved" },
1296
+ { text: "Rejected", value: "rejected" },
1297
+ { text: "Cancelled", value: "cancelled" },
1298
+ ],
1299
+ },
1300
+ },
1301
+ schema: { default_value: "pending" },
1302
+ },
1303
+ {
1304
+ collection: "hr_leave_requests",
1305
+ field: "start_date",
1306
+ type: "date",
1307
+ meta: { interface: "datetime", width: "half", required: true },
1308
+ schema: { is_nullable: false },
1309
+ },
1310
+ {
1311
+ collection: "hr_leave_requests",
1312
+ field: "end_date",
1313
+ type: "date",
1314
+ meta: { interface: "datetime", width: "half", required: true },
1315
+ schema: { is_nullable: false },
1316
+ },
1317
+ {
1318
+ collection: "hr_leave_requests",
1319
+ field: "days",
1320
+ type: "decimal",
1321
+ meta: { interface: "input", width: "half" },
1322
+ schema: {},
1323
+ },
1324
+ {
1325
+ collection: "hr_leave_requests",
1326
+ field: "reason",
1327
+ type: "text",
1328
+ meta: { interface: "input-multiline", width: "full" },
1329
+ schema: {},
1330
+ },
1331
+ {
1332
+ collection: "hr_leave_requests",
1333
+ field: "approved_by",
1334
+ type: "uuid",
1335
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
1336
+ schema: {},
1337
+ },
1338
+ {
1339
+ collection: "hr_leave_requests",
1340
+ field: "approved_at",
1341
+ type: "timestamp",
1342
+ meta: { interface: "datetime", width: "half", readonly: true },
1343
+ schema: {},
1344
+ },
1345
+ {
1346
+ collection: "hr_leave_requests",
1347
+ field: "date_created",
1348
+ type: "timestamp",
1349
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
1350
+ schema: {},
1351
+ },
1352
+ {
1353
+ collection: "hr_leave_requests",
1354
+ field: "date_updated",
1355
+ type: "timestamp",
1356
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
1357
+ schema: {},
1358
+ },
1359
+
1360
+ // ════════════════════════════════════════
1361
+ // hr_company_holidays
1362
+ // ════════════════════════════════════════
1363
+ {
1364
+ collection: "hr_company_holidays",
1365
+ field: "id",
1366
+ type: "integer",
1367
+ meta: { hidden: true, readonly: true, interface: "input" },
1368
+ schema: { is_primary_key: true, has_auto_increment: true },
1369
+ },
1370
+ {
1371
+ collection: "hr_company_holidays",
1372
+ field: "name",
1373
+ type: "string",
1374
+ meta: { interface: "input", width: "half", required: true },
1375
+ schema: { is_nullable: false },
1376
+ },
1377
+ {
1378
+ collection: "hr_company_holidays",
1379
+ field: "date",
1380
+ type: "date",
1381
+ meta: { interface: "datetime", width: "half", required: true },
1382
+ schema: { is_nullable: false },
1383
+ },
1384
+ {
1385
+ collection: "hr_company_holidays",
1386
+ field: "year",
1387
+ type: "integer",
1388
+ meta: { interface: "input", width: "half" },
1389
+ schema: {},
1390
+ },
1391
+ {
1392
+ collection: "hr_company_holidays",
1393
+ field: "recurring",
1394
+ type: "boolean",
1395
+ meta: { interface: "boolean", width: "half" },
1396
+ schema: { default_value: false },
1397
+ },
1398
+ {
1399
+ collection: "hr_company_holidays",
1400
+ field: "sort",
1401
+ type: "integer",
1402
+ meta: { interface: "input", hidden: true },
1403
+ schema: {},
1404
+ },
1405
+
1406
+ // ════════════════════════════════════════
1407
+ // hr_documents
1408
+ // ════════════════════════════════════════
1409
+ {
1410
+ collection: "hr_documents",
1411
+ field: "id",
1412
+ type: "integer",
1413
+ meta: { hidden: true, readonly: true, interface: "input" },
1414
+ schema: { is_primary_key: true, has_auto_increment: true },
1415
+ },
1416
+ {
1417
+ collection: "hr_documents",
1418
+ field: "person_id",
1419
+ type: "integer",
1420
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
1421
+ schema: { is_nullable: false },
1422
+ },
1423
+ {
1424
+ collection: "hr_documents",
1425
+ field: "name",
1426
+ type: "string",
1427
+ meta: { interface: "input", width: "half", required: true },
1428
+ schema: { is_nullable: false },
1429
+ },
1430
+ {
1431
+ collection: "hr_documents",
1432
+ field: "type",
1433
+ type: "string",
1434
+ meta: {
1435
+ interface: "select",
1436
+ width: "half",
1437
+ options: {
1438
+ choices: [
1439
+ { text: "Contract", value: "contract" },
1440
+ { text: "Offer Letter", value: "offer_letter" },
1441
+ { text: "ID Document", value: "id_document" },
1442
+ { text: "Generated", value: "generated" },
1443
+ { text: "Other", value: "other" },
1444
+ ],
1445
+ },
1446
+ },
1447
+ schema: { default_value: "other" },
1448
+ },
1449
+ {
1450
+ collection: "hr_documents",
1451
+ field: "file_id",
1452
+ type: "uuid",
1453
+ meta: { interface: "file", width: "full" },
1454
+ schema: {},
1455
+ },
1456
+ {
1457
+ collection: "hr_documents",
1458
+ field: "template_id",
1459
+ type: "integer",
1460
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
1461
+ schema: {},
1462
+ },
1463
+ {
1464
+ collection: "hr_documents",
1465
+ field: "trigger_event",
1466
+ type: "string",
1467
+ meta: { interface: "input", width: "half", hidden: true },
1468
+ schema: {},
1469
+ },
1470
+ {
1471
+ collection: "hr_documents",
1472
+ field: "date_created",
1473
+ type: "timestamp",
1474
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
1475
+ schema: {},
1476
+ },
1477
+ {
1478
+ collection: "hr_documents",
1479
+ field: "user_created",
1480
+ type: "uuid",
1481
+ meta: { interface: "select-dropdown-m2o", special: ["user-created"], readonly: true, hidden: true, width: "half" },
1482
+ schema: {},
1483
+ },
1484
+
1485
+ // ════════════════════════════════════════
1486
+ // hr_document_templates
1487
+ // ════════════════════════════════════════
1488
+ {
1489
+ collection: "hr_document_templates",
1490
+ field: "id",
1491
+ type: "integer",
1492
+ meta: { hidden: true, readonly: true, interface: "input" },
1493
+ schema: { is_primary_key: true, has_auto_increment: true },
1494
+ },
1495
+ {
1496
+ collection: "hr_document_templates",
1497
+ field: "name",
1498
+ type: "string",
1499
+ meta: { interface: "input", width: "half", required: true },
1500
+ schema: { is_nullable: false },
1501
+ },
1502
+ {
1503
+ collection: "hr_document_templates",
1504
+ field: "description",
1505
+ type: "string",
1506
+ meta: { interface: "input", width: "full" },
1507
+ schema: {},
1508
+ },
1509
+ {
1510
+ collection: "hr_document_templates",
1511
+ field: "body",
1512
+ type: "text",
1513
+ meta: { interface: "input-rich-text-md", width: "full" },
1514
+ schema: {},
1515
+ },
1516
+ {
1517
+ collection: "hr_document_templates",
1518
+ field: "status",
1519
+ type: "string",
1520
+ meta: {
1521
+ interface: "select",
1522
+ width: "half",
1523
+ options: {
1524
+ choices: [
1525
+ { text: "Active", value: "active" },
1526
+ { text: "Archived", value: "archived" },
1527
+ ],
1528
+ },
1529
+ },
1530
+ schema: { default_value: "active" },
1531
+ },
1532
+ {
1533
+ collection: "hr_document_templates",
1534
+ field: "date_created",
1535
+ type: "timestamp",
1536
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
1537
+ schema: {},
1538
+ },
1539
+ {
1540
+ collection: "hr_document_templates",
1541
+ field: "date_updated",
1542
+ type: "timestamp",
1543
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
1544
+ schema: {},
1545
+ },
1546
+ {
1547
+ collection: "hr_document_templates",
1548
+ field: "user_created",
1549
+ type: "uuid",
1550
+ meta: { interface: "select-dropdown-m2o", special: ["user-created"], readonly: true, hidden: true, width: "half" },
1551
+ schema: {},
1552
+ },
1553
+
1554
+ // ════════════════════════════════════════
1555
+ // hr_document_triggers
1556
+ // ════════════════════════════════════════
1557
+ {
1558
+ collection: "hr_document_triggers",
1559
+ field: "id",
1560
+ type: "integer",
1561
+ meta: { hidden: true, readonly: true, interface: "input" },
1562
+ schema: { is_primary_key: true, has_auto_increment: true },
1563
+ },
1564
+ {
1565
+ collection: "hr_document_triggers",
1566
+ field: "event",
1567
+ type: "string",
1568
+ meta: { interface: "input", width: "half", required: true },
1569
+ schema: { is_nullable: false, is_unique: true },
1570
+ },
1571
+ {
1572
+ collection: "hr_document_triggers",
1573
+ field: "label",
1574
+ type: "string",
1575
+ meta: { interface: "input", width: "half" },
1576
+ schema: {},
1577
+ },
1578
+ {
1579
+ collection: "hr_document_triggers",
1580
+ field: "auto",
1581
+ type: "boolean",
1582
+ meta: { interface: "boolean", width: "half" },
1583
+ schema: { default_value: false },
1584
+ },
1585
+ // M2M alias for templates
1586
+ {
1587
+ collection: "hr_document_triggers",
1588
+ field: "templates",
1589
+ type: "alias",
1590
+ meta: { interface: "list-m2m", special: ["m2m"], width: "full" },
1591
+ schema: null,
1592
+ },
1593
+
1594
+ // ════════════════════════════════════════
1595
+ // hr_document_trigger_tpl_jn (M2M junction)
1596
+ // ════════════════════════════════════════
1597
+ {
1598
+ collection: "hr_document_trigger_tpl_jn",
1599
+ field: "id",
1600
+ type: "integer",
1601
+ meta: { hidden: true, readonly: true, interface: "input" },
1602
+ schema: { is_primary_key: true, has_auto_increment: true },
1603
+ },
1604
+ {
1605
+ collection: "hr_document_trigger_tpl_jn",
1606
+ field: "hr_document_triggers_id",
1607
+ type: "integer",
1608
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true },
1609
+ schema: { is_nullable: true },
1610
+ },
1611
+ {
1612
+ collection: "hr_document_trigger_tpl_jn",
1613
+ field: "hr_document_templates_id",
1614
+ type: "integer",
1615
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true },
1616
+ schema: { is_nullable: true },
1617
+ },
1618
+
1619
+ // ════════════════════════════════════════
1620
+ // hr_assets
1621
+ // ════════════════════════════════════════
1622
+ {
1623
+ collection: "hr_assets",
1624
+ field: "id",
1625
+ type: "integer",
1626
+ meta: { hidden: true, readonly: true, interface: "input" },
1627
+ schema: { is_primary_key: true, has_auto_increment: true },
1628
+ },
1629
+ {
1630
+ collection: "hr_assets",
1631
+ field: "person_id",
1632
+ type: "integer",
1633
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
1634
+ schema: { is_nullable: false },
1635
+ },
1636
+ {
1637
+ collection: "hr_assets",
1638
+ field: "type",
1639
+ type: "string",
1640
+ meta: {
1641
+ interface: "select",
1642
+ width: "half",
1643
+ options: {
1644
+ choices: [
1645
+ { text: "Laptop", value: "laptop" },
1646
+ { text: "Phone", value: "phone" },
1647
+ { text: "Access Card", value: "access_card" },
1648
+ { text: "Other", value: "other" },
1649
+ ],
1650
+ },
1651
+ },
1652
+ schema: {},
1653
+ },
1654
+ {
1655
+ collection: "hr_assets",
1656
+ field: "name",
1657
+ type: "string",
1658
+ meta: { interface: "input", width: "half", required: true },
1659
+ schema: { is_nullable: false },
1660
+ },
1661
+ {
1662
+ collection: "hr_assets",
1663
+ field: "serial_number",
1664
+ type: "string",
1665
+ meta: { interface: "input", width: "half" },
1666
+ schema: {},
1667
+ },
1668
+ {
1669
+ collection: "hr_assets",
1670
+ field: "value",
1671
+ type: "decimal",
1672
+ meta: { interface: "input", width: "half", note: "Asset monetary value (optional)" },
1673
+ schema: { is_nullable: true, numeric_precision: 12, numeric_scale: 2 },
1674
+ },
1675
+ {
1676
+ collection: "hr_assets",
1677
+ field: "images",
1678
+ type: "json",
1679
+ meta: { interface: "files", width: "full", special: ["files"], note: "Asset photos (multiple)" },
1680
+ schema: { is_nullable: true },
1681
+ },
1682
+ {
1683
+ collection: "hr_assets",
1684
+ field: "issued_at",
1685
+ type: "date",
1686
+ meta: { interface: "datetime", width: "half" },
1687
+ schema: {},
1688
+ },
1689
+ {
1690
+ collection: "hr_assets",
1691
+ field: "returned_at",
1692
+ type: "date",
1693
+ meta: { interface: "datetime", width: "half" },
1694
+ schema: {},
1695
+ },
1696
+ {
1697
+ collection: "hr_assets",
1698
+ field: "notes",
1699
+ type: "text",
1700
+ meta: { interface: "input-multiline", width: "full" },
1701
+ schema: {},
1702
+ },
1703
+ {
1704
+ collection: "hr_assets",
1705
+ field: "date_created",
1706
+ type: "timestamp",
1707
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
1708
+ schema: {},
1709
+ },
1710
+
1711
+ // ════════════════════════════════════════
1712
+ // hr_notes
1713
+ // ════════════════════════════════════════
1714
+ {
1715
+ collection: "hr_notes",
1716
+ field: "id",
1717
+ type: "integer",
1718
+ meta: { hidden: true, readonly: true, interface: "input" },
1719
+ schema: { is_primary_key: true, has_auto_increment: true },
1720
+ },
1721
+ {
1722
+ collection: "hr_notes",
1723
+ field: "person_id",
1724
+ type: "integer",
1725
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
1726
+ schema: { is_nullable: false },
1727
+ },
1728
+ {
1729
+ collection: "hr_notes",
1730
+ field: "body",
1731
+ type: "text",
1732
+ meta: { interface: "input-rich-text-md", required: true },
1733
+ schema: { is_nullable: false },
1734
+ },
1735
+ {
1736
+ collection: "hr_notes",
1737
+ field: "author_id",
1738
+ type: "uuid",
1739
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
1740
+ schema: {},
1741
+ },
1742
+ {
1743
+ collection: "hr_notes",
1744
+ field: "author_name",
1745
+ type: "string",
1746
+ meta: { interface: "input", width: "half" },
1747
+ schema: {},
1748
+ },
1749
+ {
1750
+ collection: "hr_notes",
1751
+ field: "date_created",
1752
+ type: "timestamp",
1753
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
1754
+ schema: {},
1755
+ },
1756
+
1757
+ // ════════════════════════════════════════
1758
+ // hr_policies
1759
+ // ════════════════════════════════════════
1760
+ {
1761
+ collection: "hr_policies",
1762
+ field: "id",
1763
+ type: "integer",
1764
+ meta: { hidden: true, readonly: true, interface: "input" },
1765
+ schema: { is_primary_key: true, has_auto_increment: true },
1766
+ },
1767
+ {
1768
+ collection: "hr_policies",
1769
+ field: "key",
1770
+ type: "string",
1771
+ meta: { interface: "input", width: "half", required: true },
1772
+ schema: { is_nullable: false, is_unique: true },
1773
+ },
1774
+ {
1775
+ collection: "hr_policies",
1776
+ field: "name",
1777
+ type: "string",
1778
+ meta: { interface: "input", width: "half" },
1779
+ schema: {},
1780
+ },
1781
+ {
1782
+ collection: "hr_policies",
1783
+ field: "type",
1784
+ type: "string",
1785
+ meta: {
1786
+ interface: "select",
1787
+ width: "half",
1788
+ options: {
1789
+ choices: [
1790
+ { text: "Leave Base", value: "leave_base" },
1791
+ { text: "Tenure Bonus", value: "tenure_bonus" },
1792
+ { text: "Eligibility", value: "eligibility" },
1793
+ { text: "Probation", value: "probation" },
1794
+ { text: "Other", value: "other" },
1795
+ ],
1796
+ },
1797
+ },
1798
+ schema: {},
1799
+ },
1800
+ {
1801
+ collection: "hr_policies",
1802
+ field: "enabled",
1803
+ type: "boolean",
1804
+ meta: { interface: "boolean", width: "half" },
1805
+ schema: { default_value: true },
1806
+ },
1807
+ {
1808
+ collection: "hr_policies",
1809
+ field: "params",
1810
+ type: "json",
1811
+ meta: { interface: "input-code", special: ["cast-json"], options: { language: "json" }, width: "full" },
1812
+ schema: {},
1813
+ },
1814
+ {
1815
+ collection: "hr_policies",
1816
+ field: "description",
1817
+ type: "text",
1818
+ meta: { interface: "input-multiline", width: "full" },
1819
+ schema: {},
1820
+ },
1821
+ {
1822
+ collection: "hr_policies",
1823
+ field: "date_updated",
1824
+ type: "timestamp",
1825
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
1826
+ schema: {},
1827
+ },
1828
+
1829
+ // ════════════════════════════════════════
1830
+ // hr_settings (singleton)
1831
+ // ════════════════════════════════════════
1832
+ {
1833
+ collection: "hr_settings",
1834
+ field: "id",
1835
+ type: "integer",
1836
+ meta: { hidden: true, readonly: true, interface: "input" },
1837
+ schema: { is_primary_key: true, has_auto_increment: true },
1838
+ },
1839
+ {
1840
+ collection: "hr_settings",
1841
+ field: "company_name",
1842
+ type: "string",
1843
+ meta: { interface: "input", width: "half" },
1844
+ schema: {},
1845
+ },
1846
+ {
1847
+ collection: "hr_settings",
1848
+ field: "currency",
1849
+ type: "string",
1850
+ meta: { interface: "input", width: "half" },
1851
+ schema: { default_value: "VND" },
1852
+ },
1853
+ {
1854
+ collection: "hr_settings",
1855
+ field: "fiscal_year_start",
1856
+ type: "integer",
1857
+ meta: { interface: "input", width: "half" },
1858
+ schema: { default_value: 1 },
1859
+ },
1860
+ {
1861
+ collection: "hr_settings",
1862
+ field: "probation_months_default",
1863
+ type: "integer",
1864
+ meta: { interface: "input", width: "half" },
1865
+ schema: { default_value: 2 },
1866
+ },
1867
+ {
1868
+ collection: "hr_settings",
1869
+ field: "leave_year_start",
1870
+ type: "integer",
1871
+ meta: { interface: "input", width: "half" },
1872
+ schema: { default_value: 1 },
1873
+ },
1874
+ {
1875
+ collection: "hr_settings",
1876
+ field: "label_talent",
1877
+ type: "string",
1878
+ meta: { interface: "input", width: "half" },
1879
+ schema: {},
1880
+ },
1881
+ {
1882
+ collection: "hr_settings",
1883
+ field: "label_interviewing",
1884
+ type: "string",
1885
+ meta: { interface: "input", width: "half" },
1886
+ schema: {},
1887
+ },
1888
+ {
1889
+ collection: "hr_settings",
1890
+ field: "label_offer",
1891
+ type: "string",
1892
+ meta: { interface: "input", width: "half" },
1893
+ schema: {},
1894
+ },
1895
+ {
1896
+ collection: "hr_settings",
1897
+ field: "label_probation",
1898
+ type: "string",
1899
+ meta: { interface: "input", width: "half" },
1900
+ schema: {},
1901
+ },
1902
+ {
1903
+ collection: "hr_settings",
1904
+ field: "label_active",
1905
+ type: "string",
1906
+ meta: { interface: "input", width: "half" },
1907
+ schema: {},
1908
+ },
1909
+ {
1910
+ collection: "hr_settings",
1911
+ field: "label_resigned",
1912
+ type: "string",
1913
+ meta: { interface: "input", width: "half" },
1914
+ schema: {},
1915
+ },
1916
+
1917
+ // ════════════════════════════════════════
1918
+ // hr_providers
1919
+ // ════════════════════════════════════════
1920
+ {
1921
+ collection: "hr_providers",
1922
+ field: "id",
1923
+ type: "integer",
1924
+ meta: { hidden: true, readonly: true, interface: "input" },
1925
+ schema: { is_primary_key: true, has_auto_increment: true },
1926
+ },
1927
+ {
1928
+ collection: "hr_providers",
1929
+ field: "name",
1930
+ type: "string",
1931
+ meta: { interface: "input", width: "half", required: true },
1932
+ schema: { is_nullable: false },
1933
+ },
1934
+ {
1935
+ collection: "hr_providers",
1936
+ field: "type",
1937
+ type: "string",
1938
+ meta: {
1939
+ interface: "select",
1940
+ width: "half",
1941
+ options: {
1942
+ choices: [
1943
+ { text: "Authentik", value: "authentik" },
1944
+ { text: "Webhook", value: "webhook" },
1945
+ { text: "Other", value: "other" },
1946
+ ],
1947
+ },
1948
+ },
1949
+ schema: {},
1950
+ },
1951
+ {
1952
+ collection: "hr_providers",
1953
+ field: "enabled",
1954
+ type: "boolean",
1955
+ meta: { interface: "boolean", width: "half" },
1956
+ schema: { default_value: false },
1957
+ },
1958
+ {
1959
+ collection: "hr_providers",
1960
+ field: "config",
1961
+ type: "json",
1962
+ meta: { interface: "input-code", special: ["cast-json"], options: { language: "json" }, width: "full", hidden: true },
1963
+ schema: {},
1964
+ },
1965
+ {
1966
+ collection: "hr_providers",
1967
+ field: "date_created",
1968
+ type: "timestamp",
1969
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
1970
+ schema: {},
1971
+ },
1972
+ {
1973
+ collection: "hr_providers",
1974
+ field: "date_updated",
1975
+ type: "timestamp",
1976
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
1977
+ schema: {},
1978
+ },
1979
+
1980
+ // ════════════════════════════════════════
1981
+ // hr_provisioning_logs
1982
+ // ════════════════════════════════════════
1983
+ {
1984
+ collection: "hr_provisioning_logs",
1985
+ field: "id",
1986
+ type: "integer",
1987
+ meta: { hidden: true, readonly: true, interface: "input" },
1988
+ schema: { is_primary_key: true, has_auto_increment: true },
1989
+ },
1990
+ {
1991
+ collection: "hr_provisioning_logs",
1992
+ field: "person_id",
1993
+ type: "integer",
1994
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true },
1995
+ schema: {},
1996
+ },
1997
+ {
1998
+ collection: "hr_provisioning_logs",
1999
+ field: "provider_id",
2000
+ type: "integer",
2001
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
2002
+ schema: {},
2003
+ },
2004
+ {
2005
+ collection: "hr_provisioning_logs",
2006
+ field: "action",
2007
+ type: "string",
2008
+ meta: {
2009
+ interface: "select",
2010
+ width: "half",
2011
+ options: {
2012
+ choices: [
2013
+ { text: "Provision", value: "provision" },
2014
+ { text: "Deprovision", value: "deprovision" },
2015
+ { text: "Update", value: "update" },
2016
+ ],
2017
+ },
2018
+ },
2019
+ schema: {},
2020
+ },
2021
+ {
2022
+ collection: "hr_provisioning_logs",
2023
+ field: "status",
2024
+ type: "string",
2025
+ meta: {
2026
+ interface: "select",
2027
+ width: "half",
2028
+ options: {
2029
+ choices: [
2030
+ { text: "Success", value: "success" },
2031
+ { text: "Failed", value: "failed" },
2032
+ { text: "Pending", value: "pending" },
2033
+ ],
2034
+ },
2035
+ },
2036
+ schema: {},
2037
+ },
2038
+ {
2039
+ collection: "hr_provisioning_logs",
2040
+ field: "message",
2041
+ type: "text",
2042
+ meta: { interface: "input-multiline", width: "full" },
2043
+ schema: {},
2044
+ },
2045
+ {
2046
+ collection: "hr_provisioning_logs",
2047
+ field: "payload",
2048
+ type: "json",
2049
+ meta: { interface: "input-code", special: ["cast-json"], options: { language: "json" }, hidden: true },
2050
+ schema: {},
2051
+ },
2052
+ {
2053
+ collection: "hr_provisioning_logs",
2054
+ field: "date_created",
2055
+ type: "timestamp",
2056
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
2057
+ schema: {},
2058
+ },
2059
+
2060
+ // ════════════════════════════════════════
2061
+ // hr_offboarding
2062
+ // ════════════════════════════════════════
2063
+ {
2064
+ collection: "hr_offboarding",
2065
+ field: "id",
2066
+ type: "integer",
2067
+ meta: { interface: "input", hidden: true, readonly: true },
2068
+ schema: { is_primary_key: true, has_auto_increment: true },
2069
+ },
2070
+ {
2071
+ collection: "hr_offboarding",
2072
+ field: "person_id",
2073
+ type: "integer",
2074
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
2075
+ schema: { is_nullable: false },
2076
+ },
2077
+ {
2078
+ collection: "hr_offboarding",
2079
+ field: "status",
2080
+ type: "string",
2081
+ meta: { interface: "select", width: "half", options: { choices: [
2082
+ { text: "Initiated", value: "initiated" },
2083
+ { text: "In Progress", value: "in_progress" },
2084
+ { text: "Completed", value: "completed" },
2085
+ { text: "Cancelled", value: "cancelled" },
2086
+ ] } },
2087
+ schema: { default_value: "initiated" },
2088
+ },
2089
+ {
2090
+ collection: "hr_offboarding",
2091
+ field: "exit_type",
2092
+ type: "string",
2093
+ meta: { interface: "select", width: "half", options: { choices: [
2094
+ { text: "Voluntary resignation", value: "voluntary" },
2095
+ { text: "Involuntary termination", value: "involuntary" },
2096
+ { text: "Mutual agreement", value: "mutual" },
2097
+ { text: "Contract end", value: "contract_end" },
2098
+ { text: "Retirement", value: "retirement" },
2099
+ ] } },
2100
+ schema: { default_value: "voluntary" },
2101
+ },
2102
+ {
2103
+ collection: "hr_offboarding",
2104
+ field: "reason",
2105
+ type: "text",
2106
+ meta: { interface: "input-multiline", width: "full" },
2107
+ schema: {},
2108
+ },
2109
+ {
2110
+ collection: "hr_offboarding",
2111
+ field: "notice_date",
2112
+ type: "date",
2113
+ meta: { interface: "datetime", width: "half" },
2114
+ schema: {},
2115
+ },
2116
+ {
2117
+ collection: "hr_offboarding",
2118
+ field: "last_working_day",
2119
+ type: "date",
2120
+ meta: { interface: "datetime", width: "half" },
2121
+ schema: {},
2122
+ },
2123
+ {
2124
+ collection: "hr_offboarding",
2125
+ field: "rehire_eligible",
2126
+ type: "boolean",
2127
+ meta: { interface: "boolean", width: "half" },
2128
+ schema: { default_value: true },
2129
+ },
2130
+ {
2131
+ collection: "hr_offboarding",
2132
+ field: "exit_interview_notes",
2133
+ type: "text",
2134
+ meta: { interface: "input-multiline", width: "full" },
2135
+ schema: {},
2136
+ },
2137
+ {
2138
+ collection: "hr_offboarding",
2139
+ field: "exit_interview_rating",
2140
+ type: "integer",
2141
+ meta: { interface: "input", width: "half" },
2142
+ schema: {},
2143
+ },
2144
+ {
2145
+ collection: "hr_offboarding",
2146
+ field: "leave_payout_days",
2147
+ type: "float",
2148
+ meta: { interface: "input", width: "half" },
2149
+ schema: {},
2150
+ },
2151
+ {
2152
+ collection: "hr_offboarding",
2153
+ field: "leave_payout_amount",
2154
+ type: "float",
2155
+ meta: { interface: "input", width: "half" },
2156
+ schema: {},
2157
+ },
2158
+ {
2159
+ collection: "hr_offboarding",
2160
+ field: "final_settlement_notes",
2161
+ type: "text",
2162
+ meta: { interface: "input-multiline", width: "full" },
2163
+ schema: {},
2164
+ },
2165
+ {
2166
+ collection: "hr_offboarding",
2167
+ field: "workflow_instance_id",
2168
+ type: "string",
2169
+ meta: { interface: "input", hidden: true },
2170
+ schema: {},
2171
+ },
2172
+ {
2173
+ collection: "hr_offboarding",
2174
+ field: "initiated_by",
2175
+ type: "uuid",
2176
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
2177
+ schema: {},
2178
+ },
2179
+ {
2180
+ collection: "hr_offboarding",
2181
+ field: "completed_by",
2182
+ type: "uuid",
2183
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
2184
+ schema: {},
2185
+ },
2186
+ {
2187
+ collection: "hr_offboarding",
2188
+ field: "completed_at",
2189
+ type: "timestamp",
2190
+ meta: { interface: "datetime", readonly: true, width: "half" },
2191
+ schema: {},
2192
+ },
2193
+ {
2194
+ collection: "hr_offboarding",
2195
+ field: "tasks",
2196
+ type: "alias",
2197
+ meta: { interface: "list-o2m", special: ["o2m"], hidden: true },
2198
+ schema: null,
2199
+ },
2200
+ {
2201
+ collection: "hr_offboarding",
2202
+ field: "date_created",
2203
+ type: "timestamp",
2204
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-created"] },
2205
+ schema: {},
2206
+ },
2207
+ {
2208
+ collection: "hr_offboarding",
2209
+ field: "date_updated",
2210
+ type: "timestamp",
2211
+ meta: { interface: "datetime", readonly: true, hidden: true, special: ["date-updated"] },
2212
+ schema: {},
2213
+ },
2214
+
2215
+ // ════════════════════════════════════════
2216
+ // hr_offboarding_tasks
2217
+ // ════════════════════════════════════════
2218
+ {
2219
+ collection: "hr_offboarding_tasks",
2220
+ field: "id",
2221
+ type: "integer",
2222
+ meta: { interface: "input", hidden: true, readonly: true },
2223
+ schema: { is_primary_key: true, has_auto_increment: true },
2224
+ },
2225
+ {
2226
+ collection: "hr_offboarding_tasks",
2227
+ field: "offboarding_id",
2228
+ type: "integer",
2229
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], hidden: true, required: true },
2230
+ schema: { is_nullable: false },
2231
+ },
2232
+ {
2233
+ collection: "hr_offboarding_tasks",
2234
+ field: "key",
2235
+ type: "string",
2236
+ meta: { interface: "input", width: "half" },
2237
+ schema: {},
2238
+ },
2239
+ {
2240
+ collection: "hr_offboarding_tasks",
2241
+ field: "label",
2242
+ type: "string",
2243
+ meta: { interface: "input", width: "half" },
2244
+ schema: {},
2245
+ },
2246
+ {
2247
+ collection: "hr_offboarding_tasks",
2248
+ field: "category",
2249
+ type: "string",
2250
+ meta: { interface: "input", width: "half" },
2251
+ schema: {},
2252
+ },
2253
+ {
2254
+ collection: "hr_offboarding_tasks",
2255
+ field: "status",
2256
+ type: "string",
2257
+ meta: { interface: "select", width: "half", options: { choices: [
2258
+ { text: "Pending", value: "pending" },
2259
+ { text: "Done", value: "done" },
2260
+ { text: "N/A", value: "na" },
2261
+ ] } },
2262
+ schema: { default_value: "pending" },
2263
+ },
2264
+ {
2265
+ collection: "hr_offboarding_tasks",
2266
+ field: "assignee",
2267
+ type: "uuid",
2268
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
2269
+ schema: {},
2270
+ },
2271
+ {
2272
+ collection: "hr_offboarding_tasks",
2273
+ field: "completed_by",
2274
+ type: "uuid",
2275
+ meta: { interface: "select-dropdown-m2o", special: ["m2o"], width: "half" },
2276
+ schema: {},
2277
+ },
2278
+ {
2279
+ collection: "hr_offboarding_tasks",
2280
+ field: "completed_at",
2281
+ type: "timestamp",
2282
+ meta: { interface: "datetime", readonly: true, width: "half" },
2283
+ schema: {},
2284
+ },
2285
+ {
2286
+ collection: "hr_offboarding_tasks",
2287
+ field: "notes",
2288
+ type: "text",
2289
+ meta: { interface: "input-multiline", width: "full" },
2290
+ schema: {},
2291
+ },
2292
+ {
2293
+ collection: "hr_offboarding_tasks",
2294
+ field: "sort",
2295
+ type: "integer",
2296
+ meta: { interface: "input", hidden: true },
2297
+ schema: {},
2298
+ },
2299
+ ],
2300
+
2301
+ relations: [
2302
+ // ── hr_people → hr_departments (M2O) ──
2303
+ {
2304
+ collection: "hr_people",
2305
+ field: "department_id",
2306
+ related_collection: "hr_departments",
2307
+ meta: { one_deselect_action: "nullify" },
2308
+ },
2309
+ // ── hr_people → hr_employment_types (M2O) ──
2310
+ {
2311
+ collection: "hr_people",
2312
+ field: "employment_type_id",
2313
+ related_collection: "hr_employment_types",
2314
+ meta: { one_deselect_action: "nullify" },
2315
+ },
2316
+ // ── hr_departments.head_person_id → hr_people (self-loop M2O) ──
2317
+ {
2318
+ collection: "hr_departments",
2319
+ field: "head_person_id",
2320
+ related_collection: "hr_people",
2321
+ meta: { one_deselect_action: "nullify" },
2322
+ },
2323
+ // ── hr_departments.parent_department_id → hr_departments (self-reference) ──
2324
+ {
2325
+ collection: "hr_departments",
2326
+ field: "parent_department_id",
2327
+ related_collection: "hr_departments",
2328
+ meta: { one_deselect_action: "nullify" },
2329
+ },
2330
+ // ── hr_stage_transitions → hr_people (O2M, cascade) ──
2331
+ {
2332
+ collection: "hr_stage_transitions",
2333
+ field: "person_id",
2334
+ related_collection: "hr_people",
2335
+ schema: { on_delete: "CASCADE" },
2336
+ meta: { one_field: "stage_transitions", one_deselect_action: "delete" },
2337
+ },
2338
+ // ── hr_stage_transitions.performed_by → odp_users ──
2339
+ {
2340
+ collection: "hr_stage_transitions",
2341
+ field: "performed_by",
2342
+ related_collection: "odp_users",
2343
+ meta: { one_deselect_action: "nullify" },
2344
+ },
2345
+ // ── hr_applications → hr_people (O2M, cascade) ──
2346
+ {
2347
+ collection: "hr_applications",
2348
+ field: "person_id",
2349
+ related_collection: "hr_people",
2350
+ schema: { on_delete: "CASCADE" },
2351
+ meta: { one_field: "applications", one_deselect_action: "delete" },
2352
+ },
2353
+ // ── hr_interviews → hr_applications (O2M, cascade) ──
2354
+ {
2355
+ collection: "hr_interviews",
2356
+ field: "application_id",
2357
+ related_collection: "hr_applications",
2358
+ schema: { on_delete: "CASCADE" },
2359
+ meta: { one_field: "interviews", one_deselect_action: "delete" },
2360
+ },
2361
+ // ── hr_interviews.interviewer → odp_users ──
2362
+ {
2363
+ collection: "hr_interviews",
2364
+ field: "interviewer",
2365
+ related_collection: "odp_users",
2366
+ meta: { one_deselect_action: "nullify" },
2367
+ },
2368
+ // ── hr_offers → hr_applications (1:1, cascade) ──
2369
+ {
2370
+ collection: "hr_offers",
2371
+ field: "application_id",
2372
+ related_collection: "hr_applications",
2373
+ schema: { on_delete: "CASCADE" },
2374
+ meta: { one_field: "offer", one_deselect_action: "delete" },
2375
+ },
2376
+ // ── hr_contracts → hr_people (O2M, cascade) ──
2377
+ {
2378
+ collection: "hr_contracts",
2379
+ field: "person_id",
2380
+ related_collection: "hr_people",
2381
+ schema: { on_delete: "CASCADE" },
2382
+ meta: { one_field: "contracts", one_deselect_action: "delete" },
2383
+ },
2384
+ // ── hr_compensations → hr_people (O2M, cascade) ──
2385
+ {
2386
+ collection: "hr_compensations",
2387
+ field: "person_id",
2388
+ related_collection: "hr_people",
2389
+ schema: { on_delete: "CASCADE" },
2390
+ meta: { one_field: "compensations", one_deselect_action: "delete" },
2391
+ },
2392
+ // ── hr_compensation_allowances → hr_compensations (O2M, cascade) ──
2393
+ {
2394
+ collection: "hr_compensation_allowances",
2395
+ field: "compensation_id",
2396
+ related_collection: "hr_compensations",
2397
+ schema: { on_delete: "CASCADE" },
2398
+ meta: { one_field: "allowances", one_deselect_action: "delete" },
2399
+ },
2400
+ // ── hr_insurances → hr_people (O2M, cascade) ──
2401
+ {
2402
+ collection: "hr_insurances",
2403
+ field: "person_id",
2404
+ related_collection: "hr_people",
2405
+ schema: { on_delete: "CASCADE" },
2406
+ meta: { one_field: "insurances", one_deselect_action: "delete" },
2407
+ },
2408
+ // ── hr_leave_balances → hr_people (O2M, cascade) ──
2409
+ {
2410
+ collection: "hr_leave_balances",
2411
+ field: "person_id",
2412
+ related_collection: "hr_people",
2413
+ schema: { on_delete: "CASCADE" },
2414
+ meta: { one_field: "leave_balances", one_deselect_action: "delete" },
2415
+ },
2416
+ // ── hr_leave_balances → hr_leave_types (M2O) ──
2417
+ {
2418
+ collection: "hr_leave_balances",
2419
+ field: "leave_type_id",
2420
+ related_collection: "hr_leave_types",
2421
+ meta: { one_deselect_action: "nullify" },
2422
+ },
2423
+ // ── hr_leave_requests → hr_people (O2M, cascade) ──
2424
+ {
2425
+ collection: "hr_leave_requests",
2426
+ field: "person_id",
2427
+ related_collection: "hr_people",
2428
+ schema: { on_delete: "CASCADE" },
2429
+ meta: { one_field: "leave_requests", one_deselect_action: "delete" },
2430
+ },
2431
+ // ── hr_leave_requests → hr_leave_types (M2O) ──
2432
+ {
2433
+ collection: "hr_leave_requests",
2434
+ field: "leave_type_id",
2435
+ related_collection: "hr_leave_types",
2436
+ meta: { one_deselect_action: "nullify" },
2437
+ },
2438
+ // ── hr_leave_requests.approved_by → odp_users ──
2439
+ {
2440
+ collection: "hr_leave_requests",
2441
+ field: "approved_by",
2442
+ related_collection: "odp_users",
2443
+ meta: { one_deselect_action: "nullify" },
2444
+ },
2445
+ // ── hr_people.user_id → odp_users ──
2446
+ {
2447
+ collection: "hr_people",
2448
+ field: "user_id",
2449
+ related_collection: "odp_users",
2450
+ meta: { one_deselect_action: "nullify" },
2451
+ },
2452
+ // ── hr_documents → hr_people (O2M, cascade) ──
2453
+ {
2454
+ collection: "hr_documents",
2455
+ field: "person_id",
2456
+ related_collection: "hr_people",
2457
+ schema: { on_delete: "CASCADE" },
2458
+ meta: { one_field: "documents", one_deselect_action: "delete" },
2459
+ },
2460
+ // ── hr_documents.template_id → hr_document_templates (M2O) ──
2461
+ {
2462
+ collection: "hr_documents",
2463
+ field: "template_id",
2464
+ related_collection: "hr_document_templates",
2465
+ meta: { one_deselect_action: "nullify" },
2466
+ },
2467
+ // ── hr_assets → hr_people (O2M, cascade) ──
2468
+ {
2469
+ collection: "hr_assets",
2470
+ field: "person_id",
2471
+ related_collection: "hr_people",
2472
+ schema: { on_delete: "CASCADE" },
2473
+ meta: { one_field: "assets", one_deselect_action: "delete" },
2474
+ },
2475
+ // ── hr_notes → hr_people (O2M, cascade) ──
2476
+ {
2477
+ collection: "hr_notes",
2478
+ field: "person_id",
2479
+ related_collection: "hr_people",
2480
+ schema: { on_delete: "CASCADE" },
2481
+ meta: { one_field: "notes", one_deselect_action: "delete" },
2482
+ },
2483
+ // ── hr_notes.author_id → odp_users ──
2484
+ {
2485
+ collection: "hr_notes",
2486
+ field: "author_id",
2487
+ related_collection: "odp_users",
2488
+ meta: { one_deselect_action: "nullify" },
2489
+ },
2490
+ // ── hr_provisioning_logs → hr_people (O2M, cascade) ──
2491
+ {
2492
+ collection: "hr_provisioning_logs",
2493
+ field: "person_id",
2494
+ related_collection: "hr_people",
2495
+ schema: { on_delete: "CASCADE" },
2496
+ meta: { one_field: "provisioning_logs", one_deselect_action: "delete" },
2497
+ },
2498
+ // ── hr_provisioning_logs → hr_providers (M2O) ──
2499
+ {
2500
+ collection: "hr_provisioning_logs",
2501
+ field: "provider_id",
2502
+ related_collection: "hr_providers",
2503
+ meta: { one_deselect_action: "nullify" },
2504
+ },
2505
+ // ── M2M: hr_document_triggers ↔ hr_document_templates via hr_document_trigger_tpl_jn ──
2506
+ {
2507
+ collection: "hr_document_trigger_tpl_jn",
2508
+ field: "hr_document_triggers_id",
2509
+ related_collection: "hr_document_triggers",
2510
+ schema: { on_delete: "CASCADE" },
2511
+ meta: { one_field: "templates", junction_field: "hr_document_templates_id", one_deselect_action: "nullify" },
2512
+ },
2513
+ {
2514
+ collection: "hr_document_trigger_tpl_jn",
2515
+ field: "hr_document_templates_id",
2516
+ related_collection: "hr_document_templates",
2517
+ meta: { one_field: null, junction_field: "hr_document_triggers_id", one_deselect_action: "nullify" },
2518
+ },
2519
+ // ── hr_offboarding → hr_people (O2M, cascade) ──
2520
+ {
2521
+ collection: "hr_offboarding",
2522
+ field: "person_id",
2523
+ related_collection: "hr_people",
2524
+ schema: { on_delete: "CASCADE" },
2525
+ meta: { one_field: "offboarding", one_deselect_action: "delete" },
2526
+ },
2527
+ // ── hr_offboarding.initiated_by / completed_by → odp_users ──
2528
+ {
2529
+ collection: "hr_offboarding",
2530
+ field: "initiated_by",
2531
+ related_collection: "odp_users",
2532
+ meta: { one_deselect_action: "nullify" },
2533
+ },
2534
+ {
2535
+ collection: "hr_offboarding",
2536
+ field: "completed_by",
2537
+ related_collection: "odp_users",
2538
+ meta: { one_deselect_action: "nullify" },
2539
+ },
2540
+ // ── hr_offboarding_tasks → hr_offboarding (O2M, cascade) ──
2541
+ {
2542
+ collection: "hr_offboarding_tasks",
2543
+ field: "offboarding_id",
2544
+ related_collection: "hr_offboarding",
2545
+ schema: { on_delete: "CASCADE" },
2546
+ meta: { one_field: "tasks", one_deselect_action: "delete" },
2547
+ },
2548
+ // ── hr_offboarding_tasks.assignee / completed_by → odp_users ──
2549
+ {
2550
+ collection: "hr_offboarding_tasks",
2551
+ field: "assignee",
2552
+ related_collection: "odp_users",
2553
+ meta: { one_deselect_action: "nullify" },
2554
+ },
2555
+ {
2556
+ collection: "hr_offboarding_tasks",
2557
+ field: "completed_by",
2558
+ related_collection: "odp_users",
2559
+ meta: { one_deselect_action: "nullify" },
2560
+ },
2561
+ ],
2562
+
2563
+ // Seed data runs after collections are created
2564
+ seed: [
2565
+ {
2566
+ collection: "hr_employment_types",
2567
+ data: [
2568
+ { key: "full_time", label: "Full-time" },
2569
+ { key: "part_time", label: "Part-time" },
2570
+ { key: "contractor", label: "Contractor" },
2571
+ { key: "intern", label: "Intern" },
2572
+ ],
2573
+ },
2574
+ {
2575
+ collection: "hr_leave_types",
2576
+ data: [
2577
+ { key: "annual", label: "Annual Leave", default_days: 12, paid: true },
2578
+ { key: "sick", label: "Sick Leave", default_days: 5, paid: true },
2579
+ { key: "unpaid", label: "Unpaid Leave", default_days: 0, paid: false },
2580
+ { key: "maternity", label: "Maternity Leave", default_days: 180, paid: true },
2581
+ { key: "paternity", label: "Paternity Leave", default_days: 5, paid: true },
2582
+ ],
2583
+ },
2584
+ {
2585
+ collection: "hr_settings",
2586
+ data: [
2587
+ {
2588
+ company_name: "My Company",
2589
+ currency: "VND",
2590
+ fiscal_year_start: 1,
2591
+ probation_months_default: 2,
2592
+ leave_year_start: 1,
2593
+ },
2594
+ ],
2595
+ },
2596
+ {
2597
+ collection: "hr_document_triggers",
2598
+ data: [
2599
+ { event: "talent_created", label: "Talent Created", auto: false },
2600
+ { event: "offer_sent", label: "Offer Sent", auto: false },
2601
+ { event: "offer_accepted", label: "Offer Accepted", auto: false },
2602
+ { event: "hired", label: "Employee Hired", auto: false },
2603
+ { event: "probation_confirmed", label: "Probation Confirmed", auto: false },
2604
+ { event: "resigned", label: "Employee Resigned", auto: false },
2605
+ ],
2606
+ },
2607
+ ],
2608
+ }