feat(库存报表): 新增出入库报表功能及变动箱数字段

添加成品库出入库报表功能,包括入库报表和出库报表的查询接口
在WmGoodsRecord模型中新增ChangePackage字段记录变动箱数
修复Job_Blank.cs中多余的return null语句
This commit is contained in:
赵正易 2025-08-15 14:58:32 +08:00
parent 1be5945f2f
commit 20c7855995
14 changed files with 608 additions and 3 deletions

View File

@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Mvc;
using ZR.Admin.WebApi.Extensions;
using ZR.Model.MES.mm;
using ZR.Model.MES.mm.Dto;
using ZR.Service.mes.mm.IService;
namespace ZR.Admin.WebApi.Controllers.mes.mm
{
/// <summary>
/// 生产投料
/// </summary>
[Route("mes/mm/mmInventoryReport")]
public class MmInventoryReportController : BaseController
{
readonly IMmInventoryReportService mmInventoryReportService;
public MmInventoryReportController(IMmInventoryReportService mmInventoryReportService)
{
this.mmInventoryReportService = mmInventoryReportService;
}
/// <summary>
/// 成品库,入库清单
/// </summary>
/// <returns></returns>
[HttpPost("GetInventoryReportByPage")]
public IActionResult GetInventoryReportByPage([FromBody] WmGoodsRecordReportQueryDto query)
{
try
{
var response = mmInventoryReportService.GetInventoryReportByPage(query);
return SUCCESS(response);
}
catch (Exception)
{
throw;
}
}
}
}

View File

