package com.zfire.mall.manager.logic.engin.info;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zfire.mall.manager.bean.ExcelData;
import com.zfire.mall.manager.bean.admin.AdminUserCom;
import com.zfire.mall.manager.bean.engin.info.EnginInfoOrderBean;
import com.zfire.mall.manager.bean.engin.info.EnginInfoOrderListBean;
import com.zfire.mall.manager.bean.engin.info.EnginInfoSaleExecBean;
import com.zfire.mall.manager.commonmapper.engin.info.EnginInfoOrderReserveMapper;
import com.zfire.mall.manager.commonmapper.trade.LoginOrderMapper;
import com.zfire.mall.manager.constant.SysDictConstant;
import com.zfire.mall.manager.enums.ExamineStatusEnum;
import com.zfire.mall.manager.exception.RemoteServiceException;
import com.zfire.mall.manager.logic.common.CommonLogic;
import com.zfire.mall.manager.logic.saletype.SaleTypeLogic;
import com.zfire.mall.manager.plus.entity.*;
import com.zfire.mall.manager.plus.service.*;
import com.zfire.mall.manager.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Slf4j
public class EnginInfoOrderLogic {

    @Resource
    EnginInfoOrderReserveMapper enginInfoOrderReserveMapper;
    @Resource
    CommonLogic commonLogic;
    @Resource
    EnginInfoOrderService enginInfoOrderService;
    @Resource
    EnginInfoOrderItemService enginInfoOrderItemService;
    @Resource
    EnginInfoItemEditHistoryService enginInfoItemEditHistoryService;
    @Resource
    EnginOrderService enginOrderService;
    @Resource
    SaleTypeLogic saleTypeLogic;
    @Resource
    KingDeeMaterialService kingDeeMaterialService;
    @Resource
    EnginOrderItemService enginOrderItemService;
    @Resource
    TradeLoginOrderService tradeLoginOrderService;
    @Resource
    LoginOrderMapper loginOrderMapper;

    public IPage<EnginInfoOrderListBean> listPage(String enginInfoNo, String productCategoryId, String customerKeyword,
                                                  String projectName, String machineType, String useUnit, String installAddress,
                                                  String projectNo, String enginFactoryNo, String enginSignType, String serviceId,
                                                  String startContractExpireDate, String endContractExpireDate, String createName,
                                                  String confirmName, List<String> examineStatus, String specification,
                                                  String startOrderDate, String endOrderDate, Boolean isClose, String enginOrderType,
                                                  Integer pageNum, Integer pageSize) {
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        String customerId = adminUser.getIsCustomer() ? adminUser.getCustomerId() : "";

        if(examineStatus != null && examineStatus.contains(ExamineStatusEnum.CLOSE.toString())) {
            isClose = true;
            examineStatus.remove(ExamineStatusEnum.CLOSE.toString());
        }

        return enginInfoOrderReserveMapper.listPage(new Page<>(pageNum, pageSize), enginInfoNo, productCategoryId, customerKeyword, projectName, machineType,
                useUnit, installAddress, projectNo, enginFactoryNo, enginSignType, serviceId, startContractExpireDate, endContractExpireDate, createName, confirmName, examineStatus,
                specification,  startOrderDate, endOrderDate,isClose, adminUser.getAdminCompanyIds(), adminUser.getServiceIds(), customerId, enginOrderType);

    }

    public EnginInfoOrderBean detail(String id) {
        AdminUserCom adminUser = commonLogic.getAdminUser(true);
        List<String> adminCompanyIds = adminUser.getAdminCompanyIds();
        String customerId = adminUser.getIsCustomer() ? adminUser.getCustomerId() : "";
        return enginInfoOrderReserveMapper.detail(id, adminCompanyIds, adminUser.getServiceIds(), customerId);
    }

