from threading import Thread from math import log import time from uuid import uuid4 from fastapi import HTTPException, APIRouter from fastapi.responses import JSONResponse from fudo import fudo from models.sales import OrderWeb from services.fudo_service import add_product_to_fudo from services.email_service import send_email from services.logging_service import log_order from impresora.printer import PrinterUSB from impresora.order import Order, Item from logging import getLogger 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 logger = getLogger(__name__) user_data_service = DataServiceFactory.get_user_service() product_data_service = DataServiceFactory.get_product_service() sale_data_service = DataServiceFactory.get_sales_service() printer_orders = [] order_router = APIRouter() @order_router.post("/send") async def printer_order(order: OrderWeb): """Process printer order""" logger.info("Printer order received") logger.info(order) if not DEVELOPMENT: if not PrinterUSB.check_usb_port(0xfe6, 0x811e): logger.error("Printer is not connected.") email_thread = Thread( target=send_email, args=(PRINTER_DISCONNECTED_MAIL["subject"], PRINTER_DISCONNECTED_MAIL["body"], ["erwinjacimino2003@gmail.com"]), daemon=True ) email_thread.start() logger.error("Email sent to admin about printer issue.") return JSONResponse(status_code=424, content={"message": ErrorResponse.PRINTER_DISCONNECTED}) items = order.items table = order.table if not items or not table: return JSONResponse(status_code=400, content={"message": ErrorResponse.MISSING_FIELDS}) if not isinstance(table, int): return JSONResponse(status_code=400, content={"message": ErrorResponse.INVALID_TABLE_TYPE}) # Add products to Fudo product_errors = [] for item in items: fudo.get_token() product = add_product_to_fudo(item.id, item.quantity, table) if not product: product_errors.append(f"Error adding product {item.id} to table {table}.") if product_errors: return JSONResponse( status_code=424, content={"message": ErrorResponse.PRODUCT_ADD_ERROR, "errors": product_errors} ) user = user_data_service.get_by_id(order.customerId) if not user: return JSONResponse(status_code=404, content={"message": UserResponse.USER_NOT_FOUND.format(user_id=order.customerId)}) active_sale_id = fudo.get_active_sale(fudo.get_table(table)) if not active_sale_id: logger.error(f"Error: No active sale found for table {table}.") raise HTTPException(status_code=404) active_sale_id = active_sale_id['id'] products = product_data_service.get_products([item.id for item in items]) 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] ) logger.info(f"Sale created: {sale}") # Print order printer_orders.append(Order( user=user.name if user else "Unknown User", items=[Item(product.name, product.price, item.quantity) for product, item in zip(products, items)] )) # Log order log_order(user.name, order.table, order_date=order.orderDate, items=[product.name for product in products]) return JSONResponse({"message": SuccessResponse.ORDER_SUCCESS}) def order_thread(): """Thread to process orders""" logger.info("Starting order thread") while True: if printer_orders: order = printer_orders.pop(0) logger.info(f"Processing order: {order}") try: printer = PrinterUSB(0xfe6, 0x811e) if not printer.is_connected(): logger.error("Printer is not connected.") continue printer.print_order(order) logger.info(f"Order printed: {order}") except Exception as e: logger.error(f"Error printing order: {e}") time.sleep(1) # Sleep to avoid busy waiting