package cn.superdesk.uniorder.service.accounting.unified.customer.impl;


import cn.hutool.core.date.DateUtil;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderBackAccountStatusEnum;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderDimCreateByEnum;
import cn.superdesk.uniorder.common.enums.accounting.customer.AccountingOrderCustomerAccountingStatusEnum;
import cn.superdesk.uniorder.common.enums.common.CommonAccountingStateEnum;
import cn.superdesk.uniorder.common.exception.UnifiedOrderRuntimeException;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
import cn.superdesk.uniorder.common.numerical.AnCollectionUtils;
import cn.superdesk.uniorder.common.numerical.AnIntegerUtils;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.dao.entity.accounting.unified.customer.*;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrder;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderExample;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderGoods;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderGoodsExample;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApplyXGoods;
import cn.superdesk.uniorder.dao.entity.sys.SysOrder;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.*;
import cn.superdesk.uniorder.dao.mapper.base.*;
import cn.superdesk.uniorder.dao.mapper.invoice.common.InvoiceBankInfoMapperEx;
import cn.superdesk.uniorder.dao.mapper.invoice.customer.InvoiceApplyMapperEx;
import cn.superdesk.uniorder.dao.mapper.organisation.SysEnterpriseMapperEx;
import cn.superdesk.uniorder.dao.mapper.organisation.SysOrganizationMapperEx;
import cn.superdesk.uniorder.dao.mapper.scheduler.SysQuartzScheduleTaskStatementOfAccountMapper;
import cn.superdesk.uniorder.dao.mapper.sys.SysConfigMapper;
import cn.superdesk.uniorder.dao.mapper.sys.SysOderUserMapperEx;
import cn.superdesk.uniorder.dao.mapper.sys.SysOrderMapper;
import cn.superdesk.uniorder.dto.vo.accounting.unified.customer.*;
import cn.superdesk.uniorder.dto.vo.accounting.unified.customer.statement.CustomerStatementOfAccountDetailItemVo;
import cn.superdesk.uniorder.dto.vo.accounting.unified.customer.statement.CustomerStatementOfAccountDetailVo;
import cn.superdesk.uniorder.dto.vo.sys.SysInvoiceOrder;
import cn.superdesk.uniorder.dto.vo.sys.SysOrderQuery;
import cn.superdesk.uniorder.service.accounting.unified.customer.*;
import cn.superdesk.uniorder.service.order.base.UnifiedOrderCreditService;
import cn.superdesk.uniorder.service.order.base.UnifiedOrderGoodsService;
import cn.superdesk.uniorder.service.order.base.UnifiedOrderService;
import cn.superdesk.uniorder.service.sys.SysConfigService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Description: 客户结算 对账单 TODO 此类存在乱七八糟的东西 要清理
 * @Author: linjinyu 补充 修改
 * @CreateDate: 4/28/20 4:30 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 4/28/20 4:30 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
@Service
public class AccountingUnifiedCustomerServiceImpl implements AccountingUnifiedCustomerService {


    @Autowired
    private AccountingUnifiedCustomerMapper      accountingUnifiedCustomerMapper;
    @Autowired
    private AccountingUnifiedCustomerMapperEx    accountingUnifiedCustomerMapperEx;
    @Autowired
    private AccountingUnifiedCustomerMapperExSys accountingUnifiedCustomerMapperExSys;

    @Autowired
    private AccountingUnifiedCustomerXGoodsMapper  accountingUnifiedCustomerXGoodsMapper;
    @Autowired
    private AccountingUnifiedCustomerXGoodsService accountingUnifiedCustomerXGoodsService;
    @Autowired
    private AccountingUnifiedCustomerServiceCommon accountingUnifiedCustomerServiceCommon;

    /****************************************** 对账单 订单 商品 表 将要弃用 start ******************************************/
    @Autowired
    private AccountingUnifiedCustomerOrderMapper   accountingUnifiedCustomerOrderMapper;
    @Autowired
    private AccountingUnifiedCustomerOrderMapperEx accountingUnifiedCustomerOrderMapperEx;

    @Autowired
    private AccountingUnifiedCustomerOrderGoodsMapper   accountingUnifiedCustomerOrderGoodsMapper;
    @Autowired
    private AccountingUnifiedCustomerOrderGoodsMapperEx accountingUnifiedCustomerOrderGoodsMapperEx;

    @Autowired
    private AccountingUnifiedCustomerOrderService      accountingUnifiedCustomerOrderService;
    @Autowired
    private AccountingUnifiedCustomerOrderGoodsService accountingUnifiedCustomerOrderGoodsService;

    /****************************************** 对账单 订单 商品 表 将要弃用   end ******************************************/

    @Autowired
    private InvoiceBankInfoMapperEx unifiedBankInfoMapper;


