package com.ruoyi.warehouseBusiness.service.impl;


import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.approvalFlow.domain.AuditItems;
import com.ruoyi.approvalFlow.service.impl.AuditItemsServiceImpl;
import com.ruoyi.basicData.domain.TCorps;
import com.ruoyi.basicData.domain.TFees;
import com.ruoyi.basicData.mapper.TCorpsMapper;
import com.ruoyi.basicData.mapper.TFeesMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.WarehouseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.warehouseBusiness.domain.BillnoDel;
import com.ruoyi.warehouseBusiness.domain.TAnnex;
import com.ruoyi.warehouseBusiness.domain.TWarehouseAgreement;
import com.ruoyi.warehouseBusiness.domain.TWarehouseAgreementitems;
import com.ruoyi.warehouseBusiness.domain.dto.CalculateStorageFeesDTO;
import com.ruoyi.warehouseBusiness.domain.dto.StorageFeeRangeDTO;
import com.ruoyi.warehouseBusiness.domain.enums.AnnexActEnum;
import com.ruoyi.warehouseBusiness.domain.enums.WarehouseTypeEnum;
import com.ruoyi.warehouseBusiness.domain.vo.StorageFeeCalculationResultVO;
import com.ruoyi.warehouseBusiness.mapper.BillnoDelMapper;
import com.ruoyi.warehouseBusiness.mapper.TAnnexMapper;
import com.ruoyi.warehouseBusiness.mapper.TWarehouseAgreementMapper;
import com.ruoyi.warehouseBusiness.mapper.TWarehouseAgreementitemsMapper;
import com.ruoyi.warehouseBusiness.service.ITWarehouseAgreementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * 仓储费Service业务层处理
 *
 * @author ruoyi
 * @date 2020-12-11
 */
@Service
public class TWarehouseAgreementServiceImpl implements ITWarehouseAgreementService {
    @Autowired
    private TWarehouseAgreementMapper tWarehouseAgreementMapper;

    @Autowired
    private TWarehouseAgreementitemsMapper tWarehouseAgreementitemsMapper;

    @Autowired
    private BillnoSerialServiceImpl billnoSerialServiceImpl;

    @Autowired
    private BillnoDelMapper billnoDelMapper;

    @Autowired
    private TCorpsMapper tCorpsMapper;

    @Autowired
    private TAnnexMapper annexMapper;

    @Autowired
    private TFeesMapper tFeesMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysConfigMapper sysConfigMapper;

    @Autowired
    private AuditItemsServiceImpl auditItemsService;


    /**
     * 查询仓储费
     *
     * @param fId 仓储费ID
     * @return 仓储费
     */
    @Override
    public TWarehouseAgreement selectTWarehouseAgreementById(Long fId) {
        return tWarehouseAgreementMapper.selectTWarehouseAgreementById(fId);
    }

