refundHelper.js 6.25 KB
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 ''
}