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 }