在2013即将结束的最后一个月里,我跑客户的时间时间达到了26天,作为一个技术出身的我这是非常不可思议的,在多年前我敢都不敢想! 在历史上一个月里我连续工作的天数也就27天,当然这是呆在公司办公室里,负责码代码,不会与直接客户面对面接触的(目前大多数技术人员都是如此)。这段时间的持续改变让我不得不深思!
一. 代码的价值
案例1:
最近有个项目实施难度有点大,当然我本身是技术出身,所以有时候还是比较有优势,因为可以当场为客户解决问题。我们是为一家生产型企业实施一个生产仓库管理系统,现在条件比较复杂,反正就是涉及到生产,出入库等!实施到一个出库的时候,有个功能是这样的:
客户要求公司客服人员直接查询仓库库存,然后根据订单配货,这个配货是可以合并多个订单的,做好配货单要系统生成一个拣货清单[也就是告诉仓库人员到哪里去拿货,在货架哪里,在货架第几层,是否需要拆托盘,是否要拆箱等等],仓库人员拿着清单直接到仓库将取货让后用叉车搬到代发货区域。然后发货人员拿着PDA(非常老式的那种)去扫描箱码或者托盘条码进行配货校验,最后打印发运标签(每个箱子上都要贴这种标签,每个单子估计都有几百上千箱货)。
现在有个问题就是这搬出来的货要自动分配到不同的订单中去,而且要满足订单情况。
比如A订单 产品P 需要数量 16,000 ; B 订单需要产品 P 数量为 54,000; C订单需要产品P数量 16,000; C 订单需要产品P1 2,000;
仓库拣货数量为: 16,000+54,000+16,000 (P产品) ; 2,000 (P1产品)
P产品包装: 标准包装5,000 P1产品包装: 标准包装 600
实际拣货为: 4*5000(整箱) + 10*5000(整箱)+ 2*5000(整箱) + 2000(零箱)+ 4000(零箱) --P产品; 3*600(整箱)+200(零箱)
那上面分配货品有很多种分配方式,不同的订单可以共箱(在一个箱子上贴两个标签 200 + 400 分别是不同的订单)。
至于具体情况如何,这个也不是一会能够描述清楚的,做过拣货的朋友应该清楚:
问题是我写了一段代码,自动分配拣货的,大概花了我4天左右的时间,总共代码行估计接近一千行了,代码部分如下:
int qty = detail.Qty; int fullBoxNum = packageNum != 0 ? qty / packageNum : 0; //理论整箱箱数 int sinQty = packageNum != 0 ? qty % packageNum : 0; //理论零箱数 int sinBoxNum = sinQty == 0 ? 0 : 1; //理论零箱箱数 string PO = detail.OrderNum;//PO ShipLableEntity ship = null; /** * 当拣货得到的箱子中整箱数大于0的情况: * 当拣货得到的箱子中整箱数==0的情况: 说明所有的拣货都要从零箱中去组合得到 * */ if (listFullBoxes.Count > 0) { //当理论拣货整箱箱数大于0 且 实际整箱也大于0的时候 if (fullBoxNum > 0) { //如果理论总箱数小于或等于实际总箱数则扣除实际理论箱数,并且判断是否有零箱 if (fullBoxNum <= listFullBoxes.Count) { ship = FormatShipLable(product, PO, outNum, listFullBoxes.First(), orderEntity, index, fullBoxNum, listDefault, listBills); listShipLables.Add(ship); listFullBoxes.RemoveRange(0, fullBoxNum); index++; //判断有零箱的情况,找到最适合的箱数,没有就要拆箱分组. 如果没有零箱什么都不用处理 所以不需要else if (sinBoxNum == 1) { //如果存在理论零箱的时候,先要实际零箱的箱数是否大于0且零箱的总数也大于理论零箱的数量 if (listSinBoxes.Count > 0 && listSinBoxes.Sum(a=>a.QTY)>=sinQty) { //升序排列,查找大于等于零箱数的第一个箱拆分 listSinBoxes = listSinBoxes.OrderBy(a => a.QTY).ToList(); OutBillEntity tempBill = listSinBoxes.Where(a => a.QTY >= sinQty).FirstOrDefault(); //如果存在满足上面条件的箱,则需要拆分处理 if (tempBill != null) { //如果数量刚好满足则直接生成标签 如果不满足则拆分为两个 if (tempBill.QTY == sinQty) { ship = FormatShipLable(product, PO, outNum, tempBill, orderEntity, index, 1, listDefault, listBills); listShipLables.Add(ship); listSinBoxes.Remove(tempBill); index++; } else { tempBill.QTY = tempBill.QTY - sinQty; OutBillEntity billNew = new OutBillEntity(); billNew.LairdPN = tempBill.LairdPN; billNew.CustomerPN = tempBill.CustomerPN; billNew.StackBarCode = tempBill.StackBarCode; billNew.BoxBarCode = tempBill.BoxBarCode; billNew.QTY = sinQty; ship = FormatShipLable(product, PO, outNum, billNew, orderEntity, index, 1, listDefault, listBills); listShipLables.Add(ship); if (tempBill.QTY <= 0) { listSinBoxes.Remove(tempBill); } index++; } } else { //如果不存在则需要组合得到,查询组合求和数量小于等于零箱的数量 int zuQty = 0; //计算总和 int sinIndex = 0; //满足条件之后停止的索引 for (int i = 0; i < listSinBoxes.Count; i++) { zuQty += listSinBoxes[i].QTY; if (zuQty >= sinQty) { sinIndex = i; break; } } //如果刚好满足则生成相应的标签,并且删除 if (zuQty == sinQty) { for (int i = 0; i <= sinIndex; i++) { ship = FormatShipLable(product, PO, outNum, listSinBoxes[i], orderEntity, index, 1, listDefault, listBills); listShipLables.Add(ship); index++; } listSinBoxes.RemoveRange(0, sinIndex + 1); } else { //删除之前的,最后一个拆分 int beforeQty = 0; for (int i = 0; i <= sinIndex - 1; i++) { beforeQty += listSinBoxes[i].QTY; ship = FormatShipLable(product, PO, outNum, listSinBoxes[i], orderEntity, index, 1, listDefault, listBills); listShipLables.Add(ship); index++; } tempBill = listSinBoxes[sinIndex]; tempBill.QTY = tempBill.QTY - (sinQty - beforeQty); OutBillEntity billNew = new OutBillEntity(); billNew.LairdPN = tempBill.LairdPN; billNew.CustomerPN = tempBill.CustomerPN; billNew.StackBarCode = tempBill.StackBarCode; billNew.BoxBarCode = tempBill.BoxBarCode; billNew.QTY = sinQty - beforeQty; ship = FormatShipLable(product, PO, outNum, billNew, orderEntity, index, 1, listDefault, listBills); listShipLables.Add(ship); index++; listSinBoxes.RemoveRange(0, sinIndex); } } } else { //如果实际零箱数为0 或者实际零箱数小于理论零箱数,那么就要拆整箱,因为实际整箱大于理论整箱所以拆整箱 if (listFullBoxes.Count > 0) { OutBillEntity tempBill = listFullBoxes.First(); tempBill.QTY = tempBill.QTY - sinQty; listFullBoxes.Remove(tempBill); listSinBoxes.Add(tempBill); OutBillEntity billNew = new OutBillEntity(); billNew.LairdPN = tempBill.LairdPN; billNew.CustomerPN = tempBill.CustomerPN; billNew.StackBarCode = tempBill.StackBarCode; billNew.BoxBarCode = tempBill.BoxBarCode; billNew.QTY = sinQty; ship = FormatShipLable(product, PO, outNum, billNew, orderEntity, index, 1, listDefault, listBills); listShipLables.Add(ship); index++; } } } }