Пример #1
0
        public AccountRepository_Test()
        {
            var dbLogger = new Mock <ILogger <ChilindoContext> >();
            // Given
            // https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory
            var options = new DbContextOptionsBuilder <ChilindoContext>()
                          .UseInMemoryDatabase(databaseName: "Chilindo")
                          .Options;

            using (var context = new ChilindoContext(options, dbLogger.Object))
            {
                context.Database.EnsureDeleted();

                context.Accounts.Add(new Account
                {
                    AccountNumber = 1234,
                    IsActive      = true,
                    Balances      = new List <AccountBalance>
                    {
                        new AccountBalance {
                            AccountNumber = 1234, Currency = "THB", Balance = 5000
                        },
                        new AccountBalance {
                            AccountNumber = 1234, Currency = "USD", Balance = 250
                        }
                    }
                });

                context.Accounts.Add(new Account
                {
                    AccountNumber = 3456,
                    IsActive      = true,
                    Balances      = new List <AccountBalance>
                    {
                        new AccountBalance {
                            AccountNumber = 3456, Currency = "THB", Balance = 22500
                        }
                    }
                });

                context.Accounts.Add(new Account
                {
                    AccountNumber = 7890,
                    IsActive      = true,
                    Balances      = new List <AccountBalance>
                    {
                        new AccountBalance {
                            AccountNumber = 7890, Currency = "USD", Balance = 750
                        }
                    }
                });

                context.SaveChanges();
            }
            var starWarsContext = new ChilindoContext(options, dbLogger.Object);
            var repoLogger      = new Mock <ILogger <AccountRepository> >();

            _accountRepository = new AccountRepository(starWarsContext, repoLogger.Object);
        }
Пример #2
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env,
                              ILoggerFactory loggerFactory, ChilindoContext db)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors(builder => builder
                        .AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());

            app.UseMvc();

            db.EnsureSeedData();
        }
Пример #3
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env,
                              ILoggerFactory loggerFactory, ChilindoContext db)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
                {
                    HotModuleReplacement      = true,
                    ReactHotModuleReplacement = true
                });
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Index" });
            });


            db.EnsureSeedData();
        }
Пример #4
0
        public static void EnsureSeedData(this ChilindoContext db)
        {
            if (db.Accounts == null)
            {
                return;
            }

            db._logger.LogInformation("Seeding database");

            //Account 1
            var account1 = new Account {
                AccountNumber = 1234, IsActive = true
            };

            account1.Balances = new List <AccountBalance>
            {
                new AccountBalance
                {
                    AccountNumber = 1234,
                    Currency      = "THB",
                    Balance       = 15000
                },
                new AccountBalance
                {
                    AccountNumber = 1234,
                    Currency      = "USD",
                    Balance       = 250
                },
            };

            //Account 2
            var account2 = new Account {
                AccountNumber = 3456, IsActive = true
            };

            account2.Balances = new List <AccountBalance>
            {
                new AccountBalance
                {
                    AccountNumber = 3456,
                    Currency      = "THB",
                    Balance       = 25000
                },
                new AccountBalance
                {
                    AccountNumber = 3456,
                    Currency      = "USD",
                    Balance       = 0
                },
            };

            //Account 3
            var account3 = new Account {
                AccountNumber = 7890, IsActive = true
            };

            account3.Balances = new List <AccountBalance>
            {
                new AccountBalance
                {
                    AccountNumber = 7890,
                    Currency      = "THB",
                    Balance       = 0
                },
                new AccountBalance
                {
                    AccountNumber = 7890,
                    Currency      = "USD",
                    Balance       = 500
                },
            };

            var accounts = new List <Account> {
                account1, account2, account3
            };

            if (!db.Accounts.Any())
            {
                db._logger.LogInformation("Seeding accounts");
                db.Accounts.AddRange(accounts);
                db.SaveChanges();
            }
        }
