test: map finance supplier category from fee type
This commit is contained in:
@@ -31,13 +31,15 @@ test('fee writes use verified Firstleg paths and do not fabricate historical IDs
|
|||||||
assert.match(source, /chargeUnit === 'CBM'/)
|
assert.match(source, /chargeUnit === 'CBM'/)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('PAYABLE fee selection requires the formal flag and a Finance-supported supplier category', () => {
|
test('PAYABLE fee selection uses the formal feeCode and feeTypeName fields', () => {
|
||||||
const selector = source.slice(source.indexOf('async function loadFeeItem'), source.indexOf('async function createManualFee'))
|
const selector = source.slice(source.indexOf('async function loadFeeItem'), source.indexOf('async function createManualFee'))
|
||||||
assert.match(selector, /item\.warehousePayable === true/)
|
assert.match(selector, /item\.warehousePayable === true/)
|
||||||
assert.match(selector, /supplierCategoryForFeeItem\(item\)/)
|
assert.match(selector, /supplierCategoryForFeeItem\(item\)/)
|
||||||
assert.equal(supplierCategoryForFeeItem({ feeCode: 'FBA_HEAD_FREIGHT', feeName: '头程运费' }), 'BOOKING')
|
assert.equal(supplierCategoryForFeeItem({ feeCode: 'FBA_HEAD_FREIGHT', feeTypeName: '头程运费' }), 'BOOKING')
|
||||||
assert.equal(supplierCategoryForFeeItem({ code: 'CUSTOMS_CLEARANCE', name: '报关费' }), 'CUSTOMS')
|
assert.equal(supplierCategoryForFeeItem({ feeCode: 'FEE_TYPE_001', feeTypeName: '拖车费2' }), 'TRUCKING')
|
||||||
assert.equal(supplierCategoryForFeeItem({ feeCode: 'UNSUPPORTED', feeName: '操作费' }), null)
|
assert.equal(supplierCategoryForFeeItem({ feeCode: 'CUSTOMS_CLEARANCE', feeTypeName: '报关费' }), 'CUSTOMS')
|
||||||
|
assert.equal(supplierCategoryForFeeItem({ feeCode: 'UNSUPPORTED', feeTypeName: '操作费' }), null)
|
||||||
|
assert.equal(supplierCategoryForFeeItem({ feeCode: 'FEE_TYPE_001', feeName: '拖车费2' }), null)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Finance PAYABLE fixture creates an isolated ACTIVE supplier through the formal API', () => {
|
test('Finance PAYABLE fixture creates an isolated ACTIVE supplier through the formal API', () => {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function normalizeFinanceFixtureSources(sources, orders, allocations, cus
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function supplierCategoryForFeeItem(item) {
|
export function supplierCategoryForFeeItem(item) {
|
||||||
const value = `${item?.feeCode ?? item?.code ?? ''} ${item?.feeName ?? item?.name ?? ''}`.toUpperCase()
|
const value = `${item?.feeCode ?? ''} ${item?.feeTypeName ?? ''}`.toUpperCase()
|
||||||
if (['TRUCK', 'TRAILER', 'DRAYAGE', '拖车', '卡车'].some((candidate) => value.includes(candidate))) return 'TRUCKING'
|
if (['TRUCK', 'TRAILER', 'DRAYAGE', '拖车', '卡车'].some((candidate) => value.includes(candidate))) return 'TRUCKING'
|
||||||
if (['CUSTOMS', 'CLEARANCE', 'DECLARATION', '报关', '清关'].some((candidate) => value.includes(candidate))) return 'CUSTOMS'
|
if (['CUSTOMS', 'CLEARANCE', 'DECLARATION', '报关', '清关'].some((candidate) => value.includes(candidate))) return 'CUSTOMS'
|
||||||
if (['CERTIFICATE', 'CERTIFICATION', 'CERT_', '认证', '证书'].some((candidate) => value.includes(candidate))) return 'CERTIFICATE'
|
if (['CERTIFICATE', 'CERTIFICATION', 'CERT_', '认证', '证书'].some((candidate) => value.includes(candidate))) return 'CERTIFICATE'
|
||||||
@@ -406,7 +406,7 @@ export async function run(context) {
|
|||||||
const payableSupplierCategory = supplierCategoryForFeeItem(feeItems.PAYABLE)
|
const payableSupplierCategory = supplierCategoryForFeeItem(feeItems.PAYABLE)
|
||||||
const supplier = await loadSupplier(context, payableSupplierCategory)
|
const supplier = await loadSupplier(context, payableSupplierCategory)
|
||||||
if (!supplier?.id) blocker(context, '取得 Warehouse PAYABLE 供应商',
|
if (!supplier?.id) blocker(context, '取得 Warehouse PAYABLE 供应商',
|
||||||
`未找到 ACTIVE ${payableSupplierCategory || 'SUPPORTED'} 供应商或匹配正式类别的 PAYABLE 费用项;不能伪造 supplierId/partnerId`)
|
`未找到 ACTIVE ${payableSupplierCategory || 'SUPPORTED'} 供应商或 feeCode + feeTypeName 无法映射正式类别的 PAYABLE 费用项;不能伪造 supplierId/partnerId`)
|
||||||
for (const direction of ['RECEIVABLE', 'PAYABLE']) {
|
for (const direction of ['RECEIVABLE', 'PAYABLE']) {
|
||||||
if (!feeItems[direction]) context.addCoverageGap(MODULE, `missing-${direction.toLowerCase()}-fee-item`, `${direction} 人工费用 fixture`,
|
if (!feeItems[direction]) context.addCoverageGap(MODULE, `missing-${direction.toLowerCase()}-fee-item`, `${direction} 人工费用 fixture`,
|
||||||
`没有找到带 warehouse${direction === 'RECEIVABLE' ? 'Receivable' : 'Payable'}=true 的 ACTIVE 费用项目,禁止猜测费用项目 ID`, 'missing-deployed-fee-item')
|
`没有找到带 warehouse${direction === 'RECEIVABLE' ? 'Receivable' : 'Payable'}=true 的 ACTIVE 费用项目,禁止猜测费用项目 ID`, 'missing-deployed-fee-item')
|
||||||
@@ -465,11 +465,14 @@ export async function run(context) {
|
|||||||
supplierName: supplier?.name || null, supplierCategory: supplier?.category || payableSupplierCategory,
|
supplierName: supplier?.name || null, supplierCategory: supplier?.category || payableSupplierCategory,
|
||||||
containerBookingId: id(container.containerBookingId), containerNo: container.containerNo || null,
|
containerBookingId: id(container.containerBookingId), containerNo: container.containerNo || null,
|
||||||
loadingPlanId: id(container.loadingPlanId) }
|
loadingPlanId: id(container.loadingPlanId) }
|
||||||
} else {
|
} else if (!containerOwned) {
|
||||||
context.addStep(MODULE, '取得同 marker 柜次用于整柜费用分摊', null, false,
|
context.addStep(MODULE, '取得同 marker 柜次用于整柜费用分摊', null, false,
|
||||||
'没有同 marker 的已完成柜次和可核验 containerBookingId;不读取历史柜次、不猜测柜号', OPTIONS)
|
'没有同 marker 的已完成柜次和可核验 containerBookingId;不读取历史柜次、不猜测柜号', OPTIONS)
|
||||||
context.addCoverageGap(MODULE, 'container-shared-cost-allocation', '按柜添加费用并按订单/运单体积分摊',
|
context.addCoverageGap(MODULE, 'container-shared-cost-allocation', '按柜添加费用并按订单/运单体积分摊',
|
||||||
'当前上下文没有同 marker 的已完成柜次及真实 Firstleg 体积快照,禁止借用历史柜次或模拟 Finance 分摊成功', 'no-marker-owned-container-snapshot')
|
'当前上下文没有同 marker 的已完成柜次及真实 Firstleg 体积快照,禁止借用历史柜次或模拟 Finance 分摊成功', 'no-marker-owned-container-snapshot')
|
||||||
|
} else {
|
||||||
|
context.addCoverageGap(MODULE, 'container-shared-cost-allocation', '按柜添加费用并按订单/运单体积分摊',
|
||||||
|
'已识别同 marker 的 COMPLETED 柜次,但 PAYABLE 费用项目无法按 feeCode + feeTypeName 映射类别或缺少 ACTIVE 供应商', 'missing-payable-supplier')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (containerFixture) fixtures.push(containerFixture)
|
if (containerFixture) fixtures.push(containerFixture)
|
||||||
|
|||||||
Reference in New Issue
Block a user