145 lines
3.9 KiB
Go
145 lines
3.9 KiB
Go
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,
|
|
)
|
|
|
|
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
|
|
}
|