package com.junmp.jyzb.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.junmp.junmpProcess.dto.StartProcessInstanceDTO;
import com.junmp.junmpProcess.service.IFlowInstanceService;
import com.junmp.jyzb.api.bean.dto.*;
import com.junmp.jyzb.api.bean.query.*;
import com.junmp.jyzb.api.bean.query.InAndOutRecordReq.DetailJsonReq;
import com.junmp.jyzb.api.bean.req.UpdateOrderDetailReq;
import com.junmp.jyzb.api.bean.req.UpdateOrderReq;
import com.junmp.jyzb.api.bean.vo.InOrderInfoVo;
import com.junmp.jyzb.api.exception.JYZBAppException;
import com.junmp.jyzb.api.exception.enums.InventoryExceptionEnum;
import com.junmp.jyzb.api.exception.enums.OrderExceptionEnum;
import com.junmp.jyzb.api.exception.enums.WarehouseExceptionEnum;
import com.junmp.jyzb.cache.MsgRedisCache;
import com.junmp.jyzb.entity.*;
import com.junmp.jyzb.mapper.InventorySummaryMapper;
import com.junmp.jyzb.mapper.OrderMainMapper;
import com.junmp.jyzb.service.*;
import com.junmp.jyzb.utils.DateTimeUtil;
import com.junmp.jyzb.utils.RabbitMQSendMsg;
import com.junmp.v2.auth.api.bean.login.LoginUser;
import com.junmp.v2.auth.api.context.LoginContext;
import com.junmp.v2.common.exception.base.ServiceException;
import com.junmp.v2.common.util.BeanPlusUtil;
import com.junmp.v2.common.util.HttpServletUtil;
import com.junmp.v2.db.api.factory.PageFactory;
import com.junmp.v2.db.api.factory.PageResultFactory;
import com.junmp.v2.db.api.page.PageResult;
import com.junmp.v2.dict.entity.SysDict;
import com.junmp.v2.dict.entity.SysDictItem;
import com.junmp.v2.dict.service.SysDictItemService;
import com.junmp.v2.dict.service.SysDictService;
import com.junmp.v2.message.api.MessageApi;
import com.junmp.v2.message.api.bean.req.MessageSendReq;
import com.junmp.v2.office.api.OfficeExcelApi;
import com.junmp.v2.office.api.bean.ExcelExportParam;
import com.junmp.v2.sys.user.entity.SysUser;
import com.junmp.v2.sys.user.service.SysUserService;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain> implements OrderMainService {

    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private RabbitAdmin rabbitAdmin;

    @Resource
    private OrderNumService orderNumService;

    @Resource
    private MessageApi messageApi;
    @Resource
    private MsgRedisCache redisCache;
    @Resource
    private OrderMainMapper orderMainMapper;

    @Resource
    private SysDictItemService sysDictItemService;

    @Resource
    private OrderLogService orderLogService;
    @Resource
    private IFlowInstanceService FlowInstanceService;
    @Resource
    private OfficeExcelApi officeExcelApi;

    @Resource
    private InventorySummaryService inventorySummaryService;

    @Resource
    private InventoryService inventoryService;
    @Resource
    private WarehouseService warehouseService;
    @Resource
    private BusFormService busFormService;

    @Resource
    private BussinessInventoryService bussinessInventoryService;

    @Resource
    private BussinessInventoryDetailService bussinessInventoryDetailService;

    @Resource
    private ReassignmentService reassignmentService;

    @Resource
    private PoliceEquipmentService policeEquipmentService;

    @Resource
    private SysDictService sysDictService;

    @Resource
    protected TaskService taskService;

    @Resource
    private PubOrgService pubOrgService;

    @Resource
    private PolicemanService policemanService;

    @Resource
    private SysUserService sysUserService;
    @Resource
    private LogSummaryService logSummaryService;

    @Resource
    private InventorySummaryMapper inventorySummaryMapper;
    @Autowired
    private RabbitMQSendMsg MQ;

    @Resource
    private EquipmentTypeService equipmentTypeService;

    @Resource
    private WarehouseInventoryService warehouseInventoryService;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<String> AddOrder(UpdateOrderReq req) {
        //判断该单子是否是销毁出库单，如果是，则直接查询然后相应的库存进行修改，如果库存不足的情况下直接抛出异常提示
//        if (req.getBussinessType().equals("destruction") && ObjectUtil.isNotEmpty(req.getProcessDefinitionId())){
//            Boolean aBoolean= addOrRevokeAgentDestructionNum(req);
//        }
        //修改单据使用次数状态，判断数据库是否有该单据，如果有，那么就判断当前单号是否一致，如果不一致，修改单据使用次数
        Long orgId = req.getOrderType().equals("in")?req.getEndOrgId():Long.parseLong(req.getStartOrgId());
        OrderMain one =null ;
        //修改业务单可用次数
        if (ObjectUtil.isNotNull(req.getBussinessCode())){
            one = setBusFormState(req, one, orgId);
        }

        if (one!=null){
            //判断该单据是否可以进行修改(如果审核中则不允许修改)
            if (ObjectUtil.isNotNull(one.getExamineState()) && one.getExamineState().equals("working")){
                throw new ServiceException(OrderExceptionEnum.ORDER_CAN_NOT_UPDATE);
            }
        }

        //判断是否有工作流id，如果有则将状态进行修改
        if (ObjectUtil.isEmpty(req.getProcessDefinitionId())) {
            req.setExamineState("none");
        } else {
            req.setExamineState("working");
        }

        OrderMain order = new OrderMain();
        BeanPlusUtil.copyProperties(req, order);

        //先判断该单据id是否存在，如果存在，进行更新操作即可
        if (ObjectUtil.isNotNull(req.getId()) && ! req.getId().trim().isEmpty()){
            //删除子单据
            orderDetailService.remove(new LambdaQueryWrapper<OrderDetail>()
                    .eq(ObjectUtil.isNotNull(req.getId()),OrderDetail::getOrderId,req.getId()));
        }else {
            //设置id
            String id=UUID.randomUUID().toString();
            order.setId(id);
            //设置单据单号
            OrderNum orderNum = setOrderCode(req);
            String codeValue=String.format("%04d",orderNum.getNum());
            order.setOrderCode(orderNum.getBussinessType()+orderNum.getYear()+
                    String.format("%02d",LocalDateTime.now().getMonth().getValue())+
                    String.format("%02d",LocalDateTime.now().getDayOfMonth())+codeValue);
        }

        //设置总价格和应出入库数量
        Integer sumNum=0;
        BigDecimal priceTotal=new BigDecimal(0);
        List<OrderDetail> detailList = new ArrayList<>();
        //通过遍历批量保存详细信息
        String s="";
        if (req.getLogSummaryId() !=null){
            if (req.getOrderType().equals("in")){
                Long dictId = sysDictService.getOne(new LambdaQueryWrapper<SysDict>()
                        .eq(SysDict::getDictCode, "bussiness_type")).getDictId();
                String itemText = sysDictItemService.getOne(new LambdaQueryWrapper<SysDictItem>()
                        .eq(SysDictItem::getDictId, dictId)
                        .eq(SysDictItem::getItemValue, req.getBussinessType())).getItemText();
                s=s+itemText+"单：";
            }else {
                Long dictId = sysDictService.getOne(new LambdaQueryWrapper<SysDict>()
                        .eq(SysDict::getDictCode, "out_type")).getDictId();
                String itemText = sysDictItemService.getOne(new LambdaQueryWrapper<SysDictItem>()
                        .eq(SysDictItem::getDictId, dictId)
                        .eq(SysDictItem::getItemValue, req.getBussinessType())).getItemText();
                s=s+itemText+"单：";
            }
        }

        List<Object[]> searchItem=new ArrayList<>();
        for (UpdateOrderDetailReq listReq:req.getDetailList()) {
            OrderDetail detail=new OrderDetail();
            BeanPlusUtil.copyProperties(listReq, detail);
            detail.setOrderId(order.getId());
            //设置单据类型
            detail.setType(order.getOrderType());
            //将数量和价格进行累加
            sumNum += detail.getPlanNum();
            priceTotal = priceTotal.add(BigDecimal.valueOf(detail.getPlanNum()).multiply(detail.getTotalPrice())) ;
            detail.setCreateTime(DateTimeUtil.getCurrentDateTime());
            String productionDate = listReq.getProductionDate();
            if (ObjectUtil.isNotNull(productionDate) && !productionDate.trim().isEmpty()){
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    detail.setCreateTime(format.parse(productionDate));
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
            //添加日志记录
            if (ObjectUtil.isNull(req.getLogSummaryId()) || req.getLogSummaryId()==null){
                s=s+"【"+listReq.getTypeName()+"--"+listReq.getSizeName()+"】预计数量："+listReq.getPlanNum()+"\n";
            }
            detailList.add(detail);
            Object[] item=new Object[]{req.getStartOrgId(),listReq.getWarehouseId(),listReq.getTypeId(),listReq.getSizeId(),listReq.getPrice()};
            searchItem.add(item);
        }
        orderDetailService.saveBatch(detailList);
        //设置总价格和总数量
        order.setPrice(priceTotal);
        order.setInventoryQuantity(sumNum);
        order.setCreateTime(DateTimeUtil.getCurrentDateTime());
        String processInstanceId = null;
       if (req.getExamineState().equals("working")){
           //执行工作流
           StartProcessInstanceDTO startProcessInstanceDTO=new StartProcessInstanceDTO();

           //设置参数
           startProcessInstanceDTO = setParams(startProcessInstanceDTO, req,order);

           if (!req.getBussinessType().equals("quick") && req.getExamineState().equals("working"))//其他出入库单
           {
               startProcessInstanceDTO.setTypeOrder("workOrder");
               processInstanceId= FlowInstanceService.startProcessInstanceById(startProcessInstanceDTO);
               

           }else if (req.getBussinessType().equals("quick") && req.getExamineState().equals("working")){//快速移库单
               startProcessInstanceDTO.setTypeOrder("quickOrder");
               processInstanceId= FlowInstanceService.startProcessInstanceById(startProcessInstanceDTO);

           }else if (ObjectUtil.isNotNull(req.getLogSummaryId()) && req.getExamineState().equals("working")){
               startProcessInstanceDTO.setTypeOrder("normalOrder");
               processInstanceId= FlowInstanceService.startProcessInstanceById(startProcessInstanceDTO);
           }
       }
       //如果是销毁出库，并且有审核流，那么直接将库存汇总信息进行修改
//       if (req.getExamineState().equals("working") && req.getBussinessType().equals("destruction")){
//           List<InventorySummary> inventorySummaryList = inventorySummaryMapper.selectSumByItems(searchItem);
//           for (UpdateOrderDetailReq dq:req.getDetailList()) {
//               for (InventorySummary is:inventorySummaryList) {
//                   if (is.getLocationId().equals(dq.getWarehouseId()) && is.getTypeId().equals(dq.getTypeId())
//                   && is.getSizeId().equals(dq.getSizeId()) && is.getUnitPrice().compareTo(dq.getPrice())==0){
//
//                   }
//               }
//           }
//       }

        //list返回数据
        List<String> list=new ArrayList<>();
        //当前审核是否跳过
        if (processInstanceId!=null && processInstanceId.substring(0,4).equals("skip") ){
            String substring = processInstanceId.substring(4);
            order.setProcessId(substring);
            if (ObjectUtil.isNotNull(req.getId()) && !req.getId().trim().isEmpty()) {
                updateById(order);
            } else {
                //保存
                //将创建人员添加（为的是将审核员创建的单子，审核员能看见）
                //将该组织机构下的所有审核人员进行查询，并添加到historyAssign中
                String userIds=policemanService.searchUserByRoleId(orgId);
                String userId=req.getUserId()+","+userIds;
                order.setHistoryAssign(userId);

                this.save(order);
            }
            Task currentTask = taskService.createTaskQuery().processInstanceId(substring).singleResult();
            // 直接完成当前任务
            taskService.complete(currentTask.getId());
        }else {
            order.setProcessId(processInstanceId);
            if (ObjectUtil.isNotNull(req.getId()) && !req.getId().trim().isEmpty()) {
                updateById(order);
            } else {
                //保存
                //将创建人员添加（为的是将审核员创建的单子，审核员能看见）
                //将该组织机构下的所有审核人员进行查询，并添加到historyAssign中
                String userIds=policemanService.searchUserByRoleId(orgId);
                String userId=req.getUserId()+","+userIds;
                order.setHistoryAssign(userId);
                this.save(order);
            }
        }
        list.add(order.getId());
        for (OrderDetail orderDetail:detailList) {
            list.add(Long.toString(orderDetail.getId()));
        }
        //判断orderId在orderLog表中是否存在，如果存在，则直接替换
        //判断是否有流程id，如果有，则进行添加
        if (order.getProcessId()!=null && ObjectUtil.isNull(req.getLogSummaryId())){
            boolean b = addOrderLog(req,order.getId(),order.getOrderCode(),s);
        }

        String objJson= redisCache.get(order.getProcessId());
        redisCache.remove(order.getProcessId());
        List<MessageSendReq> msgs= JSONObject.parseArray(objJson,MessageSendReq.class);
        if (CollectionUtil.isNotEmpty(msgs)){
            msgs.forEach(msg->
                    {
                        messageApi.sendMessage(msg);
                    }

            );
        }
        //如果是无单据转业务
        if (ObjectUtil.isNotNull(req.getLogSummaryId())){
            logSummaryService.update(new LambdaUpdateWrapper<LogSummary>()
                    .set(LogSummary::getOrderMainId,order.getId())
                    .set(LogSummary::getOrderCode,order.getOrderCode())
                    .set(LogSummary::getBussinessType,order.getBussinessType())
                    .eq(LogSummary::getId,req.getLogSummaryId()));
        }

        return list;
    }

    //销毁装备申请之后将库存信息删除
    public boolean addOrRevokeAgentDestructionNum(UpdateOrderReq req){
        List<UpdateOrderDetailReq> list = req.getDetailList();
        List<Object[]> searchItem=new ArrayList<>();
        for (UpdateOrderDetailReq detialReq:list) {
            //我先去数据库查询summary表中的数据
            Object[] item=new Object[]{req.getStartOrgId(),detialReq.getWarehouseId(),detialReq.getTypeId(),detialReq.getSizeId(),detialReq.getPrice()};
            searchItem.add(item);
        }
        List<InventorySummary> inventorySummaryList = inventorySummaryMapper.selectSumByItems(searchItem);
        String msg="";
        for (UpdateOrderDetailReq detialReq:list) {
            for (InventorySummary is:inventorySummaryList) {

                if (detialReq.getWarehouseId().equals(is.getLocationId()) && detialReq.getTypeId().equals(is.getTypeId())
                        && detialReq.getSizeId().equals(is.getSizeId()) && new BigDecimal(detialReq.getPrice()).compareTo(is.getUnitPrice())==0){

                    if (ObjectUtil.isNull(is.getDestructionNumber())){
                        is.setDestructionNumber(0);
                    }
                    if (is.getNumber()-detialReq.getPlanNum()<0){
//                        is.setDestructionNumber(is.getDestructionNumber()+is.getNumber());
//                        is.setNumber(0);
                        msg=msg+"装备：" +detialReq.getTypeName()+"号型："+detialReq.getSizeName()+"装备销毁数小于库存数,库存数为："+is.getNumber()+"\n";
                    }else {
                        is.setDestructionNumber(is.getDestructionNumber()+detialReq.getPlanNum());
                        is.setNumber(is.getNumber() - detialReq.getPlanNum());
                        is.setStockNumber(is.getStockNumber() - detialReq.getPlanNum());
                        is.setPrice(is.getUnitPrice().multiply(BigDecimal.valueOf(is.getNumber())));
                        is.setDestructionPrice(is.getUnitPrice().multiply(BigDecimal.valueOf(is.getDestructionNumber())));

                    }
                    break;
                }
            }

        }
        if (!msg.trim().isEmpty()){
            throw new JYZBAppException(InventoryExceptionEnum.EQUIPMENT_NOT_EXIST, msg);
        }

        return inventorySummaryService.updateBatchById(inventorySummaryList);
    }

    public StartProcessInstanceDTO setParams(StartProcessInstanceDTO startProcessInstanceDTO,UpdateOrderReq req,OrderMain order){

        //业务单走审核流
        startProcessInstanceDTO.setProcessDefinitionId(req.getProcessDefinitionId());
        startProcessInstanceDTO.setOrderId(order.getId());
        startProcessInstanceDTO.setUserId(req.getUserId());
        //装备列表
        startProcessInstanceDTO.setInvList(req.getInvList());
        startProcessInstanceDTO.setOutInState(req.getOrderType());
        startProcessInstanceDTO.setType("orderDto");
        startProcessInstanceDTO.setBussinessType(req.getBussinessType());
        if (req.getOrderType().equals("in")){
            //发物单位和收物单位
            switch (req.getBussinessType()){
                case "purchase":
                case "gift":
                case "repair":
                case "other":
                    startProcessInstanceDTO.setStartOrgName(req.getSupplierName());
                    startProcessInstanceDTO.setEndOrgName(req.getEndOrgName());
                    break;
                case "return":
                    startProcessInstanceDTO.setStartOrgName(req.getEndOrgName());
                    startProcessInstanceDTO.setEndOrgName(req.getEndOrgName());
                case "allocate":
                    startProcessInstanceDTO.setStartOrgName(req.getStartOrgName());
                    startProcessInstanceDTO.setEndOrgName(req.getEndOrgName());
                    break;
            }
        }else {
            //发物单位和收物单位
            switch (req.getBussinessType()){
                case "use":
                    startProcessInstanceDTO.setStartOrgName(req.getStartOrgName());
                    startProcessInstanceDTO.setEndOrgName(req.getStartOrgName());
                    break;
                case "return":
                    startProcessInstanceDTO.setStartOrgName(req.getEndOrgName());
                    startProcessInstanceDTO.setEndOrgName(req.getEndOrgName());
                    break;
                case "allocate":
                    startProcessInstanceDTO.setStartOrgName(req.getStartOrgName());
                    startProcessInstanceDTO.setEndOrgName(req.getEndOrgName());
                    break;
                case "repair":
                case "destruction":
                case "other":
                    startProcessInstanceDTO.setStartOrgName(req.getStartOrgName());
                    startProcessInstanceDTO.setEndOrgName(req.getSupplierName());
                    break;
            }
        }
        Object A= JSON.toJSONString(req, SerializerFeature.WriteDateUseDateFormat);
        JSONObject jsonObject = JSON.parseObject(A.toString());

        startProcessInstanceDTO.setFormData(jsonObject);
        return startProcessInstanceDTO;
    }

    //纪录日志
    private boolean addOrderLog(UpdateOrderReq req,String orderId,String orderCode,String s){

        //我要的是detail的明细存入到history—msg中
        OrderLog orderLog = new OrderLog();
        orderLog.setId(UUID.randomUUID().toString());
        orderLog.setHistoryMsg(s);
        orderLog.setOrderCode(orderCode);
        orderLog.setBussinessType(req.getBussinessType());
        orderLog.setOrderType(req.getOrderType());
        if (ObjectUtil.isNotNull(req.getStartOrgUserName())){
            orderLog.setCreateUser(req.getStartOrgUserName());
        }else {
            orderLog.setCreateUser(req.getEndOrgUserName());
        }
        orderLog.setProcessType("createOrder");
        if (req.getOrderType().equals("in")){
            orderLog.setOrgId(req.getEndOrgId());
            orderLog.setOrgName(req.getEndOrgName());
        }else {
            orderLog.setOrgId(Long.parseLong(req.getStartOrgId()));
            orderLog.setOrgName(req.getStartOrgName());
        }
        orderLog.setOrderId(orderId);
        orderLog.setCreateTime(DateTimeUtil.getCurrentDateTime());

        return orderLogService.save(orderLog);
    }
    //修改业务单据可用次数
    private OrderMain setBusFormState(UpdateOrderReq req,OrderMain one,Long orgId){
        boolean a=true;
        boolean b=true;
        if (ObjectUtil.isNotNull(req.getId())){
            one = orderMainExist(req.getId());
            if (ObjectUtil.isNotNull(req.getBussinessCode()) && ObjectUtil.isNotNull(one.getBussinessCode())) {
                if (!one.getBussinessCode().equals(req.getBussinessCode())) {

                    //入参
                    BusForm one1 = setState1(req.getOrderType(),orgId, req.getBussinessCode());
                    a=busFormService.updateById(one1);

                    //库存
                    BusForm one2 = setState2(orgId, one.getBussinessCode());
                    b=busFormService.updateById(one2);

                }
            }
            //入参不为空，库里为空
            else if (ObjectUtil.isNotNull(req.getBussinessCode()) && ObjectUtil.isNull(one.getBussinessCode())){
                //只需要改一条数据
                //入参
                BusForm one1 = setState1(req.getOrderType(),orgId, req.getBussinessCode());
                a=busFormService.updateById(one1);
            }
            //入参为空，库里不为空
            else if (ObjectUtil.isNull(req.getBussinessCode()) && ObjectUtil.isNotNull(one.getBussinessCode())){
                //只需要改一条数据
                //库存
                BusForm one2 = setState2(orgId, one.getBussinessCode());
                b=busFormService.updateById(one2);
            }
            return one;
        }else {
            if (ObjectUtil.isNotNull(req.getBussinessCode())){
                //只需要更改一条单据
                //入参
                BusForm one1 = setState1(req.getOrderType(),orgId, req.getBussinessCode());
                a=busFormService.updateById(one1);
            }
            return one;
        }
    }

    private BusForm setState2(Long orgId,String bussinessCode){
        BusForm busform = busFormService.getOne(new LambdaQueryWrapper<BusForm>()
                .eq(BusForm::getOrgId, orgId)
                .in(BusForm::getBussinessCode, bussinessCode));
        busform.setOrderCurrentState(busform.getOrderLastState());
        switch (busform.getOrderCurrentState()){

            case "none":
                busform.setOrderCurrentState("outgoing");
                break;
            case "incoming":
                busform.setOrderCurrentState("bothuseing");
                break;
            case "outgoing":
                busform.setOrderCurrentState("bothuseing");
                break;
        }
        return busform;
    }

    private BusForm setState1(String orderType,Long orgId,String bussinessCode){
        BusForm busform = busFormService.getOne(new LambdaQueryWrapper<BusForm>()
                .eq(BusForm::getOrgId, orgId)
                .in(BusForm::getBussinessCode, bussinessCode));
        busform.setOrderCurrentState(busform.getOrderLastState());
        if (orderType.equals("in")){
            switch (busform.getOrderCurrentState()){
                case "bothuseing":
                    busform.setOrderCurrentState("outgoing");
                    break;
                case "outgoing":
                    busform.setOrderCurrentState("forbidden");
                    break;

            }
        }else {
            switch (busform.getOrderCurrentState()){
                case "bothuseing":
                    busform.setOrderCurrentState("incoming");
                    break;
                case "incoming":
                    busform.setOrderCurrentState("forbidden");
                    break;

            }
        }

        return busform;
    }


    //设置单据单号（并且对order_num表进行新增或者更新）
    public OrderNum setOrderCode(UpdateOrderReq req){
        //设置采购单号，需要先判断该组织机构的采购单号是否存在，如果存在则将数量进行增加，如果不存在则新增一条对应的数据
        OrderNum orderNum = new OrderNum();
        //获取年,月，日，获取业务出入状态，获取组织机构id，获取业务类型
        orderNum.setYear(LocalDateTime.now().getYear());
        //将业务类型转为中文简写(CK出库，RK入库)
        Long sysDictId = sysDictService.getOne(new LambdaQueryWrapper<SysDict>()
                .eq(SysDict::getDictCode, "order_chinese_setting")).getDictId();
        String itemValue = sysDictItemService.getOne(new LambdaQueryWrapper<SysDictItem>()
                .eq(SysDictItem::getItemText, req.getOrderType())
                .eq(SysDictItem::getDictId,sysDictId)).getItemValue();
        orderNum.setBussinessType(itemValue);
        //出入业务状态
        orderNum.setOutInType(req.getOrderType());
        //判断是出库还是入库，出库为发物单位，入库为收物单位
        OrderNum one = new OrderNum();
        if (req.getOrderType().equals("in")){
            orderNum.setEndOrgId(req.getEndOrgId());
            one = orderNumService.getOne(new LambdaQueryWrapper<OrderNum>()
                    .eq(OrderNum::getEndOrgId, orderNum.getEndOrgId())
                    .eq(OrderNum::getBussinessType, orderNum.getBussinessType())
                    .eq(OrderNum::getYear, orderNum.getYear())
                    .eq(OrderNum::getOutInType, orderNum.getOutInType()));
        }else {
            orderNum.setStartOrgId(Long.valueOf(req.getStartOrgId()));
            one = orderNumService.getOne(new LambdaQueryWrapper<OrderNum>()
                    .eq(OrderNum::getStartOrgId, orderNum.getStartOrgId())
                    .eq(OrderNum::getBussinessType,orderNum.getBussinessType())
                    .eq(OrderNum::getYear, orderNum.getYear())
                    .eq(OrderNum::getOutInType, orderNum.getOutInType()));
        }
        
        //设置num的数量
        if (ObjectUtil.isNull(one)){
            orderNum.setNum(1);
            orderNumService.save(orderNum);
            return orderNum;
        }else {
            one.setNum(one.getNum()+1);
            orderNumService.updateById(one);
            return one;
        }

    }



    //新增默认审核通过的任务单（可以没有工作流）
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String AddFinishOrder(UpdateOrderReq req) {

        //添加到数据库中(如果该单据没有审批流，那么就直接存入数据库)
        if (ObjectUtil.isNull(req.getProcessDefinitionId()) && ObjectUtil.isNull(req.getProcessId())){
            List<String> strings = AddOrder(req);
            OrderMain orderMain = getById(strings.get(0));
//            List<OrderDetail> list = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
//                    .eq(OrderDetail::getOrderId, strings.get(0)));
//            BeanPlusUtil.copyProperties(orderMain,req);
//            req.setExamineState("finished");
            orderMain.setExamineState("finished");
            updateById(orderMain);
//            List<UpdateOrderDetailReq> collect = list.stream().map(orderDetail -> {
//                UpdateOrderDetailReq orderDetailReq = new UpdateOrderDetailReq();
//                BeanPlusUtil.copyProperties(orderDetail, orderDetailReq);
//                return orderDetailReq;
//            }).collect(Collectors.toList());
//            req.setDetailList(collect);

        }else {
            //单据类型，分发单据
            req.setApi("DistributeOrder");
            //将完成的任务单直接推送到消息队列rabbitmq中（需要判断是入库单还是出库单，入库单传发物单位id，出库单传收物单位id）
            //方法2：一个交换机，多个队列。动态创建队列
            String exchangeName="orderExchange";
            //需要判断是入库单还是出库单，入库单传收物单位id，出库单传发物单位id

            if(req.getOrderType().equals("in")){

                MQ.SendMsg(exchangeName,req.getEndOrgId().toString(),req);
            }else {
                MQ.SendMsg(exchangeName,req.getStartOrgId().toString(),req);
            }
        }

        return req.getId();
    }


    //更新任务单（进入工作流中之后不能进行更改）
//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public Boolean  updateOrder(UpdateOrderReq req) {
//        OrderMain order = orderMainExist(req.getId());
//        if (!order.getExamineState().equals("none"))
//        {
//            throw new ServiceException(OrderExceptionEnum.ORDER_CAN_NOT_UPDATE);
//        }
//        //（直接删除并重新插入数据）----------------------------------------------
//        orderDetailService.remove(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, req.getId()));
//        Integer sumNum=0;
//        BigDecimal priceTotal=new BigDecimal(0);
//        List<OrderDetail> detailList = new ArrayList<>();
//        for (UpdateOrderDetailReq listReq:req.getDetailList()) {
//            OrderDetail detail=new OrderDetail();
//            BeanPlusUtil.copyProperties(listReq, detail);
//            detail.setOrderId(order.getId());
//            //设置单据类型
//            detail.setType(order.getOrderType());
//            //将数量和价格进行累加
//            sumNum += detail.getPlanNum();
//            priceTotal = priceTotal.add(BigDecimal.valueOf(detail.getPlanNum()).multiply(detail.getPrice())) ;
//            detail.setCreateTime(DateTimeUtil.getCurrentDateTime());
//            detailList.add(detail);
//        }
//        orderDetailService.saveBatch(detailList);
//        //设置总价格和总数量
//        order.setPrice(priceTotal);
//        order.setInventoryQuantity(sumNum);
//        order.setCreateTime(DateTimeUtil.getCurrentDateTime());
//        return this.updateById(order);
//    }
//

    //更新任务单（进入工作流中之后不能进行更改）
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean  ChangeOrderState(UpdateOrderReq req) {
        OrderMain order = orderMainExist(req.getId());

        order.setExamineState(req.getExamineState());
        order.setOrderState(req.getOrderState());
        return this.updateById(order);
    }
    public boolean hasCommonElements(List<?> list1, List<?> list2) {
        for (Object item1 : list1) {
            if (list2.contains(item1)) {
                return true; // 找到相同值
            }
        }
        return false; // 没有相同值
    }

    //查询任务列表(根据组织机构id)
    @Override
    public PageResult<OrderMainDto> getOrderPage(OrderMainReq req) {
        Page<OrderMain> page = new Page<>();
        //排序字段处理，将驼峰改成和数据库同步的字段名(如果传其他不是数据库字段参数或者排序规则不是deac或者asc可能会出现错误)
        if (ObjectUtil.isNotNull(req.getColumn()) && !req.getColumn().trim().isEmpty() &&
                (req.getOrder().equalsIgnoreCase("asc")|| req.getOrder().equalsIgnoreCase("desc")) &&
                ObjectUtil.isNotNull(req.getOrder()) &&!req.getOrder().trim().isEmpty()) {
            //修改字段，和数据库字段进行统一
            req.setColumn(req.getColumn().replaceAll("[A-Z]", "_$0").toLowerCase());
            req.setOrder(req.getOrder().toLowerCase());
        }
        //根据查询条件得到单据
        LoginUser loginUser = LoginContext.getContext().getLoginUser();

        IPage<OrderMain> outOrderPage = orderMainMapper.getOrderPage(PageFactory.getDefaultPage(req.getPageNo(), req.getPageSize()),req,loginUser.getUserId());
        page.setRecords(outOrderPage.getRecords());
        page.setTotal(outOrderPage.getTotal());

        List<OrderMainDto> orderMainDtoList = page.getRecords().stream().map(orderMain -> {
            OrderMainDto orderMainDto = new OrderMainDto();
            BeanPlusUtil.copyProperties(orderMain,orderMainDto);
            return orderMainDto;
        }).collect(Collectors.toList());
        Page<OrderMainDto> page1 = PageFactory.getDefaultPage(req.getPageNo(), req.getPageSize());
        page1.setTotal(page.getTotal());
        page1.setRecords(orderMainDtoList);
        return PageResultFactory.createPageResult(page1);
    }



    //根据任务单id查看业务明细
    @Override
    public OrderDto GetDetailById(OrderMainReq req) {
        //判断任务单是否存在
        OrderMain orderMain = orderMainExist(req.getId());
        OrderDto orderDto = new OrderDto();
        BeanPlusUtil.copyProperties(orderMain,orderDto);
        List<OrderDetail> list=new ArrayList<>();
        //排序字段处理，将驼峰改成和数据库同步的字段名
        //将详细信息存入列表属性中
        //通过任务单id查询对应的详细信息
        if (ObjectUtil.isNotNull(req.getColumn()) && !req.getColumn().trim().isEmpty() &&
                (req.getOrder().equalsIgnoreCase("asc")|| req.getOrder().equalsIgnoreCase("desc")) && !req.getOrder().trim().isEmpty()) {
            //修改字段，和数据库字段进行统一
            req.setColumn(req.getColumn().replaceAll("[A-Z]", "_$0").toLowerCase());
            list=orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                    .eq(OrderDetail::getOrderId, req.getId())
                    .last("order by "+req.getColumn() +" "+req.getOrder()));

        } else {
            list = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                    .eq(OrderDetail::getOrderId, req.getId())
                    .orderByDesc(OrderDetail::getCreateTime));
        }

        List<OrderDetailDto> orderDetailDtoList=new ArrayList<>();
        for (OrderDetail orderDetail:list) {
            OrderDetailDto orderDetailDto = new OrderDetailDto();
            BeanPlusUtil.copyProperties(orderDetail,orderDetailDto);
            String detailJson = orderDetail.getDetailJson();
            List<DetailJsonReq> detailJsonReqs = JSONObject.parseArray(detailJson, DetailJsonReq.class);
            if (CollectionUtil.isEmpty(detailJsonReqs)|| ObjectUtil.isNull(detailJsonReqs)){
                orderDetailDto.setChildJson(new ArrayList<>());
            }else {

                orderDetailDto.setChildJson(detailJsonReqs);
            }
            orderDetailDtoList.add(orderDetailDto);
        }




//        String detailJson = orderMain.getDetailJson();
//        List<DetailJsonReq> detailJsonReqs = JSONObject.parseArray(detailJson, DetailJsonReq.class);
//        List<OrderDetailDto> orderDetailDtoList=new ArrayList<>();
//        //直接将数据库中的子单进行遍历，将orderMain中的具体detailjson进行解析并且重新修改子单的实际出入库数量，在将实际出入库信息存放到子单的child中返回给前端
//        Map<String, DetailJsonReq> summaryMap = new HashMap<>();
//        //遍历第一遍（确保号型一致，类型一致，价格一致的情况下该出入库信息存在该子单据中）
//        for (OrderDetail orderDetail:list) {
//            OrderDetailDto orderDetailDto = new OrderDetailDto();
//            BeanPlusUtil.copyProperties(orderDetail,orderDetailDto);
//            if (CollectionUtil.isNotEmpty(detailJsonReqs)){
//                for (int i = 0; i < detailJsonReqs.size(); i++) {
//                    DetailJsonReq detailReq = detailJsonReqs.get(i);
//                    if (detailReq.getTypeId().equals(orderDetail.getTypeId())
//                            && detailReq.getSizeId().equals(orderDetail.getSizeId())
//                            && detailReq.getPrice().compareTo(orderDetail.getPrice())==0){//如果类型、号型、单价与子单一致，那么直接存在子单中
//                        List<DetailJsonReq> childJson = orderDetailDto.getChildJson();
//                        if (CollectionUtil.isEmpty(childJson)){
//                            List<DetailJsonReq> list1=new ArrayList<>();
//                            list1.add(detailReq);
//                            orderDetailDto.setChildJson(list1);
//                        }else {
//                            childJson.add(detailReq);
//                            orderDetailDto.setChildJson(childJson);
//                        }
//                        detailJsonReqs.remove(detailReq);
//                        i--;
//
//                    }
//                }
//
//            }else {
//                orderDetailDto.setChildJson(new ArrayList<>());
//            }
//
//            orderDetailDtoList.add(orderDetailDto);
//        }
//        //遍历第二遍，将剩余多的单子存放到sizeId和typeId一样的第一个子单中去
//        if (CollectionUtil.isNotEmpty(detailJsonReqs)){
//            for (OrderDetailDto dto:orderDetailDtoList) {
//                for (int i = 0; i < detailJsonReqs.size(); i++) {
//                    DetailJsonReq deReq = detailJsonReqs.get(i);
//                    if (dto.getTypeId().equals(deReq.getTypeId()) && dto.getSizeId().equals(deReq.getSizeId())){
//                        List<DetailJsonReq> childJson = dto.getChildJson();
//                        if (CollectionUtil.isEmpty(childJson)){
//                            List<DetailJsonReq> list1=new ArrayList<>();
//                            list1.add(deReq);
//                            dto.setChildJson(list1);
//                        }else {
//                            childJson.add(deReq);
//                            dto.setChildJson(childJson);
//                        }
//                        detailJsonReqs.remove(deReq);
//                        i--;
//                    }
//                }
//
//            }
//
//        }
//        //遍历第三遍（将每个childJson进行汇总，并且将具体存放到每个childDetailJson中去）
//        for (OrderDetailDto dto:orderDetailDtoList) {
//            //具体的值
//            List<DetailJsonReq> childJson = dto.getChildJson();
//            //最终存储数据list
//            List<DetailJsonReq> detailList=new ArrayList<>();
//            //第二层数据
//            List<DetailJsonReq> filteredValues=new ArrayList<>();
//            for (DetailJsonReq dReq:childJson) {
//                String key = dReq.getLocationId() + "_" + dReq.getSizeId() + "_" + dReq.getTypeId();
//                DetailJsonReq summary = summaryMap.get(key);
//                if (summary == null) {
//                    summary = new DetailJsonReq();
//                    summary.setLocationId(dReq.getLocationId());
//                    summary.setLocationName(dReq.getLocationName());
//                    summary.setSizeId(dReq.getSizeId());
//                    summary.setTypeId(dReq.getTypeId());
//                    detailList.add(dReq);
//                    summary.setChildDetailJson(detailList);
//                    summaryMap.put(key, summary);
//                }
//                // 汇总数量
//                if (dReq.getNum() != null) {
//                    Integer newNum = summary.getNum() != null ? summary.getNum() + dReq.getNum() : dReq.getNum();
//                    summary.setNum(newNum);
//                    summary.setModifyQuantity(newNum);
//                }
//
//                // 汇总子数据
//                if (dReq.getChildDetailJson() != null) {
//                    detailList.add(dReq);
//                    summary.getChildDetailJson().addAll(detailList);
//                }
//                if (!summaryMap.isEmpty()){
//                    filteredValues = summaryMap.entrySet().stream()
//                            .filter(entry -> {
//                                String[] keyParts = entry.getKey().split("_");
//                                String typeId = keyParts[2];
//                                String sizeId = keyParts[1];
//                                String locationId = keyParts[0];
//                                return typeId.equals(dReq.getTypeId()) && sizeId.equals(dto.getSizeId()) && locationId.equals(dReq.getLocationId());
//                            })
//                            .map(Map.Entry::getValue)
//                            .collect(Collectors.toList());
//                }
//            }
//            dto.setChildJson(filteredValues);
//
//            summaryMap.clear();
//
//        }


        orderDto.setDetailList(orderDetailDtoList);
        return orderDto;
    }

    //单据状态上报
    @Override
    public boolean PushState(OrderUploadReq req) {
        OrderMain orderMain = orderMainExist(req.getId());
        //获取单据的出入库，获取发物单位id或者收物单位id
        String orderType = orderMain.getOrderType();
        String exchangeName="OrderStateExchange";
        //推送到rabbitmq中去
        if (orderType.equals("in")){
            Long endOrgId = orderMain.getEndOrgId();
            Queue queue=new Queue(Long.toString(endOrgId),true,false,false);
            Exchange exchange = new DirectExchange(exchangeName, true, false);
            rabbitAdmin.declareQueue(queue);
            rabbitAdmin.declareExchange(exchange);
            rabbitAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange).with(Long.toString(endOrgId)).noargs());
            rabbitTemplate.convertAndSend(exchangeName, Long.toString(endOrgId), req);

        }else {
            Long startOrgId = orderMain.getStartOrgId();
            Queue queue = new Queue(Long.toString(startOrgId), true, false, false);
            Exchange exchange = new DirectExchange(exchangeName, true, false);
            rabbitAdmin.declareQueue(queue);
            rabbitAdmin.declareExchange(exchange);
            rabbitAdmin.declareBinding(BindingBuilder.bind(queue).to(exchange).with(Long.toString(startOrgId)).noargs());
            rabbitTemplate.convertAndSend(exchangeName, Long.toString(startOrgId), req);
        }
        return true;
    }

    //（只对summary表进行操作）
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean Accounting(UpdateOrderReq req) {
        //将组织机构下面的所有仓库进行查询
        //判断传递的订单主id是否存在
        OrderMain orderMain = orderMainExist(req.getId());

        List<Warehouse> warehouseList = warehouseService.list(new LambdaQueryWrapper<Warehouse>().eq(Warehouse::getOrgId,
                orderMain.getOrderType().equals("in") ? orderMain.getEndOrgId() : orderMain.getStartOrgId()));
        Map<String,Warehouse> warehouseMap=new HashMap<>();
        warehouseList.forEach(warehouse -> warehouseMap.put(warehouse.getId(), warehouse));


//        List<DetailJsonReq> childJsonList=new ArrayList<>();
//        String detailJson = orderMain.getDetailJson();
        //出入库传递的具体汇总信息
//        List<DetailJsonReq> detailJsonList = JSONObject.parseArray(detailJson, DetailJsonReq.class);
        //记账子单据不能传空
        if (req.getDetailList().size()==0){
            throw new ServiceException(OrderExceptionEnum.ORDERDETAIL_ISNOT_NULL);
        }
        //前端传递的子单数据
        List<UpdateOrderDetailReq> reqList = req.getDetailList();
        //将记账数量进行相加
        Integer updateQuantity=0;
        //将价格进行添加修改
        BigDecimal priceTotal=new BigDecimal(0);
        //获取子单据
        List<OrderDetail> list = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId,req.getId()));
        //获取所有传递的子单据id
        Set<Long> collect = req.getDetailList().stream().map(UpdateOrderDetailReq::getId).collect(Collectors.toSet());
        //获取所有数据库的子单据id
        Set<Long> existingIds = list.stream().map(OrderDetail::getId).collect(Collectors.toSet());
        //创建一个操作记录(用于在记账log表中记录)
