diff --git a/src/modules/overseas-warehouse/utils/returnReceiptDisplay.test.mjs b/src/modules/overseas-warehouse/utils/returnReceiptDisplay.test.mjs new file mode 100644 index 0000000..3643b8e --- /dev/null +++ b/src/modules/overseas-warehouse/utils/returnReceiptDisplay.test.mjs @@ -0,0 +1,22 @@ +import assert from 'node:assert/strict' +import { readFileSync } from 'node:fs' +import test from 'node:test' +import ts from 'typescript' + +const source = readFileSync(new URL('./returnReceiptDisplay.ts', import.meta.url), 'utf8') +const compiled = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.CommonJS } }).outputText +const exports = {} +new Function('exports', compiled)(exports) + +test('volume rounds upward to exactly three decimal places without increasing exact thousandths', () => { + for (const [input, expected] of [[0.186624, '0.187'], [0.15, '0.150'], [1.001, '1.001'], [1.00100001, '1.002'], [0.0000001, '0.001'], [0, '0.000'], [null, '—'], [NaN, '—']]) { + assert.equal(exports.formatReturnVolume(input), expected) + } +}) + +test('parcel waybills appear as tracking numbers while generated parcel codes remain physical codes', () => { + assert.equal(exports.receiptTrackingNo({ unitType: 'PARCEL', unitCode: 'sf561626' }), 'sf561626') + assert.equal(exports.receiptTrackingNo({ unitType: 'PARCEL', unitCode: 'PK0123456789ABCDEF' }), '') + assert.equal(exports.receiptTrackingNo({ unitType: 'PARCEL', unitCode: 'PK0123456789ABCDEF', trackingNo: ' SF123 ' }), 'SF123') + assert.equal(exports.receiptTrackingNo({ unitType: 'PALLET', unitCode: 'PLT123' }), '') +}) diff --git a/src/modules/overseas-warehouse/utils/returnReceiptDisplay.ts b/src/modules/overseas-warehouse/utils/returnReceiptDisplay.ts new file mode 100644 index 0000000..57e1087 --- /dev/null +++ b/src/modules/overseas-warehouse/utils/returnReceiptDisplay.ts @@ -0,0 +1,21 @@ +import type { ReturnReceipt } from '../api/returnOrders' + +export function receiptTrackingNo(receipt: Pick | Record) { + const trackingNo = typeof receipt.trackingNo === 'string' ? receipt.trackingNo.trim() : '' + if (trackingNo) return trackingNo + const code = typeof receipt.unitCode === 'string' ? receipt.unitCode.trim() : '' + return receipt.unitType === 'PARCEL' && code && !/^PK[0-9A-F]{16}$/.test(code) ? code : '' +} + +export function formatReturnVolume(value?: number | null) { + if (value == null || !Number.isFinite(value) || value < 0) return '—' + // Shift the decimal in text to avoid floating-point over-rounding exact thousandths. + const [coefficient, exponent = '0'] = String(value).toLowerCase().split('e') + const [integer, fraction = ''] = coefficient!.split('.') + const digits = integer! + fraction + const cutoff = integer!.length + Number(exponent) + 3 + const scaled = cutoff <= 0 ? '0' : digits.slice(0, cutoff).padEnd(cutoff, '0') + const remainder = cutoff < 0 ? digits : digits.slice(Math.max(0, cutoff)) + const rounded = BigInt(scaled) + (/[1-9]/.test(remainder) ? 1n : 0n) + return `${rounded / 1000n}.${String(rounded % 1000n).padStart(3, '0')}` +} diff --git a/src/modules/overseas-warehouse/views/ReturnOrdersView.vue b/src/modules/overseas-warehouse/views/ReturnOrdersView.vue index a646d48..770fb7e 100644 --- a/src/modules/overseas-warehouse/views/ReturnOrdersView.vue +++ b/src/modules/overseas-warehouse/views/ReturnOrdersView.vue @@ -11,6 +11,7 @@ import { getMerchantWarehouses, type MerchantWarehouse } from '@/modules/first-l import { createIdempotencyKey } from '@/utils/idempotencyKey' import { createReturnOrder, downloadReturnPhoto, getReturnOrder, listReturnOrders, updateReturnOrder, type ReturnOrderDetail, type ReturnOrderSummary, type ReturnReceipt } from '../api/returnOrders' import { getReturnInventoryLabel } from '../api/returnInventory' +import { formatReturnVolume, receiptTrackingNo } from '../utils/returnReceiptDisplay' const props = withDefaults(defineProps<{ createPage?: boolean; detailPage?: boolean; returnNo?: string }>(), { createPage: false, detailPage: false, returnNo: '' }) const router = useRouter() @@ -67,7 +68,7 @@ const receiptColumns: DataTableColumn[] = [ { prop: 'receiptBatchNo', label: '批次号', minWidth: 145 }, { prop: 'receiptNo', label: '签收单号', minWidth: 145 }, { key: 'unitType', label: '实物类型', slotName: 'unitType', width: 90 }, - { prop: 'unitCode', label: '实物编码', minWidth: 160 }, + { key: 'unitCode', label: '实物编码', slotName: 'unitCode', minWidth: 160 }, { key: 'trackingNo', label: '快递单号', slotName: 'trackingNo', minWidth: 140 }, { key: 'startedBy', label: '开始方式', slotName: 'startedBy', width: 100 }, { prop: 'receivedQuantity', label: '实收', width: 80 }, @@ -389,7 +390,7 @@ onBeforeUnmount(clearPhotoUrls)

实物明细({{ selected.pallets?.length || 0 }} 个托盘/箱)打印全部箱唛({{ printableBoxCount }} 箱)

- +
长 {{ pallet.length ?? '—' }} cm · 宽 {{ pallet.width ?? '—' }} cm · 高 {{ pallet.height ?? '—' }} cm · 重量 {{ pallet.weight ?? '—' }} kg
@@ -437,7 +438,8 @@ onBeforeUnmount(clearPhotoUrls)

签收批次

- + +