151 lines
7.2 KiB
JavaScript
151 lines
7.2 KiB
JavaScript
export const RECEIVING_PHOTO_ROLES = ['LICENSE_PLATE', 'CONTAINER_SEAL', 'DOOR_OPEN']
|
|
|
|
const number = (value) => Math.max(0, Number(value || 0))
|
|
const text = (value) => typeof value === 'string' ? value.trim() : ''
|
|
|
|
function warehouseContractError(message) {
|
|
return Object.assign(new Error(message), { code: 'RECEIVING_WAREHOUSE_CONTRACT_INVALID' })
|
|
}
|
|
|
|
export function normalizeReceivingWarehouseProfile(value = {}) {
|
|
const profile = {
|
|
warehouseId: value.warehouseId === null || value.warehouseId === undefined ? '' : String(value.warehouseId),
|
|
warehouseCode: text(value.warehouseCode),
|
|
warehouseName: text(value.warehouseName)
|
|
}
|
|
if (!profile.warehouseId || !profile.warehouseCode || !profile.warehouseName) {
|
|
throw warehouseContractError('当前 PDA 绑定仓信息不完整,请联系管理员检查账号绑定')
|
|
}
|
|
return profile
|
|
}
|
|
|
|
export function assertReceivingWarehouse(value, profile, label = '当前柜') {
|
|
const expectedCode = text(profile?.warehouseCode)
|
|
const expectedName = text(profile?.warehouseName)
|
|
const actualCode = text(value?.overseasWarehouseCode)
|
|
const actualName = text(value?.overseasWarehouseName)
|
|
if (!expectedCode || !expectedName) {
|
|
throw warehouseContractError('当前 PDA 绑定仓信息不完整,暂停接柜作业')
|
|
}
|
|
if (!actualCode || !actualName) {
|
|
throw warehouseContractError(`${label}缺少已分配海外接柜仓信息,暂停操作并请联系管理员`)
|
|
}
|
|
if (actualCode !== expectedCode) {
|
|
throw Object.assign(new Error(`${label}已分配至其他海外接柜仓,当前仓不可操作`), { code: 'RECEIVING_WAREHOUSE_MISMATCH' })
|
|
}
|
|
return value
|
|
}
|
|
|
|
export function normalizeReceivingInbound(value = {}) {
|
|
return {
|
|
...normalizeReceivingAssignment(value),
|
|
wholePalletInbound: value.wholePalletInbound === true,
|
|
plannedPalletCount: number(value.plannedPalletCount),
|
|
totalPackages: number(value.totalPackages),
|
|
receivedPackages: number(value.receivedPackages),
|
|
pendingPackages: number(value.pendingPackages)
|
|
}
|
|
}
|
|
|
|
export function normalizeReceivingAssignment(value = {}) {
|
|
return {
|
|
...value,
|
|
assigned: value.assigned === true,
|
|
mergeAllowed: value.mergeAllowed === true,
|
|
urgent: value.urgent === true,
|
|
mergeHint: value.mergeAllowed === true ? text(value.mergeHint) : ''
|
|
}
|
|
}
|
|
|
|
export function normalizeReceivingCandidate(value = {}) {
|
|
return {
|
|
...value,
|
|
sourceContainerBookingId: typeof value.sourceContainerBookingId === 'string' ? value.sourceContainerBookingId.trim() : '',
|
|
containerNo: String(value.containerNo || '').trim(),
|
|
overseasWarehouseCode: text(value.overseasWarehouseCode),
|
|
overseasWarehouseName: text(value.overseasWarehouseName),
|
|
plannedArrivalAt: typeof value.plannedArrivalAt === 'string' && value.plannedArrivalAt.trim() ? value.plannedArrivalAt.trim() : null,
|
|
totalOrderCount: number(value.totalOrderCount),
|
|
planCount: number(value.planCount),
|
|
inboundCodeCount: number(value.inboundCodeCount),
|
|
missingInboundCodeCount: number(value.missingInboundCodeCount),
|
|
plannedInboundCodeCount: number(value.plannedInboundCodeCount),
|
|
pendingPlanCount: number(value.pendingPlanCount),
|
|
destinationCodes: Array.isArray(value.destinationCodes) ? value.destinationCodes.filter(Boolean) : [],
|
|
plannedPalletCount: number(value.plannedPalletCount),
|
|
totalPackages: number(value.totalPackages),
|
|
receivedPackages: number(value.receivedPackages),
|
|
currentAccount: value.currentAccount === true,
|
|
allPlansReady: value.allPlansReady === true,
|
|
operable: value.operable === true,
|
|
blockReason: typeof value.blockReason === 'string' ? value.blockReason.trim() : ''
|
|
}
|
|
}
|
|
|
|
export function normalizeReceivingSession(value) {
|
|
if (!value) return null
|
|
const photos = Array.isArray(value.photos)
|
|
? value.photos.map((photo) => ({ ...photo, fileId: String(photo.fileId) }))
|
|
: []
|
|
const domesticLoadingPhotos = Array.isArray(value.domesticLoadingPhotos)
|
|
? value.domesticLoadingPhotos.filter((photo) => photo?.evidenceType && photo?.downloadPath)
|
|
.map((photo) => ({ ...photo, status: 'idle', localPath: '' }))
|
|
: []
|
|
return {
|
|
...value,
|
|
overseasWarehouseCode: text(value.overseasWarehouseCode),
|
|
overseasWarehouseName: text(value.overseasWarehouseName),
|
|
photos: RECEIVING_PHOTO_ROLES.map((role) => photos.find((photo) => photo?.role === role && photo?.fileId)).filter(Boolean),
|
|
domesticLoadingPhotos,
|
|
totalPackages: number(value.totalPackages),
|
|
receivedPackages: number(value.receivedPackages),
|
|
pendingPackages: number(value.pendingPackages),
|
|
inbounds: Array.isArray(value.inbounds) ? value.inbounds.map(normalizeReceivingInbound) : []
|
|
}
|
|
}
|
|
|
|
export function isNoCurrentReceiving(error) {
|
|
return ['404', 'A0404', 'B0404'].includes(String(error?.code || ''))
|
|
}
|
|
|
|
export function isReceivingConflict(error) {
|
|
return ['409', 'A0409', 'B0409'].includes(String(error?.code || ''))
|
|
}
|
|
|
|
export function toReceivingError(error, fallback = '海外仓作业失败') {
|
|
const code = error?.code
|
|
const rawMessage = String(error?.message || '').trim()
|
|
const palletConflictMessages = {
|
|
'Reserved pallet binding is incomplete': '预留托盘资料不完整,请联系管理员检查入仓计划',
|
|
'Reserved pallet customer binding is invalid': '预留托盘与当前客户不匹配,请联系管理员检查入仓计划',
|
|
'Scanned pallet does not match the reserved inbound plan resource': '扫描托盘与入仓计划预留资源不一致,请扫描已预留的托盘',
|
|
'Pallet code matches multiple reserved resources in this inbound plan': '托盘码对应多个预留资源,请联系管理员检查入仓计划',
|
|
'Pallet is not idle': '该托盘已被占用,当前不可用于收货,请更换可用托盘',
|
|
'Pallet location was not found': '该托盘未关联有效库位,请联系管理员维护后重试',
|
|
'Pallet virtual location is not active': '该托盘所在虚拟库位不可用,请更换托盘或联系管理员',
|
|
'Pallet location is not idle': '该托盘所在库位已被占用,请更换可用托盘',
|
|
'Pallet resource availability could not be verified': '无法确认该托盘是否可用,请更换托盘或联系管理员',
|
|
'Pallet does not match an available destination pallet in this inbound code': '该托盘不适用于当前入仓码,请更换符合目的仓要求的可用托盘',
|
|
'Pallet is scrapped': '该托盘已报废,请更换可用托盘',
|
|
'Pallet belongs to another overseas warehouse': '该托盘属于其他海外仓,当前仓不可使用',
|
|
'Pallet FBA destination does not match the inbound code': '该托盘的FBA目的仓与当前入仓码不一致,请更换托盘',
|
|
'FBA-designated pallet cannot receive an OVERSEAS destination carton': 'FBA专用托盘不能接收海外仓目的箱,请更换托盘'
|
|
}
|
|
const conflictMessage = ['409', 'A0409', 'B0409'].includes(String(code || ''))
|
|
? palletConflictMessages[rawMessage]
|
|
: ''
|
|
const palletUnavailable = String(code || '') === 'S0503'
|
|
&& rawMessage === 'Warehouse pallet service returned no usable response'
|
|
const mapped = Object.assign(new Error(
|
|
conflictMessage || (palletUnavailable
|
|
? '该托盘当前不可用于收货,请更换可用托盘或联系管理员检查托盘状态'
|
|
: rawMessage || fallback)
|
|
), {
|
|
code,
|
|
requestId: error?.requestId,
|
|
traceId: error?.traceId,
|
|
network: Boolean(error?.network)
|
|
})
|
|
return mapped
|
|
}
|