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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deepoove.poi.data.*;
import com.deepoove.poi.data.style.BorderStyle;
import com.sunxung.factoring.component.datatransfer.WordWriter;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.component.util.onlineConverter.OfficeConverterUtil;
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.SettlementDict;
import com.sunxung.factoring.entity.ResponseJson;
import com.sunxung.factoring.entity.ValidatorEntity;
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.customerinformation.Customer;
import com.sunxung.factoring.entity.electronicsignature.FddSignData;
import com.sunxung.factoring.entity.entprise.Enterprise;
import com.sunxung.factoring.entity.project.BusinessAssignee;
import com.sunxung.factoring.entity.purchcontractmanagement.*;
import com.sunxung.factoring.entity.salescontractmanagement.CSalesContract;
import com.sunxung.factoring.entity.salescontractmanagement.CSalesContractPersonInfo;
import com.sunxung.factoring.entity.salescontractmanagement.CSalesContractBasicInfo;
import com.sunxung.factoring.entity.salescontractmanagement.SalesContractApproval;
import com.sunxung.factoring.entity.settlement.*;
import com.sunxung.factoring.entity.supplier.SupplierInfo;
import com.sunxung.factoring.entity.sys.Dictionary;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.entity.sys.FileStorageDO;
import com.sunxung.factoring.entity.sys.User;
import com.sunxung.factoring.entity.tradingPlatform.Platform;
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.entprise.IEnterpriseService;
import com.sunxung.factoring.service.project.BusinessAssigneeService;
import com.sunxung.factoring.service.purchcontractmanagement.*;
import com.sunxung.factoring.service.salescontractmanagement.*;
import com.sunxung.factoring.service.settlement.*;
import com.sunxung.factoring.service.supplier.ISupplierInfoService;
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.tradingPlatform.PlatformService;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.xwpf.usermodel.XWPFTable;
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.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liutao
 * @date 2021.09.24
 */
@Service
public class SettlementManagementServiceImpl implements SettlementManagementService {

    @Autowired
    private SerialNumberGenerator serialNumberGenerator;

    @Autowired
    private SettlementBasicInfoService settlementBasicInfoService;

    @Autowired
    private DictionaryService dictService;

    @Autowired
    private ICSalesContractBasicInfoService salesContractBasicInfoService;

    @Autowired
    private SalesContractSettleInfoService salesContractSettleInfoService;

    @Autowired
    private SalesContractService salesContractService;

    @Autowired
    private SettlementGoodsInfoService settlementGoodsInfoService;

    @Autowired
    private SettlementRepaymentPlanService settlementRepaymentPlanService;

    @Autowired
    private BusinessAssigneeService assigneeService;

    @Autowired
    private UserService userService;

    @Autowired
    private FlowableService flowableService;

    @Autowired
    private SettlementApprovalService settlementApprovalService;

    @Autowired
    private BusinessBasicInfoService businessBasicInfoService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private PurchContractBasicInfoService purchContractBasicInfoService;

    @Autowired
    private PurchContractApprovalService purchContractApprovalService;

    @Autowired
    private IPurchContractApprovalSettleCycleService purchContractApprovalSettleCycleService;

    @Autowired
    private PurchContractService purchContractService;

    @Autowired
    private AcceptanceGoodsInfoService acceptanceGoodsInfoService;

    @Autowired
    private AcceptanceBasicInfoService acceptanceBasicInfoService;

    @Autowired
    private PlatformService platformService;

    @Autowired
    private SettlementHisGoodsInfoService settlementHisGoodsInfoService;

    @Autowired
    private SettlementHisRepaymentPlanService settlementHisRepaymentPlanService;

    @Autowired
    private SettlementHisInfoService settlementHisInfoService;

    @Autowired
    private ISalesContractPersonInfoService salesContractPersonInfoService;

    @Autowired
    private ISysAttachmentRefService sysAttachmentRefService;

    @Autowired
    private GoodsCalculateService goodsCalculateService;

    @Autowired
    private SettlementElectronicInfoService settlementElectronicInfoService;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private IPurchContractBuyerSellerService purchContractBuyerSellerService;

    @Autowired
    private PurchContractElectronicInfoService purchContractElectronicInfoService;

    @Resource(name = "SupplierInfoService")
    private ISupplierInfoService iSupplierInfoService;
    @Autowired
    @Lazy
    private IEnterpriseService iEnterpriseService;

    @Autowired
    private FileService fileService;
    @Autowired
    private IPurchContractNeedUserRelService iPurchContractNeedUserRelService;

    @Autowired
    private SalesContractApprovalService salesContractApprovalService;


    private static Logger logger = LogManager.getLogger(SettlementManagementServiceImpl.class);

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SettlementBasicInfo settlementBasicInfo, HttpServletRequest request) throws Exception {
        //保存结算单相关信息
        SettlementBasicInfo saveSettlementBasicInfo = addSettlement(settlementBasicInfo, request);
        //新建结算单完成后需要开启法务流程并完成第一步流程
        startProcess(settlementBasicInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void financeReview(SettlementApproval settlementApproval) {
        SettlementBasicInfo settlementBasicInfo = settlementBasicInfoService.getById(settlementApproval.getSettlementBasicInfoId());
        String result;
        switch (settlementApproval.getApprovalConclusion()) {
            case ConstantConversionUtil.APPROVAL_RESULT_PASS:
                result = ConstantUtil.APPROVAL;
                settlementBasicInfo.setSettlementStatus(ProjectInitiationStatusDict.ChildEnum.PROCESSING.getCode());
                //历史里添加一条审核通过记录供发票查询业务使用   getBusinessListOfInvoice
                SettlementHisInfo settlementHisInfo = new SettlementHisInfo();
                BeanUtils.copyProperties(settlementBasicInfo, settlementHisInfo);
                settlementHisInfo.setSettlementBasicInfoId(settlementBasicInfo.getId());
                settlementHisInfoService.save(settlementHisInfo);
                break;
            case ConstantConversionUtil.APPROVAL_RESULT_BACK:
                result = ConstantUtil.OVERRULE;
                settlementBasicInfo.setSettlementStatus(ProjectInitiationStatusDict.ChildEnum.PROCESSING.getCode());
                //结算单否决  释放本结算单的货物
                List<SettlementGoodsInfo> settlementGoodsInfos = settlementGoodsInfoService.list(new QueryWrapper<SettlementGoodsInfo>().eq("c_settlement_basic_info_id", settlementBasicInfo.getId()));
                for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
                    AcceptanceBasicInfo acceptanceBasicInfo = acceptanceBasicInfoService.getById(settlementGoodsInfo.getcAcceptanceBasicInfoId());
                    acceptanceBasicInfo.setSettlement(false);
                    acceptanceBasicInfoService.updateById(acceptanceBasicInfo);
                }
                break;
            default:
                result = "";

        }
        if (StringUtil.isEmpty(result)) {
            throw new ValidatorException(CodeUtil.FAIL, "结论不能为空");
        }
        //修改结算单信息
        settlementBasicInfoService.updateById(settlementBasicInfo);
        //保存审核结果
        settlementApproval.setAuditorId(ThreadLocalUtil.getUserId());
        settlementApprovalService.save(settlementApproval);
        //完成审核流程流转到下一流程或者完成流程
        Map<String, Object> msgVariables = new HashMap<>();
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, "结算单编号：" + settlementBasicInfo.getSettlementNumber());
        if (result.equals(ConstantUtil.OVERRULE)) {
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "结算单编号为“" + settlementBasicInfo.getSettlementNumber() + "”的结算单已退回，进入“"
                            + ConstantConversionUtil.flowBusinessKeyNames.get(ConstantUtil.BILL_BASIC_INFORMATION) + "—修改”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);
        } else if (result.equals(ConstantUtil.APPROVAL)) {
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "结算单编号为“" + settlementBasicInfo.getSettlementNumber() + "”的结算单已通过审核，待签署");
        }
        flowableService.completeMyTask(settlementApproval.getTaskId(), settlementBasicInfo, null, result, settlementApproval.getId(), msgVariables, ConstantUtil.BILL_BASIC_INFORMATION);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBill(SettlementBasicInfo settlementBasicInfo, HttpServletRequest request) throws IOException {
        //审核处理人
        List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.LEGAL_SPECIALIST);
        if (legalSpecialists == null || legalSpecialists.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.OPERATION_SPECIALIST + "角色内无任何用户！");
        }
        Long oldId = settlementBasicInfo.getId();
        //修改原始记录
        if (settlementBasicInfo.getSubmit()) {
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.UPDATE, settlementBasicInfo);
            settlementBasicInfo = updateBillBasicInformation(settlementBasicInfo, request);
            //保存历史记录供getView方法使用
            Long historyId = addHistoryBillBasicInformation(settlementBasicInfo);
            //完成修改流转到下一流程财务审核
            Map<String, Object> procVariables = new HashMap<>();
            SupplierInfo supplierInfo = iSupplierInfoService.get(settlementBasicInfo.getSupplierId());
            procVariables.put(ConstantUtil.BILL_SIGN_ASSIGNEE,supplierInfo.getSysUserId());
            procVariables.put(ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE,
                    assigneeService.getCandidateByBusiness(settlementBasicInfo.getId(), ConstantUtil.BILL_BASIC_INFORMATION, ConstantUtil.LEGAL_SPECIALIST));
            Map<String, Object> msgVariables = new HashMap<>();
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, "结算单编号：" + settlementBasicInfo.getSettlementNumber());
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "结算单编号为“" + settlementBasicInfo.getSettlementNumber() + "”的结算单已进入“"
                            + ConstantConversionUtil.flowBusinessKeyNames.get(ConstantUtil.BILL_BASIC_INFORMATION) + "—法务审核”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);
            settlementBasicInfo.setId(oldId);
            flowableService.completeMyTask(settlementBasicInfo.getTaskId(), settlementBasicInfo, procVariables, null,
                    historyId, msgVariables, ConstantUtil.BILL_BASIC_INFORMATION, legalSpecialists);
        } else {
            settlementBasicInfo = updateBillBasicInformation(settlementBasicInfo, request);
        }
    }

