using System.Dynamic; using JNPF.Common.Core.Manager; using JNPF.Common.Dtos.Message; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Security; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.FriendlyException; using JNPF.Logging; using JNPF.Message.Entitys.Entity; using JNPF.Message.Service; using JNPF.Systems.Entitys.Permission; using JNPF.Systems.Entitys.System; using JNPF.Systems.Interfaces.System; using JNPF.TaskScheduler; using JNPF.TaskScheduler.Entitys.Dto.TaskScheduler; using JNPF.TaskScheduler.Entitys.Model; using Mapster; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using SqlSugar; using Tnb.BasicData; using Tnb.BasicData.Entities; using Tnb.EquipMgr.Entities; using Tnb.EquipMgr.Entities.Dto; using Tnb.EquipMgr.Interfaces; using Tnb.ProductionMgr.Entities; using Tnb.ProductionMgr.Entities.Dto.PrdManage; using Tnb.ProductionMgr.Interfaces; using MessageTemplateEntity = JNPF.Message.Entitys.Entity.MessageTemplateEntity; namespace Tnb.ProductionMgr { /// /// 业务实现:生产管理 /// [ApiDescriptionSettings(Tag = ModuleConst.Tag, Area = ModuleConst.Area, Order = 700)] [Route("api/[area]/[controller]/[action]")] public class PrdCancelCloseDownService : IPrdCancelCloseDownService, IDynamicApiController, ITransient { private readonly ISqlSugarClient _db; private readonly IToolMoldMaintainTaskService _maintainTaskService; private readonly IToolMoldsService _moldService; private readonly IPrdMoTaskService _prdMoTaskService; private readonly IUserManager _userManager; private readonly IBillRullService _billRullService; private readonly TimeTaskService _timeTaskService; private readonly SendMessageService _sendMessageService; private static readonly Dictionary _dicWorkStationAndShopRelacion = new(); private static Dictionary _dicWorkShop = new(); private const string PUSHRULEID = "27121606262805";//异常停机的推送规则id public PrdCancelCloseDownService( ISqlSugarRepository repository, IPrdMoTaskService prdMoTaskService, IToolMoldsService moldsService, IToolMoldMaintainTaskService maintainTaskService, IBillRullService billRullService, TimeTaskService timeTaskService, SendMessageService sendMessageService, IUserManager userManager ) { _prdMoTaskService = prdMoTaskService; _maintainTaskService = maintainTaskService; _moldService = moldsService; _userManager = userManager; _billRullService = billRullService; _timeTaskService = timeTaskService; _sendMessageService = sendMessageService; _db = repository.AsSugarClient(); } /// /// 根据设备ID获取异常关机信息 /// /// /// [HttpGet] public async Task GetClosedownEndList([FromRoute] string eqpId) { if (_dicWorkShop.Count < 1) { List orgs = await _db.Queryable().Where(it => it.Category == "workstation").ToListAsync(); if (orgs?.Count > 0) { List shopIds = orgs.Select(x => { string shopId = ""; string[] orgTree = x.OrganizeIdTree.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (orgTree?.Length > 1) { shopId = orgTree[^2]; _dicWorkStationAndShopRelacion[x.EnCode] = shopId; } return shopId; }).Where(x => !x.IsNullOrEmpty()).ToList(); if (shopIds?.Count > 0) { _dicWorkShop = await _db.Queryable().Where(it => it.Category == "department" && shopIds.Contains(it.Id)).ToDictionaryAsync(x => x.Id, x => x.FullName); } } } List result = new(); PrdCancelClosedown closeDown = await _db.Queryable().FirstAsync(it => it.eqp_id == eqpId); if (closeDown != null) { if (!closeDown.reason.IsNullOrEmpty()) { EqpEquipment? eqp = await _db.Queryable().FirstAsync(it => it.id == eqpId); EqpEquipType? eqpTypeInfo = null; if (eqp != null) { eqpTypeInfo = await _db.Queryable().FirstAsync(it => it.id == eqp.equip_type_id); } string[] reasonArr = closeDown.reason.Split(","); foreach (string reason in reasonArr) { ClosedownEndListOutput ot = new(); if (eqp != null) { if (_dicWorkStationAndShopRelacion.ContainsKey(eqp.station_code)) { string? shopId = _dicWorkStationAndShopRelacion[eqp.station_code].ToString(); ot.workshop_name = _dicWorkShop.ContainsKey(shopId) ? _dicWorkShop[shopId].ToString()! : ""; } } ot.reason = reason; ot.eqp_code = eqp?.code; ot.eqp_type_code = eqpTypeInfo?.code; ot.operator_name = _userManager.RealName; ot.remark = closeDown.remark; ot.closeddown_start_time = closeDown.closedown_start_time; result.Add(ot); } } } if (result.Count < 1) { ClosedownEndListOutput output = new(); result.Add(output); } return result; } /// /// 获取停机历史记录 /// /// /// [HttpGet] public async Task GetClosedownHistory([FromQuery] ClosedownHistoryQuery input) { List pagedList = await _db.Queryable() .WhereIF(!string.IsNullOrEmpty(input.eqpName), it => it.eqp_name.Contains(input.eqpName)) .WhereIF(input.beginTime.HasValue, it => it.closedown_start_time.Value >= input.beginTime) .WhereIF(input.endTime.HasValue, it => it.closedown_start_time.Value <= input.endTime) .Select(it => new ClosedownHistoryOutput { eqp_code = it.eqp_code, eqp_name = it.eqp_name, closedown_start_time = it.closedown_start_time.HasValue ? it.closedown_start_time.Value.ToString(DbTimeFormat.SS) : null, closedown_end_time = it.closedown_end_time.HasValue ? it.closedown_end_time.Value.ToString(DbTimeFormat.SS) : null, closedown_time = it.closedown_time, }) .ToListAsync(); return pagedList; } /// /// 根据设备id获取生产任务单信息,模具信息 /// /// 设备Id /// /// returns: ///
{ ///
mo_task_code:任务单编号 ///
mold_code:模具编号 ///
mold_name:模具名称 ///
} ///
[HttpGet] public async Task GetInfoFromEqpId([FromRoute] string eqpId) { dynamic info = new ExpandoObject(); PrdMoTask moTask = await _db.Queryable().Where(it => it.mo_task_status == DictConst.InProgressEnCode).FirstAsync(it => it.eqp_id == eqpId); if (moTask != null) { ToolMolds? mold = await _db.Queryable().FirstAsync(it => it.id == moTask.mo_id); info.mo_task_code = moTask.mo_task_code; info.mold_code = mold?.mold_code; info.mold_name = mold?.mold_name; } return info; } /// /// 异常停机-开始 /// /// /// [HttpPost] public async Task CloseDownStart(CloseDownStartInput input) { if (input == null) { throw new ArgumentNullException("input"); } if (input.eqp_id.IsNullOrWhiteSpace()) { throw new ArgumentException($"parameter {nameof(input.eqp_id)} not be null or empty"); } EqpEquipment? eqp = await _db.Queryable().FirstAsync(it => it.id == input.eqp_id); PrdCancelClosedown cancelCloseDown = input.Adapt(); EqpRepairApply? eqpRepairApply = null; BasPushRuleD basPushRuleD = await _db.Queryable().FirstAsync(x => x.push_rule_id == PUSHRULEID && x.ordinal == 1); try { DbResult result = await _db.Ado.UseTranAsync(async () => { List? moTaskList = await _prdMoTaskService.GetListByEqpId(input.eqp_id); if (moTaskList?.Count > 1) { throw new AppFriendlyException($"设备{input.eqp_id},目前有两条进行中的生产任务", 500); } if (moTaskList?.Count > 0) { cancelCloseDown.id = SnowflakeIdHelper.NextId(); cancelCloseDown.eqp_id = input.eqp_id; cancelCloseDown.create_id = _userManager.UserId; cancelCloseDown.create_time = DateTime.Now; cancelCloseDown.closedown_start_time = DateTime.Now; _ = await _db.Insertable(cancelCloseDown).ExecuteCommandAsync(); PrdCancelClosedownRecord record = cancelCloseDown.Adapt(); record.eqp_code = eqp?.code; record.eqp_name = eqp?.name; _ = await _db.Insertable(record).ExecuteCommandAsync(); string? moldId = moTaskList.First().mold_id; if (!moldId.IsNullOrEmpty()) { ToolMolds mold = await _moldService.GetListById(moldId); ToolMoldMaintainTask maintaindTask = new() { mold_id = moldId, code = mold?.mold_code ?? "", create_id = _userManager.UserId, status = DictConst.UnMaintainStatusCode, create_time = DateTime.Now }; await _maintainTaskService.Create(maintaindTask); } string reason = ""; if (!string.IsNullOrEmpty(input.reason)) { List prdCancelClosedownReasons = await _db.Queryable().ToListAsync(); string[] reasonArr = input.reason.Split(","); List reasonList = prdCancelClosedownReasons.Where(x => reasonArr.Contains(x.id)).Select(x => x.reason).ToList(); reason = string.Join(',', reasonList); } string code = await _billRullService.GetBillNumber("EqpRepair"); eqpRepairApply = new EqpRepairApply() { code = code, name = eqp.name + "停机", equip_id = input.eqp_id, status = Tnb.EquipMgr.RepairApplyStatus.TOBEEXECUTED, description = reason, create_id = _userManager.UserId, create_time = DateTime.Now, remark = input.remark, }; _ = await _db.Insertable(eqpRepairApply).ExecuteCommandAsync(); if (!string.IsNullOrEmpty(eqp.responsibler_id)) { List list = await _sendMessageService.SendTest(basPushRuleD.send_config_id); List toUsers = JsonConvert.DeserializeObject>(eqp.responsibler_id); foreach (MessageSendModel item in list) { foreach (MessageSendParam param in item.paramJson) { if (param.field == "equip_code") { param.value = eqp.code; } } item.toUser = toUsers; } foreach (MessageSendModel item in list) { _ = await _sendMessageService.SendMessage(item, new Dictionary()); } } } else { throw Oops.Oh(ErrorCode.COM1001); } }); if (result.IsSuccess) { BasPushRuleH basPushRuleH = await _db.Queryable().SingleAsync(x => x.id == PUSHRULEID); if (basPushRuleH?.enabled == 1) { string sendConfigId = basPushRuleD?.send_config_id ?? ""; List sendModels = await GetSendParamJson(sendConfigId); if (sendModels != null && sendModels.Count > 0) { DateTime executeTime = DateTime.Now.AddMinutes(basPushRuleD.interval); // string cron = $"0 {executeTime.Minute} {executeTime.Hour} {executeTime.Day} {executeTime.Month} ? {executeTime.Year}"; string cron = $"0 {executeTime.Minute} {executeTime.Hour} {executeTime.Day} {executeTime.Month} ?"; ContentModel comtentModel = new() { // comtentModel.cron = (2 * 60).ToString(); cron = cron, interfaceId = "", interfaceName = "", parameter = new List(), localHostTaskId = "PushMsgTimeWorker/PushMsg", startTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(), // comtentModel.endTime = DateTimeOffset.Now.AddSeconds(3).ToUnixTimeMilliseconds().ToString(); TenantId = _userManager?.TenantId, TenantDbName = _userManager?.TenantDbName, ConnectionConfig = _userManager?.ConnectionConfig, Token = _userManager?.ToKen }; foreach (MessageSendModel item in sendModels) { foreach (MessageSendParam param in item.paramJson) { if (param.field == "equip_code") { param.value = eqp?.code; } } } TimeTaskCrInput timeTaskCrInput = new() { enCode = DateTime.Now.ToString("yyyyMMddHHmmss"), fullName = "临时推送消息" + DateTime.Now.ToString("yyyyMMddHHmmss"), executeType = "3", executeContent = comtentModel.ToJsonString(), description = JsonConvert.SerializeObject(sendModels[0].paramJson), sortCode = 9999, enabledMark = 1, }; await _timeTaskService.Create(timeTaskCrInput, false); TimeTaskEntity timeTaskEntity = await _db.Queryable().Where(x => x.EnCode == timeTaskCrInput.enCode).FirstAsync(); BasPushRuleLog basPushRuleLog = new() { push_rule_id = PUSHRULEID, timetask_id = timeTaskEntity?.Id, biz_id = eqpRepairApply.id, ordinal = 1, is_push = 1, }; _ = await _db.Insertable(basPushRuleLog).ExecuteCommandAsync(); } } } } catch (Exception ex) { Log.Error("停机开始失败", ex); // await _db.Ado.RollbackTranAsync(); throw; } } /// /// 停机结束 /// /// /// [HttpPost] public async Task CloseDownEnd(CloseDownStartInput input) { if (input == null) { throw new ArgumentNullException("input"); } if (input.eqp_id.IsNullOrWhiteSpace()) { throw new ArgumentException($"parameter {nameof(input.eqp_id)} not be null or empty"); } try { await _db.Ado.BeginTranAsync(); PrdCancelClosedown closeDown = await _db.Queryable().Where(it => it.eqp_id == input.eqp_id).OrderByDescending(it => it.closedown_start_time).FirstAsync(); if (closeDown != null) { closeDown.closedown_end_time = DateTime.Now; _ = await _db.Updateable(closeDown).ExecuteCommandAsync(); PrdCancelClosedownRecord record = closeDown.Adapt(); //计算停机时间间隔,以小时为单位 if (record.closedown_start_time.HasValue && record.closedown_end_time.HasValue) { double interval = record.closedown_end_time.Value.Subtract(record.closedown_start_time.Value).TotalHours; record.closedown_time = Convert.ToDecimal(interval); } _ = await _db.Updateable(record).ExecuteCommandAsync(); await _db.Ado.CommitTranAsync(); } } catch (Exception ex) { Log.Error("停机结束失败", ex); await _db.Ado.RollbackTranAsync(); throw; } } private async Task> GetSendParamJson(string id) { List list = await _db.Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.TemplateId == b.Id)) .Where((a, b) => a.SendConfigId == id && a.DeleteMark == null && b.DeleteMark == null) .Select((a, b) => new MessageSendModel { accountConfigId = a.AccountConfigId, id = a.Id, messageType = SqlFunc.Subqueryable().Where(u => u.Type == "1" && u.EnCode == a.MessageType).Select(u => u.FullName), msgTemplateName = b.FullName, sendConfigId = a.SendConfigId, templateId = a.TemplateId, }).ToListAsync(); foreach (MessageSendModel? item in list) { // 是否存在参数. bool flag = await _db.Queryable().AnyAsync(x => x.TemplateId == item.templateId && x.DeleteMark == null); item.paramJson = flag ? await _db.Queryable((a, b, c) => new JoinQueryInfos(JoinType.Left, a.TemplateId == b.Id, JoinType.Left, a.TemplateId == c.TemplateId)) .Where((a, b, c) => a.TemplateId == item.templateId && a.DeleteMark == null && b.DeleteMark == null && a.Field == c.Field && a.Field != "@flowLink") .Select((a, b) => new MessageSendParam { field = a.Field, fieldName = a.FieldName, id = a.Id, templateCode = b.TemplateCode, templateId = a.TemplateId, templateName = b.FullName, templateType = b.TemplateType }).ToListAsync() : await _db.Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.TemplateId == b.Id)) .Where((a, b) => a.TemplateId == item.templateId && a.DeleteMark == null && b.DeleteMark == null && a.Field != "@flowLink") .Where((a, b) => b.Title.Contains(a.Field) || b.Content.Contains(a.Field)) .Select((a, b) => new MessageSendParam { field = a.Field, fieldName = a.FieldName, id = a.Id, templateCode = b.TemplateCode, templateId = a.TemplateId, templateName = b.FullName, templateType = b.TemplateType }).ToListAsync(); } return list; } } }