From 0defd9bfb79b23653ba1e8045ebf1219814c6411 Mon Sep 17 00:00:00 2001 From: wuchunlei Date: Mon, 2 Mar 2026 17:34:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=B4=E5=BA=A6=E7=BB=9F=E8=AE=A1=E5=B8=A6?= =?UTF-8?q?=E5=A4=A9=E5=8C=BB=E5=B8=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/StatisticsController.java | 846 ++++++++++++------ 1 file changed, 563 insertions(+), 283 deletions(-) diff --git a/src/main/java/com/zmzm/finance/common/controller/StatisticsController.java b/src/main/java/com/zmzm/finance/common/controller/StatisticsController.java index 3c5c3e8..b75b20b 100644 --- a/src/main/java/com/zmzm/finance/common/controller/StatisticsController.java +++ b/src/main/java/com/zmzm/finance/common/controller/StatisticsController.java @@ -40,300 +40,277 @@ public class StatisticsController { @Autowired private IFinanceOrderService financeOrderService; - //全部统计 - @RequestMapping("/getMonthStatistics") - public R getMonthStatistics(HttpServletResponse response) throws ParseException { - SimpleDateFormat sdfmonth = new SimpleDateFormat("yyyy-MM"); - Date beginDate = sdfmonth.parse("2023-01"); - Date nowDate = sdfmonth.parse(sdfmonth.format(new Date())); + private BigDecimal getFee(List> incomes, String type) { + return incomes.stream() + .filter(income -> type.equals(String.valueOf(income.get("type")))) + .map(income -> new BigDecimal(String.valueOf(income.get("fee")))) + .findFirst() + .orElse(BigDecimal.ZERO); + } + private List> getIncomesList(int type,String date){ + return ordersService.listMaps(new MPJLambdaWrapper() + .leftJoin(PaymentToOrder.class,PaymentToOrder::getOrderId,Orders::getId) + .leftJoin(Payment.class,Payment::getId,PaymentToOrder::getPaymentId) + .disableSubLogicDel() + .eq(Orders::getUseFlag,1).eq(Orders::getType,type) + .apply("DATE_FORMAT(t.order_time, '%Y-%m') = '"+date+"'") + .select("IF(t.pay_type=1,'天医币',IF(t2.type=0,'微信',IF(t2.type=1,'支付宝','银行'))) type,SUM(t.fee) fee") + .groupBy(Payment::getType)); + } + //年度统计带天医币 + @RequestMapping("/getYearStatistics") + public R getYearStatistics(HttpServletResponse response,@RequestBody Map params) { + String year = params.get("year").toString(); List> resultList = new ArrayList<>(); - for (Date d=beginDate;!d.equals(nowDate);d = DateUtils.addMonths(d,1)){ - String date = sdfmonth.format(d); + // 使用 BigDecimal.ZERO 初始化,避免重复创建对象 + BigDecimal pointTotal = BigDecimal.ZERO; + BigDecimal vipTotal = BigDecimal.ZERO; + BigDecimal courseTotal = BigDecimal.ZERO; + BigDecimal physicalTotal = BigDecimal.ZERO; + BigDecimal trainingClassTotal = BigDecimal.ZERO; + + List yewuTotalList = new ArrayList<>(Collections.nCopies(19, BigDecimal.ZERO)); + BigDecimal totalTotal = new BigDecimal("0"); + for (int i=1;i<=12;i++){ + String month = String.format("%02d", i); + String date = year+"-"+month; Map resultMap = new HashMap<>(); BigDecimal monthTotal = new BigDecimal("0"); - resultMap.put("01月份",date); + resultMap.put("01月份",month); - Orders physical = ordersService.getOne(new MPJLambdaWrapper() - .eq(Orders::getUseFlag,1).eq(Orders::getType,3) - .apply("DATE_FORMAT(t.order_time,'%Y-%m') = '"+date+"'") - .selectSum(Orders::getFee)); - BigDecimal physicalFee = physical==null?BigDecimal.ZERO:physical.getFee(); - resultMap.put("02实物",physicalFee); + List> pointIncomes = ordersService.listMaps(new MPJLambdaWrapper() + .leftJoin(PaymentToOrder.class,PaymentToOrder::getOrderId,Orders::getId) + .leftJoin(Payment.class,Payment::getId,PaymentToOrder::getPaymentId) + .eq(Orders::getType,0) + .apply("DATE_FORMAT(t.order_time, '%Y-%m') = '"+date+"'") + .groupBy(Payment::getType) + .select("IF(t2.type=0,'微信',IF(t2.type=1,'支付宝','银行')) type") + .selectSum(Orders::getFee,"fee").selectSum(Orders::getPoint,"point")); + BigDecimal wxPointFee = getFee(pointIncomes,"微信"); + BigDecimal zfbPointFee = getFee(pointIncomes,"支付宝"); + BigDecimal bankPointFee = getFee(pointIncomes,"银行"); + BigDecimal pointFee = wxPointFee.add(zfbPointFee).add(bankPointFee); + resultMap.put("02微信天医币",wxPointFee); + resultMap.put("03支付宝天医币",zfbPointFee); + resultMap.put("04银行天医币",bankPointFee); + yewuTotalList.set(0,yewuTotalList.get(0).add(wxPointFee)); + yewuTotalList.set(1,yewuTotalList.get(1).add(zfbPointFee)); + yewuTotalList.set(2,yewuTotalList.get(2).add(bankPointFee)); + pointTotal = pointTotal.add(pointFee); + monthTotal = monthTotal.add(pointFee); + + List> vipIncomes = getIncomesList(1,date); + BigDecimal pointVipFee = getFee(vipIncomes,"天医币"); + BigDecimal wxVipFee = getFee(vipIncomes,"微信"); + BigDecimal zfbVipFee = getFee(vipIncomes,"支付宝"); + BigDecimal bankVipFee = getFee(vipIncomes,"银行"); + BigDecimal vipFee = pointVipFee.add(wxVipFee).add(zfbVipFee).add(bankVipFee); + resultMap.put("05天医币vip",pointVipFee); + resultMap.put("06微信vip",wxVipFee); + resultMap.put("07支付宝vip",zfbVipFee); + resultMap.put("08银行vip",bankVipFee); + yewuTotalList.set(3,yewuTotalList.get(3).add(pointVipFee)); + yewuTotalList.set(4,yewuTotalList.get(4).add(wxVipFee)); + yewuTotalList.set(5,yewuTotalList.get(5).add(zfbVipFee)); + yewuTotalList.set(6,yewuTotalList.get(6).add(bankVipFee)); + vipTotal = vipTotal.add(vipFee); + monthTotal = monthTotal.add(vipFee); + + List> courseIncomes = getIncomesList(2,date); + BigDecimal pointCourseFee = getFee(courseIncomes,"天医币"); + BigDecimal wxCourseFee = getFee(courseIncomes,"微信"); + BigDecimal zfbCourseFee = getFee(courseIncomes,"支付宝"); + BigDecimal bankCourseFee = getFee(courseIncomes,"银行"); + BigDecimal courseFee = pointCourseFee.add(wxCourseFee).add(zfbCourseFee).add(bankCourseFee); + resultMap.put("09天医币课程",pointCourseFee); + resultMap.put("10微信课程",wxCourseFee); + resultMap.put("11支付宝课程",zfbCourseFee); + resultMap.put("12银行课程",bankCourseFee); + yewuTotalList.set(7,yewuTotalList.get(7).add(pointCourseFee)); + yewuTotalList.set(8,yewuTotalList.get(8).add(wxCourseFee)); + yewuTotalList.set(9,yewuTotalList.get(9).add(zfbCourseFee)); + yewuTotalList.set(10,yewuTotalList.get(10).add(bankCourseFee)); + courseTotal = courseTotal.add(courseFee); + monthTotal = monthTotal.add(courseFee); + + List> physicalIncomes = getIncomesList(3,date); + BigDecimal pointPhysicalFee = getFee(physicalIncomes,"天医币"); + BigDecimal wxPhysicalFee = getFee(physicalIncomes,"微信"); + BigDecimal zfbPhysicalFee = getFee(physicalIncomes,"支付宝"); + BigDecimal bankPhysicalFee = getFee(physicalIncomes,"银行"); + BigDecimal physicalFee = pointPhysicalFee.add(wxPhysicalFee).add(zfbPhysicalFee).add(bankPhysicalFee); + resultMap.put("13天医币实物",pointPhysicalFee); + resultMap.put("14微信实物",wxPhysicalFee); + resultMap.put("15支付宝实物",zfbPhysicalFee); + resultMap.put("16银行实物",bankPhysicalFee); + yewuTotalList.set(11,yewuTotalList.get(11).add(pointPhysicalFee)); + yewuTotalList.set(12,yewuTotalList.get(12).add(wxPhysicalFee)); + yewuTotalList.set(13,yewuTotalList.get(13).add(zfbPhysicalFee)); + yewuTotalList.set(14,yewuTotalList.get(14).add(bankPhysicalFee)); + physicalTotal = physicalTotal.add(physicalFee); monthTotal = monthTotal.add(physicalFee); - Orders trangingClass = ordersService.getOne(new MPJLambdaWrapper() - .eq(Orders::getUseFlag,1).eq(Orders::getType,4) - .apply("DATE_FORMAT(t.order_time,'%Y-%m') = '"+date+"'") - .selectSum(Orders::getFee)); - BigDecimal trangingClassFee = trangingClass==null?BigDecimal.ZERO:trangingClass.getFee(); - resultMap.put("03培训班",trangingClassFee); - monthTotal = monthTotal.add(trangingClassFee); + List> trainingClassIncomes = getIncomesList(4,date); + BigDecimal pointTrainingClassFee = getFee(trainingClassIncomes,"天医币"); + BigDecimal wxTrainingClassFee = getFee(trainingClassIncomes,"微信"); + BigDecimal zfbTrainingClassFee = getFee(trainingClassIncomes,"支付宝"); + BigDecimal bankTrainingClassFee = getFee(trainingClassIncomes,"银行"); + BigDecimal trainingClassFee = pointTrainingClassFee.add(wxTrainingClassFee).add(zfbTrainingClassFee).add(bankTrainingClassFee); + resultMap.put("17天医币培训班",pointTrainingClassFee); + resultMap.put("18微信培训班",wxTrainingClassFee); + resultMap.put("19支付宝培训班",zfbTrainingClassFee); + resultMap.put("20银行培训班",bankTrainingClassFee); + yewuTotalList.set(15,yewuTotalList.get(15).add(pointTrainingClassFee)); + yewuTotalList.set(16,yewuTotalList.get(16).add(wxTrainingClassFee)); + yewuTotalList.set(17,yewuTotalList.get(17).add(zfbTrainingClassFee)); + yewuTotalList.set(18,yewuTotalList.get(18).add(bankTrainingClassFee)); + trainingClassTotal = trainingClassTotal.add(trainingClassFee); + monthTotal = monthTotal.add(trainingClassFee); - YearMonth yearMonth = YearMonth.parse(date); - SimpleDateFormat sdfday = new SimpleDateFormat("yyyy-MM-dd"); - String day = date+"-"+yearMonth.lengthOfMonth(); - String month = date; - BigDecimal vipNowTotal = BigDecimal.ZERO; - //所有vip订单 - List vipOrders = ordersService.list(new MPJLambdaWrapper() - .eq(Orders::getUseFlag,1).eq(Orders::getType,1)); - //吴门医述订单 - List wumenOrderIds = vipOrders.stream().filter(o -> o.getSource() == 1).map(Orders::getOrderOldId).collect(Collectors.toList()); - List> buyOrders = buyOrderService.listMaps(new MPJLambdaWrapper() - .leftJoin(UserVipLog.class,UserVipLog::getOrderSn,BuyOrder::getOrderSn) - .disableSubLogicDel() - .in(BuyOrder::getOrderId,wumenOrderIds) - .select("t.order_id oid,t1.price fee,DATE_FORMAT(start_time, '%Y-%m-%d %H:%i:%s') startTime,DATE_FORMAT(end_time, '%Y-%m-%d %H:%i:%s') endTime")); - Map buyOrdersMap = new HashMap<>(); - for (Map m : buyOrders) { - List> l = new ArrayList<>(); - if(buyOrdersMap.get(m.get("oid").toString())!=null){ - l = (List>) buyOrdersMap.get(m.get("oid").toString()); - } - l.add(m); - buyOrdersMap.put(m.get("oid").toString(),l); - } - for(Orders orders:vipOrders){ - List> list = new ArrayList<>(); - if (orders.getSource()==1){ - List> l = (List>) buyOrdersMap.get(orders.getOrderOldId()); - for (Map m : l) { - if (m.get("fee")!=null){ - Map map = new HashMap<>(); - map.put("fee",m.get("fee")); - map.put("startTime",m.get("startTime")); - map.put("endTime",m.get("endTime")); - list.add(map); - }else { - Map map = new HashMap<>(); - map.put("fee",orders.getFee()); - map.put("startTime",sdfday.format(orders.getOrderTime())); - map.put("endTime",sdfday.format(orders.getOrderTime())); - list.add(map); - } - } - }else { - FinanceOrder financeOrder = financeOrderService.getById(orders.getOrderOldId()); - Map map = new HashMap<>(); - map.put("fee",financeOrder.getRealMoney()); - map.put("startTime",sdfday.format(financeOrder.getStartTime())); - map.put("endTime",sdfday.format(financeOrder.getEndTime())); - list.add(map); - } - for (Map map:list){ - BigDecimal fee = (BigDecimal) map.get("fee"); - String startTime = map.get("startTime")==null?"":map.get("startTime").toString(); - String endTime = map.get("endTime")==null?"":map.get("endTime").toString(); - if (startTime.equals(endTime)){ - if (sdfmonth.format(orders.getOrderTime()).contains(month)){ - vipNowTotal = vipNowTotal.add(fee); - } else if (sdfmonth.parse(startTime).getTime()sdfmonth.parse(endTime).getTime()){ - //未开始摊销 - }else if (sdfday.parse(day).getTime()0){ - }else { - alreadyDays = 0; - } - //当前月天数 - int nowDays = Integer.parseInt(day.substring(8, 10)); - BigDecimal now = BigDecimal.ZERO; - //如果开始时间是当前月,月天数-开始日=当月摊销天数 - if (startTime.contains(month)){ - nowDays = Integer.parseInt(day.substring(8, 10))-Integer.parseInt(startTime.substring(8, 10))+1; - now = dayAmount.multiply(new BigDecimal(nowDays)); - } else if (endTime.contains(month)) { - now = fee.subtract(dayAmount.multiply(new BigDecimal(alreadyDays))); - }else { - now = dayAmount.multiply(new BigDecimal(nowDays)); - } - vipNowTotal = vipNowTotal.add(now); - } - } - } - resultMap.put("04VIP月摊销",vipNowTotal); - monthTotal = monthTotal.add(vipNowTotal); - - BigDecimal courseNowTotal = BigDecimal.ZERO; - //所有课程订单 - List> courseOrders = ordersService.listMaps(new MPJLambdaWrapper() - .eq(Orders::getUseFlag,1).eq(Orders::getType,2) - .select("DATE_FORMAT(order_time, '%Y-%m-%d %H:%i:%s') orderTime,if(source=0,'一路健康',if(source=1,'吴门医述','管理员')) source,order_old_id orderOldId," + - "tel,order_sn,t.tel,t.fee realMoney") - .orderByAsc(Orders::getOrderTime)); - //一路健康订单课程 - List taihuOrderIds = courseOrders.stream().filter(o -> o.get("source").equals("一路健康")) - .map(map->map.get("orderOldId").toString()).collect(Collectors.toList()); - Map> taihuClassMap = customerApplyCurriculumService.listMaps(new MPJLambdaWrapper() - .in("t.oid", taihuOrderIds) - .apply("t.valid=1 and t.status = '50'") - .select("t.oid,if(t.point>0,t.point,t.money) fee,curriculumID")) - .stream().collect(Collectors.toMap(m -> m.get("oid").toString(), m -> m)); - //订单开课记录 - Map> ctc = customerTaihuClassService.listMaps(new MPJLambdaWrapper() - .like(TCustomerTaihuClass::getDescription,"KC20") - .in(TCustomerTaihuClass::getStatus,10) - .gt(TCustomerTaihuClass::getStudydays,0) - .select("SUBSTRING(description, LOCATE('KC', description), 16) description,oid,DATE_FORMAT(startDate, '%Y-%m-%d') startDate,studyDays")) - .stream().collect(Collectors.toMap(m -> m.get("description").toString()+"-"+m.get("oid").toString(), m -> m)); - //吴门医述订单课程 - List courseWumenOrderIds = courseOrders.stream().filter(o -> o.get("source").equals("吴门医述")) - .map(map->map.get("orderOldId").toString()).collect(Collectors.toList()); - List> buyOrdersList = buyOrderService.listMaps(new MPJLambdaWrapper() - .leftJoin("user_course_buy_log t1 on (t1.order_sn = t.order_sn )") - .leftJoin("user_course_buy t2 on t2.id = t1.user_course_buy_id") - .in("t.order_id",courseWumenOrderIds) - .gt(BuyOrder::getRealMoney,0) - .select("t.order_id oid,t1.id ucblid,if(t1.fee is null,t.real_money,t1.fee) fee,t1.days,t1.begin_day," + - "DATE_FORMAT(t2.start_time, '%Y-%m-%d %H:%i:%s') startTime")); - Map courseBuyOrdersMap = new HashMap<>(); - for (Map m : buyOrdersList) { - List> l = new ArrayList<>(); - if(courseBuyOrdersMap.get(m.get("oid").toString())!=null){ - l = (List>) courseBuyOrdersMap.get(m.get("oid").toString()); - } - l.add(m); - courseBuyOrdersMap.put(m.get("oid").toString(),l); - } - List> result = new ArrayList<>(); - for(Map courseOrder:courseOrders){ - String orderTime = courseOrder.get("orderTime").toString().substring(0,10); - if (courseOrder.get("source").equals("一路健康")){ - Map res = new HashMap<>(); - Map taihuClass = taihuClassMap.get(courseOrder.get("orderOldId").toString()); - Map tc = ctc.entrySet().stream().filter(e -> e.getKey() - .contains(taihuClass.get("curriculumID").toString())).map(Map.Entry::getValue).findFirst().orElse(null); - res.put("fee",courseOrder.get("realMoney")); - if (tc != null&&tc.get("startDate")!=null) { - res.put("startTime",tc.get("startDate")); - res.put("endTime",sdfday.format(DateUtils.addDays(sdfday.parse(tc.get("startDate").toString()), (Integer) tc.get("studyDays")))); - }else { - res.put("startTime",orderTime); - res.put("endTime",orderTime); - } - res.putAll(courseOrder); - result.add(res); - }else if(courseOrder.get("source").equals("吴门医述")){ - List> l = (List>) courseBuyOrdersMap.get(courseOrder.get("orderOldId")); - if (l!=null){ - for (int i=0;i res = new HashMap<>(); - Map m = l.get(i); - if (m.get("ucblid")!=null){ - if (new BigDecimal(m.get("fee").toString()).compareTo(BigDecimal.ZERO)>0){ - res.put("fee",m.get("fee")); - }else { - BigDecimal one = new BigDecimal(courseOrder.get("realMoney").toString()).divide(new BigDecimal(l.size()),2,BigDecimal.ROUND_HALF_UP); - if (i==l.size()-1){ - res.put("fee",new BigDecimal(courseOrder.get("realMoney").toString()).subtract(one.multiply(new BigDecimal(l.size()-1)))); - }else { - res.put("fee",one); - } - } - if (m.get("startTime")==null){ - res.put("startTime",null); - res.put("endTime",null); - }else { - if (Integer.parseInt(m.get("begin_day").toString())==0){ - res.put("startTime",m.get("startTime").toString()); - res.put("endTime",sdfday.format(DateUtils.addDays(sdfday.parse(m.get("startTime").toString()), - Integer.parseInt(m.get("days").toString())-1))); - }else { - res.put("startTime",sdfday.format(DateUtils.addDays(sdfday.parse(m.get("startTime").toString()), - Integer.parseInt(m.get("days").toString())))); - res.put("endTime",sdfday.format(DateUtils.addDays(sdfday.parse(res.get("startTime").toString()), - Integer.parseInt(m.get("days").toString())-1))); - } - } - }else { - res.put("fee",courseOrder.get("realMoney")); - res.put("startTime",orderTime); - res.put("endTime",orderTime); - } - res.putAll(courseOrder); - result.add(res); - } - }else { - Map res = new HashMap<>(); - res.put("fee",courseOrder.get("realMoney")); - res.put("startTime",orderTime); - res.put("endTime",orderTime); - res.putAll(courseOrder); - result.add(res); - } - }else { - FinanceOrder financeOrder = financeOrderService.getById(courseOrder.get("orderOldId").toString()); - courseOrder.put("fee",financeOrder.getRealMoney()); - courseOrder.put("startTime",sdfday.format(financeOrder.getStartTime())); - courseOrder.put("endTime",sdfday.format(financeOrder.getEndTime())); - result.add(courseOrder); - } - } - for (Map map:result) { - BigDecimal fee = (BigDecimal) map.get("fee"); - String startTime = (String) map.get("startTime"); - String endTime = (String) map.get("endTime"); - if (startTime==null){ - if (sdfmonth.parse(map.get("orderTime").toString()).getTime()<=sdfmonth.parse(month).getTime()){ - } - }else if (startTime.equals(endTime)){ - if (startTime.contains(month)){ - courseNowTotal = courseNowTotal.add(fee); - } else if (sdfmonth.parse(startTime).getTime()sdfmonth.parse(endTime).getTime()){ - }else if (sdfday.parse(day).getTime()0){ - }else { - alreadyDays = 0; - } - //当前月天数 - int nowDays = Integer.parseInt(day.substring(8, 10)); - BigDecimal now = BigDecimal.ZERO; - //如果开始时间是当前月,月天数-开始日=当月摊销天数 - if (startTime.contains(month)&&endTime.contains(month)){ - now = fee; - } else if (startTime.contains(month)){ - nowDays = Integer.parseInt(day.substring(8, 10))-Integer.parseInt(startTime.substring(8, 10))+1; - now = dayAmount.multiply(new BigDecimal(nowDays)); - } else if (endTime.contains(month)) { - now = fee.subtract(dayAmount.multiply(new BigDecimal(alreadyDays))); - }else { - now = dayAmount.multiply(new BigDecimal(nowDays)); - } - courseNowTotal = courseNowTotal.add(now); - } - } - resultMap.put("05课程月摊销",courseNowTotal); - monthTotal = monthTotal.add(courseNowTotal); - resultMap.put("06合计",monthTotal); + totalTotal = totalTotal.add(monthTotal); + resultMap.put("21合计",monthTotal); resultList.add(resultMap); } XSSFWorkbook wb = new XSSFWorkbook(); - Sheet sheet1 = wb.createSheet("全部汇总"); + Sheet sheet1 = wb.createSheet(year+"全部汇总"); exportCommon(sheet1 ,resultList); - exportTem(response,wb,"全部汇总.xlsx"); + int rowNum = sheet1.getLastRowNum(); + Row row = sheet1.createRow(rowNum+1); + row.createCell(0).setCellValue("业务合计"); + for (int c=0;c<19;c++){ + row.createCell(c+1).setCellValue(yewuTotalList.get(c).toString()); + } + Row row1 = sheet1.createRow(rowNum+2); + row1.createCell(0).setCellValue("总合计"); + row1.createCell(1).setCellValue(pointTotal.toString()); + row1.createCell(4).setCellValue(vipTotal.toString()); + row1.createCell(8).setCellValue(courseTotal.toString()); + row1.createCell(12).setCellValue(physicalTotal.toString()); + row1.createCell(16).setCellValue(trainingClassTotal.toString()); + row1.createCell(20).setCellValue(totalTotal.toString()); + exportTem(response,wb,year+"全部汇总.xlsx"); + return R.ok(); + } + //年度统计不带天医币 + @RequestMapping("/getYearStatisticsNoPoint") + public R getYearStatisticsNoPoint(HttpServletResponse response,@RequestBody Map params) { + String year = params.get("year").toString(); + List> resultList = new ArrayList<>(); + // 使用 BigDecimal.ZERO 初始化,避免重复创建对象 + BigDecimal pointTotal = BigDecimal.ZERO; + BigDecimal vipTotal = BigDecimal.ZERO; + BigDecimal courseTotal = BigDecimal.ZERO; + BigDecimal physicalTotal = BigDecimal.ZERO; + BigDecimal trainingClassTotal = BigDecimal.ZERO; + + List yewuTotalList = new ArrayList<>(Collections.nCopies(15, BigDecimal.ZERO)); + BigDecimal totalTotal = new BigDecimal("0"); + for (int i=1;i<=12;i++){ + String month = String.format("%02d", i); + String date = year+"-"+month; + Map resultMap = new HashMap<>(); + BigDecimal monthTotal = new BigDecimal("0"); + resultMap.put("01月份",month); + + List> pointIncomes = ordersService.listMaps(new MPJLambdaWrapper() + .leftJoin(PaymentToOrder.class,PaymentToOrder::getOrderId,Orders::getId) + .leftJoin(Payment.class,Payment::getId,PaymentToOrder::getPaymentId) + .eq(Orders::getType,0) + .apply("DATE_FORMAT(t.order_time, '%Y-%m') = '"+date+"'") + .groupBy(Payment::getType) + .select("IF(t2.type=0,'微信',IF(t2.type=1,'支付宝','银行')) type") + .selectSum(Orders::getFee,"fee").selectSum(Orders::getPoint,"point")); + BigDecimal wxPointFee = getFee(pointIncomes,"微信"); + BigDecimal zfbPointFee = getFee(pointIncomes,"支付宝"); + BigDecimal bankPointFee = getFee(pointIncomes,"银行"); + BigDecimal pointFee = wxPointFee.add(zfbPointFee).add(bankPointFee); + resultMap.put("02微信天医币",wxPointFee); + resultMap.put("03支付宝天医币",zfbPointFee); + resultMap.put("04银行天医币",bankPointFee); + yewuTotalList.set(0,yewuTotalList.get(0).add(wxPointFee)); + yewuTotalList.set(1,yewuTotalList.get(1).add(zfbPointFee)); + yewuTotalList.set(2,yewuTotalList.get(2).add(bankPointFee)); + pointTotal = pointTotal.add(pointFee); + monthTotal = monthTotal.add(pointFee); + + List> vipIncomes = getIncomesList(1,date); + BigDecimal wxVipFee = getFee(vipIncomes,"微信"); + BigDecimal zfbVipFee = getFee(vipIncomes,"支付宝"); + BigDecimal bankVipFee = getFee(vipIncomes,"银行"); + BigDecimal vipFee = wxVipFee.add(zfbVipFee).add(bankVipFee); + resultMap.put("05微信vip",wxVipFee); + resultMap.put("06支付宝vip",zfbVipFee); + resultMap.put("07银行vip",bankVipFee); + yewuTotalList.set(3,yewuTotalList.get(3).add(wxVipFee)); + yewuTotalList.set(4,yewuTotalList.get(4).add(zfbVipFee)); + yewuTotalList.set(5,yewuTotalList.get(5).add(bankVipFee)); + vipTotal = vipTotal.add(vipFee); + monthTotal = monthTotal.add(vipFee); + + List> courseIncomes = getIncomesList(2,date); + BigDecimal wxCourseFee = getFee(courseIncomes,"微信"); + BigDecimal zfbCourseFee = getFee(courseIncomes,"支付宝"); + BigDecimal bankCourseFee = getFee(courseIncomes,"银行"); + BigDecimal courseFee = wxCourseFee.add(zfbCourseFee).add(bankCourseFee); + resultMap.put("08微信课程",wxCourseFee); + resultMap.put("09支付宝课程",zfbCourseFee); + resultMap.put("10银行课程",bankCourseFee); + yewuTotalList.set(6,yewuTotalList.get(6).add(wxCourseFee)); + yewuTotalList.set(7,yewuTotalList.get(7).add(zfbCourseFee)); + yewuTotalList.set(8,yewuTotalList.get(8).add(bankCourseFee)); + courseTotal = courseTotal.add(courseFee); + monthTotal = monthTotal.add(courseFee); + + List> physicalIncomes = getIncomesList(3,date); + BigDecimal wxPhysicalFee = getFee(physicalIncomes,"微信"); + BigDecimal zfbPhysicalFee = getFee(physicalIncomes,"支付宝"); + BigDecimal bankPhysicalFee = getFee(physicalIncomes,"银行"); + BigDecimal physicalFee = wxPhysicalFee.add(zfbPhysicalFee).add(bankPhysicalFee); + resultMap.put("11微信实物",wxPhysicalFee); + resultMap.put("12支付宝实物",zfbPhysicalFee); + resultMap.put("13银行实物",bankPhysicalFee); + yewuTotalList.set(9,yewuTotalList.get(9).add(wxPhysicalFee)); + yewuTotalList.set(10,yewuTotalList.get(10).add(zfbPhysicalFee)); + yewuTotalList.set(11,yewuTotalList.get(11).add(bankPhysicalFee)); + physicalTotal = physicalTotal.add(physicalFee); + monthTotal = monthTotal.add(physicalFee); + + List> trainingClassIncomes = getIncomesList(4,date); + BigDecimal wxTrainingClassFee = getFee(trainingClassIncomes,"微信"); + BigDecimal zfbTrainingClassFee = getFee(trainingClassIncomes,"支付宝"); + BigDecimal bankTrainingClassFee = getFee(trainingClassIncomes,"银行"); + BigDecimal trainingClassFee = wxTrainingClassFee.add(zfbTrainingClassFee).add(bankTrainingClassFee); + resultMap.put("14微信培训班",wxTrainingClassFee); + resultMap.put("15支付宝培训班",zfbTrainingClassFee); + resultMap.put("16银行培训班",bankTrainingClassFee); + yewuTotalList.set(12,yewuTotalList.get(12).add(wxTrainingClassFee)); + yewuTotalList.set(13,yewuTotalList.get(13).add(zfbTrainingClassFee)); + yewuTotalList.set(14,yewuTotalList.get(14).add(bankTrainingClassFee)); + trainingClassTotal = trainingClassTotal.add(trainingClassFee); + monthTotal = monthTotal.add(trainingClassFee); + + totalTotal = totalTotal.add(monthTotal); + resultMap.put("17合计",monthTotal); + resultList.add(resultMap); + } + XSSFWorkbook wb = new XSSFWorkbook(); + Sheet sheet1 = wb.createSheet(year+"全部汇总"); + exportCommon(sheet1 ,resultList); + int rowNum = sheet1.getLastRowNum(); + Row row = sheet1.createRow(rowNum+1); + row.createCell(0).setCellValue("业务合计"); + for (int c=0;c<15;c++){ + row.createCell(c+1).setCellValue(yewuTotalList.get(c).toString()); + } + Row row1 = sheet1.createRow(rowNum+2); + row1.createCell(0).setCellValue("总合计"); + row1.createCell(1).setCellValue(pointTotal.toString()); + row1.createCell(4).setCellValue(vipTotal.toString()); + row1.createCell(7).setCellValue(courseTotal.toString()); + row1.createCell(10).setCellValue(physicalTotal.toString()); + row1.createCell(13).setCellValue(trainingClassTotal.toString()); + row1.createCell(16).setCellValue(totalTotal.toString()); + exportTem(response,wb,year+"全部汇总.xlsx"); return R.ok(); } @@ -364,6 +341,7 @@ public class StatisticsController { .select(""" IF(t.type=3,'实物','培训班') as type, sum(t.fee) as sumFee, + sum(case when t.pay_type = 0 then t.fee else 0 end) as cashFee, sum(case when t.pay_type = 0&&t2.type = 0 then t.fee else 0 end) as wx, sum(case when t.pay_type = 0&&t2.type = 1 then t.fee else 0 end) as zfb, sum(case when t.pay_type = 0&&t2.type = 2 then t.fee else 0 end) as bank, @@ -874,4 +852,306 @@ public class StatisticsController { } } } + + + + + + + //年度统计 + @RequestMapping("/getMonthStatistics") + public R getMonthStatistics(HttpServletResponse response) throws ParseException { + SimpleDateFormat sdfmonth = new SimpleDateFormat("yyyy-MM"); + Date beginDate = sdfmonth.parse("2023-01"); + Date nowDate = sdfmonth.parse(sdfmonth.format(new Date())); + List> resultList = new ArrayList<>(); + for (Date d=beginDate;!d.equals(nowDate);d = DateUtils.addMonths(d,1)){ + String date = sdfmonth.format(d); + Map resultMap = new HashMap<>(); + BigDecimal monthTotal = new BigDecimal("0"); + resultMap.put("01月份",date); + + Orders physical = ordersService.getOne(new MPJLambdaWrapper() + .eq(Orders::getUseFlag,1).eq(Orders::getType,3) + .apply("DATE_FORMAT(t.order_time,'%Y-%m') = '"+date+"'") + .selectSum(Orders::getFee)); + BigDecimal physicalFee = physical==null?BigDecimal.ZERO:physical.getFee(); + resultMap.put("02实物",physicalFee); + monthTotal = monthTotal.add(physicalFee); + + Orders trangingClass = ordersService.getOne(new MPJLambdaWrapper() + .eq(Orders::getUseFlag,1).eq(Orders::getType,4) + .apply("DATE_FORMAT(t.order_time,'%Y-%m') = '"+date+"'") + .selectSum(Orders::getFee)); + BigDecimal trangingClassFee = trangingClass==null?BigDecimal.ZERO:trangingClass.getFee(); + resultMap.put("03培训班",trangingClassFee); + monthTotal = monthTotal.add(trangingClassFee); + + YearMonth yearMonth = YearMonth.parse(date); + SimpleDateFormat sdfday = new SimpleDateFormat("yyyy-MM-dd"); + String day = date+"-"+yearMonth.lengthOfMonth(); + String month = date; + BigDecimal vipNowTotal = BigDecimal.ZERO; + //所有vip订单 + List vipOrders = ordersService.list(new MPJLambdaWrapper() + .eq(Orders::getUseFlag,1).eq(Orders::getType,1)); + //吴门医述订单 + List wumenOrderIds = vipOrders.stream().filter(o -> o.getSource() == 1).map(Orders::getOrderOldId).collect(Collectors.toList()); + List> buyOrders = buyOrderService.listMaps(new MPJLambdaWrapper() + .leftJoin(UserVipLog.class,UserVipLog::getOrderSn,BuyOrder::getOrderSn) + .disableSubLogicDel() + .in(BuyOrder::getOrderId,wumenOrderIds) + .select("t.order_id oid,t1.price fee,DATE_FORMAT(start_time, '%Y-%m-%d %H:%i:%s') startTime,DATE_FORMAT(end_time, '%Y-%m-%d %H:%i:%s') endTime")); + Map buyOrdersMap = new HashMap<>(); + for (Map m : buyOrders) { + List> l = new ArrayList<>(); + if(buyOrdersMap.get(m.get("oid").toString())!=null){ + l = (List>) buyOrdersMap.get(m.get("oid").toString()); + } + l.add(m); + buyOrdersMap.put(m.get("oid").toString(),l); + } + for(Orders orders:vipOrders){ + List> list = new ArrayList<>(); + if (orders.getSource()==1){ + List> l = (List>) buyOrdersMap.get(orders.getOrderOldId()); + for (Map m : l) { + if (m.get("fee")!=null){ + Map map = new HashMap<>(); + map.put("fee",m.get("fee")); + map.put("startTime",m.get("startTime")); + map.put("endTime",m.get("endTime")); + list.add(map); + }else { + Map map = new HashMap<>(); + map.put("fee",orders.getFee()); + map.put("startTime",sdfday.format(orders.getOrderTime())); + map.put("endTime",sdfday.format(orders.getOrderTime())); + list.add(map); + } + } + }else { + FinanceOrder financeOrder = financeOrderService.getById(orders.getOrderOldId()); + Map map = new HashMap<>(); + map.put("fee",financeOrder.getRealMoney()); + map.put("startTime",sdfday.format(financeOrder.getStartTime())); + map.put("endTime",sdfday.format(financeOrder.getEndTime())); + list.add(map); + } + for (Map map:list){ + BigDecimal fee = (BigDecimal) map.get("fee"); + String startTime = map.get("startTime")==null?"":map.get("startTime").toString(); + String endTime = map.get("endTime")==null?"":map.get("endTime").toString(); + if (startTime.equals(endTime)){ + if (sdfmonth.format(orders.getOrderTime()).contains(month)){ + vipNowTotal = vipNowTotal.add(fee); + } else if (sdfmonth.parse(startTime).getTime()sdfmonth.parse(endTime).getTime()){ + //未开始摊销 + }else if (sdfday.parse(day).getTime()0){ + }else { + alreadyDays = 0; + } + //当前月天数 + int nowDays = Integer.parseInt(day.substring(8, 10)); + BigDecimal now = BigDecimal.ZERO; + //如果开始时间是当前月,月天数-开始日=当月摊销天数 + if (startTime.contains(month)){ + nowDays = Integer.parseInt(day.substring(8, 10))-Integer.parseInt(startTime.substring(8, 10))+1; + now = dayAmount.multiply(new BigDecimal(nowDays)); + } else if (endTime.contains(month)) { + now = fee.subtract(dayAmount.multiply(new BigDecimal(alreadyDays))); + }else { + now = dayAmount.multiply(new BigDecimal(nowDays)); + } + vipNowTotal = vipNowTotal.add(now); + } + } + } + resultMap.put("04VIP月摊销",vipNowTotal); + monthTotal = monthTotal.add(vipNowTotal); + + BigDecimal courseNowTotal = BigDecimal.ZERO; + //所有课程订单 + List> courseOrders = ordersService.listMaps(new MPJLambdaWrapper() + .eq(Orders::getUseFlag,1).eq(Orders::getType,2) + .select("DATE_FORMAT(order_time, '%Y-%m-%d %H:%i:%s') orderTime,if(source=0,'一路健康',if(source=1,'吴门医述','管理员')) source,order_old_id orderOldId," + + "tel,order_sn,t.tel,t.fee realMoney") + .orderByAsc(Orders::getOrderTime)); + //一路健康订单课程 + List taihuOrderIds = courseOrders.stream().filter(o -> o.get("source").equals("一路健康")) + .map(map->map.get("orderOldId").toString()).collect(Collectors.toList()); + Map> taihuClassMap = customerApplyCurriculumService.listMaps(new MPJLambdaWrapper() + .in("t.oid", taihuOrderIds) + .apply("t.valid=1 and t.status = '50'") + .select("t.oid,if(t.point>0,t.point,t.money) fee,curriculumID")) + .stream().collect(Collectors.toMap(m -> m.get("oid").toString(), m -> m)); + //订单开课记录 + Map> ctc = customerTaihuClassService.listMaps(new MPJLambdaWrapper() + .like(TCustomerTaihuClass::getDescription,"KC20") + .in(TCustomerTaihuClass::getStatus,10) + .gt(TCustomerTaihuClass::getStudydays,0) + .select("SUBSTRING(description, LOCATE('KC', description), 16) description,oid,DATE_FORMAT(startDate, '%Y-%m-%d') startDate,studyDays")) + .stream().collect(Collectors.toMap(m -> m.get("description").toString()+"-"+m.get("oid").toString(), m -> m)); + //吴门医述订单课程 + List courseWumenOrderIds = courseOrders.stream().filter(o -> o.get("source").equals("吴门医述")) + .map(map->map.get("orderOldId").toString()).collect(Collectors.toList()); + List> buyOrdersList = buyOrderService.listMaps(new MPJLambdaWrapper() + .leftJoin("user_course_buy_log t1 on (t1.order_sn = t.order_sn )") + .leftJoin("user_course_buy t2 on t2.id = t1.user_course_buy_id") + .in("t.order_id",courseWumenOrderIds) + .gt(BuyOrder::getRealMoney,0) + .select("t.order_id oid,t1.id ucblid,if(t1.fee is null,t.real_money,t1.fee) fee,t1.days,t1.begin_day," + + "DATE_FORMAT(t2.start_time, '%Y-%m-%d %H:%i:%s') startTime")); + Map courseBuyOrdersMap = new HashMap<>(); + for (Map m : buyOrdersList) { + List> l = new ArrayList<>(); + if(courseBuyOrdersMap.get(m.get("oid").toString())!=null){ + l = (List>) courseBuyOrdersMap.get(m.get("oid").toString()); + } + l.add(m); + courseBuyOrdersMap.put(m.get("oid").toString(),l); + } + List> result = new ArrayList<>(); + for(Map courseOrder:courseOrders){ + String orderTime = courseOrder.get("orderTime").toString().substring(0,10); + if (courseOrder.get("source").equals("一路健康")){ + Map res = new HashMap<>(); + Map taihuClass = taihuClassMap.get(courseOrder.get("orderOldId").toString()); + Map tc = ctc.entrySet().stream().filter(e -> e.getKey() + .contains(taihuClass.get("curriculumID").toString())).map(Map.Entry::getValue).findFirst().orElse(null); + res.put("fee",courseOrder.get("realMoney")); + if (tc != null&&tc.get("startDate")!=null) { + res.put("startTime",tc.get("startDate")); + res.put("endTime",sdfday.format(DateUtils.addDays(sdfday.parse(tc.get("startDate").toString()), (Integer) tc.get("studyDays")))); + }else { + res.put("startTime",orderTime); + res.put("endTime",orderTime); + } + res.putAll(courseOrder); + result.add(res); + }else if(courseOrder.get("source").equals("吴门医述")){ + List> l = (List>) courseBuyOrdersMap.get(courseOrder.get("orderOldId")); + if (l!=null){ + for (int i=0;i res = new HashMap<>(); + Map m = l.get(i); + if (m.get("ucblid")!=null){ + if (new BigDecimal(m.get("fee").toString()).compareTo(BigDecimal.ZERO)>0){ + res.put("fee",m.get("fee")); + }else { + BigDecimal one = new BigDecimal(courseOrder.get("realMoney").toString()).divide(new BigDecimal(l.size()),2,BigDecimal.ROUND_HALF_UP); + if (i==l.size()-1){ + res.put("fee",new BigDecimal(courseOrder.get("realMoney").toString()).subtract(one.multiply(new BigDecimal(l.size()-1)))); + }else { + res.put("fee",one); + } + } + if (m.get("startTime")==null){ + res.put("startTime",null); + res.put("endTime",null); + }else { + if (Integer.parseInt(m.get("begin_day").toString())==0){ + res.put("startTime",m.get("startTime").toString()); + res.put("endTime",sdfday.format(DateUtils.addDays(sdfday.parse(m.get("startTime").toString()), + Integer.parseInt(m.get("days").toString())-1))); + }else { + res.put("startTime",sdfday.format(DateUtils.addDays(sdfday.parse(m.get("startTime").toString()), + Integer.parseInt(m.get("days").toString())))); + res.put("endTime",sdfday.format(DateUtils.addDays(sdfday.parse(res.get("startTime").toString()), + Integer.parseInt(m.get("days").toString())-1))); + } + } + }else { + res.put("fee",courseOrder.get("realMoney")); + res.put("startTime",orderTime); + res.put("endTime",orderTime); + } + res.putAll(courseOrder); + result.add(res); + } + }else { + Map res = new HashMap<>(); + res.put("fee",courseOrder.get("realMoney")); + res.put("startTime",orderTime); + res.put("endTime",orderTime); + res.putAll(courseOrder); + result.add(res); + } + }else { + FinanceOrder financeOrder = financeOrderService.getById(courseOrder.get("orderOldId").toString()); + courseOrder.put("fee",financeOrder.getRealMoney()); + courseOrder.put("startTime",sdfday.format(financeOrder.getStartTime())); + courseOrder.put("endTime",sdfday.format(financeOrder.getEndTime())); + result.add(courseOrder); + } + } + for (Map map:result) { + BigDecimal fee = (BigDecimal) map.get("fee"); + String startTime = (String) map.get("startTime"); + String endTime = (String) map.get("endTime"); + if (startTime==null){ + if (sdfmonth.parse(map.get("orderTime").toString()).getTime()<=sdfmonth.parse(month).getTime()){ + } + }else if (startTime.equals(endTime)){ + if (startTime.contains(month)){ + courseNowTotal = courseNowTotal.add(fee); + } else if (sdfmonth.parse(startTime).getTime()sdfmonth.parse(endTime).getTime()){ + }else if (sdfday.parse(day).getTime()0){ + }else { + alreadyDays = 0; + } + //当前月天数 + int nowDays = Integer.parseInt(day.substring(8, 10)); + BigDecimal now = BigDecimal.ZERO; + //如果开始时间是当前月,月天数-开始日=当月摊销天数 + if (startTime.contains(month)&&endTime.contains(month)){ + now = fee; + } else if (startTime.contains(month)){ + nowDays = Integer.parseInt(day.substring(8, 10))-Integer.parseInt(startTime.substring(8, 10))+1; + now = dayAmount.multiply(new BigDecimal(nowDays)); + } else if (endTime.contains(month)) { + now = fee.subtract(dayAmount.multiply(new BigDecimal(alreadyDays))); + }else { + now = dayAmount.multiply(new BigDecimal(nowDays)); + } + courseNowTotal = courseNowTotal.add(now); + } + } + resultMap.put("05课程月摊销",courseNowTotal); + monthTotal = monthTotal.add(courseNowTotal); + resultMap.put("06合计",monthTotal); + resultList.add(resultMap); + } + XSSFWorkbook wb = new XSSFWorkbook(); + Sheet sheet1 = wb.createSheet("全部汇总"); + exportCommon(sheet1 ,resultList); + exportTem(response,wb,"全部汇总.xlsx"); + return R.ok(); + } }