private async Task <DomainValidationResult <ITransaction> > CreateChargeTransactionAsync( IMoneyAccount account, Money money, TransactionMetadata?metadata = null, CancellationToken cancellationToken = default ) { var result = new DomainValidationResult <ITransaction>(); if (!account.HaveSufficientMoney(money)) { result.AddFailedPreconditionError("Insufficient funds."); } if (result.IsValid) { var transaction = account.Charge(money, metadata); await _accountRepository.CommitAsync(true, cancellationToken); return(transaction.Cast <Transaction>()); } return(result); }
private async Task <DomainValidationResult <ITransaction> > CreateWithdrawTransactionAsync( IMoneyAccount account, Money money, CancellationToken cancellationToken = default ) { var result = new DomainValidationResult <ITransaction>(); var transactionBundles = await this.FetchTransactionBundlesAsync(EnumTransactionType.Withdraw, EnumCurrencyType.Money); if (transactionBundles.All(withdraw => withdraw.Currency.Amount != money.Amount)) { result.AddFailedPreconditionError( $"The amount of {nameof(Money)} is invalid. These are valid amounts: [{string.Join(", ", transactionBundles.Select(deposit => deposit.Currency.Amount))}]."); } if (!account.HaveSufficientMoney(money)) { result.AddFailedPreconditionError("Insufficient funds."); } if (!account.IsWithdrawAvailable()) { result.AddFailedPreconditionError( $"Withdraw is unavailable until {account.LastWithdraw?.Add(MoneyAccountDecorator.WithdrawInterval)}. For security reason we limit the number of financial transaction that can be done in {MoneyAccountDecorator.WithdrawInterval.TotalHours} hours."); } if (result.IsValid) { var transaction = account.Withdraw(money); await _accountRepository.CommitAsync(true, cancellationToken); return(transaction.Cast <Transaction>()); } return(result); }