Example #1
0
        public async Task GetAccountCachesCreatedProfileWhenNewAccountCreatedTest()
        {
            var provider = Guid.NewGuid().ToString();
            var username = Guid.NewGuid().ToString();
            var user     = Model.CreateWith <User>(provider + "|" + username);
            var account  = Model.Create <AccountResult>().Set(x => x.IsNewAccount = true);

            var accountStore = Substitute.For <IAccountStore>();
            var profileStore = Substitute.For <IProfileStore>();
            var accountCache = Substitute.For <IAccountCache>();
            var profileCache = Substitute.For <IProfileCache>();

            var sut = new AccountQuery(accountStore, profileStore, accountCache, profileCache);

            using (var tokenSource = new CancellationTokenSource())
            {
                accountStore.GetAccount(provider, username, tokenSource.Token).Returns(account);

                var actual = await sut.GetAccount(user, tokenSource.Token).ConfigureAwait(false);

                profileCache.Received(1).StoreProfile(Arg.Any <Profile>());
                profileCache.Received().StoreProfile(Arg.Is <Profile>(x => x.Id == actual.Id));
                profileCache.Received().StoreProfile(Arg.Is <Profile>(x => x.Email == user.Email));
                profileCache.Received().StoreProfile(Arg.Is <Profile>(x => x.FirstName == user.FirstName));
                profileCache.Received().StoreProfile(Arg.Is <Profile>(x => x.LastName == user.LastName));
            }
        }
Example #2
0
        public async Task GetAccountCachesAccountReturnedFromStoreTest()
        {
            var provider = Guid.NewGuid().ToString();
            var username = Guid.NewGuid().ToString();
            var user     = Model.CreateWith <User>(provider + "|" + username);
            var expected = Model.Create <AccountResult>().Set(x => x.IsNewAccount = false);

            var accountStore = Substitute.For <IAccountStore>();
            var profileStore = Substitute.For <IProfileStore>();
            var accountCache = Substitute.For <IAccountCache>();
            var profileCache = Substitute.For <IProfileCache>();

            var sut = new AccountQuery(accountStore, profileStore, accountCache, profileCache);

            using (var tokenSource = new CancellationTokenSource())
            {
                accountStore.GetAccount(provider, username, tokenSource.Token).Returns(expected);

                await sut.GetAccount(user, tokenSource.Token).ConfigureAwait(false);

                accountCache.Received().StoreAccount(expected);
                profileCache.DidNotReceive().StoreProfile(Arg.Any <Profile>());
                await profileStore.DidNotReceive().StoreProfile(Arg.Any <Profile>(), Arg.Any <CancellationToken>())
                .ConfigureAwait(false);
            }
        }
Example #3
0
        public void GetAccountThrowsExceptionWithNullUserTest()
        {
            var accountStore = Substitute.For <IAccountStore>();
            var profileStore = Substitute.For <IProfileStore>();
            var accountCache = Substitute.For <IAccountCache>();
            var profileCache = Substitute.For <IProfileCache>();

            var sut = new AccountQuery(accountStore, profileStore, accountCache, profileCache);

            Func <Task> action = async() => await sut.GetAccount(null, CancellationToken.None).ConfigureAwait(false);

            action.Should().Throw <ArgumentNullException>();
        }
        public async Task <IActionResult> GetAccountDetails([FromQuery(Name = "id")] int id = 0)
        {
            using (var db = new AppDb()) {
                await db.Connection.OpenAsync();

                var query  = new AccountQuery(db);
                var result = await query.GetAccount(id);

                if (result == null)
                {
                    return(new BadRequestResult());
                }
                return(new OkObjectResult(result));
            }
        }
Example #5
0
        public async Task GetAccountReturnsCachedAccountTest()
        {
            var user     = Model.Create <User>();
            var expected = Model.Create <Account>();

            var accountStore = Substitute.For <IAccountStore>();
            var profileStore = Substitute.For <IProfileStore>();
            var accountCache = Substitute.For <IAccountCache>();
            var profileCache = Substitute.For <IProfileCache>();

            var sut = new AccountQuery(accountStore, profileStore, accountCache, profileCache);

            using (var tokenSource = new CancellationTokenSource())
            {
                accountCache.GetAccount(user.Username).Returns(expected);

                var actual = await sut.GetAccount(user, tokenSource.Token).ConfigureAwait(false);

                actual.Should().BeEquivalentTo(expected);
            }
        }
