001package top.cenze.rulepolicy.utils;
002
003import cn.hutool.core.util.ObjectUtil;
004import org.kie.api.runtime.KieSession;
005import org.springframework.stereotype.Component;
006import top.cenze.rulepolicy.entity.dto.FeeDTO;
007import top.cenze.rulepolicy.enums.TaxWayEnum;
008import top.cenze.rulepolicy.frame.utils.KieUtil;
009
010import java.math.BigDecimal;
011import java.math.RoundingMode;
012
013/**
014 * @desc: 费用规则工具
015 * @author: chengze
016 * @createByDate: 2023/8/9 15:43
017 */
018@Component
019public class FeeRuleUtil {
020    private static Integer PARAM_DEFAULT_SCALE = 6;     // 计算参数默认保留小数点位数
021    private static Integer RESULT_DEFAULT_SCALE = 2;     // 计算结果默认保留小数点位数
022
023    public static void calculate(FeeDTO dto) {
024        // 格式化参数
025        formatParam(dto);
026
027        ruleFee(dto);
028    }
029
030    /**
031     * 执行费用规则
032     * @param dto
033     */
034    public static void ruleFee(FeeDTO dto) {
035        KieSession kieSession = KieUtil.getKieBase().newKieSession();
036        kieSession.insert(dto);
037        kieSession.fireAllRules();
038        kieSession.dispose();
039    }
040
041    /**
042     * 校对计算参数,按指定小数点位数对参数进行格式化
043     * @param dto
044     */
045    private static void formatParam(FeeDTO dto) {
046        // 空值校验
047        switch (dto.getFeeRule()) {
048            case VOLUME:
049                if (ObjectUtil.isNull(dto.getVolume())) {
050                    throw new NullPointerException("volume is null");
051                }
052
053                if (ObjectUtil.isNull(dto.getVolumeScale())) {
054                    dto.setVolumeScale(PARAM_DEFAULT_SCALE);
055                }
056                dto.setVolume(dto.getVolume().setScale(dto.getVolumeScale(), RoundingMode.HALF_UP));
057                break;
058            case WEIGHT:
059                if (ObjectUtil.isNull(dto.getWeight())) {
060                    throw new NullPointerException("weigth is null");
061                }
062
063                if (ObjectUtil.isNull(dto.getWeightScale())) {
064                    dto.setWeightScale(PARAM_DEFAULT_SCALE);
065                }
066                dto.setWeight(dto.getWeight().setScale(dto.getWeightScale(), RoundingMode.HALF_UP));
067                break;
068            case QUANTITY:
069                if (ObjectUtil.isNull(dto.getQuantity())) {
070                    throw new NullPointerException("quantity is null");
071                }
072
073                if (ObjectUtil.isNull(dto.getQuantityScale())) {
074                    dto.setQuantityScale(PARAM_DEFAULT_SCALE);
075                }
076                dto.setQuantity(dto.getQuantity().setScale(dto.getQuantityScale(), RoundingMode.HALF_UP));
077                break;
078        }
079        if (ObjectUtil.isNotNull(dto.getTaxWay())) {
080            if (ObjectUtil.isNull(dto.getTaxRate())) {
081                throw new NullPointerException("taxRate is null");
082            }
083
084            if (ObjectUtil.isNull(dto.getTaxScale())) {
085                dto.setTaxScale(PARAM_DEFAULT_SCALE);
086            }
087            dto.setTaxRate(dto.getTaxRate().setScale(dto.getTaxScale(), RoundingMode.HALF_UP));
088        }
089        // 如果计税方式为空,则默认为乘法,税率为0
090        else {
091            dto.setTaxWay(TaxWayEnum.MULTIPLY);
092            dto.setTaxRate(BigDecimal.ZERO);
093        }
094        if (ObjectUtil.isNull(dto.getPrice())) {
095            throw new NullPointerException("price is null");
096        }
097
098        // 小数位格式化
099        if (ObjectUtil.isNull(dto.getScale())) {
100            dto.setScale(RESULT_DEFAULT_SCALE);
101        }
102
103        if (ObjectUtil.isNull(dto.getPriceScale())) {
104            dto.setPriceScale(PARAM_DEFAULT_SCALE);
105        }
106        dto.setPrice(dto.getPrice().setScale(dto.getPriceScale(), RoundingMode.HALF_UP));
107    }
108}