package com.zfire.mall.manager.logic.retail;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.EnumUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zfire.mall.manager.bean.DirectOrderBean;
import com.zfire.mall.manager.bean.ExcelData;
import com.zfire.mall.manager.bean.OrderExecBean;
import com.zfire.mall.manager.bean.PoySaleCountBean;
import com.zfire.mall.manager.bean.admin.AdminUserCom;
import com.zfire.mall.manager.bean.invoice.InvoiceApplicationOrderRequest;
import com.zfire.mall.manager.bean.invoice.InvoiceRequestJson;
import com.zfire.mall.manager.bean.k3.K3CustomerBean;
import com.zfire.mall.manager.bean.k3.RequestExcuteOperationBean;
import com.zfire.mall.manager.bean.k3.bill.SalesChangeBean;
import com.zfire.mall.manager.bean.k3.bill.SalesChangeItemBean;
import com.zfire.mall.manager.bean.k3.bill.SalesOrderBean;
import com.zfire.mall.manager.bean.k3.bill.SalesOrderItemBean;
import com.zfire.mall.manager.bean.k3.bill.result.BillItem;
import com.zfire.mall.manager.bean.k3.bill.result.ResultEntity;
import com.zfire.mall.manager.bean.listV2.*;
import com.zfire.mall.manager.bean.listV2.dto.EnginOrderDTO;
import com.zfire.mall.manager.bean.listV2.dto.ExamineZfireParamBean;
import com.zfire.mall.manager.bean.retail.*;
import com.zfire.mall.manager.bean.wallet.CustomerWalletAmountBean;
import com.zfire.mall.manager.bean.wallet.CustomerWalletBean;
import com.zfire.mall.manager.commonmapper.CommonCountMapper;
import com.zfire.mall.manager.commonmapper.CountMapper;
import com.zfire.mall.manager.commonmapper.InvoiceMapper;
import com.zfire.mall.manager.commonmapper.listV2.CommonCMapper;
import com.zfire.mall.manager.commonmapper.retail.RetailOrderCommonMapper;
import com.zfire.mall.manager.enums.*;
import com.zfire.mall.manager.exception.RemoteServiceException;
import com.zfire.mall.manager.logic.common.CommonLogic;
import com.zfire.mall.manager.logic.customer.CustomerProductTypeLogic;
import com.zfire.mall.manager.logic.invoice.InvoiceLogic;
import com.zfire.mall.manager.logic.k3.K3CommonMethodLogic;
import com.zfire.mall.manager.logic.k3.K3CustomerLogic;
import com.zfire.mall.manager.logic.k3.bill.SalesChangeOrderLogic;
import com.zfire.mall.manager.logic.k3.bill.SalesOrderLogic;
import com.zfire.mall.manager.logic.policy.PolicyLogic;
import com.zfire.mall.manager.logic.stock.StockCommonLogic;
import com.zfire.mall.manager.logic.wallet.CustomerWalletCreditLogic;
import com.zfire.mall.manager.logic.wallet.RebateOrderLogic;
import com.zfire.mall.manager.logic.wallet.WalletLogic;
import com.zfire.mall.manager.plus.entity.*;
import com.zfire.mall.manager.plus.service.*;
import com.zfire.mall.manager.utils.ArithUtils;
import com.zfire.mall.manager.utils.CommonUtils;
import com.zfire.mall.manager.zfire.bean.ZfireParamBean;
import com.zfire.mall.manager.zfire.util.FieldUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 零售单
 */
@Slf4j
@Service
public class RetailOrderLogic {


    @Autowired
    PolicyLogic policyLogic;
    @Autowired
    CommonLogic commonLogic;
    @Autowired
    StockCommonLogic stockCommonLogic;
    @Autowired
    WalletLogic walletLogic;
    @Autowired
    CustomerWalletCreditLogic customerWalletCreditLogic;
    @Autowired
    CustomerProductTypeLogic customerProductTypeLogic;
    @Autowired
    RebateOrderLogic rebateOrderLogic;
    @Autowired
    SalesOrderLogic salesOrderLogic;
    @Autowired
    K3CustomerLogic k3CustomerLogic;
    @Autowired
    SalesChangeOrderLogic salesChangeOrderLogic;
    @Resource
    K3CommonMethodLogic k3CommonMethodLogic;
    @Resource
    InvoiceLogic invoiceLogic;
    @Resource
    KingDeeStockService kingDeeStockService;
    @Resource
    ReservedOrderItemService reservedOrderItemService;
    @Resource
    CommonCountMapper commonCountMapper;
    @Autowired
    EnginOrderRefundNoteService enginOrderRefundNoteService;
    @Autowired
    InvoiceMapper invoiceMapper;
    @Autowired
    CountMapper countMapper;
    @Autowired
    RetailOrderService retailOrderService;
    @Autowired
    RetailOrderItemService retailOrderItemService;
    @Autowired
    RetailOrderCommonMapper retailOrderCommonMapper;
    @Autowired
    ProductPriceService productPriceService;
    @Autowired
    PolicyWalletRelaService policyWalletRelaService;
    @Autowired
    PolicyMaterialService policyMaterialService;
    @Autowired
    AdminUserService adminUserService;
    @Autowired
    KingDeeMaterialService kingDeeMaterialService;
    @Autowired
    ProductPriceWalletService productPriceWalletService;
    @Autowired
    SaleTypeService saleTypeService;
    @Autowired
    PolicyCustomerService policyCustomerService;
    @Autowired
    PolicyCustomerLimitService policyCustomerLimitService;
    @Autowired
    AdminUserWebsitRelaService adminUserWebsitRelaService;
    @Resource
    InvoiceApplicationService invoiceApplicationService;
    @Resource
    KingDeeCustomerService kingDeeCustomerService;
    @Resource
    InvoiceApplicationOrderService invoiceApplicationOrderService;
    @Autowired
    AdminUserCategoryRelaService adminUserCategoryRelaService;
    @Autowired
    CommonCMapper commonCMapper;
    @Resource
    OrderExecRecordService orderExecRecordService;
    @Autowired
    PolicyGroupLimitService policyGroupLimitService;

    /**
     * 其他零售单列表-v2
     */
    public IPage<RetailOrderVO> retailOrderListV2(ExamineZfireParamBean examineZfireParamBean){
        AdminUserCom adminUser = commonLogic.getAdminUser();
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():null;
        ZfireParamBean zfireParamBean = FieldUtils.supplyParam(examineZfireParamBean);
        IPage<RetailOrderVO> page = commonCMapper.queryRetailOrder(new Page(examineZfireParamBean.getPageNum(), examineZfireParamBean.getPageSize()),
                zfireParamBean,customerId, examineZfireParamBean.getExamineStatus(), adminUser.getServiceIds(), adminUser.getK3CategoryIds());
        return page;
    }

    /**
     * 其他零售单列表-v2
     */
    public IPage<RetailOrderPolicyVO> policyOrderListV2(ExamineZfireParamBean examineZfireParamBean){
        AdminUserCom adminUser = commonLogic.getAdminUser();
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():null;
        ZfireParamBean zfireParamBean = FieldUtils.supplyParam(examineZfireParamBean);
        IPage<RetailOrderPolicyVO> page = commonCMapper.queryPolicyOrder(new Page(examineZfireParamBean.getPageNum(), examineZfireParamBean.getPageSize()),
                zfireParamBean,customerId, examineZfireParamBean.getExamineStatus(), adminUser.getServiceIds(), adminUser.getK3CategoryIds());
        return page;
    }



    /**
     * 列表
     * @return
     */
    public IPage<RetailOrderList> list(String customerWalletId,String saleTypeId,String id,String policyCode,String policyRemark,String serviceId,String k3ServiceId,String examineStatus,Integer type,String materialOldNumber,String materialCode,String materialName, String specification,String customer, String startTime,String endTime,String createBy,String examineBy,
                                       String stockId,Boolean isDirectTransfer,String k3CategoryNumber,Integer pageNum,Integer pageSize){
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():"";

        Integer total = retailOrderCommonMapper
                .queryRetailOrderCount(customerWalletId, saleTypeId, id, policyCode, policyRemark, serviceId, k3ServiceId, examineStatus, type, materialName,
                        specification, customer, customerId, adminUser.getServiceIds(), startTime, endTime, createBy, examineBy, adminUser.getAdminCompanyIds(),
                        isDirectTransfer, materialOldNumber, materialCode, k3CategoryNumber, adminUser.getK3CategoryIds());

        IPage<RetailOrderList> retailOrderListIPage = retailOrderCommonMapper
                .queryRetailOrderList(new Page(pageNum, pageSize,total,false),customerWalletId,saleTypeId, id,policyCode,policyRemark,serviceId,k3ServiceId, examineStatus,type, materialName,
                        specification, customer,customerId,adminUser.getServiceIds(), startTime, endTime, createBy, examineBy, adminUser.getAdminCompanyIds(),
                        isDirectTransfer,materialOldNumber,materialCode,k3CategoryNumber,adminUser.getK3CategoryIds());
        return retailOrderListIPage;
    }

    public PoySaleCountBean listCount(String id, String serviceId, String examineStatus, Integer type, String materialOldNumber, String materialCode, String materialName,
                                      String specification, String customer, String startTime, String endTime, String createBy, String examineBy,
                                      String stockId, Boolean isDirectTransfer){
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():"";
        PoySaleCountBean bean = commonCountMapper.retailOrderListCount(id,serviceId, examineStatus,type, materialName,
                specification, customer,customerId,adminUser.getServiceIds(), startTime, endTime, createBy, examineBy, adminUser.getAdminCompanyIds(),
                isDirectTransfer,materialOldNumber,materialCode);
        return bean;
    }

