优化
This commit is contained in:
@@ -1,20 +1,20 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { http } from '@/shared/api/http'
|
||||
import { listContainerArrivalTimes, updateContainerExpectedArrival } from './containerArrivalTimes'
|
||||
|
||||
vi.mock('@/shared/api/overseasHttp', () => ({ overseasHttp: { post: vi.fn(), put: vi.fn() } }))
|
||||
vi.mock('@/shared/api/http', async (importOriginal) => ({ ...(await importOriginal<typeof import('@/shared/api/http')>()), http: { post: vi.fn(), put: vi.fn() } }))
|
||||
|
||||
describe('container arrival-time overseas API', () => {
|
||||
beforeEach(() => vi.clearAllMocks())
|
||||
|
||||
it('queries visible containers and updates the whole-container expected arrival', async () => {
|
||||
vi.mocked(overseasHttp.post).mockResolvedValue({ code: '200', data: [{ sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, version: 0 }] })
|
||||
vi.mocked(overseasHttp.put).mockResolvedValue({ code: '200', data: { sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', actualWarehouseArrivalAt: null, version: 1 } } as never)
|
||||
vi.mocked(http.post).mockResolvedValue({ code: '200', data: [{ sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, version: 0 }] })
|
||||
vi.mocked(http.put).mockResolvedValue({ code: '200', data: { sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', actualWarehouseArrivalAt: null, version: 1 } } as never)
|
||||
|
||||
await listContainerArrivalTimes(['9001'])
|
||||
await updateContainerExpectedArrival('9001', { estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', expectedVersion: 0 })
|
||||
|
||||
expect(overseasHttp.post).toHaveBeenCalledWith('/platform/v1/last-leg/orders/container-arrival-times/query', { sourceContainerBookingIds: ['9001'] })
|
||||
expect(overseasHttp.put).toHaveBeenCalledWith('/platform/v1/last-leg/orders/container-summaries/9001/expected-arrival', { estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', expectedVersion: 0 }, { headers: { 'Idempotency-Key': expect.stringContaining('container-expected-arrival-9001-') } })
|
||||
expect(http.post).toHaveBeenCalledWith('/platform/v1/last-leg/orders/container-arrival-times/query', { sourceContainerBookingIds: ['9001'] })
|
||||
expect(http.put).toHaveBeenCalledWith('/platform/v1/last-leg/orders/container-summaries/9001/expected-arrival', { estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', expectedVersion: 0 }, { headers: { 'Idempotency-Key': expect.stringContaining('container-expected-arrival-9001-') } })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
|
||||
|
||||
export interface ContainerArrivalTime {
|
||||
sourceContainerBookingId: string
|
||||
@@ -16,7 +16,7 @@ function operationId(containerBookingId: string) {
|
||||
|
||||
export async function listContainerArrivalTimes(sourceContainerBookingIds: string[]) {
|
||||
if (!sourceContainerBookingIds.length) return []
|
||||
const response = await overseasHttp.post<ApiEnvelope<ContainerArrivalTime[]>, ApiEnvelope<ContainerArrivalTime[]>>(
|
||||
const response = await http.post<ApiEnvelope<ContainerArrivalTime[]>, ApiEnvelope<ContainerArrivalTime[]>>(
|
||||
queryPath,
|
||||
{ sourceContainerBookingIds },
|
||||
)
|
||||
@@ -27,7 +27,7 @@ export async function updateContainerExpectedArrival(
|
||||
sourceContainerBookingId: string,
|
||||
body: { estimatedWarehouseArrivalAt: string; expectedVersion: number; remark?: string },
|
||||
) {
|
||||
const response = await overseasHttp.put<ApiEnvelope<ContainerArrivalTime>, ApiEnvelope<ContainerArrivalTime>>(
|
||||
const response = await http.put<ApiEnvelope<ContainerArrivalTime>, ApiEnvelope<ContainerArrivalTime>>(
|
||||
`/platform/v1/last-leg/orders/container-summaries/${encodeURIComponent(sourceContainerBookingId)}/expected-arrival`,
|
||||
body,
|
||||
{ headers: { 'Idempotency-Key': operationId(sourceContainerBookingId) } },
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { http } from '@/shared/api/http'
|
||||
import { adjustOverseasContainerFee, createOverseasContainerFee, listOverseasContainerCustomers, listOverseasContainerFees, reviewOverseasContainerFee, submitOverseasContainerFee, voidOverseasContainerFee, type OverseasContainerFeeSaveRequest } from './overseasContainerFees'
|
||||
|
||||
const raw = { id: 91, sourceFeeId: 81, sourceVersion: 2, customerId: 11, customerName: '客户A', sourceType: 'OVERSEAS_CONTAINER_FEE', businessType: 'OVERSEAS_CONTAINER', businessId: 99, businessNo: 'CONT-99', containerBookingId: 99, containerNo: 'CONT-99', feeItemCode: 'PORT_FEE', feeItemName: '港口费', direction: 'PAYABLE', amount: 300, currency: 'CNY', reviewStatus: 'DRAFT', sourceStatus: 'ACTIVE', businessDate: '2026-09-08' }
|
||||
@@ -7,14 +7,14 @@ const fee: OverseasContainerFeeSaveRequest = { customerId: '11', customerName: '
|
||||
describe('overseas container fees API', () => {
|
||||
beforeEach(() => vi.restoreAllMocks())
|
||||
it('loads all fees and customers with two container aggregate requests', async () => {
|
||||
const get = vi.spyOn(overseasHttp, 'get').mockResolvedValueOnce({ code: '200', data: [raw] }).mockResolvedValueOnce({ code: '200', data: [{ customerId: 11, customerName: '客户A' }] })
|
||||
const get = vi.spyOn(http, 'get').mockResolvedValueOnce({ code: '200', data: [raw] }).mockResolvedValueOnce({ code: '200', data: [{ customerId: 11, customerName: '客户A' }] })
|
||||
await expect(listOverseasContainerFees('99')).resolves.toMatchObject([{ sourceFeeId: '81', containerBookingId: '99', feeItemCode: 'PORT_FEE' }])
|
||||
await expect(listOverseasContainerCustomers('99')).resolves.toEqual([{ customerId: '11', customerName: '客户A' }])
|
||||
expect(get).toHaveBeenNthCalledWith(1, '/platform/v1/last-leg/finance-fee-sources', { params: { containerBookingId: '99', businessType: 'OVERSEAS_CONTAINER' } })
|
||||
expect(get).toHaveBeenNthCalledWith(2, '/platform/v1/last-leg/finance-fee-sources/container-customers', { params: { containerBookingId: '99' } })
|
||||
})
|
||||
it('uses the exact create and lifecycle action contracts', async () => {
|
||||
const post = vi.spyOn(overseasHttp, 'post').mockResolvedValue({ code: '200', data: raw })
|
||||
const post = vi.spyOn(http, 'post').mockResolvedValue({ code: '200', data: raw })
|
||||
await createOverseasContainerFee(fee, 'create-1'); await submitOverseasContainerFee('81', 'submit-1'); await reviewOverseasContainerFee('81', 'APPROVE', null, 'review-1'); await adjustOverseasContainerFee('81', 2, fee, 'adjust-1'); await voidOverseasContainerFee('81', 2, '重复费用', 'void-1')
|
||||
expect(post).toHaveBeenCalledWith('/platform/v1/last-leg/finance-fee-sources', fee, { headers: { 'Idempotency-Key': 'create-1' } })
|
||||
expect(post).toHaveBeenCalledWith('/platform/v1/last-leg/finance-fee-sources/81/submit', { idempotencyKey: 'submit-1' })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { overseasHttp } from '@/shared/api/overseasHttp'
|
||||
import { unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
|
||||
|
||||
const basePath = '/platform/v1/last-leg/finance-fee-sources'
|
||||
type RawResource = Record<string, unknown>
|
||||
@@ -42,25 +42,25 @@ function normalizeFee(raw: RawResource): OverseasContainerFeeSource {
|
||||
}
|
||||
}
|
||||
export async function listOverseasContainerFees(containerBookingId: string) {
|
||||
const response = await overseasHttp.get<ApiEnvelope<RawResource[]>, ApiEnvelope<RawResource[]>>(basePath, { params: { containerBookingId, businessType: 'OVERSEAS_CONTAINER' } })
|
||||
const response = await http.get<ApiEnvelope<RawResource[]>, ApiEnvelope<RawResource[]>>(basePath, { params: { containerBookingId, businessType: 'OVERSEAS_CONTAINER' } })
|
||||
return unwrapApiResponse(response).map(normalizeFee)
|
||||
}
|
||||
export async function listOverseasContainerCustomers(containerBookingId: string) {
|
||||
const response = await overseasHttp.get<ApiEnvelope<Array<{ customerId: unknown; customerName?: unknown }>>, ApiEnvelope<Array<{ customerId: unknown; customerName?: unknown }>>>(`${basePath}/container-customers`, { params: { containerBookingId } })
|
||||
const response = await http.get<ApiEnvelope<Array<{ customerId: unknown; customerName?: unknown }>>, ApiEnvelope<Array<{ customerId: unknown; customerName?: unknown }>>>(`${basePath}/container-customers`, { params: { containerBookingId } })
|
||||
return unwrapApiResponse(response).map((item) => ({ customerId: requiredText(item.customerId), customerName: text(item.customerName) }))
|
||||
}
|
||||
export async function createOverseasContainerFee(payload: OverseasContainerFeeSaveRequest, idempotencyKey: string) {
|
||||
return normalizeFee(unwrapApiResponse(await overseasHttp.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(basePath, payload, { headers: { 'Idempotency-Key': idempotencyKey } })))
|
||||
return normalizeFee(unwrapApiResponse(await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(basePath, payload, { headers: { 'Idempotency-Key': idempotencyKey } })))
|
||||
}
|
||||
export async function submitOverseasContainerFee(sourceFeeId: string, idempotencyKey: string) {
|
||||
return normalizeFee(unwrapApiResponse(await overseasHttp.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/${encodeURIComponent(sourceFeeId)}/submit`, { idempotencyKey })))
|
||||
return normalizeFee(unwrapApiResponse(await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/${encodeURIComponent(sourceFeeId)}/submit`, { idempotencyKey })))
|
||||
}
|
||||
export async function reviewOverseasContainerFee(sourceFeeId: string, decision: 'APPROVE' | 'REJECT', reason: string | null, idempotencyKey: string) {
|
||||
return normalizeFee(unwrapApiResponse(await overseasHttp.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/${encodeURIComponent(sourceFeeId)}/review`, { decision, reason, idempotencyKey })))
|
||||
return normalizeFee(unwrapApiResponse(await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/${encodeURIComponent(sourceFeeId)}/review`, { decision, reason, idempotencyKey })))
|
||||
}
|
||||
export async function adjustOverseasContainerFee(sourceFeeId: string, expectedVersion: number, fee: OverseasContainerFeeSaveRequest, idempotencyKey: string) {
|
||||
return normalizeFee(unwrapApiResponse(await overseasHttp.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/${encodeURIComponent(sourceFeeId)}/adjust`, { expectedVersion, fee, idempotencyKey })))
|
||||
return normalizeFee(unwrapApiResponse(await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/${encodeURIComponent(sourceFeeId)}/adjust`, { expectedVersion, fee, idempotencyKey })))
|
||||
}
|
||||
export async function voidOverseasContainerFee(sourceFeeId: string, expectedVersion: number, reason: string, idempotencyKey: string) {
|
||||
return normalizeFee(unwrapApiResponse(await overseasHttp.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/${encodeURIComponent(sourceFeeId)}/void`, { expectedVersion, reason, idempotencyKey })))
|
||||
return normalizeFee(unwrapApiResponse(await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/${encodeURIComponent(sourceFeeId)}/void`, { expectedVersion, reason, idempotencyKey })))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user