@open-mercato/core 0.6.7-develop.6751.1.ac823a3d26 → 0.6.7-develop.6758.1.697eade236
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/modules/attachments/api/route.js +16 -2
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/lib/upload-limits.js +33 -0
- package/dist/modules/attachments/lib/upload-limits.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +52 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/currencies/di.js +4 -0
- package/dist/modules/currencies/di.js.map +2 -2
- package/dist/modules/currencies/services/baseCurrencyService.js +42 -0
- package/dist/modules/currencies/services/baseCurrencyService.js.map +7 -0
- package/dist/modules/customers/analytics.js +3 -1
- package/dist/modules/customers/analytics.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +5 -4
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/summary/route.js +5 -4
- package/dist/modules/customers/api/deals/summary/route.js.map +2 -2
- package/dist/modules/customers/lib/optionalBaseCurrency.js +19 -0
- package/dist/modules/customers/lib/optionalBaseCurrency.js.map +7 -0
- package/dist/modules/dashboards/api/widgets/data/batch/route.js +8 -1
- package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/route.js +8 -1
- package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/schema.js +2 -1
- package/dist/modules/dashboards/api/widgets/data/schema.js.map +2 -2
- package/dist/modules/dashboards/components/UnlabelledAmountNotice.js +33 -0
- package/dist/modules/dashboards/components/UnlabelledAmountNotice.js.map +7 -0
- package/dist/modules/dashboards/lib/aggregations.js +17 -0
- package/dist/modules/dashboards/lib/aggregations.js.map +2 -2
- package/dist/modules/dashboards/lib/formatters.js +84 -11
- package/dist/modules/dashboards/lib/formatters.js.map +2 -2
- package/dist/modules/dashboards/lib/optionalBaseCurrency.js +11 -0
- package/dist/modules/dashboards/lib/optionalBaseCurrency.js.map +7 -0
- package/dist/modules/dashboards/services/widgetDataService.js +86 -6
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dashboards/subscribers/invalidateWidgetDataCache.js +26 -0
- package/dist/modules/dashboards/subscribers/invalidateWidgetDataCache.js.map +7 -0
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +9 -3
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +10 -4
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +9 -3
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +8 -3
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +26 -18
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +22 -14
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +10 -4
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
- package/dist/modules/notifications/api/route.js +62 -3
- package/dist/modules/notifications/api/route.js.map +2 -2
- package/dist/modules/sales/analytics.js +7 -3
- package/dist/modules/sales/analytics.js.map +2 -2
- package/dist/modules/sales/api/document-history/route.js +2 -1
- package/dist/modules/sales/api/document-history/route.js.map +2 -2
- package/dist/modules/sales/lib/historyHelpers.js +69 -1
- package/dist/modules/sales/lib/historyHelpers.js.map +2 -2
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js +51 -2
- package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/attachments/api/route.ts +16 -2
- package/src/modules/attachments/lib/upload-limits.ts +35 -0
- package/src/modules/communication_channels/api/post/test-seed/route.ts +69 -2
- package/src/modules/currencies/di.ts +4 -1
- package/src/modules/currencies/services/baseCurrencyService.ts +59 -0
- package/src/modules/customers/analytics.ts +2 -0
- package/src/modules/customers/api/deals/aggregate/route.ts +5 -4
- package/src/modules/customers/api/deals/summary/route.ts +5 -4
- package/src/modules/customers/lib/optionalBaseCurrency.ts +34 -0
- package/src/modules/dashboards/api/widgets/data/batch/route.ts +8 -1
- package/src/modules/dashboards/api/widgets/data/route.ts +8 -1
- package/src/modules/dashboards/api/widgets/data/schema.ts +1 -0
- package/src/modules/dashboards/components/UnlabelledAmountNotice.tsx +43 -0
- package/src/modules/dashboards/i18n/de.json +2 -0
- package/src/modules/dashboards/i18n/en.json +2 -0
- package/src/modules/dashboards/i18n/es.json +2 -0
- package/src/modules/dashboards/i18n/pl.json +2 -0
- package/src/modules/dashboards/lib/aggregations.ts +35 -0
- package/src/modules/dashboards/lib/formatters.ts +137 -12
- package/src/modules/dashboards/lib/optionalBaseCurrency.ts +22 -0
- package/src/modules/dashboards/services/widgetDataService.ts +110 -4
- package/src/modules/dashboards/subscribers/invalidateWidgetDataCache.ts +32 -0
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +9 -3
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +9 -3
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +9 -3
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +7 -2
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +25 -15
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +21 -11
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +9 -3
- package/src/modules/notifications/api/route.ts +88 -3
- package/src/modules/sales/analytics.ts +4 -0
- package/src/modules/sales/api/document-history/route.ts +1 -0
- package/src/modules/sales/i18n/de.json +19 -0
- package/src/modules/sales/i18n/en.json +19 -0
- package/src/modules/sales/i18n/es.json +19 -0
- package/src/modules/sales/i18n/pl.json +19 -0
- package/src/modules/sales/lib/historyHelpers.ts +88 -1
- package/src/modules/sales/widgets/injection/document-history/widget.client.tsx +64 -3
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import { Spinner } from "@open-mercato/ui/primitives/spinner"
|
|
5
|
-
import { useT } from "@open-mercato/shared/lib/i18n/context"
|
|
5
|
+
import { useT, type TranslateFn } from "@open-mercato/shared/lib/i18n/context"
|
|
6
6
|
import { apiCall } from "@open-mercato/ui/backend/utils/apiCall"
|
|
7
7
|
import { formatRelativeTime, formatDateTime } from "@open-mercato/shared/lib/time"
|
|
8
8
|
import { cn } from "@open-mercato/shared/lib/utils"
|
|
@@ -21,6 +21,7 @@ export type TimelineEntry = {
|
|
|
21
21
|
statusTo?: string | null
|
|
22
22
|
documentKind?: "order" | "quote"
|
|
23
23
|
commandId?: string
|
|
24
|
+
changedFields?: string[]
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -65,6 +66,49 @@ const KIND_BG_COLORS = {
|
|
|
65
66
|
comment: 'bg-muted',
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
const CHANGED_FIELD_LABELS: Record<string, { key: string; fallback: string }> = {
|
|
70
|
+
productId: { key: 'sales.documents.history.fields.product', fallback: 'Product' },
|
|
71
|
+
productVariantId: { key: 'sales.documents.history.fields.variant', fallback: 'Variant' },
|
|
72
|
+
name: { key: 'sales.documents.history.fields.name', fallback: 'Name' },
|
|
73
|
+
description: { key: 'sales.documents.history.fields.description', fallback: 'Description' },
|
|
74
|
+
comment: { key: 'sales.documents.history.fields.comment', fallback: 'Comment' },
|
|
75
|
+
quantity: { key: 'sales.documents.history.fields.quantity', fallback: 'Quantity' },
|
|
76
|
+
quantityUnit: { key: 'sales.documents.history.fields.quantityUnit', fallback: 'Quantity unit' },
|
|
77
|
+
currencyCode: { key: 'sales.documents.history.fields.currency', fallback: 'Currency' },
|
|
78
|
+
unitPriceNet: { key: 'sales.documents.history.fields.unitPriceNet', fallback: 'Net unit price' },
|
|
79
|
+
unitPriceGross: { key: 'sales.documents.history.fields.unitPriceGross', fallback: 'Gross unit price' },
|
|
80
|
+
discountAmount: { key: 'sales.documents.history.fields.discountAmount', fallback: 'Discount amount' },
|
|
81
|
+
discountPercent: { key: 'sales.documents.history.fields.discountPercent', fallback: 'Discount percent' },
|
|
82
|
+
taxRate: { key: 'sales.documents.history.fields.taxRate', fallback: 'Tax class' },
|
|
83
|
+
configuration: { key: 'sales.documents.history.fields.configuration', fallback: 'Configuration' },
|
|
84
|
+
promotionCode: { key: 'sales.documents.history.fields.promotionCode', fallback: 'Promotion code' },
|
|
85
|
+
customFields: { key: 'sales.documents.history.fields.customFields', fallback: 'Custom fields' },
|
|
86
|
+
statusEntryId: { key: 'sales.documents.history.fields.status', fallback: 'Status' },
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function normalizeChangedField(field: string): string {
|
|
90
|
+
const segment = field.split('.').pop() ?? field
|
|
91
|
+
return segment.replace(/_([a-z])/g, (_, letter: string) => letter.toUpperCase())
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function humanizeChangedField(field: string): string {
|
|
95
|
+
const normalized = normalizeChangedField(field)
|
|
96
|
+
const spaced = normalized.replace(/([a-z0-9])([A-Z])/g, '$1 $2').trim()
|
|
97
|
+
return spaced.length > 0 ? `${spaced[0].toUpperCase()}${spaced.slice(1)}` : field
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function translateChangedField(t: TranslateFn, field: string): string {
|
|
101
|
+
const normalized = normalizeChangedField(field)
|
|
102
|
+
const translation = CHANGED_FIELD_LABELS[normalized]
|
|
103
|
+
return translation ? t(translation.key, translation.fallback) : humanizeChangedField(field)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function translateAction(t: TranslateFn, entry: TimelineEntry): string {
|
|
107
|
+
const commandId = entry.metadata?.commandId
|
|
108
|
+
if (!commandId?.startsWith('sales.')) return entry.action
|
|
109
|
+
return t(`sales.audit.${commandId.slice('sales.'.length)}`, entry.action)
|
|
110
|
+
}
|
|
111
|
+
|
|
68
112
|
function StatusDot({ color, className }: { color: string | null | undefined; className?: string }) {
|
|
69
113
|
if (!color) return <span className={cn('h-2.5 w-2.5 rounded-full bg-muted-foreground/40 border border-border inline-flex', className)} />
|
|
70
114
|
return (
|
|
@@ -118,11 +162,19 @@ function TimelineItem({
|
|
|
118
162
|
statusMap: Record<string, StatusOption>
|
|
119
163
|
isLast: boolean
|
|
120
164
|
}) {
|
|
165
|
+
const t = useT()
|
|
121
166
|
const KindIcon = KIND_ICONS[entry.kind]
|
|
122
167
|
const relativeTime = formatRelativeTime(entry.occurredAt)
|
|
123
168
|
const absoluteTime = formatDateTime(entry.occurredAt)
|
|
124
169
|
|
|
125
170
|
const isStatusChange = entry.kind === 'status' && entry.metadata?.statusTo
|
|
171
|
+
const action = translateAction(t, entry)
|
|
172
|
+
const actorLabel = entry.actor.id
|
|
173
|
+
? entry.actor.label
|
|
174
|
+
: t('sales.documents.history.actor.system', 'System')
|
|
175
|
+
const changedFieldLabels = Array.from(
|
|
176
|
+
new Set((entry.metadata?.changedFields ?? []).map((field) => translateChangedField(t, field))),
|
|
177
|
+
)
|
|
126
178
|
|
|
127
179
|
return (
|
|
128
180
|
<div data-testid="timeline-entry" className="relative flex gap-3">
|
|
@@ -148,7 +200,7 @@ function TimelineItem({
|
|
|
148
200
|
<div className="flex items-center justify-between gap-2 flex-wrap">
|
|
149
201
|
<span className="inline-flex items-center gap-1.5 text-xs font-medium text-foreground">
|
|
150
202
|
<User className="h-3 w-3 text-muted-foreground" aria-hidden />
|
|
151
|
-
{
|
|
203
|
+
{actorLabel}
|
|
152
204
|
</span>
|
|
153
205
|
<span
|
|
154
206
|
className="text-xs text-muted-foreground"
|
|
@@ -166,7 +218,16 @@ function TimelineItem({
|
|
|
166
218
|
statusMap={statusMap}
|
|
167
219
|
/>
|
|
168
220
|
) : (
|
|
169
|
-
<div className="
|
|
221
|
+
<div className="space-y-0.5">
|
|
222
|
+
<div className="text-sm text-foreground">{action}</div>
|
|
223
|
+
{entry.kind === 'action' && changedFieldLabels.length > 0 ? (
|
|
224
|
+
<div className="text-xs text-muted-foreground">
|
|
225
|
+
{t('sales.documents.history.changedFields', 'Changed fields: {fields}', {
|
|
226
|
+
fields: changedFieldLabels.join(', '),
|
|
227
|
+
})}
|
|
228
|
+
</div>
|
|
229
|
+
) : null}
|
|
230
|
+
</div>
|
|
170
231
|
)}
|
|
171
232
|
</div>
|
|
172
233
|
</div>
|