import { formatKdrq, buildBillingKdrqRange, billingDateYmd } from '@/utils/billingHelper' export { buildBillingKdrqRange as buildTksjRange } export function formatTksj(date) { const d = date instanceof Date ? date : new Date(date) if (Number.isNaN(d.getTime())) return formatKdrq(new Date()) const pad = n => String(n).padStart(2, '0') return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}` } export function refundDateYmd(form) { return billingDateYmd({ billingDate: form.refundDate }) } export function calcItemRefundAmount(item) { if (!item || !item.projectId) return 0 return (Number(item.price) || 0) * (Number(item.refundCount) || 0) } export function calcFormTkje(form) { return (form.items || []).reduce((s, it) => s + calcItemRefundAmount(it), 0) } export function calcFormSgfy(form) { return (form.items || []).reduce((s, it) => { if (!it || !it.projectId) return s return s + (Number(it.laborCost) || 0) * (Number(it.refundCount) || 0) }, 0) } /** 实际退款 = 各品项健康师业绩之和(对齐小程序) */ export function calcFormActualRefund(form) { let total = 0 ;(form.items || []).forEach(it => { if (!it || !it.projectId) return ;(it.workers || []).forEach(w => { total += Number(w.jksyj) || 0 }) }) return total } export function redistributeRefundWorkers(item) { if (!item.workers || !item.workers.length) return const totalCount = Number(item.refundCount) || 0 const totalPerf = calcItemRefundAmount(item) const totalLabor = (Number(item.laborCost) || 0) * totalCount const n = item.workers.length item.workers.forEach(w => { w.jksyj = n > 0 ? (totalPerf / n).toFixed(2) : '0.00' w.count = n > 0 ? (totalCount / n).toFixed(2) : '0' w.laborCost = n > 0 ? (totalLabor / n).toFixed(2) : '0.00' }) } export function redistributeRefundTechTeachers(item) { if (!item.techTeachers || !item.techTeachers.length) return const totalCount = Number(item.refundCount) || 0 const totalPerf = calcItemRefundAmount(item) const totalLabor = (Number(item.laborCost) || 0) * totalCount const n = item.techTeachers.length item.techTeachers.forEach(t => { t.kjblsyj = n > 0 ? (totalPerf / n).toFixed(2) : '0.00' t.count = n > 0 ? (totalCount / n).toFixed(2) : '0' t.laborCost = n > 0 ? (totalLabor / n).toFixed(2) : '0.00' }) } function mapWorkerToJks(w, item, hwMap) { const name = hwMap.get(w.workerId) || w.workerName || '' return { jks: name, jksxm: name, jkszh: w.workerId, jksyj: Number(w.jksyj) || 0, F_jsjid: w.jsjId || '', F_tkpxid: item.itemId || item.projectId, F_LaborCost: Number(w.laborCost) || 0, F_tkpxNumber: Number(w.count) || 0 } } function mapTechToKjb(t, item, kjbMap) { const name = kjbMap.get(t.teacherId) || t.teacherName || '' return { kjbls: name, kjblsxm: name, kjblszh: t.teacherId, kjblsyj: Number(t.kjblsyj) || 0, F_tkpxid: item.itemId || item.projectId, F_LaborCost: Number(t.laborCost) || 0, F_tkpxNumber: Number(t.count) || 0 } } export function buildRefundSubmitBody(form, { storeId, storeName, member, healthWorkerOptions, kjbWorkerOptions }) { const hwMap = new Map((healthWorkerOptions || []).map(x => [x.value, x.label])) const kjbMap = new Map((kjbWorkerOptions || []).map(x => [x.value, x.label])) const tkje = calcFormTkje(form) const sgfy = calcFormSgfy(form) const actualRefundAmount = calcFormActualRefund(form) const hasKemei = (form.items || []).some(it => it.qt2 === '科美') const lqHytkMxList = (form.items || []) .filter(it => it && it.projectId) .map(it => { const qty = Number(it.refundCount) || 1 const pxjg = Number(it.price) || 0 const lineTkje = pxjg * qty return { billingItemId: it.billingItemId || it.projectId, px: it.itemId || '', pxmc: it.label || '', pxjg, tkje: lineTkje, F_ProjectNumber: qty, F_SourceType: it.sourceType || '', F_TotalPrice: lineTkje, lqHytkJksyjList: (it.workers || []) .filter(w => w && w.workerId) .map(w => mapWorkerToJks(w, it, hwMap)), lqHytkKjbsyjList: (it.techTeachers || []) .filter(t => t && t.teacherId) .map(t => mapTechToKjb(t, it, kjbMap)) } }) const fileList = form.fileList || [] return { md: storeId, mdbh: storeId, mdmc: storeName || '', hy: form.memberId, hyzh: (member && member.phone) || form.memberPhone || '', hymc: (member && member.label) || form.memberName || '', gklx: (member && member.type) || form.memberType || '', tksj: formatTksj(form.refundDate), tkje, sgfy, actualRefundAmount, bz: form.remark || '', fileUrl: JSON.stringify(fileList), signatureFile: '[]', sfykjb: hasKemei ? '是' : '否', lqHytkMxList } } export function validateRefundForm(form) { if (!form.memberId) return '请选择会员' if (!form.refundDate) return '请选择退卡日期' const items = (form.items || []).filter(it => it && it.projectId) if (!items.length) return '请至少添加 1 个品项' const billingSet = new Set() for (let i = 0; i < items.length; i++) { const it = items[i] const idx = i + 1 const qty = Number(it.refundCount) || 0 if (qty <= 0) return `第 ${idx} 个品项退卡次数必须大于 0` if (it.remaining != null && qty > it.remaining) { return `第 ${idx} 个品项退卡次数不能超过剩余次数(${it.remaining})` } const bid = it.billingItemId || it.projectId if (billingSet.has(bid)) return `品项「${it.label}」不能重复添加` billingSet.add(bid) const workers = (it.workers || []).filter(w => w && w.workerId) if (!workers.length) return `第 ${idx} 个品项请至少添加一名健康师` for (let j = 0; j < workers.length; j++) { const w = workers[j] if (w.jksyj === '' || w.jksyj == null || Number.isNaN(Number(w.jksyj))) { return `第 ${idx} 个品项第 ${j + 1} 名健康师业绩必须填写` } } if (it.qt2 === '科美') { const kjbs = (it.techTeachers || []).filter(t => t && t.teacherId) if (!kjbs.length) return `第 ${idx} 个科美品项请至少添加一名科技部老师` } } return '' }