package com.jeeplus.assess.invoice.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.jeeplus.assess.invoice.domain.OMS.InvoiceDown.OMSInvoiceDetailInfo;
import com.jeeplus.assess.invoice.service.dto.*;
import com.jeeplus.assess.invoice.thread.ApprovalThread;
import com.jeeplus.assess.invoice.thread.RedApprovalThread;
import com.jeeplus.assess.invoice.utils.DingTalkUtil;
import com.jeeplus.assess.invoice.utils.OMS.FileHandlingUtil;
import com.jeeplus.common.TokenProvider;
import com.jeeplus.core.query.QueryWrapperGenerator;
import com.jeeplus.flowable.feign.IFlowableApi;
import com.jeeplus.sys.domain.User;
import com.jeeplus.sys.domain.WorkAttachmentInfo;
import com.jeeplus.sys.feign.IDictApi;
import com.jeeplus.sys.feign.IRoleApi;
import com.jeeplus.sys.feign.IUserApi;
import com.jeeplus.sys.feign.IWorkAttachmentApi;
import com.jeeplus.sys.service.dto.OfficeDTO;
import com.jeeplus.sys.service.dto.RoleDTO;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.assess.invoice.domain.*;
import com.jeeplus.assess.invoice.mapper.*;
import com.jeeplus.assess.invoice.service.mapstruct.*;
import com.jeeplus.assess.workContract.mapper.WorkContractInfoMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.jeeplus.assess.invoice.config.FinanceOmsConfig.*;

@Service
@Transactional(rollbackFor = Exception.class)
public class FinanceInvoiceService extends ServiceImpl<FinanceInvoiceMapper, FinanceInvoice> {

    @Resource
    private FinanceInvoiceMapper financeInvoiceMapper;
    @Resource
    private FinanceInvoiceBaseMapper financeInvoiceBaseMapper;
    @Resource
    private FinanceInvoiceDetailMapper financeInvoiceDetailMapper;
    @Resource
    private FinanceInvoiceReceivablesMapper financeInvoiceReceivablesMapper;
    @Resource
    private FinanceInvoiceInvalidMapper financeInvoiceInvalidMapper;
//    @Resource
//    private SerialnumTplService serialnumTplService;
//    @Resource
//    private OssServiceMapper ossServiceMapper;
    @Resource
    private WorkContractInfoMapper workContractInfoMapper;
//    @Resource
//    private UserService userService;
    @Resource
    private IFlowableApi flowTaskService;

    @Value("${oms.omsEnabled}")
    private Boolean omsEnabled;

    @Resource
    private DingTalkUtil dingTalkUtil;

    private static final String unitName = "兴光评估";

    Pattern mobilePattern = Pattern.compile("^1[3-9]\\d{9}$");

    public List<String> getSearchList(ArrayList<String> searchIdList, List<String> ids) {
        List<String> newSearchIdList = searchIdList.stream().filter(item -> {
            AtomicInteger num = new AtomicInteger();
            ids.stream().forEach(id -> {
                if (item.equals(id)) {
                    num.getAndIncrement();
                }
            });
            if (num.get() > 0) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        return newSearchIdList;
    }

    public IPage<FinanceInvoiceDTO> findList(Page<FinanceInvoiceDTO> page, FinanceInvoiceDTO financeInvoiceDTO) throws Exception{
        QueryWrapper<FinanceInvoice> queryWrapper = QueryWrapperGenerator.buildQueryCondition ( FinanceInvoiceWrapper.INSTANCE.toEntity(financeInvoiceDTO), FinanceInvoice.class );
        queryWrapper.eq("fi.del_flag","0");
        queryWrapper.orderByDesc("fi.create_time");
        queryWrapper.orderByAsc("fi.id");
        queryWrapper.orderByAsc("fibs.rn");
        ArrayList<String> searchIdList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        AtomicInteger checkNum = new AtomicInteger();
        if (ObjectUtil.isNotEmpty(financeInvoiceDTO)) {
            if (StringUtils.isNotBlank(financeInvoiceDTO.getNumber())) {
                List<FinanceInvoiceDetail> financeInvoiceDetails = financeInvoiceDetailMapper.selectList(new LambdaQueryWrapper<FinanceInvoiceDetail>().like(FinanceInvoiceDetail::getNumber, financeInvoiceDTO.getNumber()));
                List<String> ids = financeInvoiceDetails.stream().distinct().map(FinanceInvoiceDetail::getInvoiceId).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(ids)) {
                    return new Page<FinanceInvoiceDTO>();
                }else{
                    if (CollectionUtil.isNotEmpty(searchIdList)){
                        List<String> newSearchIdList = getSearchList(searchIdList,ids);
                        searchIdList = new ArrayList<String>();
                        for (String item : newSearchIdList) {
                            searchIdList.add(item);
                        }
                    }else{
                        if (checkNum.get() > 0){
                            return new Page<FinanceInvoiceDTO>();
                        }else{
                            for (String item : ids) {
                                searchIdList.add(item);
                            }
                        }
                    }
                    checkNum.getAndIncrement();
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getAccountBegin())&&StringUtils.isNotBlank(financeInvoiceDTO.getAccountEnd())) {
                List<FinanceInvoice> financeInvoices = financeInvoiceMapper.selectList(new LambdaQueryWrapper<FinanceInvoice>()
                        .between(FinanceInvoice::getAccount, new BigDecimal(financeInvoiceDTO.getAccountBegin()), new BigDecimal(financeInvoiceDTO.getAccountEnd())));
                List<String> ids = financeInvoices.stream().distinct().map(FinanceInvoice::getId).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(ids)) {
                    return new Page<FinanceInvoiceDTO>();
                }else{
                    if (CollectionUtil.isNotEmpty(searchIdList)){
                        List<String> newSearchIdList = getSearchList(searchIdList,ids);
                        searchIdList = new ArrayList<String>();
                        for (String item : newSearchIdList) {
                            searchIdList.add(item);
                        }
                    }else{
                        if (checkNum.get() > 0){
                            return new Page<FinanceInvoiceDTO>();
                        }else{
                            for (String item : ids) {
                                searchIdList.add(item);
                            }
                        }
                    }
                    checkNum.getAndIncrement();
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getBillingDateBegin())&&StringUtils.isNotBlank(financeInvoiceDTO.getBillingDateEnd())) {
                List<FinanceInvoice> financeInvoices = financeInvoiceMapper.selectList(new LambdaQueryWrapper<FinanceInvoice>()
                        .between(FinanceInvoice::getBillingDate, sdf.parse(financeInvoiceDTO.getBillingDateBegin()), sdf.parse(financeInvoiceDTO.getBillingDateEnd())));
                List<String> ids = financeInvoices.stream().distinct().map(FinanceInvoice::getId).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(ids)) {
                    return new Page<FinanceInvoiceDTO>();
                }else{
                    if (CollectionUtil.isNotEmpty(searchIdList)){
                        List<String> newSearchIdList = getSearchList(searchIdList,ids);
                        searchIdList = new ArrayList<String>();
                        for (String item : newSearchIdList) {
                            searchIdList.add(item);
                        }
                    }else{
                        if (checkNum.get() > 0){
                            return new Page<FinanceInvoiceDTO>();
                        }else{
                            for (String item : ids) {
                                searchIdList.add(item);
                            }
                        }
                    }
                    checkNum.getAndIncrement();
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getRemittanceDateBegin())&&StringUtils.isNotBlank(financeInvoiceDTO.getRemittanceDateEnd())) {
                List<FinanceInvoice> financeInvoices = financeInvoiceMapper.selectList(new LambdaQueryWrapper<FinanceInvoice>()
                        .between(FinanceInvoice::getReceivablesDate, sdf.parse(financeInvoiceDTO.getRemittanceDateBegin()), sdf.parse(financeInvoiceDTO.getRemittanceDateEnd())));
                List<String> ids = financeInvoices.stream().distinct().map(FinanceInvoice::getId).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(ids)) {
                    return new Page<FinanceInvoiceDTO>();
                }else{
                    if (CollectionUtil.isNotEmpty(searchIdList)){
                        List<String> newSearchIdList = getSearchList(searchIdList,ids);
                        searchIdList = new ArrayList<String>();
                        for (String item : newSearchIdList) {
                            searchIdList.add(item);
                        }
                    }else{
                        if (checkNum.get() > 0){
                            return new Page<FinanceInvoiceDTO>();
                        }else{
                            for (String item : ids) {
                                searchIdList.add(item);
                            }
                        }
                    }
                    checkNum.getAndIncrement();
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getProgramId())||StringUtils.isNotBlank(financeInvoiceDTO.getProgramName())) {
                if (StringUtils.isNotBlank(financeInvoiceDTO.getProgramId())){
                    List<FinanceInvoiceBase> financeInvoiceBaseList = financeInvoiceBaseMapper.selectList(new LambdaQueryWrapper<FinanceInvoiceBase>()
                            .eq(FinanceInvoiceBase::getProgramId,financeInvoiceDTO.getProgramId()));
                    List<String> ids = financeInvoiceBaseList.stream().distinct().map(FinanceInvoiceBase::getInvoiceId).collect(Collectors.toList());
                    if(CollectionUtil.isEmpty(ids)) {
                        return new Page<FinanceInvoiceDTO>();
                    }else{
                        if (CollectionUtil.isNotEmpty(searchIdList)){
                            List<String> newSearchIdList = getSearchList(searchIdList,ids);
                            searchIdList = new ArrayList<String>();
                            for (String item : newSearchIdList) {
                                searchIdList.add(item);
                            }
                        }else{
                            if (checkNum.get() > 0){
                                return new Page<FinanceInvoiceDTO>();
                            }else{
                                for (String item : ids) {
                                    searchIdList.add(item);
                                }
                            }
                        }
                        checkNum.getAndIncrement();
                    }
                }else{
                    List<FinanceInvoiceBase> financeInvoiceBaseList = financeInvoiceBaseMapper.selectList(new LambdaQueryWrapper<FinanceInvoiceBase>()
                            .like(FinanceInvoiceBase::getProgramName,financeInvoiceDTO.getProgramName()));
                    List<String> ids = financeInvoiceBaseList.stream().distinct().map(FinanceInvoiceBase::getInvoiceId).collect(Collectors.toList());
                    if(CollectionUtil.isEmpty(ids)) {
                        return new Page<FinanceInvoiceDTO>();
                    }else{
                        if (CollectionUtil.isNotEmpty(searchIdList)){
                            List<String> newSearchIdList = getSearchList(searchIdList,ids);
                            searchIdList = new ArrayList<String>();
                            for (String item : newSearchIdList) {
                                searchIdList.add(item);
                            }
                        }else{
                            if (checkNum.get() > 0){
                                return new Page<FinanceInvoiceDTO>();
                            }else{
                                for (String item : ids) {
                                    searchIdList.add(item);
                                }
                            }
                        }
                        checkNum.getAndIncrement();
                    }
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getOperator())){
                queryWrapper.eq("su.id",financeInvoiceDTO.getOperator()).or().like("su.name",financeInvoiceDTO.getOperator());
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getReconciliationPeopleName())) {
//                List<User> users = SpringUtil.getBean ( IUserApi.class ).selectListByName(financeInvoiceDTO.getReconciliationPeopleName());
//                List<String> userIdList = users.stream().distinct().map(User::getId).collect(Collectors.toList());
//                if (CollectionUtil.isNotEmpty(userIdList)) {
//                    queryWrapper.in("fi.reconciliation_people",userIdList);
//                } else {
//                    return new Page<FinanceInvoiceDTO>();
//                }
                queryWrapper.like("su1.name",financeInvoiceDTO.getReconciliationPeopleName());

            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getOperatorOffice())){
                List<User> userList = SpringUtil.getBean ( IUserApi.class ).getUserByOfficeAll(financeInvoiceDTO.getOperatorOffice());
                if (CollectionUtil.isNotEmpty(userList)) {
                    List<String> userIdList = userList.stream().distinct().map(User::getId).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(userIdList)) {
                        queryWrapper.in("fi.create_by_id",userIdList);
                    } else {
                        return new Page<FinanceInvoiceDTO>();
                    }
                } else {
                    return new Page<FinanceInvoiceDTO>();
                }
            }
        }
        if (CollectionUtil.isNotEmpty(searchIdList)){
            List<String> ids = searchIdList.stream().distinct().collect(Collectors.toList());
            queryWrapper.in("fi.id",ids);
        } else{
            if (checkNum.get() > 0) {
                return new Page<FinanceInvoiceDTO>();
            }
        }
        if (StringUtils.isNotBlank(financeInvoiceDTO.getName())){
            queryWrapper.like("fi.name",financeInvoiceDTO.getName());
        }
        //开票类型筛选
        if (StringUtils.isNotBlank(financeInvoiceDTO.getBillingType())){
            queryWrapper.eq("fi.billing_type",financeInvoiceDTO.getBillingType());
        }
        //是否手动开票
        if (StringUtils.isNotBlank(financeInvoiceDTO.getIsOmsBilling())) {
            String isOmsBilling = financeInvoiceDTO.getIsOmsBilling();
            if ("1".equals(isOmsBilling)) {
                // 当值为0时，匹配is_oms_billing = 0 或者 is_oms_billing 为空
                queryWrapper.and(wrapper -> wrapper
                        .eq("fi.is_oms_billing", "1")
                        .or()
                        .isNull("fi.is_oms_billing") // 匹配数据库null值
                        .or()
                        .eq("fi.is_oms_billing", "")); // 匹配数据库空字符串
            } else {
                queryWrapper.eq("fi.is_oms_billing", isOmsBilling);
            }
        }
        //关闭自动查询count
        page.setSearchCount(false);
        //自定义count
        Long total = financeInvoiceMapper.findListCount(queryWrapper);

        IPage<FinanceInvoiceDTO> pageList = financeInvoiceMapper.findList(page, queryWrapper);
        pageList.setTotal(total);

        pageList.getRecords().stream().forEach(item ->{
            // 发票申请
            if (StringUtils.isNotBlank(item.getTaskId()) && StringUtils.isNotBlank(item.getStatus())) {
                if ("2".equals(item.getStatus())) { // “审核中”的数据要获取数据审核人
                    item.setAuditUserIds(flowTaskService.getTaskAuditUsers(item.getTaskId()));  // 获取数据审核人
                }
            }
            // 发票作废
            if (StringUtils.isNotBlank(item.getTaskIdInvalid()) && StringUtils.isNotBlank(item.getStatus())) {
                if ("6".equals(item.getStatus())) { // “审核中”的数据要获取数据审核人
                    item.setAuditUserIdsInvalid(flowTaskService.getTaskAuditUsers(item.getTaskIdInvalid()));  // 获取数据审核人
                }
            }

            if(StringUtils.isNotBlank(item.getBillingType()) && "2".equals(item.getBillingType()) && StringUtils.isNotBlank(item.getName())){
                item.setBillingWorkplaceReal(item.getName());
            }

        });


        List<String> idList = Lists.newArrayList();
        //对数据进行处理
        for (FinanceInvoiceDTO invoice : pageList.getRecords()) {
            if(StringUtils.isNotBlank(invoice.getStatus()) && "5".equals(invoice.getStatus())){
                //获取所有id，并用这些id查询对应的oms文件（仅需一条即可）
                idList.add(invoice.getId());
            }
        }

        List<WorkAttachmentInfo> omsInvoiceFileList  = SpringUtil.getBean(IWorkAttachmentApi.class).getByAttachmentIdListAndFlag(idList);
        if(CollectionUtil.isNotEmpty(omsInvoiceFileList)){
            for (FinanceInvoiceDTO invoice : pageList.getRecords()) {
                for (WorkAttachmentInfo workattachment : omsInvoiceFileList) {
                    if(invoice.getId().equals(workattachment.getAttachmentId())){
                        invoice.setOmsAttachmentUrl(workattachment.getUrl());
                        break;
                    }
                }
            }
        }


        return pageList;
    }

