feat(web-admin): add receive account snapshot value helpers.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
947e6ae6f8
commit
d946b91dd1
2 files changed
+187
No files matched your search
@@ -0,0 +1,68 @@
|
||||
import { describe, it } from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import {
|
||||
ACCOUNT_TYPE_LABEL,
|
||||
formatReceiveAccountDisplay,
|
||||
formatReceiveAccountLine,
|
||||
isReceiveAccountSnapshot,
|
||||
normalizeReceiveAccountModelValue,
|
||||
type ReceiveAccountSnapshot
|
||||
} from './oa-receive-account-value'
|
||||
|
||||
const alipay: ReceiveAccountSnapshot = {
|
||||
id: '1',
|
||||
accountType: 'alipay',
|
||||
accountName: '张三',
|
||||
accountNo: '13800138000',
|
||||
bankName: '',
|
||||
bankProvince: '',
|
||||
bankCity: '',
|
||||
bankBranch: '',
|
||||
remark: '日常'
|
||||
}
|
||||
|
||||
const personal: ReceiveAccountSnapshot = {
|
||||
id: '2',
|
||||
accountType: 'personal',
|
||||
accountName: '李四',
|
||||
accountNo: '6222',
|
||||
bankName: '工行',
|
||||
bankProvince: '安徽省',
|
||||
bankCity: '合肥市',
|
||||
bankBranch: '长江中路支行',
|
||||
remark: ''
|
||||
}
|
||||
|
||||
describe('oa-receive-account-value', () => {
|
||||
it('type labels', () => {
|
||||
assert.equal(ACCOUNT_TYPE_LABEL.alipay, '支付宝')
|
||||
assert.equal(ACCOUNT_TYPE_LABEL.personal, '个人银行卡')
|
||||
assert.equal(ACCOUNT_TYPE_LABEL.corporate, '对公银行账户')
|
||||
})
|
||||
it('isReceiveAccountSnapshot', () => {
|
||||
assert.equal(isReceiveAccountSnapshot(alipay), true)
|
||||
assert.equal(isReceiveAccountSnapshot({ id: '1' }), false)
|
||||
})
|
||||
it('normalize always array', () => {
|
||||
assert.deepEqual(normalizeReceiveAccountModelValue(null), [])
|
||||
assert.deepEqual(normalizeReceiveAccountModelValue(alipay), [alipay])
|
||||
assert.deepEqual(normalizeReceiveAccountModelValue([alipay, personal]), [alipay, personal])
|
||||
})
|
||||
it('format line alipay omits bank', () => {
|
||||
const line = formatReceiveAccountLine(alipay)
|
||||
assert.ok(line.includes('支付宝'))
|
||||
assert.ok(line.includes('张三'))
|
||||
assert.ok(!line.includes('工行'))
|
||||
assert.ok(line.includes('日常'))
|
||||
})
|
||||
it('format line personal full', () => {
|
||||
const line = formatReceiveAccountLine(personal)
|
||||
assert.ok(line.includes('个人银行卡'))
|
||||
assert.ok(line.includes('安徽省 / 合肥市'))
|
||||
assert.ok(line.includes('长江中路支行'))
|
||||
})
|
||||
it('format display multiline', () => {
|
||||
const text = formatReceiveAccountDisplay([alipay, personal])
|
||||
assert.ok(text.includes('\n'))
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,119 @@
|
||||
export type ReceiveAccountType = 'alipay' | 'personal' | 'corporate'
|
||||
|
||||
export type ReceiveAccountSnapshot = {
|
||||
id: string
|
||||
accountType: ReceiveAccountType
|
||||
accountName: string
|
||||
accountNo: string
|
||||
bankName: string
|
||||
bankProvince: string
|
||||
bankCity: string
|
||||
bankBranch: string
|
||||
remark: string
|
||||
}
|
||||
|
||||
export const ACCOUNT_TYPE_LABEL: Record<ReceiveAccountType, string> = {
|
||||
alipay: '支付宝',
|
||||
personal: '个人银行卡',
|
||||
corporate: '对公银行账户'
|
||||
}
|
||||
|
||||
const SNAPSHOT_FIELDS: (keyof ReceiveAccountSnapshot)[] = [
|
||||
'id',
|
||||
'accountType',
|
||||
'accountName',
|
||||
'accountNo',
|
||||
'bankName',
|
||||
'bankProvince',
|
||||
'bankCity',
|
||||
'bankBranch',
|
||||
'remark'
|
||||
]
|
||||
|
||||
function isReceiveAccountType(v: unknown): v is ReceiveAccountType {
|
||||
return v === 'alipay' || v === 'personal' || v === 'corporate'
|
||||
}
|
||||
|
||||
export function isReceiveAccountSnapshot(v: unknown): v is ReceiveAccountSnapshot {
|
||||
if (!v || typeof v !== 'object') return false
|
||||
const o = v as Record<string, unknown>
|
||||
if (!isReceiveAccountType(o.accountType)) return false
|
||||
for (const key of SNAPSHOT_FIELDS) {
|
||||
if (typeof o[key] !== 'string') return false
|
||||
}
|
||||
return String(o.id || '').trim() !== ''
|
||||
}
|
||||
|
||||
function trimSnapshot(v: ReceiveAccountSnapshot): ReceiveAccountSnapshot {
|
||||
return {
|
||||
id: String(v.id).trim(),
|
||||
accountType: v.accountType,
|
||||
accountName: String(v.accountName).trim(),
|
||||
accountNo: String(v.accountNo).trim(),
|
||||
bankName: String(v.bankName).trim(),
|
||||
bankProvince: String(v.bankProvince).trim(),
|
||||
bankCity: String(v.bankCity).trim(),
|
||||
bankBranch: String(v.bankBranch).trim(),
|
||||
remark: String(v.remark).trim()
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeReceiveAccountModelValue(
|
||||
raw: unknown
|
||||
): ReceiveAccountSnapshot[] {
|
||||
if (Array.isArray(raw)) {
|
||||
return raw.filter(isReceiveAccountSnapshot).map(trimSnapshot)
|
||||
}
|
||||
if (isReceiveAccountSnapshot(raw)) {
|
||||
return [trimSnapshot(raw)]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
export function formatReceiveAccountLine(item: ReceiveAccountSnapshot): string {
|
||||
const parts: string[] = [
|
||||
ACCOUNT_TYPE_LABEL[item.accountType],
|
||||
item.accountName,
|
||||
item.accountNo
|
||||
]
|
||||
if (item.accountType === 'personal' || item.accountType === 'corporate') {
|
||||
if (item.bankName) parts.push(item.bankName)
|
||||
if (item.bankProvince || item.bankCity) {
|
||||
parts.push(`${item.bankProvince} / ${item.bankCity}`)
|
||||
}
|
||||
if (item.bankBranch) parts.push(item.bankBranch)
|
||||
}
|
||||
if (item.remark) parts.push(item.remark)
|
||||
return parts.filter(Boolean).join(' · ')
|
||||
}
|
||||
|
||||
export function formatReceiveAccountDisplay(raw: unknown): string {
|
||||
return normalizeReceiveAccountModelValue(raw)
|
||||
.map(formatReceiveAccountLine)
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
export function optionLabelFromRow(row: ReceiveAccountSnapshot): string {
|
||||
return [
|
||||
ACCOUNT_TYPE_LABEL[row.accountType],
|
||||
row.accountName,
|
||||
row.accountNo
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' · ')
|
||||
}
|
||||
|
||||
export function snapshotFromRow(row: any): ReceiveAccountSnapshot {
|
||||
const accountType = row?.accountType
|
||||
return {
|
||||
id: String(row?.id ?? '').trim(),
|
||||
accountType: isReceiveAccountType(accountType) ? accountType : 'personal',
|
||||
accountName: String(row?.accountName ?? '').trim(),
|
||||
accountNo: String(row?.accountNo ?? '').trim(),
|
||||
bankName: String(row?.bankName ?? '').trim(),
|
||||
bankProvince: String(row?.bankProvince ?? '').trim(),
|
||||
bankCity: String(row?.bankCity ?? '').trim(),
|
||||
bankBranch: String(row?.bankBranch ?? '').trim(),
|
||||
remark: String(row?.remark ?? '').trim()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user