@open-mercato/core 0.7.1-develop.7178.1.ab93fbaf4e → 0.7.1-develop.7180.1.9717fbbb43

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 (808) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/staff_time_entry/index.js +14 -0
  3. package/dist/generated/entities/staff_time_entry/index.js.map +2 -2
  4. package/dist/generated/entities/staff_time_entry_tag/index.js +15 -0
  5. package/dist/generated/entities/staff_time_entry_tag/index.js.map +7 -0
  6. package/dist/generated/entities/staff_time_project/index.js +16 -0
  7. package/dist/generated/entities/staff_time_project/index.js.map +2 -2
  8. package/dist/generated/entities/staff_time_report/index.js +57 -0
  9. package/dist/generated/entities/staff_time_report/index.js.map +7 -0
  10. package/dist/generated/entities/staff_time_report_entry/index.js +27 -0
  11. package/dist/generated/entities/staff_time_report_entry/index.js.map +7 -0
  12. package/dist/generated/entities/staff_time_report_event/index.js +21 -0
  13. package/dist/generated/entities/staff_time_report_event/index.js.map +7 -0
  14. package/dist/generated/entities/staff_time_report_project/index.js +15 -0
  15. package/dist/generated/entities/staff_time_report_project/index.js.map +7 -0
  16. package/dist/generated/entities/staff_time_tag/index.js +21 -0
  17. package/dist/generated/entities/staff_time_tag/index.js.map +7 -0
  18. package/dist/generated/entities/staff_time_task/index.js +37 -0
  19. package/dist/generated/entities/staff_time_task/index.js.map +7 -0
  20. package/dist/generated/entities/staff_time_task_comment/index.js +21 -0
  21. package/dist/generated/entities/staff_time_task_comment/index.js.map +7 -0
  22. package/dist/generated/entities/staff_time_task_status/index.js +29 -0
  23. package/dist/generated/entities/staff_time_task_status/index.js.map +7 -0
  24. package/dist/generated/entities/staff_time_task_tag/index.js +15 -0
  25. package/dist/generated/entities/staff_time_task_tag/index.js.map +7 -0
  26. package/dist/generated/entities.ids.generated.js +11 -1
  27. package/dist/generated/entities.ids.generated.js.map +2 -2
  28. package/dist/generated/entity-fields-registry.js +149 -0
  29. package/dist/generated/entity-fields-registry.js.map +2 -2
  30. package/dist/helpers/integration/timesheetFixtures.js +7 -0
  31. package/dist/helpers/integration/timesheetFixtures.js.map +2 -2
  32. package/dist/modules/auth/cli.js +16 -0
  33. package/dist/modules/auth/cli.js.map +2 -2
  34. package/dist/modules/auth/lib/backendChrome.js +1 -0
  35. package/dist/modules/auth/lib/backendChrome.js.map +2 -2
  36. package/dist/modules/customer_accounts/lib/customerRoleAcls.js +44 -0
  37. package/dist/modules/customer_accounts/lib/customerRoleAcls.js.map +7 -0
  38. package/dist/modules/customer_accounts/setup.js +1 -28
  39. package/dist/modules/customer_accounts/setup.js.map +2 -2
  40. package/dist/modules/data_sync/api/options.js +2 -0
  41. package/dist/modules/data_sync/api/options.js.map +2 -2
  42. package/dist/modules/data_sync/backend/data-sync/page.js +39 -17
  43. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  44. package/dist/modules/data_sync/lib/start-controls.js +42 -0
  45. package/dist/modules/data_sync/lib/start-controls.js.map +7 -0
  46. package/dist/modules/staff/acl.js +9 -1
  47. package/dist/modules/staff/acl.js.map +2 -2
  48. package/dist/modules/staff/ai-agents.js +142 -0
  49. package/dist/modules/staff/ai-agents.js.map +7 -0
  50. package/dist/modules/staff/ai-tools/time-tracking-pack.js +348 -0
  51. package/dist/modules/staff/ai-tools/time-tracking-pack.js.map +7 -0
  52. package/dist/modules/staff/ai-tools/types.js +54 -0
  53. package/dist/modules/staff/ai-tools/types.js.map +7 -0
  54. package/dist/modules/staff/ai-tools.js +8 -0
  55. package/dist/modules/staff/ai-tools.js.map +7 -0
  56. package/dist/modules/staff/analytics.js +84 -1
  57. package/dist/modules/staff/analytics.js.map +2 -2
  58. package/dist/modules/staff/api/guards.js +37 -3
  59. package/dist/modules/staff/api/guards.js.map +2 -2
  60. package/dist/modules/staff/api/leave-requests/accept/route.js +1 -3
  61. package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
  62. package/dist/modules/staff/api/leave-requests/reject/route.js +1 -3
  63. package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
  64. package/dist/modules/staff/api/portal/time-reports/[id]/route.js +131 -0
  65. package/dist/modules/staff/api/portal/time-reports/[id]/route.js.map +7 -0
  66. package/dist/modules/staff/api/portal/time-reports/route.js +179 -0
  67. package/dist/modules/staff/api/portal/time-reports/route.js.map +7 -0
  68. package/dist/modules/staff/api/team-members/self/route.js +1 -3
  69. package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
  70. package/dist/modules/staff/api/team-members/tags/assign/route.js +1 -3
  71. package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
  72. package/dist/modules/staff/api/team-members/tags/unassign/route.js +1 -3
  73. package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
  74. package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js +174 -0
  75. package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js.map +7 -0
  76. package/dist/modules/staff/api/timesheets/access-requests/route.js +226 -0
  77. package/dist/modules/staff/api/timesheets/access-requests/route.js.map +7 -0
  78. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +15 -8
  79. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +2 -2
  80. package/dist/modules/staff/api/timesheets/my-projects/route.js +13 -1
  81. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +2 -2
  82. package/dist/modules/staff/api/timesheets/my-work/myWorkAggregate.js +42 -0
  83. package/dist/modules/staff/api/timesheets/my-work/myWorkAggregate.js.map +7 -0
  84. package/dist/modules/staff/api/timesheets/my-work/route.js +383 -0
  85. package/dist/modules/staff/api/timesheets/my-work/route.js.map +7 -0
  86. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +14 -2
  87. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +2 -2
  88. package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js +168 -0
  89. package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js.map +7 -0
  90. package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js +246 -0
  91. package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js.map +7 -0
  92. package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js +183 -0
  93. package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js.map +7 -0
  94. package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js +164 -0
  95. package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js.map +7 -0
  96. package/dist/modules/staff/api/timesheets/reports/preview/route.js +360 -0
  97. package/dist/modules/staff/api/timesheets/reports/preview/route.js.map +7 -0
  98. package/dist/modules/staff/api/timesheets/reports/route.js +316 -0
  99. package/dist/modules/staff/api/timesheets/reports/route.js.map +7 -0
  100. package/dist/modules/staff/api/timesheets/reports/shared.js +63 -0
  101. package/dist/modules/staff/api/timesheets/reports/shared.js.map +7 -0
  102. package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js +164 -0
  103. package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js.map +7 -0
  104. package/dist/modules/staff/api/timesheets/settings/rounding-impact/route.js +168 -0
  105. package/dist/modules/staff/api/timesheets/settings/rounding-impact/route.js.map +7 -0
  106. package/dist/modules/staff/api/timesheets/settings/route.js +199 -0
  107. package/dist/modules/staff/api/timesheets/settings/route.js.map +7 -0
  108. package/dist/modules/staff/api/timesheets/tags/access.js +76 -0
  109. package/dist/modules/staff/api/timesheets/tags/access.js.map +7 -0
  110. package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js +235 -0
  111. package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js.map +7 -0
  112. package/dist/modules/staff/api/timesheets/tags/route.js +160 -0
  113. package/dist/modules/staff/api/timesheets/tags/route.js.map +7 -0
  114. package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js +233 -0
  115. package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js.map +7 -0
  116. package/dist/modules/staff/api/timesheets/task-statuses/route.js +188 -0
  117. package/dist/modules/staff/api/timesheets/task-statuses/route.js.map +7 -0
  118. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +399 -0
  119. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +7 -0
  120. package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js +210 -0
  121. package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js.map +7 -0
  122. package/dist/modules/staff/api/timesheets/tasks/route.js +333 -0
  123. package/dist/modules/staff/api/timesheets/tasks/route.js.map +7 -0
  124. package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js +228 -0
  125. package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js.map +7 -0
  126. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +29 -10
  127. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +2 -2
  128. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +31 -18
  129. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +2 -2
  130. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +21 -7
  131. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
  132. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +27 -7
  133. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +2 -2
  134. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +215 -32
  135. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +2 -2
  136. package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js +378 -0
  137. package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js.map +7 -0
  138. package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js +340 -0
  139. package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js.map +7 -0
  140. package/dist/modules/staff/api/timesheets/time-entries/route.js +238 -26
  141. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
  142. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +23 -8
  143. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
  144. package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js +209 -0
  145. package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js.map +7 -0
  146. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +59 -2
  147. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +2 -2
  148. package/dist/modules/staff/api/timesheets/time-projects/route.js +264 -22
  149. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
  150. package/dist/modules/staff/backend/staff/time-tracking/board/page.js +110 -0
  151. package/dist/modules/staff/backend/staff/time-tracking/board/page.js.map +7 -0
  152. package/dist/modules/staff/backend/staff/time-tracking/board/page.meta.js +18 -0
  153. package/dist/modules/staff/backend/staff/time-tracking/board/page.meta.js.map +7 -0
  154. package/dist/modules/staff/backend/staff/time-tracking/entries/page.js +981 -0
  155. package/dist/modules/staff/backend/staff/time-tracking/entries/page.js.map +7 -0
  156. package/dist/modules/staff/backend/staff/time-tracking/entries/page.meta.js +18 -0
  157. package/dist/modules/staff/backend/staff/time-tracking/entries/page.meta.js.map +7 -0
  158. package/dist/modules/staff/backend/staff/time-tracking/page.js +583 -0
  159. package/dist/modules/staff/backend/staff/time-tracking/page.js.map +7 -0
  160. package/dist/modules/staff/backend/staff/time-tracking/page.meta.js +15 -0
  161. package/dist/modules/staff/backend/staff/time-tracking/page.meta.js.map +7 -0
  162. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.js +65 -0
  163. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.js.map +7 -0
  164. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.js +16 -0
  165. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.js.map +7 -0
  166. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +229 -0
  167. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +7 -0
  168. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.js +16 -0
  169. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.js.map +7 -0
  170. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +1014 -0
  171. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +7 -0
  172. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.js +16 -0
  173. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.js.map +7 -0
  174. package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.js +97 -0
  175. package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.js.map +7 -0
  176. package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.meta.js +16 -0
  177. package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.meta.js.map +7 -0
  178. package/dist/modules/staff/backend/staff/time-tracking/projects/page.js +1040 -0
  179. package/dist/modules/staff/backend/staff/time-tracking/projects/page.js.map +7 -0
  180. package/dist/modules/staff/backend/staff/time-tracking/projects/page.meta.js +19 -0
  181. package/dist/modules/staff/backend/staff/time-tracking/projects/page.meta.js.map +7 -0
  182. package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js +353 -0
  183. package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js.map +7 -0
  184. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js +457 -0
  185. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js.map +7 -0
  186. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.js +16 -0
  187. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.js.map +7 -0
  188. package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.js +697 -0
  189. package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.js.map +7 -0
  190. package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.meta.js +16 -0
  191. package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.meta.js.map +7 -0
  192. package/dist/modules/staff/backend/staff/time-tracking/reports/page.js +174 -0
  193. package/dist/modules/staff/backend/staff/time-tracking/reports/page.js.map +7 -0
  194. package/dist/modules/staff/backend/staff/time-tracking/reports/page.meta.js +18 -0
  195. package/dist/modules/staff/backend/staff/time-tracking/reports/page.meta.js.map +7 -0
  196. package/dist/modules/staff/backend/staff/time-tracking/settings/page.js +546 -0
  197. package/dist/modules/staff/backend/staff/time-tracking/settings/page.js.map +7 -0
  198. package/dist/modules/staff/backend/staff/time-tracking/settings/page.meta.js +18 -0
  199. package/dist/modules/staff/backend/staff/time-tracking/settings/page.meta.js.map +7 -0
  200. package/dist/modules/staff/backend/staff/time-tracking/timesheet/GridView.js +710 -0
  201. package/dist/modules/staff/backend/staff/time-tracking/timesheet/GridView.js.map +7 -0
  202. package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.js +646 -0
  203. package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.js.map +7 -0
  204. package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.meta.js +18 -0
  205. package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.meta.js.map +7 -0
  206. package/dist/modules/staff/backend/staff/timesheets/page.js +4 -793
  207. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  208. package/dist/modules/staff/backend/staff/timesheets/page.meta.js +2 -7
  209. package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +2 -2
  210. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +5 -136
  211. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +2 -2
  212. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +1 -7
  213. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +2 -2
  214. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +5 -445
  215. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +3 -3
  216. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +1 -7
  217. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +2 -2
  218. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +4 -76
  219. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +2 -2
  220. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +1 -7
  221. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +2 -2
  222. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +4 -613
  223. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  224. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +2 -17
  225. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +2 -2
  226. package/dist/modules/staff/ce.js +40 -0
  227. package/dist/modules/staff/ce.js.map +2 -2
  228. package/dist/modules/staff/cli.js +166 -1
  229. package/dist/modules/staff/cli.js.map +2 -2
  230. package/dist/modules/staff/commands/index.js +5 -0
  231. package/dist/modules/staff/commands/index.js.map +2 -2
  232. package/dist/modules/staff/commands/timesheets-entries.js +569 -21
  233. package/dist/modules/staff/commands/timesheets-entries.js.map +3 -3
  234. package/dist/modules/staff/commands/timesheets-projects.js +450 -7
  235. package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
  236. package/dist/modules/staff/commands/timesheets-reports.js +1036 -0
  237. package/dist/modules/staff/commands/timesheets-reports.js.map +7 -0
  238. package/dist/modules/staff/commands/timesheets-tags.js +1015 -0
  239. package/dist/modules/staff/commands/timesheets-tags.js.map +7 -0
  240. package/dist/modules/staff/commands/timesheets-task-comments.js +438 -0
  241. package/dist/modules/staff/commands/timesheets-task-comments.js.map +7 -0
  242. package/dist/modules/staff/commands/timesheets-task-statuses.js +723 -0
  243. package/dist/modules/staff/commands/timesheets-task-statuses.js.map +7 -0
  244. package/dist/modules/staff/commands/timesheets-tasks.js +834 -0
  245. package/dist/modules/staff/commands/timesheets-tasks.js.map +7 -0
  246. package/dist/modules/staff/data/enrichers.js +426 -12
  247. package/dist/modules/staff/data/enrichers.js.map +2 -2
  248. package/dist/modules/staff/data/entities.js +552 -3
  249. package/dist/modules/staff/data/entities.js.map +2 -2
  250. package/dist/modules/staff/data/extensions.js +41 -0
  251. package/dist/modules/staff/data/extensions.js.map +7 -0
  252. package/dist/modules/staff/data/validators.js +254 -9
  253. package/dist/modules/staff/data/validators.js.map +2 -2
  254. package/dist/modules/staff/di.js +42 -1
  255. package/dist/modules/staff/di.js.map +2 -2
  256. package/dist/modules/staff/events.js +84 -6
  257. package/dist/modules/staff/events.js.map +2 -2
  258. package/dist/modules/staff/events.payloads.js +158 -0
  259. package/dist/modules/staff/events.payloads.js.map +7 -0
  260. package/dist/modules/staff/extension-points.js +261 -0
  261. package/dist/modules/staff/extension-points.js.map +7 -0
  262. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js +138 -0
  263. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js.map +7 -0
  264. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.js +12 -0
  265. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.js.map +7 -0
  266. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js +133 -0
  267. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js.map +7 -0
  268. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.js +19 -0
  269. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.js.map +7 -0
  270. package/dist/modules/staff/lib/crud.js +11 -1
  271. package/dist/modules/staff/lib/crud.js.map +2 -2
  272. package/dist/modules/staff/lib/time-tracking/access.js +92 -0
  273. package/dist/modules/staff/lib/time-tracking/access.js.map +7 -0
  274. package/dist/modules/staff/lib/time-tracking/billability.js +39 -0
  275. package/dist/modules/staff/lib/time-tracking/billability.js.map +7 -0
  276. package/dist/modules/staff/lib/time-tracking/capacity.js +68 -0
  277. package/dist/modules/staff/lib/time-tracking/capacity.js.map +7 -0
  278. package/dist/modules/staff/lib/time-tracking/componentContracts.js +15 -0
  279. package/dist/modules/staff/lib/time-tracking/componentContracts.js.map +7 -0
  280. package/dist/modules/staff/lib/time-tracking/cost.js +82 -0
  281. package/dist/modules/staff/lib/time-tracking/cost.js.map +7 -0
  282. package/dist/modules/staff/lib/time-tracking/duration.js +55 -0
  283. package/dist/modules/staff/lib/time-tracking/duration.js.map +7 -0
  284. package/dist/modules/staff/lib/time-tracking/featureAccess.js +41 -0
  285. package/dist/modules/staff/lib/time-tracking/featureAccess.js.map +7 -0
  286. package/dist/modules/staff/lib/time-tracking/interval.js +72 -0
  287. package/dist/modules/staff/lib/time-tracking/interval.js.map +7 -0
  288. package/dist/modules/staff/lib/time-tracking/migrateProjectCodes.js +88 -0
  289. package/dist/modules/staff/lib/time-tracking/migrateProjectCodes.js.map +7 -0
  290. package/dist/modules/staff/lib/time-tracking/moneyVisibility.js +10 -0
  291. package/dist/modules/staff/lib/time-tracking/moneyVisibility.js.map +7 -0
  292. package/dist/modules/staff/lib/time-tracking/overlap.js +87 -0
  293. package/dist/modules/staff/lib/time-tracking/overlap.js.map +7 -0
  294. package/dist/modules/staff/lib/time-tracking/portalRecipients.js +27 -0
  295. package/dist/modules/staff/lib/time-tracking/portalRecipients.js.map +7 -0
  296. package/dist/modules/staff/lib/time-tracking/portalReports.js +16 -0
  297. package/dist/modules/staff/lib/time-tracking/portalReports.js.map +7 -0
  298. package/dist/modules/staff/lib/time-tracking/projectCode.js +135 -0
  299. package/dist/modules/staff/lib/time-tracking/projectCode.js.map +7 -0
  300. package/dist/modules/staff/lib/time-tracking/reapplyRounding.js +187 -0
  301. package/dist/modules/staff/lib/time-tracking/reapplyRounding.js.map +7 -0
  302. package/dist/modules/staff/lib/time-tracking/recalculationRunner.js +80 -0
  303. package/dist/modules/staff/lib/time-tracking/recalculationRunner.js.map +7 -0
  304. package/dist/modules/staff/lib/time-tracking/recalculations.js +56 -0
  305. package/dist/modules/staff/lib/time-tracking/recalculations.js.map +7 -0
  306. package/dist/modules/staff/lib/time-tracking/registries/invoke.js +63 -0
  307. package/dist/modules/staff/lib/time-tracking/registries/invoke.js.map +7 -0
  308. package/dist/modules/staff/lib/time-tracking/registries/registry.js +62 -0
  309. package/dist/modules/staff/lib/time-tracking/registries/registry.js.map +7 -0
  310. package/dist/modules/staff/lib/time-tracking/registries/scope.js +21 -0
  311. package/dist/modules/staff/lib/time-tracking/registries/scope.js.map +7 -0
  312. package/dist/modules/staff/lib/time-tracking/rollup.js +34 -0
  313. package/dist/modules/staff/lib/time-tracking/rollup.js.map +7 -0
  314. package/dist/modules/staff/lib/time-tracking/rounding.js +66 -0
  315. package/dist/modules/staff/lib/time-tracking/rounding.js.map +7 -0
  316. package/dist/modules/staff/lib/time-tracking/roundingImpact.js +39 -0
  317. package/dist/modules/staff/lib/time-tracking/roundingImpact.js.map +7 -0
  318. package/dist/modules/staff/lib/time-tracking/settingKeys.js +214 -0
  319. package/dist/modules/staff/lib/time-tracking/settingKeys.js.map +7 -0
  320. package/dist/modules/staff/lib/time-tracking/settings.js +87 -0
  321. package/dist/modules/staff/lib/time-tracking/settings.js.map +7 -0
  322. package/dist/modules/staff/lib/time-tracking/sqlInClause.js +9 -0
  323. package/dist/modules/staff/lib/time-tracking/sqlInClause.js.map +7 -0
  324. package/dist/modules/staff/lib/time-tracking/timeEntrySources.js +48 -0
  325. package/dist/modules/staff/lib/time-tracking/timeEntrySources.js.map +7 -0
  326. package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js +283 -0
  327. package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js.map +7 -0
  328. package/dist/modules/staff/lib/time-tracking-ui/CustomerPicker.js +324 -0
  329. package/dist/modules/staff/lib/time-tracking-ui/CustomerPicker.js.map +7 -0
  330. package/dist/modules/staff/lib/time-tracking-ui/DurationInput.js +121 -0
  331. package/dist/modules/staff/lib/time-tracking-ui/DurationInput.js.map +7 -0
  332. package/dist/modules/staff/lib/time-tracking-ui/EntryDetailsFields.js +188 -0
  333. package/dist/modules/staff/lib/time-tracking-ui/EntryDetailsFields.js.map +7 -0
  334. package/dist/modules/staff/lib/time-tracking-ui/EntryFilterBar.js +89 -0
  335. package/dist/modules/staff/lib/time-tracking-ui/EntryFilterBar.js.map +7 -0
  336. package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js +855 -0
  337. package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js.map +7 -0
  338. package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js +360 -0
  339. package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js.map +7 -0
  340. package/dist/modules/staff/lib/time-tracking-ui/KanbanColumn.js +259 -0
  341. package/dist/modules/staff/lib/time-tracking-ui/KanbanColumn.js.map +7 -0
  342. package/dist/modules/staff/lib/time-tracking-ui/NewTaskDialog.js +238 -0
  343. package/dist/modules/staff/lib/time-tracking-ui/NewTaskDialog.js.map +7 -0
  344. package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js +130 -0
  345. package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js.map +7 -0
  346. package/dist/modules/staff/lib/time-tracking-ui/PeriodSelector.js +98 -0
  347. package/dist/modules/staff/lib/time-tracking-ui/PeriodSelector.js.map +7 -0
  348. package/dist/modules/staff/lib/time-tracking-ui/PhasePlaceholder.js +27 -0
  349. package/dist/modules/staff/lib/time-tracking-ui/PhasePlaceholder.js.map +7 -0
  350. package/dist/modules/staff/lib/time-tracking-ui/ProjectCodeField.js +166 -0
  351. package/dist/modules/staff/lib/time-tracking-ui/ProjectCodeField.js.map +7 -0
  352. package/dist/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.js +295 -0
  353. package/dist/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.js.map +7 -0
  354. package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js +212 -0
  355. package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js.map +7 -0
  356. package/dist/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.js +729 -0
  357. package/dist/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.js.map +7 -0
  358. package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js +217 -0
  359. package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js.map +7 -0
  360. package/dist/modules/staff/lib/time-tracking-ui/TagPicker.js +158 -0
  361. package/dist/modules/staff/lib/time-tracking-ui/TagPicker.js.map +7 -0
  362. package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js +224 -0
  363. package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js.map +7 -0
  364. package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js +93 -0
  365. package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js.map +7 -0
  366. package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js +1196 -0
  367. package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js.map +7 -0
  368. package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js +176 -0
  369. package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js.map +7 -0
  370. package/dist/modules/staff/lib/time-tracking-ui/TaskPicker.js +307 -0
  371. package/dist/modules/staff/lib/time-tracking-ui/TaskPicker.js.map +7 -0
  372. package/dist/modules/staff/lib/time-tracking-ui/TaskQuickLog.js +284 -0
  373. package/dist/modules/staff/lib/time-tracking-ui/TaskQuickLog.js.map +7 -0
  374. package/dist/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.js +73 -0
  375. package/dist/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.js.map +7 -0
  376. package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDialog.js +1499 -0
  377. package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDialog.js.map +7 -0
  378. package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.js +95 -0
  379. package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.js.map +7 -0
  380. package/dist/modules/staff/lib/time-tracking-ui/TimesheetCalendar.js +188 -0
  381. package/dist/modules/staff/lib/time-tracking-ui/TimesheetCalendar.js.map +7 -0
  382. package/dist/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.js +61 -0
  383. package/dist/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.js.map +7 -0
  384. package/dist/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.js +45 -0
  385. package/dist/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.js.map +7 -0
  386. package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js +176 -0
  387. package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js.map +7 -0
  388. package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js +82 -0
  389. package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js.map +7 -0
  390. package/dist/modules/staff/lib/time-tracking-ui/boardSummary.js +5 -0
  391. package/dist/modules/staff/lib/time-tracking-ui/boardSummary.js.map +7 -0
  392. package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js +152 -0
  393. package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js.map +7 -0
  394. package/dist/modules/staff/lib/time-tracking-ui/projectTeamAssignment.js +92 -0
  395. package/dist/modules/staff/lib/time-tracking-ui/projectTeamAssignment.js.map +7 -0
  396. package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js +111 -0
  397. package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js.map +7 -0
  398. package/dist/modules/staff/lib/time-tracking-ui/timeEntryDialogState.js +243 -0
  399. package/dist/modules/staff/lib/time-tracking-ui/timeEntryDialogState.js.map +7 -0
  400. package/dist/modules/staff/lib/time-tracking-ui/timeEntryListData.js +151 -0
  401. package/dist/modules/staff/lib/time-tracking-ui/timeEntryListData.js.map +7 -0
  402. package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js +105 -0
  403. package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js.map +7 -0
  404. package/dist/modules/staff/lib/time-tracking-ui/timesheetData.js +132 -0
  405. package/dist/modules/staff/lib/time-tracking-ui/timesheetData.js.map +7 -0
  406. package/dist/modules/staff/lib/time-tracking-ui/timesheetPeriod.js +205 -0
  407. package/dist/modules/staff/lib/time-tracking-ui/timesheetPeriod.js.map +7 -0
  408. package/dist/modules/staff/lib/time-tracking-ui/timesheetTargets.js +53 -0
  409. package/dist/modules/staff/lib/time-tracking-ui/timesheetTargets.js.map +7 -0
  410. package/dist/modules/staff/lib/time-tracking-ui/useBoardFilters.js +77 -0
  411. package/dist/modules/staff/lib/time-tracking-ui/useBoardFilters.js.map +7 -0
  412. package/dist/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.js +151 -0
  413. package/dist/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.js.map +7 -0
  414. package/dist/modules/staff/lib/timeTrackingSeeds.js +809 -0
  415. package/dist/modules/staff/lib/timeTrackingSeeds.js.map +7 -0
  416. package/dist/modules/staff/lib/timesheets/timeEntryCacheInvalidation.js +2 -3
  417. package/dist/modules/staff/lib/timesheets/timeEntryCacheInvalidation.js.map +2 -2
  418. package/dist/modules/staff/lib/timesheets/timeEntryDecoration.js +152 -0
  419. package/dist/modules/staff/lib/timesheets/timeEntryDecoration.js.map +7 -0
  420. package/dist/modules/staff/lib/timesheets-projects/budgetBurn.js +36 -0
  421. package/dist/modules/staff/lib/timesheets-projects/budgetBurn.js.map +7 -0
  422. package/dist/modules/staff/lib/timesheets-projects/budgetThreshold.js +66 -0
  423. package/dist/modules/staff/lib/timesheets-projects/budgetThreshold.js.map +7 -0
  424. package/dist/modules/staff/lib/timesheets-projects/budgetThresholdState.js +78 -0
  425. package/dist/modules/staff/lib/timesheets-projects/budgetThresholdState.js.map +7 -0
  426. package/dist/modules/staff/lib/timesheets-projects/computeProjectFinancials.js +81 -0
  427. package/dist/modules/staff/lib/timesheets-projects/computeProjectFinancials.js.map +7 -0
  428. package/dist/modules/staff/lib/timesheets-projects/reportSelection.js +44 -0
  429. package/dist/modules/staff/lib/timesheets-projects/reportSelection.js.map +7 -0
  430. package/dist/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.js +169 -0
  431. package/dist/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.js.map +7 -0
  432. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.js +22 -0
  433. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.js.map +7 -0
  434. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +51 -1
  435. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +2 -2
  436. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.js +70 -0
  437. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.js.map +7 -0
  438. package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js +63 -0
  439. package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js.map +7 -0
  440. package/dist/modules/staff/lib/timesheets-reports/loadReportData.js +170 -0
  441. package/dist/modules/staff/lib/timesheets-reports/loadReportData.js.map +7 -0
  442. package/dist/modules/staff/lib/timesheets-reports/pdf.js +205 -0
  443. package/dist/modules/staff/lib/timesheets-reports/pdf.js.map +7 -0
  444. package/dist/modules/staff/lib/timesheets-reports/reportApprovalPolicies.js +68 -0
  445. package/dist/modules/staff/lib/timesheets-reports/reportApprovalPolicies.js.map +7 -0
  446. package/dist/modules/staff/lib/timesheets-reports/reportConfigData.js +135 -0
  447. package/dist/modules/staff/lib/timesheets-reports/reportConfigData.js.map +7 -0
  448. package/dist/modules/staff/lib/timesheets-reports/reportConfigState.js +48 -0
  449. package/dist/modules/staff/lib/timesheets-reports/reportConfigState.js.map +7 -0
  450. package/dist/modules/staff/lib/timesheets-reports/reportExport.js +262 -0
  451. package/dist/modules/staff/lib/timesheets-reports/reportExport.js.map +7 -0
  452. package/dist/modules/staff/lib/timesheets-reports/reportExportFormats.js +34 -0
  453. package/dist/modules/staff/lib/timesheets-reports/reportExportFormats.js.map +7 -0
  454. package/dist/modules/staff/lib/timesheets-reports/reportGroupings.js +79 -0
  455. package/dist/modules/staff/lib/timesheets-reports/reportGroupings.js.map +7 -0
  456. package/dist/modules/staff/lib/timesheets-reports/reportLabels.js +11 -0
  457. package/dist/modules/staff/lib/timesheets-reports/reportLabels.js.map +7 -0
  458. package/dist/modules/staff/lib/timesheets-reports/reportReference.js +83 -0
  459. package/dist/modules/staff/lib/timesheets-reports/reportReference.js.map +7 -0
  460. package/dist/modules/staff/lib/timesheets-reports/reportRows.js +42 -0
  461. package/dist/modules/staff/lib/timesheets-reports/reportRows.js.map +7 -0
  462. package/dist/modules/staff/lib/timesheets-reports/reportSheetData.js +107 -0
  463. package/dist/modules/staff/lib/timesheets-reports/reportSheetData.js.map +7 -0
  464. package/dist/modules/staff/lib/timesheets-reports/reportTotals.js +289 -0
  465. package/dist/modules/staff/lib/timesheets-reports/reportTotals.js.map +7 -0
  466. package/dist/modules/staff/lib/timesheets-reports/xlsx.js +145 -0
  467. package/dist/modules/staff/lib/timesheets-reports/xlsx.js.map +7 -0
  468. package/dist/modules/staff/lib/timesheets-tasks/computeTaskRollups.js +116 -0
  469. package/dist/modules/staff/lib/timesheets-tasks/computeTaskRollups.js.map +7 -0
  470. package/dist/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.js +50 -0
  471. package/dist/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.js.map +7 -0
  472. package/dist/modules/staff/lib/timesheets-tasks/seedProjectStatuses.js +27 -0
  473. package/dist/modules/staff/lib/timesheets-tasks/seedProjectStatuses.js.map +7 -0
  474. package/dist/modules/staff/lib/timesheets-tasks/statusPositions.js +65 -0
  475. package/dist/modules/staff/lib/timesheets-tasks/statusPositions.js.map +7 -0
  476. package/dist/modules/staff/lib/timesheets-tasks/statusSlug.js +31 -0
  477. package/dist/modules/staff/lib/timesheets-tasks/statusSlug.js.map +7 -0
  478. package/dist/modules/staff/lib/timesheets-tasks/taskHierarchy.js +31 -0
  479. package/dist/modules/staff/lib/timesheets-tasks/taskHierarchy.js.map +7 -0
  480. package/dist/modules/staff/lib/timesheets-tasks/taskHoursTotals.js +17 -0
  481. package/dist/modules/staff/lib/timesheets-tasks/taskHoursTotals.js.map +7 -0
  482. package/dist/modules/staff/lib/timesheets-tasks/taskReference.js +51 -0
  483. package/dist/modules/staff/lib/timesheets-tasks/taskReference.js.map +7 -0
  484. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +11 -4
  485. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +2 -2
  486. package/dist/modules/staff/lib/timesheets-ui/ListView.js +369 -111
  487. package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +2 -2
  488. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +47 -2
  489. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +2 -2
  490. package/dist/modules/staff/migrations/Migration20260813073131_staff.js +79 -0
  491. package/dist/modules/staff/migrations/Migration20260813073131_staff.js.map +7 -0
  492. package/dist/modules/staff/migrations/Migration20260824143357_staff.js +15 -0
  493. package/dist/modules/staff/migrations/Migration20260824143357_staff.js.map +7 -0
  494. package/dist/modules/staff/notifications.client.js +16 -0
  495. package/dist/modules/staff/notifications.client.js.map +7 -0
  496. package/dist/modules/staff/notifications.handlers.js +80 -0
  497. package/dist/modules/staff/notifications.handlers.js.map +7 -0
  498. package/dist/modules/staff/notifications.js +168 -0
  499. package/dist/modules/staff/notifications.js.map +2 -2
  500. package/dist/modules/staff/search.js +159 -1
  501. package/dist/modules/staff/search.js.map +2 -2
  502. package/dist/modules/staff/setup.js +20 -1
  503. package/dist/modules/staff/setup.js.map +2 -2
  504. package/dist/modules/staff/subscribers/time-project-access-requested-notification.js +68 -0
  505. package/dist/modules/staff/subscribers/time-project-access-requested-notification.js.map +7 -0
  506. package/dist/modules/staff/subscribers/time-project-budget-threshold-notification.js +149 -0
  507. package/dist/modules/staff/subscribers/time-project-budget-threshold-notification.js.map +7 -0
  508. package/dist/modules/staff/subscribers/time-report-approved-notification.js +78 -0
  509. package/dist/modules/staff/subscribers/time-report-approved-notification.js.map +7 -0
  510. package/dist/modules/staff/subscribers/time-report-portal-broadcast.js +78 -0
  511. package/dist/modules/staff/subscribers/time-report-portal-broadcast.js.map +7 -0
  512. package/dist/modules/staff/translations.js +4 -1
  513. package/dist/modules/staff/translations.js.map +2 -2
  514. package/dist/modules/staff/widgets/components.js +7 -0
  515. package/dist/modules/staff/widgets/components.js.map +7 -0
  516. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +5 -4
  517. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +2 -2
  518. package/dist/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.js +135 -0
  519. package/dist/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.js.map +7 -0
  520. package/dist/modules/staff/widgets/notifications/index.js +5 -0
  521. package/dist/modules/staff/widgets/notifications/index.js.map +7 -0
  522. package/dist/modules/staff/workers/timesheets-reapply-rounding.js +43 -0
  523. package/dist/modules/staff/workers/timesheets-reapply-rounding.js.map +7 -0
  524. package/generated/entities/staff_time_entry/index.ts +7 -0
  525. package/generated/entities/staff_time_entry_tag/index.ts +6 -0
  526. package/generated/entities/staff_time_project/index.ts +8 -0
  527. package/generated/entities/staff_time_report/index.ts +27 -0
  528. package/generated/entities/staff_time_report_entry/index.ts +12 -0
  529. package/generated/entities/staff_time_report_event/index.ts +9 -0
  530. package/generated/entities/staff_time_report_project/index.ts +6 -0
  531. package/generated/entities/staff_time_tag/index.ts +9 -0
  532. package/generated/entities/staff_time_task/index.ts +17 -0
  533. package/generated/entities/staff_time_task_comment/index.ts +9 -0
  534. package/generated/entities/staff_time_task_status/index.ts +13 -0
  535. package/generated/entities/staff_time_task_tag/index.ts +6 -0
  536. package/generated/entities.ids.generated.ts +11 -1
  537. package/generated/entity-fields-registry.ts +149 -0
  538. package/package.json +7 -7
  539. package/src/helpers/integration/timesheetFixtures.ts +31 -1
  540. package/src/modules/auth/README.md +1 -1
  541. package/src/modules/auth/cli.ts +35 -1
  542. package/src/modules/auth/i18n/de.json +7 -0
  543. package/src/modules/auth/i18n/en.json +7 -0
  544. package/src/modules/auth/i18n/es.json +7 -0
  545. package/src/modules/auth/i18n/ko.json +7 -0
  546. package/src/modules/auth/i18n/pl.json +7 -0
  547. package/src/modules/auth/lib/backendChrome.tsx +1 -0
  548. package/src/modules/customer_accounts/lib/customerRoleAcls.ts +79 -0
  549. package/src/modules/customer_accounts/setup.ts +1 -45
  550. package/src/modules/data_sync/AGENTS.md +34 -0
  551. package/src/modules/data_sync/api/options.ts +2 -0
  552. package/src/modules/data_sync/backend/data-sync/page.tsx +82 -33
  553. package/src/modules/data_sync/i18n/de.json +1 -0
  554. package/src/modules/data_sync/i18n/en.json +1 -0
  555. package/src/modules/data_sync/i18n/es.json +1 -0
  556. package/src/modules/data_sync/i18n/ko.json +1 -0
  557. package/src/modules/data_sync/i18n/pl.json +1 -0
  558. package/src/modules/data_sync/lib/adapter.ts +45 -0
  559. package/src/modules/data_sync/lib/start-controls.ts +89 -0
  560. package/src/modules/staff/AGENTS.md +769 -1
  561. package/src/modules/staff/acl.ts +9 -0
  562. package/src/modules/staff/ai-agents.ts +189 -0
  563. package/src/modules/staff/ai-tools/time-tracking-pack.ts +494 -0
  564. package/src/modules/staff/ai-tools/types.ts +82 -0
  565. package/src/modules/staff/ai-tools.ts +13 -0
  566. package/src/modules/staff/analytics.ts +113 -0
  567. package/src/modules/staff/api/guards.ts +85 -3
  568. package/src/modules/staff/api/leave-requests/accept/route.ts +0 -2
  569. package/src/modules/staff/api/leave-requests/reject/route.ts +0 -2
  570. package/src/modules/staff/api/portal/time-reports/[id]/route.ts +182 -0
  571. package/src/modules/staff/api/portal/time-reports/route.ts +270 -0
  572. package/src/modules/staff/api/team-members/self/route.ts +0 -2
  573. package/src/modules/staff/api/team-members/tags/assign/route.ts +0 -2
  574. package/src/modules/staff/api/team-members/tags/unassign/route.ts +0 -2
  575. package/src/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.ts +292 -0
  576. package/src/modules/staff/api/timesheets/access-requests/route.ts +299 -0
  577. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +15 -7
  578. package/src/modules/staff/api/timesheets/my-projects/route.ts +14 -1
  579. package/src/modules/staff/api/timesheets/my-work/myWorkAggregate.ts +90 -0
  580. package/src/modules/staff/api/timesheets/my-work/route.ts +475 -0
  581. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +15 -2
  582. package/src/modules/staff/api/timesheets/reports/[id]/close/route.ts +203 -0
  583. package/src/modules/staff/api/timesheets/reports/[id]/export/route.ts +315 -0
  584. package/src/modules/staff/api/timesheets/reports/[id]/sheet/route.ts +220 -0
  585. package/src/modules/staff/api/timesheets/reports/[id]/unlock/route.ts +208 -0
  586. package/src/modules/staff/api/timesheets/reports/preview/route.ts +449 -0
  587. package/src/modules/staff/api/timesheets/reports/route.ts +386 -0
  588. package/src/modules/staff/api/timesheets/reports/shared.ts +121 -0
  589. package/src/modules/staff/api/timesheets/settings/reapply-rounding/route.ts +205 -0
  590. package/src/modules/staff/api/timesheets/settings/rounding-impact/route.ts +226 -0
  591. package/src/modules/staff/api/timesheets/settings/route.ts +242 -0
  592. package/src/modules/staff/api/timesheets/tags/access.ts +134 -0
  593. package/src/modules/staff/api/timesheets/tags/entry-assignments/route.ts +290 -0
  594. package/src/modules/staff/api/timesheets/tags/route.ts +177 -0
  595. package/src/modules/staff/api/timesheets/tags/task-assignments/route.ts +294 -0
  596. package/src/modules/staff/api/timesheets/task-statuses/route.ts +232 -0
  597. package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +532 -0
  598. package/src/modules/staff/api/timesheets/tasks/[id]/status/route.ts +271 -0
  599. package/src/modules/staff/api/timesheets/tasks/route.ts +443 -0
  600. package/src/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.ts +306 -0
  601. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +32 -10
  602. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +32 -17
  603. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +27 -6
  604. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +36 -6
  605. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +331 -34
  606. package/src/modules/staff/api/timesheets/time-entries/copy-day/route.ts +533 -0
  607. package/src/modules/staff/api/timesheets/time-entries/overlaps/route.ts +457 -0
  608. package/src/modules/staff/api/timesheets/time-entries/route.ts +378 -24
  609. package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +31 -9
  610. package/src/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.ts +246 -0
  611. package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +62 -2
  612. package/src/modules/staff/api/timesheets/time-projects/route.ts +397 -22
  613. package/src/modules/staff/backend/staff/time-tracking/board/page.meta.ts +14 -0
  614. package/src/modules/staff/backend/staff/time-tracking/board/page.tsx +151 -0
  615. package/src/modules/staff/backend/staff/time-tracking/entries/page.meta.ts +14 -0
  616. package/src/modules/staff/backend/staff/time-tracking/entries/page.tsx +1229 -0
  617. package/src/modules/staff/backend/staff/time-tracking/page.meta.ts +11 -0
  618. package/src/modules/staff/backend/staff/time-tracking/page.tsx +823 -0
  619. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.ts +12 -0
  620. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.tsx +81 -0
  621. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.ts +12 -0
  622. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +275 -0
  623. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.ts +12 -0
  624. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +1420 -0
  625. package/src/modules/staff/backend/staff/time-tracking/projects/create/page.meta.ts +12 -0
  626. package/src/modules/staff/backend/staff/time-tracking/projects/create/page.tsx +109 -0
  627. package/src/modules/staff/backend/staff/time-tracking/projects/page.meta.ts +15 -0
  628. package/src/modules/staff/backend/staff/time-tracking/projects/page.tsx +1254 -0
  629. package/src/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.ts +466 -0
  630. package/src/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.ts +12 -0
  631. package/src/modules/staff/backend/staff/time-tracking/reports/[id]/page.tsx +632 -0
  632. package/src/modules/staff/backend/staff/time-tracking/reports/create/page.meta.ts +12 -0
  633. package/src/modules/staff/backend/staff/time-tracking/reports/create/page.tsx +867 -0
  634. package/src/modules/staff/backend/staff/time-tracking/reports/page.meta.ts +14 -0
  635. package/src/modules/staff/backend/staff/time-tracking/reports/page.tsx +246 -0
  636. package/src/modules/staff/backend/staff/time-tracking/settings/page.meta.ts +14 -0
  637. package/src/modules/staff/backend/staff/time-tracking/settings/page.tsx +701 -0
  638. package/src/modules/staff/backend/staff/time-tracking/timesheet/GridView.tsx +953 -0
  639. package/src/modules/staff/backend/staff/time-tracking/timesheet/page.meta.ts +14 -0
  640. package/src/modules/staff/backend/staff/time-tracking/timesheet/page.tsx +800 -0
  641. package/src/modules/staff/backend/staff/timesheets/page.meta.ts +6 -6
  642. package/src/modules/staff/backend/staff/timesheets/page.tsx +12 -1010
  643. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +0 -6
  644. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +4 -158
  645. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +0 -6
  646. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -609
  647. package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +0 -6
  648. package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +3 -89
  649. package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +2 -19
  650. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +3 -778
  651. package/src/modules/staff/ce.ts +63 -0
  652. package/src/modules/staff/cli.ts +207 -1
  653. package/src/modules/staff/commands/index.ts +5 -0
  654. package/src/modules/staff/commands/timesheets-entries.ts +1006 -28
  655. package/src/modules/staff/commands/timesheets-projects.ts +593 -7
  656. package/src/modules/staff/commands/timesheets-reports.ts +1329 -0
  657. package/src/modules/staff/commands/timesheets-tags.ts +1315 -0
  658. package/src/modules/staff/commands/timesheets-task-comments.ts +583 -0
  659. package/src/modules/staff/commands/timesheets-task-statuses.ts +889 -0
  660. package/src/modules/staff/commands/timesheets-tasks.ts +1121 -0
  661. package/src/modules/staff/data/enrichers.ts +675 -10
  662. package/src/modules/staff/data/entities.ts +494 -2
  663. package/src/modules/staff/data/extensions.ts +68 -0
  664. package/src/modules/staff/data/validators.ts +348 -3
  665. package/src/modules/staff/di.ts +96 -0
  666. package/src/modules/staff/events.payloads.ts +268 -0
  667. package/src/modules/staff/events.ts +87 -5
  668. package/src/modules/staff/extension-points.ts +308 -0
  669. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.ts +10 -0
  670. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.tsx +225 -0
  671. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.ts +17 -0
  672. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/page.tsx +182 -0
  673. package/src/modules/staff/i18n/de.json +899 -0
  674. package/src/modules/staff/i18n/en.json +899 -0
  675. package/src/modules/staff/i18n/es.json +899 -0
  676. package/src/modules/staff/i18n/ko.json +899 -0
  677. package/src/modules/staff/i18n/pl.json +899 -0
  678. package/src/modules/staff/lib/crud.ts +14 -3
  679. package/src/modules/staff/lib/time-tracking/access.ts +155 -0
  680. package/src/modules/staff/lib/time-tracking/billability.ts +68 -0
  681. package/src/modules/staff/lib/time-tracking/capacity.ts +124 -0
  682. package/src/modules/staff/lib/time-tracking/componentContracts.ts +26 -0
  683. package/src/modules/staff/lib/time-tracking/cost.ts +144 -0
  684. package/src/modules/staff/lib/time-tracking/duration.ts +68 -0
  685. package/src/modules/staff/lib/time-tracking/featureAccess.ts +115 -0
  686. package/src/modules/staff/lib/time-tracking/interval.ts +90 -0
  687. package/src/modules/staff/lib/time-tracking/migrateProjectCodes.ts +161 -0
  688. package/src/modules/staff/lib/time-tracking/moneyVisibility.ts +37 -0
  689. package/src/modules/staff/lib/time-tracking/overlap.ts +159 -0
  690. package/src/modules/staff/lib/time-tracking/portalRecipients.ts +76 -0
  691. package/src/modules/staff/lib/time-tracking/portalReports.ts +31 -0
  692. package/src/modules/staff/lib/time-tracking/projectCode.ts +221 -0
  693. package/src/modules/staff/lib/time-tracking/reapplyRounding.ts +313 -0
  694. package/src/modules/staff/lib/time-tracking/recalculationRunner.ts +118 -0
  695. package/src/modules/staff/lib/time-tracking/recalculations.ts +135 -0
  696. package/src/modules/staff/lib/time-tracking/registries/invoke.ts +122 -0
  697. package/src/modules/staff/lib/time-tracking/registries/registry.ts +124 -0
  698. package/src/modules/staff/lib/time-tracking/registries/scope.ts +56 -0
  699. package/src/modules/staff/lib/time-tracking/rollup.ts +59 -0
  700. package/src/modules/staff/lib/time-tracking/rounding.ts +126 -0
  701. package/src/modules/staff/lib/time-tracking/roundingImpact.ts +75 -0
  702. package/src/modules/staff/lib/time-tracking/settingKeys.ts +274 -0
  703. package/src/modules/staff/lib/time-tracking/settings.ts +168 -0
  704. package/src/modules/staff/lib/time-tracking/sqlInClause.ts +22 -0
  705. package/src/modules/staff/lib/time-tracking/timeEntrySources.ts +85 -0
  706. package/src/modules/staff/lib/time-tracking-ui/BoardFilterChips.tsx +360 -0
  707. package/src/modules/staff/lib/time-tracking-ui/CustomerPicker.tsx +427 -0
  708. package/src/modules/staff/lib/time-tracking-ui/DurationInput.tsx +192 -0
  709. package/src/modules/staff/lib/time-tracking-ui/EntryDetailsFields.tsx +224 -0
  710. package/src/modules/staff/lib/time-tracking-ui/EntryFilterBar.tsx +144 -0
  711. package/src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx +1065 -0
  712. package/src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx +435 -0
  713. package/src/modules/staff/lib/time-tracking-ui/KanbanColumn.tsx +316 -0
  714. package/src/modules/staff/lib/time-tracking-ui/NewTaskDialog.tsx +291 -0
  715. package/src/modules/staff/lib/time-tracking-ui/NoProjectAccess.tsx +162 -0
  716. package/src/modules/staff/lib/time-tracking-ui/PeriodSelector.tsx +149 -0
  717. package/src/modules/staff/lib/time-tracking-ui/PhasePlaceholder.tsx +31 -0
  718. package/src/modules/staff/lib/time-tracking-ui/ProjectCodeField.tsx +230 -0
  719. package/src/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.tsx +432 -0
  720. package/src/modules/staff/lib/time-tracking-ui/ProjectFormSections.tsx +323 -0
  721. package/src/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.tsx +930 -0
  722. package/src/modules/staff/lib/time-tracking-ui/ReportSheet.tsx +357 -0
  723. package/src/modules/staff/lib/time-tracking-ui/TagPicker.tsx +195 -0
  724. package/src/modules/staff/lib/time-tracking-ui/TaskBoardScreen.tsx +243 -0
  725. package/src/modules/staff/lib/time-tracking-ui/TaskCommentThread.tsx +137 -0
  726. package/src/modules/staff/lib/time-tracking-ui/TaskDrawer.tsx +1405 -0
  727. package/src/modules/staff/lib/time-tracking-ui/TaskListView.tsx +260 -0
  728. package/src/modules/staff/lib/time-tracking-ui/TaskPicker.tsx +435 -0
  729. package/src/modules/staff/lib/time-tracking-ui/TaskQuickLog.tsx +296 -0
  730. package/src/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.tsx +97 -0
  731. package/src/modules/staff/lib/time-tracking-ui/TimeEntryDialog.tsx +1929 -0
  732. package/src/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.tsx +126 -0
  733. package/src/modules/staff/lib/time-tracking-ui/TimesheetCalendar.tsx +265 -0
  734. package/src/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.tsx +78 -0
  735. package/src/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.tsx +70 -0
  736. package/src/modules/staff/lib/time-tracking-ui/boardDirectory.ts +231 -0
  737. package/src/modules/staff/lib/time-tracking-ui/boardFilters.ts +128 -0
  738. package/src/modules/staff/lib/time-tracking-ui/boardSummary.ts +20 -0
  739. package/src/modules/staff/lib/time-tracking-ui/kanbanBoardData.ts +228 -0
  740. package/src/modules/staff/lib/time-tracking-ui/projectTeamAssignment.ts +143 -0
  741. package/src/modules/staff/lib/time-tracking-ui/taskDrawerData.ts +194 -0
  742. package/src/modules/staff/lib/time-tracking-ui/timeEntryDialogState.ts +400 -0
  743. package/src/modules/staff/lib/time-tracking-ui/timeEntryListData.ts +271 -0
  744. package/src/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.ts +168 -0
  745. package/src/modules/staff/lib/time-tracking-ui/timesheetData.ts +225 -0
  746. package/src/modules/staff/lib/time-tracking-ui/timesheetPeriod.ts +278 -0
  747. package/src/modules/staff/lib/time-tracking-ui/timesheetTargets.ts +93 -0
  748. package/src/modules/staff/lib/time-tracking-ui/useBoardFilters.ts +107 -0
  749. package/src/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.ts +245 -0
  750. package/src/modules/staff/lib/timeTrackingSeeds.ts +1037 -0
  751. package/src/modules/staff/lib/timesheets/timeEntryCacheInvalidation.ts +11 -10
  752. package/src/modules/staff/lib/timesheets/timeEntryDecoration.ts +256 -0
  753. package/src/modules/staff/lib/timesheets-projects/budgetBurn.ts +60 -0
  754. package/src/modules/staff/lib/timesheets-projects/budgetThreshold.ts +135 -0
  755. package/src/modules/staff/lib/timesheets-projects/budgetThresholdState.ts +137 -0
  756. package/src/modules/staff/lib/timesheets-projects/computeProjectFinancials.ts +142 -0
  757. package/src/modules/staff/lib/timesheets-projects/reportSelection.ts +82 -0
  758. package/src/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.tsx +237 -0
  759. package/src/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.tsx +33 -0
  760. package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +56 -1
  761. package/src/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.tsx +90 -0
  762. package/src/modules/staff/lib/timesheets-reports/buildReportSheet.ts +125 -0
  763. package/src/modules/staff/lib/timesheets-reports/loadReportData.ts +251 -0
  764. package/src/modules/staff/lib/timesheets-reports/pdf.ts +263 -0
  765. package/src/modules/staff/lib/timesheets-reports/reportApprovalPolicies.ts +137 -0
  766. package/src/modules/staff/lib/timesheets-reports/reportConfigData.ts +247 -0
  767. package/src/modules/staff/lib/timesheets-reports/reportConfigState.ts +89 -0
  768. package/src/modules/staff/lib/timesheets-reports/reportExport.ts +373 -0
  769. package/src/modules/staff/lib/timesheets-reports/reportExportFormats.ts +71 -0
  770. package/src/modules/staff/lib/timesheets-reports/reportGroupings.ts +153 -0
  771. package/src/modules/staff/lib/timesheets-reports/reportLabels.ts +23 -0
  772. package/src/modules/staff/lib/timesheets-reports/reportReference.ts +146 -0
  773. package/src/modules/staff/lib/timesheets-reports/reportRows.ts +89 -0
  774. package/src/modules/staff/lib/timesheets-reports/reportSheetData.ts +196 -0
  775. package/src/modules/staff/lib/timesheets-reports/reportTotals.ts +544 -0
  776. package/src/modules/staff/lib/timesheets-reports/xlsx.ts +207 -0
  777. package/src/modules/staff/lib/timesheets-tasks/computeTaskRollups.ts +238 -0
  778. package/src/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.ts +90 -0
  779. package/src/modules/staff/lib/timesheets-tasks/seedProjectStatuses.ts +43 -0
  780. package/src/modules/staff/lib/timesheets-tasks/statusPositions.ts +132 -0
  781. package/src/modules/staff/lib/timesheets-tasks/statusSlug.ts +43 -0
  782. package/src/modules/staff/lib/timesheets-tasks/taskHierarchy.ts +99 -0
  783. package/src/modules/staff/lib/timesheets-tasks/taskHoursTotals.ts +42 -0
  784. package/src/modules/staff/lib/timesheets-tasks/taskReference.ts +108 -0
  785. package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +18 -4
  786. package/src/modules/staff/lib/timesheets-ui/ListView.tsx +504 -149
  787. package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +50 -2
  788. package/src/modules/staff/migrations/.snapshot-open-mercato.json +3244 -228
  789. package/src/modules/staff/migrations/Migration20260813073131_staff.ts +94 -0
  790. package/src/modules/staff/migrations/Migration20260824143357_staff.ts +17 -0
  791. package/src/modules/staff/notifications.client.ts +16 -0
  792. package/src/modules/staff/notifications.handlers.ts +88 -0
  793. package/src/modules/staff/notifications.ts +163 -0
  794. package/src/modules/staff/search.ts +191 -1
  795. package/src/modules/staff/setup.ts +22 -0
  796. package/src/modules/staff/subscribers/time-project-access-requested-notification.ts +95 -0
  797. package/src/modules/staff/subscribers/time-project-budget-threshold-notification.ts +226 -0
  798. package/src/modules/staff/subscribers/time-report-approved-notification.ts +116 -0
  799. package/src/modules/staff/subscribers/time-report-portal-broadcast.ts +120 -0
  800. package/src/modules/staff/translations.ts +17 -0
  801. package/src/modules/staff/widgets/components.ts +34 -0
  802. package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +6 -5
  803. package/src/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.tsx +138 -0
  804. package/src/modules/staff/widgets/notifications/index.ts +1 -0
  805. package/src/modules/staff/workers/timesheets-reapply-rounding.ts +59 -0
  806. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +0 -123
  807. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +0 -7
  808. package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +0 -138
