package order import ( "enaklo-pos-be/internal/common/errors" "enaklo-pos-be/internal/common/logger" "enaklo-pos-be/internal/common/mycontext" "enaklo-pos-be/internal/constants" "enaklo-pos-be/internal/entity" "go.uber.org/zap" ) func (s *orderSvc) CreateOrderInquiry(ctx mycontext.Context, req *entity.OrderRequest) (*entity.OrderInquiryResponse, error) { productIDs, filteredItems, err := s.validateOrderItems(ctx, req.OrderItems) if err != nil { return nil, err } req.OrderItems = filteredItems productDetails, err := s.product.GetProductDetails(ctx, productIDs, req.PartnerID) if err != nil { logger.ContextLogger(ctx).Error("failed to get product details", zap.Error(err)) return nil, err } orderCalculation, err := s.calculateOrderTotals(ctx, req.OrderItems, productDetails, req.Source) if err != nil { return nil, err } customerID, err := s.customer.ResolveCustomer(ctx, &entity.CustomerResolutionRequest{ ID: req.CustomerID, Name: req.CustomerName, Email: req.CustomerEmail, PhoneNumber: req.CustomerPhoneNumber, }) if err != nil { logger.ContextLogger(ctx).Error("failed to resolve customer", zap.Error(err)) return nil, err } inquiry := entity.NewOrderInquiry( req.PartnerID, customerID, orderCalculation.Subtotal, orderCalculation.Fee, orderCalculation.Total, req.PaymentMethod, req.Source, req.CreatedBy, req.CustomerName, req.CustomerPhoneNumber, req.CustomerEmail, req.PaymentProvider, req.TableNumber, req.OrderType, ) for _, item := range req.OrderItems { product := productDetails.Products[item.ProductID] inquiry.AddOrderItem(item, product) } savedInquiry, err := s.repo.CreateInquiry(ctx, inquiry) if err != nil { logger.ContextLogger(ctx).Error("failed to create order inquiry", zap.Error(err)) return nil, err } token, err := s.crypt.GenerateJWTOrderInquiry(savedInquiry) if err != nil { logger.ContextLogger(ctx).Error("failed to generate token", zap.Error(err)) return nil, err } return &entity.OrderInquiryResponse{ OrderInquiry: savedInquiry, Token: token, }, nil } func (s *orderSvc) validateOrderItems(ctx mycontext.Context, items []entity.OrderItemRequest) ([]int64, []entity.OrderItemRequest, error) { var productIDs []int64 var filteredItems []entity.OrderItemRequest for _, item := range items { if item.Quantity <= 0 { continue } productIDs = append(productIDs, item.ProductID) filteredItems = append(filteredItems, item) } if len(productIDs) == 0 { return nil, nil, errors.ErrorBadRequest } return productIDs, filteredItems, nil } func (s *orderSvc) calculateOrderTotals( ctx mycontext.Context, items []entity.OrderItemRequest, productDetails *entity.ProductDetails, source string, ) (*entity.OrderCalculation, error) { subtotal := 0.0 for _, item := range items { product, ok := productDetails.Products[item.ProductID] if !ok { return nil, errors.NewError(errors.ErrorInvalidRequest.ErrorType(), "product not found") } subtotal += product.Price * float64(item.Quantity) } fee := s.cfg.GetOrderFee(source) return &entity.OrderCalculation{ Subtotal: subtotal, Fee: fee, Total: subtotal + fee, }, nil } func (s *orderSvc) validateInquiry(ctx mycontext.Context, token string) (*entity.OrderInquiry, error) { partnerID, inquiryID, err := s.crypt.ValidateJWTOrderInquiry(token) if err != nil { return nil, errors.NewError(errors.ErrorInvalidRequest.ErrorType(), "inquiry is not valid or expired") } if partnerID != *ctx.GetPartnerID() { return nil, errors.NewError(errors.ErrorInvalidRequest.ErrorType(), "invalid request") } inquiry, err := s.repo.FindInquiryByID(ctx, inquiryID) if err != nil { logger.ContextLogger(ctx).Error("error when finding inquiry", zap.Error(err)) return nil, err } if inquiry.Status != constants.StatusPending { return nil, errors.NewError(errors.ErrorInvalidRequest.ErrorType(), "inquiry is no longer pending") } return inquiry, nil }