feat: add per-row load and delivery qty helpers for plan list

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
wuzilongandCursor committed 2026-10-06 09:36:26 +08:00
1 parent 47cd09d1e5
commit c19318d0d0
2 files changed
+96

No files matched your search

@@ -5,6 +5,9 @@ import {
buildPlPlanListSpanMethod,
flattenPlanArchivePairRows,
flattenPlanListRows,
formatDashNumber,
getRowSideIoQty,
getRowSidePlanQty,
matchLoadProduct,
PL_DELIVERY_SPAN_PROPS,
PL_PLAN_SPAN_PROPS
@@ -189,3 +192,64 @@ describe('buildPlPlanListSpanMethod two-level', () => {
)
})
})
describe('row side qty helpers', () => {
it('reads load and delivery qtys from matched products', () => {
const rows = flattenPlanArchivePairRows([samplePlan()])
assert.equal(getRowSidePlanQty(rows[0], 'load'), 30)
assert.equal(getRowSidePlanQty(rows[0], 'delivery'), 20)
assert.equal(getRowSidePlanQty(rows[1], 'load'), 10)
assert.equal(getRowSidePlanQty(rows[1], 'delivery'), 8)
assert.equal(getRowSidePlanQty(rows[2], 'load'), 30)
assert.equal(getRowSidePlanQty(rows[2], 'delivery'), 12)
})
it('returns null and dash when qty is missing', () => {
const rows = flattenPlanArchivePairRows([samplePlan()])
const empty = { ...rows[0], loadProduct: undefined, deliveryProduct: undefined }
assert.equal(getRowSidePlanQty(empty, 'load'), null)
assert.equal(formatDashNumber(null), '—')
assert.equal(formatDashNumber(12), '12')
})
it('maps IO qty by internal customer direction', () => {
const plan = samplePlan()
plan.load = {
...plan.load,
customerName: '安徽云栋化工有限公司',
products: [
sp({
planProductId: 'pp-u',
productId: 'u',
productName: '尿素',
planQty: 30,
inboundQty: 1,
outboundQty: 28
})
]
}
plan.deliveries = [
{
seq: 1,
customerName: '宜昌磷肥厂',
products: [
sp({
planProductId: 'pp-u',
productId: 'u',
productName: '尿素',
planQty: 20,
inboundQty: 2,
outboundQty: 19
})
]
}
] as Plan['deliveries']
const rows = flattenPlanArchivePairRows([plan])
// 装货内部客户 → 出库列展示;数量仍读装货段 inboundQty
assert.equal(getRowSideIoQty(rows[0], 'load', 'outbound'), 1)
assert.equal(getRowSideIoQty(rows[0], 'load', 'inbound'), null)
// 送货外部客户 → 出库列展示;数量读送货段 outboundQty
assert.equal(getRowSideIoQty(rows[0], 'delivery', 'outbound'), 19)
assert.equal(getRowSideIoQty(rows[0], 'delivery', 'inbound'), null)
})
})
@@ -602,6 +602,38 @@ export function resolveArchiveListIoColumn(
return internal ? 'inbound' : 'outbound'
}
/** 列表行:读取装货/送货侧计划数量(单件) */
export function getRowSidePlanQty(
row: PlPlanListDisplayRow,
side: 'load' | 'delivery'
): number | null {
const product = side === 'load' ? row.loadProduct : row.deliveryProduct
if (product?.planQty == null || product.planQty === ('' as unknown)) return null
const num = Number(product.planQty)
return Number.isFinite(num) ? num : null
}
export function formatDashNumber(value: number | null | undefined): string {
if (value == null) return '—'
return String(value)
}
/**
* 列表行:按装/送侧与入出库列读取数量。
* 列是否展示由 resolveArchiveListIoColumn 决定;数值仍走 getStopArchiveActualQty。
*/
export function getRowSideIoQty(
row: PlPlanListDisplayRow,
side: 'load' | 'delivery',
column: 'inbound' | 'outbound'
): number | null {
const stop = side === 'load' ? getPairLoadStop(row) : getPairDeliveryStop(row)
const product = side === 'load' ? row.loadProduct : row.deliveryProduct
if (!product) return null
if (resolveArchiveListIoColumn(side, stop?.customerName) !== column) return null
return getStopArchiveActualQty(product, side)
}
/** 段次归档实际数量(装货读 inboundQty,送货读 outboundQty) */
export function getStopArchiveActualQty(product: PlanStopProduct, kind: PlPlanListDisplayRowKind): number | null {
const raw = kind === 'load' ? product.inboundQty : product.outboundQty