    @Override
    public Map<String, Object> selectTWarehouseAgreementById1(Long fId) {
        Map<String, Object> map = new HashMap<>();
        // 查询协议主表数据
        TWarehouseAgreement tWarehouseAgreement = tWarehouseAgreementMapper.selectTWarehouseAgreementById(fId);
        // 客户表
        List<Long> corpsId = new ArrayList<>();
        // 费用
        List<Long> feesId = new ArrayList<>();
        if (!StringUtils.isNull(tWarehouseAgreement)) {
            corpsId.add(tWarehouseAgreement.getfCorpid());
            map.put("tWarehouseAgreement", tWarehouseAgreement);
        }
        // 协议从表
        TWarehouseAgreementitems tWarehouseAgreementitems = new TWarehouseAgreementitems();
        tWarehouseAgreementitems.setfPid(fId);
        List<TWarehouseAgreementitems> tWarehouseAgreementitemss = tWarehouseAgreementitemsMapper.selectTWarehouseAgreementitemsList(tWarehouseAgreementitems);
        if (StringUtils.isNotEmpty(tWarehouseAgreementitemss)) {
            for (TWarehouseAgreementitems fees : tWarehouseAgreementitemss) {
                feesId.add(fees.getfFeeid());
            }
        }
        // 附件
        Long type;
        if (tWarehouseAgreement.getfFeetypeid() < 1) {
            type = AnnexActEnum.STORAGE_FEE.getType();
        } else {
            type = AnnexActEnum.HOMEWORK_FEE.getType();
        }
        TAnnex annex = new TAnnex();
        annex.setfPid(fId);
        annex.setfActid(type);
        List<TAnnex> annexList = annexMapper.selectTAnnexList(annex);
        if (StringUtils.isNotEmpty(annexList)) {
            map.put("attachList", annexList);
        }
        List<TCorps> corpsList = new ArrayList<>();
        List<Long> corpsIdList = StringUtils.integerDeduplication(corpsId);
        for (Long corpId : corpsIdList) {
            TCorps corps = tCorpsMapper.selectTCorpsById(corpId);
            if (StringUtils.isNotNull(corps)) {
                corpsList.add(corps);
            }
        }
        List<TFees> feesList = new ArrayList<>();
        List<Long> longList = StringUtils.integerDeduplication(feesId);
        for (Long fees : longList) {
            TFees tFees = tFeesMapper.selectTFeesById(fees);
            if (StringUtils.isNotNull(tFees)) {
                feesList.add(tFees);
            }
        }
        map.put("corps", corpsList);
        map.put("feesList", feesList);
        map.put("tWarehouseAgreementitems", tWarehouseAgreementitemss);
        map.put("dept", sysDeptMapper.selectDeptById(tWarehouseAgreement.getfDeptid()));
        return map;
    }


    /**
     * 查询仓储费列表
     *
     * @param tWarehouseAgreement 仓储费
     * @return 仓储费
     */
    @Override
    public List<Map<String, Object>> selectTWarehouseAgreementList1(TWarehouseAgreement tWarehouseAgreement) {
        return tWarehouseAgreementMapper.selectTWarehouseAgreementList1(tWarehouseAgreement);
    }

    /**
     * 查询仓储费列表
     *
     * @param tWarehouseAgreement 仓储费
     * @return 仓储费
     */
    @Override
    public List<TWarehouseAgreement> selectTWarehouseAgreementList(TWarehouseAgreement tWarehouseAgreement) {
        return tWarehouseAgreementMapper.selectTWarehouseAgreementList(tWarehouseAgreement);
    }