//        StringBuilder stringBuilder = new StringBuilder();
        //存放更新数据库中的子单据
        List<OrderDetail> orderDetailList=new ArrayList<>();
        //创建一个列表用于修改summary数据库表中数据。
        List<UpdateOrderDetailReq> orderDetailReqList=new ArrayList<>();
//        List<AccountingDto> accountingDtoList=new ArrayList<>();
        String s="";
        //比较两个子单id完全一致,判断传递的子单据id在数据库中是否存在，如果不存在则抛出子单据不存在异常
        if (collect.size() == existingIds.size() && collect.containsAll(existingIds) && existingIds.containsAll(collect)){
            //新增空装备
            List<Inventory> addInvList=new ArrayList<>();
            //删除空装备
            List<Inventory> delInvList=new ArrayList<>();
            List<WarehouseInventory> addWareInvList=new ArrayList<>();
            List<WarehouseInventory> delWareInvList=new ArrayList<>();

            //遍历子单
            for (UpdateOrderDetailReq uploadDetailReq : reqList) {
                OrderDetail orderDetail = new OrderDetail();
                BeanPlusUtil.copyProperties(uploadDetailReq,orderDetail);
                List<DetailJsonReq> JsonList = uploadDetailReq.getChildJson();
                String jsonString = JSONObject.toJSONString(JsonList);
                orderDetail.setDetailJson(jsonString);
                if (ObjectUtil.isNull(uploadDetailReq.getActualNum())){
                    uploadDetailReq.setActualNum(0);
                }
                //获取修改后的数量并且记录(modifyQuantity表示有记账数量)
                if (ObjectUtil.isNull(uploadDetailReq.getModifyQuantity())){
                    throw new ServiceException(OrderExceptionEnum.ORDER_NUM_IS_NULL);
                }
                Inventory inventory = new Inventory();
                WarehouseInventory warehouseInventory=new WarehouseInventory();
                if (uploadDetailReq.getModifyQuantity() >= 0 ){

                    //记账内容
//                    List<DetailJsonReq> childJson = uploadDetailReq.getChildJson();
                    for (DetailJsonReq detailJsonReq:JsonList) {
                        if (!warehouseMap.isEmpty()){
                            //判断是否有key存在，如果没有直接报错
                            boolean b = warehouseMap.containsKey(detailJsonReq.getLocationId());
                            if (b){
                                //判断改仓库是否处于锁库状态，如果是提示错误仓库正在锁库中
                                Warehouse warehouse = warehouseMap.get(detailJsonReq.getLocationId());
                                if (warehouse.getIsLocked()==1){
                                    throw new ServiceException(WarehouseExceptionEnum.WAREHOUSE_IS_LOCKED);
                                }
                            }
                        }

                        //记账差值
                        if (ObjectUtil.isNull(detailJsonReq.getModifyQuantity())){
                            detailJsonReq.setModifyQuantity(uploadDetailReq.getModifyQuantity());
                        }
                        int subNum=detailJsonReq.getModifyQuantity()-(ObjectUtil.isNull(detailJsonReq.getNum())?0:detailJsonReq.getNum());
                        detailJsonReq.setSizeName(uploadDetailReq.getSizeName());
                        detailJsonReq.setTypeName(uploadDetailReq.getTypeName());
                        //添加list为修改库存Summary
                        UpdateOrderDetailReq data = new UpdateOrderDetailReq();
                        data.setActualNum(ObjectUtil.isNull(detailJsonReq.getNum())?0:detailJsonReq.getNum());
                        data.setWarehouseId(detailJsonReq.getLocationId());
                        data.setWarehouseName(detailJsonReq.getLocationName());
                        data.setSizeId(ObjectUtil.isNull(detailJsonReq.getSizeId())? uploadDetailReq.getSizeId():detailJsonReq.getSizeId());
                        data.setTypeId(ObjectUtil.isNull(detailJsonReq.getTypeId())? uploadDetailReq.getTypeId():detailJsonReq.getTypeId());
                        BigDecimal price=BigDecimal.ZERO;
                        if (ObjectUtil.isNull(detailJsonReq.getPrice())){
                            price=equipmentTypeService.getOne(new LambdaQueryWrapper<EquipmentType>()
                                            .eq(EquipmentType::getId,uploadDetailReq.getTypeId()))
                                    .getPrice();

                        }
                        data.setPrice(ObjectUtil.isNull(detailJsonReq.getPrice())? price.toString() :detailJsonReq.getPrice().toString());
                        data.setProperty(ObjectUtil.isNull(detailJsonReq.getProperty())?0:detailJsonReq.getProperty());
                        data.setSizeName(detailJsonReq.getSizeName());
                        data.setTypeName(detailJsonReq.getTypeName());
                        data.setModifyQuantity(detailJsonReq.getModifyQuantity());
                        orderDetailReqList.add(data);
                        //添加出入库日志记录
                        if (orderMain.getOrderType().equals("in")){

                            s = s+detailJsonReq.getLocationName()+"--"+detailJsonReq.getTypeName()+"【"+
                                    detailJsonReq.getSizeName()+"】，单价："+(ObjectUtil.isNull(detailJsonReq.getPrice())?price:detailJsonReq.getPrice())
                                    +"，数量实入："+(ObjectUtil.isNull(detailJsonReq.getNum())?0:detailJsonReq.getNum())+"，记账："+ detailJsonReq.getModifyQuantity()+"\n";
                        }else {
                            s = s+detailJsonReq.getLocationName()+"--"+detailJsonReq.getTypeName()+"【"+
                                    detailJsonReq.getSizeName()+"】，单价："+(ObjectUtil.isNull(detailJsonReq.getPrice())?price:detailJsonReq.getPrice())
                                    +"，数量实出："+(ObjectUtil.isNull(detailJsonReq.getNum())?0:detailJsonReq.getNum())+"，记账："+ detailJsonReq.getModifyQuantity()+"\n";

                        }

                        if (subNum>0){
                            //实际出库或者入库数量大于实际数量，则对空数据进行增删改查
                            if (orderMain.getOrderType().equals("in")){ //入库
                                for (int j = 0; j < subNum; j++) {
                                    inventory.setEpc("0");
                                    inventory.setLocationId(detailJsonReq.getLocationId());
                                    inventory.setSizeId(ObjectUtil.isNull(detailJsonReq.getSizeId())? uploadDetailReq.getSizeId():detailJsonReq.getSizeId());
                                    inventory.setTypeId(ObjectUtil.isNull(detailJsonReq.getTypeId())? uploadDetailReq.getTypeId():detailJsonReq.getTypeId());
                                    inventory.setOrgId(orderMain.getEndOrgId());
                                    inventory.setLocationType(0);
                                    inventory.setPrice(ObjectUtil.isNull(detailJsonReq.getPrice())?price:detailJsonReq.getPrice());
                                    inventory.setProperty(0);
                                    addInvList.add(inventory);
                                    warehouseInventory.setOrgId(orderMain.getEndOrgId());
                                    warehouseInventory.setLocationId(detailJsonReq.getLocationId());
                                    warehouseInventory.setTypeId(ObjectUtil.isNull(detailJsonReq.getTypeId())? uploadDetailReq.getTypeId():detailJsonReq.getTypeId());
                                    warehouseInventory.setSizeId(ObjectUtil.isNull(detailJsonReq.getSizeId())? uploadDetailReq.getSizeId():detailJsonReq.getSizeId());
                                    warehouseInventory.setLocationType("0");
                                    addWareInvList.add(warehouseInventory);
                                }
                            }else {//出库
                                List<Inventory> list1 = inventoryService.list(new LambdaQueryWrapper<Inventory>()
                                        .eq(Inventory::getEpc, "0")
                                        .eq(Inventory::getLocationId, detailJsonReq.getLocationId())
                                        .eq(Inventory::getSizeId, ObjectUtil.isNull(detailJsonReq.getSizeId())? uploadDetailReq.getSizeId():detailJsonReq.getSizeId())
                                        .eq(Inventory::getOrgId, orderMain.getStartOrgId())
                                        .eq(Inventory::getTypeId, ObjectUtil.isNull(detailJsonReq.getTypeId())? uploadDetailReq.getTypeId():detailJsonReq.getTypeId())
                                        .eq(Inventory::getPrice, detailJsonReq.getPrice())
                                        .eq(Inventory::getLocationType, "0"));
                                List<WarehouseInventory> list2 = warehouseInventoryService.list(new LambdaQueryWrapper<WarehouseInventory>()
                                        .eq(WarehouseInventory::getEpc, "0")
                                        .eq(WarehouseInventory::getLocationId, detailJsonReq.getLocationId())
                                        .eq(WarehouseInventory::getOrgId, orderMain.getStartOrgId())
                                        .eq(WarehouseInventory::getSizeId, ObjectUtil.isNull(detailJsonReq.getSizeId())? uploadDetailReq.getSizeId():detailJsonReq.getSizeId())
                                        .eq(WarehouseInventory::getTypeId,ObjectUtil.isNull(detailJsonReq.getTypeId())? uploadDetailReq.getTypeId():detailJsonReq.getTypeId()));


                                if (list1.size()>0){
                                    //如果记账数量大于库存中存在空数据，那么全部删除，否则选择前几条进行删除
                                    if (subNum>=list1.size()){
                                        delInvList.addAll(list1);
                                    }else {

                                        for (int j = 0; j < subNum; j++) {
                                            delInvList.add(list1.get(j));
                                        }
                                    }
                                }
                                if (list2.size()>0){
                                    if (subNum>=list2.size()){
                                        delWareInvList.addAll(list2);
                                    }else {
                                        for (int j = 0; j < subNum; j++) {
                                            delInvList.add(list1.get(j));
                                        }
                                    }
                                }

                            }

                        }

                    }
//                    childJsonList.addAll(childJson);

                    //修改单子数量数量
                    orderDetail.setModifyQuantity(uploadDetailReq.getModifyQuantity());
                    orderDetail.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                    orderDetailList.add(orderDetail);
                    updateQuantity+=orderDetail.getModifyQuantity();

                }else {
                    throw new ServiceException(OrderExceptionEnum.ORDERDETAIL_ERROR);
                }
            }



            if (addWareInvList.size()>0){
                inventoryService.saveBatch(addInvList);
            }
            if (addInvList.size()>0){
                warehouseInventoryService.saveBatch(addWareInvList);
            }
            if (delInvList.size()>0){
                inventoryService.removeBatchByIds(delInvList);
            }
            if (delWareInvList.size()>0){
                warehouseInventoryService.removeBatchByIds(delWareInvList);
            }
        }else {
            throw new ServiceException(OrderExceptionEnum.ORDERDETAIL_ERROR);
        }
        //批量更新子单据数量
        boolean a=false;
        if (orderDetailList.size()!=0){
            a = orderDetailService.updateBatchById(orderDetailList);
        }
        //更新主单据的数量和价格
        orderMain.setActualQuantity(updateQuantity);
        orderMain.setOrderState("finished");
        //修改记账状态，0未记账，1已记账
        orderMain.setManualState(1);
        orderMain.setUpdateTime(DateTimeUtil.getCurrentDateTime());
        boolean b = updateById(orderMain);
        //将修改内容存储记录（历史操作，数量，单据，价格，组织机构）
        //创建记账操作记录并且记录到数据表order_log中
        boolean c = saveAccountingLog(req, s, updateQuantity);