@@ -1,11 +1,26 @@
1
+ import { z } from "zod";
1
2
  import { registerCommand } from "@open-mercato/shared/lib/commands";
2
3
  import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
3
4
  import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
4
5
  import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
5
6
  import { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from "@open-mercato/shared/lib/commands/helpers";
6
7
  import { makeCreateRedo } from "@open-mercato/shared/lib/commands/redo";
7
- import { StaffTimeEntry, StaffTimeEntrySegment, StaffTimeProject } from "../data/entities.js";
8
+ import {
9
+ StaffTimeEntry,
10
+ StaffTimeEntrySegment,
11
+ StaffTimeProject,
12
+ StaffTimeTask
13
+ } from "../data/entities.js";
8
14
  import { emitStaffEvent } from "../events.js";
15
+ import { deriveInterval, formatClock, parseClock } from "../lib/time-tracking/interval.js";
16
+ import { roundMinutes } from "../lib/time-tracking/rounding.js";
17
+ import { resolveBillability } from "../lib/time-tracking/billability.js";
18
+ import {
19
+ DEFAULT_TIME_TRACKING_SETTINGS,
20
+ readTimeTrackingSettings
21
+ } from "../lib/time-tracking/settings.js";
22
+ import { resolveProjectAccess } from "../lib/time-tracking/access.js";
23
+ import { staffTimeTagCommandIds, TAG_TARGET_LOCKED_CODE } from "./timesheets-tags.js";
9
24
  const timeEntryCrudIndexer = {
10
25
  entityType: "staff:staff_time_entry"
11
26
  };
@@ -57,14 +72,15 @@ async function resolveCallerStaffMemberId(em, ctx) {
57
72
  );
58
73
  return member?.id ?? null;
59
74
  }
