Sfoglia il codice sorgente

feat(policy): 批量新增或修改策略费用接口

- 控制器方法改为接收策略费用信息列表,实现批量新增或修改
- service层新增批量处理策略费用接口及其事务支持实现
- ThirdPartyChargingServiceImpl新增充电站、设备、接口信息的新增或更新判定逻辑
- 优化价格策略保存逻辑,改为对比后更新或新增,避免全量删除插入
- 充电站实体新增站点提示语字段及对应数据库映射和VO字段扩展
SheepHy 16 ore fa
parent
commit
a84591ae72

+ 5 - 5
src/main/java/com/zsElectric/boot/business/controller/PolicyFeeController.java

@@ -91,14 +91,14 @@ public class PolicyFeeController {
     }
 
     /**
-     * 新增/修改策略费用
+     * 批量新增/修改策略费用
      *
-     * @param addPolicyFeeDTO 策略费用信息
+     * @param addPolicyFeeDTOList 策略费用信息列表
      * @return 操作结果
      */
-    @Operation(summary = "新增/修改策略费用")
+    @Operation(summary = "批量新增/修改策略费用")
     @PostMapping("/addPolicyFee")
-    public Result<Boolean> addPolicyFee(@RequestBody AddPolicyFeeDTO addPolicyFeeDTO) {
-        return Result.success(policyFeeService.addPolicyFee(addPolicyFeeDTO));
+    public Result<Boolean> addPolicyFee(@RequestBody List<AddPolicyFeeDTO> addPolicyFeeDTOList) {
+        return Result.success(policyFeeService.batchAddPolicyFee(addPolicyFeeDTOList));
     }
 }

+ 3 - 0
src/main/java/com/zsElectric/boot/business/model/vo/ThirdPartyStationInfoVO.java

@@ -59,6 +59,9 @@ public class ThirdPartyStationInfoVO {
     @Schema(description = "站点引导")
     private String siteGuide;
 
+    @Schema(description = "站点提示语")
+    private String stationTips;
+
     @Schema(description = "电费")
     private BigDecimal electricityFee;
 

+ 8 - 0
src/main/java/com/zsElectric/boot/business/service/PolicyFeeService.java

@@ -28,4 +28,12 @@ public interface PolicyFeeService {
      * */
     boolean addPolicyFee(AddPolicyFeeDTO addPolicyFeeDTO);
 
+    /**
+     * 批量新增/修改策略费用
+     *
+     * @param addPolicyFeeDTOList 策略费用信息列表
+     * @return 操作结果
+     */
+    boolean batchAddPolicyFee(List<AddPolicyFeeDTO> addPolicyFeeDTOList);
+
 }

+ 13 - 0
src/main/java/com/zsElectric/boot/business/service/impl/PolicyFeeServiceImpl.java

@@ -17,6 +17,7 @@ import com.zsElectric.boot.system.service.DictItemService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
@@ -173,4 +174,16 @@ public class PolicyFeeServiceImpl implements PolicyFeeService {
             return inserted;
         }
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean batchAddPolicyFee(List<AddPolicyFeeDTO> addPolicyFeeDTOList) {
+        if (addPolicyFeeDTOList == null || addPolicyFeeDTOList.isEmpty()) {
+            return false;
+        }
+        for (AddPolicyFeeDTO dto : addPolicyFeeDTOList) {
+            addPolicyFee(dto);
+        }
+        return true;
+    }
 }

+ 173 - 24
src/main/java/com/zsElectric/boot/business/service/impl/ThirdPartyChargingServiceImpl.java

@@ -30,6 +30,7 @@ import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
@@ -155,9 +156,30 @@ public class ThirdPartyChargingServiceImpl implements ThirdPartyChargingService
                         .eq(ThirdPartyStationInfo::getStationId, stationInfo.getStationID())
         );
 
