using JNPF.Common.Core.Manager; using JNPF.Common.Security; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.FriendlyException; using JNPF.Logging; using JNPF.Systems.Interfaces.System; using JNPF.VisualDev; using Mapster; using Microsoft.AspNetCore.Mvc; using SqlSugar; using Tnb.BasicData; using Tnb.BasicData.Entitys.Entity; using Tnb.EquipMgr.Entities; using Tnb.ProductionMgr.Entities; using Tnb.ProductionMgr.Entities.Dto; using Tnb.ProductionMgr.Interfaces; namespace Tnb.ProductionMgr { /// /// 生产计划管理 /// [ApiDescriptionSettings(Tag = ModuleConst.Tag, Area = ModuleConst.Area, Order = 700)] [Route("api/[area]/[controller]/[action]")] public class PrdMoService : IOverideVisualDevService, IPrdMoService, IDynamicApiController, ITransient { private readonly ISqlSugarRepository _repository; private readonly IDataBaseManager _dataBaseManager; private readonly IUserManager _userManager; private readonly IDictionaryDataService _dictionaryDataService; public OverideVisualDevFunc OverideFuncs => new OverideVisualDevFunc(); public PrdMoService( ISqlSugarRepository repository, IDataBaseManager dataBaseManager, IUserManager userManager, IDictionaryDataService dictionaryDataService ) { _repository = repository; _dataBaseManager = dataBaseManager; _userManager = userManager; _dictionaryDataService = dictionaryDataService; } #region Get /// /// 根据产品ID获取模具列表 /// /// 产品ID /// /// ///
return results: ///
[ ///
{ ///
mold_code:模具编号 ///
mold_name:模具名称 ///
item_name:产品名称 ///
item_code:产品编号 ///
cavity_qty:模穴数 ///
} ///
] ///
[HttpGet("{itemId}")] public async Task GetMoldListByItemId(string itemId) { var db = _repository.AsSugarClient(); var list = await db.Queryable().InnerJoin((a, b) => a.item_id == b.id) .Where((a, b) => a.item_id == itemId) .Select((a, b) => new MoldListOutput { id = a.id, mold_code = a.mold_code, mold_name = a.mold_name, item_name = b.item_name, cavity_qty = a.cavity_qty, item_code = b.item_code, }) .ToListAsync(); return list; } /// /// 根据模具Id获取设备列表 /// /// /// [HttpGet("{moldId}")] public async Task GetEquipmentListByMoldId(string moldId) { var items = await _repository.AsSugarClient().Queryable() .Where(it => it.mold_id == moldId) .Select(it => new EquipmentListOutput { eqp_id = it.id, eqp_code = it.eqp_code, eqp_type_code = it.eqp_type_code, eqp_machine_num = it.eqp_machine_num, tonnage = it.tonnage, task_list_qty = SqlFunc.Subqueryable().Where(x => x.eqp_id == it.id).Count(), estimated_end_date = SqlFunc.Subqueryable().Where(x => x.eqp_id == it.id).OrderByDesc(o => o.estimated_end_date).Select(x => x.estimated_end_date) }) .Mapper(x => { x.first_date = x.estimated_end_date.HasValue ? x.estimated_end_date.Value.ToString("yyyy-MM-dd HH:mm:ss") : ""; }) .ToListAsync(); return items; } /// /// 工单调整-生产任务重新排序 /// /// 设备ID /// 排序后生产任务列表 /// /// returns: ///
[ ///
{ ///
no:生产序号 ///
mo_id:工单编号 ///
group_flag:同组标识 ///
plan_qty:计划生产数量 ///
comple_qty:完成数量 ///
item_name:产品名称 ///
mold_code:模具编号 ///
} ///
] ///
[HttpGet("{eqpId}")] public async Task PrdTaskSort(string eqpId) { var taskStatusDic = await _dictionaryDataService.GetDicByTypeId(DictConst.PrdTaskStatusTypeId); var list = await _repository.AsSugarClient().Queryable() .Where(it => it.eqp_id == eqpId) .OrderBy(o => o.estimated_start_date) .ToListAsync(); var data = list.Select((x, idx) => new PrdTaskSortOutput { no = idx + 1, mo_id = x.mo_id, status = taskStatusDic.ContainsKey(x.status) ? taskStatusDic[x.status].ToString() : "", group_flag = x.group_flag, plan_qty = x.plan_qty, comple_qty = x.comple_qty, item_name = x.item_name, mold_code = x.mold_code, }) .ToList(); return data; } /// /// 查看工单操作记录 /// /// 任务ID /// [HttpGet("{taskId}")] public async Task GetMoOperRecord(string taskId) { var list = await _repository.AsSugarClient().Queryable().Where(it => it.id == taskId).ToListAsync(); var data = list.Adapt>(); var dic = await _dictionaryDataService.GetDicByTypeId(DictConst.PrdTaskStatusTypeId); _repository.AsSugarClient().ThenMapper(data, x => x.statusName = dic.ContainsKey(x.status) ? dic[x.status].ToString() : ""); return data; } #endregion #region Post /// /// 生产工单创建-生产工单下发 /// /// 生产工单下发输入参数 /// [HttpPut] public async Task WorkOrderIssue(MoCrInput input) { if (input is null) { throw new ArgumentNullException(nameof(input)); } var db = _repository.AsSugarClient(); //获取同组工单的Id,一起下发 var combineMoCodes = await db.Queryable().Where(it => input.WorkOrderIds.Contains(it.id)).Select(it => it.combine_mo_code).ToListAsync(); if (combineMoCodes?.Count > 0) { var moIds = await db.Queryable().Where(it => combineMoCodes.Contains(it.combine_mo_code) && !input.WorkOrderIds.Contains(it.id)).Select(it => it.id).ToListAsync(); input.WorkOrderIds = input.WorkOrderIds.Concat(moIds).ToList(); } var row = await db.Updateable() .SetColumns(it => new PrdMo { mo_status = DictConst.IssueId, icmo_status = DictConst.ToBeScheduledEncode }) .Where(it => input.WorkOrderIds.Contains(it.id)) .ExecuteCommandAsync(); return (row > 0); } /// /// 关联同组工单 /// /// 关联同组工单输入参数 /// [HttpPost] public async Task RelevancySameGroupMo(MoCrInput input) { (bool executeRes, string errMsg) multi = (true, ""); var list = await _repository.AsSugarClient().Queryable() .InnerJoin((a, b) => a.item_code == b.item_id) .Where((a, b) => input.WorkOrderIds.Contains(a.id)) .Select((a, b) => new { planDate = a.plan_start_date, mold_code = b.mold_code, }).ToListAsync(); var planDateAll = true; var moldIdAll = true; if (list?.Count > 0) { var planDate = list.FirstOrDefault()?.planDate; var moldCode = list.FirstOrDefault()?.mold_code; planDateAll = list.Skip(1).All(x => x.planDate == planDate); moldIdAll = list.Skip(1).All(x => x.mold_code == moldCode); if (planDateAll && moldIdAll) { var groupId = SnowflakeIdHelper.NextId(); multi.executeRes = await _repository.AsSugarClient().Updateable() .SetColumns(c => new PrdMo { combine_mo_code = groupId }) .Where(it => input.WorkOrderIds.Contains(it.id)) .ExecuteCommandHasChangeAsync(); } else { multi.executeRes = false; if (!planDateAll) { throw new AppFriendlyException("计划开始日期不一致", null); } if (!moldIdAll) { throw new AppFriendlyException("未关联到同一模具下", null); } } } return multi; } /// /// 取消关联 /// /// 取消关联输入参数 /// [HttpPost] public async Task CanelRelevancy(MoCrInput input) { return await _repository.AsSugarClient().Updateable() .SetColumns(c => new PrdMo { combine_mo_code = "" }) .Where(it => input.WorkOrderIds.Contains(it.id)) .ExecuteCommandHasChangeAsync(); } /// /// 生产工单-生产排产 /// /// ///
{ ///
Id:生产任务主键Id ///
MoType:工单类型 1、注塑/挤出 2、组装/包装 ///
MoId:工单Id ///
ItemId:产品编号 ///
ItemName:产品名称 ///
MoldId:模具Id ///
MoldName:模具名称 ///
EqpId:设备Id ///
EqpName:设备名称 ///
LineId:产线编号 ///
LineName:产线名称 ///
} /// /// [HttpPost] public async Task ProductionScheduling(ProductionSchedulingCrInput input) { var row = -1; if (input.mo_type.HasValue && input.mo_type.Value == 1) { input.id ??= SnowflakeIdHelper.NextId(); var entity = input.Adapt(); entity.status = DictConst.ToBeStartedEnCode; //任务单状态默认,待排产 entity.create_id = _userManager.UserId; entity.create_time = DateTime.Now; entity.prd_task_id = input.id; var db = _repository.AsSugarClient(); try { List entities = new(); //根据工单Id查询同组工单号,进行同组工单排产处理 var combineMoCodes = await db.Queryable().Where(it => it.id == input.mo_id).Select(it => it.combine_mo_code).Distinct().ToListAsync(); if (combineMoCodes?.Count > 0) { entities = await db.Queryable().Where(it => combineMoCodes.Contains(it.combine_mo_code)).ToListAsync(); } await db.Ado.BeginTranAsync(); //同组工单排产 if (entities.Count > 0) { var icmoEntities = entities.Adapt>(); icmoEntities.ForEach(x => { x.id = SnowflakeIdHelper.NextId(); x.status = DictConst.ToBeStartedEnCode; //任务单状态默认,待排产 x.create_id = _userManager.UserId; x.create_time = DateTime.Now; x.prd_task_id = input.id; }); row = await db.Storageable(entities).ExecuteCommandAsync(); var icmoRecords = icmoEntities.Adapt>(); icmoRecords.ForEach(x => { x.id ??= SnowflakeIdHelper.NextId(); x.task_id = input.id; x.status ??= "ToBeStarted"; x.create_id = _userManager.UserId; x.create_time = DateTime.Now; x.operator_name = _userManager.RealName; }); var icmoIds = icmoRecords.Select(it => it.id).ToList(); var statusMany = icmoRecords.Select(it => it.status).ToList(); //任务状态变更时插入操作记录 var logEntities = await db.Queryable().Where(it => !icmoIds.Contains(it.id) && !statusMany.Contains(it.status)).ToListAsync(); row = await db.Insertable(logEntities).ExecuteCommandAsync(); } else { row = await db.Storageable(entity).ExecuteCommandAsync(); var taskLogEntity = input.Adapt(); taskLogEntity.id ??= SnowflakeIdHelper.NextId(); taskLogEntity.task_id = input.id; taskLogEntity.status ??= "ToBeStarted"; taskLogEntity.create_id = _userManager.UserId; taskLogEntity.create_time = DateTime.Now; taskLogEntity.operator_name = _userManager.RealName; //任务状态变更时插入操作记录 if (!db.Queryable().Where(it => it.task_id == input.id && it.status == taskLogEntity.status).Any()) { row = await db.Insertable(taskLogEntity).ExecuteCommandAsync(); } } if (row > 0) { if (combineMoCodes?.Count > 0 && combineMoCodes?.FirstOrDefault() is not null) { var moList = await db.Queryable().Where(it => combineMoCodes.Contains(it.combine_mo_code)).ToListAsync(); var icmoList = moList.Adapt>(); var combinePlanQty = icmoList.Sum(x => x.plan_qty); //合并工单后的计划数量 var combineScheduledQty = icmoList.Sum(x => x.scheduled_qty); //合并后的已排产数量 if (combineScheduledQty < combinePlanQty) { icmoList.ForEach(x => { var item = moList.Find(xx => xx.id == x.mo_id); if (item != null) { item.input_qty += x.scheduled_qty; item.mo_status = DictConst.WaitProductId; } }); } else { //如果已排产数量大于计划数量,修改工单状态为,待开工 if (combineScheduledQty >= combinePlanQty) { icmoList.ForEach(x => { var item = moList.Find(xx => xx.id == x.mo_id); if (item != null) { item.input_qty += x.scheduled_qty; item.mo_status = DictConst.AlreadyId; } }); } } row = await db.Updateable(moList).ExecuteCommandAsync(); } else { var obj = (await db.Queryable().FirstAsync(it => it.id == input.mo_id)); obj.input_qty += entity.scheduled_qty; string moStatus = "",icmoStatus=""; //判断,已排产数量>=计划数量时将状态改为 已排产 if (obj.input_qty >= obj.plan_qty) { moStatus = DictConst.AlreadyId; icmoStatus = DictConst.ToBeStartedEnCode; } else { //修改工单状态为待排产,同事修改已排产数量 moStatus = DictConst.WaitProductId; icmoStatus = DictConst.ToBeScheduledEncode; } row = await db.Updateable().SetColumns(it => new PrdMo { mo_status = moStatus, icmo_status = icmoStatus, input_qty = obj.input_qty }) .Where(it => it.id == entity.mo_id).ExecuteCommandAsync(); } } await db.Ado.CommitTranAsync(); } catch (Exception ex) { Log.Error("生产任务发布时发生错误", ex); await db.Ado.RollbackTranAsync(); } } return row > 0; } /// /// 生产任务下发 /// /// [HttpPost] public async Task PrdTaskRelease(PrdTaskReleaseUpInput input) { if (input is null) { throw new ArgumentNullException(nameof(input)); } var db = _repository.AsSugarClient(); var row = await db.Updateable() .SetColumns(it => new PrdTask { status = DictConst.ToBeStartedEnCode }) .Where(it => input.TaskIds.Contains(it.id)) .ExecuteCommandAsync(); return (row > 0); } /// /// 生产任务单修改 /// /// 生产任务单修改输入参数 /// /// [HttpPost] public async Task IcmoModify(IcmoUpInput input) { var row = -1; var db = _repository.AsSugarClient(); var icmoItem = await db.Queryable().FirstAsync(it => it.id == input.icmo_id); switch (input.category) { case 1: //设备 var eqpItem = await db.Queryable().FirstAsync(it => it.id == input.eqp_id); icmoItem.eqp_id = eqpItem.id; icmoItem.eqp_type_code = eqpItem.eqp_type_code; if (input.scheduled_qty > icmoItem.plan_qty) { throw new AppFriendlyException("任务单数量不能大于计划数量", 500); } row = await db.Updateable().SetColumns(it => new PrdMo { input_qty = input.scheduled_qty }).Where(it => it.id == input.mo_id).ExecuteCommandAsync(); break; case 2: //模具 var moldItem = await db.Queryable().FirstAsync(it => it.id == input.mold_id); icmoItem.mold_id = moldItem.id; icmoItem.mold_code = moldItem.mold_code; icmoItem.mold_name = moldItem.mold_name; icmoItem.mold_cavity_qty = moldItem.cavity_qty; break; } row = await db.Updateable(icmoItem).ExecuteCommandAsync(); return (row > 0); } #endregion } }