diff --git a/DOAN.Admin.WebApi/Controllers/PBL/Logging/InventorylogController.cs b/DOAN.Admin.WebApi/Controllers/PBL/Logging/InventorylogController.cs index cae5506..379fa3d 100644 --- a/DOAN.Admin.WebApi/Controllers/PBL/Logging/InventorylogController.cs +++ b/DOAN.Admin.WebApi/Controllers/PBL/Logging/InventorylogController.cs @@ -3,6 +3,7 @@ using DOAN.Model.PBL.Dto; using DOAN.Model.PBL; using DOAN.Service.PBL.IService; using DOAN.Admin.WebApi.Filters; +using System.Collections.Generic; //创建时间:2024-09-23 namespace DOAN.Admin.WebApi.Controllers.PBL @@ -98,5 +99,21 @@ namespace DOAN.Admin.WebApi.Controllers.PBL return ToResponse(_InventorylogService.Delete(idArr)); } + /// + /// 导出库存日志 + /// + /// + [HttpGet("export")] + [AllowAnonymous] + [Log(Title = "库存日志", BusinessType = BusinessType.EXPORT)] + public IActionResult AddInventorylog([FromQuery] InventorylogExportDto parm) + { + var list = _InventorylogService.ExportInventorylog(parm); + // 添加调试日志 + Console.WriteLine($"导出的库存日志数量: {list.Count}"); + var result = ExportExcelMini(list, "Inventorylog", "库存日志"); + return ExportExcel(result.Item2, result.Item1); + } + } } \ No newline at end of file diff --git a/DOAN.Admin.WebApi/Controllers/PBL/StoragelocationController.cs b/DOAN.Admin.WebApi/Controllers/PBL/StoragelocationController.cs index 4aa7ae7..77193e0 100644 --- a/DOAN.Admin.WebApi/Controllers/PBL/StoragelocationController.cs +++ b/DOAN.Admin.WebApi/Controllers/PBL/StoragelocationController.cs @@ -37,6 +37,19 @@ namespace DOAN.Admin.WebApi.Controllers.PBL return SUCCESS(response); } + /// + /// 查询料架表列表(零件号聚合) + /// + /// + /// + [HttpGet("listByPartnumber")] + [ActionPermissionFilter(Permission = "storagelocation:list")] + public IActionResult QueryListByPartnumber() + { + var response = _StoragelocationService.GetPartNumberList(); + return SUCCESS(response); + } + /// /// 查询料架表详情 diff --git a/DOAN.Admin.WebApi/appsettings.Development.json b/DOAN.Admin.WebApi/appsettings.Development.json index f32e150..1ae1546 100644 --- a/DOAN.Admin.WebApi/appsettings.Development.json +++ b/DOAN.Admin.WebApi/appsettings.Development.json @@ -10,8 +10,8 @@ "dbConfigs": [ { - - "Conn": "Data Source=10.72.80.161;User ID=root;Password=doantech123;Initial Catalog=pbl_huaxiang_v2;Port=3306", + "Conn": "Data Source=192.168.0.58;User ID=root;Password=123456;Initial Catalog=pbl_huaxiang;Port=3306", + //"Conn": "Data Source=10.72.80.161;User ID=root;Password=doantech123;Initial Catalog=pbl_huaxiang_v2;Port=3306", "DbType": 0, //数据库类型 MySql = 0, SqlServer = 1, Oracle = 3,PgSql = 4 "ConfigId": "0", //多租户唯一标识 "IsAutoCloseConnection": true diff --git a/DOAN.Model/PBL/Dto/InventorylogDto.cs b/DOAN.Model/PBL/Dto/InventorylogDto.cs index ecdb8f1..855bd5c 100644 --- a/DOAN.Model/PBL/Dto/InventorylogDto.cs +++ b/DOAN.Model/PBL/Dto/InventorylogDto.cs @@ -7,7 +7,7 @@ namespace DOAN.Model.PBL.Dto public class InventorylogQueryDto : PagerInfo { public string RackCode { get; set; } - + public string Partnumber { get; set; } public int? Operation { get; set; } } @@ -20,6 +20,7 @@ namespace DOAN.Model.PBL.Dto public string Id { get; set; } public string RackCode { get; set; } + public string Partnumber { get; set; } public int? Operation { get; set; } @@ -36,4 +37,13 @@ namespace DOAN.Model.PBL.Dto } + + /// + /// 库存日志查询对象 + /// + public class InventorylogExportDto + { + public string StartTime { get; set; } + public string EndTime { get; set; } + } } \ No newline at end of file diff --git a/DOAN.Model/PBL/Dto/StoragelocationDto.cs b/DOAN.Model/PBL/Dto/StoragelocationDto.cs index 5be60b7..84e909f 100644 --- a/DOAN.Model/PBL/Dto/StoragelocationDto.cs +++ b/DOAN.Model/PBL/Dto/StoragelocationDto.cs @@ -31,7 +31,6 @@ public class StoragelocationDto public int? PackageNum { get; set; } - /// /// 箱子数 /// @@ -44,4 +43,16 @@ public class StoragelocationDto public string UpdatedBy { get; set; } public DateTime? UpdatedTime { get; set; } -} \ No newline at end of file +} + +/// +/// 料架表零件号聚合结果 +/// +public class StoragelocationPartNumberGroupDto +{ + public string RackCode { get; set; } + public string Partnumber { get; set; } + public string MirrorshellName { get; set; } + public string Productname { get; set; } + public int PackageNum { get; set; } = 0; +} diff --git a/DOAN.Model/PBL/Inventorylog.cs b/DOAN.Model/PBL/Inventorylog.cs index de7c07a..a1eea9f 100644 --- a/DOAN.Model/PBL/Inventorylog.cs +++ b/DOAN.Model/PBL/Inventorylog.cs @@ -11,47 +11,62 @@ namespace DOAN.Model.PBL /// 雪花 /// [SugarColumn(IsPrimaryKey = true, IsIdentity = false)] + [ExcelIgnore] public string Id { get; set; } /// /// 料架号 /// [SugarColumn(ColumnName = "rack_code")] + [ExcelColumn(Name = "料架号")] public string RackCode { get; set; } + /// + /// 零件号 + /// + [SugarColumn(ColumnName = "partnumber")] + [ExcelColumn(Name = "零件号")] + public string Partnumber { get; set; } + /// /// 操作(1出、2入库) /// + [ExcelColumn(Name = "操作(1出库、2入库) ")] public int? Operation { get; set; } /// /// 箱子数 /// [SugarColumn(ColumnName = "package_num")] + [ExcelColumn(Name = "箱子变动数")] public int? PackageNum { get; set; } /// /// 创建人 /// [SugarColumn(ColumnName = "cREATED_BY")] + [ExcelColumn(Name = "生成来源")] public string CreatedBy { get; set; } /// /// 创建时间 /// [SugarColumn(ColumnName = "cREATED_TIME")] + [ExcelColumn(Name = "生成时间", Format = "yyyy-MM-dd HH:mm:ss")] public DateTime? CreatedTime { get; set; } /// /// 更新人 /// [SugarColumn(ColumnName = "uPDATED_BY")] + [ExcelIgnore] public string UpdatedBy { get; set; } /// /// 更新时间 /// [SugarColumn(ColumnName = "uPDATED_TIME")] + [ExcelIgnore] public DateTime? UpdatedTime { get; set; } } diff --git a/DOAN.Service/PBL/IService/IInventorylogService.cs b/DOAN.Service/PBL/IService/IInventorylogService.cs index 6df3f4e..c254206 100644 --- a/DOAN.Service/PBL/IService/IInventorylogService.cs +++ b/DOAN.Service/PBL/IService/IInventorylogService.cs @@ -17,6 +17,11 @@ namespace DOAN.Service.PBL.IService Inventorylog AddInventorylog(Inventorylog parm); int UpdateInventorylog(Inventorylog parm); - + /// + /// 导出日志信息 + /// + /// + /// + public List ExportInventorylog(InventorylogExportDto model); } } diff --git a/DOAN.Service/PBL/IService/IStoragelocationService.cs b/DOAN.Service/PBL/IService/IStoragelocationService.cs index 97fd7b8..c362667 100644 --- a/DOAN.Service/PBL/IService/IStoragelocationService.cs +++ b/DOAN.Service/PBL/IService/IStoragelocationService.cs @@ -16,6 +16,11 @@ namespace DOAN.Service.PBL.IService Storagelocation AddStoragelocation(Storagelocation parm); int UpdateStoragelocation(Storagelocation parm); - + /// + /// 获取零件号库存 + /// + /// + /// + List GetPartNumberList(); } } diff --git a/DOAN.Service/PBL/InventorylogService.cs b/DOAN.Service/PBL/InventorylogService.cs index 97fa258..2420f34 100644 --- a/DOAN.Service/PBL/InventorylogService.cs +++ b/DOAN.Service/PBL/InventorylogService.cs @@ -4,6 +4,8 @@ using DOAN.Model.PBL.Dto; using DOAN.Model.PBL; using DOAN.Repository; using DOAN.Service.PBL.IService; +using Aliyun.OSS; +using System; namespace DOAN.Service.PBL @@ -82,5 +84,47 @@ namespace DOAN.Service.PBL return predicate; } + + /// + /// 导出库存日志 + /// + /// + /// + public List ExportInventorylog(InventorylogExportDto model) + { + try + { + // 将字符串类型的 StartTime 和 EndTime 转换为 DateTime 类型 + if (!DateTime.TryParse(model.StartTime, out DateTime startTime)) + { + throw new ArgumentException("开始时间格式无效。"); + } + + if (!DateTime.TryParse(model.EndTime, out DateTime endTime)) + { + throw new ArgumentException("结束时间格式无效。"); + } + + // 设置开始时间为当天的开始时间(00:00:00) + startTime = startTime.Date; + + // 设置结束时间为当天的结束时间(23:59:59) + endTime = endTime.Date.AddDays(1).AddTicks(-1); + + // 查询符合条件的库存日志 + var response = Queryable() + .Where(it => it.CreatedTime >= startTime && it.CreatedTime <= endTime) + .OrderBy(it => it.CreatedTime) + .ToList(); + + return response; + } + catch (Exception ex) + { + // 记录异常信息(可以使用日志框架如 NLog 或 Serilog) + Console.WriteLine($"导出库存日志异常: {ex.Message}\n堆栈跟踪: {ex.StackTrace}"); + throw; // 或者返回空列表或其他适当的响应 + } + } } } \ No newline at end of file diff --git a/DOAN.Service/PBL/StoragelocationService.cs b/DOAN.Service/PBL/StoragelocationService.cs index 0545e2d..15c6f2d 100644 --- a/DOAN.Service/PBL/StoragelocationService.cs +++ b/DOAN.Service/PBL/StoragelocationService.cs @@ -65,6 +65,22 @@ namespace DOAN.Service.PBL return Update(model, true); } + public List GetPartNumberList() + { + var response = Queryable() + .GroupBy(it=>it.Partnumber) + .OrderBy(it=>it.RackCode) + .Select(it=>new StoragelocationPartNumberGroupDto() + { + RackCode = SqlFunc.AggregateMax(it.RackCode), + Partnumber = SqlFunc.AggregateMax( it.Partnumber), + PackageNum = SqlFunc.AggregateSum(it.PackageNum) ?? 0 + }) + .ToList(); + return response; + } + + /// /// 查询导出表达式 /// @@ -79,5 +95,7 @@ namespace DOAN.Service.PBL return predicate; } + + } } \ No newline at end of file diff --git a/DOAN.ServiceCore/DoanBackgroundService.cs b/DOAN.ServiceCore/DoanBackgroundService.cs index 7d491ec..5986805 100644 --- a/DOAN.ServiceCore/DoanBackgroundService.cs +++ b/DOAN.ServiceCore/DoanBackgroundService.cs @@ -61,209 +61,114 @@ namespace DOAN.ServiceCore } /// - /// 功能:检测传感器信号,判断箱子数 + /// 功能:检测传感器信号,判断箱子数并更新库存及日志 /// - /// + /// 取消令牌 /// private async Task ExecuteAsync(CancellationToken stoppingToken) { - - try { - //int index = 1; - //int indexMax = await DbScoped.SugarScope.CopyNew() - // .Queryable().CountAsync(); + try + { while (!stoppingToken.IsCancellationRequested) { + // 读取PLC I/O状态 12个数组 + byte[] plcSensorValues = pLCTool.ReadAllValue("VB100", 12); - //读取PLC I/O状态 12个数组 - Byte[] getPLCValueByteArray=pLCTool.ReadAllValue("VB100",12); - //判断 每个料架每层的箱子数 - - //1. 获取所有料架层 合并的箱子 料架层翻倍 + // 获取所有料架层 List storagelocationList = await DbScoped.SugarScope.CopyNew().Queryable().ToListAsync(); - - //2. 获取点位表 + // 获取点位表 List pointPositionList = await DbScoped.SugarScope.CopyNew().Queryable().ToListAsync(); - List updateStoragelocationList=new List(); - List inventorylogs = new List(); + List updateStoragelocationList = []; + List inventoryLogs = []; - if (storagelocationList.Count() > 0) { + foreach (Storagelocation layerItem in storagelocationList) + { + // 获取这个料架层的点位表 + List layerPoints = pointPositionList.Where(it => it.FkStorageId == layerItem.Id).ToList(); - foreach (Storagelocation layerItem in storagelocationList) + if (layerPoints != null && layerPoints.Count > 0) { - //2 获取这个料架层的点位表 - List thisLayItemPointPositionList= pointPositionList.Where(it => it.FkStorageId == layerItem.Id).ToList(); + int currentPackageCount = 1; // 默认最小值为1 - //3 判断这个料架层箱子的个数 - if(thisLayItemPointPositionList!=null&& thisLayItemPointPositionList.Count()>0) + foreach (PlcAddressTable point in layerPoints) { - // 这一层箱子数 默认最小值为1 - int packNum = 1; - foreach(PlcAddressTable i in thisLayItemPointPositionList) + int row = point.ByteNum - 100; + int col = point.BitNum - 1; + + if (plcSensorValues != null) { - - int row = i.ByteNum-100; - int col = i.BitNum - 1; - - // Console.WriteLine($"row={row},col={col},PLCValueByteArray[row]={getPLCValueByteArray.Length}"); - packNum= packNum+( GetInvertedBit(getPLCValueByteArray[row], col) ? 1 : 0); - //Console.WriteLine($"row:{row}-col:{col} packNum:{packNum} "); + currentPackageCount += GetInvertedBit(plcSensorValues[row], col) ? 1 : 0; } - // 记录日志 - if(packNum> layerItem.PackageNum) - { - Storagelocation storagelocation = layerItem; - - storagelocation.PackageNum = packNum; - storagelocation.UpdatedBy = "补料"; - storagelocation.UpdatedTime = DateTime.Now; - updateStoragelocationList.Add(storagelocation); + } - - - Inventorylog inventorylog = new Inventorylog(); - //入库 - inventorylog.Id= SnowFlakeSingle.Instance.NextId().ToString(); - inventorylog.RackCode = storagelocation.RackCode; - inventorylog.Operation = 2; - inventorylog.PackageNum = packNum- layerItem.PackageNum; - inventorylog.CreatedBy = "补料"; - inventorylog.CreatedTime = DateTime.Now.ToLocalTime(); - inventorylogs.Add(inventorylog); - - } - else if(packNum < layerItem.PackageNum) - { - - Storagelocation storagelocation = layerItem; - storagelocation.PackageNum = packNum; - storagelocation.UpdatedBy = "出料"; - storagelocation.UpdatedTime = DateTime.Now; - updateStoragelocationList.Add(storagelocation); - - //出库 - Inventorylog inventorylog = new Inventorylog(); - inventorylog.Id = SnowFlakeSingle.Instance.NextId().ToString(); - inventorylog.RackCode = storagelocation.RackCode; - inventorylog.Operation = 1; - inventorylog.PackageNum =layerItem.PackageNum - packNum ; - inventorylog.CreatedBy = "出料"; - inventorylog.CreatedTime = DateTime.Now.ToLocalTime(); - inventorylogs.Add(inventorylog); - } - + // 检查箱子数量变化并记录日志 + if (currentPackageCount > layerItem.PackageNum) + { + UpdateAndLog(layerItem, currentPackageCount, 2, "补料", inventoryLogs); + updateStoragelocationList.Add(layerItem); + } + else if (currentPackageCount < layerItem.PackageNum) + { + UpdateAndLog(layerItem, currentPackageCount, 1, "出料", inventoryLogs); + updateStoragelocationList.Add(layerItem); } } - - //修正库存 - if (updateStoragelocationList.Count() > 0) - { - await DbScoped.SugarScope.CopyNew().Updateable(updateStoragelocationList).ExecuteCommandAsync(); - } - - //增加库存变更日志 - if(inventorylogs.Count()>0) - { - await DbScoped.SugarScope.CopyNew().Insertable(inventorylogs).ExecuteCommandAsync(); - } - - - } + // 更新库存 + if (updateStoragelocationList.Count > 0) + { + await DbScoped.SugarScope.CopyNew().Updateable(updateStoragelocationList).ExecuteCommandAsync(); + } + // 插入库存变更日志 + if (inventoryLogs.Count > 0) + { + await DbScoped.SugarScope.CopyNew().Insertable(inventoryLogs).ExecuteCommandAsync(); + } - - - - - - - - - - //List storagelocationList = await DbScoped.SugarScope.CopyNew() - //.Queryable().Where(it => it.Id == index).ToListAsync(); - //if (storagelocationList.Count > 0) - //{ - - // foreach (var storagelocation in storagelocationList) - // { - - // //遮挡不亮 false - // bool result = pLCTool.ReadBit(storagelocation.PlcAddress2); - // // 写补料日志 - // Inventorylog inventorylog = new Inventorylog(); - // inventorylog.Id = SnowFlakeSingle.Instance.NextId().ToString(); - // inventorylog.RackCode = storagelocation.RackCode; - // // 合并货架的id - // //int[] ids = {1,2,3,4,19,20,21,22 }; - // int PackageLine = 2; - // //if (ids.Contains(storagelocation.Id)) - // //{ - // // PackageLine = 1; - // //} - // if (result) - // { - // //缺料,需要补料 - // // 仓库库存修正 - // if (storagelocation.PackageNum > PackageLine) - // { - // storagelocation.PackageNum = PackageLine; - // /*inventorylog.Operation = 1; - // inventorylog.PackageNum = 1; - // inventorylog.CreatedBy = "PLC"; - // inventorylog.CreatedTime = DateTime.Now.ToLocalTime();*/ - // await DbScoped.SugarScope.CopyNew().Updateable(storagelocation).ExecuteCommandAsync(); - // //await DbScoped.SugarScope.CopyNew().Insertable(inventorylog).ExecuteCommandAsync(); - - - // } - // } - // else - // { - // // 仓库库存修正 - // if (storagelocation.PackageNum <= PackageLine) - // { - // //不需要补料 补料成功 - // storagelocation.PackageNum = storagelocation.MaxCapacity; - // inventorylog.Operation = 2; - // inventorylog.PackageNum = storagelocation.MaxCapacity; - // inventorylog.CreatedBy = "PLC"; - // inventorylog.CreatedTime = DateTime.Now.ToLocalTime(); - // await DbScoped.SugarScope.CopyNew().Updateable(storagelocation).ExecuteCommandAsync(); - // await DbScoped.SugarScope.CopyNew().Insertable(inventorylog).ExecuteCommandAsync(); - // } - - // } - // //Console.WriteLine("永驻线程,正在读取对射传感器plc值 " + result + "地址:" + storagelocation.PlcAddress2); - - // } - - - - - - //} - - - - //// await Task.Delay(500, stoppingToken); - - - //index++; - //if (index > indexMax) - //{ - // index = 1; - //} - + // 添加延迟以避免频繁查询 + await Task.Delay(200, stoppingToken); } - } catch (Exception ex) { - Console.WriteLine("DoanBackGround线程ExecuteAsync异常:" + ex.Message); } - + catch (OperationCanceledException) + { + Console.WriteLine("任务已取消"); + } + catch (Exception ex) + { + Console.WriteLine($"DoanBackGround线程ExecuteAsync异常: {ex.Message}\n堆栈跟踪: {ex.StackTrace}"); + } + } + + /// + /// 更新料架位置的箱子数量并记录库存日志 + /// + /// 料架位置对象 + /// 新的箱子数量 + /// 操作类型 (1-出库, 2-入库) + /// 操作员名称 + /// 库存日志列表 + private void UpdateAndLog(Storagelocation storageLocation, int newPackageCount, int operation, string operatorName, List inventoryLogs) + { + storageLocation.PackageNum = newPackageCount; + storageLocation.UpdatedBy = operatorName; + storageLocation.UpdatedTime = DateTime.Now; + + Inventorylog inventoryLog = new Inventorylog + { + Id = SnowFlakeSingle.Instance.NextId().ToString(), + RackCode = storageLocation.RackCode, + Partnumber = storageLocation.Partnumber, + Operation = operation, + PackageNum = Math.Abs((int)(newPackageCount - storageLocation.PackageNum)), + CreatedBy = operatorName, + CreatedTime = DateTime.Now.ToLocalTime() + }; + + inventoryLogs.Add(inventoryLog); } public void Dispose()