diff --git a/BankAccount/go.mod b/BankAccount/go.mod new file mode 100644 index 0000000..75fe168 --- /dev/null +++ b/BankAccount/go.mod @@ -0,0 +1,8 @@ +module bankacc + +go 1.13 + +require ( + github.com/go-sql-driver/mysql v1.5.0 + github.com/stretchr/testify v1.4.0 +) diff --git a/BankAccount/go.sum b/BankAccount/go.sum new file mode 100644 index 0000000..ecf908b --- /dev/null +++ b/BankAccount/go.sum @@ -0,0 +1,13 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/BankAccount/pkg/store/transactionhistory.go b/BankAccount/pkg/store/transactionhistory.go index 72440ea..320fc15 100644 --- a/BankAccount/pkg/store/transactionhistory.go +++ b/BankAccount/pkg/store/transactionhistory.go @@ -1 +1,80 @@ package store + +import ( + "bankacc/pkg/entities" + "database/sql" + "fmt" + "time" +) + +type TransactionHistoryStore interface { + Insert(userId int, accountId int, amount float64, action string) (entities.TransactionHistory, error) + GetTransactionsById(id int) ([]entities.TransactionHistory, error) + GetTransactionsByIdFromToDate(id int, fromDate time.Time, toDate time.Time) ([]entities.TransactionHistory, error) +} + +type TransactionHistoryModel struct { + Db *sql.DB +} + +func NewTransactionHistoryStoreModel(db *sql.DB) *TransactionHistoryModel { + return &TransactionHistoryModel{ + Db: db, + } +} + +func (store *TransactionHistoryModel) Insert(userId int, accountId int, amount float64, action string) (entities.TransactionHistory, error) { + now := time.Now() + + result, err := store.Db.Exec("INSERT INTO TransactionHistory(user_id, account_id, amount, action, created_at) VALUES(?, ?, ?, ?, ?)", userId, accountId, amount, action, now) + if err != nil { + fmt.Println(err) + } + res, err := result.LastInsertId() + if err != nil { + fmt.Println(err) + } + transaction := entities.TransactionHistory{ + Id: int(res), + UserId: userId, + AccountId: accountId, + Amount: amount, + Action: action, + CreatedAt: now, + } + return transaction, nil +} + +func (store *TransactionHistoryModel) GetTransactionsById(id int) ([]entities.TransactionHistory, error) { + var transactions []entities.TransactionHistory + result, err := store.Db.Query("SELECT * FROM TransactionHistory WHERE user_id = ?", id) + if err != nil { + return nil, err + } + var transaction entities.TransactionHistory + for result.Next() { + err := result.Scan(&transaction.Id, &transaction.UserId, &transaction.AccountId, &transaction.Amount, &transaction.Action, &transaction.CreatedAt) + if err != nil { + return nil, err + } + transactions = append(transactions, transaction) + } + return transactions, nil +} + +func (store *TransactionHistoryModel) GetTransactionsByIdFromToDate(id int, fromDate time.Time, toDate time.Time) ([]entities.TransactionHistory, error) { + var transactions []entities.TransactionHistory + result, err := store.Db.Query("SELECT * FROM TransactionHistory WHERE user_id = ? and created_at BETWEEN ? and ?", id, fromDate, toDate) + if err != nil { + return nil, err + } + var transaction entities.TransactionHistory + for result.Next() { + err := result.Scan(&transaction.Id, &transaction.UserId, &transaction.AccountId, &transaction.Amount, &transaction.Action, &transaction.CreatedAt) + if err != nil { + return nil, err + } + transactions = append(transactions, transaction) + } + return transactions, nil +} diff --git a/BankAccount/pkg/tests/transactionhistorystore_test.go b/BankAccount/pkg/tests/transactionhistorystore_test.go new file mode 100644 index 0000000..ea677c9 --- /dev/null +++ b/BankAccount/pkg/tests/transactionhistorystore_test.go @@ -0,0 +1,213 @@ +package tests + +import ( + "bankacc/pkg/entities" + "bankacc/pkg/store" + "database/sql" + "log" + "testing" + "time" + + _ "github.com/go-sql-driver/mysql" + "github.com/stretchr/testify/suite" +) + +func MySQLInit() *sql.DB { + dbDriver := "mysql" + dbUser := "root" + dbPass := "Password1!" + dbName := "BankAccount?parseTime=true" + db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@/"+dbName) + if err != nil { + log.Println(err) + } + return db +} + +type TearDownTestSuite interface { + TearDownTest() +} + +type TransactionHistoryTestSuite struct { + suite.Suite + Transaction entities.TransactionHistory + Transactions []entities.TransactionHistory + TransactionStore store.TransactionHistoryModel + Db *sql.DB +} + +func (suite *TransactionHistoryTestSuite) SetupTest() { + var err error + suite.Db = MySQLInit() + transaction := store.NewTransactionHistoryStoreModel(suite.Db) + suite.Transactions = []entities.TransactionHistory{ + { + UserId: 1, + AccountId: 1, + Amount: 100, + Action: "Deposit", + }, + { + UserId: 1, + AccountId: 1, + Amount: 100, + Action: "Withdraw", + }, + { + UserId: 1, + AccountId: 2, + Amount: 44, + Action: "Deposit", + }, + { + UserId: 2, + AccountId: 1, + Amount: 741, + Action: "Withdraw", + }, + } + + for i, current := range suite.Transactions { + suite.Transaction, err = transaction.Insert(current.UserId, current.AccountId, current.Amount, current.Action) + if err != nil { + suite.T().Fatal("Unable to run InsertTransactionHistory store func") + } + suite.Transactions[i] = suite.Transaction + } +} + +func (suite *TransactionHistoryTestSuite) TestGetTransactionById() { + store := store.NewTransactionHistoryStoreModel(suite.Db) + var err error + var transaction []entities.TransactionHistory + var transactionsUserIDOne []entities.TransactionHistory + var transactionsUserIDTwo []entities.TransactionHistory + var transactionsUserIDFive []entities.TransactionHistory + now := time.Now() + + transaction, err = store.GetTransactionsById(1) + if err != nil { + suite.T().Fatal("Unable to run GetTransactionsById store func") + } + for i, current := range suite.Transactions { + current.CreatedAt = now + if len(transaction) > i { + transaction[i].CreatedAt = now + } + + if current.UserId == 1 { + transactionsUserIDOne = append(transactionsUserIDOne, current) + } + } + suite.Equal(transactionsUserIDOne, transaction, "Users with ID 1 not equal") + + transaction, err = store.GetTransactionsById(2) + if err != nil { + suite.T().Fatal("Unable to run GetTransactionsById store func") + } + for i, current := range suite.Transactions { + current.CreatedAt = now + if len(transaction) > i { + transaction[i].CreatedAt = now + } + if current.UserId == 2 { + transactionsUserIDTwo = append(transactionsUserIDTwo, current) + } + } + suite.Equal(transactionsUserIDTwo, transaction, "Users with ID 2 not equal") + + transaction, err = store.GetTransactionsById(5) + if err != nil { + suite.T().Fatal("Unable to run GetTransactionsById store func") + } + for i, current := range suite.Transactions { + current.CreatedAt = now + if len(transaction) > i { + transaction[i].CreatedAt = now + } + if current.UserId == 5 { + transactionsUserIDFive = append(transactionsUserIDFive, current) + } + } + suite.Equal(transactionsUserIDFive, transaction, "GetTransactionById should return empty struct") +} + +func (suite *TransactionHistoryTestSuite) TestGetTransactionByIdFromToDate() { + store := store.NewTransactionHistoryStoreModel(suite.Db) + var err error + var transaction []entities.TransactionHistory + var transactionsUserIDOne []entities.TransactionHistory + var transactionsUserIDTwo []entities.TransactionHistory + var transactionsUserIDFive []entities.TransactionHistory + var now time.Time + + for _, current := range suite.Transactions { + var k int + for k = current.CreatedAt.Nanosecond(); k >= 10; k = k / 10 { + } + if k >= 5 { + current.CreatedAt = suite.Transactions[0].CreatedAt.Add(time.Second * 1) + } + current.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", current.CreatedAt.UTC().Format("2006-01-02 15:04:05")) + now = current.CreatedAt + } + + transaction, err = store.GetTransactionsByIdFromToDate(1, now, now) + if err != nil { + suite.T().Fatal("Unable to run GetTransactionsById store func") + } + for i, current := range suite.Transactions { + current.CreatedAt = now + if len(transaction) > i { + transaction[i].CreatedAt = now + } + + if current.UserId == 1 { + transactionsUserIDOne = append(transactionsUserIDOne, current) + } + } + suite.Equal(transactionsUserIDOne, transaction, "Users with ID 1 not equal") + + transaction, err = store.GetTransactionsByIdFromToDate(2, now, now) + if err != nil { + suite.T().Fatal("Unable to run GetTransactionsById store func") + } + for i, current := range suite.Transactions { + current.CreatedAt = now + if len(transaction) > i { + transaction[i].CreatedAt = now + } + if current.UserId == 2 { + transactionsUserIDTwo = append(transactionsUserIDTwo, current) + } + } + suite.Equal(transactionsUserIDTwo, transaction, "Users with ID 2 not equal") + + transaction, err = store.GetTransactionsByIdFromToDate(5, now, now) + if err != nil { + suite.T().Fatal("Unable to run GetTransactionsById store func") + } + for i, current := range suite.Transactions { + current.CreatedAt = now + if len(transaction) > i { + transaction[i].CreatedAt = now + } + if current.UserId == 5 { + transactionsUserIDFive = append(transactionsUserIDFive, current) + } + } + suite.Equal(transactionsUserIDFive, transaction, "GetTransactionById should return empty struct") +} + +func TestTransactionHistoryTestSuite(t *testing.T) { + suite.Run(t, new(TransactionHistoryTestSuite)) +} + +func (suite *TransactionHistoryTestSuite) TearDownTest() { + for i := 0; i < len(suite.Transactions); i++ { + _, err := suite.Db.Exec("DELETE FROM TransactionHistory WHERE id=?", suite.Transactions[i].Id) + if err != nil { + suite.T().Fatal("Unable to run delete query") + } + } +}