//    public List<FinanceInvoiceDTO> exportList(Page<FinanceInvoiceDTO> page, FinanceInvoiceDTO financeInvoiceDTO) throws Exception{
//        IPage<FinanceInvoiceDTO> FinanceInvoiceDTOIPage = this.findList(page, financeInvoiceDTO);
//        List<FinanceInvoiceDTO> records = FinanceInvoiceDTOIPage.getRecords();
//        if(CollectionUtil.isNotEmpty(records)){
//            records.stream().forEach(record->{
//                if(CollectionUtil.isNotEmpty(record.getFinanceInvoiceBaseDTOList())){
//                    if(record.getFinanceInvoiceBaseDTOList().size() == 1 && StringUtils.isBlank(record.getFinanceInvoiceBaseDTOList().get(0).getProgramId())) {
//                        record.setProgramName("其他： " + record.getFinanceInvoiceBaseDTOList().get(0).getProgramName());
//                    } else {
//                        AtomicReference<String> programName = new AtomicReference<>("");
//                        AtomicInteger n = new AtomicInteger();
//                        record.getFinanceInvoiceBaseDTOList().stream().forEach((item)->{
//                            n.getAndIncrement();
//                            if (n.get() == record.getFinanceInvoiceBaseDTOList().size()){
//                                if(StringUtils.isNotBlank(item.getProgramName())){
//                                    programName.set(programName.get() + item.getProgramName());
//                                }
//                            } else {
//                                if(StringUtils.isNotBlank(item.getProgramName())){
//                                    programName.set(programName.get() + item.getProgramName() + ",");
//                                }
//                            }
//                        });
//                        record.setProgramName(programName.get());
//                    }
//                }else{
//                    record.setProgramName("");
//                }
//                if(CollectionUtil.isNotEmpty(record.getFinanceInvoiceDetailDTOList())){
//                    AtomicReference<String> programName = new AtomicReference<>("");
//                    AtomicInteger n = new AtomicInteger();
//                    record.getFinanceInvoiceBaseDTOList().stream().forEach((item)->{
//                        n.getAndIncrement();
//                        if (n.get() == record.getFinanceInvoiceBaseDTOList().size()){
//                            if(StringUtils.isNotBlank(item.getProgramName())){
//                                programName.set(programName.get() + item.getProgramName());
//                            }
//                        } else {
//                            if(StringUtils.isNotBlank(item.getProgramName())){
//                                programName.set(programName.get() + item.getProgramName() + ",");
//                            }
//                        }
//                    });
//                    record.setProgramName(programName.get());
//                }
//            });
//        }else{
//            return records;
//        }
//    }

    public FinanceInvoiceDTO queryById(String id) {
        FinanceInvoiceDTO financeInvoiceDTO = financeInvoiceMapper.queryById(id);
        if(ObjectUtil.isNotEmpty(financeInvoiceDTO) && "1".equals(financeInvoiceDTO.getRedInvoiceFlag()) ){
            //此处为红冲数据 需要获取发票号
            if(StringUtils.isNotBlank(financeInvoiceDTO.getRedInvoiceRelevancyId())){
                FinanceInvoiceDTO redCwFinanceInvoiceDTO = financeInvoiceMapper.queryById(financeInvoiceDTO.getRedInvoiceRelevancyId());
                String invoiceNumberStr = financeInvoiceMapper.getInvoiceNumberStr(redCwFinanceInvoiceDTO.getId());
                financeInvoiceDTO.setInvoiceNumberStr(invoiceNumberStr);
                financeInvoiceDTO.setOriginalAccount(redCwFinanceInvoiceDTO.getAccount());
            }
        }
        // 查询附件信息
        List<WorkAttachmentInfo> fileList = workContractInfoMapper.findDtos(id);
        if (CollectionUtil.isNotEmpty(fileList)) {
            for (WorkAttachmentInfo i : fileList) {
                i.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(i.getBy()));
            }
        }
        if(CollectionUtil.isNotEmpty(fileList)){
            financeInvoiceDTO.setWorkAttachmentDtoList(fileList);
        }
        // 查询发票文件
        List<WorkAttachmentInfo> invoiceList = workContractInfoMapper.findInvoiceList(id);
        if (CollectionUtil.isNotEmpty(invoiceList)) {
            for (WorkAttachmentInfo i : invoiceList) {
                i.setCreateBy(SpringUtil.getBean ( IUserApi.class ).getById(i.getBy()));
            }
        }
        if(CollectionUtil.isNotEmpty(invoiceList)){
            financeInvoiceDTO.setInvoiceList(invoiceList);
        }

        return financeInvoiceDTO;
    }

    /**
     * 仅作为单独保存发票数据接口使用
     * @param financeInvoiceDTO
     * @return
     * @throws Exception
     */
    public String saveFormOnly(FinanceInvoiceDTO financeInvoiceDTO) throws Exception{
        //添加钉钉通知处理
        boolean isDDNotice = false;
        String isOms = "0";

        FinanceInvoice financeInvoice = FinanceInvoiceWrapper.INSTANCE.toEntity(financeInvoiceDTO);
        if(StringUtils.isNotBlank(financeInvoiceDTO.getRelatedInvoice())){
            financeInvoice.setRelatedInvoice(financeInvoiceDTO.getRelatedInvoice());
        }
        if(StringUtils.isNotBlank(financeInvoiceDTO.getSituationDetail())){
            financeInvoice.setSituationDetail(financeInvoiceDTO.getSituationDetail());
        }
        if(StringUtils.isNotBlank(financeInvoiceDTO.getRedFlushReason())){
            financeInvoice.setRedFlushReason(financeInvoiceDTO.getRedFlushReason());
        }
        if(StringUtils.isNotBlank(financeInvoiceDTO.getIsSmsNotice())){
            financeInvoice.setIsSmsNotice(financeInvoiceDTO.getIsSmsNotice());
        }
        if(StringUtils.isNotBlank(financeInvoiceDTO.getIsOmsBilling())){
            financeInvoice.setIsOmsBilling(financeInvoiceDTO.getIsOmsBilling());
        }
        if (ObjectUtil.isNotEmpty(financeInvoice)) {
            if(StringUtils.isBlank(financeInvoice.getId())){
                //获取当前登录人信息
                UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByToken(TokenProvider.getCurrentToken());
                //发票编号生成
                String serialNum = SpringUtil.getBean ( IWorkAttachmentApi.class ).genSerialNum(userDTO.getCompanyDTO().getId(), FinanceInvoiceDTO.BIZ_CODE, TokenProvider.getCurrentToken());
                financeInvoice.setNo(serialNum);
                if (StringUtils.isBlank(financeInvoice.getInvalidStatus())){
                    financeInvoice.setInvalidStatus("0");
                }
                if (StringUtils.isBlank(financeInvoice.getReceivablesStatus())){
                    financeInvoice.setReceivablesStatus("0");
                }
            }
            if(StringUtils.isNotEmpty(financeInvoiceDTO.getActualDrawerEmailAddress())){
                financeInvoice.setActualDrawerEmailAddress(financeInvoiceDTO.getActualDrawerEmailAddress());
            }
            financeInvoice.setRedInvoiceFlag(financeInvoiceDTO.getRedInvoiceFlag());
            financeInvoice.setRedInvoiceRelevancyId(financeInvoiceDTO.getRedInvoiceRelevancyId());
            financeInvoice.setRedInvoiceRelevancyNumber(financeInvoiceDTO.getRedInvoiceRelevancyNumber());
        }
        this.saveOrUpdate(financeInvoice);
        if (ObjectUtil.isNotEmpty(financeInvoiceDTO)) {
            // 如果当前是执行的是收款页面的保存方法
            if ("1".equals(financeInvoiceDTO.getIsReceivables())) {
                // 如果传过来的收款日期为空，则将本条发票的收款日期置空
                if (ObjectUtil.isEmpty(financeInvoiceDTO.getReceivablesDate())) {
                    // 根据发票id，置空发票的收款日期
                    financeInvoiceMapper.setReceivablesDateNull(financeInvoice.getId());
                }
            }
            // 基本信息保存
            if(CollectionUtil.isNotEmpty(financeInvoiceDTO.getFinanceInvoiceBaseDTOList())){
                List<String> delIds = financeInvoiceDTO.getFinanceInvoiceBaseDTOList().stream().distinct().filter(item->{
                    if(StringUtils.isNotBlank(item.getId())){
                        return true;
                    }
                    return false;
                }).map(FinanceInvoiceBaseDTO::getId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(delIds)){
                    financeInvoiceBaseMapper.delete(new QueryWrapper<FinanceInvoiceBase>().lambda()
                            .eq(FinanceInvoiceBase::getInvoiceId,financeInvoice.getId()).notIn(FinanceInvoiceBase::getId,delIds));
                }else{
                    financeInvoiceBaseMapper.delete(new QueryWrapper<FinanceInvoiceBase>().lambda()
                            .eq(FinanceInvoiceBase::getInvoiceId,financeInvoice.getId()));
                }
                financeInvoiceDTO.getFinanceInvoiceBaseDTOList().stream().forEach(item->{
                    FinanceInvoiceBase financeInvoiceBase = FinanceInvoiceBaseWrapper.INSTANCE.toEntity(item);
                    if(StringUtils.isNotBlank(financeInvoiceBase.getId())){
                        financeInvoiceBaseMapper.updateById(financeInvoiceBase);
                    }else{
                        financeInvoiceBase.setInvoiceId(financeInvoice.getId());
                        financeInvoiceBaseMapper.insert(financeInvoiceBase);
                    }
                });
            }else{
                financeInvoiceBaseMapper.delete(new QueryWrapper<FinanceInvoiceBase>().lambda()
                        .eq(FinanceInvoiceBase::getInvoiceId,financeInvoice.getId()));
            }
            // 附件保存
            if(CollectionUtil.isNotEmpty(financeInvoiceDTO.getWorkAttachmentDtoList())){
                List<String> delIds = financeInvoiceDTO.getWorkAttachmentDtoList().stream().distinct().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return true;
                    }
                    return false;
                }).map(WorkAttachmentInfo::getId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(delIds)){
                    SpringUtil.getBean ( IWorkAttachmentApi.class ).deleteByAttachmentIdNotInIds(financeInvoice.getId(),delIds);
                }else{
                    SpringUtil.getBean ( IWorkAttachmentApi.class ).deleteByAttachmentId(financeInvoice.getId());
                }
                //获取当前登录人信息
                UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByToken(TokenProvider.getCurrentToken());
                AtomicInteger j = new AtomicInteger(1);
                List<WorkAttachmentInfo> collect = financeInvoiceDTO.getWorkAttachmentDtoList().stream().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return false;
                    }
                    return true;
                }).collect(Collectors.toList());
                collect.forEach(item->{
                    this.saveFiles(item,financeInvoice.getId(),userDTO,j);
                    j.getAndIncrement();
                });
            }else{
                SpringUtil.getBean ( IWorkAttachmentApi.class ).deleteByAttachmentId(financeInvoice.getId());
            }
            // 发票明细保存
            if(CollectionUtil.isNotEmpty(financeInvoiceDTO.getFinanceInvoiceDetailDTOList())){
                List<String> delIds = financeInvoiceDTO.getFinanceInvoiceDetailDTOList().stream().distinct().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return true;
                    }
                    return false;
                }).map(FinanceInvoiceDetailDTO::getId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(delIds)){
                    financeInvoiceDetailMapper.delete(new QueryWrapper<FinanceInvoiceDetail>().lambda()
                            .eq(FinanceInvoiceDetail::getInvoiceId,financeInvoice.getId())
                            .notIn(FinanceInvoiceDetail::getId,delIds));
                }else{
                    financeInvoiceDetailMapper.delete(new QueryWrapper<FinanceInvoiceDetail>().lambda().eq(FinanceInvoiceDetail::getInvoiceId,financeInvoice.getId()));
                }
                financeInvoiceDTO.getFinanceInvoiceDetailDTOList().stream().forEach(item->{
                    FinanceInvoiceDetail financeInvoiceDetail = FinanceInvoiceDetailWrapper.INSTANCE.toEntity(item);
                    if(StringUtils.isNotBlank(financeInvoiceDetail.getId())){
                        financeInvoiceDetailMapper.updateById(financeInvoiceDetail);
                    }else{
                        financeInvoiceDetail.setInvoiceId(financeInvoice.getId());
                        financeInvoiceDetailMapper.insert(financeInvoiceDetail);
                    }
                });
            }else{
                financeInvoiceDetailMapper.delete(new QueryWrapper<FinanceInvoiceDetail>().lambda().eq(FinanceInvoiceDetail::getInvoiceId,financeInvoice.getId()));
            }
            // 收款明细保存
            if(CollectionUtil.isNotEmpty(financeInvoiceDTO.getFinanceInvoiceReceivablesDTOList())){
                List<String> delIds = financeInvoiceDTO.getFinanceInvoiceReceivablesDTOList().stream().distinct().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return true;
                    }
                    return false;
                }).map(FinanceInvoiceReceivablesDTO::getId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(delIds)){
                    financeInvoiceReceivablesMapper.delete(new QueryWrapper<FinanceInvoiceReceivables>().lambda()
                            .eq(FinanceInvoiceReceivables::getInvoiceId,financeInvoice.getId())
                            .notIn(FinanceInvoiceReceivables::getId,delIds));
                }else{
                    financeInvoiceReceivablesMapper.delete(new QueryWrapper<FinanceInvoiceReceivables>().lambda().eq(FinanceInvoiceReceivables::getInvoiceId,financeInvoice.getId()));
                }
                financeInvoiceDTO.getFinanceInvoiceReceivablesDTOList().stream().forEach(item->{
                    FinanceInvoiceReceivables financeInvoiceReceivables = FinanceInvoiceReceivablesWrapper.INSTANCE.toEntity(item);
                    if(StringUtils.isNotBlank(financeInvoiceReceivables.getId())){
                        financeInvoiceReceivablesMapper.updateById(financeInvoiceReceivables);
                    }else{
                        financeInvoiceReceivables.setInvoiceId(financeInvoice.getId());
                        financeInvoiceReceivablesMapper.insert(financeInvoiceReceivables);
                    }
                });
            }else{
                financeInvoiceReceivablesMapper.delete(new QueryWrapper<FinanceInvoiceReceivables>().lambda().eq(FinanceInvoiceReceivables::getInvoiceId,financeInvoice.getId()));
            }
            // 作废信息保存
            if(ObjectUtil.isNotEmpty(financeInvoiceDTO.getFinanceInvoiceInvalidDTO())){
                FinanceInvoiceInvalid financeInvoiceInvalid = FinanceInvoiceInvalidWrapper.INSTANCE.toEntity(financeInvoiceDTO.getFinanceInvoiceInvalidDTO());
                if(StringUtils.isNotBlank(financeInvoiceInvalid.getId())){
                    financeInvoiceInvalidMapper.update(financeInvoiceInvalid,
                            new QueryWrapper<FinanceInvoiceInvalid>().lambda().eq(FinanceInvoiceInvalid::getId,financeInvoiceInvalid.getId()));
                }else{
                    financeInvoiceInvalid.setInvalidStatus("0");
                    financeInvoiceInvalid.setInvoiceId(financeInvoice.getId());
                    financeInvoiceInvalidMapper.insert(financeInvoiceInvalid);
                }
            }else{
                financeInvoiceInvalidMapper.delete(new QueryWrapper<FinanceInvoiceInvalid>().lambda().eq(FinanceInvoiceInvalid::getInvoiceId,financeInvoice.getId()));
                FinanceInvoiceInvalid financeInvoiceInvalid = new FinanceInvoiceInvalid();
                financeInvoiceInvalid.setInvalidStatus("0");
                financeInvoiceInvalid.setInvoiceId(financeInvoice.getId());
                financeInvoiceInvalidMapper.insert(financeInvoiceInvalid);
            }
        }
        return financeInvoice.getId();
    }


    public String saveForm(FinanceInvoiceDTO financeInvoiceDTO) throws Exception{
        //添加钉钉通知处理
        boolean isDDNotice = false;
        if(financeInvoiceDTO.getStatus().equals("2")){
            isDDNotice = true;
        }

        String isOms = "0";
        if("5".equals(financeInvoiceDTO.getStatus())){
            //IsOmsBilling为0时，需要走系统开票
            if("0".equals(financeInvoiceDTO.getIsOmsBilling())){
                isOms = handleDoInvoice(financeInvoiceDTO);
                //如果需要走开票系统，则设置状态为12
                if("1".equals(isOms) || "2".equals(isOms)){
                    financeInvoiceDTO.setStatus("12");
                }
            }
        }
        FinanceInvoice financeInvoice = FinanceInvoiceWrapper.INSTANCE.toEntity(financeInvoiceDTO);
        if(StringUtils.isNotBlank(financeInvoiceDTO.getRelatedInvoice())){
            financeInvoice.setRelatedInvoice(financeInvoiceDTO.getRelatedInvoice());
        }
        if(StringUtils.isNotBlank(financeInvoiceDTO.getSituationDetail())){
            financeInvoice.setSituationDetail(financeInvoiceDTO.getSituationDetail());
        }
        if(StringUtils.isNotBlank(financeInvoiceDTO.getRedFlushReason())){
            financeInvoice.setRedFlushReason(financeInvoiceDTO.getRedFlushReason());
        }
        if(StringUtils.isNotBlank(financeInvoiceDTO.getIsSmsNotice())){
            financeInvoice.setIsSmsNotice(financeInvoiceDTO.getIsSmsNotice());
        }
        if(StringUtils.isNotBlank(financeInvoiceDTO.getIsOmsBilling())){
            financeInvoice.setIsOmsBilling(financeInvoiceDTO.getIsOmsBilling());
        }
        if (ObjectUtil.isNotEmpty(financeInvoice)) {
            if(StringUtils.isBlank(financeInvoice.getId())){
                //获取当前登录人信息
                UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByToken(TokenProvider.getCurrentToken());
                //发票编号生成
                String serialNum = SpringUtil.getBean ( IWorkAttachmentApi.class ).genSerialNum(userDTO.getCompanyDTO().getId(), FinanceInvoiceDTO.BIZ_CODE, TokenProvider.getCurrentToken());
                financeInvoice.setNo(serialNum);
                if (StringUtils.isBlank(financeInvoice.getInvalidStatus())){
                    financeInvoice.setInvalidStatus("0");
                }
                if (StringUtils.isBlank(financeInvoice.getReceivablesStatus())){
                    financeInvoice.setReceivablesStatus("0");
                }
            }
            if(StringUtils.isNotEmpty(financeInvoiceDTO.getActualDrawerEmailAddress())){
                financeInvoice.setActualDrawerEmailAddress(financeInvoiceDTO.getActualDrawerEmailAddress());
            }
            financeInvoice.setRedInvoiceFlag(financeInvoiceDTO.getRedInvoiceFlag());
            financeInvoice.setRedInvoiceRelevancyId(financeInvoiceDTO.getRedInvoiceRelevancyId());
            financeInvoice.setRedInvoiceRelevancyNumber(financeInvoiceDTO.getRedInvoiceRelevancyNumber());
        }
        this.saveOrUpdate(financeInvoice);
        if (ObjectUtil.isNotEmpty(financeInvoiceDTO)) {
            // 如果当前是执行的是收款页面的保存方法
            if ("1".equals(financeInvoiceDTO.getIsReceivables())) {
                // 如果传过来的收款日期为空，则将本条发票的收款日期置空
                if (ObjectUtil.isEmpty(financeInvoiceDTO.getReceivablesDate())) {
                    // 根据发票id，置空发票的收款日期
                    financeInvoiceMapper.setReceivablesDateNull(financeInvoice.getId());
                }
            }
            // 基本信息保存
            if(CollectionUtil.isNotEmpty(financeInvoiceDTO.getFinanceInvoiceBaseDTOList())){
                List<String> delIds = financeInvoiceDTO.getFinanceInvoiceBaseDTOList().stream().distinct().filter(item->{
                    if(StringUtils.isNotBlank(item.getId())){
                        return true;
                    }
                    return false;
                }).map(FinanceInvoiceBaseDTO::getId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(delIds)){
                    financeInvoiceBaseMapper.delete(new QueryWrapper<FinanceInvoiceBase>().lambda()
                            .eq(FinanceInvoiceBase::getInvoiceId,financeInvoice.getId()).notIn(FinanceInvoiceBase::getId,delIds));
                }else{
                    financeInvoiceBaseMapper.delete(new QueryWrapper<FinanceInvoiceBase>().lambda()
                            .eq(FinanceInvoiceBase::getInvoiceId,financeInvoice.getId()));
                }
                financeInvoiceDTO.getFinanceInvoiceBaseDTOList().stream().forEach(item->{
                    FinanceInvoiceBase financeInvoiceBase = FinanceInvoiceBaseWrapper.INSTANCE.toEntity(item);
                    if(StringUtils.isNotBlank(financeInvoiceBase.getId())){
                        financeInvoiceBaseMapper.updateById(financeInvoiceBase);
                    }else{
                        financeInvoiceBase.setInvoiceId(financeInvoice.getId());
                        financeInvoiceBaseMapper.insert(financeInvoiceBase);
                    }
                });
            }else{
                financeInvoiceBaseMapper.delete(new QueryWrapper<FinanceInvoiceBase>().lambda()
                        .eq(FinanceInvoiceBase::getInvoiceId,financeInvoice.getId()));
            }
            // 附件保存
            if(CollectionUtil.isNotEmpty(financeInvoiceDTO.getWorkAttachmentDtoList())){
                List<String> delIds = financeInvoiceDTO.getWorkAttachmentDtoList().stream().distinct().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return true;
                    }
                    return false;
                }).map(WorkAttachmentInfo::getId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(delIds)){
                    SpringUtil.getBean ( IWorkAttachmentApi.class ).deleteByAttachmentIdNotInIds(financeInvoice.getId(),delIds);
                }else{
                    SpringUtil.getBean ( IWorkAttachmentApi.class ).deleteByAttachmentId(financeInvoice.getId());
                }
                //获取当前登录人信息
                UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByToken(TokenProvider.getCurrentToken());
                AtomicInteger j = new AtomicInteger(1);
                List<WorkAttachmentInfo> collect = financeInvoiceDTO.getWorkAttachmentDtoList().stream().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return false;
                    }
                    return true;
                }).collect(Collectors.toList());
                collect.forEach(item->{
                    this.saveFiles(item,financeInvoice.getId(),userDTO,j);
                    j.getAndIncrement();
                });
            }else{
                SpringUtil.getBean ( IWorkAttachmentApi.class ).deleteByAttachmentId(financeInvoice.getId());
            }
            // 发票明细保存
            if(CollectionUtil.isNotEmpty(financeInvoiceDTO.getFinanceInvoiceDetailDTOList())){
                List<String> delIds = financeInvoiceDTO.getFinanceInvoiceDetailDTOList().stream().distinct().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return true;
                    }
                    return false;
                }).map(FinanceInvoiceDetailDTO::getId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(delIds)){
                    financeInvoiceDetailMapper.delete(new QueryWrapper<FinanceInvoiceDetail>().lambda()
                            .eq(FinanceInvoiceDetail::getInvoiceId,financeInvoice.getId())
                            .notIn(FinanceInvoiceDetail::getId,delIds));
                }else{
                    financeInvoiceDetailMapper.delete(new QueryWrapper<FinanceInvoiceDetail>().lambda().eq(FinanceInvoiceDetail::getInvoiceId,financeInvoice.getId()));
                }
                financeInvoiceDTO.getFinanceInvoiceDetailDTOList().stream().forEach(item->{
                    FinanceInvoiceDetail financeInvoiceDetail = FinanceInvoiceDetailWrapper.INSTANCE.toEntity(item);
                    if(StringUtils.isNotBlank(financeInvoiceDetail.getId())){
                        financeInvoiceDetailMapper.updateById(financeInvoiceDetail);
                    }else{
                        financeInvoiceDetail.setInvoiceId(financeInvoice.getId());
                        financeInvoiceDetailMapper.insert(financeInvoiceDetail);
                    }
                });
            }else{
                financeInvoiceDetailMapper.delete(new QueryWrapper<FinanceInvoiceDetail>().lambda().eq(FinanceInvoiceDetail::getInvoiceId,financeInvoice.getId()));
            }
            // 收款明细保存
            if(CollectionUtil.isNotEmpty(financeInvoiceDTO.getFinanceInvoiceReceivablesDTOList())){
                List<String> delIds = financeInvoiceDTO.getFinanceInvoiceReceivablesDTOList().stream().distinct().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return true;
                    }
                    return false;
                }).map(FinanceInvoiceReceivablesDTO::getId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(delIds)){
                    financeInvoiceReceivablesMapper.delete(new QueryWrapper<FinanceInvoiceReceivables>().lambda()
                            .eq(FinanceInvoiceReceivables::getInvoiceId,financeInvoice.getId())
                            .notIn(FinanceInvoiceReceivables::getId,delIds));
                }else{
                    financeInvoiceReceivablesMapper.delete(new QueryWrapper<FinanceInvoiceReceivables>().lambda().eq(FinanceInvoiceReceivables::getInvoiceId,financeInvoice.getId()));
                }
                financeInvoiceDTO.getFinanceInvoiceReceivablesDTOList().stream().forEach(item->{
                    FinanceInvoiceReceivables financeInvoiceReceivables = FinanceInvoiceReceivablesWrapper.INSTANCE.toEntity(item);
                    if(StringUtils.isNotBlank(financeInvoiceReceivables.getId())){
                        financeInvoiceReceivablesMapper.updateById(financeInvoiceReceivables);
                    }else{
                        financeInvoiceReceivables.setInvoiceId(financeInvoice.getId());
                        financeInvoiceReceivablesMapper.insert(financeInvoiceReceivables);
                    }
                });
            }else{
                financeInvoiceReceivablesMapper.delete(new QueryWrapper<FinanceInvoiceReceivables>().lambda().eq(FinanceInvoiceReceivables::getInvoiceId,financeInvoice.getId()));
            }
            // 作废信息保存
            if(ObjectUtil.isNotEmpty(financeInvoiceDTO.getFinanceInvoiceInvalidDTO())){
                FinanceInvoiceInvalid financeInvoiceInvalid = FinanceInvoiceInvalidWrapper.INSTANCE.toEntity(financeInvoiceDTO.getFinanceInvoiceInvalidDTO());
                if(StringUtils.isNotBlank(financeInvoiceInvalid.getId())){
                    financeInvoiceInvalidMapper.update(financeInvoiceInvalid,
                            new QueryWrapper<FinanceInvoiceInvalid>().lambda().eq(FinanceInvoiceInvalid::getId,financeInvoiceInvalid.getId()));
                }else{
                    financeInvoiceInvalid.setInvalidStatus("0");
                    financeInvoiceInvalid.setInvoiceId(financeInvoice.getId());
                    financeInvoiceInvalidMapper.insert(financeInvoiceInvalid);
                }
            }else{
                financeInvoiceInvalidMapper.delete(new QueryWrapper<FinanceInvoiceInvalid>().lambda().eq(FinanceInvoiceInvalid::getInvoiceId,financeInvoice.getId()));
                FinanceInvoiceInvalid financeInvoiceInvalid = new FinanceInvoiceInvalid();
                financeInvoiceInvalid.setInvalidStatus("0");
                financeInvoiceInvalid.setInvoiceId(financeInvoice.getId());
                financeInvoiceInvalidMapper.insert(financeInvoiceInvalid);
            }
        }

        //蓝票
        if("1".equals(isOms)){
            FinanceInvoiceDTO dto = queryById(financeInvoice.getId());
            new ApprovalThread(dto, "21").start();
        }
        //红票
        if("2".equals(isOms)){
            FinanceInvoiceDTO dto = queryById(financeInvoice.getId());
            new RedApprovalThread(dto,financeInvoiceDTO.getInvoiceNumberStr(), "21").start();
        }

        //钉钉通知
        if(isDDNotice){
            //根据字典判断是否钉钉通知用户
            String realTimeDictValue = SpringUtil.getBean(IDictApi.class).getRealTimeDictValue("是否接收钉钉通知");
            if(StringUtils.isNotBlank(realTimeDictValue) && realTimeDictValue.equals("1")){
                FinanceInvoiceDTO dto = queryById(financeInvoice.getId());
                addDingtalkNotice(dto);
            }
        }
        return financeInvoice.getId();
    }

    public String addDingtalkNotice(FinanceInvoiceDTO dto){
        dingTalkUtil.addDingtalkNotice(dto);
        return "ok";
    }


    /**
     * 判断是否开票逻辑
     */

    public String handleDoInvoice(FinanceInvoiceDTO financeInvoiceDTO){
        boolean OMS_ENABLED = omsEnabled;
        //保存数据结束，触发开票接口
        if(OMS_ENABLED){
            if("5".equals(financeInvoiceDTO.getStatus())){
                BigDecimal account = new BigDecimal(financeInvoiceDTO.getAccount());
                if (account.compareTo(BigDecimal.ZERO) > 0) {
                    //返回开蓝票标记
                    return "1";
                }else{
                    //先获取对应红冲发票的数电票  票号
                    //查询关联红冲发票的开票号
                    if("1".equals(financeInvoiceDTO.getRedInvoiceFlag())){
                        if(StringUtils.isBlank(financeInvoiceDTO.getInvoiceNumberStr())){
                            if(StringUtils.isNotBlank(financeInvoiceDTO.getRedInvoiceRelevancyId())){
                                String invoiceNumberStr = this.getInvoiceNumberStr(financeInvoiceDTO.getRedInvoiceRelevancyId());
                                financeInvoiceDTO.setInvoiceNumberStr(invoiceNumberStr);
                            }
                        }
                        String invoiceNumber = financeInvoiceDTO.getInvoiceNumberStr();
                        //判断 如果发票小于10位，则表示为老发票红冲，需要按照老方法进行处理
                        if (invoiceNumber == null || StringUtils.isBlank(invoiceNumber) || invoiceNumber.length() < 10) {
                            OMS_ENABLED = false;
                        }
                        if(OMS_ENABLED && StringUtils.isBlank(invoiceNumber)){
                            throw new RuntimeException("红冲发票号不存在，无法进行红冲！");
                        }
                    }
                    if(OMS_ENABLED){
                        //返回开红票标记
                        return "2";
                    }
                }
            }
        }
        return "0";
    }

    public String getInvoiceNumberStr(String invoiceId) {
        return financeInvoiceMapper.getInvoiceNumberStr(invoiceId);
    }

    public ResponseEntity saveInvoice(FinanceInvoiceDTO financeInvoiceDTO) throws Exception{
        this.saveForm(financeInvoiceDTO);
        return ResponseEntity.ok("保存成功");
    }

    public String saveFormInvalid(FinanceInvoiceDTO financeInvoiceDTO) throws Exception{
        String invoiceId = this.saveForm(financeInvoiceDTO);
        List<FinanceInvoiceInvalid> financeInvoiceInvalids = financeInvoiceInvalidMapper.selectList(
                new QueryWrapper<FinanceInvoiceInvalid>().lambda().eq(FinanceInvoiceInvalid::getInvoiceId, invoiceId));
        return financeInvoiceInvalids.get(0).getId();
    }

    /**
     * 添加附件
     * @param item 要添加的附件信息
     * @param id 附件id: attachmentId
     * @param userDTO 当前登录人信息
     * @param j 排序序号
     */
    public void saveFiles(WorkAttachmentInfo item,String id,UserDTO userDTO,AtomicInteger j){
        WorkAttachmentInfo i = new WorkAttachmentInfo();
        //包含了url、size、name
        i.setId(UUID.randomUUID().toString().replace("-", ""));
        i.setCreateTime(new Date());
        i.setUpdateTime(new Date());
        i.setDelFlag(0);
        i.setUrl(item.getUrl());
        //文件类型处理
        String fileName = item.getName();
        List<String> strings = Arrays.asList(fileName.split("\\."));
        // 检查文件名是否有后缀
        if (CollectionUtil.isNotEmpty(strings) && strings.size() > 1) {
            // 获取最后一个部分作为文件类型
            i.setType(strings.get(strings.size() - 1));
        } else {
            // 如果没有后缀或文件名无效，设置一个默认类型或空
            i.setType("");
        }
        i.setAttachmentId(id);
        i.setAttachmentName(item.getName());
        i.setAttachmentFlag("invoice");
        i.setFileSize(item.getSize());
        i.setSort(j.get());
        Map<String,String> map = new HashMap<>();
        String workAttachment = JSON.toJSONString((i));
        String userDTOInfo = JSON.toJSONString((userDTO));
        map.put("workAttachment",workAttachment);
        map.put("userDTO",userDTOInfo);
        SpringUtil.getBean ( IWorkAttachmentApi.class ).insertWorkAttachment(map);
    }

    public ResponseEntity deleteByIds(String ids) {
        String idArray[] =ids.split(",");
        this.removeByIds (Lists.newArrayList (idArray));
        return ResponseEntity.ok ("删除成功");
    }

    public Boolean queryByNumber(String number, String id) {
        List<FinanceInvoiceDetail> financeInvoiceDetails = financeInvoiceDetailMapper.selectList(new QueryWrapper<FinanceInvoiceDetail>().lambda()
                .eq(FinanceInvoiceDetail::getNumber, number)
                .eq(FinanceInvoiceDetail::getDelFlag, '0')
                .ne(StringUtils.isNotBlank(id),FinanceInvoiceDetail::getId,id));
        if (CollectionUtil.isNotEmpty(financeInvoiceDetails)) {
            return true;
        }
        return false;
    }

    public String queryIdByInvalidId(String id) {
        FinanceInvoiceInvalid financeInvoiceInvalid = financeInvoiceInvalidMapper.selectById(id);
        return financeInvoiceInvalid.getInvoiceId();
    }

    public String updateStatusById(FinanceInvoiceDTO financeInvoiceDTO) {
        FinanceInvoice financeInvoice = FinanceInvoiceWrapper.INSTANCE.toEntity(financeInvoiceDTO);
        financeInvoiceMapper.update(financeInvoice, new QueryWrapper<FinanceInvoice>().lambda().eq(FinanceInvoice::getId, financeInvoice.getId()));
        return "操作成功";
    }

    public String isReceivables(FinanceInvoiceDTO financeInvoiceDTO) {
        FinanceInvoice financeInvoice = FinanceInvoiceWrapper.INSTANCE.toEntity(financeInvoiceDTO);
        financeInvoice.setReceivablesDate(new Date());
        financeInvoiceMapper.update(financeInvoice, new QueryWrapper<FinanceInvoice>().lambda().eq(FinanceInvoice::getId, financeInvoice.getId()));
        return "操作成功";
    }

    public String importDecide(List<FinanceInvoiceDetailDTO> list, ArrayList<FinanceInvoiceDetailDTO> arrayList, HashMap<String,String> hashMap){
        for (FinanceInvoiceDetailDTO financeInvoiceDetailDTO : list) {
            if(ObjectUtil.isEmpty(financeInvoiceDetailDTO)){
                continue;
            }

            if(StringUtils.isBlank(financeInvoiceDetailDTO.getNumber())){
                return "文件中有发票号为空，请重新填写";
            }
            if(StringUtils.isNotBlank(financeInvoiceDetailDTO.getNumber())){
                try {
                    Integer integer = new Integer(financeInvoiceDetailDTO.getNumber());
                    if (integer < 0) {
                        return "文件中有发票号填写不正确，请重新填写";
                    }
                }catch (Exception e){
                    return "文件中有发票号填写不正确，请重新填写";
                }
                List<FinanceInvoiceDetail> financeInvoiceDetailList = financeInvoiceDetailMapper.selectList(new QueryWrapper<FinanceInvoiceDetail>().eq("number", financeInvoiceDetailDTO.getNumber()));
                if(CollectionUtil.isNotEmpty(financeInvoiceDetailList)){
                    return "文件中有发票号已在系统中存在，请重新填写";
                }
            }
//            if (StringUtils.isBlank(financeInvoiceDetailDTO.getRate())) {
//                return "文件中有税率为空，请重新填写";
//            }
            if (StringUtils.isNotBlank(financeInvoiceDetailDTO.getRate())) {
                try {
                    if ((new BigDecimal(financeInvoiceDetailDTO.getRate())).compareTo(new BigDecimal(1)) == -1
                            || (new BigDecimal(financeInvoiceDetailDTO.getRate())).compareTo(new BigDecimal(100)) == 1) {
                        return "文件中有税率填写不正确，请重新填写";
                    }
                }catch (Exception e){
                    return "文件中有税率填写不正确，请重新填写";
                }
            }
            if (StringUtils.isBlank(financeInvoiceDetailDTO.getAccount())) {
                return "文件中有开票金额为空，请重新填写";
            } else {
                try {
                    financeInvoiceDetailDTO.setAccount(new BigDecimal(financeInvoiceDetailDTO.getAccount()).toString());
                }catch (Exception e){
                    return "文件中有开票金额填写不正确，请重新填写";
                }
            }

            hashMap.put(financeInvoiceDetailDTO.getNumber(),null);

            arrayList.add(financeInvoiceDetailDTO);
        }
        return null;
    }

    /**
     * 查询开票时间距今超过1个月的开票数据
     * @return
     */
    public List<FinanceInvoiceDTO> getExceedFinance() {
        //查询开票时间为空的，或者是否开票为否的  开票时间距今超过1个月的开票数据
        List<FinanceInvoiceDTO> list=financeInvoiceMapper.getExceedFinance();
        //将红字发票及红字发票关联的发票进行剔除
        ArrayList<String> redReveId = new ArrayList<>();
        for (FinanceInvoiceDTO financeInvoiceDTO : list) {
            if (ObjectUtils.isNotEmpty(financeInvoiceDTO.getRedInvoiceFlag()) && "1".equals(financeInvoiceDTO.getRedInvoiceFlag())){
                redReveId.add(financeInvoiceDTO.getId());
                redReveId.add(financeInvoiceDTO.getRedInvoiceRelevancyId());
            }
        }
        //将redReveId中存放的id从list中进行去除
        List<FinanceInvoiceDTO> filteredList = list.stream()
                .filter(dto -> !redReveId.contains(dto.getId()))
                .collect(Collectors.toList());

        return filteredList;
    }

    /**
     * 查询红字发票数据
     * @param page
     * @param financeInvoiceDTO
     * @param s
     * @return
     */
    public IPage<FinanceInvoiceDTO> findRedList(Page<FinanceInvoiceDTO> page, FinanceInvoiceDTO financeInvoiceDTO, String s) throws Exception {
        QueryWrapper<FinanceInvoice> queryWrapper = QueryWrapperGenerator.buildQueryCondition ( FinanceInvoiceWrapper.INSTANCE.toEntity(financeInvoiceDTO), FinanceInvoice.class );
        queryWrapper.eq("fi.del_flag","0");
        queryWrapper.orderByDesc("fi.create_time");
        //判定开票金额大于等于0 的发票信息
        queryWrapper.ge("fi.account","0");
        ArrayList<String> searchIdList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        AtomicInteger checkNum = new AtomicInteger();
        if (ObjectUtil.isNotEmpty(financeInvoiceDTO)) {
            if (StringUtils.isNotBlank(financeInvoiceDTO.getNumber())) {
                List<FinanceInvoiceDetail> financeInvoiceDetails = financeInvoiceDetailMapper.selectList(new LambdaQueryWrapper<FinanceInvoiceDetail>().like(FinanceInvoiceDetail::getNumber, financeInvoiceDTO.getNumber()));
                List<String> ids = financeInvoiceDetails.stream().distinct().map(FinanceInvoiceDetail::getInvoiceId).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(ids)) {
                    return new Page<FinanceInvoiceDTO>();
                }else{
                    if (CollectionUtil.isNotEmpty(searchIdList)){
                        List<String> newSearchIdList = getSearchList(searchIdList,ids);
                        searchIdList = new ArrayList<String>();
                        for (String item : newSearchIdList) {
                            searchIdList.add(item);
                        }
                    }else{
                        if (checkNum.get() > 0){
                            return new Page<FinanceInvoiceDTO>();
                        }else{
                            for (String item : ids) {
                                searchIdList.add(item);
                            }
                        }
                    }
                    checkNum.getAndIncrement();
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getAccountBegin())&&StringUtils.isNotBlank(financeInvoiceDTO.getAccountEnd())) {
                List<FinanceInvoice> financeInvoices = financeInvoiceMapper.selectList(new LambdaQueryWrapper<FinanceInvoice>()
                        .between(FinanceInvoice::getAccount, new BigDecimal(financeInvoiceDTO.getAccountBegin()), new BigDecimal(financeInvoiceDTO.getAccountEnd())));
                List<String> ids = financeInvoices.stream().distinct().map(FinanceInvoice::getId).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(ids)) {
                    return new Page<FinanceInvoiceDTO>();
                }else{
                    if (CollectionUtil.isNotEmpty(searchIdList)){
                        List<String> newSearchIdList = getSearchList(searchIdList,ids);
                        searchIdList = new ArrayList<String>();
                        for (String item : newSearchIdList) {
                            searchIdList.add(item);
                        }
                    }else{
                        if (checkNum.get() > 0){
                            return new Page<FinanceInvoiceDTO>();
                        }else{
                            for (String item : ids) {
                                searchIdList.add(item);
                            }
                        }
                    }
                    checkNum.getAndIncrement();
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getBillingDateBegin())&&StringUtils.isNotBlank(financeInvoiceDTO.getBillingDateEnd())) {
                List<FinanceInvoice> financeInvoices = financeInvoiceMapper.selectList(new LambdaQueryWrapper<FinanceInvoice>()
                        .between(FinanceInvoice::getBillingDate, sdf.parse(financeInvoiceDTO.getBillingDateBegin()), sdf.parse(financeInvoiceDTO.getBillingDateEnd())));
                List<String> ids = financeInvoices.stream().distinct().map(FinanceInvoice::getId).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(ids)) {
                    return new Page<FinanceInvoiceDTO>();
                }else{
                    if (CollectionUtil.isNotEmpty(searchIdList)){
                        List<String> newSearchIdList = getSearchList(searchIdList,ids);
                        searchIdList = new ArrayList<String>();
                        for (String item : newSearchIdList) {
                            searchIdList.add(item);
                        }
                    }else{
                        if (checkNum.get() > 0){
                            return new Page<FinanceInvoiceDTO>();
                        }else{
                            for (String item : ids) {
                                searchIdList.add(item);
                            }
                        }
                    }
                    checkNum.getAndIncrement();
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getRemittanceDateBegin())&&StringUtils.isNotBlank(financeInvoiceDTO.getRemittanceDateEnd())) {
                List<FinanceInvoice> financeInvoices = financeInvoiceMapper.selectList(new LambdaQueryWrapper<FinanceInvoice>()
                        .between(FinanceInvoice::getReceivablesDate, sdf.parse(financeInvoiceDTO.getRemittanceDateBegin()), sdf.parse(financeInvoiceDTO.getRemittanceDateEnd())));
                List<String> ids = financeInvoices.stream().distinct().map(FinanceInvoice::getId).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(ids)) {
                    return new Page<FinanceInvoiceDTO>();
                }else{
                    if (CollectionUtil.isNotEmpty(searchIdList)){
                        List<String> newSearchIdList = getSearchList(searchIdList,ids);
                        searchIdList = new ArrayList<String>();
                        for (String item : newSearchIdList) {
                            searchIdList.add(item);
                        }
                    }else{
                        if (checkNum.get() > 0){
                            return new Page<FinanceInvoiceDTO>();
                        }else{
                            for (String item : ids) {
                                searchIdList.add(item);
                            }
                        }
                    }
                    checkNum.getAndIncrement();
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getProgramId())||StringUtils.isNotBlank(financeInvoiceDTO.getProgramName())) {
                if (StringUtils.isNotBlank(financeInvoiceDTO.getProgramId())){
                    List<FinanceInvoiceBase> financeInvoiceBaseList = financeInvoiceBaseMapper.selectList(new LambdaQueryWrapper<FinanceInvoiceBase>()
                            .eq(FinanceInvoiceBase::getProgramId,financeInvoiceDTO.getProgramId()));
                    List<String> ids = financeInvoiceBaseList.stream().distinct().map(FinanceInvoiceBase::getInvoiceId).collect(Collectors.toList());
                    if(CollectionUtil.isEmpty(ids)) {
                        return new Page<FinanceInvoiceDTO>();
                    }else{
                        if (CollectionUtil.isNotEmpty(searchIdList)){
                            List<String> newSearchIdList = getSearchList(searchIdList,ids);
                            searchIdList = new ArrayList<String>();
                            for (String item : newSearchIdList) {
                                searchIdList.add(item);
                            }
                        }else{
                            if (checkNum.get() > 0){
                                return new Page<FinanceInvoiceDTO>();
                            }else{
                                for (String item : ids) {
                                    searchIdList.add(item);
                                }
                            }
                        }
                        checkNum.getAndIncrement();
                    }
                }else{
                    List<FinanceInvoiceBase> financeInvoiceBaseList = financeInvoiceBaseMapper.selectList(new LambdaQueryWrapper<FinanceInvoiceBase>()
                            .like(FinanceInvoiceBase::getProgramName,financeInvoiceDTO.getProgramName()));
                    List<String> ids = financeInvoiceBaseList.stream().distinct().map(FinanceInvoiceBase::getInvoiceId).collect(Collectors.toList());
                    if(CollectionUtil.isEmpty(ids)) {
                        return new Page<FinanceInvoiceDTO>();
                    }else{
                        if (CollectionUtil.isNotEmpty(searchIdList)){
                            List<String> newSearchIdList = getSearchList(searchIdList,ids);
                            searchIdList = new ArrayList<String>();
                            for (String item : newSearchIdList) {
                                searchIdList.add(item);
                            }
                        }else{
                            if (checkNum.get() > 0){
                                return new Page<FinanceInvoiceDTO>();
                            }else{
                                for (String item : ids) {
                                    searchIdList.add(item);
                                }
                            }
                        }
                        checkNum.getAndIncrement();
                    }
                }
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getOperator())){
                queryWrapper.eq("su.id",financeInvoiceDTO.getOperator()).or().like("su.name",financeInvoiceDTO.getOperator());
            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getReconciliationPeopleName())) {
//                List<User> users = SpringUtil.getBean ( IUserApi.class ).selectListByName(financeInvoiceDTO.getReconciliationPeopleName());
//                List<String> userIdList = users.stream().distinct().map(User::getId).collect(Collectors.toList());
//                if (CollectionUtil.isNotEmpty(userIdList)) {
//                    queryWrapper.in("fi.reconciliation_people",userIdList);
//                } else {
//                    return new Page<FinanceInvoiceDTO>();
//                }
                queryWrapper.like("su1.name",financeInvoiceDTO.getReconciliationPeopleName());

            }
            if (StringUtils.isNotBlank(financeInvoiceDTO.getOperatorOffice())){
                List<User> userList = SpringUtil.getBean ( IUserApi.class ).getUserByOfficeAll(financeInvoiceDTO.getOperatorOffice());
                if (CollectionUtil.isNotEmpty(userList)) {
                    List<String> userIdList = userList.stream().distinct().map(User::getId).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(userIdList)) {
                        queryWrapper.in("fi.create_by_id",userIdList);
                    } else {
                        return new Page<FinanceInvoiceDTO>();
                    }
                } else {
                    return new Page<FinanceInvoiceDTO>();
                }
            }
        }
        if (CollectionUtil.isNotEmpty(searchIdList)){
            List<String> ids = searchIdList.stream().distinct().collect(Collectors.toList());
            queryWrapper.in("fi.id",ids);
        } else{
            if (checkNum.get() > 0) {
                return new Page<FinanceInvoiceDTO>();
            }
        }
        if (StringUtils.isNotBlank(financeInvoiceDTO.getName())){
            queryWrapper.like("fi.name",financeInvoiceDTO.getName());
        }
        //开票类型筛选
        if (StringUtils.isNotBlank(financeInvoiceDTO.getBillingType())){
            queryWrapper.eq("fi.billing_type",financeInvoiceDTO.getBillingType());
        }

        IPage<FinanceInvoiceDTO> pageList = financeInvoiceMapper.findRedList(page, queryWrapper);
        pageList.getRecords().stream().forEach(item ->{
            // 发票申请
            if (StringUtils.isNotBlank(item.getTaskId()) && StringUtils.isNotBlank(item.getStatus())) {
                if ("2".equals(item.getStatus())) { // “审核中”的数据要获取数据审核人
                    item.setAuditUserIds(flowTaskService.getTaskAuditUsers(item.getTaskId()));  // 获取数据审核人
                }
            }
            // 发票作废
            if (StringUtils.isNotBlank(item.getTaskIdInvalid()) && StringUtils.isNotBlank(item.getStatus())) {
                if ("6".equals(item.getStatus())) { // “审核中”的数据要获取数据审核人
                    item.setAuditUserIdsInvalid(flowTaskService.getTaskAuditUsers(item.getTaskIdInvalid()));  // 获取数据审核人
                }
            }

            if(StringUtils.isNotBlank(item.getBillingType()) && "2".equals(item.getBillingType()) && StringUtils.isNotBlank(item.getName())){
                item.setBillingWorkplaceReal(item.getName());
            }

        });
        return pageList;
    }

    /**
     * 文件添加到work_attachment表中
     * @param uploadResult
     * @param workInvoice
     * @param type
     * @param sort
     */
    public void fileUploadOnAttachment(Map<String, Object> uploadResult, FinanceInvoiceDTO workInvoice, String type, String sort){
        // 解析Map返回结果（核心适配点）
        boolean isUploadSuccess = (boolean) uploadResult.get("success");
        String ossFilePath = (String) uploadResult.get("ossFilePath");
        Long fileSize = (Long) uploadResult.get("fileSize"); // 从Map获取file.size的字节数

        //上传成功判断（替换原StringUtils.isNotBlank(ossFilePath)）
        if (isUploadSuccess && StringUtils.isNotBlank(ossFilePath)) {
            // 检查是否以"/"开头，若不是则添加
            if (!ossFilePath.startsWith("/")) {
                ossFilePath = "/" + ossFilePath;
            }
            // 5. 构建附件表实体（保留你的核心业务逻辑，调整fileSize赋值）
            WorkAttachmentInfo workattachment = new WorkAttachmentInfo();
            workattachment.setDelFlag(0);
            workattachment.setUrl(ossFilePath); // 存入OSS路径
            workattachment.setType(type); // 文件类型
            workattachment.setName(workInvoice.getNo() + "." + type); // 附件名称
            workattachment.setAttachmentName(workInvoice.getNo() + "." + type); // 附件名称
            workattachment.setAttachmentFlag("PG_OMS_invoice_file"); // 附件标识
            workattachment.setSize(String.valueOf(fileSize)); // 改用Map中的文件大小（上传后本地文件已删除，原f.length()可能失效）
            workattachment.setAttachmentId(workInvoice.getId()); // 关联发票ID
            workattachment.setId(UUID.randomUUID().toString().replace("-", "")); // 主键ID

            //校验数据库中是否已存在该附件（避免重复插入）

            List<WorkAttachmentInfo> existAttachments =   SpringUtil.getBean ( IWorkAttachmentApi.class ).getByAttachmentIdAndUrlAndAttachmentFlag(workattachment);
            if (CollectionUtils.isEmpty(existAttachments)) { // 建议用CollectionUtils.isEmpty判断空集合，更安全
                Map<String, String> map = new HashMap<>();
                String workAttachmentDtoInfo = JSON.toJSONString(workattachment);
                AtomicInteger sortinfo = new AtomicInteger(Integer.parseInt(sort));
                String userDTOInfo = JSON.toJSONString(workInvoice.getCreateBy());
                String attachmentId = workInvoice.getId();
                String attachmentFlag = "PG_OMS_invoice_file";
                String sortInfo = Integer.toString(sortinfo.get());
                map.put("workAttachmentDtoInfo", workAttachmentDtoInfo);
                map.put("userDTOInfo", userDTOInfo);
                map.put("attachmentId", attachmentId);
                map.put("attachmentFlag", attachmentFlag);
                map.put("sortInfo", sortInfo);
                String fileId = SpringUtil.getBean(IWorkAttachmentApi.class).saveFile(map);
            }
        }
    }

    /**
     * OMS发票开具失败进行的提示方法操作
     * @param workInvoice
     * @param errorMessage
     * @param informType
     * @return
     */
    @Transactional(readOnly = false)
    public  Boolean handleInvoiceRetryAllFail(FinanceInvoiceDTO workInvoice, String errorMessage, String informType){
        Boolean isSuccess = false;

        //需要修改流程完成通知
        //审核完成提示框
        List<UserDTO> users = new ArrayList<>();
        users.add(workInvoice.getCreateBy());

        //项目名称获取
        List<String> projectNameList = getProjectNameList(workInvoice);
        String projectNameStr = String.join(",", projectNameList);
        projectNameStr = projectNameStr.length() > 900
                ? projectNameStr.substring(0, 900)
                : projectNameStr;

        String str = "发票申请编号："+workInvoice.getNo() + "发票金额：" + workInvoice.getAccount() + "(元)。项目【"+ projectNameStr +"】发票申请失败,请核实后重新发起。失败原因：" + errorMessage;

        String title = str;
        UserDTO user = SpringUtil.getBean ( IUserApi.class ).getById(workInvoice.getCreateBy().getId());

        //通知开票发起人和发票管理员
        RoleDTO roleDTO = SpringUtil.getBean(IRoleApi.class).getRoleDTOByName2("发票管理员");
        List<UserDTO> notifiedPartyUsers =SpringUtil.getBean(IUserApi.class).findListByRoleId(roleDTO.getId());
        //发票管理员
        notifiedPartyUsers.add(user);
        if (StringUtils.isNotBlank(workInvoice.getStatus()) && workInvoice.getStatus().equals("3")){
            for (UserDTO notifiedPartyUser : notifiedPartyUsers) {
                    sendNotify(notifiedPartyUser,workInvoice.getProcessDefinitionId(),workInvoice.getProcInsId(),title);
                //发起短信通知，用于通知开票人
                //查询开票人员的手机号
                if (StringUtils.isNotBlank(user.getMobile()) && mobilePattern.matcher(user.getMobile().trim()).matches() ) {
                    //验证手机号是否已经注册
                    if(StringUtils.isNotBlank(user.getMobile())){
                        Map<String,Object> result = null;
                        try{
                            //调用工具类返回结果
                            result = SpringUtil.getBean ( IUserApi.class ).sendEntryRandomCodesByInvoice(notifiedPartyUser.getMobile(),unitName,workInvoice.getNo(),"开票失败",smsCode);
                            Integer statusCode = (Integer) result.get("statusCode");
                            if (200 == statusCode) {
                                System.out.println("短信发送成功!");
                            } else if (10001 == statusCode) {
                                String message = (String) result.get("message");
                                System.out.println(message);
                            }else if(10002 == statusCode){
                                System.out.println("账户短信量余额不足，请联系管理员进行充值!");
                            }else if(10003 == statusCode){
                                System.out.println("手机号获取验证码次数已达每日上限!");
                            } else {
                                System.out.println("短信发送失败，错误代码：101，请联系管理员!");
                            }
                        }catch (Exception e){
                            System.out.println("阿里云发送短信失败。失败原因为：" + e.getMessage());
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        isSuccess = true;
        return isSuccess;
    }


    /**
     * OMS开票开票成功后对数据进行处理
     * @param workInvoice
     * @param invoiceInfo
     * @param informType
     * @return
     */
    @Transactional(readOnly = false)
    public  Boolean updateOmsByIdOnDown(FinanceInvoiceDTO workInvoice, OMSInvoiceDetailInfo invoiceInfo, String informType) {
        String uploadPrefix = "pg";
        Boolean isSuccess = false;
        workInvoice.setOmsEinVno(invoiceInfo.getAllEinVno());
        if(StringUtils.isNotBlank(invoiceInfo.getOfdUrl())){
            //先将文件下载到本地
            String ofdLocalFilePath = FileHandlingUtil.downloadFileToSpecifiedPath(invoiceInfo.getOfdUrl(), workInvoice.getNo() + ".ofd");
            //如果文件下载下来了，并且返回值正常，则此处需要对文件进行上传到阿里云操作
            if(StringUtils.isNotBlank(ofdLocalFilePath)){
                // 调用上传方法，接收Map类型返回值（替换原String类型接收）
                Map<String, Object> uploadResult = FileHandlingUtil.fileUpload(ofdLocalFilePath, workInvoice.getNo(),uploadPrefix);
                fileUploadOnAttachment(uploadResult,workInvoice, "ofd", "1");
            }
        }
        workInvoice.setOmsOfdUrl(invoiceInfo.getOfdUrl());

        if(StringUtils.isNotBlank(invoiceInfo.getPdfUrl())){
            //先将文件下载到本地
            String ofdLocalFilePath = FileHandlingUtil.downloadFileToSpecifiedPath(invoiceInfo.getPdfUrl(), workInvoice.getNo() + ".pdf");
            //如果文件下载下来了，并且返回值正常，则此处需要对文件进行上传到阿里云操作
            if(StringUtils.isNotBlank(ofdLocalFilePath)){
                // 调用上传方法，接收Map类型返回值（替换原String类型接收）
                Map<String, Object> uploadResult = FileHandlingUtil.fileUpload(ofdLocalFilePath, workInvoice.getNo(),uploadPrefix);
                fileUploadOnAttachment(uploadResult,workInvoice, "pdf", "2");
            }
        }
        workInvoice.setOmsPdfUrl(invoiceInfo.getPdfUrl());
        if(StringUtils.isNotBlank(invoiceInfo.getXmlUrl())){
            //先将文件下载到本地
            String ofdLocalFilePath = FileHandlingUtil.downloadFileToSpecifiedPath(invoiceInfo.getXmlUrl(), workInvoice.getNo() + ".xml");
            //如果文件下载下来了，并且返回值正常，则此处需要对文件进行上传到阿里云操作
            if(StringUtils.isNotBlank(ofdLocalFilePath)){
                // 调用上传方法，接收Map类型返回值（替换原String类型接收）
                Map<String, Object> uploadResult = FileHandlingUtil.fileUpload(ofdLocalFilePath, workInvoice.getNo(),uploadPrefix);
                fileUploadOnAttachment(uploadResult,workInvoice, "xml", "3");
            }
        }
        workInvoice.setOmsXmlUrl(invoiceInfo.getXmlUrl());
        workInvoice.setStatus("5");

        //修改结果
        updateOmsUrlById(workInvoice);
        //还需要修改work_invoice_detail表中的对应发票编号（number）值
        FinanceInvoiceDetail workInvoiceDetail = new FinanceInvoiceDetail();
        workInvoiceDetail.setInvoiceId(workInvoice.getId());
        workInvoiceDetail.setNumber(invoiceInfo.getAllEinVno());
        financeInvoiceDetailMapper.updateNumberById(workInvoiceDetail);

        //需要修改流程完成通知
        //审核完成提示框
        List<UserDTO> users = new ArrayList<>();
        users.add(workInvoice.getCreateBy());

        UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getById(workInvoice.getCreateBy().getId());
        OfficeDTO office = userDTO.getOfficeDTO();
        String userName = userDTO.getName();

        //项目名称获取
        List<String> projectNameList = getProjectNameList(workInvoice);
        String projectNameStr = String.join(",", projectNameList);
        projectNameStr = projectNameStr.length() > 900
                ? projectNameStr.substring(0, 900)
                : projectNameStr;

        String str = "发票金额：" + workInvoice.getAccount() + "(元)。项目【"+ projectNameStr +"】发票申请通过，发票申请编号："+workInvoice.getNo() + ",创建人："+userName+",所属部门:"+office.getName();
        if(null != workInvoice.getBillingWorkplaceRealId()){
            str = str + ",实际开票单位："+workInvoice.getBillingWorkplaceReal();
        }

        String title = str;

        //通知开票发起人
        if (StringUtils.isNotBlank(workInvoice.getStatus()) && !workInvoice.getStatus().equals("3")){
            workInvoice.setStatus("5");
            sendNotify(userDTO,workInvoice.getProcessDefinitionId(),workInvoice.getProcInsId(),title);
        }

        //发起短信通知，用于通知开票人
        if(workInvoice.getIsSmsNotice().equals("1")) {
            if (StringUtils.isNotBlank(userDTO.getMobile()) && mobilePattern.matcher(userDTO.getMobile().trim()).matches()) {
                //验证手机号是否已经注册
                if (StringUtils.isNotBlank(userDTO.getMobile())) {
                    Map<String, Object> result = null;
                    try {
                        //调用工具类返回结果
                        result = SpringUtil.getBean(IUserApi.class).sendEntryRandomCodesByInvoice(userDTO.getMobile(), unitName, workInvoice.getNo(), "开票成功", smsCode);
                        Integer statusCode = (Integer) result.get("statusCode");
                        if (200 == statusCode) {
                            System.out.println("短信发送成功!");
                        } else if (10001 == statusCode) {
                            String message = (String) result.get("message");
                            System.out.println(message);
                        } else if (10002 == statusCode) {
                            System.out.println("账户短信量余额不足，请联系管理员进行充值!");
                        } else if (10003 == statusCode) {
                            System.out.println("手机号获取验证码次数已达每日上限!");
                        } else {
                            System.out.println("短信发送失败，错误代码：101，请联系管理员!");
                        }
                    } catch (Exception e) {
                        System.out.println("阿里云发送短信失败。失败原因为：" + e.getMessage());
                        e.printStackTrace();
                    } finally {

                    }
                }
            }
        }
        isSuccess = true;
        return isSuccess;
    }

    public void sendNotify(UserDTO userDto,String defId,String procInsId,String title ){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String day = format.format(new Date());
        Map<String ,String > map = new HashMap<>();
        map.put("taskId",procInsId);
        map.put("title",title);
        map.put("defId",defId);
        map.put("taskName","开票通知");
        map.put("createUser",userDto.getName());
        map.put("createTime",day);
        map.put("noticeName",userDto.getLoginName());
        map.put("noticeId",userDto.getId());
        map.put("createById",userDto.getId());
        SpringUtil.getBean ( IFlowableApi.class ).add(map);
    }

    /**
     * 获取关联项目名称list
     * @param workInvoice
     * @return
     */
    public List<String> getProjectNameList(FinanceInvoiceDTO workInvoice){
        //项目名称获取
        List<String> projectNameList = Lists.newArrayList();
        if(null != workInvoice.getFinanceInvoiceBaseDTOList()){
            for (FinanceInvoiceBaseDTO projectRelation : workInvoice.getFinanceInvoiceBaseDTOList()) {
                if(StringUtils.isNotBlank(projectRelation.getProgramId())){
                    projectNameList.add(projectRelation.getProgramName());
                }else{
                    projectNameList.add("其它："+projectRelation.getProgramName().replaceAll("\\r|\\n*",""));
                }

            }
        }
        return projectNameList;
    }

    @Transactional(readOnly = false)
    public  void updateOmsUrlById(FinanceInvoiceDTO workInvoice){
        financeInvoiceMapper.updateOmsUrlById(workInvoice);
    }


    /**
     * 根据项目id集合查询相关的所有的发票信息
     * @return
     */
    public List<FinanceInvoiceDTO> getFinanceInvoiceByProgramId(List<String> programIdList) {
        return financeInvoiceMapper.getFinanceInvoiceByProgramId(programIdList);
    }



    /**
     * 查询同项目名称、价格、材料名称的数量是否只有一个
     */
    @Transactional(readOnly = false)
    public Map<String, List<WorkInvoiceReceiptInfo>> distinctProjectMaterialStorage(
            List<WorkInvoiceReceiptInfo> workInvoiceReceiptInfo) {

        HashMap<String, List<WorkInvoiceReceiptInfo>> map = new HashMap<>();

        // 第一步：对本次导入数据进行去重（自身重复）
        Set<String> seen = new HashSet<>();
        List<WorkInvoiceReceiptInfo> uniqueList = new ArrayList<>();      // 本次去重后的有效值
        List<WorkInvoiceReceiptInfo> duplicateList = new ArrayList<>();   // 本次自身重复值
        List<WorkInvoiceReceiptInfo> alreadyExistList = new ArrayList<>();   // 已经有收款信息的数据
        List<WorkInvoiceReceiptInfo> inexistenceList = new ArrayList<>();   // 数据表中不存在的的数据
        List<WorkInvoiceReceiptInfo> moneyMismatchingList = new ArrayList<>();   // 数据表中金额大于开票价的的数据

        for (WorkInvoiceReceiptInfo item : workInvoiceReceiptInfo) {
            String distinctStr = item.getDistinctStr();

            // 处理null值（视为重复）
            if (distinctStr == null) {
                duplicateList.add(item);
                continue;
            }

            if (!seen.contains(distinctStr)) {
                seen.add(distinctStr);
                uniqueList.add(item);
            } else {
                duplicateList.add(item);
            }
        }

        //对有效值进行发票查询操作，如果已经存在记录 则表示 给该数据存在问题（重复上传）
        List<String> invoiceNumberList = Lists.newArrayList();
        for (WorkInvoiceReceiptInfo invoiceReceiptInfo : uniqueList) {
            invoiceNumberList.add(invoiceReceiptInfo.getInvoiceNumber());
        }
        //根据 invoiceNumberList 去进行查询已经存在的数据信息
        List<WorkInvoiceReceipt> alreadyExistReceiptList = financeInvoiceMapper.getByInvoiceNumber(invoiceNumberList);

        //遍历有效值和查出来的已经存在的收款信息进行对比，若存在同一发票号的信息，金额进行累加，若金额大于应收金额，则表示该条数据存在问题，所小于则表示部分收款，若等于 则表示完全收款，改成已收款
        // 迭代器方式：内层循环安全删除
        for (WorkInvoiceReceipt workInvoiceReceipt : alreadyExistReceiptList) {
            // 内层用迭代器遍历uniqueList，支持安全删除
            Iterator<WorkInvoiceReceiptInfo> iterator = uniqueList.iterator();
            while (iterator.hasNext()) {
                WorkInvoiceReceiptInfo invoiceReceiptInfo = iterator.next();
                if (workInvoiceReceipt.getNumber().equals(invoiceReceiptInfo.getInvoiceNumber())) {
                    alreadyExistList.add(invoiceReceiptInfo); // 加入待处理列表
                    invoiceReceiptInfo.setInvoiceId(workInvoiceReceipt.getInvoiceId());
                    iterator.remove(); // 迭代器安全删除，不会触发并发修改异常
                }
            }
        }

        //对剩下的有效数据进行处理
        //判定金额和开票额是否一致，若一致，则表示全部收款，若小于开票额，表示部分收款，若大于，应当是填写错误，进行抛出，不进行导入
        invoiceNumberList = Lists.newArrayList();
        for (WorkInvoiceReceiptInfo invoiceReceiptInfo : uniqueList) {
            invoiceNumberList.add(invoiceReceiptInfo.getInvoiceNumber());
        }
        //根据 invoiceNumberList 去进行查询已经存在的数据信息
        List<FinanceInvoiceDetailDTO> invoiceDetailList = financeInvoiceDetailMapper.getInvoiceDetailByNumber(invoiceNumberList);
        for (FinanceInvoiceDetailDTO workInvoiceDetail : invoiceDetailList) {
            for (WorkInvoiceReceiptInfo info : uniqueList) {
                if(workInvoiceDetail.getNumber().equals(info.getInvoiceNumber())){
                    info.setInvoiceId(workInvoiceDetail.getInvoiceId());
                }
            }
        }

        //如果两者数据量不同，说明 要么发票号错误，要么该发票没有录入，需要抛出，其余的再进行比较金额
        if(invoiceDetailList.size() != uniqueList.size()){
            //将invoiceDetailList 和uniqueList 进行对比，如果uniqueList中存在 但是 invoiceDetailList 不存在，则就要将这个值从uniqueList删除并写入到 inexistenceList中

            // 1. 提取invoiceDetailList中所有发票号存入Set，用于O(1)快速判断是否存在（核心优化）
            Set<String> detailInvoiceNumberSet = new HashSet<>();
            for (FinanceInvoiceDetailDTO detail : invoiceDetailList) {
                detailInvoiceNumberSet.add(detail.getNumber());
            }

            // 2. 迭代器遍历uniqueList，安全删除+收集不存在的元素（避免ConcurrentModificationException）
            Iterator<WorkInvoiceReceiptInfo> iterator = uniqueList.iterator();
            while (iterator.hasNext()) {
                WorkInvoiceReceiptInfo uniqueInfo = iterator.next();
                String uniqueInvoiceNo = uniqueInfo.getInvoiceNumber();
                // 判断：uniqueList的发票号 在invoiceDetailList中不存在
                if (!detailInvoiceNumberSet.contains(uniqueInvoiceNo)) {
                    inexistenceList.add(uniqueInfo); // 加入不存在的列表
                    iterator.remove(); // 迭代器安全删除，不会触发并发修改异常
                }
            }
        }
        //到此处 说明数据已经匹配几乎完成，现在还需要对有效的参数的金额进行匹配
        for (FinanceInvoiceDetailDTO workInvoiceDetail : invoiceDetailList) {
            for (WorkInvoiceReceiptInfo unique : uniqueList) {
                if(workInvoiceDetail.getNumber().equals(unique.getInvoiceNumber())){
                    //判定金额是否相同，小于为-1  相同为0 大于为1
                    String totalMoney = workInvoiceDetail.getAccount();
                    String money = unique.getMoney();
                    BigDecimal totalMoneyB = new BigDecimal(totalMoney);
                    BigDecimal moneyB = new BigDecimal(money);
                    // 核心比较：直接得到-1/0/1的结果
                    int compareResult = moneyB.compareTo(totalMoneyB);
                    // 后续可根据结果做业务处理
                    if (compareResult == 1) {
                        // totalMoney 小于 money 业务逻辑
                        //说明新导入的额度要大于开票额度
                        unique.setMoneyFlag(1);
                    } else if (compareResult == 0) {
                        // 金额相等 业务逻辑
                        //说明金额相等
                        unique.setMoneyFlag(0);
                    } else {
                        // totalMoney 大于 money 业务逻辑
                        //说明部分收款
                        unique.setMoneyFlag(-1);
                    }
                }

            }
        }

        //对处理完的数据进行区分，大于1的值不能进行导入，需要剔除
        Iterator<WorkInvoiceReceiptInfo> iterator = uniqueList.iterator();
        while (iterator.hasNext()) {
            WorkInvoiceReceiptInfo info = iterator.next();
            // 判定moneyFlag为1（导入金额超开票金额），剔除并收集
            if (info.getMoneyFlag() == 1) {
                moneyMismatchingList.add(info); // 加入无效数据列表
                iterator.remove(); // 从有效列表uniqueList中安全删除
            }
        }

        //此处可以对剩余的数据进行处理了

        // 2. 生成唯一文件名（避免覆盖）
        UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByToken(TokenProvider.getCurrentToken());

        List<WorkInvoiceReceipt> insertReceiptList = Lists.newArrayList();
        for (WorkInvoiceReceiptInfo info : uniqueList) {
            WorkInvoiceReceipt insertReceipt = new WorkInvoiceReceipt();

            if (info.getMoneyFlag() == 0) {
                info.setReceiptMoneyDate(new Date());
                info.setReceiptMoney(1);
                insertReceipt.setStatus("1");
            } else if(info.getMoneyFlag() == -1){
                info.setReceiptMoney(2);
                insertReceipt.setStatus("2");
            }

            insertReceipt.setInvoiceId(info.getInvoiceId());
            String dateStr = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                    .withZone(ZoneId.systemDefault())
                    .format(Instant.ofEpochMilli(new Date().getTime()));
            insertReceipt.setReceiptDate(dateStr);
            insertReceipt.setCompanyName(info.getBuyerName());
            insertReceipt.setMoney(new BigDecimal(info.getMoney().trim()));

            // 生成id
            String id = UUID.randomUUID().toString().replace("-", "");
            insertReceipt.setId(id);
            insertReceipt.setCreateBy(userDTO);
            insertReceipt.setCreateTime(new Date());
            insertReceipt.setUpdateBy(userDTO);
            insertReceipt.setUpdateTime(new Date());
            insertReceipt.setDelFlag(0);
            insertReceiptList.add(insertReceipt);
        }
        if(!insertReceiptList.isEmpty()){
            //将收款信息添加到数据库中
            financeInvoiceMapper.batchInsert(insertReceiptList);
        }
        if(!uniqueList.isEmpty()){
            for (WorkInvoiceReceiptInfo invoiceReceiptInfo : uniqueList) {
                invoiceReceiptInfo.setUpdateBy(userDTO);
                invoiceReceiptInfo.setUpdateTime(new Date());
                invoiceReceiptInfo.setDelFlag(0);
            }
            //修改work_invoice表中 receipt_money_date 和 receipt_money 参数信息
            financeInvoiceMapper.batchUpdateByForeach(uniqueList);
        }



        // 最终返回处理后的列表
        map.put("uniqueList", uniqueList);      // 仅包含本次新增且不与历史重复的数据
        map.put("duplicateList", duplicateList); // 包含自身重复和与历史重复的数据
        map.put("alreadyExistList", alreadyExistList); // 已经有收款信息的数据
        map.put("inexistenceList", inexistenceList); // 数据表中不存在的的数据 invoiceDetail 表中不存在，也就是说 没有开票信息
        map.put("moneyMismatchingList", moneyMismatchingList); // 数据表中金额大于开票价的的数据
        return map;
    }
}
