EnakGame phase 10 of docs/tasks-enakgame.md (EG-1001 to EG-1003). Spin (EG-1001) - PROBABILITY entries take an optional label (a wheel segment). The customer game list shows a PROBABILITY game's prizes (entry, label, amount, never weights), and completing returns the drawn prize, so the client can draw the wheel and stop it on the server's draw. - docs/enakgame-spin.md: the admin steps to set up spin per organization (no seeder) and the customer app flow. An HTTP test plays it end to end. Old game flow removed (EG-1002) - Routes POST /customer/spin, GET /customer/games, GET /customer/ferris-wheel, and admin /marketing/games, /marketing/game-prizes, /marketing/rewards, with their handlers, services, processors, repositories, validators, models, contracts, mappers and tests (GamePlayProcessor, SpinGameService, rewards, ...). This also closes RFC §15 findings 1 and 2 (double charge, spinning another org's game). - Tables games, game_prizes, game_plays and rewards stay for ledger history. entities.StringSlice moves to its own file; the omset tracker (unrouted) keeps game_id but no longer embeds the old game response. games.is_active dropped (EG-1003) - Migration 000115; nothing reads metadata.coin_cost any more. The EnakPoint integration docs now point at /customer/enakgame. The Postgres tests were not run: no test database here. Migration 000115 has not been run anywhere. The customer app must stop calling the removed endpoints before this is deployed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
715 lines
42 KiB
Go
715 lines
42 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"
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
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
|
|
vendorHandler *handler.VendorHandler
|
|
purchaseOrderHandler *handler.PurchaseOrderHandler
|
|
purchaseCategoryHandler *handler.PurchaseCategoryHandler
|
|
unitConverterHandler *handler.IngredientUnitConverterHandler
|
|
chartOfAccountTypeHandler *handler.ChartOfAccountTypeHandler
|
|
chartOfAccountHandler *handler.ChartOfAccountHandler
|
|
accountHandler *handler.AccountHandler
|
|
orderIngredientTransactionHandler *handler.OrderIngredientTransactionHandler
|
|
gamificationHandler *handler.GamificationHandler
|
|
campaignHandler *handler.CampaignHandler
|
|
customerAuthHandler *handler.CustomerAuthHandler
|
|
customerPointsHandler *handler.CustomerPointsHandler
|
|
userDeviceHandler *handler.UserDeviceHandler
|
|
notificationHandler *handler.NotificationHandler
|
|
selfOrderHandler *handler.SelfOrderHandler
|
|
productOutletPriceHandler *handler.ProductOutletPriceHandler
|
|
expenseHandler *handler.ExpenseHandler
|
|
cashAdvanceHandler *handler.CashAdvanceHandler
|
|
walletAdminHandler *handler.WalletAdminHandler
|
|
loyaltySettingsHandler *handler.LoyaltySettingsHandler
|
|
customerPinHandler *handler.CustomerPinHandler
|
|
customerWalletHandler *handler.CustomerWalletHandler
|
|
customerDeviceHandler *handler.CustomerDeviceHandler
|
|
customerOutletHandler *handler.CustomerOutletHandler
|
|
customerOrderHandler *handler.CustomerOrderHandler
|
|
enakGameAdminHandler *handler.EnakGameAdminHandler
|
|
enakGameCustomerHandler *handler.EnakGameCustomerHandler
|
|
authMiddleware *middleware.AuthMiddleware
|
|
customerAuthMiddleware *middleware.CustomerAuthMiddleware
|
|
redisClient *redis.Client
|
|
}
|
|
|
|
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, vendorService service.VendorService, vendorValidator validator.VendorValidator, purchaseOrderService service.PurchaseOrderService, purchaseOrderValidator validator.PurchaseOrderValidator, purchaseCategoryService service.PurchaseCategoryService, purchaseCategoryValidator validator.PurchaseCategoryValidator, unitConverterService service.IngredientUnitConverterService, unitConverterValidator validator.IngredientUnitConverterValidator, chartOfAccountTypeService service.ChartOfAccountTypeService, chartOfAccountTypeValidator validator.ChartOfAccountTypeValidator, chartOfAccountService service.ChartOfAccountService, chartOfAccountValidator validator.ChartOfAccountValidator, accountService service.AccountService, accountValidator validator.AccountValidator, orderIngredientTransactionService service.OrderIngredientTransactionService, orderIngredientTransactionValidator validator.OrderIngredientTransactionValidator, gamificationService service.GamificationService, gamificationValidator validator.GamificationValidator, campaignService service.CampaignService, campaignValidator validator.CampaignValidator, customerAuthService service.CustomerAuthService, customerAuthValidator validator.CustomerAuthValidator, customerPointsService service.CustomerPointsService, customerAuthMiddleware *middleware.CustomerAuthMiddleware, userDeviceService service.UserDeviceService, userDeviceValidator validator.UserDeviceValidator, notificationService service.NotificationService, notificationValidator validator.NotificationValidator, productOutletPriceService service.ProductOutletPriceService, productOutletPriceValidator validator.ProductOutletPriceValidator, selfOrderHandler *handler.SelfOrderHandler, expenseService *service.ExpenseServiceImpl, expenseValidator *validator.ExpenseValidatorImpl, cashAdvanceService service.CashAdvanceService, cashAdvanceValidator validator.CashAdvanceValidator, walletAdminService service.WalletAdminService, walletValidator validator.WalletValidator, loyaltySettingsService service.LoyaltySettingsService, customerPinService service.CustomerPinService, customerWalletService service.CustomerWalletService, customerDeviceService service.CustomerDeviceService, customerOutletService service.CustomerOutletService, customerOrderService service.CustomerOrderService, enakGameAdminService service.EnakGameAdminService, enakGameCustomerService service.EnakGameCustomerService, redisClient *redis.Client) *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, cfg.Server.SelfOrderUrl),
|
|
unitHandler: handler.NewUnitHandler(unitService),
|
|
ingredientHandler: handler.NewIngredientHandler(ingredientService),
|
|
productRecipeHandler: handler.NewProductRecipeHandler(productRecipeService),
|
|
vendorHandler: handler.NewVendorHandler(vendorService, vendorValidator),
|
|
purchaseOrderHandler: handler.NewPurchaseOrderHandler(purchaseOrderService, purchaseOrderValidator),
|
|
purchaseCategoryHandler: handler.NewPurchaseCategoryHandler(purchaseCategoryService, purchaseCategoryValidator),
|
|
unitConverterHandler: handler.NewIngredientUnitConverterHandler(unitConverterService, unitConverterValidator),
|
|
chartOfAccountTypeHandler: handler.NewChartOfAccountTypeHandler(chartOfAccountTypeService, chartOfAccountTypeValidator),
|
|
chartOfAccountHandler: handler.NewChartOfAccountHandler(chartOfAccountService, chartOfAccountValidator),
|
|
accountHandler: handler.NewAccountHandler(accountService, accountValidator),
|
|
orderIngredientTransactionHandler: handler.NewOrderIngredientTransactionHandler(&orderIngredientTransactionService, orderIngredientTransactionValidator),
|
|
gamificationHandler: handler.NewGamificationHandler(gamificationService, gamificationValidator),
|
|
campaignHandler: handler.NewCampaignHandler(campaignService, campaignValidator),
|
|
customerAuthHandler: handler.NewCustomerAuthHandler(customerAuthService, customerAuthValidator),
|
|
customerPointsHandler: handler.NewCustomerPointsHandler(customerPointsService),
|
|
authMiddleware: authMiddleware,
|
|
customerAuthMiddleware: customerAuthMiddleware,
|
|
productVariantHandler: handler.NewProductVariantHandler(productVariantService, productVariantValidator),
|
|
userDeviceHandler: handler.NewUserDeviceHandler(userDeviceService, userDeviceValidator),
|
|
notificationHandler: handler.NewNotificationHandler(notificationService, notificationValidator),
|
|
selfOrderHandler: selfOrderHandler,
|
|
productOutletPriceHandler: handler.NewProductOutletPriceHandler(productOutletPriceService, productOutletPriceValidator),
|
|
expenseHandler: handler.NewExpenseHandler(expenseService, expenseValidator),
|
|
cashAdvanceHandler: handler.NewCashAdvanceHandler(cashAdvanceService, cashAdvanceValidator),
|
|
walletAdminHandler: handler.NewWalletAdminHandler(walletAdminService, walletValidator),
|
|
loyaltySettingsHandler: handler.NewLoyaltySettingsHandler(loyaltySettingsService),
|
|
customerPinHandler: handler.NewCustomerPinHandler(customerPinService),
|
|
customerWalletHandler: handler.NewCustomerWalletHandler(customerWalletService),
|
|
customerDeviceHandler: handler.NewCustomerDeviceHandler(customerDeviceService),
|
|
customerOutletHandler: handler.NewCustomerOutletHandler(customerOutletService),
|
|
customerOrderHandler: handler.NewCustomerOrderHandler(customerOrderService),
|
|
enakGameAdminHandler: handler.NewEnakGameAdminHandler(enakGameAdminService),
|
|
enakGameCustomerHandler: handler.NewEnakGameCustomerHandler(enakGameCustomerService),
|
|
redisClient: redisClient,
|
|
}
|
|
}
|
|
|
|
func (r *Router) Init() *gin.Engine {
|
|
gin.SetMode(gin.ReleaseMode)
|
|
engine := gin.New()
|
|
engine.Use(
|
|
middleware.JsonAPI(),
|
|
middleware.CORS(),
|
|
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)
|
|
}
|
|
|
|
// Customer authentication routes
|
|
customerAuth := v1.Group("/customer-auth")
|
|
{
|
|
customerAuth.POST("/check-phone", r.customerAuthHandler.CheckPhone)
|
|
customerAuth.POST("/register/start", r.customerAuthHandler.RegisterStart)
|
|
customerAuth.POST("/register/verify-otp", r.customerAuthHandler.RegisterVerifyOtp)
|
|
customerAuth.POST("/register/set-password", r.customerAuthHandler.RegisterSetPassword)
|
|
customerAuth.POST("/login", r.customerAuthHandler.Login)
|
|
customerAuth.POST("/resend-otp", r.customerAuthHandler.ResendOtp)
|
|
}
|
|
|
|
// Customer authenticated routes
|
|
customer := v1.Group("/customer")
|
|
customer.Use(r.customerAuthMiddleware.ValidateCustomerToken())
|
|
{
|
|
customer.GET("/points", r.customerPointsHandler.GetCustomerPoints)
|
|
customer.GET("/wallet", r.customerPointsHandler.GetCustomerWallet)
|
|
customer.GET("/wallet/transactions", r.customerPointsHandler.GetCustomerWalletTransactions)
|
|
customer.GET("/wallet/expiring", r.customerPointsHandler.GetCustomerWalletExpiring)
|
|
customer.GET("/wallet/exchange/preview", r.customerWalletHandler.PreviewExchange)
|
|
customer.POST("/wallet/exchange", r.customerWalletHandler.Exchange)
|
|
customer.GET("/wallet/transfer/recipient", r.customerWalletHandler.TransferRecipient)
|
|
customer.POST("/wallet/transfer", r.customerWalletHandler.Transfer)
|
|
customer.PUT("/devices", r.customerDeviceHandler.Register)
|
|
customer.DELETE("/devices/:device_id", r.customerDeviceHandler.Unregister)
|
|
customer.GET("/outlets", r.customerOutletHandler.List)
|
|
customer.GET("/orders", r.customerOrderHandler.List)
|
|
customer.GET("/orders/:id", r.customerOrderHandler.Detail)
|
|
// PIN that approves moving EnakPoint and EnakCoin (docs/prd-point-coin.md F11)
|
|
customer.GET("/pin/status", r.customerPinHandler.Status)
|
|
customer.POST("/pin/otp", r.customerPinHandler.RequestOtp)
|
|
customer.POST("/pin", r.customerPinHandler.CreatePin)
|
|
customer.PUT("/pin", r.customerPinHandler.ChangePin)
|
|
customer.POST("/pin/reset", r.customerPinHandler.ResetPin)
|
|
|
|
// EnakGame (docs/rfc-enakgame.md §11). /enakgame because /customer/games was
|
|
// the old spin.
|
|
enakGame := customer.Group("/enakgame")
|
|
{
|
|
enakGame.GET("/games", r.enakGameCustomerHandler.ListGames)
|
|
enakGame.POST("/sessions", r.enakGameCustomerHandler.StartSession)
|
|
enakGame.GET("/sessions", r.enakGameCustomerHandler.ListSessions)
|
|
enakGame.GET("/sessions/:id", r.enakGameCustomerHandler.GetSession)
|
|
enakGame.POST("/sessions/:id/complete", r.enakGameCustomerHandler.CompleteSession)
|
|
enakGame.GET("/vouchers", r.enakGameCustomerHandler.ListVouchers)
|
|
enakGame.POST("/vouchers/:id/redeem", r.enakGameCustomerHandler.RedeemVoucher)
|
|
enakGame.GET("/redemptions", r.enakGameCustomerHandler.ListRedemptions)
|
|
}
|
|
}
|
|
|
|
selfOrder := v1.Group("/self-order")
|
|
{
|
|
selfOrder.GET("/table/:token", r.selfOrderHandler.ValidateToken)
|
|
selfOrder.GET("/categories", r.selfOrderHandler.ListCategories)
|
|
selfOrder.GET("/menu", r.selfOrderHandler.GetMenu)
|
|
selfOrder.POST("/orders", r.selfOrderHandler.CreateOrder)
|
|
selfOrder.GET("/orders/:session_id", r.selfOrderHandler.GetOrdersBySession)
|
|
}
|
|
|
|
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("/all", r.productHandler.ListProductAll)
|
|
products.GET("/:id", r.productHandler.GetProduct)
|
|
products.PUT("/:id", r.productHandler.UpdateProduct)
|
|
products.DELETE("/:id", r.productHandler.DeleteProduct)
|
|
}
|
|
|
|
productOutletPrices := protected.Group("/product-outlet-prices")
|
|
productOutletPrices.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
productOutletPrices.POST("", r.productOutletPriceHandler.Upsert)
|
|
productOutletPrices.POST("/bulk", r.productOutletPriceHandler.BulkUpsert)
|
|
productOutletPrices.GET("/product/:product_id", r.productOutletPriceHandler.GetByProduct)
|
|
productOutletPrices.GET("/outlet/:outlet_id", r.productOutletPriceHandler.GetByOutlet)
|
|
productOutletPrices.GET("/product/:product_id/outlet/:outlet_id", r.productOutletPriceHandler.GetByProductAndOutlet)
|
|
productOutletPrices.DELETE("/:id", r.productOutletPriceHandler.Delete)
|
|
}
|
|
|
|
productVariants := protected.Group("/product-variants")
|
|
{
|
|
productVariants.POST("", r.productVariantHandler.CreateProductVariant)
|
|
productVariants.PUT("/:id", r.productVariantHandler.UpdateProductVariant)
|
|
productVariants.DELETE("/:id", r.productVariantHandler.DeleteProductVariant)
|
|
productVariants.GET("/:id", r.productVariantHandler.GetProductVariant)
|
|
}
|
|
|
|
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.POST("/restock", r.inventoryHandler.RestockInventory)
|
|
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/:outlet_id", 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", middleware.IdempotencyMiddleware(r.redisClient), r.orderHandler.AddToOrder)
|
|
orders.PUT("/:id", r.orderHandler.UpdateOrder)
|
|
orders.PUT("/:id/customer", r.orderHandler.SetOrderCustomer)
|
|
orders.POST("/void", middleware.IdempotencyMiddleware(r.redisClient), r.orderHandler.VoidOrder)
|
|
orders.POST("/:id/refund", middleware.IdempotencyMiddleware(r.redisClient), r.orderHandler.RefundOrder)
|
|
orders.POST("/split-bill", r.orderHandler.SplitBill)
|
|
}
|
|
|
|
payments := protected.Group("/payments")
|
|
payments.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
payments.POST("", middleware.IdempotencyMiddleware(r.redisClient), r.orderHandler.CreatePayment)
|
|
payments.POST("/:id/refund", middleware.IdempotencyMiddleware(r.redisClient), 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("/purchasing", r.analyticsHandler.GetPurchasingAnalytics)
|
|
analytics.GET("/products", r.analyticsHandler.GetProductAnalytics)
|
|
analytics.GET("/categories", r.analyticsHandler.GetProductAnalyticsPerCategory)
|
|
analytics.GET("/profit-sharing", r.analyticsHandler.GetProductAnalyticsPerParentCategory)
|
|
analytics.GET("/profit-sharing/:parent_category_id", r.analyticsHandler.GetParentCategoryAnalyticsDetail)
|
|
analytics.GET("/dashboard", r.analyticsHandler.GetDashboardAnalytics)
|
|
analytics.GET("/profit-loss", r.analyticsHandler.GetProfitLossAnalytics)
|
|
analytics.GET("/exclusive-summary/period", r.analyticsHandler.GetExclusiveSummaryPeriod)
|
|
analytics.GET("/exclusive-summary/monthly", r.analyticsHandler.GetExclusiveSummaryMonthly)
|
|
analytics.GET("/exclusive-summary/mtd", r.analyticsHandler.GetExclusiveSummaryMTD)
|
|
}
|
|
|
|
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)
|
|
tables.GET("/:id/qr", r.tableHandler.GenerateQRCode)
|
|
}
|
|
|
|
ingredients := protected.Group("/ingredients")
|
|
ingredients.Use(r.authMiddleware.RequireAdminOrManagerOrPurchasing())
|
|
{
|
|
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)
|
|
ingredients.POST("/:id/compositions", r.ingredientHandler.AddCompositions)
|
|
ingredients.PUT("/compositions/:composition_id", r.ingredientHandler.UpdateComposition)
|
|
ingredients.DELETE("/compositions/:composition_id", r.ingredientHandler.DeleteComposition)
|
|
}
|
|
|
|
vendors := protected.Group("/vendors")
|
|
vendors.Use(r.authMiddleware.RequireAdminOrManagerOrPurchasing())
|
|
{
|
|
vendors.POST("", r.vendorHandler.CreateVendor)
|
|
vendors.GET("", r.vendorHandler.ListVendors)
|
|
vendors.GET("/active", r.vendorHandler.GetActiveVendors)
|
|
vendors.GET("/:id", r.vendorHandler.GetVendor)
|
|
vendors.PUT("/:id", r.vendorHandler.UpdateVendor)
|
|
vendors.DELETE("/:id", r.vendorHandler.DeleteVendor)
|
|
}
|
|
|
|
purchaseOrders := protected.Group("/purchase-orders")
|
|
purchaseOrders.Use(r.authMiddleware.RequireAdminOrManagerOrPurchasing())
|
|
{
|
|
purchaseOrders.POST("", r.purchaseOrderHandler.CreatePurchaseOrder)
|
|
purchaseOrders.GET("", r.purchaseOrderHandler.ListPurchaseOrders)
|
|
purchaseOrders.GET("/status/:status", r.purchaseOrderHandler.GetPurchaseOrdersByStatus)
|
|
purchaseOrders.GET("/overdue", r.purchaseOrderHandler.GetOverduePurchaseOrders)
|
|
purchaseOrders.GET("/teams", r.purchaseOrderHandler.ListPurchaseTeams)
|
|
purchaseOrders.GET("/:id", r.purchaseOrderHandler.GetPurchaseOrder)
|
|
purchaseOrders.PUT("/:id", r.purchaseOrderHandler.UpdatePurchaseOrder)
|
|
purchaseOrders.PUT("/:id/status/:status", r.purchaseOrderHandler.UpdatePurchaseOrderStatus)
|
|
purchaseOrders.DELETE("/:id", r.purchaseOrderHandler.DeletePurchaseOrder)
|
|
}
|
|
|
|
purchaseCategories := protected.Group("/purchase-categories")
|
|
purchaseCategories.Use(r.authMiddleware.RequireAdminOrManagerOrPurchasing())
|
|
{
|
|
purchaseCategories.POST("", r.purchaseCategoryHandler.CreatePurchaseCategory)
|
|
purchaseCategories.GET("", r.purchaseCategoryHandler.ListPurchaseCategories)
|
|
purchaseCategories.GET("/:id", r.purchaseCategoryHandler.GetPurchaseCategory)
|
|
purchaseCategories.PUT("/:id", r.purchaseCategoryHandler.UpdatePurchaseCategory)
|
|
purchaseCategories.DELETE("/:id", r.purchaseCategoryHandler.DeletePurchaseCategory)
|
|
}
|
|
|
|
unitConverters := protected.Group("/unit-converters")
|
|
unitConverters.Use(r.authMiddleware.RequireAdminOrManagerOrPurchasing())
|
|
{
|
|
unitConverters.POST("", r.unitConverterHandler.CreateIngredientUnitConverter)
|
|
unitConverters.GET("", r.unitConverterHandler.ListIngredientUnitConverters)
|
|
unitConverters.GET("/ingredient/:ingredient_id", r.unitConverterHandler.GetConvertersForIngredient)
|
|
unitConverters.GET("/ingredient/:ingredient_id/units", r.unitConverterHandler.GetUnitsByIngredientID)
|
|
unitConverters.POST("/convert", r.unitConverterHandler.ConvertUnit)
|
|
unitConverters.GET("/:id", r.unitConverterHandler.GetIngredientUnitConverter)
|
|
unitConverters.PUT("/:id", r.unitConverterHandler.UpdateIngredientUnitConverter)
|
|
unitConverters.DELETE("/:id", r.unitConverterHandler.DeleteIngredientUnitConverter)
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
// Accounting routes
|
|
chartOfAccountTypes := protected.Group("/chart-of-account-types")
|
|
chartOfAccountTypes.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
chartOfAccountTypes.POST("", r.chartOfAccountTypeHandler.CreateChartOfAccountType)
|
|
chartOfAccountTypes.GET("", r.chartOfAccountTypeHandler.ListChartOfAccountTypes)
|
|
chartOfAccountTypes.GET("/:id", r.chartOfAccountTypeHandler.GetChartOfAccountTypeByID)
|
|
chartOfAccountTypes.PUT("/:id", r.chartOfAccountTypeHandler.UpdateChartOfAccountType)
|
|
chartOfAccountTypes.DELETE("/:id", r.chartOfAccountTypeHandler.DeleteChartOfAccountType)
|
|
}
|
|
|
|
chartOfAccounts := protected.Group("/chart-of-accounts")
|
|
chartOfAccounts.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
chartOfAccounts.POST("", r.chartOfAccountHandler.CreateChartOfAccount)
|
|
chartOfAccounts.GET("", r.chartOfAccountHandler.ListChartOfAccounts)
|
|
chartOfAccounts.GET("/:id", r.chartOfAccountHandler.GetChartOfAccountByID)
|
|
chartOfAccounts.PUT("/:id", r.chartOfAccountHandler.UpdateChartOfAccount)
|
|
chartOfAccounts.DELETE("/:id", r.chartOfAccountHandler.DeleteChartOfAccount)
|
|
chartOfAccounts.GET("/organization/:organization_id", r.chartOfAccountHandler.GetChartOfAccountsByOrganization)
|
|
chartOfAccounts.GET("/organization/:organization_id/type/:type_id", r.chartOfAccountHandler.GetChartOfAccountsByType)
|
|
}
|
|
|
|
accounts := protected.Group("/accounts")
|
|
accounts.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
accounts.POST("", r.accountHandler.CreateAccount)
|
|
accounts.GET("", r.accountHandler.ListAccounts)
|
|
accounts.GET("/:id", r.accountHandler.GetAccountByID)
|
|
accounts.PUT("/:id", r.accountHandler.UpdateAccount)
|
|
accounts.DELETE("/:id", r.accountHandler.DeleteAccount)
|
|
accounts.GET("/organization/:organization_id", r.accountHandler.GetAccountsByOrganization)
|
|
accounts.GET("/chart-of-account/:chart_of_account_id", r.accountHandler.GetAccountsByChartOfAccount)
|
|
accounts.PUT("/:id/balance", r.accountHandler.UpdateAccountBalance)
|
|
accounts.GET("/:id/balance", r.accountHandler.GetAccountBalance)
|
|
}
|
|
|
|
expenses := protected.Group("/expenses")
|
|
expenses.Use(r.authMiddleware.RequireAdminOrManagerOrPurchasing())
|
|
{
|
|
expenses.POST("", r.expenseHandler.CreateExpense)
|
|
expenses.GET("", r.expenseHandler.ListExpenses)
|
|
expenses.GET("/analytics", r.expenseHandler.GetExpenseAnalytics)
|
|
expenses.GET("/:id", r.expenseHandler.GetExpense)
|
|
expenses.PUT("/:id", r.expenseHandler.UpdateExpense)
|
|
expenses.DELETE("/:id", r.expenseHandler.DeleteExpense)
|
|
}
|
|
|
|
cashAdvances := protected.Group("/cash-advances")
|
|
cashAdvances.Use(r.authMiddleware.RequireAdminOrManagerOrPurchasing())
|
|
{
|
|
cashAdvances.POST("", r.cashAdvanceHandler.CreateCashAdvance)
|
|
cashAdvances.GET("", r.cashAdvanceHandler.ListCashAdvances)
|
|
// Registered ahead of /:id so the picker path is not read as an id.
|
|
cashAdvances.GET("/teams", r.cashAdvanceHandler.ListCashAdvanceTeams)
|
|
cashAdvances.GET("/:id", r.cashAdvanceHandler.GetCashAdvance)
|
|
cashAdvances.PUT("/:id", r.cashAdvanceHandler.UpdateCashAdvance)
|
|
cashAdvances.PUT("/:id/status/:status", r.cashAdvanceHandler.UpdateCashAdvanceStatus)
|
|
cashAdvances.DELETE("/:id", r.cashAdvanceHandler.DeleteCashAdvance)
|
|
}
|
|
|
|
orderIngredientTransactions := protected.Group("/order-ingredient-transactions")
|
|
orderIngredientTransactions.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
orderIngredientTransactions.POST("", r.orderIngredientTransactionHandler.CreateOrderIngredientTransaction)
|
|
orderIngredientTransactions.GET("", r.orderIngredientTransactionHandler.ListOrderIngredientTransactions)
|
|
orderIngredientTransactions.GET("/:id", r.orderIngredientTransactionHandler.GetOrderIngredientTransactionByID)
|
|
orderIngredientTransactions.PUT("/:id", r.orderIngredientTransactionHandler.UpdateOrderIngredientTransaction)
|
|
orderIngredientTransactions.DELETE("/:id", r.orderIngredientTransactionHandler.DeleteOrderIngredientTransaction)
|
|
orderIngredientTransactions.GET("/order/:order_id", r.orderIngredientTransactionHandler.GetOrderIngredientTransactionsByOrder)
|
|
orderIngredientTransactions.GET("/order-item/:order_item_id", r.orderIngredientTransactionHandler.GetOrderIngredientTransactionsByOrderItem)
|
|
orderIngredientTransactions.GET("/ingredient/:ingredient_id", r.orderIngredientTransactionHandler.GetOrderIngredientTransactionsByIngredient)
|
|
orderIngredientTransactions.GET("/summary", r.orderIngredientTransactionHandler.GetOrderIngredientTransactionSummary)
|
|
orderIngredientTransactions.POST("/bulk", r.orderIngredientTransactionHandler.BulkCreateOrderIngredientTransactions)
|
|
}
|
|
|
|
gamification := protected.Group("/marketing")
|
|
gamification.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
// Tiers
|
|
tiers := gamification.Group("/tiers")
|
|
{
|
|
tiers.POST("", r.gamificationHandler.CreateTier)
|
|
tiers.GET("", r.gamificationHandler.ListTiers)
|
|
tiers.GET("/:id", r.gamificationHandler.GetTier)
|
|
tiers.PUT("/:id", r.gamificationHandler.UpdateTier)
|
|
tiers.DELETE("/:id", r.gamificationHandler.DeleteTier)
|
|
tiers.GET("/by-points/:points", r.gamificationHandler.GetTierByPoints)
|
|
}
|
|
|
|
// Omset Tracker
|
|
//omsetTracker := gamification.Group("/omset-tracker")
|
|
//{
|
|
// omsetTracker.POST("", r.gamificationHandler.CreateOmsetTracker)
|
|
// omsetTracker.GET("", r.gamificationHandler.ListOmsetTrackers)
|
|
// omsetTracker.GET("/:id", r.gamificationHandler.GetOmsetTracker)
|
|
// omsetTracker.PUT("/:id", r.gamificationHandler.UpdateOmsetTracker)
|
|
// omsetTracker.DELETE("/:id", r.gamificationHandler.DeleteOmsetTracker)
|
|
//}
|
|
|
|
// Campaigns
|
|
campaigns := gamification.Group("/campaigns")
|
|
{
|
|
campaigns.POST("", r.campaignHandler.CreateCampaign)
|
|
campaigns.GET("", r.campaignHandler.ListCampaigns)
|
|
campaigns.GET("/active", r.campaignHandler.GetActiveCampaigns)
|
|
campaigns.GET("/app", r.campaignHandler.GetCampaignsForApp)
|
|
campaigns.GET("/:id", r.campaignHandler.GetCampaign)
|
|
campaigns.PUT("/:id", r.campaignHandler.UpdateCampaign)
|
|
campaigns.DELETE("/:id", r.campaignHandler.DeleteCampaign)
|
|
}
|
|
|
|
// Campaign Rules
|
|
// EnakPoint & EnakCoin settings of the organization (docs/prd-point-coin.md F2)
|
|
gamification.GET("/loyalty-settings", r.loyaltySettingsHandler.GetOrganizationSettings)
|
|
gamification.PUT("/loyalty-settings", r.authMiddleware.RequireLoyaltyManager(), r.loyaltySettingsHandler.UpdateOrganizationSettings)
|
|
gamification.GET("/loyalty-settings/history", r.loyaltySettingsHandler.ListHistory)
|
|
|
|
// EnakPoint & EnakCoin wallet of one customer (docs/prd-point-coin.md F7)
|
|
marketingCustomers := gamification.Group("/customers")
|
|
{
|
|
marketingCustomers.GET("/:id/wallet", r.walletAdminHandler.GetCustomerWallet)
|
|
marketingCustomers.POST("/:id/wallet/adjust", r.authMiddleware.RequireLoyaltyManager(), r.walletAdminHandler.AdjustCustomerWallet)
|
|
marketingCustomers.DELETE("/:id/pin", r.authMiddleware.RequireLoyaltyManager(), r.customerPinHandler.RemovePin)
|
|
marketingCustomers.GET("/:id/security-events", r.customerPinHandler.ListSecurityEvents)
|
|
}
|
|
// Trace one ledger row lot by lot back to where its balance came from (F7, §8.1)
|
|
gamification.GET("/wallet-transactions/:id/trace", r.walletAdminHandler.TraceTransaction)
|
|
|
|
// EnakGame (docs/rfc-enakgame.md §11). Reward configurations and budgets
|
|
// change what rewards cost, so writing them takes a loyalty manager.
|
|
enakGame := gamification.Group("/enakgame")
|
|
{
|
|
enakGame.POST("/games", r.enakGameAdminHandler.CreateGame)
|
|
enakGame.GET("/games", r.enakGameAdminHandler.ListGames)
|
|
enakGame.GET("/games/:id", r.enakGameAdminHandler.GetGame)
|
|
enakGame.PUT("/games/:id", r.enakGameAdminHandler.UpdateGame)
|
|
enakGame.PUT("/games/:id/status", r.enakGameAdminHandler.SetGameStatus)
|
|
enakGame.GET("/games/:id/reward-configs", r.enakGameAdminHandler.ListRewardConfigs)
|
|
enakGame.POST("/games/:id/reward-configs", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.CreateRewardConfig)
|
|
enakGame.POST("/reward-configs/:id/activate", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.ActivateRewardConfig)
|
|
|
|
enakGame.GET("/budgets", r.enakGameAdminHandler.ListBudgets)
|
|
enakGame.GET("/budgets/:id", r.enakGameAdminHandler.GetBudget)
|
|
enakGame.GET("/budgets/:id/metrics", r.enakGameAdminHandler.BudgetMetrics)
|
|
enakGame.POST("/budgets", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.CreateBudget)
|
|
enakGame.PUT("/budgets/:id", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.UpdateBudget)
|
|
enakGame.DELETE("/budgets/:id", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.DeleteBudget)
|
|
// Accepting writes new reward configuration versions.
|
|
enakGame.GET("/budgets/:id/recommendation", r.enakGameAdminHandler.BudgetRecommendation)
|
|
enakGame.POST("/budgets/:id/recommendation/accept", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.AcceptBudgetRecommendation)
|
|
|
|
enakGame.GET("/analytics/games", r.enakGameAdminHandler.GameAnalytics)
|
|
enakGame.GET("/analytics/economy", r.enakGameAdminHandler.EconomyAnalytics)
|
|
|
|
// Events change what rewards cost, like budgets.
|
|
enakGame.GET("/events", r.enakGameAdminHandler.ListEvents)
|
|
enakGame.GET("/events/:id", r.enakGameAdminHandler.GetEvent)
|
|
enakGame.POST("/events", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.CreateEvent)
|
|
enakGame.PUT("/events/:id", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.UpdateEvent)
|
|
enakGame.PUT("/events/:id/status", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.SetEventStatus)
|
|
|
|
enakGame.GET("/vouchers", r.enakGameAdminHandler.ListVouchers)
|
|
enakGame.GET("/vouchers/:id", r.enakGameAdminHandler.GetVoucher)
|
|
enakGame.GET("/vouchers/:id/codes", r.enakGameAdminHandler.ListVoucherCodes)
|
|
enakGame.POST("/vouchers", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.CreateVoucher)
|
|
enakGame.PUT("/vouchers/:id", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.UpdateVoucher)
|
|
enakGame.PUT("/vouchers/:id/status", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.SetVoucherStatus)
|
|
enakGame.POST("/vouchers/:id/codes", r.authMiddleware.RequireLoyaltyManager(), r.enakGameAdminHandler.ImportVoucherCodes)
|
|
}
|
|
|
|
campaignRules := gamification.Group("/campaign-rules")
|
|
{
|
|
campaignRules.POST("", r.campaignHandler.CreateCampaignRule)
|
|
campaignRules.GET("", r.campaignHandler.ListCampaignRules)
|
|
campaignRules.GET("/:id", r.campaignHandler.GetCampaignRule)
|
|
campaignRules.PUT("/:id", r.campaignHandler.UpdateCampaignRule)
|
|
campaignRules.DELETE("/:id", r.campaignHandler.DeleteCampaignRule)
|
|
campaignRules.GET("/campaign/:campaign_id", r.campaignHandler.GetCampaignRulesByCampaignID)
|
|
}
|
|
}
|
|
|
|
outlets := protected.Group("/outlets")
|
|
outlets.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
outlets.POST("", r.outletHandler.CreateOutlet)
|
|
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)
|
|
// EnakPoint & EnakCoin settings of the outlet (docs/prd-point-coin.md F1)
|
|
outlets.GET("/:outlet_id/loyalty-settings", r.loyaltySettingsHandler.GetOutletSettings)
|
|
outlets.PUT("/:outlet_id/loyalty-settings", r.authMiddleware.RequireLoyaltyManager(), r.loyaltySettingsHandler.UpdateOutletSettings)
|
|
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)
|
|
outlets.GET("/:outlet_id/reports/profit-loss.pdf", r.reportHandler.GetProfitLossReportPDF)
|
|
}
|
|
|
|
// User device routes - accessible by authenticated users for their own devices
|
|
userDevices := protected.Group("/user-devices")
|
|
{
|
|
userDevices.POST("/register", r.userDeviceHandler.RegisterDevice)
|
|
userDevices.GET("/me", r.userDeviceHandler.GetMyDevices)
|
|
userDevices.GET("/:id", r.userDeviceHandler.GetDevice)
|
|
userDevices.PUT("/:id", r.userDeviceHandler.UpdateDevice)
|
|
userDevices.DELETE("/:id", r.userDeviceHandler.DeleteDevice)
|
|
}
|
|
|
|
// Admin-only user device routes
|
|
adminUserDevices := protected.Group("/user-devices")
|
|
adminUserDevices.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
adminUserDevices.GET("", r.userDeviceHandler.ListDevices)
|
|
adminUserDevices.GET("/user/:user_id", r.userDeviceHandler.GetDevicesByUser)
|
|
}
|
|
|
|
// Notification routes - authenticated users manage their own notifications
|
|
notifications := protected.Group("/notifications")
|
|
{
|
|
notifications.GET("", r.notificationHandler.List)
|
|
notifications.GET("/:id", r.notificationHandler.GetByID)
|
|
notifications.PUT("/:id/read", r.notificationHandler.MarkAsRead)
|
|
notifications.PUT("/read-all", r.notificationHandler.MarkAllAsRead)
|
|
notifications.DELETE("/:id", r.notificationHandler.Delete)
|
|
}
|
|
|
|
// Admin notification routes - send and broadcast
|
|
adminNotifications := protected.Group("/notifications")
|
|
adminNotifications.Use(r.authMiddleware.RequireAdminOrManager())
|
|
{
|
|
adminNotifications.POST("/send", r.notificationHandler.Send)
|
|
adminNotifications.POST("/broadcast", r.notificationHandler.Broadcast)
|
|
}
|
|
}
|
|
}
|
|
}
|