using BakeryErp.Infrastructure.Database; namespace BakeryErp.Infrastructure.Repositories; public sealed class SupplierRepository { private readonly DatabaseOptions _options; public SupplierRepository(DatabaseOptions options) { _options = options; } public IReadOnlyList List() { return LocalDataStoreFile.Load(_options) .Suppliers .OrderByDescending(static supplier => supplier.IsActive) .ThenBy(static supplier => supplier.Code) .ToList(); } public LocalSupplier? Find(Guid id) { return LocalDataStoreFile.Load(_options) .Suppliers .FirstOrDefault(supplier => supplier.Id == id); } public SaveSupplierResult Save(LocalSupplier supplier) { var store = LocalDataStoreFile.Load(_options); var normalizedCode = supplier.Code?.Trim().ToUpperInvariant() ?? string.Empty; var normalizedName = supplier.Name?.Trim() ?? string.Empty; if (string.IsNullOrWhiteSpace(normalizedCode) || string.IsNullOrWhiteSpace(normalizedName)) { return SaveSupplierResult.ValidationError("供應商代號與名稱為必填。"); } var duplicatedCode = store.Suppliers.Any(existing => existing.Id != supplier.Id && string.Equals(existing.Code, normalizedCode, StringComparison.OrdinalIgnoreCase)); if (duplicatedCode) { return SaveSupplierResult.ValidationError("供應商代號已存在,請改用其他代號。"); } var existingSupplier = store.Suppliers.FirstOrDefault(existing => existing.Id == supplier.Id); if (existingSupplier is null) { supplier.Id = supplier.Id == Guid.Empty ? Guid.NewGuid() : supplier.Id; supplier.Code = normalizedCode; supplier.Name = normalizedName; supplier.TaxId = BlankToNull(supplier.TaxId); supplier.ContactName = BlankToNull(supplier.ContactName); supplier.Phone = BlankToNull(supplier.Phone); supplier.Email = BlankToNull(supplier.Email); supplier.Address = BlankToNull(supplier.Address); supplier.PaymentTermDays = Math.Max(0, supplier.PaymentTermDays); supplier.CreatedAt = DateTime.UtcNow; supplier.IsActive = true; store.Suppliers.Add(supplier); } else { existingSupplier.Code = normalizedCode; existingSupplier.Name = normalizedName; existingSupplier.TaxId = BlankToNull(supplier.TaxId); existingSupplier.ContactName = BlankToNull(supplier.ContactName); existingSupplier.Phone = BlankToNull(supplier.Phone); existingSupplier.Email = BlankToNull(supplier.Email); existingSupplier.Address = BlankToNull(supplier.Address); existingSupplier.PaymentTermDays = Math.Max(0, supplier.PaymentTermDays); existingSupplier.UpdatedAt = DateTime.UtcNow; } LocalDataStoreFile.Save(_options, store); return SaveSupplierResult.Success(); } public void SetActive(Guid id, bool isActive) { var store = LocalDataStoreFile.Load(_options); var supplier = store.Suppliers.FirstOrDefault(existing => existing.Id == id); if (supplier is null) { return; } supplier.IsActive = isActive; supplier.UpdatedAt = DateTime.UtcNow; LocalDataStoreFile.Save(_options, store); } private static string? BlankToNull(string? value) { return string.IsNullOrWhiteSpace(value) ? null : value.Trim(); } } public sealed record SaveSupplierResult(bool IsSuccess, string? ErrorMessage) { public static SaveSupplierResult Success() => new(true, null); public static SaveSupplierResult ValidationError(string message) => new(false, message); }