ソースを参照

feat(web-admin): add mp CRM contract card query helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
wuzilong 2 週間 前
親
コミット
b5b3b1f327

+ 116 - 0
web-admin/src/utils/mp-crm-contract-card.test.ts

@@ -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), '—')
+  })
+})

+ 77 - 0
web-admin/src/utils/mp-crm-contract-card.ts

@@ -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 || '—'
+  }
+}