訂單生產線分配以及拆分邏輯實現

王嘯tr1912發表於2017-09-17

        由於公司需要實現訂單處理,分揀,驗收,打包,出庫的一體化操作,所以衍生了我們這次做的這一版的進銷存的訂單的業務邏輯處理流程這個的實現了。因為邏輯不是很複雜,只是步驟比較繁瑣,所以來依次說明。


一、巨集觀理解


        

      由於要把訂單的處理還有物品的分解變為一個整體話的流程,所以我們需要對於每一步都進行一個演算法的處理。首先要知道我們的電商系統是銷售的蔬菜和水果,還有套裝菜,這裡就需要進行分解,對於整個的一套進行分解到最小單位的商品,所以分解就不難解釋了,還有就是分揀,由於需要達到最大的分揀效率,每個分揀員只是負責分揀幾類商品,所以我們需要通過商品型別來找到相對應的分揀員。

      這裡是一個詳細的圖:

    

    下面我將會對於比較重要的部分:生產線和坑位的選擇,人員的選擇,庫存的消減進行詳細的描述。


二、生產線和坑位的選擇

        

        首先,我們需要根據獲得的分庫資訊去查詢生產線的資訊,然後我們需要根據生產線的優先順序去優先選擇一個生產線,然後判斷他是否達到了最大的負載量,如果達到最大負載量,就切換到下一個生產線再次判斷,如果都達到了最大的負載量,那麼我們就可以從中挑選一個負責最小的進行訂單分配,也就是選擇。具體的程式碼如下;


        //排隊訂單數量最少的該訂單
        TRepositorypipeline lessOrder= null;
        //排隊訂單最少數
        int lessNum=0;
        List<TRepositorypipeline> tRepositorypipelines=new ArrayList<TRepositorypipeline>();
        try {
            //按照優先順序倒序查詢流水線
            tRepositorypipelines=repositoryPipelineService.findByRepCode(bRepoProvidCode);
        }catch (Exception e){
            logger.error("查詢倉儲流水線資訊失敗!",e);
            throw new Exception(e.getMessage());
        }
        if (tRepositorypipelines.size()==0) {
            logger.info("查詢失敗,沒有查詢到流水線!");
            throw new Exception("查詢失敗,沒有查詢到流水線!");
        }
        //按照優先順序遍歷,是否到達峰值,如果沒有到達,優先使用
        for (TRepositorypipeline tRepositorypipeline:tRepositorypipelines) {
            //獲取訂單排隊數
            int onLineOrder=acceptanceformService.countByPipeLine(bRepoProvidCode,tRepositorypipeline.getId());
            //如果數量未登記,則賦值現有值
            if (lessNum==0){
                lessNum=onLineOrder;
            }
            //如果暫存實體沒有,則賦值現在的
            if (lessOrder==null){
                lessOrder=tRepositorypipeline;
            }else if (lessNum>onLineOrder){
                lessNum=onLineOrder;
                lessOrder=tRepositorypipeline;
            }
            //判斷此優先順序最大的是或否到達最大承載量
            if (onLineOrder<=tRepositorypipeline.getMaxnum()){
                return tRepositorypipeline;
            }else{
                continue;
            }
        }
        //都到達峰值,返回訂單數量最少的那個
        return lessOrder;

        選擇完了生產線,下一步就是選擇生產線上的筐位來存放訂單,因為一個訂單隻能放在一個筐裡面去分揀,所以需要對於筐位進行排序,從1-10(最大數量),我們需要不斷的遍歷和記錄當前的筐是哪個筐,另外還有批次的概念,就是從一次筐位全部沾滿開始,沾滿一次,批次就加一,知道第二天才會清零。

       分筐的程式碼:

        //生產線
        TRepositorypipeline tRepositorypipeline;
        //獲得倉庫生產線
        tRepositorypipeline=repositoryPipelineService.findByID(pipeLineID);
        //取得批次號
        int batch=tRepositorypipeline.getBatch();
        boolean flag=false;
        //當前已經分配的坑數
        int streamcount = tRepositorypipeline.getStreamcount();
        //總坑數
        int holenum = tRepositorypipeline.getHolenum();
        //判斷是否是初始化狀態
        if (streamcount==0){
            streamcount++;
            flag=repositoryPipelineService.updateStreamNum(streamcount,pipeLineID);
            if (flag==false){
                throw new Exception("修改坑位號失敗!");
            }
            //判斷是否到了坑位最大值
        }else if(streamcount==holenum){
            streamcount=1;
            batch++;
            flag=repositoryPipelineService.updateStreamNum(streamcount,pipeLineID);
            if (flag==false){
                throw new Exception("修改坑位號失敗!");
            }
            //資料插入資料庫
            flag=repositoryPipelineService.updateBatch(batch,tRepositorypipeline.getRepcode());
            if (flag==false){
                throw new Exception("修改批次號失敗!");
            }
        }else{
            streamcount++;
            flag=repositoryPipelineService.updateStreamNum(streamcount,pipeLineID);
            if (flag==false){
                throw new Exception("修改坑位號失敗!");
            }
        }
        return Integer.toString(streamcount);


