Spaces:
Sleeping
Sleeping
| using BakeryErp.Infrastructure.Database; | |
| namespace BakeryErp.Infrastructure.Repositories; | |
| public sealed class SupplierRepository | |
| { | |
| private readonly DatabaseOptions _options; | |
| public SupplierRepository(DatabaseOptions options) | |
| { | |
| _options = options; | |
| } | |
| public IReadOnlyList<LocalSupplier> 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); | |
| } | |