    /**
     * 新增
     *
     * @param agreement
     * @param agreementitems
     * @param loginUser
     * @return
     */
    @Override
    @Transactional
    public AjaxResult insertTWarehouseAgreement(String agreement, String agreementitems, String attachments, LoginUser loginUser, int fFeetypeid) {
        Long fPid;
        Long type;
        Map<String, Object> map = new HashMap<>();
        if (fFeetypeid < 1) {
            type = AnnexActEnum.STORAGE_FEE.getType();
        } else {
            type = AnnexActEnum.HOMEWORK_FEE.getType();
        }
        TWarehouseAgreement tWarehouseAgreement = JSONArray.parseObject(agreement, TWarehouseAgreement.class);
        if (StringUtils.isNull(tWarehouseAgreement.getfId())) {
            // 如果是新数据
            tWarehouseAgreement.setCreateBy(loginUser.getUser().getUserName());
            tWarehouseAgreement.setCreateTime(new Date());
            // 业务编码
            String billNo = billnoSerialServiceImpl.getBillNo("WA", new Date());
            tWarehouseAgreement.setfBillno(billNo);
            tWarehouseAgreement.setfDeptid(loginUser.getUser().getDeptId());
            tWarehouseAgreement.setfFeetypeid((long) fFeetypeid);
            tWarehouseAgreement.setfStatus("1"); // 停用
            tWarehouseAgreement.setfBillstatus("2"); // 暂存
            tWarehouseAgreementMapper.insertTWarehouseAgreement(tWarehouseAgreement);
            fPid = tWarehouseAgreement.getfId();
        } else {
            fPid = tWarehouseAgreement.getfId();
            tWarehouseAgreement.setfBillstatus("2");
            tWarehouseAgreement.setUpdateBy(loginUser.getUser().getUserName());
            tWarehouseAgreement.setUpdateTime(new Date());
            tWarehouseAgreementMapper.updateTWarehouseAgreement(tWarehouseAgreement);
            tWarehouseAgreementitemsMapper.deleteByFPid(fPid);
            annexMapper.deleteByPid(fPid, type);
        }
        //  从表添加
        if (StringUtils.isNotNull(agreementitems) && !"[]".equals(agreementitems)) {
            JSONArray jsonDrArray = JSONArray.parseArray(agreementitems);
            List<TWarehouseAgreementitems> tWarehouseAgreementitemsList = JSONObject.parseArray(jsonDrArray.toJSONString(), TWarehouseAgreementitems.class);
            for (TWarehouseAgreementitems tWarehouseAgreementitems : tWarehouseAgreementitemsList) {
                tWarehouseAgreementitems.setfPid(fPid);
                tWarehouseAgreementitems.setCreateBy(loginUser.getUser().getUserName());
                tWarehouseAgreementitems.setCreateTime(new Date());
                tWarehouseAgreementitemsMapper.insertTWarehouseAgreementitems(tWarehouseAgreementitems);
            }
        }
        //  附件添加
        if (StringUtils.isNotNull(attachments) && !"[]".equals(attachments)) {
            JSONArray jsonDrArray = JSONArray.parseArray(attachments);
            List<TAnnex> annexList = JSONObject.parseArray(jsonDrArray.toJSONString(), TAnnex.class);
            annexList.forEach(li -> {
                li.setfPid(fPid);
                li.setfActid(type);
                if (Objects.nonNull(li.getfId())) {
                    li.setCreateTime(new Date());
                    li.setCreateBy(loginUser.getUsername());
                } else {
                    li.setUpdateTime(new Date());
                    li.setUpdateBy(loginUser.getUsername());
                }
                annexMapper.insertTAnnex(li);
            });
            map.put("attachList", annexList);
        }
        TWarehouseAgreementitems tWarehouseAgreementitems = new TWarehouseAgreementitems();
        tWarehouseAgreementitems.setfPid(fPid);
        map.put("tWarehouseAgreement", tWarehouseAgreement);
        map.put("tWarehouseAgreementitems", tWarehouseAgreementitemsMapper.selectTWarehouseAgreementitemsList(tWarehouseAgreementitems));
        return AjaxResult.success("成功", map);
    }