    public ExcelData export(List<RetailOrderList> list,Integer type){
        //普通零售单
        List<String> titles = null;
        if (type == 1) {
            titles = Arrays.asList("订单号","订单日期","销售类型","经销商编号","经销商名称","厂产品编码","物料编号","产品名称",
                    "规格型号","计量单位","是否直调","总数量","直调数量","单价",
                    "金额","返利使用比例","返利","制表人","制表日期","审核人","审核日期","审核状态","表头备注","表体备注","物料分组","存货类别");

        }else{
            //政策单
            titles = Arrays.asList("订单号","订单日期","销售类型","经销商编号","经销商名称","厂产品编码","销售政策编号","销售政策名称","销售政策说明","物料编号","产品名称",
                    "规格型号","计量单位", "是否直调","总数量","直调数量","单价","金额","返利使用比例","返利","制表人","制表日期","审核人","审核日期",
                    "审核状态","表头备注","表体备注","物料分组","存货类别");
        }
        List<List<Object>> rows = new ArrayList<>();
        for(RetailOrderList bean : list){
            List<Object> row = new ArrayList<>();
            // row.add(bean.getThjd());
//            row.add(bean.getId());
//            row.add(DateUtil.formatDate(bean.getTheTime()));
//            row.add(bean.getSaleTypeName());
//            row.add(bean.getCustomerNumber());
//            row.add(bean.getCustomerName());
//            row.add(bean.getMaterialOldNumber());
//            if(type == 1){
//
//            }else{
//                row.add(bean.getPolicyCode());
//                row.add(bean.getPolicyTitle());
//                row.add(bean.getPolicyRemark());
//            }
//            row.add(bean.getMaterialCode());
//            row.add(bean.getMaterialName());
//            row.add(bean.getSpecification());
//            row.add(bean.getUnit());
//            row.add(bean.getIsDirectTransfer()?"是":"否");
//            row.add(bean.getQty());
//            row.add(bean.getDirectTransferQty());
//            row.add(bean.getPrice());
//            row.add(bean.getPayAmount());
//            row.add(bean.getRebateRate());
//            row.add(bean.getPayRebateAmount());
//            row.add(bean.getCreateBy());
//            row.add(DateUtil.formatDate(bean.getCreateTime()));
//            row.add(bean.getExamineName());
//            if(bean.getExamineTime() !=null) {
//                row.add(DateUtil.formatDate(bean.getExamineTime()));
//            }else{
//                row.add("");
//            }
//            row.add(ExamineStatusEnum.valueOf(bean.getExamineStatus()).getMsg());
//            row.add(bean.getRemark());
//            row.add(bean.getItemRemark());
//            row.add(bean.getMaterialGroupName());
//            row.add(bean.getK3CategoryName());
            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setTitles(titles);
        excelData.setRows(rows);
        return excelData;
    }

    /**
     * 详情
     * @param id
     * @return
     */
    public RetailOrderBean detail(String id){
        RetailOrder retailOrder = retailOrderService.getById(id);
        RetailOrderBean retailOrderBean = new RetailOrderBean();
        BeanUtils.copyProperties(retailOrder,retailOrderBean);

        //明细
        List<RetailOrderItem> list = retailOrderItemService.lambdaQuery().eq(RetailOrderItem::getRetailOrderId, id).list();

        List<CustomerWalletBean> customerWalletBeans = walletLogic.queryWalletByCustomerId(retailOrder.getCustomerId(),null, null);
        //所有钱包的map  key = walletId
        Map<String, CustomerWalletBean> customerWalletMap = customerWalletBeans.stream()
                .collect(Collectors.toMap(CustomerWalletBean::getWalletRebateId, v -> v));

        //所有钱包的map  key = customerWalletId
        Map<String, CustomerWalletBean> customerWalletIdMap = customerWalletBeans.stream()
                .collect(Collectors.toMap(CustomerWalletBean::getCustomerWalletId, v -> v));

        //总的提货数量
        Integer takeQty = 0;
        List<RetailOrderItemBean> newList = new ArrayList<>();
        for(RetailOrderItem retailOrderItem : list){
            RetailOrderItemBean bean = new RetailOrderItemBean();
            BeanUtils.copyProperties(retailOrderItem,bean);

            if(retailOrder.getType() == 2) {
                PolicyMaterial policyMaterial = policyLogic.getPolicyMaterial(bean.getPolicyId(), bean.getMaterialId(), bean.getSaleTypeId());
                //现金钱包
                if(policyMaterial != null) {
                    List<CustomerWalletBean> customerWallets = this.supplyWallet2(policyMaterial.getId(), customerWalletMap, WalletTypeEnum.COMMONLY.getKey());
                    bean.setWallets(customerWallets);

                    //返利钱包
                    List<CustomerWalletBean> customerWallets2 = this.supplyWallet2(policyMaterial.getId(), customerWalletMap, WalletTypeEnum.REBATE.getKey());
                    List<CustomerWalletBean> rebateRate = CommonUtils.findRebateRate(customerWallets2, bean.getSaleTypeId());
                    bean.getRebateWallets().addAll(rebateRate);
                }

            }else{

                List<CustomerWalletBean> customerWallets = this.supplyWallet1(bean.getProductPriceId(), customerWalletMap,WalletTypeEnum.COMMONLY.getKey());
                bean.getWallets().addAll(customerWallets);

                //返利钱包
                List<CustomerWalletBean> customerWallets2 = this.supplyWallet1(bean.getProductPriceId(), customerWalletMap,WalletTypeEnum.REBATE.getKey());
                List<CustomerWalletBean> rebateRate = CommonUtils.findRebateRate(customerWallets2, bean.getSaleTypeId());
                bean.getRebateWallets().addAll(rebateRate);
            }

            if(CollectionUtils.isEmpty(bean.getWallets())){
                CustomerWalletBean customerWalletBean1 = customerWalletIdMap.get(bean.getCustomerWalletId());
                if(customerWalletBean1 != null) {
                    bean.getWallets().add(customerWalletBean1);
                }
                CustomerWalletBean customerWalletBean2 = customerWalletIdMap.get(bean.getCustomerWalletId2());
                if(customerWalletBean2 != null) {
                    bean.getRebateWallets().add(customerWalletBean2);
                }
            }


            //当前可用返利金额
            if (CollectionUtil.isNotEmpty(bean.getRebateWallets())) {
                List<CustomerWalletBean> curRebate = bean.getRebateWallets().stream()
                        .filter(v -> v != null && StringUtils.isNotEmpty(retailOrderItem.getCustomerWalletId2()) && v.getCustomerWalletId().equals(retailOrderItem.getCustomerWalletId2()))
                        .collect(Collectors.toList());
                if (curRebate.size() > 0) {
                    bean.setCurRebateAmount(curRebate.get(0).getAmount());
                }
            }

            bean.setRefundableQty(bean.getRefundableQty() - invoiceMapper.selectInvoice(retailOrderItem.getId()));
            newList.add(bean);

            //计算提货进度
            takeQty += retailOrderItem.getHasSendQty();
        }
        retailOrderBean.setThjd(BigDecimal.valueOf(ArithUtils.div(takeQty,retailOrder.getTotalQty(),4)));
        retailOrderBean.setRetailOrderItemList(newList);
        return retailOrderBean;
    }

    //零售单补充钱包数据
    public List<CustomerWalletBean> supplyWallet1(String productPriceId,Map<String, CustomerWalletBean> customerWalletMap,String type){

        List<ProductPriceWallet> productPriceWallets = productPriceWalletService.lambdaQuery()
                .eq(ProductPriceWallet::getProductPriceId, productPriceId)
                .list();
        List<CustomerWalletBean> list = new ArrayList<>();
        for (ProductPriceWallet productPriceWallet : productPriceWallets) {
            CustomerWalletBean customerWalletBean = customerWalletMap.get(productPriceWallet.getWalletId());
            if (customerWalletBean != null && customerWalletBean.getType().equals(type)) {
                list.add(customerWalletBean);
            }
        }
        return list;
    }

    //销售政策单补充钱包数据，销售政策的返利钱包是直接根据销售类型来匹配的
    public List<CustomerWalletBean> supplyWallet2(String policyMaterialId, Map<String, CustomerWalletBean> customerWalletMap,String type){
        List<PolicyWalletRela> policyWalletRelas = policyWalletRelaService.lambdaQuery()
                .eq(PolicyWalletRela::getPolicyMaterialId, policyMaterialId)
                .list();
        List<CustomerWalletBean> list = new ArrayList<>();
        for(PolicyWalletRela wallet : policyWalletRelas){
            CustomerWalletBean customerWalletBean = customerWalletMap.get(wallet.getWalletId());
            if(customerWalletBean != null && customerWalletBean.getType().equals(type)){
                list.add(customerWalletBean);
            }
        }
        return list;
    }

    /**
     * 直调完成
     */
    @Transactional
    public void transferOver(String id){
        RetailOrder retailOrder = retailOrderService.getById(id);
        if(retailOrder.getDirectTransferStatus()){
            throw new RemoteServiceException("已直调完成");
        }
        retailOrderItemService.lambdaUpdate()
                .set(RetailOrderItem::getDirectTransferStatus,true)
                .eq(RetailOrderItem::getIsDirectTransfer,true)
                .eq(RetailOrderItem::getRetailOrderId,id)
                .update();
        retailOrderService.lambdaUpdate()
                .set(RetailOrder::getDirectTransferStatus,true)
                .eq(RetailOrder::getId,id).update();

  /*      List<RetailOrderItem> items = retailOrderItemService.lambdaQuery().eq(RetailOrderItem::getRetailOrderId, id).list();
        for(RetailOrderItem item : items){
            BigDecimal amount = item.getSinglePayPrice().multiply(BigDecimal.valueOf(item.getDirectTransferQty()));
            String billType = retailOrder.getType() == 1 ? "零售单直调发货":"销售政策单直调发货";

            CustomerWallet customerWallet = walletLogic.queryCustomerWalletById(item.getCustomerWalletId());
            walletLogic.saveCustomerWalletRecord(customerWallet,amount,"直调发货",billType,new Date(),id,3,"OUT");
        }
*/
    }


    /**
     * 新增零售订单信息
     * @param retailOrderAdd
     */
    @Transactional
    public void add(RetailOrderAdd retailOrderAdd) throws Exception {

        AdminUserCom adminUser = commonLogic.getAdminUser();
        String policyId = retailOrderAdd.getPolicyId();
        Policy policy = null;
        if(!adminUser.getIsCustomer()){
            throw new RemoteServiceException("非经销商不可下单");
        }
        if(CollectionUtils.isEmpty(retailOrderAdd.getRetailOrderItemList())){
            throw new RemoteServiceException("请选择机型");
        }

        RetailOrder retailOrder = new RetailOrder();
        String idPrefix = "1";
        if(retailOrderAdd.getType() == 2){
            idPrefix = "2";

            policy = this.checkPolicy(policyId,adminUser,adminUser.getCustomerId());

            if (!policy.getCommercialType() && !retailOrderAdd.getIsPlanOrder())
                throw new RemoteServiceException("非商用政策，传非计划单有误");
        }
        retailOrder.setId(commonLogic.generateNo(idPrefix,"retailOrder",13));
        retailOrder.setAdminCompanyId(adminUser.getAdminCompanyId());
        retailOrder.setAdminUserId(adminUser.getAdminUserId());
        retailOrder.setAdminWebsitId(adminUser.getAdminWebsitId());
        retailOrder.setCustomerId(adminUser.getCustomerId());
        retailOrder.setCustomerName(adminUser.getCustomerName());
        retailOrder.setCustomerNumber(adminUser.getCustomerNumber());
        retailOrder.setRemark(retailOrderAdd.getRemark());
        retailOrder.setTheTime(new Date());
        retailOrder.setType(retailOrderAdd.getType());
        retailOrder.setK3ServiceId(retailOrderAdd.getK3ServiceId());
        retailOrder.setK3ServiceName(retailOrderAdd.getK3ServiceName());
        retailOrder.setFileNo(retailOrderAdd.getFileNo());
        retailOrder.setCreateName(adminUser.getNickName());
        retailOrder.setUpdateName(adminUser.getNickName());
        retailOrder.setIsPlanOrder(retailOrderAdd.getIsPlanOrder());
        retailOrder.setCorrespondId(retailOrderAdd.getCorrespondId());
        retailOrder.setCorrespondName(retailOrderAdd.getCorrespondName());
        retailOrder.setIsAllDirect(retailOrderAdd.getIsAllDirect());
        if(policy != null){
            retailOrder.setPolicyId(policyId);
            retailOrder.setPolicyCode(policy.getCode());
            retailOrder.setPolicyTitle(policy.getTitle());
            retailOrder.setPolicyRemark(policy.getRemark());
            retailOrder.setCommercialType(policy.getCommercialType());
            if (policy.getCommercialType().equals(0)){
                retailOrder.setIsPlanOrder(true);
            }
        }

        //处理明细
        retailOrderAdd.getRetailOrderItemList().forEach(v -> v.setId(null));
        this.addRetailOrderItem(retailOrder, retailOrderAdd.getRetailOrderItemList(),policy,true);
        //此处新增一定要在item下
        retailOrder.insert();

        //新增销售订单基础 add by ljh 2022-09-19 方便后续统一的订单管理，也方便合并统计
        commonLogic.addOrderBase(retailOrder.getId(),retailOrder.getType() == 1 ? OrderTypeEnum.RETAIL.getKey() : OrderTypeEnum.RETAIL_POLICY.getKey());
        submit(retailOrder.getId());
    }


    /**
     * 编辑零售订单信息
     */
    @Transactional
    public void update(RetailOrderAdd retailOrderAdd) throws InterruptedException {

        AdminUserCom adminUser = commonLogic.getAdminUser();
        RetailOrder retailOrder = retailOrderService.getById(retailOrderAdd.getId());
        Policy policy = null;
        String policyId = retailOrderAdd.getPolicyId();
        if(retailOrderAdd.getType() != null && retailOrderAdd.getType() == 2){
            policy = this.checkPolicy(policyId,adminUser,retailOrder.getCustomerId());
        }

        retailOrder.setId(retailOrderAdd.getId());
        retailOrder.setRemark(retailOrderAdd.getRemark());
        retailOrder.setK3ServiceId(retailOrderAdd.getK3ServiceId());
        retailOrder.setK3ServiceName(retailOrderAdd.getK3ServiceName());
        retailOrder.setFileNo(retailOrderAdd.getFileNo());
        retailOrder.setIsPlanOrder(retailOrderAdd.getIsPlanOrder());
        retailOrder.setCorrespondId(retailOrderAdd.getCorrespondId());
        retailOrder.setCorrespondName(retailOrderAdd.getCorrespondName());
        retailOrder.setIsAllDirect(retailOrderAdd.getIsAllDirect());
        if(StringUtils.isNotEmpty(retailOrderAdd.getTheTime())) {
            retailOrder.setTheTime(DateUtil.parseDateTime(retailOrderAdd.getTheTime()));
        }
        retailOrder.setUpdateName(adminUser.getNickName());
        //retailOrderItemService.lambdaUpdate().eq(RetailOrderItem::getRetailOrderId,retailOrderAdd.getId()).remove();
        if(CollectionUtils.isNotEmpty(retailOrderAdd.getRetailOrderItemList())) {
            //处理明细
            this.addRetailOrderItem(retailOrder, retailOrderAdd.getRetailOrderItemList(),policy,false);
        }
        if(policy != null){
            retailOrder.setPolicyId(policyId);
            retailOrder.setPolicyCode(policy.getCode());
            retailOrder.setPolicyTitle(policy.getTitle());
            retailOrder.setPolicyRemark(policy.getRemark());
        }

        retailOrder.updateById();
    }

    @Transactional
    public void delete(String id){
        RetailOrder retailOrder = retailOrderService.getById(id);
        if(!retailOrder.getExamineStatus().equals(ExamineStatusEnum.SAVE.toString())){
            throw new RemoteServiceException("非保存状态不可删除");
        }
        retailOrder.deleteById();
        retailOrderItemService.lambdaUpdate().eq(RetailOrderItem::getRetailOrderId,id).remove();
    }


    private Policy checkPolicy(String policyId,AdminUserCom adminUser,String customerId){
        Policy policy = policyLogic.detail(policyId);
        if(policy == null){
            return null;
        }
        if(StringUtils.isEmpty(customerId)){
            customerId = adminUser.getCustomerId();
        }
        if(policy.getFlag() == 0){
            //检查经销商是否可以下单
            Integer count = policyCustomerService.lambdaQuery()
                    .eq(PolicyCustomer::getPolicyId, policy.getId())
                    .eq(PolicyCustomer::getCustomerId, customerId).count();
            if(count == 0 ){
                throw new RemoteServiceException("非本销售政策适用经销商对象");
            }
        }else{
            if(adminUser != null && adminUser.getAdminWebsit() != null) {
                if ((adminUser.getAdminWebsit().getWebsitNumber().equals("GZ") && policy.getFlag() != 1)
                        || (adminUser.getAdminWebsit().getWebsitNumber().equals("FS") && policy.getFlag() != 2)) {
                    throw new RemoteServiceException("非本销售政策适用经销商对象");
                }
            }
        }
        return policy;
    }

    /**
     * 新增零售单明细
     * @param retailOrder
     * @param retailOrderItemList
     *
     *    如果是配提政策，前端传表体的policyMaterialId  其实是policy_condition_material的id，需注意
     */
    public void addRetailOrderItem(RetailOrder retailOrder,List<RetailOrderItemBean> retailOrderItemList,Policy policy,Boolean add) throws InterruptedException {
        String retailOrderId = retailOrder.getId();
        String customerId = retailOrder.getCustomerId();
        Integer type = retailOrder.getType();
        String adminUserId = retailOrder.getAdminUserId();
        //配提了多少套
        Integer groupNum = 0;

        if(CollectionUtils.isEmpty(retailOrderItemList)){
            return ;
        }
        //判断表头的业务员是否存在表体中
//        List<String> itemServiceIds = retailOrderItemList.stream().map(RetailOrderItem::getServiceId).distinct().collect(Collectors.toList());
//        if(StringUtils.isNotEmpty(retailOrder.getK3ServiceId()) && !itemServiceIds.contains(retailOrder.getK3ServiceId())){
//            throw new RemoteServiceException("表头业务员必须存在表体业务员中");
//        }
        if(!add && !StringUtils.equals(retailOrder.getExamineStatus(),ExamineStatusEnum.SAVE.toString())){
            throw new RemoteServiceException("非保存状态不可编辑");
        }
        //判断是否购买了同机型并同销售类型的机型
        Map<String,RetailOrderItemBean> checkProduct = new HashMap<>();
        for (RetailOrderItemBean retailOrderItemBean : retailOrderItemList) {
            if(checkProduct.containsKey(retailOrderItemBean.getMaterialId() + retailOrderItemBean.getSaleTypeId())){
                throw new RemoteServiceException("请勿重复选择同型号同销售类型的产品");
            }
            checkProduct.put(retailOrderItemBean.getMaterialId() + retailOrderItemBean.getSaleTypeId(),retailOrderItemBean);
        }
        //先清空机型
        retailOrderItemService.lambdaUpdate()
                .eq(RetailOrderItem::getRetailOrderId,retailOrderId)
                .remove();

        //政策机型的购买上限
        List<PolicyCustomerLimit> list = policyCustomerLimitService.lambdaQuery()
                .eq(PolicyCustomerLimit::getPolicyId, retailOrder.getPolicyId())
                .eq(PolicyCustomerLimit::getCustomerId, customerId).list();

        //政策的配提套数上限
        PolicyGroupLimit policyGroupLimit = policyGroupLimitService.lambdaQuery()
                .eq(PolicyGroupLimit::getPolicyId, retailOrder.getPolicyId())
                .eq(PolicyGroupLimit::getCustomerId, customerId).last("limit 1").one();

        //销售政策 type=1 普通零售单 type =2 销售政策单
        if(type == 2){

            retailOrder.setPolicyId(retailOrder.getPolicyCode());

            //政策单相关检查,如果是配提政策会返回配提了多少套，如果是限量政策则返回0
            groupNum = this.checkPolicy(retailOrder, retailOrderItemList, policy, add);

        }
        //查询钱包名称
        List<CustomerWalletBean> customerWalletBeans = walletLogic.queryWalletByCustomerId(customerId, null,null);

        Map<String, CustomerWalletBean> walletMap = customerWalletBeans.stream()
                .collect(Collectors.toMap(CustomerWalletBean::getCustomerWalletId, v -> v));

        //当前用户有用的存货品类权限
        List<AdminUserCategoryRela> adminUserCategoryRelas = adminUserCategoryRelaService.lambdaQuery().eq(AdminUserCategoryRela::getAdminUserId, adminUserId).list();
        Map<String, String> categoryMap = adminUserCategoryRelas.stream().collect(Collectors.toMap(AdminUserCategoryRela::getK3CategoryId, AdminUserCategoryRela::getK3CategoryName));

        //新增明细
        for(RetailOrderItemBean retailOrderItem : retailOrderItemList){
            SaleType saleType = saleTypeService.getById(retailOrderItem.getSaleTypeId());
            String policyId = retailOrderItem.getPolicyId();
            //单价
            BigDecimal price = BigDecimal.valueOf(0);
            //折扣价
            BigDecimal discAmount = BigDecimal.valueOf(0);
            String materialId = "";

            //检查是否有该分类权限
            if(adminUserCategoryRelas.size() > 0 && !categoryMap.containsKey(retailOrderItem.getK3CategoryId())){
                throw new RemoteServiceException("您暂无存货类别【"+retailOrderItem.getK3CategoryName()+"】的权限，请联系相关人员");
            }

            if(type == 2){
                //销售政策
                PolicyMaterial policyMaterial = policyLogic.getPolicyMaterial(policyId, retailOrderItem.getMaterialId(), retailOrderItem.getSaleTypeId());
                if(policyMaterial == null || !policyMaterial.getStatus()){
                    throw new RemoteServiceException("机型型号【"+retailOrderItem.getSpecification()+"】在当前政策中无效，请联系相关人员");
                }

                price = policyMaterial.getPrice();
                discAmount = policyMaterial.getDiscAmount();
                materialId = policyMaterial.getMaterialId();
                //这里覆盖下前端传错的参数
                retailOrderItem.setPolicyMaterialId(policyMaterial.getId());
                //补充下政策订单需要的参数
                retailOrderItem.setPriceType(policyMaterial.getPriceType());
                retailOrderItem.setOrgPrice(policyMaterial.getOrgPrice());
            }else {
                if(!add && StringUtils.isNotEmpty(retailOrderItem.getId())){
                    //零售单可以改单价,所以直接使用前端传的价格
                    price = retailOrderItem.getPrice();
                    //折扣价
                    discAmount = retailOrderItem.getDiscAmount();
                    materialId = retailOrderItem.getMaterialId();
                }else {
                    //零售
                    String productPriceId = retailOrderItem.getProductPriceId();
                    ProductPrice productPrice = productPriceService.getById(productPriceId);
                    if (productPrice == null) {
                        throw new RemoteServiceException("机型型号【" + retailOrderItem.getSpecification() + "】价格表失效，请联系相关人员");
                    }
                    //单价
                    price = productPrice.getBatchPrice();
                    //折扣价
                    discAmount = productPrice.getDiscAmount();
                    materialId = productPrice.getMaterialId();
                }

            }


            if(retailOrderItem.getQty() <= 0){
                throw new RemoteServiceException("数量必须大于等于1");
            }

            //现金钱包
            CustomerWalletBean amountCustomerWallet = walletMap.get(retailOrderItem.getCustomerWalletId());
            //返利钱包
            CustomerWalletBean rebateCustomerWallet = walletMap.get(retailOrderItem.getCustomerWalletId2());
            //数量
            BigDecimal qty = BigDecimal.valueOf(retailOrderItem.getQty());
            //总价
            BigDecimal totalAmount = price.multiply(qty);
            //总折扣价格
            BigDecimal totalDiscAmount = discAmount.multiply(qty);
            //实际支付价格
            BigDecimal payAmount = totalAmount.subtract(totalDiscAmount);
            //总返利价格
            BigDecimal totalRebateAmount = new BigDecimal(0);
            if(rebateCustomerWallet != null) {
                BigDecimal rebateRate = CommonUtils.getRebateRate(rebateCustomerWallet, retailOrderItem.getSaleTypeId());
                retailOrderItem.setRebateRate(rebateRate);
                totalRebateAmount = retailOrderItem.getRebateRate().multiply(payAmount);
            }
            //实际返利金额
            BigDecimal payRebateAmount = totalRebateAmount;
            if(rebateCustomerWallet != null){
                boolean subRebateAmountBol = rebateCustomerWallet.getAmount().doubleValue() < totalRebateAmount.doubleValue();
                if(subRebateAmountBol) {
                    payRebateAmount = rebateCustomerWallet.getAmount().doubleValue() > 0 ? rebateCustomerWallet.getAmount() : BigDecimal.valueOf(0);
                    //扣减当前返利钱包的钱，防止每次对比都是和原金额对比
                    rebateCustomerWallet.setAmount(BigDecimal.valueOf(0));
                }else{
                    //扣减当前返利钱包的钱，防止每次对比都是和原金额对比
                    rebateCustomerWallet.setAmount(rebateCustomerWallet.getAmount().subtract(totalRebateAmount));
                }

                walletMap.put(retailOrderItem.getCustomerWalletId2(),rebateCustomerWallet);
            }
            //实际支付价格
            payAmount = payAmount.subtract(payRebateAmount);

            //销售政策的限制
            if (type == 2) {
                //检查机型
                this.checkPolicyProduct(retailOrder,retailOrderItem,list,policyGroupLimit,groupNum);

                //检测返利钱包是否达标
                if(policy.getIsFullRebate() != null && policy.getIsFullRebate()
                        && (rebateCustomerWallet == null || totalRebateAmount.doubleValue() != payRebateAmount.doubleValue())){
                    throw new RemoteServiceException("机型【"+retailOrderItem.getMaterialName()+"】在当前政策必须使用返利钱包，且返利余额必须充足");
                }
            }

            KingDeeMaterial kingDeeMaterial = kingDeeMaterialService.getById(materialId);

            //检测钱包的合法性
            this.checkWallet(retailOrderItem,amountCustomerWallet,rebateCustomerWallet,type);

            retailOrderItem.setId(null);
            retailOrderItem.setFileNo(retailOrder.getFileNo());
            retailOrderItem.setAdminUserId(retailOrder.getAdminUserId());
            retailOrderItem.setAdminWebsitId(retailOrder.getAdminWebsitId());
            retailOrderItem.setIsUseRebate(StringUtils.isNotEmpty(retailOrderItem.getCustomerWalletId2()));
            retailOrderItem.setRetailOrderId(retailOrderId);
            retailOrderItem.setCustomerWalletName(amountCustomerWallet.getName());
            retailOrderItem.setCustomerWalletNumber(amountCustomerWallet.getWalletNumber());
            retailOrderItem.setWalletId1(amountCustomerWallet.getWalletRebateId());
            if(rebateCustomerWallet != null) {
                retailOrderItem.setCustomerWalletName2(rebateCustomerWallet.getName());
                retailOrderItem.setWalletId2(rebateCustomerWallet.getWalletRebateId());
            }
            if(kingDeeMaterial != null){
                retailOrderItem.setMaterialOldNumber(kingDeeMaterial.getOldNumber());
                retailOrderItem.setMaterialCode(kingDeeMaterial.getNumber());
                retailOrderItem.setK3CategoryId(kingDeeMaterial.getCategoryId());
                retailOrderItem.setK3CategoryNumber(kingDeeMaterial.getCategoryNumber());
                retailOrderItem.setK3CategoryName(kingDeeMaterial.getCategoryName());
            }
            if(saleType != null) {
                retailOrderItem.setSaleTypeCode(saleType.getSaleCode());
            }
            retailOrderItem.setServiceId(amountCustomerWallet.getServiceId());
            retailOrderItem.setServiceName(amountCustomerWallet.getServiceName());
            if(StringUtils.isEmpty(retailOrder.getK3ServiceId())){
                retailOrder.setK3ServiceId(retailOrderItem.getServiceId());
                retailOrder.setK3ServiceName(retailOrderItem.getServiceName());
            }
            //retailOrderItem.setSaleTypeCode();
            retailOrderItem.setPrice(price);
            retailOrderItem.setTotalAmount(totalAmount);
            retailOrderItem.setRebateAmount(totalRebateAmount.doubleValue() < 0?BigDecimal.valueOf(0):totalRebateAmount);
            retailOrderItem.setPayAmount(payAmount.doubleValue() < 0 ? BigDecimal.valueOf(0):payAmount);
            retailOrderItem.setPayRebateAmount(payRebateAmount);
            retailOrderItem.setSingleRebateAmount(payRebateAmount.divide(qty,6, RoundingMode.HALF_UP));
            retailOrderItem.setTotalDiscAmount(totalDiscAmount);
            retailOrderItem.setDiscAmount(discAmount);
            retailOrderItem.setSinglePayPrice(retailOrderItem.getPayAmount().divide(qty,6,RoundingMode.HALF_UP));
            //retailOrderItem.setPayCreditAmount(creditAmount);
            //retailOrderItem.setPayCashAmount(retailOrderItem.getPayAmount().subtract(creditAmount));
            retailOrderItem.setRefundableQty(retailOrderItem.getQty());
            retailOrderItem.setOldPayAmount(retailOrderItem.getPayAmount());
            retailOrderItem.setOldQty(retailOrderItem.getQty());
        }

        Integer totalQty = 0;
        BigDecimal totalAmount = new BigDecimal(0);
        for(RetailOrderItem retailOrderItem : retailOrderItemList){
            totalQty += retailOrderItem.getQty();
            totalAmount = totalAmount.add(retailOrderItem.getTotalAmount());
            //新增
            retailOrderItem.insert();
        }
        retailOrder.setTotalAmount(totalAmount);
        retailOrder.setTotalQty(totalQty);
    }

    /**
     * 政策订单相关检查
     */
    public Integer checkPolicy(RetailOrder retailOrder,List<RetailOrderItemBean> retailOrderItemList,Policy policy,Boolean add){
        String customerId = retailOrder.getCustomerId();
        String retailOrderId = retailOrder.getId();
        //检测前端传参是否有异常，表体是否存在和表头不同的政策id
        long count = retailOrderItemList.stream().filter(v -> !v.getPolicyId().equals(retailOrder.getPolicyId())).count();
        if(count > 0){
            throw new RemoteServiceException("检测到您的订单存在异常参数，请重新下单或者联系相关人员");
        }

        if(policy.getType().equals(PolicyTypeEnum.PROVISION.toString())) {

            if(CollectionUtils.isNotEmpty(retailOrderItemList) && retailOrderItemList.size() <= 1){
                throw new RemoteServiceException("配提政策请购买最少2个机型");
            }

            List<PolicyCondition> policyConditions = policyLogic.getConditionByPolicyId(retailOrder.getPolicyId());

            //有配置政策条件且有购买限定机型的需要检查配比是否正确
            if (CollectionUtils.isEmpty(policyConditions)) {
                throw new RemoteServiceException("配提条件不存在,请联系相关人员");
            }

            //判断配比是否正确
            int groupNum = this.checkPop(retailOrderItemList);
            return groupNum;

        }else{
            //限制限量政策，最小提货数，最大提货组数
            Integer totalQty = retailOrderItemList.stream().map(RetailOrderItemBean::getQty).reduce(Integer::sum).orElse(0);
            Integer minBuyNum = policy.getMinBuyNum();
            Integer maxBuyNum = policy.getMaxBuyNum();

            //查询是否有单独设置最少起提数和最大提货组数
            PolicyGroupLimit policyGroupLimit = getPolicyGroupLimit(policy.getId(), customerId);
            if(policyGroupLimit != null){
                minBuyNum = policyGroupLimit.getMinBuyNum();
                maxBuyNum = policyGroupLimit.getMaxBuyNum();
            }

            //最小提货数
            if(minBuyNum != null && minBuyNum.intValue() != 0 && minBuyNum.intValue() > totalQty.intValue()){
                throw new RemoteServiceException("当前政策限制最小提货数为"+minBuyNum+",请检查总购买机型数量");
            }
            //同集团的经销商id
            //List<String> customerIds = k3CustomerLogic.getGroupCustomerId(customerId);
            List<String> customerIds = Arrays.asList(customerId);
            Integer orderCount = retailOrderService.lambdaQuery()
                    .in(RetailOrder::getCustomerId, customerIds)
                    .eq(RetailOrder::getPolicyId,policy.getId())
                    .ne(add != null && !add,RetailOrder::getId,retailOrderId)
                    .count();

            if(maxBuyNum != null && maxBuyNum.intValue() != 0 && maxBuyNum.intValue() <= orderCount.intValue()){
                throw new RemoteServiceException("当前政策限制最大提货组数为"+maxBuyNum+",请检查所属集团或当前帐号在此政策已下单数量");
            }
            return 0;
        }
    }

    /**
     * 政策订单机型购买上限限制
     */
    public void checkPolicyProduct(final RetailOrder retailOrder,RetailOrderItemBean retailOrderItem,
                                   List<PolicyCustomerLimit> limitList,PolicyGroupLimit policyGroupLimit,Integer groupNum){
        String customerId = retailOrder.getCustomerId();
        String policyId = retailOrderItem.getPolicyId();
        String materialId = retailOrderItem.getMaterialId();
        String retailOrderId = retailOrderItem.getRetailOrderId();
        if(CollectionUtils.isEmpty(limitList)){
            return;
        }

        Map<String, Integer> limitMap = limitList.stream()
                .collect(Collectors.toMap(PolicyCustomerLimit::getMaterialId, PolicyCustomerLimit::getLimitQty));

        List<RetailOrder> retailOrders = retailOrderService.lambdaQuery().eq(RetailOrder::getCustomerId, customerId).list();
        List<String> retailOrderIds = retailOrders.stream().map(RetailOrder::getId).collect(Collectors.toList());
        //检测是否符合购买上限
        List<RetailOrderItem> retailOrderItems = new ArrayList<>();
        if(retailOrderIds.size() > 0) {
            retailOrderItems = retailOrderItemService.lambdaQuery()
                    .eq(RetailOrderItem::getPolicyId, policyId)
                    .eq(RetailOrderItem::getMaterialId, materialId)
                    .in(RetailOrderItem::getRetailOrderId, retailOrderIds)
                    .ne(StringUtils.isNotEmpty(retailOrderId), RetailOrderItem::getRetailOrderId, retailOrderId)
                    .list();
        }
        int oldTotalQty = 0;
        if(retailOrderItems.size() > 0) {
            oldTotalQty =  retailOrderItems.stream().mapToInt(RetailOrderItem::getQty).sum();
        }
        if(limitMap != null && limitMap.get(materialId) != null) {
            Integer limitQty = limitMap.get(materialId);
            if (limitQty != 0 && limitQty.intValue() < oldTotalQty + retailOrderItem.getQty()) {
                throw new RemoteServiceException("机型【" + retailOrderItem.getSpecification() + "】已超过最大购买上限");
            }
        }
        //配提套数上限限制
        if(policyGroupLimit != null && policyGroupLimit.getGroupLimitNum() != 0) {
            Integer popQty = policyGroupLimit.getGroupLimitNum();
            if (popQty != null && popQty != 0 && groupNum.intValue() > popQty.intValue()) {
                throw new RemoteServiceException("您已超过允许购买的最大配提上限，请联系相关人员");
            }
        }
    }

    /**
     * 检测政策单下单时钱包的合法性
     * @param retailOrderItem
     * @param amountCustomerWallet 现金钱包
     * @param rebateCustomerWallet 返利钱包(可能为空)
     * @param type 1=零售  2=政策
     */
    public void checkWallet(RetailOrderItemBean retailOrderItem, CustomerWalletBean amountCustomerWallet,CustomerWalletBean rebateCustomerWallet,Integer type){
        if(amountCustomerWallet == null){
            log.info("【请选择现金钱包】:{}",JSONObject.toJSONString(retailOrderItem));
            throw new RemoteServiceException("请选择现金钱包");
        }
        if(rebateCustomerWallet != null && !amountCustomerWallet.getIsRebate()){
            throw new RemoteServiceException(amountCustomerWallet.getName() + "不允许搭配使用返利钱包");
        }
        if(StringUtils.isEmpty(amountCustomerWallet.getServiceId())){
            throw new RemoteServiceException("钱包【"+amountCustomerWallet.getName()+"】未绑定业务员，无法下单");
        }

        //其他零售机
        if(type == 1 && StringUtils.isNotEmpty(retailOrderItem.getProductPriceId())){
            List<ProductPriceWallet> productPriceWallets = productPriceWalletService
                    .lambdaQuery().eq(ProductPriceWallet::getProductPriceId, retailOrderItem.getProductPriceId()).list();
            List<String> walletIds = productPriceWallets.stream().map(ProductPriceWallet::getWalletId).collect(Collectors.toList());
            if(!walletIds.contains(amountCustomerWallet.getWalletRebateId())){
                throw new RemoteServiceException(retailOrderItem.getSpecification()+"的现金钱包【"+amountCustomerWallet.getName()+"】不能使用");
            }
            if(rebateCustomerWallet != null && !walletIds.contains(rebateCustomerWallet.getWalletRebateId())){
                throw new RemoteServiceException(retailOrderItem.getSpecification()+"返利钱包【"+rebateCustomerWallet.getName()+"】不能使用");
            }
        }else if(type == 2){
            //如果是配提政策，前端传的policyMaterialId其实是政策条件机型的id（policyConditionMaterialId）
            List<PolicyWalletRela> policyWalletRelas = policyWalletRelaService
                    .lambdaQuery().eq(PolicyWalletRela::getPolicyId,retailOrderItem.getPolicyId())
                    .eq(PolicyWalletRela::getPolicyMaterialId, retailOrderItem.getPolicyMaterialId())
                    .list();
            List<String> walletIds = policyWalletRelas.stream().map(PolicyWalletRela::getWalletId).collect(Collectors.toList());
            if(!walletIds.contains(amountCustomerWallet.getWalletRebateId())){
                throw new RemoteServiceException(retailOrderItem.getSpecification()+"现金钱包【"+amountCustomerWallet.getName()+"】不能使用");
            }
            if(rebateCustomerWallet != null && !walletIds.contains(rebateCustomerWallet.getWalletRebateId())){
                throw new RemoteServiceException(retailOrderItem.getSpecification()+"返利钱包【"+rebateCustomerWallet.getName()+"】不能使用");
            }
        }
    }


    public PolicyGroupLimit getPolicyGroupLimit(String policyId,String customerId){
        PolicyGroupLimit policyGroupLimit = policyGroupLimitService.lambdaQuery()
                .eq(PolicyGroupLimit::getPolicyId, policyId)
                .eq(PolicyGroupLimit::getCustomerId, customerId)
                .last(" limit 1")
                .one();
        return policyGroupLimit;
    }


    /**
     * 退订
     * @param retailOrderRefundBean 退订的商品明细
     * @return
     * @throws InterruptedException
     */
    @Transactional
    public List<Map<String, Object>> tuiding(RetailOrderRefundBean retailOrderRefundBean) throws InterruptedException {
        List<RetailOrderItemBean> retailOrderItemList = retailOrderRefundBean.getRetailOrderItemList();
        RetailOrder retailOrder = retailOrderService.getById(retailOrderRefundBean.getId());
        if(!retailOrder.getExamineStatus().equals(ExamineStatusEnum.OK.toString())){
            throw new RemoteServiceException("非审核通过订单不可退订");
        }
        AdminUserCom adminUser = commonLogic.getAdminUser();
        if(adminUser.getIsCustomer()){
            throw new RemoteServiceException("暂无权限操作");
        }
        List<Map<String, Object>> resultMap = new ArrayList<>();
        //需要终结的
        List<String> endItemIds = new ArrayList<>();
        Map<String,Object> map = new HashMap<>();
        List<RefundOrderItem> refundOrderItems = new ArrayList<>();
        List<RetailOrderItem> execRecords = new ArrayList<>();
        for(RetailOrderItemBean retailOrderItem : retailOrderItemList) {
            RetailOrderItem item = retailOrderItemService.getById(retailOrderItem.getId());

            //退订数量
            int tdQty = (retailOrderItem.getTdQty() == null ? 0 : retailOrderItem.getTdQty());
            //订单明细的退订
            Map<String, Object> paramsMap = this.refundItem(item,tdQty);
            resultMap.add(paramsMap);
            //钱包金额的退订
            this.refund(item,tdQty);
            //组装终结接口的金蝶内码id
            if(retailOrderItem.getQty() == 0 && tdQty > 0){
                endItemIds.add(retailOrderItem.getKingDeeEntryId());
            }
            map.put(item.getId(),retailOrderItem.getQty());

            //预留单更改，当数量变为0，修改预留单预留为0，关闭
            if (retailOrderItem.getRefundableQty().equals(0)) {
                reservedOrderItemService.lambdaUpdate().eq(ReservedOrderItem::getOrderId, retailOrderItem.getId())
                        .set(ReservedOrderItem::getStatus,0)
                        .set(ReservedOrderItem::getReservedNum,0).update();
            }

            if (tdQty > 0 && Objects.nonNull(paramsMap.get("refundOrderItem")))
                refundOrderItems.add((RefundOrderItem) paramsMap.get("refundOrderItem"));

            if (tdQty > 0 && Objects.nonNull(paramsMap.get("execRecord")))
                execRecords.add((RetailOrderItem) paramsMap.get("execRecord"));
        }

        //金蝶变更单
        this.pushSalesChange(retailOrder.getKingDeeId(),retailOrder.getId(),"",map,endItemIds);

        if (CollectionUtil.isNotEmpty(execRecords))
            this.insertOrderRecord(retailOrder, execRecords, OrderOperationTypeEnum.ORDER_REFUND, "订单退订");

        return resultMap;
    }


    /**
     * 订单明细退订处理(不处理钱包的钱，只处理明细数量和订单里的钱)
     * @param retailOrderItem 订单明细
     * @param itemTdQty 退订明细数量
     * @return 退订现金金额
     */
    public Map<String, Object> refundItem(RetailOrderItem retailOrderItem, Integer itemTdQty){
        RetailOrderItem item = retailOrderItemService.getById(retailOrderItem.getId());
        //退订数量
        int tdQty = (itemTdQty == null ? 0 : itemTdQty);

        if (item.getRefundableQty() - invoiceMapper.selectInvoice(retailOrderItem.getId()) < tdQty){
            throw new RemoteServiceException("检测到订单可退数量小于退订数量，不可退订");
        }
        //退订金额
        BigDecimal tdAmount = retailOrderItem.getSinglePayPrice().multiply(BigDecimal.valueOf(tdQty));
        if(item.getQty() == tdQty){
            tdAmount = retailOrderItem.getPayAmount();
        }
        //退订的实际返利金额
        BigDecimal tdPayRebateAmount = retailOrderItem.getSingleRebateAmount().multiply(BigDecimal.valueOf(tdQty));
        if(item.getQty() == tdQty){
            tdPayRebateAmount = retailOrderItem.getPayRebateAmount();
        }
        //退订折扣金额
        BigDecimal tdDiscAmount = retailOrderItem.getDiscAmount().multiply(BigDecimal.valueOf(tdQty));
        if(item.getQty() == tdQty){
            tdDiscAmount = retailOrderItem.getTotalDiscAmount();
        }
        //剩余金额
        BigDecimal balanceNewPrice = retailOrderItem.getPayAmount().subtract(tdAmount);
        //剩余返利金额
        BigDecimal balanceRebateAmount = retailOrderItem.getPayRebateAmount().subtract(tdPayRebateAmount);
        //剩余折扣金额
        BigDecimal balanceDiscAmount = retailOrderItem.getTotalDiscAmount().subtract(tdDiscAmount);

        if(tdQty < 0){
            throw new RemoteServiceException("退订数量不可为负数");
        }
        if(tdQty > item.getRefundableQty().intValue()){
            throw new RemoteServiceException("机型:"+item.getSpecification()+"退货数量不可大于可退数量");
        }
        //处理数量
        retailOrderItem.setRefundableQty(item.getRefundableQty() - tdQty);
        retailOrderItem.setRetiredQty(item.getRetiredQty() + tdQty);
        retailOrderItem.setQty(retailOrderItem.getQty() - tdQty);

        //处理金额
        retailOrderItem.setPayAmount(balanceNewPrice.doubleValue() < 0 ? BigDecimal.valueOf(0) : balanceNewPrice);
        retailOrderItem.setPayRebateAmount(balanceRebateAmount.doubleValue() < 0 ? BigDecimal.valueOf(0) : balanceRebateAmount);
        retailOrderItem.setTotalDiscAmount(balanceDiscAmount.doubleValue() < 0 ? BigDecimal.valueOf(0) : balanceDiscAmount);
        retailOrderItem.setTotalAmount(retailOrderItem.getPrice().multiply(BigDecimal.valueOf(retailOrderItem.getQty())));

        retailOrderItem.updateById();

        Map<String, Object> paramsMap = new HashMap<>();
        if (tdQty > 0) {
            RetailOrderItem execRecord = new RetailOrderItem();
            BeanUtils.copyProperties(item, execRecord);
            execRecord.setQty(tdQty)
                    .setTotalAmount(item.getPrice().multiply(BigDecimal.valueOf(tdQty)))
                    .setTotalDiscAmount(tdDiscAmount)
                    .setPayRebateAmount(tdPayRebateAmount)
                    .setPayAmount(tdAmount);

            paramsMap.put("execRecord", execRecord);
        }

        paramsMap.put("tdAmount", tdAmount);

        return paramsMap;
    }





    /**
     * 金蝶变更单
     * @param kingDeeId
     * @param enginOrderNo
     * @param remark
     * @param orderItems
     * @param endItemIds
     */
    public void pushSalesChange(String kingDeeId,String enginOrderNo,String remark,Map<String,Object> orderItems,List<String> endItemIds) {
        if(StringUtils.isEmpty(kingDeeId)){
            return;
        }
        // 检查是否需要调用业务终止明细
        if (CollectionUtil.isNotEmpty(endItemIds) && endItemIds.size() > 0) {
            RequestExcuteOperationBean bean = new RequestExcuteOperationBean();
            bean.setIds(kingDeeId);
            bean.setPkEntryIds(kingDeeId, String.join(",", endItemIds));
            salesOrderLogic.excuteOperationEnd(bean);
            // 插入终止退订说明
            enginOrderRefundNoteService.save(new EnginOrderRefundNote()
                    .setEnginOrderNo(enginOrderNo)
                    .setRefundNote(enginOrderNo + ">" + String.join(",", endItemIds)));
        }

        if (CollectionUtil.isNotEmpty(endItemIds) && endItemIds.size() == orderItems.size()) {
            return;
        }

        ResultEntity resultEntity = salesOrderLogic.pushSalesChange(kingDeeId, null);
        String refundNo = IdWorker.getIdStr();
        SalesChangeBean salesChangeBean = new SalesChangeBean();
        salesChangeBean.setId(resultEntity.getId());
        salesChangeBean.setBillNo(refundNo);
        salesChangeBean.setNote(enginOrderNo);
        salesChangeBean.setRemark(StringUtils.isBlank(remark)?"退订":remark);

        List<SalesChangeItemBean> items = new ArrayList<>(10);
        for (BillItem billItem : resultEntity.getItems()) {
            Integer qty = (Integer)orderItems.get(billItem.getSupplyColVal());
            if(qty == null || qty == 0){
                continue;
            }
            SalesChangeItemBean salesChangeItemBean = new SalesChangeItemBean();
            salesChangeItemBean.setEntryId(billItem.getEntryId());
            salesChangeItemBean.setQty(BigDecimal.valueOf(qty));
            items.add(salesChangeItemBean);
        }
        salesChangeBean.setOrderItems(items);
        salesChangeOrderLogic.syncBillData(salesChangeBean);

        // 插入退订说明
        enginOrderRefundNoteService.save(new EnginOrderRefundNote()
                .setEnginOrderNo(enginOrderNo)
                .setRefundNote(remark)
                .setKingDeeId(resultEntity.getId())
                .setRefundNo(refundNo));
    }


    /**
     * 检查配比是否正确
     * @param list
     * @return 政策配提 套购数量
     */
    private int checkPop(List<RetailOrderItemBean> list){
        List<String> policyConditionIds = list.stream().map(RetailOrderItem::getPolicyConditionId).distinct().collect(Collectors.toList());
        Map<String,List<RetailOrderItem>> map = new HashMap<>();
        for(String policyConditionId : policyConditionIds){
            List<RetailOrderItem> items = list.stream().filter(v -> StringUtils.equals(v.getPolicyConditionId(),policyConditionId)).collect(Collectors.toList());
            if(StringUtils.isEmpty(policyConditionId) || CollectionUtils.isEmpty(items)){
                throw new RemoteServiceException("该销售政策有购买条件，请选择条件购买");
            }
            if(map.containsKey(policyConditionId)){
                map.get(policyConditionId).addAll(items);
            }else {
                map.put(policyConditionId, items);
            }
        }
        int groupNum = 1;
        //检查
        for(String policyConditionId : map.keySet()){
            PolicyCondition condition = policyLogic.getCondition(policyConditionId);
            if(condition == null){
                throw new RemoteServiceException("政策条件不存在请联系相关人员");
            }
            List<RetailOrderItem> retailOrderItems = map.get(policyConditionId);

            String pop = condition.getPop();
            String[] split = pop.split(":");
            //检查配提购买的机型是否大于等于限定机型购买的倍数，
            //倍数 num = 购买的数量 / 所属比例
            double num = -1;
            for(int i = 1;i <= split.length;i++){
                int a = i;
                int rate = Integer.parseInt(split[i-1]);
                int sum = retailOrderItems.stream().filter(v -> v.getPopType() == a).mapToInt(RetailOrderItem::getQty).sum();
                double div = sum / rate;
                if(div == 0)
                    throw new RemoteServiceException("检查到配比不正确");

//                if(i == 1 && sum % rate != 0)
//                    throw new RemoteServiceException("限定机型购买数量必须是"+rate+"的倍数");
//
//                if(num != -1 && num > div)
//                    throw new RemoteServiceException("检查到配比不正确");

                if(sum % rate != 0)
                    throw new RemoteServiceException("机型购买数量必须是政策对应比例的整倍数");

                if(num != -1 && num != div)
                    throw new RemoteServiceException("检查到配比不正确");

                if(i == 1) {
                    num = div;
                }

                groupNum = (int)div;
            }
        }
        return groupNum;
    }

    /**
     * 提审
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void submit(String id) throws Exception {
        //零售单表头
        RetailOrder retailOrder = retailOrderService.getById(id);
        if(!retailOrder.getExamineStatus().equals(ExamineStatusEnum.SAVE.toString())){
            throw new RemoteServiceException("请勿重复提审");
        }
        if(retailOrder.getType() == 2){
            Policy policy = policyLogic.detail(retailOrder.getPolicyId());
            if(policy == null || !policy.getStatus() || policy.getEndTime().getTime() < new Date().getTime() || policy.getStartTime().getTime() > new Date().getTime()){
                throw new RemoteServiceException("政策已失效，无法提审");
            }
        }
        //零售单表体
        List<RetailOrderItem> list = retailOrderItemService.lambdaQuery().eq(RetailOrderItem::getRetailOrderId, id).list();

        //重新刷新次要计算的金额
        List<RetailOrderItemBean> beanList = new ArrayList<>();
        for (RetailOrderItem retailOrderItem : list) {
            RetailOrderItemBean bean = new RetailOrderItemBean();
            BeanUtils.copyProperties(retailOrderItem,bean);
            beanList.add(bean);
        }
        RetailOrderAdd retailOrderAdd = new RetailOrderAdd();
        BeanUtils.copyProperties(retailOrder,retailOrderAdd);
        retailOrderAdd.setRetailOrderItemList(beanList);
        this.update(retailOrderAdd);

        //提审扣钱
        List<CustomerWalletAmountBean> walletAmountBeans = new ArrayList<>();
        for(RetailOrderItem retailOrderItem : retailOrderAdd.getRetailOrderItemList()) {
            //检查是否存在未确认的返利单
            rebateOrderLogic.checkNeedAck(retailOrderItem.getCustomerWalletId2());

            //扣现金钱包
            walletAmountBeans.add(new CustomerWalletAmountBean(retailOrderItem.getCustomerWalletId(), retailOrderItem.getPayAmount(),
                    retailOrderItem.getRemark(), "零售单扣款",
                    retailOrder.getTheTime(), retailOrder.getId(), 2,"sub"));
            //扣返利钱包
            walletAmountBeans.add(new CustomerWalletAmountBean(retailOrderItem.getCustomerWalletId2(), retailOrderItem.getPayRebateAmount(),
                    retailOrderItem.getRemark(), "零售单返利扣款",
                    retailOrder.getTheTime(), retailOrder.getId(), 0,"sub"));
        }
        walletLogic.doWalletAmount(walletAmountBeans);

        retailOrder.setTheTime(new Date());
        retailOrder.setExamineStatus(ExamineStatusEnum.WAIT.toString());
        retailOrder.updateById();

        //单且为非计划单 发货
        if(!retailOrder.getIsPlanOrder() && retailOrder.getType() == 2 ){
            Policy policy = policyLogic.detail(retailOrder.getPolicyId());
            if (!policy.getCommercialType())
                return;

            List<RetailOrderItem> listSales = retailOrderItemService.lambdaQuery().eq(RetailOrderItem::getRetailOrderId, id).list();
            invoiceAddProject(retailOrder,listSales);
        }
    }


    private void invoiceAddProject(RetailOrder retailOrder, List<RetailOrderItem> orderItems) throws Exception {
        InvoiceRequestJson invoiceRequestJson = BeanUtil.toBean(retailOrder, InvoiceRequestJson.class);
        invoiceRequestJson.setId(null);
        invoiceRequestJson.setExamineStatus("WAIT");
        invoiceRequestJson.setAutomaticStatus(true);
        invoiceRequestJson.setSyncType(2);
        invoiceRequestJson.setType(1);
        if (StringUtils.isEmpty(retailOrder.getCorrespondId()) && retailOrder.getIsPlanOrder() != null && !retailOrder.getIsPlanOrder())
            throw new RemoteServiceException("仓库为空，请选择仓库");
        invoiceRequestJson.setCorrespondId(retailOrder.getCorrespondId());
        invoiceRequestJson.setCorrespondName(retailOrder.getCorrespondName());
        List<InvoiceApplicationOrderRequest> invoiceApplicationOrderRequests = new ArrayList<>();
        for (RetailOrderItem orderItem : orderItems) {
            InvoiceApplicationOrderRequest invoiceApplicationOrderRequest = BeanUtil.toBean(orderItem, InvoiceApplicationOrderRequest.class);
            invoiceApplicationOrderRequest.setId(null);
            invoiceApplicationOrderRequest.setMainOrderId(retailOrder.getId());
            invoiceApplicationOrderRequest.setOrderType(retailOrder.getType().equals(1)?"RETAIL":"RETAIL_POLICY");
            invoiceApplicationOrderRequest.setOrderId(orderItem.getId());
            invoiceApplicationOrderRequest.setInvoiceNum(orderItem.getRefundableQty());
            invoiceApplicationOrderRequest.setTheTime(retailOrder.getTheTime());
            invoiceApplicationOrderRequest.setMaterialCode(orderItem.getMaterialCode());
            invoiceApplicationOrderRequest.setMaterialId(orderItem.getMaterialId());
            invoiceApplicationOrderRequest.setHeaderRemark(retailOrder.getRemark());
            invoiceApplicationOrderRequest.setRemark(orderItem.getRemark());
            invoiceApplicationOrderRequests.add(invoiceApplicationOrderRequest);
        }
        invoiceRequestJson.setOrders(invoiceApplicationOrderRequests);
        invoiceLogic.add(invoiceRequestJson);
    }


    /**
     * 撤回提审
     */
    @Transactional(rollbackFor = Exception.class)
    public void submitCancel(String id) throws Exception {
        RetailOrder retailOrder = retailOrderService.getById(id);
        if(!retailOrder.getExamineStatus().equals(ExamineStatusEnum.WAIT.toString())){
            throw new RemoteServiceException("无法撤回提审");
        }
        retailOrder.setExamineStatus(ExamineStatusEnum.SAVE.toString());
        retailOrder.updateById();

        //不通过，直接退钱
        //全退
        this.refundAll(retailOrder);
        //需要删除台账记录
        walletLogic.deleteCustomerWalletRecord(retailOrder.getId());

        //删除发货单，撤回
        if (!retailOrder.getIsPlanOrder()) {
            //删除发货单
            InvoiceApplicationOrder one = invoiceApplicationOrderService.lambdaQuery().eq(InvoiceApplicationOrder::getMainOrderId, retailOrder.getId()).last("limit 1").one();
            invoiceLogic.submit(one.getInvoiceId(), "SAVE");
            invoiceLogic.delete(one.getInvoiceId());
        }
    }

    /**
     * 审核
     * @param id
     * @param examineStatus
     * @param examineRemark
     */
    @Transactional(rollbackFor = Exception.class)
    public void examine(String id,String examineStatus,String examineRemark,String remark,String fileNo,String serviceId) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        RetailOrder retailOrder = retailOrderService.getById(id);
        if(!retailOrder.getExamineStatus().equals(ExamineStatusEnum.WAIT.toString())){
            throw new RemoteServiceException("非待审核单据不可审核");
        }
        if(adminUser.getIsCustomer()){
            throw new RemoteServiceException("暂无权限操作");
        }
        //驳回直接变回保存状态
        retailOrder.setRemark(remark);
        retailOrder.setExamineStatus(examineStatus.equals(ExamineStatusEnum.FAIL.toString())?ExamineStatusEnum.SAVE.toString():examineStatus);
        retailOrder.setExamineName(adminUser.getNickName());
        retailOrder.setExamineRemark(examineRemark);
        retailOrder.setExamineBy(adminUser.getUserName());
        retailOrder.setExamineTime(new Date());
        retailOrder.setFileNo(fileNo);
        if(StringUtils.isNotEmpty(serviceId)){
            retailOrder.setK3ServiceId(serviceId);
        }

        List<RetailOrderItem> retailOrderItems = retailOrderItemService.lambdaQuery()
                .eq(RetailOrderItem::getRetailOrderId, id).list();

        //审核通过
        if(StringUtils.equals(examineStatus,ExamineStatusEnum.OK.toString())){
            //update by ljh 2022-09-22 改成从出库单同步
           /* ResultEntity resultEntity = this.toK3(retailOrder, retailOrderItems);
            if(resultEntity == null) {
                throw new RemoteServiceException("同步金蝶单据失败");
            }
            retailOrder.setK3SyncStatus(true);
            retailOrder.setKingDeeSync(K3SyncStatusEnum.SALES.toString());
            retailOrder.setKingDeeId(resultEntity.getId());
            if (StringUtils.isNotBlank(resultEntity.getId())) {
                Map<String, BillItem> map = resultEntity.getItems().stream()
                        .collect(Collectors.toMap(billItem -> billItem.getSupplyColVal() + billItem.getMaterialId(), Function.identity()));
                for (RetailOrderItem item : retailOrderItems) {
                    BillItem billItem = map.get(item.getId() + item.getMaterialId());
                    item.setKingDeeSeq(billItem.getSeq());
                    item.setKingDeeEntryId(billItem.getEntryId());
                }
            }*/
            this.insertOrderRecord(retailOrder, retailOrderItems, OrderOperationTypeEnum.ORDER_EXAMINE, "订单审批");
        }else if(StringUtils.equals(examineStatus,ExamineStatusEnum.FAIL.toString())){
            //全退
            this.refundAll(retailOrder);
            //不通过的要删掉记录
            //walletLogic.deleteCustomerWalletRecord(retailOrder.getId());

        }

        if (!retailOrder.getIsPlanOrder() && StringUtils.equals(examineStatus,ExamineStatusEnum.FAIL.toString())) {
            //删除发货单
            InvoiceApplicationOrder one = invoiceApplicationOrderService.lambdaQuery().eq(InvoiceApplicationOrder::getMainOrderId, retailOrder.getId()).last("limit 1").one();
            invoiceLogic.submit(one.getInvoiceId(), "SAVE");
            invoiceLogic.delete(one.getInvoiceId());
        }
        retailOrder.updateById();
        retailOrderItemService.saveOrUpdateBatch(retailOrderItems);



        //通过审核发货单
        if (retailOrder.getExamineStatus().equals(ExamineStatusEnum.OK.toString()) && !retailOrder.getIsPlanOrder()) {
            //审核通过发货单
            invoiceApprovalInvoice(retailOrder,retailOrderItems);
        }
    }

