using System.ComponentModel.DataAnnotations; using MiGu.Server.Persistence; namespace MiGu.Server.Wms; public abstract class WarehouseHistoryBase { public Guid Id { get; set; } = Guid.NewGuid(); public Guid? RelationId { get; set; } public string EventType { get; set; } = ""; public string BeforeJson { get; set; } = "{}"; public string AfterJson { get; set; } = "{}"; public Guid? ContainerId { get; set; } public string Operator { get; set; } = ""; public DateTimeOffset OperatedAt { get; set; } public string Source { get; set; } = "Manual"; public string Reason { get; set; } = ""; public string Remark { get; set; } = ""; public string Extend { get; set; } = "{}"; } public sealed class Warehouse : EntityBase { [MaxLength(64)] public string Code { get; set; } = ""; [MaxLength(128)] public string Name { get; set; } = ""; [MaxLength(64)] public string Type { get; set; } = "Default"; public bool Enabled { get; set; } = true; public int SortOrder { get; set; } } public sealed class WarehouseArea : EntityBase { public Guid WarehouseId { get; set; } [MaxLength(64)] public string Code { get; set; } = ""; [MaxLength(128)] public string Name { get; set; } = ""; [MaxLength(64)] public string Type { get; set; } = "Storage"; [MaxLength(32)] public string LayoutMode { get; set; } = AreaLayoutModes.Flat; [MaxLength(32)] public string State { get; set; } = "Default"; public bool Enabled { get; set; } = true; public int SortOrder { get; set; } } public sealed class Storage : EntityBase { public Guid AreaId { get; set; } [MaxLength(64)] public string Code { get; set; } = ""; [MaxLength(128)] public string Name { get; set; } = ""; [MaxLength(64)] public string StorageType { get; set; } = "Storage"; [MaxLength(32)] public string LocationKind { get; set; } = LocationKinds.Station; public int ColumnNo { get; set; } public int LevelNo { get; set; } = 1; public int DepthNo { get; set; } = 1; [MaxLength(64)] public string SiteId { get; set; } = ""; [MaxLength(64)] public string SiteCode { get; set; } = ""; [MaxLength(128)] public string Barcode { get; set; } = ""; /// 已废弃:一货位一容器,保留列兼容旧库。 public int Capacity { get; set; } [MaxLength(32)] public string Status { get; set; } = StorageStatuses.Empty; [MaxLength(64)] public string Usage { get; set; } = ""; public int Priority { get; set; } [MaxLength(64)] public string ZoneCode { get; set; } = ""; public bool AllowInbound { get; set; } = true; public bool AllowOutbound { get; set; } = true; public bool Enabled { get; set; } = true; } public sealed class Container : EntityBase { public Guid? AreaId { get; set; } [MaxLength(64)] public string Code { get; set; } = ""; [MaxLength(128)] public string Name { get; set; } = ""; [MaxLength(64)] public string ContainerType { get; set; } = "Box"; [MaxLength(64)] public string Status { get; set; } = ContainerStatuses.EmptyMaterial; [MaxLength(128)] public string Barcode { get; set; } = ""; public double Length { get; set; } public double Width { get; set; } public double Height { get; set; } public bool Enabled { get; set; } = true; } public sealed class MaterialType : EntityBase { [MaxLength(64)] public string Code { get; set; } = ""; [MaxLength(128)] public string Name { get; set; } = ""; [MaxLength(128)] public string Spec { get; set; } = ""; [MaxLength(32)] public string Unit { get; set; } = "pcs"; [MaxLength(64)] public string Category { get; set; } = ""; [MaxLength(64)] public string BarcodePrefix { get; set; } = ""; public bool Enabled { get; set; } = true; } public sealed class Material : EntityBase { [MaxLength(64)] public string Code { get; set; } = ""; [MaxLength(128)] public string Name { get; set; } = ""; [MaxLength(64)] public string TypeCode { get; set; } = ""; [MaxLength(128)] public string Barcode { get; set; } = ""; [MaxLength(128)] public string Spec { get; set; } = ""; [MaxLength(32)] public string Unit { get; set; } = "pcs"; [MaxLength(64)] public string Category { get; set; } = ""; [MaxLength(32)] public string LifecycleStatus { get; set; } = MaterialLifecycles.Active; public DateTimeOffset? UnboundAt { get; set; } public bool Enabled { get; set; } = true; } public sealed class ContainerLocation : EntityBase { public Guid ContainerId { get; set; } [MaxLength(32)] public string LocationType { get; set; } = ContainerLocationTypes.Storage; [MaxLength(64)] public string LocationId { get; set; } = ""; [MaxLength(64)] public string LocationCode { get; set; } = ""; [MaxLength(128)] public string LocationName { get; set; } = ""; [MaxLength(32)] public string Status { get; set; } = ContainerLocationStatuses.Active; public DateTimeOffset EnteredAt { get; set; } } /// 容器-物料绑定(无数量语义;Quantity 列仅兼容旧库,固定为 1)。 public sealed class ContainerMaterial : EntityBase { public Guid ContainerId { get; set; } public Guid MaterialId { get; set; } public decimal Quantity { get; set; } = 1; [MaxLength(64)] public string BatchNo { get; set; } = ""; [MaxLength(64)] public string SerialNo { get; set; } = ""; [MaxLength(32)] public string Status { get; set; } = ContainerMaterialStatuses.Bound; public DateTimeOffset BoundAt { get; set; } public DateTimeOffset LoadedAt { get; set; } public DateTimeOffset? UnloadedAt { get; set; } } public sealed class StockEvent { public Guid Id { get; set; } = Guid.NewGuid(); [MaxLength(32)] public string EventType { get; set; } = ""; public Guid? MaterialId { get; set; } [MaxLength(64)] public string MaterialCode { get; set; } = ""; [MaxLength(128)] public string MaterialName { get; set; } = ""; [MaxLength(128)] public string MaterialBarcode { get; set; } = ""; [MaxLength(64)] public string MaterialTypeCode { get; set; } = ""; public Guid? ContainerId { get; set; } [MaxLength(64)] public string ContainerCode { get; set; } = ""; [MaxLength(128)] public string ContainerName { get; set; } = ""; public Guid? StorageId { get; set; } [MaxLength(64)] public string StorageCode { get; set; } = ""; [MaxLength(128)] public string StorageName { get; set; } = ""; [MaxLength(64)] public string AreaCode { get; set; } = ""; public Guid? FromStorageId { get; set; } [MaxLength(64)] public string FromStorageCode { get; set; } = ""; [MaxLength(128)] public string FromStorageName { get; set; } = ""; public Guid? ToStorageId { get; set; } [MaxLength(64)] public string ToStorageCode { get; set; } = ""; [MaxLength(128)] public string ToStorageName { get; set; } = ""; [MaxLength(64)] public string RefType { get; set; } = "Manual"; public Guid? RefId { get; set; } [MaxLength(64)] public string RefCode { get; set; } = ""; [MaxLength(128)] public string Operator { get; set; } = ""; public DateTimeOffset OperatedAt { get; set; } [MaxLength(500)] public string Reason { get; set; } = ""; } public sealed class ContainerLocationHistory : WarehouseHistoryBase { [MaxLength(32)] public string FromLocationType { get; set; } = ""; [MaxLength(64)] public string FromLocationId { get; set; } = ""; [MaxLength(32)] public string ToLocationType { get; set; } = ""; [MaxLength(64)] public string ToLocationId { get; set; } = ""; } public sealed class ContainerMaterialHistory : WarehouseHistoryBase { public Guid? MaterialId { get; set; } public decimal QuantityDelta { get; set; } } public static class AreaLayoutModes { public const string Flat = "Flat"; public const string Grid = "Grid"; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { Flat, Grid }; } public static class LocationKinds { public const string Grid = "Grid"; public const string Station = "Station"; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { Grid, Station }; } public static class ContainerLocationTypes { public const string Storage = "Storage"; public const string Car = "Car"; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { Storage, Car }; } public static class ContainerLocationStatuses { public const string Active = "Active"; public const string Locked = "Locked"; public const string Exception = "Exception"; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { Active, Locked, Exception }; } public static class ContainerMaterialStatuses { public const string Bound = "Bound"; // 兼容旧数据 public const string Loaded = "Loaded"; public const string Unloaded = "Unloaded"; public const string Adjusted = "Adjusted"; public const string Frozen = "Frozen"; public static readonly HashSet ActiveBind = new(StringComparer.OrdinalIgnoreCase) { Bound, Loaded, Adjusted, Frozen }; } public static class ContainerStatuses { public const string EmptyMaterial = "EmptyMaterial"; public const string FullMaterial = "FullMaterial"; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { EmptyMaterial, FullMaterial }; } public static class StorageStatuses { public const string Empty = "Empty"; public const string EmptyContainer = "EmptyContainer"; public const string FullContainer = "FullContainer"; public const string Disabled = "Disabled"; // 兼容旧值(读时映射,写时用新值) public const string Available = "Available"; public const string Idle = "Idle"; public const string Occupied = "Occupied"; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { Empty, EmptyContainer, FullContainer, Disabled }; public static string Normalize(string? status) => status switch { Available or Idle => Empty, Occupied => FullContainer, _ when string.IsNullOrWhiteSpace(status) => Empty, _ => status }; } public static class StorageTypes { public const string Storage = "Storage"; public const string LineSide = "LineSide"; public const string OfflinePoint = "OfflinePoint"; public const string Buffer = "Buffer"; public const string FinishedGoods = "FinishedGoods"; } public static class MaterialLifecycles { public const string Active = "Active"; public const string Archived = "Archived"; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { Active, Archived }; } public static class StockEventTypes { public const string Bind = "Bind"; public const string Unbind = "Unbind"; public const string ContainerMove = "ContainerMove"; } public static class WmsTransportTriggerTypes { public const string MaterialCall = "MaterialCall"; public const string FinishedGoodsOffline = "FinishedGoodsOffline"; public const string AutoTransfer = "AutoTransfer"; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { MaterialCall, FinishedGoodsOffline, AutoTransfer }; } public static class WmsTransportTaskStatuses { public const string Pending = "Pending"; public const string Reserved = "Reserved"; public const string Dispatched = "Dispatched"; public const string InTransit = "InTransit"; public const string Completed = "Completed"; public const string Failed = "Failed"; public const string Cancelled = "Cancelled"; public static readonly HashSet Active = new(StringComparer.OrdinalIgnoreCase) { Pending, Reserved, Dispatched, InTransit }; public static readonly HashSet All = new(StringComparer.OrdinalIgnoreCase) { Pending, Reserved, Dispatched, InTransit, Completed, Failed, Cancelled }; } public static class WmsReservationStatuses { public const string Active = "Active"; public const string Released = "Released"; public const string Expired = "Expired"; } public sealed class WmsTransportRule : EntityBase { [MaxLength(64)] public string Code { get; set; } = ""; [MaxLength(128)] public string Name { get; set; } = ""; [MaxLength(64)] public string TriggerType { get; set; } = WmsTransportTriggerTypes.MaterialCall; public bool Enabled { get; set; } = true; public int Priority { get; set; } public string SourceSelectorJson { get; set; } = "{}"; public string TargetSelectorJson { get; set; } = "{}"; public string TaskOptionsJson { get; set; } = "{}"; } public sealed class WmsTransportTask : EntityBase { [MaxLength(64)] public string BusinessType { get; set; } = ""; public Guid? RuleId { get; set; } public Guid SourceStorageId { get; set; } public Guid TargetStorageId { get; set; } public Guid ContainerId { get; set; } public Guid? MaterialId { get; set; } /// 已废弃:单物料实体模型不再使用数量。 public decimal? Quantity { get; set; } [MaxLength(32)] public string Status { get; set; } = WmsTransportTaskStatuses.Pending; [MaxLength(64)] public string DispatchMissionId { get; set; } = ""; [MaxLength(64)] public string DeliveryId { get; set; } = ""; [MaxLength(32)] public string DispatchStatus { get; set; } = ""; [MaxLength(500)] public string Reason { get; set; } = ""; public string SnapshotJson { get; set; } = "{}"; [MaxLength(1000)] public string ErrorMessage { get; set; } = ""; public int TaskPriority { get; set; } } public sealed class WmsTransportReservation : EntityBase { public Guid TaskId { get; set; } public Guid ContainerId { get; set; } public Guid SourceStorageId { get; set; } public Guid TargetStorageId { get; set; } [MaxLength(32)] public string Status { get; set; } = WmsReservationStatuses.Active; public DateTimeOffset? ExpiresAt { get; set; } } public sealed class WmsTransportTaskHistory { public Guid Id { get; set; } = Guid.NewGuid(); public Guid TaskId { get; set; } [MaxLength(32)] public string FromStatus { get; set; } = ""; [MaxLength(32)] public string ToStatus { get; set; } = ""; [MaxLength(128)] public string Operator { get; set; } = ""; public DateTimeOffset OperatedAt { get; set; } [MaxLength(500)] public string Reason { get; set; } = ""; [MaxLength(1000)] public string ErrorMessage { get; set; } = ""; public string SnapshotJson { get; set; } = "{}"; } public static class WmsDefaults { public const string DefaultWarehouseCode = "DEFAULT"; public const string DefaultWarehouseName = "默认仓库"; }