From c2ec3f0dbf07c434357df3b4a18f81e9ede4d106 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Thu, 23 Apr 2026 17:39:04 +0800 Subject: [PATCH 1/8] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96app=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E6=9F=A5=E8=AF=A2=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/service/mold/MoldService.java | 4 + .../erp/service/mold/MoldServiceImpl.java | 7 + .../admin/device/DeviceController.java | 6 +- .../enums/DeviceRateTrendPeriodEnum.java | 4 + .../DeviceOperationRecordController.java | 7 +- .../vo/DeviceTotalTimeRecordReqVO.java | 3 + .../iot/dal/mysql/device/DeviceMapper.java | 5 +- .../iot/service/device/DeviceService.java | 2 + .../iot/service/device/DeviceServiceImpl.java | 307 +++++++++++++++--- .../iot/service/device/TDengineService.java | 105 ++++++ .../DeviceOperationRecordService.java | 2 +- .../DeviceOperationRecordServiceImpl.java | 192 +++++++++-- .../resources/mapper/device/DeviceMapper.xml | 8 + .../admin/dashboard/DashboardController.java | 137 ++++---- .../deviceledger/DeviceLedgerService.java | 2 + .../deviceledger/DeviceLedgerServiceImpl.java | 7 + 16 files changed, 667 insertions(+), 131 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldService.java index 77d2d84c2..0e3598627 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldService.java @@ -102,4 +102,8 @@ public interface MoldService { List getInTransitMoldAllList(); List getMoldListByStatus(Long status); + + List getMoldListByIds(Collection ids); + + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldServiceImpl.java index 97a1e4c1e..d8363e364 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldServiceImpl.java @@ -136,4 +136,11 @@ public class MoldServiceImpl implements MoldService { .eqIfPresent(MoldDO::getStatus, status); return moldMapper.selectList(queryWrapper); } + + @Override + public List getMoldListByIds(Collection ids) { + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + return moldMapper.selectBatchIds(ids); } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java index edf0fe2b0..ef0681e90 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java @@ -137,9 +137,9 @@ public class DeviceController { } @GetMapping("/deviceList") // @PreAuthorize("@ss.hasPermission('iot:device:query')") - public CommonResult> deviceList(@Valid DevicePageReqVO pageReqVO) { - pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = deviceService.getDevicePage(pageReqVO).getList(); + public CommonResult> deviceList(@Valid DevicePageReqVO pageReqVO) { +// List list = deviceService.getDevicePage(pageReqVO).getList(); + List list = deviceService.deviceList(pageReqVO); return success(list); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/enums/DeviceRateTrendPeriodEnum.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/enums/DeviceRateTrendPeriodEnum.java index ece8cfba2..d94145624 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/enums/DeviceRateTrendPeriodEnum.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/enums/DeviceRateTrendPeriodEnum.java @@ -9,6 +9,10 @@ import java.time.temporal.TemporalAdjusters; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_RATE_TREND_PERIOD_INVALID; + +/** + 不含今天日期枚举 + */ @Getter @AllArgsConstructor public enum DeviceRateTrendPeriodEnum { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/deviceoperationrecord/DeviceOperationRecordController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/deviceoperationrecord/DeviceOperationRecordController.java index cce051eee..f74ee3a5a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/deviceoperationrecord/DeviceOperationRecordController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/deviceoperationrecord/DeviceOperationRecordController.java @@ -111,10 +111,11 @@ public class DeviceOperationRecordController { } @GetMapping("/deviceRateTrendByDeviceId") - @Operation(summary = "根据设备ID查询某个设备近7日开机率和稼动率") + @Operation(summary = "根据设备ID查询某个设备开机率和稼动率") @PreAuthorize("@ss.hasPermission('iot:device-operation-record:query')") - public CommonResult> getDeviceRateTrendByDeviceId(@RequestParam("deviceId") Long deviceId) { - return success(deviceOperationRecordService.getDeviceRateTrendByDeviceId(deviceId)); + public CommonResult> getDeviceRateTrendByDeviceId(@RequestParam("deviceId") Long deviceId, + @RequestParam(value = "period", required = false) String period) { + return success(deviceOperationRecordService.getDeviceRateTrendByDeviceId(deviceId, period)); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/deviceoperationrecord/vo/DeviceTotalTimeRecordReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/deviceoperationrecord/vo/DeviceTotalTimeRecordReqVO.java index 0032afc7d..ab33724cd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/deviceoperationrecord/vo/DeviceTotalTimeRecordReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/deviceoperationrecord/vo/DeviceTotalTimeRecordReqVO.java @@ -14,6 +14,9 @@ import lombok.ToString; @ToString(callSuper = true) public class DeviceTotalTimeRecordReqVO extends PageParam{ + @Schema(description = "时间区间:LAST_WEEK/THIS_WEEK/LAST_7_DAYS/LAST_MONTH/THIS_MONTH") + private String period; + @Schema(description = "设备编码") private String deviceCode; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceMapper.java index 6b6cc8169..d8f8f4295 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceMapper.java @@ -140,6 +140,9 @@ public interface DeviceMapper extends BaseMapperX { List selectHolidayDays(@Param("startDay") Date startDay, @Param("endDay") Date endDay); - List getAvailableDevicePage(@Param("page") Page page,@Param("param") DevicePageReqVO pageReqVO); + + List selectHolidayDaysInRange(@Param("startDay") Date startDay, @Param("endDayExclusive") Date endDayExclusive); + + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java index d53c62e34..4d399004d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java @@ -157,4 +157,6 @@ public interface DeviceService { PageResult getAvailableDevicePage(DevicePageReqVO pageReqVO); + + List deviceList(@Valid DevicePageReqVO pageReqVO); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java index b435468d8..c950d5f07 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.scheduler.T import cn.iocoder.yudao.module.iot.controller.admin.device.utils.DataTypeParseUtil; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*; import cn.iocoder.yudao.module.iot.controller.admin.devicecontactmodel.vo.DeviceContactModelPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.utils.TimeConverterUtil; import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.vo.DeviceTotalTimeRecordReqVO; import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.vo.DeviceTotalTimeRecordRespVO; import cn.iocoder.yudao.module.iot.controller.admin.mqttdatarecord.vo.MqttDataRecordPageReqVO; @@ -64,10 +65,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.sql.Timestamp; import java.text.SimpleDateFormat; -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; +import java.time.*; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.Function; @@ -1746,40 +1744,97 @@ public class DeviceServiceImpl implements DeviceService { return new PageResult<>(availableDeviceList, page.getTotal()); } + @Override + public List deviceList(DevicePageReqVO pageReqVO) { + return deviceMapper.selectList(pageReqVO); + } + /** - * 按时间区间查询设备整体开机率、稼动率日趋势。 - * 按天复用 deviceOperationPage 统计单设备数据后求平均。 + * 按时间区间查询设备整体开机率、稼动率日趋势 + * 一次性查询时间范围内按天、按设备的统计数据,避免按天循环重复查库 */ @Override public List getDeviceRateTrend(DeviceRateTrendReqVO reqVO) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND); - // 根据 period 解析查询日期范围,不包含当天 - DeviceRateTrendPeriodEnum.DateRange dateRange = DeviceRateTrendPeriodEnum.valueOfCode(reqVO.getPeriod()).resolve(LocalDate.now()); - LocalDateTime startDateTime = dateRange.getStart().atStartOfDay(); - LocalDateTime endDateTime = dateRange.getEnd().atTime(LocalTime.MAX).withNano(0); - // 默认只统计排产设备,这里先得到最终参与统计的设备集合 + + DeviceRateTrendPeriodEnum.DateRange dateRange = + DeviceRateTrendPeriodEnum.valueOfCode(reqVO.getPeriod()).resolve(LocalDate.now()); + + LocalDate startDate = dateRange.getStart(); + LocalDate endDate = dateRange.getEnd(); + LocalDateTime startDateTime = startDate.atStartOfDay(); + LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX).withNano(0); + String filteredIds = buildFilteredDeviceIds(reqVO); + if (StringUtils.isBlank(filteredIds)) { + return Collections.emptyList(); + } + + List deviceIds = Arrays.stream(filteredIds.split(",")) + .filter(StringUtils::isNotBlank) + .map(Long::valueOf) + .distinct() + .collect(Collectors.toList()); + + + List> statsList = tdengineService.selectDeviceStatsTrendFromTD( + deviceIds, + startDateTime.format(formatter), + endDateTime.format(formatter) + ); + // day -> (deviceId -> record) + Map> dayDeviceRecordMap = convertTrendStatsToMap(statsList); + + // skipHoliday 时,区间一次查出所有节假日,避免按天查库 + Set holidaySet = Collections.emptySet(); + if (Boolean.TRUE.equals(reqVO.getSkipHoliday())) { + List holidays = deviceMapper.selectHolidayDaysInRange( + java.sql.Timestamp.valueOf(startDate.atStartOfDay()), + java.sql.Timestamp.valueOf(endDate.plusDays(1).atStartOfDay()) + ); + holidaySet = holidays == null ? Collections.emptySet() : holidays.stream() + .filter(Objects::nonNull) + .map(this::toLocalDateSafe) + .collect(Collectors.toSet()); + } + + int deviceCount = deviceIds.size(); List result = new ArrayList<>(); - for (LocalDate day = startDateTime.toLocalDate(); !day.isAfter(endDateTime.toLocalDate()); day = day.plusDays(1)) { - // 跳过节假日时,这一天不查询,也不返回 - if (Boolean.TRUE.equals(reqVO.getSkipHoliday()) && isHoliday(day)) { + + for (LocalDate day = startDate; !day.isAfter(endDate); day = day.plusDays(1)) { + if (Boolean.TRUE.equals(reqVO.getSkipHoliday()) && holidaySet.contains(day)) { continue; } - LocalDateTime dayStart = day.atStartOfDay(); - LocalDateTime dayEnd = day.atTime(LocalTime.MAX).withNano(0); - // 复用现有 deviceOperationPage,查出当天每台设备的开机率、稼动率基础数据 - List deviceDayList = queryDeviceDayList(reqVO, filteredIds, dayStart.format(formatter), dayEnd.format(formatter)); + + Map dayMap = + dayDeviceRecordMap.getOrDefault(day, Collections.emptyMap()); double powerOnRateSum = 0D; double utilizationRateSum = 0D; - int deviceCount = deviceDayList.size(); - for (DeviceTotalTimeRecordRespVO record : deviceDayList) { - powerOnRateSum += parsePercentValue(record.getPowerOnRate()); - utilizationRateSum += parsePercentValue(record.getUtilizationRate()); - } + for (Long deviceId : deviceIds) { + DeviceTotalTimeRecordRespVO record = dayMap.get(deviceId); + if (record == null) { + // 无数据按 0 + continue; + } + + // 直接按秒计算,不走字符串百分比解析 + double offlineSec = record.getTotalOfflineTime(); + double runningSec = record.getTotalRunningTime(); + double standbySec = record.getTotalStandbyTime(); + double faultSec = record.getTotalFaultTime(); + double onlineSec = runningSec + standbySec + faultSec; + double totalSec = offlineSec + onlineSec; + + double powerOnRate = totalSec > 0 ? (onlineSec / totalSec) : 0D; + double utilizationRate = onlineSec > 0 ? (runningSec / onlineSec) : 0D; + + powerOnRateSum += powerOnRate * 100D; + utilizationRateSum += utilizationRate * 100D; + } DeviceRateTrendPointRespVO point = new DeviceRateTrendPointRespVO(); point.setDay(day.toString()); @@ -1787,11 +1842,101 @@ public class DeviceServiceImpl implements DeviceService { point.setPowerOnRate(formatPercentValue(deviceCount > 0 ? powerOnRateSum / deviceCount : 0D)); point.setUtilizationRate(formatPercentValue(deviceCount > 0 ? utilizationRateSum / deviceCount : 0D)); result.add(point); + } + + return result; + } + + + private Map> convertTrendStatsToMap(List> statsList) { + Map> result = new LinkedHashMap<>(); + if (statsList == null || statsList.isEmpty()) { + return result; + } + + for (Map row : statsList) { + Object statDayObj = row.get("statDay"); + if (statDayObj == null) { + statDayObj = row.get("statday"); + } + if (statDayObj == null || row.get("deviceId") == null) { + continue; + } + + LocalDate statDay; + if (statDayObj instanceof Timestamp) { + statDay = ((Timestamp) statDayObj).toLocalDateTime().toLocalDate(); + } else if (statDayObj instanceof LocalDateTime) { + statDay = ((LocalDateTime) statDayObj).toLocalDate(); + } else { + statDay = LocalDateTime.parse(statDayObj.toString().replace(" ", "T")).toLocalDate(); + } + + Long deviceId = ((Number) row.get("deviceId")).longValue(); + + DeviceTotalTimeRecordRespVO vo = new DeviceTotalTimeRecordRespVO(); + vo.setId(deviceId); + vo.setTotalOfflineTime(getDoubleValue(row, "totalOfflineTime")); + vo.setTotalRunningTime(getDoubleValue(row, "totalRunningTime")); + vo.setTotalStandbyTime(getDoubleValue(row, "totalStandbyTime")); + vo.setTotalFaultTime(getDoubleValue(row, "totalFaultTime")); + + result.computeIfAbsent(statDay, key -> new HashMap<>()).put(deviceId, vo); + } + + return result; + } + + + /** + * 将按天按设备统计结果转换为 day -> device stats + */ + private Map> convertTrendStats(List> statsList) { + Map> result = new LinkedHashMap<>(); + if (statsList == null || statsList.isEmpty()) { + return result; + } + for (Map row : statsList) { + Object statDayObj = row.get("statDay"); + if (statDayObj == null) { + statDayObj = row.get("statday"); + } + if (statDayObj == null) { + continue; + } + + LocalDate statDay; + if (statDayObj instanceof Timestamp) { + statDay = ((Timestamp) statDayObj).toLocalDateTime().toLocalDate(); + } else if (statDayObj instanceof LocalDateTime) { + statDay = ((LocalDateTime) statDayObj).toLocalDate(); + } else { + statDay = LocalDateTime.parse(statDayObj.toString().replace(" ", "T")).toLocalDate(); + } + + DeviceTotalTimeRecordRespVO vo = new DeviceTotalTimeRecordRespVO(); + vo.setId(((Number) row.get("deviceId")).longValue()); + vo.setTotalOfflineTime(getDoubleValue(row, "totalOfflineTime")); + vo.setTotalRunningTime(getDoubleValue(row, "totalRunningTime")); + vo.setTotalStandbyTime(getDoubleValue(row, "totalStandbyTime")); + vo.setTotalFaultTime(getDoubleValue(row, "totalFaultTime")); + + result.computeIfAbsent(statDay, key -> new ArrayList<>()).add(vo); } + return result; } + + private DeviceTotalTimeRecordReqVO buildTrendReqVO(LocalDate day) { + DeviceTotalTimeRecordReqVO reqVO = new DeviceTotalTimeRecordReqVO(); + reqVO.setStartTime(day.atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + reqVO.setEndTime(day.atTime(LocalTime.MAX).withNano(0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + return reqVO; + } + + private double parsePercentValue(String percent) { if (StringUtils.isBlank(percent)) { return 0D; @@ -1810,37 +1955,57 @@ public class DeviceServiceImpl implements DeviceService { return String.format("%.2f%%", value); } + private LocalDate toLocalDateSafe(Date date) { + if (date instanceof java.sql.Date) { + return ((java.sql.Date) date).toLocalDate(); + } + if (date instanceof java.sql.Timestamp) { + return ((java.sql.Timestamp) date).toLocalDateTime().toLocalDate(); + } + return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + } - private List queryDeviceDayList(DeviceRateTrendReqVO reqVO, String ids, String startTime, String endTime) { - DeviceTotalTimeRecordReqVO pageReqVO = - new DeviceTotalTimeRecordReqVO(); - pageReqVO.setDeviceCode(reqVO.getDeviceCode()); - pageReqVO.setDeviceName(reqVO.getDeviceName()); - pageReqVO.setIds(ids); - pageReqVO.setStartTime(startTime); - pageReqVO.setEndTime(endTime); - return deviceOperationRecordService.deviceOperationPageList(pageReqVO); - } private String buildFilteredDeviceIds(DeviceRateTrendReqVO reqVO) { boolean onlyScheduled = reqVO.getOnlyScheduled() == null || reqVO.getOnlyScheduled(); + + // 不只看排产设备时: + // 1. 如果前端传了 ids,就按传入 ids 查询 + // 2. 如果前端没传 ids,就查询全部设备 id if (!onlyScheduled) { - return reqVO.getIds(); + if (StringUtils.isNotBlank(reqVO.getIds())) { + return reqVO.getIds(); + } + + List allDeviceIds = deviceMapper.getAllDeviceIds(); + if (CollectionUtils.isEmpty(allDeviceIds)) { + return "-1"; + } + return allDeviceIds.stream() + .map(String::valueOf) + .collect(Collectors.joining(",")); } + // 只统计排产设备 Collection requestIds = parseIds(reqVO.getIds()); List filteredDvIds = deviceMapper.selectScheduledDvIds(requestIds); + // 如果前端传了 ids,则在排产设备中再次过滤 if (StringUtils.isNotBlank(reqVO.getIds())) { Set requestIdSet = new HashSet<>(requestIds); - filteredDvIds = filteredDvIds.stream().filter(requestIdSet::contains).collect(Collectors.toList()); + filteredDvIds = filteredDvIds.stream() + .filter(requestIdSet::contains) + .collect(Collectors.toList()); } if (filteredDvIds.isEmpty()) { return "-1"; } - return filteredDvIds.stream().map(String::valueOf).collect(Collectors.joining(",")); + + return filteredDvIds.stream() + .map(String::valueOf) + .collect(Collectors.joining(",")); } private boolean isHoliday(LocalDate day) { @@ -1848,10 +2013,6 @@ public class DeviceServiceImpl implements DeviceService { return !CollectionUtils.isEmpty(holidays); } - private String toPercent(double value) { - return String.format("%.2f%%", value * 100); - } - private Collection parseIds(String ids) { if (StringUtils.isBlank(ids)) { return Collections.emptyList(); @@ -1865,5 +2026,71 @@ public class DeviceServiceImpl implements DeviceService { + /** + * 根据设备单条运行时长统计,计算开机率和稼动率 + * 计算逻辑与 calculateAndSetConvertedValues 保持一致: + * 开机率 = 在线时间 / 总时间 + * 稼动率 = 运行时间 / 在线时间 + */ + private void calculateRate(DeviceTotalTimeRecordRespVO record) { + if (record == null) { + return; + } + + double offlineSec = record.getTotalOfflineTime(); + double runningSec = record.getTotalRunningTime(); + double standbySec = record.getTotalStandbyTime(); + double faultSec = record.getTotalFaultTime(); + + // 在线时间 = 运行 + 待机 + 故障 + double onlineSec = runningSec + standbySec + faultSec; + double totalSec = offlineSec + onlineSec; + + // 防止异常值 + if (totalSec < 0) { + totalSec = 0; + } + + // 开机率 = 在线时间 / 总时间 + double powerOnRate = 0D; + if (totalSec > 0) { + powerOnRate = onlineSec / totalSec; + } + + // 稼动率 = 运行时间 / 在线时间 + double utilizationRate = 0D; + if (onlineSec > 0) { + utilizationRate = runningSec / onlineSec; + } + + record.setPowerOnRate(TimeConverterUtil.getPercentString(powerOnRate)); + record.setUtilizationRate(TimeConverterUtil.getPercentString(utilizationRate)); + } + + + private Double getDoubleValue(Map row, String key) { + if (row == null || key == null) { + return 0D; + } + + Object value = row.get(key); + if (value == null) { + value = row.get(key.toLowerCase()); + } + if (value == null) { + return 0D; + } + + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + + try { + return Double.parseDouble(value.toString()); + } catch (Exception e) { + return 0D; + } + } + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java index caa958bc9..5b20c424b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java @@ -2535,4 +2535,109 @@ public class TDengineService { } } + + // ========================= app报表相关接口 =================== + @DS("tdengine") + public List> selectDeviceStatsTrendFromTD(List deviceIds, String startTime, String endTime) { + StringBuilder sql = new StringBuilder(); + List params = new ArrayList<>(); + + sql.append("SELECT ") + .append("_wstart AS statDay, ") + .append("device_id AS deviceId, ") + .append("SUM(CASE WHEN rule = '0' THEN 1 ELSE 0 END) * 60 AS totalOfflineTime, ") + .append("SUM(CASE WHEN rule = '1' THEN 1 ELSE 0 END) * 60 AS totalRunningTime, ") + .append("SUM(CASE WHEN rule = '2' THEN 1 ELSE 0 END) * 60 AS totalStandbyTime, ") + .append("SUM(CASE WHEN rule = '3' THEN 1 ELSE 0 END) * 60 AS totalFaultTime ") + .append("FROM besure_server.iot_device_operation_record ") + .append("WHERE deleted = 0 "); + + if (startTime != null && !startTime.trim().isEmpty()) { + sql.append("AND create_time >= ? "); + params.add(startTime); + } + + if (endTime != null && !endTime.trim().isEmpty()) { + sql.append("AND create_time <= ? "); + params.add(endTime); + } + + // deviceIds 不为空时才加过滤 + if (deviceIds != null && !deviceIds.isEmpty()) { + sql.append("AND device_id IN ("); + for (int i = 0; i < deviceIds.size(); i++) { + if (i > 0) { + sql.append(", "); + } + sql.append("?"); + params.add(deviceIds.get(i)); + } + sql.append(") "); + } + + sql.append("PARTITION BY device_id ") + .append("INTERVAL(1d) ") + .append("ORDER BY statDay ASC"); + + try { + return jdbcTemplate.queryForList(sql.toString(), params.toArray()); + } catch (Exception e) { + log.error("TDengine 查询设备日趋势统计失败,sql={}, params={}", sql, params, e); + return Collections.emptyList(); + } + } + + @DS("tdengine") + public List> queryDeviceDayTrend(Long deviceId, String startTime, String endTime) { + StringBuilder sql = new StringBuilder(); + List params = new ArrayList<>(); + + sql.append("SELECT ") + .append("_wstart AS statDay, ") + .append("device_id AS deviceId, ") + .append("SUM(CASE WHEN rule = '0' THEN 1 ELSE 0 END) * 60 AS totalOfflineTime, ") + .append("SUM(CASE WHEN rule = '1' THEN 1 ELSE 0 END) * 60 AS totalRunningTime, ") + .append("SUM(CASE WHEN rule = '2' THEN 1 ELSE 0 END) * 60 AS totalStandbyTime, ") + .append("SUM(CASE WHEN rule = '3' THEN 1 ELSE 0 END) * 60 AS totalFaultTime ") + .append("FROM besure_server.iot_device_operation_record ") + .append("WHERE deleted = 0 ") + .append("AND device_id = ? "); + params.add(deviceId); + + if (startTime != null && !startTime.trim().isEmpty()) { + sql.append("AND create_time >= ? "); + params.add(startTime); + } + if (endTime != null && !endTime.trim().isEmpty()) { + sql.append("AND create_time <= ? "); + params.add(endTime); + } + + sql.append("PARTITION BY device_id ") + .append("INTERVAL(1d) ") + .append("ORDER BY statDay ASC"); + + try { + List> list = jdbcTemplate.queryForList(sql.toString(), params.toArray()); + for (Map row : list) { + Object statDay = row.get("statDay"); + if (statDay instanceof java.sql.Timestamp) { + row.put("day", ((java.sql.Timestamp) statDay).toLocalDateTime().toLocalDate().toString()); + } else if (statDay != null) { + String text = String.valueOf(statDay); + row.put("day", text.length() >= 10 ? text.substring(0, 10) : text); + } else { + row.put("day", null); + } + } + return list; + } catch (Exception e) { + log.error("TDengine 查询单设备日趋势失败,sql={}, params={}", sql, params, e); + return Collections.emptyList(); + } + } + + + + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/deviceoperationrecord/DeviceOperationRecordService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/deviceoperationrecord/DeviceOperationRecordService.java index 92ed6f461..154c9c91b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/deviceoperationrecord/DeviceOperationRecordService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/deviceoperationrecord/DeviceOperationRecordService.java @@ -56,7 +56,7 @@ public interface DeviceOperationRecordService { List deviceOperationPageList(@Valid DeviceTotalTimeRecordReqVO pageReqVO); - List getDeviceRateTrendByDeviceId(Long deviceId); + List getDeviceRateTrendByDeviceId(Long deviceId, String period); List deviceOperationList(@Valid DeviceTotalTimeRecordReqVO pageReqVO); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/deviceoperationrecord/DeviceOperationRecordServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/deviceoperationrecord/DeviceOperationRecordServiceImpl.java index cc6c475b9..25d5ea992 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/deviceoperationrecord/DeviceOperationRecordServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/deviceoperationrecord/DeviceOperationRecordServiceImpl.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.iot.service.deviceoperationrecord; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.module.iot.controller.admin.device.enums.DeviceRateTrendPeriodEnum; import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.utils.TimeConverterUtil; import cn.iocoder.yudao.module.iot.service.device.TDengineService; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -12,11 +14,9 @@ import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; import org.springframework.transaction.annotation.Transactional; -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; +import java.time.*; import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAdjusters; import java.util.*; import java.util.stream.Collectors; @@ -92,6 +92,8 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe @Override public PageResult deviceOperationPage(DeviceTotalTimeRecordReqVO pageReqVO) { + applyPeriodIfNecessary(pageReqVO); + // 1. 先从 MySQL 查询设备分页信息 Page page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()); IPage mysqlDevicePage = @@ -106,6 +108,9 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe .map(DeviceTotalTimeRecordRespVO::getId) .collect(Collectors.toList()); + log.info("deviceOperationPage mysql设备ID列表 pageReqVO.startTime={}, pageReqVO.endTime={}, deviceIds={}", + pageReqVO.getStartTime(), pageReqVO.getEndTime(), deviceIds); + // 3. 从 TDengine 批量查询统计数据 List> statsList = deviceOperationRecordMapper.selectDeviceStatsFromTD( @@ -114,6 +119,9 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe pageReqVO.getEndTime() ); + log.info("deviceOperationPage TD原始统计 startTime={}, endTime={}, statsList={}", + pageReqVO.getStartTime(), pageReqVO.getEndTime(), statsList); + // 4. 转换为 Map<设备ID, 统计数据> Map tdStatsMap = convertStatsListToMap(statsList); @@ -122,6 +130,10 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe List result = new ArrayList<>(); for (DeviceTotalTimeRecordRespVO device : mysqlDevicePage.getRecords()) { DeviceTotalTimeRecordRespVO stats = tdStatsMap.get(device.getId()); + + log.info("deviceOperationPage 合并前 deviceId={}, deviceCode={}, deviceName={}, stats={}", + device.getId(), device.getDeviceCode(), device.getDeviceName(), stats); + if (stats != null) { // 设置统计数据 device.setTotalOfflineTime(stats.getTotalOfflineTime()); @@ -137,6 +149,7 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe } result.add(device); } + log.info("deviceOperationPage mysql设备ID列表: {}", deviceIds); // 5. 计算和转换 calculateAndSetConvertedValues(result, pageReqVO); @@ -148,6 +161,8 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe @Override public List deviceOperationPageList(DeviceTotalTimeRecordReqVO pageReqVO) { + applyPeriodIfNecessary(pageReqVO); + List deviceList = deviceOperationRecordMapper.selectDeviceListFromMySQL(pageReqVO); @@ -191,33 +206,153 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe } @Override - public List getDeviceRateTrendByDeviceId(Long deviceId) { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - List result = new ArrayList<>(); + public List getDeviceRateTrendByDeviceId(Long deviceId, String period) { + DeviceRateTrendPeriodEnum.DateRange dateRange = resolvePeriodRange(period); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND); - for (int offset = 6; offset >= 0; offset--) { - LocalDate day = LocalDate.now().minusDays(offset); - LocalDateTime dayStart = day.atStartOfDay(); - LocalDateTime dayEnd = day.atTime(LocalTime.MAX).withNano(0); + String startTime = dateRange.getStart().atStartOfDay().format(formatter); + String endTime = dateRange.getEnd().atTime(LocalTime.MAX).withNano(0).format(formatter); - DeviceTotalTimeRecordReqVO reqVO = new DeviceTotalTimeRecordReqVO(); - reqVO.setIds(String.valueOf(deviceId)); - reqVO.setStartTime(dayStart.format(formatter)); - reqVO.setEndTime(dayEnd.format(formatter)); + log.info("getDeviceRateTrendByDeviceId 开始 deviceId={}, period={}, startTime={}, endTime={}", + deviceId, period, startTime, endTime); + + // queryDeviceDayTrend 改成“按 create_time 的日期分组”, + // 则这里每一天的结果就等价于 deviceOperationPage 单独查当天 + List> dayRows = tDengineService.queryDeviceDayTrend(deviceId, startTime, endTime); + + log.info("getDeviceRateTrendByDeviceId TD原始结果 deviceId={}, dayRows={}", deviceId, dayRows); + + Map> dayMap = new HashMap<>(); + if (CollectionUtils.isNotEmpty(dayRows)) { + for (Map row : dayRows) { + Object dayObj = row.get("day"); + if (dayObj == null) { + continue; + } + try { + dayMap.put(LocalDate.parse(String.valueOf(dayObj)), row); + } catch (Exception e) { + log.warn("解析设备日趋势日期失败,deviceId={}, day={}", deviceId, dayObj); + } + } + } - List dayList = deviceOperationPageList(reqVO); - DeviceTotalTimeRecordRespVO record = CollectionUtils.isNotEmpty(dayList) ? dayList.get(0) : null; + List result = new ArrayList<>(); + for (LocalDate day = dateRange.getStart(); !day.isAfter(dateRange.getEnd()); day = day.plusDays(1)) { + Map row = dayMap.get(day); DeviceOperationRateTrendRespVO trend = new DeviceOperationRateTrendRespVO(); trend.setDay(day.toString()); - trend.setPowerOnRate(record != null ? record.getPowerOnRate() : "0%"); - trend.setUtilizationRate(record != null ? record.getUtilizationRate() : "0%"); + + if (row == null) { + trend.setPowerOnRate("0%"); + trend.setUtilizationRate("0%"); + result.add(trend); + continue; + } + + try { + // 与 calculateAndSetConvertedValues 完全一致 + double offlineSec = toDouble(row, "totalOfflineTime"); + double runningSec = toDouble(row, "totalRunningTime"); + double standbySec = toDouble(row, "totalStandbyTime"); + double faultSec = toDouble(row, "totalFaultTime"); + + double onlineSec = runningSec + standbySec + faultSec; + double totalSec = offlineSec + onlineSec; + + if (totalSec < 0) { + totalSec = 0; + } + + double powerOnRate = 0D; + if (totalSec > 0D) { + powerOnRate = onlineSec / totalSec; + } + + double utilizationRate = 0D; + if (onlineSec > 0D) { + utilizationRate = runningSec / onlineSec; + } + + trend.setPowerOnRate(TimeConverterUtil.getPercentString(powerOnRate)); + trend.setUtilizationRate(TimeConverterUtil.getPercentString(utilizationRate)); + + log.info("getDeviceRateTrendByDeviceId 每日计算 deviceId={}, day={}, row={}, " + + "offlineSec={}, runningSec={}, standbySec={}, faultSec={}, onlineSec={}, totalSec={}, " + + "powerOnRateRaw={}, utilizationRateRaw={}, powerOnRateStr={}, utilizationRateStr={}", + deviceId, + day, + row, + offlineSec, + runningSec, + standbySec, + faultSec, + onlineSec, + totalSec, + powerOnRate, + utilizationRate, + TimeConverterUtil.getPercentString(powerOnRate), + TimeConverterUtil.getPercentString(utilizationRate) + ); + + + } catch (Exception e) { + log.error("计算设备日趋势失败,deviceId={}, day={}", deviceId, day, e); + trend.setPowerOnRate("0%"); + trend.setUtilizationRate("0%"); + } + result.add(trend); + + } return result; } + private static double toDouble(Map row, String key) { + if (row == null || row.get(key) == null) { + return 0D; + } + Object value = row.get(key); + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + try { + return Double.parseDouble(String.valueOf(value)); + } catch (Exception e) { + return 0D; + } + } + + private void applyPeriodIfNecessary(DeviceTotalTimeRecordReqVO reqVO) { + if (StringUtils.isNotBlank(reqVO.getStartTime()) && StringUtils.isNotBlank(reqVO.getEndTime())) { + return; + } + + String period = StringUtils.defaultIfBlank( + reqVO.getPeriod(), + DeviceRateTrendPeriodEnum.LAST_7_DAYS.getCode() + ); + + DeviceRateTrendPeriodEnum.DateRange dateRange = DeviceRateTrendPeriodEnum + .valueOfCode(period) + .resolve(LocalDate.now()); + + LocalDateTime startDateTime = dateRange.getStart().atStartOfDay(); + LocalDateTime endDateTime = dateRange.getEnd().atTime(LocalTime.MAX).withNano(0); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND); + reqVO.setStartTime(startDateTime.format(formatter)); + reqVO.setEndTime(endDateTime.format(formatter)); + } + + private DeviceRateTrendPeriodEnum.DateRange resolvePeriodRange(String period) { + String actualPeriod = StringUtils.defaultIfBlank(period, DeviceRateTrendPeriodEnum.LAST_7_DAYS.getCode()); + return DeviceRateTrendPeriodEnum.valueOfCode(actualPeriod).resolve(LocalDate.now()); + } + @Override public List deviceOperationList(DeviceTotalTimeRecordReqVO deviceTotalTimeRecordReqVO) { @@ -391,6 +526,25 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe record.setPowerOnRate(TimeConverterUtil.getPercentString(powerOnRate)); record.setUtilizationRate(TimeConverterUtil.getPercentString(utilizationRate)); + log.info("calculateAndSetConvertedValues deviceId={}, deviceCode={}, startTime={}, endTime={}, " + + "offlineSec={}, runningSec={}, standbySec={}, faultSec={}, onlineSec={}, totalSec={}, " + + "powerOnRateRaw={}, utilizationRateRaw={}, powerOnRateStr={}, utilizationRateStr={}", + record.getId(), + record.getDeviceCode(), + startTimeStr, + endTimeStr, + offlineSec, + runningSec, + standbySec, + faultSec, + onlineSec, + totalSec, + powerOnRate, + utilizationRate, + TimeConverterUtil.getPercentString(powerOnRate), + TimeConverterUtil.getPercentString(utilizationRate) + ); + } catch (Exception e) { log.error("计算设备{}时间统计出错: {}", record.getDeviceCode(), e.getMessage()); setDefaultValues(record); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/DeviceMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/DeviceMapper.xml index b1733a8b1..a99775ea3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/DeviceMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/DeviceMapper.xml @@ -299,5 +299,13 @@ ORDER BY d.id DESC + diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dashboard/DashboardController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dashboard/DashboardController.java index 42ec39534..981fb9350 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dashboard/DashboardController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dashboard/DashboardController.java @@ -139,39 +139,6 @@ public class DashboardController { item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX() .betweenIfPresent(TaskDO::getCreateTime, taskReqVO.getStartTime()))); // 创建时间 taskItems.add(item); -// // 未开工任务数 -// item = new TaskRespVO.Item(); -// item.setKey("2"); -// item.setLabel("未开工任务数"); -// Collection count1 = new ArrayList<>(); -// count1.add(1L); -// count1.add(2L); -// count1.add(3L); -// item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX() -// .in(TaskDO::getStatus, count1) -// .betweenIfPresent(TaskDO::getOrderDate, taskReqVO.getStartTime()))); // 下达时间 -// taskItems.add(item); -// // 生产中任务数 -// item = new TaskRespVO.Item(); -// item.setKey("3"); -// item.setLabel("生产中任务数"); -// Collection count2 = new ArrayList<>(); -// count2.add(4L); -// item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX() -// .in(TaskDO::getStatus, count2) -// .betweenIfPresent(TaskDO::getOrderDate, taskReqVO.getStartTime()))); -// taskItems.add(item); -// // 完工任务数 -// item = new TaskRespVO.Item(); -// item.setKey("4"); -// item.setLabel("完工任务数"); -// Collection count3 = new ArrayList<>(); -// count3.add(5L); -// count3.add(6L); -// item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX() -// .in(TaskDO::getStatus, count3) -// .betweenIfPresent(TaskDO::getOrderDate, taskReqVO.getStartTime()))); -// taskItems.add(item); // 生产计划总数 @@ -347,66 +314,108 @@ public class DashboardController { @GetMapping("/getTodoList") @Operation(summary = "获得待办任务") @Parameter(name = "id", description = "编号", required = true, example = "1024") -// @PreAuthorize("@ss.hasPermission('mes:bom:query')") +// @PreAuthorize("@ss.hasPermission('mes:bom:query')") public CommonResult> getTodoList() { + // 待办结果集 List todoRespVOList = new ArrayList<>(); - // 设备维修 + + // 1. 查询各类待办数据 List dvRepairDOList = dvRepairService.getDvRepairDOListByStatus(); + List ticketManagementDOList = ticketManagementService.getListByJobStatus(); + List moldRepairDOList = moldRepairService.getMoldRepairDOListByStatus(); + List moldTicketManagementDOList = moldTicketManagementService.getListByJobStatus(); + + // 2. 批量查询设备名称,避免循环中逐条查库 + Map deviceNameMap = new HashMap<>(); + if (dvRepairDOList != null && !dvRepairDOList.isEmpty()) { + List deviceIds = dvRepairDOList.stream() + .map(DvRepairDO::getDeviceId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + + if (!deviceIds.isEmpty()) { + List deviceLedgerList = deviceLedgerService.getDeviceLedgerListByIds(deviceIds); + deviceNameMap = deviceLedgerList.stream() + .collect(Collectors.toMap( + DeviceLedgerDO::getId, + DeviceLedgerDO::getDeviceName, + (a, b) -> a + )); + } + } + + // 3. 批量查询模具名称,避免循环中逐条查库 + Map moldNameMap = new HashMap<>(); + if (moldRepairDOList != null && !moldRepairDOList.isEmpty()) { + List moldIds = moldRepairDOList.stream() + .map(MoldRepairDO::getMoldId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + + if (!moldIds.isEmpty()) { + List moldList = moldService.getMoldListByIds(moldIds); + moldNameMap = moldList.stream() + .collect(Collectors.toMap( + MoldDO::getId, + MoldDO::getName, + (a, b) -> a + )); + } + } + + // 4. 组装设备维修待办 for (DvRepairDO dvRepairDO : dvRepairDOList) { - TodoRespVO todoRespVO = new TodoRespVO(); + TodoRespVO todoRespVO = new TodoRespVO(); todoRespVO.setCode(dvRepairDO.getRepairCode()); todoRespVO.setName(dvRepairDO.getRepairName()); todoRespVO.setType("设备维修"); - todoRespVO.setDeviceName(deviceLedgerService.getDeviceLedger(dvRepairDO.getDeviceId()).getDeviceName()); + todoRespVO.setDeviceName(deviceNameMap.getOrDefault(dvRepairDO.getDeviceId(), "未知设备")); todoRespVO.setCreateTime(dvRepairDO.getCreateTime()); todoRespVOList.add(todoRespVO); } - // 设备保养 点检 - List ticketManagementDOList = ticketManagementService.getListByJobStatus(); - for (TicketManagementDO ticketManagementDO : ticketManagementDOList) { - TodoRespVO todoRespVO = new TodoRespVO(); + // 5. 组装设备保养 / 点检待办 + for (TicketManagementDO ticketManagementDO : ticketManagementDOList) { + TodoRespVO todoRespVO = new TodoRespVO(); todoRespVO.setCode(ticketManagementDO.getPlanNo()); todoRespVO.setName(ticketManagementDO.getConfigName()); - if (ticketManagementDO.getPlanType() == 2) { - todoRespVO.setType("设备保养"); - } else { - todoRespVO.setType("设备点检"); - } + todoRespVO.setType(ticketManagementDO.getPlanType() == 2 ? "设备保养" : "设备点检"); todoRespVO.setDeviceName(ticketManagementDO.getDeviceName()); todoRespVO.setCreateTime(ticketManagementDO.getCreateTime()); todoRespVOList.add(todoRespVO); } - // 模具维修 - List moldRepairDOList = moldRepairService.getMoldRepairDOListByStatus(); - for (MoldRepairDO moldRepairDO : moldRepairDOList) { - TodoRespVO todoRespVO = new TodoRespVO(); + + // 6. 组装模具维修待办 + for (MoldRepairDO moldRepairDO : moldRepairDOList) { + TodoRespVO todoRespVO = new TodoRespVO(); todoRespVO.setCode(moldRepairDO.getRepairCode()); todoRespVO.setName(moldRepairDO.getRepairName()); todoRespVO.setType("模具维修"); - todoRespVO.setDeviceName( moldRepairDO.getMoldId() != null && moldService.getMold(moldRepairDO.getMoldId()) != null - ? moldService.getMold(moldRepairDO.getMoldId()).getName() - : "未知设备"); + todoRespVO.setDeviceName(moldNameMap.getOrDefault(moldRepairDO.getMoldId(), "未知设备")); todoRespVO.setCreateTime(moldRepairDO.getCreateTime()); todoRespVOList.add(todoRespVO); - } - // 模具保养 点检 - List moldTicketManagementDOList = moldTicketManagementService.getListByJobStatus(); - for (MoldTicketManagementDO moldTicketManagementDO : moldTicketManagementDOList) { - TodoRespVO todoRespVO = new TodoRespVO(); + + // 7. 组装模具保养 / 点检待办 + for (MoldTicketManagementDO moldTicketManagementDO : moldTicketManagementDOList) { + TodoRespVO todoRespVO = new TodoRespVO(); todoRespVO.setCode(moldTicketManagementDO.getPlanNo()); todoRespVO.setName(moldTicketManagementDO.getConfigName()); - if (moldTicketManagementDO.getPlanType() == 2) { - todoRespVO.setType("模具保养"); - } else { - todoRespVO.setType("模具点检"); - } + todoRespVO.setType(moldTicketManagementDO.getPlanType() == 2 ? "模具保养" : "模具点检"); todoRespVO.setDeviceName(moldTicketManagementDO.getMoldName()); todoRespVO.setCreateTime(moldTicketManagementDO.getCreateTime()); todoRespVOList.add(todoRespVO); } - return success(todoRespVOList); + + // 8. 按创建时间倒序排序,最近的待办排前面 + todoRespVOList.sort(Comparator.comparing( + TodoRespVO::getCreateTime, + Comparator.nullsLast(Comparator.reverseOrder()) + )); + + return success(todoRespVOList); } @GetMapping("/getDeviceRepairLineOptions") diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerService.java index 4adb90ceb..450c1e185 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerService.java @@ -83,5 +83,7 @@ public interface DeviceLedgerService { Map getDeviceMap(Set longs); + List getDeviceLedgerListByIds(Collection ids); + } \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerServiceImpl.java index 9fa05db06..55029500b 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerServiceImpl.java @@ -431,4 +431,11 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService { return deviceLedgerMapper.selectListByIds(ids).stream() .collect(Collectors.toMap(DeviceLedgerDO::getId, Function.identity(), (a, b) -> a)); } + + @Override + public List getDeviceLedgerListByIds(Collection ids) { + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + return deviceLedgerMapper.selectBatchIds(ids); } } \ No newline at end of file From ec455718f109254620cf57b33e947811a74c7cb8 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Fri, 24 Apr 2026 09:56:08 +0800 Subject: [PATCH 2/8] =?UTF-8?q?fix:app=E6=89=AB=E7=A0=81=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=E6=B7=BB=E5=8A=A0=E7=BC=96?= =?UTF-8?q?=E7=A0=81=E8=BF=87=E6=BB=A4=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/mold/MoldBrandController.java | 8 ++--- .../admin/product/ErpProductController.java | 6 ++-- .../erp/service/mold/MoldBrandService.java | 4 ++- .../service/mold/MoldBrandServiceImpl.java | 21 +++++++++++- .../service/product/ErpProductService.java | 4 ++- .../product/ErpProductServiceImpl.java | 19 +++++++++++ .../CriticalComponentController.java | 8 ++--- .../deviceledger/DeviceLedgerController.java | 8 ++--- .../admin/dvrepair/DvRepairController.java | 11 ++++--- .../moldrepair/MoldRepairController.java | 11 ++++--- .../MoldTicketManagementController.java | 20 ++++++------ .../TicketManagementController.java | 20 ++++++------ .../CriticalComponentService.java | 4 ++- .../CriticalComponentServiceImpl.java | 22 ++++++++++++- .../deviceledger/DeviceLedgerService.java | 4 ++- .../deviceledger/DeviceLedgerServiceImpl.java | 22 ++++++++++++- .../mes/service/dvrepair/DvRepairService.java | 4 +-- .../service/dvrepair/DvRepairServiceImpl.java | 28 ++++++++++++++-- .../service/moldrepair/MoldRepairService.java | 2 +- .../moldrepair/MoldRepairServiceImpl.java | 29 +++++++++++++++-- .../MoldTicketManagementService.java | 6 ++-- .../MoldTicketManagementServiceImpl.java | 32 +++++++++++++++---- .../TicketManagementService.java | 6 ++-- .../TicketManagementServiceImpl.java | 31 ++++++++++++++---- 24 files changed, 251 insertions(+), 79 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/mold/MoldBrandController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/mold/MoldBrandController.java index 1790c069f..6d8b29ebe 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/mold/MoldBrandController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/mold/MoldBrandController.java @@ -167,10 +167,10 @@ public class MoldBrandController { @GetMapping("/mold/get") @Operation(summary = "获得模具") - @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('erp:mold-brand:query')") - public CommonResult getMold(@RequestParam("id") Long id) { - return success(moldBrandService.getMold(id)); + public CommonResult getMold(@RequestParam(value = "id", required = false) Long id, + @RequestParam(value = "code", required = false) String code) { + return success(moldBrandService.getMold(id, code)); } @GetMapping("/mold/export-excel") @@ -241,4 +241,4 @@ public class MoldBrandController { return success(moldBrandService.getMoldBrandProduct(id)); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java index e264000d8..397e17f05 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java @@ -104,10 +104,10 @@ public class ErpProductController { @GetMapping("/get") @Operation(summary = "获得产品") - @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('erp:product:query')") - public CommonResult getProduct(@RequestParam("id") Long id) { - return success(productService.getProduct(id)); + public CommonResult getProduct(@RequestParam(value = "id", required = false) Long id, + @RequestParam(value = "code", required = false) String code) { + return success(productService.getProduct(id, code)); } @GetMapping("/page") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldBrandService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldBrandService.java index 66b34e8b2..75943714e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldBrandService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldBrandService.java @@ -120,6 +120,8 @@ public interface MoldBrandService { * @return 模具 */ MoldDO getMold(Long id); + + MoldDO getMold(Long id, String code); List selectBy(MoldDO reqVO); // ==================== 子表(模具产品) ==================== @@ -187,4 +189,4 @@ public interface MoldBrandService { List getMoldBrandTree(); void regenerateCode(Long id, String code) throws UnsupportedEncodingException; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldBrandServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldBrandServiceImpl.java index fa24e61f6..ea0ae94fe 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldBrandServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/mold/MoldBrandServiceImpl.java @@ -256,6 +256,7 @@ public class MoldBrandServiceImpl implements MoldBrandService { @Override public MoldDO getMold(Long id) { + validateMoldExists(id); MoldDO moldDO = moldMapper.selectById(id); Map> moldRepairDOMap=new HashMap<>(); @@ -308,6 +309,24 @@ public class MoldBrandServiceImpl implements MoldBrandService { moldDO.setQrcodeUrl(qrcodeUrl); return moldDO; } + + @Override + public MoldDO getMold(Long id, String code) { + if (id != null) { + return getMold(id); + } + if (StrUtil.isNotBlank(code)) { + MoldDO moldDO = moldMapper.selectOne(new LambdaQueryWrapperX() + .like(MoldDO::getCode, code) + .orderByDesc(MoldDO::getId) + .last("LIMIT 1")); + if (moldDO == null) { + throw exception(MOLD_NOT_EXISTS); + } + return getMold(moldDO.getId()); + } + throw exception(MOLD_NOT_EXISTS); + } @Override public List selectBy(MoldDO reqVO){ return moldMapper.selectBy(reqVO); @@ -445,4 +464,4 @@ public class MoldBrandServiceImpl implements MoldBrandService { return respVO; } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java index f690778b8..b1c4e10b9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java @@ -64,6 +64,8 @@ public interface ErpProductService { */ ErpProductRespVO getProduct(Long id); + ErpProductRespVO getProduct(Long id, String code); + /** * 获得指定状态的产品 VO 列表 * @@ -138,4 +140,4 @@ public interface ErpProductService { ErpProductImportRespVO importProductList(List importProducts, boolean isUpdateSupport); void regenerateCode(Long id, String code) throws UnsupportedEncodingException; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index 9ed46431f..8b9e482c4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO; import cn.iocoder.yudao.module.common.enums.CodeTypeEnum; @@ -325,6 +326,24 @@ public class ErpProductServiceImpl implements ErpProductService { return respVO; } + @Override + public ErpProductRespVO getProduct(Long id, String code) { + if (id != null) { + return getProduct(id); + } + if (StringUtils.isNotBlank(code)) { + ErpProductDO product = productMapper.selectOne(new LambdaQueryWrapperX() + .like(ErpProductDO::getBarCode, code) + .orderByDesc(ErpProductDO::getId) + .last("LIMIT 1")); + if (product == null) { + throw exception(PRODUCT_NOT_EXISTS); + } + return getProduct(product.getId()); + } + throw exception(PRODUCT_NOT_EXISTS); + } + diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/criticalcomponent/CriticalComponentController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/criticalcomponent/CriticalComponentController.java index 6b0fcacca..4a152a3c4 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/criticalcomponent/CriticalComponentController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/criticalcomponent/CriticalComponentController.java @@ -77,10 +77,10 @@ public class CriticalComponentController { @GetMapping("/get") @Operation(summary = "获得设备关键件") - @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('mes:critical-component:query')") - public CommonResult getCriticalComponent(@RequestParam("id") Long id) { - CriticalComponentDO criticalComponent = criticalComponentService.getCriticalComponent(id); + public CommonResult getCriticalComponent(@RequestParam(value = "id", required = false) Long id, + @RequestParam(value = "code", required = false) String code) { + CriticalComponentDO criticalComponent = criticalComponentService.getCriticalComponent(id, code); return success(BeanUtils.toBean(criticalComponent, CriticalComponentRespVO.class)); } @@ -179,4 +179,4 @@ public class CriticalComponentController { return success(true); } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/deviceledger/DeviceLedgerController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/deviceledger/DeviceLedgerController.java index 9700c5500..49b7fd458 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/deviceledger/DeviceLedgerController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/deviceledger/DeviceLedgerController.java @@ -100,10 +100,10 @@ public class DeviceLedgerController { @GetMapping("/get") @Operation(summary = "获得设备台账") - @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('mes:device-ledger:query')") - public CommonResult getDeviceLedger(@RequestParam("id") Long id) { - DeviceLedgerDO deviceLedger = deviceLedgerService.getDeviceLedger(id); + public CommonResult getDeviceLedger(@RequestParam(value = "id", required = false) Long id, + @RequestParam(value = "code", required = false) String code) { + DeviceLedgerDO deviceLedger = deviceLedgerService.getDeviceLedger(id, code); DeviceLedgerRespVO respVO = BeanUtils.toBean(deviceLedger, DeviceLedgerRespVO.class); String qrcodeUrl = qrcodeService.selectQrcodeUrlByIdAndCode(QrcodeBizTypeEnum.EQUIPMENT.getCode(),id,respVO.getDeviceCode()); @@ -279,4 +279,4 @@ public class DeviceLedgerController { -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dvrepair/DvRepairController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dvrepair/DvRepairController.java index dc18c11d7..32a371ad0 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dvrepair/DvRepairController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dvrepair/DvRepairController.java @@ -174,12 +174,13 @@ public class DvRepairController { @GetMapping("/getRepairListByDeviceId") @Operation(summary = "根据设备Id获得维修历史记录") - @Parameter(name = "deviceId", description = "设备Id", required = true, example = "1024") + @Parameter(name = "deviceId", description = "设备Id", required = false, example = "1024") @PreAuthorize("@ss.hasPermission('mes:ticket-management:query')") - public CommonResult> getRepairListByDeviceId(@RequestParam("deviceId") Long deviceId, + public CommonResult> getRepairListByDeviceId(@RequestParam(value = "deviceId", required = false) Long deviceId, + @RequestParam(value = "code", required = false) String code, @RequestParam(name = "startTime",required = false) String startTime, @RequestParam(name = "endTime",required = false) String endTime) { - List dvRepairDOList = dvRepairService.getRepairListByDeviceId(deviceId,startTime,endTime,null); + List dvRepairDOList = dvRepairService.getRepairListByDeviceId(deviceId, code, startTime, endTime, null); return success(dvRepairDOList); } @@ -196,7 +197,7 @@ public class DvRepairController { HttpServletResponse response) throws IOException { // 查询数据 - List dvRepairDOList = dvRepairService.getRepairListByDeviceId(deviceId,startTime,endTime,ids); + List dvRepairDOList = dvRepairService.getRepairListByDeviceId(deviceId, null, startTime, endTime, ids); // 设置响应头 response.setContentType("application/vnd.ms-excel;charset=UTF-8"); @@ -227,4 +228,4 @@ public class DvRepairController { return dvSubjectRespVOPageResult; } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/moldrepair/MoldRepairController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/moldrepair/MoldRepairController.java index ebcf9b59c..84c7d1927 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/moldrepair/MoldRepairController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/moldrepair/MoldRepairController.java @@ -167,12 +167,13 @@ public class MoldRepairController { @GetMapping("/getRepairListByMoldId") @Operation(summary = "根据模具Id获得维修历史记录") - @Parameter(name = "moldId", description = "模具Id", required = true, example = "1024") + @Parameter(name = "moldId", description = "模具Id", required = false, example = "1024") @PreAuthorize("@ss.hasPermission('mes:mold_ticket-management:query')") - public CommonResult> getRepairListByMoldId(@RequestParam("moldId") Long moldId, + public CommonResult> getRepairListByMoldId(@RequestParam(value = "moldId", required = false) Long moldId, + @RequestParam(value = "code", required = false) String code, @RequestParam(name = "startTime",required = false) String startTime, @RequestParam(name = "endTime",required = false) String endTime) { - List moldRepairDOList = moldRepairService.getRepairListByMoldId(moldId,startTime,endTime,null); + List moldRepairDOList = moldRepairService.getRepairListByMoldId(moldId, code, startTime, endTime, null); return success(moldRepairDOList); } @@ -189,7 +190,7 @@ public class MoldRepairController { HttpServletResponse response) throws IOException { // 查询数据 - List moldRepairDOList = moldRepairService.getRepairListByMoldId(moldId,startTime,endTime,ids); + List moldRepairDOList = moldRepairService.getRepairListByMoldId(moldId, null, startTime, endTime, ids); // 设置响应头 response.setContentType("application/vnd.ms-excel;charset=UTF-8"); @@ -221,4 +222,4 @@ public class MoldRepairController { return moldSubjectRespVOPageResult; } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/moldticketmanagement/MoldTicketManagementController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/moldticketmanagement/MoldTicketManagementController.java index 55ac6dca0..edf547738 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/moldticketmanagement/MoldTicketManagementController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/moldticketmanagement/MoldTicketManagementController.java @@ -140,12 +140,13 @@ public class MoldTicketManagementController { @GetMapping("/getInspectionByMoldId") @Operation(summary = "根据模具Id获得点检历史记录") - @Parameter(name = "moldId", description = "模具Id", required = true, example = "1024") + @Parameter(name = "moldId", description = "模具Id", required = false, example = "1024") @PreAuthorize("@ss.hasPermission('mes:mold-ticket-management:query')") - public CommonResult< List> getInspectionByMoldId(@RequestParam("moldId") Long moldId, + public CommonResult< List> getInspectionByMoldId(@RequestParam(value = "moldId", required = false) Long moldId, + @RequestParam(value = "code", required = false) String code, @RequestParam(name = "startTime",required = false) String startTime, @RequestParam(name = "endTime",required = false) String endTime) { - List moldTicketResultsDOList = moldticketManagementService.getInspectionByMoldId(moldId,startTime,endTime,""); + List moldTicketResultsDOList = moldticketManagementService.getInspectionByMoldId(moldId, code, startTime, endTime, ""); return success(moldTicketResultsDOList); } @@ -160,7 +161,7 @@ public class MoldTicketManagementController { HttpServletResponse response) throws IOException { // 查询数据 - List results = moldticketManagementService.getInspectionByMoldId(moldId, startTime, endTime, ids); + List results = moldticketManagementService.getInspectionByMoldId(moldId, null, startTime, endTime, ids); // 转换为VO并处理数据 List exportVos = results.stream() @@ -179,12 +180,13 @@ public class MoldTicketManagementController { @GetMapping("/getMaintenanceByMoldId") @Operation(summary = "根据模具Id获得保养历史记录") - @Parameter(name = "moldId", description = "模具Id", required = true, example = "1024") + @Parameter(name = "moldId", description = "模具Id", required = false, example = "1024") @PreAuthorize("@ss.hasPermission('mes:mold_ticket-management:query')") - public CommonResult> getMaintenanceByMoldId(@RequestParam("moldId") Long moldId, + public CommonResult> getMaintenanceByMoldId(@RequestParam(value = "moldId", required = false) Long moldId, + @RequestParam(value = "code", required = false) String code, @RequestParam(name = "startTime",required = false) String startTime, @RequestParam(name = "endTime",required = false) String endTime) { - List moldticketResultsDOList = moldticketManagementService.getMaintenanceByMoldId(moldId,startTime,endTime,""); + List moldticketResultsDOList = moldticketManagementService.getMaintenanceByMoldId(moldId, code, startTime, endTime, ""); return success(moldticketResultsDOList); } @@ -200,7 +202,7 @@ public class MoldTicketManagementController { HttpServletResponse response) throws IOException { // 查询数据 - List results = moldticketManagementService.getMaintenanceByMoldId(moldId, startTime, endTime, ids); + List results = moldticketManagementService.getMaintenanceByMoldId(moldId, null, startTime, endTime, ids); // 转换为VO并处理数据 List exportVos = results.stream() @@ -276,4 +278,4 @@ public class MoldTicketManagementController { return vo; } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/TicketManagementController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/TicketManagementController.java index 04b10190d..fe8b20d52 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/TicketManagementController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/TicketManagementController.java @@ -160,12 +160,13 @@ public class TicketManagementController { @GetMapping("/getInspectionByDeviceId") @Operation(summary = "根据设备Id获得点检历史记录") - @Parameter(name = "deviceId", description = "设备Id", required = true, example = "1024") + @Parameter(name = "deviceId", description = "设备Id", required = false, example = "1024") @PreAuthorize("@ss.hasPermission('mes:ticket-management:query')") - public CommonResult< List> getInspectionByDeviceId(@RequestParam("deviceId") Long deviceId, + public CommonResult< List> getInspectionByDeviceId(@RequestParam(value = "deviceId", required = false) Long deviceId, + @RequestParam(value = "code", required = false) String code, @RequestParam(name = "startTime",required = false) String startTime, @RequestParam(name = "endTime",required = false) String endTime) { - List ticketResultsDOList = ticketManagementService.getInspectionByDeviceId(deviceId,startTime,endTime,""); + List ticketResultsDOList = ticketManagementService.getInspectionByDeviceId(deviceId, code, startTime, endTime, ""); return success(ticketResultsDOList); } @@ -180,7 +181,7 @@ public class TicketManagementController { HttpServletResponse response) throws IOException { // 查询数据 - List results = ticketManagementService.getInspectionByDeviceId(deviceId, startTime, endTime, ids); + List results = ticketManagementService.getInspectionByDeviceId(deviceId, null, startTime, endTime, ids); // 转换为VO并处理数据 List exportVos = results.stream() @@ -202,12 +203,13 @@ public class TicketManagementController { @GetMapping("/getMaintenanceByDeviceId") @Operation(summary = "根据设备Id获得保养历史记录") - @Parameter(name = "deviceId", description = "设备Id", required = true, example = "1024") + @Parameter(name = "deviceId", description = "设备Id", required = false, example = "1024") @PreAuthorize("@ss.hasPermission('mes:ticket-management:query')") - public CommonResult> getMaintenanceByDeviceId(@RequestParam("deviceId") Long deviceId, + public CommonResult> getMaintenanceByDeviceId(@RequestParam(value = "deviceId", required = false) Long deviceId, + @RequestParam(value = "code", required = false) String code, @RequestParam(name = "startTime",required = false) String startTime, @RequestParam(name = "endTime",required = false) String endTime) { - List ticketResultsDOList = ticketManagementService.getMaintenanceByDeviceId(deviceId,startTime,endTime,""); + List ticketResultsDOList = ticketManagementService.getMaintenanceByDeviceId(deviceId, code, startTime, endTime, ""); return success(ticketResultsDOList); } @@ -223,7 +225,7 @@ public class TicketManagementController { HttpServletResponse response) throws IOException { // 查询数据 - List results = ticketManagementService.getMaintenanceByDeviceId(deviceId, startTime, endTime, ids); + List results = ticketManagementService.getMaintenanceByDeviceId(deviceId, null, startTime, endTime, ids); // 转换为VO并处理数据 List exportVos = results.stream() @@ -299,4 +301,4 @@ public class TicketManagementController { return vo; } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/criticalcomponent/CriticalComponentService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/criticalcomponent/CriticalComponentService.java index 36b473997..1e9080ac3 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/criticalcomponent/CriticalComponentService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/criticalcomponent/CriticalComponentService.java @@ -45,6 +45,8 @@ public interface CriticalComponentService { */ CriticalComponentDO getCriticalComponent(Long id); + CriticalComponentDO getCriticalComponent(Long id, String code); + /** * 获得设备关键件分页 * @@ -63,4 +65,4 @@ public interface CriticalComponentService { CriticalComponentImportRespVO importCriticalComponentList(List importComponents, boolean isUpdateSupport); void regenerateCode(Long id, String code) throws UnsupportedEncodingException; -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/criticalcomponent/CriticalComponentServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/criticalcomponent/CriticalComponentServiceImpl.java index 385968f9c..cde4bed5f 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/criticalcomponent/CriticalComponentServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/criticalcomponent/CriticalComponentServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.mes.service.criticalcomponent; import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.common.enums.CodeTypeEnum; import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum; import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService; @@ -197,6 +198,7 @@ public class CriticalComponentServiceImpl implements CriticalComponentService { @Override public CriticalComponentDO getCriticalComponent(Long id) { + validateCriticalComponentExists(id); CriticalComponentDO criticalComponentDO = criticalComponentMapper.selectById(id); String qrcodeUrl = qrcodeService.selectQrcodeUrlByIdAndCode(QrcodeBizTypeEnum.KEY_PART.getCode(),id,criticalComponentDO.getCode()); criticalComponentDO.setQrcodeUrl(qrcodeUrl); @@ -204,6 +206,24 @@ public class CriticalComponentServiceImpl implements CriticalComponentService { } + @Override + public CriticalComponentDO getCriticalComponent(Long id, String code) { + if (id != null) { + return getCriticalComponent(id); + } + if (StringUtils.isNotBlank(code)) { + CriticalComponentDO criticalComponentDO = criticalComponentMapper.selectOne(new LambdaQueryWrapperX() + .like(CriticalComponentDO::getCode, code) + .orderByDesc(CriticalComponentDO::getId) + .last("LIMIT 1")); + if (criticalComponentDO == null) { + throw exception(CRITICAL_COMPONENT_NOT_EXISTS); + } + return getCriticalComponent(criticalComponentDO.getId()); + } + throw exception(CRITICAL_COMPONENT_NOT_EXISTS); + } + @Override public PageResult getCriticalComponentPage(CriticalComponentPageReqVO pageReqVO) { return criticalComponentMapper.selectPage(pageReqVO); @@ -338,4 +358,4 @@ public class CriticalComponentServiceImpl implements CriticalComponentService { ); } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerService.java index 450c1e185..c12da64c5 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerService.java @@ -47,6 +47,8 @@ public interface DeviceLedgerService { */ DeviceLedgerDO getDeviceLedger(Long id); + DeviceLedgerDO getDeviceLedger(Long id, String code); + /** * 获得设备类型分页 * @@ -86,4 +88,4 @@ public interface DeviceLedgerService { List getDeviceLedgerListByIds(Collection ids); -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerServiceImpl.java index 55029500b..15e5a2e32 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/deviceledger/DeviceLedgerServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mes.service.deviceledger; import cn.hutool.core.collection.CollStreamUtil; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.common.enums.CodeTypeEnum; import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum; import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService; @@ -207,6 +208,7 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService { @Override public DeviceLedgerDO getDeviceLedger(Long id) { + validateDeviceLedgerExists(id); DeviceLedgerDO deviceLedgerDO = deviceLedgerMapper.selectById(id); @@ -298,6 +300,24 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService { return deviceLedgerDO; } + @Override + public DeviceLedgerDO getDeviceLedger(Long id, String code) { + if (id != null) { + return getDeviceLedger(id); + } + if (StringUtils.isNotBlank(code)) { + DeviceLedgerDO deviceLedgerDO = deviceLedgerMapper.selectOne(new LambdaQueryWrapperX() + .like(DeviceLedgerDO::getDeviceCode, code) + .orderByDesc(DeviceLedgerDO::getId) + .last("LIMIT 1")); + if (deviceLedgerDO == null) { + throw exception(DEVICE_LEDGER_NOT_EXISTS); + } + return getDeviceLedger(deviceLedgerDO.getId()); + } + throw exception(DEVICE_LEDGER_NOT_EXISTS); + } + @Override public PageResult getDeviceLedgerPage(DeviceLedgerPageReqVO pageReqVO) { @@ -438,4 +458,4 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService { return Collections.emptyList(); } return deviceLedgerMapper.selectBatchIds(ids); } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/dvrepair/DvRepairService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/dvrepair/DvRepairService.java index 2b09e42b4..600f83a7c 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/dvrepair/DvRepairService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/dvrepair/DvRepairService.java @@ -71,7 +71,7 @@ public interface DvRepairService { void updateDvRepairStatus(@Valid DvRepirUpdateReqVO updateReqVO); - List getRepairListByDeviceId(Long deviceId, String startTime, String endTime,String ids); + List getRepairListByDeviceId(Long deviceId, String code, String startTime, String endTime, String ids); Long getRepairListCountByRepairStatus(); @@ -82,4 +82,4 @@ public interface DvRepairService { List getList(); List getLatestList(); -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/dvrepair/DvRepairServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/dvrepair/DvRepairServiceImpl.java index 0bcdb9512..a3d7a4945 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/dvrepair/DvRepairServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/dvrepair/DvRepairServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.mes.service.dvrepair; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; import cn.iocoder.yudao.module.mes.controller.admin.dashboard.vo.dashboard.EventStatisticsVO; @@ -8,8 +9,10 @@ import cn.iocoder.yudao.module.mes.controller.admin.dvrepair.enums.RepairResultE import cn.iocoder.yudao.module.mes.controller.admin.dvrepair.enums.RepairStatusEnum; import cn.iocoder.yudao.module.mes.controller.admin.dvrepair.vo.*; import cn.iocoder.yudao.module.mes.controller.admin.ticketresults.enums.JobResultEnum; +import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO; import cn.iocoder.yudao.module.mes.dal.dataobject.dvrepair.DvRepairDO; import cn.iocoder.yudao.module.mes.dal.dataobject.dvrepair.DvRepairLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper; import cn.iocoder.yudao.module.mes.dal.mysql.dvrepair.DvRepairLineMapper; import cn.iocoder.yudao.module.mes.dal.mysql.dvrepair.DvRepairMapper; import com.alibaba.excel.util.StringUtils; @@ -44,6 +47,8 @@ public class DvRepairServiceImpl implements DvRepairService { @Resource private DvRepairMapper dvRepairMapper; @Resource + private DeviceLedgerMapper deviceLedgerMapper; + @Resource private DvRepairLineMapper dvRepairLineMapper; @Resource @@ -196,12 +201,13 @@ public class DvRepairServiceImpl implements DvRepairService { } @Override - public List getRepairListByDeviceId(Long deviceId, String startTime, String endTime,String ids) { + public List getRepairListByDeviceId(Long deviceId, String code, String startTime, String endTime, String ids) { + DeviceLedgerDO deviceLedgerDO = getDeviceByIdOrCode(deviceId, code); List dvRepairLineRespVOS = new ArrayList<>(); LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() - .eq(DvRepairDO::getDeviceId, deviceId); + .eq(DvRepairDO::getDeviceId, deviceLedgerDO.getId()); @@ -270,6 +276,22 @@ public class DvRepairServiceImpl implements DvRepairService { return dvRepairLineRespVOS; } + private DeviceLedgerDO getDeviceByIdOrCode(Long deviceId, String code) { + DeviceLedgerDO deviceLedgerDO = null; + if (deviceId != null) { + deviceLedgerDO = deviceLedgerMapper.selectById(deviceId); + } else if (StringUtils.isNotBlank(code)) { + deviceLedgerDO = deviceLedgerMapper.selectOne(new LambdaQueryWrapperX() + .like(DeviceLedgerDO::getDeviceCode, code) + .orderByDesc(DeviceLedgerDO::getId) + .last("LIMIT 1")); + } + if (deviceLedgerDO == null) { + throw exception(TICKET_MANAGEMENT_NOT_EXISTS); + } + return deviceLedgerDO; + } + @Override public Long getRepairListCountByRepairStatus() { return dvRepairMapper.selectCount(Wrappers.lambdaQuery() @@ -419,4 +441,4 @@ public class DvRepairServiceImpl implements DvRepairService { dvRepairLineMapper.deleteByRepairId(repairId); } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldrepair/MoldRepairService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldrepair/MoldRepairService.java index 5258bae31..3fcaf2b2d 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldrepair/MoldRepairService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldrepair/MoldRepairService.java @@ -74,7 +74,7 @@ public interface MoldRepairService { void updateMoldRepairStatus(@Valid MoldRepairUpdateReqVO updateReqVO); - List getRepairListByMoldId(Long moldId, String startTime, String endTime, String ids); + List getRepairListByMoldId(Long moldId, String code, String startTime, String endTime, String ids); Long getRepairListCountByRepairStatus(); diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldrepair/MoldRepairServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldrepair/MoldRepairServiceImpl.java index 6f9cec155..64519e627 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldrepair/MoldRepairServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldrepair/MoldRepairServiceImpl.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.mes.service.moldrepair; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO; import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; import cn.iocoder.yudao.module.mes.controller.admin.dashboard.vo.dashboard.EventStatisticsVO; import cn.iocoder.yudao.module.common.controller.admin.moldrepair.enums.RepairResultEnum; @@ -15,6 +17,7 @@ import cn.iocoder.yudao.module.common.dal.dataobject.moldrepair.MoldRepairDO; import cn.iocoder.yudao.module.common.dal.dataobject.moldrepair.MoldRepairLineDO; import cn.iocoder.yudao.module.common.dal.mysql.moldrepair.MoldRepairLineMapper; import cn.iocoder.yudao.module.common.dal.mysql.moldrepair.MoldRepairMapper; +import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldMapper; import com.alibaba.excel.util.StringUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -32,6 +35,7 @@ import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.MOLD_NOT_EXISTS; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; import org.springframework.util.CollectionUtils; @@ -51,6 +55,8 @@ public class MoldRepairServiceImpl implements MoldRepairService { @Resource private MoldRepairMapper moldRepairMapper; @Resource + private MoldMapper moldMapper; + @Resource private MoldRepairLineMapper moldRepairLineMapper; @Resource @@ -250,12 +256,13 @@ public class MoldRepairServiceImpl implements MoldRepairService { } @Override - public List getRepairListByMoldId(Long moldId, String startTime, String endTime, String ids) { + public List getRepairListByMoldId(Long moldId, String code, String startTime, String endTime, String ids) { + MoldDO moldDO = getMoldByIdOrCode(moldId, code); List moldRepairLineRespVOS = new ArrayList<>(); LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() - .eq(MoldRepairDO::getMoldId, moldId); + .eq(MoldRepairDO::getMoldId, moldDO.getId()); @@ -324,6 +331,22 @@ public class MoldRepairServiceImpl implements MoldRepairService { return moldRepairLineRespVOS; } + private MoldDO getMoldByIdOrCode(Long moldId, String code) { + MoldDO moldDO = null; + if (moldId != null) { + moldDO = moldMapper.selectById(moldId); + } else if (StringUtils.isNotBlank(code)) { + moldDO = moldMapper.selectOne(new LambdaQueryWrapperX() + .like(MoldDO::getCode, code) + .orderByDesc(MoldDO::getId) + .last("LIMIT 1")); + } + if (moldDO == null) { + throw exception(MOLD_NOT_EXISTS); + } + return moldDO; + } + private LocalDateTime parseToLocalDateTime(String timeStr) { if (StringUtils.isBlank(timeStr)) { @@ -455,4 +478,4 @@ public class MoldRepairServiceImpl implements MoldRepairService { .last("LIMIT 100") ); } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldticketmanagement/MoldTicketManagementService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldticketmanagement/MoldTicketManagementService.java index 3bafecfd0..497a60654 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldticketmanagement/MoldTicketManagementService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldticketmanagement/MoldTicketManagementService.java @@ -58,9 +58,9 @@ public interface MoldTicketManagementService { void batchUpdateJobStatus(@Valid MoldTicketManagementBatchUpdateReqVO reqVO); - List getInspectionByMoldId(Long id, String startTime, String endTime, String ids); + List getInspectionByMoldId(Long id, String code, String startTime, String endTime, String ids); - List getMaintenanceByMoldId(Long id, String startTime, String endTime, String ids); + List getMaintenanceByMoldId(Long id, String code, String startTime, String endTime, String ids); Long getBaoyangListCountByJobStatus(); @@ -75,4 +75,4 @@ public interface MoldTicketManagementService { List getList(); List getLatestList(); -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldticketmanagement/MoldTicketManagementServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldticketmanagement/MoldTicketManagementServiceImpl.java index e076d5749..52d4f7c56 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldticketmanagement/MoldTicketManagementServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/moldticketmanagement/MoldTicketManagementServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.common.dal.dataobject.moldticketresults.MoldTicke import cn.iocoder.yudao.module.common.dal.mysql.moldticketresults.MoldTicketResultsMapper; import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper; import com.alibaba.excel.util.StringUtils; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -30,6 +31,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.common.dal.mysql.moldticketmanagement.MoldTicketManagementMapper; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.MOLD_NOT_EXISTS; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** @@ -107,10 +109,10 @@ public class MoldTicketManagementServiceImpl implements MoldTicketManagementServ @Override - public List getInspectionByMoldId(Long id, String startTime, String endTime, String ids) { - MoldDO moldDO = moldMapper.selectById(id); + public List getInspectionByMoldId(Long id, String code, String startTime, String endTime, String ids) { + MoldDO moldDO = getMoldByIdOrCode(id, code); //点检列表 - List inspectionList = moldTicketResultsMapper.findByMoldIdAndPlanType(id, MoldPlanTypeEnum.INSPECTION.getCode(),startTime,endTime,ids); + List inspectionList = moldTicketResultsMapper.findByMoldIdAndPlanType(moldDO.getId(), MoldPlanTypeEnum.INSPECTION.getCode(),startTime,endTime,ids); if(CollectionUtils.isNotEmpty(inspectionList)){ moldDO.setInspectionList(inspectionList); } @@ -119,11 +121,11 @@ public class MoldTicketManagementServiceImpl implements MoldTicketManagementServ } @Override - public List getMaintenanceByMoldId(Long id,String startTime,String endTime,String ids) { - MoldDO moldDO = moldMapper.selectById(id); + public List getMaintenanceByMoldId(Long id, String code, String startTime, String endTime, String ids) { + MoldDO moldDO = getMoldByIdOrCode(id, code); //保养列表 - List inspectionList = moldTicketResultsMapper.findByMoldIdAndPlanType(id, MoldPlanTypeEnum.MAINTENANCE.getCode(),startTime,endTime,ids); + List inspectionList = moldTicketResultsMapper.findByMoldIdAndPlanType(moldDO.getId(), MoldPlanTypeEnum.MAINTENANCE.getCode(),startTime,endTime,ids); if(CollectionUtils.isNotEmpty(inspectionList)){ moldDO.setInspectionList(inspectionList); } @@ -131,6 +133,22 @@ public class MoldTicketManagementServiceImpl implements MoldTicketManagementServ return inspectionList; } + private MoldDO getMoldByIdOrCode(Long id, String code) { + MoldDO moldDO = null; + if (id != null) { + moldDO = moldMapper.selectById(id); + } else if (StringUtils.isNotBlank(code)) { + moldDO = moldMapper.selectOne(new LambdaQueryWrapperX() + .like(MoldDO::getCode, code) + .orderByDesc(MoldDO::getId) + .last("LIMIT 1")); + } + if (moldDO == null) { + throw exception(MOLD_NOT_EXISTS); + } + return moldDO; + } + /** * 解析逗号分隔的ID字符串 */ @@ -200,4 +218,4 @@ public class MoldTicketManagementServiceImpl implements MoldTicketManagementServ ); } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementService.java index 51ec72cb9..d31d9926b 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementService.java @@ -59,9 +59,9 @@ public interface TicketManagementService { void batchUpdateJobStatus(@Valid TicketManagementBatchUpdateReqVO reqVO); - List getInspectionByDeviceId(Long id,String startTime,String endTime,String ids); + List getInspectionByDeviceId(Long id, String code, String startTime, String endTime, String ids); - List getMaintenanceByDeviceId(Long id,String startTime,String endTime,String ids); + List getMaintenanceByDeviceId(Long id, String code, String startTime, String endTime, String ids); Long getBaoyangListCountByJobStatus(); @@ -76,4 +76,4 @@ public interface TicketManagementService { List getList(); List getLatestList(); -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementServiceImpl.java index eb8bc2180..7433100bd 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.mes.service.ticketmanagement; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.mes.controller.admin.dashboard.vo.dashboard.EventStatisticsVO; import cn.iocoder.yudao.module.mes.controller.admin.ticketmanagement.enums.JobStatusEnum; import cn.iocoder.yudao.module.mes.controller.admin.ticketmanagement.enums.PlanTypeEnum; @@ -108,10 +109,10 @@ public class TicketManagementServiceImpl implements TicketManagementService { } @Override - public List getInspectionByDeviceId(Long id,String startTime,String endTime,String ids) { - DeviceLedgerDO deviceLedgerDO = deviceLedgerMapper.selectById(id); + public List getInspectionByDeviceId(Long id, String code, String startTime, String endTime, String ids) { + DeviceLedgerDO deviceLedgerDO = getDeviceByIdOrCode(id, code); //点检列表 - List inspectionList = ticketResultsMapper.findByDeviceIdAndPlanType(id, PlanTypeEnum.INSPECTION.getCode(),startTime,endTime,ids); + List inspectionList = ticketResultsMapper.findByDeviceIdAndPlanType(deviceLedgerDO.getId(), PlanTypeEnum.INSPECTION.getCode(),startTime,endTime,ids); if(CollectionUtils.isNotEmpty(inspectionList)){ deviceLedgerDO.setInspectionList(inspectionList); } @@ -120,11 +121,11 @@ public class TicketManagementServiceImpl implements TicketManagementService { } @Override - public List getMaintenanceByDeviceId(Long id,String startTime,String endTime,String ids) { - DeviceLedgerDO deviceLedgerDO = deviceLedgerMapper.selectById(id); + public List getMaintenanceByDeviceId(Long id, String code, String startTime, String endTime, String ids) { + DeviceLedgerDO deviceLedgerDO = getDeviceByIdOrCode(id, code); //保养列表 - List inspectionList = ticketResultsMapper.findByDeviceIdAndPlanType(id, PlanTypeEnum.MAINTENANCE.getCode(),startTime,endTime,ids); + List inspectionList = ticketResultsMapper.findByDeviceIdAndPlanType(deviceLedgerDO.getId(), PlanTypeEnum.MAINTENANCE.getCode(),startTime,endTime,ids); if(CollectionUtils.isNotEmpty(inspectionList)){ deviceLedgerDO.setInspectionList(inspectionList); } @@ -132,6 +133,22 @@ public class TicketManagementServiceImpl implements TicketManagementService { return inspectionList; } + private DeviceLedgerDO getDeviceByIdOrCode(Long id, String code) { + DeviceLedgerDO deviceLedgerDO = null; + if (id != null) { + deviceLedgerDO = deviceLedgerMapper.selectById(id); + } else if (StringUtils.isNotBlank(code)) { + deviceLedgerDO = deviceLedgerMapper.selectOne(new LambdaQueryWrapperX() + .like(DeviceLedgerDO::getDeviceCode, code) + .orderByDesc(DeviceLedgerDO::getId) + .last("LIMIT 1")); + } + if (deviceLedgerDO == null) { + throw exception(DEVICE_LEDGER_NOT_EXISTS); + } + return deviceLedgerDO; + } + @Override public Long getBaoyangListCountByJobStatus() { return ticketManagementMapper.selectCount(Wrappers.lambdaQuery() @@ -204,4 +221,4 @@ public class TicketManagementServiceImpl implements TicketManagementService { .collect(Collectors.toList()); } -} \ No newline at end of file +} From fcc3cf46c093310dffc2630d4e1b60ecd4cecbe2 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Fri, 24 Apr 2026 16:05:04 +0800 Subject: [PATCH 3/8] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E5=BA=93=E5=8C=BA?= =?UTF-8?q?=E5=92=8C=E5=BA=93=E4=BD=8D=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 6 + .../admin/stock/ErpWarehouseController.java | 7 +- .../vo/warehouse/ErpWarehouseRespVO.java | 26 +++- .../vo/warehouse/ErpWarehouseSaveReqVO.java | 14 +-- .../WarehouseAreaController.java | 114 ++++++++++++++++++ .../vo/WarehouseAreaPageReqVO.java | 41 +++++++ .../warehousearea/vo/WarehouseAreaRespVO.java | 48 ++++++++ .../vo/WarehouseAreaSaveReqVO.java | 38 ++++++ .../WarehouseLocationController.java | 110 +++++++++++++++++ .../vo/WarehouseLocationPageReqVO.java | 59 +++++++++ .../vo/WarehouseLocationRespVO.java | 72 +++++++++++ .../vo/WarehouseLocationSaveReqVO.java | 59 +++++++++ .../warehousearea/WarehouseAreaDO.java | 56 +++++++++ .../WarehouseLocationDO.java | 81 +++++++++++++ .../warehousearea/WarehouseAreaMapper.java | 53 ++++++++ .../WarehouseLocationMapper.java | 61 ++++++++++ .../service/stock/ErpWarehouseService.java | 5 +- .../stock/ErpWarehouseServiceImpl.java | 55 ++++++--- .../warehousearea/WarehouseAreaService.java | 59 +++++++++ .../WarehouseAreaServiceImpl.java | 100 +++++++++++++++ .../WarehouseLocationService.java | 58 +++++++++ .../WarehouseLocationServiceImpl.java | 95 +++++++++++++++ .../warehousearea/WarehouseAreaMapper.xml | 12 ++ .../WarehouseLocationMapper.xml | 12 ++ 24 files changed, 1207 insertions(+), 34 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/WarehouseAreaController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/WarehouseLocationController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/warehousearea/WarehouseAreaDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/warehouselocation/WarehouseLocationDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/warehousearea/WarehouseAreaMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/warehouselocation/WarehouseLocationMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehousearea/WarehouseAreaService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehousearea/WarehouseAreaServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehouselocation/WarehouseLocationService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehouselocation/WarehouseLocationServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/warehousearea/WarehouseAreaMapper.xml create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/warehouselocation/WarehouseLocationMapper.xml diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index ea0d8ffa5..313403caf 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -90,6 +90,12 @@ public interface ErrorCodeConstants { // ========== ERP 仓库 1-030-400-000 ========== ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); ErrorCode WAREHOUSE_NOT_ENABLE = new ErrorCode(1_030_400_001, "仓库({})未启用"); + ErrorCode WAREHOUSE_AREA_CODE_EXISTS = new ErrorCode(1_030_400_002, "仓库库区编码不存在"); + ErrorCode WAREHOUSE_AREA_DELETE_FAIL_EXISTS_LOCATION = new ErrorCode(1_030_400_003, "仓库库区删除失败,请先删除对应库位信息"); + ErrorCode WAREHOUSE_AREA_NOT_EXISTS = new ErrorCode(1_030_400_004, "仓库库区不存在"); + ErrorCode WAREHOUSE_LOCATION_CODE_EXISTS = new ErrorCode(1_030_400_005, "库位编码不存在"); + ErrorCode WAREHOUSE_LOCATION_NOT_EXISTS = new ErrorCode(1_030_400_006, "库位不存在"); + ErrorCode WAREHOUSE_LOCATION_WAREHOUSE_AREA_NOT_MATCH = new ErrorCode(1_030_400_007, "暂无匹配库位信息"); // ========== ERP 其它入库单 1-030-401-000 ========== ErrorCode STOCK_IN_NOT_EXISTS = new ErrorCode(1_030_401_000, "其它入库单不存在"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java index 9de214b80..f25a6b627 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java @@ -5,11 +5,11 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; import io.swagger.v3.oas.annotations.Operation; @@ -80,8 +80,7 @@ public class ErpWarehouseController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('erp:warehouse:query')") public CommonResult getWarehouse(@RequestParam("id") Long id) { - ErpWarehouseDO warehouse = warehouseService.getWarehouse(id); - return success(BeanUtils.toBean(warehouse, ErpWarehouseRespVO.class)); + return success(warehouseService.getWarehouseDetail(id)); } @GetMapping("/page") @@ -113,4 +112,4 @@ public class ErpWarehouseController { BeanUtils.toBean(list, ErpWarehouseRespVO.class)); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java index 188d42699..e51086788 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.WarehouseAreaRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo.WarehouseLocationRespVO; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; @@ -10,6 +12,7 @@ import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "管理后台 - ERP 仓库 Response VO") @Data @@ -20,7 +23,7 @@ public class ErpWarehouseRespVO { @ExcelProperty("仓库编号") private Long id; - @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "成品仓") @ExcelProperty("仓库名称") private String name; @@ -32,11 +35,11 @@ public class ErpWarehouseRespVO { @ExcelProperty("排序") private Long sort; - @Schema(description = "备注", example = "随便") + @Schema(description = "备注", example = "主仓") @ExcelProperty("备注") private String remark; - @Schema(description = "负责人", example = "芋头") + @Schema(description = "负责人", example = "张三") @ExcelProperty("负责人") private String principal; @@ -57,8 +60,23 @@ public class ErpWarehouseRespVO { @ExcelProperty("是否默认") private Boolean defaultStatus; + @Schema(description = "库区数量", example = "2") + @ExcelProperty("库区数量") + private Long areaCount; + + @Schema(description = "库位数量", example = "10") + @ExcelProperty("库位数量") + private Long locationCount; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file + @Schema(description = "库区列表") + private List areaList; + + @Schema(description = "库位列表") + private List locationList; + + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java index 06bf5580e..96e843979 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; @Schema(description = "管理后台 - ERP 仓库新增/修改 Request VO") @@ -16,7 +16,7 @@ public class ErpWarehouseSaveReqVO { @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11614") private Long id; - @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "成品仓") @NotEmpty(message = "仓库名称不能为空") private String name; @@ -27,10 +27,10 @@ public class ErpWarehouseSaveReqVO { @NotNull(message = "排序不能为空") private Long sort; - @Schema(description = "备注", example = "随便") + @Schema(description = "备注", example = "主仓") private String remark; - @Schema(description = "负责人", example = "芋头") + @Schema(description = "负责人", example = "张三") private String principal; @Schema(description = "仓储费,单位:元", example = "13973") @@ -39,9 +39,9 @@ public class ErpWarehouseSaveReqVO { @Schema(description = "搬运费,单位:元", example = "9903") private BigDecimal truckagePrice; - @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "开启状态不能为空") @InEnum(CommonStatusEnum.class) private Integer status; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/WarehouseAreaController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/WarehouseAreaController.java new file mode 100644 index 000000000..a798cff36 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/WarehouseAreaController.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.erp.controller.admin.warehousearea; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + + +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.*; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; +import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +@Tag(name = "管理后台 - ERP 库区信息") +@RestController +@RequestMapping("/erp/warehouse-area") +@Validated +public class WarehouseAreaController { + + @Resource + private WarehouseAreaService warehouseAreaService; + + @PostMapping("/create") + @Operation(summary = "创建ERP 库区信息") + @PreAuthorize("@ss.hasPermission('erp:warehouse-area:create')") + public CommonResult createWarehouseArea(@Valid @RequestBody WarehouseAreaSaveReqVO createReqVO) { + return success(warehouseAreaService.createWarehouseArea(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新ERP 库区信息") + @PreAuthorize("@ss.hasPermission('erp:warehouse-area:update')") + public CommonResult updateWarehouseArea(@Valid @RequestBody WarehouseAreaSaveReqVO updateReqVO) { + warehouseAreaService.updateWarehouseArea(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除ERP 库区信息") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:warehouse-area:delete')") + public CommonResult deleteWarehouseArea(@RequestParam("id") Long id) { + warehouseAreaService.deleteWarehouseArea(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得ERP 库区信息") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:warehouse-area:query')") + public CommonResult getWarehouseArea(@RequestParam("id") Long id) { + WarehouseAreaDO warehouseArea = warehouseAreaService.getWarehouseArea(id); + return success(BeanUtils.toBean(warehouseArea, WarehouseAreaRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得ERP 库区信息分页") + @PreAuthorize("@ss.hasPermission('erp:warehouse-area:query')") + public CommonResult> getWarehouseAreaPage(@Valid WarehouseAreaPageReqVO pageReqVO) { + PageResult pageResult = warehouseAreaService.getWarehouseAreaPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, WarehouseAreaRespVO.class)); + } + + + @GetMapping("/simple-list") + @Operation(summary = "获得库区精简列表", description = "只包含被开启的仓库库区,主要用于前端的下拉选项") + public CommonResult> getWarehouseSimpleList(@RequestParam(value = "warehouseId", required = false) Long warehouseId) { + List list = warehouseAreaService.getWarehouseListByStatusAndWarehouseId(CommonStatusEnum.ENABLE.getStatus(), warehouseId); + return success(convertList(list, area -> new WarehouseAreaRespVO() + .setId(area.getId()) + .setWarehouseId(area.getWarehouseId()) + .setAreaCode(area.getAreaCode()) + .setAreaName(area.getAreaName()) + .setStatus(area.getStatus()))); + } + + + @GetMapping("/export-excel") + @Operation(summary = "导出ERP 库区信息 Excel") + @PreAuthorize("@ss.hasPermission('erp:warehouse-area:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportWarehouseAreaExcel(@Valid WarehouseAreaPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = warehouseAreaService.getWarehouseAreaPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "ERP 库区信息.xls", "数据", WarehouseAreaRespVO.class, + BeanUtils.toBean(list, WarehouseAreaRespVO.class)); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaPageReqVO.java new file mode 100644 index 000000000..3aaa7e62f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaPageReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.math.BigDecimal; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 库区信息分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class WarehouseAreaPageReqVO extends PageParam { + + @Schema(description = "所属仓库id", example = "19404") + private Long warehouseId; + + @Schema(description = "库区编码") + private String areaCode; + + @Schema(description = "库区名称", example = "赵六") + private String areaName; + + @Schema(description = "面积(平方米)") + private BigDecimal areaSize; + + @Schema(description = "库区描述", example = "你说的对") + private String description; + + @Schema(description = "开启状态", example = "2") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaRespVO.java new file mode 100644 index 000000000..e0278110a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaRespVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.math.BigDecimal; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - ERP 库区信息 Response VO") +@Data +@ExcelIgnoreUnannotated +public class WarehouseAreaRespVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1157") + @ExcelProperty("id") + private Long id; + + @Schema(description = "所属仓库id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19404") + @ExcelProperty("所属仓库id") + private Long warehouseId; + + @Schema(description = "库区编码", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("库区编码") + private String areaCode; + + @Schema(description = "库区名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + @ExcelProperty("库区名称") + private String areaName; + + @Schema(description = "面积(平方米)") + @ExcelProperty("面积(平方米)") + private BigDecimal areaSize; + + @Schema(description = "库区描述", example = "你说的对") + @ExcelProperty("库区描述") + private String description; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("开启状态") + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaSaveReqVO.java new file mode 100644 index 000000000..b38b9833c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehousearea/vo/WarehouseAreaSaveReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 库区信息新增/修改 Request VO") +@Data +public class WarehouseAreaSaveReqVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1157") + private Long id; + + @Schema(description = "所属仓库id", example = "19404") + private Long warehouseId; + + @Schema(description = "库区编码", requiredMode = Schema.RequiredMode.REQUIRED) +// @NotEmpty(message = "库区编码不能为空") + private String areaCode; + + @Schema(description = "库区名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "A区") + @NotEmpty(message = "库区名称不能为空") + private String areaName; + + @Schema(description = "面积(平方米)") + private BigDecimal areaSize; + + @Schema(description = "库区描述", example = "常温区") + private String description; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + private Integer status; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/WarehouseLocationController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/WarehouseLocationController.java new file mode 100644 index 000000000..cf58dbf37 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/WarehouseLocationController.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.erp.controller.admin.warehouselocation; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo.*; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehouselocation.WarehouseLocationDO; +import cn.iocoder.yudao.module.erp.service.warehouselocation.WarehouseLocationService; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +@Tag(name = "管理后台 - ERP 库位信息") +@RestController +@RequestMapping("/erp/warehouse-location") +@Validated +public class WarehouseLocationController { + + @Resource + private WarehouseLocationService warehouseLocationService; + + @PostMapping("/create") + @Operation(summary = "创建ERP 库位信息") + @PreAuthorize("@ss.hasPermission('erp:warehouse-location:create')") + public CommonResult createWarehouseLocation(@Valid @RequestBody WarehouseLocationSaveReqVO createReqVO) { + return success(warehouseLocationService.createWarehouseLocation(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新ERP 库位信息") + @PreAuthorize("@ss.hasPermission('erp:warehouse-location:update')") + public CommonResult updateWarehouseLocation(@Valid @RequestBody WarehouseLocationSaveReqVO updateReqVO) { + warehouseLocationService.updateWarehouseLocation(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除ERP 库位信息") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:warehouse-location:delete')") + public CommonResult deleteWarehouseLocation(@RequestParam("id") Long id) { + warehouseLocationService.deleteWarehouseLocation(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得ERP 库位信息") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:warehouse-location:query')") + public CommonResult getWarehouseLocation(@RequestParam("id") Long id) { + WarehouseLocationDO warehouseLocation = warehouseLocationService.getWarehouseLocation(id); + return success(BeanUtils.toBean(warehouseLocation, WarehouseLocationRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得ERP 库位信息分页") + @PreAuthorize("@ss.hasPermission('erp:warehouse-location:query')") + public CommonResult> getWarehouseLocationPage(@Valid WarehouseLocationPageReqVO pageReqVO) { + PageResult pageResult = warehouseLocationService.getWarehouseLocationPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, WarehouseLocationRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得ERP 库位信息精简列表", description = "只包含已启用的库位,主要用于前端下拉选项") + public CommonResult> getWarehouseLocationSimpleList() { + List list = warehouseLocationService.getWarehouseLocationListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, item -> new WarehouseLocationRespVO() + .setId(item.getId()) + .setWarehouseId(item.getWarehouseId()) + .setAreaId(item.getAreaId()) + .setCode(item.getCode()) + .setName(item.getName()) + .setStatus(item.getStatus()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出ERP 库位信息 Excel") + @PreAuthorize("@ss.hasPermission('erp:warehouse-location:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportWarehouseLocationExcel(@Valid WarehouseLocationPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = warehouseLocationService.getWarehouseLocationPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "ERP 库位信息.xls", "数据", WarehouseLocationRespVO.class, + BeanUtils.toBean(list, WarehouseLocationRespVO.class)); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationPageReqVO.java new file mode 100644 index 000000000..e06f2a814 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationPageReqVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.math.BigDecimal; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 库位信息分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class WarehouseLocationPageReqVO extends PageParam { + + @Schema(description = "所属仓库ID", example = "19287") + private Long warehouseId; + + @Schema(description = "所属库区ID", example = "513") + private Long areaId; + + @Schema(description = "库位编码") + private String code; + + @Schema(description = "库位名称", example = "张三") + private String name; + + @Schema(description = "面积") + private BigDecimal areaSize; + + @Schema(description = "最大载重量") + private BigDecimal maxLoadWeight; + + @Schema(description = "库位位置X") + private Integer positionX; + + @Schema(description = "库位位置Y") + private Integer positionY; + + @Schema(description = "库位位置Z") + private Integer positionZ; + + @Schema(description = "是否允许产品混放") + private Boolean allowProductMix; + + @Schema(description = "是否允许批次混放") + private Boolean allowBatchMix; + + @Schema(description = "开启状态", example = "1") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationRespVO.java new file mode 100644 index 000000000..546628e05 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationRespVO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.math.BigDecimal; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - ERP 库位信息 Response VO") +@Data +@ExcelIgnoreUnannotated +public class WarehouseLocationRespVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "7300") + @ExcelProperty("id") + private Long id; + + @Schema(description = "所属仓库ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "19287") + @ExcelProperty("所属仓库ID") + private Long warehouseId; + + @Schema(description = "所属库区ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "513") + @ExcelProperty("所属库区ID") + private Long areaId; + + @Schema(description = "库位编码", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("库位编码") + private String code; + + @Schema(description = "库位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @ExcelProperty("库位名称") + private String name; + + @Schema(description = "面积") + @ExcelProperty("面积") + private BigDecimal areaSize; + + @Schema(description = "最大载重量") + @ExcelProperty("最大载重量") + private BigDecimal maxLoadWeight; + + @Schema(description = "库位位置X") + @ExcelProperty("库位位置X") + private Integer positionX; + + @Schema(description = "库位位置Y") + @ExcelProperty("库位位置Y") + private Integer positionY; + + @Schema(description = "库位位置Z") + @ExcelProperty("库位位置Z") + private Integer positionZ; + + @Schema(description = "是否允许产品混放", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("是否允许产品混放") + private Boolean allowProductMix; + + @Schema(description = "是否允许批次混放", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("是否允许批次混放") + private Boolean allowBatchMix; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("开启状态") + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationSaveReqVO.java new file mode 100644 index 000000000..5cd8e9553 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/warehouselocation/vo/WarehouseLocationSaveReqVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 库位信息新增/修改 Request VO") +@Data +public class WarehouseLocationSaveReqVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "7300") + private Long id; + + @Schema(description = "所属仓库ID", example = "19287") + private Long warehouseId; + + @Schema(description = "所属库区ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "513") + @NotNull(message = "所属库区ID不能为空") + private Long areaId; + + @Schema(description = "库位编码", requiredMode = Schema.RequiredMode.REQUIRED) +// @NotEmpty(message = "库位编码不能为空") + private String code; + + @Schema(description = "库位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "A-01-01") + @NotEmpty(message = "库位名称不能为空") + private String name; + + @Schema(description = "面积") + private BigDecimal areaSize; + + @Schema(description = "最大载重量") + private BigDecimal maxLoadWeight; + + @Schema(description = "库位位置X") + private Integer positionX; + + @Schema(description = "库位位置Y") + private Integer positionY; + + @Schema(description = "库位位置Z") + private Integer positionZ; + + @Schema(description = "是否允许产品混放", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "是否允许产品混放不能为空") + private Boolean allowProductMix; + + @Schema(description = "是否允许批次混放", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "是否允许批次混放不能为空") + private Boolean allowBatchMix; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + private Integer status; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/warehousearea/WarehouseAreaDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/warehousearea/WarehouseAreaDO.java new file mode 100644 index 000000000..560e6d7b5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/warehousearea/WarehouseAreaDO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea; + +import lombok.*; +import java.util.*; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * ERP 库区信息 DO + * + * @author 必硕智能 + */ +@TableName("erp_warehouse_area") +@KeySequence("erp_warehouse_area_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WarehouseAreaDO extends BaseDO { + + /** + * id + */ + @TableId + private Long id; + /** + * 所属仓库id + */ + private Long warehouseId; + /** + * 库区编码 + */ + private String areaCode; + /** + * 库区名称 + */ + private String areaName; + /** + * 面积(平方米) + */ + private BigDecimal areaSize; + /** + * 库区描述 + */ + private String description; + /** + * 开启状态 + */ + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/warehouselocation/WarehouseLocationDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/warehouselocation/WarehouseLocationDO.java new file mode 100644 index 000000000..aa5584dca --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/warehouselocation/WarehouseLocationDO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.warehouselocation; + +import lombok.*; +import java.util.*; +import java.math.BigDecimal; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * ERP 库位信息 DO + * + * @author 必硕智能 + */ +@TableName("erp_warehouse_location") +@KeySequence("erp_warehouse_location_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WarehouseLocationDO extends BaseDO { + + /** + * id + */ + @TableId + private Long id; + /** + * 所属仓库ID + */ + private Long warehouseId; + /** + * 所属库区ID + */ + private Long areaId; + /** + * 库位编码 + */ + private String code; + /** + * 库位名称 + */ + private String name; + /** + * 面积 + */ + private BigDecimal areaSize; + /** + * 最大载重量 + */ + private BigDecimal maxLoadWeight; + /** + * 库位位置X + */ + private Integer positionX; + /** + * 库位位置Y + */ + private Integer positionY; + /** + * 库位位置Z + */ + private Integer positionZ; + /** + * 是否允许产品混放 + */ + private Boolean allowProductMix; + /** + * 是否允许批次混放 + */ + private Boolean allowBatchMix; + /** + * 开启状态 + */ + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/warehousearea/WarehouseAreaMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/warehousearea/WarehouseAreaMapper.java new file mode 100644 index 000000000..d4a645d5a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/warehousearea/WarehouseAreaMapper.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.warehousearea; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.*; + +/** + * ERP 库区信息 Mapper + * + * @author 必硕智能 + */ +@Mapper +public interface WarehouseAreaMapper extends BaseMapperX { + + default PageResult selectPage(WarehouseAreaPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(WarehouseAreaDO::getWarehouseId, reqVO.getWarehouseId()) + .eqIfPresent(WarehouseAreaDO::getAreaCode, reqVO.getAreaCode()) + .likeIfPresent(WarehouseAreaDO::getAreaName, reqVO.getAreaName()) + .eqIfPresent(WarehouseAreaDO::getAreaSize, reqVO.getAreaSize()) + .eqIfPresent(WarehouseAreaDO::getDescription, reqVO.getDescription()) + .eqIfPresent(WarehouseAreaDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(WarehouseAreaDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(WarehouseAreaDO::getId)); + } + + + default WarehouseAreaDO selectByNo(String no) { + return selectOne(WarehouseAreaDO::getAreaCode, no); + } + + default List selectListByStatus(Integer status) { + return selectList(WarehouseAreaDO::getStatus, status); + } + + default List selectListByWarehouseId(Long warehouseId) { + return selectList(WarehouseAreaDO::getWarehouseId, warehouseId); + } + + default void deleteByWarehouseId(Long warehouseId) { + delete(WarehouseAreaDO::getWarehouseId, warehouseId); + } + + default Long selectCountByWarehouseId(Long warehouseId) { + return selectCount(WarehouseAreaDO::getWarehouseId, warehouseId); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/warehouselocation/WarehouseLocationMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/warehouselocation/WarehouseLocationMapper.java new file mode 100644 index 000000000..50793269b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/warehouselocation/WarehouseLocationMapper.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.warehouselocation; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehouselocation.WarehouseLocationDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo.*; + +/** + * ERP 库位信息 Mapper + * + * @author 必硕智能 + */ +@Mapper +public interface WarehouseLocationMapper extends BaseMapperX { + + default PageResult selectPage(WarehouseLocationPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(WarehouseLocationDO::getWarehouseId, reqVO.getWarehouseId()) + .eqIfPresent(WarehouseLocationDO::getAreaId, reqVO.getAreaId()) + .eqIfPresent(WarehouseLocationDO::getCode, reqVO.getCode()) + .likeIfPresent(WarehouseLocationDO::getName, reqVO.getName()) + .eqIfPresent(WarehouseLocationDO::getAreaSize, reqVO.getAreaSize()) + .eqIfPresent(WarehouseLocationDO::getMaxLoadWeight, reqVO.getMaxLoadWeight()) + .eqIfPresent(WarehouseLocationDO::getPositionX, reqVO.getPositionX()) + .eqIfPresent(WarehouseLocationDO::getPositionY, reqVO.getPositionY()) + .eqIfPresent(WarehouseLocationDO::getPositionZ, reqVO.getPositionZ()) + .eqIfPresent(WarehouseLocationDO::getAllowProductMix, reqVO.getAllowProductMix()) + .eqIfPresent(WarehouseLocationDO::getAllowBatchMix, reqVO.getAllowBatchMix()) + .eqIfPresent(WarehouseLocationDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(WarehouseLocationDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(WarehouseLocationDO::getId)); + } + + default WarehouseLocationDO selectByNo(String no) { + return selectOne(WarehouseLocationDO::getCode, no); + } + + default List selectListByWarehouseId(Long warehouseId) { + return selectList(WarehouseLocationDO::getWarehouseId, warehouseId); + } + + default void deleteByWarehouseId(Long warehouseId) { + delete(WarehouseLocationDO::getWarehouseId, warehouseId); + } + + default List selectListByStatus(Integer status) { + return selectList(WarehouseLocationDO::getStatus, status); + } + + default List selectListByAreaId(Long areaId) { + return selectList(WarehouseLocationDO::getAreaId, areaId); + } + + default Long selectCountByWarehouseId(Long warehouseId) { + return selectCount(WarehouseLocationDO::getWarehouseId, warehouseId); + } +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java index 42f493263..0d514cabb 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; @@ -58,6 +59,8 @@ public interface ErpWarehouseService { */ ErpWarehouseDO getWarehouse(Long id); + ErpWarehouseRespVO getWarehouseDetail(Long id); + /** * 校验仓库列表的有效性 * @@ -101,4 +104,4 @@ public interface ErpWarehouseService { */ PageResult getWarehousePage(ErpWarehousePageReqVO pageReqVO); -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java index 9e80128dd..10eade2f5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java @@ -4,10 +4,17 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.WarehouseAreaRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo.WarehouseLocationRespVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehouselocation.WarehouseLocationDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.warehousearea.WarehouseAreaMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.warehouselocation.WarehouseLocationMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -23,11 +30,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_ENABLE; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS; -/** - * ERP 仓库 Service 实现类 - * - * @author 芋道源码 - */ @Service @Validated public class ErpWarehouseServiceImpl implements ErpWarehouseService { @@ -35,20 +37,22 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService { @Resource private ErpWarehouseMapper warehouseMapper; + @Resource + private WarehouseAreaMapper warehouseAreaMapper; + + @Resource + private WarehouseLocationMapper warehouseLocationMapper; + @Override public Long createWarehouse(ErpWarehouseSaveReqVO createReqVO) { - // 插入 ErpWarehouseDO warehouse = BeanUtils.toBean(createReqVO, ErpWarehouseDO.class); warehouseMapper.insert(warehouse); - // 返回 return warehouse.getId(); } @Override public void updateWarehouse(ErpWarehouseSaveReqVO updateReqVO) { - // 校验存在 validateWarehouseExists(updateReqVO.getId()); - // 更新 ErpWarehouseDO updateObj = BeanUtils.toBean(updateReqVO, ErpWarehouseDO.class); warehouseMapper.updateById(updateObj); } @@ -56,25 +60,22 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService { @Override @Transactional(rollbackFor = Exception.class) public void updateWarehouseDefaultStatus(Long id, Boolean defaultStatus) { - // 1. 校验存在 validateWarehouseExists(id); - - // 2.1 如果开启,则需要关闭所有其它的默认 if (defaultStatus) { ErpWarehouseDO warehouse = warehouseMapper.selectByDefaultStatus(); if (warehouse != null) { warehouseMapper.updateById(new ErpWarehouseDO().setId(warehouse.getId()).setDefaultStatus(false)); } } - // 2.2 更新对应的默认状态 warehouseMapper.updateById(new ErpWarehouseDO().setId(id).setDefaultStatus(defaultStatus)); } @Override + @Transactional(rollbackFor = Exception.class) public void deleteWarehouse(Long id) { - // 校验存在 validateWarehouseExists(id); - // 删除 + warehouseLocationMapper.deleteByWarehouseId(id); + warehouseAreaMapper.deleteByWarehouseId(id); warehouseMapper.deleteById(id); } @@ -89,6 +90,24 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService { return warehouseMapper.selectById(id); } + @Override + public ErpWarehouseRespVO getWarehouseDetail(Long id) { + ErpWarehouseDO warehouse = warehouseMapper.selectById(id); + if (warehouse == null) { + return null; + } + ErpWarehouseRespVO respVO = BeanUtils.toBean(warehouse, ErpWarehouseRespVO.class); + + List areaList = warehouseAreaMapper.selectListByWarehouseId(id); + List locationList = warehouseLocationMapper.selectListByWarehouseId(id); + + respVO.setAreaCount((long) areaList.size()); + respVO.setLocationCount((long) locationList.size()); + respVO.setAreaList(BeanUtils.toBean(areaList, WarehouseAreaRespVO.class)); + respVO.setLocationList(BeanUtils.toBean(locationList, WarehouseLocationRespVO.class)); + return respVO; + } + @Override public List validWarehouseList(Collection ids) { if (CollUtil.isEmpty(ids)) { @@ -98,7 +117,7 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService { Map warehouseMap = convertMap(list, ErpWarehouseDO::getId); for (Long id : ids) { ErpWarehouseDO warehouse = warehouseMap.get(id); - if (warehouseMap.get(id) == null) { + if (warehouse == null) { throw exception(WAREHOUSE_NOT_EXISTS); } if (CommonStatusEnum.isDisable(warehouse.getStatus())) { @@ -123,4 +142,4 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService { return warehouseMapper.selectPage(pageReqVO); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehousearea/WarehouseAreaService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehousearea/WarehouseAreaService.java new file mode 100644 index 000000000..0f1a26d9c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehousearea/WarehouseAreaService.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.erp.service.warehousearea; + +import java.util.*; +import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.*; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +import javax.validation.Valid; + +/** + * ERP 库区信息 Service 接口 + * + * @author 必硕智能 + */ +public interface WarehouseAreaService { + + /** + * 创建ERP 库区信息 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWarehouseArea(@Valid WarehouseAreaSaveReqVO createReqVO); + + /** + * 更新ERP 库区信息 + * + * @param updateReqVO 更新信息 + */ + void updateWarehouseArea(@Valid WarehouseAreaSaveReqVO updateReqVO); + + /** + * 删除ERP 库区信息 + * + * @param id 编号 + */ + void deleteWarehouseArea(Long id); + + /** + * 获得ERP 库区信息 + * + * @param id 编号 + * @return ERP 库区信息 + */ + WarehouseAreaDO getWarehouseArea(Long id); + + /** + * 获得ERP 库区信息分页 + * + * @param pageReqVO 分页查询 + * @return ERP 库区信息分页 + */ + PageResult getWarehouseAreaPage(WarehouseAreaPageReqVO pageReqVO); + + List getWarehouseListByStatus(Integer status); + + List getWarehouseListByStatusAndWarehouseId(Integer status, Long warehouseId); +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehousearea/WarehouseAreaServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehousearea/WarehouseAreaServiceImpl.java new file mode 100644 index 000000000..b19faa7ea --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehousearea/WarehouseAreaServiceImpl.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.erp.service.warehousearea; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; +import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.WarehouseAreaPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.WarehouseAreaSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; +import cn.iocoder.yudao.module.erp.dal.mysql.warehousearea.WarehouseAreaMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.warehouselocation.WarehouseLocationMapper; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_AREA_CODE_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_AREA_DELETE_FAIL_EXISTS_LOCATION; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_AREA_NOT_EXISTS; + +@Service +@Validated +public class WarehouseAreaServiceImpl implements WarehouseAreaService { + + @Resource + private WarehouseAreaMapper warehouseAreaMapper; + + @Resource + private WarehouseLocationMapper warehouseLocationMapper; + + @Resource + private AutoCodeUtil autoCodeUtil; + + @Override + public Long createWarehouseArea(WarehouseAreaSaveReqVO createReqVO) { + WarehouseAreaDO warehouseArea = BeanUtils.toBean(createReqVO, WarehouseAreaDO.class); + if (StringUtils.isEmpty(warehouseArea.getAreaCode())) { + warehouseArea.setAreaCode(autoCodeUtil.genSerialCode("RESERVOIR_AREA_GENERATE", null)); + } else if (warehouseAreaMapper.selectByNo(warehouseArea.getAreaCode()) != null) { + throw exception(WAREHOUSE_AREA_CODE_EXISTS); + } + warehouseAreaMapper.insert(warehouseArea); + return warehouseArea.getId(); + } + + @Override + public void updateWarehouseArea(WarehouseAreaSaveReqVO updateReqVO) { + validateWarehouseAreaExists(updateReqVO.getId()); + warehouseAreaMapper.updateById(BeanUtils.toBean(updateReqVO, WarehouseAreaDO.class)); + } + + @Override + public void deleteWarehouseArea(Long id) { + validateWarehouseAreaExists(id); + if (!warehouseLocationMapper.selectListByAreaId(id).isEmpty()) { + throw exception(WAREHOUSE_AREA_DELETE_FAIL_EXISTS_LOCATION); + } + warehouseAreaMapper.deleteById(id); + } + + private void validateWarehouseAreaExists(Long id) { + if (warehouseAreaMapper.selectById(id) == null) { + throw exception(WAREHOUSE_AREA_NOT_EXISTS); + } + } + + @Override + public WarehouseAreaDO getWarehouseArea(Long id) { + return warehouseAreaMapper.selectById(id); + } + + @Override + public PageResult getWarehouseAreaPage(WarehouseAreaPageReqVO pageReqVO) { + return warehouseAreaMapper.selectPage(pageReqVO); + } + + @Override + public List getWarehouseListByStatus(Integer status) { + return warehouseAreaMapper.selectListByStatus(status); + } + + @Override + public List getWarehouseListByStatusAndWarehouseId(Integer status, Long warehouseId) { + List list = warehouseAreaMapper.selectListByStatus(status); + if (warehouseId == null) { + return list; + } + List result = new ArrayList<>(); + for (WarehouseAreaDO item : list) { + if (warehouseId.equals(item.getWarehouseId())) { + result.add(item); + } + } + return result; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehouselocation/WarehouseLocationService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehouselocation/WarehouseLocationService.java new file mode 100644 index 000000000..a2b3b252b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehouselocation/WarehouseLocationService.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.erp.service.warehouselocation; + +import java.util.*; +import cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo.*; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehouselocation.WarehouseLocationDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +import javax.validation.Valid; + +/** + * ERP 库位信息 Service 接口 + * + * @author 必硕智能 + */ +public interface WarehouseLocationService { + + /** + * 创建ERP 库位信息 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWarehouseLocation(@Valid WarehouseLocationSaveReqVO createReqVO); + + /** + * 更新ERP 库位信息 + * + * @param updateReqVO 更新信息 + */ + void updateWarehouseLocation(@Valid WarehouseLocationSaveReqVO updateReqVO); + + /** + * 删除ERP 库位信息 + * + * @param id 编号 + */ + void deleteWarehouseLocation(Long id); + + /** + * 获得ERP 库位信息 + * + * @param id 编号 + * @return ERP 库位信息 + */ + WarehouseLocationDO getWarehouseLocation(Long id); + + List getWarehouseLocationListByStatus(Integer status); + + /** + * 获得ERP 库位信息分页 + * + * @param pageReqVO 分页查询 + * @return ERP 库位信息分页 + */ + PageResult getWarehouseLocationPage(WarehouseLocationPageReqVO pageReqVO); + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehouselocation/WarehouseLocationServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehouselocation/WarehouseLocationServiceImpl.java new file mode 100644 index 000000000..e4c106613 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/warehouselocation/WarehouseLocationServiceImpl.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.service.warehouselocation; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; +import cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo.WarehouseLocationPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.warehouselocation.vo.WarehouseLocationSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehouselocation.WarehouseLocationDO; +import cn.iocoder.yudao.module.erp.dal.mysql.warehousearea.WarehouseAreaMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.warehouselocation.WarehouseLocationMapper; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_AREA_NOT_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_LOCATION_CODE_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_LOCATION_NOT_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_LOCATION_WAREHOUSE_AREA_NOT_MATCH; + +@Service +@Validated +public class WarehouseLocationServiceImpl implements WarehouseLocationService { + + @Resource + private WarehouseLocationMapper warehouseLocationMapper; + + @Resource + private WarehouseAreaMapper warehouseAreaMapper; + + @Resource + private AutoCodeUtil autoCodeUtil; + + @Override + public Long createWarehouseLocation(WarehouseLocationSaveReqVO createReqVO) { + validateWarehouseAreaMatch(createReqVO.getWarehouseId(), createReqVO.getAreaId()); + WarehouseLocationDO warehouseLocation = BeanUtils.toBean(createReqVO, WarehouseLocationDO.class); + if (StringUtils.isEmpty(warehouseLocation.getCode())) { + warehouseLocation.setCode(autoCodeUtil.genSerialCode("RESERVOIR_AREA_GENERATE", null)); + } else if (warehouseLocationMapper.selectByNo(warehouseLocation.getCode()) != null) { + throw exception(WAREHOUSE_LOCATION_CODE_EXISTS); + } + warehouseLocationMapper.insert(warehouseLocation); + return warehouseLocation.getId(); + } + + @Override + public void updateWarehouseLocation(WarehouseLocationSaveReqVO updateReqVO) { + validateWarehouseLocationExists(updateReqVO.getId()); + validateWarehouseAreaMatch(updateReqVO.getWarehouseId(), updateReqVO.getAreaId()); + warehouseLocationMapper.updateById(BeanUtils.toBean(updateReqVO, WarehouseLocationDO.class)); + } + + @Override + public void deleteWarehouseLocation(Long id) { + validateWarehouseLocationExists(id); + warehouseLocationMapper.deleteById(id); + } + + private void validateWarehouseLocationExists(Long id) { + if (warehouseLocationMapper.selectById(id) == null) { + throw exception(WAREHOUSE_LOCATION_NOT_EXISTS); + } + } + + private void validateWarehouseAreaMatch(Long warehouseId, Long areaId) { + WarehouseAreaDO area = warehouseAreaMapper.selectById(areaId); + if (area == null) { + throw exception(WAREHOUSE_AREA_NOT_EXISTS); + } + if (warehouseId == null || !warehouseId.equals(area.getWarehouseId())) { + throw exception(WAREHOUSE_LOCATION_WAREHOUSE_AREA_NOT_MATCH); + } + } + + @Override + public WarehouseLocationDO getWarehouseLocation(Long id) { + return warehouseLocationMapper.selectById(id); + } + + @Override + public List getWarehouseLocationListByStatus(Integer status) { + return warehouseLocationMapper.selectListByStatus(status); + } + + @Override + public PageResult getWarehouseLocationPage(WarehouseLocationPageReqVO pageReqVO) { + return warehouseLocationMapper.selectPage(pageReqVO); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/warehousearea/WarehouseAreaMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/warehousearea/WarehouseAreaMapper.xml new file mode 100644 index 000000000..123b6c774 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/warehousearea/WarehouseAreaMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/warehouselocation/WarehouseLocationMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/warehouselocation/WarehouseLocationMapper.xml new file mode 100644 index 000000000..9d39d7109 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/warehouselocation/WarehouseLocationMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file From b67ff2879c14c90d47ce608d8743a41c549f4ad8 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Fri, 24 Apr 2026 17:25:03 +0800 Subject: [PATCH 4/8] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E9=87=87=E9=9B=86?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/service/device/DeviceServiceImpl.java | 2 +- .../iot/service/device/TDengineService.java | 116 +++++++++++------- 2 files changed, 72 insertions(+), 46 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java index c950d5f07..eb0150190 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java @@ -361,7 +361,7 @@ public class DeviceServiceImpl implements DeviceService { // .orderByDesc(DeviceOperationRecordDO::getCreateTime) // ); - List operationRecords = tdengineService.selectLatestByDeviceAndRuleMinimal(deviceIds,ruleCodes); + List operationRecords = tdengineService.selectLatestByDeviceAndRuleMinimal(deviceIds,null); // 按 deviceId 分组,取最新一条 Map latestRecordMap = operationRecords.stream() diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java index 5b20c424b..3a5f66bfe 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java @@ -2009,7 +2009,8 @@ public class TDengineService { /** - * 批量查询设备最新一条运行记录 + * 批量查询设备最新一条运行记录(使用TDengine的LAST函数优化) + * 通过GROUP BY device_id一次性查询所有设备的最新记录 */ @DS("tdengine") public List selectLatestByDeviceAndRuleMinimal( @@ -2020,59 +2021,84 @@ public class TDengineService { return Collections.emptyList(); } - // 优化:分组查询每个设备的最新记录 - List allResults = new ArrayList<>(); - - for (Long deviceId : deviceIds) { - StringBuilder sql = new StringBuilder( - "SELECT * FROM besure_server.iot_device_operation_record " + - "WHERE deleted = 0 AND device_id = ? " - ); + // 构建SQL查询,使用TDengine的LAST函数 + StringBuilder sql = new StringBuilder( + "SELECT device_id, " + + "LAST(device_id) as last_device_id, " + + "LAST(rule) as rule, " + + "LAST(address_value) as address_value, " + + "LAST(create_time) as create_time, " + + "LAST(model_id) as model_id, " + + "LAST(creator) as creator, " + + "LAST(updater) as updater, " + + "LAST(update_time) as update_time, " + + "LAST(deleted) as deleted, " + + "LAST(tenant_id) as tenant_id, " + + "LAST(rule_id) as rule_id " + + "FROM besure_server.iot_device_operation_record " + + "WHERE deleted = 0 " + ); + + // 添加设备ID条件 + sql.append("AND device_id IN ("); + List params = new ArrayList<>(); - List params = new ArrayList<>(); - params.add(deviceId); + for (int i = 0; i < deviceIds.size(); i++) { + if (i > 0) { + sql.append(", "); + } + sql.append("?"); + params.add(deviceIds.get(i)); + } + sql.append(") "); - if (CollectionUtils.isNotEmpty(ruleCodes)) { - sql.append("AND rule IN ("); - for (int i = 0; i < ruleCodes.size(); i++) { - if (i > 0) sql.append(", "); - sql.append("?"); - params.add(ruleCodes.get(i)); + // 添加规则代码条件 + if (CollectionUtils.isNotEmpty(ruleCodes)) { + sql.append("AND rule IN ("); + for (int i = 0; i < ruleCodes.size(); i++) { + if (i > 0) { + sql.append(", "); } - sql.append(") "); + sql.append("?"); + params.add(ruleCodes.get(i)); } + sql.append(") "); + } - sql.append("ORDER BY create_time DESC LIMIT 1"); // 每个设备只取最新1条 + // 使用GROUP BY device_id获取每个设备的最新记录 + sql.append("GROUP BY device_id "); - try { - List deviceResults = jdbcTemplate.query( - sql.toString(), - params.toArray(), - (rs, rowNum) -> { - DeviceOperationRecordDO d = new DeviceOperationRecordDO(); - d.setDeviceId(rs.getLong("device_id")); - d.setModelId(rs.getLong("model_id")); - d.setRule(rs.getString("rule")); - d.setAddressValue(rs.getString("address_value")); - d.setCreator(rs.getString("creator")); - d.setCreateTime(rs.getTimestamp("create_time") != null ? rs.getTimestamp("create_time").toLocalDateTime() : null); - d.setUpdater(rs.getString("updater")); - d.setUpdateTime(rs.getTimestamp("update_time") != null ? rs.getTimestamp("update_time").toLocalDateTime() : null); - d.setDeleted(rs.getBoolean("deleted")); - d.setTenantId(String.valueOf(rs.getLong("tenant_id"))); - d.setRuleId(rs.getLong("rule_id")); - return d; - }); - - allResults.addAll(deviceResults); +// // 添加INTERVAL(0)确保正确处理时间窗口 +// sql.append("INTERVAL(0) "); - } catch (Exception e) { - log.error("查询设备{}的最新记录失败", deviceId, e); - } + // 按设备ID排序 + sql.append("ORDER BY device_id"); + try { + return jdbcTemplate.query( + sql.toString(), + params.toArray(), + (rs, rowNum) -> { + DeviceOperationRecordDO d = new DeviceOperationRecordDO(); + d.setDeviceId(rs.getLong("device_id")); + d.setModelId(rs.getLong("model_id")); + d.setRule(rs.getString("rule")); + d.setAddressValue(rs.getString("address_value")); + d.setCreator(rs.getString("creator")); + d.setCreateTime(rs.getTimestamp("create_time") != null ? + rs.getTimestamp("create_time").toLocalDateTime() : null); + d.setUpdater(rs.getString("updater")); + d.setUpdateTime(rs.getTimestamp("update_time") != null ? + rs.getTimestamp("update_time").toLocalDateTime() : null); + d.setDeleted(rs.getBoolean("deleted")); + d.setTenantId(String.valueOf(rs.getLong("tenant_id"))); + d.setRuleId(rs.getLong("rule_id")); + return d; + }); + } catch (Exception e) { + log.error("查询设备最新记录失败,设备ID: {}, 错误: {}", deviceIds, e.getMessage(), e); + return Collections.emptyList(); } - - return allResults; } /** From 564726280b0af07ba780b8274bdb470d3cd6495d Mon Sep 17 00:00:00 2001 From: ck-chenkang Date: Wed, 29 Apr 2026 18:16:15 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E4=BA=A7=E5=93=81=E7=89=A9=E6=96=99?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E5=A2=9E=E5=8A=A0=E7=BC=96=E7=A0=81=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/vo/product/ErpProductPageReqVO.java | 5 ++++- .../erp/dal/mysql/product/ErpProductMapper.java | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java index 9b0b53b0b..03366d081 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java @@ -27,7 +27,10 @@ public class ErpProductPageReqVO extends PageParam { @Schema(description = "产品编号", example = "11161") private String code; + @Schema(description = "产品编码", example = "P-001") + private String barCode; + @Schema(description = "产品规格", example = "红色") private String standard; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java index 0a39d3189..a6508130b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java @@ -27,10 +27,17 @@ import java.util.List; @Mapper public interface ErpProductMapper extends BaseMapperX { + // 适配barCode和code两种情况 + default String resolveCode(ErpProductPageReqVO reqVO){ + String barCode = StringUtils.hasText(reqVO.getBarCode()) ? reqVO.getBarCode() : reqVO.getCode(); + return barCode; + } + default PageResult selectPage(ErpProductPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(ErpProductDO::getName, reqVO.getName()) - .likeIfPresent(ErpProductDO::getBarCode, reqVO.getCode()) + .likeIfPresent(ErpProductDO::getBarCode, resolveCode(reqVO)) .eqIfPresent(ErpProductDO::getCategoryId, reqVO.getCategoryId()) .betweenIfPresent(ErpProductDO::getCreateTime, reqVO.getCreateTime()) .orderByDesc(ErpProductDO::getId)); @@ -47,9 +54,10 @@ public interface ErpProductMapper extends BaseMapperX { } default PageResult selectProductCodeExist(ErpProductPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() .eqIfPresent(ErpProductDO::getName, reqVO.getName()) - .eqIfPresent(ErpProductDO::getBarCode, reqVO.getCode()) + .eqIfPresent(ErpProductDO::getBarCode, resolveCode(reqVO)) .orderByAsc(ErpProductDO::getId)); } @@ -62,9 +70,7 @@ public interface ErpProductMapper extends BaseMapperX { Long count = selectCount(new LambdaQueryWrapper() .eq(ErpProductDO::getName, reqVO.getName()) .eq(ErpProductDO::getStandard, reqVO.getStandard())); - return count > 0; - } default Long selectCountByCategoryId(Long categoryId) { From 5ca9c9112aba3274ae5527197078cc20a59df06e Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Wed, 6 May 2026 15:41:23 +0800 Subject: [PATCH 6/8] =?UTF-8?q?fix:=E6=B7=BB=E5=8A=A0=E6=8A=A5=E5=B7=A5?= =?UTF-8?q?=E6=95=B0=E3=80=81=E6=95=B0=E6=8D=AE=E9=87=87=E9=9B=86=E7=9A=84?= =?UTF-8?q?=E4=BA=A7=E9=87=8F=E6=8E=92=E4=BA=A7=E7=9A=84=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/service/device/TDengineService.java | 43 ++++- .../module/mes/enums/ErrorCodeConstants.java | 2 + .../deviceledger/enums/CapacityTypeEnum.java | 6 +- .../admin/task/vo/CapacityContext.java | 30 +++ .../task/vo/TaskOneClickScheduleReqVO.java | 2 +- .../task/vo/TaskOneClickScheduleRespVO.java | 6 +- .../admin/task/vo/TaskPageReqVO.java | 4 +- .../baogongrecord/BaogongRecordMapper.java | 5 + .../mes/service/task/TaskServiceImpl.java | 180 +++++++++++++++++- .../baogongrecord/BaogongRecordMapper.xml | 23 +++ 10 files changed, 287 insertions(+), 14 deletions(-) create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/CapacityContext.java diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java index 1461c7f34..d6e991f6e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java @@ -2599,6 +2599,47 @@ public class TDengineService { } } + @DS("tdengine") + public Map> queryDailyLatestCapacityValues(Collection deviceIds, + LocalDateTime beginTime, + LocalDateTime endTime) { + Map> result = new HashMap<>(); + if (deviceIds == null || deviceIds.isEmpty() || beginTime == null || endTime == null || !endTime.isAfter(beginTime)) { + return result; + } + + try { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT _wstart AS day_key, device_id, LAST(capacity_value) AS capacityvalue ") + .append("FROM besure_server.iot_device_capacity_record ") + .append("WHERE ts >= ? AND ts < ? AND device_id IN (") + .append(deviceIds.stream().map(id -> "?").collect(Collectors.joining(","))) + .append(") PARTITION BY device_id INTERVAL(1d)"); + + List params = new ArrayList<>(); + params.add(Timestamp.valueOf(beginTime)); + params.add(Timestamp.valueOf(endTime)); + params.addAll(deviceIds); + + jdbcTemplate.query(sql.toString(), params.toArray(), rs -> { + Long deviceId = rs.getLong("device_id"); + Timestamp dayTs = rs.getTimestamp("day_key"); + Double capacityValue = rs.getDouble("capacityvalue"); + if (rs.wasNull() || dayTs == null) { + return; + } + LocalDate day = dayTs.toLocalDateTime().toLocalDate(); + result.computeIfAbsent(deviceId, key -> new HashMap<>()) + .put(day, capacityValue); + }); + } catch (Exception e) { + log.error("TDengine查询每日最新容量值失败, deviceIds: {}, beginTime: {}, endTime: {}", + deviceIds, beginTime, endTime, e); + } + return result; + } + + // ========================= app报表相关接口 =================== @DS("tdengine") @@ -2704,4 +2745,4 @@ public class TDengineService { -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index d188a0123..07b20e9b0 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -194,6 +194,8 @@ public interface ErrorCodeConstants { ErrorCode SCHEDULE_WORK_HOURS_INVALID = new ErrorCode(100_301_0014, "排产工时非法,start={}, end={},可用工时必须大于0"); ErrorCode WAREHOUSE_NOT_EXISTS= new ErrorCode(100_301_0014, "仓库Id不能为空"); ErrorCode PLAN_RECORD_NOT_EXISTS = new ErrorCode(100_301_0015, "生产计划操作记录不存在"); + ErrorCode SCHEDULE_PRODUCT_DAILY_AVERAGE_ZERO = new ErrorCode(100_301_0016, "产品最近半年平均报工值为0,productId={},productCode={},productName={}"); + ErrorCode SCHEDULE_DEVICE_COLLECTION_CAPACITY_ZERO = new ErrorCode(100_301_0017, "设备最近半年数据采集产能为0,deviceId={},deviceName={}"); diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/deviceledger/enums/CapacityTypeEnum.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/deviceledger/enums/CapacityTypeEnum.java index 66240b285..e79000abd 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/deviceledger/enums/CapacityTypeEnum.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/deviceledger/enums/CapacityTypeEnum.java @@ -8,19 +8,19 @@ import lombok.Getter; @AllArgsConstructor public enum CapacityTypeEnum { - RATED(1, "额定产能") { + RATED(1, "计划产能") { @Override public Integer getCapacity(DeviceLedgerDO device) { return device.getRatedCapacity(); } }, - DAILY_AVERAGE(2, "每日报工平均值") { + DAILY_AVERAGE(2, "报工产能") { @Override public Integer getCapacity(DeviceLedgerDO device) { return device.getDailyAverageValue(); } }, - DATA_COLLECTION(3, "数据采集产能") { + DATA_COLLECTION(3, "实际产能") { @Override public Integer getCapacity(DeviceLedgerDO device) { return device.getDataCollectionCapacity(); diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/CapacityContext.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/CapacityContext.java new file mode 100644 index 000000000..60ed0290c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/CapacityContext.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.controller.admin.task.vo; + +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO; +import lombok.Data; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Data +public class CapacityContext { + private List statDays = new ArrayList<>(); + private Integer statDayCount = 0; + private Map productDailyAverageMap = new HashMap<>(); + private Map deviceCollectionAverageMap = new HashMap<>(); + private Map productCache = new HashMap<>(); + private Map deviceCache = new HashMap<>(); + + public Integer getProductDailyAverageCapacity(Long productId) { + return productDailyAverageMap.get(productId); + } + + public Integer getDeviceCollectionAverageCapacity(Long deviceId) { + return deviceCollectionAverageMap.get(deviceId); + } +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleReqVO.java index b40e2596b..bdf4f63e2 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleReqVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleReqVO.java @@ -29,7 +29,7 @@ public class TaskOneClickScheduleReqVO { @NotNull(message = "排序规则不能为空") private Integer sortRule; - @Schema(description = "产能来源:1-额定产能 2-每日报工平均值 3-数据采集产能", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "产能来源:1-计划产能 2-报工产能 3-实际产能", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "产能来源不能为空") private Integer capacityType; diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleRespVO.java index 1a1401692..630509085 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleRespVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleRespVO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.task.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; @@ -16,9 +17,12 @@ public class TaskOneClickScheduleRespVO { @Schema(description = "设备名称") private String deviceName; - @Schema(description = "设备额定产能") + @Schema(description = "产能") private Integer ratedCapacity; + @Schema(description = "产能来源:1-计划产能 2-报工产能 3-实际产能") + private Integer capacityType; + @Schema(description = "该设备排产计划") private List plans; diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskPageReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskPageReqVO.java index 849be1ac6..2e4abb863 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskPageReqVO.java @@ -22,11 +22,11 @@ public class TaskPageReqVO extends PageParam { private String code; @Schema(description = "下达日期") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] orderDate; @Schema(description = "交货日期") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] deliveryDate; @Schema(description = "状态", example = "2") diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/baogongrecord/BaogongRecordMapper.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/baogongrecord/BaogongRecordMapper.java index ce66ce18a..a49d58886 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/baogongrecord/BaogongRecordMapper.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/baogongrecord/BaogongRecordMapper.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; import cn.iocoder.yudao.module.mes.controller.admin.baogongrecord.vo.*; import org.apache.ibatis.annotations.Param; +import java.time.LocalDateTime; /** * 报工 Mapper @@ -43,4 +44,8 @@ public interface BaogongRecordMapper extends BaseMapperX { List selectTrendByHour(@Param("reqVO") BaogongRecordTrendReqVO reqVO); + List> selectProductDailyReportTotals(@Param("productIds") Collection productIds, + @Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + } diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java index 76c324142..7f7086a45 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.mes.service.task; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; @@ -15,16 +14,18 @@ import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; import cn.iocoder.yudao.module.erp.dal.mysql.productdevicerel.ProductDeviceRelMapper; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO; +import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper; import cn.iocoder.yudao.module.mes.controller.admin.deviceledger.enums.CapacityTypeEnum; import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanSaveReqVO; import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanStatusEnum; import cn.iocoder.yudao.module.mes.controller.admin.task.vo.*; -import cn.iocoder.yudao.module.mes.dal.dataobject.calholiday.CalHolidayDO; import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO; import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO; import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDO; import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.task.ViewTaskProductSummary; +import cn.iocoder.yudao.module.mes.dal.mysql.baogongrecord.BaogongRecordMapper; import cn.iocoder.yudao.module.mes.dal.mysql.calholiday.CalHolidayMapper; import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper; import cn.iocoder.yudao.module.mes.dal.mysql.plan.PlanMapper; @@ -33,6 +34,7 @@ import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskMapper; import cn.iocoder.yudao.module.mes.dal.mysql.task.ViewTaskProductSummaryMapper; import cn.iocoder.yudao.module.mes.dal.redis.no.MesNoRedisDAO; import cn.iocoder.yudao.module.mes.enums.BaogongTrendTypeEnum; +import cn.iocoder.yudao.module.iot.service.device.TDengineService; import cn.iocoder.yudao.module.mes.service.deviceledger.DeviceLedgerService; import cn.iocoder.yudao.module.mes.strategy.task.ScheduleSortStrategyFactory; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -84,6 +86,10 @@ public class TaskServiceImpl implements TaskService { @Resource private DeviceLedgerMapper deviceLedgerMapper; + @Resource + @Lazy + private DeviceMapper deviceMapper; + @Resource private ProductDeviceRelMapper productDeviceRelMapper; @@ -93,6 +99,13 @@ public class TaskServiceImpl implements TaskService { @Resource private CalHolidayMapper calHolidayMapper; + @Resource + private BaogongRecordMapper baogongRecordMapper; + + @Resource + private TDengineService tdengineService; + + @Resource private AutoCodeUtil autoCodeUtil; @Resource @@ -450,7 +463,6 @@ public class TaskServiceImpl implements TaskService { } @Override - @Transactional(rollbackFor = Exception.class) public List oneClickSchedule(TaskOneClickScheduleReqVO reqVO) { if (reqVO == null || CollUtil.isEmpty(reqVO.getCreateReqVO())) { return Collections.emptyList(); @@ -515,6 +527,8 @@ public class TaskServiceImpl implements TaskService { throw exception(UNSUPPORTED_CAPACITY_TYPE, reqVO.getCapacityType()); } + CapacityContext capacityContext = buildCapacityContext(sortedPlans, skipHoliday, capacityType); + DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @@ -538,7 +552,7 @@ public class TaskServiceImpl implements TaskService { List candidates = new ArrayList<>(); for (ProductRelationRespVO rel : deviceRels) { DeviceLedgerDO device = deviceLedgerMapper.selectById(rel.getId()); - Integer dailyCapacity = capacityType.getCapacity(device); // 每日产能 + Integer dailyCapacity = resolveCapacityValue(capacityType, device, item.getProductId(), rel.getId(), capacityContext); if (dailyCapacity == null || dailyCapacity <= 0) { continue; } @@ -554,7 +568,8 @@ public class TaskServiceImpl implements TaskService { c.setDeviceName(rel.getName()); c.setCapacityValue(dailyCapacity); c.setNextAvailableTime(nextAvailable); - candidates.add(c); } + candidates.add(c); + } if (CollUtil.isEmpty(candidates)) { throw exception(SCHEDULE_PRODUCT_DEVICE_UNAVAILABLE, item.getProductId()); @@ -592,6 +607,7 @@ public class TaskServiceImpl implements TaskService { vo.setDeviceId(chosen.getDeviceId()); vo.setDeviceName(chosen.getDeviceName()); vo.setRatedCapacity(chosen.getCapacityValue()); + vo.setCapacityType(reqVO.getCapacityType()); vo.setPlans(new ArrayList<>()); return vo; }); @@ -633,7 +649,8 @@ public class TaskServiceImpl implements TaskService { TaskOneClickScheduleRespVO vo = new TaskOneClickScheduleRespVO(); vo.setDeviceId(deviceId); vo.setDeviceName(device == null ? null : device.getDeviceName()); - vo.setRatedCapacity(capacityType.getCapacity(device)); // device为空时注意判空 +// vo.setRatedCapacity(resolveCapacityValue(capacityType, device, null, deviceId, capacityContext)); +// vo.setCapacityType(reqVO.getCapacityType()); vo.setPlans(new ArrayList<>()); return vo; }); @@ -854,6 +871,157 @@ public class TaskServiceImpl implements TaskService { return d; } + private Integer resolveCapacityValue(CapacityTypeEnum capacityType, DeviceLedgerDO device, + Long productId, Long deviceId, CapacityContext capacityContext) { + if (capacityType == CapacityTypeEnum.RATED) { + return device == null ? null : capacityType.getCapacity(device); + } + if (capacityContext == null) { + return null; + } + if (capacityType == CapacityTypeEnum.DAILY_AVERAGE) { + if (productId == null) { + return null; + } + Integer value = capacityContext.getProductDailyAverageCapacity(productId); + if (value == null || value <= 0) { + ErpProductDO product = capacityContext.getProductCache().get(productId); + throw exception(SCHEDULE_PRODUCT_DAILY_AVERAGE_ZERO, productId, + product == null ? null : product.getBarCode(), + product == null ? null : product.getName()); + } + return value; + } + if (capacityType == CapacityTypeEnum.DATA_COLLECTION) { + if (deviceId == null) { + return null; + } + Integer value = capacityContext.getDeviceCollectionAverageCapacity(deviceId); + if (value == null || value <= 0) { + DeviceDO deviceInfo = capacityContext.getDeviceCache().get(deviceId); + throw exception(SCHEDULE_DEVICE_COLLECTION_CAPACITY_ZERO, deviceId, + deviceInfo == null ? null : deviceInfo.getDeviceName()); + } + return value; + } + return device == null ? null : capacityType.getCapacity(device); + } + + private CapacityContext buildCapacityContext(List sortedPlans, boolean skipHoliday, + CapacityTypeEnum capacityType) { + CapacityContext context = new CapacityContext(); + if (CollUtil.isEmpty(sortedPlans)) { + return context; + } + + LocalDate endDate = LocalDate.now(); + LocalDate startDate = endDate.minusMonths(6).plusDays(1); + List statDays = listStatDays(startDate, endDate, skipHoliday); + context.setStatDays(statDays); + context.setStatDayCount(statDays.size()); + if (CollUtil.isEmpty(statDays)) { + return context; + } + + LocalDateTime beginTime = statDays.get(0).atStartOfDay(); + LocalDateTime endTime = statDays.get(statDays.size() - 1).plusDays(1).atStartOfDay(); + + if (capacityType == CapacityTypeEnum.DAILY_AVERAGE) { + Set productIds = sortedPlans.stream().map(PlanSaveReqVO::getProductId) + .filter(Objects::nonNull).collect(Collectors.toSet()); + if (CollUtil.isNotEmpty(productIds)) { + context.setProductCache(productIds.stream().collect(Collectors.toMap( + id -> id, + erpProductMapper::selectById, + (a, b) -> a + ))); + } + context.setProductDailyAverageMap(queryProductDailyAverageMap(productIds, statDays, beginTime, endTime)); + } else if (capacityType == CapacityTypeEnum.DATA_COLLECTION) { + + Set deviceIds = deviceMapper.selectList(new LambdaQueryWrapper() + .select(DeviceDO::getId)) + .stream() + .map(DeviceDO::getId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + + if (CollUtil.isNotEmpty(deviceIds)) { + context.setDeviceCache(deviceMapper.selectBatchIds(deviceIds).stream() + .filter(Objects::nonNull) + .collect(Collectors.toMap( + DeviceDO::getId, + device -> device, + (a, b) -> a + ))); + } + context.setDeviceCollectionAverageMap(queryDeviceCollectionAverageMap(deviceIds, statDays, beginTime, endTime)); + } + return context; + } + + private Map queryProductDailyAverageMap(Set productIds, List statDays, + LocalDateTime beginTime, LocalDateTime endTime) { + Map result = new HashMap<>(); + if (CollUtil.isEmpty(productIds) || CollUtil.isEmpty(statDays)) { + return result; + } + Set validDays = new HashSet<>(statDays); + List> rows = baogongRecordMapper.selectProductDailyReportTotals(productIds, beginTime, endTime); + Map productTotalMap = new HashMap<>(); + for (Map row : rows) { + Long productId = row.get("productId") == null ? null : Long.valueOf(String.valueOf(row.get("productId"))); + LocalDate day = row.get("day") == null ? null : LocalDate.parse(String.valueOf(row.get("day"))); + if (productId == null || day == null || !validDays.contains(day)) { + continue; + } + BigDecimal totalNum = new BigDecimal(String.valueOf(row.get("totalNum"))); + productTotalMap.merge(productId, totalNum, BigDecimal::add); + } + BigDecimal divisor = BigDecimal.valueOf(statDays.size()); + for (Long productId : productIds) { + BigDecimal total = productTotalMap.getOrDefault(productId, BigDecimal.ZERO); + result.put(productId, total.divide(divisor, 0, RoundingMode.HALF_UP).intValue()); + } + return result; + } + + private Map queryDeviceCollectionAverageMap(Set deviceIds, List statDays, + LocalDateTime beginTime, LocalDateTime endTime) { + Map result = new HashMap<>(); + if (CollUtil.isEmpty(deviceIds) || CollUtil.isEmpty(statDays)) { + return result; + } + Set validDays = new HashSet<>(statDays); + Map> rawMap = tdengineService.queryDailyLatestCapacityValues(deviceIds, beginTime, endTime); + BigDecimal divisor = BigDecimal.valueOf(statDays.size()); + for (Long deviceId : deviceIds) { + Map dayMap = rawMap.getOrDefault(deviceId, Collections.emptyMap()); + BigDecimal total = BigDecimal.ZERO; + for (Map.Entry entry : dayMap.entrySet()) { + if (entry.getKey() == null || entry.getValue() == null || !validDays.contains(entry.getKey())) { + continue; + } + total = total.add(BigDecimal.valueOf(entry.getValue())); + } + result.put(deviceId, total.divide(divisor, 0, RoundingMode.HALF_UP).intValue()); + } + return result; + } + + private List listStatDays(LocalDate startDate, LocalDate endDate, boolean skipHoliday) { + List days = new ArrayList<>(); + LocalDate cursor = startDate; + while (!cursor.isAfter(endDate)) { + if (!skipHoliday || isWorkingDay(cursor)) { + days.add(cursor); + } + cursor = cursor.plusDays(1); + } + return days; + } + private Set queryDeviceIdsFromCurrentMonth() { LocalDateTime monthStart = LocalDate.now().withDayOfMonth(1).atStartOfDay(); List plans = planMapper.selectList(new LambdaQueryWrapper() diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/resources/mapper/baogongrecord/BaogongRecordMapper.xml b/yudao-module-mes/yudao-module-mes-biz/src/main/resources/mapper/baogongrecord/BaogongRecordMapper.xml index 26f0b1a83..91d4f1692 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/resources/mapper/baogongrecord/BaogongRecordMapper.xml +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/resources/mapper/baogongrecord/BaogongRecordMapper.xml @@ -195,4 +195,27 @@ ORDER BY h.day ASC + + From 4dc54fcbc861eca669a62b57ef91040f4d747643 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Wed, 6 May 2026 17:00:20 +0800 Subject: [PATCH 7/8] =?UTF-8?q?fix:=E6=B7=BB=E5=8A=A0=E6=8A=A5=E5=B7=A5?= =?UTF-8?q?=E4=BA=A7=E8=83=BD=E5=9B=9E=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/mapper/product/ErpProductMapper.xml | 4 ++-- .../admin/task/vo/TaskOneClickScheduleRespVO.java | 6 ++++++ .../yudao/module/mes/service/task/TaskServiceImpl.java | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductMapper.xml index 78c34dd1f..e6c5c1889 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductMapper.xml +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductMapper.xml @@ -24,8 +24,8 @@ SELECT DISTINCT rel.device_id AS id, CASE - WHEN d.id IS NULL THEN CONCAT('设备[', rel.device_id, ']【已删除】') - WHEN d.deleted = b'1' THEN CONCAT(d.device_name, '(', d.device_code, ')【已删除】') + WHEN d.id IS NULL THEN CONCAT('设备[', rel.device_id, '](已被删除)') + WHEN d.deleted = b'1' THEN CONCAT(d.device_name, '(', d.device_code, ')(已被删除)') ELSE CONCAT(d.device_name, '(', d.device_code, ')') END AS name FROM erp_product_device_rel rel diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleRespVO.java index 630509085..2e9f7d3dd 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleRespVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskOneClickScheduleRespVO.java @@ -48,6 +48,12 @@ public class TaskOneClickScheduleRespVO { @Schema(description = "计划数量", example = "1200") private Long planNumber; + @Schema(description = "产能") + private Integer ratedCapacity; + + @Schema(description = "产能来源:1-计划产能 2-报工产能 3-实际产能") + private Integer capacityType; + // @Schema(description = "计划开始时间") // private LocalDateTime planStartTime; // diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java index 7f7086a45..da9f7bfc0 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java @@ -621,6 +621,8 @@ public class TaskServiceImpl implements TaskService { p.setTaskDetailId(item.getTaskDetailId()); p.setPlanNumber(item.getPlanNumber()); p.setSourceType("CURRENT"); + p.setRatedCapacity(chosen.getCapacityValue()); + p.setCapacityType(reqVO.getCapacityType()); p.setTaskCode(taskDO == null ? null : taskDO.getCode()); p.setProductCode(productDO == null ? null : productDO.getBarCode()); p.setProductName(productDO == null ? null : productDO.getName()); From 000aa526e8ddb03ac74444f97e0db6cda1a078bc Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Wed, 6 May 2026 18:00:01 +0800 Subject: [PATCH 8/8] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E9=87=87=E9=9B=86?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E4=BA=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/mes/enums/ErrorCodeConstants.java | 4 +- .../mes/service/task/TaskServiceImpl.java | 65 +++++++++++++++++-- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index 07b20e9b0..ed9942634 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -195,7 +195,9 @@ public interface ErrorCodeConstants { ErrorCode WAREHOUSE_NOT_EXISTS= new ErrorCode(100_301_0014, "仓库Id不能为空"); ErrorCode PLAN_RECORD_NOT_EXISTS = new ErrorCode(100_301_0015, "生产计划操作记录不存在"); ErrorCode SCHEDULE_PRODUCT_DAILY_AVERAGE_ZERO = new ErrorCode(100_301_0016, "产品最近半年平均报工值为0,productId={},productCode={},productName={}"); - ErrorCode SCHEDULE_DEVICE_COLLECTION_CAPACITY_ZERO = new ErrorCode(100_301_0017, "设备最近半年数据采集产能为0,deviceId={},deviceName={}"); + ErrorCode SCHEDULE_DEVICE_COLLECTION_CAPACITY_ZERO = new ErrorCode(100_301_0017, "{}-{},设备最近半年数据采集产能为0,deviceId={},deviceName={}"); + ErrorCode SCHEDULE_DEVICE_ORGANIZATION_NOT_FOUND = new ErrorCode(100_301_0018, "{}-{},设备未关联产线工位,deviceId={},deviceName={}"); + ErrorCode SCHEDULE_DEVICE_COLLECTION_MAPPING_MISSING = new ErrorCode(100_301_0019, "{}-{},设备未关联采集设备,deviceId={},deviceName={}"); diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java index da9f7bfc0..121447ecc 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanSaveReqVO; import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanStatusEnum; import cn.iocoder.yudao.module.mes.controller.admin.task.vo.*; import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.organization.OrganizationDO; import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO; import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDO; import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDetailDO; @@ -28,6 +29,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.task.ViewTaskProductSummary; import cn.iocoder.yudao.module.mes.dal.mysql.baogongrecord.BaogongRecordMapper; import cn.iocoder.yudao.module.mes.dal.mysql.calholiday.CalHolidayMapper; import cn.iocoder.yudao.module.mes.dal.mysql.deviceledger.DeviceLedgerMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.organization.OrganizationMapper; import cn.iocoder.yudao.module.mes.dal.mysql.plan.PlanMapper; import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskDetailMapper; import cn.iocoder.yudao.module.mes.dal.mysql.task.TaskMapper; @@ -86,6 +88,9 @@ public class TaskServiceImpl implements TaskService { @Resource private DeviceLedgerMapper deviceLedgerMapper; + @Resource + private OrganizationMapper organizationMapper; + @Resource @Lazy private DeviceMapper deviceMapper; @@ -552,7 +557,7 @@ public class TaskServiceImpl implements TaskService { List candidates = new ArrayList<>(); for (ProductRelationRespVO rel : deviceRels) { DeviceLedgerDO device = deviceLedgerMapper.selectById(rel.getId()); - Integer dailyCapacity = resolveCapacityValue(capacityType, device, item.getProductId(), rel.getId(), capacityContext); + Integer dailyCapacity = resolveCapacityValue(capacityType, device, item.getProductId(), rel.getId(), item.getPlanNumber(), capacityContext); if (dailyCapacity == null || dailyCapacity <= 0) { continue; } @@ -874,7 +879,7 @@ public class TaskServiceImpl implements TaskService { } private Integer resolveCapacityValue(CapacityTypeEnum capacityType, DeviceLedgerDO device, - Long productId, Long deviceId, CapacityContext capacityContext) { + Long productId, Long deviceId, Long planNumber, CapacityContext capacityContext) { if (capacityType == CapacityTypeEnum.RATED) { return device == null ? null : capacityType.getCapacity(device); } @@ -898,17 +903,65 @@ public class TaskServiceImpl implements TaskService { if (deviceId == null) { return null; } - Integer value = capacityContext.getDeviceCollectionAverageCapacity(deviceId); + DeviceLedgerDO ledger = device != null ? device : deviceLedgerMapper.selectById(deviceId); + String deviceName = ledger == null ? null : ledger.getDeviceName(); + Long collectDeviceId = resolveCollectDeviceId(deviceId, deviceName, productId, planNumber); + Integer value = capacityContext.getDeviceCollectionAverageCapacity(collectDeviceId); if (value == null || value <= 0) { - DeviceDO deviceInfo = capacityContext.getDeviceCache().get(deviceId); - throw exception(SCHEDULE_DEVICE_COLLECTION_CAPACITY_ZERO, deviceId, - deviceInfo == null ? null : deviceInfo.getDeviceName()); + DeviceDO deviceInfo = queryCollectDeviceWithDeleted(collectDeviceId); + ErpProductDO product = productId == null ? null : erpProductMapper.selectById(productId); + throw exception(SCHEDULE_DEVICE_COLLECTION_CAPACITY_ZERO, + product == null ? null : product.getName(), + planNumber, + collectDeviceId, + buildCollectDeviceName(deviceInfo)); } return value; } return device == null ? null : capacityType.getCapacity(device); } + private Long resolveCollectDeviceId(Long machineId, String deviceName, Long productId, Long planNumber) { + OrganizationDO organization = organizationMapper.selectOne( + new LambdaQueryWrapper() + .eq(OrganizationDO::getMachineId, machineId) + .last("limit 1")); + ErpProductDO product = productId == null ? null : erpProductMapper.selectById(productId); + if (organization == null) { + throw exception(SCHEDULE_DEVICE_ORGANIZATION_NOT_FOUND, + product == null ? null : product.getName(), + planNumber, + machineId, + deviceName); + } + if (organization.getDvId() == null) { + throw exception(SCHEDULE_DEVICE_COLLECTION_MAPPING_MISSING, + product == null ? null : product.getName(), + planNumber, + machineId, + deviceName); + } + return organization.getDvId(); + } + + private DeviceDO queryCollectDeviceWithDeleted(Long collectDeviceId) { + if (collectDeviceId == null) { + return null; + } + return deviceMapper.selectByIdWithDeleted(collectDeviceId); + } + + private String buildCollectDeviceName(DeviceDO deviceInfo) { + if (deviceInfo == null) { + return null; + } + String deviceName = deviceInfo.getDeviceName(); + if (Boolean.TRUE.equals(deviceInfo.getDeleted())) { + return StringUtils.defaultString(deviceName) + "(已被删除)"; + } + return deviceName; + } + private CapacityContext buildCapacityContext(List sortedPlans, boolean skipHoliday, CapacityTypeEnum capacityType) { CapacityContext context = new CapacityContext();