| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- from logging import getLogger
- from typing import List
- from uuid import uuid4
- from pydantic import BaseModel
- from fastapi import APIRouter, Depends
- from toteat import toteat as fudo
- from models.sales import ItemWeb, OrderWeb
- from models.items import Product
- from models.user import User
- from services.fudo_service import add_product_to_fudo
- from services.data_service import DataServiceFactory
- from config.messages import ErrorResponse, SuccessResponse
- from auth.security import get_current_user
- from utils.responses import error_response, success_response
- logger = getLogger(__name__)
- # Data services initialization
- user_data_service = DataServiceFactory.get_user_service()
- product_data_service = DataServiceFactory.get_product_service()
- sale_data_service = DataServiceFactory.get_sales_service()
- order_router = APIRouter()
- name_promo = "Cervezas"
- class ComparePricesResponse(BaseModel):
- product: Product
- oldPrice: int
- newPrice: int
- isAvailable: bool
- def compare_prices(products: List[Product], items: List[ItemWeb]) -> list:
- """Compare prices of products and items and return the cheapest product"""
- # Initialize a dictionary to store the prices
- prices: List[ComparePricesResponse] = []
- for product, item in zip(products, items):
- if product.status == 0:
- prices.append(
- ComparePricesResponse(
- product=product,
- oldPrice=item.price,
- newPrice=product.price,
- isAvailable=False
- )
- )
- continue
- if product.price != item.price:
- prices.append(
- ComparePricesResponse(
- product=product,
- oldPrice=item.price,
- newPrice=product.price,
- isAvailable=True
- )
- )
- return list(map(lambda x: x.model_dump(), prices))
- @order_router.post("/send")
- async def printer_order(order: OrderWeb, current_user: User = Depends(get_current_user)):
- """Process printer order"""
- logger.info(f"Printer order received from user {current_user.email} for table {order.table}")
-
- # Extract order data
- items = order.items
- table = order.table
- # Input validation
- if not items or not table:
- logger.warning(f"Invalid order data from user {current_user.email}: missing items or table")
- return error_response(message=ErrorResponse.MISSING_FIELDS, status_code=400)
- if not isinstance(table, int):
- logger.warning(f"Invalid table type from user {current_user.email}: {type(table)}")
-
- return error_response(message=ErrorResponse.INVALID_TABLE_TYPE, status_code=400)
- logger.info(f"Processing order for table {table} with {len(items)} items")
- # Get products data
- try:
- products = await product_data_service.get_products([item.id for item in items])
- # Me aseguro de que los items y los productos esten en el mismo orden
- products = list(sorted(products, key=lambda x: x.id))
- items = list(sorted(items, key=lambda x: x.id))
- logger.info(f"Retrieved {len(products)} products from database")
-
-
- except Exception as e:
- error_msg = f"Error getting products: {e}"
- logger.error(error_msg)
- return error_response(message=error_msg, status_code=500)
- # Comparo los precios de los items con los productos
- prices = compare_prices(products, items)
- if prices:
- return success_response(data=prices, message="El estado de los productos y items coincide con el de la venta", status_code=409)
- # Add products to Fudo
- product_errors = []
- beers_for_promo = 0
-
- try:
- fudo.get_token()
- logger.info("Fudo token obtained successfully")
-
- for item, product in zip(items, products):
- try:
-
- if product.type == name_promo and current_user.name != "Guest":
- beers_for_promo += item.quantity
- logger.debug(f"Added {item.quantity} beers for promotion calculation")
-
- fudo_product = add_product_to_fudo(item.id, item.quantity, table)
-
- logger.info(f"Added product {item.id} to table {table} with quantity {item.quantity} in fudo")
-
- if not fudo_product:
- error_msg = f"Error adding product {item.id} to table {table}."
- product_errors.append(error_msg)
- logger.error(error_msg)
-
-
- except Exception as e:
- error_msg = f"Error processing product {item.id}: {e}"
- logger.error(error_msg)
- product_errors.append(error_msg)
-
-
- except Exception as e:
- error_msg = f"Error with Fudo integration: {e}"
- logger.error(error_msg)
-
- return error_response(message=error_msg, status_code=500)
- if product_errors:
- logger.error(f"Product errors occurred: {product_errors}")
-
- return error_response(error={"errors": product_errors}, message=ErrorResponse.PRODUCT_ADD_ERROR, status_code=424)
-
- # Get active sale
- try:
- active_sale_id = fudo.get_active_sale(fudo.get_table(table))
- if not active_sale_id:
- error_msg = f"No active sale found for table {table}"
- logger.error(error_msg)
-
- return error_response(message=error_msg, status_code=404)
-
- active_sale_id = active_sale_id['id']
- logger.info(f"Active sale found for table {table}: {active_sale_id}")
- except Exception as e:
- error_msg = f"Error retrieving active sale for table {table}: {e}"
- logger.error(error_msg)
-
- return error_response(message=error_msg, status_code=500)
- # Update user reward progress
- try:
- new_progress = current_user.reward_progress + beers_for_promo * 10
- user_data_service.set_reward_progress(current_user.id, new_progress)
-
- logger.info(f"Updated reward progress for user {current_user.email}: {current_user.reward_progress} -> {new_progress}")
-
-
- except Exception as e:
- error_msg = f"Error updating reward progress for user {current_user.id}: {e}"
- logger.error(error_msg)
- # Don't fail the order for this, just log it
- new_progress = current_user.reward_progress
- # Create sale record
- try:
- sale = sale_data_service.create(
- order.customerId,
- active_sale_id or uuid4().hex,
- order.totalAmount,
- order.table,
- [item.id for item in items],
- [item.quantity for item in items]
- )
-
- if sale > 0:
- logger.info(f"Sale created successfully: ID {sale}")
- else:
- error_msg = "Failed to create sale record"
- logger.error(error_msg)
- return error_response(message=error_msg, status_code=500)
-
- except Exception as e:
- error_msg = f"Error creating sale record: {e}"
- logger.error(error_msg)
-
- return error_response(message=error_msg, status_code=500)
- logger.info(f"Order processing completed successfully for table {table}, sale ID: {sale}")
- return success_response(data={"new_progress": new_progress}, message=SuccessResponse.ORDER_SUCCESS)
|