Example #6
0
        public async Task GetAccountCachesNewAccountTest()
        {
            var provider = Guid.NewGuid().ToString();
            var username = Guid.NewGuid().ToString();
            var user     = Model.CreateWith <User>(provider + "|" + username);
            var account  = Model.Create <AccountResult>().Set(x => x.IsNewAccount = true);

            var accountStore = Substitute.For <IAccountStore>();
            var profileStore = Substitute.For <IProfileStore>();
            var accountCache = Substitute.For <IAccountCache>();
            var profileCache = Substitute.For <IProfileCache>();

            var sut = new AccountQuery(accountStore, profileStore, accountCache, profileCache);

            using (var tokenSource = new CancellationTokenSource())
            {
                accountStore.GetAccount(provider, username, tokenSource.Token).Returns(account);

                var actual = await sut.GetAccount(user, tokenSource.Token).ConfigureAwait(false);

                accountCache.Received().StoreAccount(actual);
            }
        }
Example #7
0
        public async Task GetAccountReturnsAccountByProviderAndUsernameTest()
        {
            var provider = Guid.NewGuid().ToString();
            var username = Guid.NewGuid().ToString();
            var user     = Model.CreateWith <User>(provider + "|" + username);
            var expected = Model.Create <AccountResult>();

            var accountStore = Substitute.For <IAccountStore>();
            var profileStore = Substitute.For <IProfileStore>();
            var accountCache = Substitute.For <IAccountCache>();
            var profileCache = Substitute.For <IProfileCache>();

            var sut = new AccountQuery(accountStore, profileStore, accountCache, profileCache);

            using (var tokenSource = new CancellationTokenSource())
            {
                accountStore.GetAccount(provider, username, tokenSource.Token).Returns(expected);

                var actual = await sut.GetAccount(user, tokenSource.Token).ConfigureAwait(false);

                actual.Should().BeEquivalentTo(expected);
            }
        }
Example #8
0
        public string TopUp([FromUri(Name = "account_id")] int?accId, decimal?amount)
        {
            int _accId;

            if (!accId.HasValue ||
                (accId.HasValue ? !int.TryParse(accId.Value.ToString(), out _accId) : false) ||
                accId.Value < 1)
            {
                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.INVALID_REQUEST,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.INVALID_REQUEST),
                    Message = "Указан некорректный параметр запроса"
                }));
            }

            decimal _amount;

            if (!amount.HasValue ||
                (amount.HasValue ? !decimal.TryParse(amount.Value.ToString(), out _amount) : false) ||
                amount.Value <= 0)
            {
                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.INVALID_REQUEST,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.INVALID_REQUEST),
                    Message = "Указан некорректный параметр запроса"
                }));
            }

            //Получение информации о счете
            Account acc = new Account();

            using (AccountQuery accQuery = new AccountQuery())
                acc = accQuery.GetAccount(accId.Value);

            if (acc == null)
            {
                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.SERVICE_ERROR,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.NOT_FOUND),
                    Message = "Счет для проведения транзакции не найден"
                }));
            }

            decimal currBalance = acc.Balance;

            try
            {
                acc.Balance += amount.Value;

                using (AccountQuery accQuery = new AccountQuery())
                    accQuery.UpdateEntity(acc);

                using (AccountHistoryQuery accHistQuery = new AccountHistoryQuery())
                    accHistQuery.CreateEntity(new AccountHistory()
                    {
                        AccId     = acc.Id,
                        ChangedAt = DateTime.Now,
                        Amount    = acc.Balance
                    });

                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.OK,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.OK),
                    Message = $"Внесение средств на счет в сумме {amount.Value}. Баланс счета {acc.Balance}"
                }));
            }
            catch (Exception ex)
            {
                //Откат операции
                using (AccountQuery accQuery = new AccountQuery())
                {
                    acc.Balance = currBalance;
                    accQuery.UpdateEntity(acc);
                }

                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.SERVICE_ERROR,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.SERVICE_ERROR),
                    Message = $"Внутренняя ошибка работы сервиса. {ex.Message}"
                }));
            }
        }