    private void insertOrderRecord(RetailOrder order, List<RetailOrderItem> orderItems, OrderOperationTypeEnum type,
                                   String refType) {
        if (type.getKey().equals(OrderOperationTypeEnum.ORDER_EXAMINE.getKey())) {
            orderExecRecordService.lambdaUpdate()
                    .eq(OrderExecRecord::getRefOrderId, order.getId())
                    .remove();
        }

        List<OrderExecRecord> recordList = new ArrayList<>();
        for (RetailOrderItem item : orderItems) {
            OrderExecRecord record = new OrderExecRecord();
            BeanUtils.copyProperties(item, record);
            record.setCustomerId(order.getCustomerId())
                    .setCustomerName(order.getCustomerName())
                    .setCustomerNumber(order.getCustomerNumber())
                    .setAdminCompanyId(order.getAdminCompanyId())
                    .setTheTime((OrderOperationTypeEnum.ORDER_EXAMINE.getKey().equals(type.getKey()) ? order.getTheTime() : DateUtil.date()))
                    .setOrderType(order.getType() == 1 ? OrderTypeEnum.RETAIL.getKey() : OrderTypeEnum.RETAIL_POLICY.getKey())
                    .setPolicyId(order.getPolicyId())
                    .setPolicyCode(order.getPolicyCode())
                    .setPolicyTitle(order.getPolicyTitle())
                    .setPolicyRemark(order.getPolicyRemark())
                    .setK3ServiceId(order.getK3ServiceId())
                    .setK3ServiceName(order.getK3ServiceName())
                    .setRefOrderId(order.getId() + (OrderOperationTypeEnum.ORDER_REFUND.getKey().equals(type.getKey()) ? "T" : ""))
                    .setRefOrderItemId(item.getId())
                    .setOrderOperationType(type.getKey())
                    .setDirection(type.getKey().equals(OrderOperationTypeEnum.ORDER_EXAMINE.getKey()) ? 1 : -1)
                    .setRefType(refType)
                    .setOrderCreateTime(order.getCreateTime())
                    .setCreateBy(null)
                    .setCreateTime(null);
            recordList.add(record);
        }

        orderExecRecordService.saveBatch(recordList);
    }