Пример #5
0
        public async Task <AccountTransactionResponse> Deposit(AccountTransactionRequest request, int maxRetry = 10, int retry = 1)
        {
            try
            {
                _logger.LogInformation($"Deposit amount to account number: {request.AccountNumber}");

                var account = await _db.Accounts
                              .Include(a => a.Balances)
                              .FirstOrDefaultAsync(acc => acc.AccountNumber == request.AccountNumber);

                if (account == null)
                {
                    return(ErrorResponse(request.AccountNumber, $"Invalid Account Number: {request.AccountNumber}"));
                }

                var balanceWithCurr = account.Balances.FirstOrDefault(b => b.Currency == request.Currency);

                if (balanceWithCurr == null)
                {
                    account.Balances.Add(new Core.Models.AccountBalance
                    {
                        Currency = request.Currency,
                        Balance  = request.Amount
                    });
                }
                else
                {
                    balanceWithCurr.Balance += request.Amount;
                }

                _db.TransactionHistories.Add(new TransactionHistory
                {
                    AccountNumber   = request.AccountNumber,
                    TransactionType = TransactionType.Deposit,
                    Currency        = request.Currency,
                    Amount          = request.Amount,
                    TransactionTime = DateTime.Now
                });

                await _db.SaveChangesAsync();

                account = await _db.Accounts
                          .Include(a => a.Balances)
                          .FirstOrDefaultAsync(acc => acc.AccountNumber == request.AccountNumber);

                return(ConvertToResponse(account, request.Currency));
            }
            catch (Exception ex)
            {
                if (maxRetry >= retry)
                {
                    _db = new ChilindoContext(_db._options, _db._logger);
                    await Task.Delay(200);

                    retry += 1;
                    return(await Deposit(request, maxRetry, retry));
                }
                else
                {
                    return(ErrorResponse(request.AccountNumber, ex.Message));
                }
            }
        }
Пример #6
0
 public AccountRepository(ChilindoContext db, ILogger <AccountRepository> logger)
 {
     _db     = db;
     _logger = logger;
 }
Пример #7
0
        public async Task <AccountTransactionResponse> Withdraw(AccountTransactionRequest request, int maxRetry = 10, int retry = 1)
        {
            try
            {
                _logger.LogInformation($"Withdraw amount to account number: {request.AccountNumber}");

                var account = await _db.Accounts
                              .Include(a => a.Balances)
                              .FirstOrDefaultAsync(acc => acc.AccountNumber == request.AccountNumber);

                if (account == null)
                {
                    return(ErrorResponse(request.AccountNumber, $"Invalid Account Number: {request.AccountNumber}"));
                }

                var balanceWithCurr = account.Balances.FirstOrDefault(b => b.Currency == request.Currency);

                if (balanceWithCurr == null || balanceWithCurr.Balance < request.Amount)
                {
                    return(new AccountTransactionResponse
                    {
                        AccountNumber = request.AccountNumber,
                        Successful = false,
                        Message = $"Insufficient balance",
                        Currency = request.Currency,
                        Balance = balanceWithCurr.Balance
                    });
                }

                balanceWithCurr.Balance -= request.Amount;

                _db.TransactionHistories.Add(new TransactionHistory
                {
                    AccountNumber   = request.AccountNumber,
                    TransactionType = TransactionType.Withdraw,
                    Currency        = request.Currency,
                    Amount          = request.Amount,
                    TransactionTime = DateTime.Now
                });
                await _db.SaveChangesAsync();

                account = await _db.Accounts
                          .Include(a => a.Balances)
                          .FirstOrDefaultAsync(acc => acc.AccountNumber == request.AccountNumber);

                return(ConvertToResponse(account, request.Currency));
            }
            catch (Exception ex)
            {
                if (maxRetry >= retry)
                {
                    _db = new ChilindoContext(_db._options, _db._logger);
                    await Task.Delay(200);

                    retry += 1;
                    return(await Withdraw(request, maxRetry, retry));
                }
                else
                {
                    return(ErrorResponse(request.AccountNumber, ex.Message));
                }
            }
        }