consumeHelper.js 7.93 KB
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 })
}