@open-mercato/core 0.6.4-develop.4217.1.c9aa050183 → 0.6.4-develop.4239.1.4a264a5828
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_time_entry/index.js +37 -0
- package/dist/generated/entities/staff_time_entry/index.js.map +7 -0
- package/dist/generated/entities/staff_time_entry_segment/index.js +23 -0
- package/dist/generated/entities/staff_time_entry_segment/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project/index.js +35 -0
- package/dist/generated/entities/staff_time_project/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project_member/index.js +29 -0
- package/dist/generated/entities/staff_time_project_member/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +5 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +64 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/timesheetFixtures.js +50 -0
- package/dist/helpers/integration/timesheetFixtures.js.map +7 -0
- package/dist/modules/attachments/api/library/[id]/route.js +20 -16
- package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/route.js +18 -14
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/auth/api/roles/acl/route.js +10 -4
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +27 -20
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +16 -11
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/commands/users.js +87 -71
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/services/sidebarPreferencesService.js +39 -30
- package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
- package/dist/modules/business_rules/backend/logs/[id]/page.js +24 -5
- package/dist/modules/business_rules/backend/logs/[id]/page.js.map +2 -2
- package/dist/modules/catalog/api/offers/route.js +15 -5
- package/dist/modules/catalog/api/offers/route.js.map +2 -2
- package/dist/modules/catalog/commands/categories.js +61 -12
- package/dist/modules/catalog/commands/categories.js.map +2 -2
- package/dist/modules/catalog/commands/products.js +79 -54
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/commands/variants.js +29 -16
- package/dist/modules/catalog/commands/variants.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js +19 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/currencies/commands/currencies.js +15 -8
- package/dist/modules/currencies/commands/currencies.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users.js +27 -26
- package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
- package/dist/modules/customer_accounts/api/password/reset-confirm.js +5 -5
- package/dist/modules/customer_accounts/api/password/reset-confirm.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +11 -10
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +27 -7
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +27 -7
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +29 -8
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/addresses.js +35 -21
- package/dist/modules/customers/commands/addresses.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +163 -162
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +3 -4
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +19 -22
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/commands/people.js +18 -15
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/commands/personCompanyLinks.js +105 -94
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/commands/pipeline-stages.js +30 -23
- package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
- package/dist/modules/customers/commands/pipelines.js +27 -20
- package/dist/modules/customers/commands/pipelines.js.map +2 -2
- package/dist/modules/customers/commands/tags.js +13 -5
- package/dist/modules/customers/commands/tags.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +0 -1
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/route.js +29 -1
- package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js +4 -4
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-run-service.js +51 -27
- package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
- package/dist/modules/directory/commands/organizations.js +192 -158
- package/dist/modules/directory/commands/organizations.js.map +3 -3
- package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +22 -16
- package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +77 -75
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/commands/shared.js +132 -132
- package/dist/modules/messages/commands/shared.js.map +2 -2
- package/dist/modules/perspectives/api/[tableId]/route.js +37 -26
- package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
- package/dist/modules/progress/acl.js +8 -4
- package/dist/modules/progress/acl.js.map +2 -2
- package/dist/modules/resources/commands/resources.js +125 -117
- package/dist/modules/resources/commands/resources.js.map +2 -2
- package/dist/modules/resources/commands/tags.js +7 -3
- package/dist/modules/resources/commands/tags.js.map +2 -2
- package/dist/modules/sales/api/quotes/send/route.js +12 -11
- package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +629 -478
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +146 -146
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +68 -60
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/staff/acl.js +10 -1
- package/dist/modules/staff/acl.js.map +2 -2
- package/dist/modules/staff/analytics.js +33 -0
- package/dist/modules/staff/analytics.js.map +7 -0
- package/dist/modules/staff/api/guards.js +31 -0
- package/dist/modules/staff/api/guards.js.map +7 -0
- package/dist/modules/staff/api/interceptors.js +96 -0
- package/dist/modules/staff/api/interceptors.js.map +7 -0
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +170 -0
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/my-projects/route.js +103 -0
- package/dist/modules/staff/api/timesheets/my-projects/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js +147 -0
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +171 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +180 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +155 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +173 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +260 -0
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/route.js +188 -0
- package/dist/modules/staff/api/timesheets/time-entries/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +159 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-projects/route.js +230 -0
- package/dist/modules/staff/api/timesheets/time-projects/route.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/page.js +710 -0
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/page.meta.js +22 -0
- package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +125 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +418 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +79 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +602 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +25 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +123 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +7 -0
- package/dist/modules/staff/cli.js +38 -1
- package/dist/modules/staff/cli.js.map +2 -2
- package/dist/modules/staff/commands/index.js +2 -0
- package/dist/modules/staff/commands/index.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +30 -28
- package/dist/modules/staff/commands/leave-requests.js.map +3 -3
- package/dist/modules/staff/commands/team-members.js +21 -20
- package/dist/modules/staff/commands/team-members.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-entries.js +409 -0
- package/dist/modules/staff/commands/timesheets-entries.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-projects.js +618 -0
- package/dist/modules/staff/commands/timesheets-projects.js.map +7 -0
- package/dist/modules/staff/data/enrichers.js +104 -0
- package/dist/modules/staff/data/enrichers.js.map +7 -0
- package/dist/modules/staff/data/entities.js +226 -1
- package/dist/modules/staff/data/entities.js.map +2 -2
- package/dist/modules/staff/data/validators.js +113 -1
- package/dist/modules/staff/data/validators.js.map +2 -2
- package/dist/modules/staff/events.js +13 -1
- package/dist/modules/staff/events.js.map +2 -2
- package/dist/modules/staff/lib/crud.js +7 -1
- package/dist/modules/staff/lib/crud.js.map +2 -2
- package/dist/modules/staff/lib/staffMemberResolver.js +15 -0
- package/dist/modules/staff/lib/staffMemberResolver.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js +60 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js +260 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js +41 -0
- package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/initials.js +10 -0
- package/dist/modules/staff/lib/timesheets-projects/initials.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/kpiMath.js +12 -0
- package/dist/modules/staff/lib/timesheets-projects/kpiMath.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js +55 -0
- package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js +66 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +81 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js +58 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js +152 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +37 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js +57 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js +50 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js +163 -0
- package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js +209 -0
- package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js +52 -0
- package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +77 -0
- package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ListView.js +173 -0
- package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js +32 -0
- package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +270 -0
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js +57 -0
- package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/colors.js +43 -0
- package/dist/modules/staff/lib/timesheets-ui/colors.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260326135612.js +24 -0
- package/dist/modules/staff/migrations/Migration20260326135612.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260413102715.js +23 -0
- package/dist/modules/staff/migrations/Migration20260413102715.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260413111602.js +13 -0
- package/dist/modules/staff/migrations/Migration20260413111602.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260511112759.js +19 -0
- package/dist/modules/staff/migrations/Migration20260511112759.js.map +7 -0
- package/dist/modules/staff/search.js +35 -0
- package/dist/modules/staff/search.js.map +2 -2
- package/dist/modules/staff/setup.js +15 -1
- package/dist/modules/staff/setup.js.map +2 -2
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js +16 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +126 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js +26 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js +15 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +238 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js +26 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +145 -0
- package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection-table.js +12 -0
- package/dist/modules/staff/widgets/injection-table.js.map +7 -0
- package/dist/modules/sync_excel/api/import/route.js +19 -17
- package/dist/modules/sync_excel/api/import/route.js.map +2 -2
- package/dist/modules/translations/commands/translations.js +22 -19
- package/dist/modules/translations/commands/translations.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +24 -6
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.js +27 -5
- package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +25 -6
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/generated/entities/staff_time_entry/index.ts +17 -0
- package/generated/entities/staff_time_entry_segment/index.ts +10 -0
- package/generated/entities/staff_time_project/index.ts +16 -0
- package/generated/entities/staff_time_project_member/index.ts +13 -0
- package/generated/entities.ids.generated.ts +5 -1
- package/generated/entity-fields-registry.ts +64 -0
- package/package.json +7 -7
- package/src/helpers/integration/timesheetFixtures.ts +61 -0
- package/src/modules/attachments/api/library/[id]/route.ts +24 -17
- package/src/modules/attachments/api/route.ts +20 -14
- package/src/modules/auth/api/roles/acl/route.ts +11 -5
- package/src/modules/auth/api/sidebar/preferences/route.ts +33 -24
- package/src/modules/auth/api/users/acl/route.ts +17 -12
- package/src/modules/auth/commands/users.ts +96 -80
- package/src/modules/auth/services/sidebarPreferencesService.ts +40 -32
- package/src/modules/business_rules/backend/logs/[id]/page.tsx +32 -7
- package/src/modules/catalog/api/offers/route.ts +20 -5
- package/src/modules/catalog/commands/categories.ts +61 -12
- package/src/modules/catalog/commands/products.ts +93 -60
- package/src/modules/catalog/commands/variants.ts +29 -16
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +21 -2
- package/src/modules/currencies/commands/currencies.ts +27 -14
- package/src/modules/currencies/i18n/de.json +1 -0
- package/src/modules/currencies/i18n/en.json +1 -0
- package/src/modules/currencies/i18n/es.json +1 -0
- package/src/modules/currencies/i18n/pl.json +1 -0
- package/src/modules/customer_accounts/api/admin/users.ts +31 -26
- package/src/modules/customer_accounts/api/password/reset-confirm.ts +5 -6
- package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +14 -13
- package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -11
- package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +34 -11
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +35 -11
- package/src/modules/customers/commands/addresses.ts +35 -23
- package/src/modules/customers/commands/companies.ts +166 -165
- package/src/modules/customers/commands/deals.ts +2 -4
- package/src/modules/customers/commands/interactions.ts +20 -26
- package/src/modules/customers/commands/people.ts +18 -15
- package/src/modules/customers/commands/personCompanyLinks.ts +109 -100
- package/src/modules/customers/commands/pipeline-stages.ts +31 -27
- package/src/modules/customers/commands/pipelines.ts +29 -23
- package/src/modules/customers/commands/tags.ts +13 -5
- package/src/modules/dashboards/api/users/widgets/route.ts +0 -1
- package/src/modules/dashboards/api/widgets/data/route.ts +36 -1
- package/src/modules/data_sync/lib/sync-engine.ts +4 -5
- package/src/modules/data_sync/lib/sync-run-service.ts +57 -28
- package/src/modules/directory/commands/organizations.ts +203 -166
- package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +26 -18
- package/src/modules/messages/commands/messages.ts +82 -80
- package/src/modules/messages/commands/shared.ts +138 -133
- package/src/modules/perspectives/api/[tableId]/route.ts +38 -27
- package/src/modules/progress/acl.ts +4 -0
- package/src/modules/resources/commands/resources.ts +127 -117
- package/src/modules/resources/commands/tags.ts +7 -3
- package/src/modules/sales/api/quotes/send/route.ts +17 -12
- package/src/modules/sales/commands/documents.ts +673 -481
- package/src/modules/sales/commands/payments.ts +158 -152
- package/src/modules/sales/commands/returns.ts +74 -63
- package/src/modules/staff/acl.ts +11 -0
- package/src/modules/staff/analytics.ts +30 -0
- package/src/modules/staff/api/guards.ts +59 -0
- package/src/modules/staff/api/interceptors.ts +122 -0
- package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +191 -0
- package/src/modules/staff/api/timesheets/my-projects/route.ts +115 -0
- package/src/modules/staff/api/timesheets/projects/kpis/route.ts +159 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +187 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +191 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +168 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +191 -0
- package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +292 -0
- package/src/modules/staff/api/timesheets/time-entries/route.ts +193 -0
- package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +167 -0
- package/src/modules/staff/api/timesheets/time-projects/route.ts +244 -0
- package/src/modules/staff/backend/staff/timesheets/page.meta.ts +20 -0
- package/src/modules/staff/backend/staff/timesheets/page.tsx +899 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +141 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +579 -0
- package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +90 -0
- package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +23 -0
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +765 -0
- package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +138 -0
- package/src/modules/staff/cli.ts +40 -1
- package/src/modules/staff/commands/index.ts +2 -0
- package/src/modules/staff/commands/leave-requests.ts +37 -29
- package/src/modules/staff/commands/team-members.ts +25 -20
- package/src/modules/staff/commands/timesheets-entries.ts +504 -0
- package/src/modules/staff/commands/timesheets-projects.ts +699 -0
- package/src/modules/staff/data/enrichers.ts +134 -0
- package/src/modules/staff/data/entities.ts +198 -0
- package/src/modules/staff/data/validators.ts +129 -0
- package/src/modules/staff/events.ts +13 -0
- package/src/modules/staff/i18n/de.json +209 -1
- package/src/modules/staff/i18n/en.json +209 -1
- package/src/modules/staff/i18n/es.json +209 -1
- package/src/modules/staff/i18n/pl.json +209 -1
- package/src/modules/staff/lib/crud.ts +8 -0
- package/src/modules/staff/lib/staffMemberResolver.ts +22 -0
- package/src/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.ts +89 -0
- package/src/modules/staff/lib/timesheets-projects/computeProjectsKpis.ts +311 -0
- package/src/modules/staff/lib/timesheets-projects/dateBuckets.ts +37 -0
- package/src/modules/staff/lib/timesheets-projects/initials.ts +6 -0
- package/src/modules/staff/lib/timesheets-projects/kpiMath.ts +8 -0
- package/src/modules/staff/lib/timesheets-projects/listProjectMembersPreview.ts +83 -0
- package/src/modules/staff/lib/timesheets-projects-ui/HoursSparkline.tsx +75 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +110 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.tsx +73 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.tsx +185 -0
- package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +53 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.tsx +63 -0
- package/src/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.ts +63 -0
- package/src/modules/staff/lib/timesheets-ui/AddRowDropdown.tsx +188 -0
- package/src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx +229 -0
- package/src/modules/staff/lib/timesheets-ui/ColorPicker.tsx +65 -0
- package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +99 -0
- package/src/modules/staff/lib/timesheets-ui/ListView.tsx +230 -0
- package/src/modules/staff/lib/timesheets-ui/ProjectColorDot.tsx +40 -0
- package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +327 -0
- package/src/modules/staff/lib/timesheets-ui/ViewSwitcher.tsx +60 -0
- package/src/modules/staff/lib/timesheets-ui/colors.ts +58 -0
- package/src/modules/staff/migrations/.snapshot-open-mercato.json +1148 -0
- package/src/modules/staff/migrations/Migration20260326135612.ts +26 -0
- package/src/modules/staff/migrations/Migration20260413102715.ts +25 -0
- package/src/modules/staff/migrations/Migration20260413111602.ts +13 -0
- package/src/modules/staff/migrations/Migration20260511112759.ts +21 -0
- package/src/modules/staff/search.ts +35 -0
- package/src/modules/staff/setup.ts +15 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.ts +17 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +158 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.ts +25 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/config.ts +15 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +297 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.ts +25 -0
- package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +161 -0
- package/src/modules/staff/widgets/injection-table.ts +10 -0
- package/src/modules/sync_excel/api/import/route.ts +23 -18
- package/src/modules/translations/commands/translations.ts +49 -41
- package/src/modules/workflows/backend/events/[id]/page.tsx +32 -10
- package/src/modules/workflows/backend/instances/[id]/page.tsx +33 -9
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +33 -10
- package/src/modules/workflows/i18n/de.json +1 -0
- package/src/modules/workflows/i18n/en.json +1 -0
- package/src/modules/workflows/i18n/es.json +1 -0
- package/src/modules/workflows/i18n/pl.json +1 -0
|
@@ -12,6 +12,7 @@ import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
|
12
12
|
import { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'
|
|
13
13
|
import { DataLoader } from '@open-mercato/ui/primitives/DataLoader'
|
|
14
14
|
import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
|
|
15
|
+
import { RecordNotFoundState, ErrorMessage } from '@open-mercato/ui/backend/detail'
|
|
15
16
|
|
|
16
17
|
type CurrencyData = {
|
|
17
18
|
id: string
|
|
@@ -35,6 +36,7 @@ export default function EditCurrencyPage({ params }: { params?: { id?: string }
|
|
|
35
36
|
const [currency, setCurrency] = React.useState<CurrencyData | null>(null)
|
|
36
37
|
const [loading, setLoading] = React.useState(true)
|
|
37
38
|
const [error, setError] = React.useState<string | null>(null)
|
|
39
|
+
const [isNotFound, setIsNotFound] = React.useState(false)
|
|
38
40
|
|
|
39
41
|
React.useEffect(() => {
|
|
40
42
|
async function loadCurrency() {
|
|
@@ -42,8 +44,10 @@ export default function EditCurrencyPage({ params }: { params?: { id?: string }
|
|
|
42
44
|
const response = await apiCall<{ items: CurrencyData[] }>(`/api/currencies/currencies?id=${params?.id}`)
|
|
43
45
|
if (response.ok && response.result && response.result.items.length > 0) {
|
|
44
46
|
setCurrency(response.result.items[0])
|
|
47
|
+
} else if (!response.ok) {
|
|
48
|
+
setError(t('currencies.form.errors.load'))
|
|
45
49
|
} else {
|
|
46
|
-
|
|
50
|
+
setIsNotFound(true)
|
|
47
51
|
}
|
|
48
52
|
} catch (err) {
|
|
49
53
|
setError(t('currencies.form.errors.load'))
|
|
@@ -163,11 +167,26 @@ export default function EditCurrencyPage({ params }: { params?: { id?: string }
|
|
|
163
167
|
)
|
|
164
168
|
}
|
|
165
169
|
|
|
170
|
+
if (isNotFound) {
|
|
171
|
+
return (
|
|
172
|
+
<Page>
|
|
173
|
+
<PageBody>
|
|
174
|
+
<RecordNotFoundState
|
|
175
|
+
label={t('currencies.form.errors.notFound', 'Currency not found.')}
|
|
176
|
+
backHref="/backend/currencies"
|
|
177
|
+
backLabel={t('currencies.form.actions.backToList', 'Back to currencies')}
|
|
178
|
+
/>
|
|
179
|
+
</PageBody>
|
|
180
|
+
{ConfirmDialogElement}
|
|
181
|
+
</Page>
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
|
|
166
185
|
if (error || !currency) {
|
|
167
186
|
return (
|
|
168
187
|
<Page>
|
|
169
188
|
<PageBody>
|
|
170
|
-
<
|
|
189
|
+
<ErrorMessage label={error ?? t('currencies.form.errors.notFound', 'Currency not found.')} />
|
|
171
190
|
</PageBody>
|
|
172
191
|
{ConfirmDialogElement}
|
|
173
192
|
</Page>
|
|
@@ -2,6 +2,7 @@ import { registerCommand } from '@open-mercato/shared/lib/commands'
|
|
|
2
2
|
import type { CommandHandler } from '@open-mercato/shared/lib/commands'
|
|
3
3
|
import { buildChanges, requireId, emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'
|
|
4
4
|
import { extractUndoPayload, type UndoPayload } from '@open-mercato/shared/lib/commands/undo'
|
|
5
|
+
import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
|
|
5
6
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
6
7
|
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
7
8
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
@@ -119,13 +120,19 @@ const createCurrencyCommand: CommandHandler<CurrencyCreateInput, { currencyId: s
|
|
|
119
120
|
updatedAt: now,
|
|
120
121
|
})
|
|
121
122
|
em.persist(record)
|
|
122
|
-
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
|
|
124
|
+
// Demote any existing base currency and insert the new record in one
|
|
125
|
+
// transaction; a partial commit would leave zero or two base currencies.
|
|
126
|
+
await withAtomicFlush(
|
|
127
|
+
em,
|
|
128
|
+
[
|
|
129
|
+
() =>
|
|
130
|
+
record.isBase
|
|
131
|
+
? enforceBaseCurrency(em, record.id, record.organizationId, record.tenantId)
|
|
132
|
+
: undefined,
|
|
133
|
+
],
|
|
134
|
+
{ transaction: true },
|
|
135
|
+
)
|
|
129
136
|
|
|
130
137
|
const de = ctx.container.resolve('dataEngine') as DataEngine
|
|
131
138
|
await emitCrudSideEffects({
|
|
@@ -227,13 +234,19 @@ const updateCurrencyCommand: CommandHandler<CurrencyUpdateInput, { currencyId: s
|
|
|
227
234
|
;(record as any)[key] = change.to
|
|
228
235
|
}
|
|
229
236
|
record.updatedAt = new Date()
|
|
230
|
-
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
+
|
|
238
|
+
// Demote any existing base currency and persist the scalar changes in one
|
|
239
|
+
// transaction; a partial commit would leave zero or two base currencies.
|
|
240
|
+
await withAtomicFlush(
|
|
241
|
+
em,
|
|
242
|
+
[
|
|
243
|
+
() =>
|
|
244
|
+
parsed.isBase === true && record.isBase
|
|
245
|
+
? enforceBaseCurrency(em, record.id, record.organizationId, record.tenantId)
|
|
246
|
+
: undefined,
|
|
247
|
+
],
|
|
248
|
+
{ transaction: true },
|
|
249
|
+
)
|
|
237
250
|
|
|
238
251
|
const de = ctx.container.resolve('dataEngine') as DataEngine
|
|
239
252
|
await emitCrudSideEffects({
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"currencies.flash.updated": "Währung erfolgreich aktualisiert",
|
|
42
42
|
"currencies.form.action.create": "Währung erstellen",
|
|
43
43
|
"currencies.form.action.save": "Änderungen speichern",
|
|
44
|
+
"currencies.form.actions.backToList": "Zurück zu Währungen",
|
|
44
45
|
"currencies.form.errors.codeFormat": "Währungscode muss genau 3 Großbuchstaben sein (z.B. USD)",
|
|
45
46
|
"currencies.form.errors.delete": "Währung konnte nicht gelöscht werden",
|
|
46
47
|
"currencies.form.errors.load": "Währung konnte nicht geladen werden",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"currencies.flash.updated": "Currency updated successfully",
|
|
42
42
|
"currencies.form.action.create": "Create Currency",
|
|
43
43
|
"currencies.form.action.save": "Save Changes",
|
|
44
|
+
"currencies.form.actions.backToList": "Back to currencies",
|
|
44
45
|
"currencies.form.errors.codeFormat": "Currency code must be exactly 3 uppercase letters (e.g., USD)",
|
|
45
46
|
"currencies.form.errors.delete": "Failed to delete currency",
|
|
46
47
|
"currencies.form.errors.load": "Failed to load currency",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"currencies.flash.updated": "Moneda actualizada correctamente",
|
|
42
42
|
"currencies.form.action.create": "Crear Moneda",
|
|
43
43
|
"currencies.form.action.save": "Guardar Cambios",
|
|
44
|
+
"currencies.form.actions.backToList": "Volver a divisas",
|
|
44
45
|
"currencies.form.errors.codeFormat": "El código de moneda debe ser exactamente 3 letras mayúsculas (ej. USD)",
|
|
45
46
|
"currencies.form.errors.delete": "Error al eliminar moneda",
|
|
46
47
|
"currencies.form.errors.load": "Error al cargar moneda",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"currencies.flash.updated": "Waluta zaktualizowana pomyślnie",
|
|
42
42
|
"currencies.form.action.create": "Utwórz Walutę",
|
|
43
43
|
"currencies.form.action.save": "Zapisz Zmiany",
|
|
44
|
+
"currencies.form.actions.backToList": "Wróć do walut",
|
|
44
45
|
"currencies.form.errors.codeFormat": "Kod waluty musi składać się z dokładnie 3 wielkich liter (np. USD)",
|
|
45
46
|
"currencies.form.errors.delete": "Nie udało się usunąć waluty",
|
|
46
47
|
"currencies.form.errors.load": "Nie udało się załadować waluty",
|
|
@@ -225,35 +225,40 @@ export async function POST(req: Request) {
|
|
|
225
225
|
{ tenantId: auth.tenantId!, organizationId: auth.orgId! },
|
|
226
226
|
)
|
|
227
227
|
user.emailVerifiedAt = new Date()
|
|
228
|
-
em.persist(user)
|
|
229
|
-
await em.flush()
|
|
230
228
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
229
|
+
// Persist the user, its company association, and its role links in one
|
|
230
|
+
// transaction so a flush failure on the role loop cannot leave a roleless
|
|
231
|
+
// user committed (privilege gap).
|
|
232
|
+
await em.transactional(async (tx) => {
|
|
233
|
+
tx.persist(user)
|
|
234
|
+
await tx.flush()
|
|
234
235
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
em,
|
|
238
|
-
CustomerRole,
|
|
239
|
-
{
|
|
240
|
-
id: { $in: parsed.data.roleIds } as any,
|
|
241
|
-
tenantId: auth.tenantId,
|
|
242
|
-
deletedAt: null,
|
|
243
|
-
} as any,
|
|
244
|
-
undefined,
|
|
245
|
-
{ tenantId: auth.tenantId, organizationId: auth.orgId },
|
|
246
|
-
)
|
|
247
|
-
for (const role of validRoles) {
|
|
248
|
-
const userRole = em.create(CustomerUserRole, {
|
|
249
|
-
user,
|
|
250
|
-
role,
|
|
251
|
-
createdAt: new Date(),
|
|
252
|
-
} as any)
|
|
253
|
-
em.persist(userRole)
|
|
236
|
+
if (parsed.data.customerEntityId) {
|
|
237
|
+
await tx.nativeUpdate(CustomerUser, { id: user.id }, { customerEntityId: parsed.data.customerEntityId })
|
|
254
238
|
}
|
|
255
|
-
|
|
256
|
-
|
|
239
|
+
|
|
240
|
+
if (parsed.data.roleIds && parsed.data.roleIds.length > 0) {
|
|
241
|
+
const validRoles = await findWithDecryption(
|
|
242
|
+
tx,
|
|
243
|
+
CustomerRole,
|
|
244
|
+
{
|
|
245
|
+
id: { $in: parsed.data.roleIds } as any,
|
|
246
|
+
tenantId: auth.tenantId,
|
|
247
|
+
deletedAt: null,
|
|
248
|
+
} as any,
|
|
249
|
+
undefined,
|
|
250
|
+
{ tenantId: auth.tenantId, organizationId: auth.orgId },
|
|
251
|
+
)
|
|
252
|
+
for (const role of validRoles) {
|
|
253
|
+
const userRole = tx.create(CustomerUserRole, {
|
|
254
|
+
user,
|
|
255
|
+
role,
|
|
256
|
+
createdAt: new Date(),
|
|
257
|
+
} as any)
|
|
258
|
+
tx.persist(userRole)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
})
|
|
257
262
|
|
|
258
263
|
void emitCustomerAccountsEvent('customer_accounts.user.created', {
|
|
259
264
|
id: user.id,
|
|
@@ -44,14 +44,13 @@ export async function POST(req: Request) {
|
|
|
44
44
|
await em.transactional(async (trx) => {
|
|
45
45
|
await customerUserService.updatePassword(user, parsed.data.password, trx)
|
|
46
46
|
await customerSessionService.revokeAllUserSessions(user.id, trx)
|
|
47
|
+
await trx.nativeUpdate(
|
|
48
|
+
CustomerUser,
|
|
49
|
+
{ id: user.id, emailVerifiedAt: null },
|
|
50
|
+
{ emailVerifiedAt: new Date() },
|
|
51
|
+
)
|
|
47
52
|
})
|
|
48
53
|
|
|
49
|
-
await em.nativeUpdate(
|
|
50
|
-
CustomerUser,
|
|
51
|
-
{ id: user.id, emailVerifiedAt: null },
|
|
52
|
-
{ emailVerifiedAt: new Date() },
|
|
53
|
-
)
|
|
54
|
-
|
|
55
54
|
void emitCustomerAccountsEvent('customer_accounts.password.changed', {
|
|
56
55
|
userId: user.id,
|
|
57
56
|
tenantId: user.tenantId,
|
|
@@ -75,19 +75,20 @@ export async function PUT(req: Request, { params }: { params: { id: string } })
|
|
|
75
75
|
validatedRoles.push(role)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
78
|
+
// Replace the role set atomically: deleting the old roles and inserting the new
|
|
79
|
+
// ones in one transaction prevents a flush failure from leaving the user with
|
|
80
|
+
// zero roles (portal lockout / privilege loss) (#2337).
|
|
81
|
+
await em.transactional(async (tx) => {
|
|
82
|
+
await tx.nativeDelete(CustomerUserRole, { user: targetUser.id as any })
|
|
83
|
+
for (const role of validatedRoles) {
|
|
84
|
+
const userRole = tx.create(CustomerUserRole, {
|
|
85
|
+
user: targetUser,
|
|
86
|
+
role,
|
|
87
|
+
createdAt: new Date(),
|
|
88
|
+
} as any)
|
|
89
|
+
tx.persist(userRole)
|
|
90
|
+
}
|
|
91
|
+
})
|
|
91
92
|
|
|
92
93
|
await customerRbacService.invalidateUserCache(targetUser.id)
|
|
93
94
|
|
|
@@ -11,6 +11,7 @@ import { Spinner } from '@open-mercato/ui/primitives/spinner'
|
|
|
11
11
|
import { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
12
12
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
13
13
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
14
|
+
import { RecordNotFoundState, ErrorMessage } from '@open-mercato/ui/backend/detail'
|
|
14
15
|
|
|
15
16
|
type RoleDetail = {
|
|
16
17
|
id: string
|
|
@@ -146,10 +147,11 @@ export default function CustomerRoleDetailPage({ params }: { params?: { id?: str
|
|
|
146
147
|
const [data, setData] = React.useState<RoleDetail | null>(null)
|
|
147
148
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
148
149
|
const [error, setError] = React.useState<string | null>(null)
|
|
150
|
+
const [isNotFound, setIsNotFound] = React.useState(false)
|
|
149
151
|
|
|
150
152
|
React.useEffect(() => {
|
|
151
153
|
if (!id) {
|
|
152
|
-
|
|
154
|
+
setIsNotFound(true)
|
|
153
155
|
setIsLoading(false)
|
|
154
156
|
return
|
|
155
157
|
}
|
|
@@ -157,6 +159,7 @@ export default function CustomerRoleDetailPage({ params }: { params?: { id?: str
|
|
|
157
159
|
async function load() {
|
|
158
160
|
setIsLoading(true)
|
|
159
161
|
setError(null)
|
|
162
|
+
setIsNotFound(false)
|
|
160
163
|
try {
|
|
161
164
|
const payload = await readApiResultOrThrow<RoleDetail>(
|
|
162
165
|
`/api/customer_accounts/admin/roles/${encodeURIComponent(id!)}`,
|
|
@@ -167,8 +170,12 @@ export default function CustomerRoleDetailPage({ params }: { params?: { id?: str
|
|
|
167
170
|
setData(payload)
|
|
168
171
|
} catch (err) {
|
|
169
172
|
if (cancelled) return
|
|
170
|
-
|
|
171
|
-
|
|
173
|
+
if ((err as { status?: number }).status === 404) {
|
|
174
|
+
setIsNotFound(true)
|
|
175
|
+
} else {
|
|
176
|
+
const message = err instanceof Error ? err.message : t('customer_accounts.admin.roleDetail.error.load', 'Failed to load role')
|
|
177
|
+
setError(message)
|
|
178
|
+
}
|
|
172
179
|
} finally {
|
|
173
180
|
if (!cancelled) setIsLoading(false)
|
|
174
181
|
}
|
|
@@ -300,18 +307,34 @@ export default function CustomerRoleDetailPage({ params }: { params?: { id?: str
|
|
|
300
307
|
)
|
|
301
308
|
}
|
|
302
309
|
|
|
310
|
+
if (isNotFound) {
|
|
311
|
+
return (
|
|
312
|
+
<Page>
|
|
313
|
+
<PageBody>
|
|
314
|
+
<RecordNotFoundState
|
|
315
|
+
label={t('customer_accounts.admin.roleDetail.error.notFound', 'Role not found')}
|
|
316
|
+
backHref="/backend/customer_accounts/roles"
|
|
317
|
+
backLabel={t('customer_accounts.admin.roleDetail.actions.backToList', 'Back to roles')}
|
|
318
|
+
/>
|
|
319
|
+
</PageBody>
|
|
320
|
+
</Page>
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
|
|
303
324
|
if (error || !data) {
|
|
304
325
|
return (
|
|
305
326
|
<Page>
|
|
306
327
|
<PageBody>
|
|
307
|
-
<
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
<
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
328
|
+
<ErrorMessage
|
|
329
|
+
label={error ?? t('customer_accounts.admin.roleDetail.error.notFound', 'Role not found')}
|
|
330
|
+
action={
|
|
331
|
+
<Button asChild variant="outline" size="sm">
|
|
332
|
+
<Link href="/backend/customer_accounts/roles">
|
|
333
|
+
{t('customer_accounts.admin.roleDetail.actions.backToList', 'Back to roles')}
|
|
334
|
+
</Link>
|
|
335
|
+
</Button>
|
|
336
|
+
}
|
|
337
|
+
/>
|
|
315
338
|
</PageBody>
|
|
316
339
|
</Page>
|
|
317
340
|
)
|
|
@@ -16,6 +16,7 @@ import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
|
16
16
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
17
17
|
import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
|
|
18
18
|
import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'
|
|
19
|
+
import { RecordNotFoundState, ErrorMessage } from '@open-mercato/ui/backend/detail'
|
|
19
20
|
|
|
20
21
|
type UserDetail = {
|
|
21
22
|
id: string
|
|
@@ -147,6 +148,7 @@ export default function CustomerUserDetailPage({ params }: { params?: { id?: str
|
|
|
147
148
|
const [data, setData] = React.useState<UserDetail | null>(null)
|
|
148
149
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
149
150
|
const [error, setError] = React.useState<string | null>(null)
|
|
151
|
+
const [isNotFound, setIsNotFound] = React.useState(false)
|
|
150
152
|
const [isSaving, setIsSaving] = React.useState(false)
|
|
151
153
|
const [editActive, setEditActive] = React.useState<boolean | null>(null)
|
|
152
154
|
const [editDisplayName, setEditDisplayName] = React.useState('')
|
|
@@ -186,7 +188,7 @@ export default function CustomerUserDetailPage({ params }: { params?: { id?: str
|
|
|
186
188
|
|
|
187
189
|
React.useEffect(() => {
|
|
188
190
|
if (!id) {
|
|
189
|
-
|
|
191
|
+
setIsNotFound(true)
|
|
190
192
|
setIsLoading(false)
|
|
191
193
|
return
|
|
192
194
|
}
|
|
@@ -194,6 +196,7 @@ export default function CustomerUserDetailPage({ params }: { params?: { id?: str
|
|
|
194
196
|
async function load() {
|
|
195
197
|
setIsLoading(true)
|
|
196
198
|
setError(null)
|
|
199
|
+
setIsNotFound(false)
|
|
197
200
|
try {
|
|
198
201
|
const payload = await readApiResultOrThrow<UserDetail>(
|
|
199
202
|
`/api/customer_accounts/admin/users/${encodeURIComponent(id!)}`,
|
|
@@ -209,8 +212,12 @@ export default function CustomerUserDetailPage({ params }: { params?: { id?: str
|
|
|
209
212
|
setEditCustomerEntityId(payload.customerEntityId)
|
|
210
213
|
} catch (err) {
|
|
211
214
|
if (cancelled) return
|
|
212
|
-
|
|
213
|
-
|
|
215
|
+
if ((err as { status?: number }).status === 404) {
|
|
216
|
+
setIsNotFound(true)
|
|
217
|
+
} else {
|
|
218
|
+
const message = err instanceof Error ? err.message : t('customer_accounts.admin.detail.error.load', 'Failed to load user')
|
|
219
|
+
setError(message)
|
|
220
|
+
}
|
|
214
221
|
} finally {
|
|
215
222
|
if (!cancelled) setIsLoading(false)
|
|
216
223
|
}
|
|
@@ -463,18 +470,34 @@ export default function CustomerUserDetailPage({ params }: { params?: { id?: str
|
|
|
463
470
|
)
|
|
464
471
|
}
|
|
465
472
|
|
|
473
|
+
if (isNotFound) {
|
|
474
|
+
return (
|
|
475
|
+
<Page>
|
|
476
|
+
<PageBody>
|
|
477
|
+
<RecordNotFoundState
|
|
478
|
+
label={t('customer_accounts.admin.detail.error.notFound', 'User not found')}
|
|
479
|
+
backHref="/backend/customer_accounts/users"
|
|
480
|
+
backLabel={t('customer_accounts.admin.detail.actions.backToList', 'Back to list')}
|
|
481
|
+
/>
|
|
482
|
+
</PageBody>
|
|
483
|
+
</Page>
|
|
484
|
+
)
|
|
485
|
+
}
|
|
486
|
+
|
|
466
487
|
if (error || !data) {
|
|
467
488
|
return (
|
|
468
489
|
<Page>
|
|
469
490
|
<PageBody>
|
|
470
|
-
<
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
<
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
491
|
+
<ErrorMessage
|
|
492
|
+
label={error ?? t('customer_accounts.admin.detail.error.notFound', 'User not found')}
|
|
493
|
+
action={
|
|
494
|
+
<Button asChild variant="outline" size="sm">
|
|
495
|
+
<Link href="/backend/customer_accounts/users">
|
|
496
|
+
{t('customer_accounts.admin.detail.actions.backToList', 'Back to list')}
|
|
497
|
+
</Link>
|
|
498
|
+
</Button>
|
|
499
|
+
}
|
|
500
|
+
/>
|
|
478
501
|
</PageBody>
|
|
479
502
|
</Page>
|
|
480
503
|
)
|
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
NotesSection,
|
|
21
21
|
type CommentSummary,
|
|
22
22
|
type SectionAction,
|
|
23
|
+
RecordNotFoundState,
|
|
24
|
+
ErrorMessage,
|
|
23
25
|
} from '@open-mercato/ui/backend/detail'
|
|
24
26
|
import {
|
|
25
27
|
TagsSection,
|
|
@@ -116,6 +118,7 @@ export default function CustomerPersonDetailPage({ params }: { params?: { id?: s
|
|
|
116
118
|
const [data, setData] = React.useState<PersonOverview | null>(null)
|
|
117
119
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
118
120
|
const [error, setError] = React.useState<string | null>(null)
|
|
121
|
+
const [isNotFound, setIsNotFound] = React.useState(false)
|
|
119
122
|
const [activeTab, setActiveTab] = React.useState<SectionKey>(initialTab)
|
|
120
123
|
const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)
|
|
121
124
|
const [isDeleting, setIsDeleting] = React.useState(false)
|
|
@@ -276,7 +279,7 @@ export default function CustomerPersonDetailPage({ params }: { params?: { id?: s
|
|
|
276
279
|
const initialLoadDoneRef = React.useRef(false)
|
|
277
280
|
const loadData = React.useCallback(async () => {
|
|
278
281
|
if (!id) {
|
|
279
|
-
|
|
282
|
+
setIsNotFound(true)
|
|
280
283
|
setIsLoading(false)
|
|
281
284
|
return
|
|
282
285
|
}
|
|
@@ -284,6 +287,7 @@ export default function CustomerPersonDetailPage({ params }: { params?: { id?: s
|
|
|
284
287
|
setIsLoading(true)
|
|
285
288
|
}
|
|
286
289
|
setError(null)
|
|
290
|
+
setIsNotFound(false)
|
|
287
291
|
try {
|
|
288
292
|
const payload = await readApiResultOrThrow<PersonOverview>(
|
|
289
293
|
`/api/customers/people/${encodeURIComponent(id)}?include=todos`,
|
|
@@ -292,8 +296,12 @@ export default function CustomerPersonDetailPage({ params }: { params?: { id?: s
|
|
|
292
296
|
)
|
|
293
297
|
setData(payload as PersonOverview)
|
|
294
298
|
} catch (err) {
|
|
295
|
-
|
|
296
|
-
|
|
299
|
+
if ((err as { status?: number }).status === 404) {
|
|
300
|
+
setIsNotFound(true)
|
|
301
|
+
} else {
|
|
302
|
+
const message = err instanceof Error ? err.message : t('customers.people.detail.error.load')
|
|
303
|
+
setError(message)
|
|
304
|
+
}
|
|
297
305
|
if (!initialLoadDoneRef.current) setData(null)
|
|
298
306
|
} finally {
|
|
299
307
|
setIsLoading(false)
|
|
@@ -469,18 +477,34 @@ export default function CustomerPersonDetailPage({ params }: { params?: { id?: s
|
|
|
469
477
|
)
|
|
470
478
|
}
|
|
471
479
|
|
|
480
|
+
if (isNotFound) {
|
|
481
|
+
return (
|
|
482
|
+
<Page>
|
|
483
|
+
<PageBody>
|
|
484
|
+
<RecordNotFoundState
|
|
485
|
+
label={t('customers.people.detail.error.notFound', 'Person not found.')}
|
|
486
|
+
backHref="/backend/customers/people"
|
|
487
|
+
backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}
|
|
488
|
+
/>
|
|
489
|
+
</PageBody>
|
|
490
|
+
</Page>
|
|
491
|
+
)
|
|
492
|
+
}
|
|
493
|
+
|
|
472
494
|
if (error || !data || !personId) {
|
|
473
495
|
return (
|
|
474
496
|
<Page>
|
|
475
497
|
<PageBody>
|
|
476
|
-
<
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
<
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
498
|
+
<ErrorMessage
|
|
499
|
+
label={error ?? t('customers.people.detail.error.notFound', 'Person not found.')}
|
|
500
|
+
action={
|
|
501
|
+
<Button asChild variant="outline" size="sm">
|
|
502
|
+
<Link href="/backend/customers/people">
|
|
503
|
+
{t('customers.people.detail.actions.backToList', 'Back to people')}
|
|
504
|
+
</Link>
|
|
505
|
+
</Button>
|
|
506
|
+
}
|
|
507
|
+
/>
|
|
484
508
|
</PageBody>
|
|
485
509
|
</Page>
|
|
486
510
|
)
|
|
@@ -17,6 +17,7 @@ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
|
17
17
|
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
18
18
|
import type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
19
19
|
import { E } from '#generated/entities.ids.generated'
|
|
20
|
+
import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
|
|
20
21
|
|
|
21
22
|
const addressCrudIndexer: CrudIndexerConfig<CustomerAddress> = {
|
|
22
23
|
entityType: E.customers.customer_address,
|
|
@@ -130,13 +131,15 @@ const createAddressCommand: CommandHandler<AddressCreateInput, { addressId: stri
|
|
|
130
131
|
createdAt: new Date(),
|
|
131
132
|
updatedAt: new Date(),
|
|
132
133
|
})
|
|
133
|
-
em
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
await withAtomicFlush(em, [
|
|
135
|
+
async () => {
|
|
136
|
+
em.persist(address)
|
|
137
|
+
await em.flush()
|
|
138
|
+
if (address.isPrimary) {
|
|
139
|
+
await enforcePrimaryAddress(em, entity.id, address.id)
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
], { transaction: true })
|
|
140
143
|
|
|
141
144
|
const de = (ctx.container.resolve('dataEngine') as DataEngine)
|
|
142
145
|
await emitCrudSideEffects({
|
|
@@ -225,12 +228,13 @@ const updateAddressCommand: CommandHandler<AddressUpdateInput, { addressId: stri
|
|
|
225
228
|
if (parsed.longitude !== undefined) address.longitude = parsed.longitude ?? null
|
|
226
229
|
if (parsed.isPrimary !== undefined) address.isPrimary = parsed.isPrimary
|
|
227
230
|
|
|
228
|
-
await em
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
await withAtomicFlush(em, [
|
|
232
|
+
async () => {
|
|
233
|
+
if (address.isPrimary) {
|
|
234
|
+
await enforcePrimaryAddress(em, typeof address.entity === 'string' ? address.entity : address.entity.id, address.id)
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
], { transaction: true })
|
|
234
238
|
|
|
235
239
|
const de = (ctx.container.resolve('dataEngine') as DataEngine)
|
|
236
240
|
await emitCrudSideEffects({
|
|
@@ -348,11 +352,15 @@ const updateAddressCommand: CommandHandler<AddressUpdateInput, { addressId: stri
|
|
|
348
352
|
address.longitude = before.longitude
|
|
349
353
|
address.isPrimary = before.isPrimary
|
|
350
354
|
}
|
|
351
|
-
await em
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
355
|
+
await withAtomicFlush(em, [
|
|
356
|
+
async () => {
|
|
357
|
+
em.persist(address)
|
|
358
|
+
await em.flush()
|
|
359
|
+
if (before.isPrimary) {
|
|
360
|
+
await enforcePrimaryAddress(em, before.entityId, before.id)
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
], { transaction: true })
|
|
356
364
|
|
|
357
365
|
const de = (ctx.container.resolve('dataEngine') as DataEngine)
|
|
358
366
|
await emitCrudUndoSideEffects({
|
|
@@ -471,11 +479,15 @@ const deleteAddressCommand: CommandHandler<{ body?: Record<string, unknown>; que
|
|
|
471
479
|
address.longitude = before.longitude
|
|
472
480
|
address.isPrimary = before.isPrimary
|
|
473
481
|
}
|
|
474
|
-
await em
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
482
|
+
await withAtomicFlush(em, [
|
|
483
|
+
async () => {
|
|
484
|
+
em.persist(address)
|
|
485
|
+
await em.flush()
|
|
486
|
+
if (before.isPrimary) {
|
|
487
|
+
await enforcePrimaryAddress(em, before.entityId, before.id)
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
], { transaction: true })
|
|
479
491
|
|
|
480
492
|
const de = (ctx.container.resolve('dataEngine') as DataEngine)
|
|
481
493
|
await emitCrudUndoSideEffects({
|