//        boolean c = saveAccountingLog(req, accountingDtoList, updateQuantity);

        //修改装备汇总表中的数据 inventory_summary
        Long orgId;
        if (orderMain.getOrderType().equals("in")){
            orgId=orderMain.getEndOrgId();
        }
        else {
            orgId=orderMain.getStartOrgId();
        }
        PubOrg pubOrg = pubOrgService.PubOrgExist(orgId);
        boolean d = true;
        //如果是快速移库，记账完成之后新增入库单并且该单据不走审核流，但是审核状态和入库状态显示已完成
        boolean g=true;
        if (req.getBussinessType().equals("quick")){
            g = handleQuickOrder(orderMain,reqList);
        }else {
            d=updateSummaryInfo(req, orderDetailReqList, pubOrg.getOrgId(), pubOrg.getOrgCode(),pubOrg.getOrgName());
        }
        //如果是领用，警员绑定装备
        boolean e=true;
        if (req.getBussinessType().equals("use")){

            e = policeBindEqs(req, orderDetailReqList, orgId);
        }
//        //如果是归还入库，将警员下面的装备进行处理
        boolean f=true;
        if (req.getBussinessType().equals("return")){
            f = policeUnBindEqs(req, orderDetailReqList, orgId);
        }

        //记账结束之后往消息队列中推送一条消息
        String exchangeName="orderExchange";
        MQReturnMsgDto mqReturnMsgDto = new MQReturnMsgDto();
        mqReturnMsgDto.setApi("SettlementOrder");
        mqReturnMsgDto.setId(req.getId());
        mqReturnMsgDto.setOrderType(req.getOrderType());
        //需要判断是入库单还是出库单，入库单传收物单位id，出库单传发物单位id
        if(req.getOrderType().equals("in")){
            MQ.SendMsg(exchangeName,req.getEndOrgId().toString(),mqReturnMsgDto);
        }else {
            MQ.SendMsg(exchangeName,req.getStartOrgId().toString(),mqReturnMsgDto);
        }
        //更新主单据
        return (a && b && c && d && e && f && g );
    }
    public boolean policeUnBindEqs(UpdateOrderReq req,List<UpdateOrderDetailReq> orderDetailReqList,Long orgId){
        //根据传递的装备信息对警员进行解绑操作(判断警员下面是否有装备信息，如果有则直接进行修改或者删除，如果没有则跳过不处理)
        Policeman one = policemanService.getOne(new LambdaQueryWrapper<Policeman>().eq(Policeman::getUserId, req.getReturnUserId()));
        List<PoliceEquipment> list = policeEquipmentService.list(new LambdaQueryWrapper<PoliceEquipment>()
                .eq(ObjectUtil.isNotNull(req.getReturnUserId()), PoliceEquipment::getPoliceId, one.getId())
                .eq(PoliceEquipment::getOrgId,orgId));
        List<PoliceEquipment> delList=new ArrayList<>();
        List<PoliceEquipment> updateList=new ArrayList<>();
        if (list.size()>0){
            for (UpdateOrderDetailReq upReq:orderDetailReqList) {

                for (PoliceEquipment pEqs:list ) {
                    if (upReq.getSizeId().equals(pEqs.getSizeId()) && upReq.getTypeId().equals(pEqs.getTypeId())
                            && new BigDecimal(upReq.getPrice()).compareTo(pEqs.getPrice())==0){
                        //如果数量大于等于的情况下直接将该条数据进行删除，否则直接修改数量并且更新
                        if (upReq.getModifyQuantity()>=pEqs.getNum()){
                            delList.add(pEqs);
                        }else {
                            pEqs.setNum(pEqs.getNum()-upReq.getModifyQuantity());
                            updateList.add(pEqs);
                        }
                        break;
                    }
                }
            }
            boolean a=true;
            if (delList.size()>0){
                a=policeEquipmentService.removeBatchByIds(delList);
            }
            boolean b=true;
            if (updateList.size()>0){
                b=policeEquipmentService.updateBatchById(updateList);
            }
            return a && b;
        }else {
            return  true;
        }
    }
    public boolean policeBindEqs(UpdateOrderReq req,List<UpdateOrderDetailReq> orderDetailReqList,Long orgId){
        //如果是领用出库，那记账结束以后将装备挂到警员名下（存储到policemanEquipment表中）
        Policeman policeman = policemanService.getOne(new LambdaQueryWrapper<Policeman>().eq(Policeman::getUserId, req.getReturnUserId()));
        if (req.getBussinessType().equals("use")){
            List<PoliceEquipment> collect1 = orderDetailReqList.stream().map(updateOrderDetailReq -> {
                PoliceEquipment policeEquipment = new PoliceEquipment();
                policeEquipment.setPoliceId(policeman.getId());
                policeEquipment.setPoliceName(policeman.getName());
                policeEquipment.setSizeId(updateOrderDetailReq.getSizeId());
                policeEquipment.setSizeName(updateOrderDetailReq.getSizeName());
                policeEquipment.setTypeId(updateOrderDetailReq.getTypeId());
                policeEquipment.setTypeName(updateOrderDetailReq.getTypeName());
                policeEquipment.setNum(updateOrderDetailReq.getModifyQuantity());
                policeEquipment.setInNum(0);
                policeEquipment.setOutNum(updateOrderDetailReq.getModifyQuantity());
                policeEquipment.setOrgId(orgId);
                policeEquipment.setPrice(new BigDecimal(updateOrderDetailReq.getPrice()));
                policeEquipment.setLocationId(updateOrderDetailReq.getWarehouseId());
                policeEquipment.setCreateTime(DateTimeUtil.getCurrentDateTime());
                return policeEquipment;
            }).collect(Collectors.toList());
            return policeEquipmentService.saveBatch(collect1);
        }else {
            return true;
        }
    }

    //将修改内容存储记录（历史操作，数量，单据，价格，组织机构）
    //创建记账操作记录并且记录到数据表order_log中
    public boolean saveAccountingLog (UpdateOrderReq req,String s,Integer updateQuantity){

        OrderLog orderLog = new OrderLog();
        BeanPlusUtil.copyProperties(req,orderLog);
        orderLog.setId(UUID.randomUUID().toString());
        orderLog.setHistoryMsg(s);
//        orderLog.setHistoryMsg(JSON.toJSONString(accountingDtoList));
        orderLog.setInventoryQuantity(req.getInventoryQuantity());
        orderLog.setActualQuantity(req.getActualQuantity());
        orderLog.setUpdateQuantity(updateQuantity);
        if (req.getOrderType().equals("in")){
            orderLog.setOrgId(req.getEndOrgId());
            orderLog.setOrgName(req.getEndOrgName());
        }else {
            orderLog.setOrgId(Long.parseLong(req.getStartOrgId()));
            orderLog.setOrgName(req.getStartOrgName());
        }
        orderLog.setOrderId(req.getId());
        String userId="";
        if (ObjectUtil.isNotNull(req.getUserId())){
            userId=req.getUserId();
        }else {
            LoginUser loginUser = LoginContext.getContext().getLoginUser();
            userId=loginUser.getUserId().toString();
        }
        SysUser sysUser = sysUserService.getById(userId);
        orderLog.setCreateUser(sysUser.getNickName());
        orderLog.setCreateTime(DateTimeUtil.getCurrentDateTime());
        orderLog.setProcessType("accounting");
        //将记账记录保存
        return orderLogService.save(orderLog);
    }

    //修改装备汇总表中的数据inventory_summary
    public boolean updateSummaryInfo(UpdateOrderReq req,List<UpdateOrderDetailReq> orderDetailReqList,Long orgId,String orgCode,String orgName){
        //将库存summary表中数据进行查询出来一一进行比较，如果说sizeId，typeId，warehouseId相同则对该数据进行修改，如果说该数据不存在的话则在summary表中添加一条数据
        List<Object[]> searchCriteria=new ArrayList<>();
        for (UpdateOrderDetailReq upReq: orderDetailReqList) {

            Object[] criteria=new Object[]{orgId,upReq.getWarehouseId(),upReq.getTypeId(),upReq.getSizeId(),upReq.getPrice(),upReq.getProperty()};
            searchCriteria.add(criteria);

        }
        //库存信息
        List<InventorySummary> inventorySummaryList = inventorySummaryMapper.selectSum(searchCriteria);
        List<InventorySummary> addList=new ArrayList<>();
        List<InventorySummary> updateList=new ArrayList<>();
        for (UpdateOrderDetailReq upReq: orderDetailReqList) {
            boolean flag=false;
            for (InventorySummary is:inventorySummaryList) {
                if (upReq.getWarehouseId().equals(is.getLocationId()) && upReq.getSizeId().equals(is.getSizeId())
                        && upReq.getTypeId().equals(is.getTypeId()) && new BigDecimal(upReq.getPrice()).compareTo(is.getUnitPrice())==0){
                    is.setUpdateTime(DateTimeUtil.getCurrentDateTime());
                    //修改各种数量和价格
                    if (req.getOrderType().equals("in")){
                        switch (req.getBussinessType()){
                            case "purchase":
                            case "allocate":
                            case "gift":
                            case "other":
                                is.setStockNumber(is.getStockNumber()+upReq.getModifyQuantity());
                                is.setNumber(is.getStockNumber()+is.getOutboundNumber());
                                is.setPrice(is.getPrice().add(BigDecimal.valueOf(upReq.getModifyQuantity()).multiply(new BigDecimal(upReq.getPrice()))) );
                                break;
                            case "return":
                            case "repair":
                                //如果入库数大于实际出库数，那么在库数和总数进行添加，出库数为0
                                if (is.getOutboundNumber()-upReq.getModifyQuantity()<0){
                                    is.setOutboundNumber(0);
                                    is.setStockNumber(is.getStockNumber()+upReq.getModifyQuantity()-is.getOutboundNumber());
                                    is.setNumber(is.getNumber()+upReq.getModifyQuantity()-is.getOutboundNumber());
                                }else {
                                    is.setOutboundNumber(is.getOutboundNumber()-upReq.getModifyQuantity());
                                    is.setStockNumber(is.getStockNumber()+upReq.getModifyQuantity());
                                }
                                is.setPrice(is.getPrice().add(BigDecimal.valueOf(upReq.getModifyQuantity()).multiply(new BigDecimal(upReq.getPrice()))) );
                                break;
                        }
                    }else {
                        switch (req.getBussinessType()){
                            case "destruction":
//                                //我先把库存数量加回来，然后根据实际出库数量进行删减
//                                is.setDestructionNumber(is.getDestructionNumber() - upReq.getPlanNum());
//                                is.setNumber(is.getNumber() + upReq.getPlanNum());
//                                is.setStockNumber(is.getStockNumber() + upReq.getPlanNum());

                                //直接减去库存数量
                                is.setNumber(Math.max(is.getNumber() - upReq.getModifyQuantity(), 0));
                                is.setPrice(is.getUnitPrice().multiply(BigDecimal.valueOf(is.getNumber())));
                                is.setStockNumber(Math.max(is.getStockNumber()-upReq.getModifyQuantity(),0));
                                is.setDestructionNumber(is.getDestructionNumber()+upReq.getModifyQuantity());
                                is.setDestructionNumberPrice(is.getUnitPrice().multiply(BigDecimal.valueOf(is.getDestructionNumber())));
                                break;
                            case "allocate":
                                is.setNumber(Math.max(is.getNumber() - upReq.getModifyQuantity(), 0));
                                is.setStockNumber(Math.max(is.getStockNumber() - upReq.getModifyQuantity(), 0));
                                is.setPrice(is.getPrice().subtract(BigDecimal.valueOf(upReq.getModifyQuantity()).multiply(new BigDecimal(upReq.getPrice()))) );
                                break;
                            case "use":
                                is.setOutboundNumber(is.getOutboundNumber()+upReq.getModifyQuantity());
                                is.setStockNumber(Math.max(is.getStockNumber() - upReq.getModifyQuantity(), 0));
                                is.setPrice(is.getPrice().subtract(BigDecimal.valueOf(upReq.getModifyQuantity()).multiply(new BigDecimal(upReq.getPrice()))) );
                                if (ObjectUtil.isNull(is.getUseCount())){
                                    is.setUseCount(0);
                                }
                                is.setUseCount(is.getUseCount()+upReq.getModifyQuantity());
                                if(ObjectUtil.isNull(is.getUseNumber())){
                                    is.setUseNumber(0);
                                }
                                is.setUseNumber(is.getUseNumber()+upReq.getModifyQuantity());
                                break;
                            case "repair":
                                is.setOutboundNumber(is.getOutboundNumber()+upReq.getModifyQuantity());
                                is.setStockNumber(Math.max(is.getStockNumber() - upReq.getModifyQuantity(), 0));
                                is.setPrice(is.getPrice().subtract(BigDecimal.valueOf(upReq.getModifyQuantity()).multiply(new BigDecimal(upReq.getPrice()))) );
                                if (ObjectUtil.isNull(is.getFixCount())){
                                    is.setFixCount(0);
                                }
                                is.setFixCount(is.getFixCount()+upReq.getModifyQuantity());
                                break;
                            case "other":
                                is.setOutboundNumber(is.getOutboundNumber()+upReq.getModifyQuantity());
                                is.setStockNumber(Math.max(is.getStockNumber() - upReq.getModifyQuantity(), 0));
                                is.setPrice(is.getPrice().subtract(BigDecimal.valueOf(upReq.getModifyQuantity()).multiply(new BigDecimal(upReq.getPrice()))) );
                                break;
//                            case "quick":
//
//                                break;
                        }
                    }
                    updateList.add(is);
                    flag=true;
                    break;
                }
            }
            //表示库存中没有，那么插入数据
            if (!flag){
                InventorySummary inventorySummary = new InventorySummary();
                inventorySummary.setOrgCode(orgCode);
                inventorySummary.setOrgName(orgName);
                inventorySummary.setOrgId(orgId);
                inventorySummary.setValuekey(orgCode+upReq.getWarehouseId()+upReq.getTypeId()+upReq.getSizeId()+upReq.getPrice());
                inventorySummary.setSizeId(upReq.getSizeId());
                inventorySummary.setSizeName(upReq.getSizeName());
                inventorySummary.setTypeName(upReq.getTypeName());
                inventorySummary.setTypeId(upReq.getTypeId());
                inventorySummary.setLocationName(upReq.getWarehouseName());
                inventorySummary.setLocationId(upReq.getWarehouseId());
                inventorySummary.setUnitPrice(new BigDecimal(upReq.getPrice()));
                inventorySummary.setPrice(BigDecimal.valueOf(upReq.getModifyQuantity()).multiply(new BigDecimal(upReq.getPrice())));
                inventorySummary.setLocationType("0");
                inventorySummary.setBrokenNumber(0);
                inventorySummary.setExpireNumber(0);
                inventorySummary.setDestructionNumber(0);
                inventorySummary.setNearBrokenNumber(0);
                inventorySummary.setNumber(upReq.getModifyQuantity());
                inventorySummary.setCreateTime(DateTimeUtil.getCurrentDateTime());
                inventorySummary.setProperty(upReq.getProperty());
                if (req.getOrderType().equals("in")){
                    inventorySummary.setOutboundNumber(0);
                    inventorySummary.setUseNumber(0);
                    inventorySummary.setStockNumber(upReq.getModifyQuantity());
                    addList.add(inventorySummary);
                }
            }
        }

        boolean a=true;
        if (addList.size()>0){
            boolean b = inventorySummaryService.saveBatch(addList);
            a = b;
        }
        if (updateList.size()>0){
            boolean b = inventorySummaryService.updateBatchById(updateList);
            a = a && b;
        }

        return a;

    }

    /**
     * 查看记账列表
     * @param req
     * @return
     */
    @Override
    public PageResult<OrderLog> ShowAccountingPage(QueryOrderLogReq req) {
        LambdaQueryWrapper<OrderLog> eq = new LambdaQueryWrapper<OrderLog>()
                .eq(ObjectUtil.isNotNull(req.getBussinessType()), OrderLog::getBussinessType, req.getBussinessType())
                .eq(ObjectUtil.isNotNull(req.getOrderType()), OrderLog::getOrderType, req.getOrderType())
                .eq(ObjectUtil.isNotNull(req.getOrderId()), OrderLog::getOrgId, req.getOrgId())
                .ge(ObjectUtil.isNotNull(req.getStartTime()), OrderLog::getCreateTime, req.getStartTime())
                .le(ObjectUtil.isNotNull(req.getEndTime()), OrderLog::getCreateTime, req.getEndTime());
        Page<OrderLog> page = orderLogService.page(PageFactory.getDefaultPage(req.getPageNo(), req.getPageSize()), eq);
        return PageResultFactory.createPageResult(page);
    }


    /**
     * 入库单导出功能
     * @param req
     */
    @Override
    public void InOrderExport(OrderMainReq req) {
        LambdaQueryWrapper<OrderMain> wrapper = createWrapper(req);
        List<InOrderInfoVo> collect = list(wrapper).stream().map(orderMain -> {
            InOrderInfoVo inOrderInfoVo = new InOrderInfoVo();
            BeanPlusUtil.copyProperties(orderMain, inOrderInfoVo);
            //装备名称
            String inventoryName = "";
            List<OrderDetail> orderDetailList = orderDetailService.QueryList(orderMain.getId());
            for (OrderDetail orderDetail : orderDetailList) {
                inventoryName = inventoryName + orderDetail.getTypeName() + "/";
            }
            String substring = inventoryName.substring(0, inventoryName.length() - 1);
            inOrderInfoVo.setInventoryName(substring);
            //查询字典表设置入库类型
//            List<SysDictItem> list = sysDictItemService.list(new LambdaQueryWrapper<SysDictItem>()
//                    .eq(SysDictItem::getItemValue, orderMain.getBussinessType()));
////            inOrderInfo.setOrderType(itemText);
//            System.out.println("list = " + list);
            return inOrderInfoVo;

        }).collect(Collectors.toList());
        //设置导出的单据序号
        for (int i = 1; i <= collect.size() ; i++) {
            collect.get(i-1).setNumId(i);
        }
        HttpServletResponse response = HttpServletUtil.getResponse();
        ExcelExportParam param = new ExcelExportParam();
        param.setDataList(collect);
        param.setClazz(InOrderInfoVo.class);
        param.setResponse(response);
        param.setFileName("入库单据列表.xls");
        //对数据进行导出
        officeExcelApi.easyExportDownload(param);

    }

    @Override
    public void OutOrderExport(OrderMainReq req) {
        LambdaQueryWrapper<OrderMain> wrapper = createWrapper(req);
        List<InOrderInfoVo> collect = list(wrapper).stream().map(orderMain -> {
            InOrderInfoVo inOrderInfoVo = new InOrderInfoVo();
            BeanPlusUtil.copyProperties(orderMain, inOrderInfoVo);
            //装备名称
            String inventoryName = "";
            List<OrderDetail> orderDetailList = orderDetailService.QueryList(orderMain.getId());
            for (OrderDetail orderDetail : orderDetailList) {
                inventoryName = inventoryName + orderDetail.getTypeName() + "/";
            }
            String substring = inventoryName.substring(0, inventoryName.length() - 1);
            inOrderInfoVo.setInventoryName(substring);
            //查询字典表设置出库类型
//            List<SysDictItem> list = sysDictItemService.list(new LambdaQueryWrapper<SysDictItem>()
//                    .eq(SysDictItem::getItemValue, orderMain.getBussinessType()));
////            inOrderInfo.setOrderType(itemText);
//            System.out.println("list = " + list);
            return inOrderInfoVo;

        }).collect(Collectors.toList());
        //设置导出的单据序号
        for (int i = 1; i <= collect.size() ; i++) {
            collect.get(i-1).setNumId(i);
        }
        HttpServletResponse response = HttpServletUtil.getResponse();
        ExcelExportParam param = new ExcelExportParam();
        param.setDataList(collect);
        param.setClazz(InOrderInfoVo.class);
        param.setResponse(response);
        param.setFileName("出库单据列表.xls");
        //对数据进行导出
        officeExcelApi.easyExportDownload(param);
    }


    //判断任务单是否存在
    @Override
    public OrderMain orderMainExist(String id) {
        OrderMain order = this.getById(id);
        if (ObjectUtil.isNull(order)) {
            throw new ServiceException(OrderExceptionEnum.ORDER_NOT_EXIST);
        }
        return order;
    }


    private LambdaQueryWrapper<OrderMain> createWrapper(OrderMainReq req) {
        LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isEmpty(req)) {
            return wrapper;
        }
        //单据类型（in入库，out出库）
        wrapper.eq(ObjectUtil.isNotEmpty(req.getOrderType()),OrderMain::getOrderType,req.getOrderType());
        //单据状态 ready待入/出库，finished已入/出库，working入/出库中
        wrapper.eq(ObjectUtil.isNotEmpty(req.getOrderState()), OrderMain::getOrderState, req.getOrderState());
