| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- import time
- from logging import getLogger
- from threading import Thread
- from uuid import uuid4
- from enums.locations import Locations
- from fastapi import HTTPException, APIRouter, Depends
- from fastapi.responses import JSONResponse
- from fudo import fudo
- from models.sales import ItemWeb, OrderWeb
- from models.items import Item, Order
- from models.user import User
- from services.fudo_service import add_product_to_fudo
- from services.email_service import get_email_sender
- import services.print_service as ps
- from services.data_service import DataServiceFactory
- from config.mails import PRINTER_DISCONNECTED_MAIL
- from config.messages import ErrorResponse, SuccessResponse, UserResponse
- from config.settings import DEVELOPMENT
- from auth.security import get_current_user
- from data.product_category import CAT_ITEMS
- from utils.responses import error_response, success_response
- from datetime import datetime
- 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()
- # Global variables
- printer_orders = []
- order_router = APIRouter()
- name_promo = "Shop"
- @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 = 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)
- printers = {}
-
- for product in products:
- location = CAT_ITEMS[product.type or ""]
- if location.value not in printers:
- printers[location.value] = ps.get_status(location)
- # Printer status validation
- if not DEVELOPMENT:
- try:
- printer_status = [key for key, value in printers.items() if value == False]
- print(printer_status)
- if list(printer_status):
- logger.error(f"Printer is not connected. Order from user {current_user.email} cannot be processed.")
-
-
- # Send notification email to admins
- email_thread = Thread(
- target=get_email_sender().send_email,
- args=(
- PRINTER_DISCONNECTED_MAIL["subject"].format(location=", ".join([loc for loc in printer_status])),
- PRINTER_DISCONNECTED_MAIL["body"].format(location=", ".join([loc for loc in printer_status]), timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")), #type: ignore
- ["erwinjacimino2003@gmail.com", "mompyn@gmail.com"
- # , "i.perez03@ufromail.cl", "marceloburkart94@gmail.com"
- ]
- ),
- daemon=True
- )
- email_thread.start()
-
-
- return error_response(message=ErrorResponse.PRINTER_DISCONNECTED, status_code=424)
-
- except Exception as e:
- logger.error(f"Error checking printer status: {e}")
- return error_response(message=f"Error checking printer status: {e}", status_code=424)
- # Input validation
-
- # 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:
- # Si es dia de promo y es menos de las 8 pm
- if time.localtime().tm_wday + 1 == product.promo_day and product.promo_id and time.localtime().tm_hour < 20:
- logger.info(f"Applying promotion for product {product.id} on table {table}")
- fudo_product = add_product_to_fudo(product.promo_id, item.quantity, table)
-
- #en caso contrario
- else:
- 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)
- # Print order
- try:
- print("items:")
- print(items)
- print("products:")
- print(products)
- pizza_items = [ Item(name=product.name, price=item.price, quantity=item.quantity, comment=item.comment) for item, product in zip(items, products) if CAT_ITEMS.get(product.type) == Locations.PIZZAS]#type: ignore
- burger_items = [ Item(name=product.name, price=item.price, quantity=item.quantity, comment=item.comment) for item, product in zip(items, products) if CAT_ITEMS.get(product.type) == Locations.BURGUER]#type: ignore
- bar_items = [ Item(name=product.name, price=item.price, quantity=item.quantity, comment=item.comment) for item, product in zip(items, products) if CAT_ITEMS.get(product.type) == Locations.BAR]#type: ignore
- coctelery_items = [ Item(name=product.name, price=item.price, quantity=item.quantity, comment=item.comment) for item, product in zip(items, products) if CAT_ITEMS.get(product.type) == Locations.COCTELERY]#type: ignore
- print("bar_items:")
- print(list(map(lambda x: x.model_dump(), bar_items)))
- if pizza_items:
- ps.print_order(Order(table=table, items=pizza_items, customerName=current_user.name, totalAmount=order.totalAmount, orderDate=order.orderDate), location=Locations.PIZZAS)
- logger.info(f"Order pizza printed successfully for table {table}")
- if burger_items:
- ps.print_order(Order(table=table, items=burger_items, customerName=current_user.name, totalAmount=order.totalAmount, orderDate=order.orderDate), location=Locations.BURGUER)
- logger.info(f"Order burger printed successfully for table {table}")
- if bar_items:
- ps.print_order(Order(table=table, items=bar_items, customerName=current_user.name, totalAmount=order.totalAmount, orderDate=order.orderDate), location=Locations.BAR)
- logger.info(f"Order bar printed successfully for table {table}")
- if coctelery_items:
- ps.print_order(Order(table=table, items=coctelery_items, customerName=current_user.name, totalAmount=order.totalAmount, orderDate=order.orderDate), location=Locations.COCTELERY)
- logger.info(f"Order coctelery printed successfully for table {table}")
-
-
- logger.info(f"Order printed successfully for table {table}")
-
-
- except Exception as e:
- error_msg = f"Error printing order for table {table}: {e}"
- logger.error(error_msg)
- return error_response(message=error_msg, status_code=500)
- # Don't fail the order for print issues, just log it
- logger.info(f"Logging order for table {table} with sale ID {sale}, products= {[(product.name, item.quantity) for product, item in zip(products, items)]}")
-
- 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)
|