    private void invoiceApprovalInvoice(RetailOrder retailOrder, List<RetailOrderItem> orderItems) throws Exception {
        InvoiceApplicationOrder invoiceApplicationOrderItem = invoiceApplicationOrderService.lambdaQuery().eq(InvoiceApplicationOrder::getMainOrderId, retailOrder.getId())
                .last("limit 1").one();

        if (invoiceApplicationOrderItem == null){
            RetailOrder retailOrder1 = new RetailOrder();
            retailOrder1.setId(retailOrder.getId());
            retailOrder1.setIsPlanOrder(true);
            retailOrder1.updateById();
            return;
        }

        InvoiceApplication one = invoiceApplicationService.lambdaQuery().eq(InvoiceApplication::getId, invoiceApplicationOrderItem.getInvoiceId()).last("limit 1").one();

        InvoiceRequestJson invoiceRequestJson = new InvoiceRequestJson();
        invoiceRequestJson.setId(one.getId());
        invoiceRequestJson.setRemark(retailOrder.getRemark());
        invoiceRequestJson.setExamineStatus(ExamineStatusEnum.OK.toString());
        List<InvoiceApplicationOrderRequest> invoiceApplicationOrderRequests = new ArrayList<>();
        for (RetailOrderItem orderItem : orderItems) {
            InvoiceApplicationOrderRequest invoiceApplicationOrderRequest = BeanUtil.toBean(orderItem, InvoiceApplicationOrderRequest.class);
            InvoiceApplicationOrder invoiceApplicationOrder = invoiceApplicationOrderService.lambdaQuery().eq(InvoiceApplicationOrder::getInvoiceId, one.getId())
                    .eq(InvoiceApplicationOrder::getOrderId, orderItem.getId()).one();
            invoiceApplicationOrderRequest.setId(invoiceApplicationOrder.getId());
            invoiceApplicationOrderRequest.setMainOrderId(retailOrder.getId());
            invoiceApplicationOrderRequest.setApprovalNumber(orderItem.getRefundableQty());
            invoiceApplicationOrderRequest.setOrderType(OrderTypeEnum.RETAIL_POLICY.getKey());
            invoiceApplicationOrderRequest.setOrderId(orderItem.getId());
            invoiceApplicationOrderRequest.setInvoiceNum(orderItem.getRefundableQty());
            invoiceApplicationOrderRequest.setTheTime(retailOrder.getTheTime());
            invoiceApplicationOrderRequest.setMaterialCode(orderItem.getMaterialCode());
            invoiceApplicationOrderRequest.setHeaderRemark(retailOrder.getRemark());
            invoiceApplicationOrderRequest.setRemark(orderItem.getRemark());
            invoiceApplicationOrderRequests.add(invoiceApplicationOrderRequest);
        }
        invoiceRequestJson.setOrders(invoiceApplicationOrderRequests);
        invoiceLogic.approvalInvoice(invoiceRequestJson);
    }



