feat(web-admin): add mp CRM contract card query helpers.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
8a57bbed30
commit
b5b3b1f327
2 files changed
+193
No files matched your search
@@ -0,0 +1,116 @@
|
|||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import { describe, it } from 'node:test'
|
||||||
|
import {
|
||||||
|
MP_CONTRACT_MANAGE_TABS,
|
||||||
|
MP_CONTRACT_APPROVE_TABS,
|
||||||
|
buildContractListQuery,
|
||||||
|
buildContractCard,
|
||||||
|
formatContractMoney
|
||||||
|
} from './mp-crm-contract-card'
|
||||||
|
|
||||||
|
describe('tabs', () => {
|
||||||
|
it('manage all/approving/approved; approve submitted/approved', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
MP_CONTRACT_MANAGE_TABS.map((x) => x.value),
|
||||||
|
['all', 'approving', 'approved']
|
||||||
|
)
|
||||||
|
assert.deepEqual(
|
||||||
|
MP_CONTRACT_APPROVE_TABS.map((x) => x.value),
|
||||||
|
['submitted', 'approved']
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('buildContractListQuery', () => {
|
||||||
|
it('manage all excludes invalid and trims keyword', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
buildContractListQuery({
|
||||||
|
mode: 'manage',
|
||||||
|
view: 'all',
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
keyword: ' 合同 ',
|
||||||
|
currentUserId: 'u1'
|
||||||
|
}),
|
||||||
|
{ pageNum: 1, pageSize: 20, keyword: '合同', excludeStatus: 'invalid' }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('manage approving sets status only', () => {
|
||||||
|
const q = buildContractListQuery({
|
||||||
|
mode: 'manage',
|
||||||
|
view: 'approving',
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
keyword: '',
|
||||||
|
currentUserId: 'u1'
|
||||||
|
})
|
||||||
|
assert.equal(q.status, 'approving')
|
||||||
|
assert.equal('pendingApprovalUserId' in q, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('manage approved sets status approved', () => {
|
||||||
|
const q = buildContractListQuery({
|
||||||
|
mode: 'manage',
|
||||||
|
view: 'approved',
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
keyword: '',
|
||||||
|
currentUserId: 'u1'
|
||||||
|
})
|
||||||
|
assert.equal(q.status, 'approved')
|
||||||
|
assert.equal('approvedByUserId' in q, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('approve submitted uses pendingApprovalUserId', () => {
|
||||||
|
const q = buildContractListQuery({
|
||||||
|
mode: 'approve',
|
||||||
|
view: 'submitted',
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
keyword: '',
|
||||||
|
currentUserId: 'u9'
|
||||||
|
})
|
||||||
|
assert.equal(q.pendingApprovalUserId, 'u9')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('approve approved uses approvedByUserId', () => {
|
||||||
|
const q = buildContractListQuery({
|
||||||
|
mode: 'approve',
|
||||||
|
view: 'approved',
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
keyword: 'x',
|
||||||
|
currentUserId: 'u9'
|
||||||
|
})
|
||||||
|
assert.equal(q.approvedByUserId, 'u9')
|
||||||
|
assert.equal(q.keyword, 'x')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('buildContractCard', () => {
|
||||||
|
it('maps fields', () => {
|
||||||
|
const card = buildContractCard({
|
||||||
|
id: 'c1',
|
||||||
|
contractNo: 'HT001',
|
||||||
|
contractTitle: '硫酸销售合同',
|
||||||
|
customerName: '甲公司',
|
||||||
|
amount: 1000,
|
||||||
|
freight: 50,
|
||||||
|
barrelDeposit: 20,
|
||||||
|
status: 'draft',
|
||||||
|
signDate: '2026-10-01'
|
||||||
|
})
|
||||||
|
assert.equal(card.id, 'c1')
|
||||||
|
assert.equal(card.contractNo, 'HT001')
|
||||||
|
assert.equal(card.amountText, '¥1,070.00')
|
||||||
|
assert.equal(card.status, 'draft')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('formatContractMoney', () => {
|
||||||
|
it('formats and handles empty', () => {
|
||||||
|
assert.equal(formatContractMoney(1000), '¥1,000.00')
|
||||||
|
assert.equal(formatContractMoney(undefined), '—')
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
export type MpContractMode = 'manage' | 'approve'
|
||||||
|
export type MpContractManageView = 'all' | 'approving' | 'approved'
|
||||||
|
export type MpContractApproveView = 'submitted' | 'approved'
|
||||||
|
export type MpContractView = MpContractManageView | MpContractApproveView
|
||||||
|
|
||||||
|
export const MP_CONTRACT_MANAGE_TABS: Array<{ value: MpContractManageView; label: string }> = [
|
||||||
|
{ value: 'all', label: '全部' },
|
||||||
|
{ value: 'approving', label: '待审批' },
|
||||||
|
{ value: 'approved', label: '已审批' }
|
||||||
|
]
|
||||||
|
|
||||||
|
export const MP_CONTRACT_APPROVE_TABS: Array<{ value: MpContractApproveView; label: string }> = [
|
||||||
|
{ value: 'submitted', label: '待审批' },
|
||||||
|
{ value: 'approved', label: '已审批' }
|
||||||
|
]
|
||||||
|
|
||||||
|
export function formatContractMoney(amount?: number | null): string {
|
||||||
|
if (amount === undefined || amount === null || Number.isNaN(Number(amount))) return '—'
|
||||||
|
return `¥${Number(amount).toLocaleString('zh-CN', {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2
|
||||||
|
})}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildContractListQuery(input: {
|
||||||
|
mode: MpContractMode
|
||||||
|
view: MpContractView
|
||||||
|
pageNum: number
|
||||||
|
pageSize: number
|
||||||
|
keyword: string
|
||||||
|
currentUserId: string
|
||||||
|
}): Record<string, unknown> {
|
||||||
|
const params: Record<string, unknown> = {
|
||||||
|
pageNum: input.pageNum,
|
||||||
|
pageSize: input.pageSize
|
||||||
|
}
|
||||||
|
const kw = String(input.keyword || '').trim()
|
||||||
|
if (kw) params.keyword = kw
|
||||||
|
|
||||||
|
if (input.mode === 'manage') {
|
||||||
|
if (input.view === 'all') params.excludeStatus = 'invalid'
|
||||||
|
else if (input.view === 'approving') params.status = 'approving'
|
||||||
|
else params.status = 'approved'
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.view === 'submitted') {
|
||||||
|
params.pendingApprovalUserId = input.currentUserId
|
||||||
|
} else {
|
||||||
|
params.approvedByUserId = input.currentUserId
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildContractCard(row: {
|
||||||
|
id: string | number
|
||||||
|
contractNo?: string
|
||||||
|
contractTitle?: string
|
||||||
|
customerName?: string
|
||||||
|
amount?: number
|
||||||
|
freight?: number
|
||||||
|
barrelDeposit?: number
|
||||||
|
status?: string
|
||||||
|
signDate?: string
|
||||||
|
}) {
|
||||||
|
const total =
|
||||||
|
(Number(row.amount) || 0) + (Number(row.freight) || 0) + (Number(row.barrelDeposit) || 0)
|
||||||
|
return {
|
||||||
|
id: String(row.id),
|
||||||
|
contractNo: row.contractNo || '—',
|
||||||
|
contractTitle: row.contractTitle || '—',
|
||||||
|
customerName: row.customerName || '—',
|
||||||
|
amountText: formatContractMoney(total),
|
||||||
|
status: row.status || '',
|
||||||
|
signDate: row.signDate || '—'
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user