Просмотр исходного кода

listar las compras del usuario

latapp 9 месяцев назад
Родитель
Сommit
8f44f1d3d6

+ 0 - 1
auth/security.py

@@ -3,7 +3,6 @@ from typing import Union
 from venv import logger
 from venv import logger
 from fastapi import Depends, HTTPException
 from fastapi import Depends, HTTPException
 from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
 from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
-from typing import Annotated
 from logging import getLogger
 from logging import getLogger
 
 
 from pydantic import BaseModel
 from pydantic import BaseModel

+ 1 - 0
config/settings.py

@@ -28,6 +28,7 @@ FEEDBACK_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'logs',
 OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
 OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
 PORT = int(os.getenv("PORT", 6001))
 PORT = int(os.getenv("PORT", 6001))
 PIN_KEY = os.getenv("PIN_KEY", "-1")
 PIN_KEY = os.getenv("PIN_KEY", "-1")
+DEVELOPMENT = True if os.getenv("NODE_ENV", "development").lower() == "development" else False
 if PIN_KEY == "-1":
 if PIN_KEY == "-1":
     logging.warning("Using default PIN_KEY. Please set a strong PIN_KEY in your .env file for production.")
     logging.warning("Using default PIN_KEY. Please set a strong PIN_KEY in your .env file for production.")
 # SECRET_KEY is crucial for signing session cookies.
 # SECRET_KEY is crucial for signing session cookies.

+ 0 - 0
fudo/__init__.py


+ 1 - 2
models/__init__.py

@@ -1,7 +1,7 @@
 # Models module
 # Models module
 
 
 from .user import User, UserIDRequest, RegisterUserRequest
 from .user import User, UserIDRequest, RegisterUserRequest
-from .items import Product, ProductWithQuantity
+from .items import Product
 from .sales import Sale, ItemWeb, OrderWeb
 from .sales import Sale, ItemWeb, OrderWeb
 from .blacklist import Blacklist
 from .blacklist import Blacklist
 from .chat import Message, ChatCompletionRequest
 from .chat import Message, ChatCompletionRequest
@@ -11,7 +11,6 @@ __all__ = [
     "UserIDRequest",
     "UserIDRequest",
     "RegisterUserRequest",
     "RegisterUserRequest",
     "Product",
     "Product",
-    "ProductWithQuantity",
     "Sale",
     "Sale",
     "ItemWeb",
     "ItemWeb",
     "OrderWeb", 
     "OrderWeb", 

+ 1 - 1
models/blacklist.py

@@ -6,5 +6,5 @@ class Blacklist(BaseModel):
     id: int
     id: int
     user_id: int
     user_id: int
     email: Optional[str] = None
     email: Optional[str] = None
-    nombre: Optional[str] = None
+    name: Optional[str] = None
     rut: Optional[str] = None
     rut: Optional[str] = None

+ 1 - 6
models/items.py

@@ -10,9 +10,4 @@ class Product(BaseModel):
     price: float
     price: float
     image: Optional[str] = None
     image: Optional[str] = None
     status: int = 1  # 0: Inactive, 1: Active
     status: int = 1  # 0: Inactive, 1: Active
-
-class ProductWithQuantity(Product):
-    """Product model with quantity field for sales"""
-    cantidad: int = 1
-
-
+    quantity: Optional[int] = 1  # Optional quantity for the product

+ 5 - 14
models/sales.py

@@ -1,6 +1,8 @@
 from typing import List, Optional
 from typing import List, Optional
 from pydantic import BaseModel
 from pydantic import BaseModel
 
 
+from models.items import Product
+
 class ItemWeb(BaseModel):
 class ItemWeb(BaseModel):
     id: int
     id: int
     quantity: int
     quantity: int
@@ -12,25 +14,14 @@ class OrderWeb(BaseModel):
     orderDate: str
     orderDate: str
     table: int
     table: int
 
 
-class Product(BaseModel):
-    """Legacy Product model - use models.items.Product instead"""
-    id: int
-    name: str
-    price: float
-    type: str
-    
-    description: str
-    image: str
-    status: int  # 0: inactive, 1: active
-    quantity: Optional[int] = 1  # Optional quantity for the product
-
 class Sale(BaseModel):
 class Sale(BaseModel):
     """Sale model matching the database schema"""
     """Sale model matching the database schema"""
     id: int
     id: int
     user_id: int
     user_id: int
     total: float
     total: float
     fudo_id: str
     fudo_id: str
-    fecha: str
+    date: str
     table: int
     table: int
-    user_name: Optional[str] = None
+    username: Optional[str] = None
     user_email: Optional[str] = None
     user_email: Optional[str] = None
+    products: List[Product] = []

+ 1 - 1
models/user.py

@@ -13,7 +13,7 @@ class User(BaseModel):
     """User model matching the database schema"""
     """User model matching the database schema"""
     id: int
     id: int
     email: str
     email: str
-    nombre: str
+    name: str
     rut: str
     rut: str
     pin_hash: str
     pin_hash: str
     kleincoins: str
     kleincoins: str

+ 0 - 1
public/main/index.html

@@ -180,7 +180,6 @@
               <td class="px-6 py-4">
               <td class="px-6 py-4">
                 <div class="flex flex-col">
                 <div class="flex flex-col">
                   <span class="list-element-name text-sm font-medium text-[#101419]">Klein Lager</span>
                   <span class="list-element-name text-sm font-medium text-[#101419]">Klein Lager</span>
-                  <span class="list-element-desc text-xs text-[#58728d]">Cerveza rubia refrescante</span>
                 </div>
                 </div>
               </td>
               </td>
               <td class="list-element-price px-6 py-4 text-sm font-semibold text-[#101419] text-right">$6.000</td>
               <td class="list-element-price px-6 py-4 text-sm font-semibold text-[#101419] text-right">$6.000</td>

+ 8 - 1
public/main/js/app.js

@@ -3,7 +3,7 @@ import { getProducts, sendOrder } from './service/product.js';
 import { login } from './service/auth.js'
 import { login } from './service/auth.js'
 import { createGlobalLoader, showGlobalLoader, hideGlobalLoader } from './utils/loader.js';
 import { createGlobalLoader, showGlobalLoader, hideGlobalLoader } from './utils/loader.js';
 import { showError } from './utils/error.js';
 import { showError } from './utils/error.js';
-import { setupShoppingCart } from './utils/shoppingCart.js';
+import { addHistoryRow, setupShoppingCart } from './utils/shoppingCart.js';
 // --- Variables de Usuario ---
 // --- Variables de Usuario ---
 let userId = -1;
 let userId = -1;
 let userName = "Cliente";
 let userName = "Cliente";
@@ -307,6 +307,13 @@ async function processOrder() {
         };
         };
         await sendOrder(orderData,userToken);
         await sendOrder(orderData,userToken);
         alert("Pedido enviado con éxito.");
         alert("Pedido enviado con éxito.");
