Skip to content

Commit

Permalink
Merge pull request #8 from perebaj/balance
Browse files Browse the repository at this point in the history
✨ feat: balance
  • Loading branch information
perebaj authored Sep 26, 2023
2 parents 7510861 + b2a139a commit a50eafd
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 17 deletions.
41 changes: 34 additions & 7 deletions postgres/storage.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package postgres

import (
"context"

"github.com/jmoiron/sqlx"
"github.com/perebaj/contractus"
)
Expand All @@ -18,8 +20,8 @@ func NewStorage(db *sqlx.DB) *Storage {
}

// SaveTransaction is responsible for saving a transaction into the database.
func (s Storage) SaveTransaction(t *contractus.Transaction) error {
_, err := s.db.Exec(`
func (s Storage) SaveTransaction(ctx context.Context, t *contractus.Transaction) error {
_, err := s.db.ExecContext(ctx, `
INSERT INTO transactions (type, date, product_description, product_price_cents, seller_name, seller_type)
VALUES ($1, $2, $3, $4, $5, $6)
`, t.Type, t.Date, t.ProductDescription, t.ProductPriceCents, t.SellerName, t.SellerType)
Expand All @@ -29,10 +31,10 @@ func (s Storage) SaveTransaction(t *contractus.Transaction) error {

// Transactions is responsible for returning all the transactions from the database.
// TODO(JOJO): Have a way to paginate the transactions.
func (s Storage) Transactions() (contractus.TransactionResponse, error) {
func (s Storage) Transactions(ctx context.Context) (contractus.TransactionResponse, error) {
var transactions []contractus.Transaction

err := s.db.Select(&transactions, `
err := s.db.SelectContext(ctx, &transactions, `
SELECT type, date, product_description, product_price_cents, seller_name, seller_type
FROM transactions
`)
Expand All @@ -46,6 +48,31 @@ func (s Storage) Transactions() (contractus.TransactionResponse, error) {
}, nil
}

// func (s Storage) Balance(ctx context.Context) error {
// return nil
// }
// Balance is responsible for return the balance of a seller.
func (s Storage) Balance(ctx context.Context, sellerType, sellerName string) (*contractus.BalanceResponse, error) {
var transactions []contractus.Transaction

err := s.db.SelectContext(ctx, &transactions, `
SELECT type, date, product_description, product_price_cents, seller_name, seller_type
FROM transactions
WHERE seller_type = $1 AND seller_name = $2
`, sellerType, sellerName)

if err != nil {
return nil, err
}

var balance int64
for _, t := range transactions {
if t.Type != 3 {
balance += t.ProductPriceCents
} else {
balance -= t.ProductPriceCents
}
}

return &contractus.BalanceResponse{
Balance: balance,
SellerName: sellerName,
}, nil
}
109 changes: 101 additions & 8 deletions postgres/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,17 @@ func OpenDB(t *testing.T) *sqlx.DB {
func TestStorageSaveTransaction(t *testing.T) {
db := OpenDB(t)
storage := postgres.NewStorage(db)
ctx := context.Background()
want := contractus.Transaction{
Type: 1,
Date: time.Now().UTC(),
ProductDescription: "Product description",
ProductPriceCents: "1000",
ProductPriceCents: 1000,
SellerName: "John Doe",
SellerType: "producer",
}

err := storage.SaveTransaction(&want)
err := storage.SaveTransaction(ctx, &want)
if err != nil {
t.Fatalf("error saving transaction: %v", err)
}
Expand All @@ -108,12 +109,12 @@ func TestStorageSaveTransaction(t *testing.T) {
func TestStorageTransactions(t *testing.T) {
db := OpenDB(t)
storage := postgres.NewStorage(db)

ctx := context.Background()
want := contractus.Transaction{
Type: 1,
Date: time.Now().UTC(),
ProductDescription: "Product description",
ProductPriceCents: "1000",
ProductPriceCents: 1000,
SellerName: "John Doe",
SellerType: "producer",
}
Expand All @@ -122,22 +123,22 @@ func TestStorageTransactions(t *testing.T) {
Type: 2,
Date: time.Now().UTC(),
ProductDescription: "Product description 2",
ProductPriceCents: "2000",
ProductPriceCents: 2000,
SellerName: "John Doe 2",
SellerType: "affiliate",
}

err := storage.SaveTransaction(&want)
err := storage.SaveTransaction(ctx, &want)
if err != nil {
t.Fatalf("error saving transaction 1: %v", err)
}

err = storage.SaveTransaction(&want2)
err = storage.SaveTransaction(ctx, &want2)
if err != nil {
t.Fatalf("error saving transaction 2: %v", err)
}

got, err := storage.Transactions()
got, err := storage.Transactions(ctx)
if err != nil {
t.Fatalf("error getting transactions: %v", err)
}
Expand Down Expand Up @@ -165,6 +166,98 @@ func TestStorageTransactions(t *testing.T) {
}
}

func TestStorageBalance(t *testing.T) {
db := OpenDB(t)
storage := postgres.NewStorage(db)
ctx := context.Background()

transac1 := contractus.Transaction{
Type: 1,
Date: time.Now().UTC(),
ProductDescription: "Product description",
ProductPriceCents: 12750,
SellerName: "JOSE CARLOS",
SellerType: "producer",
}

transac2 := contractus.Transaction{
Type: 3,
Date: time.Now().UTC(),
ProductDescription: "Product description 2",
ProductPriceCents: 4500,
SellerName: "JOSE CARLOS",
SellerType: "producer",
}

transac3 := contractus.Transaction{
Type: 1,
Date: time.Now().UTC(),
ProductDescription: "Product description 3",
ProductPriceCents: 12750,
SellerName: "JOSE CARLOS",
SellerType: "producer",
}

err := storage.SaveTransaction(ctx, &transac1)
if err != nil {
t.Fatalf("error saving transaction 1: %v", err)
}

err = storage.SaveTransaction(ctx, &transac2)
if err != nil {
t.Fatalf("error saving transaction 2: %v", err)
}

err = storage.SaveTransaction(ctx, &transac3)
if err != nil {
t.Fatalf("error saving transaction 3: %v", err)
}

got, err := storage.Balance(ctx, "producer", "JOSE CARLOS")
if err != nil {
t.Fatalf("error getting balance: %v", err)
}

assert(t, got.Balance, int64(21000))
assert(t, got.SellerName, "JOSE CARLOS")

transac1 = contractus.Transaction{
Type: 2,
Date: time.Now().UTC(),
ProductDescription: "Product description",
ProductPriceCents: 155000,
SellerName: "CARLOS BATISTA",
SellerType: "affiliate",
}

transac2 = contractus.Transaction{
Type: 4,
Date: time.Now().UTC(),
ProductDescription: "Product description 2",
ProductPriceCents: 50000,
SellerName: "CARLOS BATISTA",
SellerType: "affiliate",
}

err = storage.SaveTransaction(ctx, &transac1)
if err != nil {
t.Fatalf("error saving transaction 1: %v", err)
}

err = storage.SaveTransaction(ctx, &transac2)
if err != nil {
t.Fatalf("error saving transaction 2: %v", err)
}

got, err = storage.Balance(ctx, "affiliate", "CARLOS BATISTA")
if err != nil {
t.Fatalf("error getting balance: %v", err)
}

assert(t, got.Balance, int64(205000))
assert(t, got.SellerName, "CARLOS BATISTA")
}

func assert(t *testing.T, got, want interface{}) {
t.Helper()

Expand Down
10 changes: 8 additions & 2 deletions transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@ import (
"time"
)

// TransactionResponse have the fields that represent the API response.
// TransactionResponse have the fields that represent the transactions API response.
type TransactionResponse struct {
Transactions []Transaction `json:"transactions"`
Total int `json:"total"`
}

// BalanceResponse have the fields that represent the seller balance API response.
type BalanceResponse struct {
Balance int64 `json:"balance"`
SellerName string `json:"seller_name"`
}

// Transaction have the fields that represent a single transaction.
type Transaction struct {
Type int `json:"type" db:"type"`
Date time.Time `json:"date" db:"date"`
ProductDescription string `json:"product_description" db:"product_description"`
ProductPriceCents string `json:"product_price_cents" db:"product_price_cents"`
ProductPriceCents int64 `json:"product_price_cents" db:"product_price_cents"`
SellerName string `json:"seller_name" db:"seller_name"`
SellerType string `json:"seller_type" db:"seller_type"`
}
Expand Down

0 comments on commit a50eafd

Please sign in to comment.