@things-factory/sales-base 4.3.782 → 4.3.784
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/dist-server/service/arrival-notice/arrival-notice-mutation.js +2 -0
- package/dist-server/service/arrival-notice/arrival-notice-mutation.js.map +1 -1
- package/dist-server/service/delivery-order/delivery-order-query.js +81 -4
- package/dist-server/service/delivery-order/delivery-order-query.js.map +1 -1
- package/dist-server/service/release-good/release-good-mutation.js +41 -5
- package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
- package/dist-server/service/release-good/release-good-query.js +4 -2
- package/dist-server/service/release-good/release-good-query.js.map +1 -1
- package/package.json +4 -4
- package/server/service/arrival-notice/arrival-notice-mutation.ts +1 -0
- package/server/service/delivery-order/delivery-order-query.ts +89 -4
- package/server/service/release-good/release-good-mutation.ts +39 -5
- package/server/service/release-good/release-good-query.ts +4 -3
|
@@ -106,6 +106,69 @@ export class DeliveryOrderQuery {
|
|
|
106
106
|
x.name != 'orderProductsApi'
|
|
107
107
|
)
|
|
108
108
|
|
|
109
|
+
// ── Separate count query (minimal JOINs — only those needed for WHERE conditions) ──
|
|
110
|
+
const countQb: any = getRepository(DeliveryOrder).createQueryBuilder('do')
|
|
111
|
+
buildQuery(countQb, params, context)
|
|
112
|
+
|
|
113
|
+
if (refNoFilter?.value || refNo2Filter?.value || refNo3Filter?.value || orderInfoFilter?.value || businessRestDayFilter?.value || orderProductsApiFilter?.value) {
|
|
114
|
+
countQb.leftJoin('do.releaseGood', 'releaseGood')
|
|
115
|
+
}
|
|
116
|
+
if (businessRestDayFilter?.value) {
|
|
117
|
+
countQb.leftJoin('releaseGood.deliverTo', 'deliverTo')
|
|
118
|
+
}
|
|
119
|
+
if (orderProductsApiFilter?.value) {
|
|
120
|
+
countQb.innerJoin('releaseGood.orderProducts', 'orderProducts')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (refNoFilter?.value) {
|
|
124
|
+
countQb.andWhere('releaseGood.ref_no ilike :refNo', { refNo: refNoFilter.value })
|
|
125
|
+
}
|
|
126
|
+
if (refNo2Filter?.value) {
|
|
127
|
+
countQb.andWhere('releaseGood.ref_no_2 ilike :refNo2', { refNo2: refNo2Filter.value })
|
|
128
|
+
}
|
|
129
|
+
if (refNo3Filter?.value) {
|
|
130
|
+
countQb.andWhere('releaseGood.ref_no_3 ilike :refNo3', { refNo3: refNo3Filter.value })
|
|
131
|
+
}
|
|
132
|
+
if (orderInfoFilter?.value) {
|
|
133
|
+
let removeSymbolCount = orderInfoFilter.value
|
|
134
|
+
.split('')
|
|
135
|
+
.filter(res => res !== '%')
|
|
136
|
+
.join('')
|
|
137
|
+
let orderInfosCount = removeSymbolCount
|
|
138
|
+
.toLowerCase()
|
|
139
|
+
.split(',')
|
|
140
|
+
.map(prod => {
|
|
141
|
+
return "'%" + prod.trim().replace(/'/g, "''") + "%'"
|
|
142
|
+
})
|
|
143
|
+
.join(',')
|
|
144
|
+
countQb.andWhere(
|
|
145
|
+
`(
|
|
146
|
+
lower(releaseGood.name) like any(array[${orderInfosCount}])
|
|
147
|
+
or lower(releaseGood.ref_no) like any(array[${orderInfosCount}])
|
|
148
|
+
or lower(releaseGood.ref_no_2) like any(array[${orderInfosCount}])
|
|
149
|
+
or lower(releaseGood.ref_no_3) like any(array[${orderInfosCount}])
|
|
150
|
+
)`
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
if (businessRestDayFilter?.value) {
|
|
154
|
+
const todayCount = new Date()
|
|
155
|
+
const dayOfWeekCount = todayCount.getDay()
|
|
156
|
+
const dayNamesCount = ['SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY']
|
|
157
|
+
const currentDayNameCount = dayNamesCount[dayOfWeekCount]
|
|
158
|
+
if (businessRestDayFilter.value === 'within') {
|
|
159
|
+
countQb.andWhere(`deliverTo.business_rest_day IS NOT NULL AND deliverTo.business_rest_day ILIKE :currentDay`, {
|
|
160
|
+
currentDay: `%${currentDayNameCount}%`
|
|
161
|
+
})
|
|
162
|
+
} else if (businessRestDayFilter.value === 'not_within') {
|
|
163
|
+
countQb.andWhere(`(deliverTo.business_rest_day IS NULL OR deliverTo.business_rest_day NOT ILIKE :currentDay)`, {
|
|
164
|
+
currentDay: `%${currentDayNameCount}%`
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const total: number = await countQb.getCount()
|
|
170
|
+
|
|
171
|
+
// ── Data query (full JOINs for SELECT — paginated, only processes 'limit' rows) ──
|
|
109
172
|
const qb: any = getRepository(DeliveryOrder).createQueryBuilder('do')
|
|
110
173
|
buildQuery(qb, params, context)
|
|
111
174
|
qb.addSelect('COALESCE("cc".rank, 99999)', 'rank')
|
|
@@ -206,7 +269,7 @@ export class DeliveryOrderQuery {
|
|
|
206
269
|
|
|
207
270
|
qb.orderBy(sort)
|
|
208
271
|
|
|
209
|
-
let
|
|
272
|
+
let items = await qb.getMany()
|
|
210
273
|
|
|
211
274
|
items = items.map(itm => {
|
|
212
275
|
let refNo2 = itm.refNo2 // default
|
|
@@ -296,7 +359,8 @@ export class DeliveryOrderQuery {
|
|
|
296
359
|
}
|
|
297
360
|
convertedParams.bizplace = In(await getPermittedBizplaceIds(domain, user))
|
|
298
361
|
|
|
299
|
-
const
|
|
362
|
+
const total = await getRepository(DeliveryOrder).count(convertedParams)
|
|
363
|
+
const items = await getRepository(DeliveryOrder).find({
|
|
300
364
|
...convertedParams,
|
|
301
365
|
relations: ['domain', 'bizplace', 'releaseGood', 'transportDriver', 'transportVehicle', 'creator', 'updater']
|
|
302
366
|
})
|
|
@@ -580,6 +644,26 @@ export class DeliveryOrderQuery {
|
|
|
580
644
|
|
|
581
645
|
params.filters = params.filters.filter(x => x.name != 'refNo' && x.name != 'refNo2' && x.name != 'refNo3')
|
|
582
646
|
|
|
647
|
+
// ── Separate count query (minimal JOINs — only those needed for WHERE conditions) ──
|
|
648
|
+
const countQb: any = getRepository(DeliveryOrder).createQueryBuilder('do')
|
|
649
|
+
buildQuery(countQb, params, context)
|
|
650
|
+
|
|
651
|
+
if (refNoFilter?.value || refNo2Filter?.value || refNo3Filter?.value) {
|
|
652
|
+
countQb.leftJoin('do.releaseGood', 'releaseGood')
|
|
653
|
+
}
|
|
654
|
+
if (refNoFilter?.value) {
|
|
655
|
+
countQb.andWhere('releaseGood.ref_no ilike :refNo', { refNo: refNoFilter.value })
|
|
656
|
+
}
|
|
657
|
+
if (refNo2Filter?.value) {
|
|
658
|
+
countQb.andWhere('releaseGood.ref_no_2 ilike :refNo2', { refNo2: refNo2Filter.value })
|
|
659
|
+
}
|
|
660
|
+
if (refNo3Filter?.value) {
|
|
661
|
+
countQb.andWhere('releaseGood.ref_no_3 ilike :refNo3', { refNo3: refNo3Filter.value })
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
const total: number = await countQb.getCount()
|
|
665
|
+
|
|
666
|
+
// ── Data query (full JOINs for SELECT — paginated, only processes 'limit' rows) ──
|
|
583
667
|
const qb: any = getRepository(DeliveryOrder).createQueryBuilder('do')
|
|
584
668
|
buildQuery(qb, params, context)
|
|
585
669
|
qb.addSelect('COALESCE("cc".rank, 99999)', 'rank')
|
|
@@ -634,7 +718,7 @@ export class DeliveryOrderQuery {
|
|
|
634
718
|
|
|
635
719
|
qb.orderBy(sort)
|
|
636
720
|
|
|
637
|
-
const
|
|
721
|
+
const items = await qb.getMany()
|
|
638
722
|
return { items, total }
|
|
639
723
|
} catch (error) {
|
|
640
724
|
debug('deliveryOrders', error.toString())
|
|
@@ -662,7 +746,8 @@ export async function deliveryOrderByReleaseGood(releaseGood: ReleaseGood, trxMg
|
|
|
662
746
|
const doRepo: Repository<DeliveryOrder> = trxMgr?.getRepository(DeliveryOrder) || getRepository(DeliveryOrder)
|
|
663
747
|
const oiRepo: Repository<OrderInventory> = trxMgr?.getRepository(OrderInventory) || getRepository(OrderInventory)
|
|
664
748
|
|
|
665
|
-
|
|
749
|
+
const total = await doRepo.count({ where: { releaseGood } })
|
|
750
|
+
let items = await doRepo.find({
|
|
666
751
|
where: { releaseGood },
|
|
667
752
|
relations: ['domain', 'bizplace', 'releaseGood', 'transportDriver', 'transportVehicle', 'creator', 'updater']
|
|
668
753
|
})
|
|
@@ -128,6 +128,8 @@ export class ReleaseGoodMutation {
|
|
|
128
128
|
let releaseGoods: Partial<ReleaseGood[]> = extractRawReleaseGoods(rawReleaseGoods)
|
|
129
129
|
|
|
130
130
|
let errorsCaught: any[] = []
|
|
131
|
+
let successCaught: string[] = []
|
|
132
|
+
let failedCaught: string[] = []
|
|
131
133
|
for (let i = 0, l = releaseGoods.length; i < l; i++) {
|
|
132
134
|
// generate release good by group to avoid duplication
|
|
133
135
|
// if this function is called simultaneously by different users
|
|
@@ -172,9 +174,31 @@ export class ReleaseGoodMutation {
|
|
|
172
174
|
|
|
173
175
|
createdReleaseGoods.push(createdReleaseGood)
|
|
174
176
|
})
|
|
177
|
+
// track successfully created order labels for toast message
|
|
178
|
+
const rg = releaseGoods[i] as any
|
|
179
|
+
const label = rg.refNo2 ? `${rg.refNo} / ${rg.refNo2}` : rg.refNo
|
|
180
|
+
successCaught.push(label)
|
|
175
181
|
} catch (error) {
|
|
176
|
-
|
|
177
|
-
|
|
182
|
+
// track failed order labels for toast message
|
|
183
|
+
const failedRg = releaseGoods[i] as any
|
|
184
|
+
const failedLabel = failedRg.refNo2 ? `${failedRg.refNo} / ${failedRg.refNo2}` : failedRg.refNo
|
|
185
|
+
failedCaught.push(failedLabel)
|
|
186
|
+
// for insufficient stock errors, use per-item error messages from availableItems
|
|
187
|
+
if (error?.detail?.data) {
|
|
188
|
+
try {
|
|
189
|
+
const perItemData: any[] = JSON.parse(error.detail.data)
|
|
190
|
+
const flatRows = perItemData.map((item: any) => {
|
|
191
|
+
const row = { ...releaseGoods[i], ...item, errorMsg: item.errorMsg || error.message }
|
|
192
|
+
delete row.orderInventories
|
|
193
|
+
return row
|
|
194
|
+
})
|
|
195
|
+
errorsCaught.push(...flatRows)
|
|
196
|
+
} catch {
|
|
197
|
+
errorsCaught.push(...formRawReleaseGoods(releaseGoods[i], error.message))
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
errorsCaught.push(...formRawReleaseGoods(releaseGoods[i], error.message))
|
|
201
|
+
}
|
|
178
202
|
}
|
|
179
203
|
}
|
|
180
204
|
|
|
@@ -218,7 +242,7 @@ export class ReleaseGoodMutation {
|
|
|
218
242
|
if (errorsCaught.length)
|
|
219
243
|
throw new ValidationError({
|
|
220
244
|
...ValidationError.ERROR_CODES.INVALID_DATA_FOUND,
|
|
221
|
-
detail: { data: JSON.stringify(errorsCaught) }
|
|
245
|
+
detail: { data: JSON.stringify(errorsCaught), successOrders: successCaught, failedOrders: failedCaught }
|
|
222
246
|
})
|
|
223
247
|
|
|
224
248
|
return confirmedReleaseGoods
|
|
@@ -2164,7 +2188,14 @@ function extractRawReleaseGoods(rawReleaseGoods): Partial<ReleaseGood[]> {
|
|
|
2164
2188
|
|
|
2165
2189
|
if (idx >= 0) {
|
|
2166
2190
|
const duplicateSkuIdx: number = releaseGoods[idx].orderInventories.findIndex(
|
|
2167
|
-
oi =>
|
|
2191
|
+
oi =>
|
|
2192
|
+
oi.sku === item.sku &&
|
|
2193
|
+
oi.packingType === item.packingType &&
|
|
2194
|
+
oi.packingSize === item.packingSize &&
|
|
2195
|
+
oi.uom === item.uom &&
|
|
2196
|
+
oi.batchId === item.batchId &&
|
|
2197
|
+
oi.cartonId === item.cartonId &&
|
|
2198
|
+
oi.expirationDate === item.expirationDate
|
|
2168
2199
|
)
|
|
2169
2200
|
|
|
2170
2201
|
// if there is duplicated SKU, merge them and sum up the releaseQty
|
|
@@ -2182,7 +2213,10 @@ function extractRawReleaseGoods(rawReleaseGoods): Partial<ReleaseGood[]> {
|
|
|
2182
2213
|
packingSize: item.packingSize,
|
|
2183
2214
|
uom: item.uom,
|
|
2184
2215
|
releaseQty: Math.round(parseFloat(item.releaseQty) * 1000) / 1000,
|
|
2185
|
-
releaseUomValue: Math.round(parseFloat(item.releaseUomValue) * 1000) / 1000
|
|
2216
|
+
releaseUomValue: Math.round(parseFloat(item.releaseUomValue) * 1000) / 1000,
|
|
2217
|
+
batchId: item?.batchId || null,
|
|
2218
|
+
cartonId: item?.cartonId || null,
|
|
2219
|
+
expirationDate: item?.expirationDate || null
|
|
2186
2220
|
})
|
|
2187
2221
|
}
|
|
2188
2222
|
} else {
|
|
@@ -1097,22 +1097,24 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
|
|
|
1097
1097
|
${useDetailedQuery ? ' i.batch_id, i.carton_id, i.expiration_date,' : ''}
|
|
1098
1098
|
SUM(i.qty - COALESCE(i.locked_qty, 0)) - COALESCE(
|
|
1099
1099
|
(
|
|
1100
|
-
SELECT SUM(oi.release_qty) FROM order_inventories oi
|
|
1100
|
+
SELECT SUM(oi.release_qty) FROM order_inventories oi
|
|
1101
1101
|
WHERE oi.status IN ('PENDING', 'PENDING_RECEIVE', 'PENDING_WORKSHEET', 'PENDING_SPLIT')
|
|
1102
1102
|
AND oi.inventory_id IS null
|
|
1103
1103
|
AND oi.product_id = i.product_id::uuid
|
|
1104
1104
|
AND oi.packing_type = i.packing_type
|
|
1105
|
+
AND oi.packing_size = i.packing_size
|
|
1105
1106
|
AND oi.uom = i.uom
|
|
1106
1107
|
AND oi.domain_id = $1
|
|
1107
1108
|
AND oi.bizplace_id = $2
|
|
1108
1109
|
), 0) as "remain_qty",
|
|
1109
1110
|
SUM(i.uom_value - COALESCE(i.locked_uom_value, 0)) - COALESCE(
|
|
1110
1111
|
(
|
|
1111
|
-
SELECT SUM(oi.release_uom_value) FROM order_inventories oi
|
|
1112
|
+
SELECT SUM(oi.release_uom_value) FROM order_inventories oi
|
|
1112
1113
|
WHERE oi.status IN ('PENDING', 'PENDING_RECEIVE', 'PENDING_WORKSHEET', 'PENDING_SPLIT')
|
|
1113
1114
|
AND oi.inventory_id IS null
|
|
1114
1115
|
AND oi.product_id = i.product_id::uuid
|
|
1115
1116
|
AND oi.packing_type = i.packing_type
|
|
1117
|
+
AND oi.packing_size = i.packing_size
|
|
1116
1118
|
AND oi.uom = i.uom
|
|
1117
1119
|
AND oi.domain_id = $1
|
|
1118
1120
|
AND oi.bizplace_id = $2
|
|
@@ -1240,7 +1242,6 @@ function _extractData(rawData, validatedData) {
|
|
|
1240
1242
|
|
|
1241
1243
|
return val.sku.toLowerCase() == raw.sku.toLowerCase() && a === b
|
|
1242
1244
|
})
|
|
1243
|
-
|
|
1244
1245
|
let releaseUomValue = 0
|
|
1245
1246
|
|
|
1246
1247
|
// if sku is matched, assign qty and product id
|