package com.ruoyi.system.task; import com.alibaba.fastjson2.JSON; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.ServiceConstants; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.system.domain.AsDevice; import com.ruoyi.system.domain.EtDividendDetail; import com.ruoyi.system.domain.EtOperatingArea; import com.ruoyi.system.domain.EtOrder; import com.ruoyi.system.mapper.AsDeviceMapper; import com.ruoyi.system.mapper.EtOrderMapper; import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.service.IEtDividendDetailService; import com.ruoyi.system.service.IEtOperatingAreaService; import com.ruoyi.system.service.IEtOrderService; import com.ruoyi.system.service.ISysUserService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.List; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; /** * 定时任务调度测试 * * @author ruoyi */ @Slf4j @Component("etTask") public class EtTask { @Resource private EtOrderMapper etOrderMapper; @Autowired private IEtOperatingAreaService etOperatingAreaService; @Resource private SysUserMapper userMapper; @Autowired private IEtDividendDetailService dividendDetailService; @Autowired private ScheduledExecutorService scheduledExecutorService; @Autowired private IEtOrderService etOrderService; @Resource private AsDeviceMapper asDeviceMapper; /** * 1.启动时判断是否有未取消预约的订单 * 2.判断已完成的订单未退还押金的 */ @PostConstruct public void init() { log.info("=========启动时判断是否有未取消预约的订单、已完成的订单未退还押金的=========="); List orders= etOrderMapper.selectAppointmentUnfinished(); log.info("预约未完成的订单 = " + JSON.toJSONString(orders)); for (EtOrder order:orders) { EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(order.getAreaId()); AsDevice asDevice = asDeviceMapper.selectAsDeviceBySn(order.getSn()); Date appointmentEndTime = DateUtils.getTimeAfterXMinutes(order.getAppointmentStartTime(), area.getTimeoutMinutes());//预约结束时间 int timeDifferenceInSeconds = DateUtils.timeDifferenceInSeconds(appointmentEndTime, order.getAppointmentStartTime());//(超时时间-开始时间)的秒数 int differenceInSeconds = DateUtils.timeDifferenceInSeconds(new Date(), order.getAppointmentStartTime());//(当前时间-开始时间)的秒数 int delay = timeDifferenceInSeconds - differenceInSeconds; log.info("【定时取消预约】延迟:【{}】秒", delay); //定时取消预约 scheduledExecutorService.schedule(() -> { log.error("【车辆超时预约】系统自动取消"); EtOrder order1 = etOrderService.selectEtOrderByOrderNo(order.getOrderNo()); log.info("【定时取消预约】重新获取订单信息:{}",JSON.toJSON(order1)); if(order1.getPaid().equals(ServiceConstants.ORDER_PAY_STATUS_PAID)){//已支付订单,跳过 log.error("【车辆超时预约】订单已支付,跳过"); return; } log.error("【车辆超时预约】订单未支付,系统自动处理"); //未支付 订单更新最后预约时间,并结束订单,做超出预约时间标记 order.setStatus(ServiceConstants.ORDER_STATUS_CANCEL_APPOINTMENT); order.setAppointmentEndTime(new Date()); order.setAppointmentTimeout("1"); //计算预约费 BigDecimal appointmentServiceFee = area.getAppointmentServiceFee(); BigDecimal fee = appointmentServiceFee.multiply(new BigDecimal(area.getTimeoutMinutes()).divide(new BigDecimal(10))); order.setAppointmentFee(fee); order.setTotalFee(fee); int update = etOrderService.updateEtOrder(order); if(update==0){ throw new ServiceException("【车辆超时预约】:更新订单状态失败"); } // 改变车辆状态 asDevice.setStatus(ServiceConstants.VEHICLE_STATUS_NORMAL); asDevice.setLockStatus(ServiceConstants.LOCK_STATUS_OPEN); int device = asDeviceMapper.updateAsDevice(asDevice); if(device==0){ log.error("【车辆超时预约】更新车辆状态失败"); throw new ServiceException("【车辆超时预约】更新车辆状态失败"); } }, delay, TimeUnit.SECONDS); } } /** * 每天凌晨0点5分执行,计算分账结果 * cron: 0 5 0 * * ? */ public void computeDividend() { log.info("每天凌晨0点5分执行,计算分账结果"); // 获取昨天的订单,2024-05-26 00:00:00 -- 2024-05-26 23:59:59 // 获取昨天日期格式: yyyy-MM-dd LocalDate yesterday = LocalDate.now().minusDays(1); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String formattedYesterday = yesterday.format(formatter); log.info("获取昨天日期 = " + formattedYesterday); //判断该日期是否已经计算过分账结果 if(dividendDetailService.isDividendComputed(LocalDate.now().format(formatter))){ log.info("该日期已经计算过分账结果"); return; } String startDateStr = formattedYesterday + " "+ Constants.DATE_FORMAT_START_PEREND; String endDateStr = formattedYesterday + " " +Constants.DATE_FORMAT_END_PEREND; EtOrder order = new EtOrder(); order.setStartTime(startDateStr); order.setEndTime(endDateStr); order.setPaid(ServiceConstants.ORDER_PAY_STATUS_PAID); order.setStatus(ServiceConstants.ORDER_STATUS_ORDER_END); order.setType(ServiceConstants.ORDER_TYPE_RIDING); List orderListByDate = etOrderMapper.selectEtOrderList(order); for(EtOrder order1:orderListByDate){ EtDividendDetail etDividendDetail = new EtDividendDetail(); EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(order1.getAreaId()); SysUser sysUser = new SysUser(); sysUser.setUserType("03"); sysUser.setAreaId(area.getAreaId()); List sysUsers = userMapper.selectUserList(sysUser); for(SysUser user : sysUsers){ etDividendDetail.setAreaId(area.getAreaId()); etDividendDetail.setPartnerId(user.getUserId()); etDividendDetail.setOrderNo(order1.getOrderNo()); etDividendDetail.setTotalAmount(order1.getTotalFee()); etDividendDetail.setCreateTime(DateUtils.getNowDate()); etDividendDetail.setDividendProportion(user.getDividendProportion()); String dividendItem = user.getDividendItem(); // todo 分账金额是骑行费,还是调度费,看分账项目 分账项目:1-骑行费(骑行费+预约费);2-调度费(调度费+管理费) BigDecimal dividendAmount = BigDecimal.ZERO; if(dividendItem.contains("1")){ dividendAmount.add(order1.getRidingFee().add(order1.getAppointmentFee()));//1-骑行费(骑行费+预约费) }else if(dividendItem.contains("2")){ dividendAmount.add(order1.getManageFee().add(order1.getManageFee()));//2-调度费(调度费+管理费) } BigDecimal divide = new BigDecimal(user.getDividendProportion()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP); etDividendDetail.setDividendAmount(dividendAmount.multiply(divide)); etDividendDetail.setDividendItem(dividendItem); log.info("保存分账明细 === " + JSON.toJSONString(etDividendDetail)); int i = dividendDetailService.insertEtDividendDetail(etDividendDetail); if(i==0){ throw new ServiceException("保存分账明细失败"); } } int totalDividendProportion = IntStream.of(sysUsers.stream() .mapToInt(SysUser::getDividendProportion) .toArray()) .sum(); //算运营商自己的分账 etDividendDetail.setAreaId(area.getAreaId()); etDividendDetail.setPartnerId(0L); etDividendDetail.setOrderNo(order1.getOrderNo()); etDividendDetail.setTotalAmount(order1.getTotalFee()); etDividendDetail.setCreateTime(DateUtils.getNowDate()); etDividendDetail.setDividendAmount(order1.getTotalFee().multiply(new BigDecimal(100-totalDividendProportion).divide(new BigDecimal(100),2, BigDecimal.ROUND_HALF_UP))); etDividendDetail.setDividendProportion(100-totalDividendProportion); etDividendDetail.setDividendItem("运营商"); int i = dividendDetailService.insertEtDividendDetail(etDividendDetail); if(i==0){ throw new ServiceException("保存分账明细失败"); } } } }