@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Mvc;
using ZR.Admin.WebApi.Extensions;
using ZR.Model.MES.mm;
using ZR.Model.MES.mm.Dto;
using ZR.Service.mes.mm.IService;
namespace ZR.Admin.WebApi.Controllers.mes.mm
{
/// <summary>
/// 生产投料
/// </summary>
[Route("mes/mm/mmOutboundReport")]
public class MmOutboundReportController : BaseController
{
readonly IMmOutboundReportService mmOutboundReportService;
public MmOutboundReportController(IMmOutboundReportService mmOutboundReportService)
{
this.mmOutboundReportService = mmOutboundReportService;
}
/// <summary>
/// 成品库,入库清单
/// </summary>
/// <returns></returns>
[HttpPost("GetOutboundReportByPage")]
public IActionResult GetOutboundReportByPage([FromBody] WmGoodsRecordReportQueryDto query)
{
try
{
var response = mmOutboundReportService.GetOutboundReportByPage(query);
return SUCCESS(response);
}
catch (Exception)
{
throw;
}
}
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<key id="ab5766eb-3e33-4d3f-9868-b1dbae6dbefb" version="1">
<creationDate>2025-08-13T05:44:14.9326709Z</creationDate>
<activationDate>2025-08-13T05:44:14.877032Z</activationDate>
<expirationDate>2025-11-11T05:44:14.877032Z</expirationDate>
<descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
<descriptor>
<encryption algorithm="AES_256_CBC" />
<validation algorithm="HMACSHA256" />
<masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection">
<!-- Warning: the key below is in an unencrypted form. -->
<value>XS+y3HmCKGimKj5oZV6Oq/747D2R8k7rQtVfVswIGOhbE6OHFfJo3mLhKICIDrk5ACcTP4ea5z+Uo5qMAGqp+Q==</value>
</masterKey>
</descriptor>
</descriptor>
</key>

View File

@ -0,0 +1,40 @@
using System;
using ZR.Model;
namespace ZR.Model.MES.mm.Dto
{
/// <summary>
/// 成品库记录查询参数
/// </summary>
public class WmGoodsRecordReportQueryDto : PagerInfo
{
/// <summary>
/// 数据来源
/// </summary>
public string Source { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 物料号(零件号)
/// </summary>
public string PartNumber { get; set; }
/// <summary>
/// 物料名称(暂无对应字段,可考虑用零件号替代或添加新字段)
/// </summary>
public string MaterialName { get; set; }
/// <summary>
/// 操作人(创建人)
/// </summary>
public string Operator { get; set; }
}
}

View File

@ -0,0 +1,124 @@
namespace ZR.Model.MES.mm
{
/// <summary>
/// 成品库出入库报表清单
/// </summary>
public class WmGoodsRecordReport
{
#region
/// <summary>
/// 主键
/// </summary>
public string Id { get; set; }
/// <summary>
/// 库存主键
/// </summary>
public string FkInventoryId { get; set; }
/// <summary>
/// 关联记录字段识别记录字段如PDA
/// </summary>
public string Code { get; set; }
/// <summary>
/// 零件号
/// </summary>
public string Partnumber { get; set; }
/// <summary>
/// 毛坯号
/// </summary>
public string BlankNum { get; set; }
#endregion
#region
/// <summary>
/// 变动类别 1-入库 2-出库 3-盘点
/// </summary>
public int? ChangeType { get; set; }
/// <summary>
/// 变动箱数
/// </summary>
public int? ChangePackage { get; set; }
/// <summary>
/// 变动零件数量
/// </summary>
public int? ChangeQuantity { get; set; }
/// <summary>
/// 时间(操作时间)
/// </summary>
public DateTime? ActionTime { get; set; }
/// <summary>
/// 状态(暂定)
/// </summary>
public int? Status { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
#endregion
#region
/// <summary>
/// 产品描述(产品名称)
/// </summary>
public string ProductName { get; set; }
/// <summary>
/// 产品颜色
/// </summary>
public string Color { get; set; }
/// <summary>
/// 规格(左右脚)
/// </summary>
public string Specification { get; set; }
/// <summary>
/// 显示描述(产品描述+颜色+规格)
/// </summary>
public string Description { get; set; }
/// <summary>
/// 单位
/// </summary>
public string Unit { get; set; }
#endregion
#region
/// <summary>
/// 创建人
/// </summary>
public string CreatedBy { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime? CreatedTime { get; set; }
/// <summary>
/// 更新人
/// </summary>
public string UpdatedBy { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime? UpdatedTime { get; set; }
#endregion
}
}

View File

@ -40,6 +40,12 @@ namespace ZR.Model.MES.wms
[SugarColumn(ColumnName = "change_type")]
public int? ChangeType { get; set; }
/// <summary>
/// 变动箱数
/// </summary>
[SugarColumn(ColumnName = "change_package")]
public int? ChangePackage { get; set; }
/// <summary>
/// 变动数量
/// </summary>

View File

@ -0,0 +1,24 @@
using ZR.Model;
using ZR.Model.MES.mm;
using ZR.Model.MES.mm.Dto;
namespace ZR.Service.mes.mm.IService
{
public interface IMmInventoryReportService
{
/// <summary>
/// 按时间、物料号、物料名称、操作人获取分页数据
/// </summary>
/// <param name="query">查询参数</param>
/// <param name="pagerInfo">分页信息</param>
/// <returns>分页结果</returns>
PagedInfo<WmGoodsRecordReport> GetInventoryReportByPage(WmGoodsRecordReportQueryDto query);
/// <summary>
/// 根据ID获取详细数据清单
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>详细数据</returns>
WmGoodsRecordReport GetInventoryReportDetail(string id);
}
}

View File

@ -0,0 +1,24 @@
using ZR.Model.MES.mm;
using ZR.Model.MES.mm.Dto;
using ZR.Model;
namespace ZR.Service.mes.mm.IService
{
public interface IMmOutboundReportService
{
/// <summary>
/// 按时间、物料号、物料名称、操作人获取分页数据
/// </summary>
/// <param name="query">查询参数</param>
/// <param name="pagerInfo">分页信息</param>
/// <returns>分页结果</returns>
PagedInfo<WmGoodsRecordReport> GetOutboundReportByPage(WmGoodsRecordReportQueryDto query);
/// <summary>
/// 根据ID获取详细数据清单
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>详细数据</returns>
WmGoodsRecordReport GetOutboundReportDetail(string id);
}
}

View File

@ -0,0 +1,142 @@
using System.Linq;
using Infrastructure.Attribute;
using SqlSugar;
using ZR.Model;
using ZR.Model.MES.mm;
using ZR.Model.MES.mm.Dto;
using ZR.Model.MES.wms;
using ZR.Repository;
using ZR.Service.mes.mm.IService;
using ZR.Service.mes.wms;
namespace ZR.Service.mes.mm
{
[AppService(
ServiceType = typeof(IMmInventoryReportService),
ServiceLifetime = LifeTime.Transient
)]
public class MmInventoryReportService : BaseService<WmGoodsRecord>, IMmInventoryReportService
{
/// <summary>
/// 按时间、物料号、物料名称、操作人获取分页数据
/// </summary>
/// <param name="query">查询参数</param>
/// <param name="pagerInfo">分页信息</param>
/// <returns>分页结果</returns>
public PagedInfo<WmGoodsRecordReport> GetInventoryReportByPage(
WmGoodsRecordReportQueryDto query
)
{
// 添加查询条件
var predicate = Expressionable
.Create<WmGoodsRecord, WmMaterial>()
.AndIF(query.StartTime.HasValue, (gr, m) => gr.ActionTime >= query.StartTime)
.AndIF(query.EndTime.HasValue, (gr, m) => gr.ActionTime <= query.EndTime)
.AndIF(
!string.IsNullOrEmpty(query.PartNumber),
(gr, m) => gr.Partnumber.Contains(query.PartNumber)
)
.AndIF(
!string.IsNullOrEmpty(query.Source),
(gr, m) => gr.Code.Contains(query.Source)
)
.AndIF(
!string.IsNullOrEmpty(query.MaterialName),
(gr, m) => m.Description.Contains(query.MaterialName)
)
.AndIF(
!string.IsNullOrEmpty(query.Operator),
(gr, m) => gr.CreatedBy.Contains(query.Operator)
)
.And((gr, m) => gr.ChangeType == 1); // 入库记录
// 按零件号分组并计算ChangeQuantity合计
var result = Context
.Queryable<WmGoodsRecord, WmMaterial>(
(gr, m) => new JoinQueryInfos(JoinType.Left, gr.Partnumber == m.Partnumber)
)
.Where(predicate.ToExpression())
.GroupBy(
(gr, m) =>
new
{
gr.Partnumber,
m.ProductName,
m.Color,
m.Specification,
m.Description,
m.Unit,
gr.CreatedBy
}
)
.Select(
(gr, m) =>
new WmGoodsRecordReport
{
Code = gr.Code,
Partnumber = gr.Partnumber,
ProductName = m.ProductName,
Color = m.Color,
Specification = m.Specification,
Description = m.Description,
Unit = m.Unit,
ChangePackage = SqlFunc.AggregateSum(gr.ChangePackage),
ChangeQuantity = SqlFunc.AggregateSum(gr.ChangeQuantity),
CreatedBy = gr.CreatedBy,
}
)
.ToPage(query);
return result;
}
/// <summary>
/// 根据ID获取详细数据清单
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>详细数据</returns>
public WmGoodsRecordReport GetInventoryReportDetail(string id)
{
// 获取原始记录
var record = this.GetId(id);
if (record == null)
return null;
// 创建报表模型实例
var report = new WmGoodsRecordReport
{
Id = record.Id,
FkInventoryId = record.FkInventoryId,
Code = record.Code,
Partnumber = record.Partnumber,
BlankNum = record.BlankNum,
ChangeType = record.ChangeType,
ChangeQuantity = record.ChangeQuantity,
ActionTime = record.ActionTime,
Status = record.Status,
Remark = record.Remark,
CreatedBy = record.CreatedBy,
CreatedTime = record.CreatedTime,
UpdatedBy = record.UpdatedBy,
UpdatedTime = record.UpdatedTime
};
// 如果有零件号,尝试获取物料信息
if (!string.IsNullOrEmpty(record.Partnumber))
{
var materialService = new WmMaterialService();
var material = materialService.GetFirst(it => it.Partnumber == record.Partnumber);
if (material != null)
{
report.ProductName = material.ProductName;
report.Color = material.Color;
report.Specification = material.Specification;
report.Description = material.Description;
report.Unit = material.Unit;
}
}
return report;
}
}
}

View File

@ -0,0 +1,141 @@
using Infrastructure.Attribute;
using SqlSugar;
using ZR.Model;
using ZR.Model.MES.mm;
using ZR.Model.MES.mm.Dto;
using ZR.Model.MES.wms;
using ZR.Repository;
using ZR.Service.mes.mm.IService;
using ZR.Service.mes.wms;
namespace ZR.Service.mes.mm
{
[AppService(
ServiceType = typeof(IMmOutboundReportService),
ServiceLifetime = LifeTime.Transient
)]
public class MmOutboundReportService : BaseService<WmGoodsRecord>, IMmOutboundReportService
{
/// <summary>
/// 按时间、物料号、物料名称、操作人获取分页数据
/// </summary>
/// <param name="query">查询参数</param>
/// <param name="pagerInfo">分页信息</param>
/// <returns>分页结果</returns>
public PagedInfo<WmGoodsRecordReport> GetOutboundReportByPage(
WmGoodsRecordReportQueryDto query
)
{
// 添加查询条件
var predicate = Expressionable
.Create<WmGoodsRecord, WmMaterial>()
.AndIF(query.StartTime.HasValue, (gr, m) => gr.ActionTime >= query.StartTime)
.AndIF(query.EndTime.HasValue, (gr, m) => gr.ActionTime <= query.EndTime)
.AndIF(
!string.IsNullOrEmpty(query.PartNumber),
(gr, m) => gr.Partnumber.Contains(query.PartNumber)
)
.AndIF(
!string.IsNullOrEmpty(query.Source),
(gr, m) => gr.Code.Contains(query.Source)
)
.AndIF(
!string.IsNullOrEmpty(query.MaterialName),
(gr, m) => m.Description.Contains(query.MaterialName)
)
.AndIF(
!string.IsNullOrEmpty(query.Operator),
(gr, m) => gr.CreatedBy.Contains(query.Operator)
)
.And((gr, m) => gr.ChangeType == 2); // 入库记录
// 按零件号分组并计算ChangeQuantity合计
var result = Context
.Queryable<WmGoodsRecord, WmMaterial>(
(gr, m) => new JoinQueryInfos(JoinType.Left, gr.Partnumber == m.Partnumber)
)
.Where(predicate.ToExpression())
.GroupBy(
(gr, m) =>
new
{
gr.Partnumber,
m.ProductName,
m.Color,
m.Specification,
m.Description,
m.Unit,
gr.CreatedBy
}
)
.Select(
(gr, m) =>
new WmGoodsRecordReport
{
Code = gr.Code,
Partnumber = gr.Partnumber,
ProductName = m.ProductName,
Color = m.Color,
Specification = m.Specification,
Description = m.Description,
Unit = m.Unit,
ChangePackage = SqlFunc.AggregateSum(gr.ChangePackage),
ChangeQuantity = SqlFunc.AggregateSum(gr.ChangeQuantity),
CreatedBy = gr.CreatedBy,
}
)
.ToPage(query);
return result;
}
/// <summary>
/// 根据ID获取详细数据清单
/// </summary>
/// <param name="id">记录ID</param>
/// <returns>详细数据</returns>
public WmGoodsRecordReport GetOutboundReportDetail(string id)
{
// 获取原始记录
var record = this.GetId(id);
if (record == null)
return null;
// 创建报表模型实例
var report = new WmGoodsRecordReport
{
Id = record.Id,
FkInventoryId = record.FkInventoryId,
Code = record.Code,
Partnumber = record.Partnumber,
BlankNum = record.BlankNum,
ChangeType = record.ChangeType,
ChangeQuantity = record.ChangeQuantity,
ActionTime = record.ActionTime,
Status = record.Status,
Remark = record.Remark,
CreatedBy = record.CreatedBy,
CreatedTime = record.CreatedTime,
UpdatedBy = record.UpdatedBy,
UpdatedTime = record.UpdatedTime
};
// 如果有零件号,尝试获取物料信息
if (!string.IsNullOrEmpty(record.Partnumber))
{
var materialService = new WmMaterialService();
var material = materialService.GetFirst(it => it.Partnumber == record.Partnumber);
if (material != null)
{
report.ProductName = material.ProductName;
report.Color = material.Color;
report.Specification = material.Specification;
report.Description = material.Description;
report.Unit = material.Unit;
}
}
return report;
}
}
}

View File

@ -141,6 +141,7 @@ namespace ZR.Service.mes.wms
Partnumber = partnumbers[0] ?? "无零件号",
BlankNum = "",
ChangeType = 1,
ChangePackage = totalPackage,
ChangeQuantity = totalPartnumber,
ActionTime = DateTime.Now,
Status = 1,

View File

@ -368,6 +368,7 @@ namespace ZR.Service.mes.wms
Partnumber = partnumbers[0] ?? "无零件号",
BlankNum = "",
ChangeType = 2,
ChangePackage = totalPackage,
ChangeQuantity = totalPartnumber,
ActionTime = DateTime.Now,
Status = 1,

View File

@ -551,6 +551,7 @@ namespace ZR.Service.mes.wms
Partnumber = partnumbers[0] ?? "无零件号",
BlankNum = "",
ChangeType = 2,
ChangePackage = totalPackage,
ChangeQuantity = totalPartnumber,
ActionTime = DateTime.Now,
Status = 1,
@ -571,7 +572,7 @@ namespace ZR.Service.mes.wms
+ "\n涉及批次号:\n"
+ string.Join(',', packageCodeRemark),
CreatedBy = Createby,
CreatedBy = Createby ?? "系统操作",
CreatedTime = DateTime.Now,
};
int recordNum = Context.Insertable(wmGoodsRecord).ExecuteCommand();

View File

@ -121,11 +121,10 @@ namespace ZR.Tasks.TaskScheduler
.ToList();
}
}
catch (Exception ex)
catch (Exception)
{
return null;
}
return null;
}
/// <summary>