Merge branch 'release/test' of http://8.163.30.128:10082/html/client-web into release/test
This commit is contained in:
@@ -6,9 +6,17 @@ const source = readFileSync(new URL('./inboundBilling.ts', import.meta.url), 'ut
|
|||||||
const typesSource = readFileSync(new URL('../types/inboundBilling.ts', import.meta.url), 'utf8')
|
const typesSource = readFileSync(new URL('../types/inboundBilling.ts', import.meta.url), 'utf8')
|
||||||
|
|
||||||
test('queries the merchant order inbound-billing endpoint without tenant parameters', () => {
|
test('queries the merchant order inbound-billing endpoint without tenant parameters', () => {
|
||||||
assert.match(source, /url: `\/merchant\/v1\/first-leg\/orders\/\$\{orderId\}\/inbound-billing`/)
|
const readSource = source.slice(source.indexOf('export async function getMerchantInboundBilling'), source.indexOf('function createFeeConfirmationKey'))
|
||||||
assert.match(source, /method: 'GET'/)
|
assert.match(readSource, /url: `\/merchant\/v1\/first-leg\/orders\/\$\{orderId\}\/inbound-billing`/)
|
||||||
assert.doesNotMatch(source, /tenantId|method: '(?:POST|PUT|PATCH|DELETE)'/)
|
assert.match(readSource, /method: 'GET'/)
|
||||||
|
assert.doesNotMatch(readSource, /tenantId|method: '(?:POST|PUT|PATCH|DELETE)'/)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('confirms the latest customer fee version with an idempotency key', () => {
|
||||||
|
assert.match(source, /function confirmMerchantInboundFee/)
|
||||||
|
assert.match(source, /\/inbound-billing\/confirm/)
|
||||||
|
assert.match(source, /headers: \{ 'Idempotency-Key': idempotencyKey \}/)
|
||||||
|
assert.match(source, /data: \{ expectedFeeVersion \}/)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('sanitizes the platform-shaped response into a merchant whitelist', () => {
|
test('sanitizes the platform-shaped response into a merchant whitelist', () => {
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ function sanitizeFee(fee: MerchantInboundFeeSnapshot): MerchantInboundFeeSnapsho
|
|||||||
feeStatus: fee.feeStatus,
|
feeStatus: fee.feeStatus,
|
||||||
inboundId: fee.inboundId,
|
inboundId: fee.inboundId,
|
||||||
inboundCode: fee.inboundCode,
|
inboundCode: fee.inboundCode,
|
||||||
|
measurementId: fee.measurementId == null ? null : String(fee.measurementId),
|
||||||
|
measurementSource: fee.measurementSource,
|
||||||
chargeRuleId: fee.chargeRuleId,
|
chargeRuleId: fee.chargeRuleId,
|
||||||
ruleCode: fee.ruleCode,
|
ruleCode: fee.ruleCode,
|
||||||
chargeRuleVersion: fee.chargeRuleVersion,
|
chargeRuleVersion: fee.chargeRuleVersion,
|
||||||
@@ -101,6 +103,10 @@ function sanitizeFee(fee: MerchantInboundFeeSnapshot): MerchantInboundFeeSnapsho
|
|||||||
confirmedAt: fee.confirmedAt,
|
confirmedAt: fee.confirmedAt,
|
||||||
sentAt: fee.sentAt,
|
sentAt: fee.sentAt,
|
||||||
nextProcessStatus: fee.nextProcessStatus,
|
nextProcessStatus: fee.nextProcessStatus,
|
||||||
|
customerConfirmationStatus: fee.customerConfirmationStatus,
|
||||||
|
customerConfirmedBy: fee.customerConfirmedBy == null ? null : String(fee.customerConfirmedBy),
|
||||||
|
customerConfirmedByName: fee.customerConfirmedByName,
|
||||||
|
customerConfirmedAt: fee.customerConfirmedAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +121,7 @@ function sanitizeMeasurementSummary(item: MerchantInboundBilling['measurementSum
|
|||||||
actualVolumeCbm: item.actualVolumeCbm,
|
actualVolumeCbm: item.actualVolumeCbm,
|
||||||
volumeWeightKg: item.volumeWeightKg,
|
volumeWeightKg: item.volumeWeightKg,
|
||||||
actualGoodsName: item.actualGoodsName,
|
actualGoodsName: item.actualGoodsName,
|
||||||
|
calculationSource: item.calculationSource,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +137,9 @@ function sanitizeMeasurementItem(item: MerchantInboundBilling['measurementItems'
|
|||||||
unitVolumeCbm: item.unitVolumeCbm,
|
unitVolumeCbm: item.unitVolumeCbm,
|
||||||
totalVolumeCbm: item.totalVolumeCbm,
|
totalVolumeCbm: item.totalVolumeCbm,
|
||||||
volumeWeightKg: item.volumeWeightKg,
|
volumeWeightKg: item.volumeWeightKg,
|
||||||
|
chargeRuleId: item.chargeRuleId == null ? null : String(item.chargeRuleId),
|
||||||
|
coefficientMode: item.coefficientMode,
|
||||||
|
calculationRuleVersion: item.calculationRuleVersion,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,3 +164,19 @@ export async function getMerchantInboundBilling(orderId: string): Promise<Mercha
|
|||||||
})
|
})
|
||||||
return sanitizeInboundBilling(response)
|
return sanitizeInboundBilling(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createFeeConfirmationKey(orderId: string, feeVersion: number) {
|
||||||
|
const randomPart = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`
|
||||||
|
return `inbound-fee-confirm-${orderId}-${feeVersion}-${randomPart}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function confirmMerchantInboundFee(orderId: string, expectedFeeVersion: number,
|
||||||
|
idempotencyKey = createFeeConfirmationKey(orderId, expectedFeeVersion)) {
|
||||||
|
const response = await apiRequest<MerchantInboundFeeSnapshot>({
|
||||||
|
method: 'POST',
|
||||||
|
url: `/merchant/v1/first-leg/orders/${encodeURIComponent(orderId)}/inbound-billing/confirm`,
|
||||||
|
headers: { 'Idempotency-Key': idempotencyKey },
|
||||||
|
data: { expectedFeeVersion },
|
||||||
|
})
|
||||||
|
return sanitizeFee(response)
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,17 +10,21 @@ test('renders loading, pending, isolated error, and published states', () => {
|
|||||||
assert.match(source, /role="alert"/)
|
assert.match(source, /role="alert"/)
|
||||||
assert.match(source, /v-else-if="props\.unavailable \|\| !props\.data"/)
|
assert.match(source, /v-else-if="props\.unavailable \|\| !props\.data"/)
|
||||||
assert.match(source, /role="status"/)
|
assert.match(source, /role="status"/)
|
||||||
assert.match(source, /待分柜 · 费用已发布/)
|
assert.match(source, /费用已发布 · 待确认/)
|
||||||
assert.match(source, /\$emit\('retry'\)/)
|
assert.match(source, /\$emit\('retry'\)/)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('shows the confirmed merchant inbound, measurement details and customer confirmation entry', () => {
|
test('shows the published merchant inbound, measurement details and customer confirmation entry', () => {
|
||||||
for (const label of ['入仓码', '平台收货仓', '实际毛重', '实测体积', '托盘与库位', '换算与精度', '最终计费量', '基础费用', '附加费用', '费用合计', '平台备注']) {
|
for (const label of ['入仓码', '平台收货仓', '实际毛重', '实测体积', '托盘与库位', '换算与精度', '最终计费量', '基础费用', '附加费用', '费用合计', '平台备注']) {
|
||||||
assert.match(source, new RegExp(label))
|
assert.match(source, new RegExp(label))
|
||||||
}
|
}
|
||||||
assert.match(source, /formatInboundMoney\(props\.data\.latestFee\.totalAmount/)
|
assert.match(source, /formatInboundMoney\(props\.data\.latestFee\.totalAmount/)
|
||||||
assert.match(source, /formatConversionPrecision\(/)
|
assert.match(source, /formatConversionPrecision\(/)
|
||||||
assert.match(source, /确认费用/)
|
assert.match(source, /确认费用/)
|
||||||
|
assert.match(source, /二次确认费用/)
|
||||||
|
assert.match(source, /确认后该费用将锁定,平台不能再修改/)
|
||||||
|
assert.match(source, /customerConfirmationStatus === 'CONFIRMED'/)
|
||||||
|
assert.match(source, /confirmMerchantInboundFee/)
|
||||||
assert.match(source, /measurementItems/)
|
assert.match(source, /measurementItems/)
|
||||||
assert.doesNotMatch(source, /调整费用|发送费用|下载照片/)
|
assert.doesNotMatch(source, /调整费用|发送费用|下载照片/)
|
||||||
assert.doesNotMatch(source, /internalNotes|statusHistory|files/)
|
assert.doesNotMatch(source, /internalNotes|statusHistory|files/)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Clock3, PackageCheck, RefreshCw, TriangleAlert } from '@lucide/vue'
|
import { Clock3, PackageCheck, RefreshCw, TriangleAlert } from '@lucide/vue'
|
||||||
|
import { confirmMerchantInboundFee } from '@/modules/first-leg/api/inboundBilling'
|
||||||
import type { MerchantInboundBilling } from '@/modules/first-leg/types/inboundBilling'
|
import type { MerchantInboundBilling } from '@/modules/first-leg/types/inboundBilling'
|
||||||
import {
|
import {
|
||||||
formatConversionPrecision,
|
formatConversionPrecision,
|
||||||
@@ -19,6 +21,7 @@ const props = withDefaults(defineProps<{
|
|||||||
unavailableMessage?: string
|
unavailableMessage?: string
|
||||||
error?: string
|
error?: string
|
||||||
autoOpen?: boolean
|
autoOpen?: boolean
|
||||||
|
canConfirm?: boolean
|
||||||
}>(), {
|
}>(), {
|
||||||
data: null,
|
data: null,
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -26,16 +29,49 @@ const props = withDefaults(defineProps<{
|
|||||||
unavailableMessage: '还未测量推送',
|
unavailableMessage: '还未测量推送',
|
||||||
error: '',
|
error: '',
|
||||||
autoOpen: false,
|
autoOpen: false,
|
||||||
|
canConfirm: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
defineEmits<{
|
const emit = defineEmits<{
|
||||||
retry: []
|
retry: []
|
||||||
|
confirmed: []
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const feeDialogOpen = ref(false)
|
const feeDialogOpen = ref(false)
|
||||||
|
const confirming = ref(false)
|
||||||
watch(() => [props.autoOpen, props.data] as const, ([autoOpen, data]) => {
|
watch(() => [props.autoOpen, props.data] as const, ([autoOpen, data]) => {
|
||||||
if (autoOpen && data) feeDialogOpen.value = true
|
if (autoOpen && data) feeDialogOpen.value = true
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
|
async function confirmFee() {
|
||||||
|
const fee = props.data?.latestFee
|
||||||
|
const orderId = props.data?.inbound.summary.orderId
|
||||||
|
if (!fee || !orderId || !props.canConfirm || confirming.value) return
|
||||||
|
if (fee.customerConfirmationStatus === 'CONFIRMED') {
|
||||||
|
ElMessage.info('当前费用已经确认,无需重复操作')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
`请再次确认费用单 ${fee.feeNo},合计 ${formatInboundMoney(fee.totalAmount, fee.currency)}。确认后该费用将锁定,平台不能再修改。`,
|
||||||
|
'二次确认费用',
|
||||||
|
{ type: 'warning', confirmButtonText: '确认费用无误', cancelButtonText: '返回核对' },
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
confirming.value = true
|
||||||
|
try {
|
||||||
|
await confirmMerchantInboundFee(orderId, fee.feeVersion)
|
||||||
|
ElMessage.success('费用确认成功,当前费用已锁定')
|
||||||
|
feeDialogOpen.value = false
|
||||||
|
emit('confirmed')
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error(error instanceof Error ? error.message : '费用确认失败,请刷新后重试')
|
||||||
|
} finally {
|
||||||
|
confirming.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -43,8 +79,11 @@ watch(() => [props.autoOpen, props.data] as const, ([autoOpen, data]) => {
|
|||||||
<header class="inbound-billing-heading">
|
<header class="inbound-billing-heading">
|
||||||
<h3 id="inbound-billing-title">入库与费用</h3>
|
<h3 id="inbound-billing-title">入库与费用</h3>
|
||||||
<div v-if="props.data" class="inbound-billing-actions">
|
<div v-if="props.data" class="inbound-billing-actions">
|
||||||
<el-tag type="success" effect="light">待分柜 · 费用已发布</el-tag>
|
<el-tag :type="props.data.latestFee.customerConfirmationStatus === 'CONFIRMED' ? 'success' : 'warning'" effect="light">
|
||||||
<el-button type="primary" @click="feeDialogOpen = true">确认费用</el-button>
|
{{ props.data.latestFee.customerConfirmationStatus === 'CONFIRMED' ? '客户已确认 · 费用已锁定' : '费用已发布 · 待确认' }}
|
||||||
|
</el-tag>
|
||||||
|
<el-button v-if="props.data.latestFee.customerConfirmationStatus !== 'CONFIRMED' && props.canConfirm" type="primary" @click="feeDialogOpen = true">确认费用</el-button>
|
||||||
|
<el-button v-else plain @click="feeDialogOpen = true">查看费用</el-button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -163,10 +202,10 @@ watch(() => [props.autoOpen, props.data] as const, ([autoOpen, data]) => {
|
|||||||
|
|
||||||
<el-dialog v-model="feeDialogOpen" title="确认测量与计费数据" width="min(980px, 94vw)" append-to-body>
|
<el-dialog v-model="feeDialogOpen" title="确认测量与计费数据" width="min(980px, 94vw)" append-to-body>
|
||||||
<dl v-if="props.data" class="inbound-measurements fee-dialog-summary">
|
<dl v-if="props.data" class="inbound-measurements fee-dialog-summary">
|
||||||
<div><dt>测量总箱数</dt><dd>{{ formatInboundNumber(props.data.measurementSummary.actualPackageCount, 0) }}</dd></div>
|
<div><dt>计费总箱数</dt><dd>{{ formatInboundNumber(props.data.measurementSummary.actualPackageCount, 0) }}</dd></div>
|
||||||
<div><dt>测量总毛重</dt><dd>{{ formatInboundMeasure(props.data.measurementSummary.actualGrossWeightKg, 'kg') }}</dd></div>
|
<div><dt>计费总毛重</dt><dd>{{ formatInboundMeasure(props.data.measurementSummary.actualGrossWeightKg, 'kg') }}</dd></div>
|
||||||
<div><dt>测量总体积</dt><dd>{{ formatInboundMeasure(props.data.measurementSummary.actualVolumeCbm, 'm³') }}</dd></div>
|
<div><dt>外箱规总体积</dt><dd>{{ formatInboundMeasure(props.data.measurementSummary.actualVolumeCbm, 'm³') }}</dd></div>
|
||||||
<div><dt>测量总材积重</dt><dd>{{ formatInboundMeasure(props.data.measurementSummary.volumeWeightKg, 'kg') }}</dd></div>
|
<div><dt>外箱规总材积重</dt><dd>{{ formatInboundMeasure(props.data.measurementSummary.volumeWeightKg, 'kg') }}</dd></div>
|
||||||
<div><dt>计费体积</dt><dd>{{ formatInboundMeasure(props.data.billingBasis.chargeableVolumeCbm, 'm³') }}</dd></div>
|
<div><dt>计费体积</dt><dd>{{ formatInboundMeasure(props.data.billingBasis.chargeableVolumeCbm, 'm³') }}</dd></div>
|
||||||
<div><dt>计费重量</dt><dd>{{ formatInboundMeasure(props.data.billingBasis.chargeableWeightKg, 'kg') }}</dd></div>
|
<div><dt>计费重量</dt><dd>{{ formatInboundMeasure(props.data.billingBasis.chargeableWeightKg, 'kg') }}</dd></div>
|
||||||
</dl>
|
</dl>
|
||||||
@@ -179,9 +218,22 @@ watch(() => [props.autoOpen, props.data] as const, ([autoOpen, data]) => {
|
|||||||
<el-table-column label="每箱体积" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.unitVolumeCbm, 'm³') }}</template></el-table-column>
|
<el-table-column label="每箱体积" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.unitVolumeCbm, 'm³') }}</template></el-table-column>
|
||||||
<el-table-column label="总体积" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.totalVolumeCbm, 'm³') }}</template></el-table-column>
|
<el-table-column label="总体积" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.totalVolumeCbm, 'm³') }}</template></el-table-column>
|
||||||
<el-table-column label="总材积重" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.volumeWeightKg, 'kg') }}</template></el-table-column>
|
<el-table-column label="总材积重" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.volumeWeightKg, 'kg') }}</template></el-table-column>
|
||||||
|
<el-table-column prop="calculationRuleVersion" label="箱规规则" min-width="180" />
|
||||||
<el-table-column prop="boxSpecification" label="备注" min-width="130" />
|
<el-table-column prop="boxSpecification" label="备注" min-width="130" />
|
||||||
</el-table>
|
</el-table>
|
||||||
<template #footer><el-button type="primary" @click="feeDialogOpen = false">确认</el-button></template>
|
<el-alert
|
||||||
|
v-if="props.data?.latestFee.customerConfirmationStatus === 'CONFIRMED'"
|
||||||
|
class="fee-confirmed-alert"
|
||||||
|
:title="`客户已于 ${formatInboundDateTime(props.data.latestFee.customerConfirmedAt)} 确认,费用已锁定,不允许修改。`"
|
||||||
|
type="success"
|
||||||
|
:closable="false"
|
||||||
|
show-icon
|
||||||
|
/>
|
||||||
|
<el-alert v-else class="fee-confirmed-alert" title="请核对全部计费数据。点击确认后还会进行一次确认,完成后费用将锁定。" type="warning" :closable="false" show-icon />
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="feeDialogOpen = false">关闭</el-button>
|
||||||
|
<el-button v-if="props.data?.latestFee.customerConfirmationStatus !== 'CONFIRMED' && props.canConfirm" type="primary" :loading="confirming" @click="confirmFee">确认费用</el-button>
|
||||||
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
@@ -214,6 +266,7 @@ watch(() => [props.autoOpen, props.data] as const, ([autoOpen, data]) => {
|
|||||||
.inbound-measurements > div { min-width: 0; padding: 12px; }
|
.inbound-measurements > div { min-width: 0; padding: 12px; }
|
||||||
.measurement-detail-table { margin-top: 12px; }
|
.measurement-detail-table { margin-top: 12px; }
|
||||||
.fee-dialog-summary { margin-top: 0; }
|
.fee-dialog-summary { margin-top: 0; }
|
||||||
|
.fee-confirmed-alert { margin-top: 14px; }
|
||||||
.pallet-location-list { margin-top: 9px; border-top: 1px solid var(--border); }
|
.pallet-location-list { margin-top: 9px; border-top: 1px solid var(--border); }
|
||||||
.pallet-location-list article { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 11px; padding: 12px 0; border-bottom: 1px solid var(--border); }
|
.pallet-location-list article { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 11px; padding: 12px 0; border-bottom: 1px solid var(--border); }
|
||||||
.pallet-location-list article > svg { color: var(--primary); }
|
.pallet-location-list article > svg { color: var(--primary); }
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ export interface MerchantInboundFeeSnapshot {
|
|||||||
feeStatus: MerchantInboundFeeStatus
|
feeStatus: MerchantInboundFeeStatus
|
||||||
inboundId: string
|
inboundId: string
|
||||||
inboundCode: string
|
inboundCode: string
|
||||||
|
measurementId?: string | null
|
||||||
|
measurementSource?: string | null
|
||||||
chargeRuleId: string
|
chargeRuleId: string
|
||||||
ruleCode: string
|
ruleCode: string
|
||||||
chargeRuleVersion: number
|
chargeRuleVersion: number
|
||||||
@@ -98,6 +100,10 @@ export interface MerchantInboundFeeSnapshot {
|
|||||||
confirmedAt: string | null
|
confirmedAt: string | null
|
||||||
sentAt: string | null
|
sentAt: string | null
|
||||||
nextProcessStatus: MerchantInboundProcessStatus | null
|
nextProcessStatus: MerchantInboundProcessStatus | null
|
||||||
|
customerConfirmationStatus: 'PENDING_CONFIRMATION' | 'CONFIRMED'
|
||||||
|
customerConfirmedBy: string | null
|
||||||
|
customerConfirmedByName: string | null
|
||||||
|
customerConfirmedAt: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MerchantMeasurementItem {
|
export interface MerchantMeasurementItem {
|
||||||
@@ -111,6 +117,9 @@ export interface MerchantMeasurementItem {
|
|||||||
unitVolumeCbm: number | null
|
unitVolumeCbm: number | null
|
||||||
totalVolumeCbm: number | null
|
totalVolumeCbm: number | null
|
||||||
volumeWeightKg: number | null
|
volumeWeightKg: number | null
|
||||||
|
chargeRuleId: string | null
|
||||||
|
coefficientMode: 'ADD' | 'MULTIPLY' | null
|
||||||
|
calculationRuleVersion: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MerchantBillingBasis {
|
export interface MerchantBillingBasis {
|
||||||
@@ -137,6 +146,7 @@ export interface MerchantInboundBilling {
|
|||||||
actualVolumeCbm: number | null
|
actualVolumeCbm: number | null
|
||||||
volumeWeightKg: number | null
|
volumeWeightKg: number | null
|
||||||
actualGoodsName: string | null
|
actualGoodsName: string | null
|
||||||
|
calculationSource: 'OUTER' | string | null
|
||||||
}
|
}
|
||||||
measurementItems: MerchantMeasurementItem[]
|
measurementItems: MerchantMeasurementItem[]
|
||||||
billingBasis: MerchantBillingBasis
|
billingBasis: MerchantBillingBasis
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ const companyAuditLoaded = ref(false)
|
|||||||
const companySubmissionBlocked = computed(() => companyAuditLoaded.value && tenantStore.company.auditStatus !== 'ACTIVE')
|
const companySubmissionBlocked = computed(() => companyAuditLoaded.value && tenantStore.company.auditStatus !== 'ACTIVE')
|
||||||
const canCreateOrder = computed(() => auth.hasPermission('order:first-leg:create'))
|
const canCreateOrder = computed(() => auth.hasPermission('order:first-leg:create'))
|
||||||
const canEditOrder = computed(() => auth.hasPermission('order:first-leg:edit'))
|
const canEditOrder = computed(() => auth.hasPermission('order:first-leg:edit'))
|
||||||
|
const canConfirmInboundFee = computed(() => auth.hasPermission('order:first-leg:edit'))
|
||||||
const availableWarehouses = computed(() => store.warehouses.filter((warehouse) => warehouse.warehouseType === 'DOMESTIC'))
|
const availableWarehouses = computed(() => store.warehouses.filter((warehouse) => warehouse.warehouseType === 'DOMESTIC'))
|
||||||
const availableDestinationWarehouses = computed(() => store.warehouses.filter((warehouse) => warehouse.warehouseType === form.destinationType))
|
const availableDestinationWarehouses = computed(() => store.warehouses.filter((warehouse) => warehouse.warehouseType === form.destinationType))
|
||||||
const filters = ref<QueryModel>({ orderNo: '', receivingWarehouseId: '', channelName: '', cargoKeyword: '', createdRange: [], status: '', destinationType: '', trackingNumber: '' })
|
const filters = ref<QueryModel>({ orderNo: '', receivingWarehouseId: '', channelName: '', cargoKeyword: '', createdRange: [], status: '', destinationType: '', trackingNumber: '' })
|
||||||
@@ -2153,7 +2154,9 @@ async function searchOrders(model: QueryModel) {
|
|||||||
:unavailable="inboundBillingUnavailable"
|
:unavailable="inboundBillingUnavailable"
|
||||||
:unavailable-message="inboundBillingUnavailableMessage"
|
:unavailable-message="inboundBillingUnavailableMessage"
|
||||||
:error="inboundBillingError"
|
:error="inboundBillingError"
|
||||||
|
:can-confirm="canConfirmInboundFee"
|
||||||
@retry="retryInboundBilling"
|
@retry="retryInboundBilling"
|
||||||
|
@confirmed="retryInboundBilling"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user