package com.prolog.rdc.tms.service.executeStrategy;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.rdc.tms.constant.BmsConstant;
import com.prolog.rdc.tms.dao.mapper.*;
import com.prolog.rdc.tms.model.dto.ShipBillPriceDTO;
import com.prolog.rdc.tms.model.dto.SySParameterDTO;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.strategy.AbstractSplitStrategyRuleHandler;
import com.prolog.rdc.tms.service.strategy.CostStrategyRuleHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.plugin.PluginException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Component
@CostStrategyRuleHandler(BmsConstant.PRICE_PROPORTION)
@Slf4j
public class ProportionPriceStrategy extends AbstractSplitStrategyRuleHandler {

    private final Logger logger = LoggerFactory.getLogger(ProportionPriceStrategy.class);

    @Autowired
    private ProportionBillStrategyMapper proportionBillStrategyMapper;
    @Autowired
    private ShipBillHeadMapper headMapper;
    @Autowired
    private ShipBillDetailMapper shipBillDetailMapper;
    @Autowired
    private MaindataFeign maindataTmsResource;
    @Autowired
    private BmsBillPayFeeDetailMapper bmsBillPayFeeDetailMapper;
    @Autowired
    private ShipBillFeeTemporaryDetailMapper temporaryDetailMapper;
    @Autowired
    private ExpenseManagementMapper managementMapper;
    @Autowired
    private ProportionBillStrategyDtlMapper dtlMapper;
    @Autowired
    private ExpenseAccountMapper expenseAccountMapper;

    /**
     * 按比例计费
     *
     * @param priceModel   计费数据
     * @param costStrategy 运单信息
     */

