Generete Module Handler
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"api-service/internal/models"
|
||||
"api-service/internal/services"
|
||||
models "api-service/internal/models/auth"
|
||||
services "api-service/internal/services/auth"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -1,8 +1,8 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"api-service/internal/models"
|
||||
"api-service/internal/services"
|
||||
models "api-service/internal/models/auth"
|
||||
services "api-service/internal/services/auth"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
121
internal/handlers/employee/employee.go
Normal file
121
internal/handlers/employee/employee.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"api-service/internal/models/employee"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// EmployeeHandler handles employee services
|
||||
type EmployeeHandler struct{}
|
||||
|
||||
// NewEmployeeHandler creates a new EmployeeHandler
|
||||
func NewEmployeeHandler() *EmployeeHandler {
|
||||
return &%!s(MISSING)Handler{}
|
||||
}
|
||||
// GetEmployee godoc
|
||||
// @Summary Get employee
|
||||
// @Description Returns a list of employees
|
||||
// @Tags employee
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} employee.EmployeeGetResponse "Employee GET response"
|
||||
// @Router /api/v1/employees [get]
|
||||
func (h *EmployeeHandler) GetEmployee(c *gin.Context) {
|
||||
response := employee.EmployeeGetResponse{
|
||||
Message: "List of Employee",
|
||||
Data: []string{"Employee 1", "Employee 2"},
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// GetemployeeByID godoc
|
||||
// @Summary Get employee by ID
|
||||
// @Description Returns a single employee by ID
|
||||
// @Tags Employee
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "employee ID"
|
||||
// @Success 200 {object} Employee.EmployeeGetByIDResponse "employee GET by ID response"
|
||||
// @Failure 404 {object} Employee.ErrorResponse "Employee not found"
|
||||
// @Router /api/v1/employee/{id} [get]
|
||||
func (h *EmployeeHandler) GetemployeeByID(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
response := Employee.%!s(MISSING)GetByIDResponse{
|
||||
ID: id,
|
||||
Message: "%!s(MISSING) details",
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
// CreateEmployee godoc
|
||||
// @Summary Create employee
|
||||
// @Description Creates a new employee
|
||||
// @Tags employee
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body employee.EmployeeCreateRequest true "Employee creation request"
|
||||
// @Success 201 {object} employee.EmployeeCreateResponse "Employee created successfully"
|
||||
// @Failure 400 {object} employee.ErrorResponse "Bad request"
|
||||
// @Router /api/v1/Employee [post]
|
||||
func (h *EmployeeHandler) Createemployee(c *gin.Context) {
|
||||
var req Employee.EmployeeCreateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
response := %!s(MISSING).%!s(MISSING)CreateResponse{
|
||||
ID: uuid.NewString(),
|
||||
Message: "%!s(MISSING) created successfully",
|
||||
Data: req,
|
||||
}
|
||||
c.JSON(http.StatusCreated, response)
|
||||
}
|
||||
// UpdateEmployee godoc
|
||||
// @Summary Update employee
|
||||
// @Description Updates an existing employee
|
||||
// @Tags employee
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "Employee ID"
|
||||
// @Param request body employee.EmployeeUpdateRequest true "Employee update request"
|
||||
// @Success 200 {object} Employee.employeeUpdateResponse "Employee updated successfully"
|
||||
// @Failure 400 {object} employee.ErrorResponse "Bad request"
|
||||
// @Failure 404 {object} Employee.ErrorResponse "employee not found"
|
||||
// @Router /api/v1/Employee/{id} [put]
|
||||
func (h *EmployeeHandler) UpdateEmployee(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
var req Employee.%!s(MISSING)UpdateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
response := %!s(MISSING).%!s(MISSING)UpdateResponse{
|
||||
ID: id,
|
||||
Message: "%!s(MISSING) updated successfully",
|
||||
Data: req,
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
// DeleteEmployee godoc
|
||||
// @Summary Delete employee
|
||||
// @Description Deletes a employee by ID
|
||||
// @Tags employee
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "Employee ID"
|
||||
// @Success 200 {object} employee.EmployeeDeleteResponse "Employee deleted successfully"
|
||||
// @Failure 404 {object} employee.ErrorResponse "Employee not found"
|
||||
// @Router /api/v1/Employee/{id} [delete]
|
||||
func (h *employeeHandler) DeleteEmployee(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
response := Employee.%!s(MISSING)DeleteResponse{
|
||||
ID: id,
|
||||
Message: "%!s(MISSING) deleted successfully",
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"api-service/internal/services"
|
||||
services "api-service/internal/services/auth"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
|
||||
46
internal/models/employee/employee.go
Normal file
46
internal/models/employee/employee.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package employee
|
||||
|
||||
// EmployeeGetResponse represents the response for GET employees
|
||||
type EmployeeGetResponse struct {
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// EmployeeGetByIDResponse represents the response for GET employee by ID
|
||||
type EmployeeGetByIDResponse struct {
|
||||
ID string `json:"id"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
%!(EXTRA string=employee, string=Employee)// EmployeeCreateRequest represents the request for creating employee
|
||||
type EmployeeCreateRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
// Add more fields as needed
|
||||
}
|
||||
|
||||
// employeeCreateResponse represents the response for creating Employee
|
||||
type employeeCreateResponse struct {
|
||||
ID string `json:"id"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
%!(EXTRA string=Employee)// EmployeeUpdateRequest represents the request for updating employee
|
||||
type EmployeeUpdateRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
// Add more fields as needed
|
||||
}
|
||||
|
||||
// employeeUpdateResponse represents the response for updating Employee
|
||||
type employeeUpdateResponse struct {
|
||||
ID string `json:"id"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
%!(EXTRA string=Employee)// EmployeeDeleteResponse represents the response for deleting employee
|
||||
type EmployeeDeleteResponse struct {
|
||||
ID string `json:"id"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
%!(EXTRA string=employee)// ErrorResponse represents an error response
|
||||
type ErrorResponse struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
42
internal/models/product/product.go
Normal file
42
internal/models/product/product.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// Product represents the product domain model
|
||||
type Product struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Price float64 `json:"price"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// ProductCreateRequest represents the request for creating a product
|
||||
type ProductCreateRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
Price float64 `json:"price" binding:"required,gt=0"`
|
||||
}
|
||||
|
||||
// ProductUpdateRequest represents the request for updating a product
|
||||
type ProductUpdateRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
Price float64 `json:"price" binding:"required,gt=0"`
|
||||
}
|
||||
|
||||
// ProductResponse represents the response for product operations
|
||||
type ProductResponse struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Price float64 `json:"price"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// ProductsResponse represents the response for listing products
|
||||
type ProductsResponse struct {
|
||||
Data []*Product `json:"data"`
|
||||
}
|
||||
131
internal/repository/product/product_repository.go
Normal file
131
internal/repository/product/product_repository.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package product
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
model "api-service/internal/models/product"
|
||||
)
|
||||
|
||||
// Repository defines the interface for product data operations
|
||||
type Repository interface {
|
||||
Create(ctx context.Context, product *model.Product) error
|
||||
GetByID(ctx context.Context, id string) (*model.Product, error)
|
||||
GetAll(ctx context.Context) ([]*model.Product, error)
|
||||
Update(ctx context.Context, product *model.Product) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
// repository implements the Repository interface
|
||||
type repository struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
// NewRepository creates a new product repository
|
||||
func NewRepository(db *sql.DB) Repository {
|
||||
return &repository{db: db}
|
||||
}
|
||||
|
||||
// Create adds a new product to the database
|
||||
func (r *repository) Create(ctx context.Context, product *model.Product) error {
|
||||
query := `
|
||||
INSERT INTO products (id, name, description, price, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
`
|
||||
|
||||
_, err := r.db.ExecContext(ctx, query,
|
||||
product.ID,
|
||||
product.Name,
|
||||
product.Description,
|
||||
product.Price,
|
||||
product.CreatedAt,
|
||||
product.UpdatedAt,
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetByID retrieves a product by its ID
|
||||
func (r *repository) GetByID(ctx context.Context, id string) (*model.Product, error) {
|
||||
query := `
|
||||
SELECT id, name, description, price, created_at, updated_at
|
||||
FROM products
|
||||
WHERE id = ?
|
||||
`
|
||||
|
||||
var product model.Product
|
||||
err := r.db.QueryRowContext(ctx, query, id).Scan(
|
||||
&product.ID,
|
||||
&product.Name,
|
||||
&product.Description,
|
||||
&product.Price,
|
||||
&product.CreatedAt,
|
||||
&product.UpdatedAt,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &product, nil
|
||||
}
|
||||
|
||||
// GetAll retrieves all products
|
||||
func (r *repository) GetAll(ctx context.Context) ([]*model.Product, error) {
|
||||
query := `
|
||||
SELECT id, name, description, price, created_at, updated_at
|
||||
FROM products
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
rows, err := r.db.QueryContext(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var products []*model.Product
|
||||
for rows.Next() {
|
||||
var product model.Product
|
||||
err := rows.Scan(
|
||||
&product.ID,
|
||||
&product.Name,
|
||||
&product.Description,
|
||||
&product.Price,
|
||||
&product.CreatedAt,
|
||||
&product.UpdatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
products = append(products, &product)
|
||||
}
|
||||
|
||||
return products, nil
|
||||
}
|
||||
|
||||
// Update updates an existing product
|
||||
func (r *repository) Update(ctx context.Context, product *model.Product) error {
|
||||
query := `
|
||||
UPDATE products
|
||||
SET name = ?, description = ?, price = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`
|
||||
|
||||
_, err := r.db.ExecContext(ctx, query,
|
||||
product.Name,
|
||||
product.Description,
|
||||
product.Price,
|
||||
product.UpdatedAt,
|
||||
product.ID,
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete removes a product from the database
|
||||
func (r *repository) Delete(ctx context.Context, id string) error {
|
||||
query := `DELETE FROM products WHERE id = ?`
|
||||
_, err := r.db.ExecContext(ctx, query, id)
|
||||
return err
|
||||
}
|
||||
@@ -4,9 +4,11 @@ import (
|
||||
"net/http"
|
||||
|
||||
"api-service/internal/config"
|
||||
"api-service/internal/handlers"
|
||||
authHandlers "api-service/internal/handlers/auth"
|
||||
componentHandlers "api-service/internal/handlers/component"
|
||||
employeeHandlers "api-service/internal/handlers/employee"
|
||||
"api-service/internal/middleware"
|
||||
"api-service/internal/services"
|
||||
services "api-service/internal/services/auth"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
@@ -34,13 +36,13 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
|
||||
{
|
||||
// Public routes (no authentication required)
|
||||
// Health endpoints
|
||||
healthHandler := handlers.NewHealthHandler()
|
||||
healthHandler := componentHandlers.NewHealthHandler()
|
||||
v1.GET("/health", healthHandler.GetHealth)
|
||||
v1.GET("/", healthHandler.HelloWorld)
|
||||
|
||||
// Authentication routes
|
||||
authHandler := handlers.NewAuthHandler(authService)
|
||||
tokenHandler := handlers.NewTokenHandler(authService)
|
||||
authHandler := authHandlers.NewAuthHandler(authService)
|
||||
tokenHandler := authHandlers.NewTokenHandler(authService)
|
||||
|
||||
v1.POST("/auth/login", authHandler.Login)
|
||||
v1.POST("/auth/register", authHandler.Register)
|
||||
@@ -52,11 +54,20 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
|
||||
v1.POST("/token/generate-direct", tokenHandler.GenerateTokenDirect)
|
||||
|
||||
// Protected routes (require authentication)
|
||||
|
||||
// Employee endpoints
|
||||
employeeHandler := employeeHandlers.NewEmployeeHandler()
|
||||
v1.GET("/employees", employeeHandler.GetEmployee)
|
||||
v1.GET("/employees/:id", employeeHandler.GetEmployeeByID)
|
||||
v1.POST("/employees", employeeHandler.CreateEmployee)
|
||||
v1.PUT("/employees/:id", employeeHandler.UpdateEmployee)
|
||||
v1.DELETE("/employees/:id", employeeHandler.DeleteEmployee)
|
||||
|
||||
protected := v1.Group("/")
|
||||
protected.Use(middleware.JWTAuthMiddleware(authService))
|
||||
{
|
||||
// Product endpoints
|
||||
productHandler := handlers.NewProductHandler()
|
||||
productHandler := componentHandlers.NewProductHandler()
|
||||
protected.GET("/products", productHandler.GetProduct)
|
||||
protected.GET("/products/:id", productHandler.GetProductByID)
|
||||
protected.POST("/products", productHandler.CreateProduct)
|
||||
@@ -64,7 +75,7 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine {
|
||||
protected.DELETE("/products/:id", productHandler.DeleteProduct)
|
||||
|
||||
// Example endpoints
|
||||
exampleHandler := handlers.NewExampleHandler()
|
||||
exampleHandler := componentHandlers.NewExampleHandler()
|
||||
protected.GET("/example", exampleHandler.GetExample)
|
||||
protected.POST("/example", exampleHandler.PostExample)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package services
|
||||
|
||||
import (
|
||||
"api-service/internal/config"
|
||||
"api-service/internal/models"
|
||||
models "api-service/internal/models/auth"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
141
internal/services/product/product_service.go
Normal file
141
internal/services/product/product_service.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package product
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
model "api-service/internal/models/product"
|
||||
"api-service/internal/repository/product"
|
||||
)
|
||||
|
||||
// Service defines the interface for product business logic
|
||||
type Service interface {
|
||||
CreateProduct(ctx context.Context, req *model.ProductCreateRequest) (*model.ProductResponse, error)
|
||||
GetProduct(ctx context.Context, id string) (*model.ProductResponse, error)
|
||||
GetAllProducts(ctx context.Context) (*model.ProductsResponse, error)
|
||||
UpdateProduct(ctx context.Context, id string, req *model.ProductUpdateRequest) (*model.ProductResponse, error)
|
||||
DeleteProduct(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
// service implements the Service interface
|
||||
type service struct {
|
||||
repo product.Repository
|
||||
}
|
||||
|
||||
// NewService creates a new product service
|
||||
func NewService(repo product.Repository) Service {
|
||||
return &service{repo: repo}
|
||||
}
|
||||
|
||||
// CreateProduct creates a new product
|
||||
func (s *service) CreateProduct(ctx context.Context, req *model.ProductCreateRequest) (*model.ProductResponse, error) {
|
||||
if req.Name == "" {
|
||||
return nil, errors.New("product name is required")
|
||||
}
|
||||
|
||||
if req.Price <= 0 {
|
||||
return nil, errors.New("product price must be greater than 0")
|
||||
}
|
||||
|
||||
product := &model.Product{
|
||||
ID: generateID(),
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Price: req.Price,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
err := s.repo.Create(ctx, product)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.ProductResponse{
|
||||
ID: product.ID,
|
||||
Name: product.Name,
|
||||
Description: product.Description,
|
||||
Price: product.Price,
|
||||
CreatedAt: product.CreatedAt,
|
||||
UpdatedAt: product.UpdatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetProduct retrieves a product by ID
|
||||
func (s *service) GetProduct(ctx context.Context, id string) (*model.ProductResponse, error) {
|
||||
if id == "" {
|
||||
return nil, errors.New("product ID is required")
|
||||
}
|
||||
|
||||
product, err := s.repo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.ProductResponse{
|
||||
ID: product.ID,
|
||||
Name: product.Name,
|
||||
Description: product.Description,
|
||||
Price: product.Price,
|
||||
CreatedAt: product.CreatedAt,
|
||||
UpdatedAt: product.UpdatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAllProducts retrieves all products
|
||||
func (s *service) GetAllProducts(ctx context.Context) (*model.ProductsResponse, error) {
|
||||
products, err := s.repo.GetAll(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.ProductsResponse{
|
||||
Data: products,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateProduct updates an existing product
|
||||
func (s *service) UpdateProduct(ctx context.Context, id string, req *model.ProductUpdateRequest) (*model.ProductResponse, error) {
|
||||
if id == "" {
|
||||
return nil, errors.New("product ID is required")
|
||||
}
|
||||
|
||||
existingProduct, err := s.repo.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existingProduct.Name = req.Name
|
||||
existingProduct.Description = req.Description
|
||||
existingProduct.Price = req.Price
|
||||
existingProduct.UpdatedAt = time.Now()
|
||||
|
||||
err = s.repo.Update(ctx, existingProduct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.ProductResponse{
|
||||
ID: existingProduct.ID,
|
||||
Name: existingProduct.Name,
|
||||
Description: existingProduct.Description,
|
||||
Price: existingProduct.Price,
|
||||
CreatedAt: existingProduct.CreatedAt,
|
||||
UpdatedAt: existingProduct.UpdatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteProduct deletes a product
|
||||
func (s *service) DeleteProduct(ctx context.Context, id string) error {
|
||||
if id == "" {
|
||||
return errors.New("product ID is required")
|
||||
}
|
||||
|
||||
return s.repo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
func generateID() string {
|
||||
return "prod_" + time.Now().Format("20060102150405")
|
||||
}
|
||||
Reference in New Issue
Block a user