@things-factory/sales-base 4.3.605 → 4.3.607
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-query.js +70 -66
- package/dist-server/service/arrival-notice/arrival-notice-query.js.map +1 -1
- package/dist-server/service/draft-release-good/draft-release-good-create.js +22 -12
- package/dist-server/service/draft-release-good/draft-release-good-create.js.map +1 -1
- package/dist-server/service/draft-release-good/draft-release-good-type.js +12 -0
- package/dist-server/service/draft-release-good/draft-release-good-type.js.map +1 -1
- package/dist-server/service/release-good/release-good-query.js +11 -2
- package/dist-server/service/release-good/release-good-query.js.map +1 -1
- package/dist-server/utils/datetime-util.js +22 -1
- package/dist-server/utils/datetime-util.js.map +1 -1
- package/dist-server/utils/inventory-util.js +2 -0
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/package.json +2 -2
- package/server/service/arrival-notice/arrival-notice-query.ts +116 -77
- package/server/service/draft-release-good/draft-release-good-create.ts +73 -18
- package/server/service/draft-release-good/draft-release-good-type.ts +10 -6
- package/server/service/release-good/release-good-query.ts +15 -7
- package/server/utils/datetime-util.ts +23 -0
- package/server/utils/inventory-util.ts +25 -4
|
@@ -1,19 +1,54 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Arg,
|
|
3
|
+
Ctx,
|
|
4
|
+
Directive,
|
|
5
|
+
Mutation,
|
|
6
|
+
Resolver
|
|
7
|
+
} from 'type-graphql'
|
|
8
|
+
import {
|
|
9
|
+
EntityManager,
|
|
10
|
+
getConnection,
|
|
11
|
+
getRepository,
|
|
12
|
+
In,
|
|
13
|
+
Repository
|
|
14
|
+
} from 'typeorm'
|
|
3
15
|
|
|
4
16
|
import { Bizplace } from '@things-factory/biz-base'
|
|
5
17
|
import { logger } from '@things-factory/env'
|
|
18
|
+
import {
|
|
19
|
+
WebhookEventsEnum,
|
|
20
|
+
webhookHandler
|
|
21
|
+
} from '@things-factory/integration-base'
|
|
6
22
|
import { ProductBundle } from '@things-factory/product-base'
|
|
7
|
-
import {
|
|
8
|
-
|
|
23
|
+
import {
|
|
24
|
+
PartnerSetting,
|
|
25
|
+
Setting
|
|
26
|
+
} from '@things-factory/setting-base'
|
|
9
27
|
import { Domain } from '@things-factory/shell'
|
|
10
|
-
|
|
11
|
-
import {
|
|
28
|
+
|
|
29
|
+
import {
|
|
30
|
+
bulkReleaseGoodsAvailableItemsFunction,
|
|
31
|
+
DraftReleaseGood,
|
|
32
|
+
DraftReleaseGoodInfos,
|
|
33
|
+
OrderProduct
|
|
34
|
+
} from '../'
|
|
35
|
+
import {
|
|
36
|
+
DRAFT_RELEASE_ORDER_STATUS,
|
|
37
|
+
ORDER_NUMBER_SETTING_KEY,
|
|
38
|
+
ORDER_STATUS
|
|
39
|
+
} from '../../constants'
|
|
12
40
|
import { ValidationError } from '../../errors'
|
|
13
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
InventoryUtil,
|
|
43
|
+
OrderNoGenerator
|
|
44
|
+
} from '../../utils'
|
|
14
45
|
import { ReleaseGood } from '../release-good/release-good'
|
|
46
|
+
import {
|
|
47
|
+
bulkGenerateReleaseGood,
|
|
48
|
+
confirmReleaseGood,
|
|
49
|
+
receiveReleaseGood
|
|
50
|
+
} from '../release-good/release-good-mutation'
|
|
15
51
|
import { SuccessReleasedDraftOrder } from './draft-release-good-type'
|
|
16
|
-
import { bulkGenerateReleaseGood, confirmReleaseGood, receiveReleaseGood } from '../release-good/release-good-mutation'
|
|
17
52
|
|
|
18
53
|
@Resolver(DraftReleaseGood)
|
|
19
54
|
export class DraftReleaseGoodCreate {
|
|
@@ -71,6 +106,7 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
71
106
|
relations: [
|
|
72
107
|
'orderProducts',
|
|
73
108
|
'orderProducts.product',
|
|
109
|
+
'orderProducts.productDetail',
|
|
74
110
|
'orderProducts.productBundle',
|
|
75
111
|
'orderProducts.productBundle.productBundleSettings',
|
|
76
112
|
'orderProducts.productBundle.productBundleSettings.product',
|
|
@@ -85,6 +121,7 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
85
121
|
]
|
|
86
122
|
})
|
|
87
123
|
let failReleaseOrder = []
|
|
124
|
+
let successReleaseOrder = []
|
|
88
125
|
|
|
89
126
|
if (updatableDraftOrders.length > 0) {
|
|
90
127
|
const settingRepo: Repository<Setting> = tx?.getRepository(Setting) || getRepository(Setting)
|
|
@@ -142,7 +179,8 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
142
179
|
name: 'productId',
|
|
143
180
|
operator: 'in',
|
|
144
181
|
value: productIds
|
|
145
|
-
}
|
|
182
|
+
},
|
|
183
|
+
{ name: 'deleted_at', operator: 'eq', value: true }
|
|
146
184
|
]
|
|
147
185
|
},
|
|
148
186
|
context,
|
|
@@ -178,8 +216,11 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
178
216
|
}
|
|
179
217
|
})
|
|
180
218
|
|
|
181
|
-
let
|
|
182
|
-
|
|
219
|
+
let failedInventory = draftOrder.orderProducts.find(
|
|
220
|
+
op => op.status == 'insufficient' || op.productDetail.deletedAt != null
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
if (!failedInventory) {
|
|
183
224
|
//create RO
|
|
184
225
|
let releaseGood = { ...draftOrder }
|
|
185
226
|
delete releaseGood.id
|
|
@@ -266,6 +307,14 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
266
307
|
context,
|
|
267
308
|
innerTx2
|
|
268
309
|
)
|
|
310
|
+
|
|
311
|
+
if (availableItems.some(item => item.orderProduct.productDetail.deletedAt != null)) {
|
|
312
|
+
throw new ValidationError({
|
|
313
|
+
...ValidationError.ERROR_CODES.DELETED_PRODUCT_DETAIL,
|
|
314
|
+
detail: { data: JSON.stringify(availableItems) }
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
|
|
269
318
|
if (availableItems.some(item => !item.releaseQty || item.releaseQty > item.assignedQty))
|
|
270
319
|
throw new ValidationError({
|
|
271
320
|
...ValidationError.ERROR_CODES.INSUFFICIENT_STOCK,
|
|
@@ -303,6 +352,7 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
303
352
|
if (existingReleaseGood.length > 1) {
|
|
304
353
|
throw new Error('generating release orders')
|
|
305
354
|
}
|
|
355
|
+
// successReleaseOrder.push({ draftName: draftOrder?.name, status: 'success' })
|
|
306
356
|
})
|
|
307
357
|
|
|
308
358
|
await innerTx2
|
|
@@ -332,6 +382,7 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
332
382
|
|
|
333
383
|
createdReleaseGood = await confirmReleaseGood(createdReleaseGood.name, context, innerTx2)
|
|
334
384
|
|
|
385
|
+
successReleaseOrder.push({ draftName: draftOrder?.name, status: 'success' })
|
|
335
386
|
if (settingValue > 1) {
|
|
336
387
|
createdReleaseGood = await receiveReleaseGood(createdReleaseGood.name, context, innerTx2)
|
|
337
388
|
}
|
|
@@ -340,8 +391,12 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
340
391
|
webhookHandler(createdReleaseGood, createdReleaseGood.bizplace, WebhookEventsEnum.ReleaseOrderCreated)
|
|
341
392
|
})
|
|
342
393
|
} else {
|
|
343
|
-
if (
|
|
344
|
-
|
|
394
|
+
if (
|
|
395
|
+
draftOrder.orderProducts.some(op => op.id === failedInventory?.id && op.productDetail.deletedAt != null)
|
|
396
|
+
) {
|
|
397
|
+
failReleaseOrder.push({ draftName: draftOrder?.name, status: 'deleted' })
|
|
398
|
+
} else {
|
|
399
|
+
failReleaseOrder.push({ draftName: draftOrder?.name, status: 'insufficient' })
|
|
345
400
|
}
|
|
346
401
|
}
|
|
347
402
|
} catch (e) {
|
|
@@ -352,12 +407,12 @@ export async function generateReleaseGoods(_generateReleaseGoodsRecord, context:
|
|
|
352
407
|
})
|
|
353
408
|
}
|
|
354
409
|
}
|
|
355
|
-
releasedOrders
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
410
|
+
releasedOrders.push({
|
|
411
|
+
successCount: successReleaseOrder.length,
|
|
412
|
+
insufficientCount: failReleaseOrder.filter(fro => fro.status === 'insufficient').length,
|
|
413
|
+
deletedCount: failReleaseOrder.filter(fro => fro.status === 'deleted').length
|
|
360
414
|
})
|
|
415
|
+
|
|
361
416
|
return releasedOrders
|
|
362
417
|
} catch (e) {
|
|
363
418
|
logger.error(`draft-release-good-mutation[generateReleaseGoodsFromDraft]: ${e?.message}`)
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Field,
|
|
3
|
-
InputType,
|
|
4
|
-
Int,
|
|
5
|
-
ObjectType
|
|
6
|
-
} from 'type-graphql'
|
|
1
|
+
import { Field, InputType, Int, ObjectType } from 'type-graphql'
|
|
7
2
|
|
|
8
3
|
import { ObjectRef } from '@things-factory/shell'
|
|
9
4
|
|
|
@@ -287,6 +282,15 @@ export class SuccessReleasedDraftOrder {
|
|
|
287
282
|
|
|
288
283
|
@Field({ nullable: true })
|
|
289
284
|
isProductBundle?: Boolean
|
|
285
|
+
|
|
286
|
+
@Field({ nullable: true })
|
|
287
|
+
successCount?: number
|
|
288
|
+
|
|
289
|
+
@Field({ nullable: true })
|
|
290
|
+
insufficientCount?: number
|
|
291
|
+
|
|
292
|
+
@Field({ nullable: true })
|
|
293
|
+
deletedCount?: number
|
|
290
294
|
}
|
|
291
295
|
|
|
292
296
|
@InputType()
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
ORDER_STATUS,
|
|
48
48
|
ORDER_VAS_STATUS
|
|
49
49
|
} from '../../constants'
|
|
50
|
+
import { convertExcelDateToISO } from '../../utils/datetime-util'
|
|
50
51
|
import { OrderInventory } from '../order-inventory/order-inventory'
|
|
51
52
|
import { OrderPackage } from '../order-package/order-package'
|
|
52
53
|
import { ShippingOrder } from '../shipping-order/shipping-order'
|
|
@@ -1105,6 +1106,8 @@ function _extractData(rawData, validatedData) {
|
|
|
1105
1106
|
let errMsg
|
|
1106
1107
|
let comparison = ['packingType', 'packingSize', 'uom']
|
|
1107
1108
|
let data = validatedData
|
|
1109
|
+
raw.releaseDate = raw.releaseDate ? convertExcelDateToISO(raw.releaseDate) : null
|
|
1110
|
+
raw.expirationDate = raw.expirationDate ? convertExcelDateToISO(raw.expirationDate) : null
|
|
1108
1111
|
if (raw.batchId) {
|
|
1109
1112
|
data = data.filter(val => val.batchId === raw.batchId)
|
|
1110
1113
|
comparison.push('batchId')
|
|
@@ -1176,7 +1179,8 @@ function _extractData(rawData, validatedData) {
|
|
|
1176
1179
|
raw.productId = null
|
|
1177
1180
|
}
|
|
1178
1181
|
|
|
1179
|
-
|
|
1182
|
+
|
|
1183
|
+
const dateRegex = /^\d{4}-\d{2}-\d{2}$/
|
|
1180
1184
|
|
|
1181
1185
|
return {
|
|
1182
1186
|
...raw,
|
|
@@ -1196,17 +1200,19 @@ function _extractData(rawData, validatedData) {
|
|
|
1196
1200
|
if (raw.assignedQty < raw.releaseQty) {
|
|
1197
1201
|
errors.push('insufficient stock');
|
|
1198
1202
|
}
|
|
1203
|
+
if(!dateRegex.test(raw.releaseDate)){
|
|
1204
|
+
errors.push('invalid release date format. please use dd/mm/yyyy')
|
|
1205
|
+
}
|
|
1199
1206
|
if (raw.releaseDate === '') {
|
|
1200
1207
|
errors.push('release date is empty');
|
|
1201
1208
|
}
|
|
1202
|
-
if (releaseDate < _getStdDateStr(new Date())) {
|
|
1209
|
+
if (raw.releaseDate < _getStdDateStr(new Date())) {
|
|
1203
1210
|
errors.push('backdate is not allowed');
|
|
1204
1211
|
}
|
|
1205
1212
|
if (!raw.refNo || raw.refNo === '') {
|
|
1206
1213
|
errors.push('ref no is empty');
|
|
1207
1214
|
}
|
|
1208
|
-
|
|
1209
|
-
if (raw?.type === 'b2c') {
|
|
1215
|
+
if (raw?.type === 'b2c') {
|
|
1210
1216
|
if (!raw.attentionTo) errors.push('attention to is empty');
|
|
1211
1217
|
if (!raw.postalCode) errors.push('postal code is empty');
|
|
1212
1218
|
if (!raw.country) errors.push('country is empty');
|
|
@@ -1217,12 +1223,14 @@ function _extractData(rawData, validatedData) {
|
|
|
1217
1223
|
if ((raw.codOption && !raw.paidAmount) || raw.paidAmount < 0 || raw.paidAmount == null) {
|
|
1218
1224
|
errors.push('invalid paid amount');
|
|
1219
1225
|
}
|
|
1226
|
+
if(raw?.expirationDate != null && !dateRegex.test(raw?.expirationDate)){
|
|
1227
|
+
errors.push('invalid expiration date format. please use dd/mm/yyyy')
|
|
1228
|
+
}
|
|
1220
1229
|
if (raw.airwayBill && raw.lmdOption === true) {
|
|
1221
1230
|
errors.push('kindly remove AWB as LMD is marked as true');
|
|
1222
1231
|
}
|
|
1223
1232
|
}
|
|
1224
|
-
|
|
1225
|
-
return errors.length > 0 ? errors.join(', ') : ''; // Combine all errors into a single string
|
|
1233
|
+
return errors.length > 0 ? errors.join(', ') : ''// Combine all errors into a single string
|
|
1226
1234
|
})(),
|
|
1227
1235
|
};
|
|
1228
1236
|
|
|
@@ -1252,4 +1260,4 @@ function _getStdDateStr(date) {
|
|
|
1252
1260
|
date.setHours(date.getHours() + 8)
|
|
1253
1261
|
return date.toISOString().split('T')[0]
|
|
1254
1262
|
}
|
|
1255
|
-
}
|
|
1263
|
+
}
|
|
@@ -66,3 +66,26 @@ export class DateTimeDifference {
|
|
|
66
66
|
return diffInSeconds
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
export function isValidExcelDate(excelSerial) {
|
|
71
|
+
// Check if the serial number is a valid positive number
|
|
72
|
+
if (isNaN(excelSerial) || excelSerial <= 0) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const date = new Date((parseInt(excelSerial) - 25569) * 86400 * 1000)
|
|
76
|
+
|
|
77
|
+
return !isNaN(date.getTime());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function convertExcelDateToISO(excelSerial) {
|
|
81
|
+
if (!isValidExcelDate(excelSerial)) {
|
|
82
|
+
return excelSerial; // Invalid date serial
|
|
83
|
+
}
|
|
84
|
+
const date = new Date((parseInt(excelSerial) - 25569) * 86400 * 1000)
|
|
85
|
+
// Format the date in YYYY-MM-DD format
|
|
86
|
+
const year = date.getFullYear();
|
|
87
|
+
const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are zero-indexed
|
|
88
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
89
|
+
|
|
90
|
+
return `${year}-${month}-${day}`;
|
|
91
|
+
}
|
|
@@ -1,10 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
EntityManager,
|
|
3
|
+
Equal,
|
|
4
|
+
getRepository,
|
|
5
|
+
In,
|
|
6
|
+
Not,
|
|
7
|
+
Raw,
|
|
8
|
+
Repository,
|
|
9
|
+
SelectQueryBuilder
|
|
10
|
+
} from 'typeorm'
|
|
2
11
|
|
|
3
12
|
import { User } from '@things-factory/auth-base'
|
|
4
13
|
import { Bizplace } from '@things-factory/biz-base'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
14
|
+
import {
|
|
15
|
+
Product,
|
|
16
|
+
ProductBundle,
|
|
17
|
+
ProductDetail
|
|
18
|
+
} from '@things-factory/product-base'
|
|
19
|
+
import {
|
|
20
|
+
PartnerSetting,
|
|
21
|
+
Setting
|
|
22
|
+
} from '@things-factory/setting-base'
|
|
23
|
+
import {
|
|
24
|
+
Domain,
|
|
25
|
+
ListParam
|
|
26
|
+
} from '@things-factory/shell'
|
|
8
27
|
import {
|
|
9
28
|
generateInventoryHistory,
|
|
10
29
|
Inventory,
|
|
@@ -57,6 +76,7 @@ export const InventoryUtil = {
|
|
|
57
76
|
|
|
58
77
|
let productFilter = filters.find(itm => itm.name == 'productName')
|
|
59
78
|
let inventoryBizplaceFilter = filters.find(itm => itm.name == 'bizplaceId')
|
|
79
|
+
let deletedAt = filters.find(filter => filter.name == 'deleted_at')
|
|
60
80
|
|
|
61
81
|
let queryStrings = `
|
|
62
82
|
CREATE TEMP TABLE temp_inventory_product_group ON COMMIT DROP AS (
|
|
@@ -152,6 +172,7 @@ export const InventoryUtil = {
|
|
|
152
172
|
`
|
|
153
173
|
: ``
|
|
154
174
|
}
|
|
175
|
+
${deletedAt && deletedAt.value == true ? `AND pd.deleted_at isnull` : ``}
|
|
155
176
|
GROUP BY
|
|
156
177
|
i.lock_inventory,
|
|
157
178
|
p.id,
|