This commit is contained in:
2026-08-04 11:14:29 +08:00
parent 5c25806081
commit f533024501
7 changed files with 204 additions and 28 deletions
@@ -24,7 +24,7 @@ test('maps transport and status fields instead of treating container mode as tra
test('uses real API data without falling back to demo warehouses or orders', () => {
assert.match(storeSource, /orders\.value = \[\]/)
assert.match(storeSource, /warehouses\.value = \[\]/)
assert.match(storeSource, /Promise\.all\(\[getMerchantFirstLegOrders\(\), getMerchantWarehouses\(\)\]\)/)
assert.match(storeSource, /Promise\.allSettled\(\[getMerchantFirstLegOrders\(\), getMerchantWarehouses\(\)\]\)/)
assert.doesNotMatch(storeSource, /DEMO_PLATFORM_RECEIVING_WAREHOUSES|initialOrders/)
})
@@ -35,6 +35,13 @@ test('sends backend-required channel, customs, destination and cargo fields', ()
assert.match(storeSource, /containerMode: draft\.transportMode === 'FCL' \? 'FULL_CONTAINER'/)
assert.match(storeSource, /customerId: draft\.shipperPartyId/)
assert.match(storeSource, /customerName: customerName\.trim\(\) \|\| draft\.shipperPartySnapshot\.name/)
assert.match(storeSource, /destinationWarehouseId: draft\.destinationType === 'PRIVATE' \? undefined : draft\.destinationWarehouseId/)
})
test('separates domestic receiving warehouses from public destinations', () => {
assert.match(storeSource, /warehouse\.warehouseType !== 'DOMESTIC'/)
assert.match(storeSource, /item\.warehouseType === draft\.destinationType/)
assert.match(storeSource, /draft\.amazonWarehouseCode = draft\.destinationType === 'FBA' \? destinationWarehouse\.code : ''/)
})
test('only blocks submission when a known company audit status is not active', () => {
@@ -67,6 +74,7 @@ test('maps backend warehouse snapshots and fulfillment courier fields', () => {
test('keeps failed order loads distinct from empty results', () => {
assert.match(storeSource, /const loadError = ref\(''\)/)
assert.match(storeSource, /loadError\.value = error instanceof Error/)
assert.match(storeSource, /return \{ orders, warehouses, loading, loadedFromApi, loadError/)
assert.match(storeSource, /orderResult\.reason instanceof Error/)
assert.match(storeSource, /warehouseLoadError/)
assert.match(storeSource, /return \{ orders, warehouses, loading, loadedFromApi, loadError, warehouseLoadError/)
})
+39 -13
View File
@@ -21,6 +21,12 @@ import type { FirstLegPartySnapshot } from '@/modules/first-leg/data/firstLegPar
import type { FirstLegOrder, FirstLegOrderDraft, FirstLegOrderTimelineItem } from '@/modules/first-leg/types/firstLegOrder'
import { canClientEditFirstLegOrder } from '@/modules/first-leg/utils/firstLegOrder'
export type ClientWarehouseType = 'DOMESTIC' | 'FBA' | 'OVERSEAS'
export type ClientWarehouse = PlatformReceivingWarehouse & {
warehouseType: ClientWarehouseType
countryCode: string
}
const countryCodes: Readonly<Record<string, string>> = {
中国: 'CN', 美国: 'US', 德国: 'DE', 英国: 'GB', 加拿大: 'CA', 日本: 'JP', 澳大利亚: 'AU',
}
@@ -60,7 +66,7 @@ function partyPayload(snapshot: FirstLegPartySnapshot): FirstLegOrderPartyPayloa
}
}
function savePayload(draft: FirstLegOrderDraft, warehouse: PlatformReceivingWarehouse, customerName: string): FirstLegOrderSaveRequest {
function savePayload(draft: FirstLegOrderDraft, warehouse: ClientWarehouse, customerName: string): FirstLegOrderSaveRequest {
if (!draft.shipperPartySnapshot || !draft.consigneePartySnapshot) throw new Error('请完整填写收发货信息')
return {
// 后端把 customerId 作为订单主往来单位校验并以服务端名称覆盖 customerName;
@@ -70,6 +76,7 @@ function savePayload(draft: FirstLegOrderDraft, warehouse: PlatformReceivingWare
transportMode: apiTransport(draft),
tradeTerm: draft.tradeTerm || undefined,
destinationCountryCode: draft.destinationCountryCode.trim().toUpperCase(),
destinationWarehouseId: draft.destinationType === 'PRIVATE' ? undefined : draft.destinationWarehouseId,
destinationWarehouseName: draft.destinationWarehouseName,
expectedShipDate: draft.expectedDepartureDate || undefined,
customerRemark: draft.customerRemark || undefined,
@@ -167,26 +174,29 @@ function mapOrder(order: MerchantFirstLegOrder, warehouses: PlatformReceivingWar
})),
timeline: detail ? timeline(detail) : [], createdAt: order.createdAt, updatedAt: order.updatedAt,
tradeTerm: order.tradeTerm ?? '', destinationCountryCode: order.destinationCountryCode,
destinationWarehouseId: order.destinationWarehouseId ? String(order.destinationWarehouseId) : '',
destinationWarehouseName: order.destinationWarehouseName, pickupMethod: order.pickupMethod, channelCode: order.channelCode,
channelName: order.channelName, taxMode: order.taxMode, customsInspection: order.customsInspection,
destinationType: order.destinationType, amazonWarehouseCode: order.amazonWarehouseCode ?? '', shipmentId: order.shipmentId ?? '',
}
}
function mapWarehouse(item: MerchantWarehouse): PlatformReceivingWarehouse {
function mapWarehouse(item: MerchantWarehouse): ClientWarehouse {
return {
id: String(item.id), code: item.warehouseCode, name: item.warehouseName, province: '',
city: '', address: '', contactName: item.contactName ?? '', contactPhone: item.contactPhone ?? '',
businessHours: '', status: item.status, remark: item.remark ?? '', updatedAt: item.updatedAt ?? '',
warehouseType: item.warehouseType as ClientWarehouseType, countryCode: item.countryCode,
}
}
export const useFirstLegOrdersStore = defineStore('client-first-leg-orders', () => {
const orders = ref<FirstLegOrder[]>([])
const warehouses = ref<PlatformReceivingWarehouse[]>([])
const warehouses = ref<ClientWarehouse[]>([])
const loading = ref(false)
const loadedFromApi = ref(false)
const loadError = ref('')
const warehouseLoadError = ref('')
const activeCount = computed(() => orders.value.filter((item) => ['PENDING_REVIEW', 'ACCEPTED', 'BOOKED', 'IN_TRANSIT'].includes(item.status)).length)
const pendingCount = computed(() => orders.value.filter((item) => item.status === 'PENDING_REVIEW').length)
@@ -196,16 +206,23 @@ export const useFirstLegOrdersStore = defineStore('client-first-leg-orders', ()
loading.value = true
loadedFromApi.value = true
loadError.value = ''
warehouseLoadError.value = ''
orders.value = []
warehouses.value = []
try {
const [orderPage, warehousePage] = await Promise.all([getMerchantFirstLegOrders(), getMerchantWarehouses()])
warehouses.value = warehousePage.records.filter((item) => item.status === 'ACTIVE').map(mapWarehouse)
orders.value = orderPage.records.map((item) => mapOrder(item, warehouses.value))
} catch (error) {
loadError.value = error instanceof Error ? error.message : '订单与仓库数据加载失败'
throw error
} finally { loading.value = false }
const [orderResult, warehouseResult] = await Promise.allSettled([getMerchantFirstLegOrders(), getMerchantWarehouses()])
if (warehouseResult.status === 'fulfilled') {
warehouses.value = warehouseResult.value.records
.filter((item) => item.status === 'ACTIVE' && ['DOMESTIC', 'FBA', 'OVERSEAS'].includes(item.warehouseType))
.map(mapWarehouse)
} else {
warehouseLoadError.value = warehouseResult.reason instanceof Error ? warehouseResult.reason.message : '公共仓库数据加载失败'
}
if (orderResult.status === 'fulfilled') {
orders.value = orderResult.value.records.map((item) => mapOrder(item, warehouses.value))
} else {
loadError.value = orderResult.reason instanceof Error ? orderResult.reason.message : '订单数据加载失败'
}
loading.value = false
}
async function loadDetail(id: string) {
@@ -235,7 +252,16 @@ export const useFirstLegOrdersStore = defineStore('client-first-leg-orders', ()
async function saveDraft(draft: FirstLegOrderDraft, customerName: string, id?: string) {
const warehouse = warehouses.value.find((item) => item.id === draft.receivingWarehouseId)
if (!warehouse) throw new Error('所选收货仓当前不可用')
if (!warehouse || warehouse.warehouseType !== 'DOMESTIC') throw new Error('所选国内收货仓当前不可用')
if (draft.destinationType !== 'PRIVATE') {
const destinationWarehouse = warehouses.value.find((item) => item.id === draft.destinationWarehouseId && item.warehouseType === draft.destinationType)
if (!destinationWarehouse) throw new Error('所选目的仓当前不可用,请重新选择')
draft.destinationWarehouseName = destinationWarehouse.name
draft.destinationCountryCode = destinationWarehouse.countryCode
draft.amazonWarehouseCode = draft.destinationType === 'FBA' ? destinationWarehouse.code : ''
} else {
draft.destinationWarehouseId = ''
}
if (id) {
const order = getById(id)
if (!order || !canClientEditFirstLegOrder(order.status)) throw new Error('当前订单状态不允许编辑')
@@ -253,5 +279,5 @@ export const useFirstLegOrdersStore = defineStore('client-first-leg-orders', ()
return loadDetail(order.id)
}
return { orders, warehouses, loading, loadedFromApi, loadError, activeCount, pendingCount, getById, load, loadDetail, loadWarehouseDetail, saveDraft, submit }
return { orders, warehouses, loading, loadedFromApi, loadError, warehouseLoadError, activeCount, pendingCount, getById, load, loadDetail, loadWarehouseDetail, saveDraft, submit }
})