+        cart.forEach(item => {
+            addHistoryRow({
+                productName: item.name,
+                quantity: item.quantity,
+                price: item.price,
+            });
+        });
         cart = []
         cart = []
         updateCartDisplay();
         updateCartDisplay();
     } catch (error) {
     } catch (error) {

+ 1 - 1
public/main/js/service/product.js

@@ -6,7 +6,7 @@ async function sendOrder(order, token) {
       method: "POST",
       method: "POST",
       headers: {
       headers: {
         "Content-Type": "application/json",
         "Content-Type": "application/json",
-        "X-App-Token": token
+        "Authorization": `Bearer ${token}`
       },
       },
       body: JSON.stringify(order)
       body: JSON.stringify(order)
     });
     });

+ 17 - 1
public/main/js/service/user.js

@@ -39,4 +39,20 @@ async function fetchUserSales(userId, token) {
   }
   }
 }
 }
 
 
-export { fetchUserSales };
+async function historyProducts(userId, token) {
+  const sales = await fetchUserSales(userId, token);
+  if (!sales || sales.length === 0) {
+    console.warn("No hay ventas para mostrar en el historial.");
+    return [];
+  }
+  const products = sales.map(sale => ([
+    sale.products.map(product => ({
+      quantity: product.quantity,
+      productName: product.name,
+      price: product.price.toFixed(0)
+    }))
+  ]));
+  return products.flat(2);
+}
+
+export { fetchUserSales, historyProducts };

+ 10 - 9
public/main/js/utils/shoppingCart.js

@@ -1,4 +1,4 @@
-import { fetchUserSales } from "../service/user.js";
+import { fetchUserSales, historyProducts } from "../service/user.js";
 
 
 const table = document.getElementById('historyTable');
 const table = document.getElementById('historyTable');
 const rowTemplate = document.getElementById('historyRowTemplate');
 const rowTemplate = document.getElementById('historyRowTemplate');
@@ -12,18 +12,18 @@ function setHistoryTable(tableData) {
   }
   }
     table.querySelector('tbody').innerHTML = ''; // Clear existing rows
     table.querySelector('tbody').innerHTML = ''; // Clear existing rows
     tableData.forEach(item => {
     tableData.forEach(item => {
-      addHistoryRow(item.quantity, item.productName, item.price);
+      addHistoryRow(item);
     });
     });
 }   
 }   
 
 
 
 
-function addHistoryRow(quantity, productName, price) {
+function addHistoryRow(sale) {
   const newRow = rowTemplate.content.cloneNode(true);
   const newRow = rowTemplate.content.cloneNode(true);
-  newRow.querySelector('.list-element-quantity').textContent = quantity;
-  newRow.querySelector('.list-element-name').textContent = productName;
-  newRow.querySelector('.list-element-price').textContent = `$${price.toFixed(2)}`;
+  newRow.querySelector('.list-element-quantity').textContent = sale.quantity;
+  newRow.querySelector('.list-element-name').textContent = sale.productName;
+  newRow.querySelector('.list-element-price').textContent = `$${sale.price}`;
 
 
-    addCartHistoryTotal(price);
+    addCartHistoryTotal(sale.price);
 
 
   table.querySelector('tbody').appendChild(newRow);
   table.querySelector('tbody').appendChild(newRow);
 }
 }
@@ -35,7 +35,7 @@ function addCartHistoryTotal(price) {
 }
 }
 
 
 function updateCartHistoryTotal(total) {
 function updateCartHistoryTotal(total) {
-  cartHistoryTotal.textContent = `$${total.toFixed(2)}`;
+  cartHistoryTotal.textContent = `$${total.toFixed(0)}`;
 }
 }
 
 
 function getHistoryTotal() {
 function getHistoryTotal() {
@@ -49,7 +49,8 @@ async function setupShoppingCart(userID, userToken, userName) {
   }else{
   }else{
     console.warn("No se encontró el elemento de nombre en la tabla de historial.");
     console.warn("No se encontró el elemento de nombre en la tabla de historial.");
   }
   }
-  const sales = await fetchUserSales(userID, userToken);
+  const sales = await historyProducts(userID, userToken);
+  
   if (sales){
   if (sales){
     setHistoryTable(sales);
     setHistoryTable(sales);
   }
   }

+ 40 - 23
routes/orders.py

@@ -1,6 +1,7 @@
-from itertools import product
+from threading import Thread
 from math import log
 from math import log
 import time
 import time
+from uuid import uuid4
 from fastapi import HTTPException, APIRouter
 from fastapi import HTTPException, APIRouter
 from fastapi.responses import JSONResponse
 from fastapi.responses import JSONResponse
 from fudo import fudo
 from fudo import fudo
@@ -11,14 +12,14 @@ from services.logging_service import log_order
 from impresora.printer import PrinterUSB
 from impresora.printer import PrinterUSB
 from impresora.order import Order, Item
 from impresora.order import Order, Item
 from logging import getLogger
 from logging import getLogger
-from threading import Thread
-from services.data_service import ProductDataService, UserDataService
+from services.data_service import DataServiceFactory
 from config.mails import PRINTER_DISCONNECTED_MAIL
 from config.mails import PRINTER_DISCONNECTED_MAIL
 from config.messages import ErrorResponse, SuccessResponse, UserResponse
 from config.messages import ErrorResponse, SuccessResponse, UserResponse
-
+from config.settings import DEVELOPMENT
 logger = getLogger(__name__)
 logger = getLogger(__name__)
-user_data_service = UserDataService()
-product_data_service = ProductDataService()
+user_data_service = DataServiceFactory.get_user_service()
+product_data_service = DataServiceFactory.get_product_service()
+sale_data_service = DataServiceFactory.get_sales_service()
 printer_orders = []
 printer_orders = []
 order_router = APIRouter()
 order_router = APIRouter()
 
 
@@ -27,17 +28,17 @@ async def printer_order(order: OrderWeb):
     """Process printer order"""
     """Process printer order"""
     logger.info("Printer order received")
     logger.info("Printer order received")
     logger.info(order)
     logger.info(order)
-
-    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})
+    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
     items = order.items
     table = order.table
     table = order.table
@@ -52,9 +53,9 @@ async def printer_order(order: OrderWeb):
     product_errors = []
     product_errors = []
     for item in items:
     for item in items:
         fudo.get_token()
         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}.")
+        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:
     if product_errors:
         return JSONResponse(
         return JSONResponse(
@@ -63,17 +64,33 @@ async def printer_order(order: OrderWeb):
         )
         )
 
 
     user = user_data_service.get_by_id(order.customerId)
     user = user_data_service.get_by_id(order.customerId)
+    
     if not user:
     if not user:
         return JSONResponse(status_code=404, content={"message": UserResponse.USER_NOT_FOUND.format(user_id=order.customerId)})
         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])
     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
     # Print order
     printer_orders.append(Order(
     printer_orders.append(Order(
-        user=user.nombre if user else "Unknown User",
+        user=user.name if user else "Unknown User",
         items=[Item(product.name, product.price, item.quantity) for product, item in zip(products, items)]
         items=[Item(product.name, product.price, item.quantity) for product, item in zip(products, items)]
     ))
     ))
 
 
     # Log order
     # Log order