60
- async function assertTimeProjectInScope(em, projectId, tenantId, organizationId) {
61
- if (!projectId) return;
62
- const exists = await em.findOne(
63
- StaffTimeProject,
64
- { id: projectId, tenantId, organizationId, deletedAt: null },
65
- { fields: ["id"] }
66
- );
67
- if (!exists) {
75
+ async function requireTimeProjectInScope(em, projectId, tenantId, organizationId) {
76
+ if (!projectId) return null;
77
+ const project = await em.findOne(StaffTimeProject, {
78
+ id: projectId,
79
+ tenantId,
80
+ organizationId,
81
+ deletedAt: null
82
+ });
83
+ if (!project) {
68
84
  const { translate } = await resolveTranslations();
69
85
  throw new CrudHttpError(422, {
70
86
  error: translate("staff.timesheets.errors.projectNotFound", "Time project not found or not accessible."),
@@ -73,6 +89,238 @@ async function assertTimeProjectInScope(em, projectId, tenantId, organizationId)
73
89
  }
74
90
  });
75
91
  }
92
+ return project;
93
+ }
94
+ async function requireTaskInScope(em, taskId, tenantId, organizationId) {
95
+ if (!taskId) return null;
96
+ const task = await em.findOne(StaffTimeTask, {
97
+ id: taskId,
98
+ tenantId,
99
+ organizationId,
100
+ deletedAt: null
101
+ });
102
+ if (!task) {
103
+ const { translate } = await resolveTranslations();
104
+ const message = translate("staff.timesheets.errors.taskNotFound", "Task not found or not accessible.");
105
+ throw new CrudHttpError(422, { error: message, fieldErrors: { taskId: message } });
106
+ }
107
+ return task;
108
+ }
109
+ async function assertTaskBelongsToProject(task, projectId) {
110
+ if (timeEntryTaskMatchesProject(task, projectId)) return;
111
+ const { translate } = await resolveTranslations();
112
+ const message = translate("staff.timesheets.errors.taskNotFound", "Task not found or not accessible.");
113
+ throw new CrudHttpError(422, { error: message, fieldErrors: { taskId: message } });
114
+ }
115
+ function timeEntryTaskMatchesProject(task, projectId) {
116
+ if (!task || !projectId) return true;
117
+ return task.timeProjectId === projectId;
118
+ }
119
+ function resolveTimeEntryProjectId(requestedProjectId, task) {
120
+ return requestedProjectId ?? task?.timeProjectId ?? null;
121
+ }
122
+ function resolveTimeEntryBillable(params) {
123
+ return resolveBillability({
124
+ ...params.scope ?? {},
125
+ requested: params.requested,
126
+ project: params.project ?? null,
127
+ settings: params.settings
128
+ });
129
+ }
130
+ async function readEntrySettingsFrom(container, tenantId) {
131
+ try {
132
+ const configService = container.resolve("moduleConfigService");
133
+ if (!configService?.getRecord) return DEFAULT_TIME_TRACKING_SETTINGS;
134
+ return await readTimeTrackingSettings(configService, { tenantId });
135
+ } catch {
136
+ return DEFAULT_TIME_TRACKING_SETTINGS;
137
+ }
138
+ }
139
+ async function readEntrySettings(ctx, tenantId) {
140
+ return readEntrySettingsFrom(ctx.container, tenantId);
141
+ }
142
+ async function resolveTimeEntrySettings(container, tenantId) {
143
+ return readEntrySettingsFrom(container, tenantId);
144
+ }
145
+ async function resolveRoundedMinutes(container, tenantId, durationMinutes, organizationId) {
146
+ return roundedMinutesFor(durationMinutes, await readEntrySettingsFrom(container, tenantId), {
147
+ tenantId,
148
+ organizationId: organizationId ?? void 0
149
+ });
150
+ }
151
+ async function resolveGrantedFeatures(ctx, tenantId, organizationId) {
152
+ const userId = ctx.auth?.sub;
153
+ if (!userId) return [];
154
+ try {
155
+ const rbac = ctx.container.resolve("rbacService");
156
+ if (!rbac?.getGrantedFeatures) return [];
157
+ return await rbac.getGrantedFeatures(userId, { tenantId, organizationId }) ?? [];
158
+ } catch {
159
+ return [];
160
+ }
161
+ }
162
+ async function resolveEntryProjectAccess(em, ctx, tenantId, organizationId, settings) {
163
+ return resolveProjectAccess({
164
+ em: em.fork(),
165
+ userId: ctx.auth?.sub ?? null,
166
+ tenantId,
167
+ organizationId,
168
+ userFeatures: await resolveGrantedFeatures(ctx, tenantId, organizationId),
169
+ assignmentGraceDays: settings.access.assignmentGraceDays
170
+ });
171
+ }
172
+ async function assertEntryProjectAccess(params) {
173
+ if (params.hasManageAll || params.access.canManageAll) return;
174
+ const { translate } = await resolveTranslations();
175
+ if (params.projectId) {
176
+ if (params.access.projectIds.includes(params.projectId)) return;
177
+ throw new CrudHttpError(403, {
178
+ error: translate("staff.timesheets.errors.notAssigned", "You are not assigned to this project.")
179
+ });
180
+ }
181
+ if (params.access.staffMemberId && params.access.staffMemberId === params.entryStaffMemberId) return;
182
+ throw new CrudHttpError(403, {
183
+ error: translate("staff.timesheets.errors.notOwner", "You can only manage your own time entries.")
184
+ });
185
+ }
186
+ function resolveTimeEntryNotesInput(parsed) {
187
+ if (parsed.description !== void 0) return parsed.description ?? null;
188
+ if (parsed.notes !== void 0) return parsed.notes ?? null;
189
+ return void 0;
190
+ }
191
+ function toStoredTimeEntryRateOverride(amount) {
192
+ return amount === null || amount === void 0 ? null : String(amount);
193
+ }
194
+ function roundedMinutesFor(durationMinutes, settings, scope) {
195
+ return roundMinutes(durationMinutes, settings.rounding, scope);
196
+ }
197
+ function clockOfTimestamp(value) {
198
+ return formatClock(value.getUTCHours() * 60 + value.getUTCMinutes());
199
+ }
200
+ function timestampOnDayOf(reference, clock, dayOffset) {
201
+ const minutesOfDay = parseClock(clock) ?? 0;
202
+ return new Date(
203
+ Date.UTC(
204
+ reference.getUTCFullYear(),
205
+ reference.getUTCMonth(),
206
+ reference.getUTCDate() + dayOffset,
207
+ Math.floor(minutesOfDay / 60),
208
+ minutesOfDay % 60,
209
+ 0,
210
+ 0
211
+ )
212
+ );
213
+ }
214
+ function alignEndToStart(startedAt, endedAt, endClock, crossesMidnight) {
215
+ if (endedAt.getTime() >= startedAt.getTime()) return endedAt;
216
+ return timestampOnDayOf(startedAt, endClock, crossesMidnight ? 1 : 0);
217
+ }
218
+ function reconcileTimeEntryInterval(params) {
219
+ const startProvided = params.startedAt !== void 0;
220
+ const endProvided = params.endedAt !== void 0;
221
+ const durationProvided = params.durationMinutes !== void 0;
222
+ if (!startProvided && !endProvided && !durationProvided) return params.stored;
223
+ const startedAt = startProvided ? params.startedAt ?? null : params.stored.startedAt;
224
+ const endedAt = endProvided ? params.endedAt ?? null : params.stored.endedAt;
225
+ const durationMinutes = durationProvided ? params.durationMinutes : params.stored.durationMinutes;
226
+ if (!startedAt || !endedAt) return { startedAt, endedAt, durationMinutes };
227
+ const startClock = clockOfTimestamp(startedAt);
228
+ const endClock = clockOfTimestamp(endedAt);
229
+ const durationAnchored = durationProvided && !(startProvided && endProvided);
230
+ if (durationAnchored && !endProvided) {
231
+ const derived2 = deriveInterval({ start: startClock, durationMinutes });
232
+ return {
233
+ startedAt,
234
+ endedAt: timestampOnDayOf(startedAt, derived2.end ?? endClock, derived2.crossesMidnight ? 1 : 0),
235
+ durationMinutes
236
+ };
237
+ }
238
+ if (durationAnchored && !startProvided) {
239
+ const derived2 = deriveInterval({ end: endClock, durationMinutes });
240
+ return {
241
+ startedAt: timestampOnDayOf(endedAt, derived2.start ?? startClock, derived2.crossesMidnight ? -1 : 0),
242
+ endedAt,
243
+ durationMinutes
244
+ };
245
+ }
246
+ const derived = deriveInterval({ start: startClock, end: endClock, durationMinutes });
247
+ return {
248
+ startedAt,
249
+ endedAt: alignEndToStart(startedAt, endedAt, endClock, derived.crossesMidnight),
250
+ durationMinutes: derived.durationMinutes ?? durationMinutes
251
+ };
252
+ }
253
+ const MS_PER_DAY = 864e5;
254
+ function toDateOrNull(value) {
255
+ if (value === null || value === void 0) return null;
256
+ const date = value instanceof Date ? value : new Date(value);
257
+ return Number.isNaN(date.getTime()) ? null : date;
258
+ }
259
+ function utcDayIndex(value) {
260
+ return Math.round(
261
+ Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate()) / MS_PER_DAY
262
+ );
263
+ }
264
+ function rebaseTimeEntryIntervalToDate(params) {
265
+ const fromDate = toDateOrNull(params.fromDate);
266
+ const toDate = toDateOrNull(params.toDate);
267
+ if (!fromDate || !toDate) return params.stored;
268
+ const { startedAt, endedAt } = params.stored;
269
+ if (!startedAt && !endedAt) return params.stored;
270
+ if (startedAt && !endedAt) return params.stored;
271
+ const shiftMs = (utcDayIndex(toDate) - utcDayIndex(fromDate)) * MS_PER_DAY;
272
+ if (shiftMs === 0) return params.stored;
273
+ return {
274
+ startedAt: startedAt ? new Date(startedAt.getTime() + shiftMs) : null,
275
+ endedAt: endedAt ? new Date(endedAt.getTime() + shiftMs) : null,
276
+ durationMinutes: params.stored.durationMinutes
277
+ };
278
+ }
279
+ const TIME_ENTRY_LOCKED_CODE = TAG_TARGET_LOCKED_CODE;
280
+ function buildTimeEntryLockedError(lockedEntries, translate) {
281
+ const lockedEntryIds = lockedEntries.map((entry) => entry.id);
282
+ const lockedReportIds = Array.from(
283
+ new Set(
284
+ lockedEntries.map((entry) => entry.lockedReportId).filter((reportId) => typeof reportId === "string" && reportId.length > 0)
285
+ )
286
+ );
287
+ return new CrudHttpError(409, {
288
+ code: TIME_ENTRY_LOCKED_CODE,
289
+ error: lockedEntryIds.length > 1 ? translate(
290
+ "staff.time_tracking.entries.errors.entriesLocked",
291
+ "Some of these time entries are locked in a closed report and cannot be changed. Unlock the report first."
292
+ ) : translate(
293
+ "staff.time_tracking.entries.errors.entryLocked",
294
+ "This time entry is locked in a closed report and cannot be changed. Unlock the report first."
295
+ ),
296
+ lockedReportId: lockedReportIds[0] ?? null,
297
+ lockedEntryIds,
298
+ lockedReportIds
299
+ });
300
+ }
301
+ function assertTimeEntryUnlocked(entry, translate) {
302
+ if (!entry.lockedReportId) return;
303
+ throw buildTimeEntryLockedError([{ id: entry.id, lockedReportId: entry.lockedReportId }], translate);
304
+ }
305
+ async function syncEntryTags(ctx, params) {
306
+ const bus = ctx.container.resolve("commandBus");
307
+ const desired = Array.from(new Set(params.tagIds));
308
+ const scoped = {
309
+ tenantId: params.tenantId,
310
+ organizationId: params.organizationId,
311
+ timeEntryId: params.timeEntryId
312
+ };
313
+ const assigned = await bus.execute(staffTimeTagCommandIds.assignEntry, {
314
+ input: { ...scoped, tagIds: desired },
315
+ ctx
316
+ });
317
+ const current = assigned?.result?.tagIds ?? desired;
318
+ const stale = current.filter((tagId) => !desired.includes(tagId));
319
+ if (stale.length === 0) return;
320
+ await bus.execute(staffTimeTagCommandIds.unassignEntry, {
321
+ input: { ...scoped, tagIds: stale },
322
+ ctx
323
+ });
76
324
  }