    @Autowired
    private SysConfigMapper     sysConfigMapper;
    @Autowired
    private SysOrderMapper      sysOrderMapper;
    @Autowired
    private SysOderUserMapperEx sysOderUserMapper;

    @Autowired
    private UnifiedOrderMapper   unifiedOrderMapper;
    @Autowired
    private UnifiedOrderMapperEx unifiedOrderMapperEx;
    @Autowired
    private UnifiedOrderService  unifiedOrderService;

    @Autowired
    private UnifiedOrderGoodsMapper   unifiedOrderGoodsMapper;
    @Autowired
    private UnifiedOrderGoodsMapperEx unifiedOrderGoodsMapperEx;
    @Autowired
    private UnifiedOrderGoodsService  unifiedOrderGoodsService;

    @Autowired
    private UnifiedOrderCreditService unifiedOrderCreditService;

    @Autowired
    private UnifiedOrderReturnGoodsMapperEx unifiedOrderReturnGoodsMapperEx;


    @Autowired
    private SysQuartzScheduleTaskStatementOfAccountMapper sysQuartzScheduleTaskStatementOfAccountMapper;

    @Autowired
    private SysEnterpriseMapperEx   sysEnterpriseMapperEx;
    @Autowired
    private SysOrganizationMapperEx sysOrganizationMapper;

    @Autowired
    private InvoiceApplyMapperEx invoiceApplyMapperEx;

    @Autowired
    private SysConfigService sysConfigService;


    @Override
    public PageInfo<AccountingUnifiedCustomer> findByPaging(Map<String, Object> params, Integer pageNo, Integer pageSize) {

        return null;
    }

    @Override
    public void deleteObj(Long id) {


    }

    @Override
    public int updateByPrimaryKeySelective(AccountingUnifiedCustomer t) {

        return accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(t);
    }

    @Override
    public AccountingUnifiedCustomer findById(Long id) {

        return accountingUnifiedCustomerMapper.selectByPrimaryKey(id);
    }

    @Override
    public AccountingUnifiedCustomer findByAccountingOrderSn(String accountingOrderSn) {


        AccountingUnifiedCustomerExample example = new AccountingUnifiedCustomerExample();
        example.createCriteria()
                .andAccountingOrderSnEqualTo(accountingOrderSn);

        List<AccountingUnifiedCustomer> result = accountingUnifiedCustomerMapper.selectByExample(example);

        if (AnCollectionUtils.isEmpty(result)) {
            return null;
        } else {
            return result.get(0);
        }
        // 弃用 mark by linjinyu at 20210105
//		return accountingUnifiedCustomerMapperEx.findBySn(dzSn);
    }

    @Override
    public int insertSelective(AccountingUnifiedCustomer t) {

        return accountingUnifiedCustomerMapper.insertSelective(t);

    }

    @Override
    public List<AccountingUnifiedCustomer> findAll(Map<String, Object> queryMap) {

        return null;
    }


    /****************************************** 对账单 状态 回款状态 start ******************************************/

    /**
     * 分组 by AccountingOrderId
     *
     * @param invoiceOrder
     * @return
     */
    private Long fetchGroupKeyByAccountingOrderId(InvoiceApplyXGoods invoiceOrder) {
        return invoiceOrder.getAccountingOrderId();
    }

    /**
     * TODO 再想一下重构的问题,先顺逻辑
     *
     * @param invoiceX
     */
    @Override
    public void updateFieldBackAccountStatusByInvoiceX(/*数据集为以某对账单的关联关系*/List<InvoiceApplyXGoods> invoiceX) {

        // 先判定是否存在多个对账单
        Map<Long, List<InvoiceApplyXGoods>> transferMapGroupByAccountingOrderId = invoiceX.parallelStream()
                .collect(Collectors.groupingBy(e -> fetchGroupKeyByAccountingOrderId(e), Collectors.toList()));

        Integer isManyMap = transferMapGroupByAccountingOrderId.size();

        if (isManyMap.compareTo(1) > 0) {
            log.error("此方法只能处理 1 数据集为以某1对账单的关联关系 ");
            return;
        }

        Integer invoiceXCount                = 0;
        Integer invoiceXBackAccountStatusEq1 = 0;

        invoiceXCount = invoiceX.size();
        invoiceXBackAccountStatusEq1 = AnIntegerUtils.getInteger(invoiceX.stream().filter(o -> null != o.getBackStatus() && o.getBackStatus().equals(1)).count());

        // return 为 ret 标记 不是计算数量
        if (invoiceXCount.compareTo(0) <= 0) {
            return;
        }

        if (invoiceXBackAccountStatusEq1.compareTo(0) <= 0) {
            return;
        }

        /****************************************** 不处理 未回款问题 start ******************************************/

        AccountingOrderBackAccountStatusEnum accountingOrderBackAccountStatusEnum;
        if (invoiceXCount.compareTo(invoiceXBackAccountStatusEq1) == 0) {
            accountingOrderBackAccountStatusEnum = AccountingOrderBackAccountStatusEnum.全部回款;
        } else {
            accountingOrderBackAccountStatusEnum = AccountingOrderBackAccountStatusEnum.部分回款;
        }

        List<Long> accountingOrderIds = invoiceX.stream().filter(o -> null != o.getAccountingOrderId()).map(o -> o.getAccountingOrderId()).collect(Collectors.toList());

        updateFieldBackAccountStatusByAccountingOrderIds(accountingOrderIds, accountingOrderBackAccountStatusEnum);


    }

