Compare commits
No commits in common. "4cc563f6f11f6957030c7b84a1bdc6350d42f6b7" and "3c103b7692c1444fcd4c1a411cbedd98bb01621e" have entirely different histories.
4cc563f6f1
...
3c103b7692
@ -55,7 +55,6 @@ func (a *App) Initialize(cfg *config.Config) error {
|
|||||||
repos.outletRepo,
|
repos.outletRepo,
|
||||||
repos.userRepo,
|
repos.userRepo,
|
||||||
repos.sessionRepo,
|
repos.sessionRepo,
|
||||||
repos.orderRepo,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
a.router = router.NewRouter(
|
a.router = router.NewRouter(
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
package contract
|
package contract
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +15,7 @@ type SelfOrderTableTokenResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SelfOrderMenuRequest struct {
|
type SelfOrderMenuRequest struct {
|
||||||
SessionID string `form:"session_id" validate:"required"`
|
SessionID string `json:"session_id" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SelfOrderMenuResponse struct {
|
type SelfOrderMenuResponse struct {
|
||||||
@ -62,8 +60,7 @@ type SelfOrderCreateOrderItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SelfOrderListCategoriesRequest struct {
|
type SelfOrderListCategoriesRequest struct {
|
||||||
OrganizationID string `form:"organisasi_id" validate:"required"`
|
SessionID string `form:"session_id" validate:"required"`
|
||||||
OutletID string `form:"outlet_id" validate:"required"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SelfOrderCategoryItem struct {
|
type SelfOrderCategoryItem struct {
|
||||||
@ -76,37 +73,3 @@ type SelfOrderCategoryItem struct {
|
|||||||
type SelfOrderListCategoriesResponse struct {
|
type SelfOrderListCategoriesResponse struct {
|
||||||
Categories []SelfOrderCategoryItem `json:"categories"`
|
Categories []SelfOrderCategoryItem `json:"categories"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SelfOrderListOrdersResponse struct {
|
|
||||||
Orders []SelfOrderOrderItem `json:"orders"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SelfOrderOrderItem struct {
|
|
||||||
ID uuid.UUID `json:"id"`
|
|
||||||
OrderNumber string `json:"order_number"`
|
|
||||||
TableNumber *string `json:"table_number,omitempty"`
|
|
||||||
OrderType string `json:"order_type"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
Subtotal float64 `json:"subtotal"`
|
|
||||||
TaxAmount float64 `json:"tax_amount"`
|
|
||||||
DiscountAmount float64 `json:"discount_amount"`
|
|
||||||
TotalAmount float64 `json:"total_amount"`
|
|
||||||
RemainingAmount float64 `json:"remaining_amount"`
|
|
||||||
PaymentStatus string `json:"payment_status"`
|
|
||||||
IsVoid bool `json:"is_void"`
|
|
||||||
IsRefund bool `json:"is_refund"`
|
|
||||||
Items []SelfOrderOrderLineItem `json:"items,omitempty"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SelfOrderOrderLineItem struct {
|
|
||||||
ProductID uuid.UUID `json:"product_id"`
|
|
||||||
ProductName string `json:"product_name"`
|
|
||||||
ProductVariantID *uuid.UUID `json:"product_variant_id,omitempty"`
|
|
||||||
ProductVariantNam *string `json:"product_variant_name,omitempty"`
|
|
||||||
Quantity int `json:"quantity"`
|
|
||||||
UnitPrice float64 `json:"unit_price"`
|
|
||||||
TotalPrice float64 `json:"total_price"`
|
|
||||||
Notes *string `json:"notes,omitempty"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
}
|
|
||||||
|
|||||||
@ -27,7 +27,6 @@ type SelfOrderHandler struct {
|
|||||||
outletRepo processor.OutletRepository
|
outletRepo processor.OutletRepository
|
||||||
userRepo processor.UserRepository
|
userRepo processor.UserRepository
|
||||||
sessionRepo repository.SessionRepository
|
sessionRepo repository.SessionRepository
|
||||||
orderRepo repository.OrderRepository
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSelfOrderHandler(
|
func NewSelfOrderHandler(
|
||||||
@ -38,7 +37,6 @@ func NewSelfOrderHandler(
|
|||||||
outletRepo processor.OutletRepository,
|
outletRepo processor.OutletRepository,
|
||||||
userRepo processor.UserRepository,
|
userRepo processor.UserRepository,
|
||||||
sessionRepo repository.SessionRepository,
|
sessionRepo repository.SessionRepository,
|
||||||
orderRepo repository.OrderRepository,
|
|
||||||
) *SelfOrderHandler {
|
) *SelfOrderHandler {
|
||||||
return &SelfOrderHandler{
|
return &SelfOrderHandler{
|
||||||
orderService: orderService,
|
orderService: orderService,
|
||||||
@ -48,7 +46,6 @@ func NewSelfOrderHandler(
|
|||||||
outletRepo: outletRepo,
|
outletRepo: outletRepo,
|
||||||
userRepo: userRepo,
|
userRepo: userRepo,
|
||||||
sessionRepo: sessionRepo,
|
sessionRepo: sessionRepo,
|
||||||
orderRepo: orderRepo,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,8 +150,8 @@ func (h *SelfOrderHandler) GetMenu(c *gin.Context) {
|
|||||||
ctx := c.Request.Context()
|
ctx := c.Request.Context()
|
||||||
|
|
||||||
var req contract.SelfOrderMenuRequest
|
var req contract.SelfOrderMenuRequest
|
||||||
if err := c.ShouldBindQuery(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::GetMenu -> query binding failed")
|
logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::GetMenu -> request binding failed")
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
||||||
contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()),
|
contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()),
|
||||||
}), "SelfOrderHandler::GetMenu")
|
}), "SelfOrderHandler::GetMenu")
|
||||||
@ -355,85 +352,6 @@ func (h *SelfOrderHandler) CreateOrder(c *gin.Context) {
|
|||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "SelfOrderHandler::CreateOrder")
|
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(contractResp), "SelfOrderHandler::CreateOrder")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *SelfOrderHandler) GetOrdersBySession(c *gin.Context) {
|
|
||||||
ctx := c.Request.Context()
|
|
||||||
sessionID := c.Param("sessionId")
|
|
||||||
|
|
||||||
if sessionID == "" {
|
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
||||||
contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "session_id is required"),
|
|
||||||
}), "SelfOrderHandler::GetOrdersBySession")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
session, err := h.sessionRepo.GetByID(ctx, sessionID)
|
|
||||||
if err != nil {
|
|
||||||
logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::GetOrdersBySession -> failed to get session")
|
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
||||||
contract.NewResponseError(constants.NotFoundErrorCode, constants.RequestEntity, "session not found"),
|
|
||||||
}), "SelfOrderHandler::GetOrdersBySession")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if session == nil {
|
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
||||||
contract.NewResponseError(constants.NotFoundErrorCode, constants.RequestEntity, "session not found"),
|
|
||||||
}), "SelfOrderHandler::GetOrdersBySession")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
orders, err := h.orderRepo.ListBySessionID(ctx, sessionID)
|
|
||||||
if err != nil {
|
|
||||||
logger.FromContext(ctx).WithError(err).Error("SelfOrderHandler::GetOrdersBySession -> failed to list orders")
|
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
||||||
contract.NewResponseError(constants.InternalServerErrorCode, constants.OrderServiceEntity, "failed to list orders"),
|
|
||||||
}), "SelfOrderHandler::GetOrdersBySession")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := &contract.SelfOrderListOrdersResponse{
|
|
||||||
Orders: make([]contract.SelfOrderOrderItem, 0, len(orders)),
|
|
||||||
}
|
|
||||||
for _, o := range orders {
|
|
||||||
item := contract.SelfOrderOrderItem{
|
|
||||||
ID: o.ID,
|
|
||||||
OrderNumber: o.OrderNumber,
|
|
||||||
TableNumber: o.TableNumber,
|
|
||||||
OrderType: string(o.OrderType),
|
|
||||||
Status: string(o.Status),
|
|
||||||
Subtotal: o.Subtotal,
|
|
||||||
TaxAmount: o.TaxAmount,
|
|
||||||
DiscountAmount: o.DiscountAmount,
|
|
||||||
TotalAmount: o.TotalAmount,
|
|
||||||
RemainingAmount: o.RemainingAmount,
|
|
||||||
PaymentStatus: string(o.PaymentStatus),
|
|
||||||
IsVoid: o.IsVoid,
|
|
||||||
IsRefund: o.IsRefund,
|
|
||||||
CreatedAt: o.CreatedAt,
|
|
||||||
}
|
|
||||||
for _, oi := range o.OrderItems {
|
|
||||||
lineItem := contract.SelfOrderOrderLineItem{
|
|
||||||
ProductID: oi.ProductID,
|
|
||||||
Quantity: oi.Quantity,
|
|
||||||
UnitPrice: oi.UnitPrice,
|
|
||||||
TotalPrice: oi.TotalPrice,
|
|
||||||
Notes: oi.Notes,
|
|
||||||
Status: string(oi.Status),
|
|
||||||
ProductVariantID: oi.ProductVariantID,
|
|
||||||
}
|
|
||||||
if oi.Product.ID != uuid.Nil {
|
|
||||||
lineItem.ProductName = oi.Product.Name
|
|
||||||
}
|
|
||||||
if oi.ProductVariant != nil {
|
|
||||||
lineItem.ProductVariantNam = &oi.ProductVariant.Name
|
|
||||||
}
|
|
||||||
item.Items = append(item.Items, lineItem)
|
|
||||||
}
|
|
||||||
resp.Orders = append(resp.Orders, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(resp), "SelfOrderHandler::GetOrdersBySession")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *SelfOrderHandler) validateCreateOrderRequest(req *contract.SelfOrderCreateOrderRequest) error {
|
func (h *SelfOrderHandler) validateCreateOrderRequest(req *contract.SelfOrderCreateOrderRequest) error {
|
||||||
if req.SessionID == "" {
|
if req.SessionID == "" {
|
||||||
return fmt.Errorf("session_id is required")
|
return fmt.Errorf("session_id is required")
|
||||||
@ -464,53 +382,29 @@ func (h *SelfOrderHandler) ListCategories(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.OrganizationID == "" {
|
if req.SessionID == "" {
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
||||||
contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "organisasi_id is required"),
|
contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "session_id is required"),
|
||||||
}), "SelfOrderHandler::ListCategories")
|
}), "SelfOrderHandler::ListCategories")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.OutletID == "" {
|
session, table, _, err := h.resolveSession(ctx, req.SessionID)
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
||||||
contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, "outlet_id is required"),
|
|
||||||
}), "SelfOrderHandler::ListCategories")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
orgID, err := uuid.Parse(req.OrganizationID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
||||||
contract.NewResponseError(constants.ValidationErrorCode, constants.RequestEntity, "invalid organisasi_id format"),
|
contract.NewResponseError(constants.ValidationErrorCode, constants.RequestEntity, err.Error()),
|
||||||
}), "SelfOrderHandler::ListCategories")
|
}), "SelfOrderHandler::ListCategories")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if session == nil {
|
||||||
outletID, err := uuid.Parse(req.OutletID)
|
|
||||||
if err != nil {
|
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
||||||
contract.NewResponseError(constants.ValidationErrorCode, constants.RequestEntity, "invalid outlet_id format"),
|
contract.NewResponseError(constants.NotFoundErrorCode, constants.RequestEntity, "session not found or expired"),
|
||||||
}), "SelfOrderHandler::ListCategories")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
outlet, err := h.outletRepo.GetByID(ctx, outletID)
|
|
||||||
if err != nil || outlet == nil {
|
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
||||||
contract.NewResponseError(constants.NotFoundErrorCode, constants.RequestEntity, "outlet not found"),
|
|
||||||
}), "SelfOrderHandler::ListCategories")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if outlet.OrganizationID != orgID {
|
|
||||||
util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{
|
|
||||||
contract.NewResponseError(constants.ValidationErrorCode, constants.RequestEntity, "outlet does not belong to the specified organization"),
|
|
||||||
}), "SelfOrderHandler::ListCategories")
|
}), "SelfOrderHandler::ListCategories")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
catResp := h.categoryService.ListCategories(ctx, &contract.ListCategoriesRequest{
|
catResp := h.categoryService.ListCategories(ctx, &contract.ListCategoriesRequest{
|
||||||
OrganizationID: &orgID,
|
OrganizationID: &table.OrganizationID,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
Limit: 100,
|
Limit: 100,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -18,7 +18,6 @@ type OrderRepository interface {
|
|||||||
Update(ctx context.Context, order *entities.Order) error
|
Update(ctx context.Context, order *entities.Order) error
|
||||||
Delete(ctx context.Context, id uuid.UUID) error
|
Delete(ctx context.Context, id uuid.UUID) error
|
||||||
List(ctx context.Context, filters map[string]interface{}, limit, offset int) ([]*entities.Order, int64, error)
|
List(ctx context.Context, filters map[string]interface{}, limit, offset int) ([]*entities.Order, int64, error)
|
||||||
ListBySessionID(ctx context.Context, sessionID string) ([]*entities.Order, error)
|
|
||||||
GetByOrderNumber(ctx context.Context, orderNumber string) (*entities.Order, error)
|
GetByOrderNumber(ctx context.Context, orderNumber string) (*entities.Order, error)
|
||||||
ExistsByOrderNumber(ctx context.Context, orderNumber string) (bool, error)
|
ExistsByOrderNumber(ctx context.Context, orderNumber string) (bool, error)
|
||||||
VoidOrder(ctx context.Context, id uuid.UUID, reason string, voidedBy uuid.UUID) error
|
VoidOrder(ctx context.Context, id uuid.UUID, reason string, voidedBy uuid.UUID) error
|
||||||
@ -131,24 +130,6 @@ func (r *OrderRepositoryImpl) List(ctx context.Context, filters map[string]inter
|
|||||||
return orders, total, err
|
return orders, total, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OrderRepositoryImpl) ListBySessionID(ctx context.Context, sessionID string) ([]*entities.Order, error) {
|
|
||||||
var orders []*entities.Order
|
|
||||||
err := r.db.WithContext(ctx).Model(&entities.Order{}).
|
|
||||||
Preload("Organization").
|
|
||||||
Preload("Outlet").
|
|
||||||
Preload("User").
|
|
||||||
Preload("OrderItems").
|
|
||||||
Preload("OrderItems.Product").
|
|
||||||
Preload("OrderItems.ProductVariant").
|
|
||||||
Preload("Payments").
|
|
||||||
Preload("Payments.PaymentMethod").
|
|
||||||
Preload("Payments.PaymentOrderItems").
|
|
||||||
Where("metadata->>'session_id' = ?", sessionID).
|
|
||||||
Order("created_at ASC").
|
|
||||||
Find(&orders).Error
|
|
||||||
return orders, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *OrderRepositoryImpl) GetByOrderNumber(ctx context.Context, orderNumber string) (*entities.Order, error) {
|
func (r *OrderRepositoryImpl) GetByOrderNumber(ctx context.Context, orderNumber string) (*entities.Order, error) {
|
||||||
var order entities.Order
|
var order entities.Order
|
||||||
err := r.db.WithContext(ctx).First(&order, "order_number = ?", orderNumber).Error
|
err := r.db.WithContext(ctx).First(&order, "order_number = ?", orderNumber).Error
|
||||||
|
|||||||
@ -151,9 +151,8 @@ func (r *Router) addAppRoutes(rg *gin.Engine) {
|
|||||||
{
|
{
|
||||||
selfOrder.GET("/table/:token", r.selfOrderHandler.ValidateToken)
|
selfOrder.GET("/table/:token", r.selfOrderHandler.ValidateToken)
|
||||||
selfOrder.GET("/categories", r.selfOrderHandler.ListCategories)
|
selfOrder.GET("/categories", r.selfOrderHandler.ListCategories)
|
||||||
selfOrder.GET("/menu", r.selfOrderHandler.GetMenu)
|
selfOrder.POST("/menu", r.selfOrderHandler.GetMenu)
|
||||||
selfOrder.POST("/orders", r.selfOrderHandler.CreateOrder)
|
selfOrder.POST("/orders", r.selfOrderHandler.CreateOrder)
|
||||||
selfOrder.GET("/orders/:sessionId", r.selfOrderHandler.GetOrdersBySession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
organizations := v1.Group("/organizations")
|
organizations := v1.Group("/organizations")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user