private async Task <DomainValidationResult <ITransaction> > CreateDepositTransactionAsync( IMoneyAccount account, Money money, CancellationToken cancellationToken = default ) { var result = new DomainValidationResult <ITransaction>(); var transactionBundles = await this.FetchTransactionBundlesAsync(EnumTransactionType.Deposit, EnumCurrencyType.Money); if (transactionBundles.All(deposit => deposit.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.IsDepositAvailable()) { result.AddFailedPreconditionError( $"Deposit is unavailable until {account.LastDeposit?.Add(MoneyAccountDecorator.DepositInterval)}. For security reason we limit the number of financial transaction that can be done in {MoneyAccountDecorator.DepositInterval.TotalHours} hours."); } if (result.IsValid) { var transaction = account.Deposit(money); await _accountRepository.CommitAsync(true, cancellationToken); return(transaction.Cast <Transaction>()); } return(result); }
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> > CreateTransactionAsync( IMoneyAccount account, Money money, TransactionType type, TransactionMetadata?metadata = null, CancellationToken cancellationToken = default ) { if (type == TransactionType.Deposit) { return(await this.CreateDepositTransactionAsync(account, money, cancellationToken)); } if (type == TransactionType.Withdraw) { return(await this.CreateWithdrawTransactionAsync(account, money, cancellationToken)); } if (type == TransactionType.Charge) { return(await this.CreateChargeTransactionAsync( account, money, metadata, cancellationToken)); } if (type == TransactionType.Payout) { return(await this.CreatePayoutTransactionAsync( account, money, metadata, cancellationToken)); } if (type == TransactionType.Promotion) { return(await this.CreatePromotionTransactionAsync( account, money, metadata, cancellationToken)); } return(DomainValidationResult <ITransaction> .Failure("Unsupported transaction type for money currency.")); }
private async Task <DomainValidationResult <ITransaction> > CreatePromotionTransactionAsync( IMoneyAccount account, Money money, TransactionMetadata?metadata = null, CancellationToken cancellationToken = default ) { var result = new DomainValidationResult <ITransaction>(); if (result.IsValid) { var transaction = account.Promotion(money, metadata); transaction.MarkAsSucceeded(); await _accountRepository.CommitAsync(true, cancellationToken); return(transaction.Cast <Transaction>()); } return(result); }