Files
admin-web/src/modules/overseas-warehouse/components/warehouseTransferReceiptSelection.test.ts
T

12 lines
3.2 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { canOutboundTransfer, createReceiptCommand, receiptTargetValid, type ReceiptTarget } from './warehouseTransferReceiptSelection'
import type { WarehouseTransferDetailDto } from '../api/warehouseTransfers'
const detail = (): WarehouseTransferDetailDto => ({ id: 'hidden-id', transferNo: 'WT-1', needRelabel: true, relabelNo: 'RL-1', relabelStatus: 'READY_FOR_OUTBOUND', fbaWarehouseCode: 'ABE4', destinationWarehouseCode: 'ABE4', packageCount: 2, status: 'ALLOCATED', items: [], cartons: [], pallets: [], relabelBindings: [], allocations: [1, 2].map(i => ({ inventoryPositionId: 'POS-' + i, inboundOrderId: 'INTERNAL', palletId: 'LA-' + i, packageCount: 1, status: 'RESERVED', skuCode: 'NEW' })) })
const target = (): ReceiptTarget => ({ warehouse: { id: 'NY', customerId: '0', warehouseCode: 'NY-CODE', warehouseName: '纽约', warehouseType: 'OVERSEAS', status: 'ACTIVE' }, pallet: { id: 'P-NY', customerId: '0', warehouseId: 'NY', locationId: 'L-NY', palletCode: 'PALLET-NY', palletType: 'STANDARD', fbaWarehouseCode: 'ABE4', capacityCbm: 2, unitPrice: 0, status: 'IDLE', version: 0 }, location: { id: 'L-NY', warehouseId: 'NY', locationCode: 'LOC-NY', locationType: 'NORMAL', sharedOverflow: false, status: 'IDLE', version: 0 } })
describe('transfer movement eligibility', () => {
it('blocks unconfirmed relabel and incomplete allocation before outbound', () => { const d = detail(); expect(canOutboundTransfer(d)).toBe(true); d.relabelStatus = 'CUSTOMER_CONFIRM_PENDING'; expect(canOutboundTransfer(d)).toBe(false); d.relabelStatus = 'READY_FOR_OUTBOUND'; d.allocations!.pop(); expect(canOutboundTransfer(d)).toBe(false) })
it('uses only shipped unreceived source with exact physical warehouse, FBA and binding', () => { const d = detail(), t = target(); d.status = 'PARTIALLY_RECEIVED'; d.allocations![0]!.status = 'RECEIVED'; d.allocations![1]!.status = 'SHIPPED'; expect(() => createReceiptCommand(d, 'POS-1', t, 'key')).toThrow(); expect(createReceiptCommand(d, 'POS-2', t, 'key')).toMatchObject({ sourceInventoryPositionId: 'POS-2', destinationOverseasWarehouseId: 'NY', destinationPalletNo: 'PALLET-NY', warehouseLocationCode: 'LOC-NY', destinationWarehouseCode: 'ABE4', idempotencyKey: 'key' }); t.pallet.locationId = 'wrong'; expect(receiptTargetValid(d, t)).toBe(false) })
it('rejects another occupied target and permits only the server acknowledged shared target', () => { const d = detail(), t = target(), previous = { warehouseId: 'NY', warehouseCode: 'NY-CODE', warehouseName: '纽约', palletId: 'P-NY', palletNo: 'PALLET-NY', locationId: 'L-NY', locationCode: 'LOC-NY', fbaCode: 'ABE4' }; t.pallet.status = 'OCCUPIED'; t.location.status = 'OCCUPIED'; expect(receiptTargetValid(d, t)).toBeFalsy(); expect(receiptTargetValid(d, t, previous)).toBe(true); t.pallet.id = 'OTHER'; expect(receiptTargetValid(d, t, previous)).toBeFalsy() })
it('rejects ACTIVE physical location and wrong FBA; supports ACTIVE virtual location', () => { const d = detail(), t = target(); t.location.status = 'ACTIVE'; expect(receiptTargetValid(d, t)).toBeFalsy(); t.location.locationType = 'VIRTUAL'; expect(receiptTargetValid(d, t)).toBeTruthy(); t.pallet.fbaWarehouseCode = 'OTHER'; expect(receiptTargetValid(d, t)).toBe(false) })
})