88 lines
2.7 KiB
Go
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
|
||
|
|
}
|