package com.sunxung.factoring.service.underlying.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.dict.impl.AcceptanceSheetDict;
import com.sunxung.factoring.dict.impl.FileModuleDict;
import com.sunxung.factoring.dict.impl.ProjectInitiationStatusDict;
import com.sunxung.factoring.dict.impl.UnderlyingDict;
import com.sunxung.factoring.entity.GridPage;
import com.sunxung.factoring.entity.acceptance.AcceptanceBasicInfo;
import com.sunxung.factoring.entity.acceptance.AcceptanceGoodsInfo;
import com.sunxung.factoring.entity.acceptance.BaseGoods;
import com.sunxung.factoring.entity.businessmanagement.BusinessBasicInfo;
import com.sunxung.factoring.entity.customerinformation.Customer;
import com.sunxung.factoring.entity.project.BusinessAssignee;
import com.sunxung.factoring.entity.purchcontractmanagement.PurchContractBasicInfo;
import com.sunxung.factoring.entity.purchcontractmanagement.PurchContractManagement;
import com.sunxung.factoring.entity.settlement.SettlementGoodsInfo;
import com.sunxung.factoring.entity.sys.Dictionary;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.entity.underlying.*;
import com.sunxung.factoring.entity.underlying.vo.GoodsSearch1;
import com.sunxung.factoring.entity.underlying.vo.UnderlyingCalculateVo;
import com.sunxung.factoring.entity.underlying.vo.UnderlyingInfoVo;
import com.sunxung.factoring.service.acceptancesheet.AcceptanceBasicInfoService;
import com.sunxung.factoring.service.acceptancesheet.AcceptanceGoodsInfoService;
import com.sunxung.factoring.service.acceptancesheet.GoodsCalculateService;
import com.sunxung.factoring.service.businessmanagement.BusinessBasicInfoService;
import com.sunxung.factoring.service.customerinformation.CustomerService;
import com.sunxung.factoring.service.project.BusinessAssigneeService;
import com.sunxung.factoring.service.purchcontractmanagement.PurchContractBasicInfoService;
import com.sunxung.factoring.service.purchcontractmanagement.PurchContractService;
import com.sunxung.factoring.service.purchcontractmanagement.PurchContractSettleCycleService;
import com.sunxung.factoring.service.settlement.SettlementGoodsInfoService;
import com.sunxung.factoring.service.sys.*;
import com.sunxung.factoring.service.sys.dto.AttachmentDto;
import com.sunxung.factoring.service.sys.flowable.FlowableService;
import com.sunxung.factoring.service.underlying.*;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liutao
 * @date 2021.10.11
 */
@Service
@PropertySource("classpath:config.properties")
public class UnderlyingServiceImpl implements UnderlyingService {

    @Autowired
    private UnderlyingBasicInfoService underlyingBasicInfoService;

    @Autowired
    private UnderlyingGoodsInfoService underlyingGoodsInfoService;

    @Autowired
    private UnderlyingAccountsReceivableInfoService underlyingAccountsReceivableInfoService;

    @Autowired
    private UnderlyingHisInfoService underlyingHisInfoService;

    @Autowired
    private UnderlyingHisGoodsInfoService underlyingHisGoodsInfoService;

    @Autowired
    private UnderlyingHisAccountsReceivableInfoService underlyingHisAccountsReceivableInfoService;

    @Autowired
    private ISysAttachmentRefService sysAttachmentRefService;

    @Autowired
    private SerialNumberGenerator serialNumberGenerator;

    @Autowired
    private DictionaryService dictService;

    @Autowired
    private BusinessAssigneeService assigneeService;

    @Autowired
    private UserService userService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private BusinessBasicInfoService businessBasicInfoService;

    @Autowired
    private FlowableService flowableService;

    @Autowired
    private AcceptanceBasicInfoService acceptanceBasicInfoService;

    @Autowired
    private AcceptanceGoodsInfoService acceptanceGoodsInfoService;

    @Autowired
    private SettlementGoodsInfoService settlementGoodsInfoService;

    @Autowired
    private GoodsCalculateService goodsCalculateService;

    @Autowired
    private PurchContractSettleCycleService purchContractSettleCycleService;

    @Autowired
    private PurchContractService purchContractService;

    @Autowired
    private PurchContractBasicInfoService purchContractBasicInfoService;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private UnderlyingApprovalService underlyingApprovalService;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${config.underlyingAssetsBasic.id.url}")
    private String underlyingAssetsBasicIdUrl;

    @Value("${config.underlyingAssetsDomestic.add.url}")
    private String underlyingAssetsDomesticAddUrl;

