@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.
Files changed (100) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/attachments/api/route.js +16 -2
  3. package/dist/modules/attachments/api/route.js.map +2 -2
  4. package/dist/modules/attachments/lib/upload-limits.js +33 -0
  5. package/dist/modules/attachments/lib/upload-limits.js.map +2 -2
  6. package/dist/modules/communication_channels/api/post/test-seed/route.js +52 -2
  7. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
  8. package/dist/modules/currencies/di.js +4 -0
  9. package/dist/modules/currencies/di.js.map +2 -2
  10. package/dist/modules/currencies/services/baseCurrencyService.js +42 -0
  11. package/dist/modules/currencies/services/baseCurrencyService.js.map +7 -0
  12. package/dist/modules/customers/analytics.js +3 -1
  13. package/dist/modules/customers/analytics.js.map +2 -2
  14. package/dist/modules/customers/api/deals/aggregate/route.js +5 -4
  15. package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
  16. package/dist/modules/customers/api/deals/summary/route.js +5 -4
  17. package/dist/modules/customers/api/deals/summary/route.js.map +2 -2
  18. package/dist/modules/customers/lib/optionalBaseCurrency.js +19 -0
  19. package/dist/modules/customers/lib/optionalBaseCurrency.js.map +7 -0
  20. package/dist/modules/dashboards/api/widgets/data/batch/route.js +8 -1
  21. package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
  22. package/dist/modules/dashboards/api/widgets/data/route.js +8 -1
  23. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  24. package/dist/modules/dashboards/api/widgets/data/schema.js +2 -1
  25. package/dist/modules/dashboards/api/widgets/data/schema.js.map +2 -2
  26. package/dist/modules/dashboards/components/UnlabelledAmountNotice.js +33 -0
  27. package/dist/modules/dashboards/components/UnlabelledAmountNotice.js.map +7 -0
  28. package/dist/modules/dashboards/lib/aggregations.js +17 -0
  29. package/dist/modules/dashboards/lib/aggregations.js.map +2 -2
  30. package/dist/modules/dashboards/lib/formatters.js +84 -11
  31. package/dist/modules/dashboards/lib/formatters.js.map +2 -2
  32. package/dist/modules/dashboards/lib/optionalBaseCurrency.js +11 -0
  33. package/dist/modules/dashboards/lib/optionalBaseCurrency.js.map +7 -0
  34. package/dist/modules/dashboards/services/widgetDataService.js +86 -6
  35. package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
  36. package/dist/modules/dashboards/subscribers/invalidateWidgetDataCache.js +26 -0
  37. package/dist/modules/dashboards/subscribers/invalidateWidgetDataCache.js.map +7 -0
  38. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +9 -3
  39. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +2 -2
  40. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +10 -4
  41. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
  42. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +9 -3
  43. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +2 -2
  44. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +8 -3
  45. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
  46. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +26 -18
  47. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
  48. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +22 -14
  49. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
  50. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +10 -4
  51. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
  52. package/dist/modules/notifications/api/route.js +62 -3
  53. package/dist/modules/notifications/api/route.js.map +2 -2
  54. package/dist/modules/sales/analytics.js +7 -3
  55. package/dist/modules/sales/analytics.js.map +2 -2
  56. package/dist/modules/sales/api/document-history/route.js +2 -1
  57. package/dist/modules/sales/api/document-history/route.js.map +2 -2
  58. package/dist/modules/sales/lib/historyHelpers.js +69 -1
  59. package/dist/modules/sales/lib/historyHelpers.js.map +2 -2
  60. package/dist/modules/sales/widgets/injection/document-history/widget.client.js +51 -2
  61. package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
  62. package/package.json +7 -7
  63. package/src/modules/attachments/api/route.ts +16 -2
  64. package/src/modules/attachments/lib/upload-limits.ts +35 -0
  65. package/src/modules/communication_channels/api/post/test-seed/route.ts +69 -2
  66. package/src/modules/currencies/di.ts +4 -1
  67. package/src/modules/currencies/services/baseCurrencyService.ts +59 -0
  68. package/src/modules/customers/analytics.ts +2 -0
  69. package/src/modules/customers/api/deals/aggregate/route.ts +5 -4
  70. package/src/modules/customers/api/deals/summary/route.ts +5 -4
  71. package/src/modules/customers/lib/optionalBaseCurrency.ts +34 -0
  72. package/src/modules/dashboards/api/widgets/data/batch/route.ts +8 -1
  73. package/src/modules/dashboards/api/widgets/data/route.ts +8 -1
  74. package/src/modules/dashboards/api/widgets/data/schema.ts +1 -0
  75. package/src/modules/dashboards/components/UnlabelledAmountNotice.tsx +43 -0
  76. package/src/modules/dashboards/i18n/de.json +2 -0
  77. package/src/modules/dashboards/i18n/en.json +2 -0
  78. package/src/modules/dashboards/i18n/es.json +2 -0
  79. package/src/modules/dashboards/i18n/pl.json +2 -0
  80. package/src/modules/dashboards/lib/aggregations.ts +35 -0
  81. package/src/modules/dashboards/lib/formatters.ts +137 -12
  82. package/src/modules/dashboards/lib/optionalBaseCurrency.ts +22 -0
  83. package/src/modules/dashboards/services/widgetDataService.ts +110 -4
  84. package/src/modules/dashboards/subscribers/invalidateWidgetDataCache.ts +32 -0
  85. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +9 -3
  86. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +9 -3
  87. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +9 -3
  88. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +7 -2
  89. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +25 -15
  90. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +21 -11
  91. package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +9 -3
  92. package/src/modules/notifications/api/route.ts +88 -3
  93. package/src/modules/sales/analytics.ts +4 -0
  94. package/src/modules/sales/api/document-history/route.ts +1 -0
  95. package/src/modules/sales/i18n/de.json +19 -0
  96. package/src/modules/sales/i18n/en.json +19 -0
  97. package/src/modules/sales/i18n/es.json +19 -0
  98. package/src/modules/sales/i18n/pl.json +19 -0
  99. package/src/modules/sales/lib/historyHelpers.ts +88 -1
  100. 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
- {entry.actor.label}
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="text-sm text-foreground">{entry.action}</div>
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>