@open-mercato/core 0.10.1-develop.7717.1.2befe9c634 → 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,150 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'
|
|
3
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
4
|
+
import { resolveCrudRecordId, parseScopedCommandInput } from '@open-mercato/shared/lib/api/scoped'
|
|
5
|
+
import { StaffSupportRoutingRule } from '../../../data/entities'
|
|
6
|
+
import {
|
|
7
|
+
staffSupportRoutingRuleCreateSchema,
|
|
8
|
+
staffSupportRoutingRuleUpdateSchema,
|
|
9
|
+
} from '../../../data/validators'
|
|
10
|
+
import { staffSupportRoutingRuleCommandIds } from '../../../commands/support-routing-rules'
|
|
11
|
+
import { createStaffCrudOpenApi, createPagedListResponseSchema, defaultOkResponseSchema } from '../../openapi'
|
|
12
|
+
|
|
13
|
+
const SETTINGS_FEATURE = 'staff.timesheets.settings.manage'
|
|
14
|
+
|
|
15
|
+
const F = {
|
|
16
|
+
id: 'id',
|
|
17
|
+
tenant_id: 'tenant_id',
|
|
18
|
+
organization_id: 'organization_id',
|
|
19
|
+
category_value: 'category_value',
|
|
20
|
+
time_project_id: 'time_project_id',
|
|
21
|
+
is_active: 'is_active',
|
|
22
|
+
created_at: 'created_at',
|
|
23
|
+
updated_at: 'updated_at',
|
|
24
|
+
} as const
|
|
25
|
+
|
|
26
|
+
const routeMetadata = {
|
|
27
|
+
GET: { requireAuth: true, requireFeatures: [SETTINGS_FEATURE] },
|
|
28
|
+
POST: { requireAuth: true, requireFeatures: [SETTINGS_FEATURE] },
|
|
29
|
+
PUT: { requireAuth: true, requireFeatures: [SETTINGS_FEATURE] },
|
|
30
|
+
DELETE: { requireAuth: true, requireFeatures: [SETTINGS_FEATURE] },
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const metadata = routeMetadata
|
|
34
|
+
|
|
35
|
+
const rawBodySchema = z.object({}).passthrough()
|
|
36
|
+
|
|
37
|
+
const listSchema = z
|
|
38
|
+
.object({
|
|
39
|
+
page: z.coerce.number().min(1).default(1),
|
|
40
|
+
pageSize: z.coerce.number().min(1).max(100).default(100),
|
|
41
|
+
ids: z.string().optional(),
|
|
42
|
+
sortField: z.string().optional(),
|
|
43
|
+
sortDir: z.enum(['asc', 'desc']).optional(),
|
|
44
|
+
})
|
|
45
|
+
.passthrough()
|
|
46
|
+
|
|
47
|
+
const crud = makeCrudRoute({
|
|
48
|
+
metadata: routeMetadata,
|
|
49
|
+
orm: {
|
|
50
|
+
entity: StaffSupportRoutingRule,
|
|
51
|
+
idField: 'id',
|
|
52
|
+
orgField: 'organizationId',
|
|
53
|
+
tenantField: 'tenantId',
|
|
54
|
+
softDeleteField: 'deletedAt',
|
|
55
|
+
},
|
|
56
|
+
indexer: { entityType: 'staff:staff_support_routing_rule' },
|
|
57
|
+
list: {
|
|
58
|
+
schema: listSchema,
|
|
59
|
+
entityId: 'staff:staff_support_routing_rule',
|
|
60
|
+
fields: [
|
|
61
|
+
F.id,
|
|
62
|
+
F.organization_id,
|
|
63
|
+
F.tenant_id,
|
|
64
|
+
F.category_value,
|
|
65
|
+
F.time_project_id,
|
|
66
|
+
F.is_active,
|
|
67
|
+
F.created_at,
|
|
68
|
+
F.updated_at,
|
|
69
|
+
],
|
|
70
|
+
defaultSort: { field: F.created_at, dir: 'asc' },
|
|
71
|
+
sortFieldMap: { createdAt: F.created_at, updatedAt: F.updated_at },
|
|
72
|
+
buildFilters: async (query) => {
|
|
73
|
+
const filters: Record<string, unknown> = {}
|
|
74
|
+
if (typeof query.ids === 'string' && query.ids.trim().length > 0) {
|
|
75
|
+
const ids = query.ids.split(',').map((value) => value.trim()).filter((value) => value.length > 0)
|
|
76
|
+
if (ids.length > 0) filters[F.id] = { $in: ids }
|
|
77
|
+
}
|
|
78
|
+
return filters
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
actions: {
|
|
82
|
+
create: {
|
|
83
|
+
commandId: staffSupportRoutingRuleCommandIds.create,
|
|
84
|
+
schema: rawBodySchema,
|
|
85
|
+
mapInput: async ({ raw, ctx }) => {
|
|
86
|
+
const { translate } = await resolveTranslations()
|
|
87
|
+
return parseScopedCommandInput(staffSupportRoutingRuleCreateSchema, raw ?? {}, ctx, translate)
|
|
88
|
+
},
|
|
89
|
+
response: ({ result }) => ({ id: result?.ruleId ?? null }),
|
|
90
|
+
status: 201,
|
|
91
|
+
},
|
|
92
|
+
update: {
|
|
93
|
+
commandId: staffSupportRoutingRuleCommandIds.update,
|
|
94
|
+
schema: rawBodySchema,
|
|
95
|
+
mapInput: async ({ raw, ctx }) => {
|
|
96
|
+
const { translate } = await resolveTranslations()
|
|
97
|
+
return parseScopedCommandInput(staffSupportRoutingRuleUpdateSchema, raw ?? {}, ctx, translate)
|
|
98
|
+
},
|
|
99
|
+
response: () => ({ ok: true }),
|
|
100
|
+
},
|
|
101
|
+
delete: {
|
|
102
|
+
commandId: staffSupportRoutingRuleCommandIds.delete,
|
|
103
|
+
schema: rawBodySchema,
|
|
104
|
+
mapInput: async ({ parsed, ctx }) => {
|
|
105
|
+
const { translate } = await resolveTranslations()
|
|
106
|
+
return { id: resolveCrudRecordId(parsed, ctx, translate) }
|
|
107
|
+
},
|
|
108
|
+
response: () => ({ ok: true }),
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
export const GET = crud.GET
|
|
114
|
+
export const POST = crud.POST
|
|
115
|
+
export const PUT = crud.PUT
|
|
116
|
+
export const DELETE = crud.DELETE
|
|
117
|
+
|
|
118
|
+
export const supportRoutingRuleListItemSchema = z.object({
|
|
119
|
+
id: z.string().uuid().nullable().optional(),
|
|
120
|
+
organization_id: z.string().uuid().nullable().optional(),
|
|
121
|
+
tenant_id: z.string().uuid().nullable().optional(),
|
|
122
|
+
category_value: z.string().nullable().optional(),
|
|
123
|
+
time_project_id: z.string().uuid().nullable().optional(),
|
|
124
|
+
is_active: z.boolean().nullable().optional(),
|
|
125
|
+
created_at: z.string().nullable().optional(),
|
|
126
|
+
updated_at: z.string().nullable().optional(),
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
export const openApi = createStaffCrudOpenApi({
|
|
130
|
+
resourceName: 'Support routing rule',
|
|
131
|
+
pluralName: 'Support routing rules',
|
|
132
|
+
querySchema: listSchema,
|
|
133
|
+
listResponseSchema: createPagedListResponseSchema(supportRoutingRuleListItemSchema),
|
|
134
|
+
create: {
|
|
135
|
+
schema: staffSupportRoutingRuleCreateSchema.omit({ tenantId: true, organizationId: true }),
|
|
136
|
+
responseSchema: z.object({ id: z.string().uuid().nullable() }),
|
|
137
|
+
description:
|
|
138
|
+
'Creates a routing rule. A null `categoryValue` is the organization fallback rule (exactly one; it can be repointed but not deleted or paused). A rule with a category sends that category to its own project.',
|
|
139
|
+
},
|
|
140
|
+
update: {
|
|
141
|
+
schema: staffSupportRoutingRuleUpdateSchema,
|
|
142
|
+
responseSchema: defaultOkResponseSchema,
|
|
143
|
+
description: 'Repoints a rule at another project or pauses/resumes a per-category rule. Pausing the fallback rule answers 422.',
|
|
144
|
+
},
|
|
145
|
+
del: {
|
|
146
|
+
schema: z.object({ id: z.string().uuid() }),
|
|
147
|
+
responseSchema: defaultOkResponseSchema,
|
|
148
|
+
description: 'Deletes a per-category rule so the category falls back to the fallback project. Deleting the fallback rule answers 422.',
|
|
149
|
+
},
|
|
150
|
+
})
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GET /api/staff/timesheets/support-tickets/options` — the filter options behind
|
|
3
|
+
* the Support Inbox.
|
|
4
|
+
*
|
|
5
|
+
* The inbox is open to every holder of `staff.timesheets.tasks.view`, so its option
|
|
6
|
+
* lists cannot come from routes that need more: the routing preview needs
|
|
7
|
+
* `staff.timesheets.settings.manage` and the team directory needs `staff.view`,
|
|
8
|
+
* which an agent with the `employee` role holds neither of.
|
|
9
|
+
*
|
|
10
|
+
* * `categories` is the organization's support category dictionary — the exact
|
|
11
|
+
* organization, never an inherited one, the same lookup the portal form and the
|
|
12
|
+
* ticket command use.
|
|
13
|
+
* * `assignees` is limited to the people the caller can already see through their
|
|
14
|
+
* project access: everyone actively assigned to one of the caller's projects, or,
|
|
15
|
+
* for a holder of `staff.timesheets.projects.manage`, every active staff member of
|
|
16
|
+
* the organization.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { NextResponse } from 'next/server'
|
|
20
|
+
import { z } from 'zod'
|
|
21
|
+
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
22
|
+
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
23
|
+
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
24
|
+
import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
|
|
25
|
+
import { resolveSingleOrganizationIdOrDeny } from '@open-mercato/core/modules/directory/utils/organizationScopeFilter'
|
|
26
|
+
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
27
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
28
|
+
import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
29
|
+
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
30
|
+
import { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'
|
|
31
|
+
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
32
|
+
import { StaffTeamMember, StaffTimeProjectMember } from '../../../../data/entities'
|
|
33
|
+
import { loadSupportTicketCategories } from '../../../../lib/support/dictionaries'
|
|
34
|
+
import { resolveFeatureAccess } from '../../../../lib/time-tracking/featureAccess'
|
|
35
|
+
import { MANAGE_PROJECTS_FEATURE, resolveProjectAccess } from '../../../../lib/time-tracking/access'
|
|
36
|
+
import {
|
|
37
|
+
isActiveAssignment,
|
|
38
|
+
normalizeAssignmentGraceDays,
|
|
39
|
+
resolveAssignmentGraceDaysFromContainer,
|
|
40
|
+
} from '../../../../lib/time-tracking/projectAssignment'
|
|
41
|
+
import { readSearchParamsRecord, runTimesheetInterceptors } from '../../_shared/withTimesheetInterceptors'
|
|
42
|
+
|
|
43
|
+
const logger = createLogger('staff').child({ component: 'api/timesheets/support-tickets/options' })
|
|
44
|
+
|
|
45
|
+
const VIEW_FEATURE = 'staff.timesheets.tasks.view'
|
|
46
|
+
const MAX_ASSIGNEES = 500
|
|
47
|
+
|
|
48
|
+
export const metadata = {
|
|
49
|
+
GET: { requireAuth: true, requireFeatures: [VIEW_FEATURE] },
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const optionsResponseSchema = z.object({
|
|
53
|
+
categories: z.array(z.object({ value: z.string(), label: z.string() })),
|
|
54
|
+
assignees: z.array(z.object({ id: z.string().uuid(), displayName: z.string() })),
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
type SupportInboxOptions = z.infer<typeof optionsResponseSchema>
|
|
58
|
+
|
|
59
|
+
type Scope = { tenantId: string; organizationId: string }
|
|
60
|
+
|
|
61
|
+
async function loadAssignableStaffMemberIds(
|
|
62
|
+
em: EntityManager,
|
|
63
|
+
scope: Scope,
|
|
64
|
+
projectIds: string[],
|
|
65
|
+
graceDays: number | null,
|
|
66
|
+
): Promise<string[]> {
|
|
67
|
+
if (projectIds.length === 0) return []
|
|
68
|
+
const memberships = await em.find(StaffTimeProjectMember, {
|
|
69
|
+
timeProjectId: { $in: projectIds },
|
|
70
|
+
tenantId: scope.tenantId,
|
|
71
|
+
organizationId: scope.organizationId,
|
|
72
|
+
status: 'active',
|
|
73
|
+
deletedAt: null,
|
|
74
|
+
})
|
|
75
|
+
const now = new Date()
|
|
76
|
+
return Array.from(
|
|
77
|
+
new Set(
|
|
78
|
+
memberships
|
|
79
|
+
.filter((membership) => isActiveAssignment(membership, now, normalizeAssignmentGraceDays(graceDays)))
|
|
80
|
+
.map((membership) => membership.staffMemberId),
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function loadAssignees(
|
|
86
|
+
em: EntityManager,
|
|
87
|
+
scope: Scope,
|
|
88
|
+
staffMemberIds: string[] | null,
|
|
89
|
+
): Promise<SupportInboxOptions['assignees']> {
|
|
90
|
+
if (staffMemberIds !== null && staffMemberIds.length === 0) return []
|
|
91
|
+
const where: Record<string, unknown> = {
|
|
92
|
+
tenantId: scope.tenantId,
|
|
93
|
+
organizationId: scope.organizationId,
|
|
94
|
+
isActive: true,
|
|
95
|
+
deletedAt: null,
|
|
96
|
+
}
|
|
97
|
+
if (staffMemberIds !== null) where.id = { $in: staffMemberIds }
|
|
98
|
+
const members = await findWithDecryption(em, StaffTeamMember, where, { limit: MAX_ASSIGNEES }, scope)
|
|
99
|
+
return members
|
|
100
|
+
.map((member) => ({ id: member.id, displayName: member.displayName || member.id }))
|
|
101
|
+
.sort((left, right) => left.displayName.localeCompare(right.displayName))
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function GET(req: Request) {
|
|
105
|
+
try {
|
|
106
|
+
const container = await createRequestContainer()
|
|
107
|
+
const auth = await getAuthFromRequest(req)
|
|
108
|
+
const { translate } = await resolveTranslations()
|
|
109
|
+
if (!auth) throw new CrudHttpError(401, { error: translate('staff.errors.unauthorized', 'Unauthorized') })
|
|
110
|
+
|
|
111
|
+
const orgScope = await resolveOrganizationScopeForRequest({ container, auth, request: req })
|
|
112
|
+
const tenantId = orgScope?.tenantId ?? auth.tenantId ?? null
|
|
113
|
+
const organizationId = resolveSingleOrganizationIdOrDeny(orgScope, auth) ?? null
|
|
114
|
+
if (!tenantId || !organizationId) {
|
|
115
|
+
throw new CrudHttpError(400, {
|
|
116
|
+
error: translate('staff.errors.missingScope', 'Missing tenant or organization scope.'),
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const interceptors = await runTimesheetInterceptors({
|
|
121
|
+
request: req,
|
|
122
|
+
method: 'GET',
|
|
123
|
+
scope: { container, userId: auth.sub, tenantId, organizationId },
|
|
124
|
+
query: readSearchParamsRecord(req.url),
|
|
125
|
+
})
|
|
126
|
+
if (!interceptors.ok) return interceptors.response
|
|
127
|
+
const { session } = interceptors
|
|
128
|
+
|
|
129
|
+
const scope: Scope = { tenantId, organizationId }
|
|
130
|
+
const em = (container.resolve('em') as EntityManager).fork()
|
|
131
|
+
const manageAccess = await resolveFeatureAccess(container, auth.sub ?? null, [MANAGE_PROJECTS_FEATURE], scope)
|
|
132
|
+
const graceDays = await resolveAssignmentGraceDaysFromContainer(container, tenantId)
|
|
133
|
+
const access = await resolveProjectAccess({
|
|
134
|
+
em,
|
|
135
|
+
userId: auth.sub ?? null,
|
|
136
|
+
tenantId,
|
|
137
|
+
organizationId,
|
|
138
|
+
canManageAll: manageAccess.allowed,
|
|
139
|
+
userFeatures: manageAccess.grantedFeatures,
|
|
140
|
+
assignmentGraceDays: graceDays,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const assignableIds = access.canManageAll
|
|
144
|
+
? null
|
|
145
|
+
: await loadAssignableStaffMemberIds(em, scope, access.projectIds, graceDays)
|
|
146
|
+
|
|
147
|
+
const [categories, assignees] = await Promise.all([
|
|
148
|
+
loadSupportTicketCategories(em, scope),
|
|
149
|
+
loadAssignees(em.fork(), scope, assignableIds),
|
|
150
|
+
])
|
|
151
|
+
|
|
152
|
+
const payload: SupportInboxOptions = optionsResponseSchema.parse({ categories, assignees })
|
|
153
|
+
return session.respond(200, payload)
|
|
154
|
+
} catch (err) {
|
|
155
|
+
if (err instanceof CrudHttpError) {
|
|
156
|
+
return NextResponse.json(err.body, { status: err.status })
|
|
157
|
+
}
|
|
158
|
+
logger.error('staff.support.inbox options failed', { err })
|
|
159
|
+
getTelemetryRuntime()?.reportError(err, { module: 'staff', code: 'staff.support_inbox_options_failed' })
|
|
160
|
+
const { translate } = await resolveTranslations()
|
|
161
|
+
return NextResponse.json({ error: translate('staff.errors.internal', 'Internal server error') }, { status: 500 })
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export const openApi: OpenApiRouteDoc = {
|
|
166
|
+
tag: 'Staff',
|
|
167
|
+
summary: 'Support Inbox filter options',
|
|
168
|
+
methods: {
|
|
169
|
+
GET: {
|
|
170
|
+
summary: 'Support Inbox filter options',
|
|
171
|
+
description:
|
|
172
|
+
"The organization's support ticket categories and the staff members a ticket can be filtered by assignee. Assignees are limited to the people actively assigned to the caller's projects; a holder of `staff.timesheets.projects.manage` gets every active staff member of the organization.",
|
|
173
|
+
responses: [{ status: 200, description: 'Filter options', schema: optionsResponseSchema }],
|
|
174
|
+
errors: [
|
|
175
|
+
{ status: 400, description: 'Missing tenant or organization scope' },
|
|
176
|
+
{ status: 401, description: 'Unauthorized' },
|
|
177
|
+
{ status: 403, description: 'Missing staff.timesheets.tasks.view' },
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
2
|
+
import {
|
|
3
|
+
TASK_ASSIGNMENT_VIEW_FEATURE,
|
|
4
|
+
createTaskAssignmentPostHandler,
|
|
5
|
+
taskAssignmentResponseSchema,
|
|
6
|
+
} from '../../../../../lib/time-tracking/taskAssignmentRoute'
|
|
7
|
+
|
|
8
|
+
export const metadata = {
|
|
9
|
+
POST: { requireAuth: true, requireFeatures: [TASK_ASSIGNMENT_VIEW_FEATURE] },
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const POST = createTaskAssignmentPostHandler('claim')
|
|
13
|
+
|
|
14
|
+
export const openApi: OpenApiRouteDoc = {
|
|
15
|
+
tag: 'Staff',
|
|
16
|
+
summary: 'Claim an unassigned task',
|
|
17
|
+
methods: {
|
|
18
|
+
POST: {
|
|
19
|
+
summary: 'Claim an unassigned task',
|
|
20
|
+
description: 'Sets the caller as the assignee of an unassigned, not-done task. Only active assigners of the task project (a project member flagged as assigner, inside the assignment window) may claim; `staff.timesheets.tasks.manage` is not required. The update is conditional on the task still being unassigned, so of two concurrent claims exactly one wins and the other answers 409. Accepts `x-om-ext-optimistic-lock-expected-updated-at`.',
|
|
21
|
+
responses: [{ status: 200, description: 'Claim an unassigned task', schema: taskAssignmentResponseSchema }],
|
|
22
|
+
errors: [
|
|
23
|
+
{ status: 401, description: 'Unauthorized' },
|
|
24
|
+
{ status: 403, description: 'The caller is not an active assigner of the project' },
|
|
25
|
+
{ status: 404, description: 'Task not found, or not on a project the caller can see' },
|
|
26
|
+
{ status: 409, description: 'The task was already claimed, or changed since the version the caller sent' },
|
|
27
|
+
{ status: 422, description: 'The task is in a done status' },
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
}
|
|
@@ -50,7 +50,7 @@ import { User } from '@open-mercato/core/modules/auth/data/entities'
|
|
|
50
50
|
import { StaffTimeTaskComment } from '../../../../../data/entities'
|
|
51
51
|
import {
|
|
52
52
|
staffTimeTaskCommentCreateSchema,
|
|
53
|
-
|
|
53
|
+
staffTimeTaskCommentUpdateRequestSchema,
|
|
54
54
|
} from '../../../../../data/validators'
|
|
55
55
|
import { staffTimeTaskCommentCommandIds } from '../../../../../commands/timesheets-task-comments'
|
|
56
56
|
import { STAFF_TIME_TRACKING_RESOURCE_KINDS } from '../../../../guards'
|
|
@@ -86,6 +86,8 @@ const commentItemSchema = z.object({
|
|
|
86
86
|
authorUserId: z.string().uuid().nullable(),
|
|
87
87
|
authorName: z.string().nullable(),
|
|
88
88
|
authorEmail: z.string().nullable(),
|
|
89
|
+
visibility: z.enum(['internal', 'customer']),
|
|
90
|
+
authorKind: z.enum(['staff', 'customer']),
|
|
89
91
|
createdAt: z.string().nullable(),
|
|
90
92
|
updatedAt: z.string().nullable(),
|
|
91
93
|
})
|
|
@@ -106,8 +108,16 @@ const createResponseSchema = z.object({
|
|
|
106
108
|
|
|
107
109
|
const okResponseSchema = z.object({ ok: z.boolean() })
|
|
108
110
|
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
+
const visibilitySchema = z.enum(['internal', 'customer'])
|
|
112
|
+
const createBodySchema = z.object({
|
|
113
|
+
body: z.string().trim().min(1).max(5000),
|
|
114
|
+
visibility: visibilitySchema.optional(),
|
|
115
|
+
})
|
|
116
|
+
const updateBodySchema = z.object({
|
|
117
|
+
id: z.string().uuid(),
|
|
118
|
+
body: z.string().trim().min(1).max(5000).optional(),
|
|
119
|
+
visibility: visibilitySchema.optional(),
|
|
120
|
+
})
|
|
111
121
|
|
|
112
122
|
type RouteContext = {
|
|
113
123
|
ctx: CommandRuntimeContext
|
|
@@ -233,13 +243,17 @@ async function resolveAuthorMeta(
|
|
|
233
243
|
function serializeComment(comment: StaffTimeTaskComment, authors: Map<string, AuthorMeta>) {
|
|
234
244
|
const authorUserId = comment.authorUserId ?? null
|
|
235
245
|
const meta = authorUserId ? authors.get(authorUserId) ?? null : null
|
|
246
|
+
const authorKind = comment.authorKind === 'customer' ? 'customer' : 'staff'
|
|
247
|
+
const customerName = comment.authorDisplaySnapshot?.displayName ?? null
|
|
236
248
|
return {
|
|
237
249
|
id: comment.id,
|
|
238
250
|
taskId: comment.taskId,
|
|
239
251
|
body: comment.body,
|
|
240
252
|
authorUserId,
|
|
241
|
-
authorName: meta?.name ?? null,
|
|
242
|
-
authorEmail: meta?.email ?? null,
|
|
253
|
+
authorName: authorKind === 'customer' ? customerName : meta?.name ?? null,
|
|
254
|
+
authorEmail: authorKind === 'customer' ? null : meta?.email ?? null,
|
|
255
|
+
visibility: comment.visibility === 'customer' ? 'customer' : 'internal',
|
|
256
|
+
authorKind,
|
|
243
257
|
createdAt: comment.createdAt ? comment.createdAt.toISOString() : null,
|
|
244
258
|
updatedAt: comment.updatedAt ? comment.updatedAt.toISOString() : null,
|
|
245
259
|
}
|
|
@@ -373,7 +387,7 @@ export async function POST(req: Request) {
|
|
|
373
387
|
// here and the command stamps the authenticated caller instead.
|
|
374
388
|
const input = parseScopedCommandInput(
|
|
375
389
|
staffTimeTaskCommentCreateSchema,
|
|
376
|
-
{ taskId: route.taskId, body: parsedBody.body },
|
|
390
|
+
{ taskId: route.taskId, body: parsedBody.body, visibility: parsedBody.visibility ?? 'internal' },
|
|
377
391
|
route.ctx,
|
|
378
392
|
route.translate,
|
|
379
393
|
)
|
|
@@ -416,7 +430,11 @@ export async function PUT(req: Request) {
|
|
|
416
430
|
const parsedBody = updateBodySchema.parse(raw ?? {})
|
|
417
431
|
await requireCommentOnTask(route, parsedBody.id)
|
|
418
432
|
|
|
419
|
-
const input =
|
|
433
|
+
const input = staffTimeTaskCommentUpdateRequestSchema.parse({
|
|
434
|
+
id: parsedBody.id,
|
|
435
|
+
body: parsedBody.body,
|
|
436
|
+
visibility: parsedBody.visibility,
|
|
437
|
+
})
|
|
420
438
|
|
|
421
439
|
const guardResult = await runGuards(route, 'update', input.id, input as unknown as Record<string, unknown>)
|
|
422
440
|
if (!guardResult.ok) return guardResult.response
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
2
|
+
import {
|
|
3
|
+
TASK_ASSIGNMENT_VIEW_FEATURE,
|
|
4
|
+
createTaskAssignmentPostHandler,
|
|
5
|
+
taskAssignmentResponseSchema,
|
|
6
|
+
} from '../../../../../lib/time-tracking/taskAssignmentRoute'
|
|
7
|
+
|
|
8
|
+
export const metadata = {
|
|
9
|
+
POST: { requireAuth: true, requireFeatures: [TASK_ASSIGNMENT_VIEW_FEATURE] },
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const POST = createTaskAssignmentPostHandler('release')
|
|
13
|
+
|
|
14
|
+
export const openApi: OpenApiRouteDoc = {
|
|
15
|
+
tag: 'Staff',
|
|
16
|
+
summary: 'Release a task you hold',
|
|
17
|
+
methods: {
|
|
18
|
+
POST: {
|
|
19
|
+
summary: 'Release a task you hold',
|
|
20
|
+
description: 'Clears the assignee of a task the caller is assigned to, making it claimable again; the project assigners are notified. Only the current assignee may release (403 otherwise); managers keep using PUT /api/staff/timesheets/tasks.',
|
|
21
|
+
responses: [{ status: 200, description: 'Release a task you hold', schema: taskAssignmentResponseSchema }],
|
|
22
|
+
errors: [
|
|
23
|
+
{ status: 401, description: 'Unauthorized' },
|
|
24
|
+
{ status: 403, description: 'The caller is not the current assignee' },
|
|
25
|
+
{ status: 404, description: 'Task not found, or not on a project the caller can see' },
|
|
26
|
+
{ status: 409, description: 'The task changed since the version the caller sent, or it is no longer assigned to the caller (`task_assignment_changed`)' },
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}
|