fix(admin): integrate workbench contracts and dropship review states
This commit is contained in:
@@ -258,7 +258,7 @@ async function batchApproveMeasurements() {
|
||||
batchReviewLoading.value = true
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确认批量审核通过已勾选的 ${selected.length} 条测量数据吗?通过后将进入待分柜。`,
|
||||
`确认批量审核通过已勾选的 ${selected.length} 条测量数据吗?一件代发通过后进入待组托,其他订单进入待分柜。`,
|
||||
'批量审核测量数据',
|
||||
{ confirmButtonText: '确认批量审核', cancelButtonText: '取消', type: 'warning' },
|
||||
)
|
||||
@@ -426,6 +426,7 @@ onBeforeUnmount(() => { disposed = true; requestSerial += 1; optionsRequestSeria
|
||||
v-if="selectedInbound"
|
||||
:tenant-id="selectedInbound.tenantId"
|
||||
:inbound-id="selectedInbound.id"
|
||||
:fulfillment-type="selectedInbound.fulfillmentType"
|
||||
:customer-name="selectedInbound.customerName || selectedInbound.companyName"
|
||||
:channel-name="selectedInbound.channelName"
|
||||
:channel-code="selectedInbound.channelCode"
|
||||
|
||||
@@ -218,6 +218,7 @@ onBeforeUnmount(() => {
|
||||
:key="`review-dialog-${revision}`"
|
||||
:tenant-id="customerId"
|
||||
:inbound-id="inboundId"
|
||||
:fulfillment-type="detail?.summary.fulfillmentType"
|
||||
:customer-name="detail?.summary.customerName || detail?.summary.companyName"
|
||||
:channel-name="detail?.summary.channelName"
|
||||
:channel-code="detail?.summary.channelCode"
|
||||
|
||||
@@ -8,6 +8,7 @@ export type InboundProcessStatus =
|
||||
| 'WAIT_PRICING'
|
||||
| 'FEE_CONFIRMING'
|
||||
| 'INBOUNDING'
|
||||
| 'WAIT_PALLETIZE'
|
||||
| 'WAIT_SPLIT'
|
||||
| 'VOIDED'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ElementPlus, { ElMessageBox } from 'element-plus'
|
||||
import ElementPlus, { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
@@ -92,6 +92,22 @@ describe('MeasurementReviewPanel', () => {
|
||||
expect(source).not.toContain('listMeasurementReviewHistory')
|
||||
})
|
||||
|
||||
it.each([true, false])('describes dropship palletizing and uses the server result when pricing succeeds=%s', async (initialPricingSucceeded) => {
|
||||
vi.mocked(approveMeasurement).mockResolvedValue({ inboundId: '90001', measurementId: '70001', processStatus: 'WAIT_PALLETIZE', feeStatus: initialPricingSucceeded ? 'CALCULATED' : 'UNPRICED', initialPricingSucceeded, initialPricingMessage: null, initialFee: null })
|
||||
const confirmation = vi.spyOn(ElMessageBox, 'confirm').mockResolvedValue(undefined as never)
|
||||
const success = vi.spyOn(ElMessage, 'success')
|
||||
const warning = vi.spyOn(ElMessage, 'warning')
|
||||
const wrapper = mount(MeasurementReviewPanel, { props: { customerId: '10001', inboundId: '90001', fulfillmentType: 'ONE_CLICK_DROPSHIP' }, global: { plugins: [ElementPlus] } })
|
||||
await flushPromises()
|
||||
expect(wrapper.text()).not.toContain('通过并进入待分柜')
|
||||
await wrapper.findAll('button').find((button) => button.text().includes('通过并进入待一件代发组托'))!.trigger('click')
|
||||
await flushPromises()
|
||||
expect(confirmation).toHaveBeenCalledWith(expect.stringContaining('进入待一件代发组托'), '确认测量审核通过', expect.objectContaining({ confirmButtonText: '通过并进入待一件代发组托' }))
|
||||
expect(initialPricingSucceeded ? success : warning).toHaveBeenCalledWith(expect.stringContaining('入库单已进入待一件代发组托'))
|
||||
expect(approveMeasurement).toHaveBeenCalledTimes(1)
|
||||
expect(wrapper.emitted('changed')).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('uses the list customer context when the review detail has no customer name', async () => {
|
||||
vi.mocked(getMeasurementReviewDetail).mockResolvedValue({ ...detail, companyName: null })
|
||||
const wrapper = mount(MeasurementReviewPanel, {
|
||||
|
||||
@@ -8,7 +8,7 @@ import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
import StatusBadge from '@/shared/components/StatusBadge.vue'
|
||||
import { downloadInboundMeasurementImage } from '../measurement/api'
|
||||
import MeasurementEvidenceThumbnail from '../measurement/components/MeasurementEvidenceThumbnail.vue'
|
||||
import { inboundReviewStatusLabels, inboundStatusLabel } from '../status'
|
||||
import { inboundProcessStatusLabels, inboundReviewStatusLabels, inboundStatusLabel } from '../status'
|
||||
import WeightOcrPanel from '../weight/components/WeightOcrPanel.vue'
|
||||
import { approveMeasurement, getMeasurementReviewDetail } from './api'
|
||||
import type { MeasurementReviewDetail } from './types'
|
||||
@@ -18,6 +18,7 @@ const props = defineProps<{
|
||||
/** @deprecated 仅用于兼容尚未完成 customerId 映射的上层集成。 */
|
||||
tenantId?: string
|
||||
inboundId: string
|
||||
fulfillmentType?: string | null
|
||||
customerName?: string | null
|
||||
channelName?: string | null
|
||||
channelCode?: string | null
|
||||
@@ -44,6 +45,8 @@ let imagePreviewRequestSerial = 0
|
||||
const canReview = computed(() => access.can('firstleg:inbound:measurement-review'))
|
||||
const customerId = computed(() => props.customerId || props.tenantId || '')
|
||||
const isPending = computed(() => detail.value?.measureReviewStatus === 'PENDING' && detail.value?.processStatus === 'MEASURE_PENDING')
|
||||
const approvalTargetLabel = computed(() => props.fulfillmentType === 'ONE_CLICK_DROPSHIP' ? '待一件代发组托' : '待分柜')
|
||||
const approvalButtonLabel = computed(() => `通过并进入${approvalTargetLabel.value}`)
|
||||
const isRejected = computed(() => detail.value?.measureReviewStatus === 'REJECTED' && detail.value?.processStatus === 'MEASURE_REJECTED')
|
||||
const reviewStatusLabel = computed(() => inboundStatusLabel(detail.value?.measureReviewStatus, inboundReviewStatusLabels, '未提交'))
|
||||
const displayCustomerName = computed(() => detail.value?.companyName?.trim() || props.customerName?.trim() || '客户未命名')
|
||||
@@ -134,9 +137,9 @@ async function confirmApprove() {
|
||||
if (!detail.value || !isPending.value || !canReview.value || actionLoading.value || props.postApproveLoading || props.approvalCompleted) return
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'审核通过后,入库单将进入待分柜。系统会尝试生成初算费用,但初算失败不影响审核通过,后续可由平台人员补充调整。是否继续?',
|
||||
`审核通过后,入库单将进入${approvalTargetLabel.value}。系统会尝试生成初算费用,但初算失败不影响审核通过,后续可由平台人员补充调整。是否继续?`,
|
||||
'确认测量审核通过',
|
||||
{ confirmButtonText: '通过并进入待分柜', cancelButtonText: '返回', type: 'warning' },
|
||||
{ confirmButtonText: approvalButtonLabel.value, cancelButtonText: '返回', type: 'warning' },
|
||||
)
|
||||
} catch {
|
||||
return
|
||||
@@ -147,8 +150,9 @@ async function confirmApprove() {
|
||||
measurementId: detail.value.measurementId,
|
||||
expectedVersion: detail.value.inboundVersion,
|
||||
})
|
||||
if (result.initialPricingSucceeded) ElMessage.success('审核已通过,入库单已进入待分柜,费用已完成初算')
|
||||
else ElMessage.warning(`审核已通过,入库单已进入待分柜;费用初算未完成${result.initialPricingMessage ? `:${result.initialPricingMessage}` : ''}`)
|
||||
const resultStatusLabel = inboundStatusLabel(result.processStatus, inboundProcessStatusLabels)
|
||||
if (result.initialPricingSucceeded) ElMessage.success(`审核已通过,入库单已进入${resultStatusLabel},费用已完成初算`)
|
||||
else ElMessage.warning(`审核已通过,入库单已进入${resultStatusLabel};费用初算未完成${result.initialPricingMessage ? `:${result.initialPricingMessage}` : ''}`)
|
||||
emit('changed')
|
||||
} catch (error) {
|
||||
ElMessage.error(isConflict(error) ? '数据已被更新,请刷新后重新审核' : getApiErrorDetails(error, '审核通过失败').message)
|
||||
@@ -184,7 +188,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
|
||||
</div>
|
||||
<div class="review-toolbar__actions">
|
||||
<el-button v-if="isPending && canReview" type="primary" plain @click="correctionMode = true"><Pencil :size="16" />修改重量</el-button>
|
||||
<el-button v-if="isPending && canReview" type="primary" :loading="actionLoading === 'approve' || postApproveLoading" :disabled="approvalCompleted" @click="confirmApprove"><Check :size="16" />{{ approvalCompleted ? '审核已通过' : '通过并进入待分柜' }}</el-button>
|
||||
<el-button v-if="isPending && canReview" type="primary" :loading="actionLoading === 'approve' || postApproveLoading" :disabled="approvalCompleted" @click="confirmApprove"><Check :size="16" />{{ approvalCompleted ? '审核已通过' : approvalButtonLabel }}</el-button>
|
||||
<el-button :loading="loading" aria-label="刷新审核数据" @click="reload"><RotateCcw :size="16" />刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
export const inboundProcessStatusLabels: Record<string, string> = {
|
||||
WAIT_MEASURE: '待测量', MEASURING: '测量中', MEASURE_PENDING: '待测量审核', MEASURE_REJECTED: '测量已驳回',
|
||||
WAIT_PRICING: '待计费', FEE_CONFIRMING: '费用处理中', INBOUNDING: '入库处理中', WAIT_PALLETIZE: '待一件代发合托', WAIT_SPLIT: '待分柜', VOIDED: '已作废',
|
||||
WAIT_PRICING: '待计费', FEE_CONFIRMING: '费用处理中', INBOUNDING: '入库处理中', WAIT_PALLETIZE: '待一件代发组托', WAIT_SPLIT: '待分柜', VOIDED: '已作废',
|
||||
}
|
||||
|
||||
export const inboundOrderStatusLabels: Record<string, string> = {
|
||||
DRAFT: '草稿', SUBMITTED: '待审核', APPROVED: '已审核', ACCEPTED: '已受理', REJECTED: '已驳回',
|
||||
PROCESSING: '处理中', COMPLETED: '已完成', CANCELLED: '已取消', PENDING_REVIEW: '待审核',
|
||||
WAIT_MEASURE: '待测量', WAIT_PALLETIZE: '待一件代发合托', WAIT_SPLIT: '待分柜', LOADING: '装柜中',
|
||||
WAIT_MEASURE: '待测量', WAIT_PALLETIZE: '待一件代发组托', WAIT_SPLIT: '待分柜', LOADING: '装柜中',
|
||||
LOADED: '装柜完成', DELIVERED: '派送完成',
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user