    public void updateFieldBackAccountStatusByAccountingOrderIds(List<Long> accountingOrderIds, AccountingOrderBackAccountStatusEnum accountingOrderBackAccountStatusEnum) {

        AccountingUnifiedCustomerExample exampleForUpdate = new AccountingUnifiedCustomerExample();
        exampleForUpdate.createCriteria()
                .andIdIn(accountingOrderIds);

        AccountingUnifiedCustomer entityForUpdate = new AccountingUnifiedCustomer();
        entityForUpdate.setBackAccountStatus(accountingOrderBackAccountStatusEnum.getKey());

        accountingUnifiedCustomerMapper.updateByExample(entityForUpdate, exampleForUpdate);
    }
    /****************************************** 对账单 状态 回款状态   end ******************************************/

    /**
     * 先压到这边做
     */
    public void updateFieldAccountingStatusByAccountingOrderId(Long accountingOrderId, AccountingOrderCustomerAccountingStatusEnum accountingOrderAccountingStatusEnum) {

        AccountingUnifiedCustomer accountingUnifiedCustomer = new AccountingUnifiedCustomer();
        accountingUnifiedCustomer.setId(accountingOrderId);
        accountingUnifiedCustomer.setAccountingStatus(accountingOrderAccountingStatusEnum.getKey());
        accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(accountingUnifiedCustomer);
    }


    @Override
    public List<SysOrder> findAllFromOrder(Map<String, Object> queryMap) {

        return accountingUnifiedCustomerMapperExSys.findAllFromOrder(queryMap);
    }

    @Override
    public List<String> findRealNamesByOrder(Map<String, Object> queryMap) {

        return accountingUnifiedCustomerMapperExSys.findRealNamesByOrder(queryMap);
    }

