add product ingredients
This commit is contained in:
@@ -19,6 +19,7 @@ type IngredientUnitConverterService interface {
|
||||
ListIngredientUnitConverters(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.ListIngredientUnitConvertersRequest) *contract.Response
|
||||
GetConvertersForIngredient(ctx context.Context, apctx *appcontext.ContextInfo, ingredientID uuid.UUID) *contract.Response
|
||||
ConvertUnit(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.ConvertUnitRequest) *contract.Response
|
||||
GetUnitsByIngredientID(ctx context.Context, apctx *appcontext.ContextInfo, ingredientID uuid.UUID) *contract.Response
|
||||
}
|
||||
|
||||
type IngredientUnitConverterServiceImpl struct {
|
||||
@@ -149,3 +150,14 @@ func (s *IngredientUnitConverterServiceImpl) ConvertUnit(ctx context.Context, ap
|
||||
return contract.BuildSuccessResponse(contractResponse)
|
||||
}
|
||||
|
||||
func (s *IngredientUnitConverterServiceImpl) GetUnitsByIngredientID(ctx context.Context, apctx *appcontext.ContextInfo, ingredientID uuid.UUID) *contract.Response {
|
||||
unitsResponse, err := s.converterProcessor.GetUnitsByIngredientID(ctx, apctx.OrganizationID, ingredientID)
|
||||
if err != nil {
|
||||
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.IngredientUnitConverterServiceEntity, err.Error())
|
||||
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
||||
}
|
||||
|
||||
contractResponse := transformer.IngredientUnitsModelResponseToResponse(unitsResponse)
|
||||
return contract.BuildSuccessResponse(contractResponse)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/appcontext"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/mappers"
|
||||
"apskel-pos-be/internal/models"
|
||||
"apskel-pos-be/internal/processor"
|
||||
"apskel-pos-be/internal/repository"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type OrderIngredientTransactionService struct {
|
||||
processor processor.OrderIngredientTransactionProcessor
|
||||
txManager *repository.TxManager
|
||||
}
|
||||
|
||||
func NewOrderIngredientTransactionService(processor processor.OrderIngredientTransactionProcessor, txManager *repository.TxManager) *OrderIngredientTransactionService {
|
||||
return &OrderIngredientTransactionService{
|
||||
processor: processor,
|
||||
txManager: txManager,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) CreateOrderIngredientTransaction(ctx context.Context, req *contract.CreateOrderIngredientTransactionRequest) (*contract.OrderIngredientTransactionResponse, error) {
|
||||
// Get organization and outlet from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
outletID := appCtx.OutletID
|
||||
createdBy := appCtx.UserID
|
||||
|
||||
// Convert contract to model
|
||||
modelReq := mappers.ContractToModelCreateOrderIngredientTransactionRequest(req)
|
||||
|
||||
// Create transaction
|
||||
response, err := s.processor.CreateOrderIngredientTransaction(ctx, modelReq, organizationID, outletID, createdBy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create order ingredient transaction: %w", err)
|
||||
}
|
||||
|
||||
// Convert model to contract
|
||||
contractResp := mappers.ModelToContractOrderIngredientTransactionResponse(response)
|
||||
return contractResp, nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) GetOrderIngredientTransactionByID(ctx context.Context, id uuid.UUID) (*contract.OrderIngredientTransactionResponse, error) {
|
||||
// Get organization from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
|
||||
// Get transaction
|
||||
response, err := s.processor.GetOrderIngredientTransactionByID(ctx, id, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get order ingredient transaction: %w", err)
|
||||
}
|
||||
|
||||
// Convert model to contract
|
||||
contractResp := mappers.ModelToContractOrderIngredientTransactionResponse(response)
|
||||
return contractResp, nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) UpdateOrderIngredientTransaction(ctx context.Context, id uuid.UUID, req *contract.UpdateOrderIngredientTransactionRequest) (*contract.OrderIngredientTransactionResponse, error) {
|
||||
// Get organization from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
|
||||
// Convert contract to model
|
||||
modelReq := mappers.ContractToModelUpdateOrderIngredientTransactionRequest(req)
|
||||
|
||||
// Update transaction
|
||||
response, err := s.processor.UpdateOrderIngredientTransaction(ctx, id, modelReq, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update order ingredient transaction: %w", err)
|
||||
}
|
||||
|
||||
// Convert model to contract
|
||||
contractResp := mappers.ModelToContractOrderIngredientTransactionResponse(response)
|
||||
return contractResp, nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) DeleteOrderIngredientTransaction(ctx context.Context, id uuid.UUID) error {
|
||||
// Get organization from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
|
||||
// Delete transaction
|
||||
if err := s.processor.DeleteOrderIngredientTransaction(ctx, id, organizationID); err != nil {
|
||||
return fmt.Errorf("failed to delete order ingredient transaction: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) ListOrderIngredientTransactions(ctx context.Context, req *contract.ListOrderIngredientTransactionsRequest) ([]*contract.OrderIngredientTransactionResponse, int64, error) {
|
||||
// Get organization from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
|
||||
// Convert contract to model
|
||||
modelReq := mappers.ContractToModelListOrderIngredientTransactionsRequest(req)
|
||||
|
||||
// List transactions
|
||||
responses, total, err := s.processor.ListOrderIngredientTransactions(ctx, modelReq, organizationID)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to list order ingredient transactions: %w", err)
|
||||
}
|
||||
|
||||
// Convert models to contracts
|
||||
contractResponses := mappers.ModelToContractOrderIngredientTransactionResponses(responses)
|
||||
return contractResponses, total, nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) GetOrderIngredientTransactionsByOrder(ctx context.Context, orderID uuid.UUID) ([]*contract.OrderIngredientTransactionResponse, error) {
|
||||
// Get organization from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
|
||||
// Get transactions by order
|
||||
responses, err := s.processor.GetOrderIngredientTransactionsByOrder(ctx, orderID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get order ingredient transactions by order: %w", err)
|
||||
}
|
||||
|
||||
// Convert models to contracts
|
||||
contractResponses := mappers.ModelToContractOrderIngredientTransactionResponses(responses)
|
||||
return contractResponses, nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) GetOrderIngredientTransactionsByOrderItem(ctx context.Context, orderItemID uuid.UUID) ([]*contract.OrderIngredientTransactionResponse, error) {
|
||||
// Get organization from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
|
||||
// Get transactions by order item
|
||||
responses, err := s.processor.GetOrderIngredientTransactionsByOrderItem(ctx, orderItemID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get order ingredient transactions by order item: %w", err)
|
||||
}
|
||||
|
||||
// Convert models to contracts
|
||||
contractResponses := mappers.ModelToContractOrderIngredientTransactionResponses(responses)
|
||||
return contractResponses, nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) GetOrderIngredientTransactionsByIngredient(ctx context.Context, ingredientID uuid.UUID) ([]*contract.OrderIngredientTransactionResponse, error) {
|
||||
// Get organization from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
|
||||
// Get transactions by ingredient
|
||||
responses, err := s.processor.GetOrderIngredientTransactionsByIngredient(ctx, ingredientID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get order ingredient transactions by ingredient: %w", err)
|
||||
}
|
||||
|
||||
// Convert models to contracts
|
||||
contractResponses := mappers.ModelToContractOrderIngredientTransactionResponses(responses)
|
||||
return contractResponses, nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) GetOrderIngredientTransactionSummary(ctx context.Context, req *contract.ListOrderIngredientTransactionsRequest) ([]*contract.OrderIngredientTransactionSummary, error) {
|
||||
// Get organization from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
|
||||
// Convert contract to model
|
||||
modelReq := mappers.ContractToModelListOrderIngredientTransactionsRequest(req)
|
||||
|
||||
// Get summary
|
||||
summaries, err := s.processor.GetOrderIngredientTransactionSummary(ctx, modelReq, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get order ingredient transaction summary: %w", err)
|
||||
}
|
||||
|
||||
// Convert models to contracts
|
||||
contractSummaries := mappers.ModelToContractOrderIngredientTransactionSummaries(summaries)
|
||||
return contractSummaries, nil
|
||||
}
|
||||
|
||||
func (s *OrderIngredientTransactionService) BulkCreateOrderIngredientTransactions(ctx context.Context, transactions []*contract.CreateOrderIngredientTransactionRequest) ([]*contract.OrderIngredientTransactionResponse, error) {
|
||||
// Get organization and outlet from context
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
outletID := appCtx.OutletID
|
||||
createdBy := appCtx.UserID
|
||||
|
||||
// Convert contracts to models
|
||||
modelReqs := make([]*models.CreateOrderIngredientTransactionRequest, len(transactions))
|
||||
for i, req := range transactions {
|
||||
modelReqs[i] = mappers.ContractToModelCreateOrderIngredientTransactionRequest(req)
|
||||
}
|
||||
|
||||
// Bulk create transactions
|
||||
responses, err := s.processor.BulkCreateOrderIngredientTransactions(ctx, modelReqs, organizationID, outletID, createdBy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to bulk create order ingredient transactions: %w", err)
|
||||
}
|
||||
|
||||
// Convert models to contracts
|
||||
contractResponses := mappers.ModelToContractOrderIngredientTransactionResponses(responses)
|
||||
return contractResponses, nil
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/appcontext"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"apskel-pos-be/internal/contract"
|
||||
"apskel-pos-be/internal/entities"
|
||||
"apskel-pos-be/internal/models"
|
||||
"apskel-pos-be/internal/processor"
|
||||
"apskel-pos-be/internal/repository"
|
||||
"apskel-pos-be/internal/util"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@@ -27,14 +31,22 @@ type OrderService interface {
|
||||
}
|
||||
|
||||
type OrderServiceImpl struct {
|
||||
orderProcessor processor.OrderProcessor
|
||||
tableRepo repository.TableRepositoryInterface
|
||||
orderProcessor processor.OrderProcessor
|
||||
tableRepo repository.TableRepositoryInterface
|
||||
orderIngredientTransactionService *OrderIngredientTransactionService
|
||||
orderIngredientTransactionProcessor processor.OrderIngredientTransactionProcessor
|
||||
productIngredientRepo repository.ProductIngredientRepository
|
||||
txManager *repository.TxManager
|
||||
}
|
||||
|
||||
func NewOrderServiceImpl(orderProcessor processor.OrderProcessor, tableRepo repository.TableRepositoryInterface) *OrderServiceImpl {
|
||||
func NewOrderServiceImpl(orderProcessor processor.OrderProcessor, tableRepo repository.TableRepositoryInterface, orderIngredientTransactionService *OrderIngredientTransactionService, orderIngredientTransactionProcessor processor.OrderIngredientTransactionProcessor, productIngredientRepo repository.ProductIngredientRepository, txManager *repository.TxManager) *OrderServiceImpl {
|
||||
return &OrderServiceImpl{
|
||||
orderProcessor: orderProcessor,
|
||||
tableRepo: tableRepo,
|
||||
orderProcessor: orderProcessor,
|
||||
tableRepo: tableRepo,
|
||||
orderIngredientTransactionService: orderIngredientTransactionService,
|
||||
orderIngredientTransactionProcessor: orderIngredientTransactionProcessor,
|
||||
productIngredientRepo: productIngredientRepo,
|
||||
txManager: txManager,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,47 +61,133 @@ func (s *OrderServiceImpl) CreateOrder(ctx context.Context, req *models.CreateOr
|
||||
}
|
||||
}
|
||||
|
||||
response, err := s.orderProcessor.CreateOrder(ctx, req, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create order: %w", err)
|
||||
}
|
||||
var response *models.OrderResponse
|
||||
var ingredientTransactions []*contract.CreateOrderIngredientTransactionRequest
|
||||
|
||||
if req.TableID != nil {
|
||||
if err := s.occupyTableWithOrder(ctx, *req.TableID, response.ID); err != nil {
|
||||
fmt.Printf("Warning: failed to occupy table %s with order %s: %v\n", *req.TableID, response.ID, err)
|
||||
// Use transaction to ensure atomicity
|
||||
err := s.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
|
||||
// Create the order
|
||||
orderResp, err := s.orderProcessor.CreateOrder(txCtx, req, organizationID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create order: %w", err)
|
||||
}
|
||||
response = orderResp
|
||||
|
||||
// Create ingredient transactions for each order item
|
||||
ingredientTransactions, err = s.createIngredientTransactions(txCtx, response.ID, response.OrderItems)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create ingredient transactions: %w", err)
|
||||
}
|
||||
|
||||
// Bulk create ingredient transactions
|
||||
if len(ingredientTransactions) > 0 {
|
||||
_, err = s.orderIngredientTransactionService.BulkCreateOrderIngredientTransactions(txCtx, ingredientTransactions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to bulk create ingredient transactions: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Occupy table if specified
|
||||
if req.TableID != nil {
|
||||
if err := s.occupyTableWithOrder(txCtx, *req.TableID, response.ID); err != nil {
|
||||
// Log warning but don't fail the transaction
|
||||
fmt.Printf("Warning: failed to occupy table %s with order %s: %v\n", *req.TableID, response.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// createIngredientTransactions creates ingredient transactions for order items efficiently
|
||||
func (s *OrderServiceImpl) createIngredientTransactions(ctx context.Context, orderID uuid.UUID, orderItems []models.OrderItemResponse) ([]*contract.CreateOrderIngredientTransactionRequest, error) {
|
||||
appCtx := appcontext.FromGinContext(ctx)
|
||||
organizationID := appCtx.OrganizationID
|
||||
var allTransactions []*contract.CreateOrderIngredientTransactionRequest
|
||||
|
||||
for _, orderItem := range orderItems {
|
||||
// Get product ingredients for this product
|
||||
productIngredients, err := s.productIngredientRepo.GetByProductID(ctx, orderItem.ProductID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get product ingredients for product %s: %w", orderItem.ProductID, err)
|
||||
}
|
||||
|
||||
if len(productIngredients) == 0 {
|
||||
continue // Skip if no ingredients
|
||||
}
|
||||
|
||||
// Calculate waste quantities
|
||||
transactions, err := s.calculateWasteQuantities(productIngredients, float64(orderItem.Quantity))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to calculate waste quantities for product %s: %w", err)
|
||||
}
|
||||
|
||||
// Set common fields for all transactions
|
||||
for _, transaction := range transactions {
|
||||
transaction.OrderID = orderID
|
||||
transaction.OrderItemID = &orderItem.ID
|
||||
transaction.ProductID = orderItem.ProductID
|
||||
transaction.ProductVariantID = orderItem.ProductVariantID
|
||||
}
|
||||
|
||||
allTransactions = append(allTransactions, transactions...)
|
||||
}
|
||||
|
||||
return allTransactions, nil
|
||||
}
|
||||
|
||||
func (s *OrderServiceImpl) AddToOrder(ctx context.Context, orderID uuid.UUID, req *models.AddToOrderRequest) (*models.AddToOrderResponse, error) {
|
||||
// Validate inputs
|
||||
if orderID == uuid.Nil {
|
||||
return nil, fmt.Errorf("invalid order ID")
|
||||
}
|
||||
|
||||
// Validate request
|
||||
if err := s.validateAddToOrderRequest(req); err != nil {
|
||||
return nil, fmt.Errorf("validation error: %w", err)
|
||||
}
|
||||
|
||||
// Process adding items to order
|
||||
response, err := s.orderProcessor.AddToOrder(ctx, orderID, req)
|
||||
var response *models.AddToOrderResponse
|
||||
var ingredientTransactions []*contract.CreateOrderIngredientTransactionRequest
|
||||
|
||||
err := s.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
|
||||
addResp, err := s.orderProcessor.AddToOrder(txCtx, orderID, req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add items to order: %w", err)
|
||||
}
|
||||
response = addResp
|
||||
|
||||
ingredientTransactions, err = s.createIngredientTransactions(txCtx, orderID, response.AddedItems)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create ingredient transactions: %w", err)
|
||||
}
|
||||
|
||||
if len(ingredientTransactions) > 0 {
|
||||
_, err = s.orderIngredientTransactionService.BulkCreateOrderIngredientTransactions(txCtx, ingredientTransactions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to bulk create ingredient transactions: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to add items to order: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *OrderServiceImpl) UpdateOrder(ctx context.Context, id uuid.UUID, req *models.UpdateOrderRequest) (*models.OrderResponse, error) {
|
||||
// Validate request
|
||||
if err := s.validateUpdateOrderRequest(req); err != nil {
|
||||
return nil, fmt.Errorf("validation error: %w", err)
|
||||
}
|
||||
|
||||
// Process order update
|
||||
response, err := s.orderProcessor.UpdateOrder(ctx, id, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update order: %w", err)
|
||||
@@ -137,9 +235,7 @@ func (s *OrderServiceImpl) VoidOrder(ctx context.Context, req *models.VoidOrderR
|
||||
return fmt.Errorf("failed to void order: %w", err)
|
||||
}
|
||||
|
||||
// Release table if order is voided
|
||||
if err := s.handleTableReleaseOnVoid(ctx, req.OrderID); err != nil {
|
||||
// Log the error but don't fail the void operation
|
||||
fmt.Printf("Warning: failed to handle table release for voided order %s: %v\n", req.OrderID, err)
|
||||
}
|
||||
|
||||
@@ -547,3 +643,79 @@ func (s *OrderServiceImpl) handleTableReleaseOnVoid(ctx context.Context, orderID
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *OrderServiceImpl) createOrderIngredientTransactions(ctx context.Context, order *models.Order, orderItems []*models.OrderItem) error {
|
||||
for _, orderItem := range orderItems {
|
||||
productIngredients, err := s.productIngredientRepo.GetByProductID(ctx, orderItem.ProductID, order.OrganizationID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get product ingredients for product %s: %w", orderItem.ProductID, err)
|
||||
}
|
||||
|
||||
if len(productIngredients) == 0 {
|
||||
continue // Skip if no ingredients
|
||||
}
|
||||
|
||||
// Calculate waste quantities using the utility function
|
||||
transactions, err := s.calculateWasteQuantities(productIngredients, float64(orderItem.Quantity))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to calculate waste quantities for product %s: %w", orderItem.ProductID, err)
|
||||
}
|
||||
|
||||
// Set common fields for all transactions
|
||||
for _, transaction := range transactions {
|
||||
transaction.OrderID = order.ID
|
||||
transaction.OrderItemID = &orderItem.ID
|
||||
transaction.ProductID = orderItem.ProductID
|
||||
transaction.ProductVariantID = orderItem.ProductVariantID
|
||||
}
|
||||
|
||||
// Bulk create transactions
|
||||
if len(transactions) > 0 {
|
||||
_, err := s.orderIngredientTransactionService.BulkCreateOrderIngredientTransactions(ctx, transactions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create order ingredient transactions for product %s: %w", orderItem.ProductID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// calculateWasteQuantities calculates gross, net, and waste quantities for product ingredients
|
||||
func (s *OrderServiceImpl) calculateWasteQuantities(productIngredients []*entities.ProductIngredient, quantity float64) ([]*contract.CreateOrderIngredientTransactionRequest, error) {
|
||||
if len(productIngredients) == 0 {
|
||||
return []*contract.CreateOrderIngredientTransactionRequest{}, nil
|
||||
}
|
||||
|
||||
transactions := make([]*contract.CreateOrderIngredientTransactionRequest, 0, len(productIngredients))
|
||||
|
||||
for _, pi := range productIngredients {
|
||||
// Calculate net quantity (actual quantity needed for the product)
|
||||
netQty := pi.Quantity * quantity
|
||||
|
||||
// Calculate gross quantity (including waste)
|
||||
wasteMultiplier := 1 + (pi.WastePercentage / 100)
|
||||
grossQty := netQty * wasteMultiplier
|
||||
|
||||
// Calculate waste quantity
|
||||
wasteQty := grossQty - netQty
|
||||
|
||||
// Get unit name from ingredient
|
||||
unitName := "unit" // default
|
||||
if pi.Ingredient != nil && pi.Ingredient.Unit != nil {
|
||||
unitName = pi.Ingredient.Unit.Name
|
||||
}
|
||||
|
||||
transaction := &contract.CreateOrderIngredientTransactionRequest{
|
||||
IngredientID: pi.IngredientID,
|
||||
GrossQty: util.RoundToDecimalPlaces(grossQty, 3),
|
||||
NetQty: util.RoundToDecimalPlaces(netQty, 3),
|
||||
WasteQty: util.RoundToDecimalPlaces(wasteQty, 3),
|
||||
Unit: unitName,
|
||||
}
|
||||
|
||||
transactions = append(transactions, transaction)
|
||||
}
|
||||
|
||||
return transactions, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user