    /**
     * 仓储费请核
     *
     * @param agreement
     * @param agreementitems
     * @param loginUser
     * @param fFeetypeid
     * @return
     */
    @Override
    @Transactional
    public AjaxResult tWarehouseAgreementSubmit(String agreement, String agreementitems, String attachments, LoginUser loginUser, int fFeetypeid) {
        Long fPid;
        Long type;
        Map<String, Object> map = new HashMap<>();
        if (fFeetypeid < 1) {
            type = AnnexActEnum.STORAGE_FEE.getType();
        } else {
            type = AnnexActEnum.HOMEWORK_FEE.getType();
        }
        TWarehouseAgreement tWarehouseAgreement = JSONArray.parseObject(agreement, TWarehouseAgreement.class);
        if (StringUtils.isNull(tWarehouseAgreement.getfId())) {
            // 如果是新数据
            tWarehouseAgreement.setCreateBy(loginUser.getUser().getUserName());
            // 业务编码
            String billNo = billnoSerialServiceImpl.getBillNo("WA", new Date());
            tWarehouseAgreement.setfBillno(billNo);
            tWarehouseAgreement.setCreateBy(loginUser.getUser().getUserName());
            tWarehouseAgreement.setfDeptid(loginUser.getUser().getDeptId());
            tWarehouseAgreement.setfFeetypeid((long) fFeetypeid);
            tWarehouseAgreement.setfStatus("1"); // 停用
            tWarehouseAgreement.setfBillstatus("4");
            tWarehouseAgreementMapper.insertTWarehouseAgreement(tWarehouseAgreement);
            fPid = tWarehouseAgreement.getfId();
        } else {
            fPid = tWarehouseAgreement.getfId();
            tWarehouseAgreement.setfBillstatus("4");
            tWarehouseAgreement.setUpdateBy(loginUser.getUser().getUserName());
            tWarehouseAgreement.setUpdateTime(new Date());
            tWarehouseAgreementMapper.updateTWarehouseAgreement(tWarehouseAgreement);
            tWarehouseAgreementitemsMapper.deleteByFPid(fPid);
            annexMapper.deleteByPid(fPid, type);
        }
        //  从表添加
        if (StringUtils.isNotNull(agreementitems) && !"[]".equals(agreementitems)) {
            JSONArray jsonDrArray = JSONArray.parseArray(agreementitems);
            List<TWarehouseAgreementitems> tWarehouseAgreementitemsList = JSONObject.parseArray(jsonDrArray.toJSONString(), TWarehouseAgreementitems.class);
            for (TWarehouseAgreementitems tWarehouseAgreementitems : tWarehouseAgreementitemsList) {
                tWarehouseAgreementitems.setfPid(fPid);
                tWarehouseAgreementitems.setCreateBy(loginUser.getUser().getUserName());
                tWarehouseAgreementitems.setCreateTime(new Date());
                tWarehouseAgreementitemsMapper.insertTWarehouseAgreementitems(tWarehouseAgreementitems);
            }
        }
        //  附件添加
        if (StringUtils.isNotNull(attachments) && !"[]".equals(attachments)) {
            JSONArray jsonDrArray = JSONArray.parseArray(attachments);
            List<TAnnex> annexList = JSONObject.parseArray(jsonDrArray.toJSONString(), TAnnex.class);
            annexList.forEach(li -> {
                li.setfPid(fPid);
                li.setfActid(type);
                if (Objects.nonNull(li.getfId())) {
                    li.setCreateTime(new Date());
                    li.setCreateBy(loginUser.getUsername());
                } else {
                    li.setUpdateTime(new Date());
                    li.setUpdateBy(loginUser.getUsername());
                }
                annexMapper.insertTAnnex(li);
            });
            map.put("attachList", annexList);
        }
        // 这里加个判断取系统参数来确定是否需要启用审批流
        String key = "";
        boolean isApprove = false;
        long actId = 0L;
        if (fFeetypeid == 0) {
            actId = 310L;
            key = "warehouse.storage.ApprovalFlow";
        } else if (fFeetypeid == 1) {
            actId = 320L;
            key = "warehouse.task.ApprovalFlow";
        }
        SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique(key);
        if (StringUtils.isNull(sysConfig)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("系统参数异常，未找到开启审批流参数");
        }
        if ("0".equals(sysConfig.getConfigValue())) {
            isApprove = true;
        }
        if (isApprove) {
            AuditItems auditItems = new AuditItems();
            auditItems.setLevelId(0L);
            auditItems.setBillId(fPid);
            auditItems.setActId(actId);
            auditItems.setFidStatus("f_billstatus");
            auditItems.setTimes(1L);
            auditItems.setIffinalItem("F");
            auditItems.setBillNo(tWarehouseAgreement.getfBillno());
            auditItems.setRefno1(String.valueOf(tWarehouseAgreement.getfCorpid()));
            if (fFeetypeid == 0) {
                auditItems.setRefno2("CCF");// 存储业务类型（业务类型）
            } else {
                auditItems.setRefno2("ZYF");// 存储业务类型（业务类型）
            }
            auditItems.setSendUserId(loginUser.getUser().getUserId());
            auditItems.setSendName(loginUser.getUsername());
            auditItems.setSendTime(new Date());
            auditItems.setAuditUserId(loginUser.getUser().getUserId());
            auditItems.setAuditItem(new Date());
            auditItems.setAuditOpTime(new Date());
            auditItems.setAuditMsg("提交");
            auditItems.setAuditStatus("O");
            AjaxResult approvalFlow = auditItemsService.createApprovalFlow(auditItems);
            Long code = Long.valueOf(String.valueOf(approvalFlow.get("code"))).longValue();
            if (code.equals(500L)) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
            return approvalFlow;
        } else {
            AjaxResult ajaxResult = agreementFollow(fPid, 6L);
            Long code = Long.valueOf(String.valueOf(ajaxResult.get("code"))).longValue();
            return ajaxResult;
        }
    }