    @Override
    public R<List<DzMainAutoPage>> findAllViewPage(Map<String, Object> params, int pageNo, int pageSize) {

        PageHelper.startPage(pageNo, pageSize);
        List<DzMainAutoPage>     resultList = accountingUnifiedCustomerMapperEx.findAllView(params);
        PageInfo<DzMainAutoPage> page       = new PageInfo<DzMainAutoPage>(resultList);
        PageHelper.clearPage();

        return new R<List<DzMainAutoPage>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), resultList);

    }

    @Override
    public R<List<ViewSysOrder>> findOrderViewPage(Map<String, Object> params, int pageNo, int pageSize) {

        PageHelper.startPage(pageNo, pageSize);
        List<ViewSysOrder>     resultList = accountingUnifiedCustomerMapperExSys.findViewFromOrder(params);
        PageInfo<ViewSysOrder> page       = new PageInfo<ViewSysOrder>(resultList);
        PageHelper.clearPage();
        return new R<List<ViewSysOrder>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), resultList);

    }

    @Override
    public ReportOrderQA findReportFromOrder(Map<String, Object> params) {

        return accountingUnifiedCustomerMapperExSys.findReportFromOrder(params);
    }

    @Override
    public List<ViewSysOrderGoods> findOrderViewGoods(SysOrderQuery params) {

        return accountingUnifiedCustomerMapperExSys.findViewFromOrderGoods(params);
    }


    @Override
    public R<List<CustomerStatementOfAccountDetailVo>> getAccountingUnifiedCustomerViewByPage(Map<String, Object> params, int pageNo, int pageSize) {

        PageHelper.startPage(pageNo, pageSize);

        List<CustomerStatementOfAccountDetailVo> viewDzMainList = accountingUnifiedCustomerMapperEx.getAccountingUnifiedCustomerView(params);

        PageInfo<CustomerStatementOfAccountDetailVo> page = new PageInfo<CustomerStatementOfAccountDetailVo>(viewDzMainList);

        PageHelper.clearPage();

        return new R<List<CustomerStatementOfAccountDetailVo>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), viewDzMainList);

    }

    public List<CustomerStatementOfAccountDetailVo> getAccountingUnifiedCustomerViewByPage(Map<String, Object> params) {

        List<CustomerStatementOfAccountDetailVo> viewDzMainList = accountingUnifiedCustomerMapperEx.getAccountingUnifiedCustomerView(params);

        return viewDzMainList;
    }

    /**
     * TODO 坑资源
     *
     * @param params
     * @return
     */
    @Override
    public ReportOrderQA getAccountingUnifiedCustomerViewHead(Map<String, Object> params) {

        // 这个是没有分页的 是全部的数据
        // TODO 所以问题 TAPD_ID_1000679_【PC端】对账单(客户结算、供应商结算)账单金额计算时剔除已取消、已拒绝状态对账单金额及数量
        // 在此加条件就可以达到了
        List<CustomerStatementOfAccountDetailVo> viewDzMainList = accountingUnifiedCustomerMapperEx.getAccountingUnifiedCustomerView(params);

        if (AnCollectionUtils.isNotEmpty(viewDzMainList)) {

            // 对账单 ID
            List<String> ids = new ArrayList<>();

            for (CustomerStatementOfAccountDetailVo item : viewDzMainList) {
                ids.add(item.getId().toString());
            }

            Map<String, Object> dzOrderQueryParams = new HashMap<>();
            if (ids.size() > 0) {
                dzOrderQueryParams.put("dzids", ids.toArray());
            }

            ReportOrderQA qa = accountingUnifiedCustomerOrderMapperEx.getReportQuantity(dzOrderQueryParams);

            qa.setDzquantity(viewDzMainList.size());

            return qa;

        } else {

            ReportOrderQA reportOrderQA = new ReportOrderQA();

            reportOrderQA.setAmount(new BigDecimal(0));
            reportOrderQA.setDzquantity(0);
            reportOrderQA.setQuantity(0);
            reportOrderQA.setRealamount(new BigDecimal(0));
            reportOrderQA.setReturnamount(new BigDecimal(0));

            return reportOrderQA;
        }


    }

    @Override
    public List<ViewSysOrderJoinGoods> findOrderViewGoodsTb(Map<String, Object> params) {

        return accountingUnifiedCustomerMapperExSys.findOrderViewGoodsTb(params);
    }

    /**
     * 订单 维度
     *
     * @param accountingOrderId
     * @param accountingOrderAccountingStatusEnum
     */
    @Transactional
    @Override
    public void optAccountingCustomerActionCancel(Long accountingOrderId, AccountingOrderCustomerAccountingStatusEnum accountingOrderAccountingStatusEnum) {

        AccountingUnifiedCustomer accountingUnifiedCustomer = findById(accountingOrderId);

        /****************************************** 重构 mark by linjinyu at 20210120 start ******************************************/
//		for (AccountingUnifiedCustomerOrder accountingUnifiedCustomerOrder : accountingUnifiedCustomerOrderList) {
//
//			// 老的订单是这样修正对账状态
////			SysOrder order =new SysOrder();
////			order.setId(item.getOrderId());
////			order.setIsGenBill(Byte.valueOf("0"));
////			orderMapper.updateByPrimaryKeySelective(order);
//
//			UnifiedOrder unifiedOrder = unifiedOrderMapperEx.selectByPrimaryOrderSn(accountingUnifiedCustomerOrder.getOrderSn());
//
//			// 坑位 20200715 by linjinyu
//			// 为什么 要加这个判定
//			// 超级前台的人员有可以做错单,要求后端人员去数据库删除原始订单 而这个 对账单 X 订单 的中意数据 是没有处理的 ,也没有重新核算对账单
//			if (null != unifiedOrder) {
//				UnifiedOrder order = new UnifiedOrder();
//				order.setId(unifiedOrder.getId());
//				order.setAccountingStateCustomer(CommonAccountingStateEnum.未对账.getKey());
//				order.setUpdateTime(DateUtil.date());
//				unifiedOrderMapper.updateByPrimaryKeySelective(order);
//			}
//		}

        /****************************************** 重构 mark by linjinyu at 20210120   end ******************************************/

        /****************************************** 重构为 mark by linjinyu at 20210120 start ******************************************/

        List<String> processOrderSns                = new ArrayList<>();
        List<Long>   processSysUnifiedOrderGoodsIds = new ArrayList<>();
        List<Long>   processOutGoodsIds             = new ArrayList<>();

        switch (AccountingOrderDimCreateByEnum.get(accountingUnifiedCustomer.getDimCreateBy())) {
            case 订单:

                /****************************************** 查出这个对账单 关联的 订单 中间表数据 start ******************************************/
                Map<String, Object> params = new HashMap<>();
                params.put("dzId", accountingOrderId);
                List<AccountingUnifiedCustomerOrder> accountingUnifiedCustomerOrderList = accountingUnifiedCustomerOrderMapperEx.findAll(params);

                processOrderSns = accountingUnifiedCustomerOrderList.stream()
                        .filter(o -> null != o.getOrderSn())
                        .filter(AnLamdaUtils.distinctByKey(o -> o.getOrderSn()))
                        .map(AccountingUnifiedCustomerOrder::getOrderSn).collect(Collectors.toList());

                // 更新 订单 客户对账状态
                unifiedOrderService.updateAccountingStateCustomerByOrderSns(processOrderSns, CommonAccountingStateEnum.未对账);

                // 更新 商品 客户对账状态
                unifiedOrderGoodsService.updateAccountingStateCustomerByOrderSn(processOrderSns, CommonAccountingStateEnum.未对账);

                // 更新 流水 客户对账状态
//		        unifiedOrderCreditService.updateAccountingStateCustomerByOrderSn(processOrderSn, CommonAccountingStateEnum.未对账);

                /****************************************** 查出这个对账单 关联的 订单 中间表数据 start ******************************************/

                /****************************************** 关于 X表的说明 在未更新版本前 X表都是没有数据的,后来是订单维度都加了 X表的数据 start ******************************************/

                break;
            case 商品:

                List<AccountingUnifiedCustomerXGoods> statementOfAccountXGoods = accountingUnifiedCustomerXGoodsService.findByAccountingOrderId(accountingOrderId);

                if (AnCollectionUtils.isNotEmpty(statementOfAccountXGoods)) {

                    processOrderSns = statementOfAccountXGoods.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getOrderSn())).map(AccountingUnifiedCustomerXGoods::getOrderSn).collect(Collectors.toList());
                    processSysUnifiedOrderGoodsIds = statementOfAccountXGoods.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getUnifiedOrderGoodsId())).map(AccountingUnifiedCustomerXGoods::getUnifiedOrderGoodsId).collect(Collectors.toList());
                    // 流水才会用到
