diff --git a/DOAN.Admin.WebApi/Controllers/JobKanban/WorkOrderProgressController.cs b/DOAN.Admin.WebApi/Controllers/JobKanban/WorkOrderProgressController.cs
index ba90201..f7f1671 100644
--- a/DOAN.Admin.WebApi/Controllers/JobKanban/WorkOrderProgressController.cs
+++ b/DOAN.Admin.WebApi/Controllers/JobKanban/WorkOrderProgressController.cs
@@ -51,7 +51,7 @@ public class WorkOrderProgressController : BaseController
}
///
- /// 工单list (未完成的)
+ /// 工单list (未完成的)
///
///
///
@@ -107,6 +107,29 @@ public class WorkOrderProgressController : BaseController
return SUCCESS(response);
}
+
+ //TODO 暂停某个工单
+ [HttpGet("pause_workorder")]
+ public IActionResult PauseWorkOrder(string workorder)
+ {
+ if (string.IsNullOrEmpty(workorder)) return SUCCESS(null);
+ var response = workorderProgressService.PauseWorkOrder(workorder);
+
+ return SUCCESS(response);
+ }
+
+
+ //TODO 恢复某个工单
+ [HttpGet("recover_workorder")]
+ public IActionResult RecoverWorkOrder(string workorder)
+ {
+ if (string.IsNullOrEmpty(workorder)) return SUCCESS(null);
+ var response = workorderProgressService.RecoverWorkOrder(workorder);
+
+ return SUCCESS(response);
+ }
+
+
//TODO 完成某一个工单
[HttpGet("finish_workorder")]
public IActionResult FinishWorkOrder(string workorder)
@@ -117,6 +140,22 @@ public class WorkOrderProgressController : BaseController
return SUCCESS(response);
}
+ ///
+ /// TODO 完成 工单
+ ///
+ ///
+ ///
- /// TODO 完成 工单
- ///
- ///
- ///
+ /// 生产工单
+ ///
+ [SugarTable("pro_workorder_status")]
+ public class ProWorkorderStatus
+ {
+
+ ///
+ ///
+ ///
+ [SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
+ public int Id { get; set; }
+
+
+ ///
+ /// 工单号
+ ///
+ [SugarColumn(ColumnName = "fk_workorder_code")]
+ public string FkWorkorderCode { get; set; }
+
+
+ ///
+ /// 状态(1 init,2 start 3 end 4 pause)
+ ///
+ [SugarColumn(ColumnName = "status")]
+ public int Status { get; set; }
+
+
+
+ ///
+ /// 状态更改时间
+ ///
+ [SugarColumn(ColumnName = "change_time")]
+ public DateTime ChangeTime { get; set; }
+
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "created_time")]
+ public DateTime CreatedTime { get; set; }
+ }
+
+}
diff --git a/DOAN.Service/JobKanban/IService/IWorkorderProgressService.cs b/DOAN.Service/JobKanban/IService/IWorkorderProgressService.cs
index b178760..2d2893a 100644
--- a/DOAN.Service/JobKanban/IService/IWorkorderProgressService.cs
+++ b/DOAN.Service/JobKanban/IService/IWorkorderProgressService.cs
@@ -1,12 +1,13 @@
-using System;
+using DOAN.Model.JobKanban;
+using DOAN.Model.mes.echarts;
+using DOAN.Model.MES.base_;
+using DOAN.Model.MES.product;
+using DOAN.Model.MES.product.Dto;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using DOAN.Model.JobKanban;
-using DOAN.Model.MES.base_;
-using DOAN.Model.MES.product;
-using DOAN.Model.MES.product.Dto;
namespace DOAN.Service.JobKanban.IService
{
public interface IWorkorderProgressService
@@ -26,6 +27,10 @@ namespace DOAN.Service.JobKanban.IService
KanbanInfo GetKanbanNum(DateTime today, string line_code, string group_code);
Task StartWorkOrder(string workorder);
+
+
+ int PauseWorkOrder(string workorder);
+ int RecoverWorkOrder(string workorder);
int FinishWorkOrder(string workorder);
ProWorkorder GetProductingWorkorder(string line_code, DateTime handleDate);
int AddLabelLog(string labelContext, string workOrder);
@@ -44,5 +49,8 @@ namespace DOAN.Service.JobKanban.IService
List GetWorkOrderScanCodeInfo(string workorder);
bool SwitchWorkOrderCheckLabel(string pre_workorder);
+
+
+ EchartsOptions GetHourlyProduction(string groupCode);
}
}
diff --git a/DOAN.Service/JobKanban/WorkorderProgressService.cs b/DOAN.Service/JobKanban/WorkorderProgressService.cs
index 0a50322..1df05ec 100644
--- a/DOAN.Service/JobKanban/WorkorderProgressService.cs
+++ b/DOAN.Service/JobKanban/WorkorderProgressService.cs
@@ -1,6 +1,8 @@
using DOAN.Infrastructure.Helper;
using DOAN.Model.JobKanban;
+using DOAN.Model.mes.echarts;
using DOAN.Model.MES.base_;
+using DOAN.Model.MES.group;
using DOAN.Model.MES.mm;
using DOAN.Model.MES.product;
using DOAN.Model.MES.product.Dto;
@@ -14,6 +16,7 @@ using Mapster;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Asn1;
using SqlSugar.SplitTableExtensions;
+using System.Data;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
@@ -162,59 +165,69 @@ public class WorkorderProgressService : BaseService, IWorkorderPro
//TODO 拼接MQTT消息,发送给设备,工单信息和配方信息
var spec = handleWorkorder.Specification;
- var RecipeMesg = Context.Queryable()
- .LeftJoin((rpr, r) => rpr.RecipeCode == r.RecipeCode)
- .Where((rpr, r) => SqlFunc.Like(spec, rpr.RecipeCode + "%"))
- .Where((rpr, r) => r.Status == 1)
- .Select((rpr, r) => new
- {
- RecipeCode = r.RecipeCode,
- Version = r.Version,
- ParamList = SqlFunc.Subqueryable()
- .Where(it => it.RecipeCode == r.RecipeCode && it.Version == r.Version)
- .ToList(),
- // 添加匹配长度用于排序
- MatchLength = rpr.RecipeCode.Length
- })
- .MergeTable()
- .OrderByDescending(x => x.MatchLength) // 按匹配长度降序排列
- .First(); // 取第一个(匹配最长的)
+ //var RecipeMesg = Context.Queryable()
+ // .LeftJoin((rpr, r) => rpr.RecipeCode == r.RecipeCode)
+ // .Where((rpr, r) => SqlFunc.Like(spec, rpr.RecipeCode + "%"))
+ // .Where((rpr, r) => r.Status == 1)
+ // .Select((rpr, r) => new
+ // {
+ // RecipeCode = r.RecipeCode,
+ // Version = r.Version,
+ // ParamList = SqlFunc.Subqueryable()
+ // .Where(it => it.RecipeCode == r.RecipeCode && it.Version == r.Version)
+ // .ToList(),
+ // // 添加匹配长度用于排序
+ // MatchLength = rpr.RecipeCode.Length
+ // })
+ // .MergeTable()
+ // .OrderByDescending(x => x.MatchLength) // 按匹配长度降序排列
+ // .First(); // 取第一个(匹配最长的)
// 合并两个对象为匿名对象
var combinedObject = new
{
WorkorderInfo = handleWorkorder,
- RecipeInfo = RecipeMesg
+ // RecipeInfo = RecipeMesg
};
string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(combinedObject, Newtonsoft.Json.Formatting.Indented);
//插入配方派发日志
- if (RecipeMesg != null && !string.IsNullOrEmpty(RecipeMesg.RecipeCode))
- {
- PfRecipeIssueLog pfRecipeIssueLog = new PfRecipeIssueLog();
- pfRecipeIssueLog.RecipeCode = RecipeMesg.RecipeCode;
- pfRecipeIssueLog.Version = RecipeMesg.Version;
- pfRecipeIssueLog.IssueTime = DateTime.Now;
- pfRecipeIssueLog.Workorder = handleWorkorder.Workorder;
- pfRecipeIssueLog.Productcode = handleWorkorder.ProductionCode;
- pfRecipeIssueLog.Productname = handleWorkorder.ProductionName;
- pfRecipeIssueLog.CreatedBy = "PDA";
- pfRecipeIssueLog.CreatedTime = DateTime.Now;
- Context.Insertable(pfRecipeIssueLog).ExecuteCommand();
+ //if (RecipeMesg != null && !string.IsNullOrEmpty(RecipeMesg.RecipeCode))
+ //{
+ // PfRecipeIssueLog pfRecipeIssueLog = new PfRecipeIssueLog();
+ // pfRecipeIssueLog.RecipeCode = RecipeMesg.RecipeCode;
+ // pfRecipeIssueLog.Version = RecipeMesg.Version;
+ // pfRecipeIssueLog.IssueTime = DateTime.Now;
+ // pfRecipeIssueLog.Workorder = handleWorkorder.Workorder;
+ // pfRecipeIssueLog.Productcode = handleWorkorder.ProductionCode;
+ // pfRecipeIssueLog.Productname = handleWorkorder.ProductionName;
+ // pfRecipeIssueLog.CreatedBy = "PDA";
+ // pfRecipeIssueLog.CreatedTime = DateTime.Now;
+ // Context.Insertable(pfRecipeIssueLog).ExecuteCommand();
- }
+ //}
MqttHelper _mqttHelper = new MqttHelper("192.168.50.163", 1883);
// 连接
- await _mqttHelper.ConnectAsync();
+
+ using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2)); // 总超时10秒
+ var connectTask = _mqttHelper.ConnectAsync();
+ var timeoutTask = Task.Delay(5000, cts.Token); // 5秒连接超时
+
+ var completedTask = await Task.WhenAny(connectTask, timeoutTask);
+ if (completedTask == timeoutTask)
+ {
+ throw new TimeoutException("连接MQTT服务器超时");
+ }
+ await connectTask; // 确保没有异常
// 发送多条消息
- string line = handleWorkorder.LineCode ==null?"-1": handleWorkorder.LineCode;
- await _mqttHelper.PublishMessageAsync("MES/Workorder/Start/handleWorkorder/"+ line, jsonString);
+ string line = handleWorkorder.LineCode == null ? "-1" : handleWorkorder.LineCode;
+ await _mqttHelper.PublishMessageAsync("MES/Workorder/Start/handleWorkorder/" + line, jsonString);
// 断开连接
await _mqttHelper.DisconnectAsync();
@@ -260,7 +273,7 @@ public class WorkorderProgressService : BaseService, IWorkorderPro
}
else
{
-
+
}
}
@@ -272,13 +285,91 @@ public class WorkorderProgressService : BaseService, IWorkorderPro
}
}
+ ///
+ /// 暂停工单
+ ///
+ ///
+ ///
+ public int PauseWorkOrder(string workorder)
+ {
+ int result = 0;
+ UseTran2(() =>
+ {
+ ProWorkorderStatus proWorkorderStatus = new ProWorkorderStatus();
+ proWorkorderStatus.FkWorkorderCode = workorder;
+ proWorkorderStatus.Status = 4;
+ proWorkorderStatus.ChangeTime = DateTime.Now;
+ proWorkorderStatus.CreatedTime = DateTime.Now;
+
+ Context.Insertable(proWorkorderStatus).ExecuteCommand();
+
+
+ result = Context.Updateable()
+ .SetColumns(it => it.Status == 4)
+ .SetColumns(it => it.EndTime == DateTime.Now)
+ .Where(it => it.Workorder == workorder).ExecuteCommand();
+
+ });
+ return result;
+ }
+
+
+ ///
+ /// 恢复工单
+ ///
+ ///
+ ///
+ public int RecoverWorkOrder(string workorder)
+ {
+ int result = 0;
+ UseTran2(() =>
+ {
+ ProWorkorderStatus proWorkorderStatus = new ProWorkorderStatus();
+ proWorkorderStatus.FkWorkorderCode = workorder;
+ proWorkorderStatus.Status = 5;
+ proWorkorderStatus.ChangeTime = DateTime.Now;
+ proWorkorderStatus.CreatedTime = DateTime.Now;
+
+ Context.Insertable(proWorkorderStatus).ExecuteCommand();
+
+
+ result = Context.Updateable()
+ .SetColumns(it => it.Status == 5)
+ .SetColumns(it => it.EndTime == DateTime.Now)
+ .Where(it => it.Workorder == workorder).ExecuteCommand();
+
+ });
+ return result;
+ }
+ ///
+ /// 工单完成
+ ///
+ ///
+ ///
+
public int FinishWorkOrder(string workorder)
{
- return Context.Updateable()
- .SetColumns(it => it.Status == 3)
- .SetColumns(it => it.EndTime == DateTime.Now)
- .Where(it => it.Workorder == workorder).ExecuteCommand();
+ int result = 0;
+ UseTran2(() =>
+ {
+ ProWorkorderStatus proWorkorderStatus = new ProWorkorderStatus();
+ proWorkorderStatus.FkWorkorderCode = workorder;
+ proWorkorderStatus.Status = 3;
+ proWorkorderStatus.ChangeTime = DateTime.Now;
+ proWorkorderStatus.CreatedTime = DateTime.Now;
+
+
+ Context.Insertable(proWorkorderStatus).ExecuteCommand();
+
+ result = Context.Updateable()
+ .SetColumns(it => it.Status == 3)
+ .SetColumns(it => it.EndTime == DateTime.Now)
+ .Where(it => it.Workorder == workorder).ExecuteCommand();
+
+ });
+ return result;
}
+
public ProWorkorder GetProductingWorkorder(string line_code, DateTime handleDate)
{
@@ -496,4 +587,149 @@ public class WorkorderProgressService : BaseService, IWorkorderPro
return false;
}
}
+
+ public EchartsOptions GetHourlyProduction(string groupCode)
+ {
+
+ EchartsOptions echartsOptions = new EchartsOptions();
+
+ echartsOptions.Title = new EchartsTitle("今日各组实时完工数与计划完工柱状图", "获取今日各组实时每小时完工数柱状图");
+
+ //横轴 8:00 20:00 每60分钟累加一次
+ // 1.获取这个班组工作时间
+ GroupShift Shifts = Context.Queryable().LeftJoin((sc, sh) => sc.FkShift == sh.Id)
+ .Where((sc, sh) => sc.ScheduleDate == DateTime.Today && sc.GroupCode == groupCode).Select((sc, sh) => sh).First();
+ if (Shifts == null)
+ {
+ return null;
+ }
+ // 处理每小时间隔
+ int intervals = (int)Math.Ceiling((Shifts.EndTime - Shifts.StartTime).Value.TotalMinutes / 60);
+ intervals++;
+ // 获取今天的日期
+ DateTime today = DateTime.Today;
+ // 定义一个表示8小时的时间间隔
+ TimeSpan eightOClock = new TimeSpan(Shifts.StartTime.Value.Hour, Shifts.StartTime.Value.Minute, Shifts.StartTime.Value.Second);
+ // 将今天的日期与8点的时间间隔相加
+ DateTime todayAtEight = today + eightOClock;
+ DateTime[] dateTimeArray = new DateTime[intervals];
+ for (int i = 0; i < intervals; i++)
+ {
+ TimeSpan spanItem = new TimeSpan(0, 10 * i, 0);// 60分钟间隔
+ DateTime TodayItem = todayAtEight + spanItem;
+ dateTimeArray[i] = TodayItem;
+ }
+ EchartsXAxis XAxis = new EchartsXAxis();
+ XAxis.Data = dateTimeArray.Select(it => it.ToString("HH:mm")).ToList();
+ echartsOptions.XAxis = XAxis;
+ //2 系列值-这组 今日实时完成数(60分钟)
+ EchartsSeries echartsSeries = new EchartsSeries();
+ echartsSeries.Name = groupCode + "组今日实时完成数(每60分钟)";
+ echartsSeries.Type = "bar";
+ List echartsSeriesDatas = new List();
+ //UNIX_TIMESTAMP(timestamp) 把 timestamp 转换为自 Unix 纪元以来的秒数。
+ //FLOOR(... / 600) 将该时间戳除以600(10分钟的秒数),然后向下取整到最接近的整数。
+ //*600 再次乘以600,以获得每个10分钟周期开始的时间戳。
+ //FROM_UNIXTIME(...) 将处理后的时间戳转换回日期时间格式,以便在结果集中显示。
+
+ string year = DateTime.Today.Year.ToString("D4");
+ string month = DateTime.Today.Month.ToString("D2");
+ string day = "01";
+
+ string sql = "SELECT FROM_UNIXTIME( FLOOR( UNIX_TIMESTAMP( d.created_time ) / 3600 ) * 3600 ) AS time_period, COUNT(*) AS count FROM " +
+ $"pro_workorder AS r RIGHT JOIN pro_reportwork_detail_{year}{month}{day} AS d ON r.workorder = d.workorder " +
+ "WHERE r.workorder_date = CURDATE() AND r.group_code= @groupCode " +
+ " GROUP BY FLOOR( UNIX_TIMESTAMP( d.created_time ) / 600 ) ORDER BY time_period";
+
+
+
+ DataTable result = Context.Ado.GetDataTable(sql, new { groupCode = groupCode, });
+ int sum = 0;
+
+
+ foreach (DataRow row in result.Rows)
+ {
+ // DateTime value =(DateTime)row["time_period"];
+ DateTime value = row["time_period"] != DBNull.Value ? Convert.ToDateTime(row["time_period"]) : DateTime.MinValue;
+ int count = Convert.ToInt32(row["count"]);
+
+ // sum = sum + count;
+ EchartsSeriesData echartsSeriesData = new EchartsSeriesData()
+ {
+ Name = value.ToString("HH:mm"),
+ Value = count
+ };
+ echartsSeriesDatas.Add(echartsSeriesData);
+ }
+ int currentNum = Array.IndexOf(XAxis.Data.ToArray(), echartsSeriesDatas.Select(it => it.Name).LastOrDefault());
+ for (int i = 0; i < currentNum; i++)
+ {
+ int point = 0;
+ foreach (var item in echartsSeriesDatas)
+ {
+
+ if (item.Name == XAxis.Data[i])
+ {
+ continue;
+ }
+ point++;
+
+ }
+
+ if (point == echartsSeriesDatas.Count())
+ {
+ // 获取前一个时间段产量
+ decimal productNum = 0;
+ if (i >= 1)
+ {
+ productNum = echartsSeriesDatas.Where(it => it.Name == XAxis.Data[i - 1]).Select(it => it.Value).FirstOrDefault();
+ }
+ else
+ {
+ productNum = 0;
+ }
+
+
+ echartsSeriesDatas.Add(new EchartsSeriesData() { Name = XAxis.Data[i], Value = productNum });
+ }
+ }
+ echartsSeries.Data = echartsSeriesDatas.OrderBy(it => it.Name).ToList();
+ echartsOptions.Series.Add(echartsSeries);
+
+ //3 系列值-这组 今日计划累计完成数(每60分钟)
+ //获取今天这个组的所有工单
+ List ProWorkorderList = Context.Queryable().Where(it => it.GroupCode == groupCode && it.WorkorderDate == DateTime.Today).ToList();
+
+ //求出总产量需要多少s
+ int allSecends = 0;
+ foreach (var item in ProWorkorderList)
+ {
+ int num = (item.DeliveryNum ?? 0) * (item.Beat ?? 0);
+ allSecends = num + allSecends;
+ }
+
+ // 将节拍转为每60分钟产量
+ int allproduct = ProWorkorderList.Sum(it => it.DeliveryNum ?? 0);
+ int productOfeachTenMin = allproduct / (allSecends / (60 * 60));
+
+ EchartsSeries echartsSeries02 = new EchartsSeries();
+ echartsSeries02.Name = groupCode + "组今日计划累计完成数(每60分钟)";
+ echartsSeries02.Type = "bar";
+ List echartsSeriesData02s = new List();
+ //int all_plan_product = 0;
+ for (int i = 0; i < dateTimeArray.Length; i++)
+ {
+
+ EchartsSeriesData echartsSeriesData = new EchartsSeriesData();
+ echartsSeriesData.Name = dateTimeArray[i].ToString("HH:mm");
+ echartsSeriesData.Value = productOfeachTenMin;
+ echartsSeriesData02s.Add(echartsSeriesData);
+ //all_plan_product = all_plan_product + productOfeachTenMin;
+ }
+ echartsSeries02.Data = echartsSeriesData02s;
+ echartsOptions.Series.Add(echartsSeries02);
+
+ return echartsOptions;
+
+ }
}
\ No newline at end of file
diff --git a/MDM/Controllers/Session/SessionManagerController.cs b/MDM/Controllers/Session/SessionManagerController.cs
index 1798292..bf29de1 100644
--- a/MDM/Controllers/Session/SessionManagerController.cs
+++ b/MDM/Controllers/Session/SessionManagerController.cs
@@ -74,7 +74,7 @@ namespace MDM.Controllers.Session
public IActionResult MiddleStationApply(string OperationCode, string ProcessCode)
{
- Dictionary> result = _ISessionManagerService.MiddleProcessFlowDistribution(OperationCode, ProcessCode);
+ List result = _ISessionManagerService.MiddleProcessFlowDistribution(OperationCode, ProcessCode);
return SUCCESS(result);
}
@@ -90,6 +90,9 @@ namespace MDM.Controllers.Session
}
+
+
+
//TODO 完工申请
///
/// 完工申请
diff --git a/MDM/Models/Flow/FlowEnums.cs b/MDM/Models/Flow/FlowEnums.cs
index 2e58372..52f9df3 100644
--- a/MDM/Models/Flow/FlowEnums.cs
+++ b/MDM/Models/Flow/FlowEnums.cs
@@ -169,6 +169,16 @@ namespace MDM.Models.Flow
/// 未知状态,,禁止出站
///
UnknownStatus = -10,
+ ///
+ /// 扫码流程未完成,禁止出站
+ ///
+
+ ScanFlowNotCompleted = -11,
+
+ ///
+ /// 参数采集未完成,禁止出站
+ ///
+ ParmetersCollectNotCompleted = -12
}
diff --git a/MDM/Models/Session/ProductLifecycle.cs b/MDM/Models/Product/ProductLifecycle.cs
similarity index 100%
rename from MDM/Models/Session/ProductLifecycle.cs
rename to MDM/Models/Product/ProductLifecycle.cs
diff --git a/MDM/Models/Session/ProductPassstationRecord.cs b/MDM/Models/Product/ProductPassstationRecord.cs
similarity index 100%
rename from MDM/Models/Session/ProductPassstationRecord.cs
rename to MDM/Models/Product/ProductPassstationRecord.cs
diff --git a/MDM/Models/Session/ProductProcessData.cs b/MDM/Models/Product/ProductProcessData.cs
similarity index 100%
rename from MDM/Models/Session/ProductProcessData.cs
rename to MDM/Models/Product/ProductProcessData.cs
diff --git a/MDM/Models/Product/ProductProcessParameters.cs b/MDM/Models/Product/ProductProcessParameters.cs
new file mode 100644
index 0000000..47ba467
--- /dev/null
+++ b/MDM/Models/Product/ProductProcessParameters.cs
@@ -0,0 +1,151 @@
+using MathNet.Numerics;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MDM.Models.Session
+{
+ ///
+ /// 生产过程参数
+ ///
+ [SugarTable("product_process_parameters")]
+ public class ProductProcessParameters
+ {
+ ///
+ /// 主键
+ ///
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ ///
+ /// 工单号
+ ///
+ [SugarColumn(ColumnName = "workorder", Length = 50)]
+ public string Workorder { get; set; }
+
+ ///
+ /// 产品SN
+ ///
+ [SugarColumn(ColumnName = "product_SN", Length = 50)]
+ public string ProductSN { get; set; }
+
+ ///
+ /// 工艺路线编码
+ ///
+ [SugarColumn(ColumnName = "routingCode", Length = 50)]
+ public string RoutingCode { get; set; }
+
+ ///
+ /// 工序号
+ ///
+ [SugarColumn(ColumnName = "operationCode", Length = 50)]
+ public string OperationCode { get; set; }
+
+ ///
+ /// 流程code
+ ///
+ [SugarColumn(ColumnName = "flowCode", Length = 50)]
+ public string FlowCode { get; set; }
+
+ ///
+ /// 产线code
+ ///
+ [SugarColumn(ColumnName = "productlinebodyCode", Length = 50)]
+ public string ProductlinebodyCode { get; set; }
+
+ ///
+ /// 工站code
+ ///
+ [SugarColumn(ColumnName = "workstationCode", Length = 50)]
+ public string WorkstationCode { get; set; }
+
+ ///
+ /// 参数名称,如:温度、压力、时间
+ ///
+ [SugarColumn(ColumnName = "parameter_code")]
+ public string ParameterCode { get; set; }
+
+ ///
+ /// 显示名称(用于UI展示,可和name一样)
+ ///
+ [SugarColumn(ColumnName = "parameter_name", Length = 100)]
+ public string ParameterName { get; set; }
+
+ ///
+ /// plc点位
+ ///
+ [SugarColumn(ColumnName = "plc_point", Length = 50)]
+ public string PlcPoint { get; set; }
+
+ ///
+ /// 参数描述,如:模具温度,用于热压工序
+ ///
+ [SugarColumn(ColumnName = "description", ColumnDataType = "text")]
+ public string Description { get; set; }
+
+ ///
+ /// 数据类型:FLOAT, INT, STRING, BOOL, AI(模拟量输入)等
+ ///
+ [SugarColumn(ColumnName = "data_type", Length = 50, IsNullable = false)]
+ public string DataType { get; set; } = "FLOAT";
+
+ ///
+ /// 单位,如:℃、MPa、秒、mm
+ ///
+ [SugarColumn(ColumnName = "unit", Length = 20)]
+ public string Unit { get; set; }
+
+ ///
+ /// 标准/目标值(如目标温度 200.0 ℃)
+ ///
+ [SugarColumn(ColumnName = "standard_value" )]
+ public decimal? StandardValue { get; set; }
+
+ ///
+ /// 最小允许值(用于报警/校验)
+ ///
+ [SugarColumn(ColumnName = "min_value")]
+ public decimal? MinValue { get; set; }
+
+ ///
+ /// 最大允许值(用于报警/校验)
+ ///
+ [SugarColumn(ColumnName = "max_value")]
+ public decimal? MaxValue { get; set; }
+
+ ///
+ /// 最小允许值(用于报警/校验)
+ ///
+ [SugarColumn(ColumnName = "result")]
+ public int? Result { get; set; }
+
+
+
+ ///
+ /// 创建人
+ ///
+ [SugarColumn(ColumnName = "createdby", Length = 50)]
+ public string Createdby { get; set; }
+
+ ///
+ /// 更新人
+ ///
+ [SugarColumn(ColumnName = "updatedby", Length = 50)]
+ public string Updatedby { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "created_time")]
+ public DateTime? CreatedTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "updated_time")]
+ public DateTime? UpdatedTime { get; set; }
+ }
+
+}
diff --git a/MDM/Models/Product/ProductScanRecord.cs b/MDM/Models/Product/ProductScanRecord.cs
new file mode 100644
index 0000000..bd975ce
--- /dev/null
+++ b/MDM/Models/Product/ProductScanRecord.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MDM.Models.Session
+{
+ [SugarTable("product_scan_records")]
+ public class ProductScanRecords
+ {
+ ///
+ /// 主键ID
+ ///
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = false)]
+ public long Id { get; set; }
+
+ ///
+ /// 工单号
+ ///
+ [SugarColumn(ColumnName = "workorder", Length = 50)]
+ public string Workorder { get; set; }
+
+ ///
+ /// 过程码
+ ///
+ [SugarColumn(ColumnName = "product_SN", Length = 50)]
+ public string ProductSN { get; set; }
+
+ ///
+ /// 工艺路线code
+ ///
+ [SugarColumn(ColumnName = "routingcode", Length = 50)]
+ public string Routingcode { get; set; }
+
+ ///
+ /// 工序code
+ ///
+ [SugarColumn(ColumnName = "operationCode", Length = 50)]
+ public string OperationCode { get; set; }
+
+ ///
+ /// 流程code
+ ///
+ [SugarColumn(ColumnName = "flowCode", Length = 50)]
+ public string FlowCode { get; set; }
+
+ ///
+ /// 实际扫到码
+ ///
+ [SugarColumn(ColumnName = "actual_scan_code", Length = 100)]
+ public string ActualScanCode { get; set; }
+
+ ///
+ /// 期望扫到的码
+ ///
+ [SugarColumn(ColumnName = "expected_code", Length = 100)]
+ public string ExpectedCode { get; set; }
+
+ ///
+ /// 防错规则
+ ///
+ [SugarColumn(ColumnName = "error_proof_rule_code", Length = 50)]
+ public string ErrorProofRuleCode { get; set; }
+
+ ///
+ /// 扫码结果(OK,NG)
+ ///
+ [SugarColumn(ColumnName = "scan_result")]
+ public ScanResultEnum? ScanResult { get; set; }
+
+ ///
+ /// 错误码代号
+ ///
+ [SugarColumn(ColumnName = "error_code", Length = 50)]
+ public string ErrorCode { get; set; }
+
+ ///
+ /// 错误信息
+ ///
+ [SugarColumn(ColumnName = "error_message", Length = 255)]
+ public string ErrorMessage { get; set; }
+
+ ///
+ /// 扫码时间
+ ///
+ [SugarColumn(ColumnName = "scan_time")]
+ public DateTime? ScanTime { get; set; }
+ }
+
+ ///
+ /// 扫码结果枚举
+ ///
+ public enum ScanResultEnum
+ {
+ OK = 1,
+ NG = 0
+ }
+}
diff --git a/MDM/Models/Session/ProductRunning.cs b/MDM/Models/Session/ProductRunning.cs
deleted file mode 100644
index 5daad0b..0000000
--- a/MDM/Models/Session/ProductRunning.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MDM.Models.Session
-{
-
-}
diff --git a/MDM/Models/Session/ProductScanRecord.cs b/MDM/Models/Session/ProductScanRecord.cs
deleted file mode 100644
index 39e3b8c..0000000
--- a/MDM/Models/Session/ProductScanRecord.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MDM.Models.Session
-{
- [SugarTable("product_scan_record")]
- public class ProductScanRecord
- {
- ///
- /// 主键ID
- ///
- [SugarColumn(IsPrimaryKey = true, IsIdentity = false)] // bigint类型,非自增
- public long Id { get; set; }
-
- ///
- /// 实际扫到码
- ///
- [SugarColumn(ColumnName = "actual_scan_code", Length = 100)]
- public string ActualScanCode { get; set; }
-
- ///
- /// 期望扫到的码
- ///
- [SugarColumn(ColumnName = "expected_code", Length = 100)]
- public string ExpectedCode { get; set; }
-
- ///
- /// 扫码结果 (建议:0-失败,1-成功)
- ///
- [SugarColumn(ColumnName = "scan_result")]
- public int? ScanResult { get; set; }
-
- ///
- /// 错误码代号
- ///
- [SugarColumn(ColumnName = "error_code", Length = 50)]
- public string ErrorCode { get; set; }
-
- ///
- /// 错误信息
- ///
- [SugarColumn(ColumnName = "error_message", Length = 255)]
- public string ErrorMessage { get; set; }
-
- ///
- /// 扫码时间
- ///
- [SugarColumn(ColumnName = "scan_time")]
- public DateTime? ScanTime { get; set; }
- }
-}
diff --git a/MDM/Services/Flows/CommonFlowService.cs b/MDM/Services/Flows/CommonFlowService.cs
index 1895ae6..5580f23 100644
--- a/MDM/Services/Flows/CommonFlowService.cs
+++ b/MDM/Services/Flows/CommonFlowService.cs
@@ -1,4 +1,5 @@
+using DOAN.Model.MES.product;
using DOAN.Model.MES.recipe;
using DOAN.Model.MES.recipe.Dto;
using Infrastructure.Attribute;
@@ -10,6 +11,7 @@ using MDM.Models.Process;
using MDM.Models.Session;
using MDM.Service;
using NPOI.SS.Formula.Functions;
+using System.Text.Json;
namespace MDM.Services.Flows
@@ -190,19 +192,13 @@ namespace MDM.Services.Flows
//TODO: 下发中间操作流程规则
-
-
-
//TODO: 扫码流程 类型
[RIZOFlow(FlowType = "Scanningcode_flow")]
- public List ScanningcodeFlow(string RoutingCode, string operationCode, string FlowCode)
+ public string ScanningcodeFlow(string RoutingCode, string operationCode, string FlowCode)
{
-
-
//获取这个工序d的扫码规则
- List ScanningFlowList = Context.Queryable().LeftJoin((f, m) => f.FkRoutingCode == m.FkRoutingCode && f.FkOperationCode == m.FkOperationCode && f.FlowCode == m.FkFlowCode)
-
- .Where((f, m) => f.FkRoutingCode == RoutingCode && f.FkOperationCode == operationCode && f.FlowTypeCode == "Scanningcode_flow"&&f.FlowCode== FlowCode)
+ List flowRuleList = Context.Queryable().LeftJoin((f, m) => f.FkRoutingCode == m.FkRoutingCode && f.FkOperationCode == m.FkOperationCode && f.FlowCode == m.FkFlowCode)
+ .Where((f, m) => f.FkRoutingCode == RoutingCode && f.FkOperationCode == operationCode && f.FlowTypeCode == "Scanningcode_flow" && f.FlowCode == FlowCode)
.Select((f, m) => new ProcessOperationFlowMaterialParamter()
{
id = f.id,
@@ -212,24 +208,35 @@ namespace MDM.Services.Flows
MaterialCode = m.MaterialCode,
MaterialName = m.MaterialName,
UseErrorProofRuleCode = m.UseErrorProofRuleCode,
-
+
})
.ToList();
- return ScanningFlowList;
+ var data = new
+ {
+ flowbase = new
+ {
+ routingCode = RoutingCode,
+ operationCode = operationCode,
+ flowCode = FlowCode
+ },
+ flowRuleList
+
+ };
+ return System.Text.Json.JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
}
//TODO: 数采流程 类型 (工位流程)
[RIZOFlow(FlowType = "data_collect_flow")]
- public List DataCollectFlow( string RoutingCode, string operationCode, string FlowCode, string ProductlinebodyCode, string WorkstationCode)
+ public string DataCollectFlow(string RoutingCode, string operationCode, string FlowCode, string ProductlinebodyCode, string WorkstationCode)
{
//获取这个工序d的扫码规则
- List DataCollectFlowList = Context.Queryable().LeftJoin
+ List flowRuleList = Context.Queryable().LeftJoin
((f, m) => f.FkRoutingCode == m.FkRoutingCode && f.FkOperationCode == m.FkOperationCode && f.FlowCode == m.FkFlowCode)
.Where((f, m) => f.FkRoutingCode == RoutingCode && f.FkOperationCode == operationCode && f.FlowTypeCode == "Scanningcode_flow")
- .Where((f,m)=>m.FkProductlinebodyCode== ProductlinebodyCode&&m.FkWorkstationCode== WorkstationCode&&m.FkFlowCode==FlowCode)
+ .Where((f, m) => m.FkProductlinebodyCode == ProductlinebodyCode && m.FkWorkstationCode == WorkstationCode && m.FkFlowCode == FlowCode)
.Select((f, m) => new ProcessOperationWorkstationFlowCollectParameter()
- {
+ {
FkRoutingCode = f.FkRoutingCode,
FkOperationCode = f.FkOperationCode,
FkProductlinebodyCode = m.FkProductlinebodyCode,
@@ -250,23 +257,34 @@ namespace MDM.Services.Flows
DefaultValue = m.DefaultValue,
IsRequired = m.IsRequired,
Sequence = m.Sequence,
-
-
-
})
.ToList();
- return DataCollectFlowList;
+ var data = new
+ {
+ flowbase = new
+ {
+ routingCode = RoutingCode,
+ operationCode = operationCode,
+ productlinebodyCode = ProductlinebodyCode,
+ workstationCode = WorkstationCode,
+ flowCode = FlowCode
+ },
+ flowRuleList
+
+ };
+ return System.Text.Json.JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
+
}
//TODO: 配方流程 类型
[RIZOFlow(FlowType = "recipe_distribute_flow")]
- public List RecipeDistributeFlow(string RoutingCode, string operationCode, string FlowCode)
+ public string RecipeDistributeFlow(string RoutingCode, string operationCode, string FlowCode)
{
- return Context.Queryable()
+ var flowRuleList = Context.Queryable()
.LeftJoin((refpr, ver) => refpr.RecipeCode == ver.RecipeCode)
.LeftJoin((refpr, ver, param) => ver.RecipeCode == param.RecipeCode && ver.Version == param.Version)
- .Where((refpr, ver, param) => refpr.FkFlowCode== FlowCode&&refpr.FkRoutingCode == RoutingCode && refpr.FkOperationCode == operationCode)
+ .Where((refpr, ver, param) => refpr.FkFlowCode == FlowCode && refpr.FkRoutingCode == RoutingCode && refpr.FkOperationCode == operationCode)
.Select((refpr, ver, param) => new PfRecipeParametersDto
{
Id = param.Id,
@@ -279,7 +297,18 @@ namespace MDM.Services.Flows
StandardValue = param.StandardValue,
Remark = param.Remark
}).ToList();
-
+ var data = new
+ {
+ flowbase = new
+ {
+ routingCode = RoutingCode,
+ operationCode = operationCode,
+ flowCode = FlowCode
+ },
+ flowRuleList
+
+ };
+ return System.Text.Json.JsonSerializer.Serialize(data, new JsonSerializerOptions { WriteIndented = true });
}
@@ -289,69 +318,112 @@ namespace MDM.Services.Flows
///
///
///
- //[RIZOFlow(FlowType = "common_outbound_flow")]
- //public OutStationApplyResult CommonOutboundStationFlow(string operationCode, string processCode)
- //{
- // // 参数验证
- // if (string.IsNullOrWhiteSpace(operationCode) || string.IsNullOrWhiteSpace(processCode))
- // {
- // return OutStationApplyResult.InvalidParameters;
- // }
- // // 获取产品是正常件,完成件,返工件
- // var product = GetProductBySn(processCode);
- // if (product == null)
- // {
- // // 产品未开工,不得出站
- // return OutStationApplyResult.ProductNotStartWork;
- // }
- // if (product.ProductStatus == 2)
- // {
- // // 产品已经生产完成,不得出站
- // return OutStationApplyResult.ProductCompleted;
- // }
- // //如果正常件
- // if (product.ProductStatus == 2)
- // {
- // // 此工序未入站,禁止出站
+ [RIZOFlow(FlowType = "common_outbound_flow")]
+ public OutStationApplyResult CommonOutboundStationFlow(string operationCode, string processCode)
+ {
+ // 参数验证
+ if (string.IsNullOrWhiteSpace(operationCode) || string.IsNullOrWhiteSpace(processCode))
+ {
+ return OutStationApplyResult.InvalidParameters;
+ }
- // // 此工序未完成中间流程,禁止出站
+ // 1.获取产品是正常件,完成件,返工件
+ ProductLifecycle productInfo = Context.Queryable()
+ .Where(p => p.ProductSN == processCode)
+ .First();
+ if (productInfo == null)
+ {
+ // 产品未开工,不得出站
+ RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, OutStationApplyResult.ProductNotStartWork.ToString(), "产品未开工,不得入站");
+ return OutStationApplyResult.ProductNotStartWork;
+ }
+ if (productInfo.ProductStatus == 2)
+ {
+ // 产品已经生产完成,不得出站
+ RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, OutStationApplyResult.ProductCompleted.ToString(), "产品已经生产完成,不得入站");
+ return OutStationApplyResult.ProductCompleted;
+ }
+ if (productInfo.ProductStatus == 3)
+ {
+ // 返工件允许出站
+ RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.SUCCESS, OutStationApplyResult.Success.ToString(), string.Empty);
+ return OutStationApplyResult.Success;
+ }
+ //检查扫码流程是否已经完成
+ var ScanResults = Context.Queryable()
+ .LeftJoin((f, r) => f.FkFlowCode == r.FlowCode && f.FkRoutingCode == r.Routingcode && f.FkOperationCode == r.OperationCode)
+ .Where((f, r) => f.FkRoutingCode == productInfo.RoutingCode)
+ .Where((f, r) => f.FkOperationCode == operationCode)
+ .Select((f, r) => new { f.FkFlowCode, r.ScanResult })
+ .ToList();
- // //插入出站记录
- // ProductPassstationRecord passstationRecord = new ProductPassstationRecord
- // {
- // Workorder = product.Workorder,
- // Routingcode = product.RoutingCode,
- // ProductSN = product.ProductSN,
- // OperationCode = operationCode,
- // ProuductStatus = 3, // 出站状态
- // OutStationTime = DateTime.Now,
- // CreatedTime = DateTime.Now
- // };
- // Context.Insertable(passstationRecord).ExecuteCommand();
- // return OutStationApplyResult.Success;
- // }
- // //如果,返工件
- // if (product.ProductStatus == 3)
- // {
- // //插入出站记录
- // ProductPassstationRecord passstationRecord = new ProductPassstationRecord
- // {
- // Workorder = product.Workorder,
- // Routingcode = product.RoutingCode,
- // ProductSN = product.ProductSN,
- // OperationCode = operationCode,
- // ProuductStatus = 4, // 出站状态
- // OutStationTime = DateTime.Now,
- // CreatedTime = DateTime.Now
- // };
- // Context.Insertable(passstationRecord).ExecuteCommand();
- // return OutStationApplyResult.Success;
- // }
+ bool isFinish= ScanResults.Where(it => it.ScanResult == ScanResultEnum.NG||it.ScanResult==null).Any();
+
+ if (isFinish)
+ {
+ RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, OutStationApplyResult.ScanFlowNotCompleted.ToString(), "产品未开工,不得入站");
+ return OutStationApplyResult.ScanFlowNotCompleted;
+ }
+
+ //检查数采流程是否已经完成
+ // 获取产线
+ string LineCode = Context.Queryable().Where(it => it.Workorder == productInfo.Workorder).Select(it=>it.LineCode).First();
+
+ var DataCollectList = Context.Queryable()
+ .LeftJoin((f, p) => f.FkFlowCode == p.FlowCode && f.FkRoutingCode == p.RoutingCode && f.FkOperationCode == p.OperationCode && f.ParameterCode == p.ParameterCode)
+ .Where((f, p) => f.FkRoutingCode == productInfo.RoutingCode&&f.FkOperationCode== operationCode&&f.FkProductlinebodyCode==LineCode)
+ .Select((f, r) => new { f.FkFlowCode, r.Result })
+ .ToList();
+
+ bool isFinish_ = DataCollectList.Where(it => it.Result == 0 || it.Result == null).Any();
+ if (isFinish_)
+ {
+ RecordOutTrace(productInfo, operationCode, 1, ApplyStatusEnum.REJECTED, OutStationApplyResult.ParmetersCollectNotCompleted.ToString(), "产品未开工,不得入站");
+ return OutStationApplyResult.ParmetersCollectNotCompleted;
+ }
+ //准许出站
+ return OutStationApplyResult.Success;
+ }
+
+ private void RecordOutTrace(ProductLifecycle product, string operationCode, int ProductionLifeStage, ApplyStatusEnum isPass, string rejectReasonCode, string rejectReasonDesc)
+ {
+ // 更新产品状态
+ if (product != null)
+ {
+ Context.Updateable()
+ .SetColumns(it => new ProductLifecycle
+ {
+ ProductStatus = 1, // 设置为生产中状态
+ UpdatedTime = DateTime.Now
+ })
+ .Where(it => it.ProductSN == product.ProductSN)
+ .ExecuteCommand();
+ }
+
+ // 构建入站记录
+ var passstationRecord = new ProductPassstationRecord
+ {
+ Workorder = product?.Workorder,
+ Routingcode = product?.RoutingCode,
+ ProductSN = product?.ProductSN ?? string.Empty,
+ OperationCode = operationCode,
+ ProductionLifeStage = ProductionLifeStage, // 生产中
+ ApplyType = ApplyTypeEnum.OUT,
+ ApplyStatus = isPass,
+ RejectReasonCode = rejectReasonCode,
+ RejectReasonDesc = rejectReasonDesc,
+ InStationTime = DateTime.Now,
+ CreatedTime = DateTime.Now
+ };
+
+ Context.Insertable(passstationRecord).ExecuteCommand();
- // return OutStationApplyResult.UnknownStatus;
- //}
+
+ }
+
+
}
}
diff --git a/MDM/Services/Session/IService/ISessionManagerService.cs b/MDM/Services/Session/IService/ISessionManagerService.cs
index 4ae1620..6ae3919 100644
--- a/MDM/Services/Session/IService/ISessionManagerService.cs
+++ b/MDM/Services/Session/IService/ISessionManagerService.cs
@@ -15,7 +15,7 @@ namespace MDM.Services.Session.IService
InStationApplyResult InStationApply(string OperationCode, string ProcessCode);
- Dictionary> MiddleProcessFlowDistribution(string operationCode, string ProcessCode);
+ List MiddleProcessFlowDistribution(string operationCode, string ProcessCode);
OutStationApplyResult OutStationApply(string OperationCode, string ProcessCode);
diff --git a/MDM/Services/Session/SessionManagerService.cs b/MDM/Services/Session/SessionManagerService.cs
index 11a65b7..69e3cba 100644
--- a/MDM/Services/Session/SessionManagerService.cs
+++ b/MDM/Services/Session/SessionManagerService.cs
@@ -135,19 +135,19 @@ namespace MDM.Services.Session
///
///
///
- public Dictionary> MiddleProcessFlowDistribution(string operationCode, string ProcessCode)
+ public List MiddleProcessFlowDistribution(string operationCode, string ProcessCode)
{
var lifecycle = Context.Queryable()
.Where(it => it.ProductSN == ProcessCode)
.First();
- ProWorkorder proWorkorder= Context.Queryable().Where(it=>it.Workorder== lifecycle.Workorder).First();
- ProcessOperationWorkstationMapping processOperationWorkstationMapping= Context.Queryable().Where(it => it.FkRoutingCode == lifecycle.RoutingCode && it.FkOperationCode == operationCode && it.FkProductlinebodyCode == proWorkorder.LineCode).First();
+ ProWorkorder proWorkorder = Context.Queryable().Where(it => it.Workorder == lifecycle.Workorder).First();
+ ProcessOperationWorkstationMapping processOperationWorkstationMapping = Context.Queryable().Where(it => it.FkRoutingCode == lifecycle.RoutingCode && it.FkOperationCode == operationCode && it.FkProductlinebodyCode == proWorkorder.LineCode).First();
- Dictionary> keyValuePairs= new Dictionary>();
+ List resultList = new List();
//TODO 获取这个工序的中间操作流程
- List operationFlows= Context.Queryable().Where(it => !it.FlowTypeCode.Contains("bound_flow")).ToList();
+ List operationFlows = Context.Queryable().Where(it => !it.FlowTypeCode.Contains("bound_flow")).ToList();
- if(operationFlows!=null&& operationFlows.Count()>0)
+ if (operationFlows != null && operationFlows.Count() > 0)
{
// 已知程序集和类名
string assemblyName = "MDM.Services.Flows";
@@ -174,46 +174,46 @@ namespace MDM.Services.Session
// 获取方法的参数信息
var parameters = method.GetParameters();
//工序流程
- if(parameters.Length==3)
+ if (parameters.Length == 3)
{
var result = method.Invoke(instance, new object[] { lifecycle.RoutingCode, operationCode, rizoFlow.FlowCode });
- if(result is List