import { formatKdrq, buildBillingKdrqRange } from '@/utils/billingHelper' import { billingDateYmd } from '@/utils/billingHelper' export { buildBillingKdrqRange as buildHksjRange } export function formatHksj(date) { return formatKdrq(date) } export function calcItemConsumeAmount(item) { if (!item || !item.projectId) return 0 return (Number(item.price) || 0) * (Number(item.count) || 0) } /** 单条品项手工费合计(对齐小程序 calculateTotalAmounts) */ export function calcItemLaborCost(item) { if (!item || !item.projectId) return 0 const qty = Number(item.count) || 0 const qt2 = item.qt2 || '' const beautyType = item.beautyType || '' const hasKjb = (item.techTeachers || []).length > 0 if (qt2 === '科美' && beautyType !== 'cell' && beautyType !== 'slim') { return (Number(item.techBeautyLaborCost) || 0) * qty } if (qt2 === '科美' && (beautyType === 'cell' || beautyType === 'slim')) { if (hasKjb) return (Number(item.techBeautyLaborCost) || 0) * qty return (Number(item.healthCoachLaborCost) || 0) * qty } return (Number(item.healthCoachLaborCost) || 0) * qty } export function calcFormXfje(form) { return (form.items || []).reduce((s, it) => s + calcItemConsumeAmount(it), 0) } export function calcFormSgfy(form) { return (form.items || []).reduce((s, it) => s + calcItemLaborCost(it), 0) } /** 均分健康师业绩/手工费/次数 */ export function redistributeConsumeWorkers(item) { if (!item.workers || !item.workers.length) return const totalCount = Number(item.count) || 0 const totalPerf = calcItemConsumeAmount(item) const qt2 = item.qt2 || '' const beautyType = item.beautyType || '' const hasTech = (item.techTeachers || []).length > 0 const isKemei = qt2 === '科美' && beautyType !== 'cell' && beautyType !== 'slim' const isCellSlim = qt2 === '科美' && (beautyType === 'cell' || beautyType === 'slim') const n = item.workers.length if (isKemei || (isCellSlim && hasTech)) { item.workers.forEach(w => { w.performance = n > 0 ? (totalPerf / n).toFixed(2) : '0.00' w.laborCost = '0.00' w.count = '0' }) return } const totalLabor = (Number(item.healthCoachLaborCost) || 0) * totalCount item.workers.forEach(w => { w.performance = n > 0 ? (totalPerf / n).toFixed(2) : '0.00' w.laborCost = n > 0 ? (totalLabor / n).toFixed(2) : '0.00' w.count = n > 0 ? (totalCount / n).toFixed(2) : '0' }) } export function redistributeConsumeTechTeachers(item) { if (!item.techTeachers || !item.techTeachers.length) { redistributeConsumeWorkers(item) return } const totalCount = Number(item.count) || 0 const totalPerf = calcItemConsumeAmount(item) const totalLabor = (Number(item.techBeautyLaborCost) || 0) * totalCount const n = item.techTeachers.length item.techTeachers.forEach(t => { t.performance = n > 0 ? (totalPerf / n).toFixed(2) : '0.00' t.laborCost = n > 0 ? (totalLabor / n).toFixed(2) : '0.00' t.count = n > 0 ? (totalCount / n).toFixed(2) : '0' }) const jn = (item.workers || []).length if (jn > 0) { item.workers.forEach(w => { w.performance = '0.00' w.laborCost = '0.00' w.count = '0' }) } } function mapWorkerToJks(w, item, hwMap) { const name = hwMap.get(w.workerId) || w.workerName || '' return { jks: name, jksxm: name, jkszh: w.workerId, jksyj: Number(w.performance) || 0, jsjId: w.jsjId || '', kdpxid: item.billingItemId || item.projectId, laborCost: Number(w.laborCost) || 0, kdpxNumber: Number(w.count) || 0, isAccompanied: 0, accompaniedProjectNumber: 0 } } function mapAccompaniedToJks(a, item, hwMap) { const name = hwMap.get(a.workerId) || a.workerName || '' return { jks: name, jksxm: name, jkszh: a.workerId, jksyj: 0, jsjId: a.jsjId || '', kdpxid: item.billingItemId || item.projectId, laborCost: 0, kdpxNumber: 0, isAccompanied: 1, accompaniedProjectNumber: Number(a.count) || 0 } } function mapTechToKjb(t, item, kjbMap) { const name = kjbMap.get(t.teacherId) || t.teacherName || '' return { kjbls: t.teacherId, kjblsxm: name, kjblszh: t.teacherId, kjblsyj: Number(t.performance) || 0, hkpxid: item.billingItemId || item.projectId, laborCost: Number(t.laborCost) || 0, hdpxNumber: Number(t.count) || 0 } } export function buildConsumeSubmitBody(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 xfje = calcFormXfje(form) const sgfy = calcFormSgfy(form) const hasKemei = (form.items || []).some(it => it.qt2 === '科美') const lqXhPxmxList = (form.items || []) .filter(it => it && it.projectId) .map(it => { const qty = Number(it.count) || 1 const pxjg = Number(it.price) || 0 const jksList = (it.workers || []) .filter(w => w && w.workerId) .map(w => mapWorkerToJks(w, it, hwMap)) const accompanied = (it.accompanied || []) .filter(a => a && a.workerId) .map(a => mapAccompaniedToJks(a, it, hwMap)) const kjbList = (it.techTeachers || []) .filter(t => t && t.teacherId) .map(t => mapTechToKjb(t, it, kjbMap)) return { billingItemId: it.billingItemId || it.projectId, px: it.itemId || it.pxId || '', pxmc: it.label || it.pxmc || '', pxjg, memberId: form.memberId, projectNumber: qty, sourceType: it.sourceType || '', totalPrice: pxjg * qty, lqXhJksyjList: [...jksList, ...accompanied], lqXhKjbsyjList: kjbList } }) const body = { 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 || '', xfje, sgfy, sfykjb: hasKemei ? '是' : '否', lqXhPxmxList, signatureFile: '[]', overtimeCoefficient: form.isOvertime ? (Number(form.overtimeCoefficient) || 0) : 0, remark: form.remark || '' } if (!form.appointmentId) { body.hksj = formatHksj(form.consumeDate) } else { body.appointmentId = form.appointmentId } return body } export function validateConsumeForm(form) { if (!form.memberId) return '请选择会员' if (!form.appointmentId && !form.consumeDate) return '请选择耗卡日期' const items = (form.items || []).filter(it => it && it.projectId) if (!items.length) return '请至少添加 1 个品项' const groupMap = new Map() for (let i = 0; i < items.length; i++) { const it = items[i] const idx = i + 1 if (!it.projectId) return `第 ${idx} 个品项请选择品项` const qty = Number(it.count) || 0 if (qty <= 0) return `第 ${idx} 个品项次数必须大于 0` if (it.remaining != null && qty > it.remaining) { return `第 ${idx} 个品项次数不能超过剩余次数(${it.remaining})` } const key = it.billingItemId || it.projectId if (!groupMap.has(key)) groupMap.set(key, { total: 0, name: it.label, remaining: it.remaining }) groupMap.get(key).total += qty const workers = (it.workers || []).filter(w => w && w.workerId) if (!workers.length) return `第 ${idx} 个品项请至少添加一名健康师` if (it.qt2 === '科美') { const kjbs = (it.techTeachers || []).filter(t => t && t.teacherId) if (!kjbs.length && it.beautyType !== 'cell' && it.beautyType !== 'slim') { return `第 ${idx} 个科美品项请至少添加一名科技部老师` } } } for (const [, g] of groupMap) { if (g.remaining != null && g.total > g.remaining) { return `品项「${g.name}」消耗次数合计(${g.total})不能超过剩余(${g.remaining})` } } return '' } export function billingDateYmdForConsume(form) { return billingDateYmd({ billingDate: form.consumeDate }) }