    @Override
    public AjaxResult revoke(String agreement, String agreementitems, LoginUser loginUser, int fFeetypeid) {
        Long fPid = null;
        TWarehouseAgreement tWarehouseAgreement = JSONArray.parseObject(agreement, TWarehouseAgreement.class);
        fPid = tWarehouseAgreement.getfId();
        tWarehouseAgreement.setfStatus("1"); // 停用
        tWarehouseAgreement.setfBillstatus("2");// 暂存
        tWarehouseAgreement.setUpdateBy(loginUser.getUser().getUserName());
        tWarehouseAgreement.setUpdateTime(new Date());
        tWarehouseAgreementMapper.updateTWarehouseAgreement(tWarehouseAgreement);
        tWarehouseAgreementitemsMapper.deleteByFPid(fPid);
        //  从表添加
        if (StringUtils.isNotNull(agreementitems) && !"[]".equals(agreementitems)) {
            JSONArray jsonDrArray = JSONArray.parseArray(agreementitems);
            List<TWarehouseAgreementitems> tWarehouseAgreementitemsList = JSONObject.parseArray(jsonDrArray.toJSONString(), TWarehouseAgreementitems.class);
            for (TWarehouseAgreementitems tWarehouseAgreementitems : tWarehouseAgreementitemsList) {
                tWarehouseAgreementitems.setfPid(fPid);
                tWarehouseAgreementitems.setCreateBy(loginUser.getUser().getUserName());
                tWarehouseAgreementitems.setCreateTime(new Date());
                tWarehouseAgreementitemsMapper.insertTWarehouseAgreementitems(tWarehouseAgreementitems);
            }
        }
        return AjaxResult.success();
    }

    /**
     * 根据协议主表id 更新对应明细表状态
     *
     * @param fPid 协议主表id
     * @return 结果
     */
    @Transactional
    public AjaxResult agreementFollow(Long fPid, long fettle) {
        if (StringUtils.isNull(fPid)) {
            return AjaxResult.error("协议更新状态未找到主表信息，请与管理员联系");
        }
        TWarehouseAgreement tWarehouseAgreement = new TWarehouseAgreement();
        tWarehouseAgreement.setfId(fPid);
        tWarehouseAgreement.setfBillstatus(String.valueOf(fettle));
        int tFeeUpdateResult = tWarehouseAgreementMapper.updateTWarehouseAgreement(tWarehouseAgreement);
        if (tFeeUpdateResult <= 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("更新协议明细状态失败，请联系管理员");
        }
        return AjaxResult.success();
    }

    /**
     * 修改仓储费
     *
     * @param tWarehouseAgreement 仓储费
     * @return 结果
     */
    @Override
    public int updateTWarehouseAgreement(TWarehouseAgreement tWarehouseAgreement) {
        tWarehouseAgreement.setUpdateTime(DateUtils.getNowDate());
        return tWarehouseAgreementMapper.updateTWarehouseAgreement(tWarehouseAgreement);
    }

