orders.py 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. from logging import getLogger
  2. from fastapi import APIRouter, Depends
  3. from models.sales import OrderWeb
  4. from models.user import User
  5. from auth.security import get_current_user
  6. from config.messages import ErrorResponse, SuccessResponse
  7. from utils.responses import error_response, success_response
  8. from services.order_service import (
  9. compare_prices,
  10. fetch_sorted_products,
  11. push_items_to_toteat,
  12. get_active_sale_id,
  13. update_reward_progress,
  14. create_sale_record,
  15. )
  16. logger = getLogger(__name__)
  17. order_router = APIRouter()
  18. @order_router.post("/send")
  19. async def printer_order(order: OrderWeb, current_user: User = Depends(get_current_user)):
  20. """Procesa un pedido: valida, registra en Toteat POS y persiste en BD."""
  21. items, table = order.items, order.table
  22. logger.info(f"Order received from {current_user.email} for table {table}")
  23. # 1. Validación de entrada
  24. if not items or not table:
  25. logger.warning(f"Missing fields from {current_user.email}")
  26. return error_response(message=ErrorResponse.MISSING_FIELDS, status_code=400)
  27. if not isinstance(table, int):
  28. logger.warning(f"Invalid table type from {current_user.email}: {type(table)}")
  29. return error_response(message=ErrorResponse.INVALID_TABLE_TYPE, status_code=400)
  30. # 2. Verificar precios actuales en BD
  31. try:
  32. products = await fetch_sorted_products(items)
  33. items = sorted(items, key=lambda x: x.id)
  34. logger.info(f"Retrieved {len(products)} products for table {table}")
  35. except Exception as e:
  36. return error_response(message=f"Error getting products: {e}", status_code=500)
  37. price_changes = compare_prices(products, items)
  38. if price_changes:
  39. return success_response(
  40. data=price_changes,
  41. message="El estado de los productos y items coincide con el de la venta",
  42. status_code=409,
  43. )
  44. # 3. Registrar en Toteat POS
  45. try:
  46. product_errors, beers = push_items_to_toteat(items, products, table, current_user.name)
  47. except Exception as e:
  48. return error_response(message=f"Error with Toteat integration: {e}", status_code=500)
  49. if product_errors:
  50. logger.error(f"Product errors for table {table}: {product_errors}")
  51. return error_response(error={"errors": product_errors},
  52. message=ErrorResponse.PRODUCT_ADD_ERROR, status_code=424)
  53. # 4. Venta activa de la mesa
  54. try:
  55. active_sale_id = get_active_sale_id(table)
  56. if not active_sale_id:
  57. return error_response(message=f"No active sale found for table {table}", status_code=404)
  58. logger.info(f"Active sale for table {table}: {active_sale_id}")
  59. except Exception as e:
  60. return error_response(message=f"Error retrieving active sale: {e}", status_code=500)
  61. # 5. Puntos de fidelización (no bloquea el pedido si falla)
  62. new_progress = update_reward_progress(current_user, beers)
  63. # 6. Persistir en BD
  64. try:
  65. sale_id = create_sale_record(order, active_sale_id, items)
  66. if sale_id <= 0:
  67. return error_response(message="Failed to create sale record", status_code=500)
  68. except Exception as e:
  69. return error_response(message=f"Error creating sale record: {e}", status_code=500)
  70. logger.info(f"Order completed for table {table}, sale ID: {sale_id}")
  71. return success_response(data={"new_progress": new_progress}, message=SuccessResponse.ORDER_SUCCESS)