refactor shoppingbasketapp structure. service, repository in to domain directory

This commit is contained in:
mzfarshad 2026-04-17 19:36:23 +03:30
parent 39d85397d6
commit f4756345e0
8 changed files with 51 additions and 45 deletions

View File

@ -1,4 +1,4 @@
package cart package entity
import ( import (
"git.gocasts.ir/ebhomengo/niki/types" "git.gocasts.ir/ebhomengo/niki/types"

View File

@ -4,8 +4,8 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"git.gocasts.ir/ebhomengo/niki/domain/shoppingbasket/entity"
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
"git.gocasts.ir/ebhomengo/niki/shoppingbasketapp/service/cart"
"git.gocasts.ir/ebhomengo/niki/types" "git.gocasts.ir/ebhomengo/niki/types"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"strconv" "strconv"
@ -43,7 +43,7 @@ func (r Repo) itemKey(productID types.ID) string {
return fmt.Sprintf("item:%d", productID) return fmt.Sprintf("item:%d", productID)
} }
func (r Repo) AddItem(ctx context.Context, userID types.ID, item cart.Item) error { func (r Repo) AddItem(ctx context.Context, userID types.ID, item entity.Item) error {
const op = "shoppingbasketapp.repository.AddItem" const op = "shoppingbasketapp.repository.AddItem"
cartKey := r.cartKey(userID) cartKey := r.cartKey(userID)
@ -65,7 +65,7 @@ func (r Repo) AddItem(ctx context.Context, userID types.ID, item cart.Item) erro
} else { } else {
existsItem, _ := r.client.HGet(ctx, cartKey, itemKey).Result() existsItem, _ := r.client.HGet(ctx, cartKey, itemKey).Result()
if existsItem != "" { if existsItem != "" {
var i cart.Item var i entity.Item
if err := json.Unmarshal([]byte(existsItem), &i); err != nil { if err := json.Unmarshal([]byte(existsItem), &i); err != nil {
return richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err) return richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err)
} }
@ -91,31 +91,31 @@ func parsInt(s string) int64 {
return i return i
} }
func (r Repo) GetCart(ctx context.Context, userID types.ID) (cart.Cart, error) { func (r Repo) GetCart(ctx context.Context, userID types.ID) (entity.Cart, error) {
const op = "shoppingbasketapp.repository.GetCart" const op = "shoppingbasketapp.repository.GetCart"
cartKey := r.cartKey(userID) cartKey := r.cartKey(userID)
exists, err := r.client.Exists(ctx, cartKey).Result() exists, err := r.client.Exists(ctx, cartKey).Result()
if err != nil { if err != nil {
return cart.Cart{}, richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err) return entity.Cart{}, richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err)
} }
if exists == 0 { if exists == 0 {
return cart.Cart{}, richerror.New(op).WithKind(richerror.KindNotFound).WithMessage("not found shopping basket") return entity.Cart{}, richerror.New(op).WithKind(richerror.KindNotFound).WithMessage("not found shopping basket")
} }
allCart, err := r.client.HGetAll(ctx, cartKey).Result() allCart, err := r.client.HGetAll(ctx, cartKey).Result()
if err != nil { if err != nil {
return cart.Cart{}, richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err) return entity.Cart{}, richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err)
} }
c := cart.Cart{Items: []cart.Item{}} c := entity.Cart{Items: []entity.Item{}}
for field, value := range allCart { for field, value := range allCart {
if strings.HasPrefix(field, "item:") { if strings.HasPrefix(field, "item:") {
var i cart.Item var i entity.Item
if err := json.Unmarshal([]byte(value), &i); err != nil { if err := json.Unmarshal([]byte(value), &i); err != nil {
return cart.Cart{}, richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err) return entity.Cart{}, richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err)
} }
c.Items = append(c.Items, i) c.Items = append(c.Items, i)
@ -185,7 +185,7 @@ func (r Repo) UpdateQuantity(ctx context.Context, userID, productID types.ID, qu
return richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err) return richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err)
} }
var item cart.Item var item entity.Item
if err := json.Unmarshal([]byte(data), &item); err != nil { if err := json.Unmarshal([]byte(data), &item); err != nil {
return richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err) return richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err)
} }
@ -228,7 +228,7 @@ func (r Repo) updateTotalPrice(ctx context.Context, cartKey string) error {
for field, value := range allFields { for field, value := range allFields {
if strings.HasPrefix(field, "item:") { if strings.HasPrefix(field, "item:") {
var item cart.Item var item entity.Item
if err := json.Unmarshal([]byte(value), &item); err != nil { if err := json.Unmarshal([]byte(value), &item); err != nil {
return richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err) return richerror.New(op).WithKind(richerror.KindUnexpected).WithErr(err)

View File

@ -1,6 +1,9 @@
package cart package service
import "git.gocasts.ir/ebhomengo/niki/types" import (
"git.gocasts.ir/ebhomengo/niki/domain/shoppingbasket/entity"
"git.gocasts.ir/ebhomengo/niki/types"
)
type AddToCartRequest struct { type AddToCartRequest struct {
UserID types.ID `json:"user_id"` UserID types.ID `json:"user_id"`
@ -11,11 +14,11 @@ type AddToCartRequest struct {
} }
type GetCartResponse struct { type GetCartResponse struct {
UserID types.ID `json:"user_id"` UserID types.ID `json:"user_id"`
Items []Item `json:"items"` Items []entity.Item `json:"items"`
TotalPrice types.Price `json:"total_price"` TotalPrice types.Price `json:"total_price"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
ExpireAt int64 `json:"expire_at"` ExpireAt int64 `json:"expire_at"`
} }
type RemoveFromCartRequest struct { type RemoveFromCartRequest struct {

View File

@ -1,7 +1,8 @@
package cart package service
import ( import (
"context" "context"
"git.gocasts.ir/ebhomengo/niki/domain/shoppingbasket/entity"
"git.gocasts.ir/ebhomengo/niki/pkg/logger" "git.gocasts.ir/ebhomengo/niki/pkg/logger"
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
"git.gocasts.ir/ebhomengo/niki/types" "git.gocasts.ir/ebhomengo/niki/types"
@ -9,8 +10,8 @@ import (
) )
type Repository interface { type Repository interface {
AddItem(ctx context.Context, userID types.ID, item Item) error AddItem(ctx context.Context, userID types.ID, item entity.Item) error
GetCart(ctx context.Context, userID types.ID) (Cart, error) GetCart(ctx context.Context, userID types.ID) (entity.Cart, error)
DeleteItem(ctx context.Context, userID, productID types.ID) error DeleteItem(ctx context.Context, userID, productID types.ID) error
UpdateQuantity(ctx context.Context, userID, productID types.ID, quantity int) error UpdateQuantity(ctx context.Context, userID, productID types.ID, quantity int) error
DeleteCart(ctx context.Context, userID types.ID) error DeleteCart(ctx context.Context, userID types.ID) error
@ -33,7 +34,7 @@ func (s Service) AddToBasket(ctx context.Context, req AddToCartRequest) error {
return err return err
} }
return s.repo.AddItem(ctx, req.UserID, Item{ return s.repo.AddItem(ctx, req.UserID, entity.Item{
ProductID: req.ProductID, ProductID: req.ProductID,
Quantity: req.Quantity, Quantity: req.Quantity,
Price: req.Price, Price: req.Price,

View File

@ -1,4 +1,4 @@
package cart package service
import ( import (
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"

View File

@ -4,11 +4,12 @@ import (
"context" "context"
"fmt" "fmt"
"git.gocasts.ir/ebhomengo/niki/adapter/redis" "git.gocasts.ir/ebhomengo/niki/adapter/redis"
"git.gocasts.ir/ebhomengo/niki/domain/shoppingbasket/repository"
"git.gocasts.ir/ebhomengo/niki/domain/shoppingbasket/service"
"git.gocasts.ir/ebhomengo/niki/pkg/httpserver" "git.gocasts.ir/ebhomengo/niki/pkg/httpserver"
"git.gocasts.ir/ebhomengo/niki/pkg/logger" "git.gocasts.ir/ebhomengo/niki/pkg/logger"
"git.gocasts.ir/ebhomengo/niki/shoppingbasketapp/delivery/http" "git.gocasts.ir/ebhomengo/niki/shoppingbasketapp/delivery/http"
"git.gocasts.ir/ebhomengo/niki/shoppingbasketapp/repository" "git.gocasts.ir/ebhomengo/niki/shoppingbasketapp/delivery/http/cart"
"git.gocasts.ir/ebhomengo/niki/shoppingbasketapp/service/cart"
"os" "os"
"os/signal" "os/signal"
"sync" "sync"
@ -17,8 +18,8 @@ import (
type Application struct { type Application struct {
Repo repository.Repo Repo repository.Repo
Service cart.Service Service service.Service
Handler http.Handler Handler cart.Handler
Server http.Server Server http.Server
Config Config Config Config
} }
@ -28,10 +29,10 @@ func Setup(ctx context.Context, cfg Config) (Application, error) {
adapter := redis.New(cfg.Redis) adapter := redis.New(cfg.Redis)
repo := repository.New(adapter.Client(), cfg.Repo) repo := repository.New(adapter.Client(), cfg.Repo)
validator := cart.NewValidate() validator := service.NewValidate()
svc := cart.New(validator, repo) svc := service.New(validator, repo)
handler := http.NewHandler(svc) handler := cart.NewHandler(svc)
httpServer, err := httpserver.New(cfg.HTTPServer) httpServer, err := httpserver.New(cfg.HTTPServer)
if err != nil { if err != nil {

View File

@ -1,4 +1,4 @@
package http package cart
import ( import (
"git.gocasts.ir/ebhomengo/niki/pkg/claim" "git.gocasts.ir/ebhomengo/niki/pkg/claim"
@ -18,7 +18,7 @@ func NewHandler(svc cart.Service) Handler {
return Handler{svc: svc} return Handler{svc: svc}
} }
func (h Handler) addToBasket(c echo.Context) error { func (h Handler) AddToBasket(c echo.Context) error {
claims := claim.GetClaimsFromEchoContext(c) claims := claim.GetClaimsFromEchoContext(c)
var req cart.AddToCartRequest var req cart.AddToCartRequest
@ -37,7 +37,7 @@ func (h Handler) addToBasket(c echo.Context) error {
return c.NoContent(http.StatusNoContent) return c.NoContent(http.StatusNoContent)
} }
func (h Handler) getCart(c echo.Context) error { func (h Handler) GetCart(c echo.Context) error {
claims := claim.GetClaimsFromEchoContext(c) claims := claim.GetClaimsFromEchoContext(c)
res, err := h.svc.GetCart(c.Request().Context(), types.ID(claims.UserID)) res, err := h.svc.GetCart(c.Request().Context(), types.ID(claims.UserID))
@ -49,7 +49,7 @@ func (h Handler) getCart(c echo.Context) error {
return c.JSON(http.StatusOK, res) return c.JSON(http.StatusOK, res)
} }
func (h Handler) removeCart(c echo.Context) error { func (h Handler) RemoveCart(c echo.Context) error {
claims := claim.GetClaimsFromEchoContext(c) claims := claim.GetClaimsFromEchoContext(c)
if err := h.svc.ClearCart(c.Request().Context(), types.ID(claims.UserID)); err != nil { if err := h.svc.ClearCart(c.Request().Context(), types.ID(claims.UserID)); err != nil {
@ -60,7 +60,7 @@ func (h Handler) removeCart(c echo.Context) error {
return c.NoContent(http.StatusNoContent) return c.NoContent(http.StatusNoContent)
} }
func (h Handler) removeItem(c echo.Context) error { func (h Handler) RemoveItem(c echo.Context) error {
claims := claim.GetClaimsFromEchoContext(c) claims := claim.GetClaimsFromEchoContext(c)
p := c.Param("productID") p := c.Param("productID")
@ -84,7 +84,7 @@ func (h Handler) removeItem(c echo.Context) error {
return c.NoContent(http.StatusNoContent) return c.NoContent(http.StatusNoContent)
} }
func (h Handler) updateQuantity(c echo.Context) error { func (h Handler) UpdateQuantity(c echo.Context) error {
claims := claim.GetClaimsFromEchoContext(c) claims := claim.GetClaimsFromEchoContext(c)
p := c.Param("productID") p := c.Param("productID")

View File

@ -3,14 +3,15 @@ package http
import ( import (
"context" "context"
"git.gocasts.ir/ebhomengo/niki/pkg/httpserver" "git.gocasts.ir/ebhomengo/niki/pkg/httpserver"
"git.gocasts.ir/ebhomengo/niki/shoppingbasketapp/delivery/http/cart"
) )
type Server struct { type Server struct {
handler Handler handler cart.Handler
HTTPServer *httpserver.Server HTTPServer *httpserver.Server
} }
func NewServer(handler Handler, hS *httpserver.Server) Server { func NewServer(handler cart.Handler, hS *httpserver.Server) Server {
return Server{handler: handler, HTTPServer: hS} return Server{handler: handler, HTTPServer: hS}
} }
@ -34,10 +35,10 @@ func (s Server) registerRoutes() {
r := router.Group("shoppingbasket/cart") // Authentication is required r := router.Group("shoppingbasket/cart") // Authentication is required
r.GET("/", s.handler.getCart) r.GET("/", s.handler.GetCart)
r.DELETE("/", s.handler.removeCart) r.DELETE("/", s.handler.RemoveCart)
r.POST("/items", s.handler.addToBasket) r.POST("/items", s.handler.AddToBasket)
r.DELETE("/items/:productID", s.handler.removeItem) r.DELETE("/items/:productID", s.handler.RemoveItem)
r.PUT("/items/:productID/:quantity", s.handler.updateQuantity) r.PUT("/items/:productID/:quantity", s.handler.UpdateQuantity)
} }