+        ThirdPartyStationInfo entity = buildStationEntity(stationInfo, existingStation);
+
+        if (existingStation == null) {
+            // 不存在,执行新增
+            stationInfoMapper.insert(entity);
+            log.debug("充电站信息新增成功 - stationId: {}", stationInfo.getStationID());
+        } else if (!isStationSame(existingStation, entity)) {
+            // 存在且数据变化,执行更新
+            stationInfoMapper.updateById(entity);
+            log.debug("充电站信息更新成功 - stationId: {}", stationInfo.getStationID());
+        } else {
+            log.debug("充电站信息未变化,跳过保存 - stationId: {}", stationInfo.getStationID());
+        }
+    }
+
+    /**
+     * 构建充电站实体
+     */
+    private ThirdPartyStationInfo buildStationEntity(StationInfo stationInfo, ThirdPartyStationInfo existingStation) {
         ThirdPartyStationInfo entity = new ThirdPartyStationInfo();
         if (existingStation != null) {
             entity.setId(existingStation.getId());
+            // 保留原有的配置状态
+            entity.setPolicyConfigured(existingStation.getPolicyConfigured());
         }
 
         // 设置字段值
@@ -217,12 +239,36 @@ public class ThirdPartyChargingServiceImpl implements ThirdPartyChargingService
         entity.setSupportOrder(stationInfo.getSupportOrder());
         entity.setRemark(stationInfo.getRemark());
 
-        // 插入或更新
-        if (existingStation == null) {
-            stationInfoMapper.insert(entity);
-        } else {
-            stationInfoMapper.updateById(entity);
-        }
+        return entity;
+    }
+
+    /**
+     * 判断充电站信息是否相同
+     */
+    private boolean isStationSame(ThirdPartyStationInfo existing, ThirdPartyStationInfo newEntity) {
+        return Objects.equals(existing.getOperatorId(), newEntity.getOperatorId()) &&
+                Objects.equals(existing.getEquipmentOwnerId(), newEntity.getEquipmentOwnerId()) &&
+                Objects.equals(existing.getStationName(), newEntity.getStationName()) &&
+                Objects.equals(existing.getCountryCode(), newEntity.getCountryCode()) &&
+                Objects.equals(existing.getAreaCode(), newEntity.getAreaCode()) &&
+                Objects.equals(existing.getAddress(), newEntity.getAddress()) &&
+                Objects.equals(existing.getStationTel(), newEntity.getStationTel()) &&
+                Objects.equals(existing.getServiceTel(), newEntity.getServiceTel()) &&
+                Objects.equals(existing.getStationType(), newEntity.getStationType()) &&
+                Objects.equals(existing.getStationStatus(), newEntity.getStationStatus()) &&
+                Objects.equals(existing.getParkNums(), newEntity.getParkNums()) &&
+                isBigDecimalEqual(existing.getStationLng(), newEntity.getStationLng()) &&
+                isBigDecimalEqual(existing.getStationLat(), newEntity.getStationLat()) &&
+                Objects.equals(existing.getSiteGuide(), newEntity.getSiteGuide()) &&
+                Objects.equals(existing.getConstruction(), newEntity.getConstruction()) &&
+                Objects.equals(existing.getPictures(), newEntity.getPictures()) &&
+                Objects.equals(existing.getBusineHours(), newEntity.getBusineHours()) &&
+                isBigDecimalEqual(existing.getElectricityFee(), newEntity.getElectricityFee()) &&
+                isBigDecimalEqual(existing.getServiceFee(), newEntity.getServiceFee()) &&
+                Objects.equals(existing.getParkFee(), newEntity.getParkFee()) &&
+                Objects.equals(existing.getPayment(), newEntity.getPayment()) &&
+                Objects.equals(existing.getSupportOrder(), newEntity.getSupportOrder()) &&
+                Objects.equals(existing.getRemark(), newEntity.getRemark());
     }
 
     /**
@@ -235,6 +281,25 @@ public class ThirdPartyChargingServiceImpl implements ThirdPartyChargingService
                         .eq(ThirdPartyEquipmentInfo::getEquipmentId, equipmentInfo.getEquipmentID())
         );
 
+        ThirdPartyEquipmentInfo entity = buildEquipmentEntity(equipmentInfo, stationId, existingEquipment);
+
+        if (existingEquipment == null) {
+            // 不存在,执行新增
+            equipmentInfoMapper.insert(entity);
+            log.debug("充电设备信息新增成功 - equipmentId: {}", equipmentInfo.getEquipmentID());
+        } else if (!isEquipmentSame(existingEquipment, entity)) {
+            // 存在且数据变化,执行更新
+            equipmentInfoMapper.updateById(entity);
+            log.debug("充电设备信息更新成功 - equipmentId: {}", equipmentInfo.getEquipmentID());
+        } else {
+            log.debug("充电设备信息未变化,跳过保存 - equipmentId: {}", equipmentInfo.getEquipmentID());
+        }
+    }
+
+    /**
+     * 构建充电设备实体
+     */
+    private ThirdPartyEquipmentInfo buildEquipmentEntity(EquipmentInfo equipmentInfo, String stationId, ThirdPartyEquipmentInfo existingEquipment) {
         ThirdPartyEquipmentInfo entity = new ThirdPartyEquipmentInfo();
         if (existingEquipment != null) {
             entity.setId(existingEquipment.getId());
@@ -264,12 +329,23 @@ public class ThirdPartyChargingServiceImpl implements ThirdPartyChargingService
 
         entity.setEquipmentName(equipmentInfo.getEquipmentName());
 
-        // 插入或更新
-        if (existingEquipment == null) {
-            equipmentInfoMapper.insert(entity);
-        } else {
-            equipmentInfoMapper.updateById(entity);
-        }
+        return entity;
+    }
+
+    /**
+     * 判断充电设备信息是否相同
+     */
+    private boolean isEquipmentSame(ThirdPartyEquipmentInfo existing, ThirdPartyEquipmentInfo newEntity) {
+        return Objects.equals(existing.getStationId(), newEntity.getStationId()) &&
+                Objects.equals(existing.getManufacturerId(), newEntity.getManufacturerId()) &&
+                Objects.equals(existing.getManufacturerName(), newEntity.getManufacturerName()) &&
+                Objects.equals(existing.getEquipmentModel(), newEntity.getEquipmentModel()) &&
+                Objects.equals(existing.getProductionDate(), newEntity.getProductionDate()) &&
+                Objects.equals(existing.getEquipmentType(), newEntity.getEquipmentType()) &&
+                isBigDecimalEqual(existing.getEquipmentLng(), newEntity.getEquipmentLng()) &&
+                isBigDecimalEqual(existing.getEquipmentLat(), newEntity.getEquipmentLat()) &&
+                isBigDecimalEqual(existing.getPower(), newEntity.getPower()) &&
+                Objects.equals(existing.getEquipmentName(), newEntity.getEquipmentName());
     }
 
     /**
@@ -282,6 +358,25 @@ public class ThirdPartyChargingServiceImpl implements ThirdPartyChargingService
                         .eq(ThirdPartyConnectorInfo::getConnectorId, connectorInfo.getConnectorID())
         );
 
+        ThirdPartyConnectorInfo entity = buildConnectorEntity(connectorInfo, equipmentId, stationId, existingConnector);
+
+        if (existingConnector == null) {
+            // 不存在,执行新增
+            connectorInfoMapper.insert(entity);
+            log.debug("充电接口信息新增成功 - connectorId: {}", connectorInfo.getConnectorID());
+        } else if (!isConnectorSame(existingConnector, entity)) {
+            // 存在且数据变化,执行更新
+            connectorInfoMapper.updateById(entity);
+            log.debug("充电接口信息更新成功 - connectorId: {}", connectorInfo.getConnectorID());
+        } else {
+            log.debug("充电接口信息未变化,跳过保存 - connectorId: {}", connectorInfo.getConnectorID());
+        }
+    }
+
+    /**
+     * 构建充电接口实体
+     */
+    private ThirdPartyConnectorInfo buildConnectorEntity(ConnectorInfo connectorInfo, String equipmentId, String stationId, ThirdPartyConnectorInfo existingConnector) {
         ThirdPartyConnectorInfo entity = new ThirdPartyConnectorInfo();
         if (existingConnector != null) {
             entity.setId(existingConnector.getId());
@@ -305,12 +400,23 @@ public class ThirdPartyChargingServiceImpl implements ThirdPartyChargingService
         entity.setParkNo(connectorInfo.getParkNo());
         entity.setNationalStandard(connectorInfo.getNationalStandard());
 
-        // 插入或更新
-        if (existingConnector == null) {
-            connectorInfoMapper.insert(entity);
-        } else {
-            connectorInfoMapper.updateById(entity);
-        }
+        return entity;
+    }
+
+    /**
+     * 判断充电接口信息是否相同
+     */
+    private boolean isConnectorSame(ThirdPartyConnectorInfo existing, ThirdPartyConnectorInfo newEntity) {
+        return Objects.equals(existing.getEquipmentId(), newEntity.getEquipmentId()) &&
+                Objects.equals(existing.getStationId(), newEntity.getStationId()) &&
+                Objects.equals(existing.getConnectorName(), newEntity.getConnectorName()) &&
+                Objects.equals(existing.getConnectorType(), newEntity.getConnectorType()) &&
+                Objects.equals(existing.getVoltageUpperLimits(), newEntity.getVoltageUpperLimits()) &&
+                Objects.equals(existing.getVoltageLowerLimits(), newEntity.getVoltageLowerLimits()) &&
+                Objects.equals(existing.getCurrent(), newEntity.getCurrent()) &&
+                isBigDecimalEqual(existing.getPower(), newEntity.getPower()) &&
+                Objects.equals(existing.getParkNo(), newEntity.getParkNo()) &&
+                Objects.equals(existing.getNationalStandard(), newEntity.getNationalStandard());
     }
 
     // ==================== 价格策略数据保存 ====================
@@ -351,13 +457,9 @@ public class ThirdPartyChargingServiceImpl implements ThirdPartyChargingService
                         pricePolicyVO.getEquipBizSeq(), pricePolicyVO.getConnectorID(), policyId);
             }
 