-    log_order(user.nombre, order.table, order_date=order.orderDate, items=[product.name for product in products])
+    log_order(user.name, order.table, order_date=order.orderDate, items=[product.name for product in products])
 
 
     return JSONResponse({"message": SuccessResponse.ORDER_SUCCESS})
     return JSONResponse({"message": SuccessResponse.ORDER_SUCCESS})
 
 
@@ -90,7 +107,7 @@ def order_thread():
                     logger.error("Printer is not connected.")
                     logger.error("Printer is not connected.")
                     continue
                     continue
                 
                 
-                # printer.print_order(order)
+                printer.print_order(order)
                 logger.info(f"Order printed: {order}")
                 logger.info(f"Order printed: {order}")
             except Exception as e:
             except Exception as e:
                 logger.error(f"Error printing order: {e}")
                 logger.error(f"Error printing order: {e}")

+ 5 - 6
routes/sales.py

@@ -1,15 +1,13 @@
-from csv import Error
-from tkinter import E
+from logging import getLogger
+from venv import logger
 from fastapi.responses import JSONResponse
 from fastapi.responses import JSONResponse
-from pydantic import BaseModel
 from config.messages import ErrorResponse
 from config.messages import ErrorResponse
-from models import sales
 from services.data_service import SalesDataService
 from services.data_service import SalesDataService
 from fastapi import APIRouter, Depends
 from fastapi import APIRouter, Depends
 from models.sales import Sale
 from models.sales import Sale
 sale_data_service = SalesDataService()
 sale_data_service = SalesDataService()
 
 
-
+logger = getLogger(__name__)
 sales_router = APIRouter()
 sales_router = APIRouter()
 
 
 @sales_router.get("/user/{user_id}", response_model=list[Sale])
 @sales_router.get("/user/{user_id}", response_model=list[Sale])
@@ -20,7 +18,8 @@ def get_user_sales(user_id: int):
             status_code=404,
             status_code=404,
             content={"message": ErrorResponse.SALE_NOT_FOUND}
             content={"message": ErrorResponse.SALE_NOT_FOUND}
         )
         )
+    logger.info(f"Sales found for user {user_id}: {len(sales)} sales")
     return JSONResponse(
     return JSONResponse(
         status_code=200,
         status_code=200,
-        content={"sales": sales, "message": "Ventas obtenidas correctamente."}
+        content={"sales": [sale.model_dump() for sale in sales], "message": "Ventas obtenidas correctamente."}
     )
     )

+ 2 - 2
routes/users.py

