using System; using System.Drawing; using System.Linq; using System.Threading.Tasks; using Aliyun.OSS; using Infrastructure; using Infrastructure.Attribute; using Infrastructure.Extensions; using JinianNet.JNTemplate; using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.AspNetCore.Http.HttpResults; using Newtonsoft.Json.Linq; using SqlSugar; using ZR.Common; using ZR.Model; using ZR.Model.MES.qc.DTO; using ZR.Model.MES.wms; using ZR.Model.MES.wms.Dto; using ZR.Model.System; using ZR.Repository; using ZR.Service.mes.qc; using ZR.Service.mes.wms.IService; using static System.Runtime.InteropServices.JavaScript.JSType; namespace ZR.Service.mes.wms { /// /// 工艺路线-抛光 库存表Service业务层处理 /// [AppService( ServiceType = typeof(IWmPolishInventoryService), ServiceLifetime = LifeTime.Transient )] public class WmPolishInventoryService : BaseService, IWmPolishInventoryService { /// /// 查询工艺路线-抛光 库存表列表 /// /// /// public WmPolishInventoryTableDto GetList(WmPolishInventoryQueryDto parm) { var list = Context .Queryable() .LeftJoin((m, p) => m.Partnumber == p.Partnumber) .Distinct() //.GroupBy((m, p) => p.Partnumber) .WhereIF( !string.IsNullOrEmpty(parm.Description), (m, p) => m.Description.Contains(parm.Description) ) .WhereIF( !string.IsNullOrEmpty(parm.Partnumber), (m, p) => m.Partnumber.Contains(parm.Partnumber) ) .Where((m, p) => m.Status == 1) .Where((m, p) => m.Type == 1) .WhereIF(parm.Status > -1, (m, p) => p.Status == parm.Status) .WhereIF(parm.Type > 0, (m, p) => p.Type == parm.Type) .OrderBy((m, p) => m.Description) .Select( (m, p) => new WmPolishInventoryDto { RealQuantity = 0, Color = m.Color, Specification = m.Specification, Description = m.Description, Id = p.Id, BlankNum = p.BlankNum, Partnumber = p.Partnumber, Quantity = p.Quantity, MaxNum = p.MaxNum, MinNum = p.MinNum, WarnNum = p.WarnNum, Type = p.Type, Status = p.Status, Remark = p.Remark, CreatedBy = p.CreatedBy, CreatedTime = p.CreatedTime, UpdatedBy = p.UpdatedBy, UpdatedTime = p.UpdatedTime, } ) .ToList(); foreach (WmPolishInventoryDto item in list) { // 获取实际库存 List partnumbers = new() { item.Partnumber }; Dictionary dict = GetBatchPolishRealPartNum(partnumbers); item.RealQuantity = dict.TryGetValue(item.Partnumber, out int value) ? value : 0; } list = list.Where(it => it.RealQuantity != 0 || it.Quantity != 0) .Where(it => !string.IsNullOrEmpty(it.Partnumber)) .DistinctBy(it => it.Partnumber) .ToList(); int total = list.Count; // 仓库总盘点零件数 int StocktakingTotal = Context.Queryable().Sum(it => it.Quantity) ?? 0; // 仓库当前查询盘点零件数 int QuantitySum = list.Sum(it => it.Quantity) ?? 0; // 仓库当前查询实际零件数 int RealQuantitySum = list.Sum(it => it.RealQuantity); WmPolishInventoryTableDto response = new() { Total = total, StocktakingTotal = StocktakingTotal, QuantitySum = QuantitySum, RealQuantitySum = RealQuantitySum, Result = list.Skip((parm.PageNum - 1)* parm.PageSize).Take(parm.PageSize).ToList(), }; return response; //TODO 历史查询 /*List partnumberByDescription = new(); if (parm != null && !string.IsNullOrEmpty(parm.Description)) { partnumberByDescription = Context .Queryable() .Where(it => it.Description.Contains(parm.Description)) .Select(it => it.Partnumber) .ToList(); } var predicate = Expressionable .Create() .AndIF( !string.IsNullOrEmpty(parm.Description), it => partnumberByDescription.Contains(it.Partnumber) ) .AndIF( !string.IsNullOrEmpty(parm.Partnumber), it => it.Partnumber.Contains(parm.Partnumber) ) .AndIF(parm.Status > -1, it => it.Status == parm.Status) .AndIF(parm.Type > 0, it => it.Type == parm.Type); var response = Queryable() .Where(predicate.ToExpression()) .OrderByDescending(it => it.Quantity) .ToPage(parm); if (response.Result.Count > 0) { foreach (WmPolishInventoryDto item in response.Result) { // 获取物料信息 WmMaterial material = Context .Queryable() .Where(it => it.Partnumber == item.Partnumber) .Where(it => it.Type == 1) .Where(it => it.Status == 1) .First(); if (material == null) { item.Description = "此零件号不在物料清单内!"; continue; } item.Color = material.Color; item.Specification = material.Specification; item.Description = !string.IsNullOrEmpty(material.Description) ? material.Description : material.ProductName; // 获取实际库存 List partnumbers = new List(); partnumbers.Add(item.Partnumber); Dictionary dict = GetBatchPolishRealPartNum(partnumbers); item.RealQuantity = dict.TryGetValue(item.Partnumber, out int value)? value : 0; } } return response;*/ } /// /// 获取详情 /// /// /// public WmPolishInventory GetInfo(string Id) { var response = Queryable().Where(x => x.Id == Id).First(); return response; } /// /// 添加工艺路线-抛光 库存表 /// /// /// public WmPolishInventory AddWmPolishInventory(WmPolishInventory model) { return Context.Insertable(model).ExecuteReturnEntity(); } /// /// 修改工艺路线-抛光 库存表 /// /// /// public int UpdateWmPolishInventory(WmPolishInventory model) { //var response = Update(w => w.Id == model.Id, it => new WmPolishInventory() //{ // BlankNum = model.BlankNum, // Partnumber = model.Partnumber, // Quantity = model.Quantity, // MaxNum = model.MaxNum, // MinNum = model.MinNum, // WarnNum = model.WarnNum, // Type = model.Type, // Status = model.Status, // Remark = model.Remark, // CreatedBy = model.CreatedBy, // CreatedTime = model.CreatedTime, // UpdatedBy = model.UpdatedBy, // UpdatedTime = model.UpdatedTime, //}); //return response; return Update(model, true); } /// /// 零件号下拉查询 /// /// 零件号或描述 /// public List GetMaterialSelectOption(string query) { var predicate = Expressionable .Create() .Or(it => it.Partnumber.Contains(query)) .Or(it => it.Description.Contains(query)) .Or(it => it.ProductName.Contains(query)) .And(it => it.Type == 1) .And(it => it.Status == 1); List options = Context .Queryable() .Where(predicate.ToExpression()) .Select( (it) => new WmMaterialSelectOptions { Key = it.Id, Label = "[ " + it.Partnumber + " ] " + it.Description, Value = it.Partnumber } ) .ToList(); return options; } /// /// 新增抛光仓库操作记录 /// /// 抛光仓库主键 /// 同批功能识别编号 /// 零件号 /// 类别 /// 操作数字 /// 备注 /// 创建人 /// public int AddPolishRecord( string fkInventoryId, string code, string partnumber, int type, int? changeQuantity, DateTime? actionTime, string remark, string createdBy ) { WmPolishRecord newPolishRecord = new() { Id = SnowFlakeSingle.Instance.NextId().ToString(), FkInventoryId = fkInventoryId, Code = code, Partnumber = partnumber, BlankNum = "", ChangeType = type, ChangeQuantity = changeQuantity ?? 0, ActionTime = actionTime, Status = 1, Remark = remark, CreatedBy = createdBy, CreatedTime = DateTime.Now.ToLocalTime(), UpdatedBy = createdBy, UpdatedTime = DateTime.Now.ToLocalTime(), }; return Context.Insertable(newPolishRecord).ExecuteCommand(); } public int DoWmPolishWarehousing(WmPolishInventory parm) { try { Context.Ado.BeginTran(); // 零件号检查 string partnumber = parm.Partnumber; /*WmMaterial material = Context .Queryable() .Where(it => it.Partnumber == partnumber) .Where(it => it.Type == 1) .Where(it => it.Status == 1) .First(); if (material == null) { Context.Ado.RollbackTran(); throw new Exception("零件号在物料清单未查到,请到物料清单新增零件号记录"); }*/ // 检查是否存在库中 WmPolishInventory polishInventory = Context .Queryable() .Where(it => it.Partnumber == partnumber) .Where(it => it.Type == parm.Type) .Where(it => it.Status == 1) .First(); if (polishInventory == null) { // 为空则新增库 WmPolishInventory newWmPolishInventory = new() { Id = SnowFlakeSingle.Instance.NextId().ToString(), BlankNum = "", Partnumber = partnumber, Type = parm.Type, Quantity = parm.Quantity, MaxNum = 0, MinNum = 0, WarnNum = 0, Status = 1, Remark = "系统自动创建库", CreatedBy = parm.CreatedBy, CreatedTime = DateTime.Now.ToLocalTime(), UpdatedBy = parm.CreatedBy, UpdatedTime = DateTime.Now.ToLocalTime(), }; WmPolishInventory addWmPolishInventory = Context .Insertable(newWmPolishInventory) .ExecuteReturnEntity(); string code = !string.IsNullOrEmpty(parm.WorkOrder) ? parm.WorkOrder : SnowFlakeSingle.Instance.NextId().ToString(); string remark = "初次创建仓库,新增入库数据 " + parm.Remark; int successNum = AddPolishRecord( addWmPolishInventory.Id, code, partnumber, 1, parm.Quantity, parm.ActionTime, remark, parm.CreatedBy ); if (successNum == 0) { Context.Ado.RollbackTran(); throw new Exception("入库日志添加失败"); } } else { polishInventory.Quantity += parm.Quantity; int updateNum = Context.Updateable(polishInventory).ExecuteCommand(); if (updateNum == 0) { Context.Ado.RollbackTran(); throw new Exception("修改抛光仓库数据失败"); } // 已有则新增记录 string code = SnowFlakeSingle.Instance.NextId().ToString(); int successNum = AddPolishRecord( polishInventory.Id, code, partnumber, 1, parm.Quantity, parm.ActionTime, parm.Remark, parm.CreatedBy ); if (successNum == 0) { Context.Ado.RollbackTran(); throw new Exception("入库日志添加失败"); } } Context.Ado.CommitTran(); return 1; } catch (Exception e) { Context.Ado.RollbackTran(); throw new Exception(e.Message); } } public int DoWmPolishRetrieval(WmPolishInventory parm) { try { Context.Ado.BeginTran(); // 零件号检查 string partnumber = parm.Partnumber; /*WmMaterial material = Context .Queryable() .Where(it => it.Partnumber == partnumber) .Where(it => it.Type == 1) .Where(it => it.Status == 1) .First(); if (material == null) { Context.Ado.RollbackTran(); throw new Exception("零件号在物料清单未查到,请到物料清单新增零件号记录"); }*/ // 检查是否存在库中 WmPolishInventory polishInventory = Context .Queryable() .Where(it => it.Partnumber == partnumber) .Where(it => it.Type == parm.Type) .Where(it => it.Status == 1) .First(); if (polishInventory == null) { // 为空则新增库 WmPolishInventory newWmPolishInventory = new() { Id = SnowFlakeSingle.Instance.NextId().ToString(), BlankNum = "", Partnumber = partnumber, Type = parm.Type, Quantity = parm.Quantity * -1, MaxNum = 0, MinNum = 0, WarnNum = 0, Status = 1, Remark = "系统自动创建库", CreatedBy = parm.CreatedBy, CreatedTime = DateTime.Now.ToLocalTime(), UpdatedBy = parm.CreatedBy, UpdatedTime = DateTime.Now.ToLocalTime(), }; WmPolishInventory addWmPolishInventory = Context .Insertable(newWmPolishInventory) .ExecuteReturnEntity(); string code = !string.IsNullOrEmpty(parm.WorkOrder) ? parm.WorkOrder : SnowFlakeSingle.Instance.NextId().ToString(); string remark = "初次创建仓库,新增手动出库数据" + parm.Remark; int successNum = AddPolishRecord( addWmPolishInventory.Id, code, partnumber, 2, parm.Quantity, parm.ActionTime, remark, parm.CreatedBy ); if (successNum == 0) { Context.Ado.RollbackTran(); throw new Exception("出库日志添加失败"); } } else { polishInventory.Quantity -= parm.Quantity; int updateNum = Context.Updateable(polishInventory).ExecuteCommand(); if (updateNum == 0) { Context.Ado.RollbackTran(); throw new Exception("修改抛光仓库零件数失败"); } // 已有则新增记录 string code = SnowFlakeSingle.Instance.NextId().ToString(); int successNum = AddPolishRecord( polishInventory.Id, code, partnumber, 2, parm.Quantity, parm.ActionTime, parm.Remark, parm.CreatedBy ); if (successNum == 0) { Context.Ado.RollbackTran(); throw new Exception("出库日志添加失败"); } } Context.Ado.CommitTran(); return 1; } catch (Exception e) { Context.Ado.RollbackTran(); throw new Exception(e.Message); } } public int DoWmPolishStocktaking(WmPolishInventory parm) { if (parm.Quantity < 0) { throw new Exception("修改的零件数小于0"); } try { Context.Ado.BeginTran(); // 检查是否存在库中 WmPolishInventory polishInventory = Context .Queryable() .Where(it => it.Id == parm.Id) .Where(it => it.Status == 1) .First(); if (polishInventory == null) { Context.Ado.RollbackTran(); throw new Exception("盘点记录不存在" + parm.Id); } Context.Updateable(parm).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand(); // 已有则新增记录 string code = !string.IsNullOrEmpty(parm.WorkOrder) ? parm.WorkOrder : SnowFlakeSingle.Instance.NextId().ToString(); int successNum = AddPolishRecord( parm.Id, code, parm.Partnumber, 3, parm.Quantity, parm.ActionTime, parm.Remark, parm.CreatedBy ); if (successNum == 0) { Context.Ado.RollbackTran(); throw new Exception("盘点日志添加失败"); } Context.Ado.CommitTran(); return successNum; } catch (Exception e) { Context.Ado.RollbackTran(); throw new Exception(e.Message); } } // 获取仓库零件数量 public int GetPartNumber() { return Context .Queryable() .Where(it => it.Status == 1) .Sum(it => it.Quantity) ?? 0; } // Util 获取物料清单,不包含毛坯 public List GetWmMaterialList(string partnumber) { // 获取物料信息 return Context .Queryable() .WhereIF( !string.IsNullOrEmpty(partnumber), it => it.Partnumber.Contains(partnumber) ) .Where(it => !string.IsNullOrEmpty(it.Partnumber)) .Where(it => it.Type == 1) .Where(it => it.Status == 1) .Distinct() .OrderBy(it => it.Description) .ToList(); } // 获取Excel导出数据 public List GetExportList(WmPolishInventoryQueryDto parm) { try { List materials = GetWmMaterialList(parm.Partnumber); // 获取所有partnumber列表 List partnumbers = materials .Where(it => !string.IsNullOrEmpty(it.Partnumber)) .Select(it => it.Partnumber) .Distinct() .ToList(); // 批量获取盘点数和现有库存 Dictionary stockNumbers = GetBatchPolishStockPartNum(partnumbers); Dictionary realNumbers = GetBatchPolishRealPartNum(partnumbers); // 更新盘点时间 DateTime dateTime = DateTime.Now.ToLocalTime(); // 构建导出数据 List exportDto = materials .Select(it => { bool found1 = stockNumbers.TryGetValue(it.Partnumber, out object value1); int stockNumber = found1 && value1 != null ? Convert.ToInt32(value1) : 0; bool found2 = realNumbers.TryGetValue(it.Partnumber, out int realNumber); return new WmPolishInventoryExportDto { 零件号 = it.Partnumber, 颜色 = it.Color, 规格 = it.Specification, 描述 = it.Description, 盘点时间 = dateTime, 盘点数 = stockNumber, 现有库存 = found2 ? realNumber : 0, }; }) .ToList(); return exportDto; } catch (Exception e) { throw; } } // Util 获取指定抛光库零件盘点库存 public Dictionary GetBatchPolishStockPartNum(List partnumbers) { return Context .Queryable() .Where(it => partnumbers.Contains(it.Partnumber)) .GroupBy(it => it.Partnumber) .ToDictionary(g => g.Partnumber, g => SqlFunc.AggregateSum(g.Quantity) ?? 0); } // Util 获取指定抛光库零件加报表后库存 public Dictionary GetBatchPolishRealPartNum(List partnumbers) { try { // 盘点时间 DateTime? checkTime = Context .Queryable() .Where(it => it.Status == 1) .Select(it => it.CreatedTime) .First() ?? new DateTime(2024, 11, 16, 12, 0, 0); CommonFQCService commonFQCService = new(); // 获取报表数据 // 抛光计算后库存 = 盘点库存 + 产线抛光 + 后道反抛 + GP12反抛 - 抛光投入 return commonFQCService.GetBatchPolishPartRealStock(partnumbers, checkTime.Value); } catch (Exception e) { throw; } } /// /// 导入数据 /// /// /// public (string, object, object) ImportExcel(List importList) { List wmPolishInventorylist = importList .Select(it => new WmPolishInventory { Id = SnowFlakeSingle.Instance.NextId().ToString(), Type = 1, Status = 1, MaxNum = 0, MinNum = 0, WarnNum = 0, CreatedBy = "页面导入", Remark = "EXCEL 盘点导入", CreatedTime = it.盘点时间 ?? DateTime.Now.ToLocalTime(), Partnumber = it.零件号, Quantity = it.盘点数 }) .ToList(); var x = Context .Storageable(wmPolishInventorylist) .SplitError(x => x.Item.Partnumber.IsEmpty(), "零件号不能为空") .SplitError(x => x.Item.Quantity.IsEmpty(), "盘点数不能为空") .SplitUpdate(it => it.Any()) // 数据库存在更新 .SplitDelete(it => it.Item.Quantity == 0) //盘点数为0的不导入 .SplitInsert(it => true) // 其余插入 .WhereColumns(it => it.Partnumber) //如果不是主键可以这样实现(多字段it=>new{it.x1,it.x2}) .ToStorage(); // 清空全部 var result = x.AsInsertable.ExecuteCommand(); //不存在则插入; var result2 = x.AsUpdateable.IgnoreColumns(it => new { it.Id }).ExecuteCommand(); //存在则修改; var result3 = x.AsDeleteable.ExecuteCommand(); //盘点数为0的删除; string msg = string.Format( " 插入{0} 更新{1} 错误数据{2} 不计算数据{3} 删除数据{4} 总共{5}", x.InsertList.Count, x.UpdateList.Count, x.ErrorList.Count, x.IgnoreList.Count, x.DeleteList.Count, x.TotalList.Count ); //输出统计 Console.WriteLine(msg); //输出错误信息 foreach (var item in x.ErrorList) { Console.WriteLine("零件异常:" + item.Item.Partnumber + " : " + item.StorageMessage); } return (msg, x.ErrorList, x.IgnoreList); } } }