public async Task ConvertCurrencyAsync(CurrencyConvertionDTO request) { var holder = await DbContext.Holders.SingleOrDefaultAsync(CheckHolder(request)); if (holder == null) { throw new AccountNotFoundException(); } await DbContext.Entry(holder).Collection(h => h.Accounts).LoadAsync(); var accounts = holder.Accounts.Where(acc => (acc.Currency == request.SourceCurrency) || (acc.Currency == request.DestinationCurrency)); var sourceAccount = accounts.FirstOrDefault(a => a.Currency == request.SourceCurrency); if (sourceAccount == null) { throw new AccountNotFoundException(string.Format(AccountNotFoundException.WrongCurrencyMessage, request.SourceCurrency)); } var destAccount = accounts.FirstOrDefault(a => a.Currency == request.DestinationCurrency); if (destAccount == null) { throw new AccountNotFoundException(string.Format(AccountNotFoundException.WrongCurrencyMessage, request.DestinationCurrency)); } if (sourceAccount.Debit < request.Sum) { throw new InsufficientFundException(); } try { var convertRate = await RateService.GetRateAsync(request.SourceCurrency, request.DestinationCurrency); var debit = request.Sum * convertRate; sourceAccount.Debit -= request.Sum; destAccount.Debit += debit; } catch (CurrencyRateNotFoundException ex) { throw; } try { DbContext.Update(sourceAccount); DbContext.Update(destAccount); await DbContext.SaveChangesAsync(); } catch (DbUpdateConcurrencyException ex) { throw new ConcurrencyException(); } }
public async Task ConvertCurrency_ValidSuccess() { Setup_ConvertCurrency(); var dto = new CurrencyConvertionDTO { MasterAccount = ValidTestMasterAccount, SourceCurrency = "USD", Sum = 800m, DestinationCurrency = "RUB" }; var result = await _controller.ConvertCurrency(ValidTestMasterAccount, dto); _mockService.Verify(x => x.ConvertCurrencyAsync(It.IsAny <CurrencyConvertionDTO>()), Times.Once); Assert.IsType <NoContentResult>(result); Assert.Equal(41000m, _testData.Accounts.Single(a => a.Currency == dto.DestinationCurrency).Debit); Assert.Equal(0m, _testData.Accounts.Single(a => a.Currency == dto.SourceCurrency).Debit); }
public async Task ConvertCurrency_ThrowsException() { Setup_ConvertCurrency(); var dto = new CurrencyConvertionDTO { MasterAccount = ValidTestMasterAccount, SourceCurrency = "BUZ", Sum = 100m, DestinationCurrency = "RUB" }; var result = await _controller.ConvertCurrency(ValidTestMasterAccount, dto); _mockService.Verify(x => x.ConvertCurrencyAsync(It.IsAny <CurrencyConvertionDTO>()), Times.Once); var badRequest = Assert.IsType <BadRequestObjectResult>(result); Assert.False(_controller.ModelState.IsValid); Assert.Equal(1, _controller.ModelState.ErrorCount); }
public async Task ConvertCurrency_ModelStateError() { _controller.ModelState.AddModelError("Sum", "Sum should be in range 1..1,000,000"); var dto = new CurrencyConvertionDTO { MasterAccount = ValidTestMasterAccount, SourceCurrency = "USD", Sum = 99e6m, DestinationCurrency = "RUB" }; var result = await _controller.ConvertCurrency(ValidTestMasterAccount, dto); _mockService.Verify(x => x.ConvertCurrencyAsync(It.IsAny <CurrencyConvertionDTO>()), Times.Never); var badRequest = Assert.IsType <BadRequestObjectResult>(result); Assert.False(_controller.ModelState.IsValid); Assert.Equal(1, _controller.ModelState.ErrorCount); }
public async Task <IActionResult> ConvertCurrency(string accountNumber, [FromBody] CurrencyConvertionDTO request) { if (string.IsNullOrEmpty(accountNumber) || accountNumber != request.MasterAccount) { return(BadRequest(request)); } if (!ModelState.IsValid) { return(BadRequest(ModelState)); } try { await PocketService.ConvertCurrencyAsync(request); return(NoContent()); } catch (Exception ex) { return(HandleException(ex)); } }