This commit is contained in:
2026-08-07 19:23:46 +08:00
parent aa6c349fce
commit 0b2380689c
10 changed files with 77 additions and 52 deletions
@@ -52,7 +52,7 @@ function validDraft() {
destinationType: 'FBA',
amazonWarehouseCode: 'ONT8',
shipmentId: 'FBA-001',
items: [{ ...createEmptyCargoItem('cargo-1'), sku: 'SKU-001', upc: '012345678905', cargoNameCn: '家居用品', pieces: 100, grossWeightKg: 1200, volumeCbm: 3.5, containerType: '40HQ', containerCount: 1 }],
items: [{ ...createEmptyCargoItem('cargo-1'), sku: 'SKU-001', upc: '012345678905', cargoNameCn: '家居用品', pieces: 100, grossWeightKg: 1200, volumeCbm: 3.5, shipmentId: 'FBA-001', referenceId: 'REF-001' }],
}
}
@@ -81,13 +81,10 @@ test('validates the confirmed minimum submission fields', () => {
const invalid = validDraft()
invalid.receivingWarehouseId = ''
invalid.items[0].grossWeightKg = 0
invalid.items[0].containerType = ''
invalid.items[0].containerCount = 0
const errors = validateFirstLegOrderDraft(invalid)
assert.ok(errors.includes('请选择平台收货仓'))
assert.ok(errors.includes('第 1 条货物毛重必须大于 0'))
assert.ok(errors.includes('第 1 条货物需要填写箱型和柜量'))
})
test('only requires sender for pickup and receiver for a private destination', () => {
@@ -111,20 +108,22 @@ test('only requires sender for pickup and receiver for a private destination', (
assert.ok(validateFirstLegOrderDraft(privateDraft).includes('请填写收件人姓名'))
})
test('requires FBA reference, warehouse, shipment, SKU and UPC fields', () => {
test('requires FBA warehouse and cargo-level shipment, reference, SKU and UPC fields', () => {
const draft = validDraft()
draft.referenceNo = ''
draft.amazonWarehouseCode = ''
draft.shipmentId = ''
draft.items[0].sku = ''
draft.items[0].upc = ''
draft.items[0].shipmentId = ''
draft.items[0].referenceId = ''
const errors = validateFirstLegOrderDraft(draft)
assert.ok(errors.includes('FBA 订单请填写客户参考号'))
assert.ok(errors.includes('FBA 订单请填写 Amazon 仓库编码'))
assert.ok(errors.includes('FBA 订单请填写 Shipment ID'))
assert.ok(errors.includes('第 1 条货物缺少客户 SKU'))
assert.ok(errors.includes('第 1 条货物缺少 UPC'))
assert.ok(errors.includes('第 1 条货物缺少 Shipment ID'))
assert.ok(errors.includes('第 1 条货物缺少 Reference ID'))
})
test('requires public destination ids while keeping private addresses detached from public warehouses', () => {
@@ -141,15 +140,6 @@ test('requires public destination ids while keeping private addresses detached f
assert.ok(validateFirstLegOrderDraft(privateDraft).includes('私人地址不能引用平台公共仓库'))
})
test('does not require container details for non-FCL cargo', () => {
const draft = validDraft()
draft.transportMode = 'AIR'
draft.items[0].containerType = ''
draft.items[0].containerCount = 0
assert.deepEqual(validateFirstLegOrderDraft(draft), [])
})
test('summarizes cargo values from line items', () => {
const first = validDraft().items[0]
const second = { ...first, id: 'cargo-2', pieces: 40, packageCount: 4, grossWeightKg: 300, volumeCbm: 1.25 }
@@ -78,8 +78,6 @@ export function createEmptyCargoItem(id = `cargo-${Date.now()}`): FirstLegCargoI
productHeightCm: 0,
shipmentId: '',
referenceId: '',
containerType: '',
containerCount: 0,
remark: '',
packageType: 'CARTON',
hsCode: '',
@@ -132,9 +130,6 @@ export function validateFirstLegOrderDraft(draft: FirstLegOrderDraft) {
if (!Number.isInteger(item.unitsPerPackage) || item.unitsPerPackage <= 0) errors.push(`${line}每箱数量必须为正整数`)
if (item.grossWeightKg <= 0) errors.push(`${line}毛重必须大于 0`)
if (item.volumeCbm <= 0) errors.push(`${line}体积必须大于 0`)
if (draft.transportMode === 'FCL' && (!item.containerType || item.containerCount <= 0)) {
errors.push(`${line}需要填写箱型和柜量`)
}
})
return errors
+6 -3
View File
@@ -1,11 +1,14 @@
const allowedTypes = new Set(['image/jpeg', 'image/png'])
const allowedExtensions = new Set(['jpg', 'jpeg', 'png'])
const allowedImageTypes: Readonly<Record<string, ReadonlySet<string>>> = {
'image/jpeg': new Set(['jpg', 'jpeg']),
'image/png': new Set(['png']),
}
export const PRODUCT_IMAGE_MAX_SIZE = 5 * 1024 * 1024
export function validateProductImageFile(file: Pick<File, 'name' | 'size' | 'type'>) {
const extension = file.name.split('.').pop()?.toLowerCase() ?? ''
if (!allowedTypes.has(file.type.toLowerCase()) || !allowedExtensions.has(extension)) {
const allowedExtensions = allowedImageTypes[file.type.toLowerCase()]
if (!allowedExtensions?.has(extension)) {
return '产品图片仅支持 JPG、JPEG、PNG 格式'
}
if (file.size <= 0) return '产品图片内容为空'