package com.zsElectric.boot.business.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.zsElectric.boot.business.mapper.PolicyFeeMapper; import com.zsElectric.boot.business.mapper.ThirdPartyStationInfoMapper; import com.zsElectric.boot.business.model.dto.AddPolicyFeeDTO; import com.zsElectric.boot.business.model.entity.PolicyFee; import com.zsElectric.boot.business.model.vo.TimePeriodPriceVO; import com.zsElectric.boot.business.service.PolicyFeeService; import com.zsElectric.boot.charging.entity.ThirdPartyPolicyInfo; import com.zsElectric.boot.charging.entity.ThirdPartyStationInfo; import com.zsElectric.boot.charging.mapper.ThirdPartyPolicyInfoMapper; import com.zsElectric.boot.system.mapper.DictItemMapper; import com.zsElectric.boot.system.model.entity.DictItem; 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.List; /** * 策略费用服务实现 * * @author system * @since 2025-12-15 */ @Slf4j @Service @RequiredArgsConstructor public class PolicyFeeServiceImpl implements PolicyFeeService { private final PolicyFeeMapper policyFeeMapper; private final ThirdPartyStationInfoMapper stationInfoMapper; private final ThirdPartyPolicyInfoMapper policyInfoMapper; private final DictItemMapper dictItemMapper; /** * 时段标志字典编码 */ private static final String TIME_PERIOD_FLAG_DICT_CODE = "time_period_flag"; @Override public List getPolicyFee(long stationId, int salesType, Long firmId, Long thirdPartyId) { return policyFeeMapper.selectTimePeriodPriceList(stationId, salesType, firmId, thirdPartyId); } @Override public boolean addPolicyFee(AddPolicyFeeDTO addPolicyFeeDTO) { // 根据站点+时段+销售类型+企业/渠道方查询是否已存在 PolicyFee existPolicyFee = policyFeeMapper.selectOne(Wrappers.lambdaQuery() .eq(PolicyFee::getStationInfoId, addPolicyFeeDTO.getStationInfoId()) .eq(PolicyFee::getStartTime, addPolicyFeeDTO.getTimePeriod()) .eq(PolicyFee::getSalesType, addPolicyFeeDTO.getSalesType()) .eq(addPolicyFeeDTO.getSalesType() == 1, PolicyFee::getFirmId, addPolicyFeeDTO.getFirmId()) .eq(addPolicyFeeDTO.getSalesType() == 2, PolicyFee::getThirdPartyId, addPolicyFeeDTO.getThirdPartyId()) .eq(PolicyFee::getIsDeleted, 0) .last("limit 1")); if (existPolicyFee != null) { // 已存在,执行更新 existPolicyFee.setOpFee(addPolicyFeeDTO.getOperationServiceFee()); // 计算并设置综合销售费 BigDecimal compSalesFee = calculateCompSalesFee( addPolicyFeeDTO.getStationInfoId(), addPolicyFeeDTO.getTimePeriod(), addPolicyFeeDTO.getPeriodFlag(), addPolicyFeeDTO.getOperationServiceFee() ); existPolicyFee.setCompSalesFee(compSalesFee); return policyFeeMapper.updateById(existPolicyFee) > 0; } else { // 不存在,执行新增 PolicyFee policyFee = new PolicyFee(); policyFee.setStationInfoId(addPolicyFeeDTO.getStationInfoId()); policyFee.setStartTime(addPolicyFeeDTO.getTimePeriod()); policyFee.setOpFee(addPolicyFeeDTO.getOperationServiceFee()); // 计算并设置综合销售费 BigDecimal compSalesFee = calculateCompSalesFee( addPolicyFeeDTO.getStationInfoId(), addPolicyFeeDTO.getTimePeriod(), addPolicyFeeDTO.getPeriodFlag(), addPolicyFeeDTO.getOperationServiceFee() ); policyFee.setCompSalesFee(compSalesFee); policyFee.setSalesType(addPolicyFeeDTO.getSalesType()); // 根据销售类型设置对应的ID if (addPolicyFeeDTO.getSalesType() == 1) { policyFee.setFirmId(addPolicyFeeDTO.getFirmId()); } else if (addPolicyFeeDTO.getSalesType() == 2) { policyFee.setThirdPartyId(addPolicyFeeDTO.getThirdPartyId()); } boolean inserted = policyFeeMapper.insert(policyFee) > 0; // 新增成功后,更新站点的配置状态为已配置 if (inserted) { stationInfoMapper.update(null, Wrappers.lambdaUpdate() .eq(ThirdPartyStationInfo::getId, addPolicyFeeDTO.getStationInfoId()) .set(ThirdPartyStationInfo::getPolicyConfigured, 1)); } return inserted; } } /** * 计算综合销售费 * 公式:compSalesFee = elec_price + service_price + 字典表值 + op_fee * * @param stationInfoId 站点信息ID * @param timePeriod 时间段(HHmmss格式) * @param periodFlag 时段标志 * @param opFee 运营费 * @return 综合销售费 */ private BigDecimal calculateCompSalesFee(Long stationInfoId, String timePeriod, Integer periodFlag, BigDecimal opFee) { BigDecimal elecPrice = BigDecimal.ZERO; BigDecimal servicePrice = BigDecimal.ZERO; // 直接通过stationInfoId和timePeriod查询电价和服务费 ThirdPartyPolicyInfo policyInfo = policyInfoMapper.selectElecAndServicePriceByStation(stationInfoId, timePeriod); log.info("计算compSalesFee - stationInfoId: {}, timePeriod: {}, policyInfo: {}", stationInfoId, timePeriod, policyInfo); if (policyInfo != null) { elecPrice = policyInfo.getElecPrice() != null ? policyInfo.getElecPrice() : BigDecimal.ZERO; servicePrice = policyInfo.getServicePrice() != null ? policyInfo.getServicePrice() : BigDecimal.ZERO; } // 从字典表获取periodFlag对应的值 BigDecimal dictValue = getDictValueByPeriodFlag(periodFlag); // 计算综合销售费 = elec_price + service_price + 字典值 + op_fee BigDecimal opFeeValue = opFee != null ? opFee : BigDecimal.ZERO; BigDecimal compSalesFee = elecPrice.add(servicePrice).add(dictValue).add(opFeeValue); log.info("计算综合销售费 - stationInfoId: {}, timePeriod: {}, elecPrice: {}, servicePrice: {}, dictValue: {}, opFee: {}, compSalesFee: {}", stationInfoId, timePeriod, elecPrice, servicePrice, dictValue, opFeeValue, compSalesFee); return compSalesFee; } /** * 根据时段标志获取字典值 * * @param periodFlag 时段标志(1-尖 2-峰 3-平 4-谷) * @return 综合销售费 */ private BigDecimal getDictValueByPeriodFlag(Integer periodFlag) { if (periodFlag == null) { return BigDecimal.ZERO; } // 根据时段标志获取对应的label String label; switch (periodFlag) { case 1: label = "尖"; break; case 2: label = "峰"; break; case 3: label = "平"; break; case 4: label = "谷"; break; default: return BigDecimal.ZERO; } // 从字典表查询对应的value DictItem dictItem = dictItemMapper.selectOne( new LambdaQueryWrapper() .eq(DictItem::getDictCode, TIME_PERIOD_FLAG_DICT_CODE) .eq(DictItem::getStatus, 1) .eq(DictItem::getLabel, label) .last("LIMIT 1") ); if (dictItem != null && dictItem.getValue() != null) { try { return new BigDecimal(dictItem.getValue()); } catch (NumberFormatException e) { log.warn("字典值value转换为BigDecimal失败: {}", dictItem.getValue()); return BigDecimal.ZERO; } } return BigDecimal.ZERO; } @Override @Transactional(rollbackFor = Exception.class) public boolean batchAddPolicyFee(List addPolicyFeeDTOList) { if (addPolicyFeeDTOList == null || addPolicyFeeDTOList.isEmpty()) { return false; } for (AddPolicyFeeDTO dto : addPolicyFeeDTOList) { addPolicyFee(dto); } return true; } }