优化
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
export { getInboundMeasurement, saveInboundMeasurementDraft, updateMeasurementCalculationStrategy } from './measurement/api'
|
export { getInboundMeasurement, saveInboundMeasurementDraft, updateMeasurementCalculationStrategy, updateMeasurementOuterDimensions } from './measurement/api'
|
||||||
export { createInboundHoldIdempotencyKey, downloadInboundCartonLabelsBatch, downloadPlatformInboundHoldEvidence, getPlatformInboundHold, holdPlatformInbound, releasePlatformInbound, uploadPlatformInboundHoldEvidence } from './core/api'
|
export { createInboundHoldIdempotencyKey, downloadInboundCartonLabelsBatch, downloadPlatformInboundHoldEvidence, getPlatformInboundHold, holdPlatformInbound, releasePlatformInbound, uploadPlatformInboundHoldEvidence } from './core/api'
|
||||||
export { default as InboundMeasurementPanel } from './measurement/InboundMeasurementPanel.vue'
|
export { default as InboundMeasurementPanel } from './measurement/InboundMeasurementPanel.vue'
|
||||||
export { default as InboundMeasurementDialog } from './measurement/InboundMeasurementDialog.vue'
|
export { default as InboundMeasurementDialog } from './measurement/InboundMeasurementDialog.vue'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
import { http } from '@/shared/api/http'
|
import { http } from '@/shared/api/http'
|
||||||
import { createManualCartonScan, downloadInboundMeasurementImage, getInboundMeasurement, saveInboundMeasurementDraft, submitInboundMeasurement, updateConfirmedPackageCount, updateMeasurementCalculationStrategy } from './api'
|
import { createManualCartonScan, downloadInboundMeasurementImage, getInboundMeasurement, saveInboundMeasurementDraft, submitInboundMeasurement, updateConfirmedPackageCount, updateMeasurementCalculationStrategy, updateMeasurementOuterDimensions } from './api'
|
||||||
import type { SaveInboundMeasurementDraftRequest } from './types'
|
import type { SaveInboundMeasurementDraftRequest } from './types'
|
||||||
|
|
||||||
vi.mock('@/shared/api/http', () => ({
|
vi.mock('@/shared/api/http', () => ({
|
||||||
@@ -89,6 +89,22 @@ describe('inbound measurement API', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('updates one warehouse outer dimension row without resaving the frozen measurement batch', async () => {
|
||||||
|
const payload = {
|
||||||
|
measurementId: '9001', version: 4,
|
||||||
|
outerLengthCm: 30, outerWidthCm: 20, outerHeightCm: 20,
|
||||||
|
}
|
||||||
|
const saved = { measurementId: '9001', version: 5, status: 'SUBMITTED', itemId: '81' }
|
||||||
|
vi.mocked(http.put).mockResolvedValue({ code: '200', message: 'success', data: saved })
|
||||||
|
|
||||||
|
await expect(updateMeasurementOuterDimensions('10001', '7001', '81', payload)).resolves.toEqual(saved)
|
||||||
|
expect(http.put).toHaveBeenCalledWith(
|
||||||
|
'/platform/v1/first-leg/inbounds/7001/measurement/items/81/outer-dimensions',
|
||||||
|
payload,
|
||||||
|
{ params: { tenantId: '10001' } },
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('downloads the current measurement image using the scoped file route', async () => {
|
it('downloads the current measurement image using the scoped file route', async () => {
|
||||||
const image = new Blob(['image-data'], { type: 'image/jpeg' })
|
const image = new Blob(['image-data'], { type: 'image/jpeg' })
|
||||||
vi.mocked(http.get).mockResolvedValue(image)
|
vi.mocked(http.get).mockResolvedValue(image)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import type {
|
|||||||
SubmitInboundMeasurementRequest,
|
SubmitInboundMeasurementRequest,
|
||||||
UpdateMeasurementCalculationStrategyRequest,
|
UpdateMeasurementCalculationStrategyRequest,
|
||||||
MeasurementCalculationStrategyUpdated,
|
MeasurementCalculationStrategyUpdated,
|
||||||
|
UpdateMeasurementOuterDimensionsRequest,
|
||||||
|
MeasurementOuterDimensionsUpdated,
|
||||||
ManualCartonScanRequest,
|
ManualCartonScanRequest,
|
||||||
} from './types'
|
} from './types'
|
||||||
|
|
||||||
@@ -72,6 +74,20 @@ export async function updateMeasurementCalculationStrategy(
|
|||||||
return unwrapApiResponse(response)
|
return unwrapApiResponse(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function updateMeasurementOuterDimensions(
|
||||||
|
customerId: string,
|
||||||
|
inboundId: string,
|
||||||
|
itemId: string,
|
||||||
|
payload: UpdateMeasurementOuterDimensionsRequest,
|
||||||
|
) {
|
||||||
|
const response = await http.put<ApiEnvelope<MeasurementOuterDimensionsUpdated>, ApiEnvelope<MeasurementOuterDimensionsUpdated>>(
|
||||||
|
`${measurementPath(inboundId)}/items/${segment(itemId)}/outer-dimensions`,
|
||||||
|
payload,
|
||||||
|
{ params: { tenantId: customerId } },
|
||||||
|
)
|
||||||
|
return unwrapApiResponse(response)
|
||||||
|
}
|
||||||
|
|
||||||
export async function submitInboundMeasurement(
|
export async function submitInboundMeasurement(
|
||||||
customerId: string,
|
customerId: string,
|
||||||
inboundId: string,
|
inboundId: string,
|
||||||
|
|||||||
@@ -175,6 +175,18 @@ export interface MeasurementCalculationStrategyUpdated extends InboundMeasuremen
|
|||||||
chargeRuleId: MeasurementIdentifier | null
|
chargeRuleId: MeasurementIdentifier | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateMeasurementOuterDimensionsRequest {
|
||||||
|
measurementId: MeasurementIdentifier
|
||||||
|
version: number
|
||||||
|
outerLengthCm: number | null
|
||||||
|
outerWidthCm: number | null
|
||||||
|
outerHeightCm: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MeasurementOuterDimensionsUpdated extends InboundMeasurementDraftSaved {
|
||||||
|
itemId: MeasurementIdentifier
|
||||||
|
}
|
||||||
|
|
||||||
export interface ConfirmedPackageCountRequest {
|
export interface ConfirmedPackageCountRequest {
|
||||||
measurementVersion: number
|
measurementVersion: number
|
||||||
confirmedPackageCount: number
|
confirmedPackageCount: number
|
||||||
|
|||||||
@@ -350,7 +350,9 @@ describe('UnifiedOrdersView contract', () => {
|
|||||||
expect(source).toContain('仓库修改外箱(高)')
|
expect(source).toContain('仓库修改外箱(高)')
|
||||||
expect(source).toContain('saveWarehouseOuterDimensions')
|
expect(source).toContain('saveWarehouseOuterDimensions')
|
||||||
expect(source).toContain("'PREPARING', 'WAIT_MEASURE', 'MEASURING', 'MEASURE_REJECTED'")
|
expect(source).toContain("'PREPARING', 'WAIT_MEASURE', 'MEASURING', 'MEASURE_REJECTED'")
|
||||||
expect(source).toContain('v-if="measurementDraftEditable"')
|
expect(source.match(/v-if="measurementStrategyEditable"/g)).toHaveLength(4)
|
||||||
|
expect(source).toContain('updateMeasurementOuterDimensions')
|
||||||
|
expect(source).not.toContain('await saveInboundMeasurementDraft(String(summary.tenantId), String(summary.inboundId)')
|
||||||
expect(source).not.toContain('请至少输入一项需要修改的外箱尺寸')
|
expect(source).not.toContain('请至少输入一项需要修改的外箱尺寸')
|
||||||
expect(source).toContain(".map((value) => value == null || value === '' ? null : Number(value))")
|
expect(source).toContain(".map((value) => value == null || value === '' ? null : Number(value))")
|
||||||
expect(source).toContain('相关数值已重新计算')
|
expect(source).toContain('相关数值已重新计算')
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ import {
|
|||||||
holdPlatformInbound,
|
holdPlatformInbound,
|
||||||
releasePlatformInbound,
|
releasePlatformInbound,
|
||||||
uploadPlatformInboundHoldEvidence,
|
uploadPlatformInboundHoldEvidence,
|
||||||
saveInboundMeasurementDraft,
|
|
||||||
updateMeasurementCalculationStrategy,
|
updateMeasurementCalculationStrategy,
|
||||||
|
updateMeasurementOuterDimensions,
|
||||||
InboundFeePanel,
|
InboundFeePanel,
|
||||||
InboundMeasurementDialog,
|
InboundMeasurementDialog,
|
||||||
MeasurementEvidenceThumbnail,
|
MeasurementEvidenceThumbnail,
|
||||||
@@ -1066,56 +1066,43 @@ async function updateMeasurementCalculationMode(row: Record<string, unknown> | n
|
|||||||
async function saveWarehouseOuterDimensions(row: Record<string, unknown>) {
|
async function saveWarehouseOuterDimensions(row: Record<string, unknown>) {
|
||||||
const summary = detail.value?.summary
|
const summary = detail.value?.summary
|
||||||
const measurement = measurementDetail.value
|
const measurement = measurementDetail.value
|
||||||
const currentStatus = measurement?.processStatus || summary?.mainStatus || ''
|
|
||||||
if (measurement && !measurementDraftEditableStatuses.has(currentStatus)) {
|
|
||||||
const statusLabel = orderStatusLabel(summary?.mainStatus) || measurementStatusLabel(currentStatus)
|
|
||||||
ElMessage.warning(`当前状态为“${statusLabel}”,该状态不可以修改测量数据`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!summary?.inboundId || !measurement?.measurementId || measurement.version == null
|
if (!summary?.inboundId || !measurement?.measurementId || measurement.version == null
|
||||||
|| !measurementDraftEditable.value) return
|
|| !measurementStrategyEditable.value) return
|
||||||
const dimensions = [row.outerLengthCm, row.outerWidthCm, row.outerHeightCm]
|
const dimensions = [row.outerLengthCm, row.outerWidthCm, row.outerHeightCm]
|
||||||
.map((value) => value == null || value === '' ? null : Number(value))
|
.map((value) => value == null || value === '' ? null : Number(value))
|
||||||
if (dimensions.some((value) => value != null && (!Number.isFinite(value) || value <= 0))) {
|
if (dimensions.some((value) => value != null && (!Number.isFinite(value) || value <= 0))) {
|
||||||
ElMessage.warning('仓库修改外箱尺寸必须大于 0')
|
ElMessage.warning('仓库修改外箱尺寸必须大于 0')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const selectedMode: MeasurementCalculationMode = measurementSectionModes.outer
|
|
||||||
const selectedChargeRuleId = selectedMode === 'MULTIPLY'
|
|
||||||
? activeMeasurementChargeRule.value?.id || null
|
|
||||||
: null
|
|
||||||
measurementOuterSavingId.value = String(row.id)
|
measurementOuterSavingId.value = String(row.id)
|
||||||
try {
|
try {
|
||||||
await saveInboundMeasurementDraft(String(summary.tenantId), String(summary.inboundId), {
|
const saved = await updateMeasurementOuterDimensions(
|
||||||
|
String(summary.tenantId), String(summary.inboundId), String(row.id), {
|
||||||
measurementId: String(measurement.measurementId),
|
measurementId: String(measurement.measurementId),
|
||||||
version: measurement.version,
|
version: measurement.version,
|
||||||
actualGoodsName: measurement.actualGoodsName,
|
outerLengthCm: dimensions[0],
|
||||||
items: measurement.items.filter((item) => Number(item.packageCount) > 0).map((item) => ({
|
outerWidthCm: dimensions[1],
|
||||||
inboundDetailId: item.inboundDetailId ?? undefined,
|
outerHeightCm: dimensions[2],
|
||||||
boxCode: item.boxCode,
|
|
||||||
itemNo: item.itemNo,
|
|
||||||
boxSpecification: item.boxSpecification,
|
|
||||||
packageCount: item.packageCount,
|
|
||||||
lengthCm: item.lengthCm,
|
|
||||||
widthCm: item.widthCm,
|
|
||||||
heightCm: item.heightCm,
|
|
||||||
unitWeightKg: item.unitWeightKg,
|
|
||||||
intelligentImageFileId: item.intelligentImageFileId,
|
|
||||||
machineNo: item.machineNo,
|
|
||||||
measuredAt: item.deviceMeasuredAt,
|
|
||||||
overLimitWarning: item.overLimitWarning,
|
|
||||||
outerLengthCm: String(item.id) === String(row.id) ? dimensions[0] : item.outerLengthCm,
|
|
||||||
outerWidthCm: String(item.id) === String(row.id) ? dimensions[1] : item.outerWidthCm,
|
|
||||||
outerHeightCm: String(item.id) === String(row.id) ? dimensions[2] : item.outerHeightCm,
|
|
||||||
chargeRuleId: String(item.id) === String(row.id) ? selectedChargeRuleId : item.chargeRuleId,
|
|
||||||
coefficientMode: String(item.id) === String(row.id)
|
|
||||||
? selectedMode
|
|
||||||
: item.coefficientMode || 'ACTUAL',
|
|
||||||
remark: item.remark,
|
|
||||||
})),
|
|
||||||
})
|
})
|
||||||
|
measurementDetail.value = {
|
||||||
|
...measurement,
|
||||||
|
version: saved.version,
|
||||||
|
measurementStatus: saved.status,
|
||||||
|
items: measurement.items.map((item) => String(item.id) === String(row.id) ? {
|
||||||
|
...item,
|
||||||
|
outerLengthCm: dimensions[0],
|
||||||
|
outerWidthCm: dimensions[1],
|
||||||
|
outerHeightCm: dimensions[2],
|
||||||
|
calculatedOuterLengthCm: dimensions[0],
|
||||||
|
calculatedOuterWidthCm: dimensions[1],
|
||||||
|
calculatedOuterHeightCm: dimensions[2],
|
||||||
|
} : item),
|
||||||
|
}
|
||||||
|
const refreshed = await waitForSavedMeasurementVersion(
|
||||||
|
String(summary.tenantId), String(summary.inboundId), saved.version,
|
||||||
|
)
|
||||||
|
if (refreshed) measurementDetail.value = refreshed
|
||||||
measurementLoadedKey.value = ''
|
measurementLoadedKey.value = ''
|
||||||
await loadMeasurementDetails()
|
|
||||||
ElMessage.success(`序号 ${row.itemNo || '—'} 的外箱规已更新,相关数值已重新计算`)
|
ElMessage.success(`序号 ${row.itemNo || '—'} 的外箱规已更新,相关数值已重新计算`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
measurementLoadedKey.value = ''
|
measurementLoadedKey.value = ''
|
||||||
@@ -2470,15 +2457,15 @@ onBeforeUnmount(() => {
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="#" prop="itemNo" min-width="70" fixed="left" />
|
<el-table-column label="#" prop="itemNo" min-width="70" fixed="left" />
|
||||||
<el-table-column label="仓库修改外箱(长)" min-width="160">
|
<el-table-column label="仓库修改外箱(长)" min-width="160">
|
||||||
<template #default="{ row }"><el-input-number v-if="measurementDraftEditable" v-model="row.outerLengthCm" aria-label="仓库修改外箱长" :min="0.001" :precision="3" :controls="false" placeholder="不修改" /><template v-else>{{ formatNumber(row.outerLengthCm) }}</template></template>
|
<template #default="{ row }"><el-input-number v-if="measurementStrategyEditable" v-model="row.outerLengthCm" aria-label="仓库修改外箱长" :min="0.001" :precision="3" :controls="false" placeholder="不修改" /><template v-else>{{ formatNumber(row.outerLengthCm) }}</template></template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="仓库修改外箱(宽)" min-width="160">
|
<el-table-column label="仓库修改外箱(宽)" min-width="160">
|
||||||
<template #default="{ row }"><el-input-number v-if="measurementDraftEditable" v-model="row.outerWidthCm" aria-label="仓库修改外箱宽" :min="0.001" :precision="3" :controls="false" placeholder="不修改" /><template v-else>{{ formatNumber(row.outerWidthCm) }}</template></template>
|
<template #default="{ row }"><el-input-number v-if="measurementStrategyEditable" v-model="row.outerWidthCm" aria-label="仓库修改外箱宽" :min="0.001" :precision="3" :controls="false" placeholder="不修改" /><template v-else>{{ formatNumber(row.outerWidthCm) }}</template></template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="仓库修改外箱(高)" min-width="160">
|
<el-table-column label="仓库修改外箱(高)" min-width="160">
|
||||||
<template #default="{ row }"><el-input-number v-if="measurementDraftEditable" v-model="row.outerHeightCm" aria-label="仓库修改外箱高" :min="0.001" :precision="3" :controls="false" placeholder="不修改" /><template v-else>{{ formatNumber(row.outerHeightCm) }}</template></template>
|
<template #default="{ row }"><el-input-number v-if="measurementStrategyEditable" v-model="row.outerHeightCm" aria-label="仓库修改外箱高" :min="0.001" :precision="3" :controls="false" placeholder="不修改" /><template v-else>{{ formatNumber(row.outerHeightCm) }}</template></template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="measurementDraftEditable" label="仓库外箱操作" min-width="120">
|
<el-table-column v-if="measurementStrategyEditable" label="仓库外箱操作" min-width="120">
|
||||||
<template #default="{ row }"><el-button type="primary" plain size="small" :loading="measurementOuterSavingId === String(row.id)" :disabled="Boolean(measurementOuterSavingId)" @click="saveWarehouseOuterDimensions(row as Record<string, unknown>)">保存外箱</el-button></template>
|
<template #default="{ row }"><el-button type="primary" plain size="small" :loading="measurementOuterSavingId === String(row.id)" :disabled="Boolean(measurementOuterSavingId)" @click="saveWarehouseOuterDimensions(row as Record<string, unknown>)">保存外箱</el-button></template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-for="column in actualMeasuredColumns" :key="column.key" :label="column.label" :prop="column.key" min-width="120">
|
<el-table-column v-for="column in actualMeasuredColumns" :key="column.key" :label="column.label" :prop="column.key" min-width="120">
|
||||||
|
|||||||
Reference in New Issue
Block a user