using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using JNPF.Common.Core.Manager; using JNPF.Common.Filter; using JNPF.EventBus; using JNPF.Systems.Interfaces.System; using JNPF.VisualDev; using JNPF.VisualDev.Entitys.Dto.VisualDevModelData; using JNPF.VisualDev.Interfaces; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using SqlSugar; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Attributes; using Tnb.WarehouseMgr.Entities.Entity; using Tnb.WarehouseMgr.Interfaces; using JNPF.Common.Dtos.VisualDev; using JNPF.Common.Extension; using JNPF.Common.Security; using JNPF.FriendlyException; using JNPF.VisualDev.Entitys; using Microsoft.AspNetCore.Authorization; using Tnb.BasicData.Entities; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Enums; using JNPF.Common.Enums; using Tnb.WarehouseMgr.Entities.Dto.Inputs; using Microsoft.Extensions.Logging; using JNPF.Systems.Entitys.System; using JNPF.Systems.Entitys.Permission; namespace Tnb.WarehouseMgr { /// /// 原材料转库单 /// [OverideVisualDev(ModuleConsts.MODULE_WMSMATERIALTRANSFER_ID)] [ServiceModule(BizTypeId)] public class WmsMaterialTransferService : BaseWareHouseService { private const string BizTypeId = ""; private readonly ISqlSugarClient _db; private readonly IRunService _runService; private readonly IVisualDevService _visualDevService; private readonly IWareHouseService _wareHouseService; private readonly IBillRullService _billRullService; private readonly IUserManager _userManager; public WmsMaterialTransferService( ISqlSugarRepository repository, IRunService runService, IVisualDevService visualDevService, IWareHouseService wareHouseService, IUserManager userManager, IBillRullService billRullService, IEventPublisher eventPublisher) { _db = repository.AsSugarClient(); _runService = runService; _visualDevService = visualDevService; _wareHouseService = wareHouseService; _userManager = userManager; _billRullService = billRullService; OverideFuncs.GetListAsync = GetList; } [NonAction] private async Task GetList(VisualDevModelListQueryInput input) { try { SqlSugarPagedList result = await _db.Queryable() .InnerJoin((a, b) => a.status == b.Id) .InnerJoin((a, b, c) => c.Id == a.create_id) .InnerJoin((a, b, c, d) => d.id == a.warehouse_outstock) .InnerJoin((a, b, c, d, e) => e.id == a.warehouse_instock) .Select((a, b, c, d, e) => new WmsMaterialTransfer { id = a.id, create_id = c.RealName, create_time = a.create_time, modify_id = a.modify_id, modify_time = a.modify_time, org_id = a.org_id, tenant_id = a.tenant_id, timestamp = a.timestamp, bill_code = a.bill_code, status = b.FullName, bill_date = a.bill_date, warehouse_outstock = d.whname, warehouse_instock = d.whname, type = a.type, biller_out = a.biller_out, depart_out = a.depart_out, biller_in = a.biller_in, depart_in = a.depart_in, deliver_date = a.deliver_date, arrival_date = a.arrival_date, order_code = a.order_code, }) .ToPagedListAsync(input.currentPage, input.pageSize); var _data = PageResult.SqlSugarPageResult(result); var json = JsonConvert.SerializeObject(_data); var data = JsonConvert.DeserializeObject(json); JArray mainTable = data.list; foreach (dynamic row in mainTable) { row.deliver_date = row.deliver_date.Value.ToString("yyyy-MM-dd"); row.arrival_date = row.arrival_date.Value.ToString("yyyy-MM-dd"); row.create_time = row.create_time.Value.ToString("yyyy-MM-dd"); } List wmsTransferInstockDs = _db.Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.material_id == b.id) ) .Select((a, b) => new WmsMaterialTransferD { id = a.id, material_id = a.material_id, material_code = b.code, material_ex = b.name, material_specification = b.material_specification, unit_id = a.unit_id, unit_code = a.unit_code, code_batch = a.code_batch, station_code = a.station_code, qty = a.qty, yxfqty = a.yxfqty, yzqty = a.yzqty, bill_id = a.bill_id, lineno = a.lineno, f_flowtaskid = a.f_flowtaskid, f_flowid = a.f_flowid, }) .Where(a => mainTable.Select(r => r["id"].ToString()).ToList().Contains(a.bill_id)).ToList(); foreach (JObject wmsTransferInstockH in mainTable) { wmsTransferInstockH["tablefield121"] = JArray.Parse(JsonConvert.SerializeObject(wmsTransferInstockDs.Where(r => r.bill_id == wmsTransferInstockH["id"].ToString()))); } return data; } catch (Exception ex) { return Task.FromResult(ex); } } /// /// 获取物料库存 /// /// /// /// [HttpPost, NonUnify, AllowAnonymous] public async Task MaterialInventory(MaterialTransferGetMaterialInventoryInput input) { try { if (input.palletCount <= 0) { throw new AppFriendlyException("托盘数必须大于0", 500); } if (string.IsNullOrEmpty(input.material_id)) { throw new AppFriendlyException("物料id不可为空", 500); } if (string.IsNullOrEmpty(input.code_batch)) { throw new AppFriendlyException("批号不可为空", 500); } //入库取终点 //出库起点 OutStockStrategyQuery inStockStrategyInput = new() { warehouse_id = WmsWareHouseConst.WAREHOUSE_YCL_ID, material_id = input.material_id, code_batch = input.code_batch, Size = input.palletCount }; List items = await _wareHouseService.OutStockStrategy(inStockStrategyInput); decimal qty = _db.Queryable().Where(r => items.Select(a => a.id).Contains(r.carry_id) && r.material_id == input.material_id).Sum(r => r.codeqty); JObject keyValuePairs = new JObject(); keyValuePairs["realPalletCount"] = items.Count; keyValuePairs["realInvQty"] = qty; return await ToApiResult(HttpStatusCode.OK, "成功", keyValuePairs); } catch (Exception ex) { await _db.Ado.RollbackTranAsync(); return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message); } } /// /// 按托下发 /// /// /// /// [HttpPost, NonUnify, AllowAnonymous] public async Task Distribute(MaterialTransferDistributeInput input) { try { if (string.IsNullOrEmpty(input.source_id)) { throw new AppFriendlyException("来源单据id不可为空", 500); } if (input.palletCount <= 0) { throw new AppFriendlyException("托盘数必须大于0", 500); } if (input.qty <= 0) { throw new AppFriendlyException("数量必须大于0", 500); } if (string.IsNullOrEmpty(input.code_batch)) { throw new AppFriendlyException("批号不可为空", 500); } WmsMaterialTransferD wmsMaterialTransferD = await _db.Queryable().FirstAsync(it => it.id == input.source_id); WmsMaterialTransfer wmsMaterialTransfer = await _db.Queryable().FirstAsync(it => it.id == wmsMaterialTransferD.bill_id); await s_taskExecuteSemaphore.WaitAsync(); await _db.Ado.BeginTranAsync(); //入库取终点 //出库起点 OutStockStrategyQuery inStockStrategyInput = new() { warehouse_id = WmsWareHouseConst.WAREHOUSE_YCL_ID, material_id = wmsMaterialTransferD.material_id, code_batch = wmsMaterialTransferD.code_batch, Size = input.palletCount }; List items = await _wareHouseService.OutStockStrategy(inStockStrategyInput); if (items.Count == 0) { throw new AppFriendlyException($@"没有可以出库的载具", 500); } decimal qty = _db.Queryable().Where(r => items.Select(a => a.id).Contains(r.carry_id) && r.material_id == wmsMaterialTransferD.material_id).Sum(r => r.codeqty); // 暂定PDA上查询到的物料批次和库存数量与提交时获取的不一致时,需要前台重新获取库存接口 if (input.palletCount != items.Count || input.qty != qty) { throw new AppFriendlyException($@"当前实际托盘数量为{input.palletCount} 实际库存数量为{qty},与前台数据不一致,请重新获取库存", HttpStatusCode.InternalServerError); } foreach(var wmsCarryH in items) { WmsCarryCode wmsCarryCode = await _db.Queryable().Where(r => r.carry_id == wmsCarryH.id).FirstAsync(); BasLocation startLocation = await _db.Queryable().Where(r => r.location_code == wmsCarryH.location_code).FirstAsync(); BasLocation endLocation = null; // 集中供料区三工位 if (wmsMaterialTransfer.warehouse_instock == WmsWareHouseConst.WAREHOUSE_JZGL_ID) { // 根据三工位任务数平均分配任务 暂定 endLocation = await _db.Queryable().Where(r => _wareHouseService.GetFloor1GLSGWOutstockLocation().Contains(r.id)).OrderBy("is_lock, task_nums, location_code").FirstAsync(); } // 中储仓三工位 else if(wmsMaterialTransfer.warehouse_instock == WmsWareHouseConst.WAREHOUSE_ZC_ID) { // 根据三工位任务数平均分配任务 暂定 endLocation = await _db.Queryable().Where(r => _wareHouseService.GetFloor1WXSGWOutstockLocation().Contains(r.id)).OrderBy("is_lock, task_nums, location_code").FirstAsync(); } CommonCreatePretaskInput commonCreatePretaskInput = new CommonCreatePretaskInput(); commonCreatePretaskInput.startlocation_id = startLocation.id; commonCreatePretaskInput.endlocation_id = endLocation.id; commonCreatePretaskInput.task_type = WmsWareHouseConst.WMS_PRETASK_OUTSTOCK_TYPE_ID; commonCreatePretaskInput.biz_type = WmsWareHouseConst.BIZTYPE_WMSMATERIALTRANSFER_ID; commonCreatePretaskInput.require_id = input.source_id; Entities.Dto.Outputs.Result res = await _wareHouseService.CommonCreatePretask(commonCreatePretaskInput); if (res.code != HttpStatusCode.OK) { Logger.LogInformation($@"生成预任务失败"); throw new AppFriendlyException($@"生成预任务失败", 500); } } // 更新子表已下发数量 await _db.Updateable().SetColumns(r => r.yxfqty == r.yxfqty + input.qty).Where(r => r.id == input.source_id).ExecuteCommandAsync(); await _db.Ado.CommitTranAsync(); } catch (Exception ex) { await _db.Ado.RollbackTranAsync(); return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message); } finally { _ = s_taskExecuteSemaphore.Release(); await InvokeGenPretaskExcute(); } return await ToApiResult(HttpStatusCode.OK, "成功"); } public override async Task ModifyAsync(WareHouseUpInput input) { if (input == null) { throw new ArgumentNullException(nameof(input)); } WmsCarryCode wmsCarryCode = await _db.Queryable().Where(r => r.carry_id == input.carryIds[0]).SingleAsync(); bool isOk = await _db.Updateable().SetColumns(it => new WmsMaterialTransferD { yzqty = it.yzqty + wmsCarryCode.codeqty }) .Where(it => it.id == input.requireId).ExecuteCommandHasChangeAsync(); if (!isOk) { throw Oops.Oh(ErrorCode.COM1001); } } } }