    /**
     * 批量删除仓储费
     *
     * @param fIds 需要删除的仓储费ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteTWarehouseAgreementByIds(Long[] fIds) {
        // 取出业务编号、 放入 billno_del
        for (Long id : fIds) {
            // 1、查询主表信息
            TWarehouseAgreement tWarehouseAgreement = tWarehouseAgreementMapper.selectTWarehouseAgreementById(id);
            // 2、业务编号、客存编号 放入 billno_del
            BillnoDel billnoDel = new BillnoDel();
            billnoDel.setBillType("WA");
            billnoDel.setBillNo(tWarehouseAgreement.getfBillno());

            Long type;
            if (tWarehouseAgreement.getfFeetypeid() < 1) {
                type = AnnexActEnum.STORAGE_FEE.getType();
            } else {
                type = AnnexActEnum.HOMEWORK_FEE.getType();
            }
            billnoDelMapper.insertBillnoDel(billnoDel);
            tWarehouseAgreementitemsMapper.deleteByFPid(id);
            annexMapper.deleteByPid(id, type);
        }
        tWarehouseAgreementMapper.deleteTWarehouseAgreementByIds(fIds);
        return 1;
    }

    /**
     * 删除仓储费信息
     *
     * @param fId 仓储费ID
     * @return 结果
     */
    @Override
    public int deleteTWarehouseAgreementById(Long fId) {
        return tWarehouseAgreementMapper.deleteTWarehouseAgreementById(fId);
    }

    @Override
    public AjaxResult queryRemove(Long fId) {
        // 查询协议主表数据
        TWarehouseAgreement tWarehouseAgreement = tWarehouseAgreementMapper.selectTWarehouseAgreementById(fId);
        TWarehouseAgreementitems tWarehouseAgreementitems = new TWarehouseAgreementitems();
        tWarehouseAgreementitems.setfPid(tWarehouseAgreement.getfId());
        List<TWarehouseAgreementitems> tWarehouseAgreementitemss = tWarehouseAgreementitemsMapper.selectTWarehouseAgreementitemsList(tWarehouseAgreementitems);
        if (StringUtils.isNull(tWarehouseAgreement)) {
            return AjaxResult.success("0");
        } else if (StringUtils.isNotNull(tWarehouseAgreement) && StringUtils.isEmpty(tWarehouseAgreementitemss)) {
            return AjaxResult.success("1");
        } else {
            return AjaxResult.success("2");
        }
    }

