diff --git a/internal/app/app.go b/internal/app/app.go index 34df71e..1596bb2 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -42,8 +42,16 @@ func (a *App) Initialize(cfg *config.Config) error { processors := a.initProcessors(cfg, repos) services := a.initServices(processors, repos, cfg) validators := a.initValidators() - middleware := a.initMiddleware(services, cfg, repos) + middleware := a.initMiddleware(services, cfg) healthHandler := handler.NewHealthHandler() + selfOrderHandler := handler.NewSelfOrderHandler( + services.orderService, + services.categoryService, + services.productService, + repos.tableRepo, + repos.outletRepo, + repos.userRepo, + ) a.router = router.NewRouter( cfg, @@ -105,14 +113,7 @@ func (a *App) Initialize(cfg *config.Config) error { services.customerPointsService, services.spinGameService, middleware.customerAuthMiddleware, - handler.NewSelfOrderHandler( - services.orderService, - services.productService, - repos.customerRepo, - repos.userRepo, - repos.outletRepo, - ), - middleware.selfOrderMiddleware, + selfOrderHandler, ) return nil @@ -449,14 +450,12 @@ func (a *App) initServices(processors *processors, repos *repositories, cfg *con type middlewares struct { authMiddleware *middleware.AuthMiddleware customerAuthMiddleware *middleware.CustomerAuthMiddleware - selfOrderMiddleware *middleware.SelfOrderMiddleware } -func (a *App) initMiddleware(services *services, cfg *config.Config, repos *repositories) *middlewares { +func (a *App) initMiddleware(services *services, cfg *config.Config) *middlewares { return &middlewares{ authMiddleware: middleware.NewAuthMiddleware(services.authService), customerAuthMiddleware: middleware.NewCustomerAuthMiddleware(cfg.GetCustomerJWTSecret()), - selfOrderMiddleware: middleware.NewSelfOrderMiddleware(repos.tableRepo), } } diff --git a/internal/contract/self_order_contract.go b/internal/contract/self_order_contract.go index 1a2c863..8306ba5 100644 --- a/internal/contract/self_order_contract.go +++ b/internal/contract/self_order_contract.go @@ -1,51 +1,54 @@ package contract import ( - "time" - "github.com/google/uuid" ) -type CreateSelfOrderRequest struct { - CustomerName string `json:"customer_name" validate:"required,min=1,max=255"` - PhoneNumber *string `json:"phone_number,omitempty" validate:"omitempty"` - OrderItems []SelfOrderItemRequest `json:"order_items" validate:"required,min=1,dive"` - Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000"` -} - -type SelfOrderItemRequest struct { - ProductID uuid.UUID `json:"product_id" validate:"required"` - ProductVariantID *uuid.UUID `json:"product_variant_id,omitempty"` - Quantity int `json:"quantity" validate:"required,min=1"` - Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"` -} - -type SelfOrderResponse struct { - OrderID uuid.UUID `json:"order_id"` - OrderNumber string `json:"order_number"` - TableID uuid.UUID `json:"table_id"` - TableName string `json:"table_name"` - OutletID uuid.UUID `json:"outlet_id"` - OutletName string `json:"outlet_name"` - CustomerName string `json:"customer_name"` - OrderItems []OrderItemResponse `json:"order_items"` - Subtotal float64 `json:"subtotal"` - TaxAmount float64 `json:"tax_amount"` - TotalAmount float64 `json:"total_amount"` - Status string `json:"status"` - CreatedAt time.Time `json:"created_at"` +type SelfOrderMenuRequest struct { + TableID uuid.UUID `json:"table_id" validate:"required"` + CustomerName string `json:"customer_name" validate:"required"` + Phone *string `json:"phone,omitempty"` } type SelfOrderMenuResponse struct { - OutletID uuid.UUID `json:"outlet_id"` - OutletName string `json:"outlet_name"` - TableID uuid.UUID `json:"table_id"` - TableName string `json:"table_name"` - Organization OrganizationMenuInfo `json:"organization"` - Products ListProductsResponse `json:"products"` + OutletName string `json:"outlet_name"` + TableName string `json:"table_name"` + Categories []SelfOrderMenuCategory `json:"categories"` } -type OrganizationMenuInfo struct { - ID uuid.UUID `json:"id"` - Name string `json:"name"` +type SelfOrderMenuCategory struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Order int `json:"order"` + Products []SelfOrderMenuItem `json:"products"` +} + +type SelfOrderMenuItem struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Price float64 `json:"price"` + ImageURL *string `json:"image_url,omitempty"` + Variants []SelfOrderMenuVariant `json:"variants,omitempty"` +} + +type SelfOrderMenuVariant struct { + ID uuid.UUID `json:"id"` + Name string `json:"name"` + PriceModifier float64 `json:"price_modifier"` +} + +type SelfOrderCreateOrderRequest struct { + TableID uuid.UUID `json:"table_id" validate:"required"` + CustomerName string `json:"customer_name" validate:"required"` + Phone *string `json:"phone,omitempty"` + OrderItems []SelfOrderCreateOrderItem `json:"order_items" validate:"required,min=1,dive"` +} + +type SelfOrderCreateOrderItem struct { + ProductID uuid.UUID `json:"product_id" validate:"required"` + ProductVariantID *uuid.UUID `json:"product_variant_id,omitempty"` + Quantity int `json:"quantity" validate:"required,min=1"` + Notes *string `json:"notes,omitempty"` } diff --git a/internal/handler/self_order_handler.go b/internal/handler/self_order_handler.go index 96e794e..1d5cf13 100644 --- a/internal/handler/self_order_handler.go +++ b/internal/handler/self_order_handler.go @@ -3,114 +3,196 @@ package handler import ( "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" + "apskel-pos-be/internal/entities" "apskel-pos-be/internal/logger" "apskel-pos-be/internal/models" + "apskel-pos-be/internal/processor" "apskel-pos-be/internal/repository" "apskel-pos-be/internal/service" + "apskel-pos-be/internal/transformer" "apskel-pos-be/internal/util" + "context" + "fmt" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type SelfOrderHandler struct { - orderService service.OrderService - productService service.ProductService - customerRepo *repository.CustomerRepository - userRepo *repository.UserRepositoryImpl - outletRepo *repository.OutletRepositoryImpl + orderService service.OrderService + categoryService service.CategoryService + productService service.ProductService + tableRepo repository.TableRepositoryInterface + outletRepo processor.OutletRepository + userRepo processor.UserRepository } func NewSelfOrderHandler( orderService service.OrderService, + categoryService service.CategoryService, productService service.ProductService, - customerRepo *repository.CustomerRepository, - userRepo *repository.UserRepositoryImpl, - outletRepo *repository.OutletRepositoryImpl, + tableRepo repository.TableRepositoryInterface, + outletRepo processor.OutletRepository, + userRepo processor.UserRepository, ) *SelfOrderHandler { return &SelfOrderHandler{ - orderService: orderService, - productService: productService, - customerRepo: customerRepo, - userRepo: userRepo, - outletRepo: outletRepo, + orderService: orderService, + categoryService: categoryService, + productService: productService, + tableRepo: tableRepo, + outletRepo: outletRepo, + userRepo: userRepo, } } func (h *SelfOrderHandler) GetMenu(c *gin.Context) { ctx := c.Request.Context() - organizationIDStr, _ := c.Get("self_order_organization_id") - outletIDStr, _ := c.Get("self_order_outlet_id") - tableIDStr, _ := c.Get("self_order_table_id") - tableName, _ := c.Get("self_order_table_name") - - organizationID, err := uuid.Parse(organizationIDStr.(string)) - if err != nil { + var req contract.SelfOrderMenuRequest + if err := c.ShouldBindJSON(&req); err != nil { + logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::GetMenu -> request binding failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ - contract.NewResponseError(constants.InternalServerErrorCode, constants.SelfOrderEntity, "invalid organization ID"), + contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()), }), "SelfOrderHandler::GetMenu") return } - outletID, err := uuid.Parse(outletIDStr.(string)) - if err != nil { + if req.TableID == uuid.Nil { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ - contract.NewResponseError(constants.InternalServerErrorCode, constants.SelfOrderEntity, "invalid outlet ID"), + contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "table_id is required"), }), "SelfOrderHandler::GetMenu") return } - tableID, _ := uuid.Parse(tableIDStr.(string)) + if req.CustomerName == "" { + util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ + contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "customer_name is required"), + }), "SelfOrderHandler::GetMenu") + return + } + + table, err := h.tableRepo.GetByID(ctx, req.TableID) + if err != nil { + logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::GetMenu -> table not found") + util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ + contract.NewResponseError(constants.NotFoundErrorCode, constants.TableEntity, "table not found"), + }), "SelfOrderHandler::GetMenu") + return + } + + if !table.IsActive { + util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ + contract.NewResponseError(constants.ValidationErrorCode, constants.TableEntity, "table is not active"), + }), "SelfOrderHandler::GetMenu") + return + } + + outlet, err := h.outletRepo.GetByID(ctx, table.OutletID) + if err != nil { + logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::GetMenu -> outlet not found") + util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ + contract.NewResponseError(constants.NotFoundErrorCode, constants.OrderServiceEntity, "outlet not found"), + }), "SelfOrderHandler::GetMenu") + return + } isActive := true - req := &contract.ListProductsRequest{ - OrganizationID: &organizationID, - IsActive: &isActive, + catResp := h.categoryService.ListCategories(ctx, &contract.ListCategoriesRequest{ + OrganizationID: &table.OrganizationID, Page: 1, Limit: 100, + }) + if catResp.HasErrors() { + logger.FromContext(ctx).WithError(catResp.GetErrors()[0]).Error("SelfOrderHandler::GetMenu -> failed to list categories") + util.HandleResponse(c.Writer, c.Request, catResp, "SelfOrderHandler::GetMenu") + return } - productsResponse := h.productService.ListProducts(ctx, req) - - outlet, outletErr := h.outletRepo.GetByID(ctx, outletID) - outletName := "" - if outletErr == nil && outlet != nil { - outletName = outlet.Name + prodResp := h.productService.ListProducts(ctx, &contract.ListProductsRequest{ + OrganizationID: &table.OrganizationID, + IsActive: &isActive, + Page: 1, + Limit: 1000, + }) + if prodResp.HasErrors() { + logger.FromContext(ctx).WithError(prodResp.GetErrors()[0]).Error("SelfOrderHandler::GetMenu -> failed to list products") + util.HandleResponse(c.Writer, c.Request, prodResp, "SelfOrderHandler::GetMenu") + return } - menuResponse := &contract.SelfOrderMenuResponse{ - OutletID: outletID, - OutletName: outletName, - TableID: tableID, - TableName: tableName.(string), - Organization: contract.OrganizationMenuInfo{ - ID: organizationID, - }, + catList, ok := catResp.Data.(*contract.ListCategoriesResponse) + if !ok { + util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ + contract.NewResponseError(constants.InternalServerErrorCode, constants.CategoryServiceEntity, "unexpected categories response type"), + }), "SelfOrderHandler::GetMenu") + return } - if productsResponse != nil { - if data, ok := productsResponse.Data.(*contract.ListProductsResponse); ok { - menuResponse.Products = *data + prodList, ok := prodResp.Data.(*contract.ListProductsResponse) + if !ok { + util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ + contract.NewResponseError(constants.InternalServerErrorCode, constants.ProductServiceEntity, "unexpected products response type"), + }), "SelfOrderHandler::GetMenu") + return + } + + menu := h.buildMenuResponse(outlet, table, catList.Categories, prodList.Products) + util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(menu), "SelfOrderHandler::GetMenu") +} + +func (h *SelfOrderHandler) buildMenuResponse( + outlet *entities.Outlet, + table *entities.Table, + categories []contract.CategoryResponse, + products []contract.ProductResponse, +) *contract.SelfOrderMenuResponse { + productMap := make(map[uuid.UUID][]contract.ProductResponse) + for _, p := range products { + productMap[p.CategoryID] = append(productMap[p.CategoryID], p) + } + + menuCategories := make([]contract.SelfOrderMenuCategory, 0, len(categories)) + for _, cat := range categories { + menuItems := make([]contract.SelfOrderMenuItem, 0) + if prods, ok := productMap[cat.ID]; ok { + for _, p := range prods { + item := contract.SelfOrderMenuItem{ + ID: p.ID, + Name: p.Name, + Description: p.Description, + Price: p.Price, + ImageURL: p.ImageURL, + } + for _, v := range p.Variants { + item.Variants = append(item.Variants, contract.SelfOrderMenuVariant{ + ID: v.ID, + Name: v.Name, + PriceModifier: v.PriceModifier, + }) + } + menuItems = append(menuItems, item) + } } + menuCategories = append(menuCategories, contract.SelfOrderMenuCategory{ + ID: cat.ID, + Name: cat.Name, + Description: cat.Description, + Order: cat.Order, + Products: menuItems, + }) } - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(menuResponse), "SelfOrderHandler::GetMenu") + return &contract.SelfOrderMenuResponse{ + OutletName: outlet.Name, + TableName: table.TableName, + Categories: menuCategories, + } } func (h *SelfOrderHandler) CreateOrder(c *gin.Context) { ctx := c.Request.Context() - organizationIDStr, _ := c.Get("self_order_organization_id") - outletIDStr, _ := c.Get("self_order_outlet_id") - tableIDStr, _ := c.Get("self_order_table_id") - tableName, _ := c.Get("self_order_table_name") - - organizationID, _ := uuid.Parse(organizationIDStr.(string)) - outletID, _ := uuid.Parse(outletIDStr.(string)) - tableID, _ := uuid.Parse(tableIDStr.(string)) - - var req contract.CreateSelfOrderRequest + var req contract.SelfOrderCreateOrderRequest if err := c.ShouldBindJSON(&req); err != nil { logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::CreateOrder -> request binding failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ @@ -119,121 +201,108 @@ func (h *SelfOrderHandler) CreateOrder(c *gin.Context) { return } - if req.CustomerName == "" { + if err := h.validateCreateOrderRequest(&req); err != nil { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ - contract.NewResponseError(constants.ValidationErrorCode, constants.SelfOrderEntity, "customer_name is required"), + contract.NewResponseError(constants.ValidationErrorCode, constants.RequestEntity, err.Error()), }), "SelfOrderHandler::CreateOrder") return } - if len(req.OrderItems) == 0 { - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ - contract.NewResponseError(constants.ValidationErrorCode, constants.SelfOrderEntity, "at least one order item is required"), - }), "SelfOrderHandler::CreateOrder") - return - } - - adminUser, err := h.userRepo.GetAdminByOrganizationID(ctx, organizationID) + table, err := h.tableRepo.GetByID(ctx, req.TableID) if err != nil { - logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::CreateOrder -> failed to get admin user") + logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::CreateOrder -> table not found") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ - contract.NewResponseError(constants.InternalServerErrorCode, constants.SelfOrderEntity, "failed to resolve system user"), + contract.NewResponseError(constants.NotFoundErrorCode, constants.TableEntity, "table not found"), }), "SelfOrderHandler::CreateOrder") return } - var customerID *uuid.UUID - if req.PhoneNumber != nil && *req.PhoneNumber != "" { - customer, err := h.customerRepo.GetByPhoneNumber(ctx, *req.PhoneNumber) - if err != nil { - logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::CreateOrder -> failed to lookup customer by phone") - } - if customer != nil { - customerID = &customer.ID - } + if !table.IsActive || !table.IsAvailable() { + util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ + contract.NewResponseError(constants.ValidationErrorCode, constants.TableEntity, "table is not available for ordering"), + }), "SelfOrderHandler::CreateOrder") + return } - metadata := map[string]interface{}{ - "source": string(constants.OrderSourceSelfOrder), - "customer_phone": "", - } - if req.PhoneNumber != nil { - metadata["customer_phone"] = *req.PhoneNumber + userID, err := h.resolveOrgUser(ctx, table.OrganizationID) + if err != nil { + logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::CreateOrder -> failed to resolve org user") + util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ + contract.NewResponseError(constants.InternalServerErrorCode, constants.OrderServiceEntity, "failed to create self-order"), + }), "SelfOrderHandler::CreateOrder") + return } - orderItems := make([]models.CreateOrderItemRequest, len(req.OrderItems)) - for i, item := range req.OrderItems { - orderItems[i] = models.CreateOrderItemRequest{ + orderItems := make([]models.CreateOrderItemRequest, 0, len(req.OrderItems)) + for _, item := range req.OrderItems { + orderItems = append(orderItems, models.CreateOrderItemRequest{ ProductID: item.ProductID, ProductVariantID: item.ProductVariantID, Quantity: item.Quantity, Notes: item.Notes, - } + }) } - tableNameStr := tableName.(string) + metadata := make(map[string]interface{}) + metadata["self_order"] = true + metadata["customer_name"] = req.CustomerName + if req.Phone != nil { + metadata["customer_phone"] = *req.Phone + } + + tableID := req.TableID modelReq := &models.CreateOrderRequest{ - OutletID: outletID, - UserID: adminUser.ID, - CustomerID: customerID, + OutletID: table.OutletID, + UserID: userID, TableID: &tableID, - TableNumber: &tableNameStr, + TableNumber: &table.TableName, OrderType: constants.OrderTypeDineIn, OrderItems: orderItems, - Notes: req.Notes, CustomerName: &req.CustomerName, Metadata: metadata, } - response, err := h.orderService.CreateOrder(ctx, modelReq, organizationID) + response, err := h.orderService.CreateOrder(ctx, modelReq, table.OrganizationID) if err != nil { logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::CreateOrder -> failed to create order") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ - contract.NewResponseError(constants.InternalServerErrorCode, constants.SelfOrderEntity, err.Error()), + contract.NewResponseError(constants.InternalServerErrorCode, constants.OrderServiceEntity, err.Error()), }), "SelfOrderHandler::CreateOrder") return } - outlet, _ := h.outletRepo.GetByID(ctx, outletID) - outletName := "" - if outlet != nil { - outletName = outlet.Name - } + contractResp := transformer.OrderModelToContract(response) + util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "SelfOrderHandler::CreateOrder") +} - orderItemsResp := make([]contract.OrderItemResponse, len(response.OrderItems)) - for i, item := range response.OrderItems { - orderItemsResp[i] = contract.OrderItemResponse{ - ID: item.ID, - OrderID: item.OrderID, - ProductID: item.ProductID, - ProductName: item.ProductName, - ProductVariantID: item.ProductVariantID, - ProductVariantName: item.ProductVariantName, - Quantity: item.Quantity, - UnitPrice: item.UnitPrice, - TotalPrice: item.TotalPrice, - Notes: item.Notes, - Status: string(item.Status), - CreatedAt: item.CreatedAt, - UpdatedAt: item.UpdatedAt, +func (h *SelfOrderHandler) validateCreateOrderRequest(req *contract.SelfOrderCreateOrderRequest) error { + if req.TableID == uuid.Nil { + return fmt.Errorf("table_id is required") + } + if req.CustomerName == "" { + return fmt.Errorf("customer_name is required") + } + if len(req.OrderItems) == 0 { + return fmt.Errorf("at least one order item is required") + } + for i, item := range req.OrderItems { + if item.ProductID == uuid.Nil { + return fmt.Errorf("product_id is required for item %d", i+1) + } + if item.Quantity <= 0 { + return fmt.Errorf("quantity must be greater than zero for item %d", i+1) } } - - selfOrderResp := &contract.SelfOrderResponse{ - OrderID: response.ID, - OrderNumber: response.OrderNumber, - TableID: tableID, - TableName: tableNameStr, - OutletID: outletID, - OutletName: outletName, - CustomerName: req.CustomerName, - OrderItems: orderItemsResp, - Subtotal: response.Subtotal, - TaxAmount: response.TaxAmount, - TotalAmount: response.TotalAmount, - Status: string(response.Status), - CreatedAt: response.CreatedAt, - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(selfOrderResp), "SelfOrderHandler::CreateOrder") + return nil +} + +func (h *SelfOrderHandler) resolveOrgUser(ctx context.Context, organizationID uuid.UUID) (uuid.UUID, error) { + users, err := h.userRepo.GetByOrganizationID(ctx, organizationID) + if err != nil { + return uuid.Nil, fmt.Errorf("failed to get users for organization: %w", err) + } + if len(users) == 0 { + return uuid.Nil, fmt.Errorf("no users found for organization") + } + return users[0].ID, nil } diff --git a/internal/router/router.go b/internal/router/router.go index 75d309f..ece4868 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -49,10 +49,9 @@ type Router struct { selfOrderHandler *handler.SelfOrderHandler authMiddleware *middleware.AuthMiddleware customerAuthMiddleware *middleware.CustomerAuthMiddleware - selfOrderMiddleware *middleware.SelfOrderMiddleware } -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, 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, rewardService service.RewardService, rewardValidator validator.RewardValidator, campaignService service.CampaignService, campaignValidator validator.CampaignValidator, customerAuthService service.CustomerAuthService, customerAuthValidator validator.CustomerAuthValidator, customerPointsService service.CustomerPointsService, spinGameService service.SpinGameService, customerAuthMiddleware *middleware.CustomerAuthMiddleware, selfOrderHandler *handler.SelfOrderHandler, selfOrderMiddleware *middleware.SelfOrderMiddleware) *Router { +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, 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, rewardService service.RewardService, rewardValidator validator.RewardValidator, campaignService service.CampaignService, campaignValidator validator.CampaignValidator, customerAuthService service.CustomerAuthService, customerAuthValidator validator.CustomerAuthValidator, customerPointsService service.CustomerPointsService, spinGameService service.SpinGameService, customerAuthMiddleware *middleware.CustomerAuthMiddleware, selfOrderHandler *handler.SelfOrderHandler) *Router { return &Router{ config: cfg, @@ -90,9 +89,8 @@ func NewRouter(cfg *config.Config, healthHandler *handler.HealthHandler, authSer spinGameHandler: handler.NewSpinGameHandler(spinGameService), authMiddleware: authMiddleware, customerAuthMiddleware: customerAuthMiddleware, - selfOrderHandler: selfOrderHandler, - selfOrderMiddleware: selfOrderMiddleware, productVariantHandler: handler.NewProductVariantHandler(productVariantService, productVariantValidator), + selfOrderHandler: selfOrderHandler, } } @@ -149,11 +147,9 @@ func (r *Router) addAppRoutes(rg *gin.Engine) { customer.POST("/spin", r.spinGameHandler.PlaySpinGame) } - // Self-order routes (public, token-based table identification) selfOrder := v1.Group("/self-order") - selfOrder.Use(r.selfOrderMiddleware.ResolveToken()) { - selfOrder.GET("/menu", r.selfOrderHandler.GetMenu) + selfOrder.POST("/menu", r.selfOrderHandler.GetMenu) selfOrder.POST("/order", r.selfOrderHandler.CreateOrder) }