package cn.iocoder.yudao.module.mes.service.pd.price; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.mes.controller.admin.pd.price.vo.MesPdPriceCalcDetailRespVO; import cn.iocoder.yudao.module.mes.controller.admin.pd.price.vo.MesPdPriceCalcReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pd.price.vo.MesPdPriceCalcRespVO; import cn.iocoder.yudao.module.mes.dal.dataobject.pd.basedata.MesPdDiscountPolicyDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pd.basedata.MesPdServicePackageDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pd.basedata.MesPdTieredPriceDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pd.basedata.MesPdVoltageLevelDO; import cn.iocoder.yudao.module.mes.dal.mysql.pd.basedata.MesPdDiscountPolicyMapper; import cn.iocoder.yudao.module.mes.dal.mysql.pd.basedata.MesPdTieredPriceMapper; import cn.iocoder.yudao.module.mes.service.pd.basedata.MesPdServicePackageService; import cn.iocoder.yudao.module.mes.service.pd.basedata.MesPdVoltageLevelService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PD_PRICE_CALC_OBJECT_NOT_CONFIGURED; /** * MES 阶梯电价测算 Service 实现类 * * @author 超级管理员 */ @Service @Validated @Slf4j public class MesPdPriceServiceImpl implements MesPdPriceService { private static final Integer CALC_TYPE_PACKAGE = 1; private static final Integer CALC_TYPE_VOLTAGE = 2; @Resource private MesPdTieredPriceMapper tieredPriceMapper; @Resource private MesPdDiscountPolicyMapper discountPolicyMapper; @Resource private MesPdServicePackageService servicePackageService; @Resource private MesPdVoltageLevelService voltageLevelService; @Override public MesPdPriceCalcRespVO calcPrice(MesPdPriceCalcReqVO reqVO) { // 1. 定位阶梯电价档位 List tiers = getTieredPrices(reqVO); if (CollUtil.isEmpty(tiers)) { throw exception(PD_PRICE_CALC_OBJECT_NOT_CONFIGURED); } // 2. 分档累计计算原价 BigDecimal quantity = reqVO.getQuantity(); BigDecimal originalPrice = BigDecimal.ZERO; List details = new ArrayList<>(); for (MesPdTieredPriceDO tier : tiers) { BigDecimal lower = tier.getStartValue(); BigDecimal upper = tier.getEndValue(); if (quantity.compareTo(lower) <= 0) { break; } BigDecimal upperBound = upper == null ? quantity : upper.min(quantity); BigDecimal tierQuantity = upperBound.subtract(lower); if (tierQuantity.signum() <= 0) { continue; } BigDecimal subtotal = tier.getPricePerUnit().multiply(tierQuantity); originalPrice = originalPrice.add(subtotal); MesPdPriceCalcDetailRespVO detail = new MesPdPriceCalcDetailRespVO(); detail.setStartValue(lower); detail.setEndValue(upper); detail.setTierQuantity(tierQuantity); detail.setPricePerUnit(tier.getPricePerUnit()); detail.setSubtotal(subtotal); details.add(detail); if (upper != null && quantity.compareTo(upper) <= 0) { break; } } // 3. 叠加优惠策略(目标专属 + 全局,取最优) BigDecimal finalPrice = originalPrice; Integer targetType = Objects.equals(CALC_TYPE_PACKAGE, reqVO.getCalcType()) ? 1 : 2; Long targetId = Objects.equals(CALC_TYPE_PACKAGE, reqVO.getCalcType()) ? reqVO.getPackageId() : reqVO.getVoltageLevelId(); List policies = discountPolicyMapper.selectListByTarget(targetType, targetId); LocalDateTime now = LocalDateTime.now(); for (MesPdDiscountPolicyDO policy : policies) { if (policy.getStartDate() != null && now.isBefore(policy.getStartDate())) { continue; } if (policy.getEndDate() != null && now.isAfter(policy.getEndDate())) { continue; } if (policy.getPolicyValue() == null) { continue; } BigDecimal candidate; if (Objects.equals(policy.getPolicyType(), 1)) { // 折扣 candidate = originalPrice.multiply(policy.getPolicyValue()); } else { // 立减 candidate = originalPrice.subtract(policy.getPolicyValue()).max(BigDecimal.ZERO); } finalPrice = finalPrice.min(candidate); } // 4. 组装返回 MesPdPriceCalcRespVO respVO = new MesPdPriceCalcRespVO(); respVO.setOriginalPrice(originalPrice); respVO.setFinalPrice(finalPrice); respVO.setDiscountAmount(originalPrice.subtract(finalPrice)); respVO.setDetails(details); if (reqVO.getPackageId() != null) { MesPdServicePackageDO pkg = servicePackageService.validateServicePackageExists(reqVO.getPackageId()); respVO.setPackageName(pkg.getName()); } if (reqVO.getVoltageLevelId() != null) { MesPdVoltageLevelDO level = voltageLevelService.validateVoltageLevelExists(reqVO.getVoltageLevelId()); respVO.setVoltageLevelName(level.getName()); } return respVO; } private List getTieredPrices(MesPdPriceCalcReqVO reqVO) { if (Objects.equals(CALC_TYPE_PACKAGE, reqVO.getCalcType()) && reqVO.getPackageId() != null) { return tieredPriceMapper.selectListByPackageId(reqVO.getPackageId()); } if (Objects.equals(CALC_TYPE_VOLTAGE, reqVO.getCalcType()) && reqVO.getVoltageLevelId() != null) { return tieredPriceMapper.selectListByVoltageLevelId(reqVO.getVoltageLevelId()); } return null; } }