basic-server/src/main/java/com/ruoyi/basic/dto/CoalFieldDto.java
@@ -6,15 +6,5 @@ @Data public class CoalFieldDto extends CoalField { private String fieldName; public CoalFieldDto(String name) { this.fieldName = name; } public static CoalFieldDto from(String name) { return new CoalFieldDto(name); } private String searchAll; } basic-server/src/main/java/com/ruoyi/basic/mapper/CoalFieldMapper.java
@@ -4,6 +4,7 @@ import com.ruoyi.basic.entity.CoalField; import org.apache.ibatis.annotations.Mapper; import java.util.List; import java.util.Set; /** @@ -18,4 +19,6 @@ public interface CoalFieldMapper extends BaseMapper<CoalField> { Set<String> getFieldNamesByNames(Set<String> fieldNames); List<CoalField> getFieldsByNames(Set<String> filteredNames); } basic-server/src/main/java/com/ruoyi/basic/mapper/CoalPlanMapper.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.basic.entity.CoalPlan; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * <p> @@ -15,4 +16,5 @@ @Mapper public interface CoalPlanMapper extends BaseMapper<CoalPlan> { int existsFieldIds(@Param("fieldIds") String fieldIds); } basic-server/src/main/java/com/ruoyi/basic/service/CoalFieldService.java
@@ -28,4 +28,6 @@ List<CoalField> selectAllList(CoalFieldDto coalFieldDto); Set<String> getFieldNamesByNames(Set<String> collect); List<CoalFieldDto> getFieldsByNames(Set<String> fieldNames); } basic-server/src/main/java/com/ruoyi/basic/service/CoalPlanService.java
@@ -28,4 +28,6 @@ List<CoalPlan> selectAllList(); List<CoalFieldVo> selectCoalPlanById(Long id); boolean checkPlanExists(String fieldIds); } basic-server/src/main/java/com/ruoyi/basic/service/impl/CoalFieldServiceImpl.java
@@ -9,16 +9,19 @@ import com.ruoyi.basic.entity.CoalField; import com.ruoyi.basic.mapper.CoalFieldMapper; import com.ruoyi.basic.service.CoalFieldService; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.bean.BeanUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * <p> @@ -82,6 +85,44 @@ } @Override public List<CoalFieldDto> getFieldsByNames(Set<String> fieldNames) { // 1. 参数校验 if (fieldNames == null || fieldNames.isEmpty()) { throw new IllegalArgumentException("字段名集合不能为空"); } // 2. 过滤空值 Set<String> filteredNames = fieldNames.stream() .filter(name -> name != null && !name.trim().isEmpty()) .collect(Collectors.toSet()); if (filteredNames.isEmpty()) { return Collections.emptyList(); } // 3. 查询数据库 try { List<CoalField> entities = coalFieldMapper.getFieldsByNames(filteredNames); // 4. 实体转DTO return entities.stream() .map(this::convertToDto) .collect(Collectors.toList()); } catch (Exception e) { throw new BaseException("查询煤质字段信息失败,请稍后重试"); } } private CoalFieldDto convertToDto(CoalField entity) { CoalFieldDto dto = new CoalFieldDto(); dto.setId(entity.getId()); dto.setFields(entity.getFields()); dto.setFieldName(entity.getFieldName()); return dto; } @Override public Set<String> getFieldNamesByNames(Set<String> fieldNames) { return coalFieldMapper.getFieldNamesByNames(fieldNames); } basic-server/src/main/java/com/ruoyi/basic/service/impl/CoalPlanServiceImpl.java
@@ -78,6 +78,16 @@ } @Override public boolean checkPlanExists(String fieldIds) { if (StringUtils.isBlank(fieldIds)) { return false; } // 查询数据库 return coalPlanMapper.existsFieldIds(fieldIds) > 0; } @Override public List<CoalFieldVo> selectCoalPlanById(Long id) { CoalPlan coalPlan = coalPlanMapper.selectById(id); LambdaQueryWrapper<CoalField> coalFieldLambdaQueryWrapper = new LambdaQueryWrapper<>(); basic-server/src/main/resources/mapper/CoalFieldMapper.xml
@@ -27,7 +27,20 @@ <select id="getFieldNamesByNames" resultType="java.lang.String"> SELECT field_name FROM coal_field WHERE field_name IN <foreach collection="fieldNames" item="name" open="(" separator="," close=")"> #{fieldNames} #{name} </foreach> </select> <select id="getFieldsByNames" resultType="com.ruoyi.basic.entity.CoalField"> SELECT id, field_name AS fieldName, fields AS fields FROM coal_field WHERE field_name IN <foreach collection="filteredNames" item="name" open="(" separator="," close=")"> #{name} </foreach> </select> basic-server/src/main/resources/mapper/CoalPlanMapper.xml
@@ -11,8 +11,9 @@ <result column="update_by" property="updateBy" /> <result column="update_time" property="updateTime" /> <result column="plan" property="plan" /> <result column="coal_field_id" property="coalFieldId" /> <result column="field_names" property="fieldNames" /> <result column="coal_fields" property="coalFields" /> <result column="field_ids" property="fieldIds" /> <result column="scheme_desc" property="schemeDesc" /> </resultMap> <!-- 通用查询结果列 --> @@ -24,5 +25,11 @@ update_time, id, plan, coal_field_id, field_names </sql> <select id="existsFieldIds" resultType="java.lang.Integer"> SELECT COUNT(1) FROM coal_plan WHERE field_ids = #{fieldIds} AND deleted = 0 </select> </mapper> main-business/src/main/java/com/ruoyi/business/controller/OfficialInventoryController.java
@@ -69,4 +69,11 @@ return R.ok(officialInventoryService.mergeAll(officialInventoryDto)); } /** * 配煤计算器选择list */ @GetMapping("/coalBlendingList") public R<List<OfficialInventoryDto>> coalBlendingList() { return R.ok(officialInventoryService.coalBlendingList()); } } main-business/src/main/java/com/ruoyi/business/dto/OfficialInventoryDto.java
@@ -1,5 +1,6 @@ package com.ruoyi.business.dto; import com.ruoyi.basic.entity.CoalValue; import com.ruoyi.business.entity.OfficialInventory; import lombok.Data; @@ -17,4 +18,8 @@ private String supplierName; //供应商 private String supplierCoal; //供应商 + 煤种 private List<CoalValue> coalValues; //媒质方案字段值 } main-business/src/main/java/com/ruoyi/business/service/OfficialInventoryService.java
@@ -32,4 +32,6 @@ List<OfficialInventory> selectOfficialAll(); Map<String, BigDecimal> selectOfficialAllInfo(); List<OfficialInventoryDto> coalBlendingList(); } main-business/src/main/java/com/ruoyi/business/service/PendingInventoryService.java
@@ -24,5 +24,5 @@ int addOrEditCoalValue(PendingInventoryDto pendingInventoryDto); int addPending(PendingInventoryDto pendingInventoryDto); boolean addPending(PendingInventoryDto pendingInventoryDto); } main-business/src/main/java/com/ruoyi/business/service/impl/OfficialInventoryServiceImpl.java
@@ -333,6 +333,47 @@ } @Override public List<OfficialInventoryDto> coalBlendingList() { // 1. 查询基础库存数据 List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(null); // 2. 收集所有需要查询的ID Set<Long> coalIds = new HashSet<>(); Set<Long> supplierIds = new HashSet<>(); Set<Long> planIds = new HashSet<>(); officialInventories.forEach(inventory -> { coalIds.add(inventory.getCoalId()); supplierIds.add(inventory.getSupplierId()); planIds.add(inventory.getCoalPlanId()); }); // 3. 批量查询关联数据 Map<Long, CoalInfo> coalInfoMap = coalInfoMapper.selectByIds(coalIds).stream() .collect(Collectors.toMap(CoalInfo::getId, Function.identity())); Map<Long, Supply> supplyMap = supplyMapper.selectByIds(supplierIds).stream() .collect(Collectors.toMap(Supply::getId, Function.identity())); List<CoalValue> coalValues = coalValueMapper.selectList( new LambdaQueryWrapper<CoalValue>().in(CoalValue::getPlanId, planIds)); // 4. 组装DTO return officialInventories.stream() .map(inventory -> { OfficialInventoryDto dto = new OfficialInventoryDto(); BeanUtils.copyProperties(inventory, dto); // 设置煤种信息 CoalInfo coalInfo = coalInfoMap.get(inventory.getCoalId()); Supply supply = supplyMap.get(inventory.getSupplierId()); if (coalInfo != null && supply != null) { dto.setSupplierCoal(supply.getSupplierName() + " - " + coalInfo.getCoal()); } // 设置煤质数据 dto.setCoalValues(coalValues); return dto; }) .collect(Collectors.toList()); } @Override public Map<String, BigDecimal> selectOfficialAllInfo() { // 1. 查询 official_inventory 表数据 List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(null); main-business/src/main/java/com/ruoyi/business/service/impl/PendingInventoryServiceImpl.java
@@ -6,9 +6,11 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.mchange.v2.lang.SystemUtils; import com.ruoyi.basic.dto.CoalFieldDto; import com.ruoyi.basic.entity.CoalField; import com.ruoyi.basic.entity.CoalInfo; import com.ruoyi.basic.entity.CoalPlan; import com.ruoyi.basic.entity.CoalValue; import com.ruoyi.basic.mapper.CoalFieldMapper; import com.ruoyi.basic.mapper.CoalInfoMapper; @@ -16,6 +18,7 @@ import com.ruoyi.basic.mapper.CoalValueMapper; import com.ruoyi.basic.service.CoalFieldService; import com.ruoyi.basic.service.CoalPlanService; import com.ruoyi.basic.service.CoalValueService; import com.ruoyi.business.dto.PendingInventoryDto; import com.ruoyi.business.entity.OfficialInventory; import com.ruoyi.business.entity.PendingInventory; @@ -29,6 +32,7 @@ import com.ruoyi.business.service.PendingInventoryService; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.system.mapper.SysUserMapper; @@ -38,11 +42,13 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.format.DateTimeParseException; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; /** @@ -72,10 +78,8 @@ private final InputInventoryRecordService inputInventoryRecordService; private final InventorySummaryService inventorySummaryService; private final CoalFieldService coalFieldService; private final CoalPlanService coalPlanService; private final CoalPlanMapper coalPlanMapper; private final CoalValueService coalValueService; @Override public IPage<PendingInventoryDto> selectPendingInventoryList(Page page, PendingInventoryDto pendingInventoryDto) { @@ -297,7 +301,115 @@ @Override @Transactional public int addPending(PendingInventoryDto pendingInventoryDto) { return 1; public boolean addPending(PendingInventoryDto pendingInventoryDto) { try { CoalPlan coalPlan = coalPlanMapper.selectOne(new LambdaQueryWrapper<CoalPlan>().eq(CoalPlan::getPlan, "配煤计算器方案")); if (coalPlan == null) { return false; } // 添加到待入库 Long userId = SecurityUtils.getUserId(); PendingInventory pendingInventory = new PendingInventory(); pendingInventory.setUnit("t"); pendingInventory.setRegistrantId(userId); pendingInventory.setRegistrationDate(LocalDate.now()); for (Map<String, Object> map : pendingInventoryDto.getFieldsResultList()) { pendingInventory.setSupplierName("配煤计算器方案入库"); // 处理煤炭ID if (map.get("coalId") == null) { CoalInfo coalInfo = new CoalInfo(); coalInfo.setCoal((String) map.get("createCoal")); coalInfo.setMaintainerId(userId); coalInfo.setMaintenanceDate(LocalDate.now()); if (coalInfoMapper.insert(coalInfo) <= 0) { return false; } pendingInventory.setCoalId(coalInfo.getId()); } else { pendingInventory.setCoalId((Long) map.get("coalId")); } // 设置价格和数量 BigDecimal cost = BigDecimal.valueOf((Double) map.get("cost")); BigDecimal tonnage = BigDecimal.valueOf((Double) map.get("totalTonnage")); pendingInventory.setPriceIncludingTax(cost); pendingInventory.setInventoryQuantity(tonnage); pendingInventory.setTotalPriceIncludingTax(cost.multiply(tonnage)); BigDecimal costExcludingTax = cost.divide(BigDecimal.valueOf(1.13), 2, RoundingMode.HALF_UP); pendingInventory.setPriceExcludingTax(costExcludingTax); pendingInventory.setTotalPriceExcludingTax(costExcludingTax.multiply(tonnage)); pendingInventory.setCoalPlanId(coalPlan.getId()); // 煤质字段值 String coalFields = coalPlan.getCoalFields(); List<String> coalFieldList = Arrays.asList(coalFields.split(",")); for (String field : coalFieldList) { CoalField coalField = coalFieldMapper.selectOne( new LambdaQueryWrapper<CoalField>().eq(CoalField::getFields, field)); if (coalField == null) { continue; } CoalValue coalValue = new CoalValue(); coalValue.setPlanId(coalPlan.getId()); coalValue.setFields(field); coalValue.setFieldName(coalField.getFieldName()); coalValue.setType("1"); switch (coalField.getFieldName()) { case "发热量": coalValue.setCoalValue((String) map.get("cv")); break; case "硫分": coalValue.setCoalValue((String) map.get("sulfur")); break; case "灰分": coalValue.setCoalValue((String) map.get("ash")); break; case "水分": coalValue.setCoalValue((String) map.get("moisture")); break; } // 保存煤质值 if (coalValueMapper.insert(coalValue) <= 0) { return false; } } } // 插入待入库记录 if (pendingInventoryMapper.insert(pendingInventory) <= 0) { return false; } // 更新正式库 for (Map<String, Object> coalResult : pendingInventoryDto.getCoalResultList()) { Long officialId = (Long) coalResult.get("officialId"); BigDecimal quantity = (BigDecimal) coalResult.get("quantity"); OfficialInventory officialInventory = officialInventoryMapper.selectById(officialId); if (officialInventory == null || officialInventory.getInventoryQuantity().compareTo(quantity) < 0) { throw new BaseException("库存数量不足,添加至待入库失败"); } officialInventory.setInventoryQuantity(officialInventory.getInventoryQuantity().subtract(quantity)); if (officialInventoryMapper.updateById(officialInventory) <= 0) { return false; } } return true; } catch (Exception e) { // 记录日志 log.error("添加待入库失败", e); throw new BaseException("添加待入库失败: " + e.getMessage()); } } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/init/MyStartupRunner.java
@@ -2,14 +2,14 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.basic.dto.CoalFieldDto; import com.ruoyi.basic.dto.CoalPlanDto; import com.ruoyi.basic.entity.City; import com.ruoyi.basic.entity.CoalField; import com.ruoyi.basic.entity.District; import com.ruoyi.basic.entity.Province; import com.ruoyi.basic.mapper.*; import com.ruoyi.basic.service.CoalFieldService; import com.ruoyi.basic.service.CoalPlanService; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.web.controller.init.dto.AreaDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -18,9 +18,9 @@ import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -48,7 +48,7 @@ public void run(String... args) throws Exception { // 初始化省市区 initRegion(); // 初始新增配煤计算器中的字段和方案 // 初始新增配煤计算器中的煤种字段和方案 initCoalFields(); } @@ -120,19 +120,63 @@ } private void initCoalFields() { try { // 1. 初始化字段逻辑 Supplier<CoalFieldDto> dtoSupplier = CoalFieldDto::new; // 假设存在无参构造函数 List<CoalFieldDto> fields = Stream.of("发热量", "硫分", "灰分", "水分") .map(CoalFieldDto::from) .toList(); // 批量获取已存在的 fieldNames Set<String> existingFieldNames = coalFieldService.getFieldNamesByNames( fields.stream().map(CoalFieldDto::getFieldName).collect(Collectors.toSet()) ); List<CoalFieldDto> fields = Stream.of("发热量", "硫分", "灰分", "水分") .map(fieldName -> { CoalFieldDto dto = dtoSupplier.get(); dto.setFieldName(fieldName); // 假设存在 setFieldName 方法 dto.setFieldDescription("配煤计算器媒质字段"); return dto; }) .toList(); fields.forEach(field -> { if (!existingFieldNames.contains(field.getFieldName())) { coalFieldService.addOrEditCoalField(field); // 2. 保存字段(如果不存在) Set<String> existingNames = coalFieldService.getFieldNamesByNames( fields.stream().map(CoalFieldDto::getFieldName).collect(Collectors.toSet()) ); fields.forEach(field -> { if (!existingNames.contains(field.getFieldName())) { coalFieldService.addOrEditCoalField(field); } }); // 3. 查询所有字段ID List<CoalFieldDto> allFields = coalFieldService.getFieldsByNames( fields.stream().map(CoalFieldDto::getFieldName).collect(Collectors.toSet()) ); // 4. 创建方案 String planName = "配煤计算器方案"; boolean planExists = coalPlanService.checkPlanExists(allFields.stream() .map(f -> f.getId().toString()) .collect(Collectors.joining(","))); if (!planExists) { // 创建新方案 CoalPlanDto planDto = new CoalPlanDto(); planDto.setPlan(planName); planDto.setCoalFields(allFields.stream() .map(CoalFieldDto::getFields) .collect(Collectors.joining(","))); planDto.setFieldIds(allFields.stream() .map(f -> f.getId().toString()) .collect(Collectors.joining(","))); planDto.setSchemeDesc("系统生成配煤计算器所需字段方案"); coalPlanService.addOrEditCoalPlan(planDto); log.info("成功创建配煤计算器方案"); } else { log.info("配煤计算器方案已存在,跳过创建"); } }); } catch (Exception e) { // 记录系统异常日志,并转换为业务异常抛出(触发回滚) log.error("配煤计算器初始化失败", e); throw new BaseException("初始化配煤方案失败,请稍后重试"); } } } ruoyi-common/src/main/java/com/ruoyi/common/handler/MyMetaObjectHandler.java
@@ -10,27 +10,53 @@ @Component public class MyMetaObjectHandler implements MetaObjectHandler { private static final String SYSTEM_USER = "system"; @Override public void insertFill(MetaObject meta) { LocalDateTime now = LocalDateTime.now(); Long uid = SecurityUtils.getLoginUser().getUserId(); if (uid != null) { strictInsertFill(meta, "createBy", String.class, uid.toString()); strictInsertFill(meta, "updateBy", String.class, uid.toString()); String userId = getUserId(); if (hasField(meta, "createBy")) { strictInsertFill(meta, "createBy", String.class, userId); } strictInsertFill(meta, "createTime", LocalDateTime.class, now); strictInsertFill(meta, "updateTime", LocalDateTime.class, now); if (hasField(meta, "updateBy")) { strictInsertFill(meta, "updateBy", String.class, userId); } if (hasField(meta, "createTime")) { strictInsertFill(meta, "createTime", LocalDateTime.class, now); } if (hasField(meta, "updateTime")) { strictInsertFill(meta, "updateTime", LocalDateTime.class, now); } } @Override public void updateFill(MetaObject meta) { LocalDateTime now = LocalDateTime.now(); Long uid = SecurityUtils.getLoginUser().getUserId(); if (uid != null) { strictUpdateFill(meta, "updateBy", String.class, uid.toString()); String userId = getUserId(); if (hasField(meta, "updateBy")) { strictUpdateFill(meta, "updateBy", String.class, userId); } // 强制覆盖 updateTime setFieldValByName("updateTime", now, meta); if (hasField(meta, "updateTime")) { setFieldValByName("updateTime", now, meta); } } private String getUserId() { try { Long uid = SecurityUtils.getLoginUser().getUserId(); return uid != null ? uid.toString() : SYSTEM_USER; } catch (Exception e) { return SYSTEM_USER; } } private boolean hasField(MetaObject meta, String fieldName) { if (meta == null || fieldName == null) { return false; } return meta.hasGetter(fieldName) || meta.hasSetter(fieldName); } }