using ServiceCenter.Extensions; using ServiceCenter.Logs; using ServiceCenter.Redis; using ServiceCenter.SqlSugars; using SqlSugar; using SqlSugar.Extensions; using System.Text; using WCS.Core; using WCS.Entity; using TaskStatus = WCS.Entity.TaskStatus; namespace WCS.WorkEngineering.Extensions { /// /// 任务扩展 /// public static class TaskExtension { /// /// 更新任务执行记录 /// 同步更新历史任务 /// /// 任务信息 /// 数据库上下文 /// 当前地址 /// 描述 public static void AddWCS_TASK_DTL(this WCS_TaskInfo task, SqlSugarScopeProvider db, string curPoint, string desc) => task.AddWCS_TASK_DTL(db, curPoint, "", desc); /// /// 更新任务执行记录 /// 同步更新历史任务 /// /// 任务信息 /// 数据库上下文 /// 当前地址 /// 下一个地址 /// 描述 public static void AddWCS_TASK_DTL(this WCS_TaskInfo task, SqlSugarScopeProvider db, string curPoint, string nextPoint, string desc) { db.InsertableRowLock(new WCS_TaskDtl { ID = Guid.NewGuid(), ParentTaskCode = task.ID, CurPoint = curPoint, NextPoint = nextPoint, Desc = desc, AddWho = "WCS" }).SplitTable().ExecuteCommand(); task.UpdateableOldTask(db); } /// /// 更新任务执行记录 /// 同步更新历史任务 /// /// 任务信息 /// 数据库上下文 /// 当前地址 /// 描述 public static void AddWCS_TASK_DTL(this WCS_TaskOld task, SqlSugarScopeProvider db, string curPoint, string desc) => task.AddWCS_TASK_DTL(db, curPoint, "", desc); /// /// 更新任务执行记录 /// 同步更新历史任务 /// /// 任务信息 /// 数据库上下文 /// 当前地址 /// 下一个地址 /// 描述 public static void AddWCS_TASK_DTL(this WCS_TaskOld task, SqlSugarScopeProvider db, string curPoint, string nextPoint, string desc) { db.Insertable(new WCS_TaskDtl { ID = Guid.NewGuid(), ParentTaskCode = task.Id, CurPoint = curPoint, NextPoint = nextPoint, Desc = desc, AddWho = "WCS" }).SplitTable().ExecuteCommand(); } /// /// 更新历史表数据 /// /// /// public static void UpdateableOldTask(this WCS_TaskInfo taskInfo, SqlSugarScopeProvider db) { if (taskInfo.Status == TaskStatus.NewBuild) return; // 同步任务信息 var taskOld = db.Queryable().Where(v => v.Id == taskInfo.ID).SplitTable(tabs => tabs.Take(2)).ToList().OrderByDescending(v => v.AddTime).First(); if (taskOld is not null) { if (taskInfo.Status >= TaskStatus.Finish) taskInfo.CompleteOrCancelTasks(db); else { taskOld = taskInfo.Mapper(); taskOld.Id = taskInfo.ID; db.UpdateableRowLock(taskOld).Where(x => x.Id == taskOld.Id).SplitTable(tabs => tabs.Take(2)).ExecuteCommand(); } } else { throw new KnownException($"WCS_TaskOld表中不存在任务:{taskInfo.ID},无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid); } } /// /// 完成或取消任务 /// /// /// public static void CompleteOrCancelTasks(this WCS_TaskInfo taskInfo, SqlSugarScopeProvider db) { if (taskInfo.Status is not Entity.TaskStatus.Finish and not Entity.TaskStatus.Cancel) throw new KnownException("任务未完成或取消,无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid); // 任务完成或取消,进行相关同步动作 var taskOld = db.Queryable().Where(v => v.Id == taskInfo.ID).SplitTable(tabs => tabs.Take(2)).ToList().OrderByDescending(v => v.AddTime).First(); if (taskOld is not null) { taskOld = taskInfo.Mapper(); taskOld.Id = taskInfo.ID; //更新任务历史表,删除任务当前表 db.UpdateableRowLock(taskOld).Where(x => x.Id == taskOld.Id).SplitTable(tabs => tabs.Take(2)).ExecuteCommand(); db.DeleteableRowLock(taskInfo).ExecuteCommand(); } else { throw new KnownException($"WCS_TaskOld表中不存在任务:{taskInfo.ID},无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid); } } /// /// 更新表数据 /// /// /// public static void Updateable(this WCS_TaskInfo taskInfo, SqlSugarScopeProvider db) { } ///// ///// 获取出库任务 ///// ///// 任务 ///// db ///// 可用出库站台 ///// 楼层 ///// 堆垛机 ///// 递归次数 ///// ///// //public static WCS_TaskInfo GetOutTask(this WCS_TaskInfo taskInfo, SqlSugarHelper db, List allOutCode, int floor, SRM obj, int index = 1) //{ // return task; //} /// /// 获取AGV任务ID /// /// db /// public static int GetAgvTaskId(this SqlSugarHelper db) { //最多任务号不再连续 var id = db.Default.Queryable().NoLock().SplitTable(v => v.Take(2)).Max(v => v.ID); return id + 1; } /// /// 更新任务执行记录 /// /// 任务信息 public static void UpdateRedisHash(this WCS_TaskInfo task) { var key = $"Hash:{task.ID}"; if (task.Status >= TaskStatus.Finish) { RedisHub.WMS.Del(key); } else { RedisHub.WMS.HMSet(key, task.ToDic()); } } #region 工字轮支线分流 /// /// 初始化码垛信息 /// /// public static void InitStackStructure(this WCS_TaskInfo task, SqlSugarScopeProvider db, World world) { var billBomsetgrp = db.Queryable().Single(x => x.IsStop == 0 && x.BomCode.Contains(task.MatCode)); if (billBomsetgrp == null) { world.Log($"物料规格[{task.MatCode}]无可用码垛垛形"); return; }; var billBomsetinfos = db.Queryable().Where(x => x.BomSetHdrId == billBomsetgrp.Id).ToList(); //开始构造垛形信息 var palletizing = new WCS_Palletizing() { Code = billBomsetgrp.Code, ShortCode = billBomsetgrp.ShortCode, ProMaterCode = billBomsetgrp.ProMaterCode, TpTypeCode = billBomsetgrp.TpTypeCode, LayerCountQty = 2, StampType = billBomsetgrp.StampType, Finish = false, AddTime = DateTime.Now, TaskId = task.ID, WarehouseCode = task.WarehouseCode, DeviceCode = task.Device }; palletizing = db.InsertableRowLock(palletizing).ExecuteReturnEntity(); foreach (var item in billBomsetinfos.Where(x => x.IsEmpty == 0).GroupBy(x => x.Row).OrderBy(x => x.Key)) { var layerNo = item.Key <= 6 ? 1 : 2; //获取层信息 var palletizingLayer = db.Queryable().Single(x => x.PalletizingId == palletizing.Id && x.LayerNo == layerNo); if (palletizingLayer == null) { palletizingLayer = new WCS_PalletizingLayer() { LayerNo = layerNo, PalletizingId = palletizing.Id, WarehouseCode = palletizing.WarehouseCode, }; palletizingLayer = db.InsertableRowLock(palletizingLayer).ExecuteReturnEntity(); } //获取行信息 var palletizingRow = db.Queryable().Single(x => x.PalletizingLayerId == palletizingLayer.Id && x.RowNo == item.Key); if (palletizingRow == null) { palletizingRow = new WCS_PalletizingRow() { RowNo = item.Key, PalletizingLayerId = palletizingLayer.Id, PalletizingId = palletizing.Id, WarehouseCode = palletizingLayer.WarehouseCode }; palletizingRow = db.InsertableRowLock(palletizingRow).ExecuteReturnEntity(); } //重新查询最新的数据 var layer = palletizingLayer; palletizingLayer = db.Queryable().Single(x => x.Id == layer.Id); var row = palletizingRow; palletizingRow = db.Queryable().Single(x => x.Id == row.Id); //构造位信息 foreach (var loc in item) { var palletizingLoc = db.Queryable().Single(x => x.PalletizingRowId == palletizingRow.Id && x.XYNo == loc.XYNo); if (palletizingLoc == null) { palletizingLoc = new WCS_PalletizingLoc() { IsEmpty = loc.IsEmpty != 0, XYNo = loc.XYNo, MatCode = loc.MatCode, SideNum = loc.SideNum, SpoolType = loc.SpoolType, TaskId = task.ID, PalletizingRowId = palletizingRow.Id, Finish = false, WarehouseCode = palletizingRow.WarehouseCode }; db.InsertableRowLock(palletizingLoc).ExecuteReturnEntity(); } //同步是否混合料行 palletizingRow.IsMixRow = loc.IsMixRow != 0; db.UpdateableRowLock(palletizingRow).ExecuteCommand(); } //更新行信息 palletizingRow = db.Queryable().Includes(x => x.Locs).Single(x => x.Id == row.Id); palletizingRow.QtyMaxCount = palletizingRow.Locs.Count(x => !x.IsEmpty); palletizingRow.IsEmpty = palletizingRow.QtyMaxCount <= 0; palletizingRow.MatCodeList = palletizingRow.Locs.Select(x => x.MatCode).ToList().GetMatList(); db.UpdateableRowLock(palletizingRow).ExecuteCommand(); //更新层信息 palletizingLayer = db.Queryable().Includes(x => x.Rows, l => l.Locs).Single(x => x.Id == layer.Id); var count = palletizingLayer.Rows.Count(x => !x.IsEmpty); //计算所有不空数量 palletizingLayer.IsEmpty = count <= 0; palletizingLayer.RowCountQty = palletizingLayer.Rows.Count; palletizingLayer.Finish = false; palletizingLayer.MatCodeList = palletizingLayer.Rows.SelectMany(x => x.Locs).Select(x => x.MatCode).ToList().GetMatList(); db.UpdateableRowLock(palletizingLayer).ExecuteCommand(); } var palletizing1 = palletizing; palletizing = db.Queryable().Includes(x => x.Layers, r => r.Rows, l => l.Locs).Single(x => x.Id == palletizing1.Id); //计算垛形信息 var goods = palletizing.Layers.Select(x => x.Rows).SelectMany(x => x).Select(x => x.Locs).SelectMany(x => x).ToList(); palletizing.CountQty = goods.Count(x => !x.IsEmpty); palletizing.MatCodeList = palletizing.Layers.SelectMany(x => x.Rows).SelectMany(x => x.Locs).Select(x => x.MatCode).ToList().GetMatList(); db.UpdateableRowLock(palletizing).ExecuteCommand(); } public static string GetMatList(this List matList) { return matList.Distinct().Aggregate("", (current, mat) => current + $"[{mat}]"); } /// /// 去除转义字符 /// /// /// public static string RemoveEscapeCharacters(this string? value) { return value.Trim('\0', '\a', '\b', '\f', '\n', '\r', '\t', '\v').Trim(); } #endregion 工字轮支线分流 public static string ToSqlString(this QuestDBInsertBuilder questDb) { if (questDb.IsNoInsertNull) { questDb.DbColumnInfoList = questDb.DbColumnInfoList.Where(it => it.Value != null).ToList(); } var groupList = questDb.DbColumnInfoList.GroupBy(it => it.TableId).ToList(); var isSingle = groupList.Count() == 1; string columnsString = string.Join(",", groupList.First().Select(it => questDb.Builder.GetTranslationColumnName(it.DbColumnName))); if (isSingle) { string columnParametersString = string.Join(",", questDb.DbColumnInfoList.Select(it => { var spk = questDb.Builder.SqlParameterKeyWord + it.DbColumnName; //if (it.Value is DateTime) //{ // return $"to_timestamp('{it.Value.ObjToString("yyyy-MM-ddTHH:mm:ss")}', 'yyyy-MM-ddTHH:mm:ss')"; //} return questDb.GetDbColumn(it, spk); } )); questDb.ActionMinDate(); return string.Format(questDb.SqlTemplate, questDb.GetTableNameString, columnsString, columnParametersString); } else { StringBuilder batchInsetrSql = new StringBuilder(); int pageSize = 200; int pageIndex = 1; int totalRecord = groupList.Count; int pageCount = (totalRecord + pageSize - 1) / pageSize; while (pageCount >= pageIndex) { batchInsetrSql.AppendFormat(questDb.SqlTemplateBatch, questDb.GetTableNameString, columnsString); int i = 0; foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) { var isFirst = i == 0; if (isFirst) { batchInsetrSql.Append(questDb.SqlTemplateBatchUnion); } batchInsetrSql.Append("\r\n ( " + string.Join(",", columns.Select(it => { if (it.InsertServerTime || it.InsertSql.HasValue()) { return questDb.GetDbColumn(it, null); } object value = null; if (it.Value is DateTime) { return $" cast('{it.Value.ObjToDate().ToString("yyyy-MM-dd HH:mm:ss.ffffff")}' as timestamp)"; } else if (it.Value is int || it.Value is long || it.Value is short || it.Value is short || it.Value is byte || it.Value is double) { return it.Value; } else if (it.Value is bool) { return it.Value.ObjToString().ToLower(); } else { value = it.Value; } if (value == null || value == DBNull.Value) { return string.Format(questDb.SqlTemplateBatchSelect, "NULL"); } return string.Format(questDb.SqlTemplateBatchSelect, "'" + value.ObjToString().ToSqlFilter() + "'"); })) + "),"); ++i; } pageIndex++; batchInsetrSql.Remove(batchInsetrSql.Length - 1, 1).Append("\r\n;\r\n"); } return batchInsetrSql.ToString(); } } public static bool HasValue(this object thisValue) { if (thisValue == null || thisValue == DBNull.Value) return false; return thisValue.ToString() != ""; } } /// /// 垛形位信息 /// public class StackPosInfo { /// /// 任务号 /// public int TaskNumber { get; set; } /// /// 是否空置 /// public bool IsEmpty { get; set; } /// /// 坐标号 /// public string XYNo { get; set; } /// /// 物料编码 /// public string MatCode { get; set; } /// /// 正反面 /// public int SideNum { get; set; } /// /// 工字轮类型 /// public string SpoolType { get; set; } /// /// 是否结束 /// public bool Finish { get; set; } } /// /// 垛型明细表 /// [SugarTable("Bill_BomSetInfo", tableDescription: "垛型明细表")] public partial class BillBomsetinfo { /// /// ID /// [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, ColumnDescription = "ID")] public virtual long Id { get; set; } /// /// 备注 /// [SugarColumn(ColumnName = "Memo", Length = 500, IsNullable = true, ColumnDataType = "nvarchar", DefaultValue = "", ColumnDescription = "备注")] public virtual string Memo { get; set; } /// /// 创建用户 /// [SugarColumn(ColumnName = "AddWho", Length = 50, ColumnDataType = "nvarchar", DefaultValue = "", IsNullable = false, ColumnDescription = "创建用户")] public virtual string AddWho { get; set; } = ""; /// /// 更新用户 /// [SugarColumn(ColumnName = "EditWho", Length = 50, ColumnDataType = "nvarchar", DefaultValue = "", IsNullable = false, ColumnDescription = "更新用户")] public virtual string EditWho { get; set; } = ""; /// /// 创建时间 /// [SugarColumn(ColumnName = "AddTime", DefaultValue = "1900-1-1", IsNullable = false, ColumnDescription = "创建时间")] public virtual DateTime AddTime { get; set; } = DateTime.Now; /// /// 更新时间 /// [SugarColumn(ColumnName = "EditTime", DefaultValue = "1900-1-1", IsNullable = false, ColumnDescription = "更新时间")] public virtual DateTime EditTime { get; set; } = DateTime.Now; /// /// 垛型id /// [SugarColumn(ColumnDataType = "bigint", IsNullable = false, ColumnDescription = "垛型id")] public long BomSetHdrId { get; set; } /// /// 是否停用 /// [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "是否停用")] public int IsStop { get; set; } /// /// 是否空置 /// [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "是否空置")] public int IsEmpty { get; set; } /// /// 坐标号 /// [SugarColumn(ColumnDataType = "nvarchar", Length = 50, IsNullable = false, ColumnDescription = "坐标号")] public string XYNo { get; set; } /// /// 物料id /// [SugarColumn(ColumnDataType = "bigint", ColumnDescription = "物料id")] public long MatId { get; set; } /// /// 物料编码 /// [SugarColumn(ColumnDataType = "nvarchar", IsNullable = true, Length = 50, ColumnDescription = "物料编码")] public string MatCode { get; set; } /// /// 正反面 /// [SugarColumn(ColumnDataType = "int", IsNullable = true, ColumnDescription = "正反面")] public int SideNum { get; set; } /// /// 工字轮类型 /// [SugarColumn(ColumnDataType = "nvarchar", Length = 50, IsNullable = true, ColumnDescription = "工字轮类型")] public string SpoolType { get; set; } /// /// 钢丝类型 /// [SugarColumn(ColumnDataType = "nvarchar", Length = 50, IsNullable = true, ColumnDescription = "钢丝类型")] public string SilkType { get; set; } /// /// 钢丝直径 /// [SugarColumn(ColumnDataType = "decimal", Length = 18, IsNullable = true, ColumnDescription = "钢丝直径")] public decimal SilkDiam { get; set; } /// /// 钢丝直径上限 /// [SugarColumn(ColumnDataType = "decimal", Length = 18, IsNullable = true, ColumnDescription = "钢丝直径上限")] public decimal SilkDiamMaxCount { get; set; } /// /// 数量上限 /// [SugarColumn(ColumnDataType = "int", IsNullable = true, ColumnDescription = "数量上限")] public int QtyMaxCount { get; set; } /// /// 是否芯股 /// [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "是否芯股")] public int IsCore { get; set; } /// /// 09垛型里面的行(1-12) /// [SugarColumn(ColumnDataType = "int", IsNullable = true, ColumnDescription = "09垛型里面的行(1-12)")] public int Row { get; set; } /// /// 是否混合料行(09垛型使用,1是0否) /// [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "是否混合料行(09垛型使用,1是0否)")] public int IsMixRow { get; set; } /// /// 混合料行编码 /// [SugarColumn(ColumnDataType = "nvarchar", IsNullable = true, Length = 50, ColumnDescription = "混合料行编码")] public string MixRowCode { get; set; } /// /// 第一种第二种第三种 /// [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "第一种第二种第三种")] public int CategoryId { get; set; } } /// /// 垛形主表 /// [Tenant("fj")] [SugarTable("Bill_BomSetGrp", tableDescription: "垛形主表")] public partial class BillBomsetgrp { /// /// ID /// [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, ColumnDescription = "ID")] public virtual long Id { get; set; } /// /// 备注 /// [SugarColumn(ColumnName = "Memo", Length = 500, IsNullable = true, ColumnDataType = "nvarchar", DefaultValue = "", ColumnDescription = "备注")] public virtual string Memo { get; set; } /// /// 创建用户 /// [SugarColumn(ColumnName = "AddWho", Length = 50, ColumnDataType = "nvarchar", DefaultValue = "", IsNullable = false, ColumnDescription = "创建用户")] public virtual string AddWho { get; set; } = ""; /// /// 更新用户 /// [SugarColumn(ColumnName = "EditWho", Length = 50, ColumnDataType = "nvarchar", DefaultValue = "", IsNullable = false, ColumnDescription = "更新用户")] public virtual string EditWho { get; set; } = ""; /// /// 创建时间 /// [SugarColumn(ColumnName = "AddTime", DefaultValue = "1900-1-1", IsNullable = false, ColumnDescription = "创建时间")] public virtual DateTime AddTime { get; set; } = DateTime.Now; /// /// 更新时间 /// [SugarColumn(ColumnName = "EditTime", DefaultValue = "1900-1-1", IsNullable = false, ColumnDescription = "更新时间")] public virtual DateTime EditTime { get; set; } = DateTime.Now; /// /// 是否停用 /// [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "是否停用")] public int IsStop { get; set; } /// /// 垛型编码 /// [SugarColumn(ColumnDataType = "nvarchar", Length = 50, IsNullable = false, ColumnDescription = "垛型编码")] public string Code { get; set; } /// /// 短垛型编码 /// [SugarColumn(ColumnDataType = "smallint", IsNullable = false, ColumnDescription = "短垛型编码")] public short ShortCode { get; set; } /// /// 垛型名称 /// [SugarColumn(ColumnDataType = "nvarchar", Length = 100, IsNullable = false, ColumnDescription = "垛型名称")] public string Name { get; set; } /// /// BomCode(投料信息) /// [SugarColumn(ColumnDataType = "nvarchar", Length = 200, IsNullable = false, ColumnDescription = "BomCode(投料信息)")] public string BomCode { get; set; } /// /// 帘线物料编码 /// [SugarColumn(ColumnDataType = "nvarchar", Length = 50, IsNullable = false, ColumnDescription = "帘线物料编码")] public string ProMaterCode { get; set; } /// /// 工字轮个数 /// [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "工字轮个数")] public int HWCountQty { get; set; } /// /// 托盘类型 /// [SugarColumn(ColumnDataType = "nvarchar", Length = 50, IsNullable = false, ColumnDescription = "托盘类型")] public string TpTypeCode { get; set; } /// /// 层数 /// [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "层数")] public int LayerCountQty { get; set; } /// /// 垛型大类 /// [SugarColumn(ColumnDataType = "int", IsNullable = true, ColumnDescription = "垛型大类")] public int StampType { get; set; } } }