2025-09-12 15:37:19 +07:00

88 lines
2.7 KiB
Go

package util
import (
"apskel-pos-be/internal/entities"
"apskel-pos-be/internal/models"
"fmt"
"time"
"github.com/google/uuid"
)
// CalculateWasteQuantities calculates gross, net, and waste quantities for product ingredients
func CalculateWasteQuantities(productIngredients []*entities.ProductIngredient, quantity float64) ([]*models.CreateOrderIngredientTransactionRequest, error) {
if len(productIngredients) == 0 {
return []*models.CreateOrderIngredientTransactionRequest{}, nil
}
transactions := make([]*models.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 := &models.CreateOrderIngredientTransactionRequest{
IngredientID: pi.IngredientID,
GrossQty: RoundToDecimalPlaces(grossQty, 3),
NetQty: RoundToDecimalPlaces(netQty, 3),
WasteQty: RoundToDecimalPlaces(wasteQty, 3),
Unit: unitName,
}
transactions = append(transactions, transaction)
}
return transactions, nil
}
// CreateOrderIngredientTransactionsFromProduct creates order ingredient transactions for a product
func CreateOrderIngredientTransactionsFromProduct(
productID uuid.UUID,
productVariantID *uuid.UUID,
orderID uuid.UUID,
orderItemID *uuid.UUID,
quantity float64,
productIngredients []*entities.ProductIngredient,
organizationID, outletID, createdBy uuid.UUID,
) ([]*models.CreateOrderIngredientTransactionRequest, error) {
// Calculate waste quantities
wasteTransactions, err := CalculateWasteQuantities(productIngredients, quantity)
if err != nil {
return nil, fmt.Errorf("failed to calculate waste quantities: %w", err)
}
// Set common fields for all transactions
for _, transaction := range wasteTransactions {
transaction.OrderID = orderID
transaction.OrderItemID = orderItemID
transaction.ProductID = productID
transaction.ProductVariantID = productVariantID
transaction.TransactionDate = &time.Time{}
*transaction.TransactionDate = time.Now()
}
return wasteTransactions, nil
}
// RoundToDecimalPlaces rounds a float64 to the specified number of decimal places
func RoundToDecimalPlaces(value float64, places int) float64 {
multiplier := 1.0
for i := 0; i < places; i++ {
multiplier *= 10
}
return float64(int(value*multiplier+0.5)) / multiplier
}