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 reportHandler *handler.ReportHandler tableHandler *handler.TableHandler unitHandler *handler.UnitHandler ingredientHandler *handler.IngredientHandler productRecipeHandler *handler.ProductRecipeHandler 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, reportService service.ReportService, tableService *service.TableServiceImpl, tableValidator *validator.TableValidator, unitService handler.UnitService, ingredientService handler.IngredientService, productRecipeService service.ProductRecipeService) *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()), reportHandler: handler.NewReportHandler(reportService, userService), tableHandler: handler.NewTableHandler(tableService, tableValidator), unitHandler: handler.NewUnitHandler(unitService), ingredientHandler: handler.NewIngredientHandler(ingredientService), productRecipeHandler: handler.NewProductRecipeHandler(productRecipeService), 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(), middleware.CORS(), ) 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) inventory.GET("/report/summary/:outlet_id", r.inventoryHandler.GetInventoryReportSummary) inventory.GET("/report/details", r.inventoryHandler.GetInventoryReportDetails) } 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) } productRecipes := protected.Group("/product-recipes") productRecipes.Use(r.authMiddleware.RequireAdminOrManager()) { productRecipes.POST("", r.productRecipeHandler.Create) productRecipes.POST("/bulk", r.productRecipeHandler.BulkCreate) productRecipes.GET("/:id", r.productRecipeHandler.GetByID) productRecipes.PUT("/:id", r.productRecipeHandler.Update) productRecipes.DELETE("/:id", r.productRecipeHandler.Delete) productRecipes.GET("/product/:product_id", r.productRecipeHandler.GetByProductID) productRecipes.GET("/ingredient/:ingredient_id", r.productRecipeHandler.GetByIngredientID) } 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) // Reports outlets.GET("/:outlet_id/reports/daily-transaction.pdf", r.reportHandler.GetDailyTransactionReportPDF) } } } }