@open-mercato/core 0.10.1-develop.7716.1.cefe7975df → 0.10.1-develop.7721.1.b5c4a00a68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/staff_support_routing_rule/index.js +21 -0
- package/dist/generated/entities/staff_support_routing_rule/index.js.map +7 -0
- package/dist/generated/entities/staff_support_ticket/index.js +37 -0
- package/dist/generated/entities/staff_support_ticket/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project/index.js +2 -0
- package/dist/generated/entities/staff_time_project/index.js.map +2 -2
- package/dist/generated/entities/staff_time_project_member/index.js +2 -0
- package/dist/generated/entities/staff_time_project_member/index.js.map +2 -2
- package/dist/generated/entities/staff_time_task/index.js +4 -0
- package/dist/generated/entities/staff_time_task/index.js.map +2 -2
- package/dist/generated/entities/staff_time_task_comment/index.js +9 -1
- package/dist/generated/entities/staff_time_task_comment/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +2 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +38 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/auth.js +1 -0
- package/dist/helpers/integration/auth.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js +20 -0
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
- package/dist/modules/catalog/api/bulk-delete/route.js +12 -2
- package/dist/modules/catalog/api/bulk-delete/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +17 -3
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/lib/test-seed.js +38 -5
- package/dist/modules/communication_channels/lib/test-seed.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +2 -3
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js +2 -2
- package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js.map +2 -2
- package/dist/modules/staff/api/portal/support-tickets/[id]/attachments/route.js +299 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/attachments/route.js.map +7 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/messages/route.js +91 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/messages/route.js.map +7 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/route.js +146 -0
- package/dist/modules/staff/api/portal/support-tickets/[id]/route.js.map +7 -0
- package/dist/modules/staff/api/portal/support-tickets/options/route.js +60 -0
- package/dist/modules/staff/api/portal/support-tickets/options/route.js.map +7 -0
- package/dist/modules/staff/api/portal/support-tickets/route.js +220 -0
- package/dist/modules/staff/api/portal/support-tickets/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/settings/route.js +7 -1
- package/dist/modules/staff/api/timesheets/settings/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.js +122 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/preview/route.js +180 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/preview/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/route.js +147 -0
- package/dist/modules/staff/api/timesheets/support-routing-rules/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/support-tickets/options/route.js +133 -0
- package/dist/modules/staff/api/timesheets/support-tickets/options/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/claim/route.js +33 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/claim/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +25 -7
- package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/tasks/[id]/release/route.js +32 -0
- package/dist/modules/staff/api/timesheets/tasks/[id]/release/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/tasks/route.js +94 -47
- package/dist/modules/staff/api/timesheets/tasks/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +3 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-projects/route.js +3 -0
- package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +1 -0
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +54 -4
- package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js +21 -5
- package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/settings/page.js +319 -254
- package/dist/modules/staff/backend/staff/time-tracking/settings/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/time-tracking/support/page.js +363 -0
- package/dist/modules/staff/backend/staff/time-tracking/support/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/time-tracking/support/page.meta.js +18 -0
- package/dist/modules/staff/backend/staff/time-tracking/support/page.meta.js.map +7 -0
- package/dist/modules/staff/cli.js +27 -0
- package/dist/modules/staff/cli.js.map +2 -2
- package/dist/modules/staff/commands/index.js +3 -0
- package/dist/modules/staff/commands/index.js.map +2 -2
- package/dist/modules/staff/commands/shared.js +10 -1
- package/dist/modules/staff/commands/shared.js.map +2 -2
- package/dist/modules/staff/commands/support-routing-rules.js +505 -0
- package/dist/modules/staff/commands/support-routing-rules.js.map +7 -0
- package/dist/modules/staff/commands/support-tickets.js +513 -0
- package/dist/modules/staff/commands/support-tickets.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-projects.js +72 -14
- package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-task-assignment.js +270 -0
- package/dist/modules/staff/commands/timesheets-task-assignment.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-task-comments.js +58 -12
- package/dist/modules/staff/commands/timesheets-task-comments.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-tasks.js +91 -9
- package/dist/modules/staff/commands/timesheets-tasks.js.map +3 -3
- package/dist/modules/staff/data/enrichers.js +141 -0
- package/dist/modules/staff/data/enrichers.js.map +2 -2
- package/dist/modules/staff/data/entities.js +143 -2
- package/dist/modules/staff/data/entities.js.map +2 -2
- package/dist/modules/staff/data/extensions.js +8 -0
- package/dist/modules/staff/data/extensions.js.map +2 -2
- package/dist/modules/staff/data/validators.js +34 -5
- package/dist/modules/staff/data/validators.js.map +2 -2
- package/dist/modules/staff/encryption.js +6 -0
- package/dist/modules/staff/encryption.js.map +2 -2
- package/dist/modules/staff/events.js +25 -0
- package/dist/modules/staff/events.js.map +2 -2
- package/dist/modules/staff/events.payloads.js +54 -0
- package/dist/modules/staff/events.payloads.js.map +2 -2
- package/dist/modules/staff/extension-points.js +1 -0
- package/dist/modules/staff/extension-points.js.map +2 -2
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.js +468 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.js +12 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.js +316 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.js +12 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.js +190 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.js.map +7 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.meta.js +19 -0
- package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.meta.js.map +7 -0
- package/dist/modules/staff/index.js +1 -1
- package/dist/modules/staff/index.js.map +2 -2
- package/dist/modules/staff/lib/crud.js +2 -0
- package/dist/modules/staff/lib/crud.js.map +2 -2
- package/dist/modules/staff/lib/support/attachments.js +36 -0
- package/dist/modules/staff/lib/support/attachments.js.map +7 -0
- package/dist/modules/staff/lib/support/dictionaries.js +87 -0
- package/dist/modules/staff/lib/support/dictionaries.js.map +7 -0
- package/dist/modules/staff/lib/support/notifications.js +111 -0
- package/dist/modules/staff/lib/support/notifications.js.map +7 -0
- package/dist/modules/staff/lib/support/portalAttachments.js +100 -0
- package/dist/modules/staff/lib/support/portalAttachments.js.map +7 -0
- package/dist/modules/staff/lib/support/portalBroadcast.js +117 -0
- package/dist/modules/staff/lib/support/portalBroadcast.js.map +7 -0
- package/dist/modules/staff/lib/support/portalRoute.js +99 -0
- package/dist/modules/staff/lib/support/portalRoute.js.map +7 -0
- package/dist/modules/staff/lib/support/portalStatus.js +12 -0
- package/dist/modules/staff/lib/support/portalStatus.js.map +7 -0
- package/dist/modules/staff/lib/support/portalTickets.js +148 -0
- package/dist/modules/staff/lib/support/portalTickets.js.map +7 -0
- package/dist/modules/staff/lib/support/routing.js +81 -0
- package/dist/modules/staff/lib/support/routing.js.map +7 -0
- package/dist/modules/staff/lib/support/routingRuleDraft.js +25 -0
- package/dist/modules/staff/lib/support/routingRuleDraft.js.map +7 -0
- package/dist/modules/staff/lib/support/seedDefaults.js +114 -0
- package/dist/modules/staff/lib/support/seedDefaults.js.map +7 -0
- package/dist/modules/staff/lib/support/supportActivity.js +26 -0
- package/dist/modules/staff/lib/support/supportActivity.js.map +7 -0
- package/dist/modules/staff/lib/support-ui/PortalSupportNotLinked.js +23 -0
- package/dist/modules/staff/lib/support-ui/PortalSupportNotLinked.js.map +7 -0
- package/dist/modules/staff/lib/support-ui/portalAttachmentValidation.js +112 -0
- package/dist/modules/staff/lib/support-ui/portalAttachmentValidation.js.map +7 -0
- package/dist/modules/staff/lib/support-ui/portalPendingUploads.js +45 -0
- package/dist/modules/staff/lib/support-ui/portalPendingUploads.js.map +7 -0
- package/dist/modules/staff/lib/support-ui/portalSupport.js +51 -0
- package/dist/modules/staff/lib/support-ui/portalSupport.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/access.js +3 -39
- package/dist/modules/staff/lib/time-tracking/access.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/listProjectAccess.js +54 -0
- package/dist/modules/staff/lib/time-tracking/listProjectAccess.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/portalRecipients.js +92 -2
- package/dist/modules/staff/lib/time-tracking/portalRecipients.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/projectAssignment.js +112 -0
- package/dist/modules/staff/lib/time-tracking/projectAssignment.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/settingKeys.js +14 -0
- package/dist/modules/staff/lib/time-tracking/settingKeys.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/settings.js +28 -1
- package/dist/modules/staff/lib/time-tracking/settings.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking/taskAssignmentRoute.js +143 -0
- package/dist/modules/staff/lib/time-tracking/taskAssignmentRoute.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking/workRecipients.js +92 -0
- package/dist/modules/staff/lib/time-tracking/workRecipients.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js +32 -3
- package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js +29 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js +4 -0
- package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js +141 -1
- package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.js +153 -0
- package/dist/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/SupportRequestPanel.js +67 -0
- package/dist/modules/staff/lib/time-tracking-ui/SupportRequestPanel.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js +3 -1
- package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js +80 -17
- package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js +230 -41
- package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js +21 -1
- package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js +16 -4
- package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js +3 -1
- package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.js +68 -0
- package/dist/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/settingsTabs.js +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/settingsTabs.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/supportTicketData.js +50 -0
- package/dist/modules/staff/lib/time-tracking-ui/supportTicketData.js.map +7 -0
- package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js +13 -1
- package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js.map +2 -2
- package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js +36 -2
- package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js.map +2 -2
- package/dist/modules/staff/migrations/Migration20261009180543_staff.js +42 -0
- package/dist/modules/staff/migrations/Migration20261009180543_staff.js.map +7 -0
- package/dist/modules/staff/notifications.js +92 -0
- package/dist/modules/staff/notifications.js.map +2 -2
- package/dist/modules/staff/setup.js +6 -2
- package/dist/modules/staff/setup.js.map +2 -2
- package/dist/modules/staff/subscribers/support-portal-comment-created.js +26 -0
- package/dist/modules/staff/subscribers/support-portal-comment-created.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-comment-deleted.js +26 -0
- package/dist/modules/staff/subscribers/support-portal-comment-deleted.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-comment-updated.js +26 -0
- package/dist/modules/staff/subscribers/support-portal-comment-updated.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-status-column-updated.js +24 -0
- package/dist/modules/staff/subscribers/support-portal-status-column-updated.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-task-status-changed.js +25 -0
- package/dist/modules/staff/subscribers/support-portal-task-status-changed.js.map +7 -0
- package/dist/modules/staff/subscribers/support-portal-task-updated.js +25 -0
- package/dist/modules/staff/subscribers/support-portal-task-updated.js.map +7 -0
- package/dist/modules/staff/subscribers/support-ticket-created-notification.js +25 -0
- package/dist/modules/staff/subscribers/support-ticket-created-notification.js.map +7 -0
- package/dist/modules/staff/subscribers/support-ticket-customer-replied-notification.js +25 -0
- package/dist/modules/staff/subscribers/support-ticket-customer-replied-notification.js.map +7 -0
- package/dist/modules/staff/subscribers/support-ticket-unnotified-clear.js +26 -0
- package/dist/modules/staff/subscribers/support-ticket-unnotified-clear.js.map +7 -0
- package/dist/modules/staff/subscribers/time-task-assignee-notification.js +83 -0
- package/dist/modules/staff/subscribers/time-task-assignee-notification.js.map +7 -0
- package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.client.js +112 -0
- package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.js +17 -0
- package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.js +870 -0
- package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.js +17 -0
- package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection-table.js +16 -1
- package/dist/modules/staff/widgets/injection-table.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +4 -18
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js +4 -18
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +4 -18
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +2 -2
- package/dist/modules/wms/lib/inventoryCsvExport.js +19 -0
- package/dist/modules/wms/lib/inventoryCsvExport.js.map +7 -0
- package/generated/entities/staff_support_routing_rule/index.ts +9 -0
- package/generated/entities/staff_support_ticket/index.ts +17 -0
- package/generated/entities/staff_time_project/index.ts +1 -0
- package/generated/entities/staff_time_project_member/index.ts +1 -0
- package/generated/entities/staff_time_task/index.ts +2 -0
- package/generated/entities/staff_time_task_comment/index.ts +4 -0
- package/generated/entities.ids.generated.ts +2 -0
- package/generated/entity-fields-registry.ts +38 -0
- package/package.json +8 -8
- package/src/helpers/integration/auth.ts +1 -1
- package/src/helpers/integration/communicationChannelsFixtures.ts +60 -2
- package/src/modules/catalog/api/bulk-delete/route.ts +12 -2
- package/src/modules/communication_channels/api/post/test-seed/route.ts +29 -12
- package/src/modules/communication_channels/lib/test-seed.ts +49 -10
- package/src/modules/messages/commands/messages.ts +8 -10
- package/src/modules/portal/frontend/[orgSlug]/portal/dashboard/page.tsx +2 -2
- package/src/modules/staff/AGENTS.md +22 -6
- package/src/modules/staff/api/portal/support-tickets/[id]/attachments/route.ts +327 -0
- package/src/modules/staff/api/portal/support-tickets/[id]/messages/route.ts +94 -0
- package/src/modules/staff/api/portal/support-tickets/[id]/route.ts +160 -0
- package/src/modules/staff/api/portal/support-tickets/options/route.ts +60 -0
- package/src/modules/staff/api/portal/support-tickets/route.ts +253 -0
- package/src/modules/staff/api/timesheets/settings/route.ts +7 -1
- package/src/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.ts +131 -0
- package/src/modules/staff/api/timesheets/support-routing-rules/preview/route.ts +248 -0
- package/src/modules/staff/api/timesheets/support-routing-rules/route.ts +150 -0
- package/src/modules/staff/api/timesheets/support-tickets/options/route.ts +181 -0
- package/src/modules/staff/api/timesheets/tasks/[id]/claim/route.ts +31 -0
- package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +25 -7
- package/src/modules/staff/api/timesheets/tasks/[id]/release/route.ts +30 -0
- package/src/modules/staff/api/timesheets/tasks/route.ts +119 -67
- package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +3 -0
- package/src/modules/staff/api/timesheets/time-projects/route.ts +3 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +1 -0
- package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +67 -2
- package/src/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.ts +22 -3
- package/src/modules/staff/backend/staff/time-tracking/settings/page.tsx +405 -308
- package/src/modules/staff/backend/staff/time-tracking/support/page.meta.ts +14 -0
- package/src/modules/staff/backend/staff/time-tracking/support/page.tsx +428 -0
- package/src/modules/staff/cli.ts +28 -0
- package/src/modules/staff/commands/index.ts +3 -0
- package/src/modules/staff/commands/shared.ts +22 -1
- package/src/modules/staff/commands/support-routing-rules.ts +595 -0
- package/src/modules/staff/commands/support-tickets.ts +580 -0
- package/src/modules/staff/commands/timesheets-projects.ts +84 -13
- package/src/modules/staff/commands/timesheets-task-assignment.ts +319 -0
- package/src/modules/staff/commands/timesheets-task-comments.ts +70 -15
- package/src/modules/staff/commands/timesheets-tasks.ts +106 -15
- package/src/modules/staff/data/enrichers.ts +203 -0
- package/src/modules/staff/data/entities.ts +133 -2
- package/src/modules/staff/data/extensions.ts +9 -1
- package/src/modules/staff/data/validators.ts +36 -0
- package/src/modules/staff/encryption.ts +6 -0
- package/src/modules/staff/events.payloads.ts +87 -1
- package/src/modules/staff/events.ts +26 -0
- package/src/modules/staff/extension-points.ts +1 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.ts +10 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.tsx +553 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.ts +10 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/new/page.tsx +346 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/page.meta.ts +17 -0
- package/src/modules/staff/frontend/[orgSlug]/portal/support/page.tsx +253 -0
- package/src/modules/staff/i18n/de.json +291 -0
- package/src/modules/staff/i18n/en.json +291 -0
- package/src/modules/staff/i18n/es.json +291 -0
- package/src/modules/staff/i18n/ko.json +291 -0
- package/src/modules/staff/i18n/pl.json +291 -0
- package/src/modules/staff/index.ts +1 -1
- package/src/modules/staff/lib/crud.ts +2 -1
- package/src/modules/staff/lib/support/attachments.ts +43 -0
- package/src/modules/staff/lib/support/dictionaries.ts +120 -0
- package/src/modules/staff/lib/support/notifications.ts +138 -0
- package/src/modules/staff/lib/support/portalAttachments.ts +140 -0
- package/src/modules/staff/lib/support/portalBroadcast.ts +161 -0
- package/src/modules/staff/lib/support/portalRoute.ts +108 -0
- package/src/modules/staff/lib/support/portalStatus.ts +15 -0
- package/src/modules/staff/lib/support/portalTickets.ts +233 -0
- package/src/modules/staff/lib/support/routing.ts +117 -0
- package/src/modules/staff/lib/support/routingRuleDraft.ts +45 -0
- package/src/modules/staff/lib/support/seedDefaults.ts +151 -0
- package/src/modules/staff/lib/support/supportActivity.ts +39 -0
- package/src/modules/staff/lib/support-ui/PortalSupportNotLinked.tsx +20 -0
- package/src/modules/staff/lib/support-ui/portalAttachmentValidation.ts +125 -0
- package/src/modules/staff/lib/support-ui/portalPendingUploads.ts +49 -0
- package/src/modules/staff/lib/support-ui/portalSupport.ts +116 -0
- package/src/modules/staff/lib/time-tracking/access.ts +2 -62
- package/src/modules/staff/lib/time-tracking/listProjectAccess.ts +78 -0
- package/src/modules/staff/lib/time-tracking/portalRecipients.ts +173 -5
- package/src/modules/staff/lib/time-tracking/projectAssignment.ts +172 -0
- package/src/modules/staff/lib/time-tracking/settingKeys.ts +11 -0
- package/src/modules/staff/lib/time-tracking/settings.ts +46 -1
- package/src/modules/staff/lib/time-tracking/taskAssignmentRoute.ts +165 -0
- package/src/modules/staff/lib/time-tracking/workRecipients.ts +183 -0
- package/src/modules/staff/lib/time-tracking-ui/BoardFilterChips.tsx +36 -1
- package/src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx +30 -0
- package/src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx +9 -0
- package/src/modules/staff/lib/time-tracking-ui/ProjectFormSections.tsx +185 -6
- package/src/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.tsx +188 -0
- package/src/modules/staff/lib/time-tracking-ui/SupportRequestPanel.tsx +102 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskBoardScreen.tsx +2 -0
- package/src/modules/staff/lib/time-tracking-ui/TaskCommentThread.tsx +105 -22
- package/src/modules/staff/lib/time-tracking-ui/TaskDrawer.tsx +278 -43
- package/src/modules/staff/lib/time-tracking-ui/boardDirectory.ts +21 -0
- package/src/modules/staff/lib/time-tracking-ui/boardFilters.ts +16 -2
- package/src/modules/staff/lib/time-tracking-ui/kanbanBoardData.ts +4 -0
- package/src/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.ts +117 -0
- package/src/modules/staff/lib/time-tracking-ui/settingsTabs.ts +17 -0
- package/src/modules/staff/lib/time-tracking-ui/supportTicketData.ts +71 -0
- package/src/modules/staff/lib/time-tracking-ui/taskDrawerData.ts +15 -0
- package/src/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.ts +48 -1
- package/src/modules/staff/migrations/.snapshot-open-mercato.json +714 -0
- package/src/modules/staff/migrations/Migration20261009180543_staff.ts +50 -0
- package/src/modules/staff/notifications.ts +92 -0
- package/src/modules/staff/setup.ts +6 -2
- package/src/modules/staff/subscribers/support-portal-comment-created.ts +35 -0
- package/src/modules/staff/subscribers/support-portal-comment-deleted.ts +35 -0
- package/src/modules/staff/subscribers/support-portal-comment-updated.ts +35 -0
- package/src/modules/staff/subscribers/support-portal-status-column-updated.ts +36 -0
- package/src/modules/staff/subscribers/support-portal-task-status-changed.ts +34 -0
- package/src/modules/staff/subscribers/support-portal-task-updated.ts +34 -0
- package/src/modules/staff/subscribers/support-ticket-created-notification.ts +27 -0
- package/src/modules/staff/subscribers/support-ticket-customer-replied-notification.ts +27 -0
- package/src/modules/staff/subscribers/support-ticket-unnotified-clear.ts +29 -0
- package/src/modules/staff/subscribers/time-task-assignee-notification.ts +102 -0
- package/src/modules/staff/widgets/injection/portal-support-tickets/widget.client.tsx +151 -0
- package/src/modules/staff/widgets/injection/portal-support-tickets/widget.ts +16 -0
- package/src/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.tsx +1058 -0
- package/src/modules/staff/widgets/injection/time-tracking-settings-support/widget.ts +17 -0
- package/src/modules/staff/widgets/injection-table.ts +15 -0
- package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +4 -20
- package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +4 -20
- package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +4 -19
- package/src/modules/wms/lib/inventoryCsvExport.ts +18 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/staff/backend/staff/time-tracking/support/page.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterOverlay'\nimport { ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport { TaskDrawer } from '../../../../lib/time-tracking-ui/TaskDrawer'\nimport { readItems, readString, readTotal, type BoardApiRow } from '../../../../lib/time-tracking-ui/kanbanBoardData'\nimport {\n readSupportTicket,\n SUPPORT_ACTIVITY_EVENT,\n SUPPORT_PORTAL_STATUS_VARIANT,\n type SupportTicketView,\n} from '../../../../lib/time-tracking-ui/supportTicketData'\nimport { supportPortalStatusLabel } from '../../../../lib/time-tracking-ui/SupportRequestPanel'\nimport { searchCustomers } from '../../../../lib/time-tracking-ui/CustomerPicker'\n\nconst PAGE_SIZE = 25\nconst PROJECT_SEARCH_PAGE_SIZE = 50\nconst OPTIONS_URL = '/api/staff/timesheets/support-tickets/options'\nconst UNASSIGNED_VALUE = '__unassigned__'\nconst ASSIGNEE_CHANGED_EVENT = 'staff.timesheets.time_task.assignee_changed'\n\ntype SupportRow = {\n id: string\n ticket: SupportTicketView\n projectName: string | null\n assigneeName: string | null\n updatedAt: string | null\n}\n\ntype Option = { value: string; label: string }\n\ntype InboxOptionsResponse = {\n categories?: Array<{ value?: unknown; label?: unknown }>\n assignees?: Array<{ id?: unknown; displayName?: unknown }>\n}\n\nfunction toCategoryOptions(response: InboxOptionsResponse | null | undefined): Option[] {\n return (response?.categories ?? [])\n .map((category) =>\n typeof category.value === 'string'\n ? { value: category.value, label: typeof category.label === 'string' ? category.label : category.value }\n : null,\n )\n .filter((option): option is Option => option !== null)\n}\n\nfunction toAssigneeOptions(response: InboxOptionsResponse | null | undefined): Option[] {\n return (response?.assignees ?? [])\n .map((assignee) =>\n typeof assignee.id === 'string'\n ? { value: assignee.id, label: typeof assignee.displayName === 'string' ? assignee.displayName : assignee.id }\n : null,\n )\n .filter((option): option is Option => option !== null)\n}\n\nfunction readContext(row: BoardApiRow): Record<string, unknown> | null {\n const context = (row as Record<string, unknown>)._staff\n return context && typeof context === 'object' ? (context as Record<string, unknown>) : null\n}\n\nfunction toSupportRow(row: BoardApiRow): SupportRow | null {\n const id = readString(row, 'id')\n const ticket = readSupportTicket(row)\n if (!id || !ticket) return null\n const context = readContext(row)\n return {\n id,\n ticket,\n projectName: typeof context?.projectName === 'string' ? context.projectName : null,\n assigneeName: typeof context?.assigneeName === 'string' ? context.assigneeName : null,\n updatedAt: readString(row, 'updated_at', 'updatedAt'),\n }\n}\n\nasync function loadOptions(url: string, labelOf: (row: BoardApiRow) => string | null): Promise<Option[]> {\n const call = await apiCall<Record<string, unknown>>(url)\n if (!call.ok) return []\n return readItems(call.result)\n .map((row) => {\n const id = readString(row, 'id')\n const label = labelOf(row)\n return id && label ? { value: id, label } : null\n })\n .filter((option): option is Option => option !== null)\n}\n\nexport default function SupportTicketsPage() {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const scopeVersion = useOrganizationScopeVersion()\n\n const [rows, setRows] = React.useState<SupportRow[]>([])\n const [total, setTotal] = React.useState(0)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const [page, setPage] = React.useState(1)\n const [isLoading, setIsLoading] = React.useState(true)\n const [loadError, setLoadError] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<FilterValues>(() =>\n searchParams?.get('supportUnnotified') === 'true' ? { supportUnnotified: true } : {},\n )\n const [refreshKey, setRefreshKey] = React.useState(0)\n const [projectLabels, setProjectLabels] = React.useState<Record<string, string>>({})\n const [assigneeOptions, setAssigneeOptions] = React.useState<Option[]>([])\n const [categoryOptions, setCategoryOptions] = React.useState<Option[]>([])\n const [customerLabels, setCustomerLabels] = React.useState<Record<string, string>>({})\n const [optionsError, setOptionsError] = React.useState(false)\n\n const drawerTaskId = searchParams?.get('task') ?? null\n\n const refresh = React.useCallback(() => setRefreshKey((value) => value + 1), [])\n\n React.useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const options = await apiCall<InboxOptionsResponse>(OPTIONS_URL)\n if (cancelled) return\n if (!options.ok) {\n setOptionsError(true)\n return\n }\n setOptionsError(false)\n setCategoryOptions(toCategoryOptions(options.result))\n setAssigneeOptions(toAssigneeOptions(options.result))\n } catch {\n if (!cancelled) setOptionsError(true)\n }\n })()\n return () => {\n cancelled = true\n }\n }, [scopeVersion])\n\n React.useEffect(() => {\n let cancelled = false\n setIsLoading(true)\n const params = new URLSearchParams({\n source: 'portal',\n page: String(page),\n pageSize: String(PAGE_SIZE),\n sortField: 'updatedAt',\n sortDir: 'desc',\n })\n const portalStatus = typeof filterValues.portalStatus === 'string' ? filterValues.portalStatus : ''\n if (portalStatus) params.set('portalStatus', portalStatus)\n const category = typeof filterValues.supportCategory === 'string' ? filterValues.supportCategory : ''\n if (category) params.set('supportCategory', category)\n const projectId = typeof filterValues.timeProjectId === 'string' ? filterValues.timeProjectId : ''\n if (projectId) params.set('timeProjectId', projectId)\n const customerId = typeof filterValues.customerId === 'string' ? filterValues.customerId : ''\n if (customerId) params.set('customerId', customerId)\n const assignee = typeof filterValues.assignee === 'string' ? filterValues.assignee : ''\n if (assignee === UNASSIGNED_VALUE) params.set('unassigned', 'true')\n else if (assignee) params.set('assigneeStaffMemberId', assignee)\n if (filterValues.supportUnnotified === true || filterValues.supportUnnotified === 'true') {\n params.set('supportUnnotified', 'true')\n }\n if (search.trim()) params.set('supportReference', search.trim())\n void (async () => {\n try {\n const call = await apiCall<Record<string, unknown>>(`/api/staff/timesheets/tasks?${params.toString()}`)\n if (cancelled) return\n if (!call.ok) {\n setLoadError(true)\n return\n }\n setLoadError(false)\n setRows(readItems(call.result).map(toSupportRow).filter((row): row is SupportRow => row !== null))\n setTotal(readTotal(call.result, 0))\n setTotalIsCapped(call.result?.totalIsCapped === true)\n } catch {\n if (!cancelled) setLoadError(true)\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n })()\n return () => {\n cancelled = true\n }\n }, [filterValues, page, refreshKey, scopeVersion, search])\n\n useAppEvent(SUPPORT_ACTIVITY_EVENT, () => refresh(), [refresh])\n useAppEvent(ASSIGNEE_CHANGED_EVENT, () => refresh(), [refresh])\n\n const openTask = React.useCallback(\n (taskId: string) => {\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n params.set('task', taskId)\n router.push(`?${params.toString()}`, { scroll: false })\n },\n [router, searchParams],\n )\n\n const closeTask = React.useCallback(() => {\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n params.delete('task')\n const query = params.toString()\n router.push(query.length > 0 ? `?${query}` : '?', { scroll: false })\n }, [router, searchParams])\n\n const loadCustomerOptions = React.useCallback(\n async (query?: string) => {\n const customers = await searchCustomers(query ?? '')\n setCustomerLabels((current) => ({\n ...current,\n ...Object.fromEntries(customers.map((customer) => [customer.id, customer.name])),\n }))\n return customers.map((customer) => ({\n value: customer.id,\n label: customer.name,\n description:\n customer.kind === 'company'\n ? t('staff.support.tickets.customerKind.company', 'Company')\n : t('staff.support.tickets.customerKind.person', 'Person'),\n }))\n },\n [t],\n )\n\n const loadProjectOptions = React.useCallback(async (query?: string) => {\n const params = new URLSearchParams({ page: '1', pageSize: String(PROJECT_SEARCH_PAGE_SIZE) })\n const trimmed = (query ?? '').trim()\n if (trimmed) params.set('q', trimmed)\n const projects = await loadOptions(`/api/staff/timesheets/time-projects?${params.toString()}`, (row) =>\n readString(row, 'name'),\n )\n setProjectLabels((current) => ({\n ...current,\n ...Object.fromEntries(projects.map((project) => [project.value, project.label])),\n }))\n return projects\n }, [])\n\n const filters = React.useMemo<FilterDef[]>(\n () => [\n {\n id: 'portalStatus',\n label: t('staff.support.tickets.filters.portalStatus', 'Status the customer sees'),\n type: 'select',\n options: [\n { value: 'received', label: supportPortalStatusLabel(t, 'received') },\n { value: 'in_progress', label: supportPortalStatusLabel(t, 'in_progress') },\n { value: 'resolved', label: supportPortalStatusLabel(t, 'resolved') },\n ],\n },\n {\n id: 'supportCategory',\n label: t('staff.support.tickets.filters.category', 'Category'),\n type: 'select',\n options: categoryOptions,\n },\n {\n id: 'timeProjectId',\n label: t('staff.support.tickets.filters.project', 'Project'),\n type: 'combobox',\n placeholder: t('staff.support.tickets.filters.projectPlaceholder', 'Search projects'),\n loadOptions: loadProjectOptions,\n formatValue: (value: string) => projectLabels[value] ?? value,\n },\n {\n id: 'customerId',\n label: t('staff.support.tickets.filters.customer', 'Customer'),\n type: 'combobox',\n placeholder: t('staff.support.tickets.filters.customerPlaceholder', 'Search customers'),\n loadOptions: loadCustomerOptions,\n formatValue: (value: string) => customerLabels[value] ?? value,\n },\n {\n id: 'assignee',\n label: t('staff.support.tickets.filters.assignee', 'Assignee'),\n type: 'select',\n options: [{ value: UNASSIGNED_VALUE, label: t('staff.support.tickets.unassigned', 'Unassigned') }, ...assigneeOptions],\n },\n {\n id: 'supportUnnotified',\n label: t('staff.support.tickets.filters.nobodyNotified', 'Nobody notified'),\n type: 'checkbox',\n },\n ],\n [assigneeOptions, categoryOptions, customerLabels, loadCustomerOptions, loadProjectOptions, projectLabels, t],\n )\n\n const columns = React.useMemo<ColumnDef<SupportRow>[]>(\n () => [\n {\n accessorKey: 'reference',\n header: t('staff.support.tickets.columns.reference', 'Ticket'),\n cell: ({ row }) => (\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium text-foreground\">{row.original.ticket.supportReference}</span>\n {row.original.ticket.unnotifiedAt ? (\n <Badge variant=\"warning\" size=\"sm\" data-testid=\"support-ticket-unnotified\">\n {t('staff.support.tickets.nobodyNotified', 'Nobody notified')}\n </Badge>\n ) : null}\n </div>\n ),\n },\n {\n accessorKey: 'subject',\n header: t('staff.support.tickets.columns.subject', 'Subject'),\n cell: ({ row }) => row.original.ticket.requestSubject ?? '',\n },\n {\n accessorKey: 'customer',\n header: t('staff.support.tickets.columns.customer', 'Customer'),\n cell: ({ row }) => row.original.ticket.customerName ?? '',\n },\n {\n accessorKey: 'category',\n header: t('staff.support.tickets.columns.category', 'Category'),\n cell: ({ row }) => row.original.ticket.categoryLabel,\n },\n {\n accessorKey: 'portalStatus',\n header: t('staff.support.tickets.columns.portalStatus', 'Status'),\n cell: ({ row }) => (\n <StatusBadge variant={SUPPORT_PORTAL_STATUS_VARIANT[row.original.ticket.portalStatus]} dot>\n {supportPortalStatusLabel(t, row.original.ticket.portalStatus)}\n </StatusBadge>\n ),\n },\n {\n accessorKey: 'project',\n header: t('staff.support.tickets.columns.project', 'Project'),\n cell: ({ row }) => row.original.projectName ?? '',\n },\n {\n accessorKey: 'assignee',\n header: t('staff.support.tickets.columns.assignee', 'Assignee'),\n cell: ({ row }) =>\n row.original.assigneeName ?? (\n <span className=\"text-muted-foreground\">{t('staff.support.tickets.unassigned', 'Unassigned')}</span>\n ),\n },\n {\n accessorKey: 'updatedAt',\n header: t('staff.support.tickets.columns.lastActivity', 'Last activity'),\n cell: ({ row }) => (row.original.updatedAt ? formatDateTime(row.original.updatedAt) ?? '' : ''),\n },\n ],\n [t],\n )\n\n const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE))\n\n return (\n <Page>\n <PageBody>\n {loadError ? (\n <ErrorMessage label={t('staff.support.tickets.loadError', 'Could not load the support tickets.')} />\n ) : null}\n {optionsError ? (\n <ErrorMessage\n label={t('staff.support.tickets.optionsLoadError', 'Could not load the filter options.')}\n />\n ) : null}\n <DataTable<SupportRow>\n title={t('staff.support.tickets.title', 'Support Inbox')}\n titleHeadingLevel={1}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={(value) => {\n setSearch(value)\n setPage(1)\n }}\n searchPlaceholder={t('staff.support.tickets.searchPlaceholder', 'Search by ticket reference')}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={(values) => {\n setFilterValues(values)\n setPage(1)\n }}\n onFiltersClear={() => {\n setFilterValues({})\n setPage(1)\n }}\n emptyState={\n <div className=\"py-12 text-center text-sm text-muted-foreground\">\n {t('staff.support.tickets.empty', 'No support tickets match these filters.')}\n </div>\n }\n refreshButton={{\n label: t('staff.support.tickets.refresh', 'Refresh'),\n onRefresh: refresh,\n isRefreshing: isLoading,\n }}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n totalIsCapped,\n onPageChange: setPage,\n }}\n onRowClick={(row) => openTask(row.id)}\n />\n {drawerTaskId ? (\n <TaskDrawer\n taskId={drawerTaskId}\n open\n onOpenChange={(next) => {\n if (!next) closeTask()\n }}\n onChanged={refresh}\n />\n ) : null}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const metadata = {
|
|
2
|
+
requireAuth: true,
|
|
3
|
+
requireFeatures: ["staff.timesheets.tasks.view"],
|
|
4
|
+
pageTitle: "Support Inbox",
|
|
5
|
+
pageTitleKey: "staff.support.tickets.title",
|
|
6
|
+
pageGroup: "Time tracking",
|
|
7
|
+
pageGroupKey: "staff.time_tracking.nav.group",
|
|
8
|
+
pageOrder: 35,
|
|
9
|
+
icon: "life-buoy",
|
|
10
|
+
breadcrumb: [
|
|
11
|
+
{ label: "Time tracking", labelKey: "staff.time_tracking.nav.group", href: "/backend/staff/time-tracking" },
|
|
12
|
+
{ label: "Support Inbox", labelKey: "staff.support.tickets.title" }
|
|
13
|
+
]
|
|
14
|
+
};
|
|
15
|
+
export {
|
|
16
|
+
metadata
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=page.meta.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/staff/backend/staff/time-tracking/support/page.meta.ts"],
|
|
4
|
+
"sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['staff.timesheets.tasks.view'],\n pageTitle: 'Support Inbox',\n pageTitleKey: 'staff.support.tickets.title',\n pageGroup: 'Time tracking',\n pageGroupKey: 'staff.time_tracking.nav.group',\n pageOrder: 35,\n icon: 'life-buoy',\n breadcrumb: [\n { label: 'Time tracking', labelKey: 'staff.time_tracking.nav.group', href: '/backend/staff/time-tracking' },\n { label: 'Support Inbox', labelKey: 'staff.support.tickets.title' },\n ],\n}\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,6BAA6B;AAAA,EAC/C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY;AAAA,IACV,EAAE,OAAO,iBAAiB,UAAU,iCAAiC,MAAM,+BAA+B;AAAA,IAC1G,EAAE,OAAO,iBAAiB,UAAU,8BAA8B;AAAA,EACpE;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -3,6 +3,7 @@ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
|
3
3
|
import { seedStaffActivityTypes, seedStaffAddressTypes, seedStaffTeamExamples } from "./lib/seeds.js";
|
|
4
4
|
import { seedStaffTimeTrackingExamples } from "./lib/timeTrackingSeeds.js";
|
|
5
5
|
import { migrateProjectCodes } from "./lib/time-tracking/migrateProjectCodes.js";
|
|
6
|
+
import { resolveContainerProjectCodeGenerator, seedSupportDefaults } from "./lib/support/seedDefaults.js";
|
|
6
7
|
import { appendWidgetsToRoles } from "@open-mercato/core/modules/dashboards/lib/role-widgets";
|
|
7
8
|
import {
|
|
8
9
|
STAFF_TIME_REAPPLY_ROUNDING_JOB_TYPE,
|
|
@@ -183,6 +184,31 @@ const seedAddressTypesCommand = {
|
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
186
|
};
|
|
187
|
+
const seedSupportDefaultsCommand = {
|
|
188
|
+
command: "seed-support-defaults",
|
|
189
|
+
async run(rest) {
|
|
190
|
+
const args = parseArgs(rest);
|
|
191
|
+
const tenantId = String(args.tenantId ?? args.tenant ?? "");
|
|
192
|
+
const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? "");
|
|
193
|
+
if (!tenantId || !organizationId) {
|
|
194
|
+
console.error("Usage: mercato staff seed-support-defaults --tenant <tenantId> --org <organizationId>");
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const container = await createRequestContainer();
|
|
198
|
+
const scope = { tenantId, organizationId };
|
|
199
|
+
try {
|
|
200
|
+
const em = container.resolve("em");
|
|
201
|
+
const { translate } = await resolveTranslations();
|
|
202
|
+
await seedSupportDefaults(em.fork(), scope, { translate, generateCode: resolveContainerProjectCodeGenerator(container) });
|
|
203
|
+
console.log("\u{1F3AB} Support ticket defaults seeded for organization", organizationId);
|
|
204
|
+
} finally {
|
|
205
|
+
const disposable = container;
|
|
206
|
+
if (typeof disposable.dispose === "function") {
|
|
207
|
+
await disposable.dispose();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
186
212
|
const seedTimesheetsWidgetsCommand = {
|
|
187
213
|
command: "seed-timesheets-widgets",
|
|
188
214
|
async run(rest) {
|
|
@@ -294,6 +320,7 @@ var cli_default = [
|
|
|
294
320
|
seedExamplesCommand,
|
|
295
321
|
seedTimeTrackingExamplesCommand,
|
|
296
322
|
seedTimesheetsWidgetsCommand,
|
|
323
|
+
seedSupportDefaultsCommand,
|
|
297
324
|
migrateProjectCodesCommand,
|
|
298
325
|
recalculateCommand
|
|
299
326
|
];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/staff/cli.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { seedStaffActivityTypes, seedStaffAddressTypes, seedStaffTeamExamples, type StaffSeedScope } from './lib/seeds'\nimport { seedStaffTimeTrackingExamples } from './lib/timeTrackingSeeds'\nimport { migrateProjectCodes } from './lib/time-tracking/migrateProjectCodes'\nimport { appendWidgetsToRoles } from '@open-mercato/core/modules/dashboards/lib/role-widgets'\nimport type { ProgressService } from '@open-mercato/core/modules/progress/lib/progressService'\nimport {\n STAFF_TIME_REAPPLY_ROUNDING_JOB_TYPE,\n STAFF_TIME_REAPPLY_ROUNDING_QUEUE,\n getStaffQueue,\n type ReapplyRoundingScope,\n} from './lib/time-tracking/reapplyRounding'\nimport {\n listTimeTrackingRecalculations,\n resolveTimeTrackingRecalculations,\n} from './lib/time-tracking/recalculations'\n\nconst TIMESHEETS_DASHBOARD_WIDGET_IDS = [\n 'staff.timesheets.timeReporting',\n 'staff.timesheets.hoursByProject',\n]\n\nfunction parseArgs(rest: string[]) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 1) {\n const part = rest[i]\n if (!part) continue\n if (part.startsWith('--')) {\n const [rawKey, rawValue] = part.slice(2).split('=')\n if (rawValue !== undefined) args[rawKey] = rawValue\n else if (rest[i + 1] && !rest[i + 1]!.startsWith('--')) {\n args[rawKey] = rest[i + 1]!\n i += 1\n }\n }\n }\n return args\n}\n\nconst seedExamplesCommand: ModuleCli = {\n command: 'seed-examples',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-examples --tenant <tenantId> --org <organizationId>')\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n await em.transactional(async (tem) => {\n await seedStaffTeamExamples(tem, scope)\n })\n console.log('\uD83E\uDDE9 Staff team examples seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst seedTimeTrackingExamplesCommand: ModuleCli = {\n command: 'seed-time-tracking-examples',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-time-tracking-examples --tenant <tenantId> --org <organizationId>')\n console.error('Seeds demo projects, tasks, logged hours and reports for the time-tracking suite.')\n process.exit(1)\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n const seeded = await em.transactional(async (tem) => {\n await seedStaffTeamExamples(tem, scope)\n return seedStaffTimeTrackingExamples(tem, scope)\n })\n if (seeded) {\n console.log('\u23F1\uFE0F Time-tracking demo data seeded for organization', organizationId)\n // The seed writes entities directly rather than through the commands, so\n // nothing it creates reaches the query index. Listing still works \u2014 the\n // engine reads base tables \u2014 but `$ilike` filters are answered from the\n // token index, so search silently returns nothing for seeded rows.\n console.log(' Run `mercato query_index reindex` to make this data searchable.')\n } else {\n console.log('Time-tracking demo data already present; skipping')\n }\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst migrateProjectCodesCommand: ModuleCli = {\n command: 'migrate-project-codes',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n // `parseArgs` only records `--key value` and `--key=value` pairs, so a bare\n // trailing flag never lands in it \u2014 read the argv directly rather than\n // silently running a dry run when the caller asked to apply.\n const dryRun = !rest.includes('--apply') && args.apply !== 'true' && args.apply !== '1'\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff migrate-project-codes --tenant <tenantId> --org <organizationId> [--apply]')\n console.error('Shortens project codes to the 3-letter form and re-derives every task reference.')\n console.error('Runs as a dry run unless --apply is given.')\n process.exit(1)\n return\n }\n const container = await createRequestContainer()\n try {\n const em = container.resolve<EntityManager>('em')\n const result = await migrateProjectCodes(em, { tenantId, organizationId }, { dryRun })\n if (result.changes.length === 0) {\n console.log('Nothing to migrate \u2014 every project code is already short.')\n } else {\n for (const change of result.changes) {\n console.log(\n ` ${change.fromCode} \u2192 ${change.toCode} (${change.taskCount} task${change.taskCount === 1 ? '' : 's'}) ${change.projectName}`,\n )\n }\n }\n console.log(\n dryRun\n ? `\\n\uD83D\uDD0D Dry run \u2014 ${result.changes.length} project(s) would change, ${result.tasksRenumbered} task reference(s) rewritten, ${result.skipped} left alone. Re-run with --apply.`\n : `\\n\uD83D\uDD24 ${result.changes.length} project code(s) shortened, ${result.tasksRenumbered} task reference(s) rewritten, ${result.skipped} left alone.`,\n )\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') await disposable.dispose()\n }\n },\n}\n\nconst seedActivityTypesCommand: ModuleCli = {\n command: 'seed-activity-types',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-activity-types --tenant <tenantId> --org <organizationId>')\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n await em.transactional(async (tem) => {\n await seedStaffActivityTypes(tem, scope)\n })\n console.log('\uD83D\uDDC2\uFE0F Staff activity types seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst seedAddressTypesCommand: ModuleCli = {\n command: 'seed-address-types',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-address-types --tenant <tenantId> --org <organizationId>')\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n await em.transactional(async (tem) => {\n await seedStaffAddressTypes(tem, scope)\n })\n console.log('\uD83C\uDFE0 Staff address types seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst seedTimesheetsWidgetsCommand: ModuleCli = {\n command: 'seed-timesheets-widgets',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-timesheets-widgets --tenant <tenantId> --org <organizationId>')\n console.error('Backfills timesheets dashboard widgets (timeReporting, hoursByProject) to existing tenant roles.')\n process.exit(1)\n return\n }\n const container = await createRequestContainer()\n try {\n const em = container.resolve<EntityManager>('em')\n await em.transactional(async (tem) => {\n await appendWidgetsToRoles(tem, {\n tenantId,\n organizationId,\n roleNames: ['superadmin', 'admin', 'employee'],\n widgetIds: TIMESHEETS_DASHBOARD_WIDGET_IDS,\n })\n })\n console.log('\uD83D\uDCCA Timesheets dashboard widgets seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\n/**\n * The progress job's name is rendered in the operator's top bar, so it goes\n * through the locale files like every other user-facing string. A CLI has no\n * request to derive a locale from; `resolveTranslations` falls back to the\n * default one, and a failure to load them must not stop a backfill.\n */\nasync function resolveRecalculationJobName(): Promise<string> {\n try {\n const { translate } = await resolveTranslations()\n return translate('staff.time_tracking.recalculate.jobName', 'Recalculate time tracking')\n } catch {\n return 'Recalculate time tracking'\n }\n}\n\n/**\n * EP-51. `mercato staff timesheets:recalculate` \u2014 the operator entry point to the\n * recalculation registry.\n *\n * It enqueues; it does not do the work. That is deliberate and not merely\n * convenient: the restatement is the same `ProgressJob` on the same queue the\n * settings screen drives, so an operator running a backfill from a shell and a\n * manager pressing the button in the UI produce the same job, visible in the same\n * progress bar, cancellable the same way. A CLI that did the work in-process would\n * be a second implementation of a write over billing data.\n *\n * `--hook` may be repeated (`--hook a --hook b`) or comma-separated. Omitting it\n * runs the built-in rounding pass, which is what the settings route enqueues, so\n * the flagless invocation is the documented equivalent of pressing the button.\n */\nconst recalculateCommand: ModuleCli = {\n command: 'timesheets:recalculate',\n async run(rest) {\n const args = parseArgs(rest)\n if (rest.includes('--list')) {\n const registered = listTimeTrackingRecalculations()\n if (registered.length === 0) {\n console.log('No time-tracking recalculations are registered.')\n return\n }\n console.log('Registered time-tracking recalculations:')\n for (const entry of registered) console.log(` ${entry.id} (${entry.labelKey})`)\n return\n }\n\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n if (!tenantId) {\n console.error('Usage: mercato staff timesheets:recalculate --tenant <tenantId> [--org <organizationId>] [--hook <id>]')\n console.error(' mercato staff timesheets:recalculate --list')\n console.error('Enqueues the registered recalculation hooks as a progress job. Locked entries are never touched.')\n process.exit(1)\n return\n }\n\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n const hookIds = String(args.hook ?? '')\n .split(',')\n .map((value) => value.trim())\n .filter((value) => value.length > 0)\n\n let resolvedHookIds: string[]\n try {\n resolvedHookIds = resolveTimeTrackingRecalculations(hookIds.length ? hookIds : null).map((hook) => hook.id)\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err))\n console.error('Run `mercato staff timesheets:recalculate --list` to see the registered ids.')\n process.exit(1)\n return\n }\n\n const container = await createRequestContainer()\n try {\n const scope: ReapplyRoundingScope = {\n tenantId,\n organizationIds: organizationId ? [organizationId] : null,\n userId: null,\n }\n const jobName = await resolveRecalculationJobName()\n const progressService = container.resolve<ProgressService>('progressService')\n const progressJob = await progressService.createJob(\n {\n jobType: STAFF_TIME_REAPPLY_ROUNDING_JOB_TYPE,\n name: jobName,\n description: `Running ${resolvedHookIds.join(', ')}. Locked entries are not changed.`,\n totalCount: 0,\n cancellable: true,\n meta: { source: 'staff.timesheets.cli.recalculate', hookIds: resolvedHookIds },\n },\n { tenantId, organizationId: organizationId || null, userId: null },\n )\n const queue = getStaffQueue(STAFF_TIME_REAPPLY_ROUNDING_QUEUE)\n await queue.enqueue({ progressJobId: progressJob.id, scope, hookIds: resolvedHookIds })\n console.log('\u23F1\uFE0F Time-tracking recalculation enqueued:', resolvedHookIds.join(', '))\n console.log(' Progress job:', progressJob.id)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nexport default [\n seedActivityTypesCommand,\n seedAddressTypesCommand,\n seedExamplesCommand,\n seedTimeTrackingExamplesCommand,\n seedTimesheetsWidgetsCommand,\n migrateProjectCodesCommand,\n recalculateCommand,\n]\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { seedStaffActivityTypes, seedStaffAddressTypes, seedStaffTeamExamples, type StaffSeedScope } from './lib/seeds'\nimport { seedStaffTimeTrackingExamples } from './lib/timeTrackingSeeds'\nimport { migrateProjectCodes } from './lib/time-tracking/migrateProjectCodes'\nimport { resolveContainerProjectCodeGenerator, seedSupportDefaults } from './lib/support/seedDefaults'\nimport { appendWidgetsToRoles } from '@open-mercato/core/modules/dashboards/lib/role-widgets'\nimport type { ProgressService } from '@open-mercato/core/modules/progress/lib/progressService'\nimport {\n STAFF_TIME_REAPPLY_ROUNDING_JOB_TYPE,\n STAFF_TIME_REAPPLY_ROUNDING_QUEUE,\n getStaffQueue,\n type ReapplyRoundingScope,\n} from './lib/time-tracking/reapplyRounding'\nimport {\n listTimeTrackingRecalculations,\n resolveTimeTrackingRecalculations,\n} from './lib/time-tracking/recalculations'\n\nconst TIMESHEETS_DASHBOARD_WIDGET_IDS = [\n 'staff.timesheets.timeReporting',\n 'staff.timesheets.hoursByProject',\n]\n\nfunction parseArgs(rest: string[]) {\n const args: Record<string, string> = {}\n for (let i = 0; i < rest.length; i += 1) {\n const part = rest[i]\n if (!part) continue\n if (part.startsWith('--')) {\n const [rawKey, rawValue] = part.slice(2).split('=')\n if (rawValue !== undefined) args[rawKey] = rawValue\n else if (rest[i + 1] && !rest[i + 1]!.startsWith('--')) {\n args[rawKey] = rest[i + 1]!\n i += 1\n }\n }\n }\n return args\n}\n\nconst seedExamplesCommand: ModuleCli = {\n command: 'seed-examples',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-examples --tenant <tenantId> --org <organizationId>')\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n await em.transactional(async (tem) => {\n await seedStaffTeamExamples(tem, scope)\n })\n console.log('\uD83E\uDDE9 Staff team examples seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst seedTimeTrackingExamplesCommand: ModuleCli = {\n command: 'seed-time-tracking-examples',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-time-tracking-examples --tenant <tenantId> --org <organizationId>')\n console.error('Seeds demo projects, tasks, logged hours and reports for the time-tracking suite.')\n process.exit(1)\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n const seeded = await em.transactional(async (tem) => {\n await seedStaffTeamExamples(tem, scope)\n return seedStaffTimeTrackingExamples(tem, scope)\n })\n if (seeded) {\n console.log('\u23F1\uFE0F Time-tracking demo data seeded for organization', organizationId)\n // The seed writes entities directly rather than through the commands, so\n // nothing it creates reaches the query index. Listing still works \u2014 the\n // engine reads base tables \u2014 but `$ilike` filters are answered from the\n // token index, so search silently returns nothing for seeded rows.\n console.log(' Run `mercato query_index reindex` to make this data searchable.')\n } else {\n console.log('Time-tracking demo data already present; skipping')\n }\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst migrateProjectCodesCommand: ModuleCli = {\n command: 'migrate-project-codes',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n // `parseArgs` only records `--key value` and `--key=value` pairs, so a bare\n // trailing flag never lands in it \u2014 read the argv directly rather than\n // silently running a dry run when the caller asked to apply.\n const dryRun = !rest.includes('--apply') && args.apply !== 'true' && args.apply !== '1'\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff migrate-project-codes --tenant <tenantId> --org <organizationId> [--apply]')\n console.error('Shortens project codes to the 3-letter form and re-derives every task reference.')\n console.error('Runs as a dry run unless --apply is given.')\n process.exit(1)\n return\n }\n const container = await createRequestContainer()\n try {\n const em = container.resolve<EntityManager>('em')\n const result = await migrateProjectCodes(em, { tenantId, organizationId }, { dryRun })\n if (result.changes.length === 0) {\n console.log('Nothing to migrate \u2014 every project code is already short.')\n } else {\n for (const change of result.changes) {\n console.log(\n ` ${change.fromCode} \u2192 ${change.toCode} (${change.taskCount} task${change.taskCount === 1 ? '' : 's'}) ${change.projectName}`,\n )\n }\n }\n console.log(\n dryRun\n ? `\\n\uD83D\uDD0D Dry run \u2014 ${result.changes.length} project(s) would change, ${result.tasksRenumbered} task reference(s) rewritten, ${result.skipped} left alone. Re-run with --apply.`\n : `\\n\uD83D\uDD24 ${result.changes.length} project code(s) shortened, ${result.tasksRenumbered} task reference(s) rewritten, ${result.skipped} left alone.`,\n )\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') await disposable.dispose()\n }\n },\n}\n\nconst seedActivityTypesCommand: ModuleCli = {\n command: 'seed-activity-types',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-activity-types --tenant <tenantId> --org <organizationId>')\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n await em.transactional(async (tem) => {\n await seedStaffActivityTypes(tem, scope)\n })\n console.log('\uD83D\uDDC2\uFE0F Staff activity types seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst seedAddressTypesCommand: ModuleCli = {\n command: 'seed-address-types',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-address-types --tenant <tenantId> --org <organizationId>')\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n await em.transactional(async (tem) => {\n await seedStaffAddressTypes(tem, scope)\n })\n console.log('\uD83C\uDFE0 Staff address types seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst seedSupportDefaultsCommand: ModuleCli = {\n command: 'seed-support-defaults',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-support-defaults --tenant <tenantId> --org <organizationId>')\n return\n }\n const container = await createRequestContainer()\n const scope: StaffSeedScope = { tenantId, organizationId }\n try {\n const em = container.resolve<EntityManager>('em')\n const { translate } = await resolveTranslations()\n await seedSupportDefaults(em.fork(), scope, { translate, generateCode: resolveContainerProjectCodeGenerator(container) })\n console.log('\uD83C\uDFAB Support ticket defaults seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nconst seedTimesheetsWidgetsCommand: ModuleCli = {\n command: 'seed-timesheets-widgets',\n async run(rest) {\n const args = parseArgs(rest)\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n if (!tenantId || !organizationId) {\n console.error('Usage: mercato staff seed-timesheets-widgets --tenant <tenantId> --org <organizationId>')\n console.error('Backfills timesheets dashboard widgets (timeReporting, hoursByProject) to existing tenant roles.')\n process.exit(1)\n return\n }\n const container = await createRequestContainer()\n try {\n const em = container.resolve<EntityManager>('em')\n await em.transactional(async (tem) => {\n await appendWidgetsToRoles(tem, {\n tenantId,\n organizationId,\n roleNames: ['superadmin', 'admin', 'employee'],\n widgetIds: TIMESHEETS_DASHBOARD_WIDGET_IDS,\n })\n })\n console.log('\uD83D\uDCCA Timesheets dashboard widgets seeded for organization', organizationId)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\n/**\n * The progress job's name is rendered in the operator's top bar, so it goes\n * through the locale files like every other user-facing string. A CLI has no\n * request to derive a locale from; `resolveTranslations` falls back to the\n * default one, and a failure to load them must not stop a backfill.\n */\nasync function resolveRecalculationJobName(): Promise<string> {\n try {\n const { translate } = await resolveTranslations()\n return translate('staff.time_tracking.recalculate.jobName', 'Recalculate time tracking')\n } catch {\n return 'Recalculate time tracking'\n }\n}\n\n/**\n * EP-51. `mercato staff timesheets:recalculate` \u2014 the operator entry point to the\n * recalculation registry.\n *\n * It enqueues; it does not do the work. That is deliberate and not merely\n * convenient: the restatement is the same `ProgressJob` on the same queue the\n * settings screen drives, so an operator running a backfill from a shell and a\n * manager pressing the button in the UI produce the same job, visible in the same\n * progress bar, cancellable the same way. A CLI that did the work in-process would\n * be a second implementation of a write over billing data.\n *\n * `--hook` may be repeated (`--hook a --hook b`) or comma-separated. Omitting it\n * runs the built-in rounding pass, which is what the settings route enqueues, so\n * the flagless invocation is the documented equivalent of pressing the button.\n */\nconst recalculateCommand: ModuleCli = {\n command: 'timesheets:recalculate',\n async run(rest) {\n const args = parseArgs(rest)\n if (rest.includes('--list')) {\n const registered = listTimeTrackingRecalculations()\n if (registered.length === 0) {\n console.log('No time-tracking recalculations are registered.')\n return\n }\n console.log('Registered time-tracking recalculations:')\n for (const entry of registered) console.log(` ${entry.id} (${entry.labelKey})`)\n return\n }\n\n const tenantId = String(args.tenantId ?? args.tenant ?? '')\n if (!tenantId) {\n console.error('Usage: mercato staff timesheets:recalculate --tenant <tenantId> [--org <organizationId>] [--hook <id>]')\n console.error(' mercato staff timesheets:recalculate --list')\n console.error('Enqueues the registered recalculation hooks as a progress job. Locked entries are never touched.')\n process.exit(1)\n return\n }\n\n const organizationId = String(args.organizationId ?? args.org ?? args.orgId ?? '')\n const hookIds = String(args.hook ?? '')\n .split(',')\n .map((value) => value.trim())\n .filter((value) => value.length > 0)\n\n let resolvedHookIds: string[]\n try {\n resolvedHookIds = resolveTimeTrackingRecalculations(hookIds.length ? hookIds : null).map((hook) => hook.id)\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err))\n console.error('Run `mercato staff timesheets:recalculate --list` to see the registered ids.')\n process.exit(1)\n return\n }\n\n const container = await createRequestContainer()\n try {\n const scope: ReapplyRoundingScope = {\n tenantId,\n organizationIds: organizationId ? [organizationId] : null,\n userId: null,\n }\n const jobName = await resolveRecalculationJobName()\n const progressService = container.resolve<ProgressService>('progressService')\n const progressJob = await progressService.createJob(\n {\n jobType: STAFF_TIME_REAPPLY_ROUNDING_JOB_TYPE,\n name: jobName,\n description: `Running ${resolvedHookIds.join(', ')}. Locked entries are not changed.`,\n totalCount: 0,\n cancellable: true,\n meta: { source: 'staff.timesheets.cli.recalculate', hookIds: resolvedHookIds },\n },\n { tenantId, organizationId: organizationId || null, userId: null },\n )\n const queue = getStaffQueue(STAFF_TIME_REAPPLY_ROUNDING_QUEUE)\n await queue.enqueue({ progressJobId: progressJob.id, scope, hookIds: resolvedHookIds })\n console.log('\u23F1\uFE0F Time-tracking recalculation enqueued:', resolvedHookIds.join(', '))\n console.log(' Progress job:', progressJob.id)\n } finally {\n const disposable = container as unknown as { dispose?: () => Promise<void> }\n if (typeof disposable.dispose === 'function') {\n await disposable.dispose()\n }\n }\n },\n}\n\nexport default [\n seedActivityTypesCommand,\n seedAddressTypesCommand,\n seedExamplesCommand,\n seedTimeTrackingExamplesCommand,\n seedTimesheetsWidgetsCommand,\n seedSupportDefaultsCommand,\n migrateProjectCodesCommand,\n recalculateCommand,\n]\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -14,4 +14,7 @@ import "./timesheets-tasks.js";
|
|
|
14
14
|
import "./timesheets-tags.js";
|
|
15
15
|
import "./timesheets-task-comments.js";
|
|
16
16
|
import "./timesheets-reports.js";
|
|
17
|
+
import "./support-routing-rules.js";
|
|
18
|
+
import "./timesheets-task-assignment.js";
|
|
19
|
+
import "./support-tickets.js";
|
|
17
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/index.ts"],
|
|
4
|
-
"sourcesContent": ["import './tag-assignments'\nimport './team-roles'\nimport './team-members'\nimport './teams'\nimport './comments'\nimport './activities'\nimport './addresses'\nimport './job-histories'\nimport './leave-requests'\nimport './timesheets-entries'\nimport './timesheets-projects'\nimport './timesheets-task-statuses'\nimport './timesheets-tasks'\nimport './timesheets-tags'\nimport './timesheets-task-comments'\nimport './timesheets-reports'\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;",
|
|
4
|
+
"sourcesContent": ["import './tag-assignments'\nimport './team-roles'\nimport './team-members'\nimport './teams'\nimport './comments'\nimport './activities'\nimport './addresses'\nimport './job-histories'\nimport './leave-requests'\nimport './timesheets-entries'\nimport './timesheets-projects'\nimport './timesheets-task-statuses'\nimport './timesheets-tasks'\nimport './timesheets-tags'\nimport './timesheets-task-comments'\nimport './timesheets-reports'\nimport './support-routing-rules'\nimport './timesheets-task-assignment'\nimport './support-tickets'\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
2
2
|
import { ensureOrganizationScope, ensureTenantScope } from "@open-mercato/shared/lib/commands/scope";
|
|
3
3
|
import { extractUndoPayload } from "@open-mercato/shared/lib/commands/undo";
|
|
4
|
-
import {
|
|
4
|
+
import { LockMode } from "@mikro-orm/core";
|
|
5
|
+
import { StaffTeamMember, StaffTimeProject } from "../data/entities.js";
|
|
5
6
|
function commandActorScope(ctx) {
|
|
6
7
|
const isPrivilegedActor = ctx.auth?.isSuperAdmin === true || ctx.systemActor === true;
|
|
7
8
|
const tenantId = isPrivilegedActor ? null : ctx.auth?.tenantId ?? ctx.organizationScope?.tenantId ?? null;
|
|
@@ -80,6 +81,13 @@ async function requireTeamMember(em, memberId, scope, message = "Team member not
|
|
|
80
81
|
if (!member) throw new CrudHttpError(404, { error: message });
|
|
81
82
|
return member;
|
|
82
83
|
}
|
|
84
|
+
async function lockLiveProjectForWrite(em, timeProjectId, scope) {
|
|
85
|
+
return em.findOne(
|
|
86
|
+
StaffTimeProject,
|
|
87
|
+
applyScopeToWhere({ id: timeProjectId, deletedAt: null }, scope),
|
|
88
|
+
{ lockMode: LockMode.PESSIMISTIC_READ }
|
|
89
|
+
);
|
|
90
|
+
}
|
|
83
91
|
export {
|
|
84
92
|
applyScopeToWhere,
|
|
85
93
|
commandActorScope,
|
|
@@ -88,6 +96,7 @@ export {
|
|
|
88
96
|
ensureTenantScope,
|
|
89
97
|
explicitStaffCommandScope,
|
|
90
98
|
extractUndoPayload,
|
|
99
|
+
lockLiveProjectForWrite,
|
|
91
100
|
requireTeamMember,
|
|
92
101
|
scopeForDecryption,
|
|
93
102
|
scopedStaffSnapshotWhere,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/shared.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { ensureOrganizationScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { StaffTeamMember } from '../data/entities'\n\nexport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload }\n\nexport type StaffCommandScope = {\n tenantId: string | null\n organizationId: string | null\n requireTenant: boolean\n requireOrganization: boolean\n}\n\nexport function commandActorScope(ctx: CommandRuntimeContext): StaffCommandScope {\n const isPrivilegedActor = ctx.auth?.isSuperAdmin === true || ctx.systemActor === true\n const tenantId = isPrivilegedActor ? null : (ctx.auth?.tenantId ?? ctx.organizationScope?.tenantId ?? null)\n const organizationId = isPrivilegedActor ? null : (ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null)\n const organizationUnrestricted =\n isPrivilegedActor || (organizationId === null && tenantId !== null && ctx.organizationScope?.allowedIds === null)\n return {\n tenantId,\n organizationId: organizationUnrestricted ? null : organizationId,\n requireTenant: !isPrivilegedActor,\n requireOrganization: !organizationUnrestricted,\n }\n}\n\nexport function explicitStaffCommandScope(tenantId: string | null, organizationId: string | null): StaffCommandScope {\n return {\n tenantId,\n organizationId,\n requireTenant: true,\n requireOrganization: true,\n }\n}\n\nexport function commandInputScope(ctx: CommandRuntimeContext, tenantId: string, organizationId: string): StaffCommandScope {\n if (ctx.auth?.isSuperAdmin === true || ctx.systemActor === true) {\n return explicitStaffCommandScope(tenantId, organizationId)\n }\n\n ensureTenantScope(ctx, tenantId)\n ensureOrganizationScope(ctx, organizationId)\n\n const actorTenantId = ctx.auth?.tenantId ?? ctx.organizationScope?.tenantId ?? null\n if (!actorTenantId || actorTenantId !== tenantId) {\n throw new CrudHttpError(403, { error: 'Forbidden' })\n }\n\n if (!ctx.organizationScope) {\n const currentOrganizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!currentOrganizationId || currentOrganizationId !== organizationId) {\n throw new CrudHttpError(403, { error: 'Forbidden' })\n }\n }\n\n return explicitStaffCommandScope(tenantId, organizationId)\n}\n\nexport function applyScopeToWhere<TEntity extends object>(\n where: FilterQuery<TEntity>,\n scope: StaffCommandScope,\n): FilterQuery<TEntity> {\n const scoped = { ...(where as Record<string, unknown>) }\n if (scope.requireTenant || scope.tenantId !== null) scoped.tenantId = scope.tenantId\n if (scope.requireOrganization || scope.organizationId !== null) scoped.organizationId = scope.organizationId\n return scoped as FilterQuery<TEntity>\n}\n\nexport function scopeForDecryption(scope: StaffCommandScope): { tenantId: string | null; organizationId: string | null } {\n return { tenantId: scope.tenantId, organizationId: scope.organizationId }\n}\n\nexport type StaffSnapshotScope = {\n tenantId?: string | null\n organizationId?: string | null\n}\n\ntype StaffSnapshotScopeSource = {\n tenantId?: string | null\n organizationId?: string | null\n}\n\nconst NULL_DECRYPTION_SCOPE = { tenantId: null, organizationId: null } as const\n\nexport function staffSnapshotScopeFromContext(ctx: CommandRuntimeContext): StaffSnapshotScope | null {\n const tenantId = ctx.auth?.tenantId ?? null\n if (!tenantId) return null\n return { tenantId }\n}\n\nexport function staffSnapshotScopeFromSnapshot(source: StaffSnapshotScopeSource | null | undefined): StaffSnapshotScope | null {\n if (!source?.tenantId || !source.organizationId) return null\n return { tenantId: source.tenantId, organizationId: source.organizationId }\n}\n\nexport function scopedStaffSnapshotWhere(id: string, scope?: StaffSnapshotScope | null) {\n const where: { id: string; tenantId?: string; organizationId?: string } = { id }\n if (scope?.tenantId) where.tenantId = scope.tenantId\n if (scope?.organizationId) where.organizationId = scope.organizationId\n return where\n}\n\nexport function staffSnapshotDecryptionScope(scope?: StaffSnapshotScope | null) {\n if (!scope) return NULL_DECRYPTION_SCOPE\n return {\n tenantId: scope.tenantId ?? null,\n organizationId: scope.organizationId ?? null,\n }\n}\n\nexport async function requireTeamMember(\n em: EntityManager,\n memberId: string,\n scope: StaffCommandScope,\n message = 'Team member not found',\n): Promise<StaffTeamMember> {\n const member = await em.findOne(\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: memberId, deletedAt: null }, scope),\n )\n if (!member) throw new CrudHttpError(404, { error: message })\n return member\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,yBAAyB,yBAAyB;AAC3D,SAAS,0BAA0B;AAEnC,SAAS,
|
|
4
|
+
"sourcesContent": ["import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { ensureOrganizationScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { LockMode } from '@mikro-orm/core'\nimport { StaffTeamMember, StaffTimeProject } from '../data/entities'\n\nexport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload }\n\nexport type StaffCommandScope = {\n tenantId: string | null\n organizationId: string | null\n requireTenant: boolean\n requireOrganization: boolean\n}\n\nexport function commandActorScope(ctx: CommandRuntimeContext): StaffCommandScope {\n const isPrivilegedActor = ctx.auth?.isSuperAdmin === true || ctx.systemActor === true\n const tenantId = isPrivilegedActor ? null : (ctx.auth?.tenantId ?? ctx.organizationScope?.tenantId ?? null)\n const organizationId = isPrivilegedActor ? null : (ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null)\n const organizationUnrestricted =\n isPrivilegedActor || (organizationId === null && tenantId !== null && ctx.organizationScope?.allowedIds === null)\n return {\n tenantId,\n organizationId: organizationUnrestricted ? null : organizationId,\n requireTenant: !isPrivilegedActor,\n requireOrganization: !organizationUnrestricted,\n }\n}\n\nexport function explicitStaffCommandScope(tenantId: string | null, organizationId: string | null): StaffCommandScope {\n return {\n tenantId,\n organizationId,\n requireTenant: true,\n requireOrganization: true,\n }\n}\n\nexport function commandInputScope(ctx: CommandRuntimeContext, tenantId: string, organizationId: string): StaffCommandScope {\n if (ctx.auth?.isSuperAdmin === true || ctx.systemActor === true) {\n return explicitStaffCommandScope(tenantId, organizationId)\n }\n\n ensureTenantScope(ctx, tenantId)\n ensureOrganizationScope(ctx, organizationId)\n\n const actorTenantId = ctx.auth?.tenantId ?? ctx.organizationScope?.tenantId ?? null\n if (!actorTenantId || actorTenantId !== tenantId) {\n throw new CrudHttpError(403, { error: 'Forbidden' })\n }\n\n if (!ctx.organizationScope) {\n const currentOrganizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!currentOrganizationId || currentOrganizationId !== organizationId) {\n throw new CrudHttpError(403, { error: 'Forbidden' })\n }\n }\n\n return explicitStaffCommandScope(tenantId, organizationId)\n}\n\nexport function applyScopeToWhere<TEntity extends object>(\n where: FilterQuery<TEntity>,\n scope: StaffCommandScope,\n): FilterQuery<TEntity> {\n const scoped = { ...(where as Record<string, unknown>) }\n if (scope.requireTenant || scope.tenantId !== null) scoped.tenantId = scope.tenantId\n if (scope.requireOrganization || scope.organizationId !== null) scoped.organizationId = scope.organizationId\n return scoped as FilterQuery<TEntity>\n}\n\nexport function scopeForDecryption(scope: StaffCommandScope): { tenantId: string | null; organizationId: string | null } {\n return { tenantId: scope.tenantId, organizationId: scope.organizationId }\n}\n\nexport type StaffSnapshotScope = {\n tenantId?: string | null\n organizationId?: string | null\n}\n\ntype StaffSnapshotScopeSource = {\n tenantId?: string | null\n organizationId?: string | null\n}\n\nconst NULL_DECRYPTION_SCOPE = { tenantId: null, organizationId: null } as const\n\nexport function staffSnapshotScopeFromContext(ctx: CommandRuntimeContext): StaffSnapshotScope | null {\n const tenantId = ctx.auth?.tenantId ?? null\n if (!tenantId) return null\n return { tenantId }\n}\n\nexport function staffSnapshotScopeFromSnapshot(source: StaffSnapshotScopeSource | null | undefined): StaffSnapshotScope | null {\n if (!source?.tenantId || !source.organizationId) return null\n return { tenantId: source.tenantId, organizationId: source.organizationId }\n}\n\nexport function scopedStaffSnapshotWhere(id: string, scope?: StaffSnapshotScope | null) {\n const where: { id: string; tenantId?: string; organizationId?: string } = { id }\n if (scope?.tenantId) where.tenantId = scope.tenantId\n if (scope?.organizationId) where.organizationId = scope.organizationId\n return where\n}\n\nexport function staffSnapshotDecryptionScope(scope?: StaffSnapshotScope | null) {\n if (!scope) return NULL_DECRYPTION_SCOPE\n return {\n tenantId: scope.tenantId ?? null,\n organizationId: scope.organizationId ?? null,\n }\n}\n\nexport async function requireTeamMember(\n em: EntityManager,\n memberId: string,\n scope: StaffCommandScope,\n message = 'Team member not found',\n): Promise<StaffTeamMember> {\n const member = await em.findOne(\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: memberId, deletedAt: null }, scope),\n )\n if (!member) throw new CrudHttpError(404, { error: message })\n return member\n}\n\n/**\n * Shared row lock every writer takes before it makes a task live on a project (create,\n * portal intake, restore) or points a support routing rule at one. The fallback-project\n * undo holds the exclusive lock across its checks and the project's soft-delete, so a\n * writer either lands first and the undo sees it, or waits and then sees the project\n * gone. Lock order is always project before rule. MUST run inside the writer's\n * transaction; `null` means the project is not live once the lock is granted.\n */\nexport async function lockLiveProjectForWrite(\n em: EntityManager,\n timeProjectId: string,\n scope: StaffCommandScope,\n): Promise<StaffTimeProject | null> {\n return em.findOne(\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: timeProjectId, deletedAt: null }, scope),\n { lockMode: LockMode.PESSIMISTIC_READ },\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|