main-business/src/main/java/com/ruoyi/business/controller/EquipmentUsageDetailController.java
@@ -1,19 +1,14 @@ package com.ruoyi.business.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.business.dto.EquipmentManagementDto; import com.ruoyi.business.dto.EquipmentUsageDetailDto; import com.ruoyi.business.entity.EquipmentManagement; import com.ruoyi.business.entity.EquipmentUsageDetail; import com.ruoyi.business.mapper.EquipmentUsageDetailMapper; import com.ruoyi.business.service.EquipmentManagementService; import com.ruoyi.business.service.EquipmentUsageDetailService; import com.ruoyi.common.core.domain.R; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * <p> @@ -35,8 +30,8 @@ * 设备领用归还记录查询 */ @GetMapping("/list") public R<IPage<EquipmentUsageDetailDto>> list(Page<EquipmentUsageDetail> page,EquipmentUsageDetailDto equipmentUsageDetailDto) { IPage<EquipmentUsageDetailDto> list = equipmentUsageDetailService.selectEquipmentUsageDetailList(page,equipmentUsageDetailDto); public R<List<EquipmentUsageDetailDto>> list(EquipmentUsageDetailDto equipmentUsageDetailDto) { List<EquipmentUsageDetailDto> list = equipmentUsageDetailService.selectEquipmentUsageDetailList(equipmentUsageDetailDto); return R.ok(list); } main-business/src/main/java/com/ruoyi/business/entity/EquipmentManagement.java
@@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import com.ruoyi.common.core.domain.MyBaseEntity; @@ -80,5 +81,6 @@ * 是否耗材类 */ @TableField(value = "is_consumables") @JsonProperty("isConsumables") private boolean isConsumables; } main-business/src/main/java/com/ruoyi/business/entity/SalesRecord.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.core.domain.MyBaseEntity; import lombok.Data; @@ -131,5 +132,6 @@ * 是否添加至待补库 */ @TableField(value = "is_add") @JsonProperty("isAdd") private boolean isAdd; } main-business/src/main/java/com/ruoyi/business/service/EquipmentUsageDetailService.java
@@ -1,10 +1,10 @@ package com.ruoyi.business.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.business.dto.EquipmentUsageDetailDto; import com.ruoyi.business.entity.EquipmentUsageDetail; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; /** * <p> @@ -16,5 +16,5 @@ */ public interface EquipmentUsageDetailService extends IService<EquipmentUsageDetail> { IPage<EquipmentUsageDetailDto> selectEquipmentUsageDetailList(Page<EquipmentUsageDetail> page, EquipmentUsageDetailDto equipmentUsageDetailDto); List<EquipmentUsageDetailDto> selectEquipmentUsageDetailList(EquipmentUsageDetailDto equipmentUsageDetailDto); } main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentManagementServiceImpl.java
@@ -3,23 +3,22 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.business.dto.EquipmentManagementDto; import com.ruoyi.business.entity.EquipmentManagement; import com.ruoyi.business.entity.EquipmentUsageRecord; import com.ruoyi.business.mapper.EquipmentManagementMapper; import com.ruoyi.business.mapper.EquipmentUsageRecordMapper; import com.ruoyi.business.service.EquipmentManagementService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.business.vo.EquipmentManagementVo; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import java.beans.Transient; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -108,6 +107,7 @@ vo.setId(equipment.getId()); // 设备id vo.setEquipmentName(equipment.getEquipmentName()); // 设备名称 vo.setQuantity(equipment.getQuantity()); // 数量 vo.setConsumables(equipment.isConsumables()); // 是否耗材类 return vo; }) .toList(); main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentUsageDetailServiceImpl.java
@@ -1,9 +1,7 @@ package com.ruoyi.business.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.business.dto.EquipmentManagementDto; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.business.dto.EquipmentUsageDetailDto; import com.ruoyi.business.entity.EquipmentManagement; import com.ruoyi.business.entity.EquipmentUsageDetail; @@ -11,14 +9,11 @@ import com.ruoyi.business.mapper.EquipmentManagementMapper; import com.ruoyi.business.mapper.EquipmentUsageDetailMapper; import com.ruoyi.business.mapper.EquipmentUsageRecordMapper; import com.ruoyi.business.service.EquipmentManagementService; import com.ruoyi.business.service.EquipmentUsageDetailService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.business.service.EquipmentUsageRecordService; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.bean.BeanUtils; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.HashMap; @@ -47,72 +42,70 @@ @Override public IPage<EquipmentUsageDetailDto> selectEquipmentUsageDetailList(Page<EquipmentUsageDetail> page,EquipmentUsageDetailDto equipmentUsageDetailDto) { // 必须传递usageId参数 public List<EquipmentUsageDetailDto> selectEquipmentUsageDetailList(EquipmentUsageDetailDto equipmentUsageDetailDto) { // 必须传递 usageId 参数 if (equipmentUsageDetailDto.getUsageId() == null) { throw new BaseException("请选择使用记录"); } // 查询明细列表(不分页) LambdaQueryWrapper<EquipmentUsageDetail> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(EquipmentUsageDetail::getUsageId, equipmentUsageDetailDto.getUsageId()); List<EquipmentUsageDetail> details = equipmentUsageDetailMapper.selectList(queryWrapper); Page<EquipmentUsageDetail> entityPage = equipmentUsageDetailMapper.selectPage(page, queryWrapper); IPage<EquipmentUsageDetailDto> dtoPage = new Page<>(); BeanUtils.copyProperties(entityPage, dtoPage); // 先获取主表记录 List<Long> usageIds = entityPage.getRecords().stream() // 如果没有数据,直接返回空列表 if (details.isEmpty()) { return Collections.emptyList(); } // 获取所有关联的 usageId List<Long> usageIds = details.stream() .map(EquipmentUsageDetail::getUsageId) .distinct() .collect(Collectors.toList()); if (!usageIds.isEmpty()) { // 查询关联的使用记录 List<EquipmentUsageRecord> usageRecords = equipmentUsageRecordMapper.selectList( new LambdaQueryWrapper<EquipmentUsageRecord>() .in(EquipmentUsageRecord::getId, usageIds) ); // 查询关联的使用记录 List<EquipmentUsageRecord> usageRecords = equipmentUsageRecordMapper.selectList( new LambdaQueryWrapper<EquipmentUsageRecord>() .in(EquipmentUsageRecord::getId, usageIds) ); // 获取所有设备ID List<Long> equipmentIds = usageRecords.stream() .map(EquipmentUsageRecord::getEquipmentId) .distinct() .collect(Collectors.toList()); // 获取所有设备ID List<Long> equipmentIds = usageRecords.stream() .map(EquipmentUsageRecord::getEquipmentId) .distinct() .collect(Collectors.toList()); // 查询设备信息 Map<Long, EquipmentManagement> equipmentMap; if (!equipmentIds.isEmpty()) { equipmentMap = equipmentManagementMapper.selectList( new LambdaQueryWrapper<EquipmentManagement>() .in(EquipmentManagement::getId, equipmentIds) ).stream().collect(Collectors.toMap(EquipmentManagement::getId, Function.identity())); } else { equipmentMap = new HashMap<>(); // 查询设备信息 Map<Long, EquipmentManagement> equipmentMap; if (!equipmentIds.isEmpty()) { equipmentMap = equipmentManagementMapper.selectList( new LambdaQueryWrapper<EquipmentManagement>() .in(EquipmentManagement::getId, equipmentIds) ).stream().collect(Collectors.toMap(EquipmentManagement::getId, Function.identity())); } else { equipmentMap = new HashMap<>(); } // 构建 usageId → equipmentId 的映射 Map<Long, Long> usageIdToEquipmentIdMap = usageRecords.stream() .collect(Collectors.toMap(EquipmentUsageRecord::getId, EquipmentUsageRecord::getEquipmentId)); // 转换为 DTO 并填充设备信息 return details.stream().map(detail -> { EquipmentUsageDetailDto detailDto = new EquipmentUsageDetailDto(); BeanUtils.copyProperties(detail, detailDto); // 获取关联的设备信息 Long equipmentId = usageIdToEquipmentIdMap.get(detail.getUsageId()); if (equipmentId != null && equipmentMap.containsKey(equipmentId)) { EquipmentManagement equipment = equipmentMap.get(equipmentId); detailDto.setEquipmentNo(equipment.getEquipmentNo()); detailDto.setEquipmentName(equipment.getEquipmentName()); detailDto.setSpecification(equipment.getSpecification()); } // 构建使用记录ID到设备ID的映射 Map<Long, Long> usageIdToEquipmentIdMap = usageRecords.stream() .collect(Collectors.toMap(EquipmentUsageRecord::getId, EquipmentUsageRecord::getEquipmentId)); // 转换DTO并填充设备信息 List<EquipmentUsageDetailDto> dtoList = entityPage.getRecords().stream().map(detail -> { EquipmentUsageDetailDto detailDto = new EquipmentUsageDetailDto(); BeanUtils.copyProperties(detail, detailDto); // 获取关联的设备ID Long equipmentId = usageIdToEquipmentIdMap.get(detail.getUsageId()); if (equipmentId != null && equipmentMap.containsKey(equipmentId)) { EquipmentManagement equipment = equipmentMap.get(equipmentId); detailDto.setEquipmentNo(equipment.getEquipmentNo()); detailDto.setEquipmentName(equipment.getEquipmentName()); detailDto.setSpecification(equipment.getSpecification()); } return detailDto; }).collect(Collectors.toList()); dtoPage.setRecords(dtoList); } else { dtoPage.setRecords(Collections.emptyList()); } return dtoPage; return detailDto; }).collect(Collectors.toList()); } } main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentUsageRecordServiceImpl.java
@@ -3,9 +3,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.basic.entity.Supply; import com.ruoyi.basic.mapper.CoalInfoMapper; import com.ruoyi.business.dto.EquipmentManagementDto; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.business.dto.EquipmentUsageRecordDto; import com.ruoyi.business.entity.EquipmentManagement; import com.ruoyi.business.entity.EquipmentUsageDetail; @@ -14,12 +12,11 @@ import com.ruoyi.business.mapper.EquipmentUsageDetailMapper; import com.ruoyi.business.mapper.EquipmentUsageRecordMapper; import com.ruoyi.business.service.EquipmentUsageRecordService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.system.mapper.SysUserMapper; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; @@ -133,7 +130,7 @@ } // 处理归还逻辑 if (equipmentUsageRecordDto.getEquipmentStatus() == 2) { if (equipmentUsageRecordDto.getEquipmentStatus() != 1) { result = handleReturnOperation(equipmentUsageRecordDto, equipment, originalRecord, userId, username); } else { // 处理普通编辑逻辑(非归还状态) @@ -173,7 +170,7 @@ private int handleReturnOperation(EquipmentUsageRecordDto dto, EquipmentManagement equipment, EquipmentUsageRecord originalRecord, Long userId, String username) { // 获取本次归还数量 // 校验归还数量 Integer returnQuantity = dto.getReturnQuantity(); if (returnQuantity == null || returnQuantity <= 0) { throw new RuntimeException("归还数量必须大于0"); @@ -185,18 +182,19 @@ throw new RuntimeException("归还数量不能超过未归还数量,剩余未归还数量:" + remainingQuantity); } // 更新主记录 // 准备更新记录 EquipmentUsageRecord updateRecord = new EquipmentUsageRecord(); updateRecord.setId(originalRecord.getId()); updateRecord.setReturnQuantity(originalRecord.getReturnQuantity() + returnQuantity); updateRecord.setEquipmentStatus(2); // 已归还状态 updateRecord.setUsageEndTime(LocalDate.now()); // 如果全部归还,更新状态和时间 // if (updateRecord.getReturnQuantity().equals(originalRecord.getUsageQuantity())) { // // } int newReturnQuantity = originalRecord.getReturnQuantity() + returnQuantity; updateRecord.setReturnQuantity(newReturnQuantity); // 恢复库存 // 判断是否全部归还 boolean isFullReturn = newReturnQuantity == originalRecord.getUsageQuantity(); int newStatus = isFullReturn ? 3 : 2; // 3表示全部归还,2表示部分归还 updateRecord.setEquipmentStatus(newStatus); updateRecord.setUsageEndTime(LocalDate.now()); // 恢复库存数量 equipment.setQuantity(equipment.getQuantity() + returnQuantity); equipmentManagementMapper.updateById(equipment); @@ -205,10 +203,11 @@ // 保存归还明细记录 if (result > 0) { String remark = "设备归还" + (updateRecord.getEquipmentStatus() == 2 ? "(全部归还)" : "(部分归还)"); saveUsageDetail(originalRecord.getId(), originalRecord.getEquipmentId(), 2, returnQuantity, userId, username, remark); String remark = isFullReturn ? "设备归还(全部归还)" : "设备归还(部分归还)"; int operationType = isFullReturn ? 3 : 2; // 与主记录状态保持一致 saveUsageDetail(originalRecord.getId(), originalRecord.getEquipmentId(), operationType, returnQuantity, userId, username, remark); } return result; } main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java
@@ -9,7 +9,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.entity.CoalInfo; import com.ruoyi.basic.entity.Customer; import com.ruoyi.basic.entity.Supply; import com.ruoyi.basic.mapper.CoalInfoMapper; import com.ruoyi.basic.mapper.CustomerMapper; import com.ruoyi.business.dto.SalesRecordDto; @@ -40,13 +39,9 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAdjusters; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.*; /** * <p> @@ -153,23 +148,20 @@ // 参数校验 validateSalesRecordDto(salesRecordDto); // 更新正式库待补库数量 // 获取煤种库存信息 OfficialInventory officialInventory = officialInventoryMapper.selectById(salesRecordDto.getCoalId()); if (officialInventory == null) { throw new BaseException("正式库煤种信息不存在"); } if (salesRecordDto.getSaleQuantity().compareTo(officialInventory.getInventoryQuantity()) > 0) { throw new BaseException("销售数量不能大于库存数量"); } officialInventory.setInventoryQuantity(officialInventory.getInventoryQuantity().subtract(salesRecordDto.getSaleQuantity())); if (salesRecordDto.isAdd()){ officialInventory.setPendingReplenishment(salesRecordDto.getSaleQuantity()); } officialInventoryMapper.updateById(officialInventory); // 处理销售数量变更逻辑 SalesRecord existingRecord = salesRecordDto.getId() == null ? null : salesRecordMapper.selectById(salesRecordDto.getId()); handleQuantityChanges(salesRecordDto, officialInventory, existingRecord); // 构建销售记录实体 SalesRecord salesRecord = buildSalesRecord(salesRecordDto, officialInventory.getCoalId()); // 设置销售记录中的库存数量 salesRecord.setInventoryQuantity(officialInventory.getInventoryQuantity()); // 处理新增/更新逻辑 if (salesRecordDto.getId() == null) { @@ -179,18 +171,52 @@ } } private void validateSalesRecordDto(SalesRecordDto dto) { if (dto == null) { throw new BaseException("销售记录数据不能为空"); private void handleQuantityChanges(SalesRecordDto dto, OfficialInventory officialInventory, SalesRecord existingRecord) { if (existingRecord == null) { // 新增记录 if (dto.getSaleQuantity().compareTo(officialInventory.getInventoryQuantity()) > 0) { throw new BaseException("销售数量不能大于库存数量"); } // 更新库存数量 officialInventory.setInventoryQuantity(officialInventory.getInventoryQuantity().subtract(dto.getSaleQuantity())); // 设置待补库数量 if (dto.isAdd()) { officialInventory.setPendingReplenishment( officialInventory.getPendingReplenishment() == null ? dto.getSaleQuantity() : officialInventory.getPendingReplenishment().add(dto.getSaleQuantity()) ); } } else { // 更新记录 // 比较销售数量是否有变化 int quantityComparison = dto.getSaleQuantity().compareTo(existingRecord.getSaleQuantity()); if (quantityComparison != 0) { // 计算数量差值 BigDecimal quantityDiff = dto.getSaleQuantity().subtract(existingRecord.getSaleQuantity()); // 检查新数量是否会导致库存不足 if (quantityComparison > 0 && quantityDiff.compareTo(officialInventory.getInventoryQuantity()) > 0) { throw new BaseException("销售数量增加后不能大于库存数量"); } // 更新库存数量 officialInventory.setInventoryQuantity(officialInventory.getInventoryQuantity().subtract(quantityDiff)); // 更新待补库数量(如果是需要补库的记录) if (dto.isAdd()) { BigDecimal pendingDiff = officialInventory.getPendingReplenishment() == null ? quantityDiff : officialInventory.getPendingReplenishment().add(quantityDiff); officialInventory.setPendingReplenishment(pendingDiff); } } } if (dto.getRegistrantId() == null) { throw new BaseException("登记人ID不能为空"); } if (dto.getCustomerId() == null) { throw new BaseException("客户ID不能为空"); } if (dto.getCoalId() == null) { throw new BaseException("请选择一条煤种信息"); // 更新库存记录 int updateResult = officialInventoryMapper.updateById(officialInventory); if (updateResult <= 0) { throw new BaseException("库存更新失败"); } } @@ -234,6 +260,21 @@ return record; } private void validateSalesRecordDto(SalesRecordDto dto) { if (dto == null) { throw new BaseException("销售记录数据不能为空"); } if (dto.getRegistrantId() == null) { throw new BaseException("登记人ID不能为空"); } if (dto.getCustomerId() == null) { throw new BaseException("客户ID不能为空"); } if (dto.getCoalId() == null) { throw new BaseException("请选择一条煤种信息"); } } private int insertSalesRecord(SalesRecord record) { int result = salesRecordMapper.insert(record); if (result <= 0) { main-business/src/main/java/com/ruoyi/business/vo/EquipmentManagementVo.java
@@ -1,5 +1,6 @@ package com.ruoyi.business.vo; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @Data @@ -10,4 +11,7 @@ private String equipmentName; //设备名称 private Integer quantity; //数量 @JsonProperty("isConsumables") private boolean isConsumables; //是否耗材类 }