From d4501917930ef2263551bee3ee529de49b6d6fc5 Mon Sep 17 00:00:00 2001 From: Sebas Date: Tue, 20 Feb 2024 19:28:21 -0300 Subject: [PATCH] added product --- README.md | 76 ++++++++++++------ db_diagram.png => image/db_diagram.png | Bin .../go-vertical-slice-architecture.png | Bin golang.png => image/golang.png | Bin image/internal_domain.jpg | Bin 0 -> 8436 bytes .../vertical-slice-architecture.png | Bin internal/product/handler/createProduct.go | 64 +++++++++++++++ internal/product/handler/handler.go | 11 +++ .../infrastructure/productRepository.go | 57 +++++++++++++ .../product/mock/mockProductRepository.go | 24 ++++++ internal/product/port.go | 7 ++ internal/product/product.go | 58 +++++++++++++ internal/product/service/createProduct.go | 56 +++++++++++++ internal/product/service/service.go | 42 ++++++++++ internal/user/user.go | 5 -- 15 files changed, 371 insertions(+), 29 deletions(-) rename db_diagram.png => image/db_diagram.png (100%) rename go-vertical-slice-architecture.png => image/go-vertical-slice-architecture.png (100%) rename golang.png => image/golang.png (100%) create mode 100644 image/internal_domain.jpg rename vertical-slice-architecture.png => image/vertical-slice-architecture.png (100%) create mode 100644 internal/product/handler/createProduct.go create mode 100644 internal/product/handler/handler.go create mode 100644 internal/product/infrastructure/productRepository.go create mode 100644 internal/product/mock/mockProductRepository.go create mode 100644 internal/product/port.go create mode 100644 internal/product/product.go create mode 100644 internal/product/service/createProduct.go create mode 100644 internal/product/service/service.go diff --git a/README.md b/README.md index 7a1dba6..e385760 100644 --- a/README.md +++ b/README.md @@ -18,24 +18,29 @@ This structure, created following the development guide's for vertical slice arc Vertical slice architecture is an approach to software development where code and functionality are organized around individual features or user stories, encompassing all layers of the application from user interface to data access, promoting autonomy, reduced dependencies, and iterative development. -![alt text](./vertical-slice-architecture.png) +![alt text](./image/vertical-slice-architecture.png) ## 📚 Code Structure -![alt text](./go-vertical-slice-architecture.png) +![alt text](./image/go-vertical-slice-architecture.png) - cmd - contains the main.go file that is our starting point to execute - migrations - contains all the database configuration for the api (if needed) - internal - contains all the api logic +A brief description of the layout: + +- `.github` has two template files for creating PR and issue. Please see the files for more details. +- `.gitignore` varies per project, but all projects need to ignore `bin` directory. +- `.golangci.yml` is the golangci-lint config file. +- `Makefile` is used to build the project. **You need to tweak the variables based on your project**. +- `CHANGELOG.md` contains auto-generated changelog information. +- `OWNERS` contains owners of the project. +- `README.md` is a detailed description of the project. +- `cmd` contains the main.go file that is our starting point to execute +- `pkg` places most of project business logic. +- `migrations` contains all vendored code. +- `internal` contains all the api logic. ## 🚀 Stack - - ### Programming language @@ -69,55 +74,78 @@ Vertical slice architecture is an approach to software development where code an ### Database diagram for the project -![alt text](./db_diagram.png) +![alt text](./image/db_diagram.png) + +### Internal folder structure for a new domain + +![alt text](./image/internal_domain.jpg) + +### 1 - Create product.go (domain) ## ⚙️ Usage ### Docker usage - Build server +```bash + # Build server docker-compose -p go-vertical-slice-architecture build - Start server + # Start server docker-compose up -d - Stop server + # Stop server docker-compose down +``` ### Standalone usage - air +```bash + # Live reload + air +``` ### Testing - To run unit testing +```bash + # To run unit testing go test - To run unit testing coverage + # To run unit testing coverage go test -cover ./... +``` ### Formatting, Linting and Vetting - To run formating +```bash + # Run formating go fmt ./... - To remove unused imports + # Remove unused imports goimports -l -w . - To run linting + # Run linting golangci-lint run ./... - To run vetting + # Run vetting go vet ./... + # Run shadow to check shadowed variables + # Install shadow + go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest + # Run shadow + shadow ./... +``` + ### Database migration script - To create the script +```bash + # Create the script migrate create -ext sql -dir /migrations -seq [script_name] - To run the script + # Run the script migrate -database ${POSTGRESQL_URL} -path /migrations up - * It will run automatically when the database initializes + # It will run automatically when the database initializes +``` ## 💻 Environment variables diff --git a/db_diagram.png b/image/db_diagram.png similarity index 100% rename from db_diagram.png rename to image/db_diagram.png diff --git a/go-vertical-slice-architecture.png b/image/go-vertical-slice-architecture.png similarity index 100% rename from go-vertical-slice-architecture.png rename to image/go-vertical-slice-architecture.png diff --git a/golang.png b/image/golang.png similarity index 100% rename from golang.png rename to image/golang.png diff --git a/image/internal_domain.jpg b/image/internal_domain.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7b37cea336616af1e83b973c8ebd937a9be2205e GIT binary patch literal 8436 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 NU03e+JtExHe*oXZy)Xa( literal 0 HcmV?d00001 diff --git a/vertical-slice-architecture.png b/image/vertical-slice-architecture.png similarity index 100% rename from vertical-slice-architecture.png rename to image/vertical-slice-architecture.png diff --git a/internal/product/handler/createProduct.go b/internal/product/handler/createProduct.go new file mode 100644 index 0000000..aa1192e --- /dev/null +++ b/internal/product/handler/createProduct.go @@ -0,0 +1,64 @@ +package handler + +import ( + "time" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/log" + "github.com/sebajax/go-vertical-slice-architecture/internal/user" + "github.com/sebajax/go-vertical-slice-architecture/internal/user/service" + "github.com/sebajax/go-vertical-slice-architecture/pkg/apperror" + "github.com/sebajax/go-vertical-slice-architecture/pkg/message" + "github.com/sebajax/go-vertical-slice-architecture/pkg/validate" +) + +// Body request schema for CreateUser +type UserSchema struct { + IdentityNumber string `json:"identity_number" validate:"required,min=6"` + FirstName string `json:"first_name" validate:"required,min=2"` + LastName string `json:"last_name" validate:"required,min=2"` + Email string `json:"email" validate:"required,email"` + DateOfBirth time.Time `json:"date_of_birth" validate:"required"` +} + +// Creates a new user into the database +func CreateUser(s service.CreateUserService) fiber.Handler { + return func(c *fiber.Ctx) error { + // Get body request + var body UserSchema + // Validate the body + err := c.BodyParser(&body) + if err != nil { + // Map the error and response via the middleware + log.Error(err) + return err + } + + // Validate schema + serr, err := validate.Validate(body) + if err != nil { + log.Error(serr) + return apperror.BadRequest(serr) + } + + // No schema errores then map body to domain + user := &user.User{ + IdentityNumber: body.IdentityNumber, + FirstName: body.FirstName, + LastName: body.LastName, + Email: body.Email, + DateOfBirth: body.DateOfBirth, + } + + // Execute the service + result, err := s.CreateUser(user) + if err != nil { + // if service response an error return via the middleware + log.Error(err) + return err + } + + // Success execution + return c.Status(fiber.StatusCreated).JSON(message.SuccessResponse(&result)) + } +} diff --git a/internal/product/handler/handler.go b/internal/product/handler/handler.go new file mode 100644 index 0000000..b6b7240 --- /dev/null +++ b/internal/product/handler/handler.go @@ -0,0 +1,11 @@ +package handler + +import ( + "github.com/gofiber/fiber/v2" + "github.com/sebajax/go-vertical-slice-architecture/internal/user/service" +) + +// UserRouter is the Router for GoFiber App +func UserRouter(app fiber.Router, s *service.UserService) { + app.Post("/", CreateUser(s.CreateUserServiceProvider)) +} diff --git a/internal/product/infrastructure/productRepository.go b/internal/product/infrastructure/productRepository.go new file mode 100644 index 0000000..b5d2b21 --- /dev/null +++ b/internal/product/infrastructure/productRepository.go @@ -0,0 +1,57 @@ +package infrastructure + +import ( + "database/sql" + "fmt" + + "github.com/sebajax/go-vertical-slice-architecture/internal/user" + "github.com/sebajax/go-vertical-slice-architecture/pkg/database" +) + +// User repository for querying the database +type userRepository struct { + db *database.DbConn +} + +// Create a user instance repository +func NewUserRepository(dbcon *database.DbConn) user.UserRepository { + return &userRepository{db: dbcon} +} + +// Stores a new user in the database +func (repo *userRepository) Save(u *user.User) (int64, error) { + // Get the id inserted in the database + var id int64 + + query := `INSERT INTO client (identity_number, first_name, last_name, email, date_of_birth) + VALUES ($1, $2, $3, $4, $5) RETURNING id` + err := repo.db.DbPool.QueryRow(query, u.IdentityNumber, u.FirstName, u.LastName, u.Email, u.DateOfBirth).Scan(&id) + if err != nil { + return 0, err + } + + fmt.Println("id: ", id) + + // No errors return the user id inserted + return id, nil +} + +// Gets the user by the email +func (repo *userRepository) GetByEmail(email string) (*user.User, bool, error) { + u := user.User{} + query := `SELECT id, identity_number, first_name, last_name, email, date_of_birth, created_at + FROM client + WHERE email = $1` + err := repo.db.DbPool.QueryRow(query, email).Scan(&u.Id, &u.IdentityNumber, &u.FirstName, &u.LastName, &u.Email, &u.DateOfBirth, &u.CreatedAt) + if err != nil { + // Not found, but not an error + if err == sql.ErrNoRows { + return nil, false, nil + } + // An actual error occurred + return nil, false, err + } + + // Found the item + return &u, true, nil +} diff --git a/internal/product/mock/mockProductRepository.go b/internal/product/mock/mockProductRepository.go new file mode 100644 index 0000000..0badf65 --- /dev/null +++ b/internal/product/mock/mockProductRepository.go @@ -0,0 +1,24 @@ +package mocks + +import "github.com/sebajax/go-vertical-slice-architecture/internal/user" + +type mockUserRepository struct{} + +func NewMockUserRepository() user.UserRepository { + return &mockUserRepository{} +} + +func (mock *mockUserRepository) Save(u *user.User) (int64, error) { + return 1, nil +} + +func (mock *mockUserRepository) GetByEmail(email string) (*user.User, bool, error) { + /*return &user.User{ + Id: 1, + Email: "juan@example.com", + Name: "Juan", + DateOfBirth: time.Now(), + CreatedAt: time.Now(), + }, true, nil*/ + return nil, true, nil +} diff --git a/internal/product/port.go b/internal/product/port.go new file mode 100644 index 0000000..08bc292 --- /dev/null +++ b/internal/product/port.go @@ -0,0 +1,7 @@ +package user + +// User port interface definition for depedency injection +type UserRepository interface { + Save(u *User) (int64, error) + GetByEmail(email string) (*User, bool, error) +} diff --git a/internal/product/product.go b/internal/product/product.go new file mode 100644 index 0000000..5cbe69e --- /dev/null +++ b/internal/product/product.go @@ -0,0 +1,58 @@ +package product + +import "time" + +// ProductCategory represents the categories of electronic products +type ProductCategory int + +// Enumeration of product categories +const ( + Laptop ProductCategory = iota + Smartphone + Tablet + SmartWatch + Headphones + Camera + Television + Other +) + +// String representation of the ProductCategory +func (p ProductCategory) String() string { + return [...]string{ + "Laptop", + "Smartphone", + "Tablet", + "SmartWatch", + "Headphones", + "Camera", + "Television", + "Other", + } +} + +// Const for error messages +const ( + ErrorSkuExists string = "ERROR_SKU_EXISTS" + ErrorWrongCategory string = "ERROR_WRONG_CATEGORY" +) + +// Product Domain +type User struct { + Id int + Name string + Sku string + Category ProductCategory + Price string + CreatedAt time.Time +} + +// Create a new product instance +func New(n string, s string, c string, p string) (*Product, error) { + return &Product{ + Name: n, + Sku: s, + Category: c, + Price: p, + }, nil +} diff --git a/internal/product/service/createProduct.go b/internal/product/service/createProduct.go new file mode 100644 index 0000000..9751ff0 --- /dev/null +++ b/internal/product/service/createProduct.go @@ -0,0 +1,56 @@ +package service + +import ( + "log" + + "github.com/sebajax/go-vertical-slice-architecture/internal/user" + "github.com/sebajax/go-vertical-slice-architecture/pkg/apperror" +) + +// CreateUserService interface for DI +type CreateUserService interface { + CreateUser(user *user.User) (int64, error) +} + +// User use cases (port injection) +type createUserService struct { + userRepository user.UserRepository +} + +// Create a new user service use case instance +func NewCreateUserService(repository user.UserRepository) CreateUserService { + // return the pointer to user service + return &createUserService{ + userRepository: repository, + } +} + +// Create a new user and store the user in the database +func (service *createUserService) CreateUser(u *user.User) (int64, error) { + _, check, err := service.userRepository.GetByEmail(u.Email) + // check if user does not exist and no database error ocurred + if err != nil { + // database error + log.Fatalln(err) + err := apperror.InternalServerError() + return 0, err + } + if check { + // user found + log.Println(u, user.ErrorEmailExists) + err := apperror.BadRequest(user.ErrorEmailExists) + return 0, err + } + + // create the new user and return the id + userId, err := service.userRepository.Save(u) + if err != nil { + // database error + log.Fatalln(err) + err := apperror.InternalServerError() + return 0, err + } + + // user created successfuly + return userId, nil +} diff --git a/internal/product/service/service.go b/internal/product/service/service.go new file mode 100644 index 0000000..921361e --- /dev/null +++ b/internal/product/service/service.go @@ -0,0 +1,42 @@ +package service + +import ( + "github.com/sebajax/go-vertical-slice-architecture/internal/user/infrastructure" + "go.uber.org/dig" +) + +// user service instance +type UserService struct { + CreateUserServiceProvider CreateUserService +} + +func NewUserService() *UserService { + return &UserService{} +} + +// provide components for injection +func ProvideUserComponents(c *dig.Container) { + // repositorory provider injection + err := c.Provide(infrastructure.NewUserRepository) + if err != nil { + panic(err) + } + + //service provider injection + err = c.Provide(NewCreateUserService) + if err != nil { + panic(err) + } +} + +// init service container +func (us *UserService) InitUserComponents(c *dig.Container) error { + // create user service + err := c.Invoke( + func(s CreateUserService) { + us.CreateUserServiceProvider = s + }, + ) + + return err +} diff --git a/internal/user/user.go b/internal/user/user.go index 1fc73fe..eabc83a 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -7,11 +7,6 @@ const ( ErrorEmailExists string = "ERROR_EMAIL_EXISTS" ) -// Domain types -// type name string -// type email string -// type dateOfBirth time.Time - // User Domain type User struct { Id int