@@ -50,7 +50,7 @@ async def register_user(request: RegisterUserRequest):
     send_email(
     send_email(
         REGISTER_MAIL["subject"],
         REGISTER_MAIL["subject"],
         REGISTER_MAIL["body"],
         REGISTER_MAIL["body"],
-        [user.email], name=user.nombre, app_name=APPNAME, pin=pin
+        [user.email], name=user.name, app_name=APPNAME, pin=pin
     )
     )
     return JSONResponse(status_code=201, content={"message": SuccessResponse.USER_CREATED_SUCCESS, "data": {
     return JSONResponse(status_code=201, content={"message": SuccessResponse.USER_CREATED_SUCCESS, "data": {
         **user.model_dump(exclude={"pin_hash"}),
         **user.model_dump(exclude={"pin_hash"}),
@@ -77,7 +77,7 @@ async def login_user(request: LoginRequest):
         redis_client.delete(f"login_attempts:{request.email}")
         redis_client.delete(f"login_attempts:{request.email}")
         return JSONResponse(status_code=200, content={"message": SuccessResponse.LOGIN_SUCCESS, "data": {
         return JSONResponse(status_code=200, content={"message": SuccessResponse.LOGIN_SUCCESS, "data": {
             "id": user.id,
             "id": user.id,
-            "name": user.nombre,
+            "name": user.name,
             "email": user.email,
             "email": user.email,
             "kleincoins": user.kleincoins,
             "kleincoins": user.kleincoins,
             "created_at": user.created_at,
             "created_at": user.created_at,

+ 146 - 107
services/data_service.py

@@ -2,18 +2,17 @@ import json
 from math import log
 from math import log
 import os
 import os
 import sqlite3
 import sqlite3
-from typing import List, Dict, Optional, Any, Union
+from typing import List, Dict, Optional, Any
 from abc import ABC, abstractmethod
 from abc import ABC, abstractmethod
 from config.settings import BG_DATA_PATH, DB_PATH, PRODUCT_DATA_PATH
 from config.settings import BG_DATA_PATH, DB_PATH, PRODUCT_DATA_PATH
 from logging import getLogger
 from logging import getLogger
 from datetime import datetime
 from datetime import datetime
-import uuid
 from cryptography.fernet import Fernet
 from cryptography.fernet import Fernet
 from config.settings import PIN_KEY
 from config.settings import PIN_KEY
 
 
 # Import models
 # Import models
 from models.user import User
 from models.user import User
-from models.items import Product, ProductWithQuantity
+from models.items import Product
 from models.sales import Sale
 from models.sales import Sale
 from models.blacklist import Blacklist
 from models.blacklist import Blacklist
 
 
@@ -28,14 +27,14 @@ ESQUEMA DE BASE DE DATOS SQLITE (data.db)
 -----------------------------------
 -----------------------------------
 - id           INTEGER PRIMARY KEY AUTOINCREMENT
 - id           INTEGER PRIMARY KEY AUTOINCREMENT
 - email       TEXT UNIQUE NOT NULL
 - email       TEXT UNIQUE NOT NULL
-- nombre       TEXT NOT NULL
+- name       TEXT NOT NULL
 - rut          TEXT UNIQUE NOT NULL
 - rut          TEXT UNIQUE NOT NULL
 - pin_hash     TEXT NOT NULL (encriptado)
 - pin_hash     TEXT NOT NULL (encriptado)
 - kleincoins   TEXT NOT NULL (encriptado, valor por defecto "0")
 - kleincoins   TEXT NOT NULL (encriptado, valor por defecto "0")
 - created_at   TEXT NOT NULL (fecha de creación en formato ISO 8601)
 - created_at   TEXT NOT NULL (fecha de creación en formato ISO 8601)
 (Guarda la información del usuario con su pin hasheado y kleincoins encriptadas)
 (Guarda la información del usuario con su pin hasheado y kleincoins encriptadas)
 
 
-2. Tabla: productos
+2. Tabla: products
 -----------------------------------
 -----------------------------------
 - id           INTEGER PRIMARY KEY
 - id           INTEGER PRIMARY KEY
 - name         TEXT NOT NULL
 - name         TEXT NOT NULL
@@ -46,21 +45,21 @@ ESQUEMA DE BASE DE DATOS SQLITE (data.db)
 - status       INTEGER DEFAULT 1 NOT NULL CHECK (status IN (0, 1)) -- 0: Inactivo, 1: Activo
 - status       INTEGER DEFAULT 1 NOT NULL CHECK (status IN (0, 1)) -- 0: Inactivo, 1: Activo
 (Guarda los productos disponibles para venta con su estado activo/inactivo)
 (Guarda los productos disponibles para venta con su estado activo/inactivo)
 
 
-3. Tabla: ventas
+3. Tabla: sales
 -----------------------------------
 -----------------------------------
 - id           INTEGER PRIMARY KEY AUTOINCREMENT
 - id           INTEGER PRIMARY KEY AUTOINCREMENT
 - user_id      INTEGER NOT NULL (relación a users.id)
 - user_id      INTEGER NOT NULL (relación a users.id)
 - total        REAL NOT NULL (precio total de la venta)
 - total        REAL NOT NULL (precio total de la venta)
 - fudo_id      TEXT UNIQUE NOT NULL (ID string único por venta)
 - fudo_id      TEXT UNIQUE NOT NULL (ID string único por venta)
-- fecha        TEXT NOT NULL (fecha y hora en formato ISO 8601)
+- date        TEXT NOT NULL (fecha y hora en formato ISO 8601)
 - table        INTEGER NOT NULL (número de mesa)
 - table        INTEGER NOT NULL (número de mesa)
 (Guarda cada venta, asociada a un usuario y mesa)
 (Guarda cada venta, asociada a un usuario y mesa)
 
 
-4. Tabla: venta_productos
+4. Tabla: sale_products
 -----------------------------------
 -----------------------------------
-- venta_id     INTEGER NOT NULL (relación a ventas.id)
-- producto_id  INTEGER NOT NULL (relación a productos.id)
-- cantidad     INTEGER NOT NULL DEFAULT 1 (cantidad del producto)
+- sale_id     INTEGER NOT NULL (relación a sales.id)
+- product_id  INTEGER NOT NULL (relación a products.id)
+- quantity    INTEGER NOT NULL DEFAULT 1 (cantidad del producto)
 (Relación muchos a muchos entre ventas y productos con cantidad)
 (Relación muchos a muchos entre ventas y productos con cantidad)
 
 
 5. Tabla: blacklist
 5. Tabla: blacklist
@@ -71,9 +70,9 @@ ESQUEMA DE BASE DE DATOS SQLITE (data.db)
 
 
 RELACIONES:
 RELACIONES:
 -----------------------------------
 -----------------------------------
-- users puede tener muchas ventas
-- ventas puede tener muchos productos (y viceversa), por eso se usa una tabla intermedia (venta_productos)
-- productos pueden repetirse en múltiples ventas
+- users puede tener muchas sales
+- sales puede tener muchos productos (y viceversa), por eso se usa una tabla intermedia (sale_products)
+- products pueden repetirse en múltiples sales
 """
 """
 
 
 # Base abstract class for data access
 # Base abstract class for data access
@@ -117,14 +116,14 @@ class BaseDataService(ABC):
 class UserDataService(BaseDataService):
 class UserDataService(BaseDataService):
     """Service for managing user data"""
     """Service for managing user data"""
     #region Create
     #region Create
-    def create(self, nombre: str, email: str, rut: str, pin_hash: str) -> int:
+    def create(self, name: str, email: str, rut: str, pin_hash: str) -> int:
         """Add a new user to the database"""
         """Add a new user to the database"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         try:
         try:
             cursor.execute(
             cursor.execute(
-                "INSERT INTO users (nombre, email, rut, pin_hash, kleincoins, created_at) VALUES (?, ?, ?, ?, ?, ?)",
-                (nombre, email, rut, fernet.encrypt(pin_hash.encode()).decode(), fernet.encrypt(b"0").decode(), datetime.now().isoformat())
+                "INSERT INTO users (name, email, rut, pin_hash, kleincoins, created_at) VALUES (?, ?, ?, ?, ?, ?)",
+                (name, email, rut, fernet.encrypt(pin_hash.encode()).decode(), fernet.encrypt(b"0").decode(), datetime.now().isoformat())
             )
             )
             conn.commit()
             conn.commit()
             user_id = cursor.lastrowid
             user_id = cursor.lastrowid
@@ -152,7 +151,7 @@ class UserDataService(BaseDataService):
             User(
             User(
                 id=user[0],
                 id=user[0],
                 email=user[1],
                 email=user[1],
-                nombre=user[2],
+                name=user[2],
                 rut=user[3],
                 rut=user[3],
                 pin_hash=fernet.decrypt(user[4].encode()).decode(),
                 pin_hash=fernet.decrypt(user[4].encode()).decode(),
                 kleincoins=fernet.decrypt(user[5].encode()).decode(),
                 kleincoins=fernet.decrypt(user[5].encode()).decode(),
@@ -171,7 +170,7 @@ class UserDataService(BaseDataService):
             return User(
             return User(
                 id=user[0],
                 id=user[0],
                 email=user[1],
                 email=user[1],
-                nombre=user[2],
+                name=user[2],
                 rut=user[3],
                 rut=user[3],
                 pin_hash=fernet.decrypt(user[4].encode()).decode(),
                 pin_hash=fernet.decrypt(user[4].encode()).decode(),
                 kleincoins=fernet.decrypt(user[5].encode()).decode(),
                 kleincoins=fernet.decrypt(user[5].encode()).decode(),
@@ -191,7 +190,7 @@ class UserDataService(BaseDataService):
             return User(
             return User(
                 id=user[0],
                 id=user[0],
                 email=user[1],
                 email=user[1],
-                nombre=user[2],
+                name=user[2],
                 rut=user[3],
                 rut=user[3],
                 pin_hash=user[4],
                 pin_hash=user[4],
                 kleincoins=fernet.decrypt(user[5].encode()).decode(),
                 kleincoins=fernet.decrypt(user[5].encode()).decode(),
@@ -221,7 +220,7 @@ class UserDataService(BaseDataService):
             return User(
             return User(
                 id=user[0],
                 id=user[0],
                 email=user[1],
                 email=user[1],
-                nombre=user[2],
+                name=user[2],
                 rut=user[3],
                 rut=user[3],
                 pin_hash=fernet.decrypt(user[4].encode()).decode(),
                 pin_hash=fernet.decrypt(user[4].encode()).decode(),
                 kleincoins=fernet.decrypt(user[5].encode()).decode(),
                 kleincoins=fernet.decrypt(user[5].encode()).decode(),
@@ -230,7 +229,7 @@ class UserDataService(BaseDataService):
         return None
         return None
     #endregion
     #endregion
     #region Update
     #region Update
-    def update(self, user_id: int, email=None, nombre=None, rut=None, pin_hash=None, kleincoins=None) -> bool:
+    def update(self, user_id: int, email=None, name=None, rut=None, pin_hash=None, kleincoins=None) -> bool:
         """Update user information in the database"""
         """Update user information in the database"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
@@ -239,9 +238,9 @@ class UserDataService(BaseDataService):
         if email:
         if email:
             updates.append("email = ?")
             updates.append("email = ?")
             params.append(email)
             params.append(email)
-        if nombre:
-            updates.append("nombre = ?")
-            params.append(nombre)
+        if name:
+            updates.append("name = ?")
+            params.append(name)
         if rut:
         if rut:
             updates.append("rut = ?")
             updates.append("rut = ?")
             params.append(rut)
             params.append(rut)
@@ -348,7 +347,7 @@ class BlacklistDataService(BaseDataService):
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute("""
         cursor.execute("""
-            SELECT b.id, b.user_id, u.email, u.nombre, u.rut 
+            SELECT b.id, b.user_id, u.email, u.name, u.rut 
             FROM blacklist b 
             FROM blacklist b 
             LEFT JOIN users u ON b.user_id = u.id
             LEFT JOIN users u ON b.user_id = u.id
         """)
         """)
@@ -359,7 +358,7 @@ class BlacklistDataService(BaseDataService):
                 id=row[0],
                 id=row[0],
                 user_id=row[1],
                 user_id=row[1],
                 email=row[2],
                 email=row[2],
-                nombre=row[3],
+                name=row[3],
                 rut=row[4]
                 rut=row[4]
             ) for row in blacklisted
             ) for row in blacklisted
         ]
         ]
@@ -369,7 +368,7 @@ class BlacklistDataService(BaseDataService):
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute("""
         cursor.execute("""
-            SELECT b.id, b.user_id, u.email, u.nombre, u.rut 
+            SELECT b.id, b.user_id, u.email, u.name, u.rut 
             FROM blacklist b 
             FROM blacklist b 
             LEFT JOIN users u ON b.user_id = u.id 
             LEFT JOIN users u ON b.user_id = u.id 
             WHERE b.id = ?
             WHERE b.id = ?
@@ -381,7 +380,7 @@ class BlacklistDataService(BaseDataService):
                 id=row[0],
                 id=row[0],
                 user_id=row[1],
                 user_id=row[1],
                 email=row[2],
                 email=row[2],
-                nombre=row[3],
+                name=row[3],
                 rut=row[4]
                 rut=row[4]
             )
             )
         return None
         return None
@@ -450,7 +449,7 @@ class ProductDataService(BaseDataService):
         cursor = conn.cursor()
         cursor = conn.cursor()
         try:
         try:
             cursor.execute(
             cursor.execute(
-                "INSERT INTO productos (id, name, type, description, price, image, status) VALUES (?, ?, ?, ?, ?, ?, ?)",
+                "INSERT INTO products (id, name, type, description, price, image, status) VALUES (?, ?, ?, ?, ?, ?, ?)",
                 (id, name, type, description, price, image, status)
                 (id, name, type, description, price, image, status)
             )
             )
             conn.commit()
             conn.commit()
@@ -490,7 +489,7 @@ class ProductDataService(BaseDataService):
         """Get all products from the database"""
         """Get all products from the database"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
-        cursor.execute("SELECT * FROM productos")
+        cursor.execute("SELECT * FROM products")
         products = cursor.fetchall()
         products = cursor.fetchall()
         conn.close()
         conn.close()
         return [
         return [
@@ -509,7 +508,7 @@ class ProductDataService(BaseDataService):
         """Get product by ID"""
         """Get product by ID"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
-        cursor.execute("SELECT * FROM productos WHERE id = ?", (product_id,))
+        cursor.execute("SELECT * FROM products WHERE id = ?", (product_id,))
         product = cursor.fetchone()
         product = cursor.fetchone()
         conn.close()
         conn.close()
         if product:
         if product:
@@ -528,7 +527,7 @@ class ProductDataService(BaseDataService):
         """Get products by type"""
         """Get products by type"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
-        cursor.execute("SELECT * FROM productos WHERE type = ?", (product_type,))
+        cursor.execute("SELECT * FROM products WHERE type = ?", (product_type,))
         products = cursor.fetchall()
         products = cursor.fetchall()
         conn.close()
         conn.close()
         return [
         return [
@@ -547,7 +546,7 @@ class ProductDataService(BaseDataService):
         """Search products by name"""
         """Search products by name"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
-        cursor.execute("SELECT * FROM productos WHERE name LIKE ?", (f"%{name}%",))
+        cursor.execute("SELECT * FROM products WHERE name LIKE ?", (f"%{name}%",))
         products = cursor.fetchall()
         products = cursor.fetchall()
         conn.close()
         conn.close()
         return [
         return [
@@ -569,7 +568,7 @@ class ProductDataService(BaseDataService):
         placeholders = ', '.join('?' for _ in product_ids)
         placeholders = ', '.join('?' for _ in product_ids)
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
-        cursor.execute(f"SELECT * FROM productos WHERE id IN ({placeholders})", product_ids)
+        cursor.execute(f"SELECT * FROM products WHERE id IN ({placeholders})", product_ids)
         products = cursor.fetchall()
         products = cursor.fetchall()
         conn.close()
         conn.close()
         return [
         return [
@@ -613,7 +612,7 @@ class ProductDataService(BaseDataService):
             conn.close()
             conn.close()
             return False
             return False
         try:
         try:
-            cursor.execute(f"UPDATE productos SET {', '.join(updates)} WHERE id = ?", (*params, product_id))
+            cursor.execute(f"UPDATE products SET {', '.join(updates)} WHERE id = ?", (*params, product_id))
             conn.commit()
             conn.commit()
             success = cursor.rowcount > 0
             success = cursor.rowcount > 0
             if success:
             if success:
@@ -629,7 +628,7 @@ class ProductDataService(BaseDataService):
         """Get only active products (status = 1)"""
         """Get only active products (status = 1)"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
-        cursor.execute("SELECT * FROM productos WHERE status = 1")
+        cursor.execute("SELECT * FROM products WHERE status = 1")
         products = cursor.fetchall()
         products = cursor.fetchall()
         conn.close()
         conn.close()
         return [
         return [
@@ -648,7 +647,7 @@ class ProductDataService(BaseDataService):
         """Get only inactive products (status = 0)"""
         """Get only inactive products (status = 0)"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
-        cursor.execute("SELECT * FROM productos WHERE status = 0")
+        cursor.execute("SELECT * FROM products WHERE status = 0")
         products = cursor.fetchall()
         products = cursor.fetchall()
         conn.close()
         conn.close()
         return [
         return [
@@ -683,7 +682,7 @@ class ProductDataService(BaseDataService):
         """Delete a product from the database"""
         """Delete a product from the database"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
-        cursor.execute("DELETE FROM productos WHERE id = ?", (product_id,))
+        cursor.execute("DELETE FROM products WHERE id = ?", (product_id,))
         conn.commit()
         conn.commit()
         success = cursor.rowcount > 0
         success = cursor.rowcount > 0
         conn.close()
         conn.close()
@@ -698,7 +697,7 @@ class ProductDataService(BaseDataService):
 class SalesDataService(BaseDataService):
 class SalesDataService(BaseDataService):
     """Service for managing sales"""
     """Service for managing sales"""
     #region C
     #region C
-    def create(self, user_id: int,fudo_id:str, total: float, table: int, product_ids: List[int], quantities: Optional[List[int]] = None) -> int:
+    def create(self, user_id: int, fudo_id: str, total: float, table: int, product_ids: List[int], quantities: Optional[List[int]] = None) -> int:
         """Create a new sale with products and quantities"""
         """Create a new sale with products and quantities"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
@@ -707,7 +706,7 @@ class SalesDataService(BaseDataService):
             
             
             # Insert sale
             # Insert sale
             cursor.execute(
             cursor.execute(
-                "INSERT INTO ventas (user_id, total, fudo_id, fecha, 'table') VALUES (?, ?, ?, ?, ?)",
+                "INSERT INTO sales (user_id, total, fudo_id, date, 'table') VALUES (?, ?, ?, ?, ?)",
                 (user_id, total, fudo_id, fecha, table)
                 (user_id, total, fudo_id, fecha, table)
             )
             )
             sale_id = cursor.lastrowid
             sale_id = cursor.lastrowid
@@ -720,7 +719,7 @@ class SalesDataService(BaseDataService):
                 for i, product_id in enumerate(product_ids):
                 for i, product_id in enumerate(product_ids):
                     quantity = quantities[i] if i < len(quantities) else 1
                     quantity = quantities[i] if i < len(quantities) else 1
                     cursor.execute(
                     cursor.execute(
-                        "INSERT INTO venta_productos (venta_id, producto_id, cantidad) VALUES (?, ?, ?)",
+                        "INSERT INTO sale_products (sale_id, product_id, quantity) VALUES (?, ?, ?)",
                         (sale_id, product_id, quantity)
                         (sale_id, product_id, quantity)
                     )
                     )
             
             
@@ -745,7 +744,7 @@ class SalesDataService(BaseDataService):
         cursor = conn.cursor()
         cursor = conn.cursor()
         try:
         try:
             cursor.execute(
             cursor.execute(
-                "INSERT INTO venta_productos (venta_id, producto_id, cantidad) VALUES (?, ?, ?)",
+                "INSERT INTO sale_products (sale_id, product_id, quantity) VALUES (?, ?, ?)",
                 (sale_id, product_id, quantity)
                 (sale_id, product_id, quantity)
             )
             )
             conn.commit()
             conn.commit()
@@ -759,6 +758,31 @@ class SalesDataService(BaseDataService):
         finally:
         finally:
             conn.close()
             conn.close()
     
     
+    def add_products_to_sale(self, sale_id: int, product_ids: List[int], quantities: Optional[List[int]] = None) -> bool:
+        """Add multiple products to an existing sale with quantities"""
+        conn = self._get_connection()
+        cursor = conn.cursor()
+        try:
+            if quantities is None:
+                quantities = [1] * len(product_ids)  # Default quantity 1
+            
+            for i, product_id in enumerate(product_ids):
+                quantity = quantities[i] if i < len(quantities) else 1
+                cursor.execute(
+                    "INSERT INTO sale_products (sale_id, product_id, quantity) VALUES (?, ?, ?)",
+                    (sale_id, product_id, quantity)
+                )
+            
+            conn.commit()
+            success = cursor.rowcount > 0
+            if success:
+                logger.info(f"Products added to sale {sale_id}.")
+            return success
+        except sqlite3.IntegrityError as e:
+            logger.error(f"Failed to add products to sale: {e}")
+            return False
+        finally:
+            conn.close()
     #endregion
     #endregion
     #region R
     #region R
     def get_all(self) -> List[Sale]:
     def get_all(self) -> List[Sale]:
@@ -766,10 +790,10 @@ class SalesDataService(BaseDataService):
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute("""
         cursor.execute("""
-            SELECT v.id, v.user_id, v.total, v.fudo_id, v.fecha, v.table, u.nombre, u.email
-            FROM ventas v
-            LEFT JOIN users u ON v.user_id = u.id
-            ORDER BY v.fecha DESC
+            SELECT s.id, s.user_id, s.total, s.fudo_id, s.date, s.table, u.name, u.email
+            FROM sales s
+            LEFT JOIN users u ON s.user_id = u.id
+            ORDER BY s.date DESC
         """)
         """)
         sales = cursor.fetchall()
         sales = cursor.fetchall()
         conn.close()
         conn.close()
@@ -779,10 +803,11 @@ class SalesDataService(BaseDataService):
                 user_id=sale[1],
                 user_id=sale[1],
                 total=sale[2],
                 total=sale[2],
                 fudo_id=sale[3],
                 fudo_id=sale[3],
-                fecha=sale[4],
+                date=sale[4],
                 table=sale[5],
                 table=sale[5],
-                user_name=sale[6],
-                user_email=sale[7]
+                username=sale[6],
+                user_email=sale[7],
+                products=self.get_sale_products(sale[0])
             ) for sale in sales
             ) for sale in sales
         ]
         ]
     
     
@@ -791,10 +816,10 @@ class SalesDataService(BaseDataService):
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute("""
         cursor.execute("""
-            SELECT v.id, v.user_id, v.total, v.fudo_id, v.fecha, v.table, u.nombre, u.email
-            FROM ventas v
-            LEFT JOIN users u ON v.user_id = u.id
-            WHERE v.id = ?
+            SELECT s.id, s.user_id, s.total, s.fudo_id, s.date, s.table, u.name, u.email
+            FROM sales s
+            LEFT JOIN users u ON s.user_id = u.id
+            WHERE s.id = ?
         """, (sale_id,))
         """, (sale_id,))
         sale = cursor.fetchone()
         sale = cursor.fetchone()
         conn.close()
         conn.close()
@@ -804,9 +829,9 @@ class SalesDataService(BaseDataService):
                 user_id=sale[1],
                 user_id=sale[1],
                 total=sale[2],
                 total=sale[2],
                 fudo_id=sale[3],
                 fudo_id=sale[3],
-                fecha=sale[4],
+                date=sale[4],
                 table=sale[5],
                 table=sale[5],
-                user_name=sale[6],
+                username=sale[6],
                 user_email=sale[7]
                 user_email=sale[7]
             )
             )
         return None
         return None
@@ -816,10 +841,10 @@ class SalesDataService(BaseDataService):
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute("""
         cursor.execute("""
-            SELECT v.id, v.user_id, v.total, v.fudo_id, v.fecha, v.table, u.nombre, u.email
-            FROM ventas v
-            LEFT JOIN users u ON v.user_id = u.id
-            WHERE v.fudo_id = ?
+            SELECT s.id, s.user_id, s.total, s.fudo_id, s.date, s.table, u.name, u.email
+            FROM sales s
+            LEFT JOIN users u ON s.user_id = u.id
+            WHERE s.fudo_id = ?
         """, (fudo_id,))
         """, (fudo_id,))
         sale = cursor.fetchone()
         sale = cursor.fetchone()
         conn.close()
         conn.close()
@@ -829,9 +854,9 @@ class SalesDataService(BaseDataService):
                 user_id=sale[1],
                 user_id=sale[1],
                 total=sale[2],
                 total=sale[2],
                 fudo_id=sale[3],
                 fudo_id=sale[3],
-                fecha=sale[4],
+                date=sale[4],
                 table=sale[5],
                 table=sale[5],
-                user_name=sale[6],
+                username=sale[6],
                 user_email=sale[7]
                 user_email=sale[7]
             )
             )
         return None
         return None
@@ -842,43 +867,57 @@ class SalesDataService(BaseDataService):
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute(
         cursor.execute(
             """
             """
-            SELECT v.id, v.user_id, v.total, v.fudo_id, v.fecha, v."table", u.nombre, u.email
-            FROM ventas v
-            LEFT JOIN users u ON v.user_id = u.id
-            WHERE v.user_id = ?
-            ORDER BY v.fecha DESC
+            SELECT s.id, s.user_id, s.total, s.fudo_id, s.date, s."table", u.name, u.email
+            FROM sales s
+            LEFT JOIN users u ON s.user_id = u.id
+            WHERE s.user_id = ?
+            ORDER BY s.date DESC
             """,
             """,
             (user_id,)
             (user_id,)
         )
         )
+
         sales = cursor.fetchall()
         sales = cursor.fetchall()
         conn.close()
         conn.close()
+
         return [
         return [
             Sale(
             Sale(
                 id=sale[0],
                 id=sale[0],
                 user_id=sale[1],
                 user_id=sale[1],
                 total=sale[2],
                 total=sale[2],
                 fudo_id=sale[3],
                 fudo_id=sale[3],
-                fecha=sale[4],
+                date=sale[4],
                 table=sale[5],
                 table=sale[5],
-                user_name=sale[6],
-                user_email=sale[7]
+                username=sale[6],
+                user_email=sale[7],
+                products=self.get_sale_products(sale[0])
             ) for sale in sales
             ) for sale in sales
         ]
         ]
     
     
-    def get_sale_products(self, sale_id: int) -> List[ProductWithQuantity]:
+    def get_sale_products_ids(self, sale_id: int) -> List[int]:
+        """Get product IDs for a specific sale"""
+        conn = self._get_connection()
+        cursor = conn.cursor()
+        cursor.execute("""
+            SELECT product_id FROM sale_products WHERE sale_id = ?
+        """, (sale_id,))
+        products = cursor.fetchall()
+        conn.close()
+        return [product[0] for product in products]
+
+    def get_sale_products(self, sale_id: int) -> List[Product]:
         """Get products for a specific sale with quantities"""
         """Get products for a specific sale with quantities"""
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute("""
         cursor.execute("""
-            SELECT p.id, p.name, p.type, p.description, p.price, p.image, p.status, vp.cantidad
-            FROM venta_productos vp
-            JOIN productos p ON vp.producto_id = p.id
-            WHERE vp.venta_id = ?
+            SELECT p.id, p.name, p.type, p.description, p.price, p.image, p.status, sp.quantity
+            FROM sale_products sp
+            JOIN products p ON sp.product_id = p.id
+            WHERE sp.sale_id = ?
         """, (sale_id,))
         """, (sale_id,))
         products = cursor.fetchall()
         products = cursor.fetchall()
         conn.close()
         conn.close()
         return [
         return [
-            ProductWithQuantity(
+            Product(
                 id=product[0],
                 id=product[0],
                 name=product[1],
                 name=product[1],
                 type=product[2],
                 type=product[2],
@@ -886,7 +925,7 @@ class SalesDataService(BaseDataService):
                 price=product[4],
                 price=product[4],
                 image=product[5],
                 image=product[5],
                 status=product[6],
                 status=product[6],
-                cantidad=product[7]
+                quantity=product[7]
             ) for product in products
             ) for product in products
         ]
         ]
     
     
@@ -896,11 +935,11 @@ class SalesDataService(BaseDataService):
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute(
         cursor.execute(
             """
             """
-            SELECT v.id, v.user_id, v.total, v.fudo_id, v.fecha, v."table", u.nombre, u.email
-            FROM ventas v
-            LEFT JOIN users u ON v.user_id = u.id
-            WHERE v."table" = ?
-            ORDER BY v.fecha DESC
+            SELECT s.id, s.user_id, s.total, s.fudo_id, s.date, s."table", u.name, u.email
+            FROM sales s
+            LEFT JOIN users u ON s.user_id = u.id
+            WHERE s."table" = ?
+            ORDER BY s.date DESC
             """,
             """,
             (table,)
             (table,)
         )
         )
@@ -912,9 +951,9 @@ class SalesDataService(BaseDataService):
                 user_id=sale[1],
                 user_id=sale[1],
                 total=sale[2],
                 total=sale[2],
                 fudo_id=sale[3],
                 fudo_id=sale[3],
-                fecha=sale[4],
+                date=sale[4],
                 table=sale[5],
                 table=sale[5],
-                user_name=sale[6],
+                username=sale[6],
                 user_email=sale[7]
                 user_email=sale[7]
             ) for sale in sales
             ) for sale in sales
         ]
         ]
@@ -925,7 +964,7 @@ class SalesDataService(BaseDataService):
         cursor = conn.cursor()
         cursor = conn.cursor()
         try:
         try:
             cursor.execute(
             cursor.execute(
-                "UPDATE venta_productos SET cantidad = ? WHERE venta_id = ? AND producto_id = ?",
+                "UPDATE sale_products SET quantity = ? WHERE sale_id = ? AND product_id = ?",
                 (new_quantity, sale_id, product_id)
                 (new_quantity, sale_id, product_id)
             )
             )
             conn.commit()
             conn.commit()
@@ -944,7 +983,7 @@ class SalesDataService(BaseDataService):
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute(
         cursor.execute(
-            "SELECT cantidad FROM venta_productos WHERE venta_id = ? AND producto_id = ?",
+            "SELECT quantity FROM sale_products WHERE sale_id = ? AND product_id = ?",
             (sale_id, product_id)
             (sale_id, product_id)
         )
         )
         result = cursor.fetchone()
         result = cursor.fetchone()
@@ -971,7 +1010,7 @@ class SalesDataService(BaseDataService):
             conn.close()
             conn.close()
             return False
             return False
         try:
         try:
-            cursor.execute(f"UPDATE ventas SET {', '.join(updates)} WHERE id = ?", (*params, sale_id))
+            cursor.execute(f"UPDATE sales SET {', '.join(updates)} WHERE id = ?", (*params, sale_id))
             conn.commit()
             conn.commit()
             success = cursor.rowcount > 0
             success = cursor.rowcount > 0
             if success:
             if success:
@@ -990,9 +1029,9 @@ class SalesDataService(BaseDataService):
         cursor = conn.cursor()
         cursor = conn.cursor()
         try:
         try:
             # Delete sale-product relationships first
             # Delete sale-product relationships first
-            cursor.execute("DELETE FROM venta_productos WHERE venta_id = ?", (sale_id,))
+            cursor.execute("DELETE FROM sale_products WHERE sale_id = ?", (sale_id,))
             # Delete the sale
             # Delete the sale
-            cursor.execute("DELETE FROM ventas WHERE id = ?", (sale_id,))
+            cursor.execute("DELETE FROM sales WHERE id = ?", (sale_id,))
             conn.commit()
             conn.commit()
             success = cursor.rowcount > 0
             success = cursor.rowcount > 0
             if success:
             if success:
@@ -1011,7 +1050,7 @@ class SalesDataService(BaseDataService):
         conn = self._get_connection()
         conn = self._get_connection()
         cursor = conn.cursor()
         cursor = conn.cursor()
         cursor.execute(
         cursor.execute(
-            "DELETE FROM venta_productos WHERE venta_id = ? AND producto_id = ?",
+            "DELETE FROM sale_products WHERE sale_id = ? AND product_id = ?",
             (sale_id, product_id)
             (sale_id, product_id)
         )
         )
         conn.commit()
         conn.commit()
@@ -1030,7 +1069,7 @@ class SalesDataService(BaseDataService):
         try:
         try:
             # Get current quantity
             # Get current quantity
             cursor.execute(
             cursor.execute(
-                "SELECT cantidad FROM venta_productos WHERE venta_id = ? AND producto_id = ?",
+                "SELECT quantity FROM sale_products WHERE sale_id = ? AND product_id = ?",
                 (sale_id, product_id)
                 (sale_id, product_id)
             )
             )
             result = cursor.fetchone()
             result = cursor.fetchone()
@@ -1043,14 +1082,14 @@ class SalesDataService(BaseDataService):
             if new_quantity <= 0:
             if new_quantity <= 0:
                 # Remove the product completely
                 # Remove the product completely
                 cursor.execute(
                 cursor.execute(
-                    "DELETE FROM venta_productos WHERE venta_id = ? AND producto_id = ?",
+                    "DELETE FROM sale_products WHERE sale_id = ? AND product_id = ?",
                     (sale_id, product_id)
                     (sale_id, product_id)
                 )
                 )
                 logger.info(f"Product {product_id} removed from sale {sale_id} (quantity reached 0).")
                 logger.info(f"Product {product_id} removed from sale {sale_id} (quantity reached 0).")
             else:
             else:
                 # Update with new quantity
                 # Update with new quantity
                 cursor.execute(
                 cursor.execute(
-                    "UPDATE venta_productos SET cantidad = ? WHERE venta_id = ? AND producto_id = ?",
+                    "UPDATE sale_products SET quantity = ? WHERE sale_id = ? AND product_id = ?",
                     (new_quantity, sale_id, product_id)
                     (new_quantity, sale_id, product_id)
                 )
                 )
                 logger.info(f"Product {product_id} quantity decreased to {new_quantity} in sale {sale_id}.")
                 logger.info(f"Product {product_id} quantity decreased to {new_quantity} in sale {sale_id}.")
@@ -1118,7 +1157,7 @@ def initialize_db():
     CREATE TABLE IF NOT EXISTS users (
     CREATE TABLE IF NOT EXISTS users (
         id INTEGER PRIMARY KEY AUTOINCREMENT,
         id INTEGER PRIMARY KEY AUTOINCREMENT,
         email TEXT UNIQUE NOT NULL,
         email TEXT UNIQUE NOT NULL,
-        nombre TEXT NOT NULL,
+        name TEXT NOT NULL,
         rut TEXT UNIQUE NOT NULL,
         rut TEXT UNIQUE NOT NULL,
         pin_hash TEXT NOT NULL,
         pin_hash TEXT NOT NULL,
         kleincoins TEXT NOT NULL,
         kleincoins TEXT NOT NULL,
@@ -1127,9 +1166,9 @@ def initialize_db():
     """)
     """)
 
 
     # Crear tabla de productos
     # Crear tabla de productos
-    logger.info("Creando tabla de productos...")
+    logger.info("Creando tabla de products...")
     cursor.execute("""
     cursor.execute("""
-    CREATE TABLE IF NOT EXISTS productos (
+    CREATE TABLE IF NOT EXISTS products (
         id INTEGER PRIMARY KEY,
         id INTEGER PRIMARY KEY,
         name TEXT NOT NULL,
         name TEXT NOT NULL,
         type TEXT,
         type TEXT,
@@ -1141,28 +1180,28 @@ def initialize_db():
     """)
     """)
 
 
     # Crear tabla de ventas
     # Crear tabla de ventas
-    logger.info("Creando tabla de ventas...")
+    logger.info("Creando tabla de sales...")
     cursor.execute("""
     cursor.execute("""
-    CREATE TABLE IF NOT EXISTS ventas (
+    CREATE TABLE IF NOT EXISTS sales (
         id INTEGER PRIMARY KEY AUTOINCREMENT,
         id INTEGER PRIMARY KEY AUTOINCREMENT,
         user_id INTEGER NOT NULL,
         user_id INTEGER NOT NULL,
         total REAL NOT NULL,
         total REAL NOT NULL,
-        fudo_id TEXT UNIQUE NOT NULL,
-        fecha TEXT NOT NULL,
+        fudo_id TEXT NOT NULL,
+        date TEXT NOT NULL,
         "table" INTEGER NOT NULL,
         "table" INTEGER NOT NULL,
         FOREIGN KEY (user_id) REFERENCES users(id)
         FOREIGN KEY (user_id) REFERENCES users(id)
     );
     );
     """)
     """)
 
 
     # Crear tabla intermedia para ventas y productos
     # Crear tabla intermedia para ventas y productos
-    logger.info("Creando tabla intermedia de venta_productos...")
+    logger.info("Creando tabla intermedia de sale_products...")
     cursor.execute("""
     cursor.execute("""
-    CREATE TABLE IF NOT EXISTS venta_productos (
-        venta_id INTEGER NOT NULL,
-        producto_id INTEGER NOT NULL,
-        cantidad INTEGER NOT NULL DEFAULT 1,
-        FOREIGN KEY (venta_id) REFERENCES ventas(id),
-        FOREIGN KEY (producto_id) REFERENCES productos(id)
+    CREATE TABLE IF NOT EXISTS sale_products (
+        sale_id INTEGER NOT NULL,
+        product_id INTEGER NOT NULL,
+        quantity INTEGER NOT NULL DEFAULT 1,
+        FOREIGN KEY (sale_id) REFERENCES sales(id),
+        FOREIGN KEY (product_id) REFERENCES products(id)
     );
     );
     """)
     """)