public When_A_Valid_Payment_Requested_For_A_Account() { _accountDataStore = new Mock <IAccountDataStore>(); _account = new TestAccountBuilder() .WithAccountNumber("Acct123456") .WithAllowedPaymentSchemes(AllowedPaymentSchemes.FasterPayments) .WithBalance(500m) .WithStatus(AccountStatus.Live) .Build(); _accountDataStore.Setup(x => x.GetAccount(accountNumber)).Returns(_account); _paymentTypeRule = new Mock <IPaymentTypeRule>(); var paymentRule = new Dictionary <PaymentScheme, Func <IPaymentSchemeRules> >() { { PaymentScheme.Bacs, () => new BacsPaymentSchemeRule() }, { PaymentScheme.Chaps, () => new ChapsPaymentSchemeRule() }, { PaymentScheme.FasterPayments, () => new FasterPaymentSchemeRule() } }; _paymentScheme = PaymentScheme.FasterPayments; _paymentTypeRule.Setup(x => x.GetPaymentRule(_paymentScheme)).Returns(paymentRule[_paymentScheme]); _paymentService = new PaymentService(_accountDataStore.Object, _paymentTypeRule.Object); }
public void MakePaymentRequestWithInvalidPayementScheme() { Dictionary <String, Object> debitorAccount = (Dictionary <String, Object>)context["DebitorAccount"]; Dictionary <String, Object> creditorAccount = (Dictionary <String, Object>)context["CreditorAccount"]; DateTime paymentDate = DateTime.Now; string creditorAccountNumber = creditorAccount["AccountNumber"].ToString(); string debitorAccountNumber = debitorAccount["AccountNumber"].ToString(); decimal debitAmount = (decimal)context["DebitAmount"]; // Object status = Enum.Parse(typeof(AccountStatus), debitorAccount["AccountStatus"].ToString()); PaymentScheme debitorPaymentScheme = (PaymentScheme)Enum.Parse(typeof(PaymentScheme), debitorAccount["PaymentScheme"].ToString()); //Get invalid payment scheme var values = Enum.GetValues(typeof(PaymentScheme)); foreach (var val in values) { if (!(val.ToString().Equals(debitorAccount["PaymentScheme"].ToString()))) { debitorPaymentScheme = (PaymentScheme)Enum.Parse(typeof(PaymentScheme), val.ToString()); break; } } MakePaymentRequest request = new MakePaymentRequest(creditorAccountNumber, debitorAccountNumber, debitAmount, paymentDate, debitorPaymentScheme); PaymentService paymentService = new PaymentService(); MakePaymentResult result = paymentService.MakePayment(request); context["MakePaymentResult"] = result; }
public void GetPaymentSchemeValidator_ShouldReturnCorrectValidator(PaymentScheme paymentSceme) { _paymentSchemeValidatorServiceInTest = new PaymentSchemeValidatorService(new [] { _bacPaymentRequestValidatorMock.Object, _chapsPaymentRequestValidatorMock.Object, _fasterPaymentsPaymentRequestValidatorMock.Object }); var validator = _paymentSchemeValidatorServiceInTest.GetPaymentSchemeValidator(paymentSceme); Assert.That(validator, Is.Not.Null); }
public IPaymentType Get(PaymentScheme paymentScheme) { IPaymentType paymentType = this._paymentTypes.FirstOrDefault(p => p.Type == paymentScheme); Guard.AgainstNull(paymentType, $"PaymentType for Scheme {paymentScheme.ToString()} is not registered."); return(paymentType); }
public IPaymentSchemeRules GetPaymentRule(PaymentScheme paymentScheme) { var paymentRule = new Dictionary <PaymentScheme, Func <IPaymentSchemeRules> >() { { PaymentScheme.Bacs, () => new BacsPaymentSchemeRule() }, { PaymentScheme.Chaps, () => new ChapsPaymentSchemeRule() }, { PaymentScheme.FasterPayments, () => new FasterPaymentSchemeRule() } }; return(paymentRule[paymentScheme]()); }
public bool CheckAccountStatus(Account account, PaymentScheme paymentScheme, decimal requestedAmount) { if (account == null) { return(false); } var paymentValidator = paymentValidatorFactory.GetPaymentValidator(paymentScheme); return(paymentValidator.IsAccountAllowedToMakePayment(account, requestedAmount)); }
public void FailedPayment(PaymentScheme paymentScheme, PaymentScheme allowedPaymentSchemes, decimal balance, AccountStatus accountStatus) { var payment = new TestPaymentService(); payment.Account.AllowedPaymentSchemes = allowedPaymentSchemes; payment.Account.Balance = balance; payment.Account.Status = accountStatus; var request = CreateStandardRequest(paymentScheme); Assert.IsFalse(payment.MakePayment(request).Success); }
/// <summary> /// Creates a payment request for 50 pounds to credit account 111111 from 222222 now, /// using the specified payment scheme. /// </summary> private MakePaymentRequest CreateStandardRequest(PaymentScheme paymentScheme) { return(new MakePaymentRequest { Amount = 50.0M, CreditorAccountNumber = "11111111", DebtorAccountNumber = "22222222", PaymentDate = DateTime.Now, PaymentScheme = paymentScheme }); }
public MakePaymentRequest(string creditorAccountNumber, string debitorAccountNumber, decimal amount, DateTime paymentDate, PaymentScheme paymentScheme) { CreditorAccountNumber = creditorAccountNumber; DebtorAccountNumber = debitorAccountNumber; Amount = amount; PaymentDate = paymentDate; PaymentScheme = paymentScheme; }
public void Credit(decimal amount, PaymentScheme scheme) { ValidatePaymentType(scheme); //same comment as above applies if (this.Status != AccountStatus.Live && this.Status != AccountStatus.InboundPaymentsOnly) { throw new InvalidOperationException("Incorrect account status."); } this.Balance += amount; }
public void GivenIHavePaymentRequestDetails(PaymentScheme paymentScheme, string creditorAccountNumber, string debtorAccountNumber, decimal amount, DateTime paymentDate) { var request = new MakePaymentRequest() { PaymentScheme = paymentScheme, CreditorAccountNumber = creditorAccountNumber, DebtorAccountNumber = debtorAccountNumber, Amount = amount, PaymentDate = paymentDate }; ScenarioContext.Current["Request"] = request; }
public void ReturnsCorrectValidator(PaymentScheme scheme, Type expectedType) { // Arrange var factory = new ValidatorFactory(); var request = new MakePaymentRequest { PaymentScheme = scheme }; // Act var validator = factory.BuildValidator(request); // Assert Assert.AreEqual(expectedType, validator.GetType()); }
public virtual IPaymentSchemeValidator GetPaymentSchemeValidator(PaymentScheme paymentScheme) { switch (paymentScheme) { case PaymentScheme.Bacs: return(new BacsPaymentSchemeValidator()); case PaymentScheme.FasterPayments: return(new FasterPaymentSchemeValidator()); default: return(new ChapsPaymentSchemeValidator()); } }
protected void ValidatePaymentType(PaymentScheme scheme) { //To my knowledge this rule applies to all types of payments. Therefore it belongs here because in the spirit of //DDD and DRY it's part of the validation of the Account domain entity. //Another approach is to implement all the rules in a separate service e.g. IPaymentValidationService that is injected in Payment Service. //I didn't do that because logically these checks are common for all payment schemes. In a real world scenario it //would be clear from the bussiness requirements that it's beneficial to decouple the validation logic to separate //classes per payment scheme. if (!this.AllowedPaymentSchemes.HasFlag(scheme)) { //normally there would be a custom exception like DomainArgumentException etc throw new InvalidOperationException($"The account does not support {scheme.ToString()} payments."); } }
public IEnumerable <IPaymentRule> GetRules(PaymentScheme paymentScheme) { yield return(new AccountExistsRule()); yield return(new PaymentSchemeRule(GetAllowedPaymentSchemes(paymentScheme))); if (paymentScheme is PaymentScheme.FasterPayments) { yield return(new AccountHasFundsRule()); } if (paymentScheme is PaymentScheme.Chaps) { yield return(new AccountIsLiveRule()); } }
public void MakePaymentRequest() { Dictionary <String, Object> debitorAccount = (Dictionary <String, Object>)context["DebitorAccount"]; Dictionary <String, Object> creditorAccount = (Dictionary <String, Object>)context["CreditorAccount"]; DateTime paymentDate = DateTime.Now; string creditorAccountNumber = creditorAccount["AccountNumber"].ToString(); string debitorAccountNumber = debitorAccount["AccountNumber"].ToString(); decimal debitAmount = (decimal)context["DebitAmount"]; PaymentScheme paymentScheme = (PaymentScheme)Enum.Parse(typeof(PaymentScheme), debitorAccount["PaymentScheme"].ToString()); MakePaymentRequest request = new MakePaymentRequest(creditorAccountNumber, debitorAccountNumber, debitAmount, paymentDate, paymentScheme); PaymentService paymentService = new PaymentService(); MakePaymentResult result = paymentService.MakePayment(request); context["MakePaymentResult"] = result; }
public void Debit(decimal amount, PaymentScheme scheme) { ValidatePaymentType(scheme); //same comment as above applies if (this.Status != AccountStatus.Live) { throw new InvalidOperationException("Incorrect account status."); } else if (this.Balance < amount) { throw new InvalidOperationException("Insufficient funds."); } this.Balance -= amount; }
public IPaymentRule Create(PaymentScheme scheme) { switch (scheme) { case PaymentScheme.Bacs: return(new BacsPaymentRule(_accountSuitableRule)); case PaymentScheme.FasterPayments: return(new FasterPaymentsPaymentRule(_accountSuitableRule)); case PaymentScheme.Chaps: return(new ChapsPaymentRule(_accountSuitableRule)); default: throw new InvalidEnumArgumentException("Payment scheme not recognised"); } }
public IPaymentSchemeValidator Create(PaymentScheme paymentScheme, Account account, MakePaymentRequest request) { switch (paymentScheme) { case PaymentScheme.Bacs: return(new BacsPaymentSchemeValidator(account)); case PaymentScheme.Chaps: return(new ChapsPaymentSchemeValidator(account)); case PaymentScheme.FasterPayments: return(new FasterPaymentsPaymentSchemeValidator(account, request)); default: throw new PaymentSchemeNotFoundException($"The payment scheme '{paymentScheme}' was not found."); } }
public static IPaymentSchemeValidator GetValidator(PaymentScheme paymentScheme) { switch (paymentScheme) { case PaymentScheme.Bacs: return(new BacsPaymentSchemeValidator()); case PaymentScheme.FasterPayments: return(new FasterPaymentSchemeValidator()); case PaymentScheme.Chaps: return(new ChapsPaymentSchemeValidator()); default: return(new NullPaymentSchemeValidator()); } }
public IPaymentScheme GetPaymentScheme(PaymentScheme paymentScheme) { switch (paymentScheme) { case PaymentScheme.FasterPayments: return(new FasterPaymentScheme()); case PaymentScheme.Bacs: return(new BacsPaymentScheme()); case PaymentScheme.Chaps: return(new ChapsPaymentScheme()); default: return(null); } }
public IValidator GetValidator(PaymentScheme scheme) { switch (scheme) { case PaymentScheme.FasterPayments: return(new FasterPaymentValidator()); case PaymentScheme.Bacs: return(new BacsPaymentValidator()); case PaymentScheme.Chaps: return(new ChapsPaymentValidator()); default: throw new ArgumentOutOfRangeException(nameof(scheme)); } }
public PaymentSchemeValidator GetPaymentSchemeValidator(PaymentScheme allowedPaymentSchemes) { switch (allowedPaymentSchemes) { case PaymentScheme.Bacs: return(new BacsPaymentValidator()); case PaymentScheme.FasterPayments: return(new FasterPaymentsValidator()); case PaymentScheme.Chaps: return(new ChapsPaymentValidator()); } return(null); }
public static bool IsAllowedPaymentScheme(this Account account, PaymentScheme paymentScheme) { if (account == null) { return(false); } if ((int)paymentScheme != (int)account.AllowedPaymentSchemes) { return(false); } if ((int)paymentScheme != (int)AllowedPaymentSchemes.Chaps && account.Status != AccountStatus.Live) { return(false); } //Меня смутило то, что в AllowedPaymentScheme сдвинуты номера. Я решил оставить как есть. return(true); }
public void WhenRequestIsValid_AndAccountExists_AndHasMatchingAllowedPaymentScheme_UpdatesBalanceInDatastore( PaymentScheme requestedScheme, AllowedPaymentSchemes allowedScheme) { var storedAccount = ExistingStoredAccount(balance: 1000m, allowedScheme: allowedScheme); _mockDataStore.Setup(dataStore => dataStore.GetAccount(ExistingDebtorAccountNumber)) .Returns((true, storedAccount)); var makePaymentRequest = new MakePaymentRequest( "creditorAccount", ExistingDebtorAccountNumber, 100.0m, DateTime.Now, requestedScheme); _ = _paymentService.MakePayment(makePaymentRequest); _mockDataStore.Verify(datastore => datastore.UpdateAccount( It.Is <Account>(account => account.AccountNumber.Equals(ExistingDebtorAccountNumber) && account.Balance.Equals(900m) ))); }
public static bool ExecutePayment(PaymentScheme scheme, Account account, MakePaymentRequest request) { if (account != null) { switch (scheme) { case PaymentScheme.Bacs: if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Bacs)) { return(false); } break; case PaymentScheme.FasterPayments: if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.FasterPayments) || account.Balance < request.Amount) { return(false); } break; case PaymentScheme.Chaps: if (!account.AllowedPaymentSchemes.HasFlag(AllowedPaymentSchemes.Chaps)) { return(false); } else if (account.Status != AccountStatus.Live) { return(false); } break; default: return(false); } } return(false); }
public bool IsMovementAuthorized(Account originatorAccount, PaymentScheme scheme, decimal ammount) { // Avoid nesting for compiled code optimization if (originatorAccount == null || !originatorAccount.AllowedPaymentSchemes.HasFlag((AllowedPaymentSchemes)scheme)) { return(false); } var result = false; switch (scheme) { case PaymentScheme.FasterPayments: result = originatorAccount.HasValidBalance(ammount); break; case PaymentScheme.Bacs: result = true; break; case PaymentScheme.Chaps: result = originatorAccount.Status == AccountStatus.Live; break; default: // Although we just return false (for security reasons), we still keep track of the exception for later analysis // in a live system we might also include additional information required for future investigation taking sensitive data masking // needs into account // I also chose to maintain the default handler to deal with Logger.LogException(new ArgumentOutOfRangeException(nameof(scheme), scheme, null)); break; } return(result); }
public MakePaymentResult CheckPaymentEligible(PaymentScheme paymentScheme, Account account, decimal amount) { var result = new MakePaymentResult(); var paymentSchemeValidator = _resolvePaymentSchemeValidator.GetPaymentSchemeValidator(paymentScheme); switch (paymentScheme) { case PaymentScheme.Bacs: result.Success = (account != null) && paymentSchemeValidator.IsPaymentSchemeAllowedOnAccount(account); break; case PaymentScheme.FasterPayments: result.Success = (account != null) && paymentSchemeValidator.IsPaymentSchemeAllowedOnAccount(account) && _accountService.HasSuffientBalance(account, amount); break; case PaymentScheme.Chaps: result.Success = (account != null) && paymentSchemeValidator.IsPaymentSchemeAllowedOnAccount(account) && _accountService.CheckAccountStatus(account, AccountStatus.Live); break; } return(result); }
public void MakePayment_PaymentValidationServiceIsCalledWithCorrectPaymentScheme(PaymentScheme paymentScheme) { _makePaymentRequest.PaymentScheme = paymentScheme; _paymentServiceInTest.MakePayment(_makePaymentRequest); _paymentSchemeValidatorServiceMock.Verify(validatorService => validatorService.GetPaymentSchemeValidator(paymentScheme), Times.Once); }
public IPaymentValidator CreateValidator(PaymentScheme paymentScheme) { return(_paymentValidators[paymentScheme]); }
private void detach_PaymentSchemes(PaymentScheme entity) { this.SendPropertyChanging("PaymentSchemes"); entity.Organisation = null; }
private void attach_PaymentSchemes(PaymentScheme entity) { this.SendPropertyChanging("PaymentSchemes"); entity.Person = this; }
private void detach_PaymentSchemes(PaymentScheme entity) { this.SendPropertyChanging("PaymentSchemes"); entity.RbOKPF = null; }