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<MesPdTieredPriceDO> 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<MesPdPriceCalcDetailRespVO> 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<MesPdDiscountPolicyDO> 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<MesPdTieredPriceDO> 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;
|
}
|
|
}
|