You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Aucma.Scada/Aucma.Scada.Business/OutStoreBusiness.cs

405 lines
15 KiB
C#

using HighWayIot.Config;
using HighWayIot.Log4net;
using HighWayIot.Repository.domain;
using HighWayIot.Repository.service;
using HighWayIot.Repository.service.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Aucma.Scada.Business
{
public class OutStoreBusiness
{
private static readonly Lazy<OutStoreBusiness> lazy = new Lazy<OutStoreBusiness>(() => new OutStoreBusiness());
public static OutStoreBusiness Instance
{
get
{
return lazy.Value;
}
}
private LogHelper logHelper = LogHelper.Instance;
private AppConfig appConfig = AppConfig.Instance;
private IBaseSpaceInfoService _spaceInfoService = new BaseSpaceInfoServiceImpl();
private IRealTaskInfoService _taskInfoService = new RealTaskInfoServiceImpl();
private IBaseBomInfoService _bomInfoService = new BaseBomInfoServiceImpl();
private IBaseSpaceDetailService _spaceDetailService = new BaseSpaceDetailServiceImpl();
private AssemblyPlanBusiness assemblyPlanBusiness = AssemblyPlanBusiness.Instance;
private TaskHandleBusiness taskHandleBusiness = TaskHandleBusiness.Instance;
/// <summary>
/// 初始化出库任务
/// </summary>
/// <param name="message"></param>
public delegate void RefreshOutStoreTask(RealTaskInfo taskInfos);
public event RefreshOutStoreTask RefreshOutStoreTaskEvent;
/// <summary>
/// 扫码信息刷新
/// </summary>
/// <param name="materialCode"></param>
/// <param name="materialName"></param>
/// <param name="spaceName"></param>
/// <param name="storeCode"></param>
public delegate void RefreshScanMateriaCode(string materialCode, string materialName, string spaceName, string storeCode);
public event RefreshScanMateriaCode RefreshScanMateriaCodeEvent;
/// <summary>
/// 日志信息刷新
/// </summary>
/// <param name="message"></param>
public delegate void RefreshLogMessage(string message);
public event RefreshLogMessage RefreshLogMessageEvent;
public OutStoreBusiness()
{
assemblyPlanBusiness.NextPassExecutePlanInfoEvent += PlanHandle;
Task.Run(() =>
{
StartTimerPassDown();
});
}
/// <summary>
/// 接收下达的组装计划根据BOM获取需要出库的箱壳、内胆物料信息
/// </summary>
/// <param name="planInfo"></param>
private void PlanHandle(ExecutePlanInfo planInfo)
{
lock (string.Empty)
{
Task.Run(() =>
{
if (planInfo != null)
{
string taskCode = DateTime.Now.ToString("HH:mm:ss");
var shellBomInfo = _bomInfoService.GetChildenBomInfoByMaterialCode(planInfo.materialCode, appConfig.shellMaterialType);
var linerBomInfo = _bomInfoService.GetChildenBomInfoByMaterialCode(planInfo.materialCode, appConfig.linerMaterialType);
for (int i = 0; i < planInfo.planAmount-planInfo.completeAmount; i++)
{
OutStore(appConfig.shellStoreCode, shellBomInfo, planInfo.executePlanCode, taskCode);
Thread.Sleep(500);
OutStore(appConfig.linerStoreCode, linerBomInfo, planInfo.executePlanCode, taskCode);
Thread.Sleep(500);
}
}
});
}
}
/// <summary>
/// 解析计划创建出库任务
/// </summary>
/// <param name="storeCode"></param>
/// <param name="bomInfo"></param>
/// <param name="planCode"></param>
private void OutStore(string storeCode, BaseBomInfo bomInfo,string planCode,string taskCode)
{
try
{
PrintLogInfoMessage($"收到出库计划,物料码:{bomInfo.materialCode}");
BaseSpaceInfo spaceInfo = _spaceInfoService.OutStoreGetSpaceInfoByMaterialCode(storeCode, bomInfo.materialCode);
if (spaceInfo != null)
{
PrintLogInfoMessage($"匹配货道:{spaceInfo.spaceName}");
// RefreshScanMateriaCodeEvent?.Invoke(materiaclCode, materialType, spaceInfo.spaceName, storeCode); //刷新界面扫码信息
CreateOutStoreTask(spaceInfo, planCode, taskCode); //创建出库任务
}
else
{
//报警停线
}
}
catch (Exception ex)
{
PrintLogErrorMessage("出库业务异常", ex);
}
}
/// <summary>
/// 创建出库任务
/// </summary>
/// <param name="spaceInfo"></param>
private bool CreateOutStoreTask(BaseSpaceInfo spaceInfo, string planCode,string taksCode,int taskModel=0)
{
bool result = false;
try
{
//获取出库的货道明细物料信息
BaseSpaceDetail spaceDetail = GetSpaceDetailFirstOrderByCreatTime(spaceInfo);
if (spaceDetail != null)
{
#region 出库任务赋值
RealTaskInfo realTaskInfo = new RealTaskInfo();
realTaskInfo.planCode = planCode;
realTaskInfo.taskType = 2;
realTaskInfo.taskCode = taksCode;
realTaskInfo.taskModel = taskModel;
realTaskInfo.storeCode = spaceInfo.storeCode;
realTaskInfo.spaceCode = spaceInfo.spaceCode;
realTaskInfo.spaceName = spaceInfo.spaceName;
realTaskInfo.materialType = spaceDetail.materialName;
realTaskInfo.materialCode = spaceDetail.materialCode;
realTaskInfo.planAmount = 1;
realTaskInfo.taskStatus = 1;
realTaskInfo.createTime = DateTime.Now;
#endregion
result = _taskInfoService.AddTaskInfo(realTaskInfo);
if (result)
{
PrintLogInfoMessage("出库任务创建成功");
RefreshOutStoreTaskEvent?.Invoke(realTaskInfo);
UpdateSpaceAndDetial(spaceInfo, spaceDetail);
}
else
{
PrintLogInfoMessage("出库任务创建失败");
}
}
}catch(Exception ex)
{
PrintLogErrorMessage("出库任务创建异常", ex);
}
return result;
}
/// <summary>
/// 根据创建时间获取第一个货道明细
/// </summary>
/// <param name="spaceInfo"></param>
/// <returns></returns>
private BaseSpaceDetail GetSpaceDetailFirstOrderByCreatTime(BaseSpaceInfo spaceInfo)
{
BaseSpaceDetail spaceDetail = null;
try
{
List<BaseSpaceDetail> spaceDetails = _spaceDetailService.GetSpaceDetailsBySpaceCode(spaceInfo.storeCode, spaceInfo.spaceCode);
if (spaceDetails.Count > 0)
{
spaceDetails = spaceDetails.Where(x => x.isFlag != 1).ToList();
if (spaceDetails != null)
{
spaceDetail = spaceDetails.OrderBy(x => x.createTime).First();
}
}
}catch(Exception ex)
{
PrintLogErrorMessage("获取货道明细信息异常", ex);
}
return spaceDetail;
}
/// <summary>
/// 任务创建完成后修改货道信息及货道明细
/// </summary>
/// <param name="spaceInfo"></param>
/// <param name="spaceDetail"></param>
private void UpdateSpaceAndDetial(BaseSpaceInfo spaceInfo,BaseSpaceDetail spaceDetail,int detailIsFlag = 1,bool stockFlag = true)
{
//任务创建完成后修改货道库存、货道明细修改物料标识物料不可用
spaceDetail.isFlag = detailIsFlag;
var result = _spaceDetailService.UpdateSpaceDetail(spaceDetail);
if (stockFlag)
{
spaceInfo.spaceStock = spaceInfo.spaceStock > 0 ? spaceInfo.spaceStock - 1 : 0;
}
else
{
spaceInfo.spaceStock = spaceInfo.spaceStock + 1;
}
_spaceInfoService.UpdateSpaceInfo(spaceInfo);
}
#region 开启定时获取出库任务下发至PLC等待PLC执行反馈完成后再次下发
private System.Timers.Timer timer = new System.Timers.Timer(5000);
private void StartTimerPassDown()
{
try
{
if (!timer.Enabled)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(PassDownTaskInfoByTimer);
timer.AutoReset = true;
timer.Enabled = false;
timer.Start();
PrintLogInfoMessage("StartTimerPassDown(),开启定时获取出库任务进行下发");
}
}
catch (Exception ex)
{
PrintLogErrorMessage("开启定时下发出库任务异常", ex);
}
}
/// <summary>
/// 依次获取任务队列进行下发
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
private void PassDownTaskInfoByTimer(object sender, System.Timers.ElapsedEventArgs e)
{
List<RealTaskInfo> realTasks = new List<RealTaskInfo>();
RealTaskInfo shellTask = _taskInfoService.GetTaskInfoByStoreCode(appConfig.shellStoreCode, 2);
RealTaskInfo linerTaks = _taskInfoService.GetTaskInfoByStoreCode(appConfig.linerStoreCode, 2);
if(shellTask != null && linerTaks != null)
{
if (shellTask.taskStatus != 2 && linerTaks.taskStatus != 2)
{
shellTask.taskStatus = 2;
linerTaks.taskStatus = 2;
realTasks.Add(shellTask);
realTasks.Add(linerTaks);
bool result = _taskInfoService.UpdateRangeTaskInfo(realTasks);
if (result)
{
foreach(var item in realTasks)
{
RefreshScanMateriaCodeEvent?.Invoke(item.materialCode, item.materialType, item.spaceName, item.storeCode);
taskHandleBusiness.SendOutStoreTask(item);
}
if (timer.Enabled)
{
timer.Stop();
timer.Close();
timer.Dispose();
timer = new System.Timers.Timer(5000);
}
}
}
}
}
#endregion
/// <summary>
/// 出库完成
/// </summary>
/// <param name="storeCode"></param>
/// <param name="spaceCode"></param>
/// <param name="materialType"></param>
private void OutStoreFinish(string taskCode)
{
try
{
var taskInfo = _taskInfoService.GetTaskInfoByTaskCode(taskCode);
if (taskInfo != null)
{
var spaceInfo = _spaceInfoService.GetSpaceInfoBySpaceCode(taskInfo.storeCode, taskInfo.spaceCode);
if (spaceInfo != null)
{
//读取PLC获取货道信息存放数量、在途数量
//spaceInfo.materialType = taskInfo.materialType;
_spaceInfoService.UpdateSpaceInfo(spaceInfo);
//读取PLC获取物料类型进行绑定
}
//清除任务信息
_taskInfoService.DeleteTaskInfo(taskCode);
}
}
catch (Exception ex)
{
PrintLogErrorMessage("出库完成逻辑处理异常", ex);
}
}
/// <summary>
/// 获取出库任务
/// </summary>
/// <returns></returns>
public List<RealTaskInfo> GetOutStoreTask()
{
var taskInfos = _taskInfoService.GetTaskInfosByStoreCode(new string[] { appConfig.shellStoreCode, appConfig.linerStoreCode }, appConfig.outstoreTaskType);
return taskInfos;
}
/// <summary>
/// 通过任务编号删除任务
///
/// 任务删除后是否需要还原库存,如果出库完成后减少库存则不需要
///
/// </summary>
/// <param name="taskCode"></param>
/// <returns></returns>
public bool DeleteTaskInfoByTaskCode(string taskCode)
{
return _taskInfoService.DeleteTaskInfo(taskCode);
}
/// <summary>
/// 根据货道手动出一个
/// </summary>
/// <param name="storeCode"></param>
/// <param name="spaceCode"></param>
/// <returns></returns>
public bool OutOnlyOneBySpaceCode(string storeCode,string spaceCode)
{
bool result = false;
try
{
BaseSpaceInfo spaceInfo = _spaceInfoService.GetSpaceInfoBySpaceCode(storeCode, spaceCode);
if(spaceInfo.spaceStock > 0)
{
result = this.CreateOutStoreTask(spaceInfo, System.Guid.NewGuid().ToString("N"), DateTime.Now.ToString("HH:mm:ss"), 1);
}
else
{
PrintLogInfoMessage($"仓库:{storeCode};货道:{spaceCode};出一个失败:库存不足");
}
}catch(Exception ex)
{
logHelper.Error("根据货道出一个异常", ex);
}
return result;
}
/// <summary>
/// 日志输出,界面刷新同时记录文件
/// </summary>
/// <param name="message"></param>
private void PrintLogInfoMessage(string message)
{
RefreshLogMessageEvent?.Invoke(message);
logHelper.Info(message);
}
/// <summary>
/// 异常日志输出
/// </summary>
/// <param name="message"></param>
/// <param name="ex"></param>
private void PrintLogErrorMessage(string message, Exception ex = null)
{
RefreshLogMessageEvent?.Invoke(message);
logHelper.Error(message, ex);
}
}
}