//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public GridPage getCanBeBillGoodsInformation(ConditionVo conditionVo) {
//        String businessNumber = conditionVo.getCondition();
//        Long supplierId = conditionVo.getConditionLong();
//        Long status = dictService.getByCode(ProjectInitiationStatusDict.ChildEnum.COMPLETED.getCode()).getId();
//        Page<AcceptanceBasicInfo> page = PageHelper.startPage(conditionVo.getPage(), conditionVo.getRows());
//        //存在的该业务下该供应商未结算验收单
//        List<AcceptanceBasicInfo> acceptanceBasicInfos = acceptanceBasicInfoService.getCanBeBillGoodsInformation(businessNumber, supplierId, status);
//        //验收单货物做过底层的话价格信息从底层取
//        for (AcceptanceBasicInfo acceptanceBasicInfo : acceptanceBasicInfos) {
//            List<AcceptanceGoodsInfo> acceptanceGoodsInfos = acceptanceGoodsInfoService.list(new QueryWrapper<AcceptanceGoodsInfo>().eq("acceptance_basic_info_id", acceptanceBasicInfo.getId()));
//            for (AcceptanceGoodsInfo acceptanceGoodsInfo : acceptanceGoodsInfos) {
//                UnderlyingGoodsInfo underlyingGoodsInfo = underlyingGoodsInfoService.getOne(new QueryWrapper<UnderlyingGoodsInfo>().eq("acceptance_goods_info_id", acceptanceGoodsInfo.getId()));
//                if (underlyingGoodsInfo != null) {
//                    acceptanceGoodsInfo.setSalesPrice(underlyingGoodsInfo.getSalesPrice());
//                    acceptanceGoodsInfo.setSalesTotalPrice(underlyingGoodsInfo.getSalesTotalPrice());
//                    acceptanceGoodsInfo.setSalesGuaranteeMoney(underlyingGoodsInfo.getSalesGuaranteeMoney());
//                    acceptanceGoodsInfo.setPurchasePrice(underlyingGoodsInfo.getPurchasePrice());
//                    acceptanceGoodsInfo.setPurchaseTotalPrice(underlyingGoodsInfo.getPurchaseTotalPrice());
//                    acceptanceGoodsInfo.setPurchGuaranteeMoney(underlyingGoodsInfo.getPurchaseGuaranteeMoney());
//                } else {
//                    if (acceptanceGoodsInfo.getSalesPrice() == null) {
//                        acceptanceGoodsInfo.setSalesPrice(BigDecimal.ZERO);
//                    }
//                    acceptanceGoodsInfo.setSalesTotalPrice(BigDecimal.ZERO);
//                    acceptanceGoodsInfo.setSalesGuaranteeMoney(BigDecimal.ZERO);
//                    acceptanceGoodsInfo.setPurchasePrice(BigDecimal.ZERO);
//                    acceptanceGoodsInfo.setPurchaseTotalPrice(BigDecimal.ZERO);
//                    acceptanceGoodsInfo.setPurchGuaranteeMoney(BigDecimal.ZERO);
//                }
//            }
//            acceptanceBasicInfo.setSupplier(customerService.getById(acceptanceBasicInfo.getSupplierId()));
//            acceptanceBasicInfo.setAcceptanceGoodInfos(acceptanceGoodsInfos);
//        }
//        return new GridPage<>(conditionVo.getRows(), conditionVo.getPage(), page.getTotal(), page.getResult());
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SettlementBasicInfo getDetail(Long businessKey) {
        SettlementBasicInfo settlementBasicInfo = settlementBasicInfoService.getById(businessKey);
        //结算单相关货物信息
//        List<SettlementGoodsInfo> settlementGoodsInfos = settlementGoodsInfoService.list(
//                new QueryWrapper<SettlementGoodsInfo>().eq("settlement_basic_info_id", settlementBasicInfo.getId()));
//        if (CollectionUtil.isNotEmpty(settlementGoodsInfos)) {
//            for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
//                AcceptanceBasicInfo acceptanceBasicInfo = acceptanceBasicInfoService.getById(settlementGoodsInfo.getAcceptanceBasicInfoId());
//                AcceptanceGoodsInfo acceptanceGoodsInfo = acceptanceGoodsInfoService.getById(settlementGoodsInfo.getAcceptanceGoodsInfoId());
//                settlementGoodsInfo.setAcceptanceNumber(acceptanceBasicInfo.getAcceptanceNumber());
//                settlementGoodsInfo.setAcceptanceDate(acceptanceGoodsInfo.getAcceptanceDate());
//                settlementGoodsInfo.setGoodsName(acceptanceGoodsInfo.getGoodsName());
//                settlementGoodsInfo.setGoodsFactory(acceptanceGoodsInfo.getGoodsFactory());
//                settlementGoodsInfo.setGoodsType(acceptanceGoodsInfo.getGoodsType());
//                settlementGoodsInfo.setGoodsUnit(acceptanceGoodsInfo.getGoodsUnit());
//                settlementGoodsInfo.setGoodsQuantity(acceptanceGoodsInfo.getGoodsQuantity());
//            }
//        }
//
//        settlementBasicInfo.setSettlementGoodsInfos(settlementGoodsInfos);
        //回款计划
        settlementBasicInfo.setSettlementRepaymentPlans(settlementRepaymentPlanService.list(
                new QueryWrapper<SettlementRepaymentPlan>().eq("c_settlement_basic_info_id", settlementBasicInfo.getId()))
        );
        //平台信息
        settlementBasicInfo.setPlatform(platformService.getById(settlementBasicInfo.getTradingPlatformId()));
        //供应商信息
        settlementBasicInfo.setSupplier(customerService.getById(settlementBasicInfo.getSupplierId()));
        //核心企业
        settlementBasicInfo.setCustomer(customerService.getById(settlementBasicInfo.getEnterpriseCustomerInfoId()));
        //业务信息
//        settlementBasicInfo.setBusinessBasicInfo(businessBasicInfoService.getByBusinessNumber(settlementBasicInfo.getBusinessNumber()));
        //下游结算清单附件
        AttachmentDto attachmentDto = AttachmentDto.builder()
                .setEntityId(settlementBasicInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_FILE)
                .build();
        settlementBasicInfo.setFiles(sysAttachmentRefService.getFiles(attachmentDto));
        //再新增结算单说明附件
        AttachmentDto attachmentDtoAdditional = AttachmentDto.builder()
                .setEntityId(settlementBasicInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_SUPPLEMENT_FILE)
                .build();
        settlementBasicInfo.setAdditionalFiles(sysAttachmentRefService.getFiles(attachmentDtoAdditional));
        //再新增结算单网价附件
        AttachmentDto attachmentDtoNetPrice = AttachmentDto.builder()
                .setEntityId(settlementBasicInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_NET_PRICE_FILE)
                .build();
        settlementBasicInfo.setNetPriceFiles(sysAttachmentRefService.getFiles(attachmentDtoNetPrice));
        return settlementBasicInfo;
    }

    @Override
    public List<SettlementGoodsInfo> getGoodsInfoList(Long settlementBasicInfoId) {
        //结算单相关货物信息
        List<SettlementGoodsInfo> settlementGoodsInfos = settlementGoodsInfoService.list(
                new QueryWrapper<SettlementGoodsInfo>().eq("c_settlement_basic_info_id", settlementBasicInfoId));
        if (CollectionUtil.isNotEmpty(settlementGoodsInfos)) {
            for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
                AcceptanceBasicInfo acceptanceBasicInfo = acceptanceBasicInfoService.getById(settlementGoodsInfo.getcAcceptanceBasicInfoId());
                AcceptanceGoodsInfo acceptanceGoodsInfo = acceptanceGoodsInfoService.getById(settlementGoodsInfo.getAcceptanceGoodsInfoId());
                settlementGoodsInfo.setAcceptanceNumber(acceptanceBasicInfo.getAcceptanceNumber());
                settlementGoodsInfo.setAcceptanceDate(acceptanceGoodsInfo.getAcceptanceDate());
                settlementGoodsInfo.setGoodsName(acceptanceGoodsInfo.getGoodsName());
                settlementGoodsInfo.setGoodsFactory(acceptanceGoodsInfo.getGoodsFactory());
                settlementGoodsInfo.setGoodsType(acceptanceGoodsInfo.getGoodsType());
                settlementGoodsInfo.setGoodsUnit(acceptanceGoodsInfo.getGoodsUnit());
                settlementGoodsInfo.setGoodsQuantity(acceptanceGoodsInfo.getGoodsQuantity());
            }
        }
        return settlementGoodsInfos;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public SettlementBasicInfo getExpectedSettlementDate(SettlementBasicInfo settlementBasicInfo) {

        CSalesContract salesContractManagement = salesContractService.getByBusinessNumber(settlementBasicInfo.getBusinessNumber());
        if (salesContractManagement == null || salesContractManagement.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "销售合同管理不能为空");
        }
        CSalesContractBasicInfo salesContractBasicInfo = salesContractBasicInfoService.getOne(new QueryWrapper<CSalesContractBasicInfo>()
                .eq("c_sales_contract_management_id",salesContractManagement.getId()));
        if (salesContractBasicInfo == null || salesContractBasicInfo.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "销售合同基础信息不能为空");
        }
        SalesContractApproval salesContractApproval = salesContractApprovalService.getOne(new QueryWrapper<SalesContractApproval>().eq("c_sales_contract_basic_info_id", salesContractBasicInfo.getId())
                .eq("approval_conclusion", ConstantConversionUtil.APPROVAL_RESULT_PASS).orderByDesc("gmt_create").last("LIMIT 1"));
        Date settlementStartDate = settlementBasicInfo.getSettlementStartDate();
        Dictionary settleCycleMethodDict = dictService.getByCode(salesContractApproval.getSettleCycleMethod());
        Integer settleCycle = salesContractApproval.getSettleCycle() == null?0:salesContractApproval.getSettleCycle() ;
        //预估结算日
        if (settleCycleMethodDict.getCode().equals(ConstantUtil.SALES_CONTRACT_SETTLE_CYCLE_METHOD_FIXED)) {
            Date endSettleDate = DateUtil.addDays(settlementStartDate, settleCycle - 1);
            settlementBasicInfo.setSettlementEndDate(endSettleDate);
        } else if (settleCycleMethodDict.getCode().equals(ConstantUtil.SALES_CONTRACT_SETTLE_CYCLE_METHOD_NATURAL)) {
            Date endSettleDate = DateUtil.addMonths(settlementStartDate, settleCycle);
            endSettleDate = DateUtil.addDays(endSettleDate, -1);
            settlementBasicInfo.setSettlementEndDate(endSettleDate);
        }
        return settlementBasicInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseJson calculation(SettlementBasicInfo settlementBasicInfo) {
        BigDecimal occupationSalesRetention = BigDecimal.ZERO;
        BigDecimal occupationPurchRetention = BigDecimal.ZERO;
        //需要计算的货物
        List<AcceptanceGoodsInfo> acceptanceGoodsInfos = settlementBasicInfo.getAcceptanceGoodsInfos();
        //计算现有的采购质保金
        //该业务下该供应商的所有验收单
        List<AcceptanceBasicInfo> acceptanceBasicInfoList = acceptanceBasicInfoService.list(new QueryWrapper<AcceptanceBasicInfo>()
                .eq("business_number", settlementBasicInfo.getBusinessNumber())
                .eq("supplier_id", settlementBasicInfo.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 (AcceptanceGoodsInfo acceptanceGoodsInfo : acceptanceGoodsInfos) {
//                                //如果需要计算质保金的货物和已存在底层的货物是同一个验收单货物时  不加和该货物的底层质保金(总质保金以结算单为主，这次是来算该笔货物的结算单质保金，所以底层处的不计算入内)
//                                if (underlyingGoodsInfo.getAcceptanceGoodsInfoId().equals(acceptanceGoodsInfo.getId())) {
//                                    occupationPurchRetention = occupationPurchRetention.subtract(underlyingGoodsInfo.getPurchaseGuaranteeMoney() == null ? BigDecimal.ZERO : underlyingGoodsInfo.getPurchaseGuaranteeMoney());
//                                }
//                            }
//                        }
//                    }
//                }
            }
        }
        //计算现有的销售质保金
        //该业务下的所有验收单
        List<AcceptanceBasicInfo> acceptanceBasicInfos = acceptanceBasicInfoService.list(new QueryWrapper<AcceptanceBasicInfo>()
                .eq("business_number", settlementBasicInfo.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 (AcceptanceGoodsInfo acceptanceGoodsInfo : acceptanceGoodsInfos) {
//                                //如果需要计算质保金的货物和已存在底层的货物是同一个验收单货物时  不加和该货物的底层质保金(总质保金以结算单为主，这次是来算该笔货物的结算单质保金，所以底层处的不计算入内)
//                                if (underlyingGoodsInfo.getAcceptanceGoodsInfoId().equals(acceptanceGoodsInfo.getId())) {
//                                    occupationSalesRetention = occupationSalesRetention.subtract(underlyingGoodsInfo.getSalesGuaranteeMoney() == null ? BigDecimal.ZERO : underlyingGoodsInfo.getSalesGuaranteeMoney());
//                                }
//                            }
//                        }
//                    }
//                }
            }
        }

        //一键计算质保金
        List<BaseGoods> calculate = goodsCalculateService.calculateGoodsAmount(settlementBasicInfo.getBusinessNumber(), settlementBasicInfo.getSupplierId(), settlementBasicInfo.getAcceptanceGoodsInfos(), occupationSalesRetention, occupationPurchRetention);
        calculate.forEach(goodsInfo -> {
            BigDecimal salesGuaranteeMoney = goodsInfo.getSalesGuaranteeMoney() == null ? BigDecimal.ZERO : goodsInfo.getSalesGuaranteeMoney();
            goodsInfo.setSalesGuaranteeMoney(salesGuaranteeMoney.setScale(2, RoundingMode.HALF_UP));

            goodsInfo.setSalesTotalPrice(goodsInfo.getSalesTotalPrice().setScale(2, RoundingMode.HALF_UP));
            goodsInfo.setPurchasePrice(goodsInfo.getPurchasePrice().setScale(2, RoundingMode.HALF_UP));
            goodsInfo.setPurchaseTotalPrice(goodsInfo.getPurchaseTotalPrice().setScale(2, RoundingMode.HALF_UP));

            BigDecimal purchaseGuaranteeMoney = goodsInfo.getPurchaseGuaranteeMoney() == null ? BigDecimal.ZERO : goodsInfo.getPurchaseGuaranteeMoney();
            goodsInfo.setPurchaseGuaranteeMoney(purchaseGuaranteeMoney.setScale(2, RoundingMode.HALF_UP));
        });
        return new ResponseJson(calculate);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String downloadPdf(SettlementBasicInfo settlementBasicInfo, HttpServletResponse response) {
        try {
            XMlToDoc xmlDoc = new XMlToDoc();
            //模板中填充数据
            File file = inputData(settlementBasicInfo, xmlDoc);
            FileInputStream inputFile = new FileInputStream(file);
            byte[] buffer = new byte[(int) file.length()];
            inputFile.read(buffer);
            inputFile.close();
            return "data:application/pdf;base64," + Base64.encodeBase64String(buffer);
        } catch (Exception e) {
            throw new BusinessException(CodeUtil.FAIL, "生成结算单出错");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SettlementElectronicInfo autoSign(Long businessKey, String taskId) {
        SettlementBasicInfo settlementBasicInfo = settlementBasicInfoService.getById(businessKey);
        SettlementElectronicInfo settlementElectronicInfo = settlementElectronicInfoService.getOne(new QueryWrapper<SettlementElectronicInfo>().eq("c_settlement_basic_info_id", businessKey));
        if (settlementElectronicInfo == null) {
            settlementElectronicInfo = new SettlementElectronicInfo();
            settlementElectronicInfo.setSettlementBasicInfoId(businessKey);
            Platform platform = platformService.getById(settlementBasicInfo.getTradingPlatformId());
            Customer supplier = customerService.getById(settlementBasicInfo.getSupplierId());
            //认证状态  签署状态初始化
            if (supplier.getAuthStatus() == 0) {
                String result = ElectronicSignatureUtil.getAuthInfo(supplier.getSocialCreditCode(), "2");
                if ("1".equals(result)) {
                    supplier.setAuthStatus(1);
                    customerService.updateById(supplier);
                    purchContractElectronicInfoService.lambdaUpdate()
                            .eq(PurchContractElectronicInfo::getFddCustomerId, supplier.getFddCustomerId())
                            .set(PurchContractElectronicInfo::getCertifyStatus, 1)
                            .update();
                } else {
                    throw new BusinessException(CodeUtil.FAIL, "请先前往企业信息管理模块下的供应商，打开认证链接，进行认证操作再返回此处进行后续操作");
                }
            }
            settlementElectronicInfo.setCertifyStatus(supplier.getAuthStatus());
            settlementElectronicInfo.setCertifyLink(supplier.getShortAuthUrl());
            settlementElectronicInfo.setSignStatus(0);
            //获取制作好的结算单(未签署)
            AttachmentDto attachmentDtoAcceptanceFile = AttachmentDto.builder()
                    .setEntityId(settlementBasicInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE)
                    .build();
            List<FileStorage> fileStorages = sysAttachmentRefService.getFiles(attachmentDtoAcceptanceFile);
            File pdfFile = new File(fileStorages.get(0).getAbsolutePath());
            //上传合同
            String contractId = UUID.randomUUID().toString().trim().replaceAll("-", "").toUpperCase();
            settlementBasicInfo.setContractId(contractId);
            settlementBasicInfoService.updateById(settlementBasicInfo);
            String docTitle = "上游验收单" + settlementBasicInfo.getSettlementNumber();
            String transactionId = "settlementFDD" + settlementBasicInfo.getSettlementNumber();
            ElectronicSignatureUtil.uploadContract(contractId, docTitle, pdfFile);
            //采购合同自动签署
            String signKeyword = "mypt";
            ElectronicSignatureUtil.autoSign(transactionId, contractId, platform.getFddCustomerId(), docTitle, signKeyword);
            //批量手动签署 此处只有一个合同
            List<FddSignData> fddSignDataList = new ArrayList<FddSignData>();
            FddSignData fddSignData = new FddSignData();
            fddSignData.setContractId(contractId);
            fddSignData.setContractType("settlement");
            fddSignData.setSignKeyword("gys");
            fddSignData.setTransactionId("signSettlementFDD" + businessKey + "FDD" + taskId + "FDD" + ThreadLocalUtil.getUserId());
            fddSignDataList.add(fddSignData);
            String contractLink = ElectronicSignatureUtil.manualBatchSign(supplier.getFddCustomerId(), fddSignDataList, settlementBasicInfo.getSettlementNumber());
            //合同链接
            String shortUrl = ElectronicSignatureUtil.shortUrl(null, contractLink);
            settlementElectronicInfo.setTransactionId(fddSignData.getTransactionId());
            settlementElectronicInfo.setShortContractLink(shortUrl);
            settlementElectronicInfo.setShortContractLinkCreate(new Date());
            settlementElectronicInfo.setContractLink(contractLink);
            settlementElectronicInfoService.save(settlementElectronicInfo);
        }
        return settlementElectronicInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean getSignTppe(String electronicInfoId, String taskId, String basicId) {
        if (StringUtil.isEmpty(electronicInfoId) || StringUtil.isEmpty(taskId) || StringUtil.isEmpty(basicId)) {
            throw new ValidatorException(CodeUtil.FAIL, "参数不能为空!");
        }

        boolean result = false;
        SettlementElectronicInfo electronicInfo = settlementElectronicInfoService.getById(electronicInfoId);
        if (electronicInfo == null || !electronicInfo.getSignStatus().equals(1)) {
            SettlementBasicInfo settlementBasicInfo = settlementBasicInfoService.getById(basicId);
            String contractId = settlementBasicInfo.getContractId();
            Customer supplier = customerService.getById(settlementBasicInfo.getSupplierId());
            String customerId = supplier.getFddCustomerId();
            if (electronicInfo.getSignStatus().equals(0)) {
                String signResult = ElectronicSignatureUtil.getSignInfo(customerId, contractId, electronicInfo.getTransactionId());
                if (signResult.equals("3000")) {
                    result = true;
                    String[] objStrs = new String[]{"signSettlement", electronicInfo.getSettlementBasicInfoId() + "", taskId};
                    doSignCallBackByQuery(contractId, objStrs);
                }
            } else {
                result = true;
            }
        } else {
            result = true;
        }
        return result;
    }

    @Override
    public void downloadPdfSign(Long settlementBasicInfoId, HttpServletResponse res) {
//        AttachmentDto attachmentDto = AttachmentDto.builder()
//                .setEntityId(settlementBasicInfoId)
//                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_SIGNED_FILE)
//                .build();
//        List<FileStorage> files = sysAttachmentRefService.getFiles(attachmentDto);
        List<FileStorageDO> files = fileService.findByBusinessId(settlementBasicInfoId,FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_SIGNED_FILE.getCode());
        if(CollectionUtil.isNotEmpty(files)){
            //return fileService.downloadFile(files.get(0).getId());
            //FileStorageDO fileStorage = fileService.getById(files.get(0).getId());
            FileStorageDO fileStorage = files.get(0);
            if (fileStorage != null) {
                String fileName = fileStorage.getOriginalName();
                String fileNameEncodeStr = "null";
                try {
                    fileNameEncodeStr = java.net.URLEncoder.encode(fileName, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    fileNameEncodeStr = "";
                }
                String path = fileStorage.getAbsolutePath();
                File file = new File(path);
                try {
                    FileInputStream fis = new FileInputStream(file);
                    res.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
                    res.setHeader("content-disposition", "attachment;filename=" + fileNameEncodeStr);
                    //res.setContentLength((int)file.length());
                    ServletOutputStream outputStream = res.getOutputStream();
                   // res.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
                    byte[] b = new byte[1000];
                    int read = fis.read(b);
                    while(read>0){
                        outputStream.write(b,0,read);
                        read = fis.read(b);
                    }
                    fis.close();
                    outputStream.flush();
                    outputStream.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void downloadReport(Long settlementBasicInfoId, HttpServletResponse res) {
        List<FileStorageDO> fileStorageDOList = fileService.findByBusinessId(settlementBasicInfoId, FileModuleDict.ChildEnum.SETTLEMENT_CONTRACT_REPORT.getCode());
        fileService.downloadFile(fileStorageDOList.get(0).getId(),res);
    }

    @Override
    public void doSignCallBackByQuery(String contractId, String[] fdds) {
        Long settlementBasicInfoId = Long.valueOf(fdds[1]);
        String taskId = fdds[2];

        SettlementElectronicInfo settlementElectronicInfo = settlementElectronicInfoService.getOne(new QueryWrapper<SettlementElectronicInfo>().eq("c_settlement_basic_info_id", settlementBasicInfoId));
        //合同下载
        String contDownUrl = ElectronicSignatureUtil.downloadContract(contractId);
        FileStorage contractSupplementFile = fileStorageService.addFileStorageWithBelongAndName(fdds[1], FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_SIGNED_FILE, contDownUrl, null);
        //判断是否已经下载合同
        List<FileStorage> contractSupplementFiles = sysAttachmentRefService.getFiles(AttachmentDto.builder()
                .setEntityId(Long.valueOf(fdds[1]))
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_SIGNED_FILE)
                .build());
        if (CollectionUtil.isEmpty(contractSupplementFiles)) {
            fileStorageService.saveAttachmentRefByFileStorage(contractSupplementFile, FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_SIGNED_FILE, Long.valueOf(fdds[1]));
        }
        //合同归档
        ElectronicSignatureUtil.contractFiled(contractId);
        //电子文件签署线上出证下载
        String reportDownUrl = ElectronicSignatureUtil.complianceContractReport(contractId);
        FileStorage contractSupplementReportFile = fileStorageService.addFileStorageWithBelongAndName(fdds[1], FileModuleDict.ChildEnum.SETTLEMENT_CONTRACT_REPORT, reportDownUrl, null);
        fileStorageService.saveAttachmentRefByFileStorage(contractSupplementReportFile, FileModuleDict.ChildEnum.SETTLEMENT_CONTRACT_REPORT, Long.valueOf(fdds[1]));
        //获取最新签署信息，更新签署状态
        settlementElectronicInfo.setSignStatus(1);
        settlementElectronicInfoService.updateById(settlementElectronicInfo);
        //签署后流程
        settlementElectronicInfoService.sign(settlementElectronicInfo, taskId);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void billUnitPriceAdjust(SettlementBasicInfo settlementBasicInfo) {
        //生成新的结算单
        List<FileStorageDO> fileStorageDOS3 = fileService.findByBusinessId(settlementBasicInfo.getId(), FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE.getCode());
        for (FileStorageDO fileStorageDO:fileStorageDOS3) {
            fileService.updateBusinessId(fileStorageDO.getId(),null);
        }
        SettlementBasicInfo saveSettlementBasicInfo = addSettlement(settlementBasicInfo, null);
        Long odlId = settlementBasicInfo.getId();
        String taskId = "";
        User user = userService.getByLoginName("admin");
        ThreadLocalUtil.setUser(user);
        //审核处理人
        List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.LEGAL_SPECIALIST);
        if (legalSpecialists == null || legalSpecialists.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.OPERATION_SPECIALIST + "角色内无任何用户！");
        }
//        BusinessAssignee legalSpecialist = new BusinessAssignee(settlementBasicInfo.getId(), ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE);
//        legalSpecialist.setCandidateId(StringUtils.join(legalSpecialists, ","));
//        legalSpecialist.setAssigneeType(ConstantUtil.LEGAL_SPECIALIST);
//        assigneeService.add(legalSpecialist);
        //2.提交人-- C端用户
        SupplierInfo supplierInfo = iSupplierInfoService.get(settlementBasicInfo.getSupplierId());
        //3.开启流程实例
        Map<String, Object> procVariables = new HashMap<>();
        procVariables.put(ConstantUtil.UNIT_PRICE_ADJUST_ASSIGNEE,user.getId());
        procVariables.put(ConstantUtil.BILL_SIGN_ASSIGNEE,user.getId());
        Map<String, Object> msgVariables = new HashMap<>();
        //查询条件：
        ProcessInstance processInst = flowableService.startProcessInstance(settlementBasicInfo, procVariables,
                FlowableUtil.generateBusinessKey(settlementBasicInfo, ConstantUtil.BILL_UNIT_PRICE_ADJUST, null), msgVariables, ConstantUtil.BILL_UNIT_PRICE_ADJUST);
        if (processInst == null) {
            throw new BusinessException(CodeUtil.FAIL, "流程启动失败");
        }
        Boolean result = false;
        Long historyId = addHistoryBillBasicInformation(settlementBasicInfo);
        if (StringUtil.isEmpty(taskId) ) {
            //完成流程第一步提交验收单，开启下一步法务审核
            String processInstId = processInst.getId();
            Task task = flowableService.findRuntimeTaskByProcessInstId(processInstId).get(0);
            Map<String, Object> procVariables1 = new HashMap<>();
            procVariables1.put(ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE,
                    assigneeService.getCandidateByBusiness(settlementBasicInfo.getId(), ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE, ConstantUtil.LEGAL_SPECIALIST));
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, "结算单编号：" + settlementBasicInfo.getSettlementNumber());
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "结算单编号为“" + settlementBasicInfo.getSettlementNumber() + "”的结算单已进入“单价变更—法务审核”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);
            settlementBasicInfo.setId(odlId);
            result = flowableService.completeMyTaskCustomer(task.getId(), settlementBasicInfo, procVariables1, null, historyId, msgVariables, ConstantUtil.BILL_UNIT_PRICE_ADJUST, user.getId());
            if (result == null || !result) {
                throw new ValidatorException(CodeUtil.FAIL, "结算单单价变更出错啦！");
            }
        } else {
            //法务审核
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, "结算单编号：" + settlementBasicInfo.getSettlementNumber());
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "结算单编号为“" + settlementBasicInfo.getSettlementNumber() + "”的结算单已进入“单价变更—结算单签署”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);
            flowableService.completeMyTask(taskId, settlementBasicInfo, procVariables, null, historyId, msgVariables, ConstantUtil.BILL_UNIT_PRICE_ADJUST, legalSpecialists);
        }


    }

    @Override
    public Object billSign(String electronicInfoId, String taskId) {
        SettlementElectronicInfo settlementElectronicInfo =  settlementElectronicInfoService.getById(electronicInfoId);
        //签署后流程
        settlementElectronicInfoService.sign(settlementElectronicInfo, taskId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void c_updateBill(SettlementBasicInfo settlementBasicInfo) {
        //生成新的结算单
        List<FileStorageDO> fileStorageDOS3 = fileService.findByBusinessId(settlementBasicInfo.getId(), FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE.getCode());
        for (FileStorageDO fileStorageDO:fileStorageDOS3) {
            fileService.updateBusinessId(fileStorageDO.getId(),null);
        }
        SettlementBasicInfo saveSettlementBasicInfo = addSettlement(settlementBasicInfo, null);
        //审核处理人
        List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.LEGAL_SPECIALIST);
        if (legalSpecialists == null || legalSpecialists.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.OPERATION_SPECIALIST + "角色内无任何用户！");
        }
        Long oldId = settlementBasicInfo.getId();
        String taskId = settlementBasicInfo.getTaskId();
        SupplierInfo supplierInfo = iSupplierInfoService.get(settlementBasicInfo.getSupplierId());
        User user = userService.getByLoginName("admin");
        ThreadLocalUtil.setUser(user);
        if(taskId == null){
            //2.新增处理人-- C端用户
            //审核处理人
            BusinessAssignee legalSpecialist = new BusinessAssignee(settlementBasicInfo.getId(), ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE);
            legalSpecialist.setCandidateId(StringUtils.join(legalSpecialists, ","));
            legalSpecialist.setAssigneeType(ConstantUtil.LEGAL_SPECIALIST);
            assigneeService.add(legalSpecialist);
            //签署处理人
            BusinessAssignee signtManager = new BusinessAssignee(settlementBasicInfo.getId(), ConstantUtil.BILL_BASIC_INFORMATION);
            signtManager.setAssigneeId(supplierInfo.getSysUserId());
            signtManager.setAssigneeType(ConstantUtil.SUPPLIER);
            assigneeService.add(signtManager);
            //3.开启流程实例
            Map<String, Object> procVariables = new HashMap<>();
            procVariables.put(ConstantUtil.BILL_ASSIGNEE,user.getId());
            procVariables.put(ConstantUtil.BILL_SIGN_ASSIGNEE,user.getId());
            Map<String, Object> msgVariables = new HashMap<>();
            //查询条件：结算单编号/业务编号/核心企业名称/业务名称/供应商名称
            Enterprise enterprise = iEnterpriseService.getById(supplierInfo.getcEnterpriseId());
            Enterprise customer = iEnterpriseService.getById(settlementBasicInfo.getEnterpriseCustomerInfoId());
//        Customer customer = customerService.getById(settlementBasicInfo.getEnterpriseCustomerInfoId());
//        Customer supplier = customerService.getById(settlementBasicInfo.getSupplierId());
//        String queryBusiness = settlementBasicInfo.getSettlementNumber() + FlowableUtil.splitChar + settlementBasicInfo.getBusinessNumber() + FlowableUtil.splitChar + customer.getEnterpriseName() + FlowableUtil.splitChar + businessBasicInfo.getName() + FlowableUtil.splitChar + supplier.getEnterpriseName();
//        String queryBusiness = settlementBasicInfo.getSettlementNumber() + FlowableUtil.splitChar + settlementBasicInfo.getBusinessNumber()+ FlowableUtil.splitChar + customer.getCorporateName() + FlowableUtil.splitChar + businessBasicInfo.getName()+ FlowableUtil.splitChar + enterprise.getCorporateName();
            String queryBusiness = settlementBasicInfo.getSettlementNumber() + FlowableUtil.splitChar + settlementBasicInfo.getBusinessNumber();
            ProcessInstance processInst = flowableService.startProcessInstance(settlementBasicInfo, procVariables,
                    FlowableUtil.generateBusinessKey(settlementBasicInfo, ConstantUtil.BILL_BASIC_INFORMATION, queryBusiness), msgVariables, ConstantUtil.BILL_BASIC_INFORMATION);
            if (processInst == null) {
                throw new BusinessException(CodeUtil.FAIL, "流程启动失败");
            }
            String processInstId = processInst.getId();
            Task task = flowableService.findRuntimeTaskByProcessInstId(processInstId).get(0);
            taskId = task.getId();
        }

        //修改原始记录
        if (settlementBasicInfo.getSubmit()) {
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.UPDATE, settlementBasicInfo);
            //保存历史记录供getView方法使用
            Long historyId = addHistoryBillBasicInformation(settlementBasicInfo);
            //完成修改流转到下一流程法务审核
            Map<String, Object> procVariables = new HashMap<>();
            procVariables.put(ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE,
                    assigneeService.getCandidateByBusiness(settlementBasicInfo.getId(), ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE, ConstantUtil.LEGAL_SPECIALIST));
            Map<String, Object> msgVariables = new HashMap<>();
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, "结算单编号：" + settlementBasicInfo.getSettlementNumber());
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "结算单编号为“" + settlementBasicInfo.getSettlementNumber() + "”的结算单已进入“"
                            + ConstantConversionUtil.flowBusinessKeyNames.get(ConstantUtil.BILL_BASIC_INFORMATION) + "—法务审核”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);
            settlementBasicInfo.setId(oldId);
//            flowableService.completeMyTask(taskId, settlementBasicInfo, procVariables, null,
//                    historyId, msgVariables, ConstantUtil.BILL_BASIC_INFORMATION, legalSpecialists);
            flowableService.completeMyTask(taskId, settlementBasicInfo, procVariables, null, historyId, msgVariables, ConstantUtil.BILL_BASIC_INFORMATION, legalSpecialists);
        }
    }

    private File inputData(SettlementBasicInfo settlementBasicInfo, XMlToDoc xmlDoc) {
        //业务信息
//        BusinessBasicInfo businessBasicInfo = businessBasicInfoService.getByBusinessNumber(settlementBasicInfo.getBusinessNumber());
        //收货单位
        Platform receiver = platformService.getById(settlementBasicInfo.getTradingPlatformId());
        //货物相关
        List<SettlementGoodsInfo> settlementGoodsInfos;
        //货物信息
//        if (settlementBasicInfo.getId() != null) {
//            settlementGoodsInfos = settlementGoodsInfoService.list(
//                    new QueryWrapper<SettlementGoodsInfo>().eq("c_settlement_basic_info_id", settlementBasicInfo.getId()));
//        } else {
            settlementGoodsInfos = settlementBasicInfo.getSettlementGoodsInfos();
//        }
        //合同信息 采购合同
        PurchContractManagement purchContractManagement = purchContractService.getOne(
                new QueryWrapper<PurchContractManagement>()
                        .eq("business_number", settlementBasicInfo.getBusinessNumber())
                        .eq("c_supplier_info_id", settlementBasicInfo.getSupplierId()));
        PurchContractBasicInfo purchContractBasicInfo = purchContractBasicInfoService.getOne(
                new QueryWrapper<PurchContractBasicInfo>().eq("c_purch_contract_management_id", purchContractManagement.getId()).orderByDesc("gmt_create").last("LIMIT 1")
        );
//        List<PurchContractBuyerSeller> purchContractBuyerSellers = purchContractBuyerSellerService.list(new QueryWrapper<PurchContractBuyerSeller>().eq("c_purch_contract_basic_info_id", purchContractBasicInfo.getId()).eq("buyer_or_seller", 1));
//        StringBuffer names = new StringBuffer();
//        for (PurchContractBuyerSeller purchContractBuyerSeller : purchContractBuyerSellers) {
//            String name = purchContractBuyerSeller.getName() + ",";
//            names.append(name);
//        }
        //最后一次审核的信息
        PurchContractApproval purchContractApproval = purchContractApprovalService.getOne(
                new LambdaQueryWrapper<PurchContractApproval>()
                        .eq(PurchContractApproval::getPurchContractBasicInfoId,
                                purchContractBasicInfo.getId())
                        .orderByDesc(PurchContractApproval::getGmtCreate).last("LIMIT 1"));
        List<PurchContractNeedUserRel> buyers = iPurchContractNeedUserRelService.list(
                new LambdaQueryWrapper<PurchContractNeedUserRel>()
                        .eq(PurchContractNeedUserRel::getPurchContractApprovalId,
                                purchContractApproval.getId()));
        StringBuffer names = new StringBuffer();
        for (PurchContractNeedUserRel purchContractNeedUserRel : buyers) {
            String name = purchContractNeedUserRel.getName() + ",";
            names.append(name);
        }
        String name = names.toString();
        name = name.substring(0, names.length() - 1);
        //供货单位
//        Customer supplier = customerService.getById(settlementBasicInfo.getSupplierId());
        SupplierInfo supplierInfo = iSupplierInfoService.get(settlementBasicInfo.getSupplierId());
        Enterprise enterprise = iEnterpriseService.getById(supplierInfo.getcEnterpriseId());

        //填充数据开始
        try {
            Map<String, Object> dataMap = new HashMap<>();
            //供货单位
            dataMap.put("supplierName", enterprise.getCorporateName());
            //合同编号
            dataMap.put("contractNumber", purchContractBasicInfo.getContractNumber());
            //结算日期
            dataMap.put("settlementDate", DateUtil.dateToString(settlementBasicInfo.getSettlementDate(), DateUtil.dayFormat));
            //收货单位 贸易平台
            dataMap.put("platformName", receiver.getPlatformName());
            //经办人 需方收货人姓名
            dataMap.put("manager", name);
            //供货单位
            dataMap.put("supplierName", enterprise.getCorporateName());
            //经办人（供应商）
            dataMap.put("settlementManager", settlementBasicInfo.getOperatorSupplier());
            //填充货物信息
            TableRenderData tableRenderData = makeGoddsList(settlementGoodsInfos, dataMap);
            dataMap.put("dealGoodsList", tableRenderData);
            File docxFile = null;
            String fileName;
            if (settlementBasicInfo.getSettlementNumber() == null) {
                fileName = "settlement" + settlementBasicInfo.getBusinessNumber() + DateUtil.getCurrentDate()
                        .replace("-", "").replace(":", "") + ThreadLocalUtil.getUserId();
            } else {
                BigDecimal allPurchaseTotalPrice = settlementGoodsInfos.stream().map(SettlementGoodsInfo::getPurchaseTotalPrice)
                        .reduce(BigDecimal::add).orElse(new BigDecimal(0));
                fileName = settlementBasicInfo.getSettlementNumber() + "-" + allPurchaseTotalPrice.toString() + "-上游结算";
            }
            docxFile = WordWriter.buildSettlementFile(fileName, dataMap);
            String suffix = FileUtil.getSuffix(docxFile.getName());
            String newPath = docxFile.getAbsolutePath().replace(suffix, ".pdf");
            File pdfFile = OfficeConverterUtil.office2Pdf(docxFile.getAbsolutePath(), newPath);
            return pdfFile;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(CodeUtil.FAIL, "下载结算清单错误" + e.getMessage());
        }
    }

    private TableRenderData makeGoddsList(List<SettlementGoodsInfo> settlementGoodsInfos, Map<String, Object> dataMap) {
        int number = 0;
        BigDecimal sum = new BigDecimal("0.0000");
        BigDecimal sumPrice = new BigDecimal("0.00");

        Tables.TableBuilder tableBuilder = Tables.ofA4MediumWidth();

        BorderStyle borderStyle = new BorderStyle();
        borderStyle.setSize(5);
        borderStyle.setType(XWPFTable.XWPFBorderType.SINGLE);

        String supplierName = (String) dataMap.get("supplierName");

        RowRenderData header0 = Rows.of("供货单位：", null, supplierName, null, null, null, null, null, null)
                .center()
                .textFontFamily("宋体")
                .textFontSize(10)
                .create();

        tableBuilder.addRow(header0);

        String contractNumber = (String) dataMap.get("contractNumber");

        RowRenderData header1 = Rows.of("合同编号：", null, contractNumber, null, null, null, null, null, null)
                .center()
                .textFontFamily("宋体")
                .textFontSize(10)
                .create();

        tableBuilder.addRow(header1);

        String settlementDate = (String) dataMap.get("settlementDate");

        RowRenderData header2 = Rows.of("结算日期：", null, settlementDate, null, null, null, null, null, null)
                .center()
                .textFontFamily("宋体")
                .textFontSize(10)
                .create();

        tableBuilder.addRow(header2);

        RowRenderData header = Rows.of("序号", "名称", "厂家", "型号", "材质", "单位", "数量", "结算单价", "结算金额")
                .center()
                .textFontFamily("宋体")
                .textFontSize(10)
                .create();

        tableBuilder.addRow(header);
        int indexNumber = 1;

        for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
            AcceptanceGoodsInfo acceptanceGoodsInfo = acceptanceGoodsInfoService.getById(settlementGoodsInfo.getAcceptanceGoodsInfoId());
            number = number + 1;
            sum = sum.add(acceptanceGoodsInfo.getGoodsQuantity());
            sumPrice = sumPrice.add(settlementGoodsInfo.getPurchaseTotalPrice().setScale(2, RoundingMode.HALF_UP));

            RowRenderData data = Rows.of(indexNumber + "", acceptanceGoodsInfo.getGoodsName(), acceptanceGoodsInfo.getGoodsFactory()
                            , acceptanceGoodsInfo.getGoodsType(), acceptanceGoodsInfo.getGoodsMaterial(), acceptanceGoodsInfo.getGoodsUnit()
                            , settlementGoodsInfo.getGoodsQuantity().toString(), settlementGoodsInfo.getPurchasePrice().setScale(2, RoundingMode.HALF_UP).toString()
                            , settlementGoodsInfo.getPurchaseTotalPrice().setScale(2, RoundingMode.HALF_UP).toString())
                    .center()
                    .textFontFamily("宋体")
                    .textFontSize(10)
                    .create();
            tableBuilder.addRow(data);
            indexNumber++;
        }

        RowRenderData foot = Rows.of("合计", null, null, null, null, null, sum.toString(), null, sumPrice.toString())
                .center()
                .textFontFamily("宋体")
                .textFontSize(10)
                .create();

        tableBuilder.addRow(foot);

        MergeCellRule rule = MergeCellRule.builder().map(MergeCellRule.Grid.of(0, 0), MergeCellRule.Grid.of(0, 1))
                .map(MergeCellRule.Grid.of(0, 2), MergeCellRule.Grid.of(0, 8))
                .map(MergeCellRule.Grid.of(1, 0), MergeCellRule.Grid.of(1, 1))
                .map(MergeCellRule.Grid.of(1, 2), MergeCellRule.Grid.of(1, 8))
                .map(MergeCellRule.Grid.of(2, 0), MergeCellRule.Grid.of(2, 1))
                .map(MergeCellRule.Grid.of(2, 2), MergeCellRule.Grid.of(2, 8))
                .build();

        tableBuilder.mergeRule(rule);

        int[] colWidthsPercent = {10, 15, 15, 10, 10, 10, 10, 10, 10};


        TableRenderData goodsTable = tableBuilder.center().percentWidth("100%", colWidthsPercent).border(borderStyle).create();
        return goodsTable;
    }

    private SettlementBasicInfo updateBillBasicInformation(SettlementBasicInfo settlementBasicInfo, HttpServletRequest request) throws IOException {
        Dictionary entryDic = dictService.getByCode(SettlementDict.ChildEnum.ENTRY.getCode());
        Dictionary creatDic = dictService.getByCode(SettlementDict.ChildEnum.CREATE.getCode());
        if (entryDic == null || creatDic == null) {
            throw new ValidatorException(CodeUtil.FAIL, "状态字典项为空！");
        }
        SettlementBasicInfo oldSettlement = settlementBasicInfoService.getById(settlementBasicInfo.getId());
        settlementBasicInfo.setSettlementNumber(oldSettlement.getSettlementNumber());
        //先删除所有需要删除的文件
        List<Long> deleteFileIds = settlementBasicInfo.getDeleteFileIds();
        if (deleteFileIds != null && deleteFileIds.size() > 0) {
            sysAttachmentRefService.removeFilestorageAndRef(deleteFileIds);
        }
        AttachmentDto attachmentDtoAdditional = AttachmentDto.builder()
                .setEntityId(settlementBasicInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_SUPPLEMENT_FILE)
                .build();
        List<FileStorage> files = sysAttachmentRefService.getFiles(attachmentDtoAdditional);
        //修改结算单基础信息
        if (settlementBasicInfo.getSubmit()) {
            settlementBasicInfo.setSettlementStatus(ProjectInitiationStatusDict.ChildEnum.PROCESSING.getCode());
        }
        settlementBasicInfoService.updateById(settlementBasicInfo);
        //修改结算单相关货物信息  先删除再新增
        settlementGoodsInfoService.remove(new QueryWrapper<SettlementGoodsInfo>().eq("c_settlement_basic_info_id", settlementBasicInfo.getId()));
        List<SettlementGoodsInfo> settlementGoodsInfos = settlementBasicInfo.getSettlementGoodsInfos();
        if (CollectionUtil.isNotEmpty(settlementGoodsInfos)) {
            //所选货物要么全底层要么全未底层
//            List<Long> acceptanceBasicInfoIds = settlementGoodsInfos.stream().map(SettlementGoodsInfo::getAcceptanceBasicInfoId)
//                    .collect(Collectors.toList());
//            List<AcceptanceBasicInfo> acceptanceBasicInfos = acceptanceBasicInfoService.listByIds(acceptanceBasicInfoIds);
//            List<Boolean> receivables =
//
//
//            .stream().map(AcceptanceBasicInfo::getReceivables).distinct()
//                    .collect(Collectors.toList());
//            if (receivables != null && receivables.size() > 1) {
//                throw new ValidatorException(CodeUtil.FAIL, "验收单不可混选（已底层和未底层）");
//            }

            for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
                settlementGoodsInfo.setSettlementBasicInfoId(settlementBasicInfo.getId());
            }
            //校验验收单货物
            List<Long> acceptanceBasicInfoIds = settlementGoodsInfos.stream().map(SettlementGoodsInfo::getcAcceptanceBasicInfoId)
                    .distinct().collect(Collectors.toList());
            acceptanceBasicInfoIds.forEach(id -> {
                AcceptanceBasicInfo basicInfo = acceptanceBasicInfoService.getById(id);
                if (basicInfo.getSettlement()) {
                    throw new ValidatorException(CodeUtil.FAIL, "存在已结算或者正在结算的货物");
                } else {
                    if (settlementBasicInfo.getSubmit()) {
                        basicInfo.setSettlement(true);
                        acceptanceBasicInfoService.updateById(basicInfo);
                    }
                }
            });
            settlementGoodsInfoService.saveBatch(settlementGoodsInfos);
        }
        //修改回款计划   先删除再新增
        settlementRepaymentPlanService.remove(new QueryWrapper<SettlementRepaymentPlan>().eq("c_settlement_basic_info_id", settlementBasicInfo.getId()));
        List<SettlementRepaymentPlan> settlementRepaymentPlans = settlementBasicInfo.getSettlementRepaymentPlans();
        for (SettlementRepaymentPlan settlementRepaymentPlan : settlementRepaymentPlans) {
            settlementRepaymentPlan.setSettlementBasicInfoId(settlementBasicInfo.getId());
        }
        settlementRepaymentPlanService.saveBatch(settlementRepaymentPlans);
        //下游结算清单附件
        AttachmentDto attachmentDto = AttachmentDto.builder()
                .setEntityId(settlementBasicInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_FILE)
                .build();
        List<MultipartFile> fileList = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.FILE_NAME);
        sysAttachmentRefService.saveFileAndRef(fileList, attachmentDto);
        //再新增结算单说明附件
        List<MultipartFile> additionalFiles = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.ADDITIONAL);
        sysAttachmentRefService.saveFileAndRef(additionalFiles, attachmentDtoAdditional);
        //再新增结算单网价附件
        AttachmentDto attachmentDtoNetPrice = AttachmentDto.builder()
                .setEntityId(settlementBasicInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_NET_PRICE_FILE)
                .build();
        List<MultipartFile> netPriceFiles = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.NET_PRICE_FILE);
        sysAttachmentRefService.saveFileAndRef(netPriceFiles, attachmentDtoNetPrice);
        //删除旧的上游结算单
        AttachmentDto attachmentDtoAcceptanceFile = AttachmentDto.builder()
                .setEntityId(settlementBasicInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE)
                .build();
        sysAttachmentRefService.removeFilestorageAndRef(attachmentDtoAcceptanceFile);
        if (settlementBasicInfo.getSubmit()) {
            for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
                if (settlementGoodsInfo.getSalesPrice() != null && settlementGoodsInfo.getSalesPrice().compareTo(BigDecimal.ZERO) <= 0) {
                    throw new BusinessException(CodeUtil.FAIL, "请填写销售单价并进行质保金计算");
                }
            }
            //将文件set集合的key分类
            ArrayList<String> additional = new ArrayList<>();
            if (request instanceof MultipartHttpServletRequest) {
                MultiValueMap<String, MultipartFile> multiValueMap = ((MultipartHttpServletRequest) request)
                        .getMultiFileMap();
                Set<String> keys = multiValueMap.keySet();
                for (String key : keys) {
                    //验收单附件key
                    if (key.startsWith("additional")) {
                        additional.add(key);
                    }
                }
            }
            //结算单经办人验证
            //销售合同
            CSalesContract salesContractManagement = salesContractService.getOne(
                    new QueryWrapper<CSalesContract>()
                            .eq("business_number", settlementBasicInfo.getBusinessNumber())
                            .last("LIMIT 1"));
            CSalesContractBasicInfo salesContractBasicInfo = salesContractBasicInfoService.getOne(
                    new QueryWrapper<CSalesContractBasicInfo>().eq("sales_contract_management_id", salesContractManagement.getId()).orderByDesc("gmt_create").last("LIMIT 1"));
            List<CSalesContractPersonInfo> contractPersonInfos = salesContractPersonInfoService.lambdaQuery()
                    .eq(CSalesContractPersonInfo::getcSalesContractBasicInfoId, salesContractBasicInfo.getId())
                    .eq(CSalesContractPersonInfo::getType, "结算经办人").list();
            boolean contains = false;
            for (CSalesContractPersonInfo contractPersonInfo : contractPersonInfos) {
                contains = settlementBasicInfo.getOperatorEnterprise().contains(contractPersonInfo.getName());
                if (contains) {
                    break;
                }
            }
            if (!contains && additional.size() == 0) {
                throw new ValidatorException(CodeUtil.FAIL, "结算单经办人和销售合同规定经办人不一致需要上传说明附件！");
            }
            try {
                XMlToDoc xmlDoc = new XMlToDoc();
                //模板中填充数据
                File file = inputData(settlementBasicInfo, xmlDoc);
                List<FileStorage> accepyanceFile = new ArrayList<>();
                FileStorage fileStorage = new FileStorage(file.getName(), file.getAbsolutePath(), FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE);
                accepyanceFile.add(fileStorage);
                sysAttachmentRefService.saveFileAndRefHis(accepyanceFile, attachmentDtoAcceptanceFile);
            } catch (Exception e) {
                throw new BusinessException(CodeUtil.FAIL, "生成结算单出错");
            }
        }
        //生成新的上游结算单

        return settlementBasicInfo;
    }

    private void startProcess(SettlementBasicInfo settlementBasicInfo) {
        Long odlId = settlementBasicInfo.getId();
        User user = userService.getByLoginName("admin");
        ThreadLocalUtil.setUser(user);
        //2.新增处理人-- C端用户
        SupplierInfo supplierInfo = iSupplierInfoService.get(settlementBasicInfo.getSupplierId());
        //审核处理人
        List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.LEGAL_SPECIALIST);
        if (legalSpecialists == null || legalSpecialists.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.ACCOUNTANT + "角色内无任何用户！");
        }
        BusinessAssignee legalSpecialist = new BusinessAssignee(settlementBasicInfo.getId(), ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE);
        legalSpecialist.setCandidateId(StringUtils.join(legalSpecialists, ","));
        legalSpecialist.setAssigneeType(ConstantUtil.LEGAL_SPECIALIST);
        assigneeService.add(legalSpecialist);
        //签署处理人
        BusinessAssignee signtManager = new BusinessAssignee(settlementBasicInfo.getId(), ConstantUtil.BILL_BASIC_INFORMATION);
        signtManager.setAssigneeId(supplierInfo.getSysUserId());
        signtManager.setAssigneeType(ConstantUtil.SUPPLIER);
        assigneeService.add(signtManager);

        //3.开启流程实例
        Map<String, Object> procVariables = new HashMap<>();
        procVariables.put(ConstantUtil.BILL_ASSIGNEE,user.getId());
        procVariables.put(ConstantUtil.BILL_SIGN_ASSIGNEE,user.getId());
        Map<String, Object> msgVariables = new HashMap<>();
        //查询条件：结算单编号/业务编号/核心企业名称/业务名称/供应商名称
        Enterprise enterprise = iEnterpriseService.getById(supplierInfo.getcEnterpriseId());
        Enterprise customer = iEnterpriseService.getById(settlementBasicInfo.getEnterpriseCustomerInfoId());
