Skip to content

Commit

Permalink
Merge pull request #62 from quangdangfit/cart
Browse files Browse the repository at this point in the history
Cart
  • Loading branch information
quangdangfit authored Sep 12, 2023
2 parents bc5fa2c + c9b9875 commit 2ac23fd
Show file tree
Hide file tree
Showing 47 changed files with 2,644 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
ci:
runs-on: ubuntu-latest
env:
environment: testing
environment: production
database_uri: postgres://postgres:test@localhost:5432/postgres
redis_uri: localhost:6379

Expand Down
21 changes: 3 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ $ go test

### Test with Coverage
```shell script
go test -timeout 9000s -a -v -coverprofile=coverage.out -coverpkg=./... ./...
2023-09-12T15:18:36.684+0700 INFO http/server.go:58 HTTP server is listening on PORT: 8888
2023-09-12T15:18:36.684+0700 INFO grpc/server.go:53 GRPC server is listening on PORT: 8889
```

**or**
Expand All @@ -54,24 +55,8 @@ make unittest
Project information and existing API

```
[GIN-debug] POST /api/v1/auth/register --> goshop/internal/user/port/http.(*UserHandler).Register-fm (3 handlers)
[GIN-debug] POST /api/v1/auth/login --> goshop/internal/user/port/http.(*UserHandler).Login-fm (3 handlers)
[GIN-debug] POST /api/v1/auth/refresh --> goshop/internal/user/port/http.(*UserHandler).RefreshToken-fm (4 handlers)
[GIN-debug] GET /api/v1/auth/me --> goshop/internal/user/port/http.(*UserHandler).GetMe-fm (4 handlers)
[GIN-debug] PUT /api/v1/auth/change-password --> goshop/internal/user/port/http.(*UserHandler).ChangePassword-fm (4 handlers)
[GIN-debug] GET /api/v1/products --> goshop/internal/product/port/http.(*ProductHandler).ListProducts-fm (3 handlers)
[GIN-debug] POST /api/v1/products --> goshop/internal/product/port/http.(*ProductHandler).CreateProduct-fm (4 handlers)
[GIN-debug] PUT /api/v1/products/:id --> goshop/internal/product/port/http.(*ProductHandler).UpdateProduct-fm (4 handlers)
[GIN-debug] GET /api/v1/products/:id --> goshop/internal/product/port/http.(*ProductHandler).GetProductByID-fm (3 handlers)
[GIN-debug] POST /api/v1/orders --> goshop/internal/order/port/http.(*OrderHandler).PlaceOrder-fm (4 handlers)
[GIN-debug] GET /api/v1/orders/:id --> goshop/internal/order/port/http.(*OrderHandler).GetOrderByID-fm (4 handlers)
[GIN-debug] GET /api/v1/orders --> goshop/internal/order/port/http.(*OrderHandler).GetOrders-fm (4 handlers)
[GIN-debug] PUT /api/v1/orders/:id/cancel --> goshop/internal/order/port/http.(*OrderHandler).CancelOrder-fm (4 handlers)
[GIN-debug] GET /swagger/*any --> github.com/swaggo/gin-swagger.CustomWrapHandler.func1 (3 handlers)
[GIN-debug] GET /health --> goshop/internal/server/http.Server.Run.func1 (3 handlers)
2023-08-20T13:50:57.175+0700 INFO http/server.go:53 Server is listening on PORT: 8888
2023-09-08T21:03:00.950+0700 INFO grpc/server.go:48 GRPC server is listening on PORT: 8889
[GIN-debug] Listening and serving HTTP on :8888
```

### Document
Expand Down
2 changes: 1 addition & 1 deletion cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
// @BasePath /api/v1

