批量发货、课程报表、秒杀排序

This commit is contained in:
wyn
2026-07-02 15:46:41 +08:00
parent dbcf3151bd
commit 76f96ae804
10 changed files with 361 additions and 56 deletions

View File

@@ -35,13 +35,16 @@ public class StatisticsBusinessVipController {
@RequestMapping("/getUserVipByMonth")
public R getUserVipByMonth(@RequestBody Map<String,Object> params) {
CountResult result = countInfo(userVipService.getUserVipByMonth(params.get("date").toString()));
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"));
@@ -61,17 +64,6 @@ public class StatisticsBusinessVipController {
.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());
// 定义复购规则
Map<String, List<Integer>> reBuyRules = new HashMap<>();
reBuyRules.put("医学超级", Arrays.asList(4, 5, 6, 9, 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));
reBuyRules.put("妇幼生殖学", Arrays.asList(10));
// 判断是否复购
List<Integer> required = reBuyRules.get(vipType);
if (required != null && state1UserVips.containsAll(required)) {
@@ -112,7 +104,7 @@ public class StatisticsBusinessVipController {
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 = new BigDecimal(r.get("banTotalCount").toString()).subtract(new BigDecimal(r2.get("banTotalCount").toString())).divide(new BigDecimal(r.get("banTotalCount").toString()), 4, RoundingMode.HALF_UP);
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++);
@@ -121,19 +113,19 @@ public class StatisticsBusinessVipController {
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 = new BigDecimal(r.get("yanTotalCount").toString()).subtract(new BigDecimal(r2.get("yanTotalCount").toString())).divide(new BigDecimal(r.get("yanTotalCount").toString()), 4, RoundingMode.HALF_UP);
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 = new BigDecimal(r.get("banTotalPrice").toString()).subtract(new BigDecimal(r2.get("banTotalPrice").toString())).divide(new BigDecimal(r.get("banTotalPrice").toString()), 4, RoundingMode.HALF_UP);
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 = new BigDecimal(r.get("yanTotalPrice").toString()).subtract(new BigDecimal(r2.get("yanTotalPrice").toString())).divide(new BigDecimal(r.get("yanTotalPrice").toString()), 4, RoundingMode.HALF_UP);
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());
@@ -290,7 +282,7 @@ public class StatisticsBusinessVipController {
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 = new BigDecimal(r.get("banTotalCount").toString()).subtract(new BigDecimal(r2.get("banTotalCount").toString())).divide(new BigDecimal(r.get("banTotalCount").toString()), 4, RoundingMode.HALF_UP);
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++);
@@ -299,19 +291,19 @@ public class StatisticsBusinessVipController {
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 = new BigDecimal(r.get("yanTotalCount").toString()).subtract(new BigDecimal(r2.get("yanTotalCount").toString())).divide(new BigDecimal(r.get("yanTotalCount").toString()), 4, RoundingMode.HALF_UP);
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 = new BigDecimal(r.get("banTotalPrice").toString()).subtract(new BigDecimal(r2.get("banTotalPrice").toString())).divide(new BigDecimal(r.get("banTotalPrice").toString()), 4, RoundingMode.HALF_UP);
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 = new BigDecimal(r.get("yanTotalPrice").toString()).subtract(new BigDecimal(r2.get("yanTotalPrice").toString())).divide(new BigDecimal(r.get("yanTotalPrice").toString()), 4, RoundingMode.HALF_UP);
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());
@@ -503,7 +495,13 @@ public class StatisticsBusinessVipController {
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);
@@ -517,16 +515,18 @@ public class StatisticsBusinessVipController {
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(Arrays.asList("4","5","6","9","10"))) {
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())*4));
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());
@@ -550,7 +550,7 @@ public class StatisticsBusinessVipController {
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) { copy.put("vipType","妇幼生殖学"); result.counts.computeIfPresent("fyszCount",(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());
@@ -560,6 +560,56 @@ public class StatisticsBusinessVipController {
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){
// 表头