//        Customer customer = customerService.getById(settlementBasicInfo.getEnterpriseCustomerInfoId());
//        Customer supplier = customerService.getById(settlementBasicInfo.getSupplierId());
//        String queryBusiness = settlementBasicInfo.getSettlementNumber() + FlowableUtil.splitChar + settlementBasicInfo.getBusinessNumber() + FlowableUtil.splitChar + customer.getEnterpriseName() + FlowableUtil.splitChar + businessBasicInfo.getName() + FlowableUtil.splitChar + supplier.getEnterpriseName();
//        String queryBusiness = settlementBasicInfo.getSettlementNumber() + FlowableUtil.splitChar + settlementBasicInfo.getBusinessNumber()+ FlowableUtil.splitChar + customer.getCorporateName() + FlowableUtil.splitChar + businessBasicInfo.getName()+ FlowableUtil.splitChar + enterprise.getCorporateName();
        String queryBusiness = settlementBasicInfo.getSettlementNumber() + FlowableUtil.splitChar + settlementBasicInfo.getBusinessNumber();
        ProcessInstance processInst = flowableService.startProcessInstance(settlementBasicInfo, procVariables,
                FlowableUtil.generateBusinessKey(settlementBasicInfo, ConstantUtil.BILL_BASIC_INFORMATION, queryBusiness), msgVariables, ConstantUtil.BILL_BASIC_INFORMATION);
        if (processInst == null) {
            throw new BusinessException(CodeUtil.FAIL, "流程启动失败");
        }
        if (settlementBasicInfo.getSubmit()) {
            //完成流程第一步提交验收单，开启下一步法务验收
            String processInstId = processInst.getId();
            Task task = flowableService.findRuntimeTaskByProcessInstId(processInstId).get(0);
            procVariables.put(ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE,
                    assigneeService.getCandidateByBusiness(settlementBasicInfo.getId(), ConstantUtil.BILL_APPROVAL_ASSIGNEE_CANDIDATE, ConstantUtil.LEGAL_SPECIALIST));
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, "结算单编号：" + settlementBasicInfo.getSettlementNumber());
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "结算单编号为“" + settlementBasicInfo.getSettlementNumber() + "”的结算单已进入“"
                            + ConstantConversionUtil.flowBusinessKeyNames.get(ConstantUtil.BILL_BASIC_INFORMATION) + "—法务审核”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);
            Long historyId = addHistoryBillBasicInformation(settlementBasicInfo);
            settlementBasicInfo.setId(odlId);
