src/main/java/com/ruoyi/collaborativeApproval/dto/NoticeDTO.java
@@ -10,4 +10,6 @@ private Long count; private String statusName; private String currentDate; } src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
@@ -65,7 +65,6 @@ @PostMapping ("maintenance") @ApiModelProperty("ä¿®æ¹è®¾å¤ä¿å »") public AjaxResult maintenance(@RequestBody DeviceMaintenance deviceMaintenance) { deviceMaintenance.setStatus(1); return deviceMaintenanceService.updateDeviceDeviceMaintenance(deviceMaintenance); } src/main/java/com/ruoyi/device/controller/DeviceRepairController.java
@@ -56,7 +56,6 @@ @PostMapping ("repair") @ApiModelProperty("设å¤ç»´ä¿®") public AjaxResult repair( @RequestBody DeviceRepair deviceRepair) { deviceRepair.setStatus(1); return deviceRepairService.updateDeviceRepair(deviceRepair); } src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,61 @@ package com.ruoyi.device.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.device.pojo.DeviceMaintenance; import com.ruoyi.device.pojo.MaintenanceTask; import com.ruoyi.device.service.MaintenanceTaskService; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.AjaxResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; /** * @author :yys * @date : 2025/12/22 14:58 */ @Api(tags = "设å¤ä¿å »å®æ¶ä»»å¡ç®¡ç") @RestController @RequestMapping("/deviceMaintenanceTask") public class MaintenanceTaskController extends BaseController { @Autowired private MaintenanceTaskService maintenanceTaskService; @GetMapping("/listPage") @ApiOperation(value = "设å¤ä¿å »å®æ¶ä»»å¡å表") public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) { return maintenanceTaskService.listPage(page,maintenanceTask); } @PostMapping("/add") @ApiOperation(value = "æ·»å 设å¤ä¿å »å®æ¶ä»»å¡") @Log(title = "设å¤ä¿å »å®æ¶ä»»å¡", businessType = BusinessType.INSERT) public AjaxResult add(@RequestBody MaintenanceTask maintenanceTask) { return maintenanceTaskService.add(maintenanceTask); } @PostMapping("/update") @ApiOperation(value = "ä¿®æ¹è®¾å¤ä¿å »å®æ¶ä»»å¡") @Log(title = "设å¤ä¿å »å®æ¶ä»»å¡", businessType = BusinessType.UPDATE) public AjaxResult update(@RequestBody MaintenanceTask maintenanceTask) { return maintenanceTaskService.updateByMaintenanceTaskId(maintenanceTask); } @DeleteMapping("/delete") @ApiOperation(value = "å é¤è®¾å¤ä¿å »å®æ¶ä»»å¡") @Log(title = "设å¤ä¿å »å®æ¶ä»»å¡", businessType = BusinessType.DELETE) public AjaxResult delete(@RequestBody List<Long> ids) { return maintenanceTaskService.delete(ids); } } src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
@@ -42,7 +42,7 @@ @ApiModelProperty("ä¿å »ç»æ 0 ç»´ä¿® 1 å®å¥½") private String maintenanceResult; @ApiModelProperty("ç¶æ 0 å¾ ä¿å » 1 å®ç»") @ApiModelProperty("ç¶æ 0 å¾ ä¿å » 1 å®ç» 2 失败") private Integer status; @ApiModelProperty("å建æ¶é´") src/main/java/com/ruoyi/device/execl/DeviceMaintenanceExeclDto.java
@@ -37,7 +37,7 @@ @Excel(name = "ä¿å »ç»æ") private String maintenanceResult; @ApiModelProperty("ç¶æ 0 å¾ ä¿å » 1 å®ç»") @ApiModelProperty("ç¶æ 0 å¾ ä¿å » 1 å®ç» 2 失败") @Excel(name = "ç¶æ") private String status; src/main/java/com/ruoyi/device/mapper/MaintenanceTaskMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,12 @@ package com.ruoyi.device.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.device.pojo.MaintenanceTask; import com.ruoyi.inspectiontask.pojo.TimingTask; /** * @author :yys * @date : 2025/12/22 14:56 */ public interface MaintenanceTaskMapper extends BaseMapper<MaintenanceTask> { } src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
@@ -1,6 +1,7 @@ package com.ruoyi.device.pojo; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import com.baomidou.mybatisplus.annotation.*; @@ -21,6 +22,21 @@ @ApiModelProperty("设å¤å°è´¦id") private Long deviceLedgerId; @ApiModelProperty("ä¿å »ä»»å¡id") private Long maintenanceTaskId; @ApiModelProperty(value = "颿¬¡") private String frequencyType; @ApiModelProperty(value = "颿¬¡è¯¦æ ") private String frequencyDetail; @ApiModelProperty(value = "䏿¬¡æ§è¡æ¶é´") private LocalDateTime nextExecutionTime; @ApiModelProperty(value = "æåæ§è¡æ¶é´") private LocalDateTime lastExecutionTime; private String deviceName; @@ -43,7 +59,7 @@ @ApiModelProperty("ä¿å »ç»æ 0 ç»´ä¿® 1 å®å¥½") private String maintenanceResult; @ApiModelProperty("ç¶æ 0 å¾ ä¿å » 1 å®ç»") @ApiModelProperty("ç¶æ 0 å¾ ä¿å » 1 å®ç» 2 失败") private Integer status; @ApiModelProperty("å建æ¶é´") src/main/java/com/ruoyi/device/pojo/DeviceRepair.java
@@ -49,7 +49,7 @@ @ApiModelProperty("ç»´ä¿®ç»æ") private String maintenanceResult; @ApiModelProperty("ç¶æ 0 å¾ ç»´ä¿® 1å®ç»") @ApiModelProperty("ç¶æ 0 å¾ ç»´ä¿® 1å®ç» 2 失败") private Integer status; @ApiModelProperty("å建æ¶é´") src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,109 @@ package com.ruoyi.device.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDate; import java.time.LocalDateTime; /** * @author :yys * @date : 2025/9/19 10:27 */ @Data @ApiModel @TableName("maintenance_task") public class MaintenanceTask { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "è§æ ¼åå·") private String deviceModel; /** * 主é®ID */ @TableId(type = IdType.AUTO) private Long id; @ApiModelProperty(value = "设å¤åç§°") @Excel(name = "ä¿å »ä»»å¡åç§°") private String taskName; @ApiModelProperty(value = "设å¤id") private Long taskId; @ApiModelProperty(value = "颿¬¡") @Excel(name = "颿¬¡") private String frequencyType; @ApiModelProperty(value = "颿¬¡è¯¦æ ") @Excel(name = "å¼å§æ¥æä¸æ¶é´") private String frequencyDetail; @ApiModelProperty(value = "䏿¬¡æ§è¡æ¶é´") private LocalDateTime nextExecutionTime; @ApiModelProperty(value = "æåæ§è¡æ¶é´") private LocalDateTime lastExecutionTime; @ApiModelProperty(value = "æ¯å¦æ¿æ´»") private boolean isActive; @ApiModelProperty(value = "夿³¨") @Excel(name = "夿³¨") private String remarks; @ApiModelProperty(value = "å½å ¥äººid") private Long registrantId; @ApiModelProperty(value = "å½å ¥äºº") @Excel(name = "å½å ¥äºº") private String registrant; @ApiModelProperty(value = "å½å ¥æ¥æ") @Excel(name = "å½å ¥æ¥æ", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate registrationDate; @ApiModelProperty(value = "ç¶æ") private String status; @ApiModelProperty(value = "软å 餿 å¿ï¼0=æªå é¤ï¼1=å·²å é¤") private Integer deleted; @TableField(exist = false) private String dateStr; @ApiModelProperty(value = "å建该记å½çç¨æ·") @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT) private Integer createUser; @ApiModelProperty(value = "è®°å½å建æ¶é´") @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT) // @JsonFormat(pattern = "yyyy-MM-dd") // @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDateTime createTime; @ApiModelProperty(value = "æåä¿®æ¹è¯¥è®°å½çç¨æ·") @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE) private Integer updateUser; @ApiModelProperty(value = "è®°å½æåæ´æ°æ¶é´") @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @ApiModelProperty(value = "ç§æ·ID") @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT) private Long tenantId; } src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,25 @@ package com.ruoyi.device.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.device.pojo.DeviceMaintenance; import com.ruoyi.device.pojo.MaintenanceTask; import com.ruoyi.framework.web.domain.AjaxResult; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; /** * @author :yys * @date : 2025/12/22 14:56 */ public interface MaintenanceTaskService extends IService<MaintenanceTask> { AjaxResult listPage(Page page, MaintenanceTask maintenanceTask); AjaxResult add(MaintenanceTask maintenanceTask); AjaxResult updateByMaintenanceTaskId(MaintenanceTask maintenanceTask); AjaxResult delete(List<Long> ids); } src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
@@ -59,7 +59,7 @@ supplierManageList.forEach(deviceMaintenance -> { DeviceMaintenanceExeclDto deviceRepairExeclDto = new DeviceMaintenanceExeclDto(); BeanUtils.copyProperties(deviceMaintenance,deviceRepairExeclDto); deviceRepairExeclDto.setStatus(deviceMaintenance.getStatus() == 0 ? "å¾ ç»´ä¿®" : "å®ç»"); deviceRepairExeclDto.setStatus(deviceMaintenance.getStatus() == 0 ? "å¾ ç»´ä¿®" : deviceMaintenance.getStatus() == 1 ? "å®ç»" : "失败"); // deviceRepairExeclDto.setMaintenanceResult(deviceMaintenance.getMaintenanceResult() != null && deviceMaintenance.getMaintenanceResult() == 0 ? "ç»´ä¿®" : "å®å¥½"); deviceLedgerExeclDtos.add(deviceRepairExeclDto); }); src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java
@@ -84,7 +84,7 @@ supplierManageList.stream().forEach(deviceRepair -> { DeviceRepairExeclDto deviceRepairExeclDto = new DeviceRepairExeclDto(); BeanUtils.copyProperties(deviceRepair,deviceRepairExeclDto); deviceRepairExeclDto.setStatusStr(deviceRepair.getStatus() == 0 ? "å¾ ç»´ä¿®" : "å®ç»"); deviceRepairExeclDto.setStatusStr(deviceRepair.getStatus() == 0 ? "å¾ ç»´ä¿®" : deviceRepair.getStatus() == 1 ? "å®ç»" : "失败"); deviceLedgerExeclDtos.add(deviceRepairExeclDto); }); @@ -100,7 +100,7 @@ supplierManageList.stream().forEach(deviceRepair -> { DeviceRepairExeclDto deviceRepairExeclDto = new DeviceRepairExeclDto(); BeanUtils.copyProperties(deviceRepair,deviceRepairExeclDto); deviceRepairExeclDto.setStatusStr(deviceRepair.getStatus() == 0 ? "å¾ ç»´ä¿®" : "å®ç»"); deviceRepairExeclDto.setStatusStr(deviceRepair.getStatus() == 0 ? "å¾ ç»´ä¿®" : deviceRepair.getStatus() == 1 ? "å®ç»" : "失败"); deviceLedgerExeclDtos.add(deviceRepairExeclDto); }); src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,248 @@ package com.ruoyi.device.service.impl; import com.ruoyi.device.pojo.DeviceMaintenance; import com.ruoyi.device.pojo.MaintenanceTask; import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper; import com.ruoyi.inspectiontask.mapper.TimingTaskMapper; import com.ruoyi.inspectiontask.pojo.InspectionTask; import com.ruoyi.inspectiontask.pojo.TimingTask; import com.ruoyi.inspectiontask.service.TimingTaskService; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import java.io.Serializable; import java.time.DayOfWeek; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.YearMonth; import java.util.HashSet; import java.util.List; import java.util.Set; @Component @DisallowConcurrentExecution // ç¦æ¢å¹¶åæ§è¡åä¸ä¸ªJob public class MaintenanceTaskJob implements Job, Serializable { private static final long serialVersionUID = 1L; // å¿ é¡»å®ä¹åºååID @Autowired private DeviceMaintenanceServiceImpl deviceMaintenanceService; @Autowired private JdbcTemplate jdbcTemplate; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); // ä¿®å¤ç±»å转æ¢éè¯¯ï¼æ£ç¡®è·åtaskId Long taskId = jobDataMap.getLong("maintenanceTaskId"); try { // 3. å°è¯æ¥è¯¢ä½ çä¸å¡æ°æ® // éè¿JDBCæ¨¡æ¿æ¥è¯¢å®æ¶ä»»å¡ä¿¡æ¯ï¼ä½¿ç¨åæ°åæ¥è¯¢é²æ¢SQLæ³¨å ¥ String yourSql = "SELECT * FROM maintenance_task where id = ?"; List<MaintenanceTask> tasks = jdbcTemplate.query( yourSql, new BeanPropertyRowMapper<>(MaintenanceTask.class), taskId ); MaintenanceTask timingTask = tasks.isEmpty() ? null : tasks.get(0); if (timingTask == null) { throw new JobExecutionException("MaintenanceTaskJobæ¾ä¸å°å®æ¶ä»»å¡: " + taskId); } // 2. å建并ä¿åå·¡æ£ä»»å¡è®°å½ - è¿å°±æ¯æ¨æä¾ç代ç åºè¯¥æ¾çä½ç½® DeviceMaintenance deviceMaintenance = createInspectionTask(timingTask); deviceMaintenanceService.save(deviceMaintenance); // 3. æ´æ°å®æ¶ä»»å¡çæ§è¡æ¶é´ if (!tasks.isEmpty()) { MaintenanceTask task = tasks.get(0); // æ´æ°æåæ§è¡æ¶é´ä¸ºå½åæ¶é´ LocalDateTime lastExecutionTime = LocalDateTime.now(); // 计ç®ä¸æ¬¡æ§è¡æ¶é´ LocalDateTime nextExecutionTime = calculateNextExecutionTime( task.getFrequencyType(), task.getFrequencyDetail(), lastExecutionTime ); // æ§è¡æ´æ°æä½ String updateSql = "UPDATE maintenance_task " + "SET last_execution_time = ?, next_execution_time = ? " + "WHERE id = ?"; jdbcTemplate.update( updateSql, lastExecutionTime, nextExecutionTime, taskId ); } } catch (Exception e) { throw new JobExecutionException(e); } } // è¿å°±æ¯æ¨æä¾ç代ç å°è£ æçæ¹æ³ private DeviceMaintenance createInspectionTask(MaintenanceTask timingTask) { DeviceMaintenance inspectionTask = new DeviceMaintenance(); // å¤å¶åºæ¬å±æ§ inspectionTask.setDeviceName(timingTask.getTaskName()); inspectionTask.setMaintenanceTaskId(timingTask.getId()); inspectionTask.setDeviceLedgerId(timingTask.getTaskId()); inspectionTask.setMaintenancePlanTime(LocalDateTime.now()); inspectionTask.setFrequencyType(timingTask.getFrequencyType()); inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail()); inspectionTask.setTenantId(timingTask.getTenantId()); inspectionTask.setStatus(0); inspectionTask.setDeviceModel(timingTask.getDeviceModel()); inspectionTask.setCreateUser(Integer.parseInt(timingTask.getRegistrantId().toString())); inspectionTask.setUpdateTime(LocalDateTime.now()); inspectionTask.setCreateTime(LocalDateTime.now()); inspectionTask.setUpdateUser(Integer.parseInt(timingTask.getRegistrantId().toString())); return inspectionTask; } /** * 计ç®ä¸æ¬¡æ§è¡æ¶é´ */ private LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime) { try { switch (frequencyType) { case "DAILY": return calculateDailyNextTime(frequencyDetail, currentTime); case "WEEKLY": return calculateWeeklyNextTime(frequencyDetail, currentTime); case "MONTHLY": return calculateMonthlyNextTime(frequencyDetail, currentTime); case "QUARTERLY": return calculateQuarterlyNextTime(frequencyDetail, currentTime); default: throw new IllegalArgumentException("䏿¯æçé¢çç±»å: " + frequencyType); } } catch (Exception e) { throw new RuntimeException("计ç®ä¸æ¬¡æ§è¡æ¶é´å¤±è´¥: " + e.getMessage(), e); } } /** * è®¡ç®æ¯æ¥ä»»å¡ç䏿¬¡æ§è¡æ¶é´ */ private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) { LocalTime executionTime = LocalTime.parse(timeStr); // è§£ææ ¼å¼ "HH:mm" LocalDateTime nextTime = LocalDateTime.of(current.toLocalDate(), executionTime); // 妿ä»å¤©çæ¶é´å·²è¿ï¼å宿æå¤© return current.isBefore(nextTime) ? nextTime : nextTime.plusDays(1); } /** * è®¡ç®æ¯å¨ä»»å¡ç䏿¬¡æ§è¡æ¶é´ */ private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime current) { String[] parts = detail.split(","); String dayOfWeekStr = parts[0]; // å¦ "MON" æ "MON|WED|FRI" LocalTime time = LocalTime.parse(parts[1]); // æ¶é´é¨å // è§£æææå (æ¯æå¤ä¸ªææ) Set<DayOfWeek> targetDays = parseDayOfWeeks(dayOfWeekStr); // ä»å½åæ¶é´å¼å§æ¾ä¸ä¸ä¸ªç¬¦åæ¡ä»¶çææå LocalDateTime nextTime = current; while (true) { nextTime = nextTime.plusDays(1); if (targetDays.contains(nextTime.getDayOfWeek())) { return LocalDateTime.of(nextTime.toLocalDate(), time); } // 鲿¢æ é循ç¯(ç论ä¸ä¸ä¼åç) if (nextTime.isAfter(current.plusYears(1))) { throw new RuntimeException("æ æ³æ¾å°ä¸æ¬¡æ§è¡æ¶é´"); } } } /** * è®¡ç®æ¯æä»»å¡ç䏿¬¡æ§è¡æ¶é´ */ private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime current) { String[] parts = detail.split(","); int dayOfMonth = Integer.parseInt(parts[0]); LocalTime time = LocalTime.parse(parts[1]); // ä»ä¸ä¸ªæå¼å§è®¡ç® LocalDateTime nextTime = current.plusMonths(1) .withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth())) .with(time); return nextTime; } /** * è®¡ç®æ¯å£åº¦ä»»å¡ç䏿¬¡æ§è¡æ¶é´ */ private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) { String[] parts = detail.split(","); int quarterMonth = Integer.parseInt(parts[0]); // 1=第1个æï¼2=第2个æï¼3=第3个æ int dayOfMonth = Integer.parseInt(parts[1]); LocalTime time = LocalTime.parse(parts[2]); // 计ç®å½åå£åº¦ int currentQuarter = (current.getMonthValue() - 1) / 3 + 1; int currentMonthInQuarter = (current.getMonthValue() - 1) % 3 + 1; YearMonth targetYearMonth; if (currentMonthInQuarter < quarterMonth) { // æ¬å£åº¦å è¿ææ§è¡æºä¼ targetYearMonth = YearMonth.from(current) .plusMonths(quarterMonth - currentMonthInQuarter); } else { // éè¦å°ä¸ä¸ªå£åº¦ targetYearMonth = YearMonth.from(current) .plusMonths(3 - currentMonthInQuarter + quarterMonth); } // å¤çææ«æ¥æ int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth()); return LocalDateTime.of( targetYearMonth.getYear(), targetYearMonth.getMonthValue(), adjustedDay, time.getHour(), time.getMinute() ); } /** * è§£æææå å符串 */ private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) { Set<DayOfWeek> days = new HashSet<>(); String[] dayStrs = dayOfWeekStr.split("\\|"); for (String dayStr : dayStrs) { switch (dayStr) { case "MON": days.add(DayOfWeek.MONDAY); break; case "TUE": days.add(DayOfWeek.TUESDAY); break; case "WED": days.add(DayOfWeek.WEDNESDAY); break; case "THU": days.add(DayOfWeek.THURSDAY); break; case "FRI": days.add(DayOfWeek.FRIDAY); break; case "SAT": days.add(DayOfWeek.SATURDAY); break; case "SUN": days.add(DayOfWeek.SUNDAY); break; default: throw new IllegalArgumentException("æ æçææå : " + dayStr); } } return days; } } src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,278 @@ package com.ruoyi.device.service.impl; import com.ruoyi.device.pojo.MaintenanceTask; import lombok.extern.slf4j.Slf4j; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeParseException; import java.util.Arrays; import java.util.Date; import java.util.stream.Collectors; /** * @author :yys * @date : 2025/12/22 15:16 */ @Service @Slf4j public class MaintenanceTaskScheduler { @Autowired private Scheduler scheduler; /** * æ·»å æ°ä»»å¡å°è°åº¦å¨ */ public void scheduleMaintenanceTask(MaintenanceTask task){ try { JobDetail jobDetail = buildJobDetail(task); Trigger trigger = buildJobTrigger(task, jobDetail); scheduler.scheduleJob(jobDetail, trigger); }catch (SchedulerException e){ log.error("SchedulerException scheduleMaintenanceTask ERROR",e); throw new RuntimeException(e); } } /** * æ´æ°å·²æä»»å¡ */ public void rescheduleMaintenanceTask(MaintenanceTask task){ try{ TriggerKey triggerKey = new TriggerKey("triggerMaintenanceTask_" + task.getId()); // è·åç°æè§¦åå¨å¹¶è½¬æ¢ä¸º CronTrigger Trigger oldTrigger = scheduler.getTrigger(triggerKey); if (!(oldTrigger instanceof CronTrigger)) { throw new SchedulerException("Existing trigger is not a CronTrigger"); } // 3. æå»ºCronTriggerï¼ç¡®ä¿æä¹ åé ç½® CronTrigger newTrigger = TriggerBuilder.newTrigger() .withIdentity(triggerKey) // å¯ä¸æ è¯ï¼ç¨äºæä¹ ååå¨ .withDescription(task.getTaskName() + "_TRIGGER") // 触åå¨æè¿° .forJob(oldTrigger.getJobKey()) // å ³è对åºçJob .withSchedule(CronScheduleBuilder .cronSchedule(convertToCronExpression(task)) // éè¿æ§è¡æ¶ççç¥ï¼æ ¹æ®ä¸å¡è°æ´ï¼ ) // 4. 设置å¼å§æ¶é´ï¼è¥ä¸ºnullåç«å³çæï¼ .startAt(task.getNextExecutionTime() != null ? Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant()) : new Date()) .build(); scheduler.rescheduleJob(triggerKey, newTrigger); }catch (SchedulerException e){ log.error("SchedulerException rescheduleMaintenanceTask ERROR",e); throw new RuntimeException(e); } } /** * æåä»»å¡ */ public void pauseMaintenanceTask(Long taskId) throws SchedulerException { JobKey jobKey = new JobKey("MaintenanceTask_" + taskId); scheduler.pauseJob(jobKey); } /** * æ¢å¤ä»»å¡ */ public void resumeMaintenanceTask(Long taskId) throws SchedulerException { JobKey jobKey = new JobKey("MaintenanceTask_" + taskId); scheduler.resumeJob(jobKey); } /** * å é¤ä»»å¡ */ public void unscheduleMaintenanceTask(Long taskId){ try { JobKey jobKey = new JobKey("MaintenanceTask_" + taskId); scheduler.deleteJob(jobKey); }catch (SchedulerException e){ log.error("SchedulerException unscheduleMaintenanceTask ERROR",e); throw new RuntimeException(e); } } private JobDetail buildJobDetail(MaintenanceTask task) { // 1. æå»ºå¯ä¸JobKeyï¼åºäºä»»å¡IDï¼ç¡®ä¿éå¯åè½è¯å«ï¼ JobKey jobKey = new JobKey("MaintenanceTask_" + task.getId()); // 2. å°è£ 任塿°æ®ï¼ä» 使ç¨åºæ¬ç±»åï¼ç¡®ä¿å¯åºååï¼ JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put("maintenanceTaskId", task.getId()); // ä»»å¡IDï¼Longï¼å¯åºååï¼ jobDataMap.put("taskName", task.getTaskName()); // ä»»å¡åç§°ï¼Stringï¼å¯åºååï¼ jobDataMap.put("taskType", task.getFrequencyType()); // ä»»å¡ç±»åï¼Stringï¼ // æéæ·»å å ¶ä»å¿ è¦çåºæ¬ç±»ååæ° // 3. æå»ºJobDetailï¼è®¾ç½®æä¹ åç¸å ³å±æ§ return JobBuilder.newJob(MaintenanceTaskJob.class) .withIdentity(jobKey) // å¯ä¸æ è¯ï¼ç¨äºæä¹ ååå¨ .withDescription(task.getTaskName()) // ä»»å¡æè¿°ï¼åå ¥æ°æ®åº .usingJobData(jobDataMap) // ç»å®ä»»å¡æ°æ® .storeDurably(true) // å³ä½¿æ²¡æè§¦åå¨å ³èä¹æä¹ åä¿å .requestRecovery(true) // å½è°åº¦å¨å´©æºåæ¢å¤æ¶ï¼éæ°æ§è¡æªå®æçä»»å¡ .build(); } private Trigger buildJobTrigger(MaintenanceTask task, JobDetail jobDetail) { // 1. æå»ºå¯ä¸TriggerKeyï¼åºäºä»»å¡IDï¼ TriggerKey triggerKey = new TriggerKey("triggerMaintenanceTask_" + task.getId()); // 2. çæCron表达å¼ï¼åé»è¾ä¸åï¼ String cronExpression = convertToCronExpression(task); // 3. æå»ºCronTriggerï¼ç¡®ä¿æä¹ åé ç½® return TriggerBuilder.newTrigger() .withIdentity(triggerKey) // å¯ä¸æ è¯ï¼ç¨äºæä¹ ååå¨ .withDescription(task.getTaskName() + "_TRIGGER") // 触åå¨æè¿° .forJob(jobDetail) // å ³è对åºçJob .withSchedule(CronScheduleBuilder .cronSchedule(cronExpression) .withMisfireHandlingInstructionDoNothing() // éè¿æ§è¡æ¶ççç¥ï¼æ ¹æ®ä¸å¡è°æ´ï¼ ) // 4. 设置å¼å§æ¶é´ï¼è¥ä¸ºnullåç«å³çæï¼ .startAt(task.getNextExecutionTime() != null ? Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant()) : new Date()) .build(); } private String convertToCronExpression(MaintenanceTask task) { // åæ°æ ¡éª if (task == null || task.getFrequencyType() == null || task.getFrequencyDetail() == null) { throw new IllegalArgumentException("ä»»å¡åæ°ä¸è½ä¸ºç©º"); } // 使ç¨switchç¡®ä¿æ¡ä»¶äºæ¥ String frequencyType = task.getFrequencyType().toUpperCase(); // ç»ä¸è½¬ä¸ºå¤§åæ¯è¾ switch (frequencyType) { case "DAILY": return convertDailyToCron(task.getFrequencyDetail()); case "WEEKLY": return convertWeeklyToCron(task.getFrequencyDetail()); case "MONTHLY": return convertMonthlyToCron(task.getFrequencyDetail()); case "QUARTERLY": return convertQuarterlyToCron(task.getFrequencyDetail()); default: throw new IllegalArgumentException("䏿¯æçé¢çç±»å: " + task.getFrequencyType()); } } // æ¯æ¥ä»»å¡è½¬æ¢ private String convertDailyToCron(String frequencyDetail) { LocalTime time = parseTime(frequencyDetail); return String.format("0 %d %d * * ?", time.getMinute(), time.getHour()); } // æ¯å¨ä»»å¡è½¬æ¢ private String convertWeeklyToCron(String frequencyDetail) { String[] parts = validateAndSplit(frequencyDetail, ",", 2); String daysOfWeek = convertDayNamesToCron(parts[0]); LocalTime time = parseTime(parts[1]); return String.format("0 %d %d ? * %s", time.getMinute(), time.getHour(), daysOfWeek); } // æ¯æä»»å¡è½¬æ¢ private String convertMonthlyToCron(String frequencyDetail) { String[] parts = validateAndSplit(frequencyDetail, ",", 2); int day = validateDayOfMonth(parts[0]); LocalTime time = parseTime(parts[1]); return String.format("0 %d %d %d * ?", time.getMinute(), time.getHour(), day); } // æ¯å£åº¦ä»»å¡è½¬æ¢ private String convertQuarterlyToCron(String frequencyDetail) { String[] parts = validateAndSplit(frequencyDetail, ",", 3); int month = validateMonth(parts[0]); // éªè¯æä»½(1-12) int day = validateDayOfMonth(parts[1]); // éªè¯æ¥æ LocalTime time = parseTime(parts[2]); // è§£ææ¶é´ // 计ç®å£åº¦èµ·å§æä»½(1æ=1, 4æ=4, 7æ=7, 10æ=10) int quarterStartMonth = ((month - 1) / 3) * 3 + 1; return String.format("0 %d %d %d %d/3 ?", time.getMinute(), time.getHour(), day, quarterStartMonth); } // æ°å¢éªè¯æä»½çæ¹æ³(1-12) private int validateMonth(String monthStr) { try { int month = Integer.parseInt(monthStr); if (month < 1 || month > 12) { throw new IllegalArgumentException("æä»½å¿ é¡»å¨1-12ä¹é´"); } return month; } catch (NumberFormatException e) { throw new IllegalArgumentException("æ æçæä»½æ ¼å¼"); } } // è¾ å©æ¹æ³ï¼è§£ææ¶é´ private LocalTime parseTime(String timeStr) { try { return LocalTime.parse(timeStr); } catch (DateTimeParseException e) { throw new IllegalArgumentException("æ¶é´æ ¼å¼å¿ 须为HH:mm", e); } } // è¾ å©æ¹æ³ï¼éªè¯å¹¶åå²å符串 private String[] validateAndSplit(String input, String delimiter, int expectedParts) { String[] parts = input.split(delimiter); if (parts.length != expectedParts) { throw new IllegalArgumentException( String.format("æ ¼å¼é误ï¼åºä¸º%dé¨åç¨'%s'åé", expectedParts, delimiter)); } return parts; } // è¾ å©æ¹æ³ï¼éªè¯æä»½ä¸çæ¥ private int validateDayOfMonth(String dayStr) { int day = Integer.parseInt(dayStr); if (day < 1 || day > 31) { throw new IllegalArgumentException("æ¥æå¿ é¡»å¨1-31ä¹é´"); } return day; } // è¾ å©æ¹æ³ï¼éªè¯å£åº¦ä¸çæ private int validateMonthInQuarter(String monthStr) { int month = Integer.parseInt(monthStr); if (month < 1 || month > 3) { throw new IllegalArgumentException("å£åº¦æä»½å¿ é¡»æ¯1ã2æ3"); } return month; } // è½¬æ¢ææå åç§° private String convertDayNamesToCron(String dayNames) { return Arrays.stream(dayNames.split("\\|")) .map(this::convertSingleDayName) .collect(Collectors.joining(",")); } // 转æ¢å个ææå åç§° private String convertSingleDayName(String dayName) { switch (dayName.toUpperCase()) { case "MON": return "MON"; case "TUE": return "TUE"; case "WED": return "WED"; case "THU": return "THU"; case "FRI": return "FRI"; case "SAT": return "SAT"; case "SUN": return "SUN"; default: throw new IllegalArgumentException("æ æçææå : " + dayName); } } } src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,119 @@ package com.ruoyi.device.service.impl; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.device.mapper.MaintenanceTaskMapper; import com.ruoyi.device.pojo.DeviceMaintenance; import com.ruoyi.device.pojo.MaintenanceTask; import com.ruoyi.device.service.MaintenanceTaskService; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.inspectiontask.dto.TimingTaskDto; import com.ruoyi.inspectiontask.pojo.TimingTask; import com.ruoyi.inspectiontask.service.impl.TimingTaskServiceImpl; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysUserMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; /** * @author :yys * @date : 2025/12/22 14:57 */ @Service @Slf4j public class MaintenanceTaskServiceImpl extends ServiceImpl<MaintenanceTaskMapper, MaintenanceTask> implements MaintenanceTaskService { @Autowired private MaintenanceTaskMapper maintenanceTaskMapper; @Autowired private SysUserMapper sysUserMapper; @Autowired private TimingTaskServiceImpl timingTaskService; @Autowired private MaintenanceTaskScheduler maintenanceTaskScheduler; @Override public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) { Page<MaintenanceTask> taskPage = maintenanceTaskMapper.selectPage(page, null); // 2. å¦ææ²¡ææ°æ®ï¼ç´æ¥è¿å空å页 if (taskPage.getRecords().isEmpty()) { return AjaxResult.success(taskPage); } // 3. æ¶éææéè¦æ¥è¯¢çç¨æ·ID Set<Long> userIds = new HashSet<>(); // æ¶éç»è®°äººID taskPage.getRecords().forEach(task -> { if (task.getRegistrantId() != null) { userIds.add(task.getRegistrantId()); } }); // 4. æ¹éæ¥è¯¢ç¨æ·ä¿¡æ¯ Map<Long, String> userNickNameMap = new HashMap<>(); if (!userIds.isEmpty()) { List<SysUser> users = sysUserMapper.selectUserByIds((new ArrayList<>(userIds))); users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName())); } taskPage.getRecords().forEach(task -> { // 设置ç»è®°äººæµç§° if (task.getRegistrantId() != null) { task.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "æªç¥ç¨æ·")); } }); return AjaxResult.success(taskPage); } @Override public AjaxResult add(MaintenanceTask maintenanceTask) { maintenanceTask.setActive(true); // 计ç®é¦æ¬¡æ§è¡æ¶é´ TimingTask task = new TimingTask(); task.setFrequencyType(maintenanceTask.getFrequencyType()); task.setFrequencyDetail(maintenanceTask.getFrequencyDetail()); LocalDateTime firstExecutionTime = timingTaskService.calculateFirstExecutionTime(task); maintenanceTask.setNextExecutionTime(firstExecutionTime); int insert = maintenanceTaskMapper.insert(maintenanceTask); if (insert > 0) { maintenanceTaskScheduler.scheduleMaintenanceTask(maintenanceTask); } return AjaxResult.success("æ·»å æå"); } @Override public AjaxResult updateByMaintenanceTaskId(MaintenanceTask maintenanceTask) { MaintenanceTask maintenanceTask1 = maintenanceTaskMapper.selectById(maintenanceTask.getId()); if (maintenanceTask1 == null) { return AjaxResult.warn("æ²¡ææ¤æ°æ®"); } BeanUtils.copyProperties(maintenanceTask, maintenanceTask1); int update = maintenanceTaskMapper.updateById(maintenanceTask1); if (update > 0) { maintenanceTaskScheduler.rescheduleMaintenanceTask(maintenanceTask1); } return AjaxResult.success("æ´æ°æå"); } @Override public AjaxResult delete(List<Long> ids) { int delete = maintenanceTaskMapper.deleteBatchIds(ids); if (delete > 0) { ids.forEach(id -> { maintenanceTaskScheduler.unscheduleMaintenanceTask(id); }); } return AjaxResult.success("å 餿å"); } } src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -85,5 +85,10 @@ return AjaxResult.success(map); } @GetMapping("/noticesCount") @ApiOperation("æªè¿æçå ¬åæ°é") public AjaxResult noticesCount(){ Long count = homeService.noticesCount(); return AjaxResult.success(count); } } src/main/java/com/ruoyi/home/service/HomeService.java
@@ -29,4 +29,6 @@ StatisticsReceivablePayableDto statisticsReceivablePayable(Integer type); Map<String, Object> approveAndDeviceTodos(); Long noticesCount(); } src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3,6 +3,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.approve.mapper.ApproveProcessMapper; import com.ruoyi.approve.pojo.ApproveProcess; import com.ruoyi.collaborativeApproval.mapper.NoticeMapper; import com.ruoyi.collaborativeApproval.pojo.Notice; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.device.mapper.DeviceMaintenanceMapper; import com.ruoyi.device.mapper.DeviceRepairMapper; @@ -93,6 +95,9 @@ @Autowired private SysDeptMapper sysDeptMapper; @Autowired private NoticeMapper noticeMapper; @Override public HomeBusinessDto business() { @@ -467,4 +472,12 @@ put("deviceRepairTodo", aLong1); }}; } @Override public Long noticesCount() { // æ¥è¯¢æªè¿æçéç¥æ°éï¼ç¶æä¸ºåå¸ä¸è¿ææ¶é´å¤§äºçäºå½åæ¥æ return noticeMapper.selectCount(new LambdaQueryWrapper<Notice>() .eq(Notice::getStatus, 1) // 1表示åå¸ç¶æ .ge(Notice::getExpirationDate, new Date())); // è¿ææ¶é´å¤§äºçäºå½åæ¥æ } } src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
@@ -3,6 +3,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.R; import com.ruoyi.inspectiontask.dto.TimingTaskDto; @@ -58,6 +60,7 @@ */ @PostMapping("/addOrEditTimingTask") @ApiOperation(value = "æ°å¢ä¿®æ¹å®æ¶ä»»å¡") @Log(title = "宿¶ä»»å¡", businessType = BusinessType.INSERT) public R addOrEditTimingTask(@RequestBody TimingTaskDto timingTaskDto) throws SchedulerException { return R.ok(timingTaskService.addOrEditTimingTask(timingTaskDto)); } @@ -67,6 +70,7 @@ */ @DeleteMapping("/delTimingTask") @ApiOperation(value = "å é¤å®æ¶ä»»å¡") @Log(title = "宿¶ä»»å¡", businessType = BusinessType.DELETE) public R remove(@RequestBody Long[] ids) { return R.ok(timingTaskService.delByIds(ids)); } src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
@@ -84,9 +84,13 @@ /** * å é¤ä»»å¡ */ public void unscheduleTimingTask(Long taskId) throws SchedulerException { JobKey jobKey = new JobKey("timingTask_" + taskId); scheduler.deleteJob(jobKey); public void unscheduleTimingTask(Long taskId){ try { JobKey jobKey = new JobKey("timingTask_" + taskId); scheduler.deleteJob(jobKey); }catch (SchedulerException e){ throw new RuntimeException(e); } } private JobDetail buildJobDetail(TimingTask task) { src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -155,7 +155,7 @@ } } private LocalDateTime calculateFirstExecutionTime(TimingTask task) { public LocalDateTime calculateFirstExecutionTime(TimingTask task) { // æ ¹æ®é¢çç±»åå详æ 计ç®é¦æ¬¡æ§è¡æ¶é´ String frequencyType = task.getFrequencyType(); if ("DAILY".equals(frequencyType)) { @@ -455,7 +455,13 @@ @Override public int delByIds(Long[] ids) { return timingTaskMapper.deleteBatchIds(Arrays.asList(ids)); int i = timingTaskMapper.deleteBatchIds(Arrays.asList(ids)); if(i > 0){ for (Long id : ids) { timingTaskScheduler.unscheduleTimingTask(id); } } return i; } } src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java
@@ -35,6 +35,18 @@ private ProcurementRecordService procurementRecordService; /** * éè¿éå®äº§åidè·åå ¥åºæ°é * @param salesProductId * @return */ @GetMapping("/getProcurementAmount") @ApiOperation(value = "éè¿éå®äº§åidè·åå ¥åºæ°é") public AjaxResult getProcurementAmount(@RequestParam("salesProductId") Long salesProductId) { return AjaxResult.success(procurementRecordService.getProcurementAmount(salesProductId)); } @GetMapping("/productlist") @Log(title = "éè´å ¥åº-å ¥åºç®¡ç-æ°å¢å ¥åºæ¥è¯¢", businessType = BusinessType.OTHER) public AjaxResult list(ProcurementDto procurementDto) { src/main/java/com/ruoyi/procurementrecord/dto/ProcurementRecordOutPageDto.java
@@ -6,6 +6,7 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Date; /** * @author :yys src/main/java/com/ruoyi/procurementrecord/pojo/CustomStorage.java
@@ -29,6 +29,12 @@ @Excel(name = "å ¥åºæ¶é´", width = 30, dateFormat = "yyyy-MM-dd") private Date inboundDate; /** * ç¼å· */ @Excel(name = "ç¼å·") private String code; @TableField(exist = false) private String timeStr; src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java
@@ -9,6 +9,7 @@ import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -54,4 +55,6 @@ AjaxResult deleteCustom(List<Long> ids); int updateManagementByCustom(ProcurementManagementUpdateDto procurementDto); BigDecimal getProcurementAmount(Long salesProductId); } src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.security.LoginUser; @@ -467,6 +468,7 @@ Long aLong = customStorageMapper.selectCount(null); item.setInboundBatches(aLong.equals(0L) ? "第1æ¹æ¬¡(èªå®ä¹å ¥åº)" : "第"+ (aLong + 1) + "æ¹æ¬¡(èªå®ä¹å ¥åº)" ); item.setCreateBy(loginUser.getNickName()); item.setCode(OrderUtils.countTodayByCreateTime(customStorageMapper, "")); customStorageMapper.insert(item); }); return AjaxResult.success("èªå®ä¹å ¥åºæå"); @@ -662,6 +664,20 @@ } @Override public BigDecimal getProcurementAmount(Long salesProductId) { LambdaQueryWrapper<ProcurementRecordStorage> procurementRecordStorageLambdaQueryWrapper = new LambdaQueryWrapper<>(); procurementRecordStorageLambdaQueryWrapper.eq(ProcurementRecordStorage::getSalesLedgerProductId, salesProductId) .eq(ProcurementRecordStorage::getType, 2); List<ProcurementRecordStorage> procurementRecordStorages = procurementRecordMapper.selectList(procurementRecordStorageLambdaQueryWrapper); if(CollectionUtils.isEmpty( procurementRecordStorages)){ return BigDecimal.ZERO; } return procurementRecordStorages.stream() .map(ProcurementRecordStorage::getInboundNum) .reduce(BigDecimal.ZERO, BigDecimal::add); } @Override public int add(ProcurementAddDto procurementDto) { LoginUser loginUser = SecurityUtils.getLoginUser(); // æ¹éæ°å¢ src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingDto.java
@@ -125,6 +125,9 @@ @Excel(name = "ç¶æ") private String status; @Excel(name = "è¿åº¦") private BigDecimal progress; @ApiModelProperty(value = "ç§æ·ID") private Long tenantId; src/main/java/com/ruoyi/production/service/impl/SalesLedgerSchedulingServiceImpl.java
@@ -85,12 +85,14 @@ // ç¶æ = æ°éåå®å·¥æ°éæ¯è¾ if(i.getSchedulingNum().compareTo(new BigDecimal(0)) == 0){ i.setStatus("æªå®æ"); i.setStatus("æªå¼å§"); } else if(i.getQuantity().compareTo(i.getSchedulingNum()) <= 0){ i.setStatus("已宿"); }else{ i.setStatus("ç产ä¸"); } // è¿åº¦ä¿ç两ä½å°æ° i.setProgress(i.getSchedulingNum().divide(i.getQuantity(),4,RoundingMode.CEILING).multiply(new BigDecimal(100))); }); return list; src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -10,15 +10,15 @@ import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.page.TableDataInfo; import com.ruoyi.production.mapper.SalesLedgerWorkMapper; import com.ruoyi.production.pojo.SalesLedgerWork; import com.ruoyi.sales.dto.InvoiceLedgerDto; import com.ruoyi.sales.dto.SalesLedgerDto; import com.ruoyi.sales.mapper.InvoiceLedgerMapper; import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper; import com.ruoyi.sales.mapper.ReceiptPaymentMapper; import com.ruoyi.sales.pojo.InvoiceLedger; import com.ruoyi.sales.pojo.InvoiceRegistrationProduct; import com.ruoyi.sales.pojo.ReceiptPayment; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.pojo.*; import com.ruoyi.sales.service.ICommonFileService; import com.ruoyi.sales.service.ISalesLedgerService; import lombok.AllArgsConstructor; @@ -28,10 +28,7 @@ import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.*; import java.util.stream.Collectors; /** @@ -57,6 +54,12 @@ @Autowired private ReceiptPaymentMapper receiptPaymentMapper; @Autowired private SalesLedgerProductMapper salesLedgerProductMapper; @Autowired private SalesLedgerWorkMapper salesLedgerWorkMapper; /** * æ¥è¯¢éå®å°è´¦å表 @@ -205,19 +208,54 @@ } List<Long> salesLedgerIds = iPage.getRecords().stream().map(SalesLedger::getId).collect(Collectors.toList()); List<InvoiceLedgerDto> invoiceLedgerDtoList = invoiceLedgerMapper.invoicedTotal(salesLedgerIds); if(CollectionUtils.isEmpty(invoiceLedgerDtoList)){ return iPage; } // 计ç®å款éé¢ï¼å¾ 忬¾éé¢ List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(new LambdaQueryWrapper<InvoiceRegistrationProduct>() .in(InvoiceRegistrationProduct::getSalesLedgerId, salesLedgerIds)); List<InvoiceLedger> invoiceLedgers = invoiceLedgerMapper.selectList(new LambdaQueryWrapper<InvoiceLedger>() .in(InvoiceLedger::getInvoiceRegistrationProductId, invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getId).collect(Collectors.toList()))); List<InvoiceLedger> invoiceLedgers = new ArrayList<>(); if(!CollectionUtils.isEmpty(invoiceRegistrationProducts)){ invoiceLedgers = invoiceLedgerMapper.selectList(new LambdaQueryWrapper<InvoiceLedger>() .in(InvoiceLedger::getInvoiceRegistrationProductId, invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getId).collect(Collectors.toList()))); } List<ReceiptPayment> receiptPayments = new ArrayList<>(); if(!CollectionUtils.isEmpty(invoiceLedgers)){ receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper<ReceiptPayment>() .in(ReceiptPayment::getInvoiceLedgerId, invoiceLedgers.stream().map(InvoiceLedger::getId).collect(Collectors.toList()))); } // è·åéå®äº§åæ°é List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper .selectList(new LambdaQueryWrapper<SalesLedgerProduct>() .eq(SalesLedgerProduct::getType, 1) .in(SalesLedgerProduct::getSalesLedgerId, salesLedgerIds)); Map<Long, BigDecimal> salesLedgerProductCountMap = new HashMap<>(); if (!CollectionUtils.isEmpty(salesLedgerProducts)) { salesLedgerProductCountMap = salesLedgerProducts .stream() .filter(Objects::nonNull) .collect(Collectors.groupingBy( SalesLedgerProduct::getSalesLedgerId, Collectors.reducing( BigDecimal.ZERO, SalesLedgerProduct::getQuantity, BigDecimal::add ) )); } // è·åéå®äº§åç产æ¥å·¥æ°é List<SalesLedgerWork> salesLedgerWorks = salesLedgerWorkMapper.selectList(new LambdaQueryWrapper<SalesLedgerWork>() .in(SalesLedgerWork::getSalesLedgerId, salesLedgerIds)); Map<Long, BigDecimal> salesLedgerWorkCountMap = new HashMap<>(); if (!CollectionUtils.isEmpty(salesLedgerWorks)) { salesLedgerWorkCountMap = salesLedgerWorks .stream() .filter(Objects::nonNull) .collect(Collectors.groupingBy( SalesLedgerWork::getSalesLedgerId, Collectors.reducing( BigDecimal.ZERO, SalesLedgerWork::getFinishedNum, BigDecimal::add ) )); } for (SalesLedger salesLedger : iPage.getRecords()) { boolean existFlag = false; @@ -257,6 +295,8 @@ salesLedger.setNoInvoiceAmountTotal(salesLedger.getContractAmount()); } salesLedger.setInvoiceTotal(invoiceTotal); // 夿æ¯å¦æ¯çäº§å®æ salesLedger.setProductionStatus(salesLedgerProductCountMap.get(salesLedger.getId()) == null ? "æªå¼å§" : salesLedgerProductCountMap.get(salesLedger.getId()).compareTo(salesLedgerWorkCountMap.get(salesLedger.getId())) > 0 ? "ç产ä¸" : "已宿"); } if (ObjectUtils.isNotEmpty(salesLedgerDto.getStatus())) { if (salesLedgerDto.getStatus()) { src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -48,6 +48,14 @@ private String shippingCarNumber; /** * åè´§æ¥æ */ @Excel(name = "åè´§æ¥æ", width = 30, dateFormat = "yyyy-MM-dd") @TableField(exist = false) @JsonFormat(pattern = "yyyy-MM-dd") private Date shippingDate; /** * 项ç®åç§° */ @Excel(name = "项ç®åç§°") @@ -132,5 +140,9 @@ @ApiModelProperty(value = "仿¬¾æ¹å¼") private String paymentMethod; @TableField(exist = false) @ApiModelProperty(value = "çäº§ç¶æ") private String productionStatus = "æªå¼å§"; } src/main/resources/mapper/collaborativeApproval/NoticeMapper.xml
@@ -16,6 +16,9 @@ <if test="ew.status != null"> and n.status = #{ew.status} </if> <if test="ew.currentDate != null"> and n.expiration_date >= DATE_FORMAT(#{ew.currentDate},'%Y-%m-%d') </if> </where> </select> </mapper> src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml
@@ -140,10 +140,12 @@ t1.create_time, t1.update_time, t1.create_by, t2.warn_num t2.warn_num, SUM(t1.inbound_num) - COALESCE(SUM(t4.inbound_num), 0) AS availableStock from procurement_record_storage t1 left join sales_ledger_product t2 on t2.id = t1.sales_ledger_product_id and t2.type = 2 left join purchase_ledger t3 on t3.id = t2.sales_ledger_id left join procurement_record_out t4 on t1.id = t4.procurement_record_storage_id and t4.type = 1 <where> t1.type = 1 <if test="req.supplierName != null and req.supplierName != ''"> @@ -172,6 +174,7 @@ </if> </where> group by t2.product_category,t2.specification_model,t1.unit_price having availableStock > 0 order by t1.create_time desc </select> <select id="listCopy" resultType="com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy"> @@ -296,10 +299,12 @@ t1.create_time, t1.update_time, t1.create_by, t2.warn_num t2.warn_num, SUM(t1.inbound_num) - COALESCE(SUM(t4.inbound_num), 0) AS availableStock from procurement_record_storage t1 left join sales_ledger_product t2 on t2.id = t1.sales_ledger_product_id and t2.type = 1 left join sales_ledger t3 on t3.id = t2.sales_ledger_id left join procurement_record_out t4 on t1.id = t4.procurement_record_storage_id and t4.type = 2 <where> t1.type = 2 <if test="req.customerName != null and req.customerName != ''"> @@ -328,6 +333,7 @@ </if> </where> group by t2.product_category,t2.specification_model,t1.unit_price HAVING availableStock > 0 order by t1.create_time desc </select> </mapper> src/main/resources/mapper/procurementrecord/ProcurementRecordOutMapper.xml
@@ -142,7 +142,6 @@ t2.supplier_name, t2.product_category, t1.id, t1.code, t2.specification_model, t2.unit, t2.tax_rate, @@ -152,7 +151,8 @@ t1.inbound_num, t1.create_time, t1.create_by, t2.item_type t2.item_type, t2.code from procurement_record_out t1 left join custom_storage t2 on t2.id = t1.procurement_record_storage_id <where> src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -59,7 +59,8 @@ T1.execution_date, T2.nick_name AS entry_person_name, T1.payment_method, t3.shipping_car_number t3.shipping_car_number, t3.shipping_date FROM sales_ledger T1 LEFT JOIN sys_user T2 ON T1.entry_person = T2.user_id