init project
This commit is contained in:
15
internal/controllers/controllers.go
Normal file
15
internal/controllers/controllers.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package controllers
|
||||
|
||||
// Controllers chứa tất cả các controller của ứng dụng
|
||||
type Controllers struct {
|
||||
UserController IUserController
|
||||
ProductController IProductController
|
||||
}
|
||||
|
||||
// NewControllers tạo một instance mới của Controllers
|
||||
func NewControllers(userController IUserController, productController IProductController) *Controllers {
|
||||
return &Controllers{
|
||||
UserController: userController,
|
||||
ProductController: productController,
|
||||
}
|
||||
}
|
22
internal/controllers/interfaces.go
Normal file
22
internal/controllers/interfaces.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package controllers
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
// IUserController định nghĩa interface cho UserController
|
||||
type IUserController interface {
|
||||
Register(c *gin.Context)
|
||||
Login(c *gin.Context)
|
||||
GetProfile(c *gin.Context)
|
||||
UpdateProfile(c *gin.Context)
|
||||
}
|
||||
|
||||
// IProductController định nghĩa interface cho ProductController
|
||||
type IProductController interface {
|
||||
CreateProduct(c *gin.Context)
|
||||
GetProduct(c *gin.Context)
|
||||
GetAllProducts(c *gin.Context)
|
||||
UpdateProduct(c *gin.Context)
|
||||
DeleteProduct(c *gin.Context)
|
||||
}
|
||||
|
||||
// Các interface khác có thể được thêm vào đây khi cần thiết
|
125
internal/controllers/product_controller.go
Normal file
125
internal/controllers/product_controller.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/dungnt11/senflow_app/internal/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ProductController triển khai IProductController
|
||||
type ProductController struct {
|
||||
productService services.IProductService
|
||||
}
|
||||
|
||||
// NewProductController tạo một instance mới của ProductController
|
||||
func NewProductController(productService services.IProductService) *ProductController {
|
||||
return &ProductController{
|
||||
productService: productService,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateProduct xử lý tạo sản phẩm mới
|
||||
func (pc *ProductController) CreateProduct(c *gin.Context) {
|
||||
// Gọi service để thực hiện logic tạo sản phẩm
|
||||
result, err := pc.productService.CreateProduct(c)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(201, result)
|
||||
}
|
||||
|
||||
// GetProduct xử lý lấy thông tin sản phẩm theo ID
|
||||
func (pc *ProductController) GetProduct(c *gin.Context) {
|
||||
// Lấy ID từ param
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": "ID không hợp lệ",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Gọi service để lấy thông tin sản phẩm
|
||||
result, err := pc.productService.GetProduct(uint(id))
|
||||
|
||||
if err != nil {
|
||||
c.JSON(404, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
// GetAllProducts xử lý lấy tất cả sản phẩm
|
||||
func (pc *ProductController) GetAllProducts(c *gin.Context) {
|
||||
// Gọi service để lấy tất cả sản phẩm
|
||||
result, err := pc.productService.GetAllProducts()
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
// UpdateProduct xử lý cập nhật thông tin sản phẩm
|
||||
func (pc *ProductController) UpdateProduct(c *gin.Context) {
|
||||
// Lấy ID từ param
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": "ID không hợp lệ",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Gọi service để cập nhật thông tin sản phẩm
|
||||
result, err := pc.productService.UpdateProduct(uint(id), c)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
// DeleteProduct xử lý xóa sản phẩm
|
||||
func (pc *ProductController) DeleteProduct(c *gin.Context) {
|
||||
// Lấy ID từ param
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": "ID không hợp lệ",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Gọi service để xóa sản phẩm
|
||||
result, err := pc.productService.DeleteProduct(uint(id))
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
93
internal/controllers/user_controller.go
Normal file
93
internal/controllers/user_controller.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/internal/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserController triển khai IUserController
|
||||
type UserController struct {
|
||||
userService services.IUserService
|
||||
}
|
||||
|
||||
// NewUserController tạo một instance mới của UserController
|
||||
func NewUserController(userService services.IUserService) *UserController {
|
||||
return &UserController{
|
||||
userService: userService,
|
||||
}
|
||||
}
|
||||
|
||||
// Register xử lý đăng ký người dùng
|
||||
func (uc *UserController) Register(c *gin.Context) {
|
||||
// Gọi service để thực hiện logic đăng ký
|
||||
result, err := uc.userService.Register(c)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
// Login xử lý đăng nhập
|
||||
func (uc *UserController) Login(c *gin.Context) {
|
||||
// Gọi service để thực hiện logic đăng nhập
|
||||
result, err := uc.userService.Login(c)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
// GetProfile xử lý lấy thông tin profile
|
||||
func (uc *UserController) GetProfile(c *gin.Context) {
|
||||
// Lấy user ID từ token hoặc param (giả định)
|
||||
userID := uint(1) // Trong thực tế, bạn sẽ lấy từ JWT token hoặc param
|
||||
|
||||
// Gọi service để lấy thông tin profile
|
||||
result, err := uc.userService.GetProfile(userID)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
// UpdateProfile xử lý cập nhật profile
|
||||
func (uc *UserController) UpdateProfile(c *gin.Context) {
|
||||
// Lấy user ID từ token hoặc param (giả định)
|
||||
userID := uint(1) // Trong thực tế, bạn sẽ lấy từ JWT token hoặc param
|
||||
|
||||
// Đọc dữ liệu từ request
|
||||
var data map[string]interface{}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Gọi service để cập nhật profile
|
||||
result, err := uc.userService.UpdateProfile(userID, data)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
119
internal/initialize/loadconfig.go
Normal file
119
internal/initialize/loadconfig.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/dungnt11/senflow_app/global"
|
||||
"github.com/fatih/color"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func LoadConfig() error {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Cấu hình server
|
||||
global.Config.Server.Port = os.Getenv("PORT")
|
||||
global.Config.Server.AppEnv = os.Getenv("APP_ENV")
|
||||
|
||||
// Cấu hình database
|
||||
global.Config.Database.Host = os.Getenv("BLUEPRINT_DB_HOST")
|
||||
global.Config.Database.Port = os.Getenv("BLUEPRINT_DB_PORT")
|
||||
global.Config.Database.Database = os.Getenv("BLUEPRINT_DB_DATABASE")
|
||||
global.Config.Database.Username = os.Getenv("BLUEPRINT_DB_USERNAME")
|
||||
global.Config.Database.Password = os.Getenv("BLUEPRINT_DB_PASSWORD")
|
||||
global.Config.Database.RootPassword = os.Getenv("BLUEPRINT_DB_ROOT_PASSWORD")
|
||||
|
||||
// Chuyển đổi các giá trị cấu hình database từ string sang int
|
||||
if maxIdleConns := os.Getenv("BLUEPRINT_DB_MAX_IDLE_CONNS"); maxIdleConns != "" {
|
||||
fmt.Sscanf(maxIdleConns, "%d", &global.Config.Database.MaxIdleConns)
|
||||
}
|
||||
|
||||
if maxOpenConns := os.Getenv("BLUEPRINT_DB_MAX_OPEN_CONNS"); maxOpenConns != "" {
|
||||
fmt.Sscanf(maxOpenConns, "%d", &global.Config.Database.MaxOpenConns)
|
||||
}
|
||||
|
||||
if connMaxLifetime := os.Getenv("BLUEPRINT_DB_CONN_MAX_LIFETIME"); connMaxLifetime != "" {
|
||||
fmt.Sscanf(connMaxLifetime, "%d", &global.Config.Database.ConnMaxLifetime)
|
||||
}
|
||||
|
||||
// Cấu hình logger
|
||||
global.Config.Logger.LogLevel = os.Getenv("LOGGER_LOG_LEVEL")
|
||||
global.Config.Logger.FileLogName = os.Getenv("LOGGER_FILE_LOG_NAME")
|
||||
|
||||
// Chuyển đổi từ string sang int và bool
|
||||
if maxSize := os.Getenv("LOGGER_MAX_SIZE"); maxSize != "" {
|
||||
fmt.Sscanf(maxSize, "%d", &global.Config.Logger.MaxSize)
|
||||
}
|
||||
|
||||
if maxBackups := os.Getenv("LOGGER_MAX_BACKUPS"); maxBackups != "" {
|
||||
fmt.Sscanf(maxBackups, "%d", &global.Config.Logger.MaxBackups)
|
||||
}
|
||||
|
||||
if maxAge := os.Getenv("LOGGER_MAX_AGE"); maxAge != "" {
|
||||
fmt.Sscanf(maxAge, "%d", &global.Config.Logger.MaxAge)
|
||||
}
|
||||
|
||||
if compress := os.Getenv("LOGGER_COMPRESS"); compress != "" {
|
||||
global.Config.Logger.Compress = strings.ToLower(compress) == "true"
|
||||
}
|
||||
|
||||
printConfig()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printConfig() {
|
||||
// Tạo các đối tượng màu sắc
|
||||
titleColor := color.New(color.FgHiCyan, color.Bold)
|
||||
sectionColor := color.New(color.FgHiYellow, color.Bold)
|
||||
keyColor := color.New(color.FgHiGreen)
|
||||
valueColor := color.New(color.FgHiWhite)
|
||||
|
||||
fmt.Println() // Thêm dòng trống ở đầu
|
||||
|
||||
// In tiêu đề
|
||||
titleColor.Println("✨✨✨ CẤU HÌNH ỨNG DỤNG ✨✨✨")
|
||||
fmt.Println()
|
||||
|
||||
// Sử dụng reflection để tự động in tất cả các cấu hình
|
||||
configValue := reflect.ValueOf(global.Config)
|
||||
configType := configValue.Type()
|
||||
|
||||
// Duyệt qua tất cả các trường của cấu hình
|
||||
for i := 0; i < configValue.NumField(); i++ {
|
||||
sectionName := configType.Field(i).Name
|
||||
sectionValue := configValue.Field(i)
|
||||
sectionType := sectionValue.Type()
|
||||
|
||||
// In tên section
|
||||
sectionColor.Printf("[%s]\n", strings.ToUpper(sectionName))
|
||||
|
||||
// Duyệt qua tất cả các trường của section
|
||||
for j := 0; j < sectionValue.NumField(); j++ {
|
||||
fieldName := sectionType.Field(j).Name
|
||||
fieldValue := sectionValue.Field(j).Interface()
|
||||
|
||||
// Ẩn mật khẩu
|
||||
displayValue := fmt.Sprintf("%v", fieldValue)
|
||||
if strings.Contains(strings.ToLower(fieldName), "password") {
|
||||
displayValue = "******** (ẩn)"
|
||||
}
|
||||
|
||||
// In tên trường và giá trị
|
||||
keyColor.Printf(" %-15s: ", fieldName)
|
||||
valueColor.Printf("%s\n", displayValue)
|
||||
}
|
||||
|
||||
fmt.Println() // Thêm dòng trống giữa các section
|
||||
}
|
||||
|
||||
// In thông báo thành công
|
||||
titleColor.Println("✅ Cấu hình đã được tải thành công!")
|
||||
fmt.Println() // Thêm dòng trống ở cuối
|
||||
}
|
103
internal/initialize/logger.go
Normal file
103
internal/initialize/logger.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/dungnt11/senflow_app/global"
|
||||
"github.com/natefinch/lumberjack"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// InitLogger khởi tạo logger
|
||||
func InitLogger() *zap.Logger {
|
||||
// Đảm bảo thư mục logs tồn tại
|
||||
ensureLogDir(global.Config.Logger.FileLogName)
|
||||
|
||||
// Khởi tạo logger
|
||||
return newLogger(global.Config.Logger)
|
||||
}
|
||||
|
||||
// ensureLogDir đảm bảo thư mục logs tồn tại
|
||||
func ensureLogDir(logPath string) {
|
||||
// Tìm vị trí thư mục cuối cùng trong đường dẫn
|
||||
lastSlash := 0
|
||||
for i := len(logPath) - 1; i >= 0; i-- {
|
||||
if logPath[i] == '/' {
|
||||
lastSlash = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Nếu không có thư mục, không cần tạo
|
||||
if lastSlash == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Tạo thư mục nếu chưa tồn tại
|
||||
dirPath := logPath[:lastSlash]
|
||||
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
|
||||
os.MkdirAll(dirPath, 0755)
|
||||
}
|
||||
}
|
||||
|
||||
// newLogger tạo một logger mới
|
||||
func newLogger(config global.LoggerConfig) *zap.Logger {
|
||||
// Xác định level log
|
||||
var level zapcore.Level
|
||||
switch config.LogLevel {
|
||||
case "debug":
|
||||
level = zapcore.DebugLevel
|
||||
case "info":
|
||||
level = zapcore.InfoLevel
|
||||
case "warn":
|
||||
level = zapcore.WarnLevel
|
||||
case "error":
|
||||
level = zapcore.ErrorLevel
|
||||
default:
|
||||
level = zapcore.InfoLevel
|
||||
}
|
||||
|
||||
// Cấu hình encoder
|
||||
encoder := getEncoder()
|
||||
|
||||
// Cấu hình lumberjack để xoay vòng file log
|
||||
hook := lumberjack.Logger{
|
||||
Filename: config.FileLogName,
|
||||
MaxSize: config.MaxSize, // megabytes
|
||||
MaxBackups: config.MaxBackups,
|
||||
MaxAge: config.MaxAge, // days
|
||||
Compress: config.Compress,
|
||||
}
|
||||
|
||||
// Tạo core cho zap
|
||||
core := zapcore.NewCore(
|
||||
encoder,
|
||||
zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)),
|
||||
level,
|
||||
)
|
||||
|
||||
// Tạo logger với các tùy chọn
|
||||
return zap.New(core,
|
||||
zap.AddCaller(),
|
||||
zap.AddStacktrace(zapcore.ErrorLevel),
|
||||
)
|
||||
}
|
||||
|
||||
// getEncoder trả về encoder cho zap
|
||||
func getEncoder() zapcore.Encoder {
|
||||
encoderConfig := zap.NewProductionEncoderConfig()
|
||||
|
||||
// Cấu hình thời gian
|
||||
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||
encoderConfig.TimeKey = "time"
|
||||
|
||||
// Cấu hình level
|
||||
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
|
||||
|
||||
// Cấu hình caller
|
||||
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
|
||||
|
||||
// Trả về encoder JSON
|
||||
return zapcore.NewJSONEncoder(encoderConfig)
|
||||
}
|
46
internal/initialize/mysql.go
Normal file
46
internal/initialize/mysql.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dungnt11/senflow_app/global"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// checkErrorPanic kiểm tra lỗi và gọi panic nếu có lỗi, đồng thời ghi log chi tiết.
|
||||
func checkErrorPanic(err error, errString string) {
|
||||
if err != nil {
|
||||
global.Logger.Error(errString, zap.Error(err))
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// InitMysql khởi tạo kết nối đến cơ sở dữ liệu MySQL và trả về đối tượng *gorm.DB.
|
||||
func InitMysql() *gorm.DB {
|
||||
m := global.Config.Database
|
||||
dsn := "%s:%s@tcp(%s:%v)/%s?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
s := fmt.Sprintf(dsn, m.Username, m.Password, m.Host, m.Port, m.Database)
|
||||
db, err := gorm.Open(mysql.Open(s), &gorm.Config{
|
||||
SkipDefaultTransaction: false,
|
||||
})
|
||||
checkErrorPanic(err, "InitMysql initialization error")
|
||||
global.Logger.Info("Initializing MySQL Successfully")
|
||||
setPool(db)
|
||||
return db
|
||||
}
|
||||
|
||||
// setPool thiết lập các thông số cho connection pool của cơ sở dữ liệu.
|
||||
func setPool(db *gorm.DB) {
|
||||
m := global.Config.Database
|
||||
sqlDb, err := db.DB()
|
||||
if err != nil {
|
||||
global.Logger.Error("Failed to get sql.DB from gorm.DB", zap.Error(err))
|
||||
return
|
||||
}
|
||||
sqlDb.SetMaxIdleConns(m.MaxIdleConns)
|
||||
sqlDb.SetMaxOpenConns(m.MaxOpenConns)
|
||||
sqlDb.SetConnMaxLifetime(time.Duration(m.ConnMaxLifetime) * time.Second)
|
||||
}
|
82
internal/initialize/run.go
Executable file
82
internal/initialize/run.go
Executable file
@@ -0,0 +1,82 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/dungnt11/senflow_app/global"
|
||||
"github.com/dungnt11/senflow_app/internal/routers"
|
||||
"github.com/dungnt11/senflow_app/internal/wire"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Run khởi động ứng dụng
|
||||
func Run() {
|
||||
// Tải cấu hình từ file .env
|
||||
if err := LoadConfig(); err != nil {
|
||||
fmt.Printf("Không thể tải cấu hình: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Khởi tạo logger
|
||||
global.Logger = InitLogger()
|
||||
if global.Logger == nil {
|
||||
fmt.Println("Khởi tạo logger thất bại")
|
||||
return
|
||||
}
|
||||
|
||||
// Khởi tạo database
|
||||
global.Mdb = InitMysql()
|
||||
if global.Mdb == nil {
|
||||
global.Logger.Error("Khởi tạo MySQL thất bại")
|
||||
return
|
||||
}
|
||||
|
||||
// Khởi tạo router
|
||||
r := gin.Default()
|
||||
|
||||
// Khởi tạo controllers thông qua wire
|
||||
controllers, err := wire.InitializeControllers()
|
||||
if err != nil {
|
||||
global.Logger.Error("Khởi tạo controllers thất bại", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
// Khởi tạo routers
|
||||
routers.InitRouters(r, controllers)
|
||||
|
||||
// Khởi động server
|
||||
port := global.Config.Server.Port
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf(":%s", port),
|
||||
Handler: r,
|
||||
}
|
||||
|
||||
// Khởi động server trong goroutine riêng
|
||||
go func() {
|
||||
global.Logger.Info(fmt.Sprintf("Server đang chạy trên cổng %s", port))
|
||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
global.Logger.Error("Server gặp lỗi", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
|
||||
// Graceful shutdown
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
global.Logger.Info("Đang tắt server...")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
if err := server.Shutdown(ctx); err != nil {
|
||||
global.Logger.Error("Server shutdown gặp lỗi", zap.Error(err))
|
||||
}
|
||||
|
||||
global.Logger.Info("Server đã tắt thành công.")
|
||||
}
|
16
internal/models/product.go
Normal file
16
internal/models/product.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Product đại diện cho thông tin sản phẩm
|
||||
type Product struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Name string `gorm:"size:255;not null" json:"name"`
|
||||
Description string `gorm:"type:text" json:"description"`
|
||||
Price float64 `gorm:"not null" json:"price"`
|
||||
Quantity int `gorm:"not null" json:"quantity"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
18
internal/models/user.go
Normal file
18
internal/models/user.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// User đại diện cho người dùng trong hệ thống
|
||||
type User struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
Email string `json:"email" gorm:"uniqueIndex;not null"`
|
||||
Password string `json:"-" gorm:"not null"` // Không trả về password trong JSON
|
||||
Name string `json:"name"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
}
|
23
internal/repositories/interfaces.go
Normal file
23
internal/repositories/interfaces.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package repositories
|
||||
|
||||
import "github.com/dungnt11/senflow_app/internal/models"
|
||||
|
||||
// IUserRepository định nghĩa interface cho UserRepository
|
||||
type IUserRepository interface {
|
||||
Create(user *models.User) error
|
||||
FindByID(id uint) (*models.User, error)
|
||||
FindByEmail(email string) (*models.User, error)
|
||||
Update(user *models.User) error
|
||||
Delete(id uint) error
|
||||
}
|
||||
|
||||
// IProductRepository định nghĩa interface cho ProductRepository
|
||||
type IProductRepository interface {
|
||||
Create(product *models.Product) error
|
||||
FindByID(id uint) (*models.Product, error)
|
||||
FindAll() ([]*models.Product, error)
|
||||
Update(product *models.Product) error
|
||||
Delete(id uint) error
|
||||
}
|
||||
|
||||
// Các interface khác có thể được thêm vào đây khi cần thiết
|
53
internal/repositories/product_repository.go
Normal file
53
internal/repositories/product_repository.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/internal/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ProductRepository triển khai IProductRepository
|
||||
type ProductRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewProductRepository tạo một instance mới của ProductRepository
|
||||
func NewProductRepository(db *gorm.DB) *ProductRepository {
|
||||
return &ProductRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// Create tạo một sản phẩm mới
|
||||
func (r *ProductRepository) Create(product *models.Product) error {
|
||||
return r.db.Create(product).Error
|
||||
}
|
||||
|
||||
// FindByID tìm sản phẩm theo ID
|
||||
func (r *ProductRepository) FindByID(id uint) (*models.Product, error) {
|
||||
var product models.Product
|
||||
err := r.db.First(&product, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &product, nil
|
||||
}
|
||||
|
||||
// FindAll lấy tất cả sản phẩm
|
||||
func (r *ProductRepository) FindAll() ([]*models.Product, error) {
|
||||
var products []*models.Product
|
||||
err := r.db.Find(&products).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return products, nil
|
||||
}
|
||||
|
||||
// Update cập nhật thông tin sản phẩm
|
||||
func (r *ProductRepository) Update(product *models.Product) error {
|
||||
return r.db.Save(product).Error
|
||||
}
|
||||
|
||||
// Delete xóa sản phẩm theo ID
|
||||
func (r *ProductRepository) Delete(id uint) error {
|
||||
return r.db.Delete(&models.Product{}, id).Error
|
||||
}
|
53
internal/repositories/user_repository.go
Normal file
53
internal/repositories/user_repository.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/internal/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// UserRepository triển khai IUserRepository
|
||||
type UserRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewUserRepository tạo một instance mới của UserRepository
|
||||
func NewUserRepository(db *gorm.DB) *UserRepository {
|
||||
return &UserRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// Create tạo một user mới trong database
|
||||
func (ur *UserRepository) Create(user *models.User) error {
|
||||
return ur.db.Create(user).Error
|
||||
}
|
||||
|
||||
// FindByID tìm user theo ID
|
||||
func (ur *UserRepository) FindByID(id uint) (*models.User, error) {
|
||||
var user models.User
|
||||
err := ur.db.First(&user, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// FindByEmail tìm user theo email
|
||||
func (ur *UserRepository) FindByEmail(email string) (*models.User, error) {
|
||||
var user models.User
|
||||
err := ur.db.Where("email = ?", email).First(&user).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// Update cập nhật thông tin user
|
||||
func (ur *UserRepository) Update(user *models.User) error {
|
||||
return ur.db.Save(user).Error
|
||||
}
|
||||
|
||||
// Delete xóa user theo ID
|
||||
func (ur *UserRepository) Delete(id uint) error {
|
||||
return ur.db.Delete(&models.User{}, id).Error
|
||||
}
|
18
internal/routers/product/product_router.go
Normal file
18
internal/routers/product/product_router.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package product
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/internal/controllers"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// InitProductRoutes khởi tạo các routes cho product
|
||||
func InitProductRoutes(router *gin.RouterGroup, productController controllers.IProductController) {
|
||||
productRoutes := router.Group("/products")
|
||||
{
|
||||
productRoutes.POST("", productController.CreateProduct)
|
||||
productRoutes.GET("", productController.GetAllProducts)
|
||||
productRoutes.GET("/:id", productController.GetProduct)
|
||||
productRoutes.PUT("/:id", productController.UpdateProduct)
|
||||
productRoutes.DELETE("/:id", productController.DeleteProduct)
|
||||
}
|
||||
}
|
20
internal/routers/router_group.go
Normal file
20
internal/routers/router_group.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/internal/controllers"
|
||||
"github.com/dungnt11/senflow_app/internal/routers/product"
|
||||
"github.com/dungnt11/senflow_app/internal/routers/user"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// InitRouters khởi tạo tất cả các routers
|
||||
func InitRouters(r *gin.Engine, controllers *controllers.Controllers) {
|
||||
// API v1
|
||||
apiV1 := r.Group("/api/v1")
|
||||
|
||||
// Khởi tạo các routes
|
||||
user.InitUserRoutes(apiV1, controllers.UserController)
|
||||
product.InitProductRoutes(apiV1, controllers.ProductController)
|
||||
|
||||
// Các routes khác có thể được thêm vào đây
|
||||
}
|
17
internal/routers/user/user_router.go
Normal file
17
internal/routers/user/user_router.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/internal/controllers"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// InitUserRoutes khởi tạo các routes liên quan đến user
|
||||
func InitUserRoutes(router *gin.RouterGroup, userController controllers.IUserController) {
|
||||
userGroup := router.Group("/users")
|
||||
{
|
||||
userGroup.POST("/register", userController.Register)
|
||||
userGroup.POST("/login", userController.Login)
|
||||
userGroup.GET("/profile", userController.GetProfile)
|
||||
userGroup.PUT("/profile", userController.UpdateProfile)
|
||||
}
|
||||
}
|
22
internal/services/interfaces.go
Normal file
22
internal/services/interfaces.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package services
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
// IUserService định nghĩa interface cho UserService
|
||||
type IUserService interface {
|
||||
Register(c *gin.Context) (map[string]interface{}, error)
|
||||
Login(c *gin.Context) (map[string]interface{}, error)
|
||||
GetProfile(userID uint) (map[string]interface{}, error)
|
||||
UpdateProfile(userID uint, data map[string]interface{}) (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// IProductService định nghĩa interface cho ProductService
|
||||
type IProductService interface {
|
||||
CreateProduct(c *gin.Context) (map[string]interface{}, error)
|
||||
GetProduct(id uint) (map[string]interface{}, error)
|
||||
GetAllProducts() (map[string]interface{}, error)
|
||||
UpdateProduct(id uint, c *gin.Context) (map[string]interface{}, error)
|
||||
DeleteProduct(id uint) (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// Các interface khác có thể được thêm vào đây khi cần thiết
|
123
internal/services/product_service.go
Normal file
123
internal/services/product_service.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/dungnt11/senflow_app/internal/models"
|
||||
"github.com/dungnt11/senflow_app/internal/repositories"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ProductService triển khai IProductService
|
||||
type ProductService struct {
|
||||
productRepo repositories.IProductRepository
|
||||
}
|
||||
|
||||
// NewProductService tạo một instance mới của ProductService
|
||||
func NewProductService(productRepo repositories.IProductRepository) *ProductService {
|
||||
return &ProductService{
|
||||
productRepo: productRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateProduct tạo một sản phẩm mới
|
||||
func (s *ProductService) CreateProduct(c *gin.Context) (map[string]interface{}, error) {
|
||||
var product models.Product
|
||||
if err := c.ShouldBindJSON(&product); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if product.Name == "" {
|
||||
return nil, errors.New("tên sản phẩm không được để trống")
|
||||
}
|
||||
|
||||
if product.Price <= 0 {
|
||||
return nil, errors.New("giá sản phẩm phải lớn hơn 0")
|
||||
}
|
||||
|
||||
if err := s.productRepo.Create(&product); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"message": "tạo sản phẩm thành công",
|
||||
"product": product,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetProduct lấy thông tin sản phẩm theo ID
|
||||
func (s *ProductService) GetProduct(id uint) (map[string]interface{}, error) {
|
||||
product, err := s.productRepo.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("không tìm thấy sản phẩm")
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"product": product,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAllProducts lấy tất cả sản phẩm
|
||||
func (s *ProductService) GetAllProducts() (map[string]interface{}, error) {
|
||||
products, err := s.productRepo.FindAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"products": products,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateProduct cập nhật thông tin sản phẩm
|
||||
func (s *ProductService) UpdateProduct(id uint, c *gin.Context) (map[string]interface{}, error) {
|
||||
product, err := s.productRepo.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("không tìm thấy sản phẩm")
|
||||
}
|
||||
|
||||
var updatedProduct models.Product
|
||||
if err := c.ShouldBindJSON(&updatedProduct); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Cập nhật thông tin
|
||||
if updatedProduct.Name != "" {
|
||||
product.Name = updatedProduct.Name
|
||||
}
|
||||
if updatedProduct.Description != "" {
|
||||
product.Description = updatedProduct.Description
|
||||
}
|
||||
if updatedProduct.Price > 0 {
|
||||
product.Price = updatedProduct.Price
|
||||
}
|
||||
if updatedProduct.Quantity >= 0 {
|
||||
product.Quantity = updatedProduct.Quantity
|
||||
}
|
||||
|
||||
if err := s.productRepo.Update(product); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"message": "cập nhật sản phẩm thành công",
|
||||
"product": product,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DeleteProduct xóa sản phẩm theo ID
|
||||
func (s *ProductService) DeleteProduct(id uint) (map[string]interface{}, error) {
|
||||
// Kiểm tra sản phẩm tồn tại
|
||||
_, err := s.productRepo.FindByID(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("không tìm thấy sản phẩm")
|
||||
}
|
||||
|
||||
if err := s.productRepo.Delete(id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"message": "xóa sản phẩm thành công",
|
||||
}, nil
|
||||
}
|
118
internal/services/user_service.go
Normal file
118
internal/services/user_service.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/dungnt11/senflow_app/internal/models"
|
||||
"github.com/dungnt11/senflow_app/internal/repositories"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserService triển khai IUserService
|
||||
type UserService struct {
|
||||
userRepo repositories.IUserRepository
|
||||
}
|
||||
|
||||
// NewUserService tạo một instance mới của UserService
|
||||
func NewUserService(userRepo repositories.IUserRepository) *UserService {
|
||||
return &UserService{
|
||||
userRepo: userRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// Register xử lý logic đăng ký người dùng
|
||||
func (us *UserService) Register(c *gin.Context) (map[string]interface{}, error) {
|
||||
// Đọc dữ liệu từ request
|
||||
var user models.User
|
||||
if err := c.ShouldBindJSON(&user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Kiểm tra email đã tồn tại chưa
|
||||
existingUser, _ := us.userRepo.FindByEmail(user.Email)
|
||||
if existingUser != nil {
|
||||
return nil, errors.New("email đã được sử dụng")
|
||||
}
|
||||
|
||||
// Lưu vào database thông qua repository
|
||||
err := us.userRepo.Create(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Trả về kết quả
|
||||
return map[string]interface{}{
|
||||
"message": "Đăng ký thành công",
|
||||
"user_id": user.ID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Login xử lý logic đăng nhập
|
||||
func (us *UserService) Login(c *gin.Context) (map[string]interface{}, error) {
|
||||
// Đọc dữ liệu từ request
|
||||
var loginData struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&loginData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Tìm user theo email
|
||||
user, err := us.userRepo.FindByEmail(loginData.Email)
|
||||
if err != nil {
|
||||
return nil, errors.New("email hoặc mật khẩu không đúng")
|
||||
}
|
||||
|
||||
// Kiểm tra mật khẩu (giả định)
|
||||
if user.Password != loginData.Password {
|
||||
return nil, errors.New("email hoặc mật khẩu không đúng")
|
||||
}
|
||||
|
||||
// Trả về kết quả
|
||||
return map[string]interface{}{
|
||||
"message": "Đăng nhập thành công",
|
||||
"user_id": user.ID,
|
||||
"token": "jwt_token_here", // Trong thực tế, bạn sẽ tạo JWT token
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetProfile lấy thông tin profile của người dùng
|
||||
func (us *UserService) GetProfile(userID uint) (map[string]interface{}, error) {
|
||||
// Tìm user theo ID
|
||||
user, err := us.userRepo.FindByID(userID)
|
||||
if err != nil {
|
||||
return nil, errors.New("không tìm thấy người dùng")
|
||||
}
|
||||
|
||||
// Trả về kết quả
|
||||
return map[string]interface{}{
|
||||
"user": user,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateProfile cập nhật thông tin profile của người dùng
|
||||
func (us *UserService) UpdateProfile(userID uint, data map[string]interface{}) (map[string]interface{}, error) {
|
||||
// Tìm user theo ID
|
||||
user, err := us.userRepo.FindByID(userID)
|
||||
if err != nil {
|
||||
return nil, errors.New("không tìm thấy người dùng")
|
||||
}
|
||||
|
||||
// Cập nhật thông tin (giả định)
|
||||
if name, ok := data["name"].(string); ok {
|
||||
user.Name = name
|
||||
}
|
||||
|
||||
// Lưu vào database
|
||||
err = us.userRepo.Update(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Trả về kết quả
|
||||
return map[string]interface{}{
|
||||
"message": "Cập nhật thành công",
|
||||
"user": user,
|
||||
}, nil
|
||||
}
|
17
internal/wire/injector.go
Normal file
17
internal/wire/injector.go
Normal file
@@ -0,0 +1,17 @@
|
||||
//go:build wireinject
|
||||
// +build wireinject
|
||||
|
||||
package wire
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/internal/controllers"
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
// InitializeControllers khởi tạo tất cả các controllers
|
||||
func InitializeControllers() (*controllers.Controllers, error) {
|
||||
wire.Build(
|
||||
AppSet,
|
||||
)
|
||||
return nil, nil
|
||||
}
|
62
internal/wire/wire.go
Normal file
62
internal/wire/wire.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Package wire chứa các định nghĩa cho dependency injection sử dụng Google Wire
|
||||
package wire
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/global"
|
||||
"github.com/dungnt11/senflow_app/internal/controllers"
|
||||
"github.com/dungnt11/senflow_app/internal/repositories"
|
||||
"github.com/dungnt11/senflow_app/internal/services"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/wire"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// RepositorySet là tập hợp các provider cho repositories
|
||||
var RepositorySet = wire.NewSet(
|
||||
repositories.NewUserRepository,
|
||||
wire.Bind(new(repositories.IUserRepository), new(*repositories.UserRepository)),
|
||||
repositories.NewProductRepository,
|
||||
wire.Bind(new(repositories.IProductRepository), new(*repositories.ProductRepository)),
|
||||
)
|
||||
|
||||
// ServiceSet là tập hợp các provider cho services
|
||||
var ServiceSet = wire.NewSet(
|
||||
services.NewUserService,
|
||||
wire.Bind(new(services.IUserService), new(*services.UserService)),
|
||||
services.NewProductService,
|
||||
wire.Bind(new(services.IProductService), new(*services.ProductService)),
|
||||
)
|
||||
|
||||
// ControllerSet là tập hợp các provider cho controllers
|
||||
var ControllerSet = wire.NewSet(
|
||||
controllers.NewUserController,
|
||||
wire.Bind(new(controllers.IUserController), new(*controllers.UserController)),
|
||||
controllers.NewProductController,
|
||||
wire.Bind(new(controllers.IProductController), new(*controllers.ProductController)),
|
||||
controllers.NewControllers,
|
||||
)
|
||||
|
||||
// AppSet là tập hợp tất cả các provider
|
||||
var AppSet = wire.NewSet(
|
||||
RepositorySet,
|
||||
ServiceSet,
|
||||
ControllerSet,
|
||||
ProvideDB,
|
||||
)
|
||||
|
||||
// ProvideDB cung cấp instance của *gorm.DB
|
||||
func ProvideDB() *gorm.DB {
|
||||
return global.Mdb
|
||||
}
|
||||
|
||||
// ProvideRouter cung cấp instance của *gin.Engine
|
||||
func ProvideRouter() *gin.Engine {
|
||||
if global.Config.Server.AppEnv == "local" {
|
||||
gin.SetMode(gin.DebugMode)
|
||||
gin.ForceConsoleColor()
|
||||
return gin.Default()
|
||||
} else {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
return gin.New()
|
||||
}
|
||||
}
|
28
internal/wire/wire_gen.go
Normal file
28
internal/wire/wire_gen.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Code generated by Wire. DO NOT EDIT.
|
||||
|
||||
//go:generate go run -mod=mod github.com/google/wire/cmd/wire
|
||||
//go:build !wireinject
|
||||
// +build !wireinject
|
||||
|
||||
package wire
|
||||
|
||||
import (
|
||||
"github.com/dungnt11/senflow_app/internal/controllers"
|
||||
"github.com/dungnt11/senflow_app/internal/repositories"
|
||||
"github.com/dungnt11/senflow_app/internal/services"
|
||||
)
|
||||
|
||||
// Injectors from injector.go:
|
||||
|
||||
// InitializeControllers khởi tạo tất cả các controllers
|
||||
func InitializeControllers() (*controllers.Controllers, error) {
|
||||
db := ProvideDB()
|
||||
userRepository := repositories.NewUserRepository(db)
|
||||
userService := services.NewUserService(userRepository)
|
||||
userController := controllers.NewUserController(userService)
|
||||
productRepository := repositories.NewProductRepository(db)
|
||||
productService := services.NewProductService(productRepository)
|
||||
productController := controllers.NewProductController(productService)
|
||||
controllersControllers := controllers.NewControllers(userController, productController)
|
||||
return controllersControllers, nil
|
||||
}
|
Reference in New Issue
Block a user