77
325
  async function loadTimeEntrySnapshot(em, id, scope) {
78
326
  const entry = await findOneWithDecryption(
@@ -90,13 +338,18 @@ async function loadTimeEntrySnapshot(em, id, scope) {
90
338
  staffMemberId: entry.staffMemberId,
91
339
  date: entry.date instanceof Date ? entry.date.toISOString().split("T")[0] : String(entry.date),
92
340
  durationMinutes: entry.durationMinutes,
341
+ roundedMinutes: entry.roundedMinutes ?? null,
93
342
  startedAt: entry.startedAt ? entry.startedAt.toISOString() : null,
94
343
  endedAt: entry.endedAt ? entry.endedAt.toISOString() : null,
95
344
  notes: entry.notes ?? null,
96
345
  timeProjectId: entry.timeProjectId ?? null,
346
+ taskId: entry.taskId ?? null,
97
347
  customerId: entry.customerId ?? null,
98
348
  dealId: entry.dealId ?? null,
99
349
  orderId: entry.orderId ?? null,
350
+ isBillable: entry.isBillable,
351
+ rateOverrideAmount: entry.rateOverrideAmount ?? null,
352
+ rateCurrencyCode: entry.rateCurrencyCode ?? null,
100
353
  source: entry.source,
101
354
  deletedAt: entry.deletedAt ? entry.deletedAt.toISOString() : null
102
355
  };
@@ -109,13 +362,18 @@ function timeEntrySeedFromSnapshot(snapshot) {
109
362
  staffMemberId: snapshot.staffMemberId,
110
363
  date: snapshot.date,
111
364
  durationMinutes: snapshot.durationMinutes,
365
+ roundedMinutes: snapshot.roundedMinutes ?? null,
112
366
  startedAt: snapshot.startedAt ? new Date(snapshot.startedAt) : null,
113
367
  endedAt: snapshot.endedAt ? new Date(snapshot.endedAt) : null,
114
368
  notes: snapshot.notes ?? null,
115
369
  timeProjectId: snapshot.timeProjectId ?? null,
370
+ taskId: snapshot.taskId ?? null,
116
371
  customerId: snapshot.customerId ?? null,
117
372
  dealId: snapshot.dealId ?? null,
118
373
  orderId: snapshot.orderId ?? null,
374
+ isBillable: snapshot.isBillable ?? true,
375
+ rateOverrideAmount: snapshot.rateOverrideAmount ?? null,
376
+ rateCurrencyCode: snapshot.rateCurrencyCode ?? null,
119
377
  source: snapshot.source ?? "manual",
120
378
  createdAt: /* @__PURE__ */ new Date(),
121
379
  updatedAt: /* @__PURE__ */ new Date(),
@@ -141,7 +399,17 @@ const createTimeEntryCommand = {
141
399
  }
142
400
  effectiveStaffMemberId = callerStaffMemberId;
143
401
  }
144
- await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId);
402
+ const task = await requireTaskInScope(em, parsed.taskId ?? null, parsed.tenantId, parsed.organizationId);
403
+ const requestedProjectId = resolveTimeEntryProjectId(parsed.timeProjectId, task);
404
+ const project = await requireTimeProjectInScope(em, requestedProjectId, parsed.tenantId, parsed.organizationId);
405
+ await assertTaskBelongsToProject(task, project?.id ?? null);
406
+ const settings = await readEntrySettings(ctx, parsed.tenantId);
407
+ await assertEntryProjectAccess({
408
+ access: await resolveEntryProjectAccess(em, ctx, parsed.tenantId, parsed.organizationId, settings),
409
+ hasManageAll: await callerHasManageAll(ctx),
410
+ projectId: project?.id ?? null,
411
+ entryStaffMemberId: effectiveStaffMemberId
412
+ });
145
413
  const now = /* @__PURE__ */ new Date();
146
414
  const entry = em.create(StaffTimeEntry, {
147
415
  tenantId: parsed.tenantId,
@@ -149,13 +417,28 @@ const createTimeEntryCommand = {
149
417
  staffMemberId: effectiveStaffMemberId,
150
418
  date: parsed.date,
151
419
  durationMinutes: parsed.durationMinutes,
420
+ roundedMinutes: roundedMinutesFor(parsed.durationMinutes, settings, {
421
+ tenantId: parsed.tenantId,
422
+ organizationId: parsed.organizationId
423
+ }),
152
424
  startedAt: parsed.startedAt ?? null,
153
425
  endedAt: parsed.endedAt ?? null,
154
- notes: parsed.notes ?? null,
155
- timeProjectId: parsed.timeProjectId ?? null,
426
+ notes: resolveTimeEntryNotesInput(parsed) ?? null,
427
+ timeProjectId: project?.id ?? null,
428
+ taskId: task?.id ?? null,
156
429
  customerId: parsed.customerId ?? null,
157
430
  dealId: parsed.dealId ?? null,
158
431
  orderId: parsed.orderId ?? null,
432
+ isBillable: resolveTimeEntryBillable({
433
+ requested: parsed.isBillable,
434
+ project,
435
+ settings,
436
+ scope: { tenantId: parsed.tenantId, organizationId: parsed.organizationId }
437
+ }),
438
+ rateOverrideAmount: toStoredTimeEntryRateOverride(parsed.rateOverrideAmount),
439
+ // Snapshotted rather than joined at read time so a later project currency
440
+ // change cannot re-denominate money that has already been reported (D-3).
441
+ rateCurrencyCode: project?.currencyCode ?? null,
159
442
  source: parsed.source ?? "manual",
160
443
  createdAt: now,
161
444
  updatedAt: now,
@@ -163,6 +446,14 @@ const createTimeEntryCommand = {
163
446
  });
164
447
  em.persist(entry);
165
448
  await em.flush();
449
+ if (parsed.tagIds !== void 0) {
450
+ await syncEntryTags(ctx, {
451
+ timeEntryId: entry.id,
452
+ tenantId: parsed.tenantId,
453
+ organizationId: parsed.organizationId,
454
+ tagIds: parsed.tagIds
455
+ });
456
+ }
166
457
  await emitCrudSideEffects({
167
458
  dataEngine: ctx.container.resolve("dataEngine"),
168
459
  action: "created",
@@ -245,7 +536,11 @@ const startTimerCommand = {
245
536
  }
246
537
  effectiveStaffMemberId = callerStaffMemberId;
247
538
  }
248
- await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId);
539
+ const task = await requireTaskInScope(em, parsed.taskId ?? null, parsed.tenantId, parsed.organizationId);
540
+ const requestedProjectId = resolveTimeEntryProjectId(parsed.timeProjectId, task);
541
+ const project = await requireTimeProjectInScope(em, requestedProjectId, parsed.tenantId, parsed.organizationId);
542
+ await assertTaskBelongsToProject(task, project?.id ?? null);
543
+ const settings = await readEntrySettings(ctx, parsed.tenantId);
249
544
  const scopeCtx = { tenantId: parsed.tenantId, organizationId: parsed.organizationId };
250
545
  const { entry, startedAt } = await em.transactional(async (trx) => {
251
546
  const otherRunningEntry = await findOneWithDecryption(
@@ -278,10 +573,15 @@ const startTimerCommand = {
278
573
  staffMemberId: effectiveStaffMemberId,
279
574
  date: parsed.date,
280
575
  durationMinutes: 0,
576
+ roundedMinutes: roundedMinutesFor(0, settings, {
577
+ tenantId: parsed.tenantId,
578
+ organizationId: parsed.organizationId
579
+ }),
281
580
  startedAt: startedAt2,
282
581
  endedAt: null,
283
582
  notes: parsed.notes ?? null,
284
- timeProjectId: parsed.timeProjectId ?? null,
583
+ timeProjectId: project?.id ?? null,
584
+ taskId: task?.id ?? null,
285
585
  customerId: null,
286
586
  dealId: null,
287
587
  orderId: null,
@@ -389,7 +689,9 @@ const updateTimeEntryCommand = {
389
689
  if (!entry) throw new CrudHttpError(404, { error: "Time entry not found." });
390
690
  ensureTenantScope(ctx, entry.tenantId);
391
691
  ensureOrganizationScope(ctx, entry.organizationId);
392
- if (!await callerHasManageAll(ctx)) {
692
+ assertTimeEntryUnlocked(entry, (await resolveTranslations()).translate);
693
+ const hasManageAll = await callerHasManageAll(ctx);
694
+ if (!hasManageAll) {
393
695
  const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx);
394
696
  if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {
395
697
  const { translate } = await resolveTranslations();
@@ -398,18 +700,76 @@ const updateTimeEntryCommand = {
398
700
  });
399
701
  }
400
702
  }
401
- if (parsed.timeProjectId !== void 0 && parsed.timeProjectId !== null) {
402
- await assertTimeProjectInScope(em, parsed.timeProjectId, entry.tenantId, entry.organizationId);
703
+ const task = parsed.taskId !== void 0 ? await requireTaskInScope(em, parsed.taskId, entry.tenantId, entry.organizationId) : null;
704
+ const nextProjectId = parsed.timeProjectId !== void 0 ? parsed.timeProjectId ?? null : task?.timeProjectId ?? entry.timeProjectId ?? null;
705
+ const projectChanged = nextProjectId !== (entry.timeProjectId ?? null);
706
+ const project = projectChanged ? await requireTimeProjectInScope(em, nextProjectId, entry.tenantId, entry.organizationId) : null;
707
+ await assertTaskBelongsToProject(task, nextProjectId);
708
+ const settings = await readEntrySettings(ctx, entry.tenantId);
709
+ const access = await resolveEntryProjectAccess(em, ctx, entry.tenantId, entry.organizationId, settings);
710
+ await assertEntryProjectAccess({
711
+ access,
712
+ hasManageAll,
713
+ projectId: entry.timeProjectId ?? null,
714
+ entryStaffMemberId: entry.staffMemberId
715
+ });
716
+ if (projectChanged) {
717
+ await assertEntryProjectAccess({
718
+ access,
719
+ hasManageAll,
720
+ projectId: nextProjectId,
721
+ entryStaffMemberId: entry.staffMemberId
722
+ });
403
723
  }
724
+ const notes = resolveTimeEntryNotesInput(parsed);
725
+ const stored = rebaseTimeEntryIntervalToDate({
726
+ stored: {
727
+ startedAt: entry.startedAt ?? null,
728
+ endedAt: entry.endedAt ?? null,
729
+ durationMinutes: entry.durationMinutes
730
+ },
731
+ fromDate: entry.date,
732
+ toDate: parsed.date
733
+ });
734
+ const interval = reconcileTimeEntryInterval({
735
+ stored,
736
+ startedAt: parsed.startedAt,
737
+ endedAt: parsed.endedAt,
738
+ durationMinutes: parsed.durationMinutes
739
+ });
404
740
  if (parsed.date !== void 0) entry.date = parsed.date;
405
- if (parsed.durationMinutes !== void 0) entry.durationMinutes = parsed.durationMinutes;
406
- if (parsed.timeProjectId !== void 0) entry.timeProjectId = parsed.timeProjectId ?? null;
741
+ if (interval.startedAt !== (entry.startedAt ?? null)) entry.startedAt = interval.startedAt;
742
+ if (interval.endedAt !== (entry.endedAt ?? null)) entry.endedAt = interval.endedAt;
743
+ if (parsed.durationMinutes !== void 0 || interval.durationMinutes !== entry.durationMinutes) {
744
+ entry.durationMinutes = interval.durationMinutes;
745
+ entry.roundedMinutes = roundedMinutesFor(interval.durationMinutes, settings, {
746
+ tenantId: entry.tenantId,
747
+ organizationId: entry.organizationId
748
+ });
749
+ }
750
+ if (projectChanged) {
751
+ entry.timeProjectId = nextProjectId;
752
+ entry.rateCurrencyCode = project?.currencyCode ?? null;
753
+ }
754
+ if (parsed.taskId !== void 0) entry.taskId = task?.id ?? null;
407
755
  if (parsed.customerId !== void 0) entry.customerId = parsed.customerId ?? null;
408
756
  if (parsed.dealId !== void 0) entry.dealId = parsed.dealId ?? null;
409
757
  if (parsed.orderId !== void 0) entry.orderId = parsed.orderId ?? null;
410
- if (parsed.notes !== void 0) entry.notes = parsed.notes ?? null;
758
+ if (parsed.isBillable !== void 0) entry.isBillable = parsed.isBillable;
759
+ if (parsed.rateOverrideAmount !== void 0) {
760
+ entry.rateOverrideAmount = toStoredTimeEntryRateOverride(parsed.rateOverrideAmount);
761
+ }
762
+ if (notes !== void 0) entry.notes = notes;
411
763
  entry.updatedAt = /* @__PURE__ */ new Date();
412
764
  await em.flush();
765
+ if (parsed.tagIds !== void 0) {
766
+ await syncEntryTags(ctx, {
767
+ timeEntryId: entry.id,
768
+ tenantId: entry.tenantId,
769
+ organizationId: entry.organizationId,
770
+ tagIds: parsed.tagIds
771
+ });
772
+ }
413
773
  await emitCrudSideEffects({
414
774
  dataEngine: ctx.container.resolve("dataEngine"),
415
775
  action: "updated",
@@ -429,10 +789,19 @@ const updateTimeEntryCommand = {
429
789
  const changes = buildChanges(before, after, [
430
790
  "date",
431
791
  "durationMinutes",
792
+ "roundedMinutes",
793
+ // A time correction is exactly the edit somebody will later have to justify
794
+ // on an invoice, so the clocks are named in the trail beside the minutes.
795
+ "startedAt",
796
+ "endedAt",
432
797
  "timeProjectId",
798
+ "taskId",
433
799
  "customerId",
434
800
  "dealId",
435
801
  "orderId",
802
+ "isBillable",
803
+ "rateOverrideAmount",
804
+ "rateCurrencyCode",
436
805
  "notes",
437
806
  "deletedAt"
438
807
  ]);
@@ -463,10 +832,17 @@ const updateTimeEntryCommand = {
463
832
  if (!entry) return;
464
833
  entry.date = before.date;
465
834
  entry.durationMinutes = before.durationMinutes;
835
+ entry.roundedMinutes = before.roundedMinutes ?? null;
836
+ entry.startedAt = before.startedAt ? new Date(before.startedAt) : null;
837
+ entry.endedAt = before.endedAt ? new Date(before.endedAt) : null;
466
838
  entry.timeProjectId = before.timeProjectId ?? null;
839
+ entry.taskId = before.taskId ?? null;
467
840
  entry.customerId = before.customerId ?? null;
468
841
  entry.dealId = before.dealId ?? null;
469
842
  entry.orderId = before.orderId ?? null;
843
+ entry.isBillable = before.isBillable ?? true;
844
+ entry.rateOverrideAmount = before.rateOverrideAmount ?? null;
845
+ entry.rateCurrencyCode = before.rateCurrencyCode ?? null;
470
846
  entry.notes = before.notes ?? null;
471
847
  entry.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null;
472
848
  entry.updatedAt = /* @__PURE__ */ new Date();
@@ -506,7 +882,9 @@ const deleteTimeEntryCommand = {
506
882
  if (!entry) throw new CrudHttpError(404, { error: "Time entry not found." });
507
883
  ensureTenantScope(ctx, entry.tenantId);
508
884
  ensureOrganizationScope(ctx, entry.organizationId);
509
- if (!await callerHasManageAll(ctx)) {
885
+ assertTimeEntryUnlocked(entry, (await resolveTranslations()).translate);
886
+ const hasManageAll = await callerHasManageAll(ctx);
887
+ if (!hasManageAll) {
510
888
  const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx);
511
889
  if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {
512
890
  const { translate } = await resolveTranslations();
@@ -515,6 +893,13 @@ const deleteTimeEntryCommand = {
515
893
  });
516
894
  }
517
895
  }
896
+ const settings = await readEntrySettings(ctx, entry.tenantId);
897
+ await assertEntryProjectAccess({
898
+ access: await resolveEntryProjectAccess(em, ctx, entry.tenantId, entry.organizationId, settings),
899
+ hasManageAll,
900
+ projectId: entry.timeProjectId ?? null,
901
+ entryStaffMemberId: entry.staffMemberId
902
+ });
518
903
  entry.deletedAt = /* @__PURE__ */ new Date();
519
904
  entry.updatedAt = /* @__PURE__ */ new Date();
520
905
  await em.flush();
@@ -560,13 +945,18 @@ const deleteTimeEntryCommand = {
560
945
  staffMemberId: before.staffMemberId,
561
946
  date: before.date,
562
947
  durationMinutes: before.durationMinutes,
948
+ roundedMinutes: before.roundedMinutes ?? null,
563
949
  startedAt: before.startedAt ? new Date(before.startedAt) : null,
564
950
  endedAt: before.endedAt ? new Date(before.endedAt) : null,
565
951
  notes: before.notes ?? null,
566
952
  timeProjectId: before.timeProjectId ?? null,
953
+ taskId: before.taskId ?? null,
567
954
  customerId: before.customerId ?? null,
568
955
  dealId: before.dealId ?? null,
569
956
  orderId: before.orderId ?? null,
957
+ isBillable: before.isBillable ?? true,
958
+ rateOverrideAmount: before.rateOverrideAmount ?? null,
959
+ rateCurrencyCode: before.rateCurrencyCode ?? null,
570
960
  source: before.source ?? "manual",
571
961
  deletedAt: null,
572
962
  createdAt: /* @__PURE__ */ new Date(),
@@ -577,13 +967,18 @@ const deleteTimeEntryCommand = {
577
967
  entry.staffMemberId = before.staffMemberId;
578
968
  entry.date = before.date;
579
969
  entry.durationMinutes = before.durationMinutes;
970
+ entry.roundedMinutes = before.roundedMinutes ?? null;
580
971
  entry.startedAt = before.startedAt ? new Date(before.startedAt) : null;
581
972
  entry.endedAt = before.endedAt ? new Date(before.endedAt) : null;
582
973
  entry.notes = before.notes ?? null;
583
974
  entry.timeProjectId = before.timeProjectId ?? null;
975
+ entry.taskId = before.taskId ?? null;
584
976
  entry.customerId = before.customerId ?? null;
585
977
  entry.dealId = before.dealId ?? null;
586
978
  entry.orderId = before.orderId ?? null;
979
+ entry.isBillable = before.isBillable ?? true;
980
+ entry.rateOverrideAmount = before.rateOverrideAmount ?? null;
981
+ entry.rateCurrencyCode = before.rateCurrencyCode ?? null;
587
982
  entry.source = before.source ?? "manual";
588
983
  entry.deletedAt = null;
589
984
  entry.updatedAt = /* @__PURE__ */ new Date();
@@ -599,8 +994,161 @@ const deleteTimeEntryCommand = {
599
994
  });
600
995
  }
601
996
  };
997
+ const staffTimeEntryDuplicateSchema = z.object({
998
+ id: z.string().uuid(),
999
+ // The copy usually lands on another day (US-D6 "log the same thing again"), so
1000
+ // the caller may move it; omitted, it keeps the source's day.
1001
+ date: z.coerce.date().optional(),
1002
+ // US-D6 ends "…I adjust the duration and the date", so both adjustments travel
1003
+ // with the copy request rather than costing a second round trip that would
1004
+ // leave the unadjusted duration visible in between. Omitted, the copy keeps the
1005
+ // source's minutes. The rounded twin is always recomputed by the create command
1006
+ // from the tenant rule, so an overridden duration can never carry the source's
1007
+ // stale `rounded_minutes` into a new entry (D-7).
1008
+ durationMinutes: z.number().int().min(0).max(1440).optional(),
1009
+ // Tags are NOT read off the source here: this file writes tags only through the
1010
+ // tag commands and never touches `staff_time_entry_tags`, so the caller — which
1011
+ // already has the source's `tags[]` from the list response — passes them on.
1012
+ tagIds: z.array(z.string().uuid()).max(50).optional()
1013
+ });
1014
+ const duplicateTimeEntryCommand = {
1015
+ id: "staff.timesheets.time_entries.duplicate",
1016
+ async execute(rawInput, ctx) {
1017
+ const parsed = staffTimeEntryDuplicateSchema.parse(rawInput);
1018
+ const em = ctx.container.resolve("em").fork();
1019
+ const scope = commandActorScope(ctx);
1020
+ const source = await findOneWithDecryption(
1021
+ em,
1022
+ StaffTimeEntry,
1023
+ applyScopeToWhere({ id: parsed.id, deletedAt: null }, scope),
1024
+ void 0,
1025
+ scopeForDecryption(scope)
1026
+ );
1027
+ if (!source) throw new CrudHttpError(404, { error: "Time entry not found." });
1028
+ ensureTenantScope(ctx, source.tenantId);
1029
+ ensureOrganizationScope(ctx, source.organizationId);
1030
+ assertTimeEntryUnlocked(source, (await resolveTranslations()).translate);
1031
+ const bus = ctx.container.resolve("commandBus");
1032
+ const created = await bus.execute(createTimeEntryCommand.id, {
1033
+ input: {
1034
+ tenantId: source.tenantId,
1035
+ organizationId: source.organizationId,
1036
+ staffMemberId: source.staffMemberId,
1037
+ date: parsed.date ?? source.date,
1038
+ durationMinutes: parsed.durationMinutes ?? source.durationMinutes,
1039
+ timeProjectId: source.timeProjectId ?? null,
1040
+ taskId: source.taskId ?? null,
1041
+ customerId: source.customerId ?? null,
1042
+ dealId: source.dealId ?? null,
1043
+ orderId: source.orderId ?? null,
1044
+ isBillable: source.isBillable,
1045
+ rateOverrideAmount: source.rateOverrideAmount === null || source.rateOverrideAmount === void 0 ? null : Number(source.rateOverrideAmount),
1046
+ description: source.notes ?? null,
1047
+ // A copy is typed, not timed: carrying `started_at`/`ended_at` over would
1048
+ // manufacture an overlap with the entry it was copied from (US-D7).
1049
+ source: "manual",
1050
+ ...parsed.tagIds !== void 0 ? { tagIds: parsed.tagIds } : {}
1051
+ },
1052
+ ctx
1053
+ });
1054
+ const timeEntryId = created?.result?.timeEntryId;
1055
+ if (!timeEntryId) throw new CrudHttpError(400, { error: "Failed to duplicate time entry." });
1056
+ return { timeEntryId };
1057
+ }
1058
+ };
1059
+ const staffTimeEntryReapplyRoundingSchema = z.object({
1060
+ tenantId: z.string().uuid(),
1061
+ organizationId: z.string().uuid(),
1062
+ entryIds: z.array(z.string().uuid()).min(1).max(500)
1063
+ });
1064
+ const reapplyRoundingCommand = {
1065
+ id: "staff.timesheets.time_entries.reapply_rounding",
1066
+ async execute(input, ctx) {
1067
+ const parsed = staffTimeEntryReapplyRoundingSchema.parse(input ?? {});
1068
+ if (ctx.systemActor !== true && ctx.auth?.isSuperAdmin !== true) {
1069
+ const { translate } = await resolveTranslations();
1070
+ throw new CrudHttpError(403, { error: translate("staff.errors.forbidden", "Forbidden") });
1071
+ }
1072
+ const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId);
1073
+ const em = ctx.container.resolve("em").fork();
1074
+ const settings = await readEntrySettings(ctx, parsed.tenantId);
1075
+ const entries = await em.find(
1076
+ StaffTimeEntry,
1077
+ applyScopeToWhere(
1078
+ {
1079
+ id: { $in: parsed.entryIds },
1080
+ deletedAt: null,
1081
+ // Non-negotiable: a frozen entry has already been billed at the value it
1082
+ // carries, so it is excluded at the query, not at an `if`.
1083
+ lockedReportId: null
1084
+ },
1085
+ scope
1086
+ )
1087
+ );
1088
+ const changed = [];
1089
+ let unchangedCount = 0;
1090
+ for (const entry of entries) {
1091
+ const next = roundedMinutesFor(entry.durationMinutes, settings, {
1092
+ tenantId: entry.tenantId,
1093
+ organizationId: entry.organizationId
1094
+ });
1095
+ if (entry.roundedMinutes === next) {
1096
+ unchangedCount += 1;
1097
+ continue;
1098
+ }
1099
+ entry.roundedMinutes = next;
1100
+ entry.updatedAt = /* @__PURE__ */ new Date();
1101
+ changed.push(entry);
1102
+ }
1103
+ if (changed.length > 0) await em.flush();
1104
+ const dataEngine = ctx.container.resolve("dataEngine");
1105
+ for (const entry of changed) {
1106
+ await emitCrudSideEffects({
1107
+ dataEngine,
1108
+ action: "updated",
1109
+ entity: entry,
1110
+ identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },
1111
+ events: staffTimeEntryCrudEvents,
1112
+ indexer: timeEntryCrudIndexer
1113
+ });
1114
+ }
1115
+ return {
1116
+ updatedCount: changed.length,
1117
+ unchangedCount,
1118
+ skippedCount: Math.max(0, parsed.entryIds.length - entries.length)
1119
+ };
1120
+ }
1121
+ };
602
1122
  registerCommand(createTimeEntryCommand);
603
1123
  registerCommand(startTimerCommand);
604
1124
  registerCommand(updateTimeEntryCommand);
605
1125
  registerCommand(deleteTimeEntryCommand);
1126
+ registerCommand(duplicateTimeEntryCommand);
1127
+ registerCommand(reapplyRoundingCommand);
1128
+ const staffTimeEntryCommandIds = {
1129
+ create: createTimeEntryCommand.id,
1130
+ startTimer: startTimerCommand.id,
1131
+ update: updateTimeEntryCommand.id,
1132
+ delete: deleteTimeEntryCommand.id,
1133
+ duplicate: duplicateTimeEntryCommand.id,
1134
+ reapplyRounding: reapplyRoundingCommand.id
1135
+ };
1136
+ export {
1137
+ TIME_ENTRY_LOCKED_CODE,
1138
+ assertTimeEntryUnlocked,
1139
+ buildTimeEntryLockedError,
1140
+ rebaseTimeEntryIntervalToDate,
1141
+ reconcileTimeEntryInterval,
1142
+ resolveRoundedMinutes,
1143
+ resolveTimeEntryBillable,
1144
+ resolveTimeEntryNotesInput,
1145
+ resolveTimeEntryProjectId,
1146
+ resolveTimeEntrySettings,
1147
+ roundedMinutesFor,
1148
+ staffTimeEntryCommandIds,
1149
+ staffTimeEntryDuplicateSchema,
1150
+ staffTimeEntryReapplyRoundingSchema,
1151
+ timeEntryTaskMatchesProject,
1152
+ toStoredTimeEntryRateOverride
1153
+ };
606
1154
  //# sourceMappingURL=timesheets-entries.js.map