更新计费预览与测量精度并精简作业界面
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
createFeeActionIdempotencyKey,
|
||||
createFeeAdjustmentIdempotencyKey,
|
||||
getLatestInboundFee,
|
||||
previewInboundFee,
|
||||
sendInboundFee,
|
||||
} from './api'
|
||||
|
||||
@@ -32,6 +33,15 @@ describe('inbound fee API', () => {
|
||||
expect(http.get).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('previews selected outer billing values without a write idempotency header', async () => {
|
||||
const preview = { actualWeightKg: 570.5, actualVolumeCbm: 3.894, chargeableQuantity: 650.298, priceMatched: true }
|
||||
vi.mocked(http.post).mockResolvedValue({ code: '200', message: 'success', data: preview })
|
||||
const payload = { selectedWeightKg: 570.5, selectedVolumeCbm: 3.894, selectedUnitPrice: 13.6, weightSource: 'ACTUAL', volumeSource: 'OUTER' }
|
||||
|
||||
await expect(previewInboundFee('10001', '88', payload)).resolves.toEqual(preview)
|
||||
expect(http.post).toHaveBeenCalledWith('/platform/v1/inbounds/88/fees/preview', payload, { params: { tenantId: '10001' } })
|
||||
})
|
||||
|
||||
it('loads the latest immutable fee snapshot with string IDs', async () => {
|
||||
vi.mocked(http.get).mockResolvedValue({ code: '200', message: 'success', data: snapshot })
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import type { AdjustPublishedInboundFeeRequest, InboundFeeSnapshot } from './types'
|
||||
import type { AdjustPublishedInboundFeeRequest, InboundFeePreview, InboundFeePreviewRequest, InboundFeeSelectionRequest, InboundFeeSnapshot } from './types'
|
||||
|
||||
function feeBasePath(inboundId: string) {
|
||||
const identifier = String(inboundId ?? '').trim()
|
||||
@@ -15,7 +15,14 @@ export async function getLatestInboundFee(tenantId: string, inboundId: string) {
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function calculateInboundFee(tenantId: string, inboundId: string, payload: { selectedWeightKg: number; selectedVolumeCbm: number; weightSource: string; volumeSource: string }, idempotencyKey: string) {
|
||||
export async function previewInboundFee(tenantId: string, inboundId: string, payload: InboundFeePreviewRequest) {
|
||||
const response = await http.post<unknown, ApiEnvelope<InboundFeePreview>>(
|
||||
`${feeBasePath(inboundId)}/preview`, payload, { params: { tenantId } },
|
||||
)
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function calculateInboundFee(tenantId: string, inboundId: string, payload: InboundFeeSelectionRequest, idempotencyKey: string) {
|
||||
const response = await http.post<unknown, ApiEnvelope<InboundFeeSnapshot>>(
|
||||
`${feeBasePath(inboundId)}/calculate`, payload,
|
||||
{ params: { tenantId }, headers: { 'Idempotency-Key': idempotencyKey } },
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
export type InboundFeeStatus = 'CALCULATED' | 'CONFIRMED' | 'SENT' | 'SUPERSEDED' | string
|
||||
export type InboundChargeMode = 'KG' | 'CBM' | string
|
||||
|
||||
export interface InboundFeeSelectionRequest {
|
||||
selectedWeightKg: number
|
||||
selectedVolumeCbm: number
|
||||
weightSource: string
|
||||
volumeSource: string
|
||||
}
|
||||
|
||||
export interface InboundFeePreview {
|
||||
actualWeightKg: number
|
||||
actualVolumeCbm: number
|
||||
chargeableQuantity: number
|
||||
chargeUnit: string
|
||||
conversionFactor: number
|
||||
roundingScale: number
|
||||
roundingMode: string
|
||||
unitPrice: number | null
|
||||
additionalAmount: number
|
||||
totalAmount: number | null
|
||||
currency: string
|
||||
priceMatched: boolean
|
||||
}
|
||||
|
||||
export interface InboundFeePreviewRequest extends InboundFeeSelectionRequest {
|
||||
selectedUnitPrice: number | null
|
||||
}
|
||||
|
||||
export interface InboundFeeSnapshot {
|
||||
feeId: string
|
||||
feeNo: string
|
||||
|
||||
@@ -14,9 +14,10 @@ export {
|
||||
createFeeAdjustmentIdempotencyKey,
|
||||
createFeeActionIdempotencyKey,
|
||||
getLatestInboundFee,
|
||||
previewInboundFee,
|
||||
sendInboundFee,
|
||||
} from './fee/api'
|
||||
export type { AdjustPublishedInboundFeeRequest, InboundFeeSnapshot } from './fee/types'
|
||||
export type { AdjustPublishedInboundFeeRequest, InboundFeePreview, InboundFeeSnapshot } from './fee/types'
|
||||
export { downloadWeightImage } from './weight/api/weightOcr'
|
||||
export type { InboundMeasurementDetail } from './measurement/types'
|
||||
export type { InboundHoldCommand, InboundHoldDetail, InboundHoldEvidenceUpload, InboundHoldHistoryEntry } from './core/types'
|
||||
|
||||
@@ -213,7 +213,7 @@ defineExpose({ confirmApprove, approvalButtonLabel, isPending, canReview, action
|
||||
<tbody>
|
||||
<tr><th scope="row">箱数</th><td>{{ formatNumber(detail.originalPackageCount, 0) }}</td><td>{{ formatNumber(detail.actualPackageCount, 0) }}</td><td>{{ formatDifference(detail.actualPackageCount, detail.originalPackageCount, 0) }}</td></tr>
|
||||
<tr><th scope="row">毛重(kg)</th><td>{{ formatNumber(detail.originalGrossWeightKg) }}</td><td>{{ formatNumber(detail.actualGrossWeightKg) }}</td><td>{{ formatDifference(detail.actualGrossWeightKg, detail.originalGrossWeightKg, 3, ' kg') }}</td></tr>
|
||||
<tr><th scope="row">体积(m³)</th><td>{{ formatNumber(detail.originalVolumeCbm, 4) }}</td><td>{{ formatNumber(detail.actualVolumeCbm, 4) }}</td><td>{{ formatDifference(detail.actualVolumeCbm, detail.originalVolumeCbm, 4, ' m³') }}</td></tr>
|
||||
<tr><th scope="row">体积(m³)</th><td>{{ formatNumber(detail.originalVolumeCbm, 3) }}</td><td>{{ formatNumber(detail.actualVolumeCbm, 3) }}</td><td>{{ formatDifference(detail.actualVolumeCbm, detail.originalVolumeCbm, 3, ' m³') }}</td></tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
<div class="review-extra-facts"><span>货物净重 <strong>{{ formatNumber(detail.actualNetWeightKg) }}</strong> kg</span><span>体积重 <strong>{{ formatNumber(detail.volumeWeightKg) }}</strong> kg</span></div>
|
||||
@@ -249,10 +249,10 @@ defineExpose({ confirmApprove, approvalButtonLabel, isPending, canReview, action
|
||||
<template #default="{ row }">{{ formatNumber(row.packageCount, 0) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单箱体积(m³)" width="106" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.unitVolumeCbm, 4) }}</template>
|
||||
<template #default="{ row }">{{ formatNumber(row.unitVolumeCbm, 3) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总体积(m³)" width="96" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.totalVolumeCbm, 4) }}</template>
|
||||
<template #default="{ row }">{{ formatNumber(row.totalVolumeCbm, 3) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="体积重(kg)" width="96" align="right">
|
||||
<template #default="{ row }">{{ formatNumber(row.volumeWeightKg) }}</template>
|
||||
|
||||
Reference in New Issue
Block a user