|
|
@@ -0,0 +1,312 @@
|
|
|
+package com.zsElectric.boot.business.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.zsElectric.boot.business.model.dto.UpdatePricePolicyDTO;
|
|
|
+import com.zsElectric.boot.business.model.query.PricePolicyPageQuery;
|
|
|
+import com.zsElectric.boot.business.model.vo.PricePolicyPageVO;
|
|
|
+import com.zsElectric.boot.business.service.PricePolicyManagementService;
|
|
|
+import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo;
|
|
|
+import com.zsElectric.boot.charging.entity.ThirdPartyEquipmentPricePolicy;
|
|
|
+import com.zsElectric.boot.charging.entity.ThirdPartyPolicyInfo;
|
|
|
+import com.zsElectric.boot.charging.entity.ThirdPartyStationInfo;
|
|
|
+import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper;
|
|
|
+import com.zsElectric.boot.charging.mapper.ThirdPartyEquipmentPricePolicyMapper;
|
|
|
+import com.zsElectric.boot.charging.mapper.ThirdPartyPolicyInfoMapper;
|
|
|
+import com.zsElectric.boot.charging.mapper.ThirdPartyStationInfoMapper;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 价格策略管理服务实现
|
|
|
+ *
|
|
|
+ * @author system
|
|
|
+ * @since 2025-12-12
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class PricePolicyManagementServiceImpl implements PricePolicyManagementService {
|
|
|
+
|
|
|
+ private final ThirdPartyStationInfoMapper stationInfoMapper;
|
|
|
+ private final ThirdPartyConnectorInfoMapper connectorInfoMapper;
|
|
|
+ private final ThirdPartyEquipmentPricePolicyMapper pricePolicyMapper;
|
|
|
+ private final ThirdPartyPolicyInfoMapper policyInfoMapper;
|
|
|
+
|
|
|
+ private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Page<PricePolicyPageVO> queryPricePolicyPage(PricePolicyPageQuery query) {
|
|
|
+ // 查询充电站列表
|
|
|
+ LambdaQueryWrapper<ThirdPartyStationInfo> queryWrapper = Wrappers.lambdaQuery();
|
|
|
+
|
|
|
+ if (StringUtils.hasText(query.getStationId())) {
|
|
|
+ queryWrapper.eq(ThirdPartyStationInfo::getStationId, query.getStationId());
|
|
|
+ }
|
|
|
+ if (StringUtils.hasText(query.getStationName())) {
|
|
|
+ queryWrapper.like(ThirdPartyStationInfo::getStationName, query.getStationName());
|
|
|
+ }
|
|
|
+
|
|
|
+ Page<ThirdPartyStationInfo> stationPage = stationInfoMapper.selectPage(
|
|
|
+ new Page<>(query.getPageNo(), query.getPageSize()),
|
|
|
+ queryWrapper
|
|
|
+ );
|
|
|
+
|
|
|
+ // 转换为VO
|
|
|
+ Page<PricePolicyPageVO> resultPage = new Page<>(stationPage.getCurrent(), stationPage.getSize(), stationPage.getTotal());
|
|
|
+ List<PricePolicyPageVO> voList = stationPage.getRecords().stream()
|
|
|
+ .map(this::convertToVO)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ resultPage.setRecords(voList);
|
|
|
+ return resultPage;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转换为VO对象
|
|
|
+ */
|
|
|
+ private PricePolicyPageVO convertToVO(ThirdPartyStationInfo station) {
|
|
|
+ PricePolicyPageVO vo = new PricePolicyPageVO();
|
|
|
+ vo.setStationId(station.getStationId());
|
|
|
+ vo.setStationName(station.getStationName());
|
|
|
+ vo.setCity(getCity(station.getAreaCode()));
|
|
|
+ vo.setEquipmentOwner(station.getEquipmentOwnerId());
|
|
|
+ vo.setAddress(station.getAddress());
|
|
|
+ vo.setLocationType(getLocationType(station.getConstruction()));
|
|
|
+ vo.setTerminalCount(getTerminalCount(station.getStationId()));
|
|
|
+ vo.setStationStatus(getStationStatusText(station.getStationStatus()));
|
|
|
+ vo.setServiceTel(station.getServiceTel());
|
|
|
+ vo.setUpdateTime(station.getUpdateTime());
|
|
|
+
|
|
|
+ // 查询价格策略明细
|
|
|
+ vo.setPolicyDetails(queryPolicyDetails(station.getStationId()));
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询价格策略明细
|
|
|
+ */
|
|
|
+ private List<PricePolicyPageVO.PricePolicyDetail> queryPolicyDetails(String stationId) {
|
|
|
+ // 查询该充电站的所有充电桩接口
|
|
|
+ List<ThirdPartyConnectorInfo> connectors = connectorInfoMapper.selectList(
|
|
|
+ Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
|
|
|
+ .eq(ThirdPartyConnectorInfo::getStationId, stationId)
|
|
|
+ .last("LIMIT 1") // 取第一个充电桩的价格策略
|
|
|
+ );
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(connectors)) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ String connectorId = connectors.get(0).getConnectorId();
|
|
|
+
|
|
|
+ // 查询最新的价格策略
|
|
|
+ List<ThirdPartyEquipmentPricePolicy> policies = pricePolicyMapper.selectList(
|
|
|
+ Wrappers.<ThirdPartyEquipmentPricePolicy>lambdaQuery()
|
|
|
+ .eq(ThirdPartyEquipmentPricePolicy::getConnectorId, connectorId)
|
|
|
+ .orderByDesc(ThirdPartyEquipmentPricePolicy::getCreateTime)
|
|
|
+ .last("LIMIT 1")
|
|
|
+ );
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(policies)) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ Long policyId = policies.get(0).getId();
|
|
|
+
|
|
|
+ // 查询价格策略明细
|
|
|
+ List<ThirdPartyPolicyInfo> policyInfos = policyInfoMapper.selectList(
|
|
|
+ Wrappers.<ThirdPartyPolicyInfo>lambdaQuery()
|
|
|
+ .eq(ThirdPartyPolicyInfo::getPricePolicyId, policyId)
|
|
|
+ .orderBy(true, true, ThirdPartyPolicyInfo::getStartTime)
|
|
|
+ );
|
|
|
+
|
|
|
+ return convertToPolicyDetails(policyInfos);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转换价格策略明细
|
|
|
+ */
|
|
|
+ private List<PricePolicyPageVO.PricePolicyDetail> convertToPolicyDetails(List<ThirdPartyPolicyInfo> policyInfos) {
|
|
|
+ List<PricePolicyPageVO.PricePolicyDetail> details = new ArrayList<>();
|
|
|
+
|
|
|
+ for (int i = 0; i < policyInfos.size(); i++) {
|
|
|
+ ThirdPartyPolicyInfo info = policyInfos.get(i);
|
|
|
+ PricePolicyPageVO.PricePolicyDetail detail = new PricePolicyPageVO.PricePolicyDetail();
|
|
|
+
|
|
|
+ // 时间段处理
|
|
|
+ String startTime = formatTime(info.getStartTime());
|
|
|
+ String endTime;
|
|
|
+ if (i < policyInfos.size() - 1) {
|
|
|
+ endTime = formatTime(policyInfos.get(i + 1).getStartTime());
|
|
|
+ } else {
|
|
|
+ endTime = formatTime(policyInfos.get(0).getStartTime());
|
|
|
+ }
|
|
|
+ detail.setTimePeriod(startTime + "-" + endTime);
|
|
|
+
|
|
|
+ detail.setElecPrice(info.getElecPrice());
|
|
|
+ detail.setServicePrice(info.getServicePrice());
|
|
|
+
|
|
|
+ // 结算费合计 = 电价 + 结算服务费
|
|
|
+ BigDecimal settlementTotal = BigDecimal.ZERO;
|
|
|
+ if (info.getElecPrice() != null) {
|
|
|
+ settlementTotal = settlementTotal.add(info.getElecPrice());
|
|
|
+ }
|
|
|
+ if (info.getServicePrice() != null) {
|
|
|
+ settlementTotal = settlementTotal.add(info.getServicePrice());
|
|
|
+ }
|
|
|
+ detail.setSettlementTotal(settlementTotal);
|
|
|
+
|
|
|
+ detail.setOperationServiceFee(info.getOperationServiceFee());
|
|
|
+ detail.setTotalSalesPrice(info.getTotalSalesPrice());
|
|
|
+
|
|
|
+ details.add(detail);
|
|
|
+ }
|
|
|
+
|
|
|
+ return details;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void updatePricePolicy(UpdatePricePolicyDTO dto) {
|
|
|
+ // 查询该充电站的所有充电桩接口
|
|
|
+ List<ThirdPartyConnectorInfo> connectors = connectorInfoMapper.selectList(
|
|
|
+ Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
|
|
|
+ .eq(ThirdPartyConnectorInfo::getStationId, dto.getStationId())
|
|
|
+ );
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(connectors)) {
|
|
|
+ log.warn("未找到充电站的充电桩接口信息, stationId: {}", dto.getStationId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal operationServiceFee = dto.getHasContractServiceFee() && dto.getContractServiceFee() != null
|
|
|
+ ? dto.getContractServiceFee()
|
|
|
+ : BigDecimal.ZERO;
|
|
|
+
|
|
|
+ // 更新所有充电桩的价格策略
|
|
|
+ for (ThirdPartyConnectorInfo connector : connectors) {
|
|
|
+ updateConnectorPricePolicy(connector.getConnectorId(), operationServiceFee);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("更新充电站价格策略成功, stationId: {}, operationServiceFee: {}", dto.getStationId(), operationServiceFee);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新单个充电桩的价格策略
|
|
|
+ */
|
|
|
+ private void updateConnectorPricePolicy(String connectorId, BigDecimal operationServiceFee) {
|
|
|
+ // 查询最新的价格策略
|
|
|
+ List<ThirdPartyEquipmentPricePolicy> policies = pricePolicyMapper.selectList(
|
|
|
+ Wrappers.<ThirdPartyEquipmentPricePolicy>lambdaQuery()
|
|
|
+ .eq(ThirdPartyEquipmentPricePolicy::getConnectorId, connectorId)
|
|
|
+ .orderByDesc(ThirdPartyEquipmentPricePolicy::getCreateTime)
|
|
|
+ .last("LIMIT 1")
|
|
|
+ );
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(policies)) {
|
|
|
+ log.warn("未找到充电桩的价格策略, connectorId: {}", connectorId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Long policyId = policies.get(0).getId();
|
|
|
+
|
|
|
+ // 查询所有价格策略明细
|
|
|
+ List<ThirdPartyPolicyInfo> policyInfos = policyInfoMapper.selectList(
|
|
|
+ Wrappers.<ThirdPartyPolicyInfo>lambdaQuery()
|
|
|
+ .eq(ThirdPartyPolicyInfo::getPricePolicyId, policyId)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 更新每条明细的运营服务费和销售合计价格
|
|
|
+ for (ThirdPartyPolicyInfo info : policyInfos) {
|
|
|
+ info.setOperationServiceFee(operationServiceFee);
|
|
|
+
|
|
|
+ // 重新计算销售合计价格
|
|
|
+ BigDecimal totalSalesPrice = calculateTotalSalesPrice(
|
|
|
+ info.getElecPrice(),
|
|
|
+ info.getServicePrice(),
|
|
|
+ operationServiceFee
|
|
|
+ );
|
|
|
+ info.setTotalSalesPrice(totalSalesPrice);
|
|
|
+
|
|
|
+ policyInfoMapper.updateById(info);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算销售合计价格 = 电价 + 结算服务费 + 运营服务费
|
|
|
+ */
|
|
|
+ private BigDecimal calculateTotalSalesPrice(BigDecimal elecPrice, BigDecimal servicePrice, BigDecimal operationServiceFee) {
|
|
|
+ BigDecimal total = BigDecimal.ZERO;
|
|
|
+
|
|
|
+ if (elecPrice != null) {
|
|
|
+ total = total.add(elecPrice);
|
|
|
+ }
|
|
|
+ if (servicePrice != null) {
|
|
|
+ total = total.add(servicePrice);
|
|
|
+ }
|
|
|
+ if (operationServiceFee != null) {
|
|
|
+ total = total.add(operationServiceFee);
|
|
|
+ }
|
|
|
+
|
|
|
+ return total;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 格式化时间 HHmmss -> HH:mm
|
|
|
+ */
|
|
|
+ private String formatTime(String timeStr) {
|
|
|
+ if (timeStr == null || timeStr.length() < 4) {
|
|
|
+ return timeStr;
|
|
|
+ }
|
|
|
+ return timeStr.substring(0, 2) + ":" + timeStr.substring(2, 4);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取城市名称(简化处理)
|
|
|
+ */
|
|
|
+ private String getCity(String areaCode) {
|
|
|
+ // TODO: 根据区域码查询城市名称
|
|
|
+ return "贵阳市";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取场所类型文本
|
|
|
+ */
|
|
|
+ private String getLocationType(Integer construction) {
|
|
|
+ // TODO: 根据建设场所代码返回文本
|
|
|
+ return "其他";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取充电终端数量
|
|
|
+ */
|
|
|
+ private Integer getTerminalCount(String stationId) {
|
|
|
+ Long count = connectorInfoMapper.selectCount(
|
|
|
+ Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
|
|
|
+ .eq(ThirdPartyConnectorInfo::getStationId, stationId)
|
|
|
+ );
|
|
|
+ return count != null ? count.intValue() : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取站点状态文本
|
|
|
+ */
|
|
|
+ private String getStationStatusText(Integer status) {
|
|
|
+ // TODO: 根据状态代码返回文本
|
|
|
+ return "未知";
|
|
|
+ }
|
|
|
+}
|