新增密炼物料皮重策略功能,包括相关实体、服务、控制器及接口,支持桌面端免密CRUD操作,优化打印记录与原料入场记录的衍生字段填充逻辑,提升用户体验。
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
using Prism.Events;
|
||||
|
||||
namespace YY.Admin.Core.Events;
|
||||
|
||||
public class MixerMaterialTareStrategyChangedPayload
|
||||
{
|
||||
public string Action { get; set; } = string.Empty;
|
||||
public string? TareStrategyId { get; set; }
|
||||
}
|
||||
|
||||
public class MixerMaterialTareStrategyChangedEvent : PubSubEvent<MixerMaterialTareStrategyChangedPayload> { }
|
||||
@@ -0,0 +1,28 @@
|
||||
using YY.Admin.Core.Entity;
|
||||
|
||||
namespace YY.Admin.Core.Services;
|
||||
|
||||
public interface IMixerMaterialTareStrategyService
|
||||
{
|
||||
Task<MixerMaterialTareStrategyPageResult> PageAsync(
|
||||
int pageNo,
|
||||
int pageSize,
|
||||
string? mixerMaterialName = null,
|
||||
string? supplierName = null,
|
||||
CancellationToken ct = default);
|
||||
|
||||
Task<MesXslMixerMaterialTareStrategy?> GetByIdAsync(string id, CancellationToken ct = default);
|
||||
Task<bool> AddAsync(MesXslMixerMaterialTareStrategy strategy, CancellationToken ct = default);
|
||||
Task<bool> EditAsync(MesXslMixerMaterialTareStrategy strategy, CancellationToken ct = default);
|
||||
Task<bool> DeleteAsync(string id, CancellationToken ct = default);
|
||||
Task<List<MesXslUnit>> GetUnitsAsync(CancellationToken ct = default);
|
||||
|
||||
/// <summary>拉取全部策略(用于原料入场拆码明细自动/手动匹配)。</summary>
|
||||
Task<IReadOnlyList<MesXslMixerMaterialTareStrategy>> GetAllForMatchAsync(CancellationToken ct = default);
|
||||
}
|
||||
|
||||
public record MixerMaterialTareStrategyPageResult(
|
||||
List<MesXslMixerMaterialTareStrategy> Records,
|
||||
long Total,
|
||||
int PageNo,
|
||||
int PageSize);
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace YY.Admin.Core.Entity;
|
||||
|
||||
public class MesXslMixerMaterialTareStrategy
|
||||
{
|
||||
public string? Id { get; set; }
|
||||
public int? TenantId { get; set; }
|
||||
public string? MixerMaterialId { get; set; }
|
||||
public string? MixerMaterialName { get; set; }
|
||||
public string? SupplierId { get; set; }
|
||||
public string? SupplierName { get; set; }
|
||||
public string? MaterialSpec { get; set; }
|
||||
public decimal? TareWeight { get; set; }
|
||||
public decimal? PalletWeight { get; set; }
|
||||
public string? UnitId { get; set; }
|
||||
public string? UnitName { get; set; }
|
||||
public DateTime? EffectiveStartDate { get; set; }
|
||||
public DateTime? EffectiveEndDate { get; set; }
|
||||
public string? MaintainBy { get; set; }
|
||||
public string? CreateBy { get; set; }
|
||||
public DateTime? CreateTime { get; set; }
|
||||
public string? UpdateBy { get; set; }
|
||||
public DateTime? UpdateTime { get; set; }
|
||||
public string? SysOrgCode { get; set; }
|
||||
public int? DelFlag { get; set; }
|
||||
|
||||
public string EffectiveStartDateText =>
|
||||
EffectiveStartDate?.ToString("yyyy-MM-dd") ?? string.Empty;
|
||||
|
||||
public string EffectiveEndDateText =>
|
||||
EffectiveEndDate?.ToString("yyyy-MM-dd") ?? string.Empty;
|
||||
}
|
||||
@@ -17,6 +17,10 @@ public class MesXslRawMaterialCard
|
||||
public string? ManufacturerMaterialName { get; set; }
|
||||
public string? ShelfLife { get; set; }
|
||||
public decimal? TotalWeight { get; set; }
|
||||
/// <summary>包装物皮重(KG)</summary>
|
||||
public decimal? PackagingTare { get; set; }
|
||||
/// <summary>托盘重量(KG)</summary>
|
||||
public decimal? PalletWeight { get; set; }
|
||||
public decimal? RemainingWeight { get; set; }
|
||||
public int? RemainingQuantity { get; set; }
|
||||
|
||||
|
||||
@@ -17,11 +17,15 @@ public class MesXslRawMaterialEntry
|
||||
public string? ManufacturerMaterialName { get; set; }
|
||||
public string? ShelfLife { get; set; }
|
||||
public double? TotalWeight { get; set; }
|
||||
public double? PalletTareTotal { get; set; }
|
||||
|
||||
// 总份数 / 每份总重 / 每份包数:与后端同步升级为字符串,
|
||||
// 用于持久化「拆码明细」多行拼接(如 20/1/、100/200/)。
|
||||
public string? TotalPortions { get; set; }
|
||||
public string? PortionWeight { get; set; }
|
||||
public string? PortionPackagingTare { get; set; }
|
||||
public string? PortionPalletWeight { get; set; }
|
||||
public string? PortionTareStrategyIds { get; set; }
|
||||
public string? PortionPackages { get; set; }
|
||||
// 拆码明细各行库位的拼接(以 / 分隔,末尾带 /,如 1F-A01/1F-A02/)。
|
||||
// 与 WarehouseLocation(基础资料整票级单值)独立,专供明细行回填。
|
||||
|
||||
9
yy-admin-master/YY.Admin.Core/Entity/MesXslUnit.cs
Normal file
9
yy-admin-master/YY.Admin.Core/Entity/MesXslUnit.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace YY.Admin.Core.Entity;
|
||||
|
||||
public class MesXslUnit
|
||||
{
|
||||
public string? Id { get; set; }
|
||||
public string? UnitCode { get; set; }
|
||||
public string? UnitName { get; set; }
|
||||
public int? TenantId { get; set; }
|
||||
}
|
||||
@@ -40,6 +40,17 @@ public class MesXslWeightRecord
|
||||
/// </summary>
|
||||
public double? EnteredWeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货物皮重(KG) —— 后端/本地实时计算,不入库。
|
||||
/// 来源:所有引用本榜单(BillNo)的原料入场记录 pallet_tare_total(托盘及皮重合计)累加。
|
||||
/// </summary>
|
||||
public double? CargoTareWeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原料重量(KG) —— 实时计算,不入库。公式:净重 - 货物皮重。
|
||||
/// </summary>
|
||||
public double? RawMaterialWeight { get; set; }
|
||||
|
||||
/// <summary>司机姓名</summary>
|
||||
public string? DriverName { get; set; }
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
|
||||
new SysMenu{ Id=1300150010901, Pid=1300150000101, Title="原材料卡片", Path="/xslmes/mesXslRawMaterialCard", Name="mesXslRawMaterialCard", Component="RawMaterialCardListView", Icon="", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=108 },
|
||||
// 库区管理
|
||||
new SysMenu{ Id=1300150011001, Pid=1300150000101, Title="库区管理", Path="/xslmes/mesXslWarehouseArea", Name="mesXslWarehouseArea", Component="WarehouseAreaListView", Icon="", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=109 },
|
||||
// 密炼物料皮重策略
|
||||
new SysMenu{ Id=1300150011101, Pid=1300150000101, Title="密炼物料皮重策略", Path="/xslmes/mesXslMixerMaterialTareStrategy", Name="mesXslMixerMaterialTareStrategy", Component="MixerMaterialTareStrategyListView", Icon="", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ public class SysTenantMenuSeedData : ISqlSugarEntitySeedData<SysTenantMenu>
|
||||
new SysTenantMenu(){ TenantId=1300000000001,MenuId=1300150010801},
|
||||
new SysTenantMenu(){ TenantId=1300000000001,MenuId=1300150010901},
|
||||
new SysTenantMenu(){ TenantId=1300000000001,MenuId=1300150011001},
|
||||
new SysTenantMenu(){ TenantId=1300000000001,MenuId=1300150011101},
|
||||
new SysTenantMenu(){ TenantId=1300000000001,MenuId=1300200012101},
|
||||
new SysTenantMenu(){ TenantId=1300000000001,MenuId=1300200012111},
|
||||
new SysTenantMenu(){ TenantId=1300000000001,MenuId=1300200012121},
|
||||
|
||||
@@ -268,6 +268,8 @@ namespace YY.Admin.Core.SqlSugar
|
||||
if (config.SeedSettings.EnableInitSeed) InitSeedData(db, config);
|
||||
// 关闭全量种子时首启可能无菜单数据;补一份基准菜单,避免打包版本左侧空白
|
||||
EnsureBaselineSysMenuSeed(db, config);
|
||||
// 旧库升级:按种子补全缺失菜单及租户/角色授权(仅插入缺失项)
|
||||
EnsureIncrementalDesktopMenuSeed(db, config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -392,6 +394,106 @@ namespace YY.Admin.Core.SqlSugar
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 旧库升级:sys_menu 已有数据时,按 SysMenuSeedData 补全缺失菜单,并同步租户菜单、管理员角色菜单授权。
|
||||
/// </summary>
|
||||
private static void EnsureIncrementalDesktopMenuSeed(SqlSugarScope db, DbConnectionConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.Equals(config.ConfigId.ToString(), SqlSugarConst.MainConfigId, StringComparison.Ordinal))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.DbType != DbType.Sqlite)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dbProvider = db.GetConnectionScope(config.ConfigId);
|
||||
var menuEntityInfo = dbProvider.EntityMaintenance.GetEntityInfo(typeof(SysMenu));
|
||||
if (!dbProvider.DbMaintenance.IsAnyTable(menuEntityInfo.DbTableName, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (dbProvider.Queryable<SysMenu>().ClearFilter().Count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var seedMenus = new SysMenuSeedData().HasData().ToList();
|
||||
var existingMenuIds = dbProvider.Queryable<SysMenu>().ClearFilter()
|
||||
.Select(m => m.Id).ToList().ToHashSet();
|
||||
var missingMenus = seedMenus.Where(m => !existingMenuIds.Contains(m.Id)).ToList();
|
||||
if (missingMenus.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var menu in missingMenus)
|
||||
{
|
||||
if (menu.CreateTime == default)
|
||||
{
|
||||
menu.CreateTime = DateTime.Parse("2022-02-10 00:00:00");
|
||||
}
|
||||
|
||||
menu.Status = StatusEnum.Enable;
|
||||
}
|
||||
|
||||
dbProvider.Insertable(missingMenus).ExecuteCommand();
|
||||
|
||||
const long defaultTenantId = 1300000000001;
|
||||
var tenantSeed = new SysTenantMenuSeedData().HasData()
|
||||
.Where(t => t.TenantId == defaultTenantId)
|
||||
.ToList();
|
||||
var existingTenantMenuIds = dbProvider.Queryable<SysTenantMenu>()
|
||||
.Where(t => t.TenantId == defaultTenantId)
|
||||
.Select(t => t.MenuId)
|
||||
.ToList()
|
||||
.ToHashSet();
|
||||
|
||||
var tenantMenusToInsert = tenantSeed
|
||||
.Where(t => missingMenus.Any(m => m.Id == t.MenuId) && !existingTenantMenuIds.Contains(t.MenuId))
|
||||
.Select(t => new SysTenantMenu { Id = t.MenuId, TenantId = t.TenantId, MenuId = t.MenuId })
|
||||
.ToList();
|
||||
if (tenantMenusToInsert.Count > 0)
|
||||
{
|
||||
dbProvider.Insertable(tenantMenusToInsert).ExecuteCommand();
|
||||
}
|
||||
|
||||
var adminRole = dbProvider.Queryable<SysRole>().OrderBy(r => r.Id).First();
|
||||
if (adminRole == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var existingRoleMenuIds = dbProvider.Queryable<SysRoleMenu>()
|
||||
.Where(r => r.RoleId == adminRole.Id)
|
||||
.Select(r => r.MenuId)
|
||||
.ToList()
|
||||
.ToHashSet();
|
||||
var roleMenusToInsert = missingMenus
|
||||
.Where(m => !existingRoleMenuIds.Contains(m.Id))
|
||||
.Select(m => new SysRoleMenu
|
||||
{
|
||||
Id = m.Id + (adminRole.Id % 1300000000000),
|
||||
RoleId = adminRole.Id,
|
||||
MenuId = m.Id,
|
||||
})
|
||||
.ToList();
|
||||
if (roleMenusToInsert.Count > 0)
|
||||
{
|
||||
dbProvider.Insertable(roleMenusToInsert).ExecuteCommand();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 启动阶段不因增量菜单失败而阻断
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 兼容旧库:补齐桌面端「登录设置」所需的 sys_config 配置项(升级前库可能缺少这些 code)
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using YY.Admin.Core.Entity;
|
||||
|
||||
namespace YY.Admin.Core.Util;
|
||||
|
||||
/// <summary>
|
||||
/// 「货物皮重」桌面端本地累计计算器。
|
||||
/// 与后端 IMesXslRawMaterialEntryService.sumCargoTareByBillNos 保持同一口径:
|
||||
/// 同一榜单(BillNo)下所有原料入场记录的 PalletTareTotal(托盘及皮重合计)累加。
|
||||
/// </summary>
|
||||
public static class CargoTareWeightCalculator
|
||||
{
|
||||
/// <summary>按 BillNo 分组累计「货物皮重」。</summary>
|
||||
public static Dictionary<string, double> SumByBillNos(
|
||||
IEnumerable<MesXslRawMaterialEntry> entries,
|
||||
IEnumerable<string?> billNos)
|
||||
{
|
||||
var keys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var b in billNos)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(b)) keys.Add(b!);
|
||||
}
|
||||
var result = new Dictionary<string, double>(StringComparer.OrdinalIgnoreCase);
|
||||
if (keys.Count == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var e in entries)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(e.BillNo) || !keys.Contains(e.BillNo!))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (e.PalletTareTotal is not { } tare || tare == 0d)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (result.TryGetValue(e.BillNo!, out var acc))
|
||||
{
|
||||
result[e.BillNo!] = acc + tare;
|
||||
}
|
||||
else
|
||||
{
|
||||
result[e.BillNo!] = tare;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user