|
|
|
@ -2,9 +2,17 @@ package net.lab1024.sa.admin.module.service.service; |
|
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil; |
|
|
|
import com.alibaba.excel.EasyExcel; |
|
|
|
import com.alibaba.excel.ExcelWriter; |
|
|
|
import com.alibaba.excel.write.handler.SheetWriteHandler; |
|
|
|
import com.alibaba.excel.write.metadata.WriteSheet; |
|
|
|
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; |
|
|
|
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; |
|
|
|
import com.alibaba.excel.write.metadata.style.WriteCellStyle; |
|
|
|
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; |
|
|
|
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; |
|
|
|
import net.lab1024.sa.base.common.util.SmartRequestUtil; |
|
|
|
import org.apache.poi.ss.usermodel.HorizontalAlignment; |
|
|
|
import org.apache.poi.ss.usermodel.VerticalAlignment; |
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import net.lab1024.sa.base.common.code.UserErrorCode; |
|
|
|
@ -28,6 +36,8 @@ import net.lab1024.sa.admin.module.service.dao.ServiceApplicationsDao; |
|
|
|
import net.lab1024.sa.admin.module.service.domain.entity.ServiceApplicationsEntity; |
|
|
|
import net.lab1024.sa.admin.module.service.domain.form.*; |
|
|
|
import net.lab1024.sa.admin.module.service.domain.vo.*; |
|
|
|
import net.lab1024.sa.admin.module.service.domain.form.ActivityDetailExportForm; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeViewTypeEnum; |
|
|
|
import net.lab1024.sa.admin.module.system.datascope.service.DataScopeViewService; |
|
|
|
import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity; |
|
|
|
@ -36,16 +46,12 @@ import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; |
|
|
|
import net.lab1024.sa.admin.module.system.employee.service.EmployeeService; |
|
|
|
import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee; |
|
|
|
import net.lab1024.sa.admin.module.system.position.service.PositionService; |
|
|
|
import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEntity; |
|
|
|
import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; |
|
|
|
import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; |
|
|
|
import net.lab1024.sa.admin.module.system.role.service.RoleService; |
|
|
|
import net.lab1024.sa.admin.util.AdminRequestUtil; |
|
|
|
import net.lab1024.sa.admin.util.CellStyleStrategy; |
|
|
|
import net.lab1024.sa.admin.util.DateTimeUtil; |
|
|
|
import net.lab1024.sa.admin.util.TimeVo; |
|
|
|
import net.sf.jsqlparser.expression.LongValue; |
|
|
|
import org.apache.catalina.util.RequestUtil; |
|
|
|
import org.apache.commons.collections4.CollectionUtils; |
|
|
|
import org.apache.poi.ss.usermodel.*; |
|
|
|
import org.apache.poi.ss.util.CellRangeAddressList; |
|
|
|
@ -56,14 +62,14 @@ import org.springframework.web.multipart.MultipartFile; |
|
|
|
import javax.annotation.Resource; |
|
|
|
import javax.servlet.http.HttpServletResponse; |
|
|
|
import javax.validation.Valid; |
|
|
|
import java.io.FileOutputStream; |
|
|
|
import java.io.IOException; |
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.math.RoundingMode; |
|
|
|
import java.net.URLEncoder; |
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
import java.util.*; |
|
|
|
import java.time.LocalDateTime; |
|
|
|
import java.util.function.Function; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -260,7 +266,7 @@ public class ServiceApplicationsService { |
|
|
|
|
|
|
|
|
|
|
|
public PageResult<ServiceApplicationsVO> queryPageReport(@Valid ServiceApplicationsQueryForm queryForm) { |
|
|
|
List<Long> longs = new ArrayList<>(); |
|
|
|
|
|
|
|
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm); |
|
|
|
//根据用户角色的查询数据范围来查询数据
|
|
|
|
RequestUser requestUser = AdminRequestUtil.getRequestUser(); |
|
|
|
@ -1322,6 +1328,12 @@ public class ServiceApplicationsService { |
|
|
|
return ResponseDTO.ok(); |
|
|
|
} |
|
|
|
|
|
|
|
public Long queryNoReview() { |
|
|
|
//查询上个月是否有未审核的数据,注意跨年情况
|
|
|
|
Long departmentId = AdminRequestUtil.getRequestUser().getDepartmentId(); |
|
|
|
return serviceApplicationsDao.queryNoReview(departmentId); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Excel下拉列表处理器 |
|
|
|
@ -1588,7 +1600,18 @@ public class ServiceApplicationsService { |
|
|
|
queryForm.setFirmId(requestUser.getDepartmentId()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 应用用户权限控制(分页表单) |
|
|
|
*/ |
|
|
|
private void applyUserPermissionControl(LawyerStatisticsQueryFormPage queryForm) { |
|
|
|
RequestEmployee requestUser = AdminRequestUtil.getRequestUser(); |
|
|
|
RoleVO roleList = roleEmployeeService.getRoleIdList(requestUser.getEmployeeId()).get(0); |
|
|
|
if (UserTypeEnum.CTO.getDesc().equals(roleList.getRoleCode())){ |
|
|
|
queryForm.setFirmId(requestUser.getDepartmentId()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 设置年度时间范围 |
|
|
|
*/ |
|
|
|
@ -1597,6 +1620,42 @@ public class ServiceApplicationsService { |
|
|
|
queryForm.setStartTime(yearStartAndEnd.getStartTime()); |
|
|
|
queryForm.setEndTime(yearStartAndEnd.getEndTime()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据季度设置时间范围 |
|
|
|
*/ |
|
|
|
private void setTimeRangeByQuarter(LawyerStatisticsQueryForm queryForm) { |
|
|
|
if (queryForm.getQuarter() != null) { |
|
|
|
// 有季度参数,使用季度时间范围
|
|
|
|
LocalDateTime quarterStart = DateTimeEnum.getQuarterStart(queryForm.getYear(), queryForm.getQuarter()); |
|
|
|
LocalDateTime quarterEnd = DateTimeEnum.getQuarterEnd(queryForm.getYear(), queryForm.getQuarter()); |
|
|
|
queryForm.setStartTime(quarterStart.toString()); |
|
|
|
queryForm.setEndTime(quarterEnd.toString()); |
|
|
|
} else { |
|
|
|
// 没有季度参数,使用年度时间范围
|
|
|
|
TimeVo yearStartAndEnd = DateTimeUtil.getYearStartAndEnd(queryForm.getYear()); |
|
|
|
queryForm.setStartTime(yearStartAndEnd.getStartTime()); |
|
|
|
queryForm.setEndTime(yearStartAndEnd.getEndTime()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据季度设置时间范围(分页表单) |
|
|
|
*/ |
|
|
|
private void setTimeRangeByQuarter(LawyerStatisticsQueryFormPage queryForm) { |
|
|
|
if (queryForm.getQuarter() != null) { |
|
|
|
// 有季度参数,使用季度时间范围
|
|
|
|
LocalDateTime quarterStart = DateTimeEnum.getQuarterStart(queryForm.getYear(), queryForm.getQuarter()); |
|
|
|
LocalDateTime quarterEnd = DateTimeEnum.getQuarterEnd(queryForm.getYear(), queryForm.getQuarter()); |
|
|
|
queryForm.setStartTime(quarterStart.toString()); |
|
|
|
queryForm.setEndTime(quarterEnd.toString()); |
|
|
|
} else { |
|
|
|
// 没有季度参数,使用年度时间范围
|
|
|
|
TimeVo yearStartAndEnd = DateTimeUtil.getYearStartAndEnd(queryForm.getYear()); |
|
|
|
queryForm.setStartTime(yearStartAndEnd.getStartTime()); |
|
|
|
queryForm.setEndTime(yearStartAndEnd.getEndTime()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 处理有服务时长类型数据的律师统计 |
|
|
|
@ -2057,4 +2116,622 @@ public class ServiceApplicationsService { |
|
|
|
List<ServiceReportStatisticsVO> list = serviceApplicationsDao.getServiceReportStatistics(page, queryForm); |
|
|
|
return SmartPageUtil.convert2PageResult(page, list); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按律师统计活动参与次数 |
|
|
|
*/ |
|
|
|
public PageResult<LawyerActivityCountVO> getLawyerActivityCount(LawyerStatisticsQueryFormPage queryForm) { |
|
|
|
// 应用权限控制
|
|
|
|
applyUserPermissionControl(queryForm); |
|
|
|
|
|
|
|
// 设置时间范围(根据季度参数设置)
|
|
|
|
setTimeRangeByQuarter(queryForm); |
|
|
|
|
|
|
|
// 第一阶段:使用 SmartPageUtil 创建分页对象,查询律师列表
|
|
|
|
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm); |
|
|
|
List<LawyerActivityCountVO> lawyerList = serviceApplicationsDao.getLawyerActivityCount(page, queryForm); |
|
|
|
|
|
|
|
// 第二阶段:查询每个律师的活动统计
|
|
|
|
if (lawyerList != null && !lawyerList.isEmpty()) { |
|
|
|
for (LawyerActivityCountVO lawyer : lawyerList) { |
|
|
|
// 查询该律师的所有活动统计
|
|
|
|
List<LawyerActivityCountVO> activityStats = |
|
|
|
serviceApplicationsDao.getLawyerActivityDetail(lawyer.getUserId(), queryForm); |
|
|
|
|
|
|
|
List<LawyerActivityCountVO.ActivityParticipationVO> activityList = new ArrayList<>(); |
|
|
|
int totalCount = 0; |
|
|
|
|
|
|
|
if (activityStats != null && !activityStats.isEmpty()) { |
|
|
|
for (LawyerActivityCountVO stat : activityStats) { |
|
|
|
LawyerActivityCountVO.ActivityParticipationVO activityVO = |
|
|
|
new LawyerActivityCountVO.ActivityParticipationVO(); |
|
|
|
activityVO.setActivityId(stat.getActivityId()); |
|
|
|
activityVO.setCount(stat.getCount() != null ? stat.getCount() : 0); |
|
|
|
activityList.add(activityVO); |
|
|
|
totalCount += activityVO.getCount(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
lawyer.setActivityList(activityList); |
|
|
|
lawyer.setTotalCount(totalCount); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 按服务总次数降序排序
|
|
|
|
lawyerList.sort((a, b) -> { |
|
|
|
int countA = a.getTotalCount() != null ? a.getTotalCount() : 0; |
|
|
|
int countB = b.getTotalCount() != null ? b.getTotalCount() : 0; |
|
|
|
return Integer.compare(countB, countA); |
|
|
|
}); |
|
|
|
|
|
|
|
// 使用 SmartPageUtil 构建分页结果
|
|
|
|
return SmartPageUtil.convert2PageResult(page, lawyerList); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按律所统计活动参与次数 |
|
|
|
*/ |
|
|
|
public PageResult<FirmActivityCountVO> getFirmActivityCount(LawyerStatisticsQueryFormPage queryForm) { |
|
|
|
// 应用权限控制
|
|
|
|
applyUserPermissionControl(queryForm); |
|
|
|
|
|
|
|
// 设置时间范围(根据季度参数设置)
|
|
|
|
setTimeRangeByQuarter(queryForm); |
|
|
|
|
|
|
|
// 使用 SmartPageUtil 创建分页对象,查询律所列表
|
|
|
|
Page<?> page = SmartPageUtil.convert2PageQuery(queryForm); |
|
|
|
List<FirmActivityCountVO> firmList = serviceApplicationsDao.getFirmActivityCount(page, queryForm); |
|
|
|
|
|
|
|
// 如果没有数据,返回空分页结果
|
|
|
|
if (firmList == null || firmList.isEmpty()) { |
|
|
|
return SmartPageUtil.convert2PageResult(page, new ArrayList<FirmActivityCountVO>()); |
|
|
|
} |
|
|
|
|
|
|
|
// 查询所有活动(用于获取活动名称)
|
|
|
|
List<GoodsEntity> allGoods = goodsService.getAllGoods(); |
|
|
|
|
|
|
|
// 处理每个律所的统计
|
|
|
|
for (FirmActivityCountVO firm : firmList) { |
|
|
|
// 查询该律所下的所有律师
|
|
|
|
List<LawyerActivityCountVO> firmLawyers = |
|
|
|
serviceApplicationsDao.getLawyersByFirmId(firm.getFirmId(), queryForm); |
|
|
|
|
|
|
|
// 为每个律师查询活动统计
|
|
|
|
if (firmLawyers != null && !firmLawyers.isEmpty()) { |
|
|
|
for (LawyerActivityCountVO lawyer : firmLawyers) { |
|
|
|
// 查询该律师的所有活动统计
|
|
|
|
List<LawyerActivityCountVO> activityStats = |
|
|
|
serviceApplicationsDao.getLawyerActivityDetail(lawyer.getUserId(), queryForm); |
|
|
|
|
|
|
|
List<LawyerActivityCountVO.ActivityParticipationVO> activityList = new ArrayList<>(); |
|
|
|
int lawyerTotalCount = 0; |
|
|
|
|
|
|
|
if (activityStats != null && !activityStats.isEmpty()) { |
|
|
|
for (LawyerActivityCountVO stat : activityStats) { |
|
|
|
LawyerActivityCountVO.ActivityParticipationVO activityVO = |
|
|
|
new LawyerActivityCountVO.ActivityParticipationVO(); |
|
|
|
activityVO.setActivityId(stat.getActivityId()); |
|
|
|
activityVO.setCount(stat.getCount() != null ? stat.getCount() : 0); |
|
|
|
activityList.add(activityVO); |
|
|
|
lawyerTotalCount += activityVO.getCount(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
lawyer.setActivityList(activityList); |
|
|
|
lawyer.setTotalCount(lawyerTotalCount); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
firm.setLawyerList(firmLawyers); |
|
|
|
|
|
|
|
// 累加律师的参与次数到律所
|
|
|
|
Map<Long, Integer> firmActivityCount = new HashMap<>(); |
|
|
|
for (LawyerActivityCountVO lawyer : firmLawyers) { |
|
|
|
if (lawyer.getActivityList() != null) { |
|
|
|
for (LawyerActivityCountVO.ActivityParticipationVO activity : lawyer.getActivityList()) { |
|
|
|
firmActivityCount.merge(activity.getActivityId(), activity.getCount(), Integer::sum); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 确保所有goods活动都有记录
|
|
|
|
for (GoodsEntity goods : allGoods) { |
|
|
|
firmActivityCount.putIfAbsent(goods.getGoodsId(), 0); |
|
|
|
} |
|
|
|
|
|
|
|
// 计算总参与次数
|
|
|
|
int totalCount = 0; |
|
|
|
List<FirmActivityCountVO.ActivityParticipationVO> activityList = new ArrayList<>(); |
|
|
|
for (Map.Entry<Long, Integer> entry : firmActivityCount.entrySet()) { |
|
|
|
FirmActivityCountVO.ActivityParticipationVO vo = |
|
|
|
new FirmActivityCountVO.ActivityParticipationVO(); |
|
|
|
vo.setActivityId(entry.getKey()); |
|
|
|
vo.setActivityName(getGoodsNameById(allGoods, entry.getKey())); |
|
|
|
vo.setCount(entry.getValue()); |
|
|
|
activityList.add(vo); |
|
|
|
totalCount += entry.getValue(); |
|
|
|
} |
|
|
|
firm.setActivityList(activityList); |
|
|
|
firm.setActivityCountMap(firmActivityCount); |
|
|
|
firm.setTotalCount(totalCount); |
|
|
|
} |
|
|
|
|
|
|
|
// 按服务总次数降序排序
|
|
|
|
firmList.sort((a, b) -> { |
|
|
|
int countA = a.getTotalCount() != null ? a.getTotalCount() : 0; |
|
|
|
int countB = b.getTotalCount() != null ? b.getTotalCount() : 0; |
|
|
|
return Integer.compare(countB, countA); |
|
|
|
}); |
|
|
|
|
|
|
|
return SmartPageUtil.convert2PageResult(page, firmList); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 导出律师活动统计(不分页) |
|
|
|
*/ |
|
|
|
public void exportLawyerActivityStatistics(LawyerStatisticsQueryForm queryForm, HttpServletResponse response) { |
|
|
|
// 应用权限控制
|
|
|
|
applyUserPermissionControl(queryForm); |
|
|
|
|
|
|
|
// 设置时间范围(根据季度参数设置)
|
|
|
|
setTimeRangeByQuarter(queryForm); |
|
|
|
|
|
|
|
// 直接查询有数据的律师活动统计(有什么导出什么)
|
|
|
|
List<LawyerActivityCountVO> lawyerList = serviceApplicationsDao.exportLawyerActivity(queryForm); |
|
|
|
|
|
|
|
// 导出Excel
|
|
|
|
exportLawyerActivityExcel(lawyerList, response); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 导出律所活动统计(不含律师分级) |
|
|
|
*/ |
|
|
|
public void exportFirmActivityStatistics(LawyerStatisticsQueryForm queryForm, HttpServletResponse response) { |
|
|
|
// 应用权限控制
|
|
|
|
applyUserPermissionControl(queryForm); |
|
|
|
|
|
|
|
// 设置时间范围(根据季度参数设置)
|
|
|
|
setTimeRangeByQuarter(queryForm); |
|
|
|
|
|
|
|
// 直接查询有数据的律所活动统计(有什么导出什么)
|
|
|
|
List<FirmActivityCountVO> firmList = serviceApplicationsDao.exportFirmActivity(queryForm); |
|
|
|
|
|
|
|
// 导出Excel
|
|
|
|
exportFirmActivityExcel(firmList, response); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 导出律师活动统计Excel |
|
|
|
*/ |
|
|
|
private void exportLawyerActivityExcel(List<LawyerActivityCountVO> rawList, HttpServletResponse response) { |
|
|
|
// 设置响应头
|
|
|
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); |
|
|
|
response.setCharacterEncoding("utf-8"); |
|
|
|
String fileName = URLEncoder.encode("律师活动统计", StandardCharsets.UTF_8).replaceAll("\\+", "%20"); |
|
|
|
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); |
|
|
|
|
|
|
|
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build()) { |
|
|
|
// 按律师分组
|
|
|
|
Map<Long, LawyerActivityCountVO> lawyerMap = new LinkedHashMap<>(); |
|
|
|
// 查询所有活动及其分类信息
|
|
|
|
List<GoodsEntity> allGoods = goodsService.getAllGoods(); |
|
|
|
Map<Long, GoodsEntity> goodsMap = allGoods.stream() |
|
|
|
.collect(Collectors.toMap(GoodsEntity::getGoodsId, g -> g)); |
|
|
|
|
|
|
|
// 获取活动分类信息
|
|
|
|
Map<Long, String> categoryMap = getActivityCategoryMap(allGoods); |
|
|
|
|
|
|
|
// 收集所有涉及的活动ID
|
|
|
|
Set<Long> activityIds = new LinkedHashSet<>(); |
|
|
|
|
|
|
|
if (rawList != null && !rawList.isEmpty()) { |
|
|
|
for (LawyerActivityCountVO record : rawList) { |
|
|
|
Long userId = record.getUserId(); |
|
|
|
LawyerActivityCountVO lawyer = lawyerMap.get(userId); |
|
|
|
|
|
|
|
if (lawyer == null) { |
|
|
|
lawyer = new LawyerActivityCountVO(); |
|
|
|
lawyer.setUserId(userId); |
|
|
|
lawyer.setLawyerName(record.getLawyerName()); |
|
|
|
lawyer.setFirmId(record.getFirmId()); |
|
|
|
lawyer.setFirmName(record.getFirmName()); |
|
|
|
lawyer.setCertificateNumber(record.getCertificateNumber()); |
|
|
|
lawyer.setActivityList(new ArrayList<>()); |
|
|
|
lawyerMap.put(userId, lawyer); |
|
|
|
} |
|
|
|
|
|
|
|
// 添加活动
|
|
|
|
if (record.getActivityId() != null && record.getCount() != null) { |
|
|
|
LawyerActivityCountVO.ActivityParticipationVO activity = |
|
|
|
new LawyerActivityCountVO.ActivityParticipationVO(); |
|
|
|
activity.setActivityId(record.getActivityId()); |
|
|
|
activity.setActivityName(record.getActivityName()); |
|
|
|
activity.setCount(record.getCount()); |
|
|
|
lawyer.getActivityList().add(activity); |
|
|
|
activityIds.add(record.getActivityId()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 按分类组织所有活动(不是只包含有数据的)
|
|
|
|
Map<String, List<Long>> categoryActivities = new LinkedHashMap<>(); |
|
|
|
for (GoodsEntity goods : allGoods) { |
|
|
|
String categoryName = categoryMap.getOrDefault(goods.getCategoryId(), "未分类"); |
|
|
|
categoryActivities.computeIfAbsent(categoryName, k -> new ArrayList<>()).add(goods.getGoodsId()); |
|
|
|
} |
|
|
|
|
|
|
|
// 构建两级表头 - 使用 List<List<String>> 格式,每个内部列表是一列
|
|
|
|
List<List<String>> head = new ArrayList<>(); |
|
|
|
|
|
|
|
// 第一列:律所名称(合并两行)
|
|
|
|
head.add(Arrays.asList("律所名称", "")); |
|
|
|
// 第二列:律师名称(合并两行)
|
|
|
|
head.add(Arrays.asList("律师名称", "")); |
|
|
|
|
|
|
|
// 构建表头
|
|
|
|
List<Long> activityIdList = new ArrayList<>(); |
|
|
|
for (Map.Entry<String, List<Long>> entry : categoryActivities.entrySet()) { |
|
|
|
String categoryName = entry.getKey(); |
|
|
|
List<Long> activities = entry.getValue(); |
|
|
|
|
|
|
|
// 为每个活动添加一列
|
|
|
|
for (Long activityId : activities) { |
|
|
|
GoodsEntity goods = goodsMap.get(activityId); |
|
|
|
String activityName = goods != null ? goods.getGoodsName() : "未知活动"; |
|
|
|
// 第一行是大类,第二行是活动名称
|
|
|
|
head.add(Arrays.asList(categoryName, activityName)); |
|
|
|
activityIdList.add(activityId); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 最后一列:服务总次数(合并两行)
|
|
|
|
head.add(Arrays.asList("服务总次数", "")); |
|
|
|
|
|
|
|
// 构建数据
|
|
|
|
List<List<Object>> data = new ArrayList<>(); |
|
|
|
for (LawyerActivityCountVO lawyer : lawyerMap.values()) { |
|
|
|
List<Object> row = new ArrayList<>(); |
|
|
|
row.add(lawyer.getFirmName()); |
|
|
|
row.add(lawyer.getLawyerName()); |
|
|
|
|
|
|
|
// 按活动ID顺序填充数据
|
|
|
|
Map<Long, Integer> activityCountMap = lawyer.getActivityList().stream() |
|
|
|
.collect(Collectors.toMap( |
|
|
|
LawyerActivityCountVO.ActivityParticipationVO::getActivityId, |
|
|
|
LawyerActivityCountVO.ActivityParticipationVO::getCount, |
|
|
|
(v1, v2) -> v1 |
|
|
|
)); |
|
|
|
|
|
|
|
int totalCount = 0; |
|
|
|
for (Long activityId : activityIdList) { |
|
|
|
Integer count = activityCountMap.getOrDefault(activityId, 0); |
|
|
|
row.add(count); |
|
|
|
totalCount += count; |
|
|
|
} |
|
|
|
row.add(totalCount); |
|
|
|
data.add(row); |
|
|
|
} |
|
|
|
|
|
|
|
// 添加合计行
|
|
|
|
List<Object> totalRow = new ArrayList<>(); |
|
|
|
totalRow.add("合计"); |
|
|
|
totalRow.add(""); |
|
|
|
int grandTotal = 0; |
|
|
|
for (Long activityId : activityIdList) { |
|
|
|
int activityTotal = 0; |
|
|
|
for (LawyerActivityCountVO lawyer : lawyerMap.values()) { |
|
|
|
Map<Long, Integer> activityCountMap = lawyer.getActivityList().stream() |
|
|
|
.collect(Collectors.toMap( |
|
|
|
LawyerActivityCountVO.ActivityParticipationVO::getActivityId, |
|
|
|
LawyerActivityCountVO.ActivityParticipationVO::getCount, |
|
|
|
(v1, v2) -> v1 |
|
|
|
)); |
|
|
|
activityTotal += activityCountMap.getOrDefault(activityId, 0); |
|
|
|
} |
|
|
|
totalRow.add(activityTotal); |
|
|
|
grandTotal += activityTotal; |
|
|
|
} |
|
|
|
totalRow.add(grandTotal); |
|
|
|
data.add(totalRow); |
|
|
|
|
|
|
|
// 创建样式策略 - 设置字体不换行
|
|
|
|
HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy( |
|
|
|
getHeadStyle(), // 表头样式
|
|
|
|
getContentStyle() // 内容样式
|
|
|
|
); |
|
|
|
|
|
|
|
WriteSheet writeSheet = EasyExcel.writerSheet("律师活动统计") |
|
|
|
.head(head) |
|
|
|
.registerWriteHandler(styleStrategy) |
|
|
|
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(15)) // 设置默认列宽
|
|
|
|
.build(); |
|
|
|
excelWriter.write(data, writeSheet); |
|
|
|
} catch (IOException e) { |
|
|
|
log.error("导出律师活动统计失败", e); |
|
|
|
throw new RuntimeException("导出失败"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取表头样式 - 字体不换行 |
|
|
|
*/ |
|
|
|
private WriteCellStyle getHeadStyle() { |
|
|
|
WriteCellStyle headStyle = new WriteCellStyle(); |
|
|
|
headStyle.setWrapped(false); // 不换行
|
|
|
|
headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); |
|
|
|
headStyle.setVerticalAlignment(VerticalAlignment.CENTER); |
|
|
|
return headStyle; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取内容样式 - 字体不换行 |
|
|
|
*/ |
|
|
|
private WriteCellStyle getContentStyle() { |
|
|
|
WriteCellStyle contentStyle = new WriteCellStyle(); |
|
|
|
contentStyle.setWrapped(false); // 不换行
|
|
|
|
contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); |
|
|
|
contentStyle.setVerticalAlignment(VerticalAlignment.CENTER); |
|
|
|
return contentStyle; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取活动分类映射 |
|
|
|
*/ |
|
|
|
private Map<Long, String> getActivityCategoryMap(List<GoodsEntity> goodsList) { |
|
|
|
Map<Long, String> categoryMap = new HashMap<>(); |
|
|
|
// 获取所有分类ID
|
|
|
|
Set<Long> categoryIds = goodsList.stream() |
|
|
|
.map(GoodsEntity::getCategoryId) |
|
|
|
.filter(Objects::nonNull) |
|
|
|
.collect(Collectors.toSet()); |
|
|
|
|
|
|
|
// 查询所有分类
|
|
|
|
List<CategoryEntity> categories = categoryService.getAllCategory(); |
|
|
|
Map<Long, String> categoryNameMap = categories.stream() |
|
|
|
.collect(Collectors.toMap(CategoryEntity::getCategoryId, CategoryEntity::getCategoryName, (v1, v2) -> v1)); |
|
|
|
|
|
|
|
// 构建分类映射
|
|
|
|
for (Long categoryId : categoryIds) { |
|
|
|
categoryMap.put(categoryId, categoryNameMap.getOrDefault(categoryId, "未分类")); |
|
|
|
} |
|
|
|
|
|
|
|
return categoryMap; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 导出律所活动统计Excel |
|
|
|
*/ |
|
|
|
private void exportFirmActivityExcel(List<FirmActivityCountVO> rawList, HttpServletResponse response) { |
|
|
|
// 设置响应头
|
|
|
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); |
|
|
|
response.setCharacterEncoding("utf-8"); |
|
|
|
String fileName = URLEncoder.encode("律所活动统计", StandardCharsets.UTF_8).replaceAll("\\+", "%20"); |
|
|
|
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); |
|
|
|
|
|
|
|
try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build()) { |
|
|
|
// 按律所分组
|
|
|
|
Map<Long, FirmActivityCountVO> firmMap = new LinkedHashMap<>(); |
|
|
|
Set<String> activityNames = new LinkedHashSet<>(); |
|
|
|
|
|
|
|
if (rawList != null && !rawList.isEmpty()) { |
|
|
|
for (FirmActivityCountVO record : rawList) { |
|
|
|
Long firmId = record.getFirmId(); |
|
|
|
FirmActivityCountVO firm = firmMap.get(firmId); |
|
|
|
|
|
|
|
if (firm == null) { |
|
|
|
firm = new FirmActivityCountVO(); |
|
|
|
firm.setFirmId(firmId); |
|
|
|
firm.setFirmName(record.getFirmName()); |
|
|
|
firm.setActivityList(new ArrayList<>()); |
|
|
|
firmMap.put(firmId, firm); |
|
|
|
} |
|
|
|
|
|
|
|
// 添加活动
|
|
|
|
if (record.getActivityId() != null && record.getCount() != null) { |
|
|
|
FirmActivityCountVO.ActivityParticipationVO activity = |
|
|
|
new FirmActivityCountVO.ActivityParticipationVO(); |
|
|
|
activity.setActivityId(record.getActivityId()); |
|
|
|
activity.setActivityName(record.getActivityName()); |
|
|
|
activity.setCount(record.getCount()); |
|
|
|
firm.getActivityList().add(activity); |
|
|
|
activityNames.add(record.getActivityName()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 查询所有活动及其分类信息
|
|
|
|
List<GoodsEntity> allGoods = goodsService.getAllGoods(); |
|
|
|
Map<Long, GoodsEntity> goodsMap = allGoods.stream() |
|
|
|
.collect(Collectors.toMap(GoodsEntity::getGoodsId, g -> g)); |
|
|
|
|
|
|
|
// 获取活动分类信息
|
|
|
|
Map<Long, String> categoryMap = getActivityCategoryMap(allGoods); |
|
|
|
|
|
|
|
// 按分类组织所有活动(不是只包含有数据的)
|
|
|
|
Map<String, List<Long>> categoryActivities = new LinkedHashMap<>(); |
|
|
|
for (GoodsEntity goods : allGoods) { |
|
|
|
String categoryName = categoryMap.getOrDefault(goods.getCategoryId(), "未分类"); |
|
|
|
categoryActivities.computeIfAbsent(categoryName, k -> new ArrayList<>()).add(goods.getGoodsId()); |
|
|
|
} |
|
|
|
|
|
|
|
// 构建两级表头 - 使用 List<List<String>> 格式,每个内部列表是一列
|
|
|
|
List<List<String>> head = new ArrayList<>(); |
|
|
|
|
|
|
|
// 第一列:律所名称(合并两行)
|
|
|
|
head.add(Arrays.asList("律所名称", "")); |
|
|
|
|
|
|
|
// 构建表头
|
|
|
|
List<Long> activityIdList = new ArrayList<>(); |
|
|
|
for (Map.Entry<String, List<Long>> entry : categoryActivities.entrySet()) { |
|
|
|
String categoryName = entry.getKey(); |
|
|
|
List<Long> activities = entry.getValue(); |
|
|
|
|
|
|
|
// 为每个活动添加一列
|
|
|
|
for (Long activityId : activities) { |
|
|
|
GoodsEntity goods = goodsMap.get(activityId); |
|
|
|
String activityName = goods != null ? goods.getGoodsName() : "未知活动"; |
|
|
|
// 第一行是大类,第二行是活动名称
|
|
|
|
head.add(Arrays.asList(categoryName, activityName)); |
|
|
|
activityIdList.add(activityId); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 最后一列:服务总次数(合并两行)
|
|
|
|
head.add(Arrays.asList("服务总次数", "")); |
|
|
|
|
|
|
|
// 构建数据
|
|
|
|
List<List<Object>> data = new ArrayList<>(); |
|
|
|
for (FirmActivityCountVO firm : firmMap.values()) { |
|
|
|
List<Object> row = new ArrayList<>(); |
|
|
|
row.add(firm.getFirmName()); |
|
|
|
|
|
|
|
// 按活动ID顺序填充数据
|
|
|
|
Map<Long, Integer> activityCountMap = firm.getActivityList().stream() |
|
|
|
.collect(Collectors.toMap( |
|
|
|
FirmActivityCountVO.ActivityParticipationVO::getActivityId, |
|
|
|
FirmActivityCountVO.ActivityParticipationVO::getCount, |
|
|
|
(v1, v2) -> v1 |
|
|
|
)); |
|
|
|
|
|
|
|
int totalCount = 0; |
|
|
|
for (Long activityId : activityIdList) { |
|
|
|
Integer count = activityCountMap.getOrDefault(activityId, 0); |
|
|
|
row.add(count); |
|
|
|
totalCount += count; |
|
|
|
} |
|
|
|
row.add(totalCount); |
|
|
|
data.add(row); |
|
|
|
} |
|
|
|
|
|
|
|
// 添加合计行
|
|
|
|
List<Object> totalRow = new ArrayList<>(); |
|
|
|
totalRow.add("合计"); |
|
|
|
int grandTotal = 0; |
|
|
|
for (Long activityId : activityIdList) { |
|
|
|
int activityTotal = 0; |
|
|
|
for (FirmActivityCountVO firm : firmMap.values()) { |
|
|
|
Map<Long, Integer> activityCountMap = firm.getActivityList().stream() |
|
|
|
.collect(Collectors.toMap( |
|
|
|
FirmActivityCountVO.ActivityParticipationVO::getActivityId, |
|
|
|
FirmActivityCountVO.ActivityParticipationVO::getCount, |
|
|
|
(v1, v2) -> v1 |
|
|
|
)); |
|
|
|
activityTotal += activityCountMap.getOrDefault(activityId, 0); |
|
|
|
} |
|
|
|
totalRow.add(activityTotal); |
|
|
|
grandTotal += activityTotal; |
|
|
|
} |
|
|
|
totalRow.add(grandTotal); |
|
|
|
data.add(totalRow); |
|
|
|
|
|
|
|
// 创建样式策略 - 设置字体不换行
|
|
|
|
HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy( |
|
|
|
getHeadStyle(), // 表头样式
|
|
|
|
getContentStyle() // 内容样式
|
|
|
|
); |
|
|
|
|
|
|
|
WriteSheet writeSheet = EasyExcel.writerSheet("律所活动统计") |
|
|
|
.head(head) |
|
|
|
.registerWriteHandler(styleStrategy) |
|
|
|
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(15)) // 设置默认列宽
|
|
|
|
.build(); |
|
|
|
excelWriter.write(data, writeSheet); |
|
|
|
} catch (IOException e) { |
|
|
|
log.error("导出律所活动统计失败", e); |
|
|
|
throw new RuntimeException("导出失败"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据goodsID获取goods名称 |
|
|
|
*/ |
|
|
|
private String getGoodsNameById(List<GoodsEntity> goodsList, Long goodsId) { |
|
|
|
if (goodsList == null || goodsId == null) { |
|
|
|
return "未知活动"; |
|
|
|
} |
|
|
|
return goodsList.stream() |
|
|
|
.filter(g -> g != null && goodsId.equals(g.getGoodsId())) |
|
|
|
.map(GoodsEntity::getGoodsName) |
|
|
|
.findFirst() |
|
|
|
.orElse("未知活动"); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 导出活动明细 |
|
|
|
* 根据权限导出:个人只看自己的,律所看本所,CEO看所有 |
|
|
|
*/ |
|
|
|
public void exportActivityDetail( HttpServletResponse response) { |
|
|
|
ServiceApplicationsQueryForm queryForm = new ServiceApplicationsQueryForm(); |
|
|
|
// 获取当前登录用户
|
|
|
|
RequestEmployee requestUser = AdminRequestUtil.getRequestUser(); |
|
|
|
RoleVO roleList = roleEmployeeService.getRoleIdList(requestUser.getEmployeeId()).get(0); |
|
|
|
|
|
|
|
// 根据用户类型应用权限控制
|
|
|
|
if (UserTypeEnum.USER.getDesc().equals(roleList.getRoleCode())) { |
|
|
|
// 律师只能看自己
|
|
|
|
queryForm.setUserId(requestUser.getUserId()); |
|
|
|
} else if (UserTypeEnum.CTO.getDesc().equals(roleList.getRoleCode())) { |
|
|
|
// 律所管理员看本所
|
|
|
|
queryForm.setFirmId(requestUser.getDepartmentId()); |
|
|
|
} |
|
|
|
// CEO可以看所有,不需要设置过滤条件
|
|
|
|
|
|
|
|
// 查询活动明细数据
|
|
|
|
List<ServiceApplicationsVO> dataList = serviceApplicationsDao.exportActivityDetail(queryForm); |
|
|
|
|
|
|
|
// 转换为导出实体
|
|
|
|
List<ActivityDetailExportForm> exportList = convertToExportForm(dataList); |
|
|
|
|
|
|
|
// 写入数据到文件
|
|
|
|
exportExcel(response, "活动明细.xlsx", "活动明细", ActivityDetailExportForm.class, exportList); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 转换为导出实体 |
|
|
|
*/ |
|
|
|
private List<ActivityDetailExportForm> convertToExportForm(List<ServiceApplicationsVO> dataList) { |
|
|
|
List<ActivityDetailExportForm> exportList = new ArrayList<>(); |
|
|
|
if (dataList == null || dataList.isEmpty()) { |
|
|
|
return exportList; |
|
|
|
} |
|
|
|
|
|
|
|
for (ServiceApplicationsVO vo : dataList) { |
|
|
|
ActivityDetailExportForm form = new ActivityDetailExportForm(); |
|
|
|
form.setRecordNo(vo.getRecordNo()); |
|
|
|
form.setUserName(vo.getUserName()); |
|
|
|
form.setDepartmentName(vo.getDepartmentName()); |
|
|
|
form.setActivityName(vo.getActivityName()); |
|
|
|
form.setServiceStart(vo.getServiceStart()); |
|
|
|
form.setServiceEnd(vo.getServiceEnd()); |
|
|
|
form.setServiceDuration(vo.getServiceDuration()); |
|
|
|
form.setBeneficiaryCount(vo.getBeneficiaryCount()); |
|
|
|
form.setOrganizerName(vo.getOrganizerName()); |
|
|
|
form.setOrganizerContact(vo.getOrganizerContact()); |
|
|
|
form.setOrganizerPhone(vo.getOrganizerPhone()); |
|
|
|
exportList.add(form); |
|
|
|
} |
|
|
|
|
|
|
|
return exportList; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取审核状态文本 |
|
|
|
*/ |
|
|
|
private String getAuditStatusText(Integer status) { |
|
|
|
if (status == null) { |
|
|
|
return "未知"; |
|
|
|
} |
|
|
|
switch (status) { |
|
|
|
case 0: |
|
|
|
return "待审核"; |
|
|
|
case 1: |
|
|
|
return "审核中"; |
|
|
|
case 2: |
|
|
|
return "已通过"; |
|
|
|
case 3: |
|
|
|
return "已拒绝"; |
|
|
|
default: |
|
|
|
return "未知"; |
|
|
|
} |
|
|
|
} |
|
|
|
} |