140 lines
4.1 KiB
Go
140 lines
4.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
"git.pbiernat.dev/egommerce/api-entities/model"
|
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/event"
|
|
"git.pbiernat.dev/egommerce/go-api-pkg/api"
|
|
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
|
"git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
|
"github.com/georgysavva/scany/v2/pgxscan"
|
|
"github.com/go-redis/redis/v8"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
"github.com/streadway/amqp"
|
|
)
|
|
|
|
const (
|
|
ServiceUserAgent = "basket-httpclient"
|
|
)
|
|
|
|
type BasketService struct {
|
|
dbConn *pgxpool.Pool
|
|
redis *redis.Client
|
|
ebCh *amqp.Channel
|
|
log *fluentd.Logger
|
|
}
|
|
|
|
func NewBasketService(dbConn *pgxpool.Pool, redis *redis.Client, chn *amqp.Channel, log *fluentd.Logger) *BasketService {
|
|
return &BasketService{dbConn, redis, chn, log}
|
|
}
|
|
|
|
func (s *BasketService) Log(format string, val ...any) {
|
|
s.log.Log(format, val...)
|
|
}
|
|
|
|
func (s *BasketService) CreateBasket(ctx context.Context, basketID string) (*model.BasketModel, error) {
|
|
sql := `INSERT INTO basket.basket(id) VALUES($1)`
|
|
if _, err := s.dbConn.Exec(ctx, sql, basketID); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &model.BasketModel{ID: basketID}, nil // FIXME
|
|
}
|
|
|
|
func (s *BasketService) FetchFromDB(ctx context.Context, basketID string) (*model.BasketModel, error) {
|
|
basket := new(model.BasketModel)
|
|
err := pgxscan.Get(ctx, s.dbConn, basket, `SELECT id,state,created_at,updated_at FROM basket.basket WHERE id=$1 LIMIT 1`, basketID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return basket, nil
|
|
}
|
|
|
|
func (s *BasketService) FetchItems(ctx context.Context, basketID string) ([]*model.BasketItemModel, error) {
|
|
items := []*model.BasketItemModel{}
|
|
sql := `SELECT id,basket_id,product_id,quantity,price,created_at FROM basket.basket_item WHERE basket_id=$1`
|
|
rows, err := s.dbConn.Query(ctx, sql, basketID)
|
|
if err != nil {
|
|
// s.Log("Fetch basket items error: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
if err := pgxscan.ScanAll(&items, rows); err != nil {
|
|
// s.Log("Fetch basket items error: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
return items, nil
|
|
}
|
|
|
|
func (s *BasketService) FetchItem(ctx context.Context, basketID string, productID int) (*model.BasketItemModel, error) {
|
|
item := new(model.BasketItemModel)
|
|
sql := `SELECT id,basket_id,product_id,quantity,price,created_at FROM basket.basket_item WHERE basket_id=$1 AND product_id=$2 LIMIT 1`
|
|
err := pgxscan.Get(ctx, s.dbConn, item, sql, basketID, productID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return item, nil
|
|
}
|
|
|
|
func (s *BasketService) AddItem(ctx context.Context, itemID int, basketID string, qty int) error {
|
|
var price float64 = 0
|
|
pricingAPI := api.NewPricingAPI(ServiceUserAgent, s.redis)
|
|
|
|
productPrice, err := pricingAPI.GetProductPrice(itemID)
|
|
if err == nil {
|
|
price = productPrice.Price
|
|
}
|
|
|
|
sql := `INSERT INTO basket.basket_item(basket_id,product_id,price,quantity) VALUES($1,$2,$3,$4)`
|
|
if _, err := s.dbConn.Exec(ctx, sql, basketID, itemID, price, qty); err != nil {
|
|
return err
|
|
}
|
|
|
|
// update basket updated_at field...
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *BasketService) RemoveItem(ctx context.Context, itemID int, basketID string) error {
|
|
sql := `DELETE FROM basket.basket_item WHERE basket_id=$1 AND product_id=$2`
|
|
if _, err := s.dbConn.Exec(ctx, sql, basketID, itemID); err != nil {
|
|
return err
|
|
}
|
|
|
|
// update basket updated_at field...
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *BasketService) UpdateItem(ctx context.Context, item *model.BasketItemModel, qty int) error {
|
|
var price float64 = 0
|
|
pricingAPI := api.NewPricingAPI(ServiceUserAgent, s.redis)
|
|
|
|
productPrice, err := pricingAPI.GetProductPrice(item.ProductID)
|
|
if err == nil {
|
|
price = productPrice.Price
|
|
}
|
|
|
|
sql := `UPDATE basket.basket_item SET quantity=$1, price=$2 WHERE basket_id=$3 AND product_id=$4`
|
|
if _, err := s.dbConn.Exec(ctx, sql, qty, price, item.BasketID, item.ProductID); err != nil {
|
|
return err
|
|
}
|
|
|
|
// update basket updated_at field...
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *BasketService) Checkout(reqID, basketID string) (string, error) {
|
|
s.log.Log("Creating initial order from basket#:%s", basketID)
|
|
|
|
msg := &event.BasketCheckoutEvent{Event: event.NewEvent(reqID), BasketID: basketID} // FIXME: send more info...
|
|
rabbitmq.Publish(s.ebCh, "api-events", "basket.order.basketCheckout", msg)
|
|
|
|
return basketID, nil
|
|
}
|