Files
admin-web/src/modules/overseas-warehouse/api/deliveryOrders.test.ts
T

78 lines
5.9 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { http } from '@/shared/api/http'
import { getDeliveryOrder, listDeliveryOrders, listDeliveryReturnInboundOptions, markDeliveryReturn } from './deliveryOrders'
vi.mock('@/shared/api/http', async (importOriginal) => ({ ...(await importOriginal<typeof import('@/shared/api/http')>()), http: { get: vi.fn(), post: vi.fn() } }))
describe('delivery order API', () => {
beforeEach(() => {
vi.mocked(http.get).mockReset()
vi.mocked(http.post).mockReset()
})
it('passes paging and expanded filters and normalizes page numbers', async () => {
vi.mocked(http.get).mockResolvedValue({ code: '200', data: { records: [], page: '2', size: '20', total: '41', pages: '3' } })
const result = await listDeliveryOrders({ page: 2, size: 20, documentNo: 'DEL-1', vehiclePlate: 'CA-1' })
expect(http.get).toHaveBeenCalledWith('/platform/v1/last-leg/delivery-orders', { params: { page: 2, size: 20, documentNo: 'DEL-1', vehiclePlate: 'CA-1' } })
expect(result).toMatchObject({ page: 2, size: 20, total: 41, pages: 3 })
})
it('loads an encoded detail in its explicit customer scope', async () => {
vi.mocked(http.get).mockResolvedValue({ code: '200', data: { order: { deliveryNo: 'DEL/1', version: '0' }, skus: [], fees: [], operations: [] } })
await getDeliveryOrder('DEL/1', '1001')
expect(http.get).toHaveBeenCalledWith('/platform/v1/last-leg/delivery-orders/DEL%2F1', { params: { customerId: '1001', page: 1, size: 200 } })
})
it.each([null, 0, 3])('preserves actual nullable signed quantity %s in list and detail', async signedPackages => {
const order = { deliveryNo: 'DEL-1', version: '0', packageCount: 9, signedPackages }
vi.mocked(http.get).mockResolvedValueOnce({ code: '200', data: { records: [order], page: 1, size: 20, total: 1, pages: 1 } })
const page = await listDeliveryOrders({ page: 1, size: 20 })
expect(page.records[0]?.signedPackages).toBe(signedPackages)
vi.mocked(http.get).mockResolvedValueOnce({ code: '200', data: { order, skus: [], fees: [], operations: [] } })
expect((await getDeliveryOrder('DEL-1', '1001')).order.signedPackages).toBe(signedPackages)
})
it.each(['0', '7', '9007199254740991'])('reads Java Long version %s for status editing', async version => {
vi.mocked(http.get).mockResolvedValue({ code: '200', data: { order: { version, id: '2097515131537313794' } } })
const detail = await getDeliveryOrder('DEL/1', '1001')
expect(detail.order.version).toBe(Number(version))
expect(detail.order.id).toBe('2097515131537313794')
})
it.each([null, undefined, '', ' ', '-1', '1.5', '9007199254740992', -1])('rejects invalid version %s', async version => {
vi.mocked(http.get).mockResolvedValue({ code: '200', data: { order: { version } } })
await expect(getDeliveryOrder('DEL/1', '1001')).rejects.toThrow('派送单缺少有效版本')
})
it('loads return options and marks a return in the explicit customer scope', async () => {
vi.mocked(http.get).mockResolvedValue({ code: '200', data: [{ lastMileOrderId: '109', lastMileOrderNo: 'LM-1', inboundOrderId: '9', inboundCode: 'IN-1', returnSources: [] }] })
await listDeliveryReturnInboundOptions('DEL/1', '1001')
expect(http.get).toHaveBeenCalledWith('/platform/v1/last-leg/delivery-orders/DEL%2F1/return-inbound-options', { params: { customerId: '1001' } })
const payload = { lastMileOrderId: '109', reason: '客户拒收', returnDirection: 'OVERSEAS_WAREHOUSE' as const, items: [{ outboundPalletItemId: '9007199254740995', inventoryPositionId: '9007199254740996', packageCount: 2 }], idempotencyKey: 'return-1' }
vi.mocked(http.post).mockResolvedValue({ code: '200', data: { id: '19', exceptionNo: 'EXC-1', status: 'PENDING' } })
await markDeliveryReturn('DEL/1', '1001', payload)
expect(http.post).toHaveBeenCalledWith('/platform/v1/last-leg/delivery-orders/DEL%2F1/mark-return', payload, { params: { customerId: '1001' } })
})
it('preserves original return carton identity and submits it without inventing an inventory position', async () => {
const source = { outboundPalletItemId: '9007199254740995', inventoryPositionId: null, returnCartonId: '9007199254740997', cartonMark: 'RTN-CARTON-1', maxReturnPackages: 1 }
const relation = { lastMileOrderId: '9007199254741299', lastMileOrderNo: 'LM-RETURN-1', inboundOrderId: null, inboundCode: null, customerId: '1001', returnSources: [{ ...source, maxReturnPackages: '1' }] }
vi.mocked(http.get).mockResolvedValue({ code: '200', data: [relation] })
const options = await listDeliveryReturnInboundOptions('DEL/1', '1001')
expect(options[0]?.returnSources[0]).toEqual(source)
expect(options[0]).toMatchObject({ lastMileOrderId: relation.lastMileOrderId, inboundOrderId: null, inboundCode: null })
const payload = { lastMileOrderId: relation.lastMileOrderId, reason: '原箱拒收', returnDirection: 'OVERSEAS_WAREHOUSE' as const, items: [{ outboundPalletItemId: source.outboundPalletItemId, returnCartonId: source.returnCartonId, packageCount: 1 }], idempotencyKey: 'carton-return' }
vi.mocked(http.post).mockResolvedValue({ code: '200', data: { exceptionNo: 'EX-1' } })
await markDeliveryReturn('DEL/1', '1001', payload)
expect(http.post).toHaveBeenLastCalledWith('/platform/v1/last-leg/delivery-orders/DEL%2F1/mark-return', payload, { params: { customerId: '1001' } })
expect(vi.mocked(http.post).mock.calls[0]?.[1]).not.toHaveProperty('inboundOrderId')
})
it.each([undefined, null, '', '0', 'invalid'])('rejects a candidate with invalid master identity %s even if it has an inbound association', async lastMileOrderId => {
vi.mocked(http.get).mockResolvedValue({ code: '200', data: [{ lastMileOrderId, inboundOrderId: '9', inboundCode: 'IN-1', returnSources: [] }] })
await expect(listDeliveryReturnInboundOptions('DEL/1', '1001')).rejects.toThrow('尾程主单标识')
expect(http.post).not.toHaveBeenCalled()
})
})