using JNPF; using JNPF.Common.Core.Manager; using JNPF.Common.Extension; using JNPF.Common.Filter; using JNPF.Common.Security; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.Extras.CollectiveOAuth.Utils; using JNPF.FriendlyException; using JNPF.Logging; using JNPF.Systems.Entitys.Permission; using JNPF.Systems.Entitys.System; using JNPF.Systems.Interfaces.System; using JNPF.VisualDev; using JNPF.VisualDev.Entitys.Dto.VisualDevModelData; using JNPF.VisualDev.Interfaces; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using SqlSugar; using Tnb.BasicData; using Tnb.BasicData.Entities; using Tnb.EquipMgr.Entities; using Tnb.ProductionMgr.Entities; using Tnb.ProductionMgr.Entities.Dto; using Tnb.ProductionMgr.Entities.Dto.PrdManage; using Tnb.ProductionMgr.Entities.Enums; using Tnb.ProductionMgr.Interfaces; using AuthResponse = JNPF.Extras.CollectiveOAuth.Models.AuthResponse; using StringExtensions = JNPF.Common.Extension.StringExtensions; namespace Tnb.ProductionMgr { /// /// 生产计划管理 /// [ApiDescriptionSettings(Tag = ModuleConst.Tag, Area = ModuleConst.Area, Order = 700)] [Route("api/[area]/[controller]/[action]")] [OverideVisualDev(ModuleId)] public class PrdMoService : IOverideVisualDevService, IPrdMoService, IDynamicApiController, ITransient { // private const string ModuleId = "25018860321301"; private const string ModuleId = "26900026924053"; private readonly ISqlSugarRepository _repository; private readonly IDataBaseManager _dataBaseManager; private readonly IUserManager _userManager; private readonly IDictionaryDataService _dictionaryDataService; private readonly IRunService _runService; private readonly IVisualDevService _visualDevService; private readonly ISqlSugarClient _db; public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc(); public PrdMoService( ISqlSugarRepository repository, IDataBaseManager dataBaseManager, IUserManager userManager, IDictionaryDataService dictionaryDataService, IRunService runService, IVisualDevService visualDevService ) { _repository = repository; _dataBaseManager = dataBaseManager; _userManager = userManager; _dictionaryDataService = dictionaryDataService; _runService = runService; _visualDevService = visualDevService; _db = _repository.AsSugarClient(); OverideFuncs.GetListAsync = GetList; } // private async Task GetList(VisualDevModelListQueryInput input) // { // var db = _repository.AsSugarClient(); // VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(ModuleId, true); // var data = await _runService.GetListResult(templateEntity, input); // if (data?.list?.Count > 0) // { // foreach (var row in data.list) // { // var dic = row.ToDictionary(x => x.Key, x => x.Value); // var pkName = "material_id_id"; // if (dic.ContainsKey(pkName)) // { // var materialId = dic[pkName]?.ToString(); // var material = await db.Queryable().FirstAsync(it => it.id == materialId); // if (material != null) // { // row.Add("material_name", material.name); // row.Add($"material_attribute", material.attribute); // if (dic.ContainsKey("material_id")) // { // row["material_id"] = material.code + "/" + material.name; // } // } // // if (dic.ContainsKey("unit_id")) // { // string unitId = dic["unit_id"]?.ToString() ?? ""; // var unit = await db.Queryable().SingleAsync(x => x.Id == unitId); // row["unit_id"] = unit?.FullName ?? ""; // } // } // } // } // return data!; // } private async Task GetList(VisualDevModelListQueryInput input) { ISqlSugarClient db = _repository.AsSugarClient(); Dictionary? queryJson = !string.IsNullOrEmpty(input.queryJson) ? Newtonsoft.Json.JsonConvert.DeserializeObject>(input.queryJson) : new Dictionary(); string moCode = queryJson.ContainsKey("mo_code") ? queryJson["mo_code"].ToString() : ""; string moStatus = queryJson.ContainsKey("mo_status") ? queryJson["mo_status"].ToString() : ""; string combineMoCode = queryJson.ContainsKey("combine_mo_code") ? queryJson["combine_mo_code"].ToString() : ""; string mo_type = queryJson.ContainsKey("mo_type") ? queryJson["mo_type"].ToString() : ""; string mo_source = queryJson.ContainsKey("mo_source") ? queryJson["mo_source"].ToString() : ""; DateTime[] plan_start_date = queryJson.ContainsKey("plan_start_date") ? queryJson["plan_start_date"].ToObject().Select(x => DateTimeOffset.FromUnixTimeSeconds(x / 1000).ToLocalTime().DateTime).ToArray() : null; DateTime[] plan_end_date = queryJson.ContainsKey("plan_end_date") ? queryJson["plan_end_date"].ToObject().Select(x => DateTimeOffset.FromUnixTimeSeconds(x / 1000).ToLocalTime().DateTime).ToArray() : null; DateTime? s_s_date = null; DateTime? s_e_date = null; DateTime? e_s_date = null; DateTime? e_e_date = null; if (plan_start_date != null && plan_start_date.Length == 2) { s_s_date = plan_start_date[0]; s_e_date = plan_start_date[1]; } if (plan_end_date != null && plan_end_date.Length == 2) { e_s_date = plan_end_date[0]; e_e_date = plan_end_date[1]; } SqlSugarPagedList result = await db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .LeftJoin((a, b, c) => c.EnCode == DictConst.MeasurementUnit) .LeftJoin((a, b, c, d) => c.Id == d.DictionaryTypeId && a.unit_id == d.Id) .LeftJoin((a, b, c, d, e) => a.mo_status == e.Id) .LeftJoin((a, b, c, d, e, f) => a.mo_type == f.Id) .WhereIF(!string.IsNullOrEmpty(moCode), (a, b, c, d, e) => a.mo_code.Contains(moCode)) .WhereIF(!string.IsNullOrEmpty(combineMoCode), (a, b, c, d, e) => a.combine_mo_code.Contains(combineMoCode)) .WhereIF(!string.IsNullOrEmpty(moStatus), (a, b, c, d, e) => a.mo_status == moStatus) .WhereIF(!string.IsNullOrEmpty(mo_type), (a, b, c, d, e) => a.mo_type == mo_type) .WhereIF(!string.IsNullOrEmpty(mo_source), (a, b, c, d, e) => a.mo_source == mo_source) .WhereIF(plan_start_date!=null && plan_start_date.Length==2,a=>a.plan_start_date>=s_s_date && a.plan_start_date<=s_e_date) .WhereIF(plan_end_date!=null && plan_end_date.Length==2,a=>a.plan_end_date>=e_s_date && a.plan_end_date<=e_e_date) .Where(a => SqlFunc.IsNullOrEmpty(a.parent_id)) .OrderByDescending(a => a.create_time) .Select((a, b, c, d, e, f) => new PrdMoListOuput { id = a.id, mo_type = f.FullName, mo_source = a.mo_source == "1" ? "ERP同步" : "新建/导入", mo_code = a.mo_code, plan_start_date = a.plan_start_date == null ? "" : a.plan_start_date.Value.ToString("yyyy-MM-dd"), plan_end_date = a.plan_end_date == null ? "" : a.plan_end_date.Value.ToString("yyyy-MM-dd"), material_id = b.code + "/" + b.name, material_id_id = b.id, plan_qty = a.plan_qty, unit_id = d.FullName, mo_status = e.FullName, ebom_version = a.ebom_version, remark = a.remark, f_flowtaskid = b.material_specification, f_flowid = b.material_standard, children = SqlFunc.Subqueryable() .LeftJoin((aa, bb) => aa.material_id == bb.id) .LeftJoin((aa, bb, cc) => cc.EnCode == DictConst.MeasurementUnit) .LeftJoin((aa, bb, cc, dd) => cc.Id == dd.DictionaryTypeId && aa.unit_id == dd.Id) .LeftJoin((aa, bb, cc, dd, ee) => aa.mo_status == ee.Id) .LeftJoin((aa, bb, cc, dd, ee, ff) => aa.mo_type == ff.Id) .Where(aa => aa.parent_id == a.id) .ToList((aa, bb, cc, dd, ee, ff) => new PrdMoListOuput { id = aa.id, mo_type = ff.FullName, mo_source = aa.mo_source == "1" ? "ERP同步" : "新建/导入", mo_code = aa.mo_code, plan_start_date = aa.plan_start_date == null ? "" : aa.plan_start_date.Value.ToString("yyyy-MM-dd"), plan_end_date = aa.plan_end_date == null ? "" : aa.plan_end_date.Value.ToString("yyyy-MM-dd"), material_id = bb.code + "/" + bb.name, material_id_id = bb.id, plan_qty = aa.plan_qty, unit_id = dd.FullName, mo_status = ee.FullName, remark = aa.remark, }) }).ToPagedListAsync(input.currentPage, int.MaxValue); return PageResult.SqlSugarPageResult(result); } #region Get /// /// 获取自建报废记录 /// /// /// [HttpGet("{icmoCode}")] public dynamic GetReportRecord(string icmoCode) { _ = _repository.AsSugarClient(); PrdMoTaskDefectOutput output = new(); //output.mo_task_code = icmoCode; //var scrap = (await db.Queryable().FirstAsync(it => it.icmo_code == icmoCode)); //output.items = new List(); //var categorys = await db.Queryable().Where(it => it.icmo_code == icmoCode).ToListAsync(); //foreach (var category in categorys) //{ // var categoryItem = category.Adapt(); // categoryItem.items = new List(); // var items = await db.Queryable().Where(it => it.defective_cagetory_id == category.id).ToListAsync(); // categoryItem.items.AddRange(items); // output.categoryItems.Add(categoryItem); //} return output; } #endregion #region Post /// /// 生产工单创建-生产工单下发 /// /// 生产工单下发输入参数 /// [HttpPut] public async Task WorkOrderIssue(MoCrInput input) { if (input is null) { throw new ArgumentNullException(nameof(input)); } if (StringExtensions.IsNullOrWhiteSpace(input.Behavior)) { throw new ArgumentException($"{nameof(input.Behavior)},not be null or empty"); } ISqlSugarClient db = _repository.AsSugarClient(); //获取同组工单的Id,一起下发 List combineMoCodes = await db.Queryable().Where(it => input.WorkOrderIds.Contains(it.id)).Select(it => it.combine_mo_code).ToListAsync(); if (combineMoCodes?.Count > 0) { List 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(); } List prdMos = await db.Queryable().Where(x => input.WorkOrderIds.Contains(x.id)).ToListAsync(); foreach (var item in prdMos) { if (!await db.Queryable().AnyAsync(x => x.material_id == item.material_id && x.version == item.ebom_version)) { throw Oops.Bah($"系统中无法找到物料清单{item.ebom_version}版本"); } if (!await db.Queryable().LeftJoin((a, b) => a.ebom_id == b.id).Where((a, b) => a.material_id == item.material_id && b.version == item.ebom_version).AnyAsync()) { throw Oops.Bah($"系统中无法找到物料清单对应的生产bom{item.ebom_version}版本"); } } static string getMoStatus(MoBehavior behavior) { string status = ""; switch (behavior) { case MoBehavior.Release: status = DictConst.IssueId; break; case MoBehavior.Closed: status = DictConst.MoCloseId; break; } return status!; } MoBehavior behavior = input.Behavior.ToEnum(); string status = getMoStatus(behavior); int row = await db.Updateable() .SetColumns(it => new PrdMo { mo_status = status }) .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.material_id == b.material_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 RelevancySameGroupMo(MoCrInput input) { (bool executeRes, string errMsg) multi = (true, ""); var list = await _repository.AsSugarClient().Queryable() .LeftJoin((a, b) => a.material_id == b.material_id) .LeftJoin((a, b, c) => b.mold_id == c.id) .Where((a, b, c) => input.WorkOrderIds.Contains(a.id)) .Select((a, b, c) => new { planDate = a.plan_start_date, c.mold_code, }).ToListAsync(); bool planDateAll = true; bool moldIdAll = true; if (list?.Count > 0) { DateTime? planDate = list.FirstOrDefault()?.planDate; string? moldCode = list.FirstOrDefault()?.mold_code; planDateAll = list.All(x => x.planDate == planDate); moldIdAll = moldCode != null && list.All(x => x.mold_code == moldCode); if (planDateAll && moldIdAll) { string 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 Oops.Bah("计划开始日期不一致"); } if (!moldIdAll) { throw Oops.Bah("未关联到同一模具下"); } } } 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(); } /// /// 工单统计 /// /// /// [HttpPost] public async Task GetPrdMoStatistics(PrdMoStatisticsInput input) { SqlSugarPagedList result = await _db.Queryable() .LeftJoin((a, b) => a.mo_status == b.Id) .LeftJoin((a, b, c) => a.material_id == c.id) .WhereIF(!string.IsNullOrEmpty(input.mo_status), (a, b) => b.EnCode == input.mo_status) // .OrderByDescending((a,b,c)=>a.reported_work_qty==null?0:a.reported_work_qty*100/a.plan_qty) .Select((a, b, c) => new PrdMoStatisticsOutput { id = a.id, mo_code = a.mo_code, mo_status = b.FullName, material_code = c.code, material_name = c.name, plan_qty = a.plan_qty, scheduled_qty = a.scheduled_qty, tobe_scheduled_qty = a.plan_qty - a.scheduled_qty, reported_work_qty = a.reported_work_qty, complete_rate = a.reported_work_qty == null ? 0 : SqlFunc.ToDecimal(a.reported_work_qty * 100) / SqlFunc.ToDecimal(a.plan_qty), children = SqlFunc.Subqueryable() .LeftJoin((x, y) => x.mo_task_status == y.EnCode && y.DictionaryTypeId == DictConst.PrdTaskStatusTypeId) .Where(x => x.mo_id == a.id && SqlFunc.IsNullOrEmpty(x.parent_id)) .OrderByDesc((x, y) => x.create_time) .ToList((x, y) => new PrdMoStatisticsDetailOutput() { id = x.id, mo_task_code = x.mo_task_code, mo_task_status = y.FullName, estimated_start_date = x.estimated_start_date == null ? "" : x.estimated_start_date.Value.ToString(DbTimeFormat.SS), estimated_end_date = x.estimated_end_date == null ? "" : x.estimated_end_date.Value.ToString(DbTimeFormat.SS), scheduled_qty = x.scheduled_qty, reported_work_qty = x.reported_work_qty, scrap_qty = x.scrap_qty, }), }) .MergeTable().OrderByDescending(a => a.complete_rate) .ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(result); } public class data { public string mo_code { get; set; } public string f_fullname { get; set; } public string material_name { get; set; } public string plan_qty { get; set; } public string scheduled_qty { get; set; } public string tobe_scheduled_qty { get; set; } public string reported_work_qty { get; set; } public string complete_rate { get; set; } public string orderby_field { get; set; } } [HttpPost] [AllowAnonymous] public async Task GetPrdTask() { var result= _db.Ado.SqlQuery("select a.mo_code,b.f_fullname,c.name as material_name,a.plan_qty,a.scheduled_qty,(a.plan_qty-a.scheduled_qty) as tobe_scheduled_qty, a.reported_work_qty,(case when a.scheduled_qty is null or a.scheduled_qty<=0 or a.reported_work_qty is null or a.reported_work_qty<=0 then null else round(a.reported_work_qty*100::numeric/a.plan_qty, 1)||'%' end) as complete_rate,(case when a.scheduled_qty is null or a.scheduled_qty<=0 or a.reported_work_qty is null or a.reported_work_qty<=0 then 0 else round(a.reported_work_qty*100::numeric/a.plan_qty, 1) end) as orderby_field from prd_mo a left join base_dictionarydata b on a.mo_status=b.f_id left join bas_material c on a.material_id=c.id where a.mo_status not in ('25501969636645','25501960891941');"); return result; } #endregion #region 正向工单追溯相关 /// /// 工单追溯一级列表 /// /// /// [HttpPost] public async Task PrdMoFromOneList(PrdMoFromQueryInput input) { List ids = new(); List ids1 = new(); List ids2 = new(); if (!string.IsNullOrEmpty(input.mo_task_code)) { ids1 = await _db.Queryable().Where(x => x.mo_task_code.Contains(x.mo_task_code)).Select(x => x.mo_id).ToListAsync(); ids = ids1; } if (!string.IsNullOrEmpty(input.barcode)) { ids2 = await _db.Queryable() .LeftJoin((a, b) => a.mo_task_id == b.id) .Where((a, b) => a.barcode.Contains(input.barcode)).Select((a, b) => b.mo_id).ToListAsync(); ids = ids2; } if (!string.IsNullOrEmpty(input.mo_task_code) && !string.IsNullOrEmpty(input.barcode)) { ids = ids1.Intersect(ids2).ToList(); } SqlSugarPagedList result = await _db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .WhereIF(!string.IsNullOrEmpty(input.mo_code), (a, b) => a.mo_code.Contains(input.mo_code)) .WhereIF(ids != null && ids.Count > 0, (a, b) => ids.Contains(a.id)) .Select((a, b) => new PrdMoFromOneListOutput { id = a.id, mo_code = a.mo_code, material_id = a.material_id, type = (a.mo_type == DictConst.PrdMoTypeZS || a.mo_type == DictConst.PrdMoTypeJC) ? 1 : 2, material_code = b.code, material_name = b.name, material_standard = b.material_specification, act_start_date = a.act_start_date == null ? "" : a.act_start_date.Value.ToString(DbTimeFormat.SS), act_end_date = a.act_end_date == null ? "" : a.act_end_date.Value.ToString(DbTimeFormat.SS) }).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(result); } /// /// 工单追溯二级列表 /// /// [HttpPost] public async Task PrdMoFromTwoList(PrdMoFromTwoQueryInput prdMoFromTwoQueryInput) { string mo_id = prdMoFromTwoQueryInput.mo_id ?? ""; string mo_task_code = prdMoFromTwoQueryInput.mo_task_code ?? ""; string barcode = prdMoFromTwoQueryInput.barcode ?? ""; List ids = new(); if (!string.IsNullOrEmpty(barcode)) { ids = await _db.Queryable().Where(x => x.barcode.Contains(barcode)).Select(x => x.mo_task_id).ToListAsync(); } PrdMo prdMo = await _repository.GetSingleAsync(x => x.id == mo_id); return prdMo.mo_type is DictConst.PrdMoTypeZS or DictConst.PrdMoTypeJC ? await _db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .LeftJoin((a, b, c) => a.eqp_id == c.ObjectId && c.ObjectType == "Eqp") .LeftJoin((a, b, c, d) => c.OrganizeId == d.Id) .LeftJoin((a, b, c, d, e) => d.OrganizeIdTree.Contains(e.Id) && e.Category == DictConst.RegionCategoryWorkshopCode) .LeftJoin((a, b, c, d, e, f) => a.eqp_id == f.id) .WhereIF(!string.IsNullOrEmpty(mo_id), (a, b, c, d) => a.mo_id == mo_id) .WhereIF(!string.IsNullOrEmpty(mo_task_code), (a, b, c, d) => a.mo_task_code == mo_task_code) .WhereIF(ids != null && ids.Count > 0, (a, b, c, d) => ids.Contains(a.id)) .Select((a, b, c, d, e, f) => new PrdMoFromTwoListOutput { id = a.id, mo_task_code = a.mo_task_code, material_id = a.material_id, material_code = b.code, material_name = b.name, material_standard = b.material_specification, act_start_date = a.act_start_date == null ? "" : a.act_start_date.Value.ToString(DbTimeFormat.SS), act_end_date = a.act_end_date == null ? "" : a.act_end_date.Value.ToString(DbTimeFormat.SS), workshop_name = e.FullName, station_name = d.FullName, equip_code = f.code }).ToListAsync() : (dynamic)await _db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .LeftJoin((a, b, c) => a.workline_id == c.Id) .LeftJoin((a, b, c, d) => a.bom_id == d.id) .WhereIF(!string.IsNullOrEmpty(mo_id), (a, b, c, d) => a.mo_id == mo_id) .WhereIF(!string.IsNullOrEmpty(mo_task_code), (a, b, c, d) => a.mo_task_code.Contains(mo_task_code)) .WhereIF(ids != null && ids.Count > 0, (a, b, c, d) => ids.Contains(a.id)) .Select((a, b, c, d) => new PrdMoFromTwoListOutput { id = a.id, mo_task_code = a.mo_task_code, material_id = a.material_id, material_code = b.code, material_name = b.name, material_standard = b.material_specification, act_start_date = a.act_start_date == null ? "" : a.act_start_date.Value.ToString(DbTimeFormat.SS), act_end_date = a.act_end_date == null ? "" : a.act_end_date.Value.ToString(DbTimeFormat.SS), workline_name = c.FullName, mbom_version = d.version }).ToListAsync(); } /// /// 工单追溯三级级列表 /// /// [HttpPost] public async Task PrdMoFromThreeList(PrdMoFromThreeQueryInput prdMoFromThreeQueryInput) { string mo_task_id = prdMoFromThreeQueryInput.mo_task_id ?? ""; string mo_task_code = prdMoFromThreeQueryInput.mo_task_code ?? ""; string barcode = prdMoFromThreeQueryInput.barcode ?? ""; List ids = new(); if (!string.IsNullOrEmpty(barcode)) { ids = await _db.Queryable().Where(x => x.barcode.Contains(barcode)).Select(x => x.mo_task_id).ToListAsync(); } PrdMoTask prdMoTask = await _db.Queryable().SingleAsync(x => x.id == mo_task_id); List processStations = await _db.Queryable().Where(x => x.process_id == prdMoTask.process_id).ToListAsync(); List orgIds = processStations.Select(x => x.id).ToList(); List orgs = await _db.Queryable().Where(x => x.Category == DictConst.RegionCategoryStationCode && x.DeleteMark == null).ToListAsync(); return await _db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .LeftJoin((a, b, c) => a.process_id == c.id) .WhereIF(!string.IsNullOrEmpty(mo_task_id), (a, b, c) => a.id == mo_task_id) .WhereIF(!string.IsNullOrEmpty(mo_task_code), (a, b, c) => a.mo_task_code.Contains(mo_task_code)) .WhereIF(ids != null && ids.Count > 0, (a, b, c) => ids.Contains(a.id)) .Select((a, b, c) => new PrdMoFromThreeListOutput { id = a.id, mo_task_code = a.mo_task_code, material_id = a.material_id, material_code = b.code, workline_id = a.workline_id, material_name = b.name, process_id = a.process_id, process_name = c.process_name, }).Mapper(x => { List orgId1 = orgs.Where(y => y.OrganizeIdTree.Contains(x.workline_id)).Select(y => y.Id).ToList(); string? station_id = orgIds.Intersect(orgId1)?.FirstOrDefault(); if (!string.IsNullOrEmpty(station_id)) { x.station_name = orgs.FirstOrDefault(y => y.Id == station_id)?.FullName; } }).ToListAsync(); } /// /// 工单追溯人列表 /// /// [HttpPost] public async Task PrdMoFromManList(PrdMoFromTabQueryInput prdMoFromTabQueryInput) { string mo_task_id = prdMoFromTabQueryInput.mo_task_id ?? ""; string barcode = prdMoFromTabQueryInput.barcode ?? ""; List ids = new(); if (!string.IsNullOrEmpty(barcode)) { ids = await _db.Queryable().Where(x => x.barcode.Contains(barcode)).Select(x => x.mo_task_id).ToListAsync(); } return await _db.Queryable() .LeftJoin((a, b) => a.create_id == b.Id) .WhereIF(!string.IsNullOrEmpty(mo_task_id), (a, b) => a.mo_task_id == mo_task_id) // .WhereIF(ids!=null && ids.Count>0,(a,b)=>ids.Contains(a.mo_task_id)) .WhereIF(!string.IsNullOrEmpty(barcode), (a, b) => a.barcode.Contains(barcode)) .GroupBy((a, b) => new { a.create_id, employee_name = b.RealName }) .Select((a, b) => new PrdMoFromManListOutput() { // id = a.id, employee_name = b.RealName, start_time = SqlFunc.AggregateMin(a.create_time), end_time = SqlFunc.AggregateMax(a.create_time) }).Mapper(x => { x.work_time = (x.start_time == null ? "" : x.start_time.Value.ToString("yyyy-MM-dd HH:mm:ss")) + "~" + (x.end_time == null ? "" : x.end_time.Value.ToString("yyyy-MM-dd HH:mm:ss")); }) .ToListAsync(); } /// /// 工单追溯机列表 /// /// [HttpPost] public async Task PrdMoFromEquipList(PrdMoFromTabQueryInput prdMoFromTabQueryInput) { string mo_task_id = prdMoFromTabQueryInput.mo_task_id ?? ""; string barcode = prdMoFromTabQueryInput.barcode ?? ""; List ids = new(); if (!string.IsNullOrEmpty(barcode)) { ids = await _db.Queryable().Where(x => x.barcode.Contains(barcode)).Select(x => x.mo_task_id).ToListAsync(); } return await _db.Queryable() .LeftJoin((a, b) => a.eqp_id == b.id) .LeftJoin((a, b, c) => a.mold_id == c.id) .WhereIF(!string.IsNullOrEmpty(mo_task_id), (a, b) => a.id == mo_task_id) .WhereIF(ids != null && ids.Count > 0, (a, b) => ids.Contains(a.id)) .Select((a, b, c) => new PrdMoFromEquipListOutput() { equip_code = b.code, mold_code = b.code, }).ToListAsync(); } /// /// 工单追溯料列表 /// /// [HttpPost] public async Task PrdMoFromMaterialList(PrdMoFromTabQueryInput prdMoFromTabQueryInput) { string mo_task_id = prdMoFromTabQueryInput.mo_task_id ?? ""; string barcode = prdMoFromTabQueryInput.barcode ?? ""; List ids = new(); if (!string.IsNullOrEmpty(barcode)) { ids = await _db.Queryable().Where(x => x.barcode.Contains(barcode)).Select(x => x.mo_task_id).ToListAsync(); } PrdMoTask prdMoTask = await _db.Queryable().SingleAsync(x => x.id == mo_task_id); PrdMo prdMo = await _db.Queryable().SingleAsync(x => x.id == prdMoTask.mo_id); /* * 注塑投料记录 1产出物料二维码为精确搜索 * 2 不填产出物料二维码 则投入物料列表不计算批次等 * 3 物料二维码为精确搜索时 按照先进先出的规则计算投入物料 * 4 组装包装可投入物料组成 1)直接从生产线上流转下来的物料 2)投入的物料 */ if (string.IsNullOrEmpty(barcode)) { return prdMoTask.schedule_type == 1 ? await _db.Queryable() .LeftJoin((a, b) => a.id == b.ebom_id) .LeftJoin((a, b, c) => b.material_id == c.id) .Where((a, b, c) => a.id == prdMoTask.ebom_id) .Select((a, b, c) => new PrdMoFromMaterialListOutput() { material_code = c.code, material_name = c.name, }).ToListAsync() : (dynamic)await _db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .Where((a, b) => a.mbom_id == prdMoTask.bom_id) .Select((a, b) => new PrdMoFromMaterialListOutput() { material_code = b.code, material_name = b.name, }).ToListAsync(); } else { PrdReport prdReport = await _db.Queryable().Where(x => x.barcode == barcode).FirstAsync(); List prdReports = await _db.Queryable().Where(x => x.create_time <= prdReport.create_time && x.barcode != barcode && x.mo_task_id == mo_task_id).ToListAsync(); int? beforeReportNum = prdReports.Sum(x => x.reported_qty); List prdFeedingIds = new(); if (prdMoTask.schedule_type == 1) { BasEbomH basEbomH = await _db.Queryable().SingleAsync(x => x.id == prdMoTask.ebom_id); List basEbomDs = await _db.Queryable().Where(x => x.ebom_id == prdMoTask.ebom_id).ToListAsync(); foreach (BasEbomD item in basEbomDs) { // decimal? num1 = beforeReportNum / basEbomH.quantity * item.quantity; decimal? num1 = beforeReportNum / (item.molecule/item.denominator); List prdFeedingDs = await _db.Queryable() .LeftJoin((a, b) => a.feeding_id == b.id) .Where((a, b) => a.material_id == item.material_id && b.mo_task_id == mo_task_id) .OrderBy((a, b) => b.create_time) .Select((a, b) => a).ToListAsync(); decimal sum1 = 0; decimal sum2 = 0; foreach (PrdFeedingD prdFeedingD in prdFeedingDs) { if (sum1 <= num1) { sum1 += prdFeedingD.num; } else { // decimal? num2 = prdReport.reported_qty / basEbomH.quantity * item.quantity; decimal? num2 = prdReport.reported_qty / (item.molecule/item.denominator); if (sum2 <= num2) { prdFeedingIds.Add(item.id); } else { break; } } } } return await _db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .LeftJoin((a, b, c) => a.material_receipt_detail_id == c.id) .LeftJoin((a, b, c, d) => c.supplier_id == d.id) .LeftJoin((a, b, c, d, e) => a.feeding_id == e.id) .WhereIF(prdFeedingIds != null && prdFeedingIds.Count > 0, (a, b, c, d, e) => prdFeedingIds.Contains(a.id)) .Select((a, b, c, d, e) => new PrdMoFromMaterialListOutput() { material_code = b.code, material_name = b.name, batch = a.batch, supplier_name = d.supplier_name, check_conclusion = c.check_conclusion, instock_time = c.instock_time==null ? "" : c.instock_time.Value.ToString(DbTimeFormat.SS), feeding_time = e.create_time == null ? "" : e.create_time.Value.ToString(DbTimeFormat.SS), }).ToListAsync(); } else { List basMbomInputs = await _db.Queryable().Where(x => x.mbom_process_id == prdMoTask.mbom_process_id).ToListAsync(); BasMbom basMbom = await _db.Queryable().SingleAsync(x => x.id == prdMoTask.bom_id); BasMbomProcess basMbomProcess = await _db.Queryable().SingleAsync(x => x.id == prdMoTask.mbom_process_id); List lastPrdReportIds = new(); foreach (BasMbomInput item in basMbomInputs) { BasMbomOutput basMbomOutput = await _db.Queryable().Where(x => x.mbom_process_id == basMbomProcess.id && x.material_id == prdMoTask.material_id).FirstAsync(); if (basMbomOutput == null) { break; } // decimal? num1 = beforeReportNum / Convert.ToDecimal(basMbomOutput.num) * item.num; decimal? num1 = beforeReportNum / (basMbomOutput.molecule/basMbomOutput.denominator) * (item.molecule/item.denominator); List prdFeedingDs = await _db.Queryable() .LeftJoin((a, b) => a.feeding_id == b.id) .Where((a, b) => a.material_id == item.material_id && b.mo_task_id == mo_task_id) .OrderBy((a, b) => b.create_time) .Select((a, b) => a).ToListAsync(); if (prdFeedingDs == null || prdFeedingDs.Count <= 0) { if (string.IsNullOrEmpty(basMbomProcess.last_process_no)) { continue; } List lastBasMbomProcesses = await _db.Queryable().Where(x => x.no == basMbomProcess.last_process_no && x.mbom_id == prdMoTask.bom_id).ToListAsync(); foreach (BasMbomProcess lastBasMbomProcess in lastBasMbomProcesses) { List lastPrdReports = await _db.Queryable() .Where(x => x.mbom_process_id == lastBasMbomProcess.id && x.material_id == item.material_id) .OrderBy(x => x.create_time) .ToListAsync(); if (lastPrdReports == null || lastPrdReports.Count <= 0) { continue; } PrdMoTask lastPrdMoTask = await _db.Queryable().FirstAsync(x => x.mo_id == prdMo.id && x.mbom_process_id == lastBasMbomProcess.id); decimal sum1 = 0; decimal sum2 = 0; foreach (PrdReport lastPrdReport in lastPrdReports) { if (sum1 <= num1) { sum1 += lastPrdReport.reported_qty ?? 0; } else { // decimal? num2 = lastPrdReport.reported_qty / Convert.ToDecimal(basMbomOutput.num) * item.num; decimal? num2 = lastPrdReport.reported_qty / (basMbomOutput.molecule/basMbomOutput.denominator) * (item.molecule/item.denominator); if (sum2 <= num2) { lastPrdReportIds.Add(lastPrdReport.id); } else { break; } } } } } else { decimal sum1 = 0; decimal sum2 = 0; foreach (PrdFeedingD prdFeedingD in prdFeedingDs) { if (sum1 <= num1) { sum1 += prdFeedingD.num; } else { // decimal? num2 = prdReport.reported_qty / Convert.ToDecimal(basMbomOutput.num) * item.num; decimal? num2 = prdReport.reported_qty / (basMbomOutput.molecule/basMbomOutput.denominator) * (item.molecule/item.denominator); if (sum2 <= num2) { prdFeedingIds.Add(item.id); } else { break; } } } } } ISugarQueryable queryable1 = _db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .LeftJoin((a, b, c) => a.material_receipt_detail_id == c.id) .LeftJoin((a, b, c, d) => c.supplier_id == d.id) .LeftJoin((a, b, c, d, e) => a.feeding_id == e.id) .WhereIF(!string.IsNullOrEmpty(mo_task_id), (a, b, c, d, e) => e.mo_task_id == mo_task_id) .WhereIF(prdFeedingIds != null && prdFeedingIds.Count > 0, (a, b, c, d, e) => prdFeedingIds.Contains(a.id)) .Select((a, b, c, d, e) => new PrdMoFromMaterialListOutput() { material_code = b.code, material_name = b.name, batch = a.batch, supplier_name = d.supplier_name, check_conclusion = c.check_conclusion, instock_time = c.instock_time==null ? "" : c.instock_time.Value.ToString(DbTimeFormat.SS), feeding_time = e.create_time == null ? "" : e.create_time.Value.ToString(DbTimeFormat.SS), }); if (lastPrdReportIds != null && lastPrdReportIds.Count > 0) { ISugarQueryable queryable2 = _db.Queryable() .LeftJoin((a, b) => a.material_id == b.id) .Where((a, b) => lastPrdReportIds.Contains(a.id)) .Select((a, b) => new PrdMoFromMaterialListOutput() { material_code = b.code, material_name = b.name, batch = a.batch, supplier_name = "自制" }); return await _db.UnionAll(queryable1, queryable2).ToListAsync(); } else { return await queryable1.ToListAsync(); } } } } #endregion #region 反向工单追溯相关 /// /// 物料反向追溯物料信息 /// /// [HttpPost] public async Task PrdMoReverseFromMaterialInfo(PrdMoReverseFromQueryInput prdMoReverseFromQueryInput) { string barcode = prdMoReverseFromQueryInput.barcode ?? ""; string domain = _userManager.Domain; Dictionary header = new() { ["Authorization"] = App.HttpContext!=null ? App.HttpContext.Request.Headers["Authorization"] : "" }; Dictionary postData = new() { ["org_id"] = _userManager.GetUserInfo().Result.organizeId, ["barcode"] = new List() { barcode }, ["currentPage"] = 1, ["pageSize"] = int.MaxValue, }; string sendResult = HttpUtils.RequestPost(domain + WebApiConst.MES_FETCH_IN_OUT_STOCK_INFO_BY_BAR_CODE, JsonConvert.SerializeObject(postData), header); Log.Information(sendResult); AuthResponse authResponse = JsonConvert.DeserializeObject(sendResult); if (authResponse.code != 200) { throw Oops.Bah(authResponse.msg); } else { PageResult output = JsonConvert.DeserializeObject>(authResponse.data.ToString(), new Tnb.Common.Utils.DateTimeJsonConverter()); if (output.list != null && output.list.Count > 0) { BasMaterial basMaterial = await _db.Queryable().SingleAsync(x => x.id == output.list[0].material_id); BasSupplier basSupplier = await _db.Queryable().SingleAsync(x => x.id == output.list[0].supplier_id); DictionaryDataEntity unit = await _db.Queryable() .LeftJoin((a, b) => a.Id == b.DictionaryTypeId) .Where((a, b) => a.EnCode == DictConst.MeasurementUnit && b.EnCode == output.list[0].unit_id) .Select((a, b) => b) .FirstAsync(); output.list[0].feeding_num = await _db.Queryable() .LeftJoin((a, b) => a.id == b.material_receipt_detail_id) .Where((a, b) => a.barcode == barcode).SumAsync((a, b) => b.num); output.list[0].material_name = basMaterial.name; output.list[0].material_standard = basMaterial.material_specification; output.list[0].supplier_name = basSupplier?.supplier_name ?? ""; output.list[0].unit_name = unit?.FullName ?? ""; return output.list[0]; } } return Array.Empty(); } /// /// 物料反向追溯投料信息 /// /// [HttpPost] public async Task PrdMoReverseFromFeedingInfo(PrdMoReverseFromQueryInput prdMoReverseFromQueryInput) { string barcode = prdMoReverseFromQueryInput.barcode ?? ""; List ids = await _db.Queryable() .LeftJoin((a, b) => a.id == b.material_receipt_detail_id) .LeftJoin((a, b, c) => b.feeding_id == c.id) .Where(a => a.barcode == barcode) .Select((a, b, c) => c.mo_task_id).ToListAsync(); List result = await _db.Queryable() .LeftJoin((a, b) => a.mo_id == b.id) .LeftJoin((a, b, c) => a.material_id == c.id) .Where((a, b, c) => ids.Contains(a.id)) .Select((a, b, c) => new PrdMoReverseFromFeedingOutput { mo_task_id = a.id, mo_task_code = a.mo_task_code, mo_code = b.mo_code, material_code = c.code, material_name = c.name, material_standard = c.material_specification, children = SqlFunc.Subqueryable() .LeftJoin((x, y) => x.feeding_id == y.id) .LeftJoin((x, y, z) => y.create_id == z.Id) .LeftJoin((x, y, z, org) => y.station_id == org.Id) .LeftJoin((x, y, z, org, process) => y.process_id == process.id) .LeftJoin((x, y, z, org, process, mp) => x.material_receipt_detail_id == mp.id) .Where((x, y, z) => y.mo_task_id == a.id).ToList((x, y, z, org, process, mp) => new PrdMoReverseFromFeedingDetailOutput { feeding_detail_id = x.id, feeding_time = y.create_time == null ? "" : y.create_time.Value.ToString(DbTimeFormat.SS), num = x.num, check_conclusion = mp.check_conclusion, feeding_name = z.RealName, station_name = org.FullName, process_name = process.process_name }), }).ToListAsync(); return result; // return PageResult.SqlSugarPageResult(result); } /// /// 物料反向追溯产出信息 /// /// [HttpPost] public async Task PrdMoReverseFromOutInfo(PrdMoReverseFromOutInfoQueryInput prdMoReverseFromOutInfoQueryInput) { string feeding_detail_id = prdMoReverseFromOutInfoQueryInput.feeding_detail_id ?? ""; PrdFeedingD prdFeedingD = await _db.Queryable().FirstAsync(x => x.id == feeding_detail_id); if (prdFeedingD.use_num <= 0) { return Array.Empty(); } PrdFeedingH prdFeedingH = await _db.Queryable().FirstAsync(x => x.id == prdFeedingD.feeding_id); PrdMoTask prdMoTask = await _db.Queryable().FirstAsync(x => x.id == prdFeedingH.mo_task_id); List prdFeedingDs = await _db.Queryable() .LeftJoin((a, b) => a.feeding_id == b.id) .Where((a, b) => a.material_id == prdFeedingD.material_id && b.mo_task_id == prdFeedingH.mo_task_id && b.create_time <= prdFeedingH.create_time && a.id != prdFeedingD.id) .Select((a, b) => a).ToListAsync(); decimal beforeIn = prdFeedingDs.Sum(x => x.num); List reportIds = new(); if (prdMoTask.schedule_type == 1) { BasEbomH basEbomH = await _db.Queryable().SingleAsync(x => x.id == prdMoTask.ebom_id); List basEbomDs = await _db.Queryable().Where(x => x.ebom_id == prdMoTask.ebom_id).ToListAsync(); BasEbomD basEbomD = basEbomDs.Where(x => x.material_id == prdFeedingD.material_id).FirstOrDefault(); if (basEbomD != null) { List prdReports = await _db.Queryable().Where(x => x.mo_task_id == prdMoTask.id).OrderBy(x => x.create_time).ToListAsync(); if (prdReports != null && prdReports.Count > 0) { bool flag = true; decimal residueNeed = 0; foreach (PrdReport prdReport in prdReports) { // decimal needNum = (prdReport.reported_qty ?? 0) / basEbomH.quantity * basEbomD.quantity; decimal needNum = (prdReport.reported_qty ?? 0) / (basEbomD.molecule/basEbomD.denominator); if (beforeIn - needNum >= 0) { beforeIn -= needNum; } else { if (flag) { if (prdFeedingD.num > needNum - beforeIn) { residueNeed = prdFeedingD.num - (needNum - beforeIn); reportIds.Add(prdReport.id); } else { reportIds.Add(prdReport.id); break; } flag = false; continue; } if (residueNeed - needNum > 0) { residueNeed -= needNum; reportIds.Add(prdReport.id); } else { reportIds.Add(prdReport.id); break; } } } } else { return Array.Empty(); } } else { return Array.Empty(); } } else { List prdReports = await _db.Queryable() .LeftJoin((a, b) => a.mbom_process_id == b.id) .LeftJoin((a, b, c) => a.id == c.mo_task_id) .Where((a, b, c) => a.mo_id == prdMoTask.mo_id && b.next_process_no == null) .OrderBy((a, b, c) => c.create_time) .Select((a, b, c) => c).ToListAsync(); if (prdReports != null && prdReports.Count > 0) { List mbomProcesssIds = new() { prdMoTask.mbom_process_id }; BasMbomProcess startMbomProcess = await _db.Queryable().Where(x => x.id == prdMoTask.mbom_process_id).FirstAsync(); List allMbomProcesses = await _db.Queryable().Where(x => x.mbom_id == prdMoTask.bom_id).ToListAsync(); string startNo = startMbomProcess.next_process_no; if (!string.IsNullOrEmpty(startNo)) { while (true) { BasMbomProcess nextMbomProcess = allMbomProcesses.FirstOrDefault(x => x.no == startNo); if (nextMbomProcess == null || nextMbomProcess.no == null) { break; } else { startNo = nextMbomProcess.next_process_no; mbomProcesssIds.Add(nextMbomProcess.id); } } } else { if (!prdMoTask.mbom_process_id.Contains(prdMoTask.mbom_process_id)) { mbomProcesssIds.Add(startMbomProcess.id); } } List outputList = await _db.Queryable() .LeftJoin((a, b) => a.id == b.mbom_process_id) .Where((a, b) => mbomProcesssIds.Contains(a.id)) .Select((a, b) => b).ToListAsync(); List inputList = await _db.Queryable() .LeftJoin((a, b) => a.id == b.mbom_process_id) .Where((a, b) => mbomProcesssIds.Contains(a.id)) .Select((a, b) => b).ToListAsync(); decimal? needNum = 1;//一个最终物料需要本任务单投入物料的数量 string? tempMaterialId = outputList.FirstOrDefault(x => x.mbom_process_id == mbomProcesssIds[^1])?.material_id; for (int i = mbomProcesssIds.Count - 1; i > 0; i--) { List inputs = inputList.Where(x => x.mbom_process_id == mbomProcesssIds[i]).ToList(); BasMbomOutput output = outputList.FirstOrDefault(x => x.mbom_process_id == mbomProcesssIds[i] && x.material_id == tempMaterialId); List inputMaterialIds = inputs.Select(x => x.material_id).ToList(); List lastOutputs = outputList.Where(x => x.mbom_process_id == mbomProcesssIds[i - 1]).ToList(); // decimal? inputNum = inputs.FirstOrDefault(x => inputMaterialIds.Contains(x.material_id))?.num; BasMbomInput? basMbomInput = inputs.FirstOrDefault(x => inputMaterialIds.Contains(x.material_id)); if (basMbomInput == null) { throw new Exception("生产bom投入产出物料配置错误"); } else { tempMaterialId = inputs.FirstOrDefault(x => inputMaterialIds.Contains(x.material_id))?.material_id; needNum = needNum / (output.molecule/output.denominator) * (basMbomInput.molecule/basMbomInput.denominator); } } bool flag = true; decimal residueNeed = 0; foreach (PrdReport prdReport in prdReports) { decimal needNumTotal = prdReport.reported_qty * needNum ?? 0; if (beforeIn - needNumTotal >= 0) { beforeIn -= needNumTotal; } else { if (flag) { if (prdFeedingD.num > needNumTotal - beforeIn) { residueNeed = prdFeedingD.num - (needNumTotal - beforeIn); reportIds.Add(prdReport.id); } else { reportIds.Add(prdReport.id); break; } flag = false; continue; } if (residueNeed - needNumTotal > 0) { residueNeed -= needNumTotal; reportIds.Add(prdReport.id); } else { reportIds.Add(prdReport.id); break; } } } } else { return Array.Empty(); } } List barCodes = await _db.Queryable().Where(x => reportIds.Contains(x.id)).Select(x => x.barcode).ToListAsync(); string domain = _userManager.Domain; Dictionary header = new() { ["Authorization"] = App.HttpContext!=null ? App.HttpContext.Request.Headers["Authorization"] : "" }; Dictionary postData = new() { ["org_id"] = _userManager.GetUserInfo().Result.organizeId, ["barcode"] = barCodes, ["currentPage"] = 1, ["pageSize"] = int.MaxValue, }; string sendResult = HttpUtils.RequestPost(domain + WebApiConst.MES_FETCH_IN_OUT_STOCK_INFO_BY_BAR_CODE, JsonConvert.SerializeObject(postData), header); Log.Information(sendResult); AuthResponse authResponse = JsonConvert.DeserializeObject(sendResult); if (authResponse.code != 200) { throw Oops.Bah(authResponse.msg); } else { BasMaterial basMaterial = await _db.Queryable().FirstAsync(x => x.id == prdMoTask.material_id); PageResult output = JsonConvert.DeserializeObject>(authResponse.data.ToString(), new Tnb.Common.Utils.DateTimeJsonConverter()); if (output.list != null && output.list.Count > 0) { foreach (PrdMoReverseFromOutput item in output.list) { item.material_name = basMaterial.name; } } return output.list; } } #endregion } }