    /**
     * 同步到金蝶
     */
    public ResultEntity toK3(RetailOrder retailOrder,List<RetailOrderItem> items){

        K3CustomerBean customer = k3CustomerLogic.detail(retailOrder.getCustomerId());
        SalesOrderBean salesOrderBean = new SalesOrderBean();
        salesOrderBean.setBillNo(retailOrder.getId());
        salesOrderBean.setCustomerNumber(customer.getNumber());
        salesOrderBean.setOrgNumber(customer.getUseOrgNumber());
        salesOrderBean.setDate(DateUtil.formatDate(retailOrder.getCreateTime()));

        List<SalesOrderItemBean> k3Items = new ArrayList<>();
        for(RetailOrderItem item: items){

            String customerWalletId = item.getCustomerWalletId();
            CustomerProductTypeRela customerProductTypeRela = customerProductTypeLogic.getByCustomerWalletId(customerWalletId);

            SalesOrderItemBean k3Item = new SalesOrderItemBean();
            k3Item.setSupplyColVal(item.getId());
            k3Item.setMaterialNumber(item.getMaterialCode());
            k3Item.setQty(BigDecimal.valueOf(item.getQty()));
            k3Item.setTaxPrice(item.getPrice());
            k3Item.setDiscount(item.getTotalDiscAmount().add(item.getPayRebateAmount()));
            k3Item.setEntryNote(item.getRemark());
            k3Item.setWalletNumber(item.getCustomerWalletNumber());
            k3Item.setfOrderEntryPlan(salesOrderBean.getDate());

            if(customerProductTypeRela != null && StringUtils.isNotEmpty(customerProductTypeRela.getK3OrgNumber())){
                k3Item.setK3OrgNumber(customerProductTypeRela.getK3OrgNumber());
            }
            k3Items.add(k3Item);
        }
        salesOrderBean.setOrderItems(k3Items);

        return salesOrderLogic.syncBillData(salesOrderBean);
    }


