@open-mercato/core 0.6.4-develop.4011.1.4f3ed9ae3e → 0.6.4-develop.4038.1.91ce075c8a
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/customers/api/companies/route.js +6 -0
- package/dist/modules/customers/api/companies/route.js.map +2 -2
- package/dist/modules/customers/api/people/route.js +6 -0
- package/dist/modules/customers/api/people/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +10 -9
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/listSorting.js +28 -0
- package/dist/modules/customers/backend/customers/listSorting.js.map +7 -0
- package/dist/modules/customers/backend/customers/people/page.js +10 -9
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/sales/api/shipments/route.js +135 -131
- package/dist/modules/sales/api/shipments/route.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/customers/api/companies/route.ts +6 -0
- package/src/modules/customers/api/people/route.ts +6 -0
- package/src/modules/customers/backend/customers/companies/page.tsx +12 -11
- package/src/modules/customers/backend/customers/listSorting.ts +27 -0
- package/src/modules/customers/backend/customers/people/page.tsx +12 -11
- package/src/modules/sales/api/shipments/route.ts +157 -150
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
3
|
-
import { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'
|
|
3
|
+
import { makeCrudRoute, type CrudCtx } from '@open-mercato/shared/lib/crud/factory'
|
|
4
4
|
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
5
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
6
6
|
import { splitCustomFieldPayload } from '@open-mercato/shared/lib/crud/custom-fields'
|
|
@@ -53,6 +53,161 @@ const toNumber = (value: unknown): number => {
|
|
|
53
53
|
return 0
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
export async function enrichShipmentListResponse(
|
|
57
|
+
payload: { items?: unknown[] },
|
|
58
|
+
ctx: CrudCtx,
|
|
59
|
+
): Promise<void> {
|
|
60
|
+
const items = Array.isArray(payload.items) ? payload.items : []
|
|
61
|
+
if (!items.length) return
|
|
62
|
+
const snapshotMap = new Map<string, ReturnType<typeof readShipmentItemsSnapshot>>()
|
|
63
|
+
items.forEach((item: unknown) => {
|
|
64
|
+
if (!item || typeof item !== 'object') return
|
|
65
|
+
const id = (item as Record<string, unknown>).id
|
|
66
|
+
if (typeof id !== 'string') return
|
|
67
|
+
const snapshot = readShipmentItemsSnapshot(
|
|
68
|
+
(item as any).items_snapshot ?? (item as any).itemsSnapshot ?? null
|
|
69
|
+
)
|
|
70
|
+
if (snapshot.length) {
|
|
71
|
+
snapshotMap.set(id, snapshot)
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
const shipmentIds = items
|
|
75
|
+
.map((item: unknown) => {
|
|
76
|
+
if (!item || typeof item !== 'object') return null
|
|
77
|
+
const raw = (item as Record<string, unknown>).id
|
|
78
|
+
return typeof raw === 'string' ? raw : null
|
|
79
|
+
})
|
|
80
|
+
.filter((value: string | null): value is string => typeof value === 'string')
|
|
81
|
+
if (!shipmentIds.length) return
|
|
82
|
+
const em = ctx.container.resolve('em') as EntityManager
|
|
83
|
+
const statusIds: string[] = Array.from(
|
|
84
|
+
new Set(
|
|
85
|
+
items
|
|
86
|
+
.map((item: unknown) => {
|
|
87
|
+
if (!item || typeof item !== 'object') return null
|
|
88
|
+
const raw = (item as Record<string, unknown>).status_entry_id
|
|
89
|
+
return typeof raw === 'string' ? raw : null
|
|
90
|
+
})
|
|
91
|
+
.filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
const [shipmentItems, shippingMethods, statusEntries] = await Promise.all([
|
|
95
|
+
findWithDecryption(
|
|
96
|
+
em,
|
|
97
|
+
SalesShipmentItem,
|
|
98
|
+
{ shipment: { $in: shipmentIds } },
|
|
99
|
+
{ populate: ['orderLine'] },
|
|
100
|
+
{ tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },
|
|
101
|
+
),
|
|
102
|
+
(async () => {
|
|
103
|
+
const ids: string[] = Array.from(
|
|
104
|
+
new Set(
|
|
105
|
+
items
|
|
106
|
+
.map((item: unknown) => {
|
|
107
|
+
if (!item || typeof item !== 'object') return null
|
|
108
|
+
const raw = (item as Record<string, unknown>).shipping_method_id
|
|
109
|
+
return typeof raw === 'string' ? raw : null
|
|
110
|
+
})
|
|
111
|
+
.filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
if (!ids.length) return []
|
|
115
|
+
return em.find(SalesShippingMethod, { id: { $in: ids } })
|
|
116
|
+
})(),
|
|
117
|
+
statusIds.length ? em.find(DictionaryEntry, { id: { $in: statusIds } }) : [],
|
|
118
|
+
])
|
|
119
|
+
const orderLineIds = Array.from(
|
|
120
|
+
new Set(
|
|
121
|
+
shipmentItems
|
|
122
|
+
.map((entry) =>
|
|
123
|
+
typeof entry.orderLine === 'string'
|
|
124
|
+
? entry.orderLine
|
|
125
|
+
: entry.orderLine?.id ?? (entry as any).orderLineId ?? null
|
|
126
|
+
)
|
|
127
|
+
.filter((value): value is string => typeof value === 'string')
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
const orderLines = orderLineIds.length
|
|
131
|
+
? await em.find(SalesOrderLine, { id: { $in: orderLineIds } })
|
|
132
|
+
: []
|
|
133
|
+
const lineMap = new Map(
|
|
134
|
+
orderLines.map((line) => [
|
|
135
|
+
line.id,
|
|
136
|
+
{
|
|
137
|
+
lineNumber: line.lineNumber ?? null,
|
|
138
|
+
name:
|
|
139
|
+
line.name ??
|
|
140
|
+
(typeof line.catalogSnapshot === 'object' && line.catalogSnapshot
|
|
141
|
+
? ((line.catalogSnapshot as any).name as string | undefined) ?? null
|
|
142
|
+
: null),
|
|
143
|
+
},
|
|
144
|
+
])
|
|
145
|
+
)
|
|
146
|
+
const grouped = shipmentItems.reduce<Map<string, Array<Record<string, unknown>>>>((acc, entry) => {
|
|
147
|
+
const shipmentId =
|
|
148
|
+
typeof entry.shipment === 'string'
|
|
149
|
+
? entry.shipment
|
|
150
|
+
: entry.shipment?.id ?? (entry as any).shipment_id ?? null
|
|
151
|
+
const lineId =
|
|
152
|
+
typeof entry.orderLine === 'string'
|
|
153
|
+
? entry.orderLine
|
|
154
|
+
: entry.orderLine?.id ?? (entry as any).order_line_id ?? null
|
|
155
|
+
if (!shipmentId || !lineId) return acc
|
|
156
|
+
const line = lineMap.get(lineId)
|
|
157
|
+
const list = acc.get(shipmentId) ?? []
|
|
158
|
+
list.push({
|
|
159
|
+
id: entry.id,
|
|
160
|
+
orderLineId: lineId,
|
|
161
|
+
orderLineName: line?.name ?? null,
|
|
162
|
+
orderLineNumber: line?.lineNumber ?? null,
|
|
163
|
+
quantity: toNumber(entry.quantity),
|
|
164
|
+
metadata: entry.metadata ?? null,
|
|
165
|
+
})
|
|
166
|
+
acc.set(shipmentId, list)
|
|
167
|
+
return acc
|
|
168
|
+
}, new Map())
|
|
169
|
+
const shippingMap = new Map(
|
|
170
|
+
shippingMethods.map((method) => [
|
|
171
|
+
method.id,
|
|
172
|
+
{
|
|
173
|
+
code: method.code ?? null,
|
|
174
|
+
name: method.name ?? method.code ?? null,
|
|
175
|
+
},
|
|
176
|
+
])
|
|
177
|
+
)
|
|
178
|
+
const statusMap = new Map<string, { value: string | null; label: string | null }>()
|
|
179
|
+
statusEntries.forEach((entry) =>
|
|
180
|
+
statusMap.set(entry.id, {
|
|
181
|
+
value: entry.value ?? null,
|
|
182
|
+
label: entry.label ?? entry.value ?? null,
|
|
183
|
+
})
|
|
184
|
+
)
|
|
185
|
+
items.forEach((item: unknown) => {
|
|
186
|
+
if (!item || typeof item !== 'object') return
|
|
187
|
+
const id = (item as Record<string, unknown>).id
|
|
188
|
+
if (typeof id !== 'string') return
|
|
189
|
+
const snapshot = snapshotMap.get(id)
|
|
190
|
+
if (snapshot?.length) {
|
|
191
|
+
;(item as Record<string, unknown>).items_snapshot = snapshot
|
|
192
|
+
}
|
|
193
|
+
;(item as Record<string, unknown>).items = snapshot?.length ? snapshot : grouped.get(id) ?? []
|
|
194
|
+
const shippingId = (item as Record<string, unknown>).shipping_method_id
|
|
195
|
+
if (typeof shippingId === 'string' && shippingMap.has(shippingId)) {
|
|
196
|
+
const method = shippingMap.get(shippingId)
|
|
197
|
+
;(item as Record<string, unknown>).shipping_method_code = method?.code ?? null
|
|
198
|
+
;(item as Record<string, unknown>).shipping_method_name = method?.name ?? null
|
|
199
|
+
}
|
|
200
|
+
const statusId = (item as Record<string, unknown>).status_entry_id
|
|
201
|
+
if (typeof statusId === 'string' && statusMap.has(statusId)) {
|
|
202
|
+
const status = statusMap.get(statusId)
|
|
203
|
+
if (!(item as Record<string, unknown>).status) {
|
|
204
|
+
;(item as Record<string, unknown>).status = status?.value ?? null
|
|
205
|
+
}
|
|
206
|
+
;(item as Record<string, unknown>).status_label = status?.label ?? status?.value ?? null
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
}
|
|
210
|
+
|
|
56
211
|
const crud = makeCrudRoute({
|
|
57
212
|
metadata: routeMetadata,
|
|
58
213
|
orm: {
|
|
@@ -153,155 +308,7 @@ const crud = makeCrudRoute({
|
|
|
153
308
|
},
|
|
154
309
|
},
|
|
155
310
|
hooks: {
|
|
156
|
-
afterList:
|
|
157
|
-
const items = Array.isArray(payload.items) ? payload.items : []
|
|
158
|
-
if (!items.length) return
|
|
159
|
-
const snapshotMap = new Map<string, ReturnType<typeof readShipmentItemsSnapshot>>()
|
|
160
|
-
items.forEach((item: unknown) => {
|
|
161
|
-
if (!item || typeof item !== 'object') return
|
|
162
|
-
const id = (item as Record<string, unknown>).id
|
|
163
|
-
if (typeof id !== 'string') return
|
|
164
|
-
const snapshot = readShipmentItemsSnapshot(
|
|
165
|
-
(item as any).items_snapshot ?? (item as any).itemsSnapshot ?? null
|
|
166
|
-
)
|
|
167
|
-
if (snapshot.length) {
|
|
168
|
-
snapshotMap.set(id, snapshot)
|
|
169
|
-
}
|
|
170
|
-
})
|
|
171
|
-
const shipmentIds = items
|
|
172
|
-
.map((item: unknown) => (item && typeof item === 'object' ? (item as Record<string, unknown>).id : null))
|
|
173
|
-
.filter((value: string | null): value is string => typeof value === 'string')
|
|
174
|
-
if (!shipmentIds.length) return
|
|
175
|
-
const em = ctx.container.resolve('em') as EntityManager
|
|
176
|
-
const [shipmentItems, shippingMethods] = await Promise.all([
|
|
177
|
-
findWithDecryption(
|
|
178
|
-
em,
|
|
179
|
-
SalesShipmentItem,
|
|
180
|
-
{ shipment: { $in: shipmentIds } },
|
|
181
|
-
{ populate: ['orderLine'] },
|
|
182
|
-
{ tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },
|
|
183
|
-
),
|
|
184
|
-
(async () => {
|
|
185
|
-
const ids: string[] = Array.from(
|
|
186
|
-
new Set(
|
|
187
|
-
items
|
|
188
|
-
.map((item: unknown) => {
|
|
189
|
-
if (!item || typeof item !== 'object') return null
|
|
190
|
-
const raw = (item as Record<string, unknown>).shipping_method_id
|
|
191
|
-
return typeof raw === 'string' ? raw : null
|
|
192
|
-
})
|
|
193
|
-
.filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)
|
|
194
|
-
)
|
|
195
|
-
)
|
|
196
|
-
if (!ids.length) return []
|
|
197
|
-
return em.find(SalesShippingMethod, { id: { $in: ids } })
|
|
198
|
-
})(),
|
|
199
|
-
])
|
|
200
|
-
const orderLineIds = Array.from(
|
|
201
|
-
new Set(
|
|
202
|
-
shipmentItems
|
|
203
|
-
.map((entry) =>
|
|
204
|
-
typeof entry.orderLine === 'string'
|
|
205
|
-
? entry.orderLine
|
|
206
|
-
: entry.orderLine?.id ?? (entry as any).orderLineId ?? null
|
|
207
|
-
)
|
|
208
|
-
.filter((value): value is string => typeof value === 'string')
|
|
209
|
-
)
|
|
210
|
-
)
|
|
211
|
-
const orderLines = orderLineIds.length
|
|
212
|
-
? await em.find(SalesOrderLine, { id: { $in: orderLineIds } })
|
|
213
|
-
: []
|
|
214
|
-
const lineMap = new Map(
|
|
215
|
-
orderLines.map((line) => [
|
|
216
|
-
line.id,
|
|
217
|
-
{
|
|
218
|
-
lineNumber: line.lineNumber ?? null,
|
|
219
|
-
name:
|
|
220
|
-
line.name ??
|
|
221
|
-
(typeof line.catalogSnapshot === 'object' && line.catalogSnapshot
|
|
222
|
-
? ((line.catalogSnapshot as any).name as string | undefined) ?? null
|
|
223
|
-
: null),
|
|
224
|
-
},
|
|
225
|
-
])
|
|
226
|
-
)
|
|
227
|
-
const grouped = shipmentItems.reduce<Map<string, Array<Record<string, unknown>>>>((acc, entry) => {
|
|
228
|
-
const shipmentId =
|
|
229
|
-
typeof entry.shipment === 'string'
|
|
230
|
-
? entry.shipment
|
|
231
|
-
: entry.shipment?.id ?? (entry as any).shipment_id ?? null
|
|
232
|
-
const lineId =
|
|
233
|
-
typeof entry.orderLine === 'string'
|
|
234
|
-
? entry.orderLine
|
|
235
|
-
: entry.orderLine?.id ?? (entry as any).order_line_id ?? null
|
|
236
|
-
if (!shipmentId || !lineId) return acc
|
|
237
|
-
const line = lineMap.get(lineId)
|
|
238
|
-
const list = acc.get(shipmentId) ?? []
|
|
239
|
-
list.push({
|
|
240
|
-
id: entry.id,
|
|
241
|
-
orderLineId: lineId,
|
|
242
|
-
orderLineName: line?.name ?? null,
|
|
243
|
-
orderLineNumber: line?.lineNumber ?? null,
|
|
244
|
-
quantity: toNumber(entry.quantity),
|
|
245
|
-
metadata: entry.metadata ?? null,
|
|
246
|
-
})
|
|
247
|
-
acc.set(shipmentId, list)
|
|
248
|
-
return acc
|
|
249
|
-
}, new Map())
|
|
250
|
-
const shippingMap = new Map(
|
|
251
|
-
shippingMethods.map((method) => [
|
|
252
|
-
method.id,
|
|
253
|
-
{
|
|
254
|
-
code: method.code ?? null,
|
|
255
|
-
name: method.name ?? method.code ?? null,
|
|
256
|
-
},
|
|
257
|
-
])
|
|
258
|
-
)
|
|
259
|
-
const statusIds: string[] = Array.from(
|
|
260
|
-
new Set(
|
|
261
|
-
items
|
|
262
|
-
.map((item: unknown) => {
|
|
263
|
-
if (!item || typeof item !== 'object') return null
|
|
264
|
-
const raw = (item as Record<string, unknown>).status_entry_id
|
|
265
|
-
return typeof raw === 'string' ? raw : null
|
|
266
|
-
})
|
|
267
|
-
.filter((value: string | null): value is string => typeof value === 'string' && value.length > 0)
|
|
268
|
-
)
|
|
269
|
-
)
|
|
270
|
-
const statusMap = new Map<string, { value: string | null; label: string | null }>()
|
|
271
|
-
if (statusIds.length) {
|
|
272
|
-
const entries = await em.find(DictionaryEntry, { id: { $in: statusIds } })
|
|
273
|
-
entries.forEach((entry) =>
|
|
274
|
-
statusMap.set(entry.id, {
|
|
275
|
-
value: entry.value ?? null,
|
|
276
|
-
label: entry.label ?? entry.value ?? null,
|
|
277
|
-
})
|
|
278
|
-
)
|
|
279
|
-
}
|
|
280
|
-
items.forEach((item: unknown) => {
|
|
281
|
-
if (!item || typeof item !== 'object') return
|
|
282
|
-
const id = (item as Record<string, unknown>).id
|
|
283
|
-
if (typeof id !== 'string') return
|
|
284
|
-
const snapshot = snapshotMap.get(id)
|
|
285
|
-
if (snapshot?.length) {
|
|
286
|
-
;(item as Record<string, unknown>).items_snapshot = snapshot
|
|
287
|
-
}
|
|
288
|
-
;(item as Record<string, unknown>).items = snapshot?.length ? snapshot : grouped.get(id) ?? []
|
|
289
|
-
const shippingId = (item as Record<string, unknown>).shipping_method_id
|
|
290
|
-
if (typeof shippingId === 'string' && shippingMap.has(shippingId)) {
|
|
291
|
-
const method = shippingMap.get(shippingId)
|
|
292
|
-
;(item as Record<string, unknown>).shipping_method_code = method?.code ?? null
|
|
293
|
-
;(item as Record<string, unknown>).shipping_method_name = method?.name ?? null
|
|
294
|
-
}
|
|
295
|
-
const statusId = (item as Record<string, unknown>).status_entry_id
|
|
296
|
-
if (typeof statusId === 'string' && statusMap.has(statusId)) {
|
|
297
|
-
const status = statusMap.get(statusId)
|
|
298
|
-
if (!(item as Record<string, unknown>).status) {
|
|
299
|
-
;(item as Record<string, unknown>).status = status?.value ?? null
|
|
300
|
-
}
|
|
301
|
-
;(item as Record<string, unknown>).status_label = status?.label ?? status?.value ?? null
|
|
302
|
-
}
|
|
303
|
-
})
|
|
304
|
-
},
|
|
311
|
+
afterList: (payload, ctx) => enrichShipmentListResponse(payload, ctx),
|
|
305
312
|
},
|
|
306
313
|
})
|
|
307
314
|
|