2025-08-07 22:45:02 +07:00

303 lines
12 KiB
Go

package router
import (
"apskel-pos-be/config"
"apskel-pos-be/internal/handler"
"apskel-pos-be/internal/middleware"
"apskel-pos-be/internal/service"
"apskel-pos-be/internal/transformer"
"apskel-pos-be/internal/validator"
"github.com/gin-gonic/gin"
)
type Router struct {
config *config.Config
healthHandler *handler.HealthHandler
authHandler *handler.AuthHandler
userHandler *handler.UserHandler
organizationHandler *handler.OrganizationHandler
outletHandler *handler.OutletHandler
outletSettingHandler *handler.OutletSettingHandlerImpl
categoryHandler *handler.CategoryHandler
productHandler *handler.ProductHandler
productVariantHandler *handler.ProductVariantHandler
inventoryHandler *handler.InventoryHandler
orderHandler *handler.OrderHandler
fileHandler *handler.FileHandler
customerHandler *handler.CustomerHandler
paymentMethodHandler *handler.PaymentMethodHandler
analyticsHandler *handler.AnalyticsHandler
tableHandler *handler.TableHandler
unitHandler *handler.UnitHandler
ingredientHandler *handler.IngredientHandler
authMiddleware *middleware.AuthMiddleware
}
func NewRouter(cfg *config.Config,
healthHandler *handler.HealthHandler,
authService service.AuthService,
authMiddleware *middleware.AuthMiddleware,
userService *service.UserServiceImpl,
userValidator *validator.UserValidatorImpl,
organizationService service.OrganizationService,
organizationValidator validator.OrganizationValidator,
outletService service.OutletService,
outletValidator validator.OutletValidator,
outletSettingService service.OutletSettingService,
categoryService service.CategoryService,
categoryValidator validator.CategoryValidator,
productService service.ProductService,
productValidator validator.ProductValidator,
productVariantService service.ProductVariantService,
productVariantValidator validator.ProductVariantValidator,
inventoryService service.InventoryService,
inventoryValidator validator.InventoryValidator,
orderService service.OrderService,
orderValidator validator.OrderValidator,
fileService service.FileService,
fileValidator validator.FileValidator,
customerService service.CustomerService,
customerValidator validator.CustomerValidator,
paymentMethodService service.PaymentMethodService,
paymentMethodValidator validator.PaymentMethodValidator,
analyticsService *service.AnalyticsServiceImpl,
tableService *service.TableServiceImpl,
tableValidator *validator.TableValidator,
unitService handler.UnitService,
ingredientService handler.IngredientService) *Router {
return &Router{
config: cfg,
healthHandler: healthHandler,
authHandler: handler.NewAuthHandler(authService),
userHandler: handler.NewUserHandler(userService, userValidator),
organizationHandler: handler.NewOrganizationHandler(organizationService, organizationValidator),
outletHandler: handler.NewOutletHandler(outletService, outletValidator),
outletSettingHandler: handler.NewOutletSettingHandlerImpl(outletSettingService),
categoryHandler: handler.NewCategoryHandler(categoryService, categoryValidator),
productHandler: handler.NewProductHandler(productService, productValidator),
inventoryHandler: handler.NewInventoryHandler(inventoryService, inventoryValidator),
orderHandler: handler.NewOrderHandler(orderService, orderValidator, transformer.NewTransformer()),
fileHandler: handler.NewFileHandler(fileService, fileValidator, transformer.NewTransformer()),
customerHandler: handler.NewCustomerHandler(customerService, customerValidator),
paymentMethodHandler: handler.NewPaymentMethodHandler(paymentMethodService, paymentMethodValidator),
analyticsHandler: handler.NewAnalyticsHandler(analyticsService, transformer.NewTransformer()),
tableHandler: handler.NewTableHandler(tableService, tableValidator),
unitHandler: handler.NewUnitHandler(unitService),
ingredientHandler: handler.NewIngredientHandler(ingredientService),
authMiddleware: authMiddleware,
}
}
func (r *Router) Init() *gin.Engine {
gin.SetMode(gin.ReleaseMode)
engine := gin.New()
engine.Use(
middleware.JsonAPI(),
middleware.CorrelationID(),
middleware.Recover(),
middleware.HTTPStatLogger(),
middleware.PopulateContext(),
)
r.addAppRoutes(engine)
return engine
}
func (r *Router) addAppRoutes(rg *gin.Engine) {
rg.GET("/health", r.healthHandler.HealthCheck)
v1 := rg.Group("/api/v1")
{
auth := v1.Group("/auth")
{
auth.POST("/login", r.authHandler.Login)
auth.POST("/logout", r.authHandler.Logout)
auth.POST("/refresh", r.authHandler.RefreshToken)
auth.GET("/validate", r.authHandler.ValidateToken)
auth.GET("/profile", r.authHandler.GetProfile)
}
organizations := v1.Group("/organizations")
{
organizations.POST("", r.organizationHandler.CreateOrganization)
}
protected := v1.Group("")
protected.Use(r.authMiddleware.RequireAuth())
{
users := protected.Group("/users")
{
adminUsers := users.Group("")
adminUsers.Use(r.authMiddleware.RequireAdminOrManager())
{
adminUsers.POST("", r.userHandler.CreateUser)
adminUsers.GET("", r.userHandler.ListUsers)
adminUsers.GET("/:id", r.userHandler.GetUser)
adminUsers.PUT("/:id", r.userHandler.UpdateUser)
adminUsers.DELETE("/:id", r.userHandler.DeleteUser)
adminUsers.PUT("/:id/activate", r.userHandler.ActivateUser)
adminUsers.PUT("/:id/deactivate", r.userHandler.DeactivateUser)
adminUsers.POST("/select-outlet", r.userHandler.UpdateUserOutlet)
}
users.PUT("/:id/password", r.userHandler.ChangePassword)
}
protectedOrganizations := protected.Group("/organizations")
{
adminOrgRoutes := protectedOrganizations.Group("")
adminOrgRoutes.Use(r.authMiddleware.RequireSuperAdmin())
{
adminOrgRoutes.GET("", r.organizationHandler.ListOrganizations)
adminOrgRoutes.GET("/:id", r.organizationHandler.GetOrganization)
adminOrgRoutes.PUT("/:id", r.organizationHandler.UpdateOrganization)
adminOrgRoutes.DELETE("/:id", r.organizationHandler.DeleteOrganization)
}
}
categories := protected.Group("/categories")
categories.Use(r.authMiddleware.RequireAdminOrManager())
{
categories.POST("", r.categoryHandler.CreateCategory)
categories.GET("", r.categoryHandler.ListCategories)
categories.GET("/:id", r.categoryHandler.GetCategory)
categories.PUT("/:id", r.categoryHandler.UpdateCategory)
categories.DELETE("/:id", r.categoryHandler.DeleteCategory)
}
units := protected.Group("/units")
units.Use(r.authMiddleware.RequireAdminOrManager())
{
units.POST("", r.unitHandler.Create)
units.GET("", r.unitHandler.GetAll)
units.GET("/:id", r.unitHandler.GetByID)
units.PUT("/:id", r.unitHandler.Update)
units.DELETE("/:id", r.unitHandler.Delete)
}
products := protected.Group("/products")
products.Use(r.authMiddleware.RequireAdminOrManager())
{
products.POST("", r.productHandler.CreateProduct)
products.GET("", r.productHandler.ListProducts)
products.GET("/:id", r.productHandler.GetProduct)
products.PUT("/:id", r.productHandler.UpdateProduct)
products.DELETE("/:id", r.productHandler.DeleteProduct)
}
inventory := protected.Group("/inventory")
inventory.Use(r.authMiddleware.RequireAdminOrManager())
{
inventory.POST("", r.inventoryHandler.CreateInventory)
inventory.GET("", r.inventoryHandler.ListInventory)
inventory.GET("/:id", r.inventoryHandler.GetInventory)
inventory.PUT("/:id", r.inventoryHandler.UpdateInventory)
inventory.DELETE("/:id", r.inventoryHandler.DeleteInventory)
inventory.POST("/adjust", r.inventoryHandler.AdjustInventory)
inventory.GET("/low-stock/:outlet_id", r.inventoryHandler.GetLowStockItems)
inventory.GET("/zero-stock/:outlet_id", r.inventoryHandler.GetZeroStockItems)
}
orders := protected.Group("/orders")
orders.Use(r.authMiddleware.RequireAdminOrManager())
{
orders.GET("", r.orderHandler.ListOrders)
orders.GET("/:id", r.orderHandler.GetOrderByID)
orders.POST("", r.orderHandler.CreateOrder)
orders.POST("/:id/add-items", r.orderHandler.AddToOrder)
orders.PUT("/:id", r.orderHandler.UpdateOrder)
orders.PUT("/:id/customer", r.orderHandler.SetOrderCustomer)
orders.POST("/void", r.orderHandler.VoidOrder)
orders.POST("/:id/refund", r.orderHandler.RefundOrder)
orders.POST("/split-bill", r.orderHandler.SplitBill)
}
payments := protected.Group("/payments")
payments.Use(r.authMiddleware.RequireAdminOrManager())
{
payments.POST("", r.orderHandler.CreatePayment)
payments.POST("/:id/refund", r.orderHandler.RefundPayment)
}
paymentMethods := protected.Group("/payment-methods")
paymentMethods.Use(r.authMiddleware.RequireAdminOrManager())
{
paymentMethods.POST("", r.paymentMethodHandler.CreatePaymentMethod)
paymentMethods.GET("", r.paymentMethodHandler.ListPaymentMethods)
paymentMethods.GET("/:id", r.paymentMethodHandler.GetPaymentMethod)
paymentMethods.PUT("/:id", r.paymentMethodHandler.UpdatePaymentMethod)
paymentMethods.DELETE("/:id", r.paymentMethodHandler.DeletePaymentMethod)
paymentMethods.GET("/organization/:organization_id/active", r.paymentMethodHandler.GetActivePaymentMethodsByOrganization)
}
files := protected.Group("/files")
files.Use(r.authMiddleware.RequireAdminOrManager())
{
files.GET("/organization", r.fileHandler.GetFilesByOrganization)
files.GET("/user", r.fileHandler.GetFilesByUser)
files.GET("/:id", r.fileHandler.GetFileByID)
files.POST("/upload", r.fileHandler.UploadFile)
files.PUT("/:id", r.fileHandler.UpdateFile)
}
customers := protected.Group("/customers")
customers.Use(r.authMiddleware.RequireAdminOrManager())
{
customers.POST("", r.customerHandler.CreateCustomer)
customers.GET("", r.customerHandler.ListCustomers)
customers.GET("/:id", r.customerHandler.GetCustomer)
customers.PUT("/:id", r.customerHandler.UpdateCustomer)
customers.DELETE("/:id", r.customerHandler.DeleteCustomer)
customers.POST("/set-default", r.customerHandler.SetDefaultCustomer)
customers.GET("/default", r.customerHandler.GetDefaultCustomer)
}
analytics := protected.Group("/analytics")
analytics.Use(r.authMiddleware.RequireAdminOrManager())
{
analytics.GET("/payment-methods", r.analyticsHandler.GetPaymentMethodAnalytics)
analytics.GET("/sales", r.analyticsHandler.GetSalesAnalytics)
analytics.GET("/products", r.analyticsHandler.GetProductAnalytics)
analytics.GET("/dashboard", r.analyticsHandler.GetDashboardAnalytics)
analytics.GET("/profit-loss", r.analyticsHandler.GetProfitLossAnalytics)
}
tables := protected.Group("/tables")
tables.Use(r.authMiddleware.RequireAdminOrManager())
{
tables.POST("", r.tableHandler.Create)
tables.GET("", r.tableHandler.List)
tables.GET("/:id", r.tableHandler.GetByID)
tables.PUT("/:id", r.tableHandler.Update)
tables.DELETE("/:id", r.tableHandler.Delete)
tables.POST("/:id/occupy", r.tableHandler.OccupyTable)
tables.POST("/:id/release", r.tableHandler.ReleaseTable)
}
ingredients := protected.Group("/ingredients")
ingredients.Use(r.authMiddleware.RequireAdminOrManager())
{
ingredients.POST("", r.ingredientHandler.Create)
ingredients.GET("", r.ingredientHandler.GetAll)
ingredients.GET("/:id", r.ingredientHandler.GetByID)
ingredients.PUT("/:id", r.ingredientHandler.Update)
ingredients.DELETE("/:id", r.ingredientHandler.Delete)
}
outlets := protected.Group("/outlets")
outlets.Use(r.authMiddleware.RequireAdminOrManager())
{
outlets.GET("/list", r.outletHandler.ListOutlets)
outlets.GET("/detail/:id", r.outletHandler.GetOutlet)
outlets.PUT("/detail/:id", r.outletHandler.UpdateOutlet)
outlets.GET("/printer-setting/:outlet_id", r.outletSettingHandler.GetPrinterSettings)
outlets.PUT("/printer-setting/:outlet_id", r.outletSettingHandler.UpdatePrinterSettings)
outlets.GET("/:outlet_id/tables/available", r.tableHandler.GetAvailableTables)
outlets.GET("/:outlet_id/tables/occupied", r.tableHandler.GetOccupiedTables)
}
}
}
}