| | |
| | | using HH.WCS.Mobox3.YNJT_PT.api; |
| | | using HH.WCS.Mobox3.YNJT_BZP_PT.models; |
| | | using HH.WCS.Mobox3.YNJT_PT.api; |
| | | using HH.WCS.Mobox3.YNJT_PT.models; |
| | | using HH.WCS.Mobox3.YNJT_PT.models.other; |
| | | using HH.WCS.Mobox3.YNJT_PT.util; |
| | | using Newtonsoft.Json; |
| | | using NLog.Fluent; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | |
| | | var date = DateTime.Now.ToString("yyMMdd"); |
| | | return $"OP{date}{id.ToString().PadLeft(4, '0')}"; |
| | | } |
| | | internal static string GenerateSortingNo() { |
| | | var id = SYSHelper.GetSerialNumber("分拣单", "SO"); |
| | | internal static string GenerateTaskGroupNo() { |
| | | var id = SYSHelper.GetSerialNumber("任务组", "GP"); |
| | | var date = DateTime.Now.ToString("yyMMdd"); |
| | | return $"SO{date}{id.ToString().PadLeft(4, '0')}"; |
| | | return $"GP{date}{id.ToString().PadLeft(4, '0')}"; |
| | | } |
| | | internal static List<WMSTask> GetOperationListByState(string state) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | |
| | | return result; |
| | | } |
| | | |
| | | internal static bool CreateSortingOrder(List<string> list) { |
| | | var res = false; |
| | | //遍历获取发货单,然后判断库存,如果全都没库存,则不生成分拣单,如果有生成分拣单 |
| | | //更新波次单,即使只有一个发货单也更新波次单 |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var sortingOrderNo = ""; |
| | | SortingOrder sortingOrder = null; |
| | | try { |
| | | db.BeginTran(); |
| | | list.ForEach(a => { |
| | | var so = db.Queryable<ShippingOrder>().Includes(s => s.Details).Where(s => s.S_NO == a).First(); |
| | | //判断库存,只有已经入库的才可以计算,码盘的不算,入库后出库途中的也要计算,码盘后默认叫待入库,入库后叫正常 |
| | | //生成出库任务,只有托盘位置在立库才需要创建出库任务(先写死立库) |
| | | //只有全部分拣完成才允许回库(一个托盘可能对应多个分拣明细) |
| | | |
| | | |
| | | //查找仓库量表和库区量表,出库单需要定位仓库和库区了,出库定位物理库区就行,入库可能物料库区还要区分逻辑库区 |
| | | |
| | | //暂时只查仓库量表(量表如何重置,查找所有查找C_ENABLE=N的,判断如果在仓库中,改成Y,然后统计) |
| | | |
| | | //生成分拣单时候增加仓库量表分配量,生成分拣单明细时候,增加库区量表分配量 |
| | | if (so != null && so.Details.Count > 0) { |
| | | var fail = true; |
| | | for (int i = 0; i < so.Details.Count; i++) { |
| | | var whi = db.Queryable<WHInventory>().Where(w => w.S_ITEM_CODE == so.Details[i].S_ITEM_CODE).First(); |
| | | if (whi != null && whi.F_QTY - whi.F_ALLOC_QTY > 0) { |
| | | //有货就出 |
| | | float qty = whi.F_QTY - whi.F_ALLOC_QTY > so.Details[i].F_QTY ? so.Details[i].F_QTY : whi.F_QTY - whi.F_ALLOC_QTY; |
| | | fail = false; |
| | | //有可用库存,生成分拣单 |
| | | if (sortingOrderNo == "") { |
| | | sortingOrderNo = GenerateSortingNo(); |
| | | sortingOrder = new SortingOrder |
| | | { |
| | | S_NO = sortingOrderNo, |
| | | S_SHIPPING_NO = so.S_NO, |
| | | Composes = new List<SortingCompose>() |
| | | }; |
| | | //创建分拣单 |
| | | db.Insertable(sortingOrder).ExecuteCommand(); |
| | | } |
| | | else { |
| | | //获取最新分拣单 |
| | | sortingOrder = db.Queryable<SortingOrder>().Includes(s => s.Composes).Where(s => s.S_NO == sortingOrderNo).First(); |
| | | //更新分拣单中的发货单单号 |
| | | sortingOrder.S_SHIPPING_NO = sortingOrder.S_SHIPPING_NO + ";" + so.S_NO; |
| | | sortingOrder.T_MODIFY = DateTime.Now; |
| | | db.Updateable(sortingOrder).UpdateColumns(it => new { it.S_SHIPPING_NO, it.T_MODIFY }).ExecuteCommand(); |
| | | } |
| | | //查询分拣单子表(正常情况还需要增加批次判断) |
| | | var soc = db.Queryable<SortingCompose>().Where(s => s.S_ITEM_CODE == so.Details[i].S_ITEM_CODE && s.S_SORTING_NO == sortingOrder.S_NO).First(); |
| | | if (soc == null) { |
| | | soc = new SortingCompose |
| | | { |
| | | S_ITEM_CODE = so.Details[i].S_ITEM_CODE, |
| | | S_SORTING_NO = sortingOrder.S_NO, |
| | | F_QTY = qty, |
| | | N_ROW_NO = sortingOrder.Composes.Count() + 1, |
| | | S_BATCH_NO = so.Details[i].S_BATCH_NO |
| | | }; |
| | | |
| | | //创建分拣单子表 |
| | | db.Insertable(soc).ExecuteCommand(); |
| | | } |
| | | else { |
| | | soc.F_QTY += qty; |
| | | soc.T_MODIFY = DateTime.Now; |
| | | //更新分拣单子表 |
| | | db.Updateable(soc).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand(); |
| | | } |
| | | //更新仓库量表分配量 |
| | | whi.F_ALLOC_QTY += qty; |
| | | whi.T_MODIFY = DateTime.Now; |
| | | db.Updateable(whi).UpdateColumns(it => new { it.F_ALLOC_QTY, it.T_MODIFY }).ExecuteCommand(); |
| | | //跟新发货单子表配货数量 |
| | | so.Details[i].F_ACC_D_QTY += qty; |
| | | so.Details[i].T_MODIFY = DateTime.Now; |
| | | db.Updateable(so.Details[i]).UpdateColumns(it => new { it.F_ACC_D_QTY, it.T_MODIFY }).ExecuteCommand(); |
| | | } |
| | | |
| | | } |
| | | //更新发货单状态 |
| | | so.N_B_STATE = fail ? 5 : 1; |
| | | if (fail) { |
| | | so.S_NOTE = "没有库存"; |
| | | } |
| | | so.S_WAVE_CODE = sortingOrderNo; |
| | | so.T_MODIFY = DateTime.Now; |
| | | db.Updateable(so).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY, it.S_WAVE_CODE, it.S_NOTE }).ExecuteCommand(); |
| | | |
| | | } |
| | | |
| | | |
| | | //查找库区内托盘生成托盘明细(包括分拣中)怎么判断库内?查找货位绑定?还是托盘上加标识比较好,如果是整托出的,分拣确认后去掉分拣标识。 |
| | | //1、只有码盘入库后的才需要加标识,分拣回的不用,分拣回的标识还在,没有变。写死码盘入的完成后加标识,整托分拣的去掉标识,防止后面重新码盘脏数据 |
| | | //2、或者关联查询库内的,只给分拣出的加标识,每次分拣回再把标识清除了(如果不清除带标识的会很多,还不如全部加标识),整托的清除。 |
| | | //综合选择还是方案1,这样创建分拣明细,只需要托盘物料两表查询就能定位托盘(如果信息不准,可以重置),方案2需要货位、托盘、物料三表联查 |
| | | |
| | | //暂时不计库区,标识用容器表 C_ENABLE 来判断,表示能不能出库 |
| | | |
| | | //执行分拣创建任务,遍历分拣明细中的托盘,如果在仓库就出库,如果不在就不用出库 |
| | | |
| | | |
| | | }); |
| | | //全部分拣单生成之后将分拣单状态设置为开始配货,波次号为发货单 |
| | | sortingOrder = db.Queryable<SortingOrder>().Where(s => s.S_NO == sortingOrderNo).First(); |
| | | sortingOrder.N_B_STATE = 1; |
| | | sortingOrder.T_MODIFY = DateTime.Now; |
| | | db.Updateable(sortingOrder).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY }).ExecuteCommand(); |
| | | db.CommitTran(); |
| | | res = true; |
| | | } |
| | | catch (Exception ex) { |
| | | Console.WriteLine(ex.Message); |
| | | db.RollbackTran(); |
| | | } |
| | | return res; |
| | | |
| | | } |
| | | |
| | | internal static List<SortingDetail> GetSortingDetailByCntr(string cntr) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var result = db.Queryable<SortingDetail>().Where(a => a.S_CNTR_CODE == cntr && a.N_B_STATE != 2).ToList(); |
| | | return result; |
| | | } |
| | | |
| | | |
| | | internal static bool CreateWmsTask(WMSTask wmsTask) { |
| | | try { |
| | |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<WMSTask>().Where(a => a.S_CODE == code).First(); |
| | | } |
| | | /* |
| | | internal static void CreateSortingOrderDetail(string so_no) { |
| | | //分拣单配货 |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var so = db.Queryable<SortingOrder>().Includes(a => a.Composes).Where(a => a.S_NO == so_no && (a.N_B_STATE == 1 || a.N_B_STATE == 20)).First();// |
| | | if (so != null && so.Composes.Count > 0) { |
| | | db.BeginTran(); |
| | | try { |
| | | int rowNo = 1; |
| | | so.Composes.ForEach(a => { |
| | | //按分拣单子表去配货,查找可用托盘(先查所有符合的,后面再优化) |
| | | var cirList = db.Queryable<CntrItemRel>().Includes(c => c.Cntr).Where(c => c.Cntr.C_ENABLE == "Y" && c.S_ITEM_CODE == a.S_ITEM_CODE && (c.F_QTY - c.F_ALLOC_QTY) > 0).OrderBy(c => c.T_CREATE).ToList(); |
| | | for (int i = 0; i < cirList.Count; i++) { |
| | | var cir = cirList[i]; |
| | | var sd = new SortingDetail |
| | | { |
| | | N_ROW_NO = rowNo, |
| | | S_BATCH_NO = a.S_BATCH_NO, |
| | | S_ITEM_CODE = a.S_ITEM_CODE, |
| | | S_CNTR_CODE = cir.S_CNTR_CODE, |
| | | S_SORTING_NO = a.S_SORTING_NO |
| | | }; |
| | | bool needBreak = false; |
| | | if (cir.F_QTY - cir.F_ALLOC_QTY >= (a.F_QTY - a.F_ACC_S_QTY)) { |
| | | //容器可用数量大于分拣单子表要求的数量,生成分拣明细,然后跳出循环 |
| | | sd.F_QTY = a.F_QTY - a.F_ACC_S_QTY; |
| | | needBreak = true; |
| | | } |
| | | else { |
| | | //生成分拣明细,继续创建 |
| | | sd.F_QTY = cir.F_QTY - cir.F_ALLOC_QTY; |
| | | } |
| | | db.Insertable(sd).ExecuteCommand(); |
| | | rowNo++; |
| | | //更新容器货品表分配量 |
| | | cir.F_ALLOC_QTY += sd.F_QTY; |
| | | cir.T_MODIFY = DateTime.Now; |
| | | db.Updateable(cir).UpdateColumns(it => new { it.F_ALLOC_QTY, it.T_MODIFY }).ExecuteCommand(); |
| | | //更新分拣单子表的量 |
| | | a.F_ACC_S_QTY += sd.F_QTY; |
| | | a.T_MODIFY = DateTime.Now; |
| | | db.Updateable(cir).UpdateColumns(it => new { it.F_ALLOC_QTY, it.T_MODIFY }).ExecuteCommand(); |
| | | if (needBreak) { |
| | | break; |
| | | } |
| | | } |
| | | }); |
| | | //全部分拣单子表生成分拣明细,修改分拣单状态为配货完成(反正仓库的货能配的都配完了,除非数据有异常) |
| | | so.N_B_STATE = 2; |
| | | so.T_MODIFY = DateTime.Now; |
| | | db.Updateable(so).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY }).ExecuteCommand(); |
| | | db.CommitTran(); |
| | | } |
| | | catch (Exception ex) { |
| | | Console.WriteLine(ex.Message); |
| | | db.RollbackTran(); |
| | | } |
| | | } |
| | | } |
| | | */ |
| | | /// <summary> |
| | | /// 获取开始配货的分拣单,一次性生成分拣明细,避免生成一半再生成,所以创建分拣明细的时候加上事务 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | internal static List<SortingOrder> GetWaitingSortingOrderList() { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<SortingOrder>().Includes(a => a.Composes).Where(a => a.N_B_STATE == 1 || a.N_B_STATE == 20).ToList(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取配货完成的分拣单,每个分拣单单独创建分拣作业 |
| | | /// </summary> |
| | |
| | | return result; |
| | | } |
| | | |
| | | public static Location GetLocation4InEmptyRow() |
| | | |
| | | // ----------------------------------------------- 印尼佳通 - 硫化-------------------------------------------- |
| | | |
| | | /// <summary> |
| | | /// 添加成型机下线记录 |
| | | /// </summary> |
| | | /// <param name="record"></param> |
| | | /// <returns></returns> |
| | | public static bool addOffLineRecord(OffLineRecord record) |
| | | { |
| | | Location result = null; |
| | | try |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | |
| | | #region 查找所有数量是空的排 |
| | | //Console.WriteLine("查找所有数量是空的排"); |
| | | //2.0 简化查询只查每一排第一列 |
| | | var list = db.Queryable<Location>().OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList(); |
| | | //2.1 选一个空排 |
| | | for (int i = 0; i < list.Count; i++) |
| | | { |
| | | var other = db.Queryable<Location>().Where(a => a.S_AREA_CODE == list[i].S_AREA_CODE && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无").First(); |
| | | if (list[i].N_LOCK_STATE == 0 && other == null) |
| | | { |
| | | //二次校验当前排所有货位都是空的,防止系统数据错乱 |
| | | var rowSumInfo = db.Queryable<Location>().Where(l => l.S_AREA_CODE == list[i].S_AREA_CODE && l.N_ROW == list[i].N_ROW && l.N_CURRENT_NUM != 0).Count(); |
| | | if (rowSumInfo == 0) |
| | | { |
| | | result = list[i]; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N"))) |
| | | { |
| | | //禁用了选择后面一个货位 |
| | | Console.WriteLine("禁用了选择后面一个货位"); |
| | | result = db.Queryable<Location>().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == result.S_AREA_CODE && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | LogHelper.Error("GetLocation4InEmptyRow:" + ex.Message, ex); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | internal static Location GetInstockEnd(string item) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | Location end = null; |
| | | // 查询相同物料的排是否有可放货的库位 |
| | | var listMaxCol = db.Queryable<Location>() |
| | | .LeftJoin<LocCntrRel>((l, lc) => l.S_CODE == lc.S_LOC_CODE) |
| | | .LeftJoin<CntrItemRel>((l, lc, ci) => lc.S_CNTR_CODE == ci.S_CNTR_CODE) |
| | | .Where((l, lc, ci) => l.N_CURRENT_NUM > 0 && ci.S_ITEM_CODE == item && l.S_AREA_CODE != Settings.BufferArea) |
| | | .OrderByDescending((l, lc, ci) => l.N_COL).Take(1).PartitionBy((l, lc, ci) => l.N_ROW).ToList(); |
| | | |
| | | foreach (var loc in listMaxCol) |
| | | { |
| | | //排有锁也排除 |
| | | var other = db.Queryable<Location>().Where(a => a.S_AREA_CODE == loc.S_AREA_CODE && a.N_ROW == loc.N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).First(); |
| | | if (other != null) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | end = db.Queryable<Location>().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == loc.S_AREA_CODE && a.N_ROW == loc.N_ROW && a.N_CURRENT_NUM < a.N_CAPACITY && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL >= loc.N_COL).First(); |
| | | if (end != null) { |
| | | return end; |
| | | } |
| | | } |
| | | // 如果没有,则随机放空的排 |
| | | if (end == null) { |
| | | end = GetLocation4InEmptyRow(); |
| | | } |
| | | return end; |
| | | } |
| | | |
| | | public static Location GetShiftStockStart(string area ,int row) |
| | | { |
| | | Location result = null; |
| | | try |
| | | { |
| | | // 1、查询当前库区-排-物料 有托盘的货位 |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | result = db.Queryable<Location>() |
| | | .Where(l => l.N_CURRENT_NUM > 0 && l.S_AREA_CODE == area && l.N_ROW == row && l.N_LOCK_STATE == 0 && (l.C_ENABLE != "禁用" && l.C_ENABLE != "N")) |
| | | .Includes(l => l.LocCntrRel, l => l.CntrItemRel) |
| | | .OrderByDescending(l => l.N_COL) |
| | | .First(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogHelper.Error("GetShiftStockStart:" + ex.Message, ex); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | public static Location GetShiftStockStart(string area) |
| | | { |
| | | Location result = null; |
| | | try |
| | | { |
| | | // 1、查询当前库区-排-物料 有托盘的货位 |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var listMaxCol = db.Queryable<Location>() |
| | | .Where(l => l.N_CURRENT_NUM > 0 && l.S_AREA_CODE == area) |
| | | .Includes(l => l.LocCntrRel, l => l.CntrItemRel) |
| | | .OrderByDescending(l => l.N_COL) |
| | | .Take(1) |
| | | .PartitionBy(l => l.N_ROW) |
| | | .ToList(); |
| | | |
| | | foreach (var loc in listMaxCol) |
| | | { |
| | | //排有锁也排除 |
| | | var other = db.Queryable<Location>().Where(a => a.S_AREA_CODE == loc.S_AREA_CODE && a.N_ROW == loc.N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).First(); |
| | | if (other != null) |
| | | { |
| | | continue; |
| | | } |
| | | return loc; |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogHelper.Error("GetShiftStockStart:" + ex.Message, ex); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | public static bool isRowLock(Location location) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | return db.Queryable<Location>().Where(a => a.S_AREA_CODE == location.S_AREA_CODE && a.N_ROW == location.N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).Count() > 0; |
| | | } |
| | | |
| | | public static Location GetShiftStockEnd(string area, int row) |
| | | { |
| | | Location result = null; |
| | | |
| | | try |
| | | { |
| | | //1.0 获取每一排最大的列 |
| | | //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除 |
| | | var listMaxCol = new SqlHelper<Location>().GetInstance().Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); |
| | | //1.1 查到所有有托盘的排 |
| | | Console.WriteLine("查到所有有托盘的排 "); |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var list = db.Queryable<Location>().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area && a.N_ROW == row).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); |
| | | if (list.Count > 0) |
| | | { |
| | | //1.2 查找其它尺寸有托盘或者锁定的排 |
| | | for (int i = list.Count - 1; i >= 0; i--) |
| | | { |
| | | //排除已经锁定的货位 和 放满了且是最大列的货位 |
| | | if (list[i].N_LOCK_STATE != 0 || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_CODE == list[i].S_CODE) > 0)) |
| | | { |
| | | Console.WriteLine($"排除已经锁定的货位 和 放满了且是最大列的货位 排{list[i].N_ROW}"); |
| | | list.Remove(list[i]); |
| | | } |
| | | else |
| | | { |
| | | //排有锁也排除 |
| | | var other = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).First(); |
| | | if (other != null) |
| | | { |
| | | Console.WriteLine($"排除有锁的排{list[i].N_ROW}"); |
| | | list.Remove(list[i]); |
| | | } |
| | | } |
| | | } |
| | | Console.WriteLine($"有托盘排数为{list.Count}"); |
| | | if (list.Count > 0) |
| | | { |
| | | |
| | | //1.3 遍历判断物料类型是否相同 |
| | | Console.WriteLine("遍历判断物料类型是否相同"); |
| | | for (int i = 0; i < list.Count; i++) |
| | | { |
| | | //todo 还需要判断锁 |
| | | if (list[i].LocCntrRel != null && list[i].LocCntrRel.CntrItemRel != null) |
| | | { |
| | | if (list[i].N_CURRENT_NUM < list[i].N_CAPACITY) |
| | | { |
| | | result = list[i]; |
| | | } |
| | | else |
| | | { |
| | | Console.WriteLine("选择后面空位"); |
| | | result = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL && a.C_ENABLE == "Y").OrderBy(a => a.N_COL).First(); |
| | | } |
| | | |
| | | if (result != null) |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (result == null) |
| | | { |
| | | #region 查找所有数量是空的排 |
| | | //Console.WriteLine("查找所有数量是空的排"); |
| | | //2.0 简化查询只查每一排第一列 |
| | | list = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList(); |
| | | //2.1 选一个空排 |
| | | for (int i = 0; i < list.Count; i++) |
| | | { |
| | | var other = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无").First(); |
| | | if (list[i].N_LOCK_STATE == 0 && other == null) |
| | | { |
| | | //二次校验当前排所有货位都是空的,防止系统数据错乱 |
| | | var rowSumInfo = db.Queryable<Location>().Where(l => l.S_AREA_CODE == area && l.N_ROW == list[i].N_ROW && l.N_CURRENT_NUM != 0).Count(); |
| | | if (rowSumInfo == 0) |
| | | { |
| | | result = list[i]; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | #endregion |
| | | } |
| | | |
| | | if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N"))) |
| | | { |
| | | //禁用了选择后面一个货位 |
| | | //Console.WriteLine("禁用了选择后面一个货位"); |
| | | result = db.Queryable<Location>().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == area && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | LogHelper.Error("GetLocation4InFinish:" + ex.Message, ex); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | public static List<Location> GetLocationList(string area , int row) { |
| | | List<Location> result = new List<Location> (); |
| | | try { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | result = db.Queryable<Location>().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList(); |
| | | } |
| | | catch (Exception ex) { |
| | | LogHelper.Error("GetLocationList:" + ex.Message, ex); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | public static List<TN_YiKuDetail> getShiftOrderDetail(string orderNo = null) { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | List<TN_YiKuDetail> details = new List<TN_YiKuDetail>(); |
| | | var orderList = db.Queryable<TN_YiKuOrder>().Where(a => a.S_B_STATE == "执行").ToList(); |
| | | foreach (var order in orderList) |
| | | { |
| | | var detail = db.Queryable<TN_YiKuDetail>().Where(a => order.S_NO == a.S_NO).First(); |
| | | if (detail != null) |
| | | { |
| | | details.Add(detail); |
| | | } |
| | | } |
| | | return details; |
| | | } |
| | | |
| | | public static bool updateShiftOrderDetail(TN_YiKuDetail detail) { |
| | | bool result = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | LogHelper.Info("移库完成数量变更参数:" + JsonConvert.SerializeObject(detail), "TSSG"); |
| | | result = db.Updateable<TN_YiKuDetail>() |
| | | .SetColumns(a => new TN_YiKuDetail() { N_COMPLETE_NUM = a.N_COMPLETE_NUM + 1 }) |
| | | .Where(a => a.S_NO == detail.S_NO |
| | | && a.S_START_AREA == detail.S_START_AREA |
| | | && a.S_START_ROW == detail.S_START_ROW |
| | | && a.S_END_AREA == detail.S_END_AREA |
| | | && a.S_END_ROW == detail.S_END_ROW |
| | | ) |
| | | .ExecuteCommand() > 0; |
| | | var offLineRecord = db.Queryable<OffLineRecord>().Where(a => a.S_RFID == record.S_RFID).First(); |
| | | if (offLineRecord != null) |
| | | { |
| | | offLineRecord.S_LOC = record.S_LOC; |
| | | offLineRecord.N_IS_URGENT = record.N_IS_URGENT; |
| | | offLineRecord.T_OFF_TIME = record.T_OFF_TIME; |
| | | offLineRecord.N_IS_FULL = record.N_IS_FULL; |
| | | result = db.Updateable(offLineRecord).ExecuteCommand() > 0; |
| | | } |
| | | else |
| | | { |
| | | result = db.Insertable(record).ExecuteCommand() > 0; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | var completeResult = db.Queryable<TN_YiKuDetail>().Where(a => a.S_NO == detail.S_NO && a.N_QTY > a.N_COMPLETE_NUM).Count() == 0; |
| | | if(completeResult) { |
| | | result = db.Updateable<TN_YiKuOrder>().SetColumns(a => new TN_YiKuOrder() { S_B_STATE = "完成" }).Where(a => a.S_NO == detail.S_NO).ExecuteCommand() > 0; |
| | | /// <summary> |
| | | /// 查询成型机下线记录 |
| | | /// </summary> |
| | | /// <param name="rfid"></param> |
| | | /// <returns></returns> |
| | | public static OffLineRecord getOffLineRecord(string rfid) |
| | | { |
| | | OffLineRecord offLineRecord = null; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | if (rfid != null) |
| | | { |
| | | offLineRecord = db.Queryable<OffLineRecord>().Where(a => a.S_RFID == rfid).First(); |
| | | } |
| | | return offLineRecord; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 查询物料条码信息 |
| | | /// </summary> |
| | | /// <param name="barcode"></param> |
| | | /// <returns></returns> |
| | | public static GreenTireInformation GetGreenTireInformation(string barcode) |
| | | { |
| | | GreenTireInformation greenTireInformation = null; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | if (barcode != null) |
| | | { |
| | | greenTireInformation = db.Queryable<GreenTireInformation>().Where(a => a.BARCODE == barcode).First(); |
| | | } |
| | | return greenTireInformation; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 查询入库终点货位 |
| | | /// </summary> |
| | | /// <param name="itemCode"></param> |
| | | /// <param name="locNum">1.单货位 2.双货位</param> |
| | | /// <returns></returns> |
| | | public static List<Location> getInStockEndLoc(string itemCode, int locNum) |
| | | { |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | List<Location> locations = new List<Location>(); |
| | | // 1.按容积率从大到小,对巷道进行排序 |
| | | var roadwayOrderList = db.Queryable<Location>().Where(a => a.S_AREA_CODE == Settings.stockArea && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y") |
| | | .GroupBy(a => a.N_ROADWAY) |
| | | .Select(a => new { roadway = a.N_ROADWAY , num = SqlFunc.AggregateCount(a.S_CODE)}) |
| | | .OrderByDescending(a => a.num) |
| | | .ToList(); |
| | | |
| | | // 查询单货位 |
| | | if (locNum == 1) |
| | | { |
| | | foreach (var order in roadwayOrderList) |
| | | { |
| | | // 1. 查询1号货位是否有相同物料,有,则查询对应的2号货位是否为空 |
| | | var oneLocList = db.Queryable<Location>() |
| | | .LeftJoin<LocCntrRel>((a,b) => a.S_CODE == b.S_LOC_CODE) |
| | | .LeftJoin<CntrItemRel>((a,b,c) => b.S_CNTR_CODE == c.S_CNTR_CODE) |
| | | .Where((a, b, c) => a.S_AREA_CODE == Settings.stockArea |
| | | && a.N_ROADWAY == order.roadway |
| | | && a.N_COL % 2 == 1 |
| | | && a.N_CURRENT_NUM == 1 |
| | | && a.N_LOCK_STATE == 0 |
| | | && a.C_ENABLE == "Y" |
| | | && c.S_ITEM_CODE == itemCode |
| | | ) |
| | | .OrderBy(a => a.N_LAYER).OrderBy(a => a.N_COL) |
| | | .ToList(); |
| | | if (oneLocList.Count > 0) |
| | | { |
| | | foreach (var loc in oneLocList) |
| | | { |
| | | var twoLoc = db.Queryable<Location>().Where(a => a.S_AREA_CODE == Settings.stockArea && a.N_ROADWAY == order.roadway && a.N_ROW == loc.N_ROW && a.N_COL == loc.N_COL + 1 && a.N_LAYER == loc.N_LAYER && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").First(); |
| | | if (twoLoc != null) |
| | | { |
| | | locations.Add(twoLoc); |
| | | return locations; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 2.查询2号货位是否有相同物料,有,则查询对应的1号位是否为空 |
| | | if (locations.Count == 0) |
| | | { |
| | | var twoLocList = db.Queryable<Location>() |
| | | .LeftJoin<LocCntrRel>((a, b) => a.S_CODE == b.S_LOC_CODE) |
| | | .LeftJoin<CntrItemRel>((a, b, c) => b.S_CNTR_CODE == c.S_CNTR_CODE) |
| | | .Where((a, b, c) => a.S_AREA_CODE == Settings.stockArea |
| | | && a.N_ROADWAY == order.roadway |
| | | && a.N_COL % 2 == 0 |
| | | && a.N_CURRENT_NUM == 1 |
| | | && a.N_LOCK_STATE == 0 |
| | | && a.C_ENABLE == "Y" |
| | | && c.S_ITEM_CODE == itemCode |
| | | ) |
| | | .OrderBy(a => a.N_LAYER).OrderBy(a => a.N_COL) |
| | | .ToList(); |
| | | |
| | | if (twoLocList.Count > 0) |
| | | { |
| | | foreach (var loc in twoLocList) |
| | | { |
| | | var oneLoc = db.Queryable<Location>().Where(a => a.S_AREA_CODE == Settings.stockArea && a.N_ROADWAY == order.roadway && a.N_ROW == loc.N_ROW && a.N_COL == loc.N_COL - 1 && a.N_LAYER == loc.N_LAYER && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").First(); |
| | | if (oneLoc != null) |
| | | { |
| | | locations.Add(oneLoc); |
| | | return locations; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 3.没有相同物料的,优先放禁用货位旁边(单一货位) |
| | | if (locations.Count == 0) |
| | | { |
| | | var disableLocList= db.Queryable<Location>().Where(a => a.S_AREA_CODE == Settings.stockArea && a.N_ROADWAY == order.roadway && a.C_ENABLE == "N").OrderBy(a => a.N_LAYER).ToList(); |
| | | foreach (var loc in disableLocList) |
| | | { |
| | | // 货位为1号位,则查询对应二号位是否为空 |
| | | if (loc.N_LAYER % 2 == 1) |
| | | { |
| | | var twoLoc = db.Queryable<Location>().Where(a => a.S_AREA_CODE == Settings.stockArea && a.N_ROADWAY == order.roadway && a.N_ROW == loc.N_ROW && a.N_COL == loc.N_COL + 1 && a.N_LAYER == loc.N_LAYER && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").First(); |
| | | if (twoLoc != null) |
| | | { |
| | | locations.Add(twoLoc); |
| | | return locations; |
| | | } |
| | | } |
| | | |
| | | // 货位为2号位,则查询对应一号位是否为空 |
| | | if (loc.N_LAYER % 2 == 0) |
| | | { |
| | | var oneLoc = db.Queryable<Location>().Where(a => a.S_AREA_CODE == Settings.stockArea && a.N_ROADWAY == order.roadway && a.N_ROW == loc.N_ROW && a.N_COL == loc.N_COL - 1 && a.N_LAYER == loc.N_LAYER && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").First(); |
| | | if (oneLoc != null) |
| | | { |
| | | locations.Add(oneLoc); |
| | | return locations; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 4.没有相同物料的,且禁用货位旁边没有空货位,则优先放1号位 |
| | | if (locations.Count == 0) |
| | | { |
| | | oneLocList = db.Queryable<Location>().Where(a => a.S_AREA_CODE == Settings.stockArea && a.N_ROADWAY == order.roadway && a.N_COL % 2 == 1 && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").OrderBy(a => a.N_LAYER).OrderByDescending(a => a.N_COL).ToList(); |
| | | if (oneLocList.Count > 0) |
| | | { |
| | | locations.Add(oneLocList[0]); |
| | | return locations; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 查询双货位 |
| | | if (locNum == 2) |
| | | { |
| | | foreach (var order in roadwayOrderList) |
| | | { |
| | | var oneLocList = db.Queryable<Location>().Where( a => a.S_AREA_CODE == Settings.stockArea && a.N_ROADWAY == order.roadway && a.N_COL % 2 == 1 && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").OrderBy(a => a.N_LAYER).OrderBy(a => a.N_COL).ToList(); |
| | | foreach (var loc in oneLocList) |
| | | { |
| | | var twoLoc = db.Queryable<Location>().Where(a => a.S_AREA_CODE == Settings.stockArea && a.N_ROADWAY == order.roadway && a.N_ROW == loc.N_ROW && a.N_COL == loc.N_COL + 1 && a.N_LAYER == loc.N_LAYER && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").First(); |
| | | if (twoLoc != null) |
| | | { |
| | | locations.Add(loc); |
| | | locations.Add(twoLoc); |
| | | return locations; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return locations; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 查询异常区空货位 |
| | | /// </summary> |
| | | /// <param name="areaCode"></param> |
| | | public static Location getAbnormalAreaEmptyLoc(string areaCode) |
| | | { |
| | | Location location = new Location(); |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | location = db.Queryable<Location>().Where(a => a.S_AREA_CODE == areaCode && a.N_CURRENT_NUM == 0 && a.C_ENABLE == "Y" && a.N_LOCK_STATE == 0).First(); |
| | | return location; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 查询巷道任务最少的接驳位 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | public static Location getMinTaskMiddleLoc(int type) |
| | | { |
| | | Location location = new Location(); |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var roadwayGroup = db.Queryable<Location>() |
| | | .LeftJoin<WCSTask>((a,b) => a.S_CODE == b.S_END_LOC && b.N_B_STATE < 3) |
| | | .Where((a, b) => a.S_AREA_CODE == Settings.stockArea && b.S_CODE != null ) |
| | | .GroupBy((a, b) => a.N_ROADWAY) |
| | | .Select( (a, b) => new { roadway = a.N_ROADWAY , num = SqlFunc.AggregateDistinctCount(a.S_CODE)}) |
| | | .OrderBy(a => a.num) |
| | | .ToList(); |
| | | |
| | | foreach (var item in roadwayGroup) |
| | | { |
| | | // 1.查询巷道内的堆垛机状态是否正常 |
| | | |
| | | // 2.查询接驳位 |
| | | var connectLoc = Settings.connectLocList.Where(a => a.type == type && a.roadway == item.roadway).FirstOrDefault(); |
| | | if (connectLoc != null) |
| | | { |
| | | location = LocationHelper.GetLoc(connectLoc.locCode); |
| | | break; |
| | | } |
| | | } |
| | | return location; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 查询物料存放时间配置信息 |
| | | /// </summary> |
| | | /// <param name="bc_entried"></param> |
| | | /// <returns></returns> |
| | | public static Overage getOverage(string bc_entried) |
| | | { |
| | | |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | |
| | | // 直接执行 SQL(参数化查询) |
| | | var sql = "SELECT get_ovg_bar(@barcode, @mcngrp) AS overage_value"; |
| | | var sql1 = "SELECT get_minhour_bar(@barcode, @mcngrp) AS overage_value"; |
| | | |
| | | // 使用匿名对象传递参数 |
| | | var ovg_bar = db.Ado.SqlQuery<int>(sql, new { barcode = bc_entried, mcngrp = "0" }); |
| | | var minhour_bar = db.Ado.SqlQuery<float>(sql1, new { barcode = bc_entried, mcngrp = "0" }); |
| | | if (ovg_bar.Count > 0 && minhour_bar.Count > 0) |
| | | { |
| | | Overage overage = new Overage() |
| | | { |
| | | MINHOUR = minhour_bar[0], |
| | | OVERAGE = ovg_bar[0] |
| | | }; |
| | | return overage; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static bool bindBarcodeItemInfo( string cntrCode,GreenTireInformation greenTireInformation) |
| | | { |
| | | bool result = false; |
| | | var db = new SqlHelper<object>().GetInstance(); |
| | | var cntrItemRel = db.Queryable<CntrItemRel>().Where(a => a.S_CNTR_CODE == cntrCode).First(); |
| | | if (cntrItemRel == null) |
| | | { |
| | | var overage = getOverage(greenTireInformation.BARCODE); |
| | | DateTime txndate = DateTime.Parse(greenTireInformation.TXNDATE); |
| | | DateTime minTime = txndate.AddHours(overage.MINHOUR); |
| | | DateTime maxTime = txndate.AddDays(overage.OVERAGE); |
| | | cntrItemRel = new CntrItemRel() |
| | | { |
| | | S_CG_ID = greenTireInformation.BARCODE, |
| | | S_ITEM_CODE = greenTireInformation.ITEMCODE, |
| | | S_CNTR_CODE = cntrCode, |
| | | S_CELL_NO = greenTireInformation.TIRECODE, |
| | | F_QTY = greenTireInformation.QTY, |
| | | S_MCN = greenTireInformation.MCN, |
| | | S_OPR = greenTireInformation.OPR, |
| | | S_OPR02 = greenTireInformation.OPR02, |
| | | S_OPR03 = greenTireInformation.OPR03, |
| | | S_OPR04 = greenTireInformation.OPR04, |
| | | S_WINDUP = greenTireInformation.WINDUP, |
| | | S_TXNDATE = greenTireInformation.TXNDATE, |
| | | S_DATE_SHIFT = greenTireInformation.DATE_SHIFT, |
| | | S_EFFECTIVE_TIME = minTime.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | S_EXPIRATION_TIME = maxTime.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | }; |
| | | result = db.Insertable(cntrItemRel).ExecuteCommand() > 0; |
| | | } |
| | | else |
| | | { |
| | | var overage = getOverage(greenTireInformation.BARCODE); |
| | | DateTime txndate = DateTime.Parse(greenTireInformation.TXNDATE); |
| | | DateTime minTime = txndate.AddHours(overage.MINHOUR); |
| | | DateTime maxTime = txndate.AddDays(overage.OVERAGE); |
| | | cntrItemRel.S_CG_ID = greenTireInformation.BARCODE; |
| | | cntrItemRel.S_ITEM_CODE = greenTireInformation.ITEMCODE; |
| | | cntrItemRel.S_CNTR_CODE = cntrCode; |
| | | cntrItemRel.S_CELL_NO = greenTireInformation.TIRECODE; |
| | | cntrItemRel.F_QTY = greenTireInformation.QTY; |
| | | cntrItemRel.S_MCN = greenTireInformation.MCN; |
| | | cntrItemRel.S_OPR = greenTireInformation.OPR; |
| | | cntrItemRel.S_OPR02 = greenTireInformation.OPR02; |
| | | cntrItemRel.S_OPR03 = greenTireInformation.OPR03; |
| | | cntrItemRel.S_OPR04 = greenTireInformation.OPR04; |
| | | cntrItemRel.S_WINDUP = greenTireInformation.WINDUP; |
| | | cntrItemRel.S_TXNDATE = greenTireInformation.TXNDATE; |
| | | cntrItemRel.S_DATE_SHIFT = greenTireInformation.DATE_SHIFT; |
| | | cntrItemRel.S_EFFECTIVE_TIME = minTime.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | cntrItemRel.S_EXPIRATION_TIME = maxTime.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | result = db.Updateable(cntrItemRel).ExecuteCommand() > 0; |
| | | } |
| | | return result; |
| | | } |