using Distribution.Infra.UoW; using Distribution.Models; namespace Distribution.Features.BankAccount; public class BankAccountService(IBankAccountRepository repo, IUnitOfWork uow) { private const string DefaultCurrency = "LKR"; private static BankAccountResponse ToResponse(Models.BankAccount a) => new( a.AccountType, a.Id, a.AccountName, a.AccountType == BankAccountType.Bank ? a.BankName : null, a.AccountType == BankAccountType.Cash ? a.CashAccountTypeName : null, a.AccountNumber, a.CurrencyCode, a.CreatedAt, a.AccountType == BankAccountType.Cash ? a.IsActive : null, a.AccountType == BankAccountType.Cash ? a.IsDefault : null); public async Task> ListAsync(BankAccountType? accountType) => (await repo.ListAsync(accountType)).Select(ToResponse).ToList(); public async Task> ListCashAccountTypesAsync() => (await repo.ListCashAccountTypeNamesAsync()).Select(n => new CashAccountTypeDto(n)).ToList(); public async Task CreateBankAsync(CreateBankAccountRequest request, CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(request.AccountName)) throw new InvalidOperationException("AccountName is required"); if (await repo.ExistsByNameAsync(BankAccountType.Bank, request.AccountName)) throw new InvalidOperationException("A bank account with this name already exists"); var account = new Models.BankAccount { AccountType = BankAccountType.Bank, AccountName = request.AccountName, BankName = request.BankName, AccountNumber = request.AccountNumber, CurrencyCode = string.IsNullOrWhiteSpace(request.CurrencyCode) ? DefaultCurrency : request.CurrencyCode!, IsActive = true, IsDefault = false }; await repo.AddAsync(account); await uow.CommitAsync(ct); return ToResponse(account); } public async Task CreateCashAsync(CreateCashAccountRequest request, CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(request.AccountName)) throw new InvalidOperationException("AccountName is required"); if (string.IsNullOrWhiteSpace(request.CashAccountTypeName)) throw new InvalidOperationException("CashAccountTypeName is required"); if (await repo.ExistsByNameAsync(BankAccountType.Cash, request.AccountName)) throw new InvalidOperationException("A cash account with this name already exists"); var account = new Models.BankAccount { AccountType = BankAccountType.Cash, AccountName = request.AccountName, CashAccountTypeName = request.CashAccountTypeName, AccountNumber = request.AccountNumber, CurrencyCode = string.IsNullOrWhiteSpace(request.CurrencyCode) ? DefaultCurrency : request.CurrencyCode!, IsActive = true, IsDefault = false }; await repo.AddAsync(account); await uow.CommitAsync(ct); return ToResponse(account); } public async Task UpdateCashAsync(Guid id, UpdateCashAccountRequest request, CancellationToken ct = default) { var account = await repo.GetByIdAsync(id); if (account is null || account.AccountType != BankAccountType.Cash) return null; if (string.IsNullOrWhiteSpace(request.AccountName)) throw new InvalidOperationException("AccountName is required"); if (await repo.ExistsByNameAsync(BankAccountType.Cash, request.AccountName, excludeId: id)) throw new InvalidOperationException("A cash account with this name already exists"); account.AccountName = request.AccountName; repo.Update(account); await uow.CommitAsync(ct); return ToResponse(account); } public async Task SetCashStatusAsync(Guid id, SetCashAccountStatusRequest request, CancellationToken ct = default) { var account = await repo.GetByIdAsync(id); if (account is null || account.AccountType != BankAccountType.Cash) return null; if (account.IsDefault && !request.IsActive) throw new InvalidOperationException("The default cash account cannot be deactivated"); account.IsActive = request.IsActive; repo.Update(account); await uow.CommitAsync(ct); return ToResponse(account); } public async Task DeleteCashAsync(Guid id, CancellationToken ct = default) { var account = await repo.GetByIdAsync(id); if (account is null || account.AccountType != BankAccountType.Cash) return false; if (account.IsDefault) throw new InvalidOperationException("The default cash account cannot be deleted"); repo.Remove(account); await uow.CommitAsync(ct); return true; } }