    @Transactional(rollbackFor = Exception.class)
    public Object add(EnginInfoOrderBean enginInfoOrderBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
//        if (!adminUser.getIsCustomer()) {
//            throw new RemoteServiceException("不是经销商账号不能建单");
//        }
        // 注入公司编号
        enginInfoOrderBean.setAdminCompanyId(adminUser.getAdminCompanyId());
        // 注入生成单号
        if (adminUser.getIsCustomer()) {
            enginInfoOrderBean.setCustomerId(adminUser.getCustomerId());
            enginInfoOrderBean.setCustomerNumber(adminUser.getCustomerNumber());
            enginInfoOrderBean.setCustomerName(adminUser.getCustomerName());
        } else {
            enginInfoOrderBean.setCustomerId(enginInfoOrderBean.getCustomerId());
            enginInfoOrderBean.setCustomerNumber(enginInfoOrderBean.getCustomerNumber());
            enginInfoOrderBean.setCustomerName(enginInfoOrderBean.getCustomerName());
        }
        enginInfoOrderBean.setEnginInfoNo(commonLogic.generateInfoNo("EIO" ,"enginInfoOrder",12));
        enginInfoOrderBean.setOrderDate(DateUtil.date());

        // 引用登录单号逻辑处理
        if (!StrUtil.trimToEmpty(enginInfoOrderBean.getProjectNo()).equals("无")
                && ReUtil.isMatch("^\\d{2}-\\d{5}$", enginInfoOrderBean.getProjectNo())) {
            boolean isSpan = "跨区登录".equals(enginInfoOrderBean.getEnginSignType());
            TradeLoginOrder order = loginOrderMapper.syncLoginOrderRefCustomerId(StrUtil.trimToEmpty(enginInfoOrderBean.getProjectNo()), isSpan);

            // 单号为空或引用经销商不匹配时抛错
//            if (Objects.isNull(order)
//                    || (StringUtils.isNotBlank(order.getRefCustomerId()) && !order.getRefCustomerId().equals(enginInfoOrderBean.getCustomerId()))) {
//                throw new RemoteServiceException("引用商用登录单号不存在");
//            }
            if (Objects.nonNull(order) && StringUtils.isBlank(order.getRefCustomerId())) {
                tradeLoginOrderService.lambdaUpdate()
                        .set(TradeLoginOrder::getRefCustomerId, enginInfoOrderBean.getCustomerId())
                        .eq(TradeLoginOrder::getId, order.getId())
                        .update();
            }
        }

        // 保存主表
        EnginInfoOrder enginInfoOrder = enginInfoOrderBean.handleTargetInfo(adminUser);
        enginInfoOrder.insert();

        // 保存明细
        enginInfoOrderBean.setEnginInfoId(enginInfoOrder.getEnginInfoId());
        List<EnginInfoOrderItem> infoOrderItems = enginInfoOrderBean.handleTargetItem();

        enginInfoOrderItemService.saveBatch(infoOrderItems);

        return enginInfoOrder.getEnginInfoId();
    }

    @Transactional(rollbackFor = Exception.class)
    public void execHandler(EnginInfoOrderBean enginInfoOrderBean, String operType) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        EnginInfoOrder enginInfoOrder = enginInfoOrderService.lambdaQuery()
                .in(CollectionUtil.isNotEmpty(adminUser.getAdminCompanyIds()), EnginInfoOrder::getAdminCompanyId, adminUser.getAdminCompanyIds())
                .eq(adminUser.getIsCustomer(), EnginInfoOrder::getCustomerId, adminUser.getCustomerId())
                .eq(operType.equals(SysDictConstant.SUBMIT), EnginInfoOrder::getExamineStatus, ExamineStatusEnum.SAVE.toString())
                .eq(operType.equals(SysDictConstant.EXAMINE), EnginInfoOrder::getExamineStatus, ExamineStatusEnum.WAIT.toString())
                .eq(EnginInfoOrder::getEnginInfoId, enginInfoOrderBean.getEnginInfoId())
                .one();

        if (Objects.isNull(enginInfoOrder)
//                || enginInfoOrder.getExamineStatus().equals(ExamineStatusEnum.OK.toString())
                || enginInfoOrder.getExamineStatus().equals(ExamineStatusEnum.FAIL.toString())
                || enginInfoOrder.getExamineStatus().equals(ExamineStatusEnum.CLOSE.toString())) {
            if (Objects.isNull(enginInfoOrder)) {
                throw new RemoteServiceException("单据不存在");
            }
            throw new RemoteServiceException("当前单据状态：" + ExamineStatusEnum.getMsg(enginInfoOrder.getExamineStatus()) + "，操作失败");

        }

        if (operType.equals(SysDictConstant.EDIT) && enginInfoOrder.getExamineStatus().equals(ExamineStatusEnum.OK.toString())) {
            if (adminUser.getIsCustomer()) {
                throw new RemoteServiceException("审核后的单据不允许编辑");
            }
            // 审批成功后编辑的处理
            handleExamineAfterData(adminUser, enginInfoOrder, enginInfoOrderBean);
            return;
        }