//					processOutGoodsIds = statementOfAccountXGoods.stream().filter(o -> o.getGoodsId() != null).filter(AnLamdaUtils.distinctByKey(o -> o.getGoodsId())).map(AccountingUnifiedCustomerXGoods::getGoodsId).collect(Collectors.toList());

                    // 更新 订单 供应商对账状态 -> 已对账 这个是错的,商品维度可能有部分对账的情况
                    unifiedOrderService.updateAccountingStateCustomerByOrderSns(processOrderSns, CommonAccountingStateEnum.未对账);

                    // 更新 商品 供应商对账状态 -> 已对账
                    unifiedOrderGoodsService.updateAccountingStateCustomerByOrderSnAndSysUnifiedOrderGoodsIds(processOrderSns, processSysUnifiedOrderGoodsIds, CommonAccountingStateEnum.未对账);

                    // 更新 流水 供应商对账状态  -> 已对账 20200925 供应商结算 创建对账单 如果 积分 流水 有的话 关联 更新状态 为 已对账状态
//					unifiedOrderCreditService.updateAccountingStateCustomerByOrderSnAndOutGoodsIds(processOrderSns, processOutGoodsIds, CommonAccountingStateEnum.未对账);
                }


                break;
            case 流水:
                throw new UnifiedOrderRuntimeException(500, "客户结算 对账单 目前不支持 流水维度");
            default:
                break;
        }


        /****************************************** 重构为 mark by linjinyu at 20210120   end ******************************************/

        // 处理对账单 对账状态(审核向)
        updateFieldAccountingStatusByAccountingOrderId(accountingOrderId, accountingOrderAccountingStatusEnum);
    }

    @Override
    public List<CustomerStatementOfAccountDetailVo> getDzMainView(Map<String, Object> params) {

        return accountingUnifiedCustomerMapperEx.getAccountingUnifiedCustomerView(params);
    }

    /***
     * 订单列表
     */
    @Override
    public R<List<ExpSysOrder>> getOrderViewByPage(SysOrderQuery params, int pageNo, int pageSize) {

        PageHelper.startPage(pageNo, pageSize);
        //List<ExpSysOrder> resultList = dzOrderMapper.findOrderView(params);//findViewFromOrderGoods(params);
        List<ExpSysOrder> resultList = accountingUnifiedCustomerOrderMapperEx.findSysOrderGoods(params);

        PageInfo<ExpSysOrder> page = new PageInfo<ExpSysOrder>(resultList);
        PageHelper.clearPage();
        return new R<List<ExpSysOrder>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), resultList);

    }

    @Override
    public R<List<ExpSysOrder>> getOrderViewByPageProject(SysOrderQuery params, int pageNo, int pageSize) {

        PageHelper.startPage(pageNo, pageSize);
        //List<ExpSysOrder> ls = dzOrderMapper.findOrderView(params);//findViewFromOrderGoods(params);
        List<ExpSysOrder> ls = accountingUnifiedCustomerOrderMapperEx.findSysOrderGoodsProject(params);

        PageInfo<ExpSysOrder> page = new PageInfo<ExpSysOrder>(ls);
        PageHelper.clearPage();
        return new R<List<ExpSysOrder>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), ls);

    }

    /***
     * 导出对账单EXCEL-根据对账单查询结果
     */
    public List<CustomerStatementOfAccountDetailItemVo> getDzMainViewExcel(Map<String, Object> params) {

        List<CustomerStatementOfAccountDetailVo> accountingUnifiedCustomerViewList = accountingUnifiedCustomerMapperEx.getAccountingUnifiedCustomerView(params);

        List<String> ids = new ArrayList<>();

        for (CustomerStatementOfAccountDetailVo item : accountingUnifiedCustomerViewList) {
            ids.add(item.getId().toString());
        }

        Map<String, Object> paramsFindAccountingOrderUnified = new HashMap<>();
        if (ids.size() > 0) {
            paramsFindAccountingOrderUnified.put("dzIds", ids.toArray());
        }

        List<CustomerStatementOfAccountDetailItemVo> dzOrders = accountingUnifiedCustomerMapperEx.findAllDzOrderView(paramsFindAccountingOrderUnified);

        return dzOrders;
    }

    @Override
    public ReportOrderQA getOrderReportData(SysOrderQuery query) {

        return accountingUnifiedCustomerMapperExSys.getOrderReportData(query);
    }

    @Override
    public ReportOrderQA getOrderReportDataDeath(SysOrderQuery query) {

        ReportOrderQA reportOrderQA = accountingUnifiedCustomerMapperExSys.getOrderReportDataDeath(query);
        reportOrderQA.setReturnamount(accountingUnifiedCustomerMapperExSys.getOrderReturnAmountDeath(query).getAmount());
        reportOrderQA.setRealamount(reportOrderQA.getAmount().subtract(reportOrderQA.getReturnamount()));
        return reportOrderQA;
    }

    @Deprecated
    @Override
    public List<ExpSysOrder> findOrderViewExcel(Map<String, Object> params) {

        List<ViewSysOrder> ls  = accountingUnifiedCustomerMapperExSys.findViewFromOrder(params);
        List<String>       ids = new ArrayList<>();
        for (ViewSysOrder item : ls) {
            ids.add(item.getId().toString());
        }
        Map<String, Object> paramsOrder = new HashMap<>();
        if (ids.size() > 0) {
            paramsOrder.put("oIds", ids.toArray());
        }
        List<ExpSysOrder> resLs = accountingUnifiedCustomerOrderMapperEx.findOrderViewExcel(paramsOrder);
        return resLs;
    }

    /***
     * 导出订单列表
     */
    @Override
    public List<ExpSysOrder> getOrderViewExcel(SysOrderQuery query) {

//		List<ViewSysOrderGoods> ls = dzMainMapper.findViewFromOrderGoods(query);
//		List<String> ids = new ArrayList<String>();
//		for (ViewSysOrderGoods item : ls) {
//			ids.add(item.getId().toString());
//		}
//		Map<String, Object> params_order = new HashMap<>();
//		if(ids.size()>0) {
//			params_order.put("oIds", ids.toArray());
//		}
        List<ExpSysOrder> resLs = accountingUnifiedCustomerOrderMapperEx.getOrderViewExcel(query);
        return resLs;
        //return dzOrderMapper.findSysOrderGoods(query);
    }

    @Override
    public SysInvoiceOrder findInvByOrderId(Long id) {

        return accountingUnifiedCustomerOrderMapperEx.findInvByOrderId(id);
    }


    /****************************************** 补丁程序 start ******************************************/

    /**
     * 客户结算 对账单 订单维度 转 商品维度
     *
     * @param accountingOrderSn
     */
    public void patchXDimOrder2DimGoods(String accountingOrderSn) {

        AccountingUnifiedCustomerExample          example00 = new AccountingUnifiedCustomerExample();
        AccountingUnifiedCustomerExample.Criteria criteria  = example00.createCriteria();

        criteria.andDimCreateByEqualTo(AccountingOrderDimCreateByEnum.订单.getKey())
                .andAccountingStatusNotEqualTo(AccountingOrderCustomerAccountingStatusEnum.已取消.getKey());

        if (StringUtils.isNotBlank(accountingOrderSn)) {
            criteria.andAccountingOrderSnEqualTo(accountingOrderSn);
        }

        List<AccountingUnifiedCustomer> accountingUnifiedCustomerList = accountingUnifiedCustomerMapper.selectByExample(example00);

        if (AnCollectionUtils.isNotEmpty(accountingUnifiedCustomerList)) {

            for (AccountingUnifiedCustomer accountingUnifiedCustomer : accountingUnifiedCustomerList) {

                // TODO 因为这个是补丁程序 所以要添加较验 1. 先要看一下 对账单 是什么维度创建的 2. 再要查一下 X 表的数据


                /****************************************** 初始化 start ******************************************/
                // 大概的作用类似批次
                Date processDate = DateUtil.date();
                // 大概是能再放上一层
                List<AccountingUnifiedCustomerXGoods> processAccountingUnifiedCustomerXGoodsList = new ArrayList<>();
                /****************************************** 初始化   end ******************************************/


                AccountingUnifiedCustomerOrderExample example1 = new AccountingUnifiedCustomerOrderExample();
                example1.clear();
                example1.createCriteria()
                        .andDzIdEqualTo(accountingUnifiedCustomer.getId());
                List<AccountingUnifiedCustomerOrder> accountingUnifiedCustomerOrderList = accountingUnifiedCustomerOrderMapper.selectByExample(example1);

                List<String> processOrderSns = accountingUnifiedCustomerOrderList.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getOrderSn())).map(o -> o.getOrderSn()).collect(Collectors.toList());

                for (AccountingUnifiedCustomerOrder accountingUnifiedCustomerOrder : accountingUnifiedCustomerOrderList) {

                    // TODO 坑位？ 这个 createCriteria 没作用？
                    UnifiedOrderGoodsExample example2 = new UnifiedOrderGoodsExample();
                    example2.clear();
                    example2.createCriteria()
                            .andOrderSnEqualTo(accountingUnifiedCustomerOrder.getOrderSn());
                    List<UnifiedOrderGoods> unifiedOrderGoodsList = unifiedOrderGoodsMapper.selectByExample(example2);

                    // TODO 坑位？ 这个 createCriteria 没作用？
                    UnifiedOrderExample example3 = new UnifiedOrderExample();
                    example3.createCriteria()
                            .andOrderSnEqualTo(accountingUnifiedCustomerOrder.getOrderSn());
                    List<UnifiedOrder> unifiedOrderList = unifiedOrderMapper.selectByExample(example3);

                    UnifiedOrder unifiedOrder = unifiedOrderList.get(0);

                    for (UnifiedOrderGoods unifiedOrderGoods : unifiedOrderGoodsList) {


                        /****************************************** 重构了,这个不需要了 mark by linjinyu at 20210206 start ******************************************/
//						AccountingUnifiedCustomerXGoods xGoods = new AccountingUnifiedCustomerXGoods();
//
//						xGoods.setDimCreateBy(AccountingOrderDimCreateByEnum.订单.getKey());
//
//						xGoods.setAccountingOrderId(item00.getId());
//						xGoods.setAccountingOrderSn(item00.getAccountingOrderSn());
//
//						xGoods.setUnifiedOrderId(item02.getId());
//						xGoods.setOrderSn(item01.getOrderSn());
//
//						xGoods.setUnifiedOrderGoodsId(item03.getId());
//						xGoods.setGoodsId(item03.getGoodsId());
//						xGoods.setOutSnapshotOrderGoodsId(item03.getOutSnapshotOrderGoodsId());
//
//						xGoods.setCreateUserId(1L);
//						xGoods.setCreateTime(DateUtil.date());
//						xGoods.setUpdateUserId(1L);
//						xGoods.setCreateTime(DateUtil.date());
//
//						accountingUnifiedCustomerXGoodsMapper.insert(xGoods);
                        /****************************************** 重构了,这个不需要了 mark by linjinyu at 20210206   end ******************************************/

                        processAccountingUnifiedCustomerXGoodsList.add(accountingUnifiedCustomerXGoodsService.composeAccountingUnifiedCustomerXGoods01(accountingUnifiedCustomer, unifiedOrder, unifiedOrderGoods, AccountingOrderDimCreateByEnum.订单, processDate));

                    }

                    /****************************************** 重构了,这个不需要了 mark by linjinyu at 20210206 start ******************************************/
                    // 基于 orderSn 来更新 供应商对账状态
//					UnifiedOrderGoods goods = new UnifiedOrderGoods();
//					goods.setAccountingStateSupplier(CommonAccountingStateEnum.已对账.getKey());
//					unifiedOrderGoodsMapper.updateByExampleSelective(goods, example2);
                    /****************************************** 重构了,这个不需要了 mark by linjinyu at 20210206   end ******************************************/

                }

                // store 对账单 X 订单 X 商品 TODO 这个地方有 歧意
                accountingUnifiedCustomerXGoodsService.insertBatch(processAccountingUnifiedCustomerXGoodsList);

                // 更新 订单 客户对账状态
                unifiedOrderService.updateAccountingStateCustomerByOrderSns(processOrderSns, CommonAccountingStateEnum.已对账);

                // 更新 商品 客户对账状态
                unifiedOrderGoodsService.updateAccountingStateCustomerByOrderSn(processOrderSns, CommonAccountingStateEnum.已对账);

                // 更新 流水 客户对账状态 以 一般订单 订单维度 创建的 对账单 不存在 积分流水
//		        unifiedOrderCreditService.updateAccountingStateCustomerByOrderSn(processOrderSn, CommonAccountingStateEnum.已对账);

            }
        }
    }

    /**
     * 查出对账单与关联关系 重新核对 对账单 金额 订单数 商品数
     *
     * @param accountingOrderSn
     */
    public void patchXAccountingAmountAndQuantityOrderAndQuantityGoods(String accountingOrderSn) {


        if (StringUtils.isBlank(accountingOrderSn)) {
            return;
        }

        AccountingUnifiedCustomerExample          example00 = new AccountingUnifiedCustomerExample();
        AccountingUnifiedCustomerExample.Criteria criteria  = example00.createCriteria();

        criteria.andDimCreateByEqualTo(AccountingOrderDimCreateByEnum.商品.getKey())
                .andAccountingStatusNotEqualTo(AccountingOrderCustomerAccountingStatusEnum.已取消.getKey());

        if (StringUtils.isNotBlank(accountingOrderSn)) {
            criteria.andAccountingOrderSnEqualTo(accountingOrderSn);
        }

        List<AccountingUnifiedCustomer> accountingUnifiedCustomerList = accountingUnifiedCustomerMapper.selectByExample(example00);

        if (AnCollectionUtils.isNotEmpty(accountingUnifiedCustomerList) && accountingUnifiedCustomerList.size() == 1) {

            AccountingUnifiedCustomer processAccountingUnifiedCustomer  = accountingUnifiedCustomerList.get(0);
            AccountingUnifiedCustomer toUpdateAccountingUnifiedCustomer = new AccountingUnifiedCustomer();

            toUpdateAccountingUnifiedCustomer.setId(processAccountingUnifiedCustomer.getId());

            List<AccountingUnifiedCustomerXGoods> processXList = accountingUnifiedCustomerXGoodsService.findByAccountingOrderId(processAccountingUnifiedCustomer.getId());


//			来源 superdesk-uniorder/superdesk-uniorder-service/src/main/java/cn/superdesk/uniorder/service/accounting/unified/customer/impl/AccountingUnifiedCustomerServiceOpCreateDimGoodsImpl.java
            /****************************************** 待重构代码  start ******************************************/

            List<Long> processSysUnifiedOrderGoodsIds = processXList.stream()
                    .filter(o -> null != o.getUnifiedOrderGoodsId())
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getUnifiedOrderGoodsId()))
                    .map(AccountingUnifiedCustomerXGoods::getUnifiedOrderGoodsId)
                    .collect(Collectors.toList());