    /**
     * 计算存储费用
     *
     * @param storageFeesDto 参数
     * @return 结果
     * @author shanxin
     */
    public StorageFeeCalculationResultVO getCarryingCost(CalculateStorageFeesDTO storageFeesDto) {
        if (null == storageFeesDto.getfCorpid() ||
                null == storageFeesDto.getfGoodsid() ||
                null == storageFeesDto.getDays() ||
                null == storageFeesDto.getEarlySumDays() ||
                null == storageFeesDto.getWarehouseId() ||
                null == storageFeesDto.getStartTime() ||
                null == storageFeesDto.getEndTime() ||
                null == storageFeesDto.getCangKey()) {
            throw new WarehouseException("缺少查询计费规则条件");
        }
        // 查询计费规则
        List<TWarehouseAgreementitems> itemList =
                this.tWarehouseAgreementitemsMapper.getItemsBytWarehouseAgreementMsg(storageFeesDto.getfCorpid(),
                        storageFeesDto.getfGoodsid(),
                        String.valueOf(storageFeesDto.getWarehouseId()), storageFeesDto.getCangKey());
        // 如果未找到计费规则 则抛出异常
        if (CollUtil.isEmpty(itemList)) {
            throw new WarehouseException("编号" + storageFeesDto.getfMblno() + "未找到计费规则");
        }
        // 如果仓储费出现两个不同计费单位就进行抛异常
        long count = itemList.stream().map(TWarehouseAgreementitems::getfFeeunitid).distinct().count();
        if (count > 1) {
            throw new WarehouseException("计费规则存在多条，请确认");
        }
        // 根据规则的计费单位去获取要计算的数量
        TWarehouseAgreementitems agreementitems = itemList.stream().findFirst()
                .orElseThrow(() -> new WarehouseException("计费规则不存在"));
        BigDecimal qty = acquiredQuantity(storageFeesDto, agreementitems.getfFeeunitid());
        if (qty.compareTo(BigDecimal.ZERO) < 1) {
            return null;
        }
        BigDecimal money = BigDecimal.ZERO;
        Long dayLength;
        Long feeId = 0L;
        // 备注  天X钱=金额
        String remark = "";
        // 计费区间  月日-月日X钱
        String billingInterval = "";
        for (TWarehouseAgreementitems tWarehouseAgreementitems : itemList) {
            // 如果要计费天数不足一天，不予计算
            if (storageFeesDto.getDays() < 1) {
                break;
            }
            dayLength = tWarehouseAgreementitems.getfEndays() - tWarehouseAgreementitems.getfFromdays() + 1L;
            // 如果已计费天数超出本阶层，则进入下一层规则，并剪掉当前层天数
            if (storageFeesDto.getEarlySumDays() >= dayLength) {
                storageFeesDto.setEarlySumDays(storageFeesDto.getEarlySumDays() - dayLength);
                continue; //将已算账的天数 与 计费规则的 最后一天作比较如果 已算10天 > 规则结束  不算帐
            }
            // 如果计费日期超过本层天数
            if (storageFeesDto.getDays() >= dayLength) {
                // 天数剪掉 剩余已计费库存天数
                dayLength -= storageFeesDto.getEarlySumDays();
                storageFeesDto.setEarlySumDays(0L);
                feeId = tWarehouseAgreementitems.getfFeeid();
                // 获取最终金额：数量 * 单价 * 天数
                BigDecimal calculate = this.getCalculate(qty, tWarehouseAgreementitems.getfPrice(), dayLength);
                money = money.add(calculate);

                storageFeesDto.setDays(storageFeesDto.getDays() - dayLength);
                // 组装运费明细记录
                String details = assemblyBillingDetails(StorageFeeRangeDTO.builder()
                        .dayNum(dayLength).price(tWarehouseAgreementitems.getfPrice()).qty(qty).amt(calculate)
                        .build());
                remark = StringUtils.isEmpty(remark) ? details : remark + "，" + details;
                // 计算区间费用信息
                String costRange = assemblyBillingInterval(StorageFeeRangeDTO.builder()
                        .startTime(storageFeesDto.getStartTime()).dayNum(dayLength).price(tWarehouseAgreementitems.getfPrice())
                        .qty(qty).unit(agreementitems.getfFeeunitid())
                        .build());
                billingInterval = StringUtils.isEmpty(billingInterval) ? costRange : billingInterval + "，" + costRange;

                storageFeesDto.setStartTime(DateUtils.dateAdd(storageFeesDto.getStartTime(), dayLength.intValue()));
            } else {
                // 最后一次计算天数
                feeId = tWarehouseAgreementitems.getfFeeid();
                BigDecimal calculate = this.getCalculate(qty, tWarehouseAgreementitems.getfPrice(), storageFeesDto.getDays());
                money = money.add(calculate);
                // 计算费用明细
                String details = assemblyBillingDetails(StorageFeeRangeDTO.builder()
                        .dayNum(storageFeesDto.getDays()).price(tWarehouseAgreementitems.getfPrice()).qty(qty).amt(calculate)
                        .build());
                remark = StringUtils.isEmpty(remark) ? details : remark + "，" + details;
                // 计算区间费用信息
                String interval = assemblyBillingInterval(StorageFeeRangeDTO.builder()
                        .startTime(storageFeesDto.getStartTime()).dayNum(storageFeesDto.getDays())
                        .price(tWarehouseAgreementitems.getfPrice())
                        .qty(qty).unit(agreementitems.getfFeeunitid())
                        .build());
                billingInterval = StringUtils.isEmpty(billingInterval) ? interval : billingInterval + "，" + interval;
                break;
            }
        }
        StorageFeeCalculationResultVO resultVO = new StorageFeeCalculationResultVO();
        resultVO.setQty(qty);
        resultVO.setAmt(money);
        resultVO.setFeeId(feeId);
        resultVO.setRemark(remark);
        resultVO.setUnit(agreementitems.getfFeeunitid());
        resultVO.setBillingInterval(billingInterval);
        return resultVO;
    }