Example #9
0
        public string Transfer([FromUri(Name = "source_account_id")] int?srcAccId,
                               [FromUri(Name = "destination_account_id")] int?destAccId,
                               decimal?amount)
        {
            int _accId;

            if (!srcAccId.HasValue ||
                (srcAccId.HasValue ? !int.TryParse(srcAccId.Value.ToString(), out _accId) : false) ||
                srcAccId.Value < 1)
            {
                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.NOT_FOUND,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.NOT_FOUND),
                    Message = "Указан некорректный параметр запроса"
                }));
            }

            if (!destAccId.HasValue ||
                (destAccId.HasValue ? !int.TryParse(destAccId.Value.ToString(), out _accId) : false) ||
                destAccId.Value < 1)
            {
                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.NOT_FOUND,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.NOT_FOUND),
                    Message = "Указан некорректный параметр запроса"
                }));
            }

            decimal _amount;

            if (!amount.HasValue ||
                (amount.HasValue ? !decimal.TryParse(amount.Value.ToString(), out _amount) : false) ||
                amount.Value <= 0)
            {
                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.NOT_FOUND,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.NOT_FOUND),
                    Message = "Указан некорректный параметр запроса"
                }));
            }

            //Получение информации о счетах
            Account srcAcc, descAcc = new Account();

            using (AccountQuery accQuery = new AccountQuery())
            {
                srcAcc  = accQuery.GetAccount(srcAccId.Value);
                descAcc = accQuery.GetAccount(destAccId.Value);
            }

            if (srcAcc == null || descAcc == null)
            {
                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.SERVICE_ERROR,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.NOT_FOUND),
                    Message = "Счет для проведения транзакции не найден"
                }));
            }

            decimal srcAccCurrBalance  = srcAcc.Balance;
            decimal descAccCurrBalance = descAcc.Balance;

            try
            {
                if (srcAcc.Balance < amount.Value || srcAcc.Balance == 0)
                {
                    return(JsonConvert.SerializeObject(new AccountHistoryResp()
                    {
                        Code = (int)OperationCode.OK,
                        Status = Enum.GetName(typeof(OperationCode), OperationCode.OK),
                        Message = $"Запрашиваемая для снятия сумма ({amount.Value}) превышает остаток на счете {srcAcc.Balance}"
                    }));
                }

                srcAcc.Balance  -= amount.Value;
                descAcc.Balance += amount.Value;

                using (AccountQuery accQuery = new AccountQuery())
                {
                    accQuery.UpdateEntity(srcAcc);
                    accQuery.UpdateEntity(descAcc);
                }

                using (AccountHistoryQuery accHistQuery = new AccountHistoryQuery())
                {
                    accHistQuery.CreateEntity(new AccountHistory()
                    {
                        AccId     = srcAcc.Id,
                        ChangedAt = DateTime.Now,
                        Amount    = srcAcc.Balance
                    });

                    accHistQuery.CreateEntity(new AccountHistory()
                    {
                        AccId     = descAcc.Id,
                        ChangedAt = DateTime.Now,
                        Amount    = descAcc.Balance
                    });
                }

                return(JsonConvert.SerializeObject(new TransferResp()
                {
                    Code = (int)OperationCode.OK,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.OK),
                    Message = $"Перевод средств со счета {srcAcc.Id} в сумме {amount.Value} на счет {descAcc.Id}.",
                    SourceBalance = srcAcc.Balance,
                    DestinationBalance = descAcc.Balance
                }));
            }
            catch (Exception ex)
            {
                //Откат операции
                using (AccountQuery accQuery = new AccountQuery())
                {
                    srcAcc.Balance  = srcAccCurrBalance;
                    descAcc.Balance = descAccCurrBalance;

                    accQuery.UpdateEntity(srcAcc);
                    accQuery.UpdateEntity(descAcc);
                }

                return(JsonConvert.SerializeObject(new AccountHistoryResp()
                {
                    Code = (int)OperationCode.SERVICE_ERROR,
                    Status = Enum.GetName(typeof(OperationCode), OperationCode.SERVICE_ERROR),
                    Message = $"Внутренняя ошибка работы сервиса. {ex.Message}"
                }));
            }
        }