This commit is contained in:
Aditya Siregar
2025-09-13 02:17:51 +07:00
parent 75ec5274d2
commit 4f6208e479
17 changed files with 398 additions and 207 deletions
+62 -47
View File
@@ -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
}
}