@open-mercato/core 0.6.7-develop.6726.1.983ae8a07e → 0.6.7-develop.6749.1.6b54c56dfe
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 +1 -1
- package/dist/generated/entities/resources_resource/index.js +2 -0
- package/dist/generated/entities/resources_resource/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +1 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/salesFixtures.js +31 -2
- package/dist/helpers/integration/salesFixtures.js.map +2 -2
- package/dist/helpers/integration/salesUi.js +5 -0
- package/dist/helpers/integration/salesUi.js.map +2 -2
- package/dist/modules/auth/api/profile/route.js +8 -2
- package/dist/modules/auth/api/profile/route.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js.map +2 -2
- package/dist/modules/auth/backend/profile/change-password/page.js.map +2 -2
- package/dist/modules/communication_channels/data/enrichers.js +4 -4
- package/dist/modules/communication_channels/data/enrichers.js.map +2 -2
- package/dist/modules/customers/analytics.js +1 -0
- package/dist/modules/customers/analytics.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +2 -1
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +1 -1
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/data/validators.js +3 -1
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/config.js +52 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/config.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +42 -26
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/data_sync/lib/queue-policy.js +15 -0
- package/dist/modules/data_sync/lib/queue-policy.js.map +7 -0
- package/dist/modules/data_sync/lib/queue.js +16 -1
- package/dist/modules/data_sync/lib/queue.js.map +2 -2
- package/dist/modules/data_sync/lib/start-run.js +2 -1
- package/dist/modules/data_sync/lib/start-run.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js +35 -2
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-run-service.js +70 -2
- package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-export.js +9 -2
- package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-import.js +9 -2
- package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +34 -12
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
- package/dist/modules/dictionaries/api/openapi.js +15 -2
- package/dist/modules/dictionaries/api/openapi.js.map +2 -2
- package/dist/modules/dictionaries/components/hooks/useDictionaryEntries.js +30 -29
- package/dist/modules/dictionaries/components/hooks/useDictionaryEntries.js.map +2 -2
- package/dist/modules/dictionaries/data/validators.js +7 -0
- package/dist/modules/dictionaries/data/validators.js.map +2 -2
- package/dist/modules/dictionaries/lib/clientEntries.js +4 -3
- package/dist/modules/dictionaries/lib/clientEntries.js.map +2 -2
- package/dist/modules/dictionaries/lib/fetchAllEntries.js +43 -0
- package/dist/modules/dictionaries/lib/fetchAllEntries.js.map +7 -0
- package/dist/modules/entities/api/definitions.js +51 -3
- package/dist/modules/entities/api/definitions.js.map +2 -2
- package/dist/modules/entities/api/entities.js +21 -2
- package/dist/modules/entities/api/entities.js.map +2 -2
- package/dist/modules/entities/api/records.js +3 -24
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/api/sidebar-entities.js +34 -12
- package/dist/modules/entities/api/sidebar-entities.js.map +2 -2
- package/dist/modules/entities/lib/entityAcl.js +46 -0
- package/dist/modules/entities/lib/entityAcl.js.map +2 -2
- package/dist/modules/messages/api/route.js +2 -5
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/lib/participantScope.js +15 -0
- package/dist/modules/messages/lib/participantScope.js.map +7 -0
- package/dist/modules/notifications/api/route.js +3 -1
- package/dist/modules/notifications/api/route.js.map +2 -2
- package/dist/modules/notifications/api/unread-count/route.js +25 -6
- package/dist/modules/notifications/api/unread-count/route.js.map +2 -2
- package/dist/modules/notifications/lib/notificationScope.js +26 -0
- package/dist/modules/notifications/lib/notificationScope.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +7 -3
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/notifications/lib/routeHelpers.js +16 -2
- package/dist/modules/notifications/lib/routeHelpers.js.map +2 -2
- package/dist/modules/planner/components/unavailabilityReasons.js +3 -3
- package/dist/modules/planner/components/unavailabilityReasons.js.map +2 -2
- package/dist/modules/progress/lib/progressService.js +2 -0
- package/dist/modules/progress/lib/progressService.js.map +2 -2
- package/dist/modules/progress/lib/progressServiceImpl.js +322 -104
- package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
- package/dist/modules/resources/api/resources.js +2 -0
- package/dist/modules/resources/api/resources.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +3 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/resources/commands/resources.js +9 -0
- package/dist/modules/resources/commands/resources.js.map +2 -2
- package/dist/modules/resources/components/detail/dictionaries.js +3 -3
- package/dist/modules/resources/components/detail/dictionaries.js.map +2 -2
- package/dist/modules/resources/data/entities.js +3 -0
- package/dist/modules/resources/data/entities.js.map +2 -2
- package/dist/modules/resources/data/validators.js +6 -2
- package/dist/modules/resources/data/validators.js.map +2 -2
- package/dist/modules/resources/lib/seeds.js +16 -9
- package/dist/modules/resources/lib/seeds.js.map +2 -2
- package/dist/modules/resources/migrations/Migration20260608231000.js +13 -0
- package/dist/modules/resources/migrations/Migration20260608231000.js.map +7 -0
- package/dist/modules/sales/backend/sales/documents/create/page.js +11 -14
- package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +8 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +18 -9
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +12 -5
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +48 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js +167 -0
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js.map +7 -0
- package/dist/modules/sales/data/validators.js +5 -1
- package/dist/modules/sales/data/validators.js.map +2 -2
- package/dist/modules/staff/components/detail/dictionaries.js +3 -3
- package/dist/modules/staff/components/detail/dictionaries.js.map +2 -2
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +11 -4
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +2 -2
- package/generated/entities/resources_resource/index.ts +1 -0
- package/generated/entity-fields-registry.ts +1 -0
- package/package.json +7 -7
- package/src/helpers/integration/salesFixtures.ts +34 -2
- package/src/helpers/integration/salesUi.ts +8 -0
- package/src/modules/auth/api/profile/route.ts +8 -2
- package/src/modules/auth/backend/auth/profile/page.tsx +1 -0
- package/src/modules/auth/backend/profile/change-password/page.tsx +1 -0
- package/src/modules/communication_channels/data/enrichers.ts +6 -26
- package/src/modules/customers/analytics.ts +1 -0
- package/src/modules/customers/components/detail/DealForm.tsx +5 -1
- package/src/modules/customers/components/detail/DealsSection.tsx +1 -1
- package/src/modules/customers/data/validators.ts +5 -1
- package/src/modules/dashboards/i18n/de.json +3 -0
- package/src/modules/dashboards/i18n/en.json +3 -0
- package/src/modules/dashboards/i18n/es.json +3 -0
- package/src/modules/dashboards/i18n/pl.json +3 -0
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/config.ts +86 -0
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +33 -18
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
- package/src/modules/data_sync/lib/adapter.ts +18 -0
- package/src/modules/data_sync/lib/queue-policy.ts +30 -0
- package/src/modules/data_sync/lib/queue.ts +19 -1
- package/src/modules/data_sync/lib/start-run.ts +2 -1
- package/src/modules/data_sync/lib/sync-engine.ts +46 -0
- package/src/modules/data_sync/lib/sync-run-service.ts +82 -1
- package/src/modules/data_sync/workers/sync-export.ts +8 -1
- package/src/modules/data_sync/workers/sync-import.ts +8 -1
- package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +39 -11
- package/src/modules/dictionaries/api/openapi.ts +19 -0
- package/src/modules/dictionaries/components/hooks/useDictionaryEntries.ts +35 -36
- package/src/modules/dictionaries/data/validators.ts +14 -0
- package/src/modules/dictionaries/lib/clientEntries.ts +4 -3
- package/src/modules/dictionaries/lib/fetchAllEntries.ts +72 -0
- package/src/modules/entities/api/definitions.ts +51 -3
- package/src/modules/entities/api/entities.ts +30 -2
- package/src/modules/entities/api/records.ts +3 -27
- package/src/modules/entities/api/sidebar-entities.ts +43 -14
- package/src/modules/entities/lib/entityAcl.ts +58 -0
- package/src/modules/messages/api/route.ts +4 -5
- package/src/modules/messages/lib/participantScope.ts +64 -0
- package/src/modules/notifications/api/route.ts +2 -0
- package/src/modules/notifications/api/unread-count/route.ts +42 -5
- package/src/modules/notifications/lib/notificationScope.ts +40 -0
- package/src/modules/notifications/lib/notificationService.ts +5 -0
- package/src/modules/notifications/lib/routeHelpers.ts +19 -2
- package/src/modules/planner/components/unavailabilityReasons.ts +3 -3
- package/src/modules/progress/AGENTS.md +11 -1
- package/src/modules/progress/lib/progressService.ts +1 -0
- package/src/modules/progress/lib/progressServiceImpl.ts +385 -117
- package/src/modules/resources/api/resources.ts +2 -0
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +9 -3
- package/src/modules/resources/commands/resources.ts +10 -0
- package/src/modules/resources/components/detail/dictionaries.ts +3 -3
- package/src/modules/resources/data/entities.ts +3 -0
- package/src/modules/resources/data/validators.ts +5 -0
- package/src/modules/resources/lib/seeds.ts +16 -9
- package/src/modules/resources/migrations/.snapshot-open-mercato.json +17 -1
- package/src/modules/resources/migrations/Migration20260608231000.ts +13 -0
- package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -4
- package/src/modules/sales/commands/documents.ts +8 -0
- package/src/modules/sales/components/documents/ItemsSection.tsx +19 -10
- package/src/modules/sales/components/documents/LineItemDialog.tsx +13 -5
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +48 -6
- package/src/modules/sales/components/documents/SalesOrderDraftLines.tsx +198 -0
- package/src/modules/sales/data/validators.ts +7 -1
- package/src/modules/sales/i18n/de.json +2 -0
- package/src/modules/sales/i18n/en.json +2 -0
- package/src/modules/sales/i18n/es.json +2 -0
- package/src/modules/sales/i18n/pl.json +2 -0
- package/src/modules/staff/components/detail/dictionaries.ts +3 -3
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +12 -5
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import type { ColumnDef } from '@tanstack/react-table'
|
|
5
|
+
import { Plus } from 'lucide-react'
|
|
6
|
+
import { DataTable } from '@open-mercato/ui/backend/DataTable'
|
|
7
|
+
import { RowActions } from '@open-mercato/ui/backend/RowActions'
|
|
8
|
+
import { EmptyState } from '@open-mercato/ui/primitives/empty-state'
|
|
9
|
+
import { Button } from '@open-mercato/ui/primitives/button'
|
|
10
|
+
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
11
|
+
import { LineItemDialog } from './LineItemDialog'
|
|
12
|
+
import type { SalesLineRecord } from './lineItemTypes'
|
|
13
|
+
import { formatMoney, normalizeNumber } from './lineItemUtils'
|
|
14
|
+
|
|
15
|
+
export type SalesOrderLineDraft = {
|
|
16
|
+
id: string
|
|
17
|
+
payload: Record<string, unknown>
|
|
18
|
+
record: SalesLineRecord
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type SalesOrderDraftLinesProps = {
|
|
22
|
+
currencyCode: string | null | undefined
|
|
23
|
+
organizationId: string | null
|
|
24
|
+
tenantId: string | null
|
|
25
|
+
lines: SalesOrderLineDraft[]
|
|
26
|
+
error?: string | null
|
|
27
|
+
onChange: (lines: SalesOrderLineDraft[]) => void
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function draftId(): string {
|
|
31
|
+
return typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
|
|
32
|
+
? crypto.randomUUID()
|
|
33
|
+
: `draft-${Date.now()}-${Math.round(performance.now())}`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function createSalesOrderLineDraft(
|
|
37
|
+
payload: Record<string, unknown>,
|
|
38
|
+
id = draftId(),
|
|
39
|
+
): SalesOrderLineDraft {
|
|
40
|
+
const quantity = normalizeNumber(payload.quantity, 0)
|
|
41
|
+
const unitPriceNet = normalizeNumber(payload.unitPriceNet, 0)
|
|
42
|
+
const unitPriceGross = normalizeNumber(payload.unitPriceGross, unitPriceNet)
|
|
43
|
+
const taxRate = normalizeNumber(payload.taxRate, 0)
|
|
44
|
+
const totalNet = normalizeNumber(payload.totalNetAmount, unitPriceNet * quantity)
|
|
45
|
+
const totalGross = normalizeNumber(payload.totalGrossAmount, unitPriceGross * quantity)
|
|
46
|
+
const metadata = payload.metadata && typeof payload.metadata === 'object'
|
|
47
|
+
? payload.metadata as Record<string, unknown>
|
|
48
|
+
: null
|
|
49
|
+
const catalogSnapshot = payload.catalogSnapshot && typeof payload.catalogSnapshot === 'object'
|
|
50
|
+
? payload.catalogSnapshot as Record<string, unknown>
|
|
51
|
+
: null
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
id,
|
|
55
|
+
payload: { ...payload },
|
|
56
|
+
record: {
|
|
57
|
+
id,
|
|
58
|
+
name: typeof payload.name === 'string' ? payload.name : null,
|
|
59
|
+
productId: typeof payload.productId === 'string' ? payload.productId : null,
|
|
60
|
+
productVariantId: typeof payload.productVariantId === 'string' ? payload.productVariantId : null,
|
|
61
|
+
quantity,
|
|
62
|
+
quantityUnit: typeof payload.quantityUnit === 'string' ? payload.quantityUnit : null,
|
|
63
|
+
normalizedQuantity: normalizeNumber(payload.normalizedQuantity, quantity),
|
|
64
|
+
normalizedUnit: typeof payload.normalizedUnit === 'string' ? payload.normalizedUnit : null,
|
|
65
|
+
currencyCode: typeof payload.currencyCode === 'string' ? payload.currencyCode : null,
|
|
66
|
+
unitPriceNet,
|
|
67
|
+
unitPriceGross,
|
|
68
|
+
taxRate,
|
|
69
|
+
totalNet,
|
|
70
|
+
totalGross,
|
|
71
|
+
priceMode: payload.priceMode === 'net' ? 'net' : 'gross',
|
|
72
|
+
uomSnapshot: null,
|
|
73
|
+
metadata,
|
|
74
|
+
catalogSnapshot,
|
|
75
|
+
customFieldSetId: typeof payload.customFieldSetId === 'string' ? payload.customFieldSetId : null,
|
|
76
|
+
customFields: payload.customFields && typeof payload.customFields === 'object'
|
|
77
|
+
? payload.customFields as Record<string, unknown>
|
|
78
|
+
: null,
|
|
79
|
+
status: null,
|
|
80
|
+
statusEntryId: typeof payload.statusEntryId === 'string' ? payload.statusEntryId : null,
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function SalesOrderDraftLines({
|
|
86
|
+
currencyCode,
|
|
87
|
+
organizationId,
|
|
88
|
+
tenantId,
|
|
89
|
+
lines,
|
|
90
|
+
error,
|
|
91
|
+
onChange,
|
|
92
|
+
}: SalesOrderDraftLinesProps) {
|
|
93
|
+
const t = useT()
|
|
94
|
+
const [dialogOpen, setDialogOpen] = React.useState(false)
|
|
95
|
+
const [editing, setEditing] = React.useState<SalesOrderLineDraft | null>(null)
|
|
96
|
+
|
|
97
|
+
const columns = React.useMemo<ColumnDef<SalesOrderLineDraft>[]>(() => [
|
|
98
|
+
{
|
|
99
|
+
id: 'name',
|
|
100
|
+
header: t('sales.documents.items.table.product', 'Product'),
|
|
101
|
+
cell: ({ row }) => row.original.record.name ?? t('sales.documents.items.untitled', 'Untitled'),
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: 'quantity',
|
|
105
|
+
header: t('sales.documents.items.table.quantity', 'Qty'),
|
|
106
|
+
cell: ({ row }) => row.original.record.quantityUnit
|
|
107
|
+
? `${row.original.record.quantity} ${row.original.record.quantityUnit}`
|
|
108
|
+
: row.original.record.quantity,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: 'unitPrice',
|
|
112
|
+
header: t('sales.documents.items.table.unit', 'Unit price'),
|
|
113
|
+
cell: ({ row }) => formatMoney(row.original.record.unitPriceGross, row.original.record.currencyCode ?? currencyCode ?? undefined),
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: 'total',
|
|
117
|
+
header: t('sales.documents.items.table.total', 'Total'),
|
|
118
|
+
cell: ({ row }) => formatMoney(row.original.record.totalGross, row.original.record.currencyCode ?? currencyCode ?? undefined),
|
|
119
|
+
},
|
|
120
|
+
], [currencyCode, t])
|
|
121
|
+
|
|
122
|
+
const openCreate = React.useCallback(() => {
|
|
123
|
+
setEditing(null)
|
|
124
|
+
setDialogOpen(true)
|
|
125
|
+
}, [])
|
|
126
|
+
|
|
127
|
+
const rowActions = React.useCallback((line: SalesOrderLineDraft) => (
|
|
128
|
+
<RowActions
|
|
129
|
+
items={[
|
|
130
|
+
{
|
|
131
|
+
id: 'edit',
|
|
132
|
+
label: t('ui.actions.edit', 'Edit'),
|
|
133
|
+
onSelect: () => {
|
|
134
|
+
setEditing(line)
|
|
135
|
+
setDialogOpen(true)
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: 'delete',
|
|
140
|
+
label: t('ui.actions.delete', 'Delete'),
|
|
141
|
+
destructive: true,
|
|
142
|
+
onSelect: () => onChange(lines.filter((candidate) => candidate.id !== line.id)),
|
|
143
|
+
},
|
|
144
|
+
]}
|
|
145
|
+
/>
|
|
146
|
+
), [lines, onChange, t])
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<div className="space-y-3">
|
|
150
|
+
<div className="flex items-center justify-between gap-4">
|
|
151
|
+
<div>
|
|
152
|
+
<h3 className="text-sm font-medium">{t('sales.orders.form.lines', 'Line Items')}</h3>
|
|
153
|
+
<p className="text-sm text-muted-foreground">
|
|
154
|
+
{t('sales.orders.linesRequired', 'Add at least one line item before creating the order.')}
|
|
155
|
+
</p>
|
|
156
|
+
</div>
|
|
157
|
+
<Button type="button" variant="outline" onClick={openCreate}>
|
|
158
|
+
<Plus className="h-4 w-4" aria-hidden="true" />
|
|
159
|
+
{t('sales.documents.items.add', 'Add item')}
|
|
160
|
+
</Button>
|
|
161
|
+
</div>
|
|
162
|
+
{error ? <p className="text-sm text-destructive" role="alert">{error}</p> : null}
|
|
163
|
+
<DataTable
|
|
164
|
+
columns={columns}
|
|
165
|
+
data={lines}
|
|
166
|
+
embedded
|
|
167
|
+
disableRowClick
|
|
168
|
+
rowActions={rowActions}
|
|
169
|
+
emptyState={(
|
|
170
|
+
<EmptyState
|
|
171
|
+
size="sm"
|
|
172
|
+
title={t('sales.documents.items.empty', 'No items yet.')}
|
|
173
|
+
description={t('sales.orders.linesRequired', 'Add at least one line item before creating the order.')}
|
|
174
|
+
actions={<Button type="button" variant="outline" size="sm" onClick={openCreate}>{t('sales.documents.items.add', 'Add item')}</Button>}
|
|
175
|
+
/>
|
|
176
|
+
)}
|
|
177
|
+
/>
|
|
178
|
+
<LineItemDialog
|
|
179
|
+
open={dialogOpen}
|
|
180
|
+
onOpenChange={(open) => {
|
|
181
|
+
setDialogOpen(open)
|
|
182
|
+
if (!open) setEditing(null)
|
|
183
|
+
}}
|
|
184
|
+
kind="order"
|
|
185
|
+
currencyCode={currencyCode}
|
|
186
|
+
organizationId={organizationId}
|
|
187
|
+
tenantId={tenantId}
|
|
188
|
+
initialLine={editing?.record ?? null}
|
|
189
|
+
onDraftSaved={(payload, lineId) => {
|
|
190
|
+
const draft = createSalesOrderLineDraft(payload, lineId ?? undefined)
|
|
191
|
+
onChange(lineId
|
|
192
|
+
? lines.map((line) => line.id === lineId ? draft : line)
|
|
193
|
+
: [...lines, draft])
|
|
194
|
+
}}
|
|
195
|
+
/>
|
|
196
|
+
</div>
|
|
197
|
+
)
|
|
198
|
+
}
|
|
@@ -679,6 +679,8 @@ const quoteTotalsSchema = z.object({
|
|
|
679
679
|
lineItemCount: z.coerce.number().int().min(0).optional(),
|
|
680
680
|
})
|
|
681
681
|
|
|
682
|
+
export const SALES_ORDER_LINES_REQUIRED_MESSAGE_KEY = 'sales.orders.linesRequired'
|
|
683
|
+
|
|
682
684
|
export const orderCreateSchema = scoped.extend({
|
|
683
685
|
orderNumber: z.string().trim().min(1).max(191).optional(),
|
|
684
686
|
externalReference: z.string().trim().max(191).optional(),
|
|
@@ -715,7 +717,11 @@ export const orderCreateSchema = scoped.extend({
|
|
|
715
717
|
paymentMethodSnapshot: jsonRecord.optional(),
|
|
716
718
|
metadata,
|
|
717
719
|
customFieldSetId: uuid().optional(),
|
|
718
|
-
lines: z
|
|
720
|
+
lines: z
|
|
721
|
+
.array(orderLineCreateSchema.omit({ organizationId: true, tenantId: true, orderId: true }), {
|
|
722
|
+
error: SALES_ORDER_LINES_REQUIRED_MESSAGE_KEY,
|
|
723
|
+
})
|
|
724
|
+
.min(1, SALES_ORDER_LINES_REQUIRED_MESSAGE_KEY),
|
|
719
725
|
adjustments: z.array(orderAdjustmentCreateSchema.omit({ organizationId: true, tenantId: true, orderId: true })).optional(),
|
|
720
726
|
tags: z.array(uuid()).optional(),
|
|
721
727
|
...orderTotalsSchema.shape,
|
|
@@ -950,6 +950,7 @@
|
|
|
950
950
|
"sales.documents.items.empty": "Noch keine Positionen.",
|
|
951
951
|
"sales.documents.items.errorCurrency": "Währung ist erforderlich.",
|
|
952
952
|
"sales.documents.items.errorDelete": "Position konnte nicht gelöscht werden.",
|
|
953
|
+
"sales.documents.items.errorDeleteLast": "Eine Bestellung muss mindestens eine Position enthalten.",
|
|
953
954
|
"sales.documents.items.errorDeleteShipped": "Positionen mit versandten Artikeln können nicht gelöscht werden.",
|
|
954
955
|
"sales.documents.items.errorLoad": "Positionen konnten nicht geladen werden.",
|
|
955
956
|
"sales.documents.items.errorNameRequired": "Name ist für benutzerdefinierte Positionen erforderlich.",
|
|
@@ -1226,6 +1227,7 @@
|
|
|
1226
1227
|
"sales.orders.form.shipments": "Sendungen",
|
|
1227
1228
|
"sales.orders.lines.delete": "Bestellposition löschen",
|
|
1228
1229
|
"sales.orders.lines.upsert": "Bestellposition aktualisieren",
|
|
1230
|
+
"sales.orders.linesRequired": "Fügen Sie vor dem Erstellen der Bestellung mindestens eine Position hinzu.",
|
|
1229
1231
|
"sales.orders.list.title": "Aufträge",
|
|
1230
1232
|
"sales.orders.status_change.actor_api_key": "API-Schlüssel {name}",
|
|
1231
1233
|
"sales.orders.status_change.actor_unknown": "Unbekannter Benutzer",
|
|
@@ -950,6 +950,7 @@
|
|
|
950
950
|
"sales.documents.items.empty": "No items yet.",
|
|
951
951
|
"sales.documents.items.errorCurrency": "Currency is required.",
|
|
952
952
|
"sales.documents.items.errorDelete": "Failed to delete line.",
|
|
953
|
+
"sales.documents.items.errorDeleteLast": "An order must contain at least one line item.",
|
|
953
954
|
"sales.documents.items.errorDeleteShipped": "You cannot delete a line that has shipped items.",
|
|
954
955
|
"sales.documents.items.errorLoad": "Failed to load items.",
|
|
955
956
|
"sales.documents.items.errorNameRequired": "Name is required for custom lines.",
|
|
@@ -1226,6 +1227,7 @@
|
|
|
1226
1227
|
"sales.orders.form.shipments": "Shipments",
|
|
1227
1228
|
"sales.orders.lines.delete": "Delete order line",
|
|
1228
1229
|
"sales.orders.lines.upsert": "Update order line",
|
|
1230
|
+
"sales.orders.linesRequired": "Add at least one line item before creating the order.",
|
|
1229
1231
|
"sales.orders.list.title": "Orders",
|
|
1230
1232
|
"sales.orders.status_change.actor_api_key": "API key {name}",
|
|
1231
1233
|
"sales.orders.status_change.actor_unknown": "Unknown user",
|
|
@@ -950,6 +950,7 @@
|
|
|
950
950
|
"sales.documents.items.empty": "Aún no hay artículos.",
|
|
951
951
|
"sales.documents.items.errorCurrency": "La moneda es obligatoria.",
|
|
952
952
|
"sales.documents.items.errorDelete": "No se pudo eliminar la línea.",
|
|
953
|
+
"sales.documents.items.errorDeleteLast": "Un pedido debe contener al menos una línea.",
|
|
953
954
|
"sales.documents.items.errorDeleteShipped": "No puedes eliminar una línea que ya tiene envíos.",
|
|
954
955
|
"sales.documents.items.errorLoad": "No se pudieron cargar los artículos.",
|
|
955
956
|
"sales.documents.items.errorNameRequired": "El nombre es obligatorio para líneas personalizadas.",
|
|
@@ -1226,6 +1227,7 @@
|
|
|
1226
1227
|
"sales.orders.form.shipments": "Envíos",
|
|
1227
1228
|
"sales.orders.lines.delete": "Eliminar línea de pedido",
|
|
1228
1229
|
"sales.orders.lines.upsert": "Actualizar línea de pedido",
|
|
1230
|
+
"sales.orders.linesRequired": "Añade al menos una línea antes de crear el pedido.",
|
|
1229
1231
|
"sales.orders.list.title": "Pedidos",
|
|
1230
1232
|
"sales.orders.status_change.actor_api_key": "Clave API {name}",
|
|
1231
1233
|
"sales.orders.status_change.actor_unknown": "Usuario desconocido",
|
|
@@ -950,6 +950,7 @@
|
|
|
950
950
|
"sales.documents.items.empty": "Brak pozycji.",
|
|
951
951
|
"sales.documents.items.errorCurrency": "Waluta jest wymagana.",
|
|
952
952
|
"sales.documents.items.errorDelete": "Nie udało się usunąć pozycji.",
|
|
953
|
+
"sales.documents.items.errorDeleteLast": "Zamówienie musi zawierać co najmniej jedną pozycję.",
|
|
953
954
|
"sales.documents.items.errorDeleteShipped": "Nie można usunąć pozycji, która ma wysłane sztuki.",
|
|
954
955
|
"sales.documents.items.errorLoad": "Nie udało się załadować pozycji.",
|
|
955
956
|
"sales.documents.items.errorNameRequired": "Nazwa jest wymagana dla niestandardowych pozycji.",
|
|
@@ -1226,6 +1227,7 @@
|
|
|
1226
1227
|
"sales.orders.form.shipments": "Wysyłki",
|
|
1227
1228
|
"sales.orders.lines.delete": "Usuń pozycję zamówienia",
|
|
1228
1229
|
"sales.orders.lines.upsert": "Zaktualizuj pozycję zamówienia",
|
|
1230
|
+
"sales.orders.linesRequired": "Dodaj co najmniej jedną pozycję przed utworzeniem zamówienia.",
|
|
1229
1231
|
"sales.orders.list.title": "Zamówienia",
|
|
1230
1232
|
"sales.orders.status_change.actor_api_key": "Klucz API {name}",
|
|
1231
1233
|
"sales.orders.status_change.actor_unknown": "Nieznany użytkownik",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
|
|
4
|
+
import { fetchAllDictionaryEntries } from '@open-mercato/core/modules/dictionaries/lib/fetchAllEntries'
|
|
4
5
|
|
|
5
6
|
export type DictionaryEntryOption = {
|
|
6
7
|
value: string
|
|
@@ -51,10 +52,9 @@ export async function loadStaffDictionary(
|
|
|
51
52
|
const name = kind === 'activityTypes' ? 'Staff activity types' : 'Staff address types'
|
|
52
53
|
const dictionary = await ensureDictionary(key, name)
|
|
53
54
|
if (!dictionary) return { dictionary: null, entries: [] }
|
|
54
|
-
const entriesCall = await
|
|
55
|
+
const entriesCall = await fetchAllDictionaryEntries(dictionary.id)
|
|
55
56
|
if (!entriesCall.ok) return { dictionary, entries: [] }
|
|
56
|
-
const
|
|
57
|
-
const entries = items
|
|
57
|
+
const entries = entriesCall.items
|
|
58
58
|
.map((entry) => {
|
|
59
59
|
if (!entry || typeof entry !== 'object') return null
|
|
60
60
|
const record = entry as Record<string, unknown>
|
|
@@ -10,6 +10,7 @@ import { Spinner } from '@open-mercato/ui/primitives/spinner'
|
|
|
10
10
|
import { Textarea } from '@open-mercato/ui/primitives/textarea'
|
|
11
11
|
import { Badge } from '@open-mercato/ui/primitives/badge'
|
|
12
12
|
import { emitSalesDocumentDataRefresh } from '@open-mercato/core/modules/sales/lib/frontend/documentDataEvents'
|
|
13
|
+
import { fetchAllDictionaryEntries } from '@open-mercato/core/modules/dictionaries/lib/fetchAllEntries'
|
|
13
14
|
|
|
14
15
|
type OrderRecord = {
|
|
15
16
|
id: string
|
|
@@ -165,12 +166,18 @@ export default function OrderApprovalWidget({ data }: InjectionWidgetComponentPr
|
|
|
165
166
|
// Fetch order status dictionary entries using the dictionary ID
|
|
166
167
|
const { data: statusEntriesData } = useQuery({
|
|
167
168
|
queryKey: ['dictionary-entries', orderStatusDictionaryId],
|
|
168
|
-
queryFn: async () => {
|
|
169
|
+
queryFn: async (): Promise<{ items: DictionaryEntry[] }> => {
|
|
169
170
|
if (!orderStatusDictionaryId) return { items: [] }
|
|
170
|
-
const result = await
|
|
171
|
-
|
|
172
|
-
)
|
|
173
|
-
|
|
171
|
+
const result = await fetchAllDictionaryEntries(orderStatusDictionaryId)
|
|
172
|
+
if (!result.ok) return { items: [] }
|
|
173
|
+
const items = result.items.flatMap((entry) => {
|
|
174
|
+
const id = typeof entry.id === 'string' ? entry.id : null
|
|
175
|
+
const value = typeof entry.value === 'string' ? entry.value : null
|
|
176
|
+
if (!id || !value) return []
|
|
177
|
+
const label = typeof entry.label === 'string' && entry.label.trim().length ? entry.label : value
|
|
178
|
+
return [{ id, value, label }]
|
|
179
|
+
})
|
|
180
|
+
return { items }
|
|
174
181
|
},
|
|
175
182
|
enabled: Boolean(orderStatusDictionaryId),
|
|
176
183
|
staleTime: 60_000,
|