using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Aop.Api.Domain; using Aspose.Cells.Drawing; using Dm; using JNPF.Common.Contracts; using JNPF.Common.Core.Manager; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Security; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.Extras.CollectiveOAuth.Config; using JNPF.FriendlyException; using JNPF.Systems.Entitys.Dto.Module; using JNPF.Systems.Interfaces.System; using Mapster; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.CodeAnalysis; using NPOI.HPSF; using NPOI.OpenXmlFormats.Wordprocessing; using Polly.Timeout; using Senparc.Weixin.Work.AdvancedAPIs.OaDataOpen; using Spire.Pdf.Widget; using SqlSugar; using Tnb.BasicData.Entities; using Tnb.BasicData.Entities.Enums; using Tnb.Common.Utils; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Dto.Inputs; using Tnb.WarehouseMgr.Entities.Entity; using Tnb.WarehouseMgr.Entities.Enums; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.WarehouseMgr { /// /// 库房业务类(出入库) /// public class WareHouseService : BaseWareHouseService, IWareHouseService { private readonly ISqlSugarClient _db; private readonly IDictionaryDataService _dictionaryDataService; private readonly IBillRullService _billRullService; private readonly IUserManager _userManager; public WareHouseService(ISqlSugarRepository repository, IDictionaryDataService dictionaryDataService, IBillRullService billRullService, IUserManager userManager) { _db = repository.AsSugarClient(); _dictionaryDataService = dictionaryDataService; _billRullService = billRullService; _userManager = userManager; } /// /// 根据载具Id带出库位、仓库信息 /// /// 载具id /// /// returns: ///
{ ///
carry_id:载具Id ///
carry_name:载具名称 ///
location_id:库位Id ///
location_name:库位名称 ///
warehouse_id:库房Id ///
warehouse_name:库房名称 ///
} ///
[HttpGet] public async Task GetLocationAndWorkHouseByCarryId([FromRoute] string carryId) { var items = await _db.Queryable().LeftJoin((a, b) => a.location_id == b.id) .LeftJoin((a, b, c) => b.wh_id == c.id) .Where(a => a.id == carryId) .Select((a, b, c) => new { carry_id = a.id, carry_name = a.carry_name, location_id = b.id, location_name = b.location_name, warehouse_id = c.id, warehouse_name = c.whname, }) .ToListAsync(); return items ?? Enumerable.Empty(); } /// /// 库房业务,入库、出库申请新增修改功能 /// /// /// [HttpPost] public async Task ApplyFor(InOutStockApplyforUpInput input) { if (input == null) throw new ArgumentNullException(nameof(input)); async Task _updateLocalFunc(InOutStockApplyforUpInput input) where TStockD : BaseEntity, new() where TStockCode : BaseEntity, IInOutStockCode, new() { var instockD = input.Adapt(); var stockCodes = input.InstockCodes?.Adapt>(); if (stockCodes?.Count > 0) { stockCodes.ForEach(x => { if (x.id.IsNullOrWhiteSpace()) { x.id = SnowflakeIdHelper.NextId(); } x.bill_d_id = instockD.id; }); } return await Update(instockD, stockCodes!); } var isOk = input.inoutStockType switch { EnumInOutStockType.In => await _updateLocalFunc(input), EnumInOutStockType.Out => await _updateLocalFunc(input), _ => throw new ArgumentOutOfRangeException(nameof(input.inoutStockType), $"Not expected EnumInOutStockType value: {input.inoutStockType}"), }; if (!isOk) throw Oops.Oh(ErrorCode.COM1001); } /// /// 根据明细Id获取出入库明细信息 /// /// [HttpGet] public async Task GetInOutStockCodesById([FromQuery] InOutStockDetailQuery input) { dynamic? result = input.inoutStockType switch { EnumInOutStockType.In => await FetchInOutStockCodesById(input.bill_d_id), EnumInOutStockType.Out => await FetchInOutStockCodesById(input.bill_d_id), _ => throw new ArgumentOutOfRangeException(nameof(input.inoutStockType), $"Not expected EnumInOutStockType value: {input.inoutStockType}"), }; return result ?? Enumerable.Empty(); } /// /// 入库策略 /// /// [HttpGet] public async Task> InStockStrategy([FromQuery] InStockStrategyQuery input) { var items = new List(); try { //var stauts = (int)EnumCarryStatus.空闲; items = await _db.Queryable().Where(it => it.wh_id == input.warehouse_id && it.is_lock == 0 && it.is_type == "0" && it.is_use == ((int)EnumCarryStatus.空闲).ToString()).OrderBy(it => new { it.layers, it.loc_line, it.loc_column }, OrderByType.Asc).ToListAsync(); } catch (Exception) { throw; } return items.Take(input.Size).ToList(); } /// /// 出库策略 /// /// [HttpGet] public async Task OutStockStrategy() { return await Task.FromResult(true); } /// /// 生成任务执行 /// /// [HttpPost] public async Task GenTaskExecute() { //任务链属性处理内部函数 async Task _taskChainAttrHandle(List items, List areaPreTasks, int moveNum) { var groupCode = await _billRullService.GetBillNumber(WmsWareHouseConst.WMS_TASK_EXECUTE_ENCODE); await Task.Run(() => { if (moveNum == 1 || (moveNum > areaPreTasks.Count && areaPreTasks.Count == 1)) { items.ForEach(x => { x.is_chain = 0; }); items[0].groups = groupCode; items[0].bill_code = $"{groupCode}-1"; } else if ((moveNum > areaPreTasks.Count && areaPreTasks.Count > 1) || moveNum < areaPreTasks.Count) { items.ForEach(x => x.is_chain = 1); var itemsCount = items.Count; var mod = items.Count % moveNum > 0 ? itemsCount / moveNum + 1 : itemsCount / moveNum; var start = 0; var end = Math.Min(itemsCount, moveNum); var arrary = items.ToArray(); for (int i = 1; i <= mod; i++) { if (start >= itemsCount) break; var subArray = arrary[start..end]; for (int j = 0, arrLen = subArray.Length; j < arrLen; j++) { subArray[j].groups = groupCode; subArray[j].bill_code = $"{groupCode}-{i}"; } start = end; end = Math.Min((end + moveNum), arrary.Length); } } }); } //获取所有未下发的预任务申请 var preTasks = await _db.Queryable().InnerJoin((a, b) => a.startlocation_id == b.location_id && a.carry_id == b.id) .InnerJoin((a, b, c) => a.area_id == c.id) .Where(a => a.status == WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID) .OrderBy(a => new { priority = SqlFunc.Desc(a.priority), a.bill_code }) .Select((a, b, c) => new WmsPretaskH { move_num = c.move_num }, true) .ToListAsync(); var ids = preTasks.Select(x => x.id).Distinct().ToList(); var preTaskCodes = await _db.Queryable().Where(it => ids.Contains(it.bill_id)).ToListAsync(); if (preTasks.Count > 0) { //根据预任务管理区分组,获取到所有分组后的预任务,遍历每个预任务 是否为任务链,通过管理区ID var preTaskGroups = preTasks.GroupBy(g => g.area_code).ToList(); List disTasks = new(); List distaskCodes = new(); foreach (var itGroup in preTaskGroups) { var moveNum = itGroup.First().move_num; var items = itGroup.Adapt>(); for (int i = 0, cnt = items.Count; i < cnt; i++) { items[i].id = SnowflakeIdHelper.NextId(); items[i].status = WmsWareHouseConst.TASK_BILL_STATUS_DZX_ID; //items[i].groups = await _billRullService.GetBillNumber(WmsWareHouseConst.WMS_TASK_EXECUTE_ENCODE); } if (moveNum == 1) { items.ForEach(x => { x.is_chain = 0; //x.chain_type = "3"; }); } else if (moveNum > 1) { var areaPreTasks = itGroup.ToList(); //搬运数量==预任务数,可以生成任务执行,为任务链 if (moveNum == areaPreTasks.Count) { await _taskChainAttrHandle(items, areaPreTasks, moveNum); } else if (moveNum > areaPreTasks.Count && areaPreTasks.Count == 1) //搬运数量>预任务数,且预任务数等于1,不是任务链,预任务数据平替到任务执行 { await _taskChainAttrHandle(items, areaPreTasks, moveNum); } else if (moveNum > areaPreTasks.Count && areaPreTasks.Count > 1) //搬运数量>预任务数,且预任务数大于1,可以执行时,可以生成任务执行,为任务链 { await _taskChainAttrHandle(items, areaPreTasks, moveNum); } else if (false) //搬运数量>预任务数,且预任务数大于1,不可以执行时,先空着 { } else if (moveNum < areaPreTasks.Count) //搬运数量<预任务数, 按照预任务先后顺序,生成对应搬运数量的任务组 { await _taskChainAttrHandle(items, areaPreTasks, moveNum); } } if (preTaskCodes?.Count > 0) { foreach (var disTask in items) { var curPreTaskCodes = preTaskCodes.FindAll(x => x.bill_id == disTask.pretask_id); var curDisTaskCodes = curPreTaskCodes.Adapt>(); curDisTaskCodes.ForEach(x => { x.id = SnowflakeIdHelper.NextId(); x.bill_id = disTask.id; x.create_time = DateTime.Now; }); distaskCodes.AddRange(curDisTaskCodes); } } disTasks.AddRange(items); } try { await _db.Ado.BeginTranAsync(); //disTasks.ForEach(x => x.id = SnowflakeIdHelper.NextId()); var row = await _db.Insertable(disTasks).ExecuteCommandAsync(); if (preTaskCodes?.Count > 0) { row = await _db.Insertable(distaskCodes).ExecuteCommandAsync(); } if (row > 0) { var preTaskIds = preTasks.Select(x => x.id).ToList(); row = await _db.Updateable().SetColumns(it => new WmsPretaskH { status = WmsWareHouseConst.PRETASK_BILL_STATUS_YXF_ID }).Where(it => preTaskIds.Contains(it.id)).ExecuteCommandAsync(); } await _db.Ado.CommitTranAsync(); } catch (Exception) { await _db.Ado.RollbackTranAsync(); } } } /// /// 任务执行 /// /// /// [HttpPost] public async Task TaskExecute(TaskExecuteUpInput input) { try { await _db.Ado.BeginTranAsync(); //更任务执行 for (int i = 0, cnt = input.disTaskIds.Count; i < cnt; i++) { if (input.EqpIds?.Count > 0) { await _db.Updateable().SetColumns(it => new WmsDistaskH { status = WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID, device_id = input.EqpIds[i] }).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync(); } else { await _db.Updateable().SetColumns(it => new WmsDistaskH { status = WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID }).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync(); } //await _db.Updateable().SetColumns(it => setColVal).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync(); } var preTaskIds = await _db.Queryable().Where(it => input.disTaskIds.Contains(it.id)).Select(it => it.pretask_id).ToListAsync(); if (preTaskIds.Count > 0) { //更预任务申请表状态 await _db.Updateable().SetColumns(it => new WmsPretaskH { status = WmsWareHouseConst.PRETASK_BILL_STATUS_START_ID }).Where(it => preTaskIds.Contains(it.id)).ExecuteCommandAsync(); } await _db.Ado.CommitTranAsync(); } catch (Exception) { await _db.Ado.RollbackTranAsync(); throw; } } /// /// 任务执行取操作返回(后续操作) /// /// [HttpPost] public async Task TaskExecuteAfter(TaskExecuteAfterUpInput input) { //更新任务执行表单据状态 try { await _db.Ado.BeginTranAsync(); await _db.Updateable().SetColumns(it => new WmsDistaskH { status = WmsWareHouseConst.TASK_BILL_STATUS_RUNING_ID }).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync(); //清空载具库位数据 var carryAndLocIds = await _db.Queryable().Where(it => input.disTaskIds.Contains(it.id)).Select(it => new { it.carry_id, it.startlocation_id }).ToListAsync(); if (carryAndLocIds?.Count > 0) { var carryIds = carryAndLocIds.Select(x => x.carry_id).ToList(); await _db.Updateable().SetColumns(it => new WmsCarryH { location_id = null, location_code = null }).Where(it => carryIds.Contains(it.id)).ExecuteCommandAsync(); } //更新起始库位,状态改为空闲、锁定状态,未锁定 if (carryAndLocIds?.Count > 0) { var startLocationIds = carryAndLocIds.Select(x => x.startlocation_id).ToList(); await _db.Updateable().SetColumns(it => new BasLocation { is_use = ((int)EnumCarryStatus.空闲).ToString(), is_lock = 0 }).Where(it => startLocationIds.Contains(it.id)).ExecuteCommandAsync(); } await _db.Ado.CommitTranAsync(); } catch (Exception) { await _db.Ado.RollbackTranAsync(); } } /// /// 任务完成 /// /// [HttpPost] public async Task TaskComplate(TaskCompleUpInput input) { try { await _db.Ado.BeginTranAsync(); //更新任务执行表,单据状态为 完成 await _db.Updateable().SetColumns(it => new WmsDistaskH { status = WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID }).Where(it => input.disTaskIds.Contains(it.id)).ExecuteCommandAsync(); //更新预任务申请表,单据状态为 已完成 var disTasks = await _db.Queryable().InnerJoin((a, b) => a.carry_id == b.id).Where(a => input.disTaskIds.Contains(a.id)).Select((a, b) => new WmsDistaskH { carry_status = b.carry_status }, true).ToListAsync(); if (disTasks?.Count > 0) { var preTaskIds = disTasks.Select(x => x.pretask_id).ToList(); await _db.Updateable().SetColumns(it => new WmsPretaskH { status = WmsWareHouseConst.PRETASK_BILL_STATUS_COMPLE_ID }).Where(it => preTaskIds.Contains(it.id)).ExecuteCommandAsync(); } //更新载具,锁定状态为未锁定,更新载具的库位当前任务的目标库位 if (disTasks?.Count > 0) { var multiList = disTasks.Select(it => (it.carry_id, it.endlocation_id, it.endlocation_code)).ToList(); for (int i = 0; i < multiList.Count; i++) { await _db.Updateable().SetColumns(it => new WmsCarryH { is_lock = 0, location_id = multiList[i].endlocation_id, location_code = multiList[i].endlocation_code }).Where(it => it.id == multiList[i].carry_id).ExecuteCommandAsync(); //更新条码的库位和仓库信息 var carryCodes = await _db.Queryable().Where(it => it.id == multiList[i].carry_id).ToListAsync(); if (carryCodes?.Count > 0) { var loc = await _db.Queryable().SingleAsync(it => it.id == multiList[i].endlocation_id); await _db.Updateable().SetColumns(it => new WmsCarryCode { warehouse_id = loc.wh_id, location_id = multiList[i].endlocation_id, location_code = multiList[i].endlocation_code }).Where(it => it.id == multiList[i].carry_id).ExecuteCommandAsync(); } } } //更新库位信息,使用状态为 使用,锁定状态为未锁定 if (disTasks?.Count > 0) { var multis = disTasks.Select(it => (it.endlocation_id, it.carry_status)).ToList(); for (int i = 0; i < multis.Count; i++) { var carryStatus = multis[i].carry_status; if (multis[i].carry_status == ((int)EnumCarryStatus.空闲).ToString()) { carryStatus = ((int)EnumCarryStatus.占用).ToString(); } var cStatus = carryStatus.ParseToInt(); await _db.Updateable().SetColumns(it => new BasLocation { is_use = cStatus.ToString(), is_lock = 0 }).Where(it => it.id == multis[i].endlocation_id).ExecuteCommandAsync(); } //更新业务主表的单据状态 if (disTasks?.Count > 0) { foreach (var dt in disTasks) { var disTaskCodes = await _db.Queryable().Where(it => it.bill_id == dt.id).ToListAsync(); var upInput = new WareHouseUpInput { bizTypeId = dt.biz_type, requireId = dt.require_id!, distaskCodes = disTaskCodes, carryIds = disTasks.Select(x => x.carry_id).ToList() }; upInput.loginType = !_userManager.LoginType.IsNullOrEmpty() ? "app" : "web"; if (dt.is_sign == 1 && dt.chain_type == "3") { await DoUpdate(upInput); } } } await _db.Ado.CommitTranAsync(); } } catch (Exception) { await _db.Ado.RollbackTranAsync(); } } /// /// 出入库策略启用、禁用状态修改 /// /// /// [HttpPost] public async Task ModifyPoliciesStatus(ModifyPoliciesStatusInput input) { async Task _updateStatus(ModifyPoliciesStatusInput input) where T : BaseEntity, IUpdatePoliciesStatus, new() { T obj = new() { status = input.status }; await _db.Updateable(obj).UpdateColumns(it => it.status).Where(it => input.ids.Contains(it.id)).ExecuteCommandAsync(); } switch (input.strategyType) { case EnumInOutStockType.In: await _updateStatus(input); break; case EnumInOutStockType.Out: await _updateStatus(input); break; } } /// /// 生成预任务 /// /// 预任务集合 /// 预任务编码集合 /// public async Task GenPreTask(List preTasks, List preTaskCodes) { var grpList = preTasks.OrderBy(o => o.bill_code).GroupBy(g => g.carry_id).ToList(); if (grpList?.Count > 0) { foreach (var grp in grpList) { var arr = grp.ToArray(); if (arr.Length > 1) { var subArr = arr[..^1]; System.Array.ForEach(subArr, a => a.chain_type = "1"); } } } var row = await _db.Insertable(preTasks).ExecuteCommandAsync(); if (preTaskCodes?.Count > 0) { row = await _db.Insertable(preTaskCodes).ExecuteCommandAsync(); } return row > 0; } /// /// 生成预任务后续处理 /// /// [NonAction] public async Task GenInStockTaskHandleAfter(GenPreTaskUpInput input, Expression> setCarryColumnsExp, Expression> setLocaionColumbExp) { try { await _db.Ado.BeginTranAsync(); //根据生成的预任务,插入预任务操作记录 if (input.PreTaskRecord != null) { await _db.Insertable(input.PreTaskRecord).ExecuteCommandAsync(); } if (input.PreTaskHandleCodes.Count > 0) { await _db.Insertable(input.PreTaskHandleCodes).ExecuteCommandAsync(); } //根据载具ID,更新是否锁定和赋值起始库位 if (setCarryColumnsExp != null) { Expression> whereExp = input.CarryIds?.Count > 0 ? it => input.CarryIds.Contains(it.id) : it => it.id == input.CarryId; await _db.Updateable().SetColumns(setCarryColumnsExp).Where(whereExp).ExecuteCommandAsync(); } //根据所有库位更新库位的锁定状态为“锁定” if (setLocaionColumbExp != null && input.LocationIds?.Count > 0) { await _db.Updateable().SetColumns(setLocaionColumbExp).Where(it => input.LocationIds.Contains(it.id)).ExecuteCommandAsync(); } await _db.Ado.CommitTranAsync(); } catch (Exception) { await _db.Ado.RollbackTranAsync(); throw; } } /// /// 路径算法 /// /// /// /// [NonAction] public async Task> PathAlgorithms(string pStartId, string pEndId) { var roads = await _db.Queryable().ToListAsync(); var points = await LocPathCalcAlgorithms(pStartId, pEndId, roads); return points; } #region PrivateMethods private async Task> LocPathCalcAlgorithms(string pStartId, string pEndId, List roads) { var points = await _db.Queryable().ToListAsync(); List results = new(); Dictionary isVisited = roads.Select(x => x.startpoint_id).Distinct().ToDictionary(x => x, x => false); List pointIds = new(); List codes = new(); Dp dp = new(); dynamic obj = new ExpandoObject(); obj.isArrivedEpoint = false; dp.DpFunc(roads, pointIds, isVisited, pStartId, pEndId, obj); foreach (var pid in pointIds) { var point = points.Find(x => x.id == pid); if (point != null) { results.Add(point); } } return results; #region dijkstra //var points = await _db.Queryable().ToListAsync(); //var startObj = points.Find(x => x.id == pStartId); //var endObj = points.Find(x => x.id == pEndId); //var sIndex = points.IndexOf(startObj); //var eIndex = points.IndexOf(endObj); //if (eIndex < sIndex) //{ // var tempIndex = sIndex; // sIndex = eIndex; // eIndex = tempIndex; // var temp = points[sIndex]; // points[sIndex] = points[eIndex]; // points[eIndex] = temp; //} ////MatchPoint(results, roads, shortestPathPoints, isVisited, pStartId, pEndId); //var vexs = points.Select(p => p.id).ToArray(); //EData[] edges = new EData[roads.Count]; //for (int i = 0; i < edges.Length; i++) //{ // var start = roads[i].startpoint_id; // var end = roads[i].endpoint_id; // var weight = roads[i].distance; // edges[i] = new EData(start, end, weight); //} //Dijkstra pG = new(vexs, edges); //int[] prev = new int[pG.mVexs.Length]; //int[] dist = new int[pG.mVexs.Length]; //List vertexs = new() { startObj }; //pG.CalcDijkstra(sIndex, prev, dist); //var pointIds = points.Select(p => p.id).ToList(); //List result = new(); //GetPoints(pointIds, prev, result, eIndex); //var items =new List(); //foreach (var item in prev.Where(x=>x!=0)) //{ // if (points[item] != null) // { // items.Add(points[item].point_code); // } //} //var @strings = string.Join(",", items.OrderBy(o=>o)); //var shortestPathPoints = points.FindAll(x => result.Contains(x.id)); //if (shortestPathPoints.IndexOf(startObj) < 0) //{ // shortestPathPoints.Add(startObj); //} //List results = new() { startObj }; //var isVisited = shortestPathPoints.ToDictionary(x => x.id, x => false); //var isVisited2 = shortestPathPoints.ToDictionary(x => x.id, x => false); //isVisited[pStartId] = true; //MatchPoint(results, roads, shortestPathPoints, isVisited, pStartId, pEndId); //results.Add(endObj); #endregion } /// /// 获取匹配的最短路径节点 /// /// /// /// /// /// /// private void MatchPoint(List results, List roads, List shortestPathPoints, Dictionary isVisited, string pStartId, string pEndId) { var sRoads = roads.Where(x => x.startpoint_id == pStartId).ToList(); for (int j = 0; j < sRoads.Count; j++) { var sPoint = shortestPathPoints.Find(x => x.id == sRoads[j].endpoint_id); if (sPoint != null && isVisited.ContainsKey(sPoint.id) && !isVisited[sPoint.id] && sPoint.id != pEndId) { var code = sPoint.point_code; results.Add(sPoint); isVisited[sPoint.id] = true; MatchPoint(results, roads, shortestPathPoints, isVisited, sPoint.id, pEndId); } } } /// /// 根据终止节点获取最短路径顶点 /// /// /// /// /// private static void GetPoints(List pointIds, int[] prev, List result, int eIdx) { var index = eIdx; while (index != 0) { result.Add(pointIds[index]); index = prev[index]; } } private async Task Update(T1 entity, List entities) where T1 : BaseEntity, new() where T2 : BaseEntity, new() { var isOk = false; try { await _db.Ado.BeginTranAsync(); isOk = await _db.Updateable(entity).ExecuteCommandHasChangeAsync(); if (entities?.Count > 0) { var row = await _db.Storageable(entities).ExecuteCommandAsync(); isOk = row > 0; } await _db.Ado.CommitTranAsync(); } catch (Exception) { await _db.Ado.RollbackTranAsync(); } return isOk; } /// /// 根据明细Id获取出入库明细信息 /// /// 出入库明细 /// 明细输出类 /// 出入库条码 /// 明细Id /// private async Task FetchInOutStockCodesById(string billDId) where TStockD : BaseEntity, new() where TOutput : IInOutStockDetail, new() where TStockCode : BaseEntity, IInOutStockCode, new() { var dic = await _dictionaryDataService.GetDictionaryByTypeId(WmsWareHouseConst.WMS_INSTOCK_D_BILL_STATUS_TYPEID); var data = await _db.Queryable() .Where(a => a.id == billDId) .Select(a => new TOutput { CodeDetails = SqlFunc.Subqueryable().Where(it => it.bill_d_id == a.id).ToList(), }, true) .Mapper(it => it.line_status = it.line_status != null && dic.ContainsKey(key: it.line_status) ? dic[it.line_status]?.ToString() : "") .ToListAsync(); return data; } #endregion } }