//            flowableService.completeMyTaskCustomer(task.getId(), settlementBasicInfo, procVariables, null, historyId, msgVariables, ConstantUtil.BILL_BASIC_INFORMATION, supplierInfo.getSysUserId());
            flowableService.completeMyTask(task.getId(), settlementBasicInfo, procVariables, null, historyId, msgVariables, ConstantUtil.BILL_BASIC_INFORMATION, legalSpecialists);
        }

    }


    private Long addHistoryBillBasicInformation(SettlementBasicInfo oldSettlementBasicInfo) {
        Long oldId = oldSettlementBasicInfo.getId();
        //保存结算单基础信息
        SettlementHisInfo settlementHisInfo = new SettlementHisInfo();
        BeanUtils.copyProperties(oldSettlementBasicInfo, settlementHisInfo);
        settlementHisInfo.setSettlementBasicInfoId(oldId);
        settlementHisInfoService.save(settlementHisInfo);
        //保存结算单相关货物信息
        List<SettlementGoodsInfo> settlementGoodsInfos = oldSettlementBasicInfo.getSettlementGoodsInfos();
        List goodList = new ArrayList();
        for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
            SettlementHisGoodsInfo billGoodsInformationHistory = new SettlementHisGoodsInfo();
            BeanUtils.copyProperties(settlementGoodsInfo, billGoodsInformationHistory);
            billGoodsInformationHistory.setSettlementHisInfoId(settlementHisInfo.getId());
            billGoodsInformationHistory.setAcceptanceBasicInfoId(settlementGoodsInfo.getcAcceptanceBasicInfoId());
            goodList.add(billGoodsInformationHistory);
        }
        settlementHisGoodsInfoService.saveBatch(goodList);
        //保存回款计划
        List<SettlementRepaymentPlan> settlementRepaymentPlans = oldSettlementBasicInfo.getSettlementRepaymentPlans();
        if (settlementRepaymentPlans != null && settlementRepaymentPlans.size() > 0) {
            List planList = new ArrayList();
            for (SettlementRepaymentPlan settlementRepaymentPlan : settlementRepaymentPlans) {
                SettlementHisRepaymentPlan settlementHisRepaymentPlan = new SettlementHisRepaymentPlan();
                BeanUtils.copyProperties(settlementRepaymentPlan, settlementHisRepaymentPlan);
                settlementHisRepaymentPlan.setSettlementHisInfoId(settlementHisInfo.getId());
                planList.add(settlementHisRepaymentPlan);
            }
            settlementHisRepaymentPlanService.saveBatch(planList);
        }
        //下游结算清单附件
        List<Long> fileIds = oldSettlementBasicInfo.getFileIds();
        if (CollectionUtil.isNotEmpty(fileIds)) {
            List<FileStorage> fileStorageList = new ArrayList<>();
            List<FileStorageDO> fileStorageDOList = fileService.listByIds(fileIds);
            for (FileStorageDO fileStorageDO : fileStorageDOList) {
                File file = new File(fileStorageDO.getAbsolutePath());
                FileStorage fileStorage = new FileStorage(file.getName(), fileStorageDO.getOriginalName(), fileStorageDO.getAbsolutePath(), FileModuleDict.ChildEnum.SETTLEMENT_SUPPLEMENT_FILE);
                fileStorageList.add(fileStorage);
            }

            AttachmentDto attachmentDtoHis = AttachmentDto.builder()
                    .setEntityId(settlementHisInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_HIS_FILE)
                    .build();
            sysAttachmentRefService.saveFileAndRefHis(fileStorageList, attachmentDtoHis);
        }
        //再新增结算单说明附件
        List<Long> additionalFileIds = oldSettlementBasicInfo.getAdditionalFileIds();
        if (CollectionUtil.isNotEmpty(additionalFileIds)) {
            List<FileStorage> fileStorageList = new ArrayList<>();
            List<FileStorageDO> fileStorageDOList = fileService.listByIds(additionalFileIds);
            for (FileStorageDO fileStorageDO : fileStorageDOList) {
                File file = new File(fileStorageDO.getAbsolutePath());
                FileStorage fileStorage = new FileStorage(file.getName(), fileStorageDO.getOriginalName(), fileStorageDO.getAbsolutePath(), FileModuleDict.ChildEnum.SETTLEMENT_SUPPLEMENT_FILE);
                fileStorageList.add(fileStorage);
            }
            AttachmentDto attachmentDtoAdditionalHis = AttachmentDto.builder()
                    .setEntityId(settlementHisInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_HIS_SUPPLEMENT_FILE)
                    .build();
            sysAttachmentRefService.saveFileAndRefHis(fileStorageList, attachmentDtoAdditionalHis);
        }
        //再新增结算单网价附件
        List<Long> netPriceFileIds = oldSettlementBasicInfo.getNetPriceFileIds();
        if (CollectionUtil.isNotEmpty(netPriceFileIds)) {
            List<FileStorage> fileStorageList = new ArrayList<>();
            List<FileStorageDO> fileStorageDOList = fileService.listByIds(netPriceFileIds);
            for (FileStorageDO fileStorageDO : fileStorageDOList) {
                File file = new File(fileStorageDO.getAbsolutePath());
                FileStorage fileStorage = new FileStorage(file.getName(), fileStorageDO.getOriginalName(), fileStorageDO.getAbsolutePath(), FileModuleDict.ChildEnum.SETTLEMENT_SUPPLEMENT_FILE);
                fileStorageList.add(fileStorage);
            }
            AttachmentDto attachmentDtoNetPriceHis = AttachmentDto.builder()
                    .setEntityId(settlementHisInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_HIS_NET_PRICE_FILE)
                    .build();
            sysAttachmentRefService.saveFileAndRefHis(fileStorageList, attachmentDtoNetPriceHis);
        }
        //增加上有结算单附件
