@open-mercato/core 0.6.6 → 0.6.7-develop.6553.1.2ec7246e04
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/gateway_session_initialization/index.js +23 -0
- package/dist/generated/entities/gateway_session_initialization/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +12 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_keys/api/keys/route.js +30 -13
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/api_keys/cli.js +2 -1
- package/dist/modules/api_keys/cli.js.map +2 -2
- package/dist/modules/attachments/api/file/[id]/route.js +9 -7
- package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +9 -7
- package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
- package/dist/modules/attachments/api/route.js +21 -17
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentContentPreview.js +6 -35
- package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
- package/dist/modules/attachments/lib/reconcileOrganization.js +110 -0
- package/dist/modules/attachments/lib/reconcileOrganization.js.map +7 -0
- package/dist/modules/attachments/lib/requestScope.js +10 -0
- package/dist/modules/attachments/lib/requestScope.js.map +7 -0
- package/dist/modules/audit_logs/backend/audit-logs/page.js +14 -24
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/auth/api/autologin.js +85 -0
- package/dist/modules/auth/api/autologin.js.map +7 -0
- package/dist/modules/auth/api/users/route.js +6 -2
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/cli.js +3 -2
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/lib/autologin.js +19 -0
- package/dist/modules/auth/lib/autologin.js.map +7 -0
- package/dist/modules/configs/lib/upgrade-actions.js +22 -0
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js +1 -0
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles/[id].js +17 -3
- package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +6 -1
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +6 -1
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js +1 -0
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerRbacService.js +6 -1
- package/dist/modules/customer_accounts/services/customerRbacService.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection-table.js +0 -2
- package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +7 -1
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +37 -43
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DealDetailTabs.js +23 -35
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DetailTabsLayout.js +6 -21
- package/dist/modules/customers/components/detail/DetailTabsLayout.js.map +2 -2
- package/dist/modules/customers/components/detail/MobilePersonDetail.js +26 -32
- package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +29 -39
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/useDealsAccess.js +16 -0
- package/dist/modules/customers/components/detail/useDealsAccess.js.map +7 -0
- package/dist/modules/dashboards/api/roles/widgets/route.js +22 -3
- package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +22 -3
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/cli.js +4 -3
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/lib/widgetAssignmentScope.js +9 -1
- package/dist/modules/dashboards/lib/widgetAssignmentScope.js.map +2 -2
- package/dist/modules/dictionaries/commands/entries.js +7 -14
- package/dist/modules/dictionaries/commands/entries.js.map +2 -2
- package/dist/modules/dictionaries/commands/entry-operations.js +7 -16
- package/dist/modules/dictionaries/commands/entry-operations.js.map +2 -2
- package/dist/modules/dictionaries/commands/factory.js +9 -3
- package/dist/modules/dictionaries/commands/factory.js.map +2 -2
- package/dist/modules/dictionaries/fields/dictionary.js +56 -41
- package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
- package/dist/modules/directory/utils/organizationScope.js +10 -3
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/records.js +5 -4
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js +1 -0
- package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js +49 -49
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js +1 -0
- package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js.map +2 -2
- package/dist/modules/entities/cli.js +2 -1
- package/dist/modules/entities/cli.js.map +2 -2
- package/dist/modules/feature_toggles/api/check/boolean/route.js +0 -14
- package/dist/modules/feature_toggles/api/check/boolean/route.js.map +2 -2
- package/dist/modules/feature_toggles/defaults.json +8 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.js +9 -80
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +45 -0
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +173 -38
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +3 -3
- package/dist/modules/payment_gateways/lib/session-idempotency.js +104 -0
- package/dist/modules/payment_gateways/lib/session-idempotency.js.map +7 -0
- package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js +11 -0
- package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js.map +7 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +16 -14
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +18 -30
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/query_index/api/status.js +2 -8
- package/dist/modules/query_index/api/status.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -24
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/create/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/create/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/create/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/create/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +6 -4
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +44 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +2 -27
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/sales/components/SalesChannelsDisabledNotice.js +15 -0
- package/dist/modules/sales/components/SalesChannelsDisabledNotice.js.map +7 -0
- package/dist/modules/sales/components/documents/AddressesSection.js +6 -2
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +1 -0
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +9 -0
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +51 -3
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -8
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +59 -38
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/components/useSalesChannelsEnabled.js +44 -0
- package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +7 -0
- package/dist/modules/sales/lib/calculations.js +6 -0
- package/dist/modules/sales/lib/calculations.js.map +2 -2
- package/dist/modules/sales/lib/salesChannelsToggle.js +18 -0
- package/dist/modules/sales/lib/salesChannelsToggle.js.map +7 -0
- package/dist/modules/sales/lib/salesChannelsToggleId.js +5 -0
- package/dist/modules/sales/lib/salesChannelsToggleId.js.map +7 -0
- package/dist/modules/sales/lib/shipments/snapshots.js +27 -1
- package/dist/modules/sales/lib/shipments/snapshots.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +22 -25
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +12 -14
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +10 -29
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +19 -20
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/sync_excel/lib/parser.js +185 -0
- package/dist/modules/sync_excel/lib/parser.js.map +2 -2
- package/dist/modules/sync_excel/lib/upload-storage.js +20 -1
- package/dist/modules/sync_excel/lib/upload-storage.js.map +2 -2
- package/generated/entities/gateway_session_initialization/index.ts +10 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/generated/entity-fields-registry.ts +12 -0
- package/package.json +9 -8
- package/src/modules/api_keys/api/keys/route.ts +36 -13
- package/src/modules/api_keys/cli.ts +2 -3
- package/src/modules/attachments/api/file/[id]/route.ts +11 -7
- package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +11 -7
- package/src/modules/attachments/api/route.ts +26 -21
- package/src/modules/attachments/components/AttachmentContentPreview.tsx +9 -44
- package/src/modules/attachments/lib/reconcileOrganization.ts +188 -0
- package/src/modules/attachments/lib/requestScope.ts +27 -0
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +12 -22
- package/src/modules/auth/api/autologin.ts +100 -0
- package/src/modules/auth/api/users/route.ts +11 -2
- package/src/modules/auth/cli.ts +3 -2
- package/src/modules/auth/lib/autologin.ts +36 -0
- package/src/modules/configs/i18n/de.json +5 -1
- package/src/modules/configs/i18n/en.json +5 -1
- package/src/modules/configs/i18n/es.json +5 -1
- package/src/modules/configs/i18n/pl.json +5 -1
- package/src/modules/configs/lib/upgrade-actions.ts +24 -0
- package/src/modules/customer_accounts/AGENTS.md +8 -6
- package/src/modules/customer_accounts/api/admin/roles/[id]/acl.ts +1 -0
- package/src/modules/customer_accounts/api/admin/roles/[id].ts +17 -3
- package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +6 -1
- package/src/modules/customer_accounts/api/portal/users-invite.ts +6 -1
- package/src/modules/customer_accounts/services/customerInvitationService.ts +1 -0
- package/src/modules/customer_accounts/services/customerRbacService.ts +9 -2
- package/src/modules/customer_accounts/widgets/injection-table.ts +0 -2
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +11 -1
- package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +6 -2
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +39 -55
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +24 -49
- package/src/modules/customers/components/detail/DetailTabsLayout.tsx +13 -24
- package/src/modules/customers/components/detail/MobilePersonDetail.tsx +25 -31
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +29 -50
- package/src/modules/customers/components/detail/useDealsAccess.ts +19 -0
- package/src/modules/dashboards/api/roles/widgets/route.ts +22 -3
- package/src/modules/dashboards/api/users/widgets/route.ts +22 -3
- package/src/modules/dashboards/cli.ts +4 -9
- package/src/modules/dashboards/lib/widgetAssignmentScope.ts +18 -0
- package/src/modules/dictionaries/commands/entries.ts +7 -16
- package/src/modules/dictionaries/commands/entry-operations.ts +8 -18
- package/src/modules/dictionaries/commands/factory.ts +8 -2
- package/src/modules/dictionaries/fields/dictionary.tsx +55 -32
- package/src/modules/dictionaries/i18n/de.json +2 -0
- package/src/modules/dictionaries/i18n/en.json +2 -0
- package/src/modules/dictionaries/i18n/es.json +2 -0
- package/src/modules/dictionaries/i18n/pl.json +2 -0
- package/src/modules/directory/utils/organizationScope.ts +36 -2
- package/src/modules/entities/api/records.ts +5 -7
- package/src/modules/entities/backend/entities/system/[entityId]/page.meta.ts +1 -0
- package/src/modules/entities/backend/entities/user/[entityId]/page.meta.ts +1 -0
- package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +51 -49
- package/src/modules/entities/cli.ts +2 -1
- package/src/modules/entities/i18n/de.json +34 -0
- package/src/modules/entities/i18n/en.json +34 -0
- package/src/modules/entities/i18n/es.json +34 -0
- package/src/modules/entities/i18n/pl.json +34 -0
- package/src/modules/feature_toggles/api/check/boolean/route.ts +0 -15
- package/src/modules/feature_toggles/defaults.json +8 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +16 -59
- package/src/modules/payment_gateways/data/entities.ts +39 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +211 -40
- package/src/modules/payment_gateways/lib/session-idempotency.ts +142 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +236 -0
- package/src/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.ts +10 -0
- package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +14 -20
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +16 -34
- package/src/modules/query_index/api/status.ts +2 -8
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +27 -37
- package/src/modules/sales/backend/sales/channels/create/page.meta.ts +3 -0
- package/src/modules/sales/backend/sales/channels/create/page.tsx +7 -0
- package/src/modules/sales/backend/sales/channels/offers/page.meta.ts +3 -0
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +7 -0
- package/src/modules/sales/backend/sales/channels/page.meta.ts +4 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +7 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +7 -5
- package/src/modules/sales/commands/documents.ts +65 -0
- package/src/modules/sales/commands/returns.ts +2 -32
- package/src/modules/sales/components/SalesChannelsDisabledNotice.tsx +21 -0
- package/src/modules/sales/components/documents/AddressesSection.tsx +6 -2
- package/src/modules/sales/components/documents/ItemsSection.tsx +5 -0
- package/src/modules/sales/components/documents/LineItemDialog.tsx +10 -0
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +53 -3
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +10 -8
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +65 -40
- package/src/modules/sales/components/useSalesChannelsEnabled.ts +59 -0
- package/src/modules/sales/i18n/de.json +5 -0
- package/src/modules/sales/i18n/en.json +5 -0
- package/src/modules/sales/i18n/es.json +5 -0
- package/src/modules/sales/i18n/pl.json +5 -0
- package/src/modules/sales/lib/calculations.ts +15 -0
- package/src/modules/sales/lib/salesChannelsToggle.ts +26 -0
- package/src/modules/sales/lib/salesChannelsToggleId.ts +1 -0
- package/src/modules/sales/lib/shipments/snapshots.ts +30 -0
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +25 -34
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +11 -17
- package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +11 -28
- package/src/modules/sync_excel/lib/adapters/customers.ts +20 -22
- package/src/modules/sync_excel/lib/parser.ts +245 -0
- package/src/modules/sync_excel/lib/upload-storage.ts +23 -1
|
@@ -296,6 +296,13 @@ export function ShipmentDialog({
|
|
|
296
296
|
const [addressOptions, setAddressOptions] = React.useState<ShipmentAddressOption[]>([])
|
|
297
297
|
const [addressLoading, setAddressLoading] = React.useState(false)
|
|
298
298
|
const [addressError, setAddressError] = React.useState<string | null>(null)
|
|
299
|
+
const addressLoadPromiseRef = React.useRef<{
|
|
300
|
+
orderId: string
|
|
301
|
+
promise: Promise<ShipmentAddressOption[]>
|
|
302
|
+
} | null>(null)
|
|
303
|
+
const currentAddressOrderIdRef = React.useRef(orderId)
|
|
304
|
+
currentAddressOrderIdRef.current = orderId
|
|
305
|
+
const initializedDialogKeyRef = React.useRef<string | null>(null)
|
|
299
306
|
const [documentStatuses, setDocumentStatuses] = React.useState<StatusOption[]>([])
|
|
300
307
|
const [lineStatuses, setLineStatuses] = React.useState<StatusOption[]>([])
|
|
301
308
|
const [shipmentStatuses, setShipmentStatuses] = React.useState<StatusOption[]>([])
|
|
@@ -479,37 +486,52 @@ export function ShipmentDialog({
|
|
|
479
486
|
[],
|
|
480
487
|
)
|
|
481
488
|
|
|
482
|
-
const loadAddressOptions = React.useCallback(
|
|
489
|
+
const loadAddressOptions = React.useCallback((): Promise<ShipmentAddressOption[]> => {
|
|
490
|
+
const activeRequest = addressLoadPromiseRef.current
|
|
491
|
+
if (activeRequest?.orderId === orderId) return activeRequest.promise
|
|
492
|
+
|
|
483
493
|
setAddressLoading(true)
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
494
|
+
const request = (async () => {
|
|
495
|
+
try {
|
|
496
|
+
const params = new URLSearchParams({
|
|
497
|
+
page: '1',
|
|
498
|
+
pageSize: '100',
|
|
499
|
+
documentId: orderId,
|
|
500
|
+
documentKind: 'order',
|
|
501
|
+
})
|
|
502
|
+
const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(
|
|
503
|
+
`/api/sales/document-addresses?${params.toString()}`,
|
|
504
|
+
undefined,
|
|
505
|
+
{ fallback: { items: [] } },
|
|
506
|
+
)
|
|
507
|
+
const items = Array.isArray(response.result?.items) ? response.result.items : []
|
|
508
|
+
const mapped = items
|
|
509
|
+
.map((item) => mapDocumentAddressOption(item))
|
|
510
|
+
.filter((entry): entry is ShipmentAddressOption => Boolean(entry))
|
|
511
|
+
const loadedOptions = dedupeAddressOptions([...baseAddressOptions, ...mapped])
|
|
512
|
+
if (currentAddressOrderIdRef.current !== orderId) return baseAddressOptions
|
|
513
|
+
mergeAddressOptions(loadedOptions)
|
|
514
|
+
setAddressError(null)
|
|
515
|
+
return loadedOptions
|
|
516
|
+
} catch (err) {
|
|
517
|
+
logger.error('sales.shipments.addresses.load', { err })
|
|
518
|
+
if (currentAddressOrderIdRef.current === orderId) {
|
|
519
|
+
setAddressError(
|
|
520
|
+
t('sales.documents.shipments.addressLoadError', 'Failed to load addresses.'),
|
|
521
|
+
)
|
|
522
|
+
}
|
|
523
|
+
return baseAddressOptions
|
|
524
|
+
}
|
|
525
|
+
})()
|
|
526
|
+
addressLoadPromiseRef.current = { orderId, promise: request }
|
|
527
|
+
void request.then(() => {
|
|
528
|
+
if (addressLoadPromiseRef.current?.promise === request) {
|
|
529
|
+
addressLoadPromiseRef.current = null
|
|
530
|
+
setAddressLoading(false)
|
|
531
|
+
}
|
|
532
|
+
})
|
|
533
|
+
return request
|
|
534
|
+
}, [baseAddressOptions, mapDocumentAddressOption, mergeAddressOptions, orderId, t])
|
|
513
535
|
|
|
514
536
|
const buildPriceSubtitle = React.useCallback(
|
|
515
537
|
(option: ShippingMethodOption): string | undefined => {
|
|
@@ -851,16 +873,20 @@ export function ShipmentDialog({
|
|
|
851
873
|
)
|
|
852
874
|
|
|
853
875
|
React.useEffect(() => {
|
|
854
|
-
if (!open)
|
|
876
|
+
if (!open) {
|
|
877
|
+
initializedDialogKeyRef.current = null
|
|
878
|
+
return
|
|
879
|
+
}
|
|
880
|
+
const dialogKey = `${orderId}:${mode}:${shipment?.id ?? 'new'}`
|
|
881
|
+
if (initializedDialogKeyRef.current === dialogKey) return
|
|
882
|
+
initializedDialogKeyRef.current = dialogKey
|
|
855
883
|
setFormResetKey((prev) => prev + 1)
|
|
856
884
|
if (!shippingMethods.length) {
|
|
857
885
|
void loadShippingMethods()
|
|
858
886
|
}
|
|
859
887
|
setAddressOptions(baseAddressOptions)
|
|
860
888
|
setAddressError(null)
|
|
861
|
-
|
|
862
|
-
void loadAddressOptions()
|
|
863
|
-
}
|
|
889
|
+
void loadAddressOptions()
|
|
864
890
|
if (!shipmentStatuses.length) {
|
|
865
891
|
void loadShipmentStatuses()
|
|
866
892
|
}
|
|
@@ -871,7 +897,6 @@ export function ShipmentDialog({
|
|
|
871
897
|
void loadLineStatuses()
|
|
872
898
|
}
|
|
873
899
|
}, [
|
|
874
|
-
addressOptions.length,
|
|
875
900
|
baseAddressOptions,
|
|
876
901
|
documentStatuses.length,
|
|
877
902
|
loadAddressOptions,
|
|
@@ -881,6 +906,8 @@ export function ShipmentDialog({
|
|
|
881
906
|
loadShippingMethods,
|
|
882
907
|
mode,
|
|
883
908
|
open,
|
|
909
|
+
orderId,
|
|
910
|
+
shipment?.id,
|
|
884
911
|
lineStatuses.length,
|
|
885
912
|
shipmentStatuses.length,
|
|
886
913
|
shippingMethods.length,
|
|
@@ -939,11 +966,9 @@ export function ShipmentDialog({
|
|
|
939
966
|
|
|
940
967
|
const fetchAddressItems = React.useCallback(
|
|
941
968
|
async (query?: string): Promise<LookupSelectItem[]> => {
|
|
942
|
-
|
|
943
|
-
await loadAddressOptions()
|
|
944
|
-
}
|
|
969
|
+
const options = addressOptions.length ? addressOptions : await loadAddressOptions()
|
|
945
970
|
const needle = query?.trim().toLowerCase() ?? ''
|
|
946
|
-
return
|
|
971
|
+
return options
|
|
947
972
|
.filter((option) => {
|
|
948
973
|
if (!needle) return true
|
|
949
974
|
return (
|
|
@@ -962,7 +987,7 @@ export function ShipmentDialog({
|
|
|
962
987
|
),
|
|
963
988
|
}))
|
|
964
989
|
},
|
|
965
|
-
[
|
|
990
|
+
[addressOptions, loadAddressOptions],
|
|
966
991
|
)
|
|
967
992
|
|
|
968
993
|
const validateItems = React.useCallback(
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
5
|
+
import { SALES_CHANNELS_TOGGLE_ID } from '../lib/salesChannelsToggleId'
|
|
6
|
+
|
|
7
|
+
export { SALES_CHANNELS_TOGGLE_ID }
|
|
8
|
+
|
|
9
|
+
const CACHE_TTL_MS = 60_000
|
|
10
|
+
|
|
11
|
+
type FeatureToggleCheckResponse = {
|
|
12
|
+
ok?: boolean
|
|
13
|
+
value?: unknown
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Fails open: channels stay visible unless the toggle explicitly resolves to
|
|
17
|
+
// false. A missing toggle definition (404) or an absent feature_toggles module
|
|
18
|
+
// must not hide sales channel UI.
|
|
19
|
+
async function fetchSalesChannelsEnabled(): Promise<boolean> {
|
|
20
|
+
try {
|
|
21
|
+
const call = await apiCall<FeatureToggleCheckResponse>(
|
|
22
|
+
`/api/feature_toggles/check/boolean?identifier=${SALES_CHANNELS_TOGGLE_ID}`,
|
|
23
|
+
)
|
|
24
|
+
if (!call.ok) return true
|
|
25
|
+
return !(call.result?.ok === true && call.result.value === false)
|
|
26
|
+
} catch {
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let cache: { value: Promise<boolean>; at: number } | null = null
|
|
32
|
+
|
|
33
|
+
function getSalesChannelsEnabled(): Promise<boolean> {
|
|
34
|
+
const now = Date.now()
|
|
35
|
+
if (!cache || now - cache.at > CACHE_TTL_MS) {
|
|
36
|
+
cache = { value: fetchSalesChannelsEnabled(), at: now }
|
|
37
|
+
}
|
|
38
|
+
return cache.value
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function useSalesChannelsEnabled(): { enabled: boolean; isLoading: boolean } {
|
|
42
|
+
const [resolved, setResolved] = React.useState<boolean | null>(null)
|
|
43
|
+
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
let active = true
|
|
46
|
+
getSalesChannelsEnabled()
|
|
47
|
+
.then((value) => {
|
|
48
|
+
if (active) setResolved(value)
|
|
49
|
+
})
|
|
50
|
+
.catch(() => {
|
|
51
|
+
if (active) setResolved(true)
|
|
52
|
+
})
|
|
53
|
+
return () => {
|
|
54
|
+
active = false
|
|
55
|
+
}
|
|
56
|
+
}, [])
|
|
57
|
+
|
|
58
|
+
return { enabled: resolved !== false, isLoading: resolved === null }
|
|
59
|
+
}
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"sales.channels.actions.backToList": "Zurück zu Kanälen",
|
|
61
61
|
"sales.channels.actions.create": "Kanal hinzufügen",
|
|
62
62
|
"sales.channels.create": "Vertriebskanal erstellen",
|
|
63
|
+
"sales.channels.disabledNotice": "Vertriebskanäle sind für diesen Mandanten deaktiviert. Aktivieren Sie das Feature-Toggle \"Sales Channels\", um sie zu verwalten.",
|
|
63
64
|
"sales.channels.form.address1": "Adresszeile 1",
|
|
64
65
|
"sales.channels.form.address2": "Adresszeile 2",
|
|
65
66
|
"sales.channels.form.city": "Stadt",
|
|
@@ -638,8 +639,10 @@
|
|
|
638
639
|
"sales.documents.detail.items.errorDelete": "Position konnte nicht gelöscht werden.",
|
|
639
640
|
"sales.documents.detail.items.errorDeleteShipped": "Positionen mit versandten Artikeln können nicht gelöscht werden.",
|
|
640
641
|
"sales.documents.detail.items.errorLoad": "Positionen konnten nicht geladen werden.",
|
|
642
|
+
"sales.documents.detail.items.errorPriceShipped": "Preis oder Einheit einer Position mit versandten Artikeln können nicht geändert werden.",
|
|
641
643
|
"sales.documents.detail.items.errorProductRequired": "Wähle ein Produkt aus, um fortzufahren.",
|
|
642
644
|
"sales.documents.detail.items.errorQuantity": "Die Menge muss größer als 0 sein.",
|
|
645
|
+
"sales.documents.detail.items.errorQuantityBelowShipped": "Die Menge kann nicht unter die bereits versandten {{shipped}} gesenkt werden.",
|
|
643
646
|
"sales.documents.detail.items.errorSave": "Position konnte nicht gespeichert werden.",
|
|
644
647
|
"sales.documents.detail.items.errorUnitPrice": "Der Stückpreis muss größer als 0 sein.",
|
|
645
648
|
"sales.documents.detail.items.errorVariantRequired": "Wähle eine Variante aus, um fortzufahren.",
|
|
@@ -950,8 +953,10 @@
|
|
|
950
953
|
"sales.documents.items.errorDeleteShipped": "Positionen mit versandten Artikeln können nicht gelöscht werden.",
|
|
951
954
|
"sales.documents.items.errorLoad": "Positionen konnten nicht geladen werden.",
|
|
952
955
|
"sales.documents.items.errorNameRequired": "Name ist für benutzerdefinierte Positionen erforderlich.",
|
|
956
|
+
"sales.documents.items.errorPriceShipped": "Preis oder Einheit einer Position mit versandten Artikeln können nicht geändert werden.",
|
|
953
957
|
"sales.documents.items.errorProductRequired": "Wähle ein Produkt aus, um fortzufahren.",
|
|
954
958
|
"sales.documents.items.errorQuantity": "Die Menge muss größer als 0 sein.",
|
|
959
|
+
"sales.documents.items.errorQuantityBelowShipped": "Die Menge kann nicht unter die bereits versandten {{shipped}} gesenkt werden.",
|
|
955
960
|
"sales.documents.items.errorSave": "Position konnte nicht gespeichert werden.",
|
|
956
961
|
"sales.documents.items.errorScope": "Organisation und Mandant sind erforderlich.",
|
|
957
962
|
"sales.documents.items.errorUnitPrice": "Der Stückpreis muss größer als 0 sein.",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"sales.channels.actions.backToList": "Back to channels",
|
|
61
61
|
"sales.channels.actions.create": "Add channel",
|
|
62
62
|
"sales.channels.create": "Create sales channel",
|
|
63
|
+
"sales.channels.disabledNotice": "Sales channels are disabled for this tenant. Enable the \"Sales Channels\" feature toggle to manage them.",
|
|
63
64
|
"sales.channels.form.address1": "Address line 1",
|
|
64
65
|
"sales.channels.form.address2": "Address line 2",
|
|
65
66
|
"sales.channels.form.city": "City",
|
|
@@ -638,8 +639,10 @@
|
|
|
638
639
|
"sales.documents.detail.items.errorDelete": "Failed to delete line.",
|
|
639
640
|
"sales.documents.detail.items.errorDeleteShipped": "You cannot delete a line that has shipped items.",
|
|
640
641
|
"sales.documents.detail.items.errorLoad": "Failed to load items.",
|
|
642
|
+
"sales.documents.detail.items.errorPriceShipped": "You cannot change the price or unit of a line that has shipped items.",
|
|
641
643
|
"sales.documents.detail.items.errorProductRequired": "Select a product to continue.",
|
|
642
644
|
"sales.documents.detail.items.errorQuantity": "Quantity must be greater than 0.",
|
|
645
|
+
"sales.documents.detail.items.errorQuantityBelowShipped": "You cannot lower the quantity below the {{shipped}} already shipped.",
|
|
643
646
|
"sales.documents.detail.items.errorSave": "Failed to save line.",
|
|
644
647
|
"sales.documents.detail.items.errorUnitPrice": "Unit price must be greater than 0.",
|
|
645
648
|
"sales.documents.detail.items.errorVariantRequired": "Select a variant to continue.",
|
|
@@ -950,8 +953,10 @@
|
|
|
950
953
|
"sales.documents.items.errorDeleteShipped": "You cannot delete a line that has shipped items.",
|
|
951
954
|
"sales.documents.items.errorLoad": "Failed to load items.",
|
|
952
955
|
"sales.documents.items.errorNameRequired": "Name is required for custom lines.",
|
|
956
|
+
"sales.documents.items.errorPriceShipped": "You cannot change the price or unit of a line that has shipped items.",
|
|
953
957
|
"sales.documents.items.errorProductRequired": "Select a product to continue.",
|
|
954
958
|
"sales.documents.items.errorQuantity": "Quantity must be greater than 0.",
|
|
959
|
+
"sales.documents.items.errorQuantityBelowShipped": "You cannot lower the quantity below the {{shipped}} already shipped.",
|
|
955
960
|
"sales.documents.items.errorSave": "Failed to save line.",
|
|
956
961
|
"sales.documents.items.errorScope": "Organization and tenant are required.",
|
|
957
962
|
"sales.documents.items.errorUnitPrice": "Unit price must be greater than 0.",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"sales.channels.actions.backToList": "Volver a canales",
|
|
61
61
|
"sales.channels.actions.create": "Añadir canal",
|
|
62
62
|
"sales.channels.create": "Crear canal de ventas",
|
|
63
|
+
"sales.channels.disabledNotice": "Los canales de venta están desactivados para este inquilino. Active el conmutador de función \"Sales Channels\" para gestionarlos.",
|
|
63
64
|
"sales.channels.form.address1": "Línea de dirección 1",
|
|
64
65
|
"sales.channels.form.address2": "Línea de dirección 2",
|
|
65
66
|
"sales.channels.form.city": "Ciudad",
|
|
@@ -638,8 +639,10 @@
|
|
|
638
639
|
"sales.documents.detail.items.errorDelete": "No se pudo eliminar la línea.",
|
|
639
640
|
"sales.documents.detail.items.errorDeleteShipped": "No puedes eliminar una línea que ya tiene envíos.",
|
|
640
641
|
"sales.documents.detail.items.errorLoad": "No se pudieron cargar los artículos.",
|
|
642
|
+
"sales.documents.detail.items.errorPriceShipped": "No puedes cambiar el precio ni la unidad de una línea que ya tiene envíos.",
|
|
641
643
|
"sales.documents.detail.items.errorProductRequired": "Selecciona un producto para continuar.",
|
|
642
644
|
"sales.documents.detail.items.errorQuantity": "La cantidad debe ser mayor que 0.",
|
|
645
|
+
"sales.documents.detail.items.errorQuantityBelowShipped": "No puedes reducir la cantidad por debajo de las {{shipped}} ya enviadas.",
|
|
643
646
|
"sales.documents.detail.items.errorSave": "No se pudo guardar la línea.",
|
|
644
647
|
"sales.documents.detail.items.errorUnitPrice": "El precio unitario debe ser mayor que 0.",
|
|
645
648
|
"sales.documents.detail.items.errorVariantRequired": "Selecciona una variante para continuar.",
|
|
@@ -950,8 +953,10 @@
|
|
|
950
953
|
"sales.documents.items.errorDeleteShipped": "No puedes eliminar una línea que ya tiene envíos.",
|
|
951
954
|
"sales.documents.items.errorLoad": "No se pudieron cargar los artículos.",
|
|
952
955
|
"sales.documents.items.errorNameRequired": "El nombre es obligatorio para líneas personalizadas.",
|
|
956
|
+
"sales.documents.items.errorPriceShipped": "No puedes cambiar el precio ni la unidad de una línea que ya tiene envíos.",
|
|
953
957
|
"sales.documents.items.errorProductRequired": "Selecciona un producto para continuar.",
|
|
954
958
|
"sales.documents.items.errorQuantity": "La cantidad debe ser mayor que 0.",
|
|
959
|
+
"sales.documents.items.errorQuantityBelowShipped": "No puedes reducir la cantidad por debajo de las {{shipped}} ya enviadas.",
|
|
955
960
|
"sales.documents.items.errorSave": "No se pudo guardar la línea.",
|
|
956
961
|
"sales.documents.items.errorScope": "Se requieren organización e inquilino.",
|
|
957
962
|
"sales.documents.items.errorUnitPrice": "El precio unitario debe ser mayor que 0.",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"sales.channels.actions.backToList": "Powrót do kanałów",
|
|
61
61
|
"sales.channels.actions.create": "Dodaj kanał",
|
|
62
62
|
"sales.channels.create": "Utwórz kanał sprzedaży",
|
|
63
|
+
"sales.channels.disabledNotice": "Kanały sprzedaży są wyłączone dla tego najemcy. Włącz przełącznik funkcji \"Sales Channels\", aby nimi zarządzać.",
|
|
63
64
|
"sales.channels.form.address1": "Adres linia 1",
|
|
64
65
|
"sales.channels.form.address2": "Adres linia 2",
|
|
65
66
|
"sales.channels.form.city": "Miasto",
|
|
@@ -638,8 +639,10 @@
|
|
|
638
639
|
"sales.documents.detail.items.errorDelete": "Nie udało się usunąć pozycji.",
|
|
639
640
|
"sales.documents.detail.items.errorDeleteShipped": "Nie można usunąć pozycji, która ma wysłane sztuki.",
|
|
640
641
|
"sales.documents.detail.items.errorLoad": "Nie udało się wczytać pozycji.",
|
|
642
|
+
"sales.documents.detail.items.errorPriceShipped": "Nie można zmienić ceny ani jednostki pozycji, która ma wysłane sztuki.",
|
|
641
643
|
"sales.documents.detail.items.errorProductRequired": "Wybierz produkt, aby kontynuować.",
|
|
642
644
|
"sales.documents.detail.items.errorQuantity": "Ilość musi być większa niż 0.",
|
|
645
|
+
"sales.documents.detail.items.errorQuantityBelowShipped": "Nie można obniżyć ilości poniżej {{shipped}} już wysłanych.",
|
|
643
646
|
"sales.documents.detail.items.errorSave": "Nie udało się zapisać pozycji.",
|
|
644
647
|
"sales.documents.detail.items.errorUnitPrice": "Cena jednostkowa musi być większa niż 0.",
|
|
645
648
|
"sales.documents.detail.items.errorVariantRequired": "Wybierz wariant, aby kontynuować.",
|
|
@@ -950,8 +953,10 @@
|
|
|
950
953
|
"sales.documents.items.errorDeleteShipped": "Nie można usunąć pozycji, która ma wysłane sztuki.",
|
|
951
954
|
"sales.documents.items.errorLoad": "Nie udało się załadować pozycji.",
|
|
952
955
|
"sales.documents.items.errorNameRequired": "Nazwa jest wymagana dla niestandardowych pozycji.",
|
|
956
|
+
"sales.documents.items.errorPriceShipped": "Nie można zmienić ceny ani jednostki pozycji, która ma wysłane sztuki.",
|
|
953
957
|
"sales.documents.items.errorProductRequired": "Wybierz produkt, aby kontynuować.",
|
|
954
958
|
"sales.documents.items.errorQuantity": "Ilość musi być większa niż 0.",
|
|
959
|
+
"sales.documents.items.errorQuantityBelowShipped": "Nie można obniżyć ilości poniżej {{shipped}} już wysłanych.",
|
|
955
960
|
"sales.documents.items.errorSave": "Nie udało się zapisać pozycji.",
|
|
956
961
|
"sales.documents.items.errorScope": "Wymagane są organizacja i najemca.",
|
|
957
962
|
"sales.documents.items.errorUnitPrice": "Cena jednostkowa musi być większa niż 0.",
|
|
@@ -208,6 +208,21 @@ function buildBaseDocumentResult(params: {
|
|
|
208
208
|
}
|
|
209
209
|
break
|
|
210
210
|
default:
|
|
211
|
+
// `return` (credit) adjustments are handled by the dedicated loop below;
|
|
212
|
+
// skip them here so an order-scoped return is not counted twice.
|
|
213
|
+
if (adj.kind === 'return') break
|
|
214
|
+
// Custom / operator-defined kinds carry an operator-controlled sign
|
|
215
|
+
// (positive adds, negative credits). Fold the raw signed amount into the
|
|
216
|
+
// grand total so a persisted adjustment can never be silently dropped
|
|
217
|
+
// from the headline total while still appearing in the itemized
|
|
218
|
+
// breakdown (#4052). No abs()/clamp here: unlike the sign-constrained
|
|
219
|
+
// kinds above, custom kinds are intentionally unconstrained
|
|
220
|
+
// (see enforceAdjustmentSign).
|
|
221
|
+
subtotalNet += net
|
|
222
|
+
subtotalGross += gross
|
|
223
|
+
if (taxPortion) {
|
|
224
|
+
taxTotal += taxPortion
|
|
225
|
+
}
|
|
211
226
|
break
|
|
212
227
|
}
|
|
213
228
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SALES_CHANNELS_TOGGLE_ID } from './salesChannelsToggleId'
|
|
2
|
+
|
|
3
|
+
export { SALES_CHANNELS_TOGGLE_ID }
|
|
4
|
+
|
|
5
|
+
type BoolConfigResult = { ok: boolean; value?: unknown }
|
|
6
|
+
|
|
7
|
+
type FeatureTogglesServiceLike = {
|
|
8
|
+
getBoolConfig: (identifier: string, tenantId: string) => Promise<BoolConfigResult>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Server-side counterpart of useSalesChannelsEnabled with the same fail-open
|
|
12
|
+
// contract: channels stay enabled unless the toggle explicitly resolves to
|
|
13
|
+
// false. The DI container and feature_toggles service are optional peers, so
|
|
14
|
+
// they are loaded lazily and any failure keeps channels visible.
|
|
15
|
+
export async function isSalesChannelsEnabledForTenant(tenantId: string | null | undefined): Promise<boolean> {
|
|
16
|
+
if (!tenantId) return true
|
|
17
|
+
try {
|
|
18
|
+
const { createRequestContainer } = await import('@open-mercato/shared/lib/di/container')
|
|
19
|
+
const container = await createRequestContainer()
|
|
20
|
+
const service = container.resolve('featureTogglesService') as FeatureTogglesServiceLike
|
|
21
|
+
const result = await service.getBoolConfig(SALES_CHANNELS_TOGGLE_ID, tenantId)
|
|
22
|
+
return !(result.ok === true && result.value === false)
|
|
23
|
+
} catch {
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SALES_CHANNELS_TOGGLE_ID = 'sales_channels_enabled'
|
|
@@ -136,4 +136,34 @@ export const refreshShipmentItemsSnapshot = async (
|
|
|
136
136
|
return snapshot
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
export const loadShippedQuantityByLine = async (
|
|
140
|
+
em: EntityManager,
|
|
141
|
+
orderId: string,
|
|
142
|
+
scope: { tenantId: string; organizationId: string },
|
|
143
|
+
): Promise<Map<string, number>> => {
|
|
144
|
+
const shipments = await findWithDecryption(
|
|
145
|
+
em,
|
|
146
|
+
SalesShipment,
|
|
147
|
+
{ order: orderId, deletedAt: null },
|
|
148
|
+
{},
|
|
149
|
+
scope,
|
|
150
|
+
)
|
|
151
|
+
const shippedByLine = new Map<string, number>()
|
|
152
|
+
if (!shipments.length) return shippedByLine
|
|
153
|
+
const items = await findWithDecryption(
|
|
154
|
+
em,
|
|
155
|
+
SalesShipmentItem,
|
|
156
|
+
{ shipment: { $in: shipments.map((shipment) => shipment.id) } },
|
|
157
|
+
{},
|
|
158
|
+
scope,
|
|
159
|
+
)
|
|
160
|
+
items.forEach((item) => {
|
|
161
|
+
const orderLineId = typeof item.orderLine === 'string' ? item.orderLine : (item.orderLine?.id ?? null)
|
|
162
|
+
if (!orderLineId) return
|
|
163
|
+
const next = (shippedByLine.get(orderLineId) ?? 0) + coerceShipmentQuantity(item.quantity)
|
|
164
|
+
shippedByLine.set(orderLineId, next)
|
|
165
|
+
})
|
|
166
|
+
return shippedByLine
|
|
167
|
+
}
|
|
168
|
+
|
|
139
169
|
export type { ShipmentItemSnapshot } from './types'
|
|
@@ -5,6 +5,7 @@ import Link from 'next/link'
|
|
|
5
5
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
|
6
6
|
import { Page, PageBody } from '@open-mercato/ui/backend/Page'
|
|
7
7
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
8
|
+
import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
|
|
8
9
|
import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
9
10
|
import { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'
|
|
10
11
|
import { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
|
|
@@ -432,29 +433,22 @@ export default function StaffTeamMemberDetailPage({ params }: { params?: { id?:
|
|
|
432
433
|
</div>
|
|
433
434
|
</div>
|
|
434
435
|
|
|
435
|
-
<
|
|
436
|
-
|
|
437
|
-
|
|
436
|
+
<Tabs
|
|
437
|
+
value={activePanel}
|
|
438
|
+
onValueChange={(value) => setActivePanel(value as 'details' | 'availability' | 'jobHistory')}
|
|
439
|
+
variant="underline"
|
|
440
|
+
>
|
|
441
|
+
<TabsList
|
|
442
|
+
className="w-full flex-wrap"
|
|
438
443
|
aria-label={t('staff.teamMembers.detail.tabs.label', 'Team member sections')}
|
|
439
444
|
>
|
|
440
445
|
{panelTabs.map((tab) => (
|
|
441
|
-
<
|
|
442
|
-
key={tab.id}
|
|
443
|
-
type="button"
|
|
444
|
-
role="tab"
|
|
445
|
-
aria-selected={activePanel === tab.id}
|
|
446
|
-
onClick={() => setActivePanel(tab.id)}
|
|
447
|
-
className={`relative -mb-px border-b-2 px-0 py-2 text-sm font-medium transition-colors ${
|
|
448
|
-
activePanel === tab.id
|
|
449
|
-
? 'border-accent-indigo text-foreground'
|
|
450
|
-
: 'border-transparent text-muted-foreground hover:text-foreground'
|
|
451
|
-
}`}
|
|
452
|
-
>
|
|
446
|
+
<TabsTrigger key={tab.id} value={tab.id}>
|
|
453
447
|
{tab.label}
|
|
454
|
-
</
|
|
448
|
+
</TabsTrigger>
|
|
455
449
|
))}
|
|
456
|
-
</
|
|
457
|
-
</
|
|
450
|
+
</TabsList>
|
|
451
|
+
</Tabs>
|
|
458
452
|
|
|
459
453
|
{activePanel === 'details' ? (
|
|
460
454
|
<>
|
|
@@ -500,22 +494,19 @@ export default function StaffTeamMemberDetailPage({ params }: { params?: { id?:
|
|
|
500
494
|
|
|
501
495
|
<div className="rounded-lg border bg-card p-4">
|
|
502
496
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
503
|
-
<
|
|
504
|
-
{
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
</button>
|
|
517
|
-
))}
|
|
518
|
-
</div>
|
|
497
|
+
<Tabs
|
|
498
|
+
value={activeTab}
|
|
499
|
+
onValueChange={(value) => setActiveTab(value as 'notes' | 'activities' | 'addresses')}
|
|
500
|
+
variant="underline"
|
|
501
|
+
>
|
|
502
|
+
<TabsList className="h-auto flex-wrap border-b-0">
|
|
503
|
+
{tabs.map((tab) => (
|
|
504
|
+
<TabsTrigger key={tab.id} value={tab.id}>
|
|
505
|
+
{tab.label}
|
|
506
|
+
</TabsTrigger>
|
|
507
|
+
))}
|
|
508
|
+
</TabsList>
|
|
509
|
+
</Tabs>
|
|
519
510
|
{sectionAction ? (
|
|
520
511
|
<Button
|
|
521
512
|
type="button"
|
|
@@ -12,6 +12,7 @@ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimi
|
|
|
12
12
|
import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
|
|
13
13
|
import { RowActions } from '@open-mercato/ui/backend/RowActions'
|
|
14
14
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
15
|
+
import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
|
|
15
16
|
import { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'
|
|
16
17
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
17
18
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
@@ -362,29 +363,22 @@ export default function StaffTeamEditPage({ params }: { params?: { id?: string }
|
|
|
362
363
|
<Page>
|
|
363
364
|
<PageBody>
|
|
364
365
|
<div className="space-y-6">
|
|
365
|
-
<
|
|
366
|
-
|
|
366
|
+
<Tabs
|
|
367
|
+
value={activeTab}
|
|
368
|
+
onValueChange={(value) => setActiveTab(value as 'details' | 'members')}
|
|
369
|
+
variant="underline"
|
|
370
|
+
>
|
|
371
|
+
<TabsList className="w-full flex-wrap" aria-label={memberLabels.tabs.label}>
|
|
367
372
|
{[
|
|
368
373
|
{ id: 'details', label: memberLabels.tabs.details },
|
|
369
374
|
{ id: 'members', label: memberLabels.tabs.members },
|
|
370
375
|
].map((tab) => (
|
|
371
|
-
<
|
|
372
|
-
key={tab.id}
|
|
373
|
-
type="button"
|
|
374
|
-
role="tab"
|
|
375
|
-
aria-selected={activeTab === tab.id}
|
|
376
|
-
onClick={() => setActiveTab(tab.id as 'details' | 'members')}
|
|
377
|
-
className={`relative -mb-px border-b-2 px-0 py-2 text-sm font-medium transition-colors ${
|
|
378
|
-
activeTab === tab.id
|
|
379
|
-
? 'border-accent-indigo text-foreground'
|
|
380
|
-
: 'border-transparent text-muted-foreground hover:text-foreground'
|
|
381
|
-
}`}
|
|
382
|
-
>
|
|
376
|
+
<TabsTrigger key={tab.id} value={tab.id}>
|
|
383
377
|
{tab.label}
|
|
384
|
-
</
|
|
378
|
+
</TabsTrigger>
|
|
385
379
|
))}
|
|
386
|
-
</
|
|
387
|
-
</
|
|
380
|
+
</TabsList>
|
|
381
|
+
</Tabs>
|
|
388
382
|
|
|
389
383
|
{activeTab === 'details' ? (
|
|
390
384
|
<TeamForm
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
|
-
import {
|
|
4
|
+
import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
|
|
5
5
|
|
|
6
6
|
export type SavedViewTab = {
|
|
7
7
|
id: string
|
|
@@ -19,35 +19,18 @@ export type SavedViewTabsProps = {
|
|
|
19
19
|
|
|
20
20
|
export function SavedViewTabs({ tabs, activeId, onSelect, className, ariaLabel }: SavedViewTabsProps) {
|
|
21
21
|
return (
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
>
|
|
27
|
-
{tabs.map((tab) => {
|
|
28
|
-
const isActive = tab.id === activeId
|
|
29
|
-
return (
|
|
30
|
-
<Button
|
|
22
|
+
<Tabs value={activeId} onValueChange={onSelect} variant="underline" className={className}>
|
|
23
|
+
<TabsList className="w-full flex-wrap" aria-label={ariaLabel ?? 'Saved views'}>
|
|
24
|
+
{tabs.map((tab) => (
|
|
25
|
+
<TabsTrigger
|
|
31
26
|
key={tab.id}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
size="sm"
|
|
35
|
-
role="tab"
|
|
36
|
-
aria-selected={isActive}
|
|
37
|
-
className={`h-auto rounded-none px-3 py-2 text-sm hover:bg-transparent ${
|
|
38
|
-
isActive
|
|
39
|
-
? 'border-b-2 border-foreground font-medium text-foreground'
|
|
40
|
-
: 'border-b-2 border-transparent text-muted-foreground hover:text-foreground'
|
|
41
|
-
}`}
|
|
42
|
-
onClick={() => onSelect(tab.id)}
|
|
27
|
+
value={tab.id}
|
|
28
|
+
count={typeof tab.count === 'number' ? tab.count : undefined}
|
|
43
29
|
>
|
|
44
30
|
{tab.label}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
50
|
-
})}
|
|
51
|
-
</div>
|
|
31
|
+
</TabsTrigger>
|
|
32
|
+
))}
|
|
33
|
+
</TabsList>
|
|
34
|
+
</Tabs>
|
|
52
35
|
)
|
|
53
36
|
}
|