    @Value("${config.domesticAccountsReceivable.add.url}")
    private String domesticAccountsReceivableAddUrl;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(UnderlyingInfoVo underlyingInfoVo, HttpServletRequest request) {

        if (underlyingInfoVo == null || underlyingInfoVo.getUnderlyingBasicInfo() == null) {
            throw new BusinessException(CodeUtil.FAIL, "底层基础信息不能为空");
        }
        if (underlyingInfoVo.getUnderlyingBasicInfo().getBusinessNumber() == null) {
            throw new ValidatorException(CodeUtil.FAIL, "请锁定业务编号！");
        }
        //保存底层信息
        UnderlyingBasicInfo basicInfo = saveUnderlying(underlyingInfoVo, request);

        //保存历史信息
        UnderlyingHisInfo hisInfo = null;
        if (underlyingInfoVo.getSubmit()) {
            hisInfo = addHistory(underlyingInfoVo, basicInfo.getId());
        }
        //开启底层任务并且业务办理任务
        startProcess(basicInfo, hisInfo, underlyingInfoVo.getSubmit());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(UnderlyingInfoVo underlyingInfoVo, String taskId, HttpServletRequest request) {
        if (underlyingInfoVo == null || underlyingInfoVo.getUnderlyingBasicInfo() == null
                || underlyingInfoVo.getUnderlyingBasicInfo().getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "底层基础信息不能为空");
        }

        //保存底层信息
        UnderlyingBasicInfo basicInfo = editUnderlying(underlyingInfoVo, request);

        //办理业务
        if (underlyingInfoVo.getSubmit()) {
            //保存历史信息
            UnderlyingHisInfo hisInfo = addHistory(underlyingInfoVo, basicInfo.getId());
            Map<String, Object> procVariables = new HashMap<>(1);
            procVariables.put(ConstantUtil.UNDERLYING_APPROVAL_CANDIDATE,
                    assigneeService.getCandidateByBusiness(basicInfo.getId(), ConstantUtil.UNDERLYING_MANAGE, ConstantUtil.ASSIGNEE_RISK_MANAGER));

            Map<String, Object> msgVariables = new HashMap<>(2);
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, "底层编号：" + basicInfo.getReceivablesNumber());
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "底层编号为“" + basicInfo.getReceivablesNumber() + "”的底层已进入“"
                            + ConstantConversionUtil.flowBusinessKeyNames.get(ConstantUtil.UNDERLYING_MANAGE) + "—formBusiness”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);
            List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.RISK_CONTROL_MANAGER);
            flowableService.completeMyTask(taskId, basicInfo, procVariables, null, hisInfo.getId(), msgVariables,
                    ConstantUtil.UNDERLYING_MANAGE, legalSpecialists);
        }

    }

    @Override
    public GridPage<AcceptanceBasicInfo> findGoodsByAcceptance(GoodsSearch1 search) {


        AcceptanceBasicInfo basicInfo = new AcceptanceBasicInfo();
        basicInfo.setBusinessNumber(search.getBusinessNumber());
        basicInfo.setcSupplierInfoId(search.getSupplierId());

        Dictionary completed = dictService.getByCode(ProjectInitiationStatusDict.ChildEnum.COMPLETED.getCode());
        if (completed == null || completed.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "验收单状态-已审批字典项不能为空");
        }
        basicInfo.setAcceptanceStatus(ProjectInitiationStatusDict.ChildEnum.COMPLETED.getCode());
        //取未做结算，未做底层的数据
        basicInfo.setReceivables(false);
        basicInfo.setSettlement(false);

        Page<Object> page = PageHelper.startPage(search.getPage(), search.getRows());
        List<AcceptanceBasicInfo> list = new ArrayList<>();

        //获取货物信息
        if (list != null && list.size() > 0) {
            list.stream().forEach(acceptanceBasicInfo -> {
                Customer supplier = customerService.getById(acceptanceBasicInfo.getcSupplierInfoId());
                if (supplier != null) {
//                    acceptanceBasicInfo.setSupplier(supplier);
                }
                List<AcceptanceGoodsInfo> goodsInfoList = acceptanceGoodsInfoService
                        .list(new QueryWrapper<AcceptanceGoodsInfo>().eq("acceptance_basic_info_id", acceptanceBasicInfo.getId()));
                acceptanceBasicInfo.setAcceptanceGoodInfos(goodsInfoList);
            });
        }
        return new GridPage<>(search.getRows(), search.getPage(), page.getTotal(), list);

    }