/*        AttachmentDto attachmentDtoAcceptanceFile = AttachmentDto.builder()
                .setEntityId(oldId)
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE)
                .build();
        List<FileStorage> upstreamUnsignedFile = sysAttachmentRefService.getCfiles(attachmentDtoAcceptanceFile);
        AttachmentDto attachmentDtoAcceptanceFileHis = AttachmentDto.builder()
                .setEntityId(settlementHisInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_HIS_UPSTREAM_UNSIGNED_FILE)
                .build();
        sysAttachmentRefService.saveFileAndRefHis(upstreamUnsignedFile, attachmentDtoAcceptanceFileHis);*/
        return settlementHisInfo.getId();
    }

    private SettlementBasicInfo addSettlement(SettlementBasicInfo settlementBasicInfo, HttpServletRequest request) {
/*        if (settlementBasicInfo.getBusinessNumber() == null) {
            throw new ValidatorException(CodeUtil.FAIL, "请锁定业务编号后保存");
        }
        ArrayList<String> additional = new ArrayList<>();
        if (request instanceof MultipartHttpServletRequest) {
            MultiValueMap<String, MultipartFile> multiValueMap = ((MultipartHttpServletRequest) request)
                    .getMultiFileMap();
            Set<String> keys = multiValueMap.keySet();
            for (String key : keys) {
                if (key.startsWith("additional")) {
                    additional.add(key);
                }
            }
        }
        //保存结算单基础信息
        String billInformationNumber = serialNumberGenerator.nextValue(ConstantUtil.BILL_CODE);
        settlementBasicInfo.setSettlementNumber(billInformationNumber);
        if (settlementBasicInfo.getSubmit()) {
            settlementBasicInfo.setSettlementStatus(ProjectInitiationStatusDict.ChildEnum.PROCESSING.getCode());
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.ADD, settlementBasicInfo);
            settlementBasicInfoService.save(settlementBasicInfo);
        } else {
//            settlementBasicInfo.setSettlementStatus(ProjectInitiationStatusDict.ChildEnum.PROCESSING.getCode());
            settlementBasicInfoService.save(settlementBasicInfo);
        }
        //保存回款计划
        List<SettlementRepaymentPlan> settlementRepaymentPlans = settlementBasicInfo.getSettlementRepaymentPlans();
        if (settlementRepaymentPlans != null && settlementRepaymentPlans.size() > 0) {
            for (SettlementRepaymentPlan settlementRepaymentPlan : settlementRepaymentPlans) {
                settlementRepaymentPlan.setSettlementBasicInfoId(settlementBasicInfo.getId());
            }
        }
        settlementRepaymentPlanService.saveBatch(settlementRepaymentPlans);
        //下游结算清单附件
        List<MultipartFile> fileList = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.FILE_NAME);
        if (CollectionUtil.isNotEmpty(fileList)) {
            AttachmentDto attachmentDto = AttachmentDto.builder()
                    .setEntityId(settlementBasicInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_FILE)
                    .build();
            sysAttachmentRefService.saveFileAndRef(fileList, attachmentDto);
        }

        //再新增结算单说明附件
        List<MultipartFile> additionalFiles = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.ADDITIONAL);
        if (CollectionUtil.isNotEmpty(additionalFiles)) {
            AttachmentDto attachmentDtoAdditional = AttachmentDto.builder()
                    .setEntityId(settlementBasicInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_SUPPLEMENT_FILE)
                    .build();
            sysAttachmentRefService.saveFileAndRef(additionalFiles, attachmentDtoAdditional);
        }
        //再新增结算单网价附件
        List<MultipartFile> netPriceFiles = sysAttachmentRefService.getMultipartFileFromRequest(request, ConstantUtil.NET_PRICE_FILE);
        if (CollectionUtil.isNotEmpty(netPriceFiles)) {
            AttachmentDto attachmentDtoNetPrice = AttachmentDto.builder()
                    .setEntityId(settlementBasicInfo.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_NET_PRICE_FILE)
                    .build();
            sysAttachmentRefService.saveFileAndRef(netPriceFiles, attachmentDtoNetPrice);
        }
        //新增结算单货物信息
        List<SettlementGoodsInfo> settlementGoodsInfos = settlementBasicInfo.getSettlementGoodsInfos();
        if (CollectionUtil.isNotEmpty(settlementGoodsInfos)) {

            //所选货物要么全底层要么全未底层
//            List<Long> acceptanceBasicInfoIds = settlementGoodsInfos.stream().map(SettlementGoodsInfo::getAcceptanceBasicInfoId)
//                    .collect(Collectors.toList());
//            List<AcceptanceBasicInfo> acceptanceBasicInfos = acceptanceBasicInfoService.listByIds(acceptanceBasicInfoIds);
//            List<Boolean> receivables =
//
//
//            .stream().map(AcceptanceBasicInfo::getReceivables).distinct()
//                    .collect(Collectors.toList());
//            if (receivables != null && receivables.size() > 1) {
//                throw new ValidatorException(CodeUtil.FAIL, "验收单不可混选（已底层和未底层）");
//            }
            for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
                settlementGoodsInfo.setSettlementBasicInfoId(settlementBasicInfo.getId());
            }
            settlementGoodsInfoService.saveBatch(settlementGoodsInfos);
            //校验验收单货物
            List<Long> acceptanceBasicInfoIds = settlementGoodsInfos.stream().map(SettlementGoodsInfo::getcAcceptanceBasicInfoId)
                    .distinct().collect(Collectors.toList());
            acceptanceBasicInfoIds.forEach(id -> {
                AcceptanceBasicInfo basicInfo = acceptanceBasicInfoService.getById(id);
                if (basicInfo.getSettlement()) {
                    throw new ValidatorException(CodeUtil.FAIL, "存在已结算或者正在结算的货物");
                } else {
                    if (settlementBasicInfo.getSubmit()) {
                        basicInfo.setSettlement(true);
                        acceptanceBasicInfoService.updateById(basicInfo);
                    }
                }
            });
        }


        if (settlementBasicInfo.getSubmit()) {
            //保存结算单相关货物信息
            if (settlementGoodsInfos != null) {
                for (SettlementGoodsInfo settlementGoodsInfo : settlementGoodsInfos) {
                    if (settlementGoodsInfo.getSalesPrice() != null && settlementGoodsInfo.getSalesPrice().compareTo(BigDecimal.ZERO) <= 0) {
                        throw new BusinessException(CodeUtil.FAIL, "请填写销售单价并进行质保金计算");
                    }
                }
            }
            settlementBasicInfo.setSettlementStatus(ProjectInitiationStatusDict.ChildEnum.PROCESSING.getCode());
            settlementBasicInfoService.updateById(settlementBasicInfo);
            //验证经办人和销售合同经办人是否一致
            //销售合同
            CSalesContract salesContractManagement = salesContractService.getOne(
                    new QueryWrapper<CSalesContract>()
                            .eq("business_number", settlementBasicInfo.getBusinessNumber())
                            .last("LIMIT 1"));
            CSalesContractBasicInfo salesContractBasicInfo = salesContractBasicInfoService.getOne(
                    new QueryWrapper<CSalesContractBasicInfo>().eq("c_sales_contract_management_id", salesContractManagement.getId())
                            .orderByDesc("gmt_create").last("LIMIT 1"));
            List<CSalesContractPersonInfo> contractPersonInfos = salesContractPersonInfoService.lambdaQuery()
                    .eq(CSalesContractPersonInfo::getcSalesContractBasicInfoId, salesContractBasicInfo.getId())
                    .eq(CSalesContractPersonInfo::getType, "salesContractPersonType_settlement").list();
            boolean contains = false;
            for (CSalesContractPersonInfo contractPersonInfo : contractPersonInfos) {
                contains = settlementBasicInfo.getOperatorEnterprise().contains(contractPersonInfo.getName());
                if (contains) {
                    break;
                }
            }
            if (!contains && additional.size() == 0) {
               throw new ValidatorException(CodeUtil.FAIL, "结算单经办人和销售合同规定经办人不一致需要上传说明附件！");
            } */
            //生成结算单
            try {
                XMlToDoc xmlDoc = new XMlToDoc();
                //模板中填充数据
                File file = inputData(settlementBasicInfo, xmlDoc);
                AttachmentDto attachmentDtoAcceptanceFile = AttachmentDto.builder()
                        .setEntityId(settlementBasicInfo.getId())
                        .setChildEnum(FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE)
                        .build();
                List<FileStorage> accepyanceFile = new ArrayList<>();
                FileStorage fileStorage = new FileStorage(file.getName(), file.getAbsolutePath(), FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE);
                accepyanceFile.add(fileStorage);
                sysAttachmentRefService.saveFileAndRefHis(accepyanceFile, attachmentDtoAcceptanceFile);
                FileStorageDO fileStorageDO = new FileStorageDO();
                fileStorageDO.setAbsolutePath(fileStorage.getAbsolutePath());
                fileStorageDO.setPath(fileStorage.getPath());
                fileStorageDO.setOriginalName(fileStorage.getOriginalName());
                fileStorageDO.setSize(fileStorage.getSize());
                fileStorageDO.setType(fileStorage.getFileType());
                fileStorageDO.setBusinessType(FileModuleDict.ChildEnum.SETTLEMENT_UPSTREAM_UNSIGNED_FILE.getCode());
                fileStorageDO.setBusinessId(settlementBasicInfo.getId());
                fileService.save(fileStorageDO);
            } catch (Exception e) {
                throw new BusinessException(CodeUtil.FAIL, "生成结算单出错");
            }
//        }

        return settlementBasicInfo;
    }
}
