namespace BakeryErp.Infrastructure.Database; public sealed class LocalDataStore { public List Suppliers { get; set; } = []; public List Items { get; set; } = []; public List Stores { get; set; } = []; public List Warehouses { get; set; } = []; public List OcrDocuments { get; set; } = []; public List StockBalances { get; set; } = []; public List InventoryTransactions { get; set; } = []; public List PurchaseOrders { get; set; } = []; public List PettyCashTransactions { get; set; } = []; public List TransferOrders { get; set; } = []; public List StoreReturns { get; set; } = []; public List ReportDefinitions { get; set; } = []; public int SupplierCount => Suppliers.Count(static supplier => supplier.IsActive); public int ItemCount => Items.Count(static item => item.IsActive); public int StoreCount => Stores.Count(static store => store.IsActive); public int WarehouseCount => Warehouses.Count(static warehouse => warehouse.IsActive); public int OcrDocumentCount => OcrDocuments.Count; public static LocalDataStore CreateSeed() { return new LocalDataStore { Suppliers = [ new LocalSupplier { Id = Guid.Parse("55555555-5555-5555-5555-555555555555"), Code = "SUP-FLOUR", Name = "範例麵粉供應商", PaymentTermDays = 30, CreatedAt = DateTime.UtcNow, IsActive = true } ], Items = [ new LocalItem { Id = Guid.Parse("13131313-1313-1313-1313-131313131313"), Sku = "RM-FLOUR-001", Name = "高筋麵粉", ItemType = LocalItemType.RawMaterial, CategoryName = "麵粉", BaseUnit = "kg", SafetyStockQuantity = 50, ShelfLifeDays = 180, CreatedAt = DateTime.UtcNow, IsActive = true }, new LocalItem { Id = Guid.Parse("14141414-1414-1414-1414-141414141414"), Sku = "PKG-BAG-001", Name = "吐司袋", ItemType = LocalItemType.Packaging, CategoryName = "包材", BaseUnit = "個", SafetyStockQuantity = 500, CreatedAt = DateTime.UtcNow, IsActive = true } ], Stores = [ new LocalStore { Id = Guid.Parse("15151515-1515-1515-1515-151515151515"), Code = "HQ", Name = "中央廚房", StoreType = LocalStoreType.CentralKitchen, CreatedAt = DateTime.UtcNow, IsActive = true }, new LocalStore { Id = Guid.Parse("16161616-1616-1616-1616-161616161616"), Code = "S001", Name = "直營一店", StoreType = LocalStoreType.Direct, CreatedAt = DateTime.UtcNow, IsActive = true } ], Warehouses = [ new LocalWarehouse { Id = Guid.Parse("17171717-1717-1717-1717-171717171717"), Code = "WH-HQ", Name = "中央廚房主倉", StoreName = "中央廚房", WarehouseType = LocalWarehouseType.CentralKitchen, CreatedAt = DateTime.UtcNow, IsActive = true }, new LocalWarehouse { Id = Guid.Parse("18181818-1818-1818-1818-181818181818"), Code = "WH-S001", Name = "直營一店倉", StoreName = "直營一店", WarehouseType = LocalWarehouseType.Store, CreatedAt = DateTime.UtcNow, IsActive = true } ], OcrDocuments = [ new LocalOcrDocument { Id = Guid.Parse("88888888-8888-8888-8888-888888888888"), DocumentNumber = "OCR-20260525-001", FileName = "sample-receipt.jpg", SupplierName = "範例麵粉供應商", DocumentDate = DateOnly.FromDateTime(DateTime.Today), Status = LocalOcrStatus.Recognized, TotalAmount = 1280, RawText = "高筋麵粉 20kg x 2", ReviewNote = "範例辨識資料", CreatedAt = DateTime.UtcNow } ], StockBalances = [ new LocalStockBalance { Id = Guid.Parse("99999999-9999-9999-9999-999999999999"), WarehouseName = "中央廚房主倉", ItemSku = "RM-FLOUR-001", ItemName = "高筋麵粉", Unit = "kg", QuantityOnHand = 40, SafetyStockQuantity = 50, LastTransactionAt = DateTime.UtcNow }, new LocalStockBalance { Id = Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"), WarehouseName = "直營一店倉", ItemSku = "PKG-BAG-001", ItemName = "吐司袋", Unit = "個", QuantityOnHand = 800, SafetyStockQuantity = 500, LastTransactionAt = DateTime.UtcNow } ], InventoryTransactions = [ new LocalInventoryTransaction { Id = Guid.Parse("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"), TransactionNumber = "INV-20260525-001", WarehouseName = "中央廚房主倉", ItemSku = "RM-FLOUR-001", ItemName = "高筋麵粉", TransactionType = LocalInventoryTransactionType.GoodsReceipt, Quantity = 40, Unit = "kg", Status = LocalInventoryTransactionStatus.Approved, SourceDocumentNumber = "OCR-20260525-001", Note = "範例進貨入庫", OccurredAt = DateTime.UtcNow, CreatedAt = DateTime.UtcNow, ApprovedAt = DateTime.UtcNow } ], PurchaseOrders = [ new LocalPurchaseOrder { Id = Guid.Parse("cccccccc-cccc-cccc-cccc-cccccccccccc"), OrderNumber = "PO-20260525-001", SupplierName = "範例麵粉供應商", OrderDate = DateOnly.FromDateTime(DateTime.Today), ItemSku = "RM-FLOUR-001", ItemName = "高筋麵粉", Quantity = 40, Unit = "kg", UnitPrice = 32, Status = LocalPurchaseOrderStatus.Approved, Note = "範例採購單", CreatedAt = DateTime.UtcNow, ApprovedAt = DateTime.UtcNow } ], PettyCashTransactions = [ new LocalPettyCashTransaction { Id = Guid.Parse("dddddddd-dddd-dddd-dddd-dddddddddddd"), TransactionNumber = "PC-20260525-001", StoreName = "直營一店", TransactionDate = DateOnly.FromDateTime(DateTime.Today), TransactionType = LocalPettyCashTransactionType.Expense, ExpenseCategory = "清潔用品", Amount = 360, Description = "門市臨時採買清潔用品", Status = LocalPettyCashStatus.Approved, CreatedAt = DateTime.UtcNow, ApprovedAt = DateTime.UtcNow } ], TransferOrders = [ new LocalTransferOrder { Id = Guid.Parse("eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee"), TransferNumber = "TRF-20260525-001", StoreName = "直營一店", FromWarehouseName = "中央廚房主倉", ToWarehouseName = "直營一店倉", ItemSku = "PKG-BAG-001", ItemName = "吐司袋", RequestedQuantity = 200, PreparedQuantity = 200, ShippedQuantity = 200, ReceivedQuantity = 0, DifferenceQuantity = 0, Unit = "個", Status = LocalTransferStatus.InTransit, RequestDate = DateOnly.FromDateTime(DateTime.Today), CreatedAt = DateTime.UtcNow, ShippedAt = DateTime.UtcNow } ], StoreReturns = [ new LocalStoreReturn { Id = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), ReturnNumber = "RTN-20260525-001", StoreName = "直營一店", ItemSku = "PKG-BAG-001", ItemName = "吐司袋", Quantity = 20, Unit = "個", Reason = "破損", ReturnDate = DateOnly.FromDateTime(DateTime.Today), Status = LocalStoreReturnStatus.PendingCentralKitchenReview, CreatedAt = DateTime.UtcNow } ], ReportDefinitions = [ new LocalReportDefinition { Id = Guid.Parse("12121212-1212-1212-1212-121212121212"), ReportCode = "RPT-INVENTORY", ReportName = "即時庫存報表", ReportCategory = "庫存", Description = "輸出目前即時庫存、安全庫存與低庫存狀態。", Status = LocalReportStatus.Approved, CreatedAt = DateTime.UtcNow, ApprovedAt = DateTime.UtcNow } ], }; } public void EnsureSeedData() { if (Suppliers.Count == 0) { Suppliers = CreateSeed().Suppliers; } if (Items.Count == 0) { Items = CreateSeed().Items; } if (Stores.Count == 0) { Stores = CreateSeed().Stores; } if (Warehouses.Count == 0) { Warehouses = CreateSeed().Warehouses; } if (OcrDocuments.Count == 0) { OcrDocuments = CreateSeed().OcrDocuments; } if (StockBalances.Count == 0) { StockBalances = CreateSeed().StockBalances; } if (InventoryTransactions.Count == 0) { InventoryTransactions = CreateSeed().InventoryTransactions; } if (PurchaseOrders.Count == 0) { PurchaseOrders = CreateSeed().PurchaseOrders; } if (PettyCashTransactions.Count == 0) { PettyCashTransactions = CreateSeed().PettyCashTransactions; } if (TransferOrders.Count == 0) { TransferOrders = CreateSeed().TransferOrders; } if (StoreReturns.Count == 0) { StoreReturns = CreateSeed().StoreReturns; } if (ReportDefinitions.Count == 0) { ReportDefinitions = CreateSeed().ReportDefinitions; } } } public sealed class LocalSupplier { public Guid Id { get; set; } public string Code { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string? TaxId { get; set; } public string? ContactName { get; set; } public string? Phone { get; set; } public string? Email { get; set; } public string? Address { get; set; } public int PaymentTermDays { get; set; } = 30; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public bool IsActive { get; set; } = true; } public sealed class LocalItem { public Guid Id { get; set; } public string Sku { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public LocalItemType ItemType { get; set; } = LocalItemType.RawMaterial; public string CategoryName { get; set; } = string.Empty; public string BaseUnit { get; set; } = string.Empty; public decimal SafetyStockQuantity { get; set; } public int? ShelfLifeDays { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public bool IsActive { get; set; } = true; } public enum LocalItemType { RawMaterial = 1, SemiFinished = 2, FinishedProduct = 3, Packaging = 4, ExpenseSupply = 5 } public sealed class LocalStore { public Guid Id { get; set; } public string Code { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public LocalStoreType StoreType { get; set; } = LocalStoreType.Direct; public string? Phone { get; set; } public string? Address { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public bool IsActive { get; set; } = true; } public enum LocalStoreType { Direct = 1, Franchise = 2, CentralKitchen = 3 } public sealed class LocalWarehouse { public Guid Id { get; set; } public string Code { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string? StoreName { get; set; } public LocalWarehouseType WarehouseType { get; set; } = LocalWarehouseType.Store; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public bool IsActive { get; set; } = true; } public enum LocalWarehouseType { MainWarehouse = 1, CentralKitchen = 2, Store = 3 } public sealed class LocalOcrDocument { public Guid Id { get; set; } public string DocumentNumber { get; set; } = string.Empty; public string FileName { get; set; } = string.Empty; public string? SupplierName { get; set; } public DateOnly? DocumentDate { get; set; } public LocalOcrStatus Status { get; set; } = LocalOcrStatus.Uploaded; public decimal? TotalAmount { get; set; } public string? RawText { get; set; } public string? RecognizedItems { get; set; } public string? ReviewNote { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public DateTime? ReviewedAt { get; set; } } public enum LocalOcrStatus { Uploaded = 1, Recognized = 2, MappingRequired = 3, Confirmed = 4, ConvertedToReceipt = 5, Failed = 9 } public sealed class LocalStockBalance { public Guid Id { get; set; } public string WarehouseName { get; set; } = string.Empty; public string ItemSku { get; set; } = string.Empty; public string ItemName { get; set; } = string.Empty; public decimal QuantityOnHand { get; set; } public string Unit { get; set; } = string.Empty; public decimal SafetyStockQuantity { get; set; } public DateTime LastTransactionAt { get; set; } = DateTime.UtcNow; } public sealed class LocalInventoryTransaction { public Guid Id { get; set; } public string TransactionNumber { get; set; } = string.Empty; public string WarehouseName { get; set; } = string.Empty; public string ItemSku { get; set; } = string.Empty; public string ItemName { get; set; } = string.Empty; public LocalInventoryTransactionType TransactionType { get; set; } = LocalInventoryTransactionType.GoodsReceipt; public decimal Quantity { get; set; } public string Unit { get; set; } = string.Empty; public LocalInventoryTransactionStatus Status { get; set; } = LocalInventoryTransactionStatus.Draft; public string? SourceDocumentNumber { get; set; } public string? Note { get; set; } public DateTime OccurredAt { get; set; } = DateTime.UtcNow; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public DateTime? ApprovedAt { get; set; } } public enum LocalInventoryTransactionType { GoodsReceipt = 1, StockOut = 2, StockAdjustment = 3, Scrap = 4, StoreReturn = 5 } public enum LocalInventoryTransactionStatus { Draft = 1, PendingApproval = 2, Approved = 3, Cancelled = 9 } public sealed class LocalPurchaseOrder { public Guid Id { get; set; } public string OrderNumber { get; set; } = string.Empty; public string SupplierName { get; set; } = string.Empty; public DateOnly OrderDate { get; set; } = DateOnly.FromDateTime(DateTime.Today); public string ItemSku { get; set; } = string.Empty; public string ItemName { get; set; } = string.Empty; public decimal Quantity { get; set; } public string Unit { get; set; } = string.Empty; public decimal UnitPrice { get; set; } public decimal LineAmount => Quantity * UnitPrice; public LocalPurchaseOrderStatus Status { get; set; } = LocalPurchaseOrderStatus.Draft; public string? Note { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public DateTime? ApprovedAt { get; set; } public DateTime? ClosedAt { get; set; } } public enum LocalPurchaseOrderStatus { Draft = 1, PendingApproval = 2, Approved = 3, MonthlyClosed = 4, Cancelled = 9 } public sealed class LocalPettyCashTransaction { public Guid Id { get; set; } public string TransactionNumber { get; set; } = string.Empty; public string StoreName { get; set; } = string.Empty; public DateOnly TransactionDate { get; set; } = DateOnly.FromDateTime(DateTime.Today); public LocalPettyCashTransactionType TransactionType { get; set; } = LocalPettyCashTransactionType.Expense; public string ExpenseCategory { get; set; } = string.Empty; public decimal Amount { get; set; } public string? Description { get; set; } public string? ReceiptImagePath { get; set; } public LocalPettyCashStatus Status { get; set; } = LocalPettyCashStatus.Draft; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public DateTime? ApprovedAt { get; set; } public DateTime? ClosedAt { get; set; } } public enum LocalPettyCashTransactionType { Expense = 1, Replenishment = 2, Adjustment = 3 } public enum LocalPettyCashStatus { Draft = 1, PendingFinanceApproval = 2, Approved = 3, MonthlyClosed = 4, Replenished = 5, Rejected = 8, Cancelled = 9 } public sealed class LocalTransferOrder { public Guid Id { get; set; } public string TransferNumber { get; set; } = string.Empty; public string StoreName { get; set; } = string.Empty; public string FromWarehouseName { get; set; } = string.Empty; public string ToWarehouseName { get; set; } = string.Empty; public string ItemSku { get; set; } = string.Empty; public string ItemName { get; set; } = string.Empty; public decimal RequestedQuantity { get; set; } public decimal PreparedQuantity { get; set; } public decimal ShippedQuantity { get; set; } public decimal ReceivedQuantity { get; set; } public decimal DifferenceQuantity { get; set; } public string Unit { get; set; } = string.Empty; public LocalTransferStatus Status { get; set; } = LocalTransferStatus.Draft; public DateOnly RequestDate { get; set; } = DateOnly.FromDateTime(DateTime.Today); public string? Note { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public DateTime? PreparedAt { get; set; } public DateTime? ShippedAt { get; set; } public DateTime? ReceivedAt { get; set; } } public enum LocalTransferStatus { Draft = 1, StoreRequested = 2, Prepared = 3, InTransit = 4, Completed = 5, Discrepancy = 6, Cancelled = 9 } public sealed class LocalStoreReturn { public Guid Id { get; set; } public string ReturnNumber { get; set; } = string.Empty; public string StoreName { get; set; } = string.Empty; public string ItemSku { get; set; } = string.Empty; public string ItemName { get; set; } = string.Empty; public decimal Quantity { get; set; } public string Unit { get; set; } = string.Empty; public string Reason { get; set; } = string.Empty; public string? PhotoPath { get; set; } public DateOnly ReturnDate { get; set; } = DateOnly.FromDateTime(DateTime.Today); public LocalStoreReturnStatus Status { get; set; } = LocalStoreReturnStatus.Draft; public LocalStoreReturnDisposition? Disposition { get; set; } public string? ReviewNote { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public DateTime? ReviewedAt { get; set; } public DateTime? DisposedAt { get; set; } } public enum LocalStoreReturnStatus { Draft = 1, PendingCentralKitchenReview = 2, Approved = 3, Rejected = 4, Disposed = 5, Cancelled = 9 } public enum LocalStoreReturnDisposition { Restock = 1, Scrap = 2, ReturnToSupplier = 3 } public sealed class LocalReportDefinition { public Guid Id { get; set; } public string ReportCode { get; set; } = string.Empty; public string ReportName { get; set; } = string.Empty; public string ReportCategory { get; set; } = string.Empty; public string? Description { get; set; } public LocalReportStatus Status { get; set; } = LocalReportStatus.Draft; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } public DateTime? ApprovedAt { get; set; } } public enum LocalReportStatus { Draft = 1, PendingApproval = 2, Approved = 3, Cancelled = 9 }