public async Task <Result> SubtractMoney(int counterpartyAccountId, PaymentCancellationData data, UserInfo user) { return(await GetCounterpartyAccount(counterpartyAccountId) .Ensure(a => AreCurrenciesMatch(a, data), "Account and payment currency mismatch") .Ensure(IsAmountPositive, "Payment amount must be a positive number") .BindWithLock(_locker, a => Result.Success(a) .BindWithTransaction(_context, account => Result.Success(account) .Map(SubtractMoney) .Map(WriteAuditLog)))); bool IsAmountPositive(CounterpartyAccount account) => data.Amount.IsGreaterThan(decimal.Zero); async Task <CounterpartyAccount> SubtractMoney(CounterpartyAccount account) { account.Balance -= data.Amount; _context.Update(account); await _context.SaveChangesAsync(); return(account); } async Task <CounterpartyAccount> WriteAuditLog(CounterpartyAccount account) { var eventData = new CounterpartyAccountBalanceLogEventData(null, account.Balance); await _auditService.Write(AccountEventType.CounterpartySubtract, account.Id, data.Amount, user, eventData, null); return(account); } }
public async Task <Result> AddMoney(int counterpartyAccountId, PaymentData paymentData, UserInfo user) { return(await GetCounterpartyAccount(counterpartyAccountId) .Ensure(IsReasonProvided, "Payment reason cannot be empty") .Ensure(a => AreCurrenciesMatch(a, paymentData), "Account and payment currency mismatch") .BindWithLock(_locker, a => Result.Success(a) .Ensure(IsAmountPositive, "Payment amount must be a positive number") .BindWithTransaction(_context, account => Result.Success(account) .Map(AddMoneyToCounterparty) .Map(WriteAuditLog)))); bool IsReasonProvided(CounterpartyAccount account) => !string.IsNullOrEmpty(paymentData.Reason); bool IsAmountPositive(CounterpartyAccount account) => paymentData.Amount.IsGreaterThan(decimal.Zero); async Task <CounterpartyAccount> AddMoneyToCounterparty(CounterpartyAccount account) { account.Balance += paymentData.Amount; _context.Update(account); await _context.SaveChangesAsync(); return(account); } async Task <CounterpartyAccount> WriteAuditLog(CounterpartyAccount account) { var eventData = new CounterpartyAccountBalanceLogEventData(paymentData.Reason, account.Balance); await _auditService.Write(AccountEventType.CounterpartyAdd, account.Id, paymentData.Amount, user, eventData, null); return(account); } }
public async Task <Result> TransferToDefaultAgency(int counterpartyAccountId, MoneyAmount amount, UserInfo user) { return(await Result.Success(counterpartyAccountId) .Ensure(IsAmountPositive, "Payment amount must be a positive number") .Bind(GetCounterpartyAccount) .Ensure(a => AreCurrenciesMatch(a, amount), "Account and payment currency mismatch") .Bind(GetDefaultAgencyAccount) .BindWithLock(_locker, a => Result.Success(a) .Ensure(IsBalanceSufficient, "Could not charge money, insufficient balance") .BindWithTransaction(_context, accounts => Result.Success(accounts) .Map(TransferMoney) .Map(WriteAuditLog)))); bool IsAmountPositive(int _) => amount.Amount.IsGreaterThan(decimal.Zero); bool IsBalanceSufficient((CounterpartyAccount counterpartyAccount, AgencyAccount agencyAccount) accounts) => accounts.counterpartyAccount.Balance.IsGreaterOrEqualThan(amount.Amount); async Task <Result <(CounterpartyAccount, AgencyAccount)> > GetDefaultAgencyAccount(CounterpartyAccount counterpartyAccount) { var defaultAgency = await _context.Agencies .Where(a => a.CounterpartyId == counterpartyAccount.CounterpartyId && a.ParentId == null) .SingleOrDefaultAsync(); if (defaultAgency == null) { return(Result.Failure <(CounterpartyAccount, AgencyAccount)>("Could not find the default agency of the account owner")); } var agencyAccount = await _context.AgencyAccounts .Where(a => a.AgencyId == defaultAgency.Id && a.Currency == amount.Currency) .SingleOrDefaultAsync(); if (agencyAccount == null) { return(Result.Failure <(CounterpartyAccount, AgencyAccount)>("Could not find the default agency account")); } return(Result.Success <(CounterpartyAccount, AgencyAccount)>((counterpartyAccount, agencyAccount))); } async Task <(CounterpartyAccount, AgencyAccount)> TransferMoney((CounterpartyAccount, AgencyAccount) accounts) { var(counterpartyAccount, agencyAccount) = accounts; counterpartyAccount.Balance -= amount.Amount; _context.Update(counterpartyAccount); agencyAccount.Balance += amount.Amount; _context.Update(agencyAccount); await _context.SaveChangesAsync(); return(counterpartyAccount, agencyAccount); } async Task <(CounterpartyAccount, AgencyAccount)> WriteAuditLog((CounterpartyAccount, AgencyAccount) accounts) { var(counterpartyAccount, agencyAccount) = accounts; var counterpartyEventData = new CounterpartyAccountBalanceLogEventData(null, counterpartyAccount.Balance); await _auditService.Write(AccountEventType.CounterpartyTransferToAgency, counterpartyAccount.Id, amount.Amount, user, counterpartyEventData, null); var agencyEventData = new AccountBalanceLogEventData(null, agencyAccount.Balance); await _auditService.Write(AccountEventType.CounterpartyTransferToAgency, agencyAccount.Id, amount.Amount, user, agencyEventData, null); return(counterpartyAccount, agencyAccount); } }