fix: align appointment viewing and fleet follow-up navigation
This commit is contained in:
@@ -12,6 +12,7 @@ import { offerTime, appointmentCoverageLabels, appointmentMissingLabels, inquiry
|
||||
import type { CapacityOffer, CapacityInquiry, InquiryResult, InquiryWrite, OfferCustomerOption } from '../capacityOfferTypes'
|
||||
import type { TripBookingCargo } from '../bookingTypes'
|
||||
import { useFleetDraftGuard } from '../useFleetDraftGuard'
|
||||
import { inquiryOrderTarget } from '../inquiryNavigation'
|
||||
const open = defineModel<boolean>({ default: false })
|
||||
const props = defineProps<{ offer: CapacityOffer | null; inquiry: CapacityInquiry | null; readonly: boolean; confirmMode?: boolean }>()
|
||||
const emit = defineEmits<{ saved: [value: InquiryResult]; refresh: []; action: [key: string, row: CapacityInquiry] }>()
|
||||
@@ -37,6 +38,7 @@ const primaryFollowup = computed(() => {
|
||||
return followupActions.value.find(action => action.key.toUpperCase() === key)
|
||||
})
|
||||
const secondaryFollowups = computed(() => followupActions.value.filter(action => action !== primaryFollowup.value))
|
||||
const canReadOrder = computed(() => props.inquiry && inquiryOrderTarget(props.inquiry, access.can))
|
||||
const blankCargo = (): TripBookingCargo => ({ destinationKey: '', cargoName: null, packageCount: null, palletSpaces: null, weightKg: null, volumeCbm: null, priceBasis: 'PALLET', unitPrice: null, currency: 'USD', contactName: null, contactPhone: null, remark: null })
|
||||
const form = reactive({ customerId: '', businessType: 'LOCAL_LOOSEBOARD' as CapacityInquiry['businessType'], deliveryMode: 'SELF_DELIVERY' as CapacityInquiry['deliveryMode'], estimatedArrivalAt: null as string | null, expectedPalletCount: null as number | null, cargo: blankCargo(), quoteRef: null as FleetQuoteReference | null })
|
||||
const quoteSource = ref<FleetQuoteSourceSnapshot | null>(null), customers = ref<OfferCustomerOption[]>([]), customerLoading = ref(false)
|
||||
@@ -114,7 +116,7 @@ onBeforeUnmount(() => { generation++; customerSequence++; quoteSequence++; clear
|
||||
</section>
|
||||
<p v-if="pending" role="status">上次提交结果尚未确定,请保留原内容重试或核对。</p>
|
||||
<p v-if="offer">{{ offer.offerNo }} · {{ offer.warehouseName }} · {{ offer.blockReason || '询价不占位,调度确认承运后占位。' }}</p>
|
||||
<section v-if="inquiry" aria-label="本票处理进度"><strong>{{ inquiry.progress.label }} · {{ inquiry.progress.reservation }}</strong><p>下一步负责人:{{ inquiry.progress.owner }} · {{ inquiry.progress.message }}</p></section>
|
||||
<section v-if="inquiry" aria-label="本票处理进度"><strong>{{ inquiry.customerName }} · {{ inquiry.destinationLabel }}</strong><p>车次:{{ inquiry.tripNo }} · 登记:{{ inquiry.bookingNo }}</p><strong>{{ inquiry.progress.label }} · {{ inquiry.progress.reservation }}</strong><p>下一步负责人:{{ inquiry.progress.owner }} · {{ inquiry.progress.message }}</p></section>
|
||||
<p v-else>先选客户即可登记;多站车次需选择卸货站。保存后调度可见,尚不保位。</p>
|
||||
<p v-if="!inquiry">业务类型:{{ form.businessType === 'US_TRUCK' ? '本土卡车' : '本土散板' }},可在“确认承运前待补资料”中调整。</p>
|
||||
<p v-if="offer">计划发车:{{ offerTime(offer.plannedDepartureAt) }} · 最晚送仓:{{ offerTime(offer.cutoffAt) }}</p>
|
||||
@@ -163,7 +165,7 @@ onBeforeUnmount(() => { generation++; customerSequence++; quoteSequence++; clear
|
||||
<p v-for="appointment in inquiry.appointmentCoverage.appointments" :key="appointment.appointmentNo">预约:{{ appointment.appointmentNo }} · 外部确认号:{{ appointment.confirmationNo || '尚未确认' }}</p>
|
||||
<p v-if="inquiry.appointmentCoverage.changeReviewRequired">货源或数量发生变化,请负责预约的人员重新核对覆盖。</p>
|
||||
</section>
|
||||
<p v-if="inquiry">本土订单:{{ inquiry.businessOrderNo || '尚未成交' }} · 来货:{{ inquiry.incomingNo || '尚未登记' }} · 排车:{{ inquiry.dispatchNo || '尚未关联' }}</p>
|
||||
<p v-if="inquiry">本土订单:<el-button v-if="canReadOrder" link @click="emit('action', 'business-order', inquiry)">{{ inquiry.businessOrderNo }}</el-button><span v-else>{{ inquiry.businessOrderNo || '尚未成交' }}</span> · 来货:{{ inquiry.incomingNo || '尚未登记' }} · 排车:{{ inquiry.dispatchNo || '尚未关联' }}</p>
|
||||
</AppDialog>
|
||||
</template>
|
||||
<style scoped>.capacity-inquiry-form{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--admin-space-4) var(--admin-space-6)}.capacity-inquiry-form :deep(.el-select),.capacity-inquiry-form :deep(.el-input-number),.capacity-inquiry-form :deep(.el-date-editor){width:100%}.capacity-inquiry-wide{grid-column:1/-1}</style>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ElTable, ElTableColumn } from 'element-plus/es/components/table/index'
|
||||
import { ElInputNumber } from 'element-plus/es/components/input-number/index'
|
||||
import { ElInput } from 'element-plus/es/components/input/index'
|
||||
@@ -35,6 +36,7 @@ it('uses server actual pallets and preview versions while requiring explicit pri
|
||||
wrapper.findComponent({ name: 'AppDialog' }).vm.$emit('confirm'); await flushPromises()
|
||||
expect(api.acceptTripIncoming).toHaveBeenCalledWith('TR-1', 'FB-1', expect.objectContaining({ tripRecordVersion: 5, recordVersion: 2, receiptHash: 'receipt-hash', unitPrice: 55, pallets: [{ warehousePalletId: '902', palletSpaces: 2 }] }))
|
||||
expect(api.startTripIncoming).not.toHaveBeenCalled(); expect(api.bindTripBookingDispatch).not.toHaveBeenCalled()
|
||||
expect(ElMessage.success).toHaveBeenCalledWith('实收货量及约定运费已核实')
|
||||
})
|
||||
it('does not accept a receipt while the warehouse is still waiting for actual goods', async () => {
|
||||
vi.mocked(api.getTripIncoming).mockResolvedValue({ ...preview, incoming: { ...preview.incoming!, status: 'WAIT_PDA_RECEIVING', pallets: [], receivedPackages: 0 } })
|
||||
|
||||
@@ -98,7 +98,7 @@ async function save() {
|
||||
const value = props.pool ? await commandInquiryFulfillment(booking.bookingNo, mode === 'incoming' ? 'incoming' : mode === 'receipt' ? 'receipt-confirmation' : 'arrange-dispatch', mode === 'bind' ? { tripRecordVersion: (body as TripBookingBind).tripRecordVersion, recordVersion: (body as TripBookingBind).recordVersion, idempotencyKey: (body as TripBookingBind).idempotencyKey } : body) : mode === 'incoming' ? await startTripIncoming(props.trip.tripNo, booking.bookingNo, body as TripIncomingStart)
|
||||
: mode === 'bind' ? await bindTripBookingDispatch(props.trip.tripNo, booking.bookingNo, body as TripBookingBind)
|
||||
: await acceptTripIncoming(props.trip.tripNo, booking.bookingNo, body as TripIncomingAccept)
|
||||
if (current === generation) { pending.value = null; guard.capture(); emit('saved', value); open.value = false; ElMessage.success('外接履约记录已更新') }
|
||||
if (current === generation) { pending.value = null; guard.capture(); emit('saved', value); open.value = false; ElMessage.success(value.booking.status === 'BOUND' ? '已排入本车,尚未装车或发车' : value.booking.status === 'RECEIVED' ? '实收货量及约定运费已核实' : value.booking.incomingNo ? '已安排来货,等待仓库实际收货' : '履约命令已完成,请查看最新进度') }
|
||||
} catch (cause) { if (current === generation) { error.value = getApiErrorDetails(cause, '外接履约操作未完成'); if (cause instanceof ApiResponseError && /^A04/.test(cause.code)) pending.value = null } }
|
||||
finally { busy.value = false }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user