批次選擇的程式碼:

       TRepositorypipeline tRepositorypipeline;
        tRepositorypipeline=repositoryPipelineService.findByID(pipeLineID);
        //記錄日期
        Date operateDate=tRepositorypipeline.getOperatedate();
        //批次號
        int batch=tRepositorypipeline.getBatch();
        //判斷是否和當前日期一致,不一致則進行重置
        boolean flag=false;
        if(!DateTimeUtil.formatDefaultDate(operateDate).equals(DateTimeUtil.formatDefaultDate(new Date()))){
            operateDate=new Date();
            batch=1;
            flag=repositoryPipelineService.updateOperateDate(operateDate,tRepositorypipeline.getRepcode());
            if(flag==false){
                throw new Exception("更新寫入日期錯誤!");
            }
            flag=repositoryPipelineService.updateBatch(batch,tRepositorypipeline.getRepcode());
            if (flag==false){
                throw new Exception("修改批次號失敗!");
            }
        }
        //編碼變數
        String result="";
        //判斷編碼是否溢位
        if (5-Integer.toString(batch).length()<0){
            throw new Exception("批次編碼溢位");
        }
        //拼接5位編碼
        result=result+Integer.toString(batch);
        for (int i = 0; i <5-Integer.toString(batch).length() ; i++) {
            result="0"+result;
        }
        return result;


三、分揀員的選擇


        分揀員,是繫結到貨架的一類人,所以他們只能分揀特定的商品,我們在處理商品的時候,同時也要選擇分揀這個商品的人是誰。

        程式碼如下:

        //根據產品ID查詢分類
        List<TProductmanager> tProductmanagers=ordersService.queryProduct(Integer.valueOf(productID));
        if (tProductmanagers==null){
            logger.error("查詢具體商品錯誤!");
            throw new RuntimeException("具體商品為Null");
        }
        if (tProductmanagers.size()>1){
            logger.info("查詢的產品不唯一,預設使用第一個查詢到的商品!");
        }
        //根據商品分類和角色查詢分組
        List<TGroup> tGroups=groupService.queryGroupByCategory(tProductmanagers.get(0).getProtype(),roleID);
        if (tGroups==null){
            logger.error("查詢類別分組錯誤!");
            throw new RuntimeException("類別分組為Null");
        }
        if (tGroups.size()>1){
            logger.info("查詢的分組不唯一,預設使用第一個查詢到的商品!");
        }
        //根據分組去分組關係表中查詢分揀者的ID
        List<TMappingGroupUser> tUsers=mappingUserGroupService.queryUsersByGroupCategory(tGroups.get(0).getSaleid(),repoCode);
        //TODO:以後可以在這裡新增智慧判斷
        if (tUsers==null){
            logger.error("查詢使用者錯誤!");
            throw new RuntimeException("使用者查詢結果為Null");
        }
        if (tUsers.size()>1){
            logger.info("查詢到多個人,取第一個人分配!");
        }
        //返回查詢到使用者的ID
        return tUsers.get(0).getUid();

        由於商品是有型別的,然後我們的分揀分組又是和型別進行繫結的,所以可以直接通過商品分類找到分揀組,然後通過分揀組來找到組內為那個地點的人員,進行人員選擇。


四、庫存消減


        在進行了一系列分揀操作後,我們需要對於庫存進行消減,方可進行出庫和分揀操作了,但是出庫操作又要考慮好多的問題,比如可能需要對於訂單重複項進行合併,然後通過單位轉換來取消減庫存的對應單位的數量。

        這裡我們構造了一個Map,用來盛放收集好的,不重複的菜品,然後遍歷,進行消減操作。具體的程式碼就展示了,但是需要注意的是,這裡需要有事務的操作,一定要小心對待。

相關文章