//        //审核状态:none,未接入审核流，working审批中，finished已完成
        wrapper.eq(ObjectUtil.isNotEmpty(req.getExamineState()), OrderMain::getExamineState, req.getExamineState());
        //业务类型
        wrapper.eq(ObjectUtil.isNotEmpty(req.getBussinessType()), OrderMain::getBussinessType, req.getBussinessType());
        //组织机构id(入库单)
        wrapper.eq(ObjectUtil.isNotEmpty(req.getEndOrgId()),OrderMain::getEndOrgId,req.getEndOrgId());
        //组织机构id（出库单）
        wrapper.ge(ObjectUtil.isNotNull(req.getStartTime()),OrderMain::getCreateTime,req.getStartTime());
        wrapper.le(ObjectUtil.isNotNull(req.getEndTime()),OrderMain::getCreateTime,req.getEndTime());
        wrapper.orderByDesc(OrderMain::getCreateTime);

        return wrapper;

    }


    /**
     * 根据流程id和单据类型查询出该单子据的信息
     * @param req
     * @return
     */
    @Override
    public ProcessOrderDto GetByProcessId(OrderMainReq req) {
        String receiveUser="";
        if (req.getReceiveUserId()!=null)//
        {
            receiveUser = req.getReceiveUserId();
        }
        else
        {
            receiveUser= LoginContext.getContext().getLoginUser().getUserId().toString();
        }

        ProcessOrderDto processOrderDto = new ProcessOrderDto();
        if (req.getOrderType().equals("null")|| ObjectUtil.isNull(req.getOrderType())) {
            return processOrderDto;
        }

//        //点击后消除已读消息,暂时不用，依赖前端处理
//        MessageReq reqmsg=new MessageReq();
//        reqmsg.setBizId(Long.valueOf(req.getProcessInstanceId()));
//        reqmsg.setReceiveUserId(Long.valueOf(receiveUser));
//        reqmsg.setReadFlag(0);
//        List<MessageRes> msgRes= messageApi.queryList(reqmsg);
//        if (msgRes.size()>0)
//        {
//            // 使用流将 id 取出，并用逗号拼接成字符串
//            String ids = msgRes.stream()
//                    .map(MessageRes::getMsgId)
//                    .map(String::valueOf) // 将 id 转换为字符串
//                    .collect(Collectors.joining(","));
//            messageApi.batchReadFlagByMessageIds(ids, MsgReadStateEnum.READ);
//        }
        if (req.getOrderType().equals("workOrder")){
            OrderDto orderDto = new OrderDto();
            OrderMain one = getOne(new LambdaQueryWrapper<OrderMain>()
                    .eq(OrderMain::getProcessId, req.getProcessId()));
            if (ObjectUtil.isNull(one)){
                return processOrderDto;
            }
            BeanPlusUtil.copyProperties(one,orderDto);

            List<OrderDetailDto> collect = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                    .eq(OrderDetail::getOrderId, one.getId())).stream().map(orderDetail -> {
                OrderDetailDto orderDetailDto = new OrderDetailDto();
                BeanPlusUtil.copyProperties(orderDetail, orderDetailDto);
                return orderDetailDto;
            }).collect(Collectors.toList());
            orderDto.setDetailList(collect);
            processOrderDto.setOrderDto(orderDto);
        } else if (req.getOrderType().equals("bussinessOrder")) {
            BusFormDto busFormDto = new BusFormDto();
            BusForm one = busFormService.getOne(new LambdaQueryWrapper<BusForm>()
                    .eq(BusForm::getProcessId, req.getProcessId()));
            BeanPlusUtil.copyProperties(one,busFormDto);
            processOrderDto.setBusFormDto(busFormDto);
        } else if (req.getOrderType().equals("stacktakeOrder")) {
            BussinessInventoryDto bussinessInventoryDto = new BussinessInventoryDto();
            BussinessInventory one = bussinessInventoryService.getOne(new LambdaQueryWrapper<BussinessInventory>()
                    .eq(BussinessInventory::getProcessId, req.getProcessId()));
            List<EquipmentListDto> collect = bussinessInventoryDetailService.list(new LambdaQueryWrapper<BussinessDetail>()
                    .eq(BussinessDetail::getInventoryId, one.getId())).stream().map(bussinessDetail -> {
                EquipmentListDto equipmentListDto = new EquipmentListDto();
                BeanPlusUtil.copyProperties(bussinessDetail, equipmentListDto);
                return equipmentListDto;
            }).collect(Collectors.toList());
            bussinessInventoryDto.setEquipmentList(collect);
            processOrderDto.setBussinessInventoryDto(bussinessInventoryDto);
        } else if (req.getOrderType().equals("reassigment")) {
            ReassignmentDto reassignmentDto = new ReassignmentDto();
            Reassignment one = reassignmentService.getOne(new LambdaQueryWrapper<Reassignment>()
                    .eq(Reassignment::getProcessId, req.getProcessId()));
            BeanPlusUtil.copyProperties(one,reassignmentDto);
            processOrderDto.setReassignmentDto(reassignmentDto);
        }
        return processOrderDto;
    }




    public boolean handleQuickOrder(OrderMain existOrder,List<UpdateOrderDetailReq> reqList) {
        //原来出库单的查询条件list（根据条件查询库存汇总表中包含有相同条件的数据）
        List<Object[]> searchCriteria=new ArrayList<>();
        //新建的入库单查询条件list（根据条件查询库存汇总表中是否包含有相同条件的数据）
        List<Object[]> updateCriteria=new ArrayList<>();
        //创建新的orderMain入库单
        OrderMain orderMain = new OrderMain();
        BeanPlusUtil.copyProperties(existOrder,orderMain);
        orderMain.setEndOrgId(existOrder.getStartOrgId());
        orderMain.setEndOrgName(existOrder.getStartOrgName());
        orderMain.setOrderType("in");
        orderMain.setId(UUID.randomUUID().toString());
        //工作流流程设为空
        orderMain.setProcessId(null);
        //修改订单编号，设置为入库的单号
        UpdateOrderReq req = new UpdateOrderReq();
        BeanPlusUtil.copyProperties(orderMain,req);
        OrderNum orderNum = setOrderCode(req);
        String codeValue=String.format("%04d",orderNum.getNum());
        orderMain.setOrderCode(orderNum.getBussinessType()+orderNum.getYear()+
                String.format("%02d",LocalDateTime.now().getMonth().getValue())+
                String.format("%02d",LocalDateTime.now().getDayOfMonth())+codeValue);
        //保存入库单
        save(orderMain);
        //查询出库子单用于赋值到入库单中
        List<OrderDetail> list = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId, existOrder.getId()));
        //仓库id
        String locationId = orderMain.getLocationId();
        String locationName = orderMain.getLocationName();
        //查询条件，将所有查询条件放在searchCriteria中，用于修改库存表中的装备的仓库位置
        //循环记账子单
        List<DetailJsonReq> jsonCollect =new ArrayList<>();
        for (UpdateOrderDetailReq detailReq:reqList) {
            List<DetailJsonReq> childJson = detailReq.getChildJson();
            jsonCollect.addAll(childJson);
            for (DetailJsonReq jsonReq:childJson) {
                //移出仓库
                Object[] criteria=new Object[]{existOrder.getStartOrgId(),jsonReq.getLocationId(),detailReq.getTypeId(),detailReq.getSizeId(),detailReq.getPrice(),detailReq.getProperty()};
                searchCriteria.add(criteria);
                //移入仓库
                Object[] update=new Object[]{orderMain.getEndOrgId(),locationId,jsonReq.getTypeId(),detailReq.getSizeId(),detailReq.getPrice(),detailReq.getProperty()};
                updateCriteria.add(update);
//
            }
        }

        //创建入库单子单
        List<OrderDetail> collect = list.stream().map(orderDetail -> {

            OrderDetail orderDetail1 = new OrderDetail();
            BeanPlusUtil.copyProperties(orderDetail, orderDetail1);
            List<DetailJsonReq> detailJsonReqs = JSONObject.parseArray(orderDetail.getDetailJson(), DetailJsonReq.class);
            for (DetailJsonReq a:detailJsonReqs) {
                a.setLocationId(locationId);
                a.setLocationName(locationName);
            }
            orderDetail1.setDetailJson(JSONObject.toJSONString(detailJsonReqs));
            orderDetail1.setId(null);
            //修改主单据id
            orderDetail1.setOrderId(orderMain.getId());
            //修改单据出入状态
            orderDetail1.setType("in");
            //修改仓库id
            orderDetail1.setWarehouseId(locationId);
            orderDetail1.setWarehouseName(locationName);

            return orderDetail1;
        }).collect(Collectors.toList());
        orderDetailService.saveBatch(collect);


        //将summary汇总表中数据进行修改(修改该组织机构下的装备汇总信息将库存信息的在库数，库存总数，总价还有其他数据数量进行修改)
        //那么首先将原来的仓库下的装备汇总信息进行查询出来，对其进行修改
        List<InventorySummary> oldSummaryList = inventorySummaryMapper.selectSumByItems(searchCriteria);
        Map<String, InventorySummary> resultMap = new HashMap<>();
        for (InventorySummary summary : oldSummaryList) {
            String key = summary.getSizeId() + "_" + summary.getTypeId();
            if (resultMap.containsKey(key)) {
                InventorySummary existingSummary = resultMap.get(key);
                existingSummary.setStockNumber(existingSummary.getStockNumber() + summary.getStockNumber());
                existingSummary.setBrokenNumber(existingSummary.getBrokenNumber() + summary.getBrokenNumber());
                existingSummary.setNumber(existingSummary.getNumber() + summary.getNumber());
            } else {
                resultMap.put(key, summary);
            }
        }
        List<InventorySummary> summaryList = new ArrayList<>(resultMap.values());
        //其次查询出修改后的仓库下面的汇总信息，判断该仓库下是否已经存在该号型、类型、单价相同的装备数据
        List<InventorySummary> newSummaryList = inventorySummaryMapper.selectSumByItems(updateCriteria);
        //第一步：判断是否将报废区的数据也同样进行移库(flag=true表示将报废区的数量进行一起移动),如果都没有报废数量，默认是true；
        boolean flag = oldSummaryList.stream()
                .noneMatch(oldsum -> oldsum.getBrokenNumber() > 0)
                || summaryList.stream()
                .filter(sum -> sum.getBrokenNumber() > 0).allMatch(orderDetail -> orderDetail.getBrokenNumber() + orderDetail.getStockNumber() == orderDetail.getNumber());

        //创建删除列表用于将没用的数据汇总信息进行删除
        List<InventorySummary> deleteList=new ArrayList<>();
        //将修改的信息直接保存(需要的只是各种数量方便计算)
        List<InventorySummary> saveList=new ArrayList<>();

        //如果整个报废区进行移动，那么将各个数量进行修改
        if (flag){
            for (DetailJsonReq json: jsonCollect ) {

                for (InventorySummary oldSum : oldSummaryList) {
                    //如果组织机构、仓库id、sizeId、typeId、unitPrice相同，那么修改其各项数值（不会存在两个列表长度不对等的情况，一定是一对一的，只不过是顺序问题，所以需要进行遍历）
                    if (json.getSizeId().equals(oldSum.getSizeId())
                            && json.getTypeId().equals(oldSum.getTypeId())
                            && json.getPrice().compareTo(oldSum.getUnitPrice()) == 0
                            && json.getProperty() == oldSum.getProperty()) {
                        InventorySummary inventorySummary = new InventorySummary();
                        BeanPlusUtil.copyProperties(oldSum,inventorySummary);
                        inventorySummary.setLocationId(locationId);
                        inventorySummary.setLocationName(locationName);
                        inventorySummary.setNumber(json.getModifyQuantity()+oldSum.getOutboundNumber());
                        inventorySummary.setPrice(json.getPrice().multiply(BigDecimal.valueOf(json.getModifyQuantity())));
                        inventorySummary.setStockNumber(json.getModifyQuantity());
                        inventorySummary.setDestructionNumber(0);
                        //销毁金额也为0
                        inventorySummary.setDestructionPrice(BigDecimal.ZERO);
                        inventorySummary.setId(null);
                        inventorySummary.setValuekey(null);
                        saveList.add(inventorySummary);
                        //如果存在删减数量完成之后所有的数量值都是0的情况，那么将这一条数据进行删除操作
                        if (oldSum.getDestructionNumber() == 0) {
                            deleteList.add(oldSum);
                        }else {
                            oldSum.setBrokenNumber(0);
                            oldSum.setNumber(0);
                            oldSum.setPrice(BigDecimal.ZERO);
                            oldSum.setStockNumber(0);
                            oldSum.setOutboundNumber(0);
                            oldSum.setUseNumber(0);
                            oldSum.setExpireNumber(0);
                            oldSum.setNearBrokenNumber(0);
                        }
                        break;//查询到直接跳过该循环进入下一循环
                    }
                }
            }
        }else {//不将报废区的进行移动（修改的是移出仓库的库存数量）
            for (DetailJsonReq json: jsonCollect ) {
                for (InventorySummary oldSum : oldSummaryList) {
                    //如果组织机构、仓库id、sizeId、typeId、unitPrice相同，那么修改其各项数值（
                    // 不会存在两个列表长度不对等的情况，一定是一对一的，只不过是顺序问题，所以需要进行遍历）
                    if (json.getSizeId().equals(oldSum.getSizeId())
                            && json.getTypeId().equals(oldSum.getTypeId())
                            && json.getPrice().compareTo(oldSum.getUnitPrice()) == 0
                            && json.getProperty()==oldSum.getProperty()) {
                        InventorySummary inventorySummary = new InventorySummary();
                        BeanPlusUtil.copyProperties(oldSum,inventorySummary);
                        inventorySummary.setLocationId(locationId);
                        inventorySummary.setLocationName(locationName);
                        //在库数量进行修改并且报废数设为0
                        inventorySummary.setBrokenNumber(0);
                        inventorySummary.setNumber(json.getModifyQuantity()+oldSum.getOutboundNumber());
                        inventorySummary.setPrice(json.getPrice().multiply(BigDecimal.valueOf(json.getModifyQuantity()+oldSum.getOutboundNumber())));
                        inventorySummary.setStockNumber(json.getModifyQuantity());
                        inventorySummary.setDestructionNumber(0);
                        inventorySummary.setDestructionPrice(BigDecimal.ZERO);
                        inventorySummary.setId(null);
                        inventorySummary.setValuekey(null);
                        saveList.add(inventorySummary);

                        oldSum.setNumber(Math.max(oldSum.getNumber()-json.getModifyQuantity(),0));
                        oldSum.setPrice(oldSum.getPrice().multiply(new BigDecimal(oldSum.getNumber())));
                        oldSum.setStockNumber(Math.max(oldSum.getNumber()-json.getModifyQuantity(),0));
                        oldSum.setOutboundNumber(0);
                        oldSum.setNearBrokenNumber(0);
                        oldSum.setExpireNumber(0);
                        oldSum.setUseNumber(0);

                        //如果存在删减数量完成之后所有的数量值都是0的情况，那么将这一条数据进行删除操作
                        if (oldSum.getBrokenNumber()==0&& oldSum.getDestructionNumber() == 0) {
                            deleteList.add(oldSum);
                        }
                        break;//查询到直接跳过该循环进入下一循环
                    }
                }
            }
        }

        //判断查询到的newList是否有值，如果有值直接进行修改即可，但是如果不存在，则默认新增一条数据
        //修改的是移入仓库的值
        if (newSummaryList.size()>0){
            for (int i = 0; i < saveList.size(); i++) {
                for (int j = 0; j <newSummaryList.size() ; j++) {
                    InventorySummary save = saveList.get(i);
                    InventorySummary newsum = newSummaryList.get(j);
                    if (save.getSizeId().equals(newsum.getSizeId())
                            && save.getTypeId().equals(newsum.getTypeId())
                            && save.getPrice().compareTo(newsum.getUnitPrice()) == 0
                            && save.getProperty()==newsum.getProperty()){
                        newsum.setBrokenNumber(save.getBrokenNumber()+newsum.getBrokenNumber());
                        newsum.setNumber(save.getNumber()+newsum.getNumber());
                        newsum.setStockNumber(save.getStockNumber()+newsum.getStockNumber());
                        newsum.setPrice(newsum.getPrice().multiply(BigDecimal.valueOf(newsum.getStockNumber())));
                        newsum.setOutboundNumber(save.getOutboundNumber()+newsum.getOutboundNumber());
                        newsum.setExpireNumber(save.getExpireNumber()+newsum.getExpireNumber());
                        newsum.setNearBrokenNumber(save.getNearBrokenNumber()+newsum.getNearBrokenNumber());
                        newsum.setUseNumber(save.getUseNumber()+newsum.getUseNumber());
                        //remove表示该仓库下面存在数量，数量加减完之后直接在新增的list中进行移出x
                        saveList.remove(save);
                        i--;
                        break;
                    }
                }
            }
//            for (InventorySummary save: saveList) {
//                for (InventorySummary newsum:newSummaryList) {
//                    if (save.getSizeId().equals(newsum.getSizeId())
//                            && save.getTypeId().equals(newsum.getTypeId())
//                            && save.getPrice().compareTo(newsum.getUnitPrice()) == 0
//                            && save.getProperty()==newsum.getProperty()){
//                        newsum.setBrokenNumber(save.getBrokenNumber()+newsum.getBrokenNumber());
//                        newsum.setNumber(save.getNumber()+newsum.getNumber());
//                        newsum.setStockNumber(save.getStockNumber()+newsum.getStockNumber());
//                        newsum.setPrice(newsum.getPrice().multiply(BigDecimal.valueOf(newsum.getStockNumber())));
//                        newsum.setOutboundNumber(save.getOutboundNumber()+newsum.getOutboundNumber());
//                        newsum.setExpireNumber(save.getExpireNumber()+newsum.getExpireNumber());
//                        newsum.setNearBrokenNumber(save.getNearBrokenNumber()+newsum.getNearBrokenNumber());
//                        newsum.setUseNumber(save.getUseNumber()+newsum.getUseNumber());
//                        //remove表示该仓库下面存在数量，数量加减完之后直接在新增的list中进行移出x
//                        saveList.remove(save);
//                        break;
//                    }
//                }
//
//            }
        }

        //如果saveList不为空则save
        boolean a=true;
        if(saveList.size()>0){
            a=inventorySummaryService.saveBatch(saveList);
        }
        //如果删除list不为空，那么进行批量删除
        boolean b=true;
        if (deleteList.size()>0){
            b=inventorySummaryService.removeBatchByIds(deleteList);
        }
        //将orderSum和newSum两个列表进行拼接，最终得到一个更新的list进行更新
        List<InventorySummary> totalSumList=new ArrayList<>();
        totalSumList.addAll(oldSummaryList);
        totalSumList.addAll(newSummaryList);
        boolean c =inventorySummaryService.updateBatchById(totalSumList);

//        //将库存表inventory中的装备的仓库id进行修改
//        //需要判断是否将报废区的数据进行移库，如果移动，那么所有的装备修改仓库id
//        //如果保留报废区，那么将报废区的数量不进行修改，其余数据进行修改
//        List<Inventory> eqsList = inventoryService.selectEqsByItem(searchCriteria);
//        for (Inventory inventory : eqsList) {
//            for (OrderDetail detail2 : collect) {
//                if (inventory.getOrgId().equals(existOrder.getStartOrgId())
//                        && inventory.getSizeId().equals(detail2.getSizeId())
//                        && inventory.getTypeId().equals(detail2.getTypeId())
//                        && inventory.getPrice().equals(detail2.getPrice())) {
//                    // 修改 仓库id
//                    inventory.setLocationId(detail2.getWarehouseId());
//                    break; // 找到匹配的对象后跳出内循环
//                }
//            }
//        }
//        boolean d=inventoryService.updateBatchById(eqsList);
        return a && b && c;
    }





}