//			toUpdateAccountingUnifiedCustomer

            List<UnifiedOrderGoods> processUnifiedOrderGoodsList = unifiedOrderGoodsService.findBySysUnifiedOrderGoodsIds(processSysUnifiedOrderGoodsIds);


            /****************************************** 过虑商品 商户承担运费 start ******************************************/

            // 算了,这部分不用程序处理了 配合sql 做吧
//			List<Predicate<UnifiedOrderGoods>> predicatesUnifiedOrderGoodsByAccountingStateCustomerEq1 = new ArrayList<>();
//			predicatesUnifiedOrderGoodsByAccountingStateCustomerEq1.add(r -> r.getGoodsName() != null && r.getGoodsName().equals("商户承担运费") && r.getUnit().equals("商户承担运费"));
//			List<UnifiedOrderGoods> predicatesUnifiedOrderGoodsByAccountingStateCustomerEq1Filter = AnLamdaUtils.filters(processUnifiedOrderGoodsList, predicatesUnifiedOrderGoodsByAccountingStateCustomerEq1);
//
//			if (AnCollectionUtils.isNotEmpty(predicatesUnifiedOrderGoodsByAccountingStateCustomerEq1Filter)) {
//				// TODO 处理 商户承担运费
//
//
//			}
            /****************************************** 过虑商品 商户承担运费  end ******************************************/

            /****************************************** 核算 对账单 总金额 mark by linjinyu at 20210125 start ******************************************/
            BigDecimal goodsAmount = processUnifiedOrderGoodsList
                    .stream()
                    .map(item -> item.getPrice() == null ? BigDecimal.ZERO : item.getPrice().multiply(new BigDecimal(item.getQuantity())))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal goodsCostAmount = processUnifiedOrderGoodsList
                    .stream()
                    .map(item -> item.getCostPrice() == null ? BigDecimal.ZERO : item.getCostPrice().multiply(new BigDecimal(item.getQuantity())))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            toUpdateAccountingUnifiedCustomer.setAccountingAmount(goodsAmount);

            /****************************************** 核算 对账单 订单数 mark by linjinyu at 20210125 start ******************************************/
            List<Long> processUnifiedOrderIds = processXList.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getUnifiedOrderId())).map(o -> o.getUnifiedOrderId()).collect(Collectors.toList());

            toUpdateAccountingUnifiedCustomer.setQuantityOrder(processUnifiedOrderIds.size());

            /****************************************** 待重构代码   end ******************************************/

            accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(toUpdateAccountingUnifiedCustomer);

        }

    }
    /****************************************** 补丁程序   end ******************************************/

}