    /**
     * 弃审
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void abandon(String id) throws InterruptedException {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        RetailOrder retailOrder = retailOrderService.getById(id);
        if(!retailOrder.getExamineStatus().equals(ExamineStatusEnum.OK.toString())){
            throw new RemoteServiceException("非审核通过单据不可弃审");
        }
        if(adminUser.getIsCustomer()){
            throw new RemoteServiceException("暂无权限操作");
        }
        retailOrder.setExamineStatus(ExamineStatusEnum.WAIT.toString());
        retailOrder.setCloseName(adminUser.getNickName());
        retailOrder.setCloseTime(new Date());

        List<RetailOrderItem> items = retailOrderItemService.lambdaQuery().eq(RetailOrderItem::getRetailOrderId, id).list();
        for(RetailOrderItem item : items){
            if (invoiceMapper.selectInvoiceOk(item.getId()) != 0 && retailOrder.getIsPlanOrder()){
                throw new RemoteServiceException("检测到订单有申请发货，不可弃审");
            }
            if (item.getOldQty() > item.getRefundableQty() && retailOrder.getIsPlanOrder() && StringUtils.isNotBlank(item.getKingDeeSeq())) {
                throw new RemoteServiceException("销售类型：" + item.getSaleTypeName()  + " 名称：" + item.getMaterialName() + "数量发生变更，不可弃审");
            }
            item.setKingDeeSeq("");
            item.setKingDeeEntryId("");
        }
        retailOrder.updateById();
        //全退
        //this.refundAll(retailOrder);

        //弃审
        boolean b = salesOrderLogic.unAuditByBillNo(id);
        if(!b){
            throw new RemoteServiceException("弃审失败，反审金蝶单据失败");
        }

        //弃审订单，同时弃审申请发货单
        if (!retailOrder.getIsPlanOrder()) {
            InvoiceApplicationOrder invoiceApplicationOrderItem = invoiceApplicationOrderService.lambdaQuery().eq(InvoiceApplicationOrder::getMainOrderId, retailOrder.getId())
                    .last("limit 1").one();
            InvoiceApplication one = invoiceApplicationService.lambdaQuery().eq(InvoiceApplication::getId, invoiceApplicationOrderItem.getInvoiceId()).last("limit 1").one();
            invoiceLogic.giveUp(one.getId());
        }

        // 删除订单执行明细
        orderExecRecordService.lambdaUpdate()
                .eq(OrderExecRecord::getRefOrderId, retailOrder.getId())
                .remove();

    }


    /**
     * 关单
     * @param id
     */
    public void close(String id) throws InterruptedException {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        RetailOrder retailOrder = retailOrderService.getById(id);
        if(!retailOrder.getExamineStatus().equals(ExamineStatusEnum.SAVE.toString())
                && !retailOrder.getExamineStatus().equals(ExamineStatusEnum.WAIT.toString())){
            throw new RemoteServiceException("已审单据不可关闭");
        }

        //全退
        if(StringUtils.equals(retailOrder.getExamineStatus(),ExamineStatusEnum.WAIT.toString()))
            this.refundAll(retailOrder);


        retailOrder.setExamineStatus(ExamineStatusEnum.CLOSE.toString());
        retailOrder.setCloseName(adminUser.getNickName());
        retailOrder.setCloseTime(new Date());
        retailOrder.updateById();
/*


        //全退
        if(StringUtils.equals(retailOrder.getExamineStatus(),ExamineStatusEnum.WAIT.toString()))
            this.refundAll(retailOrder);

        */
    }


    /**
     * 退单
     * @param retreatDocumentId 退款单id
     * @param retailOrderItemId 零售单明细id
     * @param tdQty 退订数量
     */
    public void refund(String retreatDocumentId,String retailOrderItemId,Integer tdQty,String billType) throws InterruptedException {
        RetailOrderItem bean = retailOrderItemService.getById(retailOrderItemId);
        this.refund(bean,tdQty,retreatDocumentId,billType);
    }



    private void refund(RetailOrderItem bean,Integer tdnum) throws InterruptedException {
        this.refund(bean,tdnum,bean.getRetailOrderId(),"零售单退订");
    }


    private void refundAll(RetailOrder retailOrder) throws InterruptedException {
        //退钱
        List<CustomerWalletAmountBean> customerWalletAmountBeans = new ArrayList<>();
        List<RetailOrderItem> list = retailOrderItemService.lambdaQuery().eq(RetailOrderItem::getRetailOrderId, retailOrder.getId()).list();
        for(RetailOrderItem item : list){
            if(item.getRefundableQty().intValue() != item.getOldQty().intValue()){
                throw new RemoteServiceException("检测到订单数量与订单原数量有变动，不可弃审");
            }
            if (invoiceMapper.selectInvoice(item.getId()) != 0 && retailOrder.getIsPlanOrder()){
                throw new RemoteServiceException("检测到订单有申请发货，不可弃审");
            }
            customerWalletAmountBeans.add(new CustomerWalletAmountBean(item.getCustomerWalletId(),item.getPayAmount(),item.getRemark(),
                    "零售订单退款",retailOrder.getTheTime(),retailOrder.getId(),2,"add"));

            customerWalletAmountBeans.add(new CustomerWalletAmountBean(item.getCustomerWalletId2(),item.getPayRebateAmount(),item.getRemark(),
                    "零售单返利退款",retailOrder.getTheTime(),retailOrder.getId(),0,"add"));
        }
        walletLogic.doWalletAmount(customerWalletAmountBeans);
    }

    /**
     * 退钱
     * @param bean
     * @param tdnum
     * @param orderId  单据号
     * @param billType 单据类型，例如：退款单
     * @throws InterruptedException
     */
    private void refund(RetailOrderItem bean,Integer tdnum,String orderId,String billType) throws InterruptedException {
        if(tdnum == null || tdnum == 0){
            return;
        }
        BigDecimal tdQty = BigDecimal.valueOf(tdnum);
        //需要退的钱
        BigDecimal refundPayAmount = bean.getSinglePayPrice().multiply(tdQty);
        //需要退的返利金额
        BigDecimal refundRebateAmount = bean.getSingleRebateAmount().multiply(tdQty);
        //返利单退款
        List<CustomerWalletAmountBean> customerWalletAmountBeans = new ArrayList<>();
        customerWalletAmountBeans.add(new CustomerWalletAmountBean(bean.getCustomerWalletId2(),refundRebateAmount,bean.getRemark(),
                billType,new Date(),orderId,0,"add"));

        if(refundPayAmount.doubleValue() > 0){
            customerWalletAmountBeans.add(new CustomerWalletAmountBean(bean.getCustomerWalletId(),refundPayAmount,bean.getRemark(),
                    billType,new Date(),orderId,2,"add"));
        }
        walletLogic.doWalletAmount(customerWalletAmountBeans);
    }


    /**
     * 直调发货
     */
    @Transactional
    public void directDeliver(DirectOrderBean directOrderBean){

        String directTransferOrderId = IdWorker.getIdStr();

        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<DirectOrderBean.DirectItem> directItems = directOrderBean.getDirectItems();

        RetailOrder retailOrder =  retailOrderService.getById(directOrderBean.getOrderNo());

        if(!retailOrder.getExamineStatus().equals(ExamineStatusEnum.OK.toString())){
            throw new RemoteServiceException("请先审核该单");
        }
        String orderType = retailOrder.getType() == 1?OrderTypeEnum.RETAIL.getKey() : OrderTypeEnum.RETAIL_POLICY.getKey();
        KingDeeStock kingDeeStock = kingDeeStockService.getById(directOrderBean.getStockId());
        // 直调发货容器
        List<DirectTransferOrderItem> directTransferOrderItems = new ArrayList<>(10);

        for(DirectOrderBean.DirectItem item : directItems){
            RetailOrderItem retailOrderItem = retailOrderItemService.getById(item.getItemId());
            String retailOrderId = retailOrderItem.getRetailOrderId();

            if(retailOrder == null) {
                retailOrder = retailOrderService.getById(retailOrderId);
            }
            if(!retailOrderItem.getIsDirectTransfer() && item.getQty() != 0){
                throw new RemoteServiceException(retailOrderItem.getSpecification()+"不可直调");
            }
            if(retailOrderItem.getDirectTransferStatus()){
                throw new RemoteServiceException("已直调完成，不可直调发货");
            }
            if(retailOrderItem.getRefundableQty().intValue() < item.getQty()){
                throw new RemoteServiceException("可直调数量不足");
            }
            if(item.getQty() == 0){
                continue;
            }
            //判断库存是否足够
         /*   Integer stock = stockCommonLogic.stockVirtualStatus(directOrderBean.getStockId(), retailOrderItem.getMaterialId());
            if(item.getQty().intValue() > stock.intValue()){
                throw new RemoteServiceException(retailOrderItem.getMaterialName()+retailOrderItem.getSpecification()+"库存不足");
            }*/

            //直调数量
            BigDecimal qty = BigDecimal.valueOf(item.getQty());

            DirectTransferOrderItem dItem = new DirectTransferOrderItem();
            dItem.setDirectTransferOrderId(directTransferOrderId);
            dItem.setRefOrderId(retailOrderItem.getRetailOrderId());
            dItem.setRefOrderItemId(retailOrderItem.getId());
            dItem.setSaleTypeId(retailOrderItem.getSaleTypeId());
            dItem.setSaleTypeCode(retailOrderItem.getSaleTypeCode());
            dItem.setSaleTypeName(retailOrderItem.getSaleTypeName());
            dItem.setMaterialId(retailOrderItem.getMaterialId());
            dItem.setMaterialNumber(retailOrderItem.getMaterialCode());
            dItem.setMaterialName(retailOrderItem.getMaterialName());
            dItem.setSpecification(retailOrderItem.getSpecification());
            dItem.setUnit(retailOrderItem.getUnit());
            dItem.setPrice(retailOrderItem.getPrice());
            dItem.setQty(item.getQty());
            dItem.setDiscAmount(retailOrderItem.getDiscAmount().multiply(qty).add(retailOrderItem.getSingleRebateAmount().multiply(qty)));
            dItem.setMustTotalAmount(retailOrderItem.getSinglePayPrice().multiply(qty));
            dItem.setRealTotalAmount(retailOrderItem.getPayAmount());
            dItem.setCustomerWalletId2(retailOrderItem.getCustomerWalletId2());
            dItem.setRebateAmount(retailOrderItem.getPayRebateAmount());
            dItem.setCustomerWalletId(retailOrderItem.getCustomerWalletId());
            dItem.setCustomerWalletNumber(retailOrderItem.getCustomerWalletNumber());
            dItem.setDirectTransferQty(item.getQty());
            dItem.setTaxRate(retailOrderItem.getTax());
            dItem.setAfterTaxPrice(retailOrderItem.getPrice().subtract(retailOrderItem.getPrice().multiply(retailOrderItem.getTax())));
            dItem.setServiceId(retailOrderItem.getServiceId());
            dItem.setServiceName(retailOrderItem.getServiceName());
            dItem.setStockId(kingDeeStock.getId());
            dItem.setStockNumber(kingDeeStock.getNumber());
            dItem.setStockName(kingDeeStock.getName());
            dItem.setRefKingDeeEntryId(retailOrderItem.getKingDeeEntryId());

            dItem.insert();

            retailOrderItem.setHasSendQty(retailOrderItem.getHasSendQty() + item.getQty());
            retailOrderItem.setDirectTransferQty(retailOrderItem.getDirectTransferQty() + item.getQty());
            retailOrderItem.setRefundableQty(retailOrderItem.getRefundableQty() - item.getQty());
            retailOrderItem.updateById();


            directTransferOrderItems.add(dItem);
        }
        if(CollectionUtils.isEmpty(directTransferOrderItems)){
            throw new RemoteServiceException("所有产品明细直调数量都为0，无法直调发货");
        }

        DirectTransferOrder directTransferOrder = new DirectTransferOrder();
        directTransferOrder.setId(directTransferOrderId);
        directTransferOrder.setAdminCompanyId(adminUser.getAdminCompanyId());
        directTransferOrder.setCustomerId(retailOrder.getCustomerId());
        directTransferOrder.setCustomerName(retailOrder.getCustomerName());
        directTransferOrder.setOrderType(orderType);
        directTransferOrder.setOrderNo(retailOrder.getId());
//        directTransferOrder.setServiceId(retailOrder.getServiceId());
//        directTransferOrder.setServiceName(retailOrder.getServiceName());
        directTransferOrder.setCorrespondId(directOrderBean.getCorrespondId());
        directTransferOrder.setStockId(directOrderBean.getStockId());
        directTransferOrder.setDeliverDate(directOrderBean.getOrderDate());
        directTransferOrder.setRefKingDeeId(retailOrder.getKingDeeId());
        directTransferOrder.insert();

        // TODO 同步金蝶下推销售出库单并保存审核
        k3CommonMethodLogic.syncK3SalesOutStockOrder(directTransferOrder, directTransferOrderItems);
    }




