优化
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { createOceanBooking, deleteOceanBookingDraft, listOceanBookings, listWarehouseLogisticsChannels, releaseOceanBooking, updateOceanBookingDraft } from './platformOceanBookings'
|
||||
import { createOceanBooking, deleteOceanBookingDraft, listOceanBookingLinkCandidates, listOceanBookings, listWarehouseLogisticsChannels, releaseOceanBooking, updateOceanBookingDraft } from './platformOceanBookings'
|
||||
import { http } from '@/shared/api/http'
|
||||
|
||||
const detailResponse = (version = 0, status = 'DRAFT') => ({
|
||||
@@ -23,6 +23,16 @@ describe('ocean bookings api', () => {
|
||||
expect(result.records[0]).toMatchObject({ shipperName: '发货企业', consigneeName: '收货企业', containerCount: 3 })
|
||||
})
|
||||
|
||||
it('uses the frozen single-query link candidate contract and normalizes long ids', async () => {
|
||||
vi.spyOn(http, 'get').mockResolvedValueOnce({ code: '200', data: { records: [{ oceanBookingId: 9007199254740993, bookingNo: 'OB-1', requirementId: 9007199254740994, containerType: '40HC', capacityCbm: '76', maxWeightKg: '28000', requiredQuantity: '2', allocatedQuantity: '1', remainingQuantity: '1', customerName: '客户', warehouseName: '义乌仓', channelName: '美森正班' }], page: '1', size: '200', total: '1', pages: '1' } })
|
||||
const query = { warehouseId: '8', channelCode: 'ZBYHK', containerType: '40HC', capacityCbm: 76, maxWeightKg: 28000, page: 1, size: 200 }
|
||||
|
||||
const result = await listOceanBookingLinkCandidates(query)
|
||||
|
||||
expect(http.get).toHaveBeenCalledWith('/platform/v1/ocean-bookings/link-candidates', { params: query })
|
||||
expect(result.records[0]).toMatchObject({ oceanBookingId: '9007199254740992', requirementId: '9007199254740994', capacityCbm: 76, maxWeightKg: 28000, requiredQuantity: 2, allocatedQuantity: 1, remainingQuantity: 1 })
|
||||
})
|
||||
|
||||
it('uses version zero for create and extracts the id from the returned Detail', async () => {
|
||||
const post = vi.spyOn(http, 'post').mockResolvedValue({ code: '200', message: 'ok', data: detailResponse() })
|
||||
const created = await createOceanBooking({ expectedVersion: 0, data: { customerId: null, customerName: null, channelCode: null, warehouseId: null, billOfLadingNo: '', vesselName: '', voyageNo: '', estimatedSailingAt: null, estimatedArrivalAt: null, serviceTerm: null, freightTerm: null, parties: [], containerRequirements: [{ containerType: '40HC', containerKind: 'FCL', quantity: 2, capacityCbm: 76, maxWeightKg: 28000 }] } })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import type { OceanBookingDetail, OceanBookingPage, OceanBookingQuery, OceanBookingResource, OceanBookingSaveRequest, OceanBookingStatus, OceanBookingReleaseRequest } from '../types'
|
||||
import type { OceanBookingDetail, OceanBookingLinkCandidatePage, OceanBookingLinkCandidateQuery, OceanBookingPage, OceanBookingQuery, OceanBookingResource, OceanBookingSaveRequest, OceanBookingStatus, OceanBookingReleaseRequest } from '../types'
|
||||
|
||||
const basePath = '/platform/v1/ocean-bookings'
|
||||
|
||||
@@ -59,6 +59,27 @@ export async function listOceanBookings(query: OceanBookingQuery) {
|
||||
const result = unwrapApiResponse(response)
|
||||
return { ...result, records: (result.records || []).map(booking), page: pageNumber(result.page, query.page), size: pageNumber(result.size, query.size), total: pageNumber(result.total, 0), pages: pageNumber(result.pages, 0) } satisfies OceanBookingPage
|
||||
}
|
||||
export async function listOceanBookingLinkCandidates(query: OceanBookingLinkCandidateQuery) {
|
||||
const response = await http.get<ApiEnvelope<OceanBookingLinkCandidatePage>, ApiEnvelope<OceanBookingLinkCandidatePage>>(`${basePath}/link-candidates`, { params: query })
|
||||
const result = unwrapApiResponse(response)
|
||||
return {
|
||||
...result,
|
||||
records: (result.records || []).map((candidate) => ({
|
||||
...candidate,
|
||||
oceanBookingId: String(candidate.oceanBookingId),
|
||||
requirementId: String(candidate.requirementId),
|
||||
capacityCbm: Number(candidate.capacityCbm),
|
||||
maxWeightKg: Number(candidate.maxWeightKg),
|
||||
requiredQuantity: Number(candidate.requiredQuantity),
|
||||
allocatedQuantity: Number(candidate.allocatedQuantity),
|
||||
remainingQuantity: Number(candidate.remainingQuantity),
|
||||
})),
|
||||
page: pageNumber(result.page, query.page),
|
||||
size: pageNumber(result.size, query.size),
|
||||
total: pageNumber(result.total, 0),
|
||||
pages: pageNumber(result.pages, 0),
|
||||
} satisfies OceanBookingLinkCandidatePage
|
||||
}
|
||||
export async function getOceanBooking(id: string) { const response = await http.get<ApiEnvelope<OceanBookingDetail>, ApiEnvelope<OceanBookingDetail>>(`${basePath}/${encodeURIComponent(id)}`); return detail(unwrapApiResponse(response)) }
|
||||
function idempotencyKey() { return `ocean-booking-${Date.now()}-${Math.random().toString(36).slice(2)}` }
|
||||
export async function createOceanBooking(payload: OceanBookingSaveRequest) { const response = await http.post<ApiEnvelope<OceanBookingDetail>, ApiEnvelope<OceanBookingDetail>>(basePath, payload, { headers: { 'Idempotency-Key': idempotencyKey() } }); return detail(unwrapApiResponse(response)) }
|
||||
|
||||
Reference in New Issue
Block a user