执行中的运输计划不再随意改单;库存流水记到装卸产品明细;手工派车日历区分酸碱并记录数量。同时收紧合同附件与子表的差量保存,并清理已废弃的 bak 备份目录。 Co-authored-by: Cursor <cursoragent@cursor.com>
77 lines
2.9 KiB
TypeScript
77 lines
2.9 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import test from 'node:test'
|
|
import { parse } from '@vue/compiler-sfc'
|
|
import ts from 'typescript'
|
|
|
|
const source = readFileSync(new URL('../src/utils/crm-attachment.ts', import.meta.url), 'utf8')
|
|
const ast = ts.createSourceFile('attachments.ts', source, ts.ScriptTarget.Latest, true)
|
|
const names = [
|
|
'parseCrmAttachmentField',
|
|
'crmAttachmentDisplayName',
|
|
'buildUploadFileListFromField',
|
|
'serializeContractAttachments',
|
|
'mapContractAttachmentsPayload',
|
|
'getCrmAttachmentCategoryLabel',
|
|
'CRM_ATTACHMENT_CATEGORY_LABELS'
|
|
]
|
|
const selected = ast.statements.filter((node) =>
|
|
ts.isFunctionDeclaration(node)
|
|
? names.includes(node.name?.text || '')
|
|
: ts.isVariableStatement(node) &&
|
|
names.includes(node.declarationList.declarations[0].name.getText(ast))
|
|
)
|
|
const exports: any = {}
|
|
new Function(
|
|
'exports',
|
|
ts.transpile(selected.map((node) => node.getText(ast)).join('\n'), {
|
|
module: ts.ModuleKind.CommonJS
|
|
})
|
|
)(exports)
|
|
|
|
test('an empty attachment list is an explicit empty array so save can clear stored files', () => {
|
|
assert.equal(exports.serializeContractAttachments([]), '[]')
|
|
assert.deepEqual(exports.mapContractAttachmentsPayload([]), [])
|
|
})
|
|
|
|
test('scan attachments display their Chinese category and retain the code when edited and saved', () => {
|
|
const payload = [{ ossId: '/contract/scan.png', category: 'scan' }]
|
|
const files = exports.buildUploadFileListFromField(JSON.stringify(payload))
|
|
assert.equal(files[0].category, 'scan')
|
|
assert.equal(exports.getCrmAttachmentCategoryLabel(files[0].category), '扫描件')
|
|
assert.deepEqual(JSON.parse(exports.serializeContractAttachments(files)), payload)
|
|
assert.deepEqual(exports.mapContractAttachmentsPayload(files), payload)
|
|
for (const [category, label] of [
|
|
['single_seal', '单章附件'],
|
|
['double_seal', '双章附件'],
|
|
['other', '其他附件']
|
|
]) {
|
|
assert.equal(exports.getCrmAttachmentCategoryLabel(category), label)
|
|
}
|
|
})
|
|
|
|
test('both mobile and desktop attachment selects resolve the scan code to Chinese', () => {
|
|
const template = parse(
|
|
readFileSync(
|
|
new URL('../src/views/crm/contract/components/ContractAttachmentPanel.vue', import.meta.url),
|
|
'utf8'
|
|
)
|
|
).descriptor.template!
|
|
const selects: any[] = []
|
|
function walk(node: any) {
|
|
if (node.tag === 'el-select') selects.push(node)
|
|
node.children?.forEach(walk)
|
|
}
|
|
walk(template.ast)
|
|
assert.equal(selects.length, 2)
|
|
for (const select of selects) {
|
|
const option = select.children.find(
|
|
(node: any) =>
|
|
node.tag === 'el-option' &&
|
|
node.props.some((p: any) => p.name === 'value' && p.value?.content === 'scan')
|
|
)
|
|
assert.ok(option, 'existing scan attachments must have a matching select option')
|
|
assert.equal(option.props.find((p: any) => p.name === 'label').value.content, '扫描件')
|
|
}
|
|
})
|