feat(ingredients): make units nullable

This commit is contained in:
efrilm
2026-08-11 21:20:17 +07:00
parent 9ae5be2c33
commit 0726fcecf0
11 changed files with 54 additions and 36 deletions
+7 -4
View File
@@ -27,8 +27,11 @@ func NewIngredientProcessor(ingredientRepo IngredientRepository, unitRepo UnitRe
}
func (p *IngredientProcessorImpl) CreateIngredient(ctx context.Context, req *models.CreateIngredientRequest) (*models.IngredientResponse, error) {
if _, err := p.unitRepo.GetByID(ctx, req.UnitID, req.OrganizationID); err != nil {
return nil, err
// The unit is optional, so it is only validated when one is supplied.
if req.UnitID != nil {
if _, err := p.unitRepo.GetByID(ctx, *req.UnitID, req.OrganizationID); err != nil {
return nil, err
}
}
ingredient := &entities.Ingredient{
@@ -107,8 +110,8 @@ func (p *IngredientProcessorImpl) UpdateIngredient(ctx context.Context, id uuid.
return nil, err
}
if req.UnitID != existing.UnitID {
if _, err := p.unitRepo.GetByID(ctx, req.UnitID, organizationID); err != nil {
if req.UnitID != nil && (existing.UnitID == nil || *req.UnitID != *existing.UnitID) {
if _, err := p.unitRepo.GetByID(ctx, *req.UnitID, organizationID); err != nil {
return nil, err
}
}
@@ -266,15 +266,27 @@ func (p *IngredientUnitConverterProcessorImpl) GetUnitsByIngredientID(ctx contex
return nil, fmt.Errorf("failed to get ingredient: %w", err)
}
// Get the base unit details
baseUnit, err := p.unitRepo.GetByID(ctx, ingredient.UnitID, organizationID)
if err != nil {
return nil, fmt.Errorf("failed to get base unit: %w", err)
response := &models.IngredientUnitsResponse{
IngredientID: ingredientID,
IngredientName: ingredient.Name,
}
// Start with the base unit
units := []*models.UnitResponse{
mappers.MapUnitEntityToResponse(baseUnit),
units := make([]*models.UnitResponse, 0)
unitMap := make(map[uuid.UUID]bool)
// An ingredient does not necessarily have a unit assigned yet. When it has
// none there is no base unit to start from, so the only units on offer are
// the ones its converters mention.
if ingredient.UnitID != nil {
baseUnit, err := p.unitRepo.GetByID(ctx, *ingredient.UnitID, organizationID)
if err != nil {
return nil, fmt.Errorf("failed to get base unit: %w", err)
}
units = append(units, mappers.MapUnitEntityToResponse(baseUnit))
unitMap[baseUnit.ID] = true
response.BaseUnitID = &baseUnit.ID
response.BaseUnitName = baseUnit.Name
}
// Get all converters for this ingredient
@@ -283,10 +295,6 @@ func (p *IngredientUnitConverterProcessorImpl) GetUnitsByIngredientID(ctx contex
return nil, fmt.Errorf("failed to get converters: %w", err)
}
// Add unique units from converters
unitMap := make(map[uuid.UUID]bool)
unitMap[baseUnit.ID] = true
for _, converter := range converters {
if converter.IsActive {
// Add FromUnit if not already added
@@ -309,13 +317,7 @@ func (p *IngredientUnitConverterProcessorImpl) GetUnitsByIngredientID(ctx contex
}
}
response := &models.IngredientUnitsResponse{
IngredientID: ingredientID,
IngredientName: ingredient.Name,
BaseUnitID: baseUnit.ID,
BaseUnitName: baseUnit.Name,
Units: units,
}
response.Units = units
return response, nil
}
@@ -371,8 +371,8 @@ func (p *OrderIngredientTransactionProcessorImpl) CalculateWasteQuantities(ctx c
// Get unit name
unitName := "unit" // default
if ingredient.UnitID != uuid.Nil {
unit, err := p.unitRepo.GetByID(ctx, ingredient.UnitID, organizationID)
if ingredient.UnitID != nil {
unit, err := p.unitRepo.GetByID(ctx, *ingredient.UnitID, organizationID)
if err == nil {
unitName = unit.Name
}
@@ -462,13 +462,15 @@ func (p *PurchaseOrderProcessorImpl) UpdatePurchaseOrderStatus(ctx context.Conte
return nil, fmt.Errorf("failed to get ingredient %s: %w", *item.IngredientID, err)
}
// Convert quantity to ingredient's base unit if needed
// Convert quantity to ingredient's base unit if needed. An ingredient
// without a unit has no base unit to convert into, so the purchased
// quantity is taken as-is.
quantityToAdd := *item.Quantity
if *item.UnitID != ingredient.UnitID {
if ingredient.UnitID != nil && *item.UnitID != *ingredient.UnitID {
// Convert from purchase unit to ingredient's base unit
convertedQuantity, err := p.unitConverterRepo.ConvertQuantity(ctx, *item.IngredientID, *item.UnitID, ingredient.UnitID, organizationID, *item.Quantity)
convertedQuantity, err := p.unitConverterRepo.ConvertQuantity(ctx, *item.IngredientID, *item.UnitID, *ingredient.UnitID, organizationID, *item.Quantity)
if err != nil {
return nil, fmt.Errorf("failed to convert quantity for ingredient %s from unit %s to %s: %w", *item.IngredientID, *item.UnitID, ingredient.UnitID, err)
return nil, fmt.Errorf("failed to convert quantity for ingredient %s from unit %s to %s: %w", *item.IngredientID, *item.UnitID, *ingredient.UnitID, err)
}
quantityToAdd = convertedQuantity
}