Improve the frontend modals

This commit is contained in:
Urtzi Alfaro
2025-10-27 16:33:26 +01:00
parent 61376b7a9f
commit 858d985c92
143 changed files with 9289 additions and 2306 deletions

View File

@@ -398,11 +398,80 @@ class IngredientRepository(BaseRepository[Ingredient, IngredientCreate, Ingredie
from app.schemas.inventory import IngredientUpdate
update_data = IngredientUpdate(last_purchase_price=price)
return await self.update(ingredient_id, update_data)
except Exception as e:
logger.error("Failed to update last purchase price", error=str(e), ingredient_id=ingredient_id)
raise
async def update_weighted_average_cost(
self,
ingredient_id: UUID,
current_stock_quantity: float,
new_purchase_quantity: float,
new_unit_cost: float
) -> Optional[Ingredient]:
"""
Update the average cost using weighted average calculation.
Formula:
new_average_cost = (current_stock_qty × current_avg_cost + new_qty × new_cost) / (current_stock_qty + new_qty)
Args:
ingredient_id: ID of the ingredient
current_stock_quantity: Current stock quantity before this purchase
new_purchase_quantity: Quantity being purchased
new_unit_cost: Unit cost of the new purchase
Returns:
Updated ingredient or None if not found
"""
try:
# Get current ingredient data
ingredient = await self.get_by_id(ingredient_id)
if not ingredient:
logger.warning("Ingredient not found for average cost update", ingredient_id=ingredient_id)
return None
from decimal import Decimal
# Get current average cost (default to new cost if not set)
current_avg_cost = float(ingredient.average_cost) if ingredient.average_cost else float(new_unit_cost)
# Calculate weighted average
# If no current stock, just use the new purchase price
if current_stock_quantity <= 0:
new_average_cost = Decimal(str(new_unit_cost))
else:
# Weighted average formula
total_cost = (current_stock_quantity * current_avg_cost) + (new_purchase_quantity * new_unit_cost)
total_quantity = current_stock_quantity + new_purchase_quantity
new_average_cost = Decimal(str(total_cost / total_quantity))
# Update the ingredient
from app.schemas.inventory import IngredientUpdate
update_data = IngredientUpdate(average_cost=new_average_cost)
updated_ingredient = await self.update(ingredient_id, update_data)
logger.info(
"Updated weighted average cost",
ingredient_id=ingredient_id,
old_average_cost=current_avg_cost,
new_average_cost=float(new_average_cost),
current_stock_qty=current_stock_quantity,
new_purchase_qty=new_purchase_quantity,
new_unit_cost=new_unit_cost
)
return updated_ingredient
except Exception as e:
logger.error(
"Failed to update weighted average cost",
error=str(e),
ingredient_id=ingredient_id
)
raise
async def get_ingredients_by_category(self, tenant_id: UUID, category: str) -> List[Ingredient]:
"""Get all ingredients in a specific category"""
try:

View File

@@ -28,7 +28,9 @@ class StockMovementRepository(BaseRepository[StockMovement, StockMovementCreate,
self,
movement_data: StockMovementCreate,
tenant_id: UUID,
created_by: Optional[UUID] = None
created_by: Optional[UUID] = None,
quantity_before: Optional[float] = None,
quantity_after: Optional[float] = None
) -> StockMovement:
"""Create a new stock movement record"""
try:
@@ -37,6 +39,12 @@ class StockMovementRepository(BaseRepository[StockMovement, StockMovementCreate,
create_data['tenant_id'] = tenant_id
create_data['created_by'] = created_by
# Add quantity_before and quantity_after if provided
if quantity_before is not None:
create_data['quantity_before'] = quantity_before
if quantity_after is not None:
create_data['quantity_after'] = quantity_after
# Ensure movement_type is properly converted to enum value
if 'movement_type' in create_data:
movement_type = create_data['movement_type']
@@ -65,6 +73,8 @@ class StockMovementRepository(BaseRepository[StockMovement, StockMovementCreate,
ingredient_id=record.ingredient_id,
movement_type=record.movement_type if record.movement_type else None,
quantity=record.quantity,
quantity_before=record.quantity_before,
quantity_after=record.quantity_after,
tenant_id=tenant_id
)
return record
@@ -453,7 +463,7 @@ class StockMovementRepository(BaseRepository[StockMovement, StockMovementCreate,
# Generate reference number
reference_number = f"AUTO-EXPIRE-{batch_number or stock_id}"
# Create movement data
# Create movement data (without quantity_before/quantity_after - these will be calculated by the caller)
movement_data = {
'tenant_id': tenant_id,
'ingredient_id': ingredient_id,
@@ -462,8 +472,6 @@ class StockMovementRepository(BaseRepository[StockMovement, StockMovementCreate,
'quantity': quantity,
'unit_cost': Decimal(str(unit_cost)) if unit_cost else None,
'total_cost': total_cost,
'quantity_before': quantity,
'quantity_after': 0,
'reference_number': reference_number,
'reason_code': 'expired',
'notes': f"Lote automáticamente marcado como caducado. Vencimiento: {expiration_date.strftime('%Y-%m-%d')}",
@@ -536,4 +544,4 @@ class StockMovementRepository(BaseRepository[StockMovement, StockMovementCreate,
except Exception as e:
logger.error("Failed to get inventory waste total", error=str(e), tenant_id=str(tenant_id))
raise
raise