补齐证书齐备、证件折算、移动用证和合同绑定,并带上报销批量发放、付款备注以及个人开发流程升级,便于继续讨论已安排计划的调整规则。 Co-authored-by: Cursor <cursoragent@cursor.com>
91 lines
3.5 KiB
TypeScript
91 lines
3.5 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
import {
|
|
addDraftProducts,
|
|
canRestoreProduct,
|
|
canSaveNewLink,
|
|
canSaveProductEdit,
|
|
certChoiceLabel,
|
|
certChoiceState,
|
|
removeDraftProduct
|
|
} from '../src/views/m/pl/plan-cert/cert-link-rules'
|
|
import { replaceCertProducts } from '../src/views/pl/quota-cert/model'
|
|
|
|
const saved = { id: 'scope-1', contractProductId: 'line-1', scopeStatus: 'active' as const }
|
|
const other = { id: 'scope-2', contractProductId: 'line-2', scopeStatus: 'inactive' as const }
|
|
|
|
test('void and already linked certificates cannot be newly selected', () => {
|
|
const taken = new Set(['purchase:linked'])
|
|
assert.equal(certChoiceState({ id: 'voided', status: 'void' }, 'purchase', taken), 'void')
|
|
assert.equal(certChoiceState({ id: 'closed', status: 'closed' }, 'purchase', taken), 'closed')
|
|
assert.equal(
|
|
certChoiceLabel({ id: 'closed', status: 'closed', certNo: 'G1' }, 'purchase', taken),
|
|
'G1(已核销)'
|
|
)
|
|
assert.equal(certChoiceState({ id: 'linked', status: 'active' }, 'purchase', taken), 'taken')
|
|
assert.equal(certChoiceState({ id: 'free', status: 'active' }, 'purchase', taken), 'open')
|
|
assert.match(certChoiceLabel({ id: 'voided', status: 'void', certNo: 'G1' }, 'purchase', taken), /已作废/)
|
|
assert.match(certChoiceLabel({ id: 'linked', status: 'active', certNo: 'G2' }, 'purchase', taken), /已关联/)
|
|
})
|
|
|
|
test('a new link needs one available product and an edit saves only after the scope changes', () => {
|
|
assert.equal(canSaveNewLink([]), false)
|
|
assert.equal(canSaveNewLink([{ contractProductId: 'line-1', scopeStatus: 'inactive' }]), false)
|
|
assert.equal(canSaveNewLink([{ contractProductId: 'line-1', scopeStatus: 'active' }]), true)
|
|
assert.equal(canSaveProductEdit([saved], [saved]), false)
|
|
assert.equal(
|
|
canSaveProductEdit([saved], [{ ...saved, scopeStatus: 'inactive' }]),
|
|
true
|
|
)
|
|
})
|
|
|
|
test('saved products stay in the set and only change availability', () => {
|
|
assert.equal(canRestoreProduct('void', 'inactive'), false)
|
|
assert.equal(canRestoreProduct('void', 'active'), true)
|
|
assert.equal(canRestoreProduct('active', 'inactive'), true)
|
|
const removed = removeDraftProduct([saved, { contractProductId: 'draft', scopeStatus: 'active' }], 'line-1')
|
|
assert.deepEqual(
|
|
removed.map((product) => product.contractProductId),
|
|
['line-1', 'draft']
|
|
)
|
|
assert.deepEqual(
|
|
removeDraftProduct(removed, 'draft').map((product) => product.contractProductId),
|
|
['line-1']
|
|
)
|
|
const added = addDraftProducts([saved], ['line-1', 'line-3'])
|
|
assert.deepEqual(
|
|
added.map((product) => product.contractProductId),
|
|
['line-1', 'line-3']
|
|
)
|
|
assert.equal(added[0].id, 'scope-1')
|
|
})
|
|
|
|
test('replacing one certificate keeps the other certificate and the product id', () => {
|
|
const bindings = [
|
|
{
|
|
id: 'link-1',
|
|
certType: 'purchase' as const,
|
|
certId: 'cert-1',
|
|
linkStatus: 'active' as const,
|
|
products: [saved, other]
|
|
},
|
|
{
|
|
id: 'link-2',
|
|
certType: 'transport' as const,
|
|
certId: 'cert-2',
|
|
linkStatus: 'active' as const,
|
|
products: [{ id: 'scope-3', contractProductId: 'line-9', scopeStatus: 'active' as const }]
|
|
}
|
|
]
|
|
const next = replaceCertProducts(bindings, 'purchase', 'cert-1', [
|
|
{ ...saved, scopeStatus: 'inactive' },
|
|
other
|
|
])
|
|
assert.equal(next.length, 2)
|
|
assert.equal(next[0].id, 'link-2')
|
|
assert.equal(next[1].id, 'link-1')
|
|
assert.equal(next[1].products[0].id, 'scope-1')
|
|
assert.equal(next[1].products[0].scopeStatus, 'inactive')
|
|
assert.equal(next[1].products[1].contractProductId, 'line-2')
|
|
})
|