All checks were successful
Build and Deploy Front / deploy (push) Successful in 5m56s
- 支付弹窗(PC/H5)支持选券与批量支付体验优化,运单管理复用我的订单支付弹窗;立即支付仅允许待支付订单 - 订单详情费用明细展示优惠券抵扣/会员折扣负数行与「含优惠」;价格配置与手工加费过滤抵扣费用项 - 申报明细新增产品标识编码/非标产品标识编码/标准产品标识编码(PC/H5 下单、改单、详情、开放接口文档、公式目录、Excel 模板) - 9610 页「批量申报」改为「创建9610订单」:选运单并补充出口资质备案、电商平台 - 店铺订单批量按钮按动作独立 loading,获取面单限并发并显示进度 - 另含:国家管理、登录门户切换、监控与工作台、公告弹窗、nginx/vite 配置等改动
179 lines
7.6 KiB
TypeScript
179 lines
7.6 KiB
TypeScript
/** 从订单详情组装 createOrderOne 标准请求体(ForwardWithSubscribe) */
|
||
|
||
function pick(raw: Record<string, any> | undefined, ...keys: string[]) {
|
||
if (!raw) return undefined
|
||
for (const k of keys) {
|
||
const v = raw[k]
|
||
if (v !== undefined && v !== null && v !== '') return v
|
||
}
|
||
return undefined
|
||
}
|
||
|
||
function resolveCountryIso(
|
||
countryRef: unknown,
|
||
countryIdToCode: Map<number, string>
|
||
): string | undefined {
|
||
if (countryRef == null || countryRef === '') return undefined
|
||
if (typeof countryRef === 'string' && countryRef.length === 2) return countryRef.toUpperCase()
|
||
const n = Number(countryRef)
|
||
if (Number.isFinite(n) && countryIdToCode.has(n)) return countryIdToCode.get(n)
|
||
return typeof countryRef === 'string' ? countryRef : undefined
|
||
}
|
||
|
||
function mapItem(raw: Record<string, any>) {
|
||
const hs = pick(raw, 'hsCode', 'HsCode', 'exHsCode', 'ExHsCode', 'imHsCode', 'ImHsCode')
|
||
return {
|
||
cnName: pick(raw, 'cnName', 'CnName'),
|
||
enName: pick(raw, 'enName', 'EnName'),
|
||
sku: pick(raw, 'sku', 'Sku'),
|
||
unit: pick(raw, 'unit', 'Unit'),
|
||
unitPrice: pick(raw, 'unitPrice', 'UnitPrice'),
|
||
unitWeight: pick(raw, 'unitWeight', 'UnitWeight'),
|
||
quantity: pick(raw, 'quantity', 'Quantity'),
|
||
amount: pick(raw, 'amount', 'Amount'),
|
||
weight: pick(raw, 'weight', 'Weight'),
|
||
imHsCode: pick(raw, 'imHsCode', 'ImHsCode') ?? hs,
|
||
exHsCode: pick(raw, 'exHsCode', 'ExHsCode') ?? hs,
|
||
declareElement: pick(raw, 'declareElement', 'DeclareElement'),
|
||
productId: pick(raw, 'productId', 'ProductId'),
|
||
nonStdProductId: pick(raw, 'nonStdProductId', 'NonStdProductId'),
|
||
stdProductId: pick(raw, 'stdProductId', 'StdProductId'),
|
||
skuImage: pick(raw, 'skuImage', 'SkuImage'),
|
||
category: pick(raw, 'category', 'Category'),
|
||
brand: pick(raw, 'brand', 'Brand'),
|
||
brandType: pick(raw, 'brandType', 'BrandType'),
|
||
isMagnetic: raw.isMagnetic === true || raw.IsMagnetic === true || raw.isMagnetic === 1,
|
||
distribution: pick(raw, 'distribution', 'Distribution'),
|
||
material: pick(raw, 'material', 'Material'),
|
||
enMaterial: pick(raw, 'enMaterial', 'EnMaterial'),
|
||
purpose: pick(raw, 'purpose', 'Purpose'),
|
||
attributes: pick(raw, 'attributes', 'Attributes'),
|
||
originCountry: pick(raw, 'originCountry', 'OriginCountry'),
|
||
salesLink: pick(raw, 'salesLink', 'SalesLink'),
|
||
model: pick(raw, 'model', 'Model'),
|
||
specifications: pick(raw, 'specifications', 'Specifications'),
|
||
comment: pick(raw, 'comment', 'Comment'),
|
||
}
|
||
}
|
||
|
||
export function buildCountryIdToCodeMap(countries: any[]): Map<number, string> {
|
||
const map = new Map<number, string>()
|
||
for (const c of countries || []) {
|
||
const id = Number(c.id ?? c.Id)
|
||
const code = String(c.countryCode ?? c.CountryCode ?? '').trim()
|
||
if (Number.isFinite(id) && code) map.set(id, code)
|
||
}
|
||
return map
|
||
}
|
||
|
||
export type BuildCreateOrderOneBodyOptions = {
|
||
/** 服务渠道「预报渠道 code」,写入 productCode;不传则不带 productCode */
|
||
forecastCode?: string | null
|
||
}
|
||
|
||
/**
|
||
* 组装 createOrderOne 请求体。
|
||
* - productCode:取渠道「预报渠道 code」(forecastCode),不是销售产品 code
|
||
* - 不传 channelCode / requestId / exportCustomsMode 等 OMS 扩展字段
|
||
*/
|
||
export function buildCreateOrderOneBody(
|
||
order: Record<string, any>,
|
||
countryIdToCode: Map<number, string>,
|
||
options?: BuildCreateOrderOneBodyOptions
|
||
): Record<string, unknown> {
|
||
const weightList = (order.weightList ?? order.WeightList ?? []) as any[]
|
||
const forecast =
|
||
weightList.find((w) => String(w.type ?? w.Type ?? '').toLowerCase() === 'forecast') ??
|
||
weightList[0] ??
|
||
{}
|
||
|
||
const receiverRaw = (order.receiver ?? order.Receiver ?? {}) as Record<string, any>
|
||
const senderRaw = (order.sender ?? order.Sender ?? {}) as Record<string, any>
|
||
const itemsRaw = (order.items ?? order.Items ?? []) as any[]
|
||
|
||
const receiverCountry =
|
||
pick(order, 'consigneeCountry', 'ConsigneeCountry') ??
|
||
resolveCountryIso(
|
||
pick(receiverRaw, 'countryCode', 'CountryCode', 'country', 'Country'),
|
||
countryIdToCode
|
||
)
|
||
|
||
const senderCountry = resolveCountryIso(
|
||
pick(senderRaw, 'countryCode', 'CountryCode', 'country', 'Country'),
|
||
countryIdToCode
|
||
)
|
||
|
||
const forecastCode = String(options?.forecastCode ?? '').trim()
|
||
|
||
const body: Record<string, unknown> = {
|
||
clientNo: pick(order, 'clientNo', 'ClientNo'),
|
||
trackNo: pick(order, 'trackNo', 'TrackNo'),
|
||
serviceNo: pick(order, 'serviceNo', 'ServiceNo'),
|
||
cargoAttribute: pick(order, 'cargoAttribute', 'CargoAttribute'),
|
||
warehouseId: pick(order, 'warehouseId', 'WarehouseId'),
|
||
customerId: pick(order, 'customerId', 'CustomerId'),
|
||
length: pick(forecast, 'length', 'Length'),
|
||
width: pick(forecast, 'width', 'Width'),
|
||
height: pick(forecast, 'height', 'Height'),
|
||
actualWeight: pick(forecast, 'actualWeight', 'ActualWeight'),
|
||
volumetricWeight: pick(forecast, 'volumetricWeight', 'VolumetricWeight'),
|
||
chargeableWeight: pick(forecast, 'chargeableWeight', 'ChargeableWeight'),
|
||
cubic: pick(forecast, 'cubic', 'Cubic'),
|
||
isCod: order.isCod === true || order.IsCod === true || order.isCod === 1 || order.IsCod === 1,
|
||
codSum: pick(order, 'codSum', 'CodSum') != null ? String(pick(order, 'codSum', 'CodSum')) : undefined,
|
||
codCurrency: pick(order, 'codCurrency', 'CodCurrency'),
|
||
declaredCurrency: pick(order, 'declaredCurrency', 'DeclaredCurrency'),
|
||
declaredSum:
|
||
pick(order, 'declaredSum', 'DeclaredSum') != null
|
||
? String(pick(order, 'declaredSum', 'DeclaredSum'))
|
||
: undefined,
|
||
quantity:
|
||
pick(order, 'quantity', 'Quantity') != null
|
||
? String(pick(order, 'quantity', 'Quantity'))
|
||
: undefined,
|
||
receiver: {
|
||
recipientsName: pick(receiverRaw, 'recipientsName', 'RecipientsName'),
|
||
companyName: pick(receiverRaw, 'companyName', 'CompanyName'),
|
||
phone: pick(receiverRaw, 'phone', 'Phone'),
|
||
telePhone: pick(receiverRaw, 'telePhone', 'TelePhone'),
|
||
email: pick(receiverRaw, 'email', 'Email'),
|
||
countryCode: receiverCountry,
|
||
province: pick(receiverRaw, 'province', 'Province'),
|
||
city: pick(receiverRaw, 'city', 'City'),
|
||
streetNumber: pick(receiverRaw, 'streetNumber', 'StreetNumber'),
|
||
streetAddress1: pick(receiverRaw, 'streetAddress1', 'StreetAddress1'),
|
||
streetAddress2: pick(receiverRaw, 'streetAddress2', 'StreetAddress2'),
|
||
streetAddress3: pick(receiverRaw, 'streetAddress3', 'StreetAddress3'),
|
||
zipCode: pick(receiverRaw, 'zipCode', 'ZipCode'),
|
||
taxType: pick(receiverRaw, 'taxType', 'TaxType'),
|
||
taxNo: pick(receiverRaw, 'taxNo', 'TaxNo'),
|
||
certificateType: pick(receiverRaw, 'certificateType', 'CertificateType'),
|
||
certificateNo: pick(receiverRaw, 'certificateNo', 'CertificateNo'),
|
||
eori: pick(receiverRaw, 'eori', 'Eori'),
|
||
vat: pick(receiverRaw, 'vat', 'Vat'),
|
||
},
|
||
sender: {
|
||
senderName: pick(senderRaw, 'senderName', 'SenderName'),
|
||
company: pick(senderRaw, 'company', 'Company'),
|
||
phone: pick(senderRaw, 'phone', 'Phone'),
|
||
telePhone: pick(senderRaw, 'telePhone', 'TelePhone'),
|
||
email: pick(senderRaw, 'email', 'Email'),
|
||
countryCode: senderCountry,
|
||
province: pick(senderRaw, 'province', 'Province'),
|
||
city: pick(senderRaw, 'city', 'City'),
|
||
zipCode: pick(senderRaw, 'zipCode', 'ZipCode'),
|
||
streetAddress1: pick(senderRaw, 'streetAddress1', 'StreetAddress1'),
|
||
streetAddress2: pick(senderRaw, 'streetAddress2', 'StreetAddress2'),
|
||
streetAddress3: pick(senderRaw, 'streetAddress3', 'StreetAddress3'),
|
||
houseNumber: pick(senderRaw, 'houseNumber', 'HouseNumber'),
|
||
},
|
||
items: itemsRaw.map((row) => mapItem(row)),
|
||
}
|
||
|
||
if (forecastCode) {
|
||
body.productCode = forecastCode
|
||
}
|
||
|
||
return body
|
||
}
|