        // 保存主表
        enginInfoOrder = handleEditTargetInfo(adminUser, enginInfoOrder, enginInfoOrderBean);
        if (operType.equals(SysDictConstant.SUBMIT)) {
            enginInfoOrder.setExamineStatus(ExamineStatusEnum.WAIT.toString())
                    .setSubmitBy(CommonUtils.getUsername())
                    .setSubmitName(CommonUtils.getNickName())
                    .setSubmitTime(DateUtil.date());
        } else if (operType.equals(SysDictConstant.EXAMINE)) {
            enginInfoOrder.setExamineStatus(enginInfoOrderBean.isExamineResult() ? ExamineStatusEnum.OK.toString() : ExamineStatusEnum.SAVE.toString())
                    .setExamineNote(enginInfoOrderBean.getExamineNote())
                    .setConfirmBy(CommonUtils.getUsername())
                    .setConfirmName(CommonUtils.getNickName())
                    .setConfirmTime(DateUtil.date());
        }
        boolean update = enginInfoOrderService.update(enginInfoOrder, new LambdaUpdateWrapper<EnginInfoOrder>()
                .eq(EnginInfoOrder::getEnginInfoId, enginInfoOrder.getEnginInfoId())
                .eq(operType.equals(SysDictConstant.SUBMIT), EnginInfoOrder::getExamineStatus, ExamineStatusEnum.SAVE.toString())
                .eq(operType.equals(SysDictConstant.EXAMINE), EnginInfoOrder::getExamineStatus, ExamineStatusEnum.WAIT.toString()));
        if (!update) {
            throw new RemoteServiceException("单据内容已发生变化，处理失败");
        }

        // 保存明细
        enginInfoOrderBean.setEnginInfoNo(enginInfoOrder.getEnginInfoNo());
        enginInfoOrderItemService.remove(new LambdaUpdateWrapper<EnginInfoOrderItem>()
                .eq(EnginInfoOrderItem::getEnginInfoId, enginInfoOrder.getEnginInfoId()));

