订单生产线分配以及拆分逻辑实现
由于公司需要实现订单处理,分拣,验收,打包,出库的一体化操作,所以衍生了我们这次做的这一版的进销存的订单的业务逻辑处理流程这个的实现了。因为逻辑不是很复杂,只是步骤比较繁琐,所以来依次说明。
一、宏观理解
![Center][]
由于要把订单的处理还有物品的分解变为一个整体话的流程,所以我们需要对于每一步都进行一个算法的处理。首先要知道我们的电商系统是销售的蔬菜和水果,还有套装菜,这里就需要进行分解,对于整个的一套进行分解到最小单位的商品,所以分解就不难解释了,还有就是分拣,由于需要达到最大的分拣效率,每个分拣员只是负责分拣几类商品,所以我们需要通过商品类型来找到相对应的分拣员。
这里是一个详细的图:
![SouthEast][]
下面我将会对于比较重要的部分:生产线和坑位的选择,人员的选择,库存的消减进行详细的描述。
二、生产线和坑位的选择
首先,我们需要根据获得的分库信息去查询生产线的信息,然后我们需要根据生产线的优先级去优先选择一个生产线,然后判断他是否达到了最大的负载量,如果达到最大负载量,就切换到下一个生产线再次判断,如果都达到了最大的负载量,那么我们就可以从中挑选一个负责最小的进行订单分配,也就是选择。具体的代码如下;
//排队订单数量最少的该订单
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,用来盛放收集好的,不重复的菜品,然后遍历,进行消减操作。具体的代码就展示了,但是需要注意的是,这里需要有事务的操作,一定要小心对待。
还没有评论,来说两句吧...