package com.tievd.jyz.service.impl; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.tievd.jyz.constants.SystemConstant; import com.tievd.jyz.entity.OilRecord; import com.tievd.jyz.entity.OilStatis; import com.tievd.jyz.entity.TrafficFlow; import com.tievd.jyz.entity.vo.DataStatisReqVo; import com.tievd.jyz.entity.vo.OilVolumeVo; import com.tievd.jyz.entity.vo.StatDataTableVo; import com.tievd.jyz.mapper.OilRecordMapper; import com.tievd.jyz.mapper.OilStaticMapper; import com.tievd.jyz.mapper.TrafficFlowMapper; import com.tievd.jyz.service.IOilRecordService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * OilRecord * @author cube * @since 2023-02-27 * @version V2.0.0 */ @Service @Log4j2 public class OilRecordServiceImpl extends ServiceImpl implements IOilRecordService { @Autowired OilRecordMapper oilRecordMapper; @Autowired TrafficFlowMapper trafficFlowMapper; @Autowired OilStaticMapper oilStaticMapper; @Override public Map statisOilPosition(String licenseNum, String orgCode) { Map res = new HashMap(); List positionList = oilRecordMapper.statisOilPosition(licenseNum, orgCode); List countList = new ArrayList<>(); try { //加油位多边形统计数据 Object max = positionList.stream().max(Comparator.comparingInt(m -> Integer.valueOf(m.get("count").toString()))).get().get("count"); for (Map map : positionList) { countList.add(Integer.valueOf(map.get("count").toString())); map.put("max", max); } } catch (Exception e) { log.error("加油位统计失败", e); } res.put("count", countList); res.put("oilPosition", positionList); return res; } @Override public Map statisByMonth(String licenseNum, String orgCode) { Map res = new HashMap(); try { List monthCountList = oilRecordMapper.statisByMonth(licenseNum, orgCode); res = convertToStatisList(monthCountList); } catch (Exception e) { log.error("车辆月统计失败", e); } return res; } private Map convertToStatisList(List dataList) { Set keys = dataList.get(0).keySet(); Map res = new HashMap(); for (Object key : keys) { List convertList = new ArrayList(); for (Map map : dataList) { convertList.add(map.get(key)); } res.put(key, convertList); } return res; } @Override public Map statisByHour(String licenseNum, String orgCode) { Map res = new HashMap(); try { List hourCountList = oilRecordMapper.statisByHour(licenseNum, orgCode); res = convertToStatisList(hourCountList); } catch (Exception e) { log.error("车辆时统计失败", e); } return res; } @Override public Map statisByStayTime(String licenseNum, String orgCode) { Map res = new HashMap(); try { List stayCountList = oilRecordMapper.statisByStayTime(licenseNum, orgCode); res = convertToStatisList(stayCountList); } catch (Exception e) { log.error("车辆停留时长统计失败", e); } return res; } /** * 加油量分页 */ @Override public IPage getStatisOilVolume(IPage page, String orgCode, String dateMonth) { return oilRecordMapper.getStatisOilVolume(page, orgCode, dateMonth); } @Override public Map getOilVolumeTotal(String orgCode, String dateMonth) { return oilRecordMapper.getOilVolumeTotal(orgCode, dateMonth); } /** * 加油量详情 */ @Override public IPage descOilVolumeList(IPage page, Map map) { return oilRecordMapper.descOilVolumeList(page, map); } @Override public StatDataTableVo statisTotal(DataStatisReqVo param) { return oilRecordMapper.statisTotal(param); } @Override public List statisOrgTopTraffic(DataStatisReqVo param) { return oilRecordMapper.statisOrgTopTraffic(param); } @Override public List statisOrgTopOil(DataStatisReqVo param) { return oilRecordMapper.statisOrgTopOil(param); } @Override public List statisOrgTopVolume(DataStatisReqVo param) { return oilRecordMapper.statisOrgTopVolume(param); } @Override public List statisOilFreqCompare(DataStatisReqVo param) { return oilRecordMapper.statisOilFreqCompare(param); } @Override public JSONObject statFan(DataStatisReqVo param) { JSONObject res; List dataList = new ArrayList<>(); Function xfunc = null; Function barfunc = null; switch(param.getType()) { case 1 : dataList = oilRecordMapper.statFanByModel(param); xfunc = StatDataTableVo::getModelName; barfunc = StatDataTableVo::getOilCount; break; case 2 : dataList = oilRecordMapper.statFanByPosition(param); xfunc = StatDataTableVo::getOilPosition; barfunc = StatDataTableVo::getOilCount; break; case 3 : dataList = oilRecordMapper.statFanByModel(param); xfunc = StatDataTableVo::getModelName; barfunc = StatDataTableVo::getOilVolume; break; case 4 : dataList = oilRecordMapper.statFanByPosition(param); xfunc = StatDataTableVo::getOilPosition; barfunc = StatDataTableVo::getOilVolume; break; case 5 : dataList = oilRecordMapper.statFanByOilType(param); xfunc = StatDataTableVo::getOilType; barfunc = StatDataTableVo::getOilVolume; break; case 6 : dataList = oilRecordMapper.statFanByOilType(param); xfunc = StatDataTableVo::getOilType; barfunc = StatDataTableVo::getTotalAmount; break; } res = dataTransLists(dataList, xfunc, barfunc, null, "", ""); return res; } @Override public JSONObject statBar(DataStatisReqVo param) { JSONObject res; List dataList; Function xfunc; Function barfunc; Function linefunc; String barName = ""; String lineName = ""; if (param.getType() == 1) { dataList = oilRecordMapper.statBarByModel(param); xfunc = StatDataTableVo::getModelName; barfunc = StatDataTableVo::getOilCount; linefunc = StatDataTableVo::getCarCount; barName = "加油数"; lineName = "车流量"; } else if (param.getType() == 2) { dataList = oilRecordMapper.statFanByPosition(param); xfunc = StatDataTableVo::getOilPosition; barfunc = StatDataTableVo::getOilCount; linefunc = StatDataTableVo::getOilVolume; barName = "加油数"; lineName = "油品销量"; } else if (param.getType() == 3) { dataList = oilRecordMapper.statFanByOilType(param); xfunc = StatDataTableVo::getOilType; barfunc = StatDataTableVo::getOilVolume; linefunc = StatDataTableVo::getTotalAmount; barName = "油品销量"; lineName = "销售金额"; } else { dataList = oilRecordMapper.statFanByOilType(param); xfunc = StatDataTableVo::getOilType; barfunc = StatDataTableVo::getTotalAmount; linefunc = StatDataTableVo::getOilVolume; barName = "销售金额"; lineName = "油品销量"; } res = dataTransLists(dataList, xfunc, barfunc, linefunc, barName, lineName); return res; } /** * 加油相关图表 * @param param * @return */ @Override public JSONObject statTrend(DataStatisReqVo param) { DataStatisReqVo.StatUnit timeUnit = param.getTimeUnit(); DataStatisReqVo.TrendType trendType = param.getTrendType(); //时间区间 LocalDateTime timeLimit = LocalDateTime.now() .minus(timeUnit.value(), ChronoUnit.valueOf(timeUnit.name())) .with(timeUnit.initField(), 1); LocalDateTime timeLimitRight = LocalDateTime.now().with(timeUnit.initField(), 1); log.info("打印时间开始: {}, 打印时间结束: {}", timeLimit.toString(), timeLimitRight.toString()); LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .ge(OilRecord::getStartTime, timeLimit.toString()) .le(OilRecord::getStartTime, timeLimitRight.toString()) .likeRight(OilRecord::getOrgCode, param.getOrgCode()); List records = this.list(wrapper); //x轴 Map statVoMap = new HashMap<>(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeUnit.statFormat()); for (int i = 0; i < timeUnit.value(); i++) { LocalDateTime time = timeLimit.plus(i, ChronoUnit.valueOf(timeUnit.name())); String key = time.format(formatter); String preKey = time.minus(1, ChronoUnit.valueOf(timeUnit.name())).format(formatter); StatDataTableVo statVo = new StatDataTableVo().setStatTime(time); if (statVo.getPreStatVo() == null) statVo.setPreStatVo(statVoMap.getOrDefault(preKey, new StatDataTableVo())); statVoMap.put(key, statVo); } for (OilRecord record : records) { String key = formatter.format(record.getStartTime().toLocalDateTime()); if (!statVoMap.containsKey(key)) { continue; } StatDataTableVo statVo = statVoMap.get(key); statVo.addAppearCount(1); if (record.getBehavior().intValue() == SystemConstant.BEHAVIOR_TYPE_OIL) statVo.addOilCount(1); if (record.getBehavior().intValue() == SystemConstant.BEHAVIOR_TYPE_OIL) statVo.addOilVolume(record.getOilVolume()); if (record.getBehavior().intValue() == SystemConstant.BEHAVIOR_TYPE_OIL) statVo.addTotalAmount(record.getTotalAmount()); statVo.addSumSpand(record.getSpandTime()); } //车流量 switch(trendType) { case TRAFFIC: wrapper = new LambdaQueryWrapper() .select(TrafficFlow::getCarCount, TrafficFlow::getCaptureTime, TrafficFlow::getOrgCode) .ge(TrafficFlow::getCaptureTime, timeLimit.toString()) .le(TrafficFlow::getCaptureTime, timeLimitRight.toString()) .likeRight(TrafficFlow::getOrgCode, param.getOrgCode()); List trafficList = trafficFlowMapper.selectList(wrapper); for (TrafficFlow traffic : trafficList) { String key = formatter.format(traffic.getCaptureTime().toLocalDateTime()); if (!statVoMap.containsKey(key)) continue; StatDataTableVo statVo = statVoMap.get(key); statVo.addCarCount(traffic.getCarCount()); } break; } Function xFunc = t -> t.getStatTime().format(formatter); Function barFunc = trendType.getBarFunc(); Function lineFunc = trendType.getLineFunc(); String barName = trendType.getBarName(); String lineName = trendType.getLineName(); List dataList = new ArrayList<>(statVoMap.values()); dataList.sort((t1, t2) -> t1.getStatTime().compareTo(t2.getStatTime())); JSONObject res = dataTransLists(dataList, xFunc, barFunc, lineFunc, barName, lineName); return res; } /** * 客户图表 * @param param * @return */ @Override public JSONObject statTrendClient(DataStatisReqVo param) { DataStatisReqVo.StatUnit timeUnit = param.getTimeUnit(); DataStatisReqVo.TrendType trendType = param.getTrendType(); //时间区间 LocalDateTime timeLimit = LocalDateTime.now() .minus(timeUnit.value(), ChronoUnit.valueOf(timeUnit.name())) .with(timeUnit.initField(), 1); LocalDateTime timeLimitRight = LocalDateTime.now().with(timeUnit.initField(), 1); //x轴 Map timeValMap = new TreeMap<>(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeUnit.statFormat()); for (int i = 0; i < timeUnit.value(); i++) { LocalDateTime time = timeLimit.plus(i, ChronoUnit.valueOf(timeUnit.name())); String key = time.format(formatter); timeValMap.put(key, 0); } LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .ge(OilStatis::getUpdateTimeSelf, timeLimit.toString()) .le(OilStatis::getUpdateTimeSelf, timeLimitRight.toString()) .likeRight(OilStatis::getOrgCode, param.getOrgCode()); List oilStatis = oilStaticMapper.selectList(wrapper); List barDatas = new ArrayList(); List lineDatas = new ArrayList(); switch(trendType) { case CLIENT: Map> dataMap = new HashMap<>(); for (OilStatis stat : oilStatis) { dataMap.putIfAbsent(stat.getClientName(), new TreeMap(){{putAll(timeValMap);}}); Map client = dataMap.get(stat.getClientName()); String key = formatter.format(stat.getUpdateTimeSelf().toLocalDateTime()); if (!client.containsKey(key)) continue; client.put(key, client.get(key) + 1); } barDatas = dataMap.entrySet().stream().map(e -> { JSONObject barData = new JSONObject(); barData.put("name", e.getKey()); barData.put("value", e.getValue().values()); return barData; }).collect(Collectors.toList()); break; case LOSE_CLIENT: Map sumMap = new HashMap(){{putAll(timeValMap);}}; for (OilStatis stat : oilStatis) { String key = formatter.format(stat.getUpdateTimeSelf().toLocalDateTime()); if (!timeValMap.containsKey(key)) continue; sumMap.put(key, sumMap.get(key) + 1); if (stat.getClientId() == SystemConstant.LOSE_CLIENT_ID) { timeValMap.put(key, timeValMap.get(key) + 1); } } lineDatas = timeValMap.entrySet().stream().map(e -> sumMap.get(e.getKey()) == 0 ? 0 : e.getValue() * 100 / sumMap.get(e.getKey()) ).collect(Collectors.toList()); break; } List xDatas = new ArrayList<>(timeValMap.keySet()); JSONObject res = new JSONObject(); res.put("xData", xDatas); res.put("barData", barDatas); res.put("lineData", lineDatas); return res; } @Override public List> statTrendDetail(DataStatisReqVo param) { if (param.getTrendType() == null || param.getTimeUnit() == null || param.getStatTime() == null) { return new ArrayList<>(); } DataStatisReqVo.TrendType trendType = param.getTrendType(); DataStatisReqVo.StatUnit timeUnit = param.getTimeUnit(); LocalDateTime[] timeRange = getTrendTimeRange(timeUnit); LocalDateTime timeLimit = timeRange[0]; LocalDateTime timeLimitRight = timeRange[1]; DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeUnit.statFormat()); String statTime = param.getStatTime(); List> detailList = new ArrayList<>(); if (trendType == DataStatisReqVo.TrendType.TRAFFIC) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .ge(TrafficFlow::getCaptureTime, timeLimit.toString()) .le(TrafficFlow::getCaptureTime, timeLimitRight.toString()) .likeRight(TrafficFlow::getOrgCode, param.getOrgCode()) .orderByDesc(TrafficFlow::getCaptureTime); List list = trafficFlowMapper.selectList(wrapper); for (TrafficFlow trafficFlow : list) { if (!matchStatTime(trafficFlow.getCaptureTime().toLocalDateTime(), formatter, statTime)) { continue; } Map row = new LinkedHashMap<>(); row.put("id", trafficFlow.getId()); row.put("captureTime", trafficFlow.getCaptureTime()); row.put("carCount", trafficFlow.getCarCount()); row.put("modelCode", trafficFlow.getModelCode()); row.put("cameraCode", trafficFlow.getCameraCode()); detailList.add(row); } return detailList; } if (trendType == DataStatisReqVo.TrendType.CLIENT || trendType == DataStatisReqVo.TrendType.LOSE_CLIENT) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .ge(OilStatis::getUpdateTimeSelf, timeLimit.toString()) .le(OilStatis::getUpdateTimeSelf, timeLimitRight.toString()) .likeRight(OilStatis::getOrgCode, param.getOrgCode()) .orderByDesc(OilStatis::getUpdateTimeSelf); List list = oilStaticMapper.selectList(wrapper); for (OilStatis oilStatis : list) { if (!matchStatTime(oilStatis.getUpdateTimeSelf().toLocalDateTime(), formatter, statTime)) { continue; } if (trendType == DataStatisReqVo.TrendType.CLIENT && param.getSeriesName() != null && !param.getSeriesName().equals(oilStatis.getClientName())) { continue; } if (trendType == DataStatisReqVo.TrendType.LOSE_CLIENT && (oilStatis.getClientId() == null || oilStatis.getClientId() != SystemConstant.LOSE_CLIENT_ID)) { continue; } Map row = new LinkedHashMap<>(); row.put("id", oilStatis.getId()); row.put("updateTimeSelf", oilStatis.getUpdateTimeSelf()); row.put("licenseNum", oilStatis.getLicenseNum()); row.put("clientName", oilStatis.getClientName()); row.put("oilCount", oilStatis.getOilCount()); row.put("oilSum", oilStatis.getOilSum()); detailList.add(row); } return detailList; } LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .ge(OilRecord::getStartTime, timeLimit.toString()) .le(OilRecord::getStartTime, timeLimitRight.toString()) .likeRight(OilRecord::getOrgCode, param.getOrgCode()) .orderByDesc(OilRecord::getStartTime); List records = this.list(wrapper); for (OilRecord oilRecord : records) { if (!matchStatTime(oilRecord.getStartTime().toLocalDateTime(), formatter, statTime)) { continue; } if (trendType == DataStatisReqVo.TrendType.OIL && (oilRecord.getBehavior() == null || oilRecord.getBehavior().intValue() != SystemConstant.BEHAVIOR_TYPE_OIL)) { continue; } if (trendType == DataStatisReqVo.TrendType.OIL_vOLUME && (oilRecord.getBehavior() == null || oilRecord.getBehavior().intValue() != SystemConstant.BEHAVIOR_TYPE_OIL)) { continue; } if (trendType == DataStatisReqVo.TrendType.SALES_AMOUNT && (oilRecord.getBehavior() == null || oilRecord.getBehavior().intValue() != SystemConstant.BEHAVIOR_TYPE_OIL)) { continue; } Map row = new LinkedHashMap<>(); row.put("id", oilRecord.getId()); row.put("startTime", oilRecord.getStartTime()); row.put("licenseNum", oilRecord.getLicenseNum()); row.put("behavior", oilRecord.getBehavior()); row.put("behaviorText", behaviorText(oilRecord.getBehavior())); row.put("oilPosition", oilRecord.getOilPosition()); row.put("oilVolume", oilRecord.getOilVolume()); row.put("totalAmount", oilRecord.getTotalAmount()); row.put("spandTime", oilRecord.getSpandTime()); detailList.add(row); } return detailList; } private LocalDateTime[] getTrendTimeRange(DataStatisReqVo.StatUnit timeUnit) { LocalDateTime timeLimit = LocalDateTime.now() .minus(timeUnit.value(), ChronoUnit.valueOf(timeUnit.name())) .with(timeUnit.initField(), 1); LocalDateTime timeLimitRight = LocalDateTime.now().with(timeUnit.initField(), 1); return new LocalDateTime[]{timeLimit, timeLimitRight}; } private boolean matchStatTime(LocalDateTime time, DateTimeFormatter formatter, String statTime) { return formatter.format(time).equals(statTime); } private String behaviorText(Byte behavior) { if (behavior == null) { return ""; } if (behavior.intValue() == SystemConstant.BEHAVIOR_TYPE_OIL) { return "加油"; } if (behavior.intValue() == SystemConstant.BEHAVIOR_TYPE_TMP) { return "停靠"; } return behavior.toString(); } private JSONObject dataTransLists( List dataList, Function xDataMapper, Function barDataMapper, Function lineDataMapper, String barName, String lineName) { List xDatas = new ArrayList(); List barDatas = new ArrayList<>(); List lineDatas = new ArrayList<>(); double sum = 0; for (E statVo : dataList) { Object xData = ""; Object barData = 0; Object lineData = 0; try { xData = xDataMapper.apply(statVo); Object barValue = barDataMapper.apply(statVo); if (barValue instanceof java.math.BigDecimal) { barData = ((java.math.BigDecimal) barValue).doubleValue(); } else { barData = Integer.valueOf(barValue.toString()); } if (lineDataMapper != null) lineData = lineDataMapper.apply(statVo); } catch (Exception e) { e.printStackTrace(); log.error("统计出现异常", e); } xDatas.add(xData); barDatas.add(barData); lineDatas.add(lineData); if (barData instanceof Number) { sum += ((Number) barData).doubleValue(); } } if (lineDataMapper == null) { double finalSum = sum; lineDatas = barDatas.stream().map(n -> { if (n instanceof Number) { return ((Number) n).doubleValue() * 100 / finalSum; } return 0; }).collect(Collectors.toList()); } JSONObject res = new JSONObject(); res.put("xData", xDatas); res.put("barData", barDatas); res.put("lineData", lineDatas); res.put("barName", barName); res.put("lineName", lineName); return res; } }