        List<EnginInfoOrderItem> enginInfoOrderItems = enginInfoOrderBean.handleTargetItem();
        enginInfoOrderItemService.saveBatch(enginInfoOrderItems);
    }

    @Transactional(rollbackFor = Exception.class)
    public void revoke(String id) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        boolean upd = enginInfoOrderService.update(new LambdaUpdateWrapper<EnginInfoOrder>()
                .set(EnginInfoOrder::getExamineStatus, ExamineStatusEnum.SAVE.toString())
                .set(EnginInfoOrder::getSubmitBy, null)
                .set(EnginInfoOrder::getSubmitName, null)
                .set(EnginInfoOrder::getSubmitTime, null)
                .eq(EnginInfoOrder::getEnginInfoId, id)
                .eq(adminUser.getIsCustomer(), EnginInfoOrder::getCustomerId, adminUser.getCustomerId())
                .eq(EnginInfoOrder::getExamineStatus, ExamineStatusEnum.WAIT.toString()));
        if (!upd) {
            throw new RemoteServiceException("订单状态已发生变化");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void del(List<String> ids) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        List<String> collect = ids.stream().distinct().collect(Collectors.toList());
        boolean remove = enginInfoOrderService.lambdaUpdate()
                .eq(EnginInfoOrder::getAdminCompanyId, adminUser.getAdminCompanyId())
                .eq(adminUser.getIsCustomer(), EnginInfoOrder::getCustomerId, adminUser.getCustomerId())
                .eq(EnginInfoOrder::getExamineStatus, ExamineStatusEnum.SAVE.toString())
                .in(EnginInfoOrder::getEnginInfoId, collect)
                .remove();
        if (!remove) {
            throw new RemoteServiceException("单据状态不是“保存”状态，删除失败");
        }
    }


    /**
     * 工程信息单导出
     * @param enginInfoOrderListBeans
     * @return
     */
    public ExcelData export(List<EnginInfoOrderListBean> enginInfoOrderListBeans){
        AdminUserCom adminUser = commonLogic.getAdminUser();
        String[] titles = new String[]{"工程信息单","单据日期","合同有效期","经销商编码","经销商名称","工程名称","机型类别", "文件编号",
                "使用单位","安装地址","销售类型","物料编码","厂产品代码","产品名称","规格型号","单位","数量","单价","金额","已订数量","可订数量","出库数量","发货数量","业务员","行业类别","工程登录类型","备注"
                ,"制表人","制表日期","审核人","审核日期","审核状态","物料分组","存货类别","是否关闭"};
        if (!adminUser.getIsCustomer()) {
            titles = new String[]{"工程信息单","单据日期","合同有效期","经销商编码","经销商名称","工程名称","机型类别", "文件编号",
                    "使用单位","安装地址","销售类型","物料编码","厂产品代码","产品名称","规格型号","单位","数量","单价","金额","已订数量","可订数量","出库数量","发货数量","业务员","行业类别","工程登录类型","备注"
                    ,"制表人","制表日期","审核人","审核日期","审核状态","权限分类","格力内部备注","物料分组","存货类别","是否关闭"};
        }
        List<List<Object>> rows = new ArrayList<>();
        for (EnginInfoOrderListBean enginInfoOrderListBean : enginInfoOrderListBeans) {
            List<Object> row = new ArrayList<>();
            int qty = enginInfoOrderListBean.getQty();
            int hasOrderQty = enginInfoOrderListBean.getHasOrderQty();
            int allowQty = qty - hasOrderQty;
            row.add(enginInfoOrderListBean.getEnginInfoNo());
            row.add(DateUtil.formatDate(enginInfoOrderListBean.getOrderDate()));
            row.add(DateUtil.formatDate(enginInfoOrderListBean.getContractExpireDate()));
            row.add(enginInfoOrderListBean.getCustomerNumber());
            row.add(enginInfoOrderListBean.getCustomerName());
            row.add(enginInfoOrderListBean.getProjectName());
            row.add(enginInfoOrderListBean.getMachineType());
            row.add(enginInfoOrderListBean.getFileNo());
            row.add(enginInfoOrderListBean.getUseUnit());
            row.add(enginInfoOrderListBean.getInstallAddress());
            row.add(enginInfoOrderListBean.getSaleTypeName());
            row.add(enginInfoOrderListBean.getMaterialNumber());
            row.add(enginInfoOrderListBean.getMaterialOldNumber());
            row.add(enginInfoOrderListBean.getMaterialName());
            row.add(enginInfoOrderListBean.getSpecification());
            row.add(enginInfoOrderListBean.getUnit());
            row.add(qty);
            row.add(enginInfoOrderListBean.getPrice());
            row.add(enginInfoOrderListBean.getTotalAmount());
            row.add(hasOrderQty);
            row.add(Math.max(allowQty, 0));
            row.add(enginInfoOrderListBean.getHasDeliverQty());
            row.add(enginInfoOrderListBean.getHasSendQty());
            row.add(enginInfoOrderListBean.getServiceName());
            row.add(enginInfoOrderListBean.getTradeCategory());
            row.add(enginInfoOrderListBean.getEnginSignType());
            row.add(enginInfoOrderListBean.getRemark());
            row.add(enginInfoOrderListBean.getCreateBy());
            row.add(DateUtil.formatDate(enginInfoOrderListBean.getCreateTime()));
            row.add(enginInfoOrderListBean.getConfirmName());
            row.add(DateUtil.formatDate(enginInfoOrderListBean.getConfirmTime()));
//            row.add(ExamineStatusEnum.valueOf(enginInfoOrderListBean.getExamineStatus()).getMsg());
            row.add(EnumUtil.getNameFieldMap(ExamineStatusEnum.class, "value").get(enginInfoOrderListBean.getExamineStatus()));
            if (!adminUser.getIsCustomer()) {
                row.add(enginInfoOrderListBean.getPowerCategory());
                row.add(enginInfoOrderListBean.getGeLiInerNote());
            }
            row.add(enginInfoOrderListBean.getMaterialGroupName());
            row.add(enginInfoOrderListBean.getCategoryName());
            row.add(enginInfoOrderListBean.getIsClose()?"是":"否");
            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setRows(rows);
        excelData.setTitles(Arrays.asList(titles));
        return excelData;
    }

    private void handleExamineAfterData(AdminUserCom adminUser, EnginInfoOrder enginInfoOrder, EnginInfoOrderBean enginInfoOrderBean) {
        EnginInfoEditHistory enginInfoEditHistory = new EnginInfoEditHistory();
        BeanUtils.copyProperties(enginInfoOrder, enginInfoEditHistory);
        // 插入历史记录表
        enginInfoEditHistory.insert();

        List<EnginInfoOrderItem> infoOrderItems = enginInfoOrderItemService.lambdaQuery()
                .eq(EnginInfoOrderItem::getEnginInfoId, enginInfoOrder.getEnginInfoId())
                .list();

        List<EnginInfoItemEditHistory> itemEditHistories = infoOrderItems.stream().map(infoOrderItem -> {
            EnginInfoItemEditHistory history = new EnginInfoItemEditHistory();
            BeanUtils.copyProperties(infoOrderItem, history);
            history.setParentId(enginInfoEditHistory.getId());
            return history;
        }).collect(Collectors.toList());

        // 插入历史记录明细表
        enginInfoItemEditHistoryService.saveBatch(itemEditHistories);

        handleEditTargetInfo(adminUser, enginInfoOrder, enginInfoOrderBean);

        enginInfoOrderBean.setEnginInfoNo(enginInfoOrder.getEnginInfoNo());
//        enginInfoOrderItemService.remove(new LambdaUpdateWrapper<EnginInfoOrderItem>()
//                .eq(EnginInfoOrderItem::getEnginInfoId, enginInfoOrder.getEnginInfoId()));

        Map<String, EnginInfoItemEditHistory> historyMap = itemEditHistories.stream()
                .collect(Collectors.toMap(v -> v.getSaleTypeId() + v.getMaterialId(), Function.identity()));

        List<EnginInfoOrderItem> enginInfoOrderItems = enginInfoOrderBean.handleTargetItem();
        for (EnginInfoOrderItem enginInfoOrderItem : enginInfoOrderItems) {
            EnginInfoItemEditHistory history = historyMap.get(enginInfoOrderItem.getSaleTypeId() + enginInfoOrderItem.getMaterialId());
            if (Objects.nonNull(history)) {
                if (enginInfoOrderItem.getQty() < history.getHasOrderQty()) {
                    throw new RemoteServiceException(enginInfoOrderItem.getSaleTypeName()
                            + "|" + enginInfoOrderItem.getMaterialOldNumber()
                            + "|" + enginInfoOrderItem.getMaterialName() + "的数量不能少于已订数量");
                }
                enginInfoOrderItem.setId(history.getId());
                enginInfoOrderItem.setHasOrderQty(history.getHasOrderQty());
                enginInfoOrderItem.setHasDeliverQty(history.getHasDeliverQty());
            }
        }

        enginInfoOrder.updateById();
        enginInfoOrderItemService.saveOrUpdateBatch(enginInfoOrderItems);


    }

    private EnginInfoOrder handleEditTargetInfo(AdminUserCom adminUser, EnginInfoOrder enginInfoOrder, EnginInfoOrderBean enginInfoOrderBean) {
//        ProductCategory productCategory = productCategoryService.lambdaQuery()
//                .eq(ProductCategory::getProductCategoryId, enginInfoOrderBean.getMainId())
//                .one();
//        if (Objects.isNull(productCategory)) {
//            throw new RemoteServiceException("产品大类不存在");
//        }
        enginInfoOrder.setProjectName(enginInfoOrderBean.getProjectName())
                .setProjectType(enginInfoOrderBean.getProjectType())
                .setProjectNote(enginInfoOrderBean.getProjectNote())
                .setMachineType(enginInfoOrderBean.getMachineType())
                .setUseUnit(enginInfoOrderBean.getUseUnit())
                .setInstallAddress(enginInfoOrderBean.getInstallAddress())
                .setProjectNo(enginInfoOrderBean.getProjectNo())
                .setEnginFactoryNo(enginInfoOrderBean.getEnginFactoryNo())
                .setEnginSignType(enginInfoOrderBean.getEnginSignType())
                .setTradeCategory(enginInfoOrderBean.getTradeCategory())
                .setLinkman(enginInfoOrderBean.getLinkman())
                .setPhone(enginInfoOrderBean.getPhone())
                .setTel(enginInfoOrderBean.getTel())
                .setDeclareNo(enginInfoOrderBean.getDeclareNo())
                .setPowerCategory(enginInfoOrderBean.getPowerCategory())
                .setServiceId(enginInfoOrderBean.getServiceId())
                .setServiceName(enginInfoOrderBean.getServiceName())
                .setContractExpireDate(enginInfoOrderBean.getContractExpireDate())
                .setGeLiInerNote(enginInfoOrderBean.getGeLiInerNote())
                .setGeLiNote(enginInfoOrderBean.getGeLiNote())
                .setFileNo(enginInfoOrderBean.getFileNo())
                .setRemark(enginInfoOrderBean.getRemark())
                .setUpdateBy(CommonUtils.getUsername())
                .setUpdateName(CommonUtils.getNickName())
                .setIsPlanOrder(enginInfoOrderBean.getIsPlanOrder())
//                .setMainId(enginInfoOrderBean.getMainId())
//                .setMainName(productCategory.getProductCategoryName())
        ;
        return enginInfoOrder;
    }

    @Transactional(rollbackFor = Exception.class)
    public void updInfoOrder(EnginInfoOrderBean enginInfoOrderBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        if (Objects.nonNull(enginInfoOrderBean.getOrderDate())) {
            boolean upd = enginInfoOrderService.lambdaUpdate()
                    .set(EnginInfoOrder::getOrderDate, enginInfoOrderBean.getOrderDate())
                    .set(EnginInfoOrder::getUpdateBy, CommonUtils.getUsername())
                    .set(EnginInfoOrder::getUpdateName, CommonUtils.getNickName())
                    .eq(EnginInfoOrder::getEnginInfoId, enginInfoOrderBean.getEnginInfoId())
                    .eq(EnginInfoOrder::getAdminCompanyId, adminUser.getAdminCompanyId())
                    .eq(adminUser.getIsCustomer(), EnginInfoOrder::getCustomerId, adminUser.getCustomerId())
//                    .in(EnginInfoOrder::getExamineStatus, ExamineStatusEnum.SAVE.toString(), ExamineStatusEnum.WAIT.toString())
                    .update();
            if (!upd) {
                throw new RemoteServiceException("单据状态已发生改变，更改单据日期失败");
            }
            return;
        }

        if (Objects.nonNull(enginInfoOrderBean.getEndStatus())) {
            boolean upd = enginInfoOrderService.lambdaUpdate()
                    .set(EnginInfoOrder::getEndStatus, enginInfoOrderBean.getEndStatus())
                    .set(EnginInfoOrder::getUpdateBy, CommonUtils.getUsername())
                    .set(EnginInfoOrder::getUpdateName, CommonUtils.getNickName())
                    .eq(EnginInfoOrder::getEnginInfoId, enginInfoOrderBean.getEnginInfoId())
                    .eq(EnginInfoOrder::getAdminCompanyId, adminUser.getAdminCompanyId())
                    .eq(adminUser.getIsCustomer(), EnginInfoOrder::getCustomerId, adminUser.getCustomerId())
                    .in(EnginInfoOrder::getExamineStatus, ExamineStatusEnum.OK.toString())
                    .update();
            if (!upd) {
                throw new RemoteServiceException("只能在“审批通过”单据状态更改提前完结状态");
            }
            return;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void abandon(String id) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        EnginInfoOrder order = enginInfoOrderService.getById(id);

        if(!order.getExamineStatus().equals(ExamineStatusEnum.OK.toString())) {
            throw new RemoteServiceException(order.getEnginInfoNo() + "非审核通过单据，不可弃审");
        }

        Integer count = enginOrderService.lambdaQuery()
                .eq(EnginOrder::getRefEnginRecordNo, order.getEnginInfoNo())
                .count();

        if (count > 0) {
            throw new RemoteServiceException(order.getEnginInfoNo() + "信息单已给引用，不可弃审");
        }

        order.setExamineStatus(ExamineStatusEnum.WAIT.toString());
        order.setAbandonBy(CommonUtils.getUsername());
        order.setAbandonName(CommonUtils.getNickName());
        order.setAbandonTime(DateUtil.date());
        order.updateById();
    }


    /**
     * 商用信息单执行明细
     */
    public IPage<EnginInfoSaleExecBean> queryEnginInfoSaleExec(String startOrderDate,
                                                               String endOrderDate,
                                                               String customerId,
                                                               String refProjectName,
                                                               String specification,
                                                               String refEnginRecordNo,
                                                               String serviceId,
                                                               Boolean isClose,
                                                               String confirmName,
                                                               Integer pageNum,Integer pageSize){
        AdminUserCom adminUser = commonLogic.getAdminUser();

        IPage<EnginInfoSaleExecBean> enginInfoSaleExecBeanIPage = enginInfoOrderReserveMapper
                .queryEnginInfoSaleExec(new Page<>(pageNum, pageSize), startOrderDate, endOrderDate, customerId, refProjectName,
                        specification, refEnginRecordNo, serviceId,isClose,confirmName,adminUser.getServiceIds());
        return enginInfoSaleExecBeanIPage;
    }


    /**
     * 打开关闭信息单
     */
    public void updateClose(String enginInfoId,Boolean isClose){
        AdminUserCom adminUser = commonLogic.getAdminUser();
        if (adminUser.getIsCustomer())
            throw new RemoteServiceException("经销商账号不能操作");
        enginInfoOrderService.lambdaUpdate()
                .set(EnginInfoOrder::getIsClose,isClose)
                .eq(EnginInfoOrder::getEnginInfoId,enginInfoId)
                .update();
    }



    /**
     * 商用信息单执行明细-导出
     */
    public ExcelData exportExec(List<EnginInfoSaleExecBean> list){
        String[] titles = new String[]{"信息单日期","工程编号","经销商编码","经销商名称","项目名称","销售类型","物料编码","厂产品代码","产品名称","规格型号","数量","单价","金额","未订数量","未订金额",
        "直调数量","退订数量","退货数量","表头业务员","审核人","是否关闭","备注","格力内部备注","权限分类","合同有效期","安装地址","联系电话","工程登录类型"};
        List<List<Object>> rows = new ArrayList<>();
        for(EnginInfoSaleExecBean bean : list){
            List<Object> row = new ArrayList<>();
            row.add(DateUtil.formatDateTime(bean.getOrderDate()));
            row.add(bean.getRefEnginRecordNo());
            row.add(bean.getCustomerNumber());
            row.add(bean.getCustomerName());
            row.add(bean.getRefProjectName());
            row.add(bean.getSaleTypeName());
            row.add(bean.getMaterialNumber());
            row.add(bean.getMaterialOldNumber());
            row.add(bean.getMaterialName());
            row.add(bean.getSpecification());
            row.add(bean.getQty());
            row.add(bean.getPrice());
            row.add(bean.getTotalAmount());
            row.add(bean.getWdQty());
            row.add(bean.getWdAmount());
            row.add(bean.getDirectTransferQty());
            row.add(bean.getRetiredQty());
            row.add(bean.getRefundProductQty());
            row.add(bean.getServiceName());
            row.add(bean.getConfirmName());
            row.add(bean.getIsClose()?"是":"否");
            row.add(bean.getRemark());
            row.add(bean.getRefPowerCategory());
            if(bean.getContractExpireDate() == null){
                row.add("");
            }else {
                row.add(DateUtil.formatDateTime(bean.getContractExpireDate()));
            }
            row.add(bean.getInstallAddress());
            row.add(bean.getPhone());
            row.add(bean.getEnginSignType());
            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setTitles(Arrays.asList(titles));
        excelData.setRows(rows);
        return excelData;
    }


    /**
     * 导入信息单产品明细
     */
    public List<EnginInfoOrderItem> importData(List<Object> list) throws Exception {
        List<Object> execList;
        List<String> materialOldNumberList = new ArrayList<>();
        List<EnginInfoOrderItem> resultList = new ArrayList<>();
        Map<String, Object> itemMap = new HashMap<>();
        // 去重复遍历操作
        for(Object o : list) {
            List<Object> row = (List<Object>) o;
            String saleTypeCode = (String) row.get(0);
            if (StringUtils.isEmpty(saleTypeCode)) {
                break;
            }
            String materialOldNumber = (String) row.get(1);
            String priceStr = (String) row.get(4);
            String qtyStr = (String) row.get(5);

            if(StringUtils.isEmpty(materialOldNumber) || StringUtils.isEmpty(saleTypeCode) || Objects.isNull(priceStr)
                    || Objects.isNull(qtyStr)){
                throw new RemoteServiceException("检测到物料编码/销售类型编码/单价/数量的为空情况");
            }

            itemMap.put(saleTypeCode + "|" + materialOldNumber, o);
            materialOldNumberList.add(materialOldNumber);
        }

        if (CollectionUtil.isEmpty(itemMap)) {
            throw new RemoteServiceException("导入明细为空");
        }

        execList = new ArrayList<>(itemMap.values());
        List<KingDeeMaterial> materialList = kingDeeMaterialService.lambdaQuery()
                .in(KingDeeMaterial::getOldNumber, materialOldNumberList)
                .list();
        Map<String, KingDeeMaterial> materialMap = materialList.stream()
                .collect(Collectors.toMap(KingDeeMaterial::getOldNumber, Function.identity()));

        //所有销售类型code
        List<SaleType> saleTypes = saleTypeLogic.listAll();
        Map<String, SaleType> saleTypeMap = saleTypes.stream().collect(Collectors.toMap(SaleType::getSaleCode, v -> v));

        for(Object o : execList){
            List<Object> row = (List<Object>)o;
            String saleTypeCode = (String)row.get(0);
            String materialOldNumber = (String)row.get(1);
            String priceStr = (String)row.get(4);
            String qtyStr = (String)row.get(5);
            String remark = (String)row.get(6);

            BigDecimal price = new BigDecimal(priceStr);
            BigDecimal qty = new BigDecimal(qtyStr);

            SaleType saleType = saleTypeMap.get(saleTypeCode);
            if(Objects.isNull(saleType)){
                throw new RemoteServiceException("销售类型编码:"+saleTypeCode+"不存在");
            }
            KingDeeMaterial kingDeeMaterial = materialMap.get(materialOldNumber);
            if(Objects.isNull(kingDeeMaterial)){
                throw new RemoteServiceException("产品编码:"+materialOldNumber+"不存在");
            }
            EnginInfoOrderItem enginInfoOrderItem = new EnginInfoOrderItem();
            enginInfoOrderItem.setSaleTypeId(saleType.getId())
                    .setSaleTypeCode(saleType.getSaleCode())
                    .setSaleTypeName(saleType.getSaleName())
                    .setMaterialId(kingDeeMaterial.getId())
                    .setMaterialNumber(kingDeeMaterial.getNumber())
                    .setMaterialOldNumber(kingDeeMaterial.getOldNumber())
                    .setMaterialName(kingDeeMaterial.getName())
                    .setSpecification(kingDeeMaterial.getSpecification())
                    .setUnit(kingDeeMaterial.getBaseUnitId())
                    .setK3CategoryId(kingDeeMaterial.getCategoryId())
                    .setK3CategoryNumber(kingDeeMaterial.getCategoryNumber())
                    .setK3CategoryName(kingDeeMaterial.getCategoryName())
                    .setPrice(price)
                    .setQty(qty.intValue())
                    .setTotalAmount(qty.multiply(price))
                    .setRemark(remark)
                    .setTaxRate(kingDeeMaterial.getTaxRateId());

            resultList.add(enginInfoOrderItem);
        }

        return resultList;
    }

    @Transactional(rollbackFor = Exception.class)
    public void delItem(String enginInfoNo, String itemId) {
        // 查询信息明细
        EnginInfoOrderItem infoOrderItem = enginInfoOrderItemService.lambdaQuery()
                .eq(EnginInfoOrderItem::getEnginInfoNo, enginInfoNo)
                .eq(EnginInfoOrderItem::getId, itemId)
                .one();
        if (Objects.isNull(infoOrderItem)) {
            throw new RemoteServiceException("未发现明细");
        }
        // 查询订单明细
        EnginOrderItem orderItem = enginOrderItemService.lambdaQuery()
                .eq(EnginOrderItem::getRefEnginRecordNo, enginInfoNo)
                .eq(EnginOrderItem::getSaleTypeId, infoOrderItem.getSaleTypeId())
                .eq(EnginOrderItem::getMaterialId, infoOrderItem.getMaterialId())
                .one();
        if (Objects.nonNull(orderItem)) {
            throw new RemoteServiceException(orderItem.getEnginOrderNo() + "工程订单已引用记录，删除失败");
        }
        // 备份信息明细
        EnginInfoOrderItemBak enginInfoOrderItemBak = new EnginInfoOrderItemBak();
        BeanUtils.copyProperties(infoOrderItem, enginInfoOrderItemBak);
        enginInfoOrderItemBak.insert();

        // 删除信息明细
        infoOrderItem.deleteById();
    }
}
