651 lines
40 KiB
Java
651 lines
40 KiB
Java
package com.peanut.modules.master.controller;
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.peanut.common.utils.DateUtils;
|
|
import com.peanut.common.utils.R;
|
|
import com.peanut.modules.common.entity.UserVip;
|
|
import com.peanut.modules.master.service.UserVipService;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.apache.poi.ss.usermodel.Row;
|
|
import org.apache.poi.ss.usermodel.Sheet;
|
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.math.BigDecimal;
|
|
import java.math.RoundingMode;
|
|
import java.net.URLEncoder;
|
|
import java.text.DecimalFormat;
|
|
import java.time.LocalDate;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
@Slf4j
|
|
@RestController("masterStatisticsBusinessVip")
|
|
@RequestMapping("master/statisticsBusinessVip")
|
|
public class StatisticsBusinessVipController {
|
|
|
|
@Autowired
|
|
private UserVipService userVipService;
|
|
|
|
@RequestMapping("/getUserVipByMonth")
|
|
public R getUserVipByMonth(@RequestBody Map<String,Object> params) {
|
|
CountResult result = countInfo(userVipService.getUserVipByMonth(params.get("date").toString()), params.get("date").toString());
|
|
|
|
List<Map<String,Object>> allResultList = result.resultList;
|
|
|
|
Map<String, Integer> banCounts = new HashMap<>();
|
|
Map<String, Integer> yanCounts = new HashMap<>();
|
|
BigDecimal banTotalPrice = BigDecimal.ZERO;
|
|
BigDecimal yanTotalPrice = BigDecimal.ZERO;
|
|
String date = params.get("date").toString();
|
|
Map<String, List<Integer>> reBuyRules = buildReBuyRules(date);
|
|
for (Map<String,Object> map : allResultList) {
|
|
String vipType = map.get("vipType").toString();
|
|
boolean isBan = map.get("startTime").equals(map.get("uvlStartTime"));
|
|
// 选择对应的计数 Map
|
|
Map<String, Integer> targetCounts = isBan ? banCounts : yanCounts;
|
|
// 初始化该 vipType 的 Map
|
|
targetCounts.put(vipType, targetCounts.getOrDefault(vipType, 0) + 1);
|
|
// 累加价格
|
|
BigDecimal price = new BigDecimal(map.get("price").toString());
|
|
if (isBan) {
|
|
banTotalPrice = banTotalPrice.add(price);
|
|
} else {
|
|
yanTotalPrice = yanTotalPrice.add(price);
|
|
}
|
|
map.put("isReBuy","否");
|
|
List<Integer> state1UserVips = userVipService.list(new LambdaQueryWrapper<UserVip>()
|
|
.eq(UserVip::getUserId, map.get("userId").toString())
|
|
.eq(UserVip::getState,1).lt(UserVip::getStartTime,map.get("startTime").toString()))
|
|
.stream().map(UserVip::getType).collect(Collectors.toList());
|
|
// 判断是否复购
|
|
List<Integer> required = reBuyRules.get(vipType);
|
|
if (required != null && state1UserVips.containsAll(required)) {
|
|
map.put("isReBuy", "是");
|
|
}
|
|
}
|
|
|
|
// 计算办理总人数
|
|
int banTotalCount = banCounts.values().stream()
|
|
.mapToInt(yearMap -> yearMap.intValue())
|
|
.sum();
|
|
int yanTotalCount = yanCounts.values().stream()
|
|
.mapToInt(yearMap -> yearMap.intValue())
|
|
.sum();
|
|
|
|
return R.ok().put("allResultList",allResultList)
|
|
.put("banTotalCount",banTotalCount).put("yanTotalCount",yanTotalCount)
|
|
.put("banTotalPrice",banTotalPrice).put("yanTotalPrice",yanTotalPrice)
|
|
.put("banCounts",banCounts).put("yanCounts",yanCounts);
|
|
}
|
|
//导出月度汇总
|
|
@RequestMapping("/exportUserVipByMonth")
|
|
public void exportUserVipByMonth(HttpServletResponse response,@RequestBody Map<String,Object> params) {
|
|
R r = getUserVipByMonth(params);
|
|
String date = (String) params.get("date");
|
|
Date nowMonth = DateUtils.stringToDate(date,"yyyy-MM");
|
|
Date lastMonth = DateUtils.addDateMonths(nowMonth,-1);
|
|
String lastMothStr = DateUtils.format(lastMonth,"yyyy-MM");
|
|
|
|
params.put("date", lastMothStr);
|
|
R r2 = getUserVipByMonth(params);
|
|
if (r.get("code").toString().equals("0")) {
|
|
String fileName = "月度VIP汇总";
|
|
XSSFWorkbook wb = new XSSFWorkbook();
|
|
Sheet sheet = wb.createSheet(fileName);
|
|
int rowNum = 0;
|
|
Row row0 = sheet.createRow(rowNum++);
|
|
row0.createCell(0).setCellValue("办理总人数");row0.createCell(1).setCellValue(r.get("banTotalCount").toString());
|
|
row0.createCell(2).setCellValue("延期总人数");row0.createCell(3).setCellValue(r.get("yanTotalCount").toString());
|
|
row0.createCell(4).setCellValue("总办理金额");row0.createCell(5).setCellValue(r.get("banTotalPrice").toString());
|
|
BigDecimal a = calcGrowthRate(r.get("banTotalCount"), r2.get("banTotalCount"));
|
|
DecimalFormat df = new DecimalFormat("0.00%");
|
|
row0.createCell(6).setCellValue("办理总人数环比增长率:");row0.createCell(7).setCellValue(df.format(a));
|
|
Row row1 = sheet.createRow(rowNum++);
|
|
Map<String,Integer> state1Counts = (Map<String,Integer>) r.get("banCounts");
|
|
Map<String,Integer> state0Counts = (Map<String,Integer>) r.get("yanCounts");
|
|
row1.createCell(0).setCellValue("医学超级");row1.createCell(1).setCellValue(state1Counts.getOrDefault("医学超级",0).toString());
|
|
row1.createCell(2).setCellValue("医学超级");row1.createCell(3).setCellValue(state0Counts.getOrDefault("医学超级",0).toString());
|
|
row1.createCell(4).setCellValue("总延期金额");row1.createCell(5).setCellValue(r.get("yanTotalPrice").toString());
|
|
BigDecimal b = calcGrowthRate(r.get("yanTotalCount"), r2.get("yanTotalCount"));
|
|
row1.createCell(6).setCellValue("延期总人数环比增长率:");row1.createCell(7).setCellValue(df.format(b));
|
|
Row row2 = sheet.createRow(rowNum++);
|
|
row2.createCell(0).setCellValue("国学心理学超级");row2.createCell(1).setCellValue(state1Counts.getOrDefault("国学心理学超级",0).toString());
|
|
row2.createCell(2).setCellValue("国学心理学超级");row2.createCell(3).setCellValue(state0Counts.getOrDefault("国学心理学超级",0).toString());
|
|
row2.createCell(4).setCellValue("总金额");row2.createCell(5).setCellValue(
|
|
new BigDecimal(r.get("banTotalPrice").toString()).add(new BigDecimal(r.get("yanTotalPrice").toString())).toString());
|
|
BigDecimal c = calcGrowthRate(r.get("banTotalPrice"), r2.get("banTotalPrice"));
|
|
row2.createCell(6).setCellValue("办理金额环比增长率:");row2.createCell(7).setCellValue(df.format(c));
|
|
Row row3 = sheet.createRow(rowNum++);
|
|
row3.createCell(0).setCellValue("中医学");row3.createCell(1).setCellValue(state1Counts.getOrDefault("中医学", 0).toString());
|
|
row3.createCell(2).setCellValue("中医学");row3.createCell(3).setCellValue(state0Counts.getOrDefault("中医学", 0).toString());
|
|
BigDecimal d = calcGrowthRate(r.get("yanTotalPrice"), r2.get("yanTotalPrice"));
|
|
row3.createCell(6).setCellValue("延期金额环比增长率:");row3.createCell(7).setCellValue(df.format(d));
|
|
Row row4 = sheet.createRow(rowNum++);
|
|
row4.createCell(0).setCellValue("针灸学");row4.createCell(1).setCellValue(state1Counts.getOrDefault("针灸学", 0).toString());
|
|
row4.createCell(2).setCellValue("针灸学");row4.createCell(3).setCellValue(state0Counts.getOrDefault("针灸学", 0).toString());
|
|
Row row5 = sheet.createRow(rowNum++);
|
|
row5.createCell(0).setCellValue("肿瘤学");row5.createCell(1).setCellValue(state1Counts.getOrDefault("肿瘤学", 0).toString());
|
|
row5.createCell(2).setCellValue("肿瘤学");row5.createCell(3).setCellValue(state0Counts.getOrDefault("肿瘤学", 0).toString());
|
|
Row row6 = sheet.createRow(rowNum++);
|
|
row6.createCell(0).setCellValue("妇幼生殖学");row6.createCell(1).setCellValue(state1Counts.getOrDefault("妇幼生殖学",0).toString());
|
|
row6.createCell(2).setCellValue("妇幼生殖学");row6.createCell(3).setCellValue(state0Counts.getOrDefault("妇幼生殖学", 0).toString());
|
|
Row row7 = sheet.createRow(rowNum++);
|
|
row7.createCell(0).setCellValue("国学");row7.createCell(1).setCellValue(state1Counts.getOrDefault("国学",0).toString());
|
|
row7.createCell(2).setCellValue("国学");row7.createCell(3).setCellValue(state0Counts.getOrDefault("国学", 0).toString());
|
|
Row row8 = sheet.createRow(rowNum++);
|
|
row8.createCell(0).setCellValue("心理学");row8.createCell(1).setCellValue(state1Counts.getOrDefault("心理学", 0).toString());
|
|
row8.createCell(2).setCellValue("心理学");row8.createCell(3).setCellValue(state0Counts.getOrDefault("心理学", 0).toString());
|
|
Row row9 = sheet.createRow(rowNum++);
|
|
row9.createCell(0).setCellValue("中西汇通学");row9.createCell(1).setCellValue(state1Counts.getOrDefault("中西汇通学", 0).toString());
|
|
row9.createCell(2).setCellValue("中西汇通学");row9.createCell(3).setCellValue(state0Counts.getOrDefault("中西汇通学", 0).toString());
|
|
|
|
sheet.createRow(rowNum++);
|
|
String[] header = {"时间","姓名","电话","VIP类型","是否延期", "本次年限","本次金额","本次开始时间","本次结束时间","到期时间","是否复购"};
|
|
String[] cellValues = {"payTime","name","tel","vipType", "isYan","year","price","uvlStartTime","uvlEndTime","endTime","isReBuy"};
|
|
|
|
export(wb,sheet,fileName,++rowNum,response,header,cellValues, (List<Map<String, Object>>) r.get("allResultList"));
|
|
}
|
|
}
|
|
|
|
@RequestMapping("/getUserVipByYear")
|
|
public R getUserVipByYear(@RequestBody Map<String,Object> params) {
|
|
CountResult result = countInfo(userVipService.getUserVipByYear(Integer.parseInt(params.get("year").toString())));
|
|
List<Map<String,Object>> allResultList = result.resultList;
|
|
|
|
Map<String, Map<String, Integer>> banCounts = new HashMap<>();
|
|
Map<String, Map<String, Integer>> yanCounts = new HashMap<>();
|
|
BigDecimal banTotalPrice = BigDecimal.ZERO;
|
|
BigDecimal yanTotalPrice = BigDecimal.ZERO;
|
|
for (Map<String,Object> map : allResultList) {
|
|
String vipType = map.get("vipType").toString();
|
|
String year = map.get("year").toString();
|
|
boolean isBan = map.get("startTime").equals(map.get("uvlStartTime"));
|
|
// 选择对应的计数 Map
|
|
Map<String, Map<String, Integer>> targetCounts = isBan ? banCounts : yanCounts;
|
|
// 初始化该 vipType 的 Map
|
|
targetCounts.putIfAbsent(vipType, new HashMap<>());
|
|
Map<String, Integer> yearMap = targetCounts.get(vipType);
|
|
// 更新计数
|
|
if (isBan){
|
|
if ("3".equals(year)||"4".equals(year)){
|
|
yearMap.put(year, yearMap.getOrDefault(year, 0) + 1);
|
|
}else {
|
|
yearMap.put("其他", yearMap.getOrDefault("其他", 0) + 1);
|
|
}
|
|
}else {
|
|
if ("1".equals(year)||"3".equals(year)||"4".equals(year)){
|
|
yearMap.put(year, yearMap.getOrDefault(year, 0) + 1);
|
|
}else {
|
|
yearMap.put("其他", yearMap.getOrDefault("其他", 0) + 1);
|
|
}
|
|
}
|
|
// 累加价格
|
|
BigDecimal price = new BigDecimal(map.get("price").toString());
|
|
if (isBan) {
|
|
banTotalPrice = banTotalPrice.add(price);
|
|
} else {
|
|
yanTotalPrice = yanTotalPrice.add(price);
|
|
}
|
|
}
|
|
// 统计各个类型的办理总人数
|
|
Map<String, Integer> banTypeTotalCounts = new HashMap<>();
|
|
for (Map.Entry<String, Map<String, Integer>> entry : banCounts.entrySet()) {
|
|
String vipType = entry.getKey();
|
|
Map<String, Integer> yearMap = entry.getValue();
|
|
|
|
// 合计该类型所有年份的人数
|
|
int total = yearMap.values().stream().mapToInt(Integer::intValue).sum();
|
|
|
|
banTypeTotalCounts.put(vipType, total);
|
|
}
|
|
// 统计各个类型的延期总人数
|
|
Map<String, Integer> yanTypeTotalCounts = new HashMap<>();
|
|
for (Map.Entry<String, Map<String, Integer>> entry : yanCounts.entrySet()) {
|
|
String vipType = entry.getKey();
|
|
Map<String, Integer> yearMap = entry.getValue();
|
|
// 合计该类型所有年份的人数
|
|
int total = yearMap.values().stream().mapToInt(Integer::intValue).sum();
|
|
yanTypeTotalCounts.put(vipType, total);
|
|
}
|
|
|
|
// 计算办理总人数
|
|
int banTotalCount = banCounts.values().stream()
|
|
.mapToInt(yearMap -> yearMap.values().stream().mapToInt(Integer::intValue).sum())
|
|
.sum();
|
|
int yanTotalCount = yanCounts.values().stream()
|
|
.mapToInt(yearMap -> yearMap.values().stream().mapToInt(Integer::intValue).sum())
|
|
.sum();
|
|
|
|
// 计算各类型办理人数占比
|
|
Map<String, String> banTypeRatios = new HashMap<>();
|
|
for (Map.Entry<String, Map<String, Integer>> entry : banCounts.entrySet()) {
|
|
String vipType = entry.getKey();
|
|
int typeTotal = entry.getValue().values().stream().mapToInt(Integer::intValue).sum();
|
|
double ratio = banTotalCount == 0 ? 0.0 : (typeTotal * 1.0 / banTotalCount);
|
|
DecimalFormat df = new DecimalFormat("0.00%");
|
|
String ratioStr = df.format(ratio);
|
|
banTypeRatios.put(vipType, ratioStr);
|
|
}
|
|
|
|
// 初始化 12 个月的统计
|
|
Map<Integer, Integer> banMonthCounts = new HashMap<>();
|
|
Map<Integer, Integer> yanMonthCounts = new HashMap<>();
|
|
Map<Integer, BigDecimal> monthAmounts = new HashMap<>();
|
|
for (int m = 1; m <= 12; m++) {
|
|
banMonthCounts.put(m, 0);
|
|
yanMonthCounts.put(m, 0);
|
|
monthAmounts.put(m, BigDecimal.ZERO);
|
|
}
|
|
for (Map<String,Object> map : allResultList) {
|
|
String payTimeStr = map.get("payTime").toString();
|
|
LocalDate payDate = LocalDate.parse(payTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
|
int month = payDate.getMonthValue();
|
|
boolean isBan = map.get("startTime").equals(map.get("uvlStartTime"));
|
|
BigDecimal price = new BigDecimal(map.get("price").toString());
|
|
if (isBan) {
|
|
banMonthCounts.put(month, banMonthCounts.get(month) + 1);
|
|
} else {
|
|
yanMonthCounts.put(month, yanMonthCounts.get(month) + 1);
|
|
}
|
|
// 总金额(办理 + 延期)
|
|
monthAmounts.put(month, monthAmounts.get(month).add(price));
|
|
}
|
|
|
|
return R.ok()
|
|
.put("banTotalCount",banTotalCount).put("yanTotalCount",yanTotalCount)
|
|
.put("banTypeTotalCounts",banTypeTotalCounts).put("yanTypeTotalCounts",yanTypeTotalCounts)
|
|
.put("banTotalPrice",banTotalPrice).put("yanTotalPrice",yanTotalPrice)
|
|
.put("banCounts",banCounts).put("yanCounts",yanCounts)
|
|
.put("banTypeRatios",banTypeRatios)
|
|
.put("banMonthCounts",banMonthCounts).put("yanMonthCounts",yanMonthCounts).put("monthAmounts",monthAmounts);
|
|
}
|
|
//导出全部汇总
|
|
@RequestMapping("/exportUserVipByYear")
|
|
public void exportUserVipByYear(HttpServletResponse response,@RequestBody Map<String,Object> params) {
|
|
R r = getUserVipByYear(params);
|
|
int year = Integer.parseInt(params.get("year").toString());
|
|
params.put("year", year-1);
|
|
R r2 = getUserVipByYear(params);
|
|
if (r.get("code").toString().equals("0")) {
|
|
String fileName = "年度VIP汇总";
|
|
XSSFWorkbook wb = new XSSFWorkbook();
|
|
Sheet sheet = wb.createSheet(fileName);
|
|
int rowNum = 0;
|
|
Row row0 = sheet.createRow(rowNum++);
|
|
row0.createCell(0).setCellValue("办理总人数");row0.createCell(1).setCellValue(r.get("banTotalCount").toString());
|
|
row0.createCell(2).setCellValue("延期总人数");row0.createCell(3).setCellValue(r.get("yanTotalCount").toString());
|
|
row0.createCell(4).setCellValue("总办理金额");row0.createCell(5).setCellValue(r.get("banTotalPrice").toString());
|
|
BigDecimal a = calcGrowthRate(r.get("banTotalCount"), r2.get("banTotalCount"));
|
|
DecimalFormat df = new DecimalFormat("0.00%");
|
|
row0.createCell(6).setCellValue("办理总人数同比增长率:");row0.createCell(7).setCellValue(df.format(a));
|
|
Row row1 = sheet.createRow(rowNum++);
|
|
Map<String,Integer> state1Counts = (Map<String,Integer>) r.get("banTypeTotalCounts");
|
|
Map<String,Integer> state0Counts = (Map<String,Integer>) r.get("yanTypeTotalCounts");
|
|
row1.createCell(0).setCellValue("医学超级");row1.createCell(1).setCellValue(state1Counts.containsKey("医学超级")?state1Counts.get("医学超级").toString():"");
|
|
row1.createCell(2).setCellValue("医学超级");row1.createCell(3).setCellValue(state0Counts.containsKey("医学超级")?state0Counts.get("医学超级").toString():"");
|
|
row1.createCell(4).setCellValue("总延期金额");row1.createCell(5).setCellValue(r.get("yanTotalPrice").toString());
|
|
BigDecimal b = calcGrowthRate(r.get("yanTotalCount"), r2.get("yanTotalCount"));
|
|
row1.createCell(6).setCellValue("延期总人数同比增长率:");row1.createCell(7).setCellValue(df.format(b));
|
|
Row row2 = sheet.createRow(rowNum++);
|
|
row2.createCell(0).setCellValue("国学心理学超级");row2.createCell(1).setCellValue(state1Counts.get("国学心理学超级").toString());
|
|
row2.createCell(2).setCellValue("国学心理学超级");row2.createCell(3).setCellValue(state0Counts.get("国学心理学超级").toString());
|
|
row2.createCell(4).setCellValue("总金额");row2.createCell(5).setCellValue(
|
|
new BigDecimal(r.get("banTotalPrice").toString()).add(new BigDecimal(r.get("yanTotalPrice").toString())).toString());
|
|
BigDecimal c = calcGrowthRate(r.get("banTotalPrice"), r2.get("banTotalPrice"));
|
|
row2.createCell(6).setCellValue("办理金额同比增长率:");row2.createCell(7).setCellValue(df.format(c));
|
|
Row row3 = sheet.createRow(rowNum++);
|
|
row3.createCell(0).setCellValue("中医学");row3.createCell(1).setCellValue(state1Counts.getOrDefault("中医学", 0).toString());
|
|
row3.createCell(2).setCellValue("中医学");row3.createCell(3).setCellValue(state0Counts.getOrDefault("中医学", 0).toString());
|
|
BigDecimal d = calcGrowthRate(r.get("yanTotalPrice"), r2.get("yanTotalPrice"));
|
|
row3.createCell(6).setCellValue("延期金额同比增长率:");row3.createCell(7).setCellValue(df.format(d));
|
|
Row row4 = sheet.createRow(rowNum++);
|
|
row4.createCell(0).setCellValue("针灸学");row4.createCell(1).setCellValue(state1Counts.getOrDefault("针灸学", 0).toString());
|
|
row4.createCell(2).setCellValue("针灸学");row4.createCell(3).setCellValue(state0Counts.getOrDefault("针灸学", 0).toString());
|
|
Row row5 = sheet.createRow(rowNum++);
|
|
row5.createCell(0).setCellValue("肿瘤学");row5.createCell(1).setCellValue(state1Counts.getOrDefault("肿瘤学", 0).toString());
|
|
row5.createCell(2).setCellValue("肿瘤学");row5.createCell(3).setCellValue(state0Counts.getOrDefault("肿瘤学", 0).toString());
|
|
Row row6 = sheet.createRow(rowNum++);
|
|
row6.createCell(0).setCellValue("妇幼生殖学");row6.createCell(1).setCellValue(state1Counts.getOrDefault("妇幼生殖学",0).toString());
|
|
row6.createCell(2).setCellValue("妇幼生殖学");row6.createCell(3).setCellValue(state0Counts.getOrDefault("妇幼生殖学", 0).toString());
|
|
Row row7 = sheet.createRow(rowNum++);
|
|
row7.createCell(0).setCellValue("国学");row7.createCell(1).setCellValue(state1Counts.getOrDefault("国学",0).toString());
|
|
row7.createCell(2).setCellValue("国学");row7.createCell(3).setCellValue(state0Counts.getOrDefault("国学", 0).toString());
|
|
Row row8 = sheet.createRow(rowNum++);
|
|
row8.createCell(0).setCellValue("心理学");row8.createCell(1).setCellValue(state1Counts.getOrDefault("心理学", 0).toString());
|
|
row8.createCell(2).setCellValue("心理学");row8.createCell(3).setCellValue(state0Counts.getOrDefault("心理学", 0).toString());
|
|
Row row9 = sheet.createRow(rowNum++);
|
|
row9.createCell(0).setCellValue("中西汇通学");row9.createCell(1).setCellValue(state1Counts.getOrDefault("中西汇通学", 0).toString());
|
|
row9.createCell(2).setCellValue("中西汇通学");row9.createCell(3).setCellValue(state0Counts.getOrDefault("中西汇通学", 0).toString());
|
|
|
|
sheet.createRow(rowNum++);
|
|
String[] header2 = {"","首次办理三年","首次办理四年","其他","延期一年", "延期三年","延期四年","其他"};
|
|
Row row22 = sheet.createRow(rowNum++);
|
|
for (int i = 0; i < header2.length; i++) {
|
|
row22.createCell(i).setCellValue(header2[i]);
|
|
}
|
|
|
|
Map<String, Map<String, Object>> banCounts = (Map<String, Map<String, Object>>) r.get("banCounts");
|
|
Map<String, Map<String, Object>> yanCounts = (Map<String, Map<String, Object>>) r.get("yanCounts");
|
|
fillRow(sheet.createRow(rowNum++), 0, "医学超级", banCounts, yanCounts);
|
|
fillRow(sheet.createRow(rowNum++), 0, "国学心理学超级", banCounts, yanCounts);
|
|
fillRow(sheet.createRow(rowNum++), 0, "中医学", banCounts, yanCounts);
|
|
fillRow(sheet.createRow(rowNum++), 0, "针灸学", banCounts, yanCounts);
|
|
fillRow(sheet.createRow(rowNum++), 0, "肿瘤学", banCounts, yanCounts);
|
|
fillRow(sheet.createRow(rowNum++), 0, "妇幼生殖学", banCounts, yanCounts);
|
|
fillRow(sheet.createRow(rowNum++), 0, "国学", banCounts, yanCounts);
|
|
fillRow(sheet.createRow(rowNum++), 0, "心理学", banCounts, yanCounts);
|
|
fillRow(sheet.createRow(rowNum++), 0, "中西汇通学", banCounts, yanCounts);
|
|
|
|
sheet.createRow(rowNum++);
|
|
Row rateRow = sheet.createRow(rowNum++);
|
|
rateRow.createCell(0).setCellValue("分类");rateRow.createCell(1).setCellValue("年度办理占比");
|
|
Map<String,Object> banTypeRatios = (Map<String, Object>) r.get("banTypeRatios");
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("医学超级");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("医学超级",0).toString());
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("国学心理学超级");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("国学心理学超级",0).toString());
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("中医学");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("中医学",0).toString());
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("针灸学");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("针灸学",0).toString());
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("肿瘤学");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("肿瘤学",0).toString());
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("妇幼生殖学");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("妇幼生殖学",0).toString());
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("国学");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("国学",0).toString());
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("心理学");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("心理学",0).toString());
|
|
sheet.createRow(rowNum++).createCell(0).setCellValue("中西汇通学");sheet.getRow(rowNum-1).createCell(1).setCellValue(banTypeRatios.getOrDefault("中西汇通学",0).toString());
|
|
|
|
sheet.createRow(rowNum++);
|
|
String[] header3 = {"办理时间","办理人数","延期人数","缴费金额"};
|
|
Row row33 = sheet.createRow(rowNum++);
|
|
for (int i = 0; i < header3.length; i++) {
|
|
row33.createCell(i).setCellValue(header3[i]);
|
|
}
|
|
for (int i = 1; i < 13; i++) {
|
|
Row row = sheet.createRow(rowNum++);
|
|
row.createCell(0).setCellValue(i);
|
|
row.createCell(1).setCellValue(((Map<String,Object>)r.get("banMonthCounts")).get(i).toString());
|
|
row.createCell(2).setCellValue(((Map<String,Object>)r.get("yanMonthCounts")).get(i).toString());
|
|
row.createCell(3).setCellValue(((Map<String,Object>)r.get("monthAmounts")).get(i).toString());
|
|
}
|
|
export(wb,null,fileName,++rowNum,response,null,null, null);
|
|
}
|
|
}
|
|
private void fillRow(Row row, int startCol, String vipType,
|
|
Map<String, Map<String, Object>> banCounts,
|
|
Map<String, Map<String, Object>> yanCounts) {
|
|
row.createCell(startCol).setCellValue(vipType);
|
|
Map<String, Object> banMap = banCounts.getOrDefault(vipType, new HashMap<>());
|
|
Map<String, Object> yanMap = yanCounts.getOrDefault(vipType, new HashMap<>());
|
|
row.createCell(startCol + 1).setCellValue(banMap.getOrDefault("3", "0").toString());
|
|
row.createCell(startCol + 2).setCellValue(banMap.getOrDefault("4", "0").toString());
|
|
row.createCell(startCol + 3).setCellValue(banMap.getOrDefault("其他", "0").toString());
|
|
row.createCell(startCol + 4).setCellValue(yanMap.getOrDefault("1", "0").toString());
|
|
row.createCell(startCol + 5).setCellValue(yanMap.getOrDefault("3", "0").toString());
|
|
row.createCell(startCol + 6).setCellValue(yanMap.getOrDefault("4", "0").toString());
|
|
row.createCell(startCol + 7).setCellValue(yanMap.getOrDefault("其他", "0").toString());
|
|
}
|
|
@RequestMapping("/getUserVipByState")
|
|
public R getUserVipByState() {
|
|
CountResult state0Result = countInfo(userVipService.getUserVipByState(0));
|
|
CountResult state1Result = countInfo(userVipService.getUserVipByState(1));
|
|
// 合并结果
|
|
List<Map<String,Object>> allResultList = new ArrayList<>();
|
|
allResultList.addAll(state1Result.resultList);
|
|
allResultList.addAll(state0Result.resultList);
|
|
return R.ok()
|
|
.put("resultList", allResultList)
|
|
.put("state0Total", state0Result.total.size())
|
|
.put("state1Total", state1Result.total.size())
|
|
.put("state0Counts", state0Result.counts)
|
|
.put("state1Counts", state1Result.counts);
|
|
}
|
|
|
|
//导出全部汇总
|
|
@RequestMapping("/exportUserVipByState")
|
|
public void exportUserVipByState(HttpServletResponse response) {
|
|
R r = getUserVipByState();
|
|
if (r.get("code").toString().equals("0")) {
|
|
String fileName = "全部VIP汇总";
|
|
String[] headers = {"办理时间","姓名","注册电话","VIP类型", "最近一次年限","最近一次缴费金额","到期时间"};
|
|
String[] cellValues = {"time","name","tel","vipType", "year","price","endTime"};
|
|
XSSFWorkbook wb = new XSSFWorkbook();
|
|
Sheet sheet = wb.createSheet(fileName);
|
|
int rowNum = 0;
|
|
Row row0 = sheet.createRow(rowNum++);
|
|
row0.createCell(1).setCellValue("到期总人数");row0.createCell(2).setCellValue(r.get("state1Total").toString());
|
|
row0.createCell(4).setCellValue("在期总人数");row0.createCell(5).setCellValue(r.get("state0Total").toString());
|
|
Row row1 = sheet.createRow(rowNum++);
|
|
Map<String,Integer> state1Counts = (Map<String,Integer>) r.get("state1Counts");
|
|
Map<String,Integer> state0Counts = (Map<String,Integer>) r.get("state0Counts");
|
|
row1.createCell(1).setCellValue("医学超级");row1.createCell(2).setCellValue(state1Counts.get("yxSuperCount").toString());
|
|
row1.createCell(4).setCellValue("医学超级");row1.createCell(5).setCellValue(state0Counts.get("yxSuperCount").toString());
|
|
Row row2 = sheet.createRow(rowNum++);
|
|
row2.createCell(1).setCellValue("国学心理超级");row2.createCell(2).setCellValue(state1Counts.get("gxSuperCount").toString());
|
|
row2.createCell(4).setCellValue("国学心理超级");row2.createCell(5).setCellValue(state0Counts.get("gxSuperCount").toString());
|
|
Row row3 = sheet.createRow(rowNum++);
|
|
row3.createCell(1).setCellValue("中医学");row3.createCell(2).setCellValue(state1Counts.get("zyCount").toString());
|
|
row3.createCell(4).setCellValue("中医学");row3.createCell(5).setCellValue(state0Counts.get("zyCount").toString());
|
|
Row row4 = sheet.createRow(rowNum++);
|
|
row4.createCell(1).setCellValue("针灸学");row4.createCell(2).setCellValue(state1Counts.get("zjCount").toString());
|
|
row4.createCell(4).setCellValue("针灸学");row4.createCell(5).setCellValue(state0Counts.get("zjCount").toString());
|
|
Row row5 = sheet.createRow(rowNum++);
|
|
row5.createCell(1).setCellValue("肿瘤学");row5.createCell(2).setCellValue(state1Counts.get("zlCount").toString());
|
|
row5.createCell(4).setCellValue("肿瘤学");row5.createCell(5).setCellValue(state0Counts.get("zlCount").toString());
|
|
Row row6 = sheet.createRow(rowNum++);
|
|
row6.createCell(1).setCellValue("妇幼生殖学");row6.createCell(2).setCellValue(state1Counts.get("fyszCount").toString());
|
|
row6.createCell(4).setCellValue("妇幼生殖学");row6.createCell(5).setCellValue(state0Counts.get("fyszCount").toString());
|
|
Row row7 = sheet.createRow(rowNum++);
|
|
row7.createCell(1).setCellValue("国学");row7.createCell(2).setCellValue(state1Counts.get("gxCount").toString());
|
|
row7.createCell(4).setCellValue("国学");row7.createCell(5).setCellValue(state0Counts.get("gxCount").toString());
|
|
Row row8 = sheet.createRow(rowNum++);
|
|
row8.createCell(1).setCellValue("心理学");row8.createCell(2).setCellValue(state1Counts.get("xlCount").toString());
|
|
row8.createCell(4).setCellValue("心理学");row8.createCell(5).setCellValue(state0Counts.get("xlCount").toString());
|
|
Row row9 = sheet.createRow(rowNum++);
|
|
row9.createCell(1).setCellValue("中西汇通学");row9.createCell(2).setCellValue(state1Counts.get("zxhtCount").toString());
|
|
row9.createCell(4).setCellValue("中西汇通学");row9.createCell(5).setCellValue(state0Counts.get("zxhtCount").toString());
|
|
|
|
export(wb,sheet,fileName,++rowNum,response,headers,cellValues, (List<Map<String, Object>>) r.get("resultList"));
|
|
}
|
|
}
|
|
|
|
//导出近3个月临到期
|
|
@RequestMapping("/getExpiresByMonth")
|
|
public R getExpiresByMonth(@RequestBody Map<String,Object> params) {
|
|
int month = Integer.parseInt(params.get("month").toString());
|
|
CountResult result = countInfo(userVipService.getUserVipMerge(month));
|
|
return R.ok()
|
|
.put("total", result.total.size())
|
|
.put("resultList", result.resultList)
|
|
.put("count", result.counts);
|
|
}
|
|
|
|
//导出近3个月临到期
|
|
@RequestMapping("/exportExpiresByMonth")
|
|
public void exportCourseSaleInfoByCourseLabel(HttpServletResponse response,@RequestBody Map<String,Object> params) {
|
|
R r = getExpiresByMonth(params);
|
|
if (r.get("code").toString().equals("0")) {
|
|
String fileName = "近"+params.get("month").toString()+"个月临到期("+r.get("total")+")";
|
|
String[] headers = {"办理时间","姓名","注册电话","VIP类型", "最近一次年限","最近一次缴费金额","到期时间"};
|
|
String[] cellValues = {"time","name","tel","vipType", "year","price","endTime"};
|
|
XSSFWorkbook wb = new XSSFWorkbook();
|
|
Sheet sheet = wb.createSheet(fileName);
|
|
int rowNum = 0;
|
|
export(wb,sheet,fileName,rowNum,response,headers,cellValues, (List<Map<String, Object>>) r.get("resultList"));
|
|
}
|
|
}
|
|
|
|
// 类型映射表
|
|
private static final Map<String,String> TYPE_NAME_MAP = Map.of(
|
|
"4","中医学",
|
|
"5","针灸学",
|
|
"6","肿瘤学",
|
|
"7","国学",
|
|
"8","心理学",
|
|
"9","中西汇通学",
|
|
"10","妇幼生殖学"
|
|
);
|
|
|
|
// 封装统计结果
|
|
private static class CountResult {
|
|
List<Map<String,Object>> resultList = new ArrayList<>();
|
|
List<String> total = new ArrayList<>();
|
|
Map<String,Integer> counts = new HashMap<>();
|
|
}
|
|
|
|
private static final String MEDICAL_SUPER_CUTOFF = "2026-05";
|
|
|
|
private CountResult countInfo(List<Map<String,Object>> userVips) {
|
|
return countInfo(userVips, null);
|
|
}
|
|
|
|
private CountResult countInfo(List<Map<String,Object>> userVips, String date) {
|
|
CountResult result = new CountResult();
|
|
// 初始化计数器
|
|
result.counts.put("yxSuperCount",0);
|
|
result.counts.put("gxSuperCount",0);
|
|
result.counts.put("zyCount",0);
|
|
result.counts.put("zjCount",0);
|
|
result.counts.put("zlCount",0);
|
|
result.counts.put("gxCount",0);
|
|
result.counts.put("xlCount",0);
|
|
result.counts.put("zxhtCount",0);
|
|
result.counts.put("fyszCount",0);
|
|
|
|
for (Map<String,Object> map : userVips) {
|
|
String recordMonth = resolveRecordMonth(map, date);
|
|
List<String> medicalSuperTypes = getMedicalSuperTypes(recordMonth);
|
|
String[] types = map.get("type").toString().split(",");
|
|
Set<String> typeSet = new HashSet<>(Arrays.asList(types));
|
|
int yxFlag = 0;
|
|
int gxFlag = 0;
|
|
// 超级类型
|
|
if (typeSet.containsAll(medicalSuperTypes)) {
|
|
yxFlag = 1;
|
|
Map<String,Object> copy = new HashMap<>(map);
|
|
copy.put("vipType","医学超级");
|
|
copy.put("price",Math.round(Double.parseDouble(map.get("price").toString())*medicalSuperTypes.size()));
|
|
result.resultList.add(copy);
|
|
result.counts.computeIfPresent("yxSuperCount",(k,v)->v+1);
|
|
result.total.add(map.get("tel").toString());
|
|
}
|
|
if (typeSet.containsAll(Arrays.asList("7","8"))) {
|
|
gxFlag = 1;
|
|
Map<String,Object> copy = new HashMap<>(map);
|
|
copy.put("vipType","国学心理学超级");
|
|
copy.put("price",Math.round(Double.parseDouble(map.get("price").toString())*2));
|
|
result.resultList.add(copy);
|
|
result.counts.computeIfPresent("gxSuperCount",(k,v)->v+1);
|
|
result.total.add(map.get("tel").toString());
|
|
}
|
|
|
|
// 普通类型
|
|
for (String type : types) {
|
|
Map<String,Object> copy = new HashMap<>(map);
|
|
if ("4".equals(type) && yxFlag==0) { copy.put("vipType","中医学"); result.counts.computeIfPresent("zyCount",(k,v)->v+1); }
|
|
else if ("5".equals(type) && yxFlag==0) { copy.put("vipType","针灸学"); result.counts.computeIfPresent("zjCount",(k,v)->v+1); }
|
|
else if ("6".equals(type) && yxFlag==0) { copy.put("vipType","肿瘤学"); result.counts.computeIfPresent("zlCount",(k,v)->v+1); }
|
|
else if ("7".equals(type) && gxFlag==0) { copy.put("vipType","国学"); result.counts.computeIfPresent("gxCount",(k,v)->v+1); }
|
|
else if ("8".equals(type) && gxFlag==0) { copy.put("vipType","心理学"); result.counts.computeIfPresent("xlCount",(k,v)->v+1); }
|
|
else if ("9".equals(type) && yxFlag==0) { copy.put("vipType","中西汇通学"); result.counts.computeIfPresent("zxhtCount",(k,v)->v+1); }
|
|
else if ("10".equals(type) && yxFlag==0 && isFyszEnabled(recordMonth)) { copy.put("vipType","妇幼生殖学"); result.counts.computeIfPresent("fyszCount",(k,v)->v+1); }
|
|
if (copy.get("vipType") != null) {
|
|
result.resultList.add(copy);
|
|
result.total.add(map.get("tel").toString());
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private String resolveRecordMonth(Map<String, Object> map, String date) {
|
|
if (date != null) {
|
|
return date;
|
|
}
|
|
Object payTime = map.get("payTime");
|
|
if (payTime != null) {
|
|
String payTimeStr = payTime.toString();
|
|
return payTimeStr.length() >= 7 ? payTimeStr.substring(0, 7) : payTimeStr;
|
|
}
|
|
return MEDICAL_SUPER_CUTOFF;
|
|
}
|
|
|
|
private List<String> getMedicalSuperTypes(String recordMonth) {
|
|
if (recordMonth.compareTo(MEDICAL_SUPER_CUTOFF) < 0) {
|
|
return Arrays.asList("4", "5", "6", "9");
|
|
}
|
|
return Arrays.asList("4", "5", "6", "9", "10");
|
|
}
|
|
|
|
private boolean isFyszEnabled(String recordMonth) {
|
|
return recordMonth.compareTo(MEDICAL_SUPER_CUTOFF) >= 0;
|
|
}
|
|
|
|
private Map<String, List<Integer>> buildReBuyRules(String date) {
|
|
Map<String, List<Integer>> reBuyRules = new HashMap<>();
|
|
if (date.compareTo(MEDICAL_SUPER_CUTOFF) < 0) {
|
|
reBuyRules.put("医学超级", Arrays.asList(4, 5, 6, 9));
|
|
} else {
|
|
reBuyRules.put("医学超级", Arrays.asList(4, 5, 6, 9, 10));
|
|
reBuyRules.put("妇幼生殖学", Arrays.asList(10));
|
|
}
|
|
reBuyRules.put("国学心理学超级", Arrays.asList(7, 8));
|
|
reBuyRules.put("中医学", Arrays.asList(4));
|
|
reBuyRules.put("针灸学", Arrays.asList(5));
|
|
reBuyRules.put("肿瘤学", Arrays.asList(6));
|
|
reBuyRules.put("国学", Arrays.asList(7));
|
|
reBuyRules.put("心理学", Arrays.asList(8));
|
|
reBuyRules.put("中西汇通学", Arrays.asList(9));
|
|
return reBuyRules;
|
|
}
|
|
|
|
private BigDecimal calcGrowthRate(Object current, Object previous) {
|
|
BigDecimal currentVal = new BigDecimal(current.toString());
|
|
if (currentVal.compareTo(BigDecimal.ZERO) == 0) {
|
|
return BigDecimal.ZERO;
|
|
}
|
|
BigDecimal previousVal = new BigDecimal(previous.toString());
|
|
return currentVal.subtract(previousVal).divide(currentVal, 4, RoundingMode.HALF_UP);
|
|
}
|
|
|
|
private void export(XSSFWorkbook wb,Sheet sheet,String fileName,int rowNum,HttpServletResponse response, String[] headers, String[] cellValues, List<Map<String,Object>> list){
|
|
if (sheet!=null){
|
|
// 表头
|
|
Row titleRow = sheet.createRow(rowNum);
|
|
for (int i = 0; i < headers.length; i++) {
|
|
titleRow.createCell(i).setCellValue(headers[i]);
|
|
}
|
|
for (Map<String,Object> map : list) {
|
|
Row row = sheet.createRow(++rowNum);
|
|
for (int i = 0; i < cellValues.length; i++) {
|
|
row.createCell(i).setCellValue(map.get(cellValues[i]).toString());
|
|
}
|
|
}
|
|
}
|
|
// 输出
|
|
OutputStream outputStream =null;
|
|
try {
|
|
//文件名编码格式
|
|
fileName = URLEncoder.encode(fileName,"UTF-8");
|
|
//设置ContentType请求信息格式
|
|
response.setContentType("application/vnd.ms-excel");
|
|
//设置标头
|
|
response.setHeader("Content-disposition", "attachment;filename=" + fileName+".xlsx");
|
|
outputStream = response.getOutputStream();
|
|
wb.write(outputStream);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}finally {
|
|
try {
|
|
outputStream.flush();
|
|
outputStream.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|