using System.ComponentModel.DataAnnotations; namespace PowderCoating.Application.DTOs.Inventory; public class InventoryItemDto { public int Id { get; set; } public string SKU { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string? Description { get; set; } public int? InventoryCategoryId { get; set; } public string? CategoryName { get; set; } public string Category { get; set; } = string.Empty; // Legacy field public string? ColorName { get; set; } public string? ColorCode { get; set; } public string? Finish { get; set; } public string? Manufacturer { get; set; } public string? ManufacturerPartNumber { get; set; } public decimal? CoverageSqFtPerLb { get; set; } public decimal? TransferEfficiency { get; set; } public int? CureTemperatureF { get; set; } public int? CureTimeMinutes { get; set; } public string? ColorFamilies { get; set; } public bool RequiresClearCoat { get; set; } public string? SpecPageUrl { get; set; } public string? ImageUrl { get; set; } public string? SdsUrl { get; set; } public string? TdsUrl { get; set; } public decimal QuantityOnHand { get; set; } public string UnitOfMeasure { get; set; } = "lbs"; public decimal ReorderPoint { get; set; } public decimal ReorderQuantity { get; set; } public decimal MinimumStock { get; set; } public decimal MaximumStock { get; set; } public decimal UnitCost { get; set; } public decimal AverageCost { get; set; } public decimal LastPurchasePrice { get; set; } public DateTime? LastPurchaseDate { get; set; } public int? PrimaryVendorId { get; set; } public string? PrimaryVendorName { get; set; } public string? VendorPartNumber { get; set; } public string? Location { get; set; } public string? Notes { get; set; } public bool IsActive { get; set; } public DateTime? DiscontinuedDate { get; set; } public DateTime CreatedAt { get; set; } public bool IsLowStock { get; set; } public bool IsOutOfStock { get; set; } public bool HasSamplePanel { get; set; } [Display(Name = "Inventory Asset Account")] public int? InventoryAccountId { get; set; } public string? InventoryAccountName { get; set; } [Display(Name = "COGS Account")] public int? CogsAccountId { get; set; } public string? CogsAccountName { get; set; } } public class InventoryListDto { public int Id { get; set; } public string SKU { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public int? InventoryCategoryId { get; set; } public string? CategoryName { get; set; } public string Category { get; set; } = string.Empty; // Legacy field public string? ColorName { get; set; } public decimal QuantityOnHand { get; set; } public string UnitOfMeasure { get; set; } = "lbs"; public decimal ReorderPoint { get; set; } public decimal UnitCost { get; set; } public int? PrimaryVendorId { get; set; } public string? PrimaryVendorName { get; set; } public bool IsActive { get; set; } public bool IsLowStock { get; set; } public bool IsOutOfStock { get; set; } public bool HasSamplePanel { get; set; } } public class CreateInventoryItemDto { [Required(ErrorMessage = "SKU is required")] [StringLength(50, ErrorMessage = "SKU cannot exceed 50 characters")] [Display(Name = "SKU")] public string SKU { get; set; } = string.Empty; [Required(ErrorMessage = "Name is required")] [StringLength(200, ErrorMessage = "Name cannot exceed 200 characters")] [Display(Name = "Item Name")] public string Name { get; set; } = string.Empty; [StringLength(2000, ErrorMessage = "Description cannot exceed 2000 characters")] [Display(Name = "Description")] public string? Description { get; set; } [Display(Name = "Category")] public int? InventoryCategoryId { get; set; } [StringLength(100, ErrorMessage = "Category cannot exceed 100 characters")] [Display(Name = "Legacy Category")] public string Category { get; set; } = string.Empty; // Legacy field - kept for backward compatibility [StringLength(100, ErrorMessage = "Color name cannot exceed 100 characters")] [Display(Name = "Color Name")] public string? ColorName { get; set; } [StringLength(50, ErrorMessage = "Color code cannot exceed 50 characters")] [Display(Name = "Color Code")] public string? ColorCode { get; set; } [StringLength(50, ErrorMessage = "Finish cannot exceed 50 characters")] [Display(Name = "Finish")] public string? Finish { get; set; } [StringLength(100, ErrorMessage = "Manufacturer cannot exceed 100 characters")] [Display(Name = "Manufacturer")] public string? Manufacturer { get; set; } [StringLength(100, ErrorMessage = "Manufacturer part number cannot exceed 100 characters")] [Display(Name = "Manufacturer Part Number")] public string? ManufacturerPartNumber { get; set; } [Range(0, 10000, ErrorMessage = "Coverage must be between 0 and 10,000 sq ft/lb")] [Display(Name = "Coverage (Sq Ft/Lb)")] public decimal? CoverageSqFtPerLb { get; set; } [Range(0, 100, ErrorMessage = "Transfer efficiency must be between 0 and 100%")] [Display(Name = "Transfer Efficiency (%)")] public decimal? TransferEfficiency { get; set; } [Range(200, 500, ErrorMessage = "Cure temperature must be between 200°F and 500°F")] [Display(Name = "Cure Temperature (°F)")] public int? CureTemperatureF { get; set; } [Range(1, 120, ErrorMessage = "Cure time must be between 1 and 120 minutes")] [Display(Name = "Cure Time (minutes)")] public int? CureTimeMinutes { get; set; } [Display(Name = "Color Families")] public string? ColorFamilies { get; set; } [Display(Name = "Requires Clear Coat")] public bool RequiresClearCoat { get; set; } [StringLength(500, ErrorMessage = "URL cannot exceed 500 characters")] [Display(Name = "Product URL")] public string? SpecPageUrl { get; set; } [StringLength(1000, ErrorMessage = "Image URL cannot exceed 1000 characters")] [Display(Name = "Product Image URL")] public string? ImageUrl { get; set; } [StringLength(1000, ErrorMessage = "URL cannot exceed 1000 characters")] [Display(Name = "Safety Data Sheet URL")] public string? SdsUrl { get; set; } [StringLength(1000, ErrorMessage = "URL cannot exceed 1000 characters")] [Display(Name = "Technical Data Sheet URL")] public string? TdsUrl { get; set; } [Range(0, 999999999, ErrorMessage = "Quantity on hand must be 0 or greater")] [Display(Name = "Quantity on Hand")] public decimal QuantityOnHand { get; set; } [Required(ErrorMessage = "Unit of measure is required")] [StringLength(20, ErrorMessage = "Unit of measure cannot exceed 20 characters")] [Display(Name = "Unit of Measure")] public string UnitOfMeasure { get; set; } = "lbs"; [Range(0, 999999999, ErrorMessage = "Reorder point must be 0 or greater")] [Display(Name = "Reorder Point")] public decimal ReorderPoint { get; set; } [Range(0, 999999999, ErrorMessage = "Reorder quantity must be 0 or greater")] [Display(Name = "Reorder Quantity")] public decimal ReorderQuantity { get; set; } [Range(0, 999999999, ErrorMessage = "Minimum stock must be 0 or greater")] [Display(Name = "Minimum Stock")] public decimal MinimumStock { get; set; } [Range(0, 999999999, ErrorMessage = "Maximum stock must be 0 or greater")] [Display(Name = "Maximum Stock")] public decimal MaximumStock { get; set; } [Range(0, 9999999.99, ErrorMessage = "Unit cost must be between 0 and 9,999,999.99")] [Display(Name = "Unit Cost")] public decimal UnitCost { get; set; } [Display(Name = "Primary Vendor")] public int? PrimaryVendorId { get; set; } [StringLength(100, ErrorMessage = "Vendor part number cannot exceed 100 characters")] [Display(Name = "Vendor Part Number")] public string? VendorPartNumber { get; set; } [StringLength(200, ErrorMessage = "Location cannot exceed 200 characters")] [Display(Name = "Location")] public string? Location { get; set; } [StringLength(2000, ErrorMessage = "Notes cannot exceed 2000 characters")] [Display(Name = "Notes")] public string? Notes { get; set; } [Display(Name = "Inventory Asset Account")] public int? InventoryAccountId { get; set; } [Display(Name = "COGS Account")] public int? CogsAccountId { get; set; } [Display(Name = "Sample Panel on Wall")] public bool HasSamplePanel { get; set; } } public class UpdateInventoryItemDto : CreateInventoryItemDto { [Required] public int Id { get; set; } [Display(Name = "Active")] public bool IsActive { get; set; } } public class InventoryTransactionDto { public int Id { get; set; } public int InventoryItemId { get; set; } public string ItemName { get; set; } = string.Empty; public string SKU { get; set; } = string.Empty; public string TransactionType { get; set; } = string.Empty; public decimal Quantity { get; set; } public decimal UnitCost { get; set; } public decimal TotalCost { get; set; } public DateTime TransactionDate { get; set; } public string? Reference { get; set; } public string? Notes { get; set; } public decimal BalanceAfter { get; set; } public int? PurchaseOrderId { get; set; } public string? PurchaseOrderNumber { get; set; } public int? JobId { get; set; } public string? JobNumber { get; set; } } public class PowderUsageLogDto { public int Id { get; set; } public int JobId { get; set; } public string JobNumber { get; set; } = string.Empty; public string? CustomerName { get; set; } public int? InventoryItemId { get; set; } public string? ItemName { get; set; } public string? SKU { get; set; } public string? CoatColor { get; set; } public decimal ActualLbsUsed { get; set; } public decimal EstimatedLbs { get; set; } public decimal VarianceLbs { get; set; } public DateTime RecordedAt { get; set; } public string? Notes { get; set; } } public class InventoryLedgerViewModel { public int? InventoryItemId { get; set; } public string? SelectedItemName { get; set; } public string? SelectedItemSku { get; set; } public DateTime? DateFrom { get; set; } public DateTime? DateTo { get; set; } public string? TypeFilter { get; set; } public List Transactions { get; set; } = new(); public List PowderUsageLogs { get; set; } = new(); public List AllItems { get; set; } = new(); public decimal TotalPurchased { get; set; } public decimal TotalUsed { get; set; } public decimal TotalAdjusted { get; set; } }