54 lines
3.5 KiB
TypeScript
54 lines
3.5 KiB
TypeScript
import type { OceanBookingDetail, OceanBookingPrintType } from './types'
|
|
|
|
export interface OceanBookingWorkflowStep {
|
|
label: string
|
|
status: string
|
|
state: 'complete' | 'current' | 'pending'
|
|
}
|
|
|
|
export type OceanBookingPreviewSignatures = Partial<Record<OceanBookingPrintType, string>>
|
|
|
|
// 预览只对应其实际消费的数据;补录实值不会作废已经预览的托运单。
|
|
export function oceanBookingPrintSignature(detail: OceanBookingDetail, type: OceanBookingPrintType): string {
|
|
return JSON.stringify([
|
|
detail.id, detail.billOfLadingNo, detail.vesselName, detail.voyageNo, detail.estimatedSailingAt,
|
|
detail.shippingCompanyName, detail.bookingAgentName,
|
|
detail.departurePortCode, detail.departurePortName, detail.destinationPortCode, detail.destinationPortName,
|
|
detail.placeOfDelivery, detail.serviceTerm, detail.freightTerm, detail.packageUnit,
|
|
detail.cargoDescription, detail.marksAndNos, detail.remark,
|
|
detail.parties.map(party => [party.partyType, party.partyName, party.address, party.contactName, party.contactPhone, party.contactEmail, party.taxNo]).sort((a, b) => String(a[0]).localeCompare(String(b[0]))),
|
|
detail.containerRequirements.map(item => [item.containerType, item.containerKind, item.quantity]),
|
|
type === 'SHIPPING_INSTRUCTION'
|
|
? [detail.declaredPackageCount, detail.declaredGrossWeightKg, detail.declaredVolumeCbm]
|
|
: [detail.actualPackageCount, detail.actualGrossWeightKg, detail.actualVolumeCbm],
|
|
])
|
|
}
|
|
|
|
export function oceanBookingWorkflow(
|
|
detail: OceanBookingDetail | null,
|
|
draftDirty: boolean,
|
|
actualDirty: boolean,
|
|
previews: OceanBookingPreviewSignatures,
|
|
): OceanBookingWorkflowStep[] {
|
|
const saved = Boolean(detail && !draftDirty)
|
|
const released = detail?.status === 'RELEASED'
|
|
const actualComplete = Boolean(detail && [detail.actualPackageCount, detail.actualGrossWeightKg, detail.actualVolumeCbm]
|
|
.every(value => value != null && Number(value) > 0))
|
|
const previewed = (type: OceanBookingPrintType) => Boolean(detail && previews[type] === oceanBookingPrintSignature(detail, type))
|
|
const instructionPreviewed = saved && previewed('SHIPPING_INSTRUCTION')
|
|
// 已放舱代表已进入后续作业;刷新清除预览标记时,不让先前阶段倒退。
|
|
// 阶段通过不代表有打印记录,仍用状态文案区分本次是否预览。
|
|
const instructionPassed = released || instructionPreviewed
|
|
const confirmationPreviewed = saved && released && actualComplete && !actualDirty && previewed('BILL_OF_LADING_CONFIRMATION')
|
|
const current = !saved ? 0 : !released ? instructionPreviewed ? 2 : 1 : confirmationPreviewed ? -1 : 3
|
|
const step = (index: number, label: string, complete: boolean, status: string): OceanBookingWorkflowStep => ({
|
|
label, status, state: complete ? 'complete' : current === index ? 'current' : 'pending',
|
|
})
|
|
return [
|
|
step(0, '填写并保存订舱信息', saved, saved ? '已保存' : detail ? '修改待保存' : '待填写并保存'),
|
|
step(1, '托运单预览 / 打印', instructionPassed, instructionPreviewed ? '已预览' : released ? '可重新预览 / 打印' : saved ? '可预览 / 打印' : '待保存资料'),
|
|
step(2, '补齐资料并确认放舱', released, released ? '已放舱' : saved ? '待确认放舱' : '待补齐资料'),
|
|
step(3, '补实并预览提单确认件', confirmationPreviewed, !released ? '待放舱' : actualDirty ? '实值待保存' : !actualComplete ? '待补齐实值' : confirmationPreviewed ? '已预览' : '可预览 / 打印'),
|
|
]
|
|
}
|