Initial commit: Lagerbestand Blazor Projekt
This commit is contained in:
commit
cba9414e92
105 files changed
+36431
No files matched your search
@@ -0,0 +1,259 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Lagerbestand.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Status of a tire stack in the storage system
|
||||
/// </summary>
|
||||
public enum TireStackStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Tires are currently stored in the warehouse
|
||||
/// </summary>
|
||||
Stored = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Tires have been picked up by the customer
|
||||
/// </summary>
|
||||
PickedUp = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Tires have been disposed/recycled
|
||||
/// </summary>
|
||||
Disposed = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Tires are reserved for pickup
|
||||
/// </summary>
|
||||
Reserved = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Tires are in inventory (shop stock, not customer-owned)
|
||||
/// </summary>
|
||||
Inventory = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a stack of exactly 4 tires as a single indivisible unit.
|
||||
/// A stack is always 4 identical tires - there is no variable count.
|
||||
/// This is the main entity that tracks customer tire storage and shop inventory.
|
||||
/// </summary>
|
||||
public class TireStack
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of tires in a stack - always 4
|
||||
/// </summary>
|
||||
public const int TiresPerStack = 4;
|
||||
|
||||
[Key]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>
|
||||
/// Custom item count for inventory (default: 4 = standard stack).
|
||||
/// Only used for inventory items. Customer stacks always use TiresPerStack.
|
||||
/// </summary>
|
||||
[Range(1, 99)]
|
||||
public int ItemCount { get; set; } = TiresPerStack;
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier/ticket number for this tire stack (e.g., "TS-2024-0001")
|
||||
/// This serves as the primary human-readable identifier.
|
||||
/// </summary>
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
public string TicketNumber { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Customer who owns these tires (null for shop inventory)
|
||||
/// </summary>
|
||||
public Guid? CustomerId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(CustomerId))]
|
||||
public Customer? Customer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Vehicle these tires belong to (null for shop inventory or legacy data)
|
||||
/// </summary>
|
||||
public Guid? VehicleId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(VehicleId))]
|
||||
public Vehicle? Vehicle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current storage location (null if picked up)
|
||||
/// </summary>
|
||||
public Guid? StorageLocationId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(StorageLocationId))]
|
||||
public StorageLocation? StorageLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tire category/type (used for inventory categorization)
|
||||
/// </summary>
|
||||
public Guid? CatalogItemId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(CatalogItemId))]
|
||||
public CatalogItem? CatalogItem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current status of the tire stack
|
||||
/// </summary>
|
||||
public TireStackStatus Status { get; set; } = TireStackStatus.Stored;
|
||||
|
||||
/// <summary>
|
||||
/// Tire size (e.g., "225/45R17")
|
||||
/// </summary>
|
||||
[MaxLength(50)]
|
||||
public string? TireSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tire brand (e.g., "Michelin", "Continental")
|
||||
/// </summary>
|
||||
[MaxLength(100)]
|
||||
public string? TireBrand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tire model (e.g., "Pilot Sport 4", "WinterContact TS 860")
|
||||
/// </summary>
|
||||
[MaxLength(100)]
|
||||
public string? TireModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Season type
|
||||
/// </summary>
|
||||
public TireSeason Season { get; set; } = TireSeason.Sommer;
|
||||
|
||||
/// <summary>
|
||||
/// Tread depth in mm (average of all 4 tires)
|
||||
/// </summary>
|
||||
[Range(0, 10)]
|
||||
public decimal? TreadDepth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DOT/manufacturing date code (e.g., "2523" = week 25 of 2023)
|
||||
/// </summary>
|
||||
[MaxLength(20)]
|
||||
public string? DotCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether tires are mounted on rims
|
||||
/// </summary>
|
||||
public bool WithRims { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Rim size if with rims (e.g., "17 Zoll")
|
||||
/// </summary>
|
||||
[MaxLength(20)]
|
||||
public string? RimSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TPMS sensors present
|
||||
/// </summary>
|
||||
public bool HasTpms { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tire condition rating
|
||||
/// </summary>
|
||||
public TireCondition Condition { get; set; } = TireCondition.Good;
|
||||
|
||||
/// <summary>
|
||||
/// Additional notes about the tire condition or special requirements
|
||||
/// </summary>
|
||||
[MaxLength(1000)]
|
||||
public string? Notes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Date when tires were stored
|
||||
/// </summary>
|
||||
public DateTime StoredAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// Date when tires were picked up
|
||||
/// </summary>
|
||||
public DateTime? PickedUpAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Expected pickup date (next season change)
|
||||
/// </summary>
|
||||
public DateTime? ExpectedPickupDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User who stored the tires
|
||||
/// </summary>
|
||||
public Guid? StoredByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User who processed the pickup
|
||||
/// </summary>
|
||||
public Guid? PickedUpByUserId { get; set; }
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this is shop inventory (not customer-owned)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public bool IsInventory => CustomerId == null;
|
||||
|
||||
/// <summary>
|
||||
/// Display name - customer name or category name for inventory
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string DisplayName => Customer?.FullName ?? CatalogItem?.Name ?? "Lagerbestand";
|
||||
|
||||
/// <summary>
|
||||
/// Summary description for display
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string Summary
|
||||
{
|
||||
get
|
||||
{
|
||||
var parts = new List<string>();
|
||||
if (!string.IsNullOrEmpty(TireBrand)) parts.Add(TireBrand);
|
||||
if (!string.IsNullOrEmpty(TireSize)) parts.Add(TireSize);
|
||||
parts.Add(Season.ToString());
|
||||
if (WithRims) parts.Add("mit Felgen");
|
||||
return string.Join(" | ", parts);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status display text in German
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string StatusText => Status switch
|
||||
{
|
||||
TireStackStatus.Stored => "Eingelagert",
|
||||
TireStackStatus.PickedUp => "Abgeholt",
|
||||
TireStackStatus.Disposed => "Entsorgt",
|
||||
TireStackStatus.Reserved => "Reserviert",
|
||||
TireStackStatus.Inventory => "Lagerbestand",
|
||||
_ => "Unbekannt"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Days stored (for billing purposes)
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public int DaysStored => (PickedUpAt ?? DateTime.UtcNow).Subtract(StoredAt).Days;
|
||||
|
||||
/// <summary>
|
||||
/// Condition display text in German
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string ConditionText => Condition switch
|
||||
{
|
||||
TireCondition.Excellent => "Sehr gut",
|
||||
TireCondition.Good => "Gut",
|
||||
TireCondition.Fair => "Ausreichend",
|
||||
TireCondition.Poor => "Mangelhaft",
|
||||
TireCondition.Critical => "Kritisch",
|
||||
_ => "Unbekannt"
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user