fix: 人力成本分析按员工去重,统一与Dashboard口径;环比/同比无数据时显示暂无数据
This commit is contained in:
@@ -1116,18 +1116,34 @@ export async function getCostAnalysis(orgId: string, month: string) {
|
||||
const lastYearMonthEnd = new Date(year - 1, monthNum, 0, 23, 59, 59)
|
||||
const lastYearMonthStr = `${lastYearMonthStart.getFullYear()}-${String(lastYearMonthStart.getMonth() + 1).padStart(2, '0')}`
|
||||
|
||||
// 获取各月归档批次汇总
|
||||
// 获取各月归档批次汇总(按员工去重,与 getDashboardData 口径一致)
|
||||
const getMonthCost = async (m: string) => {
|
||||
const batches = await prisma.payrollBatch.findMany({
|
||||
where: { orgId, month: m, status: 'ARCHIVED' },
|
||||
const entries = await prisma.batchEntry.findMany({
|
||||
where: { orgId, batch: { month: m, status: 'ARCHIVED' } },
|
||||
select: { employeeId: true, totalPay: true, socialOrg: true, housingOrg: true, tax: true },
|
||||
})
|
||||
return batches.reduce((acc, b) => ({
|
||||
totalPay: acc.totalPay + b.totalPay,
|
||||
totalSocialOrg: acc.totalSocialOrg + b.totalSocialOrg,
|
||||
totalHousingOrg: acc.totalHousingOrg + b.totalHousingOrg,
|
||||
totalTax: acc.totalTax + b.totalTax,
|
||||
employeeCount: acc.employeeCount + b.employeeCount,
|
||||
}), { totalPay: 0, totalSocialOrg: 0, totalHousingOrg: 0, totalTax: 0, employeeCount: 0 })
|
||||
// 同一员工多批次只取一条(取最后一条,金额通常已合并)
|
||||
const empMap = new Map<string, { totalPay: number; socialOrg: number; housingOrg: number; tax: number }>()
|
||||
for (const e of entries) {
|
||||
const ex = empMap.get(e.employeeId)
|
||||
if (!ex) {
|
||||
empMap.set(e.employeeId, { totalPay: e.totalPay, socialOrg: e.socialOrg, housingOrg: e.housingOrg, tax: e.tax })
|
||||
} else {
|
||||
// 同一员工多批次:累加金额
|
||||
ex.totalPay += e.totalPay
|
||||
ex.socialOrg += e.socialOrg
|
||||
ex.housingOrg += e.housingOrg
|
||||
ex.tax += e.tax
|
||||
}
|
||||
}
|
||||
const deduped = Array.from(empMap.values())
|
||||
return {
|
||||
totalPay: deduped.reduce((s, e) => s + e.totalPay, 0),
|
||||
totalSocialOrg: deduped.reduce((s, e) => s + e.socialOrg, 0),
|
||||
totalHousingOrg: deduped.reduce((s, e) => s + e.housingOrg, 0),
|
||||
totalTax: deduped.reduce((s, e) => s + e.tax, 0),
|
||||
employeeCount: deduped.length,
|
||||
}
|
||||
}
|
||||
|
||||
const current = await getMonthCost(month)
|
||||
@@ -1183,7 +1199,7 @@ export async function getCostAnalysis(orgId: string, month: string) {
|
||||
})
|
||||
}
|
||||
|
||||
// 按部门拆分成本
|
||||
// 按部门拆分成本(按员工去重)
|
||||
const deptEntries = await prisma.batchEntry.findMany({
|
||||
where: {
|
||||
orgId,
|
||||
@@ -1191,14 +1207,26 @@ export async function getCostAnalysis(orgId: string, month: string) {
|
||||
},
|
||||
include: { employee: { select: { department: true } } },
|
||||
})
|
||||
const deptMap: Record<string, { totalPay: number; socialOrg: number; housingOrg: number; headcount: number }> = {}
|
||||
// 先按员工去重,同一员工多批次累加金额
|
||||
const deptEmpMap = new Map<string, { dept: string; totalPay: number; socialOrg: number; housingOrg: number }>()
|
||||
for (const e of deptEntries) {
|
||||
const dept = e.employee?.department || '未分配'
|
||||
if (!deptMap[dept]) deptMap[dept] = { totalPay: 0, socialOrg: 0, housingOrg: 0, headcount: 0 }
|
||||
deptMap[dept].totalPay += e.totalPay
|
||||
deptMap[dept].socialOrg += e.socialOrg
|
||||
deptMap[dept].housingOrg += e.housingOrg
|
||||
deptMap[dept].headcount += 1
|
||||
const ex = deptEmpMap.get(e.employeeId)
|
||||
if (!ex) {
|
||||
deptEmpMap.set(e.employeeId, { dept, totalPay: e.totalPay, socialOrg: e.socialOrg, housingOrg: e.housingOrg })
|
||||
} else {
|
||||
ex.totalPay += e.totalPay
|
||||
ex.socialOrg += e.socialOrg
|
||||
ex.housingOrg += e.housingOrg
|
||||
}
|
||||
}
|
||||
const deptMap: Record<string, { totalPay: number; socialOrg: number; housingOrg: number; headcount: number }> = {}
|
||||
for (const [, v] of deptEmpMap) {
|
||||
if (!deptMap[v.dept]) deptMap[v.dept] = { totalPay: 0, socialOrg: 0, housingOrg: 0, headcount: 0 }
|
||||
deptMap[v.dept].totalPay += v.totalPay
|
||||
deptMap[v.dept].socialOrg += v.socialOrg
|
||||
deptMap[v.dept].housingOrg += v.housingOrg
|
||||
deptMap[v.dept].headcount += 1
|
||||
}
|
||||
const departmentCost = Object.entries(deptMap)
|
||||
.map(([dept, v]) => ({
|
||||
|
||||
Reference in New Issue
Block a user