    /**
     * 根据不同计费单位获取不同 计算库存明细数量
     *
     * @param storageFeesDto 库存明细
     * @param unit           计费单位
     * @return 结果
     */
    public BigDecimal acquiredQuantity(CalculateStorageFeesDTO storageFeesDto, Long unit) {
        BigDecimal fQty = new BigDecimal(0);
        if (unit.equals(Long.parseLong(WarehouseTypeEnum.BOX_NUM.getType()))) {
            return storageFeesDto.getfQty().setScale(2, RoundingMode.HALF_UP);
        } else if (unit.equals(Long.parseLong(WarehouseTypeEnum.GROSS_WEIGHT.getType()))) {
            fQty = storageFeesDto.getfGrossweight();
        } else if (unit.equals(Long.parseLong(WarehouseTypeEnum.NET_WEIGHT.getType()))) {
            fQty = storageFeesDto.getfNetweight();
        } else if (unit.equals(Long.parseLong(WarehouseTypeEnum.MEASURE.getType()))) {
            fQty = storageFeesDto.getfVolumn();
        } else if (unit.equals(Long.parseLong(WarehouseTypeEnum.FIXED.getType()))) {
            fQty = BigDecimal.ONE;
        }
        // 结果值除以1000 保留两位
        BigDecimal divisor = new BigDecimal("1000");
        return fQty.divide(divisor, 2, RoundingMode.HALF_UP);
    }

    /**
     * 组装运费明细记录
     *
     * @param rangeDto 金额
     * @return
     */
    private String assemblyBillingDetails(StorageFeeRangeDTO rangeDto) {
        return rangeDto.getDayNum() + "天*" + rangeDto.getPrice() + "元*" + rangeDto.getQty() + " = " + rangeDto.getAmt() + "元";
    }

    /**
     * 计算计费区间
     *
     * @param feeRangeDto
     * @return 计算计费区间
     */
    private String assemblyBillingInterval(StorageFeeRangeDTO feeRangeDto) {
        // 求总金额
        BigDecimal bigDecimal = feeRangeDto.getPrice().multiply(feeRangeDto.getQty()).multiply(new BigDecimal(feeRangeDto.getDayNum()));

        return DateUtils.dateTime(feeRangeDto.getStartTime()) + "至" + DateUtils.dateTime(DateUtils.dateAdd(feeRangeDto.getStartTime(), (feeRangeDto.getDayNum().intValue() - 1))) +
                "*" + feeRangeDto.getPrice() + "元 " + feeRangeDto.getDayNum() + "天" + feeRangeDto.getQty() + WarehouseTypeEnum.getUnitCharging(feeRangeDto.getUnit())
                + " " + bigDecimal + "元";
    }

    /**
     * 数量 * 单价 * 天数
     *
     * @param itemNumsBig 数量
     * @param unitPrice   单价
     * @param dateLength  天数
     * @return
     */
    public BigDecimal getCalculate(BigDecimal itemNumsBig, BigDecimal unitPrice, Long dateLength) {
        BigDecimal money;
        BigDecimal bigDaysBig = new BigDecimal(dateLength);
        money = itemNumsBig.multiply(unitPrice).multiply(bigDaysBig);
        return money;
    }

}
