import { FIRST_LEG_ORDER_STATUSES, FIRST_LEG_TRANSPORT_MODES, type FirstLegOrderStatus, type FirstLegTransportMode, } from '@chongchong/shared' import type { FirstLegCargoItem, FirstLegOrderDraft } from '../types/firstLegOrder.ts' const statusLabels = new Map( FIRST_LEG_ORDER_STATUSES.map((item) => [item.code, item.label]), ) const transportModeLabels = new Map( FIRST_LEG_TRANSPORT_MODES.map((item) => [item.code, item.label]), ) export function getFirstLegStatusLabel(status: FirstLegOrderStatus) { return statusLabels.get(status) ?? status } export function getFirstLegTransportModeLabel(mode: FirstLegTransportMode | null) { if (!mode) return '运输方式待更新' return transportModeLabels.get(mode) ?? mode } export function getFirstLegStatusTone(status: FirstLegOrderStatus): 'success' | 'warning' | 'info' | 'danger' { if (status === 'DELIVERED') return 'success' if (status === 'DRAFT' || status === 'PENDING_REVIEW') return 'warning' return 'info' } export function canClientEditFirstLegOrder(status: FirstLegOrderStatus) { return status === 'DRAFT' } export function canClientCancelFirstLegOrder(status: FirstLegOrderStatus) { return status === 'DRAFT' || status === 'PENDING_REVIEW' } export const FIRST_LEG_PROGRESS_STAGES = FIRST_LEG_ORDER_STATUSES.filter( (item): item is (typeof FIRST_LEG_ORDER_STATUSES)[number] & { code: Exclude } => item.code !== 'DRAFT', ) export function getFirstLegProgressIndex(status: FirstLegOrderStatus) { if (status === 'DRAFT') return -1 return FIRST_LEG_PROGRESS_STAGES.findIndex((item) => item.code === status) } export function createEmptyCargoItem(id = `cargo-${Date.now()}`): FirstLegCargoItem { return { id, sku: '', upc: '', cargoNameCn: '', cargoNameEn: '', productImageFileId: '', productImageName: '', productImagePreviewUrl: '', productImageUploading: false, productImageError: '', customsHsCode: '', lengthCm: 0, widthCm: 0, heightCm: 0, unitsPerPackage: 1, pieces: 1, packageCount: 1, grossWeightKg: 0, volumeCbm: 0, netWeightKg: 0, unitDeclaredValue: 0, material: '', usage: '', model: '', brand: '', productLengthCm: 0, productWidthCm: 0, productHeightCm: 0, shipmentId: '', referenceId: '', remark: '', packageType: 'CARTON', hsCode: '', declaredValue: 0, currency: 'USD', dangerousGoods: false, } } export function validateFirstLegOrderDraft(draft: FirstLegOrderDraft) { const errors: string[] = [] if (!draft.destination.trim()) errors.push('请填写目的地') if (!/^[A-Za-z]{2}$/.test(draft.destinationCountryCode.trim())) errors.push('请输入两位英文字母的目的国代码') if (!draft.destinationWarehouseName.trim()) errors.push('请填写目的仓名称') if (draft.destinationType !== 'PRIVATE' && !draft.destinationWarehouseId) errors.push('请选择平台维护的目的仓') if (draft.destinationType === 'PRIVATE' && draft.destinationWarehouseId) errors.push('私人地址不能引用平台公共仓库') if (!draft.channelCode.trim() || !draft.channelName.trim()) errors.push('请填写渠道编码和渠道名称') if (!['TAX_INCLUDED', 'TAX_EXCLUDED'].includes(draft.pricingTaxMode)) errors.push('请选择报价包税方式') if (!draft.receivingWarehouseId) errors.push('请选择平台收货仓') if (draft.pickupMethod === 'PICKUP') { if (!draft.shipperPartySnapshot?.contactName.trim()) errors.push('请填写提货联系人') if (!draft.shipperPartySnapshot?.phone.trim()) errors.push('请填写提货联系电话') if (!draft.shipperPartySnapshot?.city.trim()) errors.push('请填写提货城市') if (!draft.shipperPartySnapshot?.address.trim()) errors.push('请填写提货地址') } if (draft.destinationType === 'PRIVATE') { if (!draft.consigneePartySnapshot?.name.trim()) errors.push('请填写私人地址名称') if (!draft.consigneePartySnapshot?.contactName.trim()) errors.push('请填写收件人姓名') if (!draft.consigneePartySnapshot?.phone.trim()) errors.push('请填写收件人电话') if (!draft.consigneePartySnapshot?.city.trim()) errors.push('请填写收件城市') if (!draft.consigneePartySnapshot?.address.trim()) errors.push('请填写收件详细地址') } if (draft.items.length === 0) errors.push('请至少添加一条货物明细') if (draft.destinationType === 'FBA') { if (!draft.amazonWarehouseCode.trim()) errors.push('FBA 订单请填写 Amazon 仓库编码') } draft.items.forEach((item, index) => { const line = `第 ${index + 1} 条货物` if (!item.cargoNameCn.trim()) errors.push(`${line}缺少中文品名`) if (!item.packageType.trim()) errors.push(`${line}缺少包装类型`) if (draft.destinationType === 'FBA' && !item.sku.trim()) errors.push(`${line}缺少客户 SKU`) if (draft.destinationType === 'FBA' && !item.upc.trim()) errors.push(`${line}缺少 UPC`) if (draft.destinationType === 'FBA' && !item.shipmentId.trim()) errors.push(`${line}缺少货件编号`) if (draft.destinationType === 'FBA' && !item.referenceId.trim()) errors.push(`${line}缺少跟踪编号`) if (!Number.isInteger(item.pieces) || item.pieces <= 0) errors.push(`${line}件数必须为正整数`) if (!Number.isInteger(item.packageCount) || item.packageCount <= 0) errors.push(`${line}箱数必须为正整数`) 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`) }) return errors } export function summarizeFirstLegCargo(items: FirstLegCargoItem[]) { return items.reduce( (summary, item) => ({ pieces: summary.pieces + item.pieces, packageCount: summary.packageCount + item.packageCount, grossWeightKg: summary.grossWeightKg + item.grossWeightKg, volumeCbm: summary.volumeCbm + item.volumeCbm, }), { pieces: 0, packageCount: 0, grossWeightKg: 0, volumeCbm: 0 }, ) }