func main() {
cfg := config.GetConfig()
cfg := config.LoadConfig()
logger.Initialize(cfg.Environment)

db, err := dbs.NewDatabase(cfg.DatabaseURI)
Expand Down
1 change: 1 addition & 0 deletions codecov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ ignore:
- "pkg/"
- "vendor/"
- "proto/"
- "internal/server"
27 changes: 27 additions & 0 deletions internal/cart/dto/cart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dto

type Cart struct {
ID string `json:"id"`
User *User `json:"user"`
Lines []*CartLineReq `json:"lines"`
}

type CartLine struct {
Product *Product `json:"product"`
Quantity uint `json:"quantity" validate:"required"`
}

type CartLineReq struct {
ProductID string `json:"product_id" validate:"required"`
Quantity uint `json:"quantity" validate:"required"`
}

type AddProductReq struct {
UserID string `json:"user_id" validate:"required"`
Line *CartLineReq `json:"line" validate:"required,dive"`
}

type RemoveProductReq struct {
UserID string `json:"user_id" validate:"required"`
ProductID string `json:"product_id" validate:"required"`
}
9 changes: 9 additions & 0 deletions internal/cart/dto/product.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dto

type Product struct {
ID string `json:"id"`
Code string `json:"code"`
Name string `json:"name"`
Description string `json:"description"`
Price float64 `json:"price"`
}
6 changes: 6 additions & 0 deletions internal/cart/dto/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dto

type User struct {
ID string `json:"id"`
Email string `json:"email"`
}
29 changes: 29 additions & 0 deletions internal/cart/model/cart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package model

import (
"time"

"github.com/google/uuid"
"gorm.io/gorm"
)

type Cart struct {
ID string `json:"id" gorm:"unique;not null;index;primary_key"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at" gorm:"index"`
UserID string `json:"user_id" gorm:"unique;not null;index"`
User *User
Lines []*CartLine `json:"lines"`
}

type CartLine struct {
ProductID string `json:"product_id"`
Product *Product
Quantity uint `json:"quantity"`
}

func (cart *Cart) BeforeCreate(tx *gorm.DB) error {
cart.ID = uuid.New().String()
return nil
}
9 changes: 9 additions & 0 deletions internal/cart/model/product.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package model

type Product struct {
ID string `json:"id" gorm:"unique;not null;index;primary_key"`
Code string `json:"code" gorm:"uniqueIndex:idx_product_code,not null"`
Name string `json:"name" gorm:"uniqueIndex:idx_product_name,not null"`
Description string `json:"description"`
Price float64 `json:"price"`
}
6 changes: 6 additions & 0 deletions internal/cart/model/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package model

type User struct {
ID string `json:"id" gorm:"unique;not null;index;primary_key"`
Email string `json:"email" gorm:"unique;not null;index:idx_user_email"`
}
85 changes: 85 additions & 0 deletions internal/cart/port/grpc/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package grpc

import (
"context"
"errors"

"github.com/quangdangfit/gocommon/logger"

"goshop/internal/cart/dto"
"goshop/internal/cart/service"
"goshop/pkg/utils"
pb "goshop/proto/gen/go/cart"
)

type CartHandler struct {
pb.UnimplementedCartServiceServer

service service.ICartService
}

func NewCartHandler(service service.ICartService) *CartHandler {
return &CartHandler{
service: service,
}
}

func (h *CartHandler) AddProduct(ctx context.Context, req *pb.AddProductReq) (*pb.AddProductRes, error) {
userID, _ := ctx.Value("userId").(string)
if userID == "" {
return nil, errors.New("unauthorized")
}

cart, err := h.service.AddProduct(ctx, &dto.AddProductReq{
UserID: userID,
Line: &dto.CartLineReq{
ProductID: req.ProductId,
Quantity: uint(req.Quantity),
},
})
if err != nil {
logger.Error("Failed to add product ", err)
return nil, err
}

var res pb.AddProductRes
utils.Copy(&res.Cart, &cart)
return &res, nil
}

func (h *CartHandler) RemoveProduct(ctx context.Context, req *pb.RemoveProductReq) (*pb.RemoveProductRes, error) {
userID, _ := ctx.Value("userId").(string)
if userID == "" {
return nil, errors.New("unauthorized")
}

cart, err := h.service.RemoveProduct(ctx, &dto.RemoveProductReq{
UserID: userID,
ProductID: req.ProductId,
})
if err != nil {
logger.Error("Failed to remove product ", err)
return nil, err
}

var res pb.RemoveProductRes
utils.Copy(&res.Cart, &cart)
return &res, nil
}

func (h *CartHandler) GetCart(ctx context.Context, req *pb.GetCartReq) (*pb.GetCartRes, error) {
userID, _ := ctx.Value("userId").(string)
if userID == "" {
return nil, errors.New("unauthorized")
}

cart, err := h.service.GetCartByUserID(ctx, userID)
if err != nil {
logger.Error("Failed to get cart ", err)
return nil, err
}

var res pb.GetCartRes
utils.Copy(&res.Cart, &cart)
return &res, nil
}
Loading

0 comments on commit 2ac23fd

Please sign in to comment.