-            // 保存价格策略明细(先删除旧的,再插入新的)
-            policyInfoMapper.delete(Wrappers.<ThirdPartyPolicyInfo>lambdaQuery()
-                    .eq(ThirdPartyPolicyInfo::getPricePolicyId, policyId));
+            // 保存价格策略明细(对比后更新或新增,不做删除操作)
             if (!CollectionUtils.isEmpty(pricePolicyVO.getPolicyInfos())) {
-                for (ChargingPricePolicyVO.PolicyInfo policyInfo : pricePolicyVO.getPolicyInfos()) {
-                    savePolicyInfoDetail(policyInfo, policyId);
-                }
+                savePolicyInfoDetails(pricePolicyVO.getPolicyInfos(), policyId);
             }
 
         } catch (Exception e) {
@@ -495,6 +597,53 @@ public class ThirdPartyChargingServiceImpl implements ThirdPartyChargingService
         return existingPolicy.getId();
     }
 
+    /**
+     * 保存价格策略明细(对比后更新或新增)
+     */
+    private void savePolicyInfoDetails(List<ChargingPricePolicyVO.PolicyInfo> policyInfos, Long policyId) {
+        // 查询已存在的明细记录,以 startTime 为 key
+        Map<String, ThirdPartyPolicyInfo> existingMap = policyInfoMapper.selectList(
+                Wrappers.<ThirdPartyPolicyInfo>lambdaQuery()
+                        .eq(ThirdPartyPolicyInfo::getPricePolicyId, policyId))
+                .stream()
+                .collect(Collectors.toMap(ThirdPartyPolicyInfo::getStartTime, info -> info, (v1, v2) -> v1));
+
+        for (ChargingPricePolicyVO.PolicyInfo policyInfo : policyInfos) {
+            ThirdPartyPolicyInfo existing = existingMap.get(policyInfo.getStartTime());
+            
+            if (existing == null) {
+                // 不存在,执行新增
+                savePolicyInfoDetail(policyInfo, policyId);
+                log.debug("价格策略明细新增成功 - policyId: {}, startTime: {}", policyId, policyInfo.getStartTime());
+            } else if (!isPolicyInfoSame(existing, policyInfo)) {
+                // 存在且数据变化,执行更新
+                updatePolicyInfoDetail(existing, policyInfo);
+                log.debug("价格策略明细更新成功 - policyId: {}, startTime: {}", policyId, policyInfo.getStartTime());
+            } else {
+                log.debug("价格策略明细未变化,跳过保存 - policyId: {}, startTime: {}", policyId, policyInfo.getStartTime());
+            }
+        }
+    }
+
+    /**
+     * 判断价格策略明细是否相同
+     */
+    private boolean isPolicyInfoSame(ThirdPartyPolicyInfo existing, ChargingPricePolicyVO.PolicyInfo newInfo) {
+        return isBigDecimalEqual(existing.getElecPrice(), newInfo.getElecPrice()) &&
+                isBigDecimalEqual(existing.getServicePrice(), newInfo.getServicePrice()) &&
+                Objects.equals(existing.getPeriodFlag(), newInfo.getPeriodFlag());
+    }
+
+    /**
+     * 更新价格策略明细
+     */
+    private void updatePolicyInfoDetail(ThirdPartyPolicyInfo existing, ChargingPricePolicyVO.PolicyInfo policyInfo) {
+        existing.setElecPrice(policyInfo.getElecPrice());
+        existing.setServicePrice(policyInfo.getServicePrice());
+        existing.setPeriodFlag(policyInfo.getPeriodFlag());
+        policyInfoMapper.updateById(existing);
+    }
+
     /**
      * 保存价格策略明细
      */

+ 5 - 0
src/main/java/com/zsElectric/boot/charging/entity/ThirdPartyStationInfo.java

@@ -146,6 +146,11 @@ public class ThirdPartyStationInfo extends BaseEntity {
      */
     private Integer policyConfigured;
 
+    /**
+     * 站点提示语
+     */
+    private String stationTips;
+
     /**
      * 创建人ID
      */

+ 3 - 1
src/main/resources/mapper/business/ThirdPartyStationInfoMapper.xml

@@ -17,6 +17,7 @@
         <result property="stationLng" column="station_lng"/>
         <result property="stationLat" column="station_lat"/>
         <result property="siteGuide" column="site_guide"/>
+        <result property="stationTips" column="station_tips"/>
     </resultMap>
 
     <select id="selectStationInfoPage" resultMap="StationInfoResultMap">
@@ -78,7 +79,8 @@
             tpsi.station_type,
             tpsi.station_lng,
             tpsi.station_lat,
-            tpsi.site_guide
+            tpsi.site_guide,
+            tpsi.station_tips
         FROM third_party_station_info tpsi
         LEFT JOIN third_party_equipment_info tpei ON tpsi.station_id = tpei.station_id AND tpei.is_deleted = 0
         WHERE tpsi.is_deleted = 0