package com.kym.service.miniapp.impl; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.ExcelWriter; import com.github.pagehelper.PageHelper; import com.kym.common.exception.BusinessException; import com.kym.common.utils.CommUtil; import com.kym.common.utils.HttpUtil; import com.kym.entity.admin.Activity; import com.kym.entity.admin.StationStatDay; import com.kym.entity.admin.StationStatMonth; import com.kym.entity.admin.queryParams.CustomChargeOrdersQueryParam; import com.kym.entity.admin.queryParams.StatQueryParam; import com.kym.entity.admin.vo.CustomOrderVo; import com.kym.entity.admin.vo.StationStatVo; import com.kym.entity.common.PageBean; import com.kym.entity.common.RedisKeys; import com.kym.entity.miniapp.ChargeOrder; import com.kym.entity.miniapp.queryParams.OrderQueryParams; import com.kym.entity.miniapp.vo.ChargeOrderVo; import com.kym.mapper.miniapp.ChargeOrderMapper; import com.kym.service.admin.ExportService; import com.kym.service.admin.StationStatDayService; import com.kym.service.admin.StationStatMonthService; import com.kym.service.cache.KymCache; import com.kym.service.miniapp.ChargeOrderService; import com.kym.service.miniapp.UserCouponService; import com.kym.service.miniapp.UserRechargeRightsService; import com.kym.service.mybatisplus.MyBaseServiceImpl; import jakarta.servlet.http.HttpServletResponse; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import okhttp3.Headers; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** *

* 充电订单表 服务实现类 *

