diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/constant/MessageConstants.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/constant/MessageConstants.java new file mode 100644 index 00000000..e0df0c3e --- /dev/null +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/constant/MessageConstants.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.constant; + +public interface MessageConstants { + + /** + * 保险到期提醒消息 + */ + String INSURANCE_DEADLINE_REMINDER = "救援车辆:%s 的保险已到期!"; + + /** + * 车辆年检到期提醒。 + */ + String CAR_CHECK_DEADLINE_REMINDER = "救援车辆:%s 的年检已到期!"; + +} diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/app/controller/admin/RescueInfoController.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/app/controller/admin/RescueInfoController.java index 74902e8e..d8b1c8e0 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/app/controller/admin/RescueInfoController.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/app/controller/admin/RescueInfoController.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.rescue.domain.RescueInfo; import cn.iocoder.yudao.module.rescue.dto.DriverInfo2Dto; import cn.iocoder.yudao.module.rescue.dto.DriverInfoDto; import cn.iocoder.yudao.module.rescue.service.IRescueInfoService; +import cn.iocoder.yudao.module.rescue.vo.RescueCarStatRespVO; import cn.iocoder.yudao.module.rescue.vo.StatisticsStaffVO; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.permission.RoleApi; @@ -19,6 +20,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -52,6 +54,42 @@ public class RescueInfoController extends BaseController { @Resource private RepairBookingService dlRepairBookingService; + /** + * 获取所有待救援订单 + */ + @GetMapping("/getAllRescueOrder") + public CommonResult> getAllRescueOrder() { + List rescueOrder = rescueInfoService.getAllRescueOrder(); + return success(rescueOrder); + } + + /** + * 获取救援车辆列表 APP业务管理 + */ + @GetMapping("/rescueCarList") + public CommonResult> rescueCarList(RescueInfo rescueInfo) { + List> rescueDriverList = rescueInfoService.rescueCarList(rescueInfo); + return success(rescueDriverList); + } + + /** + * 计算救援车辆车龄和累计里程 APP业务管理 + */ + @GetMapping("/getRescueCarAgeAndMileage") + public CommonResult> getRescueCarAgeAndMileage() { + List list = rescueInfoService.getRescueCarAgeAndMileage(); + return success(list); + } + + /** + * 通过车牌号获取救援车辆业绩表 APP业务管理 + */ + @GetMapping("/getRescueCarKPI") + public CommonResult> getRescueCarKPI(String driverCarNum,String startTime,String endTime) { + List list = rescueInfoService.getRescueCarKPI(driverCarNum,startTime,endTime); + return success(list); + } + /** * 获取救援订单 */ @@ -343,7 +381,7 @@ public class RescueInfoController extends BaseController { * 获取扣车订单 */ @GetMapping("/statisticsInfo") - public CommonResult statisticsInfo(String type) { + public CommonResult statisticsInfo(String type) { return success(rescueInfoService.statisticsInfo(type)); } diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueCarInfoController.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueCarInfoController.java index 1b7c4bb8..d4e56293 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueCarInfoController.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueCarInfoController.java @@ -1,21 +1,48 @@ package cn.iocoder.yudao.module.rescue.controller.admin; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.common.BaseConstants; +import cn.iocoder.yudao.common.SystemEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.custom.entity.CarMain; +import cn.iocoder.yudao.module.custom.service.CarMainService; +import cn.iocoder.yudao.module.custom.vo.CarMainReqVO; +import cn.iocoder.yudao.module.custom.vo.CarMainRespVO; import cn.iocoder.yudao.module.rescue.core.controller.BaseController; import cn.iocoder.yudao.module.rescue.domain.RescueCarInfo; import cn.iocoder.yudao.module.rescue.service.IRescueCarInfoService; +import cn.iocoder.yudao.module.rescue.task.RescueDeadlineReminder; import cn.iocoder.yudao.module.rescue.utils.ExcelUtil; +import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; +import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; +import cn.iocoder.yudao.module.system.api.permission.RoleApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.module.system.api.user.dto.UserDTO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.module.constant.MessageConstants.INSURANCE_DEADLINE_REMINDER; /** * 救援车辆信息Controller @@ -30,6 +57,57 @@ public class RescueCarInfoController extends BaseController { private IRescueCarInfoService rescueCarInfoService; @Autowired private AdminUserApi adminUserApi; + @Autowired + private RescueDeadlineReminder rescueDeadlineReminder; + @Autowired + private NotifyMessageSendApi sendApi; + + @Resource + @Lazy + private RoleApi roleApi; + + + /** + * 定时任务提醒,保险到期提醒。教练未进行离场打卡学员信息 + */ + @TenantIgnore +// @Scheduled(cron = "0 06 11 * * ?") + @GetMapping("/y") + public void noClockInRemind() { +// rescueCarInfoService.noClockInRemind(); + //获取当前登录用户 +// Long userId = SecurityFrameworkUtils.getLoginUserId(); + + // 1. 查询所有保险即将到期或已到期的车辆 + LocalDateTime today = LocalDateTime.now(); + List expiringCars = rescueCarInfoService.selectExpiringInsuranceCars(today); + for (RescueCarInfo expiringCar : expiringCars) { + Long tenantId = expiringCar.getTenantId(); + String message = String.format(INSURANCE_DEADLINE_REMINDER,expiringCar.getRescueCarNum()); + + //获取接收消息的用户 + List officeStaffList = roleApi.selectUserListByRoleCode(tenantId, "jiuyuan"); + if (officeStaffList != null && !officeStaffList.isEmpty()) { + for (UserDTO staff : officeStaffList) { + Long userId = staff.getId(); + NotifySendSingleToUserReqDTO dto = new NotifySendSingleToUserReqDTO(); + dto.setUserId(userId); + dto.setSystemCode(SystemEnum.RESCUE.getCode()); + dto.setTemplateCode(BaseConstants.TICKET_EMPLOY); + // 准备发送参数 + Map templateParams = new HashMap<>(); + // 发送模版内容 + templateParams.put("text", message); + dto.setTemplateParams(templateParams); + // 发送消息 + sendApi.sendSingleMessageToAdmin(dto, tenantId); + } + } + + + } + + } /** * 查询救援车辆信息列表 @@ -47,6 +125,83 @@ public class RescueCarInfoController extends BaseController { return success(rescueCarInfoService.selectRescueCarInfoList(rescueCarInfo, page)); } + /** + * 获取车辆统计数据 + */ + @GetMapping("/getStats") + public CommonResult> getStats() { + RescueCarInfo rescueCarInfo = new RescueCarInfo(); + //获取当前登录用户 + Long userId = SecurityFrameworkUtils.getLoginUserId(); + //所在顶级机构 + AdminUserRespDTO user = adminUserApi.getUser(userId); + rescueCarInfo.setDeptId(user.getDeptId()); + Page page = new Page<>(1, 100); + IPage carInfoIPage = rescueCarInfoService.selectRescueCarInfoList(rescueCarInfo, page); + // 拿到分页数据 + List records = carInfoIPage.getRecords(); + // 1. 车辆总数 + long totalCars = records.size(); + // 2. 根据car_category分组统计 + Map categoryCount = records.stream() + .filter(car -> car.getCarCategory() != null && !car.getCarCategory().trim().isEmpty()) + .collect(Collectors.groupingBy( + RescueCarInfo::getCarCategory, + Collectors.counting() + )); + + // 3. 组装返回结果 + Map result = new HashMap<>(); + result.put("totalCars", totalCars); + result.put("categoryCount", categoryCount); + + /** + * 返回给前端的数据格式示例: + * { + * "code": 200, + * "data": { + * "totalCars": 100, + * "categoryCount": { + * "大拖车": 20, + * "小拖车": 10, + * "皮卡": 15, + * "清障车": 25, + * "吊车": 30 + * } + * }, + * "msg": "操作成功" + * } + */ + + + +/* // 2. 车辆类型数(去重统计) + long typeCount = records.stream() + .map(RescueCarInfo::getRescueCarType) + .filter(Objects::nonNull) + .distinct() + .count(); + // 3. 品牌型号数(去重统计) + long brandCount = records.stream() + .map(RescueCarInfo::getRescueCarBrand) + .filter(Objects::nonNull) + .distinct() + .count(); + // 4. 车牌颜色数(去重统计) + long colorCount = records.stream() + .map(RescueCarInfo::getCarLicenseColor) + .filter(Objects::nonNull) + .distinct() + .count(); + + Map result = new HashMap<>(); + result.put("totalCars", totalCars); + result.put("typeCount", typeCount); + result.put("brandCount", brandCount); + result.put("colorCount", colorCount);*/ + return CommonResult.success(result); + } + /** * 查询救援车辆信息列表 */ diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueChannelSourceController.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueChannelSourceController.java index f9e5cfce..f21d0dda 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueChannelSourceController.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueChannelSourceController.java @@ -64,6 +64,15 @@ public class RescueChannelSourceController extends BaseController { return success(rescueChannelSourceService.channelList()); } + /** + * 获取所有来源 + */ + @GetMapping("/sourceList") + public CommonResult> sourceList() { + return success(rescueChannelSourceService.sourceList()); + } + + @GetMapping("/getChannelListByDispatchId") public CommonResult> getChannelListByDispatchId(@RequestParam(value = "dispatchId", required = false) Long dispatchId) { return success(rescueChannelSourceService.getChannelListByDispatchId(dispatchId)); diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueInfoSystem.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueInfoSystem.java index 2a77a230..356e28ce 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueInfoSystem.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/controller/admin/RescueInfoSystem.java @@ -38,6 +38,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; @@ -85,6 +86,14 @@ public class RescueInfoSystem extends BaseController { @Resource private RoleService roleService; + /** + * 新增发票信息(根据id进行修改) + */ + @PostMapping("/updateBilled") + public CommonResult updateBilled(@RequestBody RescueOrderInfo rescueOrderInfo) { + return CommonResult.success(infoService.updateById(rescueOrderInfo)); + } + /** * 新增【道路救援发起】 */ @@ -149,6 +158,15 @@ public class RescueInfoSystem extends BaseController { return success(list); } + /** + * 根据ID查询救援信息、救援订单信息详情 + */ + @GetMapping("/getById") + public CommonResult getById(Long id) { + RescueInfo rescueInfo = rescueInfoService.selectRescueInfoAndOrderById(id); + return success(rescueInfo); + } + @GetMapping("/listByRevoke") public CommonResult> listByRevoke(RescueInfo rescueInfo, @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueCarInfo.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueCarInfo.java index b2aed833..6db23f6d 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueCarInfo.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueCarInfo.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.annotation.Excel; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import lombok.Data; +import java.math.BigDecimal; import java.util.Date; /** @@ -34,6 +35,12 @@ public class RescueCarInfo extends TenantBaseDO { @TableField(exist = false) private String rescueCarTypeStr; + /** + * 车辆归属 + */ + @Excel(name = "车辆归属") + private String rescueCarOwn; + /** * 车辆种类 */ @@ -96,6 +103,11 @@ public class RescueCarInfo extends TenantBaseDO { */ @Excel(name = "车架号") private String frameNumber; + /** + * 车辆保养里程 + */ + @Excel(name = "车辆保养里程") + private BigDecimal carMaintenanceMileage; //车辆保养时间 @JsonFormat(pattern = "yyyy-MM-dd") private Date carKeepTime; diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueInfo.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueInfo.java index f1d89a8b..b86307dc 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueInfo.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueInfo.java @@ -428,6 +428,30 @@ public class RescueInfo extends TenantBaseDO @TableField(exist = false) private Date paymentTime; + /** 开发票相关字段 */ + @TableField(exist = false) + private String ifBilled; + @TableField(exist = false) + private String billedUsername; + @TableField(exist = false) + private Long billedUserid; + @TableField(exist = false) + private String billedQrcode; + @TableField(exist = false) + private String billedRemark; + + /** 救援车辆归属 */ + @TableField(exist = false) + private String rescueCarOwn; + /** 救援车辆品牌型号 */ + @TableField(exist = false) + private String rescueCarBrand; + /** 行驶里程 */ + @TableField(exist = false) + private String mileage; + /** 车龄 */ + @TableField(exist = false) + private String carAge; /** * 调度等级 */ diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueOrderInfo.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueOrderInfo.java index 9fdb0ed7..6d44c2e9 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueOrderInfo.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueOrderInfo.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.rescue.domain; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.fasterxml.jackson.annotation.JsonFormat; import cn.iocoder.yudao.annotation.Excel; @@ -38,6 +39,17 @@ public class RescueOrderInfo extends TenantBaseDO @Excel(name = "用户姓名") private String realName; + /** 是否开票 */ + private String ifBilled; + /** 开票人名字 */ + private String billedUsername; + /** 开票人Id */ + private Long billedUserid; + /** 开票二维码 */ + private String billedQrcode; + /** 开票备注 */ + private String billedRemark; + /** 用户手机号 */ @Excel(name = "用户手机号") private String phonenumber; diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueRefuelRecord.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueRefuelRecord.java index 1c58fc24..8e4de11b 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueRefuelRecord.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/domain/RescueRefuelRecord.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.annotation.Excel; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import lombok.Data; +import java.math.BigDecimal; import java.util.Date; /** @@ -57,4 +58,18 @@ public class RescueRefuelRecord extends TenantBaseDO private String phonenumber; @TableField(exist = false) private String rescueCarNum; + + /* ======= 新增派生字段 ======= */ + /** 距上次加油行驶公里 */ + @TableField(exist = false) + private Integer distancePrevKm; + /** 每公里油耗 (L/km),保留 3 位小数 */ + @TableField(exist = false) + private BigDecimal fuelEfficiencyLpkm; + /** 每公里成本 (元/km),保留 2 位小数 */ + @TableField(exist = false) + private BigDecimal costPerKm; + /** 金额兜底(refuelNum × price),用于校验 */ +// @TableField(exist = false) +// private BigDecimal costAmountCalc; } diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/mapper/RescueCarInfoMapper.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/mapper/RescueCarInfoMapper.java index a2998154..c0fb6de8 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/mapper/RescueCarInfoMapper.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/mapper/RescueCarInfoMapper.java @@ -7,7 +7,9 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -20,6 +22,14 @@ import java.util.Map; @Mapper public interface RescueCarInfoMapper extends BaseMapper { + + @Select("SELECT * FROM rescue_car_info WHERE car_insurance_time >= #{expiryDate} and deleted=0") + List selectExpiringInsuranceCars(@Param("expiryDate") LocalDateTime expiryDate); + + @Select("SELECT * FROM rescue_car_info WHERE car_check_time >= #{expiryDate} and deleted=0") + List selectExpiringCarsCheck(@Param("expiryDate") LocalDateTime expiryDate); + + /** * 查询救援车辆信息 * diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/mapper/RescueInfoMapper.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/mapper/RescueInfoMapper.java index f9ae0626..b572a306 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/mapper/RescueInfoMapper.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/mapper/RescueInfoMapper.java @@ -6,10 +6,7 @@ import cn.iocoder.yudao.module.rescue.domain.DriverInfo; import cn.iocoder.yudao.module.rescue.domain.RescueInfo; import cn.iocoder.yudao.module.rescue.dto.DriverInfo2Dto; import cn.iocoder.yudao.module.rescue.dto.DriverInfoDto; -import cn.iocoder.yudao.module.rescue.vo.BuckleVO; -import cn.iocoder.yudao.module.rescue.vo.DriverInfoExportVO; -import cn.iocoder.yudao.module.rescue.vo.DriverStaffSaveVO; -import cn.iocoder.yudao.module.rescue.vo.StatisticsStaffVO; +import cn.iocoder.yudao.module.rescue.vo.*; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.mapper.BaseMapper; @@ -17,6 +14,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; import java.util.Date; import java.util.List; @@ -111,6 +109,10 @@ public interface RescueInfoMapper extends BaseMapper List carStatistics(@Param("vo") StatisticsStaffVO statisticsStaffReqVO); List dispatchStatistics(@Param("vo") StatisticsStaffVO statisticsStaffReqVO); + RescueInfo selectRescueInfoAndOrderById(Long id); + + List getAllRescueOrder(); + IPage selectRescueStatisticsInfoList(@Param("map") RescueInfo rescueInfo, Page page); IPage selectRescueStatisticsInfoListSecondDispatcher(@Param("map") RescueInfo rescueInfo, Page page); @@ -126,4 +128,16 @@ public interface RescueInfoMapper extends BaseMapper List driverStatisticsSecond(@Param("vo") StatisticsStaffVO statisticsStaffReqVO); List carStatisticsSecond(@Param("vo") StatisticsStaffVO statisticsStaffReqVO); + + void updateBilled(RescueInfo rescueInfo); + + List> rescueCarList(@Param("map") RescueInfo rescueInfo); + + List selectCarAgeAndMileage(); + + List getRescueCarKPI( + @Param("driverCarNum") String driverCarNum, + @Param("startTime") String startTime, + @Param("endTime") String endTime + ); } diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueCarInfoService.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueCarInfoService.java index e7739bf2..2adec600 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueCarInfoService.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueCarInfoService.java @@ -4,7 +4,10 @@ import cn.iocoder.yudao.module.rescue.domain.RescueCarInfo; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import org.apache.ibatis.annotations.Select; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -16,6 +19,21 @@ import java.util.Map; */ public interface IRescueCarInfoService extends IService { + + + // 查询保险到期的所有车辆 + List selectExpiringInsuranceCars(LocalDateTime expiryDate); + + // 查询年检到期的所有车辆 + List selectExpiringCarsCheck(LocalDateTime expiryDate); + + + + + + + + /** * 查询救援车辆信息 * diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueChannelSourceService.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueChannelSourceService.java index 23fe7e54..ab941509 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueChannelSourceService.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueChannelSourceService.java @@ -50,4 +50,6 @@ public interface IRescueChannelSourceService extends IService getSourcesByChannelId(Integer channelId); + + List sourceList(); } diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueInfoService.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueInfoService.java index 35998650..0168e41e 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueInfoService.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/IRescueInfoService.java @@ -12,6 +12,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -197,6 +198,10 @@ public interface IRescueInfoService extends IService Long safeStringToLong(String str, Long defaultValue); List statisticsAll(StatisticsStaffVO statisticsStaffReqVO); + + RescueInfo selectRescueInfoAndOrderById(Long id); + + List getAllRescueOrder(); List statisticsAllSecond(StatisticsStaffVO statisticsStaffReqVO); IPage selectRescueStatisticsInfoListByAdmin(RescueInfo rescueInfo, Page page); @@ -204,4 +209,10 @@ public interface IRescueInfoService extends IService Map getRescueStatisticsInfoNum(RescueInfo rescueInfo); Map getRescueStatisticsInfoNumSecondDispatcher(RescueInfo rescueInfo); + + List> rescueCarList(RescueInfo rescueInfo); + + List getRescueCarAgeAndMileage(); + + List getRescueCarKPI(String driverCarNum,String startTime,String endTime); } diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueCarInfoServiceImpl.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueCarInfoServiceImpl.java index 30f46d72..f0bf213a 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueCarInfoServiceImpl.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueCarInfoServiceImpl.java @@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.rescue.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.custom.entity.CarMain; +import cn.iocoder.yudao.module.custom.service.CarMainService; import cn.iocoder.yudao.module.rescue.domain.RescueCarInfo; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.module.rescue.mapper.RescueCarInfoMapper; import cn.iocoder.yudao.module.system.api.dict.DictDataApi; import cn.iocoder.yudao.module.rescue.service.IRescueCarInfoService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -16,7 +19,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser; @@ -31,6 +36,16 @@ public class RescueCarInfoServiceImpl extends ServiceImpl selectExpiringInsuranceCars(LocalDateTime expiryDate) { + return baseMapper.selectExpiringInsuranceCars(expiryDate); + } + + @Override + public List selectExpiringCarsCheck(LocalDateTime expiryDate) { + return baseMapper.selectExpiringCarsCheck(expiryDate); + } + /** * 查询救援车辆信息 * diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueChannelSourceServiceImpl.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueChannelSourceServiceImpl.java index 9b4e3a18..da98a6b8 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueChannelSourceServiceImpl.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueChannelSourceServiceImpl.java @@ -74,6 +74,15 @@ public class RescueChannelSourceServiceImpl extends ServiceImpl sourceList() { + return lambdaQuery() + .eq(RescueChannelSource::getType, 1) + .eq(RescueChannelSource::getDeleted, false) + .orderByAsc(RescueChannelSource::getCreateTime) + .list(); + } + @Override public List channelList() { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueInfoServiceImpl.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueInfoServiceImpl.java index b9af754b..6c20ad6c 100644 --- a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueInfoServiceImpl.java +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/service/impl/RescueInfoServiceImpl.java @@ -851,6 +851,10 @@ public class RescueInfoServiceImpl extends ServiceImpl queryWrapperOrder = new LambdaQueryWrapper<>(); queryWrapperOrder.eq(RescueOrderInfo::getRescueInfoId, rescueId).last("limit 1"); RescueOrderInfo rescueOrderInfo = rescueOrderInfoService.getOne(queryWrapperOrder); @@ -861,6 +865,10 @@ public class RescueInfoServiceImpl extends ServiceImpl queryWrapper3 = new LambdaQueryWrapper<>(); @@ -2896,6 +2904,21 @@ public class RescueInfoServiceImpl extends ServiceImpl getAllRescueOrder() { + List allRescueOrder = baseMapper.getAllRescueOrder(); + for (RescueInfo rescueInfo : allRescueOrder) { + String dljy_type = dictDataService.getDictDataLabel("dljy_type", rescueInfo.getRescueType()); + rescueInfo.setRescueTypeStr(dljy_type); + } + return allRescueOrder; + } + public List driverStatistics(StatisticsStaffVO statisticsStaffReqVO) { return baseMapper.driverStatistics(statisticsStaffReqVO); } @@ -2982,6 +3005,21 @@ public class RescueInfoServiceImpl extends ServiceImpl> rescueCarList(RescueInfo rescueInfo) { + return baseMapper.rescueCarList(rescueInfo); + } + + @Override + public List getRescueCarAgeAndMileage() { + return baseMapper.selectCarAgeAndMileage(); + } + + @Override + public List getRescueCarKPI(String driverCarNum,String startTime,String endTime) { + return baseMapper.getRescueCarKPI(driverCarNum,startTime,endTime); + } + public List driverStatisticsSecond(StatisticsStaffVO statisticsStaffReqVO) { return baseMapper.driverStatisticsSecond(statisticsStaffReqVO); diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/task/RescueDeadlineReminder.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/task/RescueDeadlineReminder.java new file mode 100644 index 00000000..bec4a7c6 --- /dev/null +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/task/RescueDeadlineReminder.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.rescue.task; + +import cn.iocoder.yudao.common.BaseConstants; +import cn.iocoder.yudao.common.SystemEnum; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.rescue.domain.RescueCarInfo; +import cn.iocoder.yudao.module.rescue.service.IRescueCarInfoService; +import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; +import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.module.constant.MessageConstants.CAR_CHECK_DEADLINE_REMINDER; +import static cn.iocoder.yudao.module.constant.MessageConstants.INSURANCE_DEADLINE_REMINDER; + +@Component +@Slf4j +public class RescueDeadlineReminder { + + @Autowired + private NotifyMessageSendApi sendApi; + @Autowired + private AdminUserApi adminUserApi; + @Autowired + private IRescueCarInfoService rescueCarInfoService; + + /** + * 保险到期提醒。 + */ +// @Scheduled(cron = "0 0 1 * * ?") //每天凌晨一点检测 + @Scheduled(cron = "0 23 10 * * ?") + public void insuranceReminder() { + //获取当前登录用户 + Long userId = SecurityFrameworkUtils.getLoginUserId(); + // 1. 查询所有保险即将到期或已到期的车辆 + LocalDateTime today = LocalDateTime.now(); + List expiringCars = rescueCarInfoService.selectExpiringInsuranceCars(today); + for (RescueCarInfo expiringCar : expiringCars) { + Long tenantId = expiringCar.getTenantId(); + String message = String.format(INSURANCE_DEADLINE_REMINDER,expiringCar.getRescueCarNum()); + + NotifySendSingleToUserReqDTO dto = new NotifySendSingleToUserReqDTO(); + dto.setUserId(userId); + dto.setSystemCode(SystemEnum.RESCUE.getCode()); + dto.setTemplateCode(BaseConstants.TICKET_EMPLOY); + // 准备发送参数 + Map templateParams = new HashMap<>(); + // 发送模版内容 + templateParams.put("text", message); + dto.setTemplateParams(templateParams); + // 发送消息 + sendApi.sendSingleMessageToAdmin(dto, tenantId); + } + } + + + /** + * 车辆年检到期提醒。 + */ + @Scheduled(cron = "0 0 1 * * ?") //每天凌晨一点检测 + public void carCheckReminder() { + //获取当前登录用户 + Long userId = SecurityFrameworkUtils.getLoginUserId(); + // 1. 查询所有保险即将到期或已到期的车辆 + LocalDateTime today = LocalDateTime.now(); + List expiringCars = rescueCarInfoService.selectExpiringCarsCheck(today); + for (RescueCarInfo expiringCar : expiringCars) { + Long tenantId = expiringCar.getTenantId(); + String message = CAR_CHECK_DEADLINE_REMINDER; + NotifySendSingleToUserReqDTO dto = new NotifySendSingleToUserReqDTO(); + dto.setUserId(userId); + dto.setSystemCode(SystemEnum.RESCUE.getCode()); + dto.setTemplateCode(BaseConstants.TICKET_EMPLOY); + // 准备发送参数 + Map templateParams = new HashMap<>(); + // 发送模版内容 + templateParams.put("text", message); + dto.setTemplateParams(templateParams); + // 发送消息 + sendApi.sendSingleMessageToAdmin(dto, tenantId); + } + } +} diff --git a/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/vo/RescueCarStatRespVO.java b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/vo/RescueCarStatRespVO.java new file mode 100644 index 00000000..d1bcfae9 --- /dev/null +++ b/dl-module-rescue/src/main/java/cn/iocoder/yudao/module/rescue/vo/RescueCarStatRespVO.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.rescue.vo; + +import lombok.Data; + +@Data +public class RescueCarStatRespVO { + private String rescueCarNum; // 车牌号 / 编号 + private Integer carAge; // 车龄(整数年) + private Integer mileage; // 累计里程(整数 km) +} + diff --git a/dl-module-rescue/src/main/resources/mapper/rescue/RescueCarInfoMapper.xml b/dl-module-rescue/src/main/resources/mapper/rescue/RescueCarInfoMapper.xml index 139d379f..41f4c304 100644 --- a/dl-module-rescue/src/main/resources/mapper/rescue/RescueCarInfoMapper.xml +++ b/dl-module-rescue/src/main/resources/mapper/rescue/RescueCarInfoMapper.xml @@ -26,6 +26,7 @@ SELECT rci.id, rci.rescue_car_type, + rci.rescue_car_own, rci.rescue_car_num, rci.rescue_car_brand, rci.car_own, @@ -35,7 +36,7 @@ rci.car_license_color, rci.car_use_nature, rci.frame_number, - rci.car_keep_time, + rci.car_maintenance_mileage, rci.car_insurance_time, rci.car_check_time, rci.possessor_id, @@ -50,6 +51,9 @@ and rci.rescue_car_type = #{map.rescueCarType} + and rci.rescue_car_own = + #{map.rescueCarOwn} + and rci.rescue_car_num = #{map.rescueCarNum} and rci.rescue_car_brand = @@ -120,6 +124,7 @@ update rescue_car_info rescue_car_type = #{rescueCarType}, + rescue_car_own = #{rescueCarOwn}, rescue_car_num = #{rescueCarNum}, rescue_car_brand = #{rescueCarBrand}, car_own = #{carOwn}, @@ -129,7 +134,7 @@ car_license_color = #{carLicenseColor}, car_use_nature = #{carUseNature}, frame_number = #{frameNumber}, - car_keep_time = #{carKeepTime}, + car_maintenance_mileage = #{carMaintenanceMileage}, car_insurance_time = #{carInsuranceTime}, car_check_time = #{carCheckTime}, possessor_id = #{possessorId}, diff --git a/dl-module-rescue/src/main/resources/mapper/rescue/RescueChannelSourceMapper.xml b/dl-module-rescue/src/main/resources/mapper/rescue/RescueChannelSourceMapper.xml index f7d4c95b..bb4da501 100644 --- a/dl-module-rescue/src/main/resources/mapper/rescue/RescueChannelSourceMapper.xml +++ b/dl-module-rescue/src/main/resources/mapper/rescue/RescueChannelSourceMapper.xml @@ -20,7 +20,7 @@ rcs.id, rcs.name FROM rescue_second_channel_association rsca - LEFT JOIN rescue_channel_source rcs ON rcs.id = rsca.channel_id AND rcs.type = 0 AND rcs.deleted = 0 + RIGHT JOIN rescue_channel_source rcs ON rcs.id = rsca.channel_id AND rcs.type = 0 AND rcs.deleted = 0 where rsca.dispatch_id = #{dispatchId} AND rsca.deleted = 0 ORDER BY rcs.create_time ASC diff --git a/dl-module-rescue/src/main/resources/mapper/rescue/RescueInfoMapper.xml b/dl-module-rescue/src/main/resources/mapper/rescue/RescueInfoMapper.xml index e5cdad88..14a878d1 100644 --- a/dl-module-rescue/src/main/resources/mapper/rescue/RescueInfoMapper.xml +++ b/dl-module-rescue/src/main/resources/mapper/rescue/RescueInfoMapper.xml @@ -232,7 +232,7 @@ order by ri.create_time desc - SELECT ri.*, roi.order_status, roi.set_money, @@ -249,10 +249,42 @@ roi.confirm_payment_person_remark FROM rescue_info ri left join rescue_order_info roi on roi.rescue_info_id = ri.id + where ri.deleted = '0' AND ri.is_revoke = '0' and ri.id = #{id} + order by ri.create_time desc + + + + - @@ -1477,4 +1582,113 @@ rci.rescue_car_num ORDER BY rescueNum DESC + + + diff --git a/dl-module-rescue/src/main/resources/mapper/rescue/RescueRefuelRecordMapper.xml b/dl-module-rescue/src/main/resources/mapper/rescue/RescueRefuelRecordMapper.xml index 76864cb9..b670d7e0 100644 --- a/dl-module-rescue/src/main/resources/mapper/rescue/RescueRefuelRecordMapper.xml +++ b/dl-module-rescue/src/main/resources/mapper/rescue/RescueRefuelRecordMapper.xml @@ -18,21 +18,76 @@ - SELECT - rrc.*,su.nickname as real_name,su.mobile as phonenumber,rci.rescue_car_num - FROM - rescue_refuel_record rrc - inner join driver_info di ON rrc.driver_id = di.id - INNER JOIN system_users su ON su.id = di.user_id - left join rescue_car_info rci on di.id = rci.possessor_id - where rrc.deleted = '0' - and su.nickname like concat('%',#{map.realName},'%') - and rci.rescue_car_num like concat('%',#{map.rescueCarNum},'%') - order by rrc.record_time desc + rrc.*, + su.nickname AS real_name, + su.mobile AS phonenumber, + rci.rescue_car_num, + + /* ① 距上次加油公里数 */ + (rrc.refuel_distance + - LAG(rrc.refuel_distance) OVER (PARTITION BY rrc.car_id ORDER BY rrc.record_time) + ) AS distance_prev_km, + + /* ② 每公里油耗 L/km(有上一条且距离>0 才计算) */ + CASE + WHEN LAG(rrc.refuel_distance) OVER (PARTITION BY rrc.car_id ORDER BY rrc.record_time) IS NOT NULL + AND (rrc.refuel_distance + - LAG(rrc.refuel_distance) OVER (PARTITION BY rrc.car_id ORDER BY rrc.record_time)) > 0 + THEN ROUND( + rrc.refuel_num / + (rrc.refuel_distance + - LAG(rrc.refuel_distance) OVER (PARTITION BY rrc.car_id ORDER BY rrc.record_time) + ), 3) + END AS fuel_efficiency_lpkm, + + /* ③ 每公里成本 元/km */ + CASE + WHEN LAG(rrc.refuel_distance) OVER (PARTITION BY rrc.car_id ORDER BY rrc.record_time) IS NOT NULL + AND (rrc.refuel_distance + - LAG(rrc.refuel_distance) OVER (PARTITION BY rrc.car_id ORDER BY rrc.record_time)) > 0 + THEN ROUND( + rrc.refuel_money / + (rrc.refuel_distance + - LAG(rrc.refuel_distance) OVER (PARTITION BY rrc.car_id ORDER BY rrc.record_time) + ), 2) + END AS cost_per_km + + /* 金额兜底(如果表里已有 refuel_money 可不用返回) + ROUND(rrc.refuel_num * (rrc.refuel_money / NULLIF(rrc.refuel_num, 0)), 2) + AS cost_amount_calc */ + FROM rescue_refuel_record rrc + INNER JOIN driver_info di ON rrc.driver_id = di.id + INNER JOIN system_users su ON su.id = di.user_id + LEFT JOIN rescue_car_info rci ON rrc.car_id = rci.id + WHERE rrc.deleted = 0 + + AND su.nickname LIKE CONCAT('%', #{map.realName}, '%') + + + AND rci.rescue_car_num LIKE CONCAT('%', #{map.rescueCarNum}, '%') + + ORDER BY rrc.record_time DESC +