    @Override
    public List<ShipBillPriceDTO> executeStrategy(BmsLogisticsContractModel contractModel, BmsFreightPriceModel priceModel, BmsShipBillHeaderModel costStrategy, String source,UserEntity user) {
        logger.info("执行比例计费策略：" + JSONObject.toJSONString(costStrategy));
        // 查询合并策略
        Criteria criteria = Criteria.forClass(BmsProportionBillStrategyModel.class);
        Restriction r1 = Restrictions.eq("status", 1);
        Restriction r2 = Restrictions.eq("id", priceModel.getProportionStrategyId());
        Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2, r3));
        List<BmsProportionBillStrategyModel> models = proportionBillStrategyMapper.findByCriteria(criteria);
        if (ObjectUtil.isEmpty(models)) {
            throw new PluginException("比例策略不存在，请先配置");
        }
        BmsProportionBillStrategyModel model = models.get(0);
        // 3.查询匹配条件
        Map<String, Object> map = new HashMap<>();
        map.put("parentId", model.getId());
        map.put("enterpriseId", model.getEnterpriseId());
        List<BmsProportionBillStrategyDtlModel> dtlModels = dtlMapper.findByMap(map, BmsProportionBillStrategyDtlModel.class);

        List<BmsShipBillHeaderModel> headerModelList = Lists.newArrayList();
        // 条件 1：配送方式，2：发货方类型，3：收货放类型，4：订单类型，5：业务类型，6：运输模式，7：温度要求，8：货主，9：部门，10：商品，11：品类
        String deliveryMethodTypeResult = null;
        String[] shipperTypeResult = null;
        String[] consigneeTypeResult = null;
        String orderTypeResult = null;
        String orderBusinessTypeResult = null;
        String transportTypeResult = null;
        String temperatureRequirementResult = null;
        String[] cargoOwnerCodeResult = null;
        String[] departmentCodeResult = null;
        String[] itemCodeResult = null;
        String[] itemCategoryName = null;
        String[] vehicleTypeCodeResult = null;
        for (BmsProportionBillStrategyDtlModel billStrategyDtlModel : dtlModels) {
            int flowConditionType = billStrategyDtlModel.getFlowConditionType();
            int flowConditionValue = billStrategyDtlModel.getFlowConditionValue();
            String unitCode = billStrategyDtlModel.getUnitCode();
            String unitName = billStrategyDtlModel.getUnitName();
            // 1：配送方式
            if (flowConditionType == 1) {
                deliveryMethodTypeResult = flowConditionValue + "";
            }
            if (flowConditionType == 2) {
                if (ObjectUtil.isNotEmpty(unitCode)) {
                    shipperTypeResult = unitCode.split(",");
                }
            }
            if (flowConditionType == 3) {
                if (ObjectUtil.isNotEmpty(unitCode)) {
                    consigneeTypeResult = unitCode.split(",");
                }
            }
            if (flowConditionType == 4) {
                orderTypeResult = flowConditionValue + "";
            }
            if (flowConditionType == 5) {
                orderBusinessTypeResult = flowConditionValue + "";
            }
            if (flowConditionType == 6) {
                transportTypeResult = flowConditionValue + "";
            }
            if (flowConditionType == 7) {
                temperatureRequirementResult = flowConditionValue + "";
            }
            if (flowConditionType == 8) {
                if (ObjectUtil.isNotEmpty(unitCode)) {
                    cargoOwnerCodeResult = unitCode.split(",");
                }
            }
            if (flowConditionType == 9) {
                if (ObjectUtil.isNotEmpty(unitCode)) {
                    departmentCodeResult = unitCode.split(",");
                }
            }
            if (flowConditionType == 10) {
                if (ObjectUtil.isNotEmpty(unitCode)) {
                    itemCodeResult = unitCode.split(",");
                }
            }
            if (flowConditionType == 11) {
                if (ObjectUtil.isNotEmpty(unitName)) {
                    itemCategoryName = unitName.split(",");
                }
            }
            if (flowConditionType == 12) {
                if (ObjectUtil.isNotEmpty(unitCode)) {
                    vehicleTypeCodeResult = unitCode.split(",");
                }
            }
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Criteria sCriteria = Criteria.forClass(BmsShipBillHeaderModel.class);
        Restriction r4 = null;
        Restriction r5 = null;
        Restriction r6 = null;
        Restriction r7 = null;
        Restriction r8 = null;
        Restriction r9 = null;
        Restriction r10 = null;
        Restriction r11 = null;
        Restriction r12 = null;
        Restriction r13 = null;
        Restriction r27 = null;
        Restriction r26 = null;
        Integer isSameShipbillNo = model.getIsSameShipbillNo();
        if (ObjectUtil.isNotEmpty(isSameShipbillNo) && isSameShipbillNo == 1) {
            r26 = Restrictions.eq("shipbillNo", costStrategy.getShipbillNo());
        } else {

            Integer isSameBillNo = model.getIsSameBillNo();
            if (isSameBillNo == 1) {
                // 相同单号
                String orderNo = costStrategy.getOrderNo();
                r4 = Restrictions.eq("orderNo", orderNo);
            }

            Integer isSameWmsNo = model.getIsSameWmsNo();
            if (isSameWmsNo == 1) {
                // 相同的wms单号
                String wmsOrderNo = costStrategy.getWmsOrderNo();
                r5 = Restrictions.eq("wmsOrderNo", wmsOrderNo);
            }
            Integer isStartDate = model.getIsStartDate();
            if (isStartDate == 1) {
                // 相同启运时间
                Date departureTime = costStrategy.getStartDate();
                if (ObjectUtil.isNotEmpty(departureTime)) {
                    String format = sdf.format(departureTime);
                    r6 = Restrictions.between("startDate", format + " 00:00:00", format + " 23:59:59");
                } else {
                    throw new PluginException("启运时间匹配不到数据");
                }
            }
            Integer isSameCar = model.getIsSameCar();
            if (isSameCar == 1) {
                // 相同的车辆
                if (ObjectUtil.isEmpty(costStrategy.getVehicleCode())) {
                    throw new PluginException("车辆编号不能为空");
                }
                String vehicleCode = costStrategy.getVehicleCode();
                r7 = Restrictions.eq("vehicleCode", vehicleCode);
            }
            Integer isSameDriver = model.getIsSameDriver();
            if (isSameDriver == 1) {
                // 相同的司机
                if (ObjectUtil.isEmpty(costStrategy.getDriverCode())) {
                    throw new PluginException("司机不能为空");
                }
                String driverCode = costStrategy.getDriverCode();
                r8 = Restrictions.eq("driverCode", driverCode);
            }
            Integer isSameSender = model.getIsSameSender();
            if (isSameSender == 1) {
                // 相同发货方
                if (ObjectUtil.isEmpty(costStrategy.getShipperCode())) {
                    throw new PluginException("相同发货方不能为空");
                }
                String shipperCode = costStrategy.getShipperCode();
                r9 = Restrictions.eq("shipperCode", shipperCode);
            }
            Integer isSameReceive = model.getIsSameReceive();
            if (isSameReceive == 1) {
                // 相同收货方
                if (ObjectUtil.isEmpty(costStrategy.getShipperCode())) {
                    throw new PluginException("相同收货方不能为空");
                }
                r10 = Restrictions.eq("consigneeUnitCode", costStrategy.getConsigneeUnitCode());
            }
            Integer isSameEndDate = model.getIsSameEndDate();
            if (isSameEndDate == 1) {
                // 相同实际送达日期
                Date deliveryDate = costStrategy.getDeliveryDate();
                if (ObjectUtil.isNotEmpty(deliveryDate)) {
                    String format = sdf.format(deliveryDate);
                    r11 = Restrictions.between("deliveryDate", format + " 00:00:00", format + " 23:59:59");
                } else {
                    throw new PluginException("实际送达日期匹配不到数据");
                }
            }
            Integer isSameElectronicBackDate = model.getIsSameElectronicBackDate();
            if (isSameElectronicBackDate == 1) {
                // 相同电子回单日期
                Date receiptDate = costStrategy.getReceiptDate();
                if (ObjectUtil.isNotEmpty(receiptDate)) {
                    String format = sdf.format(receiptDate);
                    r12 = Restrictions.between("receiptDate", format + " 00:00:00", format + " 23:59:59");
                } else {
                    throw new PluginException("电子回单日期匹配不到数据");
                }
            }
            int isSameOriginalBackDate = model.getIsSameOriginalBackDate() == null ? 0 : model.getIsSameOriginalBackDate();
            if (isSameOriginalBackDate == 1) {
                // 相同正本回单日期
                Date originalBackDate = costStrategy.getOriginalBackDate();
                if (ObjectUtil.isNotEmpty(originalBackDate)) {
                    String format = sdf.format(originalBackDate);
                    r13 = Restrictions.between("originalBackDate", format + " 00:00:00", format + " 23:59:59");
                } else {
                    throw new PluginException("正本回单日期匹配不到数据");
                }
            }
            // 相同承运商
            int isSameCarrier = model.getIsSameCarrier() == null ? 0 : model.getIsSameCarrier();
            if (isSameCarrier == 1) {
                if (costStrategy.getCarrierType().intValue() == 1) {
                    // 相同承运商
                    String carrierCode = costStrategy.getCarrierCode();
                    if (ObjectUtil.isEmpty(carrierCode)) {
                        throw new PluginException("相同承运商匹配不到数据");
                    }
                    r27 = Restrictions.eq("carrierCode", carrierCode);
                } else if (costStrategy.getCarrierType().intValue() == 2) {
                    String affiliationCode = costStrategy.getAffiliationCode();
                    if (ObjectUtil.isEmpty(affiliationCode)) {
                        throw new PluginException("相同承运商匹配不到数据");
                    }
                    r27 = Restrictions.eq(BmsShipBillHeaderModel::getAffiliationCode, affiliationCode);
                }
            }
            r26 = Restrictions.ne("shipbillNo", costStrategy.getShipbillNo());
        }
        Restriction r14 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        Restriction r15 = ObjectUtil.isEmpty(deliveryMethodTypeResult) ? null : Restrictions.eq("deliveryMethodType", deliveryMethodTypeResult);
        Restriction r16 = ObjectUtil.isEmpty(shipperTypeResult) ? null : Restrictions.in("shipperUnitCode", shipperTypeResult);
        Restriction r17 = ObjectUtil.isEmpty(consigneeTypeResult) ? null : Restrictions.in("consigneeUnitCode", consigneeTypeResult);
        Restriction r18 = ObjectUtil.isEmpty(orderTypeResult) ? null : Restrictions.eq("orderType", orderTypeResult);
        Restriction r19 = ObjectUtil.isEmpty(orderBusinessTypeResult) ? null : Restrictions.eq("orderBusinessType", orderBusinessTypeResult);
        Restriction r20 = ObjectUtil.isEmpty(transportTypeResult) ? null : Restrictions.eq("transportType", transportTypeResult);
        Restriction r21 = ObjectUtil.isEmpty(temperatureRequirementResult) ? null : Restrictions.eq("temperatureRequirement", temperatureRequirementResult);
        Restriction r22 = ObjectUtil.isEmpty(cargoOwnerCodeResult) ? null : Restrictions.eq("cargoOwnerCode", cargoOwnerCodeResult);
        Restriction r25 = ObjectUtil.isEmpty(departmentCodeResult) ? null : Restrictions.eq(BmsShipBillHeaderModel::getSettlementDepartmentCode, departmentCodeResult);
        Restriction r28 = ObjectUtil.isEmpty(vehicleTypeCodeResult) ? null : Restrictions.in(BmsShipBillHeaderModel::getVehicleTypeCode, vehicleTypeCodeResult);
        sCriteria.setRestriction(Restrictions.and(r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r25, r26, r27,r28));
        List<BmsShipBillHeaderModel> shipBillHeaderModels = headMapper.findByCriteria(sCriteria);
        if (ObjectUtil.isEmpty(shipBillHeaderModels)) {
            throw new PluginException("查询比例数据不存在");
        } else if (1 < shipBillHeaderModels.size() && ObjectUtil.isNotEmpty(isSameShipbillNo) &&  isSameShipbillNo == 1)  {
            throw new PluginException("相同运单比例策略时,查询多条比例数据");
        }
        // 判断商品
        Map<String, List<BmsShipBillHeaderModel>> listMap = shipBillHeaderModels.stream().collect(Collectors.groupingBy(BmsShipBillHeaderModel::getShipbillNo));
        for (List<BmsShipBillHeaderModel> headerModels : listMap.values()) {
            String shipbillNo = headerModels.get(0).getShipbillNo();
            Criteria aClass = Criteria.forClass(BmsShipBillDetailModel.class);
            Restriction r30 = ObjectUtil.isEmpty(itemCodeResult) ? null : Restrictions.in(BmsShipBillDetailModel::getItemCode, itemCodeResult);
            Restriction r31 = Restrictions.eq("shipbillNo", shipbillNo);
            Restriction r32 = ObjectUtil.isEmpty(itemCategoryName) ? null : Restrictions.in("itemCategoryName", itemCategoryName);
            aClass.setRestriction(Restrictions.and(r30, r31, r32));
            List<BmsShipBillDetailModel> detailModels = shipBillDetailMapper.findByCriteria(aClass);
            if (ObjectUtil.isNotEmpty(detailModels)) {
                headerModelList.addAll(headerModels);
            }
        }
        if (ObjectUtil.isNotEmpty(itemCodeResult) && ObjectUtil.isNotEmpty(itemCategoryName) ) {
            headerModelList.addAll(shipBillHeaderModels);
            headerModelList = headerModelList.stream().distinct().collect(Collectors.toList());
        }
        if (ObjectUtil.isEmpty(headerModelList) || headerModelList.size() < 1) {
            throw new PluginException("查询比例数据不存在");
        }
        if (headerModelList.size() > 1) {
            throw new PluginException("匹配到多个比例参照");
        }
        BmsShipBillHeaderModel headerModel = headerModelList.get(0);
        BigDecimal price = headerModel.getTransportationPrice() == null ? BigDecimal.valueOf(0) : headerModel.getTransportationPrice();
        BmsProportionBillStrategyModel bmsProportionBillStrategyModel = models.get(0);
        List<ShipBillPriceDTO> list = Lists.newArrayList();
        if (ObjectUtil.isNotEmpty(bmsProportionBillStrategyModel.getRatio()) || ObjectUtil.isNotEmpty(bmsProportionBillStrategyModel.getRatioDenominator())) {
            BigDecimal bigDecimal = BigDecimal.ZERO;
            if (ObjectUtil.isNotEmpty(bmsProportionBillStrategyModel.getRatio())) {
                bigDecimal = price.multiply(new BigDecimal(bmsProportionBillStrategyModel.getRatio()));
            } else if (ObjectUtil.isNotEmpty(bmsProportionBillStrategyModel.getRatioNumerator())) {
                BigDecimal ratio = NumberUtil.div(bmsProportionBillStrategyModel.getRatioNumerator(),bmsProportionBillStrategyModel.getRatioDenominator());
                bigDecimal = price.multiply(ratio);
            }
            ShipBillPriceDTO dto = new ShipBillPriceDTO();
            dto.setShipbillNo(costStrategy.getShipbillNo());
            dto.setPrice(bigDecimal);
            dto.setCostContract(contractModel.getContractName());
            dto.setCostPriceTable(priceModel.getPriceName());
            dto.setFirstPartyId(contractModel.getFirstPartyId());
            dto.setFirstPartyCode(contractModel.getFirstPartyCode());
            dto.setFirstPartyName(contractModel.getFirstPartyName());

            this.saveFee(isSameShipbillNo, costStrategy, contractModel, priceModel, user, headerModel, source, bmsProportionBillStrategyModel);
            list.add(dto);
        }

        return list;
    }

    private void saveFee(Integer isSameShipbillNo, BmsShipBillHeaderModel costStrategy, BmsLogisticsContractModel contractModel, BmsFreightPriceModel priceModel, UserEntity user, BmsShipBillHeaderModel headerModel, String source, BmsProportionBillStrategyModel bmsProportionBillStrategyModel) {
        // 通过匹配到的运单查询对应的费用
        Criteria dcriteria = Criteria.forClass(BmsBillPayFeeDetailModel.class);
        Restriction r5 = Restrictions.eq(BmsBillPayFeeDetailModel::getBillNo, headerModel.getShipbillNo());
        Restriction r15 = Restrictions.eq(BmsBillPayFeeDetailModel::getBillId, headerModel.getId());
        Restriction r6 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        dcriteria.setRestriction(Restrictions.and(r5, r6,r15));
        List<BmsBillPayFeeDetailModel> detailModels = bmsBillPayFeeDetailMapper.findByCriteria(dcriteria);
        // 获取参照费用
        Map<String, List<BmsBillPayFeeDetailModel>> listMap = detailModels.stream().collect(Collectors.groupingBy(BmsBillPayFeeDetailModel::getExpenseCode));
        // 新增费用信息
        BmsBillPayFeeDetailModel feeDetailModel = new BmsBillPayFeeDetailModel();
        RestMessage<String> expenseNo = maindataTmsResource.getCodeNumberByCode(BmsConstant.SHIP_BILL_EXPENSE_NO, "L");
        if (!expenseNo.isSuccess() || ObjectUtil.isEmpty(expenseNo)) {
            throw new PluginException("获取费用单号为空");
        }
        feeDetailModel.setExpenseNo(expenseNo.getData());
        feeDetailModel.setBillNo(costStrategy.getShipbillNo());
        feeDetailModel.setBillNo(costStrategy.getShipbillNo());
        feeDetailModel.setBillId(costStrategy.getId());
        feeDetailModel.setPayFeeType(1);
        feeDetailModel.setBillingSource(1);
        feeDetailModel.setBillingStatus(1);
        feeDetailModel.setBillingDate(DateUtil.date());
        feeDetailModel.setBillingContract(contractModel.getContractName());
        feeDetailModel.setBillingPrice(priceModel.getPriceName());

        String expenseName = priceModel.getExpenseName();
        Criteria forClass = Criteria.forClass(BmsExpenseManagementModel.class);
        Restriction r7 = Restrictions.eq("status", 1);
        Restriction r8 = Restrictions.eq("expenseName", expenseName);
        Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        forClass.setRestriction(Restrictions.and(r7, r8, r9));
        List<BmsExpenseManagementModel> managementModels = managementMapper.findByCriteria(forClass);
        if (ObjectUtil.isEmpty(managementModels)) {
            throw new PluginException("获取费用信息失败");
        }
        BmsExpenseManagementModel managementModel = managementModels.get(0);
        feeDetailModel.setExpenseCode(managementModel.getExpenseCode());
        feeDetailModel.setExpenseName(managementModel.getExpenseName());
        feeDetailModel.setExpenseAccountCode(managementModel.getExpenseAccountCode());
        feeDetailModel.setExpenseAccountName(managementModel.getExpenseAccountName());
        // 支出，收入
        String expenseAccountCode = managementModel.getExpenseAccountCode();
        Criteria aClass = Criteria.forClass(ExpenseAccountModel.class);
        Restriction r11 = Restrictions.eq("expenseCode", expenseAccountCode);
        Restriction r12 = Restrictions.eq("status", 1);
        aClass.setRestriction(Restrictions.and(r11, r12));
        List<ExpenseAccountModel> mapper = expenseAccountMapper.findByCriteria(aClass);
        if (ObjectUtil.isNotEmpty(mapper)) {
            feeDetailModel.setExpenseType(mapper.get(0).getExpenseClassify());
            feeDetailModel.setExpenseTypeName(Objects.equals(mapper.get(0).getExpenseClassify(), 1) ? "收入" : "支出");
        }
        RestMessage<SySParameterDTO> parameterModel = maindataTmsResource.queryParameter();
        int taxPoint = Integer.parseInt(contractModel.getTaxPoint());
        // 当前 费用名称，是运费还是提货费
        String expenseCode = managementModel.getExpenseCode();
        if (ObjectUtil.isNotEmpty(isSameShipbillNo) &&  isSameShipbillNo == 1) {
            expenseCode = "运费";
        }
        // 根据参照物的费用类型计算
        List<BmsBillPayFeeDetailModel> feeDetailModels = listMap.get(expenseCode);
        if (ObjectUtil.isEmpty(feeDetailModels)) {
            return;
        }
        BmsBillPayFeeDetailModel detailModel = feeDetailModels.get(0);
        // 比例
        BigDecimal ratio = BigDecimal.ZERO;
        if (ObjectUtil.isNotEmpty(bmsProportionBillStrategyModel.getRatio())) {
            ratio = new BigDecimal(bmsProportionBillStrategyModel.getRatio());
        } else if (ObjectUtil.isNotEmpty(bmsProportionBillStrategyModel.getRatioDenominator())) {
            ratio = NumberUtil.div(bmsProportionBillStrategyModel.getRatioNumerator(),bmsProportionBillStrategyModel.getRatioDenominator());
        }
        if (ObjectUtil.isNotEmpty(parameterModel) && parameterModel.isSuccess()) {
            // 1：含税，2：未税
            Integer isTax = parameterModel.getData().getIsTax();

            BigDecimal point = BigDecimal.valueOf(taxPoint).divide(BigDecimal.valueOf(100), 5, RoundingMode.HALF_UP).add(BigDecimal.valueOf(1));
            Integer costPrecision = parameterModel.getData().getCostPrecision();
            Integer costInteger = parameterModel.getData().getCostInteger();
            if (isTax == 1) {
                BigDecimal taxAmt = new BigDecimal(0);
                // 四舍五入
                if (costInteger == 1) {
                    // 含税金额
                    taxAmt = detailModel.getTaxAmt().multiply(ratio).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.HALF_UP);
                    // 未税金额*（1 + 税点） = 含税金额
                    feeDetailModel.setNoTaxAmt(taxAmt.divide(point, costPrecision, RoundingMode.HALF_UP));
                }
                // 向上取整
                if (costInteger == 2) {
                    taxAmt = detailModel.getTaxAmt().multiply(ratio).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.UP);
                    feeDetailModel.setNoTaxAmt(taxAmt.divide(point, costPrecision, RoundingMode.UP));
                }
                // 向上取整
                if (costInteger == 3) {
                    taxAmt = detailModel.getTaxAmt().multiply(ratio).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.DOWN);
                    feeDetailModel.setNoTaxAmt(taxAmt.divide(point, costPrecision, RoundingMode.DOWN));
                }
                feeDetailModel.setTaxAmt(taxAmt);
                feeDetailModel.setTax(taxAmt.subtract(feeDetailModel.getNoTaxAmt()));
            } else {
                // 未税金额
                // 四舍五入
                if (costInteger == 1) {
                    BigDecimal noTaxAmt = detailModel.getNoTaxAmt().multiply(ratio).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.HALF_UP);
                    feeDetailModel.setNoTaxAmt(noTaxAmt);
                    // 含税金额 = 未税金额*（1 + 税点）
                    feeDetailModel.setTaxAmt(noTaxAmt.multiply(point).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.HALF_UP));
                }
                // 向上取整
                if (costInteger == 2) {
                    BigDecimal noTaxAmt = detailModel.getNoTaxAmt().multiply(ratio).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.UP);
                    feeDetailModel.setNoTaxAmt(noTaxAmt);
                    feeDetailModel.setTaxAmt(noTaxAmt.multiply(point).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.UP));
                }
                // 向上取整
                if (costInteger == 3) {
                    BigDecimal noTaxAmt = detailModel.getNoTaxAmt().multiply(ratio).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.DOWN);
                    feeDetailModel.setNoTaxAmt(noTaxAmt);
                    feeDetailModel.setTaxAmt(noTaxAmt.multiply(point).divide(BigDecimal.valueOf(1), costPrecision, RoundingMode.DOWN));
                }

                feeDetailModel.setTax(feeDetailModel.getTaxAmt().subtract(feeDetailModel.getNoTaxAmt()));
            }
        } else {
            throw new PluginException("系统参数未配置");
        }
        feeDetailModel.setBillingType("");
        feeDetailModel.setCreateperson(user.getNickname());
        feeDetailModel.setCreatetime(DateUtil.date());
        feeDetailModel.setUpdateperson(user.getNickname());
        feeDetailModel.setUpdatetime(DateUtil.date());
        feeDetailModel.setEnterpriseId(user.getEnterpriseId());
        feeDetailModel.setEnterpriseName(user.getEnterpriseName());
        feeDetailModel.setExpenseStatus(2);
        feeDetailModel.setCheckStatus(0);
        // 0：试验，1：非试验
        if (source.equals("0")) {
            BmsShipBillFeeTemporaryDetailModel temporaryDetailModel = new BmsShipBillFeeTemporaryDetailModel();
            BeanUtils.copyProperties(feeDetailModel, temporaryDetailModel);
            temporaryDetailMapper.save(temporaryDetailModel);
        } else {
            bmsBillPayFeeDetailMapper.save(feeDetailModel);
        }
    }

}