    /**
     * 可选择的商品列表
     */
    public IPage<ProductPriceBean> queryProductList(String mainId, String saleId, String materialNumber, String materialName,
                                                    String specification, BigDecimal price1, BigDecimal price2, String customerId,
                                                    List<String> oldNumbers, String billType, Integer pageNum, Integer pageSize){

        String adminUserId = CommonUtils.getUserId();
        AdminUser adminUser = adminUserService.getById(adminUserId);
        List<CustomerWalletBean> customerWalletBeans = new ArrayList<>();
        if(adminUser.getIsCustomer()){
            customerId = adminUser.getCustomerId();
            customerWalletBeans = walletLogic.queryWalletByCustomerId(customerId, null);
        } else if (StringUtils.isNotBlank(customerId)) {
            customerWalletBeans = walletLogic.queryWalletByCustomerId(customerId, null);
        }

        Map<String, CustomerWalletBean> customerWalletMap = customerWalletBeans.stream().collect(Collectors.toMap(CustomerWalletBean::getWalletRebateId, v -> v));
        IPage<ProductPriceBean> productPriceBeanIPage = retailOrderCommonMapper
                .queryProductList(new Page(pageNum, pageSize), mainId, saleId, materialNumber, materialName, specification, price1, price2, oldNumbers, billType);

        if (!billType.equals(OrderTypeEnum.DIFF.getKey())) {
            for (ProductPriceBean bean : productPriceBeanIPage.getRecords()) {
                //现金钱包
                List<CustomerWalletBean> customerWallets = this.supplyWallet1(bean.getId(), customerWalletMap, WalletTypeEnum.COMMONLY.getKey());
                bean.getWallets().addAll(customerWallets);

                //返利钱包
                List<CustomerWalletBean> rebateRate = this.supplyWallet1(bean.getId(), customerWalletMap, WalletTypeEnum.REBATE.getKey());
                bean.getRebateWallets().addAll(CommonUtils.findRebateRate(rebateRate,bean.getSaleTypeId()));
            }
        }
        return productPriceBeanIPage;
    }


    /**
     * 更变可退货数量  扣除
     * @param retailOrderItemId 明细id
     * @param qty 数量
     */
    public void changeRefundableQty(String retailOrderItemId,Integer qty){
        RetailOrderItem retailOrderItem = retailOrderItemService.getById(retailOrderItemId);
        if(retailOrderItem == null){
            return;
        }
        if(retailOrderItem.getRefundableQty().intValue() < qty.intValue()){
            throw new RemoteServiceException("可退货数量不足!");
        }

        if (retailOrderItem.getQty() < (retailOrderItem.getRefundableQty()+retailOrderItem.getHasSendQty()))
            throw new RemoteServiceException("可退数量大于了订单数量!");

        retailOrderItem.setRefundableQty(retailOrderItem.getRefundableQty() - qty);
        retailOrderItem.updateById();
    }

    /**
     * 更变可退货数量  退回
     * @param retailOrderItemId 明细id
     * @param qty 数量
     */
    public void changeSubRefundableQty(String retailOrderItemId,Integer qty){
        RetailOrderItem retailOrderItem = retailOrderItemService.getById(retailOrderItemId);
        if(retailOrderItem == null){
            return;
        }
        retailOrderItem.setRefundableQty(retailOrderItem.getRefundableQty() + qty);
        retailOrderItem.updateById();
    }

    /**
     * 变更已发货数量
     */
    public void changeHasSendQty(String retailOrderItemId,Integer qty){
        RetailOrderItem retailOrderItem = retailOrderItemService.getById(retailOrderItemId);
        if(retailOrderItem == null){
            return;
        }
        retailOrderItem.setHasSendQty(retailOrderItem.getHasSendQty() + qty);
        retailOrderItem.updateById();
    }

