package com.pusong.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.pusong.business.domain.*;
import com.pusong.business.domain.bo.*;
import com.pusong.business.domain.vo.*;
import com.pusong.business.enums.*;
import com.pusong.business.enums.TaskStatusEnum.*;
import com.pusong.business.mapper.*;
import com.pusong.business.service.*;
import com.pusong.business.service.approver.ApproverContainer;
import com.pusong.business.service.approver.ApproverService;
import com.pusong.common.core.constant.UserConstants;
import com.pusong.common.core.domain.model.LoginUser;
import com.pusong.common.core.exception.ServiceException;
import com.pusong.common.core.service.DictService;
import com.pusong.common.core.utils.DateUtils;
import com.pusong.common.core.utils.MapstructUtils;
import com.pusong.common.core.utils.StringUtils;
import com.pusong.common.doc.util.NumBerTool;
import com.pusong.common.doc.util.PdfGenerator;
import com.pusong.common.mybatis.core.page.TableDataInfo;
import com.pusong.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.pusong.common.satoken.utils.LoginHelper;
import com.pusong.system.domain.SysDictData;
import com.pusong.system.domain.vo.SysOssVo;
import com.pusong.system.service.ISysDictDataService;
import com.pusong.system.service.ISysOssService;
import jakarta.annotation.Resource;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 合同基本信息Service业务层处理
 *
 * @author wls
 * @date 2024-07-29
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class PsContractInfoServiceImpl implements IPsContractInfoService {

    private final PsContractInfoMapper baseMapper;
//    private final PsContractBusinessDetailMapper businessDetailMapper;
    private final IPsContractBusinessService businessService;
    private final IPsContractBusinessDetailService businessDetailService;
    @Resource
    private final IPsCompanyInfoService companyInfoService;
    private final PsCompanyInfoMapper companyInfoMapper;

    private final PsContractCompanyMapper psContractCompanyMapper;
    @Resource
    private final IPsCustomInfoService customInfoService;
    @Resource
    private final ISysOssService ossService;
    @Resource
    private final IPsContractPayService contractPayService;

    @Resource
    private final ApproverContainer container;

    private final IPsTaskService taskMainService;
    private final PsTaskMainMapper taskMainMapper;
    private final PsTaskAppointMapper taskAppointMapper;
    private final PsApproverRecordMapper recordMapper;
    private final PsContractBusinessMapper businessMapper;
    private final PsContractBusinessDetailMapper businessDetailMapper;
    private final ISysDictDataService dictDataService;
    private final IPsApproverRecordService approverRecordService;

    public static String getContractCode(){
        Random random = new Random();
        int randomNumber = random.nextInt(8999) + 1000;
        return DateUtils.parseDateToStr("yyyyMMddHHmm",new Date())+randomNumber;
    }
    /**
     * 生成合同
     *
     * @param bo 合同信息
     *  @param type 操作类型 1暂存2保存
     * @return 是否新增成功
     */
    @Override
    @Transactional//开启事务
    public String createContract(PsContractInfoBo bo, Integer type) {
        if (bo.getFirstPartyType() == PsContractInfoBo.FIRSTPARTYTYPE.INDIVIDUALS.getType()){
            bo.setContactPersonName(bo.getCompanyInfoBo().getLegalPersonName());
            bo.setContactPersonPhone(bo.getCompanyInfoBo().getLegalPersonPhone());
            bo.setContactPersonIdcard(bo.getCompanyInfoBo().getLegalPersonIdcard());
//            bo.setCompanyInfoBo(null);
        }

        //1校验
        PsContractInfo add = validEntity(bo, UserConstants.YES);

        //2.插入签约公司信息
        if (bo.getFirstPartyType() == PsContractInfoBo.FIRSTPARTYTYPE.COMPANY.getType()){
            if(bo.getCompanyInfoBo().getCustomId() == null){
                bo.getCompanyInfoBo().setCustomId(bo.getCustomId());
            }
            companyInfoService.saveBo(bo.getCompanyInfoBo());
        }

        //插入服务公司
        for (PsCompanyInfoBo companyInfoBo : bo.getServiceCompanyInfoList()){
            companyInfoBo.setCompanyType("2");
            companyInfoBo.setCustomId(bo.getCustomId());
            if (companyInfoBo.getId() == null){
                companyInfoService.saveBo(companyInfoBo);
            }else{
                PsCompanyInfo update = MapstructUtils.convert(companyInfoBo, PsCompanyInfo.class);
                companyInfoMapper.updateById(update);
                for (PsContractBusinessBo psContractBusinessBo : companyInfoBo.getBusinessList()) {
                    psContractBusinessBo.setCompanyId(companyInfoBo.getId());
                }
            }

            for (PsContractBusinessBo psContractBusinessBo : companyInfoBo.getBusinessList()) {
                psContractBusinessBo.setStartDate(companyInfoBo.getStartServiceDate());
                psContractBusinessBo.setEndDate(companyInfoBo.getEndServiceDate());
                psContractBusinessBo.setIsOld(companyInfoBo.getIsOld());
                psContractBusinessBo.setIsProxy(companyInfoBo.getIsProxy());
            }
        }

        //3.如果已存在合同，则进行修改，否则新增
        if(add == null){
            add = new PsContractInfo();
            MapstructUtils.convert(bo, add);
            add.setContractCode(getContractCode());//合同编码
            // 合同名称:公司名+合同编码
            if (bo.getFirstPartyType() == PsContractInfoBo.FIRSTPARTYTYPE.COMPANY.getType()){
                add.setContractName(bo.getCompanyInfoBo().getCompanyName() + add.getContractCode());
            }else{
                add.setContractName(bo.getContactPersonName() + add.getContractCode());
            }

            add.setCustomManager(LoginHelper.getUserId());//所属销售经理id
        }else{
            MapstructUtils.convert(bo, add);
        }
        if (bo.getFirstPartyType() == PsContractInfoBo.FIRSTPARTYTYPE.COMPANY.getType()) {
            add.setCompanyId(bo.getCompanyInfoBo().getId());//公司id
        }
        List<PsContractBusinessBo> list = bo.getServiceCompanyInfoList().stream().flatMap(com -> com.getBusinessList().stream()).toList();
        list.forEach(item->{
            BigDecimal mony = BigDecimal.ZERO;
            if(CollectionUtils.isNotEmpty(item.getDetailBos())){
                mony = item.getDetailBos().stream().map(PsContractBusinessDetailBo::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            }
            //服务类别填了才会修改服务项目的金额
            if(mony.compareTo(BigDecimal.ZERO) > 0){
                item.setBusinessAmount(mony);
            }
        });
        //保存公司合同关联表
        companyInfoService.saveContractCompany(bo.getServiceCompanyInfoList(),add.getContractCode());
        BigDecimal sum = list.stream().map(PsContractBusinessBo::getBusinessAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        add.setContractAmount(sum);//合同总金额
        add.setContractStatus(type == 1 ? ContractStatusEnum.INIT.getCode():ContractStatusEnum.CREATE.getCode());//合同状态
        add.setIsCancel(CommonStatusEnum.INIT.getCode());
        baseMapper.insertOrUpdate(add);
        //4.删除所有服务类型和服务项目,.插入服务类型
        businessService.saveList(list, add.getContractCode());
        //7.生成合同
        makePdf(add, bo,true);
        return add.getContractCode();
    }
    /**
     * 预览合同
     *
     * @param bo 合同信息
     * @return 是否新增成功
     */
    public Long preview(PsContractInfoBo bo){
        //3.如果已存在合同，则进行修改，否则新增
        PsContractInfo add = new PsContractInfo();
        add.setContractCode(getContractCode());//合同编码
        // 合同名称:公司名+合同编码
        add.setContractName(bo.getCompanyInfoBo().getCompanyName()+add.getContractCode());
        add.setCustomManager(LoginHelper.getUserId());//所属销售经理id
        add.setCompanyId(bo.getCompanyInfoBo().getId());//公司id
        MapstructUtils.convert(bo, add);
        List<PsContractBusinessBo> list = bo.getServiceCompanyInfoList().stream().flatMap(com -> com.getBusinessList().stream()).toList();
        list.forEach(item->{
            BigDecimal mony = BigDecimal.ZERO;
            if(CollectionUtils.isNotEmpty(item.getDetailBos())){
                mony = item.getDetailBos().stream().map(PsContractBusinessDetailBo::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            }
            //服务类别填了才会修改服务项目的金额
            if(mony.compareTo(BigDecimal.ZERO) > 0){
                item.setBusinessAmount(mony);
            }
        });
        BigDecimal sum = list.stream().map(PsContractBusinessBo::getBusinessAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        add.setContractAmount(sum);//合同总金额
        return makePdf(add,bo,false);
    }


    /**
     * 根据客户id查询暂存的合同详情信息
     *
     * @param customerId 客户id
     * @return 合同基本信息
     */
    public PsContractInfoVo queryInfoByCustomId(Long customerId){
        PsContractInfoBo bo = new PsContractInfoBo();
        bo.setCustomId(customerId);
        //校验信息并返回
        PsContractInfo info = validEntity(bo);
        if(info == null){
            return null;
        }
        PsContractInfoVo vo = MapstructUtils.convert(info, PsContractInfoVo.class);
        //装填签约公司信息
        if(vo.getCompanyId() != null){
            vo.setPsCompanyInfoVo(companyInfoService.queryById(vo.getCompanyId()));
        }
        //装填服务公司信息
        List<PsCompanyInfoVo> list = companyInfoService.getServiceCompany(vo.getContractCode());
        vo.setPsCompanySerivceVo(list);
        return vo;
    }

    /**
     * 根据客户id，合同编码询和合同状态查询合同信息
     *
     * @param code 合同编码
     * @return 合同基本信息
     */
    public List<PsContractInfo> queryByCode(Long customId,String code,String status){
        if(customId == null && StringUtils.isBlank(code)){
            return null;
        }
        return baseMapper.selectList(Wrappers.<PsContractInfo>lambdaQuery().eq(PsContractInfo::getDelFlag,"0")
                .eq(StringUtils.isNotBlank(code),PsContractInfo::getContractCode,code)
                .eq(customId != null,PsContractInfo::getCustomId,customId)
                .eq(StringUtils.isNotBlank(status) ,PsContractInfo::getContractStatus,status));
    }


    /**
     * 分页查询合同信息列表
     *
     * @param bo 查询条件
     * @param pageQuery 分页参数
     * @return 合同基本信息分页列表
     */
    @Override
    public TableDataInfo<PsContractInfoVo> queryPageList(PsContractInfoQueryBo bo, PageQuery pageQuery) {
        if(bo.getType() == null || bo.getType() == 1){//合同列表（要作废数据）
        }else if(bo.getType() == 2){//待回款（不要作废数据）
            bo.setInContractStatus(List.of(ContractStatusEnum.CREATE.getCode()));
        }else if (bo.getType() == 3){//已回款(要特定的作废数据)
            bo.setInContractStatus(ContractStatusEnum.getReturn());
        }else if (bo.getType() == 4){//托管续费合同
            bo.setInContractStatus(List.of(ContractStatusEnum.SUCCESS.getCode()));
            log.info("托管服务");
        }

        QueryWrapper<PsContractInfo> lqw = buildQueryWrapper(bo);
        Page<PsContractInfoVo> result = baseMapper.selectPageContractList(pageQuery.build(), lqw);
        if(CollectionUtils.isEmpty(result.getRecords())){
            return TableDataInfo.build(result);
        }
        //装填信息
        result.getRecords().forEach(this::fillContractInfo);
        return TableDataInfo.build(result);
    }

    public TableDataInfo<PsContractInfoVo> queryPageListByCustomId(Long customId, PageQuery pageQuery){
        Page<PsContractInfoVo> result = baseMapper.selectPageContractListByCustomId(pageQuery.build(), customId);
        if(CollectionUtils.isEmpty(result.getRecords())){
            return TableDataInfo.build(result);
        }
        //装填信息
        result.getRecords().forEach(this::fillContractInfo);
        return TableDataInfo.build(result);
    }

    /**
     * 根据合同编码查询合同详情信息
     *
     * @param contractCode 合同编码
     * @return 合同基本信息
     */
    public PsContractInfoVo queryContractByCode(String contractCode){
        PsContractInfoQueryBo bo = new PsContractInfoQueryBo();
        bo.setContractCode(contractCode);
        QueryWrapper<PsContractInfo> lqw = buildQueryWrapper(bo);
        List<PsContractInfoVo> result = baseMapper.selectContractList(lqw);
        if(CollectionUtils.isEmpty(result)){return null;}
        PsContractInfoVo vo = result.get(0);
        //装填合同信息
        this.fillContractInfo(vo);
        return vo;
    }

    /**
     * 根据合同编码修改合同信息(开启事务)
     *
     * @param updateBo 合同信息
     * @return 合同基本信息
     */
    @Transactional
    public boolean updateContractByCode(PsContractInfoBo updateBo){
        //1获取合同详情
        PsContractInfoVo old = queryContractByCode(updateBo.getContractCode());
        //2校验状态
        beforeUpdateValid(updateBo, old);

        //签约公司填充 客户id
        if(updateBo.getCompanyInfoBo().getCustomId() == null){
            updateBo.getCompanyInfoBo().setCustomId(updateBo.getCustomId());
        }

        updateBo.setBeforeContractStatus(old.getContractStatus());

        //5.已回款之后的合同修改后走审批
        if(!ContractStatusEnum.isReturn(old.getContractStatus())){
            update(old, updateBo);
            return true;
        }

        //发起审批
        ApproverService service = container.getService(ApproverTypeEnum.UPDATE.getCode());
        service.apply(updateBo.getContractCode(),updateBo.getContractCode(),updateBo.getUpdateDesc(), JSON.toJSONString(updateBo));
        PsContractInfo info = new PsContractInfo();
        info.setContractCode(updateBo.getContractCode());
        info.setContractStatus(ContractStatusEnum.UPDATEAPPROVER.getCode());
        updateByCode(info);

        return true;
    }

    public void update(PsContractInfoVo old, PsContractInfoBo updateBo){
        if (old.getCompanyId() == null){
            if (updateBo.getCompanyInfoBo().getId() != null){
                //签约主体个人转公司，修改公司信息
                //3.插入公司信息
                companyInfoService.saveBo(updateBo.getCompanyInfoBo());
            }else{
                //签约人信息变化， 不做公司信息修改， 只更新合同表
            }
        }else{
            if (updateBo.getCompanyInfoBo().getId() != null){
                //签约公司信息变更，修改公司信息
                //3.插入公司信息
                companyInfoService.saveBo(updateBo.getCompanyInfoBo());
            }else{
                //签约主体公司转个人， 不做公司信息修改， 只更新合同表
            }
        }

        Map<Long, PsCompanyInfoVo> oldCompanyMap = new HashMap<>();
        for (PsCompanyInfoVo psCompanyInfoVo : old.getPsCompanySerivceVo()) {
            oldCompanyMap.put(psCompanyInfoVo.getId(), psCompanyInfoVo);
        }
        List<PsCompanyInfoBo> addCompany = new ArrayList<>();
        List<PsCompanyInfoBo> updateCompany = new ArrayList<>();
        for (PsCompanyInfoBo companyInfoBo : updateBo.getServiceCompanyInfoList()){
            if (companyInfoBo.getId() == null){
                addCompany.add(companyInfoBo);
                continue;
            }
            PsCompanyInfoVo oldCompanyInfo = oldCompanyMap.get(companyInfoBo.getId());
            if (oldCompanyInfo == null){
                addCompany.add(companyInfoBo);
                continue;
            }
            updateCompany.add(companyInfoBo);
            oldCompanyMap.remove(companyInfoBo.getId());
        }

        for (PsCompanyInfoBo psCompanyInfoBo : updateCompany) {
            //服务公司信息修改、、服务项目修改
            companyInfoService.saveBo(psCompanyInfoBo);
        }
        for (PsCompanyInfoVo psCompanyInfoBo : oldCompanyMap.values()) {
            //删除服务公司
            QueryWrapper<PsContractCompany> qw1 = Wrappers.query();
            qw1.eq( "company_id", psCompanyInfoBo.getId());
            qw1.eq( "contract_code", updateBo.getContractCode());
            psContractCompanyMapper.delete(qw1);

            //服务公司删，则删任务，重新校验合同状态，可能已完成
            QueryWrapper<PsTaskMain> qw = Wrappers.query();
            qw.eq( "service_company_id", psCompanyInfoBo.getId());
            qw.eq( "contract_code", updateBo.getContractCode());
            List<PsTaskMain> psTaskMainList = taskMainMapper.selectList(qw);
            taskMainMapper.delete(qw);

            //服务公司删，则删任务，重新校验合同状态，可能已完成
            List<Long> taskIds = psTaskMainList.stream().map(stTask1 -> stTask1.getId()).collect(Collectors.toList());
            taskAppointMapper.deleteByIds(taskIds);
        }

        List<PsTaskMain> psTaskMainList = new ArrayList<>();
        for (PsCompanyInfoBo companyInfoBo : addCompany) {
            //服务公司加，增加任务，重新计算合同是待分配还是已分配
            companyInfoBo.setCompanyType("2");
            companyInfoBo.setCustomId(updateBo.getCustomId());
            if (companyInfoBo.getId() == null){
                companyInfoService.saveBo(companyInfoBo);
            }else{
                PsCompanyInfo update = MapstructUtils.convert(updateBo, PsCompanyInfo.class);
                companyInfoMapper.updateById(update);
                for (PsContractBusinessBo psContractBusinessBo : companyInfoBo.getBusinessList()) {
                    psContractBusinessBo.setCompanyId(companyInfoBo.getId());
                }
            }
            if(ContractStatusEnum.isReturn(old.getContractStatus())){
                //已回款的添加任务，没回款的等审批后再添加
                PsTaskMain psTaskMain = new PsTaskMain();
                psTaskMain.setContractCode(old.getContractCode());
                psTaskMain.setTaskType(TaskTypeEnum.CONTRACT.getCode());
                psTaskMain.setTaskStatus(TaskStatusEnum.INIT.getCode());
                psTaskMain.setCompanyId(updateBo.getCompanyInfoBo().getId());
                psTaskMain.setCustomId(updateBo.getCustomId());
                psTaskMain.setServiceCompanyId(companyInfoBo.getId());
                psTaskMainList.add(psTaskMain);
            }
        }
        if (!psTaskMainList.isEmpty()){
            taskMainService.insertBatch(psTaskMainList);
        }


        //保存公司合同关联表
        companyInfoService.saveContractCompany(updateBo.getServiceCompanyInfoList(), old.getContractCode());

        //4.装填合同信息
        List<PsContractBusinessBo> list = updateBo.getServiceCompanyInfoList().stream().flatMap(com -> com.getBusinessList().stream()).toList();
        for (PsContractBusinessBo item : list) {
            BigDecimal mony = BigDecimal.ZERO;
            if(CollectionUtils.isNotEmpty(item.getDetailBos())){
                mony = item.getDetailBos().stream().map(PsContractBusinessDetailBo::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            }
            //服务类别填了才会修改服务项目的金额
            if(mony.compareTo(BigDecimal.ZERO) > 0){
                item.setBusinessAmount(mony);
            }
        }
        BigDecimal sum = list.stream().map(PsContractBusinessBo::getBusinessAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        updateBo.setContractAmount(sum);//合同总金额

        //重新计算当前的合同状态，待回款、待处理、处理中、已完结、已作废；；；已完结和处理中可能会变成待处理
        if(ContractStatusEnum.isReturn(old.getContractStatus())){
            updateBo.setContractStatusCode(calcContractStatus(updateBo).getCode());
        }
        //签章：合同签字盖章成功:修改合同成功，合同签字盖章变回未签章状态，需重新进行签章申请
        if(StringUtils.equals(old.getSignStatus(), CommonStatusEnum.SUCCESS.getCode()) ){
            updateBo.setSignStatus(CommonStatusEnum.INIT.getCode());
        }

        PsContractInfo add = new PsContractInfo();
        MapstructUtils.convert(updateBo, add);
        add.setCompanyId(updateBo.getCompanyInfoBo().getId());//公司id
        add.setIsCancel(CommonStatusEnum.INIT.getCode());
        add.setContractStatus(updateBo.getContractStatusCode());
        this.updateByCode(add);

        //删除所有服务
        QueryWrapper<PsContractBusiness> qw2 = Wrappers.query();
        qw2.eq( "contract_code", updateBo.getContractCode());
        List<PsContractBusiness> psContractBusinesses = businessMapper.selectList(qw2);
        businessMapper.delete(qw2);
        List<Long> ids = psContractBusinesses.stream().map(item -> item.getId()).collect(Collectors.toList());
        businessDetailMapper.deleteByIds(ids);
        //创建服务
        businessService.saveList(list, updateBo.getContractCode());

        makePdf(add, updateBo,true);

        finish(updateBo.getContractCode());
    }

    public ContractStatusEnum calcContractStatus(PsContractInfoBo updateBo){
//        QueryWrapper<PsTaskMain> qw = Wrappers.query();
//        qw.eq( "contract_code", updateBo.getContractCode());
//        List<PsTaskMain> psTaskMainList = taskMainMapper.selectList(qw);

        QueryWrapper<PsTaskAppoint> qw2 = Wrappers.query();
        qw2.eq( "contract_code", updateBo.getContractCode());
        List<PsTaskAppoint> psTaskAppoints = taskAppointMapper.selectList(qw2);
        for (PsTaskAppoint psTaskAppoint : psTaskAppoints) {
            if (AppointStatusEnum.ING.getCode().equals(psTaskAppoint.getAppointStatus())){
                return ContractStatusEnum.EXECUTION;
            }
        }

        return ContractStatusEnum.RETURN;
    }

    /**
     * 作废合同
     *
     * @param contractCode 合同编码
     */
    @Override
    public boolean cancellation(String contractCode,String desc) {
        //创建变更对象
        PsContractInfo info = new PsContractInfo();
        info.setContractCode(contractCode);
        //查询合同详细信息
        PsContractInfoVo infoVo = this.queryContractByCode(contractCode);
        if(StringUtils.equals(CustomerStatusEnum.STOP.getCode(),infoVo.getPsCustomInfoVo().getCustomStatus())){
            throw new ServiceException("操作失败，客户已终止合作");
        }
        fillMoney(infoVo);
        //没有任何一笔收款：点击【作废】，直接作废合同
        //        if(CollectionUtils.isEmpty(infoVo.getContractPayVoList())){
        if (infoVo.getPayMoney().compareTo(BigDecimal.ZERO) == 0){
            info.setIsCancel(CommonStatusEnum.SUCCESS.getCode());
        }else{
            if(StringUtils.isBlank(desc)){throw new ServiceException("请填写作废原因");}
            //有收款：点击【作废】填写【作废原因】后发起【作废】审批
            ApproverService service = container.getService(ApproverTypeEnum.CANCELLA.getCode());
            service.apply(contractCode,contractCode,desc, null);
            info.setIsCancel(CommonStatusEnum.ING.getCode());

        }
        updateByCode(info);
        return true;
    }
    /**
     * 重启合同
     *
     * @param contractCode 合同编码
     */
    public boolean restart(String contractCode){
        //创建变更对象
        PsContractInfo info = new PsContractInfo();
        info.setContractCode(contractCode);
        //查询合同详细信息
        PsContractInfoVo infoVo = this.queryContractByCode(contractCode);
        //查询是否有审批中的退款信息
        List<PsContractPayVo> payList = contractPayService.queryListByContractCode(contractCode,null,PayStatusEnum.PAYING);
        BigDecimal pay = payList.stream().map(PsContractPayVo::getMoney).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        //有未完成的退款：【合同列表】状态更新为【处理中】；并显示在【已完成回款列表】，重新生成任务
        if(infoVo.getPayMoney().subtract(pay).compareTo(BigDecimal.ZERO) > 0){
            info.setContractStatus(ContractStatusEnum.EXECUTION.getCode());
            //重新生成任务
            PsTaskMain psTaskMain = new PsTaskMain();
            psTaskMain.setContractCode(info.getContractCode());
            psTaskMain.setTaskType(TaskTypeEnum.CONTRACT.getCode());
            psTaskMain.setTaskStatus(TaskStatusEnum.INIT.getCode());
            psTaskMain.setCompanyId(info.getCompanyId());
            psTaskMain.setCustomId(info.getCustomId());
            taskMainService.insert(psTaskMain);
        }else{
            //没有任何退款处理：【合同列表】状态更新为【待回款】，并显示在【待回款列表】中
            info.setContractStatus(ContractStatusEnum.CREATE.getCode());
        }
        info.setIsCancel(CommonStatusEnum.INIT.getCode());
        updateByCode(info);
        return true;
    }

    /**
     * 根据合同编码修改合同
     * @param info
     * @return
     */
    public PsContractInfo updateByCode(PsContractInfo info){
        baseMapper.update(info,Wrappers.<PsContractInfo>lambdaUpdate().eq(PsContractInfo::getContractCode,info.getContractCode()).eq(PsContractInfo::getDelFlag,0));
        return info;
    }
    /**
     * 生成合同pdf
     * @param add
     * @param bo
     */
    public Long makePdf(PsContractInfo add, PsContractInfoBo bo, boolean isSave){
        //todo 合同pdf
        Long ossId = null;
        SysDictData main = dictDataService.selectDict("contract_main", add.getContractMain());
        List<PsContractBusinessBo> detailBos = new ArrayList<>();
        for (PsCompanyInfoBo psCompanyInfoBo : bo.getServiceCompanyInfoList()) {
            for (PsContractBusinessBo item : psCompanyInfoBo.getBusinessList()) {
                item.setBusinessTypeName(dictDataService.selectDictLabel("contract_type",item.getBusinessType()));
                detailBos.add(item);
            }
        }

//        bo.getBusinessList().forEach(item->{
//            item.setBusinessTypeName(dictDataService.selectDictLabel("contract_type",item.getBusinessType()));
//            item.getDetailBos().forEach(it->{it.getExtentInfo().});
//        });
        try{
            //生成合同pdf
            PsCustomInfo customer = customInfoService.listById(add.getCustomId());
            Map<String,Object> map = new HashMap<>();
            LoginUser user = LoginHelper.getLoginUser();
            map.put("user", user);
            map.put("contract", add);
            map.put("business", detailBos);

            map.put("serviceCompany", bo.getServiceCompanyInfoList());

            map.put("main", JSON.parseObject(main.getRemark()));// 合同主体信息
            map.put("company", bo.getCompanyInfoBo());
            map.put("customer",customer);
            // 合同总金额大写
            map.put("contractAmount", NumBerTool.digitUppercase(add.getContractAmount().setScale(2, RoundingMode.HALF_EVEN).toString()));
            String head = "合同编号：PS-" + add.getContractCode()+"    客户编号：" + customer.getId();
            //合同标题
            map.put(PdfGenerator.HEAD, head);
            //是否签章
            map.put(PdfGenerator.SIGN, StringUtils.equals(CommonStatusEnum.SUCCESS.getCode(),add.getSignStatus()));

            String path = System.getProperty("user.dir") + "/" + (StringUtils.isBlank(bo.getCompanyInfoBo().getCompanyName()) ? "" : bo.getCompanyInfoBo().getCompanyName() + "-")+add.getContractCode()+".pdf";
            log.info(JSON.toJSONString(map));
//            path = "D:/王立帅/临时/output.pdf";
            PdfGenerator.makePdf(map, path, TenplateEnum.CONTRACT.getName());
            File file = new File(path);
            //上传到oss服务
            SysOssVo sysOssVo = ossService.upload(new File(path));
            ossId = sysOssVo.getOssId();
            //删除临时的合同文件
            if(file.exists())file.delete();
            //是否保存合同信息
            if(isSave){
                //更新合同id
                PsContractInfo psContractInfo = new PsContractInfo();
                psContractInfo.setContractCode(add.getContractCode());
                psContractInfo.setPdfId(sysOssVo.getOssId());
                this.updateByCode(psContractInfo);
                //删除原合同
                if(add.getPdfId() != null)
                    ossService.deleteWithValidByIds(List.of(add.getPdfId()),false);
                Optional<Long> a = Optional.ofNullable(add.getPdfId());
            }
        }catch (Exception e){
            log.error("生成pdf失败",e);
        }
        return ossId;
    }

    /**
     * 开发票（开发票操作）
     * @param contractCode
     * @return
     */
    public void invoice(String contractCode){
        log.info("合同未回款过，初始化任务主表");
        PsContractInfoVo info = this.queryContractByCode(contractCode);
        PsTaskMain psTaskMain = new PsTaskMain();
        psTaskMain.setCompanyId(info.getCompanyId());
        psTaskMain.setCustomId(info.getCustomId());
        psTaskMain.setContractCode(contractCode);
        psTaskMain.setTaskType(TaskTypeEnum.INVOICE.getCode());
        psTaskMain.setTaskStatus(TaskStatusEnum.INIT.getCode());
        taskMainService.insert(psTaskMain);
    }
    public void invoice(PsInvoiceBo invoiceBo){
        log.info("合同未回款过，初始化任务主表");
        PsContractInfoVo info = this.queryContractByCode(invoiceBo.getContractCode());
        PsTaskMain psTaskMain = new PsTaskMain();
        psTaskMain.setCompanyId(info.getCompanyId());
        psTaskMain.setCustomId(info.getCustomId());
        psTaskMain.setContractCode(invoiceBo.getContractCode());
        psTaskMain.setTaskType(TaskTypeEnum.INVOICE.getCode());
        psTaskMain.setTaskStatus(TaskStatusEnum.INIT.getCode());
        psTaskMain.setExtend(JSONObject.toJSONString(invoiceBo));
        taskMainService.insert(psTaskMain);
    }
    /**
     * 免费工单
     * @param contractCode 合同编码
     * @param businessType 服务类别
     * @param businessProject 服务项目
     */
    public void freeWork(String serviceCompanyId,String businessType,String businessProject) {
        //发起审批
        ApproverService service = container.getService(ApproverTypeEnum.FREE.getCode());
        service.apply(serviceCompanyId, "",null, businessType+"@@"+businessProject);
    }

    /**
     * 合同检测是否完成
     * 一、回传合同的条件
     * 1. 生成合同，所选【服务类别】不包含【托管服务】（即【非托管业务】）：包括【新签】和【续费】
     *   1. 合同金额 > = 8000元，必须回传合同，【电子签章】申请成功后才能回传合同
     *   2. 合同金额< 8000元，无需回传合同，【电子签章】申请成功后，必须回传合同
     * 2. 生成合同，所选【服务类别】包含【托管服务】：
     *   1. 新签：不论合同金额大小，必须回传合同
     *   2. 续费：
     *     1. 合同金额 > = 8000元，必须回传合同，【电子签章】申请成功后才能回传合同
     *     2. 合同金额< 8000元，无需回传合同，【电子签章】申请成功后，必须回传合同
     * 二、合同完成的条件
     * 1. 回款全部完成
     * 2. 任务全部完成
     * 3. 回传合同：根据【回传合同的条件】进行判断，必须回传合同的，需回传合同后审批通过，才能算完成。
     * @param contractCode 合同编码
     */
    @Transactional
    public String finish(String contractCode) {
        if (StringUtils.isBlank(contractCode)) {
            return "contractCode 参数错误";
        }
        Long num = taskMainMapper.selectCount(Wrappers.<PsTaskMain>lambdaQuery()
                .eq(PsTaskMain::getContractCode, contractCode)
                .ne(PsTaskMain::getTaskType, TaskTypeEnum.INVOICE.getCode())
                .notIn(PsTaskMain::getTaskStatus, TaskStatusEnum.returnFinish()));
        PsContractInfoVo info = this.queryContractByCode(contractCode);
        //任务已完成 合同已回传 回款已结束
        boolean rollbackFlag = true;

        if (!StringUtils.equals(info.getRollBackStatus(), CommonStatusEnum.SUCCESS.getCode())) {
            if (!info.isTuoguanService()) {//非托管服务
                if (info.getContractAmount().doubleValue() >= 8000) {
                    //1. 合同金额 > = 8000元，必须回传合同，【电子签章】申请成功后才能回传合同
                    rollbackFlag = false;
                } else {
                    //合同金额< 8000元，无需回传合同，【电子签章】申请成功后，必须回传合同
                    if (CommonStatusEnum.ING.getCode().equals(info.getSignStatus())
                            || CommonStatusEnum.SUCCESS.getCode().equals(info.getSignStatus())) {//申请了电子章
                        rollbackFlag = false;
                    }
                }
            }else{//托管服务
                if (info.getIsDue().equals("0")){//新签
                    //不论合同金额大小，必须回传合同
                    rollbackFlag = false;
                } else{//续费
                    if (info.getContractAmount().doubleValue() >= 8000) {
                        //1. 合合同金额 > = 8000元，必须回传合同，【电子签章】申请成功后才能回传合同
                        rollbackFlag = false;
                    } else {
                        //合同金额< 8000元，无需回传合同，【电子签章】申请成功后，必须回传合同
                        if (CommonStatusEnum.ING.getCode().equals(info.getSignStatus())
                                || CommonStatusEnum.SUCCESS.getCode().equals(info.getSignStatus())) {//申请了电子章
                            rollbackFlag = false;
                        }
                    }
                }

            }
        }
        if (!rollbackFlag){
            return "未回传合同";
        }

        if(num > 0){
            return "还有未完任务";
        }
        if (info.getResidualMoney().compareTo(BigDecimal.ZERO) > 0){
            return "还有未回款";
        }
        PsContractInfo psContractInfo = new PsContractInfo();
        psContractInfo.setContractCode(contractCode);
        psContractInfo.setContractStatus(ContractStatusEnum.SUCCESS.getCode());
        psContractInfo.setFinishDate(new Date());
        this.updateByCode(psContractInfo);
        return null;
    }


    /**
     * 根据合同编码查询服务进度
     * @param contractCode 合同编码
     */
    public ServiceScheduleVo queryScheduleByCode(String contractCode, Long serviceCompanyId){
        PsContractInfo contractInfo = this.queryByCode(null, contractCode, null).get(0);
        PsCustomInfo customer = customInfoService.listById(contractInfo.getCustomId());

        ServiceScheduleVo serviceScheduleVo = new ServiceScheduleVo();
        //分配
        serviceScheduleVo.setAllot(customer.getCustomManager());
        //生成合同
        serviceScheduleVo.setCreateContract(customer.getCustomManager());
        //支付金额
        PsContractInfoVo vo = new PsContractInfoVo();
        vo.setContractCode(contractCode);
        vo.setContractAmount(contractInfo.getContractAmount());
        this.fillMoney(vo);
        List<PsContractPayVo> payVoList = vo.getContractPayVoList().stream()
                .filter(item -> StringUtils.equals("1", item.getBusinessType())).toList();
        //第一笔回款
        serviceScheduleVo.setFirstPay(CollectionUtils.isNotEmpty(payVoList)?payVoList.get(0).getCreateBy():null);

        PsTaskMain task = taskMainService.queryByContractCodeAndServiceCompanyId(contractCode, serviceCompanyId);
        List<PsTaskAppoint> appointList = new ArrayList<>();
        if(task != null){
            appointList = taskAppointMapper.selectList(Wrappers.<PsTaskAppoint>lambdaQuery()
                    .eq(PsTaskAppoint::getContractCode, contractCode)
                    .ne(PsTaskAppoint::getAppointStatus,AppointStatusEnum.CANCEL.getCode())
                    .eq(PsTaskAppoint::getTaskId, task.getId())
            );
        }

        //派单者
        serviceScheduleVo.setAppoint(task == null ? null : task.getOperateUser());
        if(CollectionUtils.isNotEmpty(appointList)){
            appointList.forEach(item->{
                if(StringUtils.equals("1",item.getAppointType())){
                    serviceScheduleVo.addIn(new ServiceScheduleVo.UserAndStatus(item.getExecutor(), StringUtils.equals(AppointStatusEnum.FINISH.getCode(), item.getAppointStatus()) ? 1 : 0));
                }else if(StringUtils.equals("2",item.getAppointType())){
                    serviceScheduleVo.addOut(new ServiceScheduleVo.UserAndStatus(item.getExecutor(), StringUtils.equals(AppointStatusEnum.FINISH.getCode(), item.getAppointStatus()) ? 1 : 0));
                }else{
                    serviceScheduleVo.addSecret(new ServiceScheduleVo.UserAndStatus(item.getExecutor(), StringUtils.equals(AppointStatusEnum.FINISH.getCode(), item.getAppointStatus()) ? 1 : 0));
                }
            });
        }
        //回传
        serviceScheduleVo.setRollBack(StringUtils.equals(CommonStatusEnum.SUCCESS.getCode(),contractInfo.getRollBackStatus())?customer.getCustomManager():null);
        if(vo.getResidualMoney().compareTo(BigDecimal.ZERO) <=0 && CollectionUtils.isNotEmpty(payVoList)){
            PsContractPayVo pay = payVoList.get(payVoList.size() - 1);
            //最后一笔回款收款者
            serviceScheduleVo.setPayee(pay.getCreateBy());
            PsApproverRecordBo bo = new PsApproverRecordBo();
            bo.setBusinessId(pay.getId()+"");
            bo.setBusinessType(ApproverTypeEnum.PAY.getCode());
            List<PsApproverRecordVo> appro = approverRecordService.queryList(bo);
            //最后一笔回款审批者
            serviceScheduleVo.setApprove(CollectionUtils.isNotEmpty(appro)?appro.get(0).getUpdateBy():null);
        }
        //是否已完成（1是  0否）
        serviceScheduleVo.setIsFinish(StringUtils.equals(ContractStatusEnum.SUCCESS.getCode(),contractInfo.getContractStatus())?1:0);
        return serviceScheduleVo;
    }


    private QueryWrapper<PsContractInfo> buildQueryWrapper(PsContractInfoQueryBo bo) {
        QueryWrapper<PsContractInfo> qw = Wrappers.query();
        //删除标志
        qw.eq( "info.del_flag", 0);//删除标志
        //合同表条件
        qw.ne( "info.contract_status", ContractStatusEnum.INIT.getCode());
        qw.eq( StringUtils.isNotBlank(bo.getContractStatus()),"info.contract_status", bo.getContractStatus());
        qw.ne( StringUtils.isNotBlank(bo.getContractStatus()),"info.is_cancel", CommonStatusEnum.SUCCESS.getCode());
        qw.in( CollectionUtils.isNotEmpty(bo.getInContractStatus()),"info.contract_status", bo.getInContractStatus());
        qw.notIn( CollectionUtils.isNotEmpty(bo.getNotInContractStatus()),"info.contract_status", bo.getNotInContractStatus());
        qw.eq( StringUtils.isNotBlank(bo.getContractCode()),"info.contract_code", bo.getContractCode());
        qw.eq( StringUtils.isNotBlank(bo.getIsDue()),"info.is_due", bo.getIsDue());
        //客户表条件
        qw.like( StringUtils.isNotBlank(bo.getCustomName()),"cus.custom_name", bo.getCustomName());
        qw.like( StringUtils.isNotBlank(bo.getCustomMobile()),"cus.custom_mobile", bo.getCustomMobile());
        //公司表条件
        qw.like( StringUtils.isNotBlank(bo.getCompanyName()),"com.company_name", bo.getCompanyName());
        //用户表条件
        qw.like( StringUtils.isNotBlank(bo.getCustomManagerName()),"us.nick_name", bo.getCustomManagerName());

        //2待回款（不要作废数据） 3已回款（需要展示退款中的作废数据）
        qw.and(bo.getType() != null && (bo.getType() == 2 || (bo.getType() == 3)),wq->{
            wq.ne("info.is_cancel",CommonStatusEnum.SUCCESS.getCode());
            wq.or().gt( bo.getType() == 2,"((select IFNULL(sum(pa.money),0) from ps_contract_pay pa where pa.pay_status = 1 and pa.business_type = 1 and pa.contract_code =  info.contract_code\n" +
                    ")-(select IFNULL(sum(pay.money),0) from ps_contract_pay pay where pay.pay_status = 1 and pay.business_type = 2 and pay.contract_code =  info.contract_code))",0);
        });
        //托管续费合同(写死托管服务的id是2)
        if(bo.getType() != null && bo.getType() == 4){
            qw.exists("select 1 from ps_contract_business bus where info.contract_code = bus.contract_code and bus.business_type = 2");
        }else{
            //托管类服务类型编码集合
            qw.exists(bo.getServiceType() !=null && bo.getServiceType() == 1, "select 1 from ps_contract_business bus " +
                    "where bus.contract_code = info.contract_code and bus.business_type = 2");
            //非托管服务类型编码集合
            qw.notExists(bo.getServiceType() !=null && bo.getServiceType() == 2, "select 1 from ps_contract_business bus " +
                    "where bus.contract_code = info.contract_code and bus.business_type = 2");
        }
        //服务项目编码集合
        qw.exists(CollectionUtils.isNotEmpty(bo.getServiceProjects()), "select 1 from ps_contract_business detail " +
                "where detail.contract_code = info.contract_code and detail.business_type in ("+StringUtils.join(bo.getServiceProjects(),",")+")");//服务项目编码集合
        qw.between(bo.getMoneyEnd() != null && bo.getMoneyStart() !=null,"info.contract_amount",bo.getMoneyStart(),bo.getMoneyEnd());
        qw.orderByDesc("info.create_time");

        return qw;
    }
    private PsContractInfoVo fillContractInfo(PsContractInfoVo vo){

        //装填服务类型和服务项目信息
//        List<PsContractBusinessVo> list = businessService.selectBusinessList(List.of(vo.getContractCode()));
//        vo.setBusinessTypeName(StringUtils.join(list.stream().map(PsContractBusinessVo::getBusinessType).collect(Collectors.toList()), ","));

        fillMoney(vo);
        if(vo.getFirstApplyDate() != null){
            Date date = new Date();
            Date startDate = vo.getFirstApplyDate();
            long num = DateUtils.differentMonth(startDate,date);
            if(num<=0){
                vo.setConTime("0");
            }else if(num<12){
                vo.setConTime(num+"个月");
            }else {
                vo.setConTime(((int)(num/12))+"年"+num%12+"个月");
            }
//            int year = (date.getYear() - startDate.getYear());
//            int month = (date.getMonth() - startDate.getMonth());
////            int day = (date.getDate() - startDate.getDate());
//            vo.setConTime((year>0?year+"年":"")+(month>0?month+"月":"")/*+(day>0?day+"天":"") */);
        }
        //电子签章审批
        if(StringUtils.equals(CommonStatusEnum.FAIL.getCode(),vo.getSignStatus())){
            vo.setSignFailDesc(approverRecordService.getLastFail(vo.getContractCode(),vo.getContractCode(),List.of(ApproverTypeEnum.SIGN.getCode())));
        }
        //回传合同审批
        if(StringUtils.equals(CommonStatusEnum.FAIL.getCode(),vo.getRollBackStatus())){
            vo.setRollBackFailDesc(approverRecordService.getLastFail(vo.getContractCode(),vo.getContractCode(),List.of(ApproverTypeEnum.ROLBACK.getCode())));
        }
        //合同作废审批
        if(StringUtils.equals(CommonStatusEnum.FAIL.getCode(),vo.getIsCancel())){
            vo.setContractStatusDesc(approverRecordService.getLastFail(vo.getContractCode(),vo.getContractCode(),List.of(ApproverTypeEnum.CANCELLA.getCode())));
        }
//        //合同作废审批
//        if(StringUtils.equals(CommonStatusEnum.FAIL.getCode(),vo.getIsCancel())){
//            vo.setContractStatusDesc(approverRecordService.getLastFail(vo.getContractCode(),vo.getContractCode(),List.of(ApproverTypeEnum.CANCELLA.getCode())));
//        }
        //天数
        if(vo.getEndServiceDate() != null){
            int num = DateUtils.differentDaysByMillisecond(new Date(), vo.getEndServiceDate());
            vo.setEndNum(Math.max(num, 0));
        }

        //装填服务公司信息
        List<PsCompanyInfoVo> list = companyInfoService.getServiceCompany(vo.getContractCode());
        vo.setPsCompanySerivceVo(list);

        return vo;
    }
    public void fillMoney(PsContractInfoVo vo){
        //装填回款记录
        List<PsContractPayVo> payList = contractPayService.queryListByContractCode(vo.getContractCode(),null,PayStatusEnum.SUCCESS);
        vo.setContractPayVoList(payList);
        //退款金额
        vo.setReturnMoney(payList.stream().filter(item->StringUtils.equals(item.getBusinessType(), PayBuinessStatusEnum.RETURN.getCode()))
                .map(PsContractPayVo::getMoney).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
        //收款金额
        List<PsContractPayVo> returnList = payList.stream().filter(item -> StringUtils.equals(item.getBusinessType(), PayBuinessStatusEnum.PAY.getCode())).toList();
        BigDecimal netPay = returnList.stream().map(PsContractPayVo::getMoney).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal pay = netPay.subtract(vo.getReturnMoney());
        //已付金额(收款-退款)
        vo.setPayMoney(pay.compareTo(BigDecimal.ZERO) >= 0 ? pay : BigDecimal.ZERO);
        //未付金额(合同金额-已付金额)
        vo.setResidualMoney((vo.getContractAmount() == null ? BigDecimal.ZERO:vo.getContractAmount()).subtract(vo.getPayMoney()));

        //回款日期 = 第一次回款（若有全部退款过，则需要从全部退款开始算）到最后一次回款的时间
        BigDecimal big = BigDecimal.ZERO;
        Date startDate = null;
        Date endDate = null;
        for (PsContractPayVo pcp:payList){
            big = StringUtils.equals(pcp.getBusinessType(),"1")?big.add(pcp.getMoney()):big.subtract(pcp.getMoney());
            if(big.compareTo(BigDecimal.ZERO)>0){
                if( startDate == null){
                    startDate = pcp.getPayDate();
                }else{
                    endDate = pcp.getPayDate();
                }
            }else{
                startDate = null;
                endDate = null;
            }
        }

        //付款周期
        if(startDate == null){
            vo.setPeriod(0);
        }else if(endDate == null){
            vo.setPeriod(1);
        }else{
            //包含最后一天
            vo.setPeriod(DateUtils.calWorkDate(startDate,endDate));
        }
    }

    /**
     * 数据校验并返回
     * isAdd:是否为增加/修改校验
     * 校验：暂存的合同不止一个，暂存的合同并且不是传入的合同-》报错（暂存的合同只能有一个）
     */
    private PsContractInfo validEntity(PsContractInfoBo bo, String... isAdd){
        PsContractInfo add =null;
        //插入或修改合同
        log.info("校验合同查询入参：{}", bo.getCustomId());
        List<PsContractInfo> infos = this.queryByCode(bo.getCustomId(),null, ContractStatusEnum.INIT.getCode());
        log.info("校验合同查询结果：{}", infos == null?null: infos.size());
        //校验：暂存的合同不止一个，暂存的合同并且不是传入的合同-》报错（暂存的合同只能有一个）
        if (CollectionUtils.isNotEmpty(infos)) {
            if(infos.size() > 1){
                log.error("暂存的合同过多，customerid:" + bo.getCustomId());
                throw new ServiceException("系统异常，请联系管理员");
            }
            add = infos.get(0);
            //新增时校验是否有暂存的合同
            if(StringUtils.equals(isAdd.length < 1 ? "" : isAdd[0], UserConstants.YES)
                    && !StringUtils.equals(add.getContractCode(), bo.getContractCode())){
                log.error("此合已有暂存的合同，customerid:" + bo.getCustomId());
                throw new ServiceException("此合同状态已变更，请刷新页面重新操作");
            }
        }
        return add;
    }

    /**
     * 修改合同前置的校验
     *  1.合同已回传 不可修改
     *  2.已回款合同 必有修改合同说明（审批表的字段）
     */
    private void beforeUpdateValid( PsContractInfoBo updateBo,PsContractInfoVo srcVo){
        //1.合同已回传 不可修改
        if(StringUtils.equals(CommonStatusEnum.SUCCESS.getCode(),srcVo.getRollBackStatus())){
            throw new ServiceException("合同已回传，不可修改");
        }
        //2.已回款之后的合同 必有修改合同说明（审批表的字段）
        if(ContractStatusEnum.isReturn(srcVo.getContractStatus()) && StringUtil.isBlank(updateBo.getUpdateDesc())){
            throw new ServiceException("合同已回款，请输入修改说明");
        }
        //3.已完成合同不可修改
        if(StringUtils.equals(ContractStatusEnum.SUCCESS.getCode(),srcVo.getRollBackStatus())){
            throw new ServiceException("合同已完成，不可修改");
        }
    }


    public void dealReturn(String contractCode){
        PsContractInfo contract = this.queryByCode(null, contractCode, null).get(0);
        //装填金额
        PsContractInfoVo vo = new PsContractInfoVo();
        vo.setContractCode(contract.getContractCode());
        vo.setContractAmount(contract.getContractAmount());
        this.fillMoney(vo);
        //退款后金额小于0的话合同状态变为带回款
        if(vo.getPayMoney().compareTo(BigDecimal.ZERO) <= 0){
            //合同回退到待回款
            PsContractInfo con = new PsContractInfo();
            con.setContractCode(contract.getContractCode());
            con.setContractStatus(ContractStatusEnum.CREATE.getCode());
            this.updateByCode(con);
            //主任务作废
            taskMainMapper.update(Wrappers.<PsTaskMain>lambdaUpdate().set(PsTaskMain::getTaskStatus,TaskStatusEnum.CANCEL.getCode()).eq(PsTaskMain::getContractCode, contract.getContractCode()));
            //子任务作废
            List<PsTaskAppoint> list = taskAppointMapper.selectList(Wrappers.<PsTaskAppoint>lambdaQuery().select(PsTaskAppoint::getId).eq(PsTaskAppoint::getContractCode, contract.getContractCode()));
            if(CollectionUtils.isNotEmpty(list)){
                List<String> ids = list.stream().map(PsTaskAppoint::getId).map(Objects::toString).toList();
                taskAppointMapper.update(Wrappers.<PsTaskAppoint>lambdaUpdate().set(PsTaskAppoint::getAppointStatus,TaskStatusEnum.AppointStatusEnum.CANCEL.getCode()).eq(PsTaskAppoint::getContractCode, contract.getContractCode()));
                //子任务审批删除
                recordMapper.delete(Wrappers.<PsApproverRecord>lambdaQuery().in(PsApproverRecord::getBusinessId, ids));
            }
        }
    }

    /**
     * 查询合同基本信息
     *
     * @param id 主键
     * @return 合同基本信息
     *//*
    @Override
    public PsContractInfoVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    *//**
     * 分页查询合同基本信息列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 合同基本信息分页列表
     *//*
    @Override
    public TableDataInfo<PsContractInfoVo> queryPageList(PsContractInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PsContractInfo> lqw = buildQueryWrapper(bo);
        Page<PsContractInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    *//**
     * 查询符合条件的合同基本信息列表
     *
     * @param bo 查询条件
     * @return 合同基本信息列表
     *//*
    @Override
    public List<PsContractInfoVo> queryList(PsContractInfoBo bo) {
        LambdaQueryWrapper<PsContractInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PsContractInfo> buildQueryWrapper(PsContractInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PsContractInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getContractCode()), PsContractInfo::getContractCode, bo.getContractCode());
        lqw.like(StringUtils.isNotBlank(bo.getContractName()), PsContractInfo::getContractName, bo.getContractName());
        lqw.eq(bo.getCustomId() != null, PsContractInfo::getCustomId, bo.getCustomId());
        lqw.eq(bo.getCompanyId() != null, PsContractInfo::getCompanyId, bo.getCompanyId());
        lqw.eq(StringUtils.isNotBlank(bo.getContractMain()), PsContractInfo::getContractMain, bo.getContractMain());
        lqw.eq(bo.getCustomManager() != null, PsContractInfo::getCustomManager, bo.getCustomManager());
        lqw.eq(bo.getContractAmount() != null, PsContractInfo::getContractAmount, bo.getContractAmount());
        lqw.eq(StringUtils.isNotBlank(bo.getContractStatus()), PsContractInfo::getContractStatus, bo.getContractStatus());
        lqw.between(params.get("beginApplyDate") != null && params.get("endApplyDate") != null,
            PsContractInfo::getApplyDate ,params.get("beginApplyDate"), params.get("endApplyDate"));
        lqw.eq(bo.getTimeLimit() != null, PsContractInfo::getTimeLimit, bo.getTimeLimit());
        lqw.eq(StringUtils.isNotBlank(bo.getCustomScene()), PsContractInfo::getCustomScene, bo.getCustomScene());
        lqw.eq(StringUtils.isNotBlank(bo.getIsProxy()), PsContractInfo::getIsProxy, bo.getIsProxy());
        lqw.eq(StringUtils.isNotBlank(bo.getSignDesc()), PsContractInfo::getSignDesc, bo.getSignDesc());
        lqw.eq(bo.getDelFlage() != null, PsContractInfo::getDelFlage, bo.getDelFlage());
        return lqw;
    }

    *//**
     * 新增合同基本信息
     *
     * @param bo 合同基本信息
     * @return 是否新增成功
     *//*
    @Override
    public Boolean insertByBo(PsContractInfoBo bo) {
        PsContractInfo add = MapstructUtils.convert(bo, PsContractInfo.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        return flag;
    }

    *//**
     * 修改合同基本信息
     *
     * @param bo 合同基本信息
     * @return 是否修改成功
     *//*
    @Override
    public Boolean updateByBo(PsContractInfoBo bo) {
        PsContractInfo update = MapstructUtils.convert(bo, PsContractInfo.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    *//**
     * 保存前的数据校验
     *//*
    private void validEntityBeforeSave(PsContractInfo entity){
        //TODO 做一些数据校验,如唯一约束
    }

    *//**
     * 校验并批量删除合同基本信息信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     *//*
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }*/
}
