240 lines
7.8 KiB
Go
240 lines
7.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"apskel-pos-be/internal/constants"
|
|
"apskel-pos-be/internal/contract"
|
|
"apskel-pos-be/internal/logger"
|
|
"apskel-pos-be/internal/models"
|
|
"apskel-pos-be/internal/repository"
|
|
"apskel-pos-be/internal/service"
|
|
"apskel-pos-be/internal/util"
|
|
|
|
"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
|
|
}
|
|
|
|
func NewSelfOrderHandler(
|
|
orderService service.OrderService,
|
|
productService service.ProductService,
|
|
customerRepo *repository.CustomerRepository,
|
|
userRepo *repository.UserRepositoryImpl,
|
|
outletRepo *repository.OutletRepositoryImpl,
|
|
) *SelfOrderHandler {
|
|
return &SelfOrderHandler{
|
|
orderService: orderService,
|
|
productService: productService,
|
|
customerRepo: customerRepo,
|
|
userRepo: userRepo,
|
|
outletRepo: outletRepo,
|
|
}
|
|
}
|
|
|
|
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 {
|
|
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
contract.NewResponseError(constants.InternalServerErrorCode, constants.SelfOrderEntity, "invalid organization ID"),
|
|
}), "SelfOrderHandler::GetMenu")
|
|
return
|
|
}
|
|
|
|
outletID, err := uuid.Parse(outletIDStr.(string))
|
|
if err != nil {
|
|
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
contract.NewResponseError(constants.InternalServerErrorCode, constants.SelfOrderEntity, "invalid outlet ID"),
|
|
}), "SelfOrderHandler::GetMenu")
|
|
return
|
|
}
|
|
|
|
tableID, _ := uuid.Parse(tableIDStr.(string))
|
|
|
|
isActive := true
|
|
req := &contract.ListProductsRequest{
|
|
OrganizationID: &organizationID,
|
|
IsActive: &isActive,
|
|
Page: 1,
|
|
Limit: 100,
|
|
}
|
|
|
|
productsResponse := h.productService.ListProducts(ctx, req)
|
|
|
|
outlet, outletErr := h.outletRepo.GetByID(ctx, outletID)
|
|
outletName := ""
|
|
if outletErr == nil && outlet != nil {
|
|
outletName = outlet.Name
|
|
}
|
|
|
|
menuResponse := &contract.SelfOrderMenuResponse{
|
|
OutletID: outletID,
|
|
OutletName: outletName,
|
|
TableID: tableID,
|
|
TableName: tableName.(string),
|
|
Organization: contract.OrganizationMenuInfo{
|
|
ID: organizationID,
|
|
},
|
|
}
|
|
|
|
if productsResponse != nil {
|
|
if data, ok := productsResponse.Data.(*contract.ListProductsResponse); ok {
|
|
menuResponse.Products = *data
|
|
}
|
|
}
|
|
|
|
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(menuResponse), "SelfOrderHandler::GetMenu")
|
|
}
|
|
|
|
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
|
|
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{
|
|
contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()),
|
|
}), "SelfOrderHandler::CreateOrder")
|
|
return
|
|
}
|
|
|
|
if req.CustomerName == "" {
|
|
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
contract.NewResponseError(constants.ValidationErrorCode, constants.SelfOrderEntity, "customer_name is required"),
|
|
}), "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)
|
|
if err != nil {
|
|
logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::CreateOrder -> failed to get admin user")
|
|
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
contract.NewResponseError(constants.InternalServerErrorCode, constants.SelfOrderEntity, "failed to resolve system user"),
|
|
}), "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
|
|
}
|
|
}
|
|
|
|
metadata := map[string]interface{}{
|
|
"source": string(constants.OrderSourceSelfOrder),
|
|
"customer_phone": "",
|
|
}
|
|
if req.PhoneNumber != nil {
|
|
metadata["customer_phone"] = *req.PhoneNumber
|
|
}
|
|
|
|
orderItems := make([]models.CreateOrderItemRequest, len(req.OrderItems))
|
|
for i, item := range req.OrderItems {
|
|
orderItems[i] = models.CreateOrderItemRequest{
|
|
ProductID: item.ProductID,
|
|
ProductVariantID: item.ProductVariantID,
|
|
Quantity: item.Quantity,
|
|
Notes: item.Notes,
|
|
}
|
|
}
|
|
|
|
tableNameStr := tableName.(string)
|
|
modelReq := &models.CreateOrderRequest{
|
|
OutletID: outletID,
|
|
UserID: adminUser.ID,
|
|
CustomerID: customerID,
|
|
TableID: &tableID,
|
|
TableNumber: &tableNameStr,
|
|
OrderType: constants.OrderTypeDineIn,
|
|
OrderItems: orderItems,
|
|
Notes: req.Notes,
|
|
CustomerName: &req.CustomerName,
|
|
Metadata: metadata,
|
|
}
|
|
|
|
response, err := h.orderService.CreateOrder(ctx, modelReq, 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()),
|
|
}), "SelfOrderHandler::CreateOrder")
|
|
return
|
|
}
|
|
|
|
outlet, _ := h.outletRepo.GetByID(ctx, outletID)
|
|
outletName := ""
|
|
if outlet != nil {
|
|
outletName = outlet.Name
|
|
}
|
|
|
|
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,
|
|
}
|
|
}
|
|
|
|
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")
|
|
}
|