fix
This commit is contained in:
@@ -28,20 +28,20 @@ type OrderIngredientTransactionProcessor interface {
|
||||
|
||||
type OrderIngredientTransactionProcessorImpl struct {
|
||||
orderIngredientTransactionRepo OrderIngredientTransactionRepository
|
||||
productIngredientRepo ProductIngredientRepository
|
||||
productRecipeRepo ProductRecipeRepository
|
||||
ingredientRepo IngredientRepository
|
||||
unitRepo UnitRepository
|
||||
}
|
||||
|
||||
func NewOrderIngredientTransactionProcessorImpl(
|
||||
orderIngredientTransactionRepo OrderIngredientTransactionRepository,
|
||||
productIngredientRepo ProductIngredientRepository,
|
||||
productRecipeRepo ProductRecipeRepository,
|
||||
ingredientRepo IngredientRepository,
|
||||
unitRepo UnitRepository,
|
||||
) OrderIngredientTransactionProcessor {
|
||||
return &OrderIngredientTransactionProcessorImpl{
|
||||
orderIngredientTransactionRepo: orderIngredientTransactionRepo,
|
||||
productIngredientRepo: productIngredientRepo,
|
||||
productRecipeRepo: productRecipeRepo,
|
||||
ingredientRepo: ingredientRepo,
|
||||
unitRepo: unitRepo,
|
||||
}
|
||||
@@ -334,36 +334,36 @@ func (p *OrderIngredientTransactionProcessorImpl) BulkCreateOrderIngredientTrans
|
||||
}
|
||||
|
||||
func (p *OrderIngredientTransactionProcessorImpl) CalculateWasteQuantities(ctx context.Context, productID uuid.UUID, quantity float64, organizationID uuid.UUID) ([]*models.CreateOrderIngredientTransactionRequest, error) {
|
||||
// Get product ingredients
|
||||
productIngredients, err := p.productIngredientRepo.GetByProductID(ctx, productID, organizationID)
|
||||
// Get product recipes
|
||||
productRecipes, err := p.productRecipeRepo.GetByProductID(ctx, productID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get product ingredients: %w", err)
|
||||
return nil, fmt.Errorf("failed to get product recipes: %w", err)
|
||||
}
|
||||
|
||||
if len(productIngredients) == 0 {
|
||||
if len(productRecipes) == 0 {
|
||||
return []*models.CreateOrderIngredientTransactionRequest{}, nil
|
||||
}
|
||||
|
||||
// Get ingredient details for unit information
|
||||
ingredientMap := make(map[uuid.UUID]*entities.Ingredient)
|
||||
for _, pi := range productIngredients {
|
||||
ingredient, err := p.ingredientRepo.GetByID(ctx, pi.IngredientID, organizationID)
|
||||
for _, pr := range productRecipes {
|
||||
ingredient, err := p.ingredientRepo.GetByID(ctx, pr.IngredientID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get ingredient %s: %w", pi.IngredientID, err)
|
||||
return nil, fmt.Errorf("failed to get ingredient %s: %w", pr.IngredientID, err)
|
||||
}
|
||||
ingredientMap[pi.IngredientID] = ingredient
|
||||
ingredientMap[pr.IngredientID] = ingredient
|
||||
}
|
||||
|
||||
// Calculate quantities for each ingredient
|
||||
transactions := make([]*models.CreateOrderIngredientTransactionRequest, 0, len(productIngredients))
|
||||
for _, pi := range productIngredients {
|
||||
ingredient := ingredientMap[pi.IngredientID]
|
||||
transactions := make([]*models.CreateOrderIngredientTransactionRequest, 0, len(productRecipes))
|
||||
for _, pr := range productRecipes {
|
||||
ingredient := ingredientMap[pr.IngredientID]
|
||||
|
||||
// Calculate net quantity (actual quantity needed for the product)
|
||||
netQty := pi.Quantity * quantity
|
||||
netQty := pr.Quantity * quantity
|
||||
|
||||
// Calculate gross quantity (including waste)
|
||||
wasteMultiplier := 1 + (pi.WastePercentage / 100)
|
||||
wasteMultiplier := 1 + (pr.WastePercentage / 100)
|
||||
grossQty := netQty * wasteMultiplier
|
||||
|
||||
// Calculate waste quantity
|
||||
@@ -379,7 +379,7 @@ func (p *OrderIngredientTransactionProcessorImpl) CalculateWasteQuantities(ctx c
|
||||
}
|
||||
|
||||
transaction := &models.CreateOrderIngredientTransactionRequest{
|
||||
IngredientID: pi.IngredientID,
|
||||
IngredientID: pr.IngredientID,
|
||||
GrossQty: util.RoundToDecimalPlaces(grossQty, 3),
|
||||
NetQty: util.RoundToDecimalPlaces(netQty, 3),
|
||||
WasteQty: util.RoundToDecimalPlaces(wasteQty, 3),
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
package processor
|
||||
|
||||
import (
|
||||
"apskel-pos-be/internal/constants"
|
||||
"apskel-pos-be/internal/contract"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"apskel-pos-be/internal/entities"
|
||||
"apskel-pos-be/internal/models"
|
||||
"apskel-pos-be/internal/repository"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ProductRecipeProcessor interface {
|
||||
Create(ctx context.Context, req *models.CreateProductRecipeRequest, organizationID uuid.UUID) (*models.ProductRecipeResponse, error)
|
||||
GetByID(ctx context.Context, id uuid.UUID, organizationID uuid.UUID) (*models.ProductRecipeResponse, error)
|
||||
GetByProductID(ctx context.Context, productID uuid.UUID, organizationID uuid.UUID) ([]*models.ProductRecipeResponse, error)
|
||||
GetByProductAndVariantID(ctx context.Context, productID uuid.UUID, variantID *uuid.UUID, organizationID uuid.UUID) ([]*models.ProductRecipeResponse, error)
|
||||
GetByIngredientID(ctx context.Context, ingredientID uuid.UUID, organizationID uuid.UUID) ([]*models.ProductRecipeResponse, error)
|
||||
Update(ctx context.Context, id uuid.UUID, req *models.UpdateProductRecipeRequest, organizationID uuid.UUID) (*models.ProductRecipeResponse, error)
|
||||
Create(ctx context.Context, req *contract.CreateProductRecipeRequest, organizationID uuid.UUID) (*contract.ProductRecipeResponse, error)
|
||||
GetByID(ctx context.Context, id uuid.UUID, organizationID uuid.UUID) (*contract.ProductRecipeResponse, error)
|
||||
GetByProductID(ctx context.Context, productID uuid.UUID, organizationID uuid.UUID) ([]*contract.ProductRecipeResponse, error)
|
||||
GetByProductAndVariantID(ctx context.Context, productID uuid.UUID, variantID *uuid.UUID, organizationID uuid.UUID) ([]*contract.ProductRecipeResponse, error)
|
||||
GetByIngredientID(ctx context.Context, ingredientID uuid.UUID, organizationID uuid.UUID) ([]*contract.ProductRecipeResponse, error)
|
||||
Update(ctx context.Context, id uuid.UUID, req *contract.UpdateProductRecipeRequest, organizationID uuid.UUID) (*contract.ProductRecipeResponse, error)
|
||||
Delete(ctx context.Context, id uuid.UUID, organizationID uuid.UUID) error
|
||||
BulkCreate(ctx context.Context, recipes []models.CreateProductRecipeRequest, organizationID uuid.UUID) ([]*models.ProductRecipeResponse, error)
|
||||
BulkCreate(ctx context.Context, recipes []contract.CreateProductRecipeRequest, organizationID uuid.UUID) ([]*contract.ProductRecipeResponse, error)
|
||||
}
|
||||
|
||||
type ProductRecipeProcessorImpl struct {
|
||||
@@ -38,7 +37,7 @@ func NewProductRecipeProcessor(productRecipeRepo *repository.ProductRecipeReposi
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProductRecipeProcessorImpl) Create(ctx context.Context, req *models.CreateProductRecipeRequest, organizationID uuid.UUID) (*models.ProductRecipeResponse, error) {
|
||||
func (p *ProductRecipeProcessorImpl) Create(ctx context.Context, req *contract.CreateProductRecipeRequest, organizationID uuid.UUID) (*contract.ProductRecipeResponse, error) {
|
||||
_, err := p.productRepo.GetByID(ctx, req.ProductID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid product: %w", err)
|
||||
@@ -50,15 +49,16 @@ func (p *ProductRecipeProcessorImpl) Create(ctx context.Context, req *models.Cre
|
||||
}
|
||||
|
||||
entity := &entities.ProductRecipe{
|
||||
ID: uuid.New(),
|
||||
OrganizationID: organizationID,
|
||||
OutletID: req.OutletID,
|
||||
ProductID: req.ProductID,
|
||||
VariantID: req.VariantID,
|
||||
IngredientID: req.IngredientID,
|
||||
Quantity: req.Quantity,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
ID: uuid.New(),
|
||||
OrganizationID: organizationID,
|
||||
OutletID: req.OutletID,
|
||||
ProductID: req.ProductID,
|
||||
VariantID: req.VariantID,
|
||||
IngredientID: req.IngredientID,
|
||||
Quantity: req.Quantity,
|
||||
WastePercentage: req.WastePercentage,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
}
|
||||
|
||||
if err := p.productRecipeRepo.Create(ctx, entity); err != nil {
|
||||
@@ -73,7 +73,7 @@ func (p *ProductRecipeProcessorImpl) Create(ctx context.Context, req *models.Cre
|
||||
return p.entityToResponse(createdEntity), nil
|
||||
}
|
||||
|
||||
func (p *ProductRecipeProcessorImpl) GetByID(ctx context.Context, id uuid.UUID, organizationID uuid.UUID) (*models.ProductRecipeResponse, error) {
|
||||
func (p *ProductRecipeProcessorImpl) GetByID(ctx context.Context, id uuid.UUID, organizationID uuid.UUID) (*contract.ProductRecipeResponse, error) {
|
||||
entity, err := p.productRecipeRepo.GetByID(ctx, id, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get product recipe: %w", err)
|
||||
@@ -82,13 +82,13 @@ func (p *ProductRecipeProcessorImpl) GetByID(ctx context.Context, id uuid.UUID,
|
||||
return p.entityToResponse(entity), nil
|
||||
}
|
||||
|
||||
func (p *ProductRecipeProcessorImpl) GetByProductID(ctx context.Context, productID uuid.UUID, organizationID uuid.UUID) ([]*models.ProductRecipeResponse, error) {
|
||||
func (p *ProductRecipeProcessorImpl) GetByProductID(ctx context.Context, productID uuid.UUID, organizationID uuid.UUID) ([]*contract.ProductRecipeResponse, error) {
|
||||
entities, err := p.productRecipeRepo.GetByProductID(ctx, productID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get product recipes by product ID: %w", err)
|
||||
}
|
||||
|
||||
responses := make([]*models.ProductRecipeResponse, len(entities))
|
||||
responses := make([]*contract.ProductRecipeResponse, len(entities))
|
||||
for i, entity := range entities {
|
||||
responses[i] = p.entityToResponse(entity)
|
||||
}
|
||||
@@ -96,13 +96,13 @@ func (p *ProductRecipeProcessorImpl) GetByProductID(ctx context.Context, product
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
func (p *ProductRecipeProcessorImpl) GetByProductAndVariantID(ctx context.Context, productID uuid.UUID, variantID *uuid.UUID, organizationID uuid.UUID) ([]*models.ProductRecipeResponse, error) {
|
||||
func (p *ProductRecipeProcessorImpl) GetByProductAndVariantID(ctx context.Context, productID uuid.UUID, variantID *uuid.UUID, organizationID uuid.UUID) ([]*contract.ProductRecipeResponse, error) {
|
||||
entities, err := p.productRecipeRepo.GetByProductAndVariantID(ctx, productID, variantID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get product recipes by product and variant ID: %w", err)
|
||||
}
|
||||
|
||||
responses := make([]*models.ProductRecipeResponse, len(entities))
|
||||
responses := make([]*contract.ProductRecipeResponse, len(entities))
|
||||
for i, entity := range entities {
|
||||
responses[i] = p.entityToResponse(entity)
|
||||
}
|
||||
@@ -110,13 +110,13 @@ func (p *ProductRecipeProcessorImpl) GetByProductAndVariantID(ctx context.Contex
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
func (p *ProductRecipeProcessorImpl) GetByIngredientID(ctx context.Context, ingredientID uuid.UUID, organizationID uuid.UUID) ([]*models.ProductRecipeResponse, error) {
|
||||
func (p *ProductRecipeProcessorImpl) GetByIngredientID(ctx context.Context, ingredientID uuid.UUID, organizationID uuid.UUID) ([]*contract.ProductRecipeResponse, error) {
|
||||
entities, err := p.productRecipeRepo.GetByIngredientID(ctx, ingredientID, organizationID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get product recipes by ingredient ID: %w", err)
|
||||
}
|
||||
|
||||
responses := make([]*models.ProductRecipeResponse, len(entities))
|
||||
responses := make([]*contract.ProductRecipeResponse, len(entities))
|
||||
for i, entity := range entities {
|
||||
responses[i] = p.entityToResponse(entity)
|
||||
}
|
||||
@@ -124,7 +124,7 @@ func (p *ProductRecipeProcessorImpl) GetByIngredientID(ctx context.Context, ingr
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
func (p *ProductRecipeProcessorImpl) Update(ctx context.Context, id uuid.UUID, req *models.UpdateProductRecipeRequest, organizationID uuid.UUID) (*models.ProductRecipeResponse, error) {
|
||||
func (p *ProductRecipeProcessorImpl) Update(ctx context.Context, id uuid.UUID, req *contract.UpdateProductRecipeRequest, organizationID uuid.UUID) (*contract.ProductRecipeResponse, error) {
|
||||
// Get existing entity
|
||||
existingEntity, err := p.productRecipeRepo.GetByID(ctx, id, organizationID)
|
||||
if err != nil {
|
||||
@@ -135,6 +135,7 @@ func (p *ProductRecipeProcessorImpl) Update(ctx context.Context, id uuid.UUID, r
|
||||
existingEntity.OutletID = req.OutletID
|
||||
existingEntity.VariantID = req.VariantID
|
||||
existingEntity.Quantity = req.Quantity
|
||||
existingEntity.WastePercentage = req.WastePercentage
|
||||
existingEntity.UpdatedAt = time.Now().UTC()
|
||||
|
||||
if err := p.productRecipeRepo.Update(ctx, existingEntity); err != nil {
|
||||
@@ -158,8 +159,8 @@ func (p *ProductRecipeProcessorImpl) Delete(ctx context.Context, id uuid.UUID, o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProductRecipeProcessorImpl) BulkCreate(ctx context.Context, recipes []models.CreateProductRecipeRequest, organizationID uuid.UUID) ([]*models.ProductRecipeResponse, error) {
|
||||
responses := make([]*models.ProductRecipeResponse, 0, len(recipes))
|
||||
func (p *ProductRecipeProcessorImpl) BulkCreate(ctx context.Context, recipes []contract.CreateProductRecipeRequest, organizationID uuid.UUID) ([]*contract.ProductRecipeResponse, error) {
|
||||
responses := make([]*contract.ProductRecipeResponse, 0, len(recipes))
|
||||
|
||||
for _, recipe := range recipes {
|
||||
response, err := p.Create(ctx, &recipe, organizationID)
|
||||
@@ -172,21 +173,22 @@ func (p *ProductRecipeProcessorImpl) BulkCreate(ctx context.Context, recipes []m
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
func (p *ProductRecipeProcessorImpl) entityToResponse(entity *entities.ProductRecipe) *models.ProductRecipeResponse {
|
||||
response := &models.ProductRecipeResponse{
|
||||
ID: entity.ID,
|
||||
OrganizationID: entity.OrganizationID,
|
||||
OutletID: entity.OutletID,
|
||||
ProductID: entity.ProductID,
|
||||
VariantID: entity.VariantID,
|
||||
IngredientID: entity.IngredientID,
|
||||
Quantity: entity.Quantity,
|
||||
CreatedAt: entity.CreatedAt,
|
||||
UpdatedAt: entity.UpdatedAt,
|
||||
func (p *ProductRecipeProcessorImpl) entityToResponse(entity *entities.ProductRecipe) *contract.ProductRecipeResponse {
|
||||
response := &contract.ProductRecipeResponse{
|
||||
ID: entity.ID,
|
||||
OrganizationID: entity.OrganizationID,
|
||||
OutletID: entity.OutletID,
|
||||
ProductID: entity.ProductID,
|
||||
VariantID: entity.VariantID,
|
||||
IngredientID: entity.IngredientID,
|
||||
Quantity: entity.Quantity,
|
||||
WastePercentage: entity.WastePercentage,
|
||||
CreatedAt: entity.CreatedAt,
|
||||
UpdatedAt: entity.UpdatedAt,
|
||||
}
|
||||
|
||||
if entity.Product != nil {
|
||||
response.Product = &models.Product{
|
||||
response.Product = &contract.ProductResponse{
|
||||
ID: entity.Product.ID,
|
||||
OrganizationID: entity.Product.OrganizationID,
|
||||
CategoryID: entity.Product.CategoryID,
|
||||
@@ -195,11 +197,9 @@ func (p *ProductRecipeProcessorImpl) entityToResponse(entity *entities.ProductRe
|
||||
Description: entity.Product.Description,
|
||||
Price: entity.Product.Price,
|
||||
Cost: entity.Product.Cost,
|
||||
BusinessType: constants.BusinessType(entity.Product.BusinessType),
|
||||
BusinessType: string(entity.Product.BusinessType),
|
||||
ImageURL: entity.Product.ImageURL,
|
||||
PrinterType: entity.Product.PrinterType,
|
||||
UnitID: entity.Product.UnitID,
|
||||
HasIngredients: entity.Product.HasIngredients,
|
||||
Metadata: entity.Product.Metadata,
|
||||
IsActive: entity.Product.IsActive,
|
||||
CreatedAt: entity.Product.CreatedAt,
|
||||
@@ -208,7 +208,7 @@ func (p *ProductRecipeProcessorImpl) entityToResponse(entity *entities.ProductRe
|
||||
}
|
||||
|
||||
if entity.ProductVariant != nil {
|
||||
response.ProductVariant = &models.ProductVariant{
|
||||
response.ProductVariant = &contract.ProductVariantResponse{
|
||||
ID: entity.ProductVariant.ID,
|
||||
ProductID: entity.ProductVariant.ProductID,
|
||||
Name: entity.ProductVariant.Name,
|
||||
@@ -221,7 +221,7 @@ func (p *ProductRecipeProcessorImpl) entityToResponse(entity *entities.ProductRe
|
||||
}
|
||||
|
||||
if entity.Ingredient != nil {
|
||||
response.Ingredient = &models.Ingredient{
|
||||
response.Ingredient = &contract.ProductRecipeIngredientResponse{
|
||||
ID: entity.Ingredient.ID,
|
||||
OrganizationID: entity.Ingredient.OrganizationID,
|
||||
OutletID: entity.Ingredient.OutletID,
|
||||
@@ -235,7 +235,22 @@ func (p *ProductRecipeProcessorImpl) entityToResponse(entity *entities.ProductRe
|
||||
CreatedAt: entity.Ingredient.CreatedAt,
|
||||
UpdatedAt: entity.Ingredient.UpdatedAt,
|
||||
}
|
||||
|
||||
// Add unit if available
|
||||
if entity.Ingredient.Unit != nil {
|
||||
symbol := ""
|
||||
if entity.Ingredient.Unit.Abbreviation != nil {
|
||||
symbol = *entity.Ingredient.Unit.Abbreviation
|
||||
}
|
||||
response.Ingredient.Unit = &contract.ProductRecipeUnitResponse{
|
||||
ID: entity.Ingredient.Unit.ID,
|
||||
Name: entity.Ingredient.Unit.Name,
|
||||
Symbol: symbol,
|
||||
CreatedAt: entity.Ingredient.Unit.CreatedAt,
|
||||
UpdatedAt: entity.Ingredient.Unit.UpdatedAt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
}
|
||||
@@ -56,12 +56,12 @@ type OrderIngredientTransactionRepository interface {
|
||||
BulkCreate(ctx context.Context, transactions []*entities.OrderIngredientTransaction) error
|
||||
}
|
||||
|
||||
type ProductIngredientRepository interface {
|
||||
Create(ctx context.Context, productIngredient *entities.ProductIngredient) error
|
||||
GetByID(ctx context.Context, id, organizationID uuid.UUID) (*entities.ProductIngredient, error)
|
||||
GetByProductID(ctx context.Context, productID, organizationID uuid.UUID) ([]*entities.ProductIngredient, error)
|
||||
GetByIngredientID(ctx context.Context, ingredientID, organizationID uuid.UUID) ([]*entities.ProductIngredient, error)
|
||||
Update(ctx context.Context, productIngredient *entities.ProductIngredient) error
|
||||
type ProductRecipeRepository interface {
|
||||
Create(ctx context.Context, productRecipe *entities.ProductRecipe) error
|
||||
GetByID(ctx context.Context, id, organizationID uuid.UUID) (*entities.ProductRecipe, error)
|
||||
GetByProductID(ctx context.Context, productID, organizationID uuid.UUID) ([]*entities.ProductRecipe, error)
|
||||
GetByIngredientID(ctx context.Context, ingredientID, organizationID uuid.UUID) ([]*entities.ProductRecipe, error)
|
||||
Update(ctx context.Context, productRecipe *entities.ProductRecipe) error
|
||||
Delete(ctx context.Context, id, organizationID uuid.UUID) error
|
||||
DeleteByProductID(ctx context.Context, productID, organizationID uuid.UUID) error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user