//    @Override
//    public GridPage<SettlementBasicInfo> findGoodsBySettlement(GoodsSearch1 search) {
//
//        Page<Object> page = PageHelper.startPage(search.getPage(), search.getRows());
//        //查询已经结算并且审核通过的结算单信息
//        List<SettlementBasicInfo> list = acceptanceBasicInfoService.findGoodsBySettlement(search);
//        //获取货物信息
//        if (list != null && list.size() > 0) {
//            list.stream().forEach(settlementBasicInfo -> {
//                Customer supplier = customerService.getById(settlementBasicInfo.getSupplierId());
//                if (supplier != null) {
//                    settlementBasicInfo.setSupplier(supplier);
//                }
//                List<SettlementGoodsInfo> settlementGoodsInfos = settlementGoodsInfoService.list(new QueryWrapper<SettlementGoodsInfo>().eq("settlement_basic_info_id", settlementBasicInfo.getId()));
//                if (settlementGoodsInfos != null && settlementGoodsInfos.size() > 0) {
//                    settlementGoodsInfos.stream().forEach(settlementGoodsInfo -> {
//                        AcceptanceGoodsInfo acceptanceGoodsInfo = acceptanceGoodsInfoService.getById(settlementGoodsInfo.getAcceptanceGoodsInfoId());
//                        if (acceptanceGoodsInfo != null) {
//                            settlementGoodsInfo.setGoodsFactory(acceptanceGoodsInfo.getGoodsFactory());
//                            settlementGoodsInfo.setGoodsName(acceptanceGoodsInfo.getGoodsName());
//                            settlementGoodsInfo.setGoodsType(acceptanceGoodsInfo.getGoodsType());
//                            settlementGoodsInfo.setGoodsUnit(acceptanceGoodsInfo.getGoodsUnit());
//                            settlementGoodsInfo.setGoodsQuantity(acceptanceGoodsInfo.getGoodsQuantity());
//                            settlementGoodsInfo.setAcceptanceDate(acceptanceGoodsInfo.getAcceptanceDate());
//                        }
//                    });
//                }
//
//                settlementBasicInfo.setSettlementGoodsInfos(settlementGoodsInfos);
//            });
//        }
//        return new GridPage<>(search.getRows(), search.getPage(), page.getTotal(), list);
//    }

    @Override
    public List<BaseGoods> calculate(UnderlyingCalculateVo underlyingCalculateVo) {

        String businessNumber = underlyingCalculateVo.getBusinessNumber();
        if (businessNumber == null) {
            throw new BusinessException(CodeUtil.FAIL, "业务编号不能为空");
        }

        Long supplierId = underlyingCalculateVo.getSupplierId();
        if (supplierId == null) {
            throw new BusinessException(CodeUtil.FAIL, "供应商Id不能为空");
        }
        //如果做过结算  不用计算  传什么返什么
        List<AcceptanceGoodsInfo> goodsInfoList = underlyingCalculateVo.getGoodsInfoList();
        List<BaseGoods> list = new ArrayList<>();
        boolean settlement = false;
        for (AcceptanceGoodsInfo acceptanceGoodsInfo : goodsInfoList) {
            if (acceptanceGoodsInfo.getSettlementBasicInfoId() != null) {
                BaseGoods baseGoods = new BaseGoods();
                baseGoods.setAcceptanceGoodsInfoId(acceptanceGoodsInfo.getId());
                baseGoods.setcAcceptanceBasicInfoId(acceptanceGoodsInfo.getAcceptanceBasicInfoId());
                baseGoods.setSalesTotalPrice(acceptanceGoodsInfo.getSalesTotalPrice());
                baseGoods.setSalesGuaranteeMoney(acceptanceGoodsInfo.getSalesGuaranteeMoney() == null ? BigDecimal.ZERO : acceptanceGoodsInfo.getSalesGuaranteeMoney());
                baseGoods.setPurchasePrice(acceptanceGoodsInfo.getPurchasePrice());
                baseGoods.setPurchaseTotalPrice(acceptanceGoodsInfo.getPurchaseTotalPrice());
                baseGoods.setPurchaseGuaranteeMoney(acceptanceGoodsInfo.getPurchGuaranteeMoney() == null ? BigDecimal.ZERO : acceptanceGoodsInfo.getPurchGuaranteeMoney());
                list.add(baseGoods);
                settlement = true;
            }
        }
        if (settlement) {
            return list;
        }
        BigDecimal occupationSalesRetention = BigDecimal.ZERO;
        BigDecimal occupationPurchRetention = BigDecimal.ZERO;
        //计算现有的采购质保金
        //该业务下该供应商的所有验收单
        List<AcceptanceBasicInfo> acceptanceBasicInfoList = acceptanceBasicInfoService.list(new QueryWrapper<AcceptanceBasicInfo>()
                .eq("business_number", underlyingCalculateVo.getBusinessNumber())
                .eq("supplier_id", underlyingCalculateVo.getSupplierId())
                .eq("acceptance_status", dictService.getByCode(AcceptanceSheetDict.ChildEnum.APPROVAL.getCode()).getId()));
        if (acceptanceBasicInfoList != null && acceptanceBasicInfoList.size() > 0) {
            for (AcceptanceBasicInfo acceptanceBasicInfo : acceptanceBasicInfoList) {
                //验收单下做过结算的货物
                List<SettlementGoodsInfo> settlementGoodsInfoList = settlementGoodsInfoService.listByAcceptanceId(acceptanceBasicInfo.getId());
                if (settlementGoodsInfoList != null && settlementGoodsInfoList.size() > 0) {
                    for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfoList) {
                        occupationPurchRetention = occupationPurchRetention.add(settlementGoodsInfo.getPurchaseGuaranteeMoney() == null ? BigDecimal.ZERO : settlementGoodsInfo.getPurchaseGuaranteeMoney());
                    }
                } else {
                    //验收单下做过底层的货物
                    List<UnderlyingGoodsInfo> underlyingGoodsInfoList = underlyingGoodsInfoService.listByAcceptanceId(acceptanceBasicInfo.getId());
                    if (underlyingGoodsInfoList != null && underlyingGoodsInfoList.size() > 0) {
                        for (UnderlyingGoodsInfo underlyingGoodsInfo : underlyingGoodsInfoList) {
                            occupationPurchRetention = occupationPurchRetention.add(underlyingGoodsInfo.getPurchaseGuaranteeMoney() == null ? BigDecimal.ZERO : underlyingGoodsInfo.getPurchaseGuaranteeMoney());
                            //即做了底层又做了结算 不能重复计算
                            for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfoList) {
                                if (settlementGoodsInfo.getAcceptanceGoodsInfoId().equals(underlyingGoodsInfo.getAcceptanceGoodsInfoId())) {
                                    occupationPurchRetention = occupationPurchRetention.subtract(underlyingGoodsInfo.getPurchaseGuaranteeMoney() == null ? BigDecimal.ZERO : underlyingGoodsInfo.getPurchaseGuaranteeMoney());
                                }
                            }
                        }
                    }
                }
            }
        }
        //计算现有的销售质保金
        //该业务下的所有验收单
        List<AcceptanceBasicInfo> acceptanceBasicInfos = acceptanceBasicInfoService.list(new QueryWrapper<AcceptanceBasicInfo>()
                .eq("business_number", underlyingCalculateVo.getBusinessNumber())
                .eq("acceptance_status", dictService.getByCode(AcceptanceSheetDict.ChildEnum.APPROVAL.getCode()).getId()));
        if (acceptanceBasicInfos != null && acceptanceBasicInfos.size() > 0) {
            for (AcceptanceBasicInfo acceptanceBasicInfo : acceptanceBasicInfos) {
                //验收单下做过结算的货物
                List<SettlementGoodsInfo> settlementGoodsInfoList = settlementGoodsInfoService.listByAcceptanceId(acceptanceBasicInfo.getId());
                if (settlementGoodsInfoList != null && settlementGoodsInfoList.size() > 0) {
                    for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfoList) {
                        occupationSalesRetention = occupationSalesRetention.add(settlementGoodsInfo.getSalesGuaranteeMoney() == null ? BigDecimal.ZERO : settlementGoodsInfo.getSalesGuaranteeMoney());
                    }
                } else {
                    //验收单下做过底层的货物
                    List<UnderlyingGoodsInfo> underlyingGoodsInfoList = underlyingGoodsInfoService.listByAcceptanceId(acceptanceBasicInfo.getId());
                    if (underlyingGoodsInfoList != null && underlyingGoodsInfoList.size() > 0) {
                        for (UnderlyingGoodsInfo underlyingGoodsInfo : underlyingGoodsInfoList) {
                            occupationSalesRetention = occupationSalesRetention.add(underlyingGoodsInfo.getSalesGuaranteeMoney() == null ? BigDecimal.ZERO : underlyingGoodsInfo.getSalesGuaranteeMoney());
                            //即做了底层又做了结算 不能重复计算
                            for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfoList) {
                                if (settlementGoodsInfo.getAcceptanceGoodsInfoId().equals(underlyingGoodsInfo.getAcceptanceGoodsInfoId())) {
                                    occupationSalesRetention = occupationSalesRetention.subtract(underlyingGoodsInfo.getSalesGuaranteeMoney() == null ? BigDecimal.ZERO : underlyingGoodsInfo.getSalesGuaranteeMoney());
                                }
                            }
                        }
                    }
                }
            }
        }

        return goodsCalculateService.calculateGoodsAmount(businessNumber, supplierId, goodsInfoList,
                occupationSalesRetention, occupationPurchRetention);
    }

    @Override
    public List<UnderlyingAccountsReceivableInfo> generateAccountsReceivable(UnderlyingInfoVo underlyingInfoVo) {

        List<UnderlyingGoodsInfo> goodsInfoList = underlyingInfoVo.getUnderlyingGoodsInfoList();
        if (goodsInfoList != null && goodsInfoList.size() > 0) {
            List<UnderlyingAccountsReceivableInfo> accountsReceivableInfoList = goodsInfoList.stream().map(goods -> {
                if (goods.getAcceptanceGoodsInfoId() == null) {
                    throw new BusinessException(CodeUtil.FAIL, "对应验收单货物信息不存在");
                }
                AcceptanceGoodsInfo acceptanceGoodsInfo = acceptanceGoodsInfoService.getById(goods.getAcceptanceGoodsInfoId());
                UnderlyingAccountsReceivableInfo accountsReceivableInfo = new UnderlyingAccountsReceivableInfo();
                accountsReceivableInfo.setAcceptanceBasicInfoId(acceptanceGoodsInfo.getAcceptanceBasicInfoId());
                accountsReceivableInfo.setAcceptanceGoodsInfoId(acceptanceGoodsInfo.getId());
                accountsReceivableInfo.setGoodsName(acceptanceGoodsInfo.getGoodsName());
                accountsReceivableInfo.setGoodsFactory(acceptanceGoodsInfo.getGoodsFactory());
                accountsReceivableInfo.setGoodsType(acceptanceGoodsInfo.getGoodsType());
                accountsReceivableInfo.setGoodsUnit(acceptanceGoodsInfo.getGoodsUnit());
                accountsReceivableInfo.setGoodsQuantity(acceptanceGoodsInfo.getGoodsQuantity());
                //应收账款金额=采购总价
                accountsReceivableInfo.setAccountsReceivableAmount(goods.getPurchaseTotalPrice());
                //应收账款净额=采购总价-采购质保金
                accountsReceivableInfo.setNetAccountsReceivableAmount(goods.getPurchaseGuaranteeMoney() == null ?
                        goods.getPurchaseTotalPrice() : goods.getPurchaseTotalPrice().subtract(goods.getPurchaseGuaranteeMoney()));
                return accountsReceivableInfo;
            }).collect(Collectors.toList());
            return accountsReceivableInfoList;
        }
        return null;
    }

    @Override
    public UnderlyingInfoVo getDetail(Long businessKey) {
        UnderlyingInfoVo underlyingInfoVo = new UnderlyingInfoVo();
        UnderlyingBasicInfo underlyingBasicInfo = underlyingBasicInfoService.getDetail(businessKey);
        underlyingInfoVo.setUnderlyingBasicInfo(underlyingBasicInfo);
        if (underlyingBasicInfo != null) {
            //获取货物信息
//            List<UnderlyingGoodsInfo> goodsInfoList = underlyingGoodsInfoService
//                    .list(new QueryWrapper<UnderlyingGoodsInfo>().eq("underlying_basic_info_id", underlyingBasicInfo.getId()));
//            if (goodsInfoList != null && goodsInfoList.size() > 0) {
//                goodsInfoList.stream().forEach(goods -> {
//                    Long acceptanceGoodsInfoId = goods.getAcceptanceGoodsInfoId();
//                    if (acceptanceGoodsInfoId != null) {
//                        AcceptanceGoodsInfo acceptanceGoodsInfo = acceptanceGoodsInfoService.getById(acceptanceGoodsInfoId);
//                        goods.setAcceptanceGoodsInfo(acceptanceGoodsInfo);
//                    }
//                });
//            }
//            underlyingInfoVo.setUnderlyingGoodsInfoList(goodsInfoList);
            //获取网价附件
            AttachmentDto attachmentDto = AttachmentDto.builder()
                    .setEntityId(underlyingBasicInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.UNDERLYING_FILE)
                    .build();
            List<FileStorage> fileStorageList = sysAttachmentRefService.getFiles(attachmentDto);
            underlyingInfoVo.setUnderlyingFileList(fileStorageList);
            //获取应收账款信息
            List<UnderlyingAccountsReceivableInfo> accountsReceivableList = underlyingAccountsReceivableInfoService.findByBasicId(underlyingBasicInfo.getId());
            underlyingInfoVo.setAccountsReceivableInfoList(accountsReceivableList);
        }
        return underlyingInfoVo;
    }

    @Override
    public List<UnderlyingGoodsInfo> getGoodsInfoList(Long underlyingBasicInfoId) {
        //获取货物信息
        List<UnderlyingGoodsInfo> goodsInfoList = underlyingGoodsInfoService
                .list(new QueryWrapper<UnderlyingGoodsInfo>().eq("underlying_basic_info_id", underlyingBasicInfoId));
        if (CollectionUtil.isNotEmpty(goodsInfoList)) {
            goodsInfoList.stream().forEach(goods -> {
                Long acceptanceGoodsInfoId = goods.getAcceptanceGoodsInfoId();
                if (acceptanceGoodsInfoId != null) {
                    AcceptanceGoodsInfo acceptanceGoodsInfo = acceptanceGoodsInfoService.getById(acceptanceGoodsInfoId);
                    goods.setAcceptanceGoodsInfo(acceptanceGoodsInfo);
                }
            });
        }
        return goodsInfoList;
    }

    @Override
    public UnderlyingBasicInfo findAccountsReceivableByBusinessNumber(String businessNumber, Long supplierId) {

        UnderlyingBasicInfo underlyingBasicInfo = new UnderlyingBasicInfo();

        Date now = new Date();
        underlyingBasicInfo.setAccountsReceivableStartDate(now);
        //变更为  从采购合同获取预估回款日
//        SalesContractManagement salesContractManagement = salesContractService.getByBusinessNumber(businessNumber);
//        if (salesContractManagement == null || salesContractManagement.getId() == null) {
//            throw new BusinessException(CodeUtil.FAIL, "销售合同管理不能为空");
//        }
//        SalesContractBasicInfo salesContractBasicInfo = salesContractBasicInfoService.getLatestBasicInfo(salesContractManagement.getId(),
//                ConstantConversionUtil.APPROVAL_RESULT_PASS);
//        if (salesContractBasicInfo == null || salesContractBasicInfo.getId() == null) {
//            throw new BusinessException(CodeUtil.FAIL, "销售合同基础信息不能为空");
//        }
//        SalesContractSettleInfo settleInfo = salesContractSettleInfoService.findByBasicInfoId(salesContractBasicInfo.getId());
//        if (settleInfo == null) {
//            throw new BusinessException(CodeUtil.FAIL, "销售合同结算信息不能为空");
//        }
//        Integer period = settleInfo.getEstimatePaybackDays();
        PurchContractManagement purchContractManagement = purchContractService.getOne(
                new QueryWrapper<PurchContractManagement>()
                        .eq("business_number", businessNumber)
                        .eq("supplier_id", supplierId));
        if (purchContractManagement == null || purchContractManagement.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "采购合同管理不能为空");
        }
        PurchContractBasicInfo purchContractBasicInfo = purchContractBasicInfoService
                .lambdaQuery().eq(PurchContractBasicInfo::getPurchContractManagementId, purchContractManagement.getId()).one();
        if (purchContractBasicInfo == null || purchContractBasicInfo.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "采购合同基础信息不能为空");
        }


        return underlyingBasicInfo;
    }

    @Override
    public void downloadAllfile(Long id, HttpServletResponse response) {
//        List<FileStorage> underlyingAllFiles = new ArrayList<>();
//
//        //底层文件
//        List<FileStorage> underlyingFiles = sysAttachmentRefService.getFiles(AttachmentDto.builder()
//                .setChildEnum(FileModuleDict.ChildEnum.UNDERLYING_FILE).setEntityId(id).build());
//        underlyingAllFiles.addAll(underlyingFiles);
//        //审核页面所有附件
//        UnderlyingBasicInfo underlyingBasicInfo = underlyingBasicInfoService.getById(id);
//        UnderlyingApprovalVo underlyingApprovalVo ;
//        underlyingAllFiles.addAll(underlyingApprovalVo.getAcceptanceFiles());
//        underlyingAllFiles.addAll(underlyingApprovalVo.getSettlementFiles());
//        underlyingAllFiles.addAll(underlyingApprovalVo.getPurchContractFiles());
//        underlyingAllFiles.addAll(underlyingApprovalVo.getPurchInvoiceFiles());
//        underlyingAllFiles.addAll(underlyingApprovalVo.getSalesContractFiles());
//        underlyingAllFiles.addAll(underlyingApprovalVo.getSalesInvoiceFiles());
//
//        //打包下载
//        fileStorageService.renameFileStorageList(underlyingAllFiles);
//        fileStorageService.downloadZipFile(underlyingAllFiles, FileModuleDict.ChildEnum.UNDERLYING_ZIP_FILE.getCname(),
//                FileModuleDict.ChildEnum.UNDERLYING_ZIP_FILE, response);
    }

    /**
     * 开启底层流程并且业务办理任务
     *
     * @param underlyingBasicInfo
     * @param underlyingHisInfo
     */
    private void startProcess(UnderlyingBasicInfo underlyingBasicInfo, UnderlyingHisInfo underlyingHisInfo, Boolean submit) {
        Long basicId = underlyingBasicInfo.getId();
        //2.新增处理人-- 业务经理、法务专员
        BusinessAssignee projectManager = new BusinessAssignee(basicId, ConstantUtil.UNDERLYING_MANAGE);
        BusinessBasicInfo businessBasicInfo = businessBasicInfoService.getByBusinessNumber(underlyingBasicInfo.getBusinessNumber());
        if (businessBasicInfo == null || businessBasicInfo.getManagerId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应业务的业务经理");
        }
        projectManager.setAssigneeId(businessBasicInfo.getManagerId());
        projectManager.setAssigneeType(ConstantUtil.ASSIGNEE_PROJECT_MANAGER);
        assigneeService.add(projectManager);

        List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.RISK_CONTROL_MANAGER);
        if (legalSpecialists == null || legalSpecialists.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.OPERATION_SPECIALIST + "角色内无任何用户！");
        }

        BusinessAssignee legalSpecialist = new BusinessAssignee(basicId, ConstantUtil.UNDERLYING_MANAGE);
        legalSpecialist.setCandidateId(StringUtils.join(legalSpecialists, ","));
        legalSpecialist.setAssigneeType(ConstantUtil.ASSIGNEE_RISK_MANAGER);
        assigneeService.add(legalSpecialist);
        //3.开启流程实例
        Map<String, Object> procVariables = new HashMap<>();
        procVariables.put(ConstantUtil.UNDERLYING_CREATE_ASSIGNEE,
                assigneeService.getIdByBusiness(basicId, ConstantUtil.UNDERLYING_MANAGE, ConstantUtil.ASSIGNEE_PROJECT_MANAGER));
        //查询条件：业务编号/底层资产编号/供应商名称/核心企业名称
        Customer supplier = customerService.getById(underlyingBasicInfo.getSupplierId());
        if (supplier == null || supplier.getEnterpriseName() == null) {
            throw new BusinessException(CodeUtil.FAIL, "查询不到对应供应商信息");
        }
        Customer customer = customerService.getById(underlyingBasicInfo.getEnterpriseCustomerInfoId());
        if (customer == null || customer.getEnterpriseName() == null) {
            throw new BusinessException(CodeUtil.FAIL, "查询不到对应核心企业信息");
        }
        String queryBusiness = underlyingBasicInfo.getBusinessNumber() + FlowableUtil.splitChar + underlyingBasicInfo.getReceivablesNumber()
                + FlowableUtil.splitChar + supplier.getEnterpriseName() + FlowableUtil.splitChar + customer.getEnterpriseName();
        ProcessInstance processInst = flowableService.startProcessInstance(underlyingBasicInfo, procVariables,
                FlowableUtil.generateBusinessKey(underlyingBasicInfo, ConstantUtil.UNDERLYING_MANAGE, queryBusiness), null, ConstantUtil.UNDERLYING_MANAGE);
        if (processInst == null) {
            throw new BusinessException(CodeUtil.FAIL, "流程启动失败");
        }

        if (submit) {
            //完成流程第一步提交验收单，开启下一步法务验收
            String processInstId = processInst.getId();
            Task task = flowableService.findRuntimeTaskByProcessInstId(processInstId).get(0);
            Map<String, Object> procVariables1 = new HashMap<>(1);
            procVariables1.put(ConstantUtil.UNDERLYING_APPROVAL_CANDIDATE,
                    assigneeService.getCandidateByBusiness(basicId, ConstantUtil.UNDERLYING_MANAGE, ConstantUtil.ASSIGNEE_RISK_MANAGER));
            Map<String, Object> msgVariables = new HashMap<>(2);
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, "底层编号：" + underlyingBasicInfo.getReceivablesNumber());
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "底层编号为“" + underlyingBasicInfo.getReceivablesNumber() + "”的底层已进入“"
                            + ConstantConversionUtil.flowBusinessKeyNames.get(ConstantUtil.UNDERLYING_MANAGE) + "——formBusiness”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);

            flowableService.completeMyTask(task.getId(), underlyingBasicInfo, procVariables1, null,
                    underlyingHisInfo.getId(), msgVariables, ConstantUtil.UNDERLYING_MANAGE, legalSpecialists);
        }
    }

    /**
     * 保存历史信息
     */
    private UnderlyingHisInfo addHistory(UnderlyingInfoVo underlyingInfoVo, Long basicId) {

        //保存底层历史信息
        UnderlyingBasicInfo underlyingBasicInfo = underlyingInfoVo.getUnderlyingBasicInfo();
        UnderlyingHisInfo underlyingHisInfo = new UnderlyingHisInfo();
        BeanUtils.copyProperties(underlyingBasicInfo, underlyingHisInfo, "id");
        underlyingHisInfo.setUnderlyingBasicInfoId(basicId);
        underlyingHisInfoService.save(underlyingHisInfo);

        //保存货物历史信息
        List<UnderlyingGoodsInfo> goodsInfoList = underlyingInfoVo.getUnderlyingGoodsInfoList();
        if (goodsInfoList != null && goodsInfoList.size() > 0) {
            goodsInfoList.stream().forEach(goods -> {
                UnderlyingHisGoodsInfo hisGoodsInfo = new UnderlyingHisGoodsInfo();
                BeanUtils.copyProperties(goods, hisGoodsInfo, "id");
                hisGoodsInfo.setUnderlyingHisInfoId(underlyingHisInfo.getId());
                underlyingHisGoodsInfoService.save(hisGoodsInfo);
            });
        }

        //保存底层历史信息
        List<UnderlyingAccountsReceivableInfo> accountsReceivableInfoList = underlyingInfoVo.getAccountsReceivableInfoList();
        if (accountsReceivableInfoList != null && accountsReceivableInfoList.size() > 0) {
            accountsReceivableInfoList.stream().forEach(accountsReceivable -> {
                UnderlyingHisAccountsReceivableInfo hisAccountsReceivableInfo = new UnderlyingHisAccountsReceivableInfo();
                BeanUtils.copyProperties(accountsReceivable, hisAccountsReceivableInfo, "id");
                hisAccountsReceivableInfo.setUnderlyingHisInfoId(underlyingHisInfo.getId());
                underlyingHisAccountsReceivableInfoService.save(hisAccountsReceivableInfo);
            });
        }

        //保存历史附件
        AttachmentDto attachmentDto = AttachmentDto.builder()
                .setEntityId(underlyingBasicInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.UNDERLYING_FILE)
                .build();
        List<FileStorage> fileStorageList = sysAttachmentRefService.getFiles(attachmentDto);
        AttachmentDto hisAttachmentDto = AttachmentDto.builder()
                .setEntityId(underlyingHisInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.UNDERLYING_HIS_FILE)
                .build();
        sysAttachmentRefService.saveFileAndRefHis(fileStorageList, hisAttachmentDto);

        return underlyingHisInfo;
    }

    /**
     * 保存底层信息
     *
     * @param underlyingInfoVo
     * @param request
     * @return
     */
    private UnderlyingBasicInfo saveUnderlying(UnderlyingInfoVo underlyingInfoVo, HttpServletRequest request) {
        //已创建
        Dictionary createDic = dictService.getByCode(UnderlyingDict.ChildEnum.CREATE.getCode());
        //已录入
        Dictionary entryDic = dictService.getByCode(UnderlyingDict.ChildEnum.ENTRY.getCode());
        if (createDic == null || entryDic == null) {
            throw new ValidatorException(CodeUtil.FAIL, "已创建/已录入字典项为空！");
        }
        //保存底层基础信息
        UnderlyingBasicInfo underlyingBasicInfo = underlyingInfoVo.getUnderlyingBasicInfo();
        //修改状态为已创建
        underlyingBasicInfo.setUnderlyingStatus(createDic.getId());
        if (underlyingInfoVo.getSubmit()) {
            if (underlyingInfoVo.getAccountsReceivableInfoList() == null || underlyingInfoVo.getAccountsReceivableInfoList().isEmpty()) {
                throw new BusinessException(CodeUtil.FAIL, "底层信息为空，请先点一键计算生成底层信息再提交");
            }
            underlyingBasicInfo.setUnderlyingStatus(entryDic.getId());
        }
        //生成底层编号
        String underlyingNumber = serialNumberGenerator.nextValue(ConstantUtil.MORTGAGE_CODE);
        underlyingBasicInfo.setReceivablesNumber(underlyingNumber);
        underlyingBasicInfoService.save(underlyingBasicInfo);
        //保存关联信息
        saveRelatedInfo(underlyingInfoVo.getUnderlyingGoodsInfoList(), underlyingInfoVo.getAccountsReceivableInfoList(),
                request, underlyingBasicInfo.getId(), underlyingInfoVo.getSubmit());
        return underlyingBasicInfo;
    }

    /**
     * 修改底层信息
     *
     * @param underlyingInfoVo
     * @param request
     * @return
     */
    private UnderlyingBasicInfo editUnderlying(UnderlyingInfoVo underlyingInfoVo, HttpServletRequest request) {

        Dictionary entryDic = dictService.getByCode(UnderlyingDict.ChildEnum.ENTRY.getCode());
        if (entryDic == null) {
            throw new ValidatorException(CodeUtil.FAIL, "已录入字典项为空");
        }
        UnderlyingBasicInfo underlyingBasicInfo = underlyingInfoVo.getUnderlyingBasicInfo();

        if (underlyingInfoVo.getSubmit()) {
            if (underlyingInfoVo.getAccountsReceivableInfoList() == null || underlyingInfoVo.getAccountsReceivableInfoList().isEmpty()) {
                throw new BusinessException(CodeUtil.FAIL, "底层信息为空，请先点一键计算生成底层信息再提交");
            }
            //修改状态为已录入
            underlyingBasicInfo.setUnderlyingStatus(entryDic.getId());
        }

        //修改底层基础信息
        underlyingBasicInfoService.updateById(underlyingBasicInfo);

        //删除关联信息（货物信息、文件信息、底层信息）
        deleteRelatedInfo(underlyingInfoVo.getDeleteFiles(), underlyingBasicInfo.getId());

        //保存关联信息
        saveRelatedInfo(underlyingInfoVo.getUnderlyingGoodsInfoList(), underlyingInfoVo.getAccountsReceivableInfoList(),
                request, underlyingBasicInfo.getId(), underlyingInfoVo.getSubmit());
        return underlyingBasicInfo;
    }

    /**
     * 删除关联信息（货物信息、文件信息、底层信息）
     *
     * @param deleteFileIds
     * @param basicInfoId
     */
    private void deleteRelatedInfo(List<Long> deleteFileIds, Long basicInfoId) {

        //先修改验收单状态
//        List<UnderlyingGoodsInfo> oldUnderlyingGoodsInfos = underlyingGoodsInfoService
//                .list(new QueryWrapper<UnderlyingGoodsInfo>().eq("underlying_basic_info_id", basicInfoId));
//        if (CollectionUtil.isNotEmpty(oldUnderlyingGoodsInfos)) {
//            oldUnderlyingGoodsInfos.forEach(underlyingGoodsInfo -> {
//                AcceptanceBasicInfo acceptanceBasicInfo = acceptanceBasicInfoService.getById(underlyingGoodsInfo.getAcceptanceBasicInfoId());
//                acceptanceBasicInfo.setReceivables(false);
//                acceptanceBasicInfoService.updateById(acceptanceBasicInfo);
//            });
//        }
        underlyingGoodsInfoService.remove(new QueryWrapper<UnderlyingGoodsInfo>().eq("underlying_basic_info_id", basicInfoId));

        if (deleteFileIds != null && deleteFileIds.size() > 0) {
            sysAttachmentRefService.removeFilestorageAndRef(deleteFileIds);
        }
        underlyingAccountsReceivableInfoService.remove(new QueryWrapper<UnderlyingAccountsReceivableInfo>()
                .eq("underlying_basic_info_id", basicInfoId));
    }

    /**
     * 保存底层关联信息
     *
     * @param goodsInfoList              货物列表
     * @param accountsReceivableInfoList 应收账款信息
     * @param request
     * @param basicInfoId                底层基础信息Id
     */
    private void saveRelatedInfo(List<UnderlyingGoodsInfo> goodsInfoList, List<UnderlyingAccountsReceivableInfo> accountsReceivableInfoList,
                                 HttpServletRequest request, Long basicInfoId, Boolean submit) {

        if (goodsInfoList != null && goodsInfoList.size() > 0) {
            if (submit) {
                goodsInfoList.stream().forEach(goods -> {
                    if (goods.getSalesPrice() != null && goods.getSalesPrice().compareTo(BigDecimal.ZERO) <= 0) {
                        throw new BusinessException(CodeUtil.FAIL, "请填写销售单价并进行质保金计算");
                    }
                });
            }
            goodsInfoList.stream().forEach(goods -> {
                goods.setUnderlyingBasicInfoId(basicInfoId);
                underlyingGoodsInfoService.save(goods);
            });
            List<Long> acceptanceBasicInfoIds = goodsInfoList.stream().map(goods -> goods.getcAcceptanceBasicInfoId())
                    .distinct().collect(Collectors.toList());
            //判断选择的是已验收货物还是已结算货物
            if (CollectionUtil.isNotEmpty(acceptanceBasicInfoIds)) {
                acceptanceBasicInfoIds.forEach(id -> {
                    AcceptanceBasicInfo acceptanceBasicInfo = acceptanceBasicInfoService.getById(id);
                    if (acceptanceBasicInfo == null) {
                        throw new BusinessException(CodeUtil.FAIL, "获取不到货物对应验收单号");
                    }
                    if (!acceptanceBasicInfo.getReceivables()) {
                        if (submit) {
                            //判断选中货物是否已底层
                            acceptanceBasicInfo.setReceivables(true);
                            acceptanceBasicInfoService.updateById(acceptanceBasicInfo);
                        }
                    } else {
                        throw new BusinessException(CodeUtil.FAIL, "验收单号为" +
                                acceptanceBasicInfo.getAcceptanceNumber() + "的货物已做过底层，请重新选择！");
                    }
                });
            }

        }
        List<MultipartFile> fileList = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.FILE_NAME);
        if (CollectionUtil.isNotEmpty(fileList)) {
            //保存附件
            AttachmentDto attachmentDto = AttachmentDto.builder()
                    .setEntityId(basicInfoId)
                    .setChildEnum(FileModuleDict.ChildEnum.UNDERLYING_FILE)
                    .build();
            sysAttachmentRefService.saveFileAndRef(fileList, attachmentDto);
        }

        //保存底层信息
        if (accountsReceivableInfoList != null && accountsReceivableInfoList.size() > 0) {
            accountsReceivableInfoList.stream().forEach(accountsReceivable -> {
                accountsReceivable.setUnderlyingBasicInfoId(basicInfoId);
                underlyingAccountsReceivableInfoService.save(accountsReceivable);
            });
        }
    }
}