    /**
     * 销售执行明细-其他零售列表V2
     */
    public IPage<OrderExecRetailVO> queryRetailOrderExecRetailV2(ZfireParamBean zfireParamBean){

        zfireParamBean = FieldUtils.supplyParam(zfireParamBean);

        AdminUserCom adminUser = commonLogic.getAdminUser();
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():"";
        Integer total = commonCMapper.queryOrderExecRetailCount(zfireParamBean,customerId,adminUser.getServiceIds(),adminUser.getK3CategoryIds());
        IPage<OrderExecRetailVO> page = commonCMapper.queryOrderExecRetail(new Page(zfireParamBean.getPageNum(),
                        zfireParamBean.getPageSize(), total,false), zfireParamBean,customerId,
                adminUser.getServiceIds(),adminUser.getK3CategoryIds());

        //获得经销商集团
        List<KingDeeCustomer> list = kingDeeCustomerService.lambdaQuery().eq(KingDeeCustomer::getIsGroupCompany, 1).list();
        Map<String, String> collect1 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getId, KingDeeCustomer::getName));
        Map<String, String> collect2 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getNumber, KingDeeCustomer::getParentId));
        for (OrderExecRetailVO record : page.getRecords()) {
            if (StringUtils.isNotEmpty(collect2.get(record.getCustomerNumber()))) {
                record.setCustomerGroupName(collect1.get(collect2.get(record.getCustomerNumber())));
            }
        }

        //获得物料分组
        List<KingDeeMaterial> kingDeeMaterials = kingDeeMaterialService.lambdaQuery().select(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName).list();
        Map<String, String> kingDeeMaterCollect = kingDeeMaterials.stream().collect(Collectors.toMap(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName));
        for (OrderExecRetailVO record : page.getRecords()) {
            record.setMaterialGroupName(kingDeeMaterCollect.get(record.getMaterialCode()));
        }

        return page;
    }


    /**
     * 销售执行明细-政策单列表V2
     */
    public IPage<OrderExecPolicyVO> queryRetailOrderExecPolicyV2(ZfireParamBean zfireParamBean){

        zfireParamBean = FieldUtils.supplyParam(zfireParamBean);

        AdminUserCom adminUser = commonLogic.getAdminUser();
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():"";
        Integer total = commonCMapper.queryOrderExecPolicyCount(zfireParamBean,customerId,adminUser.getServiceIds(),adminUser.getK3CategoryIds());
        IPage<OrderExecPolicyVO> page = commonCMapper.queryOrderExecPolicy(new Page(zfireParamBean.getPageNum(),
                        zfireParamBean.getPageSize(), total,false),
                zfireParamBean,customerId,adminUser.getServiceIds(),adminUser.getK3CategoryIds());

        //获得经销商集团
        List<KingDeeCustomer> list = kingDeeCustomerService.lambdaQuery().eq(KingDeeCustomer::getIsGroupCompany, 1).list();
        Map<String, String> collect1 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getId, KingDeeCustomer::getName));
        Map<String, String> collect2 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getNumber, KingDeeCustomer::getParentId));
        for (OrderExecPolicyVO record : page.getRecords()) {
            if (StringUtils.isNotEmpty(collect2.get(record.getCustomerNumber()))) {
                record.setCustomerGroupName(collect1.get(collect2.get(record.getCustomerNumber())));
            }
        }

        //获得物料分组
        List<KingDeeMaterial> kingDeeMaterials = kingDeeMaterialService.lambdaQuery().select(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName).list();
        Map<String, String> kingDeeMaterCollect = kingDeeMaterials.stream().collect(Collectors.toMap(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName));
        for (OrderExecPolicyVO record : page.getRecords()) {
            record.setMaterialGroupName(kingDeeMaterCollect.get(record.getMaterialCode()));
        }

        return page;
    }

    /**
     * 工程销售执行明细
     */
    public IPage<OrderEnginVO> queryEnginOrderV2(EnginOrderDTO enginOrderDTO){
        ZfireParamBean zfireParamBean = FieldUtils.supplyParam(enginOrderDTO);
        AdminUserCom adminUser = commonLogic.getAdminUser();
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():null;

        Integer total = commonCMapper.queryEnginOrderCount(enginOrderDTO, enginOrderDTO.getEnginOrderType(), adminUser.getServiceIds(), adminUser.getK3CategoryIds(),customerId);
        IPage<OrderEnginVO> page = commonCMapper.queryEnginOrder(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize(), total, false), zfireParamBean,
                enginOrderDTO.getEnginOrderType(), adminUser.getServiceIds(), adminUser.getK3CategoryIds(),customerId);
        //获得经销商集团
        List<KingDeeCustomer> list = kingDeeCustomerService.lambdaQuery().eq(KingDeeCustomer::getIsGroupCompany, 1).list();
        Map<String, String> collect1 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getId, KingDeeCustomer::getName));
        Map<String, String> collect2 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getNumber, KingDeeCustomer::getParentId));
        for (OrderEnginVO record : page.getRecords()) {
            if (StringUtils.isNotEmpty(collect2.get(record.getCustomerNumber()))) {
                record.setCustomerGroupName(collect1.get(collect2.get(record.getCustomerNumber())));
            }
        }
        //获得物料分组
        List<KingDeeMaterial> kingDeeMaterials = kingDeeMaterialService.lambdaQuery().select(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName).list();
        Map<String, String> kingDeeMaterCollect = kingDeeMaterials.stream().collect(Collectors.toMap(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName));
        for (OrderEnginVO record : page.getRecords()) {
            record.setMaterialGroupName(kingDeeMaterCollect.get(record.getMaterialCode()));
        }
        return page;
    }



    /**
     * 销售单执行明细
     */
    public IPage<OrderExecBean> queryRetailOrderExec(String costStartTime,String costEndTime,String refUseUnit,String isCost,String materialOldNumber, String id, String customerName, String materialName,String specification,
                                                     String startTime, String endTime, String orderStartTime,String orderEndTime,
                                                     String serviceName,String itemServiceName,String newServiceName, String type,
                                                     List<String> k3CategoryNumber,String projectName,String enginRecordNo,String policyCode,String policyRemark,
                                                     Boolean isOver,Boolean isDisplaceOrder,List<String> walletIds1,List<String> walletIds2,String priceType,Integer pageNum,Integer pageSize){
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():null;
        if(type.equals("1") || type.equals("2")) {
            Integer total = countMapper.queryRetailOrderExecCount(costStartTime,costEndTime,refUseUnit,isCost,materialOldNumber, id, customerName,
                    materialName, specification, startTime, endTime,orderStartTime,orderEndTime, serviceName, itemServiceName, newServiceName, type, k3CategoryNumber,
                    customerId, adminUser.getServiceIds(), policyCode, policyRemark, isOver,isDisplaceOrder, adminUser.getK3CategoryIds(),walletIds1,walletIds2,priceType);

            IPage<OrderExecBean> orderExecBeanIPage = countMapper.queryRetailOrderExec(new Page(pageNum, pageSize,total,false),
                    isCost,materialOldNumber, id, customerName, materialName,specification, startTime, endTime,orderStartTime,orderEndTime,
                    serviceName,itemServiceName,newServiceName,
                    type,k3CategoryNumber, customerId,adminUser.getServiceIds(),policyCode,policyRemark,isOver,isDisplaceOrder,
                    adminUser.getK3CategoryIds(),walletIds1,walletIds2,priceType);

            //获得经销商集团
            List<KingDeeCustomer> list = kingDeeCustomerService.lambdaQuery().eq(KingDeeCustomer::getIsGroupCompany, 1).list();
            Map<String, String> collect1 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getId, KingDeeCustomer::getName));
            Map<String, String> collect2 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getNumber, KingDeeCustomer::getParentId));
            for (OrderExecBean record : orderExecBeanIPage.getRecords()) {
                if (StringUtils.isNotEmpty(collect2.get(record.getCustomerNumber()))) {
                    record.setCustomerGroupName(collect1.get(collect2.get(record.getCustomerNumber())));
                }
            }

            //获得物料分组
            List<KingDeeMaterial> kingDeeMaterials = kingDeeMaterialService.lambdaQuery().select(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName).list();
            Map<String, String> kingDeeMaterCollect = kingDeeMaterials.stream().collect(Collectors.toMap(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName));
            for (OrderExecBean record : orderExecBeanIPage.getRecords()) {
                record.setMaterialGroupName(kingDeeMaterCollect.get(record.getMaterialCode()));
            }
            return orderExecBeanIPage;
        }else{
            Integer total = countMapper.queryEnginOrderExecCount(costStartTime,costEndTime,refUseUnit,isCost,materialOldNumber, id, customerName,
                    materialName,specification, startTime, endTime,orderStartTime,orderEndTime, serviceName,itemServiceName,newServiceName, type,k3CategoryNumber,
                    customerId, projectName, enginRecordNo,adminUser.getServiceIds(),isOver,isDisplaceOrder,adminUser.getK3CategoryIds(),walletIds1,walletIds2,priceType);

            IPage<OrderExecBean> orderExecBeanIPage = countMapper.queryEnginOrderExec(new Page(pageNum, pageSize,total,false),isCost,
                    materialOldNumber, id, customerName, materialName,specification, startTime, endTime, orderStartTime,orderEndTime,serviceName,itemServiceName,newServiceName,
                    type,k3CategoryNumber, customerId, projectName, enginRecordNo,adminUser.getServiceIds(),isOver,isDisplaceOrder,
                    adminUser.getK3CategoryIds(),walletIds1,walletIds2,priceType);
            List<KingDeeCustomer> list = kingDeeCustomerService.lambdaQuery().eq(KingDeeCustomer::getIsGroupCompany, 1).list();
            Map<String, String> collect1 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getId, KingDeeCustomer::getName));
            Map<String, String> collect2 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getNumber, KingDeeCustomer::getParentId));
            for (OrderExecBean record : orderExecBeanIPage.getRecords()) {
                if (StringUtils.isNotEmpty(collect2.get(record.getCustomerNumber()))) {
                    record.setCustomerGroupName(collect1.get(collect2.get(record.getCustomerNumber())));
                }
            }

            //获得物料分组
            List<KingDeeMaterial> kingDeeMaterials = kingDeeMaterialService.lambdaQuery().select(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName).list();
            Map<String, String> kingDeeMaterCollect = kingDeeMaterials.stream().collect(Collectors.toMap(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName));
            for (OrderExecBean record : orderExecBeanIPage.getRecords()) {
                record.setMaterialGroupName(kingDeeMaterCollect.get(record.getMaterialCode()));
            }
            return orderExecBeanIPage;
        }
    }

    /**
     *  销售单执行明细汇总
     */
    public IPage<OrderExecBean> queryRetailOrderExecTotal(String costStartTime,String costEndTime,String refUseUnit,String isCost,String materialOldNumber, String id, String customerName, String materialName,String specification,
                                                          String startTime, String endTime,String orderStartTime,String orderEndTime,
                                                          String serviceName,String itemServiceName,String newServiceName, String type,
                                                          List<String> k3CategoryNumber, String projectName,String enginRecordNo,String policyCode,String policyRemark,
                                                          Boolean isOver,Boolean isDisplaceOrder,
                                                          List<String> walletIds1,List<String> walletIds2, String priceType,Integer pageNum,Integer pageSize){
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        String customerId = adminUser.getIsCustomer()?adminUser.getCustomerId():null;
        type = null;

        //家用的总条数
        Integer total = countMapper.queryRetailOrderExecCount(costStartTime,costEndTime,refUseUnit,isCost,materialOldNumber, id, customerName,
                materialName, specification, startTime, endTime,orderStartTime,orderEndTime, serviceName, itemServiceName, newServiceName, type, k3CategoryNumber,
                customerId, adminUser.getServiceIds(), policyCode, policyRemark, isOver,isDisplaceOrder, adminUser.getK3CategoryIds(),walletIds1,walletIds2,priceType);
        //工程的总条数
        Integer total2 = countMapper.queryEnginOrderExecCount(costStartTime,costEndTime,refUseUnit,isCost,materialOldNumber, id, customerName,
                materialName,specification, startTime, endTime,orderStartTime,orderEndTime, serviceName,itemServiceName,newServiceName, type,k3CategoryNumber,
                customerId, projectName, enginRecordNo,adminUser.getServiceIds(),isOver,isDisplaceOrder,adminUser.getK3CategoryIds(),walletIds1,walletIds2,priceType);
        if(StringUtils.isNotBlank(policyCode) || StringUtils.isNotBlank(policyRemark))
            total2 = 0;
        if(StringUtils.isNotBlank(enginRecordNo) || StringUtils.isNotBlank(enginRecordNo) || StringUtils.isNotBlank(refUseUnit))
            total = 0;

        if ((total + total2) < 1)
            return new Page();

        IPage<OrderExecBean> page = countMapper.queryOrderExecTotal(new Page(pageNum,pageSize,total+total2,false),costStartTime,costEndTime,refUseUnit,isCost,
                materialOldNumber, id, customerName, materialName,specification, startTime,
                endTime,orderStartTime,orderEndTime, serviceName,itemServiceName,newServiceName, type,k3CategoryNumber,customerId, projectName, enginRecordNo,
                adminUser.getServiceIds(),policyCode,policyRemark,isOver,isDisplaceOrder,adminUser.getK3CategoryIds(),walletIds1,walletIds2,priceType,total2,total);

        //获得经销商集团
        List<KingDeeCustomer> list = kingDeeCustomerService.lambdaQuery().eq(KingDeeCustomer::getIsGroupCompany, 1)
                .select(KingDeeCustomer::getId,KingDeeCustomer::getName,KingDeeCustomer::getNumber,KingDeeCustomer::getParentId).list();
        Map<String, String> collect1 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getId, KingDeeCustomer::getName));
        Map<String, String> collect2 = list.stream().collect(Collectors.toMap(KingDeeCustomer::getNumber, KingDeeCustomer::getParentId));

        for (OrderExecBean record : page.getRecords()) {
            if (StringUtils.isNotEmpty(collect2.get(record.getCustomerNumber()))) {
                record.setCustomerGroupName(collect1.get(collect2.get(record.getCustomerNumber())));
            }
        }

        //获得物料分组
        List<KingDeeMaterial> kingDeeMaterials = kingDeeMaterialService.lambdaQuery().select(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName).list();
        Map<String, String> kingDeeMaterCollect = kingDeeMaterials.stream().collect(Collectors.toMap(KingDeeMaterial::getNumber, KingDeeMaterial::getMaterialGroupName));
        for (OrderExecBean record : page.getRecords()) {
            record.setMaterialGroupName(kingDeeMaterCollect.get(record.getMaterialCode()));
        }

        return page;
    }



    /**
     * 零售单执行明细下载
     */
    public ExcelData exportExecList(List<OrderExecBean> orderExecBeans) {
        String[] titles = new String[]{"制单日期", "订单日期", "销售订单", "经销商编码",
                "经销商名称", "销售类型", "物料编码", "厂产品代码","产品名称", "规格型号", "直调状态","钱包","返利钱包","订单未发货数量",
                "单价","总数量","退订数量", "退货数量", "订单金额", "订单返利金额","折扣金额", "发货金额","出库数量",
                "发货数量","直调数量","直调状态","退订金额","退货金额","表头业务员","表体业务员","归属业务员","表头备注","销售政策名称","销售执行编码"
                ,"工程编号","工程登录编号","文件编号","机型类别","项目名称","所属集团","存货类别","金蝶部门","物料分组","原供价","价格类型","审核状态","审核人","审核时间","是否置换过","使用单位","项目说明"};
        List<List<Object>> rows = new ArrayList<>();
        for (OrderExecBean o : orderExecBeans) {
            List<Object> row = new ArrayList<>();
            row.add(DateUtil.formatDate(o.getCreateTime()));
            row.add(DateUtil.formatDate(o.getTheTime()));
            row.add(o.getId());
            row.add(o.getCustomerNumber());
            row.add(o.getCustomerName());
            row.add(o.getSaleTypeName());
            row.add(o.getMaterialCode());
            row.add(o.getMaterialOldNumber());
            row.add(o.getMaterialName());
            row.add(o.getSpecification());
            row.add(o.getDirectTransferStatusName());
            row.add(o.getWalletName());
            row.add(o.getRebateWalletName());
            row.add(o.getRefundableQty());
            row.add(o.getPrice());
            row.add(o.getQty());
            row.add(o.getRetiredQty());
            row.add(o.getRefundProductQty());
            row.add(o.getPayAmount());
            if(o.getPayRebateAmount() != null){
                row.add(o.getPayRebateAmount());
            }else {
                row.add(0);
            }
            row.add(o.getTotalDiscAmount());
            if(o.getHasSendAmount() != null) {
                row.add(o.getHasSendAmount());
            }else {
                row.add(0);
            }
            row.add(o.getHasSendQty());
            row.add(o.getQty() - o.getRefundableQty());
            row.add(o.getDirectTransferQty());
            row.add(o.getDirectTransferStatusName());
            row.add(o.getRetiredAmount());
            row.add(o.getRefundProductAmount());
            row.add(o.getServiceName());
            row.add(o.getItemServiceName());
            row.add(o.getNewServiceName());
            row.add(o.getRemark());
            row.add(o.getPolicyTitle());
            row.add(o.getPolicyCode());
            row.add(o.getRefProjectNo());
            row.add(o.getRefEnginRecordNo());
            row.add(o.getFileNo());
            row.add(o.getRefMachineType());
            row.add(o.getRefProjectName());
            row.add(o.getCustomerGroupName());
            row.add(o.getK3CategoryName());
            row.add(o.getK3OrgName());
            row.add(o.getMaterialGroupName());
            row.add(o.getOrgPrice());
            row.add(o.getPriceType());
//            row.add(ExamineStatusEnum.valueOf(o.getExamineStatus()).getMsg());
            row.add(EnumUtil.getNameFieldMap(ExamineStatusEnum.class, "value").get(o.getExamineStatus()));
            row.add(o.getExamineName());
            if(o.getExamineTime() != null){
                row.add(DateUtil.formatDateTime(o.getExamineTime()));
            }else{
                row.add("");
            }
            row.add(o.getIsDisplaceOrder() != null && o.getIsDisplaceOrder()?"是":"否");
            row.add(o.getRefUseUnit());
            row.add(o.getRefProjectNote());
            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setRows(rows);
        excelData.setTitles(Arrays.asList(titles));
        return excelData;
    }


    /**
     * 初始化旧系统零售单数据
     */
    public void importInit(List<Object> datas){
        List<AdminUser> adminUsers = adminUserService.list();
        List<KingDeeCustomer> kingDeeCustomers = k3CustomerLogic.allList();
        List<SaleType> saleTypes = saleTypeService.list();
        List<KingDeeMaterial> materialds = kingDeeMaterialService.list();

        Map<String, AdminUser> userMap = adminUsers.stream()
                .collect(Collectors.toMap(AdminUser::getUserName, v -> v));
        Map<String, KingDeeCustomer> customerMap = kingDeeCustomers.stream()
                .collect(Collectors.toMap(KingDeeCustomer::getNumber, v -> v));
        Map<String, SaleType> saleMap = saleTypes.stream().collect(Collectors.toMap(SaleType::getSaleCode, v -> v));
        Map<String, KingDeeMaterial> materialMap = materialds.stream().collect(Collectors.toMap(KingDeeMaterial::getNumber, v -> v));

        Map<String,List<Object>> groupDatas = new HashMap<>();
        for(Object o : datas){
            List<Object> row = (List<Object>)o;
            String orderId = (String)row.get(15);
            if(groupDatas.get(orderId) == null){
                List<Object> list = new ArrayList<>();
                list.add(o);
                groupDatas.put(orderId,list);
            }else {
                groupDatas.get(orderId).add(o);
            }
        }

        for(String key : groupDatas.keySet()){

            List<Object> rows = groupDatas.get(key);

            BigDecimal totalAmount = BigDecimal.ZERO;
            int totalQty = 0;
            for(int i =0 ;i < rows.size() ; i++ ){
                List<Object> row = (List<Object>)rows.get(i);
                String userName = (String)row.get(0);//需要查帐号
                String customerNumber = (String)row.get(1);//需要查经销商
                String fileNo = (String)row.get(2);
                String orderDate = (String)row.get(3);
                String remark = (String)row.get(4);
                String k3ServiceUserName = (String)row.get(5);//需要查帐号
                String saleTypeCode = (String)row.get(6);  //需要查销售类型
                String materialNumber = (String)row.get(7);     //需要查物料
                String serviceUserName = (String)row.get(8);
                String walletName = (String)row.get(9); //需要查钱包
                String rebateWalletName = (String)row.get(10); //需要查钱包
                BigDecimal price = new BigDecimal(row.get(11).toString());
                Integer qty = Integer.parseInt(row.get(12).toString());
                BigDecimal discAmount = new BigDecimal(row.get(13).toString());
                BigDecimal totalRebateAmount = new BigDecimal(row.get(14).toString());
                String orderId = (String)row.get(15);

                AdminUser adminUser = userMap.get(userName);
                SaleType saleType = saleMap.get(saleTypeCode);
                KingDeeCustomer customer = customerMap.get(customerNumber);
                AdminUser serviceUser = userMap.get(k3ServiceUserName);
                AdminUser itemServiceUser = userMap.get(serviceUserName);
                KingDeeMaterial material = materialMap.get(materialNumber);
                AdminUserWebsitRela adminUserWebsitRela = adminUserWebsitRelaService.lambdaQuery().eq(AdminUserWebsitRela::getAdminUserId, adminUser.getAdminUserId()).one();
                //查询钱包
                List<CustomerWalletBean> customerWalletBeans = walletLogic.queryWalletByCustomerId(customer.getId(), null);
                List<CustomerWalletBean> wallet1 = customerWalletBeans.stream()
                        .filter(v -> v.getName().equals(walletName) && v.getType().equals(WalletTypeEnum.COMMONLY.getKey())).collect(Collectors.toList());
                List<CustomerWalletBean> wallet2 = customerWalletBeans.stream()
                        .filter(v -> v.getName().equals(rebateWalletName) && v.getType().equals(WalletTypeEnum.REBATE.getKey())).collect(Collectors.toList());
                //表体
                RetailOrderItem item = new RetailOrderItem();
                item.setAdminUserId(adminUser.getAdminUserId());
                item.setAdminWebsitId(adminUserWebsitRela.getAdminWebsitId());
                item.setRetailOrderId(orderId);
                item.setProductPriceId(null);
                if(saleType != null) {
                    item.setSaleTypeId(saleType.getId());
                    item.setSaleTypeCode(saleTypeCode);
                    item.setSaleTypeName(saleType.getSaleName());
                }
                item.setMaterialId(material.getId());
                item.setMaterialCode(material.getNumber());
                item.setMaterialOldNumber(material.getOldNumber());
                item.setMaterialName(material.getName());
                item.setK3CategoryId(material.getCategoryId());
                item.setK3CategoryNumber(material.getCategoryNumber());
                item.setK3CategoryName(material.getCategoryName());
                item.setServiceId(itemServiceUser.getAdminUserId());
                item.setServiceName(itemServiceUser.getNickName());
                item.setSpecification(material.getSpecification());
                item.setUnit(material.getBaseUnitId());
                item.setIsUseRebate(totalRebateAmount != null && totalRebateAmount.doubleValue() > 0);
                if(wallet1.size() > 0) {
                    item.setCustomerWalletId(wallet1.get(0).getCustomerWalletId());
                    item.setCustomerWalletNumber(wallet1.get(0).getWalletNumber());
                    item.setCustomerWalletName(wallet1.get(0).getCustomerWalletName());
                }
                if(wallet2.size() > 0){
                    item.setCustomerWalletId2(wallet2.get(0).getCustomerWalletId());
                    item.setCustomerWalletName2(wallet2.get(0).getCustomerWalletName());
                }
                item.setPrice(price);
                item.setQty(qty);
                item.setTotalAmount(price.multiply(BigDecimal.valueOf(qty)));
                item.setDiscAmount(discAmount);
                item.setTotalDiscAmount(discAmount.multiply(BigDecimal.valueOf(qty)));
                item.setRebateAmount(totalRebateAmount);
                item.setPayRebateAmount(item.getRebateAmount());
                item.setPayAmount(item.getTotalAmount().subtract(totalRebateAmount));
                item.setSingleRebateAmount(totalRebateAmount.divide(BigDecimal.valueOf(qty),6,BigDecimal.ROUND_HALF_UP));
                item.setSinglePayPrice(item.getPayAmount().divide(BigDecimal.valueOf(qty),6,BigDecimal.ROUND_HALF_UP));
                item.setOldQty(qty);
                item.setOldPayAmount(item.getPayAmount());
                item.setRemark(remark);
                item.setFileNo(fileNo);
                item.setRefundableQty(qty);

                //返利比例
                BigDecimal rebateRate = totalRebateAmount.divide(item.getTotalAmount(),6,BigDecimal.ROUND_HALF_UP);
                item.setRebateRate(rebateRate);
                item.insert();

                totalAmount = totalAmount.add(item.getTotalAmount());
                totalQty += item.getQty();

                //表头
                if(i == rows.size() - 1){
                    RetailOrder retailOrder = new RetailOrder();
                    retailOrder.setId(orderId);
                    retailOrder.setIsOldOrder(true);
                    retailOrder.setAdminUserId(adminUser.getAdminUserId());
                    retailOrder.setAdminWebsitId(adminUserWebsitRela.getAdminWebsitId());
                    retailOrder.setCustomerId(customer.getId());
                    retailOrder.setCustomerNumber(customer.getNumber());
                    retailOrder.setCustomerName(customer.getName());
                    retailOrder.setFileNo(fileNo);
                    retailOrder.setTotalAmount(totalAmount);
                    retailOrder.setTotalQty(totalQty);
                    retailOrder.setRemark(remark);
                    retailOrder.setAdminCompanyId(adminUser.getAdminCompanyId());
                    retailOrder.setK3ServiceId(serviceUser.getAdminUserId());
                    retailOrder.setK3ServiceName(serviceUser.getNickName());
                    retailOrder.setTheTime(DateUtil.parseDateTime(orderDate));
                    retailOrder.insert();
                }
            }

        }


    }

}
