This commit is contained in:
2026-08-17 16:45:43 +08:00
parent 592da4d7e2
commit c71db4b481
6 changed files with 308 additions and 17 deletions
+45 -15
View File
@@ -8,6 +8,15 @@ import { pathToFileURL } from 'node:url'
const MAX_COUNT = 100
const MAX_ROUTE_POOL_SIZE = 40
const MAX_DESTINATIONS_PER_LOGISTICS = 3
const TRADE_TERMS = ['FOB', 'EXW', 'CIF', 'DDP']
const PICKUP_METHODS = ['SELF_EXPRESS', 'PICKUP', 'SELF_TRUCK']
const TAX_MODES = ['BUY_DECLARATION', 'TAX_REFUND']
const SENDER_LOCATIONS = [
{ province: '广东省', city: '深圳市', district: '南山区', postalCode: '518000' },
{ province: '广东省', city: '东莞市', district: '南城街道', postalCode: '523000' },
{ province: '浙江省', city: '义乌市', district: '稠城街道', postalCode: '322000' },
{ province: '福建省', city: '厦门市', district: '湖里区', postalCode: '361000' },
]
export const PRODUCT_CATALOG = [
{ cargoName: '蓝牙音箱', cargoNameEn: 'Bluetooth speaker', hsCode: '8518210000', material: '塑料和电子元件 / Plastic and electronic components', usage: '音频播放 / Audio playback', brand: 'SOUNDTEST', modelPrefix: 'SPK', lengthCm: 42, widthCm: 32, heightCm: 28, unitsPerPackage: 8, cartonGrossWeightKg: 12.8, unitDeclaredValue: 18.5, productLengthCm: 18, productWidthCm: 10, productHeightCm: 8 },
@@ -85,6 +94,10 @@ function shuffled(values) {
return result
}
function pickRandom(values) {
return values[randomInt(values.length)]
}
function round(value, scale) {
return Number(value.toFixed(scale))
}
@@ -110,6 +123,17 @@ export function diversifyRoutes(routes) {
return result
}
export function randomOrderOptions() {
return {
tradeTerm: pickRandom(TRADE_TERMS),
pickupMethod: pickRandom(PICKUP_METHODS),
taxMode: pickRandom(TAX_MODES),
customsInspection: randomInt(2) === 1,
expectedShipDays: randomInt(7, 61),
senderLocation: pickRandom(SENDER_LOCATIONS),
}
}
function requireSuccess(response, action) {
if (response.http !== 200 || String(response.body?.code) !== '200') {
throw new Error(`${action} failed: http=${response.http}, code=${response.body?.code ?? 'missing'}, message=${response.body?.message ?? 'missing'}, requestId=${response.requestId || 'missing'}, traceId=${response.traceId || 'missing'}`)
@@ -214,7 +238,7 @@ async function uploadProductImage(gateway, timeoutMs, token, marker) {
return data.fileId
}
export function buildOrderPayload({ marker, index, profile, master, product, packageCount, productImageFileId }) {
export function buildOrderPayload({ marker, index, profile, master, product, packageCount, options = randomOrderOptions(), productImageFileId }) {
const sequence = String(index).padStart(3, '0')
const shipmentId = `SHIP-${sequence}-${marker}`.slice(0, 64)
const referenceId = `REF-${sequence}-${marker}`.slice(0, 64)
@@ -228,39 +252,39 @@ export function buildOrderPayload({ marker, index, profile, master, product, pac
customerId: profile.id,
customerName: companyName,
transportMode: 'SEA',
tradeTerm: 'FOB',
tradeTerm: options.tradeTerm,
destinationCountryCode: master.destination.countryCode || 'US',
destinationWarehouseId: master.destination.id,
destinationWarehouseName: master.destination.warehouseName,
expectedShipDate: addDays(new Date(), 30),
customerRemark: `待审核订单 ${sequence} ${marker}`,
pickupMethod: 'PICKUP',
expectedShipDate: addDays(new Date(), options.expectedShipDays),
customerRemark: `基础待审核订单 ${sequence} ${marker} ${options.tradeTerm}`,
pickupMethod: options.pickupMethod,
receivingWarehouseId: master.receiving.id,
receivingWarehouseName: master.receiving.warehouseName,
channelCode: master.channel.channelCode,
channelName: master.channel.channelName,
carrierId: null,
carrierName: null,
taxMode: 'BUY_DECLARATION',
taxMode: options.taxMode,
pricingTaxMode: master.pricingTaxMode,
containerMode: 'LCL',
customsInspection: false,
customsInspection: options.customsInspection,
destinationType: 'FBA',
amazonWarehouseCode: master.destination.warehouseCode,
shipmentId,
referenceId,
sender: {
sender: options.pickupMethod === 'PICKUP' ? {
companyName,
contactName: '订单测试联系人',
phone: '13800138000',
email: 'pending-order@example.com',
countryCode: 'CN',
province: '广东省',
city: '深圳市',
district: '南山区',
province: options.senderLocation.province,
city: options.senderLocation.city,
district: options.senderLocation.district,
addressLine: `${marker} 固定客户测试地址`,
postalCode: '518000',
},
postalCode: options.senderLocation.postalCode,
} : null,
receiver: null,
cargoes: [{
skuNo: `SKU-${sequence}-${marker}`.slice(0, 64),
@@ -356,7 +380,8 @@ export async function main(argv = process.argv.slice(2)) {
const master = randomizedRoutes[(index - 1) % randomizedRoutes.length]
const product = randomizedProducts[(index - 1) % randomizedProducts.length]
const packageCount = randomInt(1, 31)
const payload = buildOrderPayload({ marker, index, profile, master, product, packageCount, productImageFileId })
const options = randomOrderOptions()
const payload = buildOrderPayload({ marker, index, profile, master, product, packageCount, options, productImageFileId })
const createResponse = await request(gateway, timeoutMs, 'POST',
'/api/merchant/v1/orders/first-leg', {
token,
@@ -401,11 +426,16 @@ export async function main(argv = process.argv.slice(2)) {
channelCode: master.channel.channelCode,
channelName: master.channel.channelName,
pricingTaxMode: master.pricingTaxMode,
tradeTerm: options.tradeTerm,
pickupMethod: options.pickupMethod,
taxMode: options.taxMode,
customsInspection: options.customsInspection,
expectedShipDate: payload.expectedShipDate,
cargoName: product.cargoName,
packageCount,
}
orders.push(result)
console.log(`CREATED ${index}/${count} orderId=${result.orderId} orderNo=${result.orderNo} logistics=${result.channelCode}/${result.pricingTaxMode} destination=${result.destinationWarehouseCode} product=${result.cargoName} cartons=${result.packageCount} status=PENDING_REVIEW`)
console.log(`CREATED ${index}/${count} orderId=${result.orderId} orderNo=${result.orderNo} logistics=${result.channelCode}/${result.pricingTaxMode} destination=${result.destinationWarehouseCode} pickup=${result.pickupMethod} tax=${result.taxMode} inspection=${result.customsInspection} product=${result.cargoName} cartons=${result.packageCount} status=PENDING_REVIEW`)
}
const report = {