* * @author skyline * @since 2023-08-08 */ @Service @Slf4j public class ChargeOrderServiceImpl extends MyBaseServiceImpl implements ChargeOrderService { private final ExportService exportService; private final UserCouponService userCouponService; private final UserRechargeRightsService userRechargeRightsService; private final StationStatDayService stationStatDayService; private final StationStatMonthService stationStatMonthService; private final StringRedisTemplate redisTemplate; @Value("${en-plus.sassClose}") public String saasClose; public ChargeOrderServiceImpl(ExportService exportService, @Lazy UserCouponService userCouponService, UserRechargeRightsService userRechargeRightsService, StationStatDayService stationStatDayService, StationStatMonthService stationStatMonthService, StringRedisTemplate redisTemplate) { this.exportService = exportService; this.userCouponService = userCouponService; this.userRechargeRightsService = userRechargeRightsService; this.stationStatDayService = stationStatDayService; this.stationStatMonthService = stationStatMonthService; this.redisTemplate = redisTemplate; } @Override public ChargeOrder getChargingOrderByUserId(Long userId) { return lambdaQuery() .eq(ChargeOrder::getUserId, userId) .eq(ChargeOrder::getOrderStatus, ChargeOrder.ORDER_STATUS_未知) .in(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_预约中, ChargeOrder.CHARGE_STATUS_启动中, ChargeOrder.CHARGE_STATUS_充电中, ChargeOrder.CHARGE_STATUS_停止中) .one(); } @Override public ChargeOrder getChargingOrderByStartChargeSeq(String startChargeSeq) { return lambdaQuery().eq(ChargeOrder::getStartChargeSeq, startChargeSeq).one(); } @Override public PageBean customChargeOrders(CustomChargeOrdersQueryParam params) { if (params.getConnectorId() != null) { var connectorId = KymCache.INSTANCE.getConnectorId(params.getConnectorId()); params.setConnectorId(connectorId); } // 判断数据权限 if (params.getStationId() == null) { params.setStationId(CommUtil.isEmptyOrNull(KymCache.INSTANCE.getAdminUserStationIds(StpUtil.getLoginIdAsLong())) ? null : KymCache.INSTANCE.getAdminUserStationIds(StpUtil.getLoginIdAsLong()).get(0)); } PageHelper.startPage(params.getPageNum(), params.getPageSize()); // 查询订单列表(订单编号,手机号,充电站,充电桩SN/短码,订单状态,建单时间,结算时间,充电电量,实付金额,付款状态) var result = baseMapper.listChargeOrders(params); var page = new PageBean<>(result); page.setList(result.stream().map(item -> item.setShortId(KymCache.INSTANCE.getShortIdByEquipmentIdOrConnectorId(item.getConnectorId())) .setStationName(KymCache.INSTANCE.getStationNameById(item.getStationId()))).collect(Collectors.toList())); var map = baseMapper.statChargeOrders(params); return page.setExtraData(map); } @SneakyThrows @Override public void exportCustomChargeOrders(CustomChargeOrdersQueryParam params, HttpServletResponse response) { if (params.getConnectorId() != null) { var connectorId = KymCache.INSTANCE.getConnectorId(params.getConnectorId()); params.setConnectorId(connectorId); } // 判断数据权限 var adminStationIds = KymCache.INSTANCE.getAdminUserStationIds(StpUtil.getLoginIdAsLong()); if (params.getStationId() != null && adminStationIds.contains(params.getStationId())) { params.setStationId(adminStationIds.get(0)); } // 查询订单列表(订单编号,手机号,充电站,充电桩SN/短码,订单状态,建单时间,结算时间,充电电量,实付金额,付款状态) var result = baseMapper.listChargeOrders(params); result = result.stream().map(item -> item.setShortId(KymCache.INSTANCE.getShortIdByEquipmentIdOrConnectorId(item.getConnectorId())) .setStationName(KymCache.INSTANCE.getStationNameById(item.getStationId()))) .toList(); // stationId,startChargeSeq,connectorId,startTime,endTime,totalPower,totalMoney,elecMoney,serviceMoney,orderStatus,chargeStatus,stopReason,invoiceStatus var rows = result.stream().map(item -> { var map = new HashMap(); map.put("stationId", item.getStationId()); map.put("startChargeSeq", item.getStartChargeSeq()); map.put("connectorId", item.getConnectorId()); map.put("startTime", item.getStartTime() == null ? "-" : item.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); map.put("endTime", item.getEndTime() == null ? "-" : item.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); map.put("totalPower", item.getTotalPower()); map.put("totalMoney", BigDecimal.valueOf(item.getTotalMoney()).divide(BigDecimal.valueOf(100))); map.put("elecMoney", BigDecimal.valueOf(item.getElecMoney()).divide(BigDecimal.valueOf(100))); map.put("serviceMoney", BigDecimal.valueOf(item.getServiceMoney()).divide(BigDecimal.valueOf(100))); map.put("orderStatus", item.getOrderStatus()); map.put("chargeStatus", item.getChargeStatus()); return map; }).toList(); // 通过工具类创建writer,默认创建xls格式 ExcelWriter writer = ExcelUtil.getWriter(); //自定义标题别名 writer.addHeaderAlias("stationId", "站点ID"); writer.addHeaderAlias("startChargeSeq", "充电订单号"); writer.addHeaderAlias("connectorId", "充电设备接口编号"); writer.addHeaderAlias("startTime", "充电开始时间"); writer.addHeaderAlias("endTime", "充电结束时间"); writer.addHeaderAlias("totalPower", "充电量(度)"); writer.addHeaderAlias("totalMoney", "累积总金额(元)"); writer.addHeaderAlias("elecMoney", "累积电费(元)"); writer.addHeaderAlias("serviceMoney", "累积服务费(元)"); writer.addHeaderAlias("orderStatus", "订单状态"); writer.addHeaderAlias("chargeStatus", "充电状态"); exportService.exportExcel("订单列表", writer, rows, response); } @Override public PageBean listUserChargeOrders(OrderQueryParams params) { PageHelper.startPage(params.getPageNum(), params.getPageSize()); var list = lambdaQuery() .eq(!CommUtil.isEmptyOrNull(params.getInvoiceStatus()), ChargeOrder::getInvoiceStatus, params.getInvoiceStatus()) .eq(ChargeOrder::getUserId, StpUtil.getLoginIdAsLong()).orderByDesc(ChargeOrder::getId).list(); var res = new PageBean<>(list); var voList = list.stream().map(chargeOrder -> { var vo = new ChargeOrderVo(); BeanUtils.copyProperties(chargeOrder, vo); vo.setPayServiceAmount(vo.getServiceMoney() - vo.getDiscountAmount()); return vo; }).toList(); return new PageBean<>(voList).setList(res); } @Override public ChargeOrderVo orderDetailForApp(String startChargeSeq) { var chargeOrder = lambdaQuery().eq(ChargeOrder::getStartChargeSeq, startChargeSeq).one(); // 订单对应的优惠信息 var orderVo = new ChargeOrderVo(); BeanUtils.copyProperties(chargeOrder, orderVo); orderVo.setStationName(KymCache.INSTANCE.getStationNameById(chargeOrder.getStationId())); // todo 修改成只显示优惠金额,具体优惠信息点击详情查看具体权益卡/优惠券 // if (chargeOrder.getDiscountAmount() > 0) { // // 充值权益 // var orderRechargeRight = orderRechargeRightsService.lambdaQuery().eq(OrderRechargeRights::getStartChargeSeq, startChargeSeq).one(); // DynamicDataSourceContextHolder.push("db-admin"); // var rechargeRights = rechargeRightsService.lambdaQuery().eq(RechargeRights::getId, orderRechargeRight.getRightsId()).one(); // DynamicDataSourceContextHolder.poll(); // var desc = rechargeRights.getRightsDesc(); // orderVo.setRightsDesc(desc); // } return orderVo; } @Override public Object orderDiscountDetail(String startChargeSeq, String discountType) { return switch (discountType) { case Activity.DISCOUNT_TYPE_服务费折扣权益 -> userRechargeRightsService.getUserOrderRechargeRights(startChargeSeq); case Activity.DISCOUNT_TYPE_优惠券 -> userCouponService.getUserOrderCoupon(startChargeSeq); default -> throw new BusinessException("未知的优惠类型"); }; } /** * 通过En+ sass关闭订单 * * @param startChargeSeq */ @Override public void closeChargeOrder(String startChargeSeq) { Headers headers = Headers.of("satoken", redisTemplate.opsForValue().get(RedisKeys.EN_PLUS_SASS_TOKEN)); var res = HttpUtil.parseJson(HttpUtil.post(saasClose + startChargeSeq, headers)); if (!(res.containsKey("success") && res.getBoolean("success"))) { log.error("关闭订单失败:{}", res); throw new BusinessException("关闭订单失败"); } } /** * 站点统计 * * @param params * @return */ @Override public PageBean stationStat(StatQueryParam params) { // 判断数据权限 var adminStationIds = KymCache.INSTANCE.getAdminUserStationIds(StpUtil.getLoginIdAsLong()); if (params.getStationId() == null && !adminStationIds.isEmpty()) { params.setStationId(adminStationIds.get(0)); } PageHelper.startPage(params.getPageNum(), params.getPageSize()); var res = baseMapper.stationStat(params).stream().peek(item -> { item.setElecMoneyPercent((new BigDecimal(item.getElecMoney())).divide(new BigDecimal(Math.max(1, item.getTotalMoney())), 2, RoundingMode.HALF_UP)); item.setServiceMoneyPercent(BigDecimal.ONE.subtract(item.getElecMoneyPercent())); }).collect(Collectors.toList()); var map = Map.of( "totalPower", BigDecimal.valueOf(res.stream().mapToDouble(StationStatVo::getTotalPower).sum()).setScale(2, RoundingMode.HALF_UP).doubleValue(), "serviceMoney", res.stream().mapToInt(StationStatVo::getServiceMoney).sum(), "payServiceAmount", res.stream().mapToInt(StationStatVo::getPayServiceAmount).sum() ); return new PageBean<>(res).setExtraData(map); } /** * 站点统计详情 * * @param params * @return */ @Override public Map stationStatDetail(StatQueryParam params) { CommUtil.asserts(CommUtil.isNotEmptyAndNull(params.getStationIds()), "站点不能为空"); if (params.getType().equals(StatQueryParam.TYPE_DAY)) { return stationStatDayService.lambdaQuery() .in(StationStatDay::getStationId, params.getStationIds()) .ge(StationStatDay::getStatDay, params.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) .le(StationStatDay::getStatDay, params.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) .orderByAsc(StationStatDay::getStatDay) .list().stream().collect(Collectors.groupingBy(StationStatDay::getStationId, Collectors.toList())); } else { return stationStatMonthService.lambdaQuery() .in(StationStatMonth::getStationId, params.getStationIds()) .ge(StationStatMonth::getStatMonth, params.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM"))) .le(StationStatMonth::getStatMonth, params.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM"))) .orderByAsc(StationStatMonth::getStatMonth) .list().stream().collect(Collectors.groupingBy(StationStatMonth::getStationId, Collectors.toList())); } } /** * 充电站当日统计 * * @return */ @Override public Map stationTodayStat(String stationId) { if (CommUtil.null2Long(stationId) <= 0) { // 判断数据权限 stationId = CommUtil.isEmptyOrNull(KymCache.INSTANCE.getAdminUserStationIds(StpUtil.getLoginIdAsLong())) ? null : KymCache.INSTANCE.getAdminUserStationIds(StpUtil.getLoginIdAsLong()).get(0); } return baseMapper.stationTodayStat(stationId); } /** * 订单号批量查询订单 * * @param startChargeSeqs * @return */ @Override public List getChargeOrdersBySeqs(String[] startChargeSeqs) { return lambdaQuery().in(ChargeOrder::getStartChargeSeq, Arrays.stream(startChargeSeqs).toList()).list(); } }