feat(web-admin): per-sample payment UI and refund registration on protocol form
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
a328b9ff2d
commit
4e71a13165
5 files changed
+1280
-19
No files matched your search
@@ -0,0 +1,73 @@
|
||||
/** 按样本缴费 · 工具函数(payment_model_version=2) */
|
||||
|
||||
export type SamplePaymentLike = {
|
||||
contractAmount?: number | null
|
||||
sampleCode?: string
|
||||
payMode?: string
|
||||
schedules?: ScheduleLike[]
|
||||
}
|
||||
|
||||
export type TransferLike = {
|
||||
payStatus?: string
|
||||
transferAmount?: number | null
|
||||
}
|
||||
|
||||
export type ScheduleLike = {
|
||||
dueAmount?: number | null
|
||||
transfers?: TransferLike[]
|
||||
}
|
||||
|
||||
export function sumSampleContractAmounts(payments: SamplePaymentLike[]): number {
|
||||
return payments.reduce((s, p) => s + (Number(p.contractAmount) || 0), 0)
|
||||
}
|
||||
|
||||
export function protocolTotalMismatchHint(
|
||||
total: number | null | undefined,
|
||||
sampleSum: number
|
||||
): string | null {
|
||||
if (total == null || Number.isNaN(Number(total))) return null
|
||||
if (Math.abs(Number(total) - sampleSum) > 0.015) {
|
||||
return `协议总金额 ${Number(total).toFixed(2)} 与样本合同合计 ${sampleSum.toFixed(2)} 不一致,请核对`
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function schedulePaidArrears(
|
||||
dueAmount: number,
|
||||
transfers: TransferLike[]
|
||||
): { paid: number; arrears: number } {
|
||||
const paid = (transfers || [])
|
||||
.filter((t) => t.payStatus === 'yjf')
|
||||
.reduce((s, t) => s + (Number(t.transferAmount) || 0), 0)
|
||||
return { paid, arrears: Math.round((dueAmount - paid) * 100) / 100 }
|
||||
}
|
||||
|
||||
/** 单样本默认定价:沿用原「1 个样本」价目 */
|
||||
export function resolvePerSamplePreset(payMode: 'dj' | 'fq'): {
|
||||
contractAmount: number
|
||||
installmentCount?: number
|
||||
installmentAmounts?: number[]
|
||||
} | null {
|
||||
if (payMode === 'dj') return { contractAmount: 22880 }
|
||||
if (payMode === 'fq') {
|
||||
return {
|
||||
contractAmount: 25880,
|
||||
installmentCount: 6,
|
||||
installmentAmounts: [6480, 3880, 3880, 3880, 3880, 3880]
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function parseInstallmentRatios(raw: unknown): number[] {
|
||||
if (Array.isArray(raw)) return raw.map((v) => Number(v) || 0)
|
||||
if (typeof raw === 'string' && raw.trim()) {
|
||||
try {
|
||||
const parsed = JSON.parse(raw)
|
||||
if (Array.isArray(parsed)) return parsed.map((v) => Number(v) || 0)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
return []
|
||||
}
|
||||
Reference in new issue
Block a user