front/src/utils/orderCreateOneBody.ts
zzh b178a2a35d
All checks were successful
Build and Deploy Front / deploy (push) Successful in 5m56s
feat: 支付选券、优惠入应收展示、申报产品标识编码、创建9610订单等
- 支付弹窗(PC/H5)支持选券与批量支付体验优化,运单管理复用我的订单支付弹窗;立即支付仅允许待支付订单
- 订单详情费用明细展示优惠券抵扣/会员折扣负数行与「含优惠」;价格配置与手工加费过滤抵扣费用项
- 申报明细新增产品标识编码/非标产品标识编码/标准产品标识编码(PC/H5 下单、改单、详情、开放接口文档、公式目录、Excel 模板)
- 9610 页「批量申报」改为「创建9610订单」:选运单并补充出口资质备案、电商平台
- 店铺订单批量按钮按动作独立 loading,获取面单限并发并显示进度
- 另含:国家管理、登录门户切换、监控与工作台、公告弹窗、nginx/vite 配置等改动
2026-10-19 16:34:06 +08:00

179 lines
7.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/** 从订单详情组装 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
}