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

add history table in shopping cart

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

+ 1 - 0
.gitignore

@@ -10,3 +10,4 @@ llm_logs.*
 dksdabjhvjhSADhsbjksf.txt
 data/data.db
 /logs
+mrda.txt

+ 4 - 0
app.py

@@ -2,6 +2,8 @@ from time import struct_time
 from fastapi import FastAPI
 from starlette.middleware.sessions import SessionMiddleware
 from config.settings import SECRET_KEY, validate_config
+from routes import sales
+
 
 
 def create_app() -> FastAPI:
@@ -37,6 +39,8 @@ def setup_routes(app: FastAPI):
     # Order routes
     app.include_router(orders.order_router, prefix="/api/orders", tags=["Orders"], dependencies=[Depends(get_current_user)])
     
+    # Sales routes
+    app.include_router(sales.sales_router, prefix="/api/sales", tags=["Sales"], dependencies=[Depends(get_current_user)])
     # Static routes
     from fastapi.responses import HTMLResponse
     app.add_api_route("/", static.serve_app_html, methods=["GET"], 

+ 1 - 0
config/messages.py

@@ -8,6 +8,7 @@ class ErrorResponse:
     USER_CREATION_ERROR = "Hubo un error al crear el usuario."
     INVALID_CREDENTIALS = "Correo electrónico o PIN inválidos."
     TOO_MANY_ATTEMPTS = "Demasiados intentos de inicio de sesión. Por favor, inténtelo más tarde."
+    SALE_NOT_FOUND = "No se encontraron ventas para este usuario."
 
 
 class SuccessResponse:

+ 1 - 2
models/__init__.py

@@ -2,7 +2,7 @@
 
 from .user import User, UserIDRequest, RegisterUserRequest
 from .items import Product, ProductWithQuantity
-from .sells import Sale, SellItem, ItemWeb, OrderWeb
+from .sales import Sale, ItemWeb, OrderWeb
 from .blacklist import Blacklist
 from .chat import Message, ChatCompletionRequest
 
@@ -13,7 +13,6 @@ __all__ = [
     "Product",
     "ProductWithQuantity",
     "Sale",
-    "SellItem",
     "ItemWeb",
     "OrderWeb", 
     "Blacklist",

+ 0 - 45
models/sells.py

@@ -1,45 +0,0 @@
-from typing import List, Optional
-from pydantic import BaseModel
-
-class ItemWeb(BaseModel):
-    id: int
-    quantity: int
-
-class OrderWeb(BaseModel):
-    customerId: int
-    items: List[ItemWeb]
-    totalAmount: float
-    orderDate: str
-    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):
-    """Sale model matching the database schema"""
-    id: int
-    user_id: int
-    total: float
-    fudo_id: str
-    fecha: str
-    table: int
-    user_name: Optional[str] = None
-    user_email: Optional[str] = None
-
-class SellItem(BaseModel):
-    """Legacy model - use Sale instead"""
-    user_id: int
-    products: list[Product]
-    total: float
-    fudo_id: str
-    fecha: str
-    table: int  

+ 48 - 3
public/main/index.html

@@ -9,7 +9,7 @@
   <link rel="stylesheet" as="style" onload="this.rel='stylesheet'"
         href="https://fonts.googleapis.com/css2?display=swap&family=Noto+Sans:wght@400;500;700;900&family=Spline+Sans:wght@400;500;700">
   <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
-  <link rel="stylesheet" href="/express/animations.css">
+  <link rel="stylesheet" href="express/animations.css">
    <!--Tailwind-->
    <script>
         tailwind.config = {
@@ -27,8 +27,8 @@
     </script>
   <!-- Markdown -->
   <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
-  <script src="/express/js/app.js" type="module"></script>
-  <link rel="stylesheet" href="/express/styles.css">
+  <script src="express/js/app.js" type="module"></script>
+  <link rel="stylesheet" href="express/styles.css">
 </head>
 
 <body class="h-[100dvh] max-h-[100dvh] flex flex-col bg-gray-50 overflow-x-hidden"
@@ -157,6 +157,51 @@
           Envia tu orden
         </button>
       </footer>
+
+      <div class="max-w-4xl mx-auto bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
+    <!-- Header con nombre de usuario -->
+    <div class="bg-gray-50 px-6 py-4 border-b border-gray-200">
+      <h2 id="usernameTable" class="text-[19px] font-bold text-[#101419]">Pedido de Juan Pérez</h2>
+    </div>
+
+    <div class="overflow-x-auto">
+      <table id="historyTable" class="w-full">
+        <thead class="bg-gray-50 border-b border-gray-200">
+          <tr>
+            <th class="px-6 py-3 text-left text-sm font-bold text-[#101419]">Cantidad</th>
+            <th class="px-6 py-3 text-left text-sm font-bold text-[#101419]">Producto</th>
+            <th class="px-6 py-3 text-right text-sm font-bold text-[#101419]">Precio</th>
+          </tr>
+        </thead>
+        <tbody class="divide-y divide-gray-200">
+          <template id="historyRowTemplate">
+            <tr class="hover:bg-gray-50 transition-colors">
+              <td class="list-element-quantity px-6 py-4 text-sm text-[#58728d]">1</td>
+              <td class="px-6 py-4">
+                <div class="flex flex-col">
+                  <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>
+              </td>
+              <td class="list-element-price px-6 py-4 text-sm font-semibold text-[#101419] text-right">$6.000</td>
+            </tr>
+          </template>
+        </tbody>
+        
+        <!-- Total -->
+        <tfoot class="bg-gray-50 border-t border-gray-200">
+          <tr>
+            <td colspan="2" class="px-6 py-4 text-base font-bold text-[#101419] text-right">
+              Total General:
+            </td>
+            <td id="cartHistoryTotal" class="px-6 py-4 text-lg font-bold text-[#101419] text-right">
+              $0
+            </td>
+          </tr>
+        </tfoot>
+      </table>
+    </div>
+  </div>
     </section>
   </main>
 

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

@@ -3,6 +3,7 @@ import { getProducts, sendOrder } from './service/product.js';
 import { login } from './service/auth.js'
 import { createGlobalLoader, showGlobalLoader, hideGlobalLoader } from './utils/loader.js';
 import { showError } from './utils/error.js';
+import { setupShoppingCart } from './utils/shoppingCart.js';
 // --- Variables de Usuario ---
 let userId = -1;
 let userName = "Cliente";
@@ -38,8 +39,11 @@ const chatSuggestionsElement = document.getElementById("chatSuggestions");
 
 //#region --- Inicialización y Configuracion ---
 async function initializeApp() {
-    
-    showGlobalLoader();
+    updateCartDisplay();
+    initializeChat();
+    setupBasicListeners();
+    showGlobalLoader("Cargando productos...");
+    setupShoppingCart(userId, userToken,userName);
     await renderProducts();
     hideGlobalLoader();
 
@@ -72,8 +76,9 @@ function initializeLoginModal() {
             const {data} = await login(email, pin)
             userToken = data.token;
             userName = data.name;
+            userId = data.id;
             if (!userToken || data.id === undefined) {
-                showError(data.message || "Error al iniciar sesión.");
+                showError("Error al iniciar sesión.");
                 return;
             }
 
@@ -380,9 +385,6 @@ async function sendMessageToAI() {
 document.addEventListener("DOMContentLoaded", async () => {
 
     createGlobalLoader();
-    updateCartDisplay();
-    initializeChat()
-    setupBasicListeners();
     initializeLoginModal();
     // initializeApp()
 

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

@@ -33,7 +33,7 @@ async function login(email,pin){
     showError("Error al iniciar sesión, Intenta mas tarde.");
     throw new Error("Error al iniciar sesión.");
   }
-  return {data};
+  return {data: data.data};
 }
 
 

+ 2 - 1
public/main/js/utils/loader.js

@@ -15,9 +15,10 @@ function createGlobalLoader() {
     document.body.appendChild(globalLoaderElement);
 }
 
-function showGlobalLoader() {
+function showGlobalLoader(message = "Procesando su pedido...") {
     if (!globalLoaderElement) createGlobalLoader();
     globalLoaderElement.style.display = 'flex';
+    globalLoaderElement.querySelector("p").textContent = message;
     setTimeout(() => { if (globalLoaderElement) globalLoaderElement.style.opacity = '1'; }, 10);
 }
 

+ 1 - 1
routes/orders.py

@@ -4,7 +4,7 @@ import time
 from fastapi import HTTPException, APIRouter
 from fastapi.responses import JSONResponse
 from fudo import fudo
-from models.sells import OrderWeb
+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

+ 0 - 2
routes/sells.py

@@ -1,2 +0,0 @@
-from pydantic import BaseModel
-

+ 1 - 0
routes/users.py

@@ -74,6 +74,7 @@ async def login_user(request: LoginRequest):
     user = user_data_service.login(request.email, request.pin)
     if user:
         # Successful login, return user data and token
+        redis_client.delete(f"login_attempts:{request.email}")
         return JSONResponse(status_code=200, content={"message": SuccessResponse.LOGIN_SUCCESS, "data": {
             "id": user.id,
             "name": user.nombre,

+ 15 - 9
services/data_service.py

@@ -14,7 +14,7 @@ from config.settings import PIN_KEY
 # Import models
 from models.user import User
 from models.items import Product, ProductWithQuantity
-from models.sells import Sale
+from models.sales import Sale
 from models.blacklist import Blacklist
 
 fernet = Fernet(PIN_KEY.encode())
@@ -707,7 +707,7 @@ class SalesDataService(BaseDataService):
             
             # Insert sale
             cursor.execute(
-                "INSERT INTO ventas (user_id, total, fudo_id, fecha, table) VALUES (?, ?, ?, ?, ?)",
+                "INSERT INTO ventas (user_id, total, fudo_id, fecha, 'table') VALUES (?, ?, ?, ?, ?)",
                 (user_id, total, fudo_id, fecha, table)
             )
             sale_id = cursor.lastrowid
@@ -840,13 +840,16 @@ class SalesDataService(BaseDataService):
         """Get sales by user ID"""
         conn = self._get_connection()
         cursor = conn.cursor()
-        cursor.execute("""
-            SELECT v.id, v.user_id, v.total, v.fudo_id, v.fecha, v.table, u.nombre, u.email
+        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
-        """, (user_id,))
+            """,
+            (user_id,)
+        )
         sales = cursor.fetchall()
         conn.close()
         return [
@@ -891,13 +894,16 @@ class SalesDataService(BaseDataService):
         """Get sales by table number"""
         conn = self._get_connection()
         cursor = conn.cursor()
-        cursor.execute("""
-            SELECT v.id, v.user_id, v.total, v.fudo_id, v.fecha, v.table, u.nombre, u.email
+        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 = ?
+            WHERE v."table" = ?
             ORDER BY v.fecha DESC
-        """, (table,))
+            """,
+            (table,)
+        )
         sales = cursor.fetchall()
         conn.close()
         return [

+ 1 - 1
services/logging_service.py

@@ -1,7 +1,7 @@
 import csv
 import os
 from typing import List
-from models.sells import OrderWeb, ItemWeb
+from models.sales import OrderWeb, ItemWeb
 
 
 def log_order(username, table, order_date, items: List[str]):

+ 0 - 113
test_models.py

@@ -1,113 +0,0 @@
-#!/usr/bin/env python3
-"""
-Test script to verify the models are correctly defined
-"""
-
-# Test imports
-try:
-    from models.user import User, UserModel, UserIDRequest, RegisterUserRequest
-    print("✅ User models imported successfully")
-except ImportError as e:
-    print(f"❌ Error importing user models: {e}")
-
-try:
-    from models.items import Product, ProductWithQuantity
-    print("✅ Product models imported successfully")
-except ImportError as e:
-    print(f"❌ Error importing product models: {e}")
-
-try:
-    from models.sells import Sale, SellItem, ItemWeb, OrderWeb
-    print("✅ Sales models imported successfully")
-except ImportError as e:
-    print(f"❌ Error importing sales models: {e}")
-
-try:
-    from models.blacklist import Blacklist
-    print("✅ Blacklist model imported successfully")
-except ImportError as e:
-    print(f"❌ Error importing blacklist model: {e}")
-
-try:
-    from models.chat import Message, ChatCompletionRequest
-    print("✅ Chat models imported successfully")
-except ImportError as e:
-    print(f"❌ Error importing chat models: {e}")
-
-# Test model creation
-try:
-    user = User(
-        id=1,
-        email="test@example.com",
-        nombre="Test User",
-        rut="12345678-9",
-        pin_hash="hashed_pin",
-        kleincoins="100",
-        created_at="2023-01-01T00:00:00"
-    )
-    print("✅ User model creation successful")
-    print(f"   User: {user.nombre} ({user.email})")
-except Exception as e:
-    print(f"❌ Error creating user model: {e}")
-
-try:
-    product = Product(
-        id=1,
-        name="Test Product",
-        type="food",
-        description="A test product",
-        price=10.99,
-        image="test.jpg",
-        status=1
-    )
-    print("✅ Product model creation successful")
-    print(f"   Product: {product.name} - ${product.price}")
-except Exception as e:
-    print(f"❌ Error creating product model: {e}")
-
-try:
-    product_with_quantity = ProductWithQuantity(
-        id=1,
-        name="Test Product",
-        type="food",
-        description="A test product",
-        price=10.99,
-        image="test.jpg",
-        status=1,
-        cantidad=3
-    )
-    print("✅ ProductWithQuantity model creation successful")
-    print(f"   Product: {product_with_quantity.name} - Qty: {product_with_quantity.cantidad}")
-except Exception as e:
-    print(f"❌ Error creating ProductWithQuantity model: {e}")
-
-try:
-    sale = Sale(
-        id=1,
-        user_id=1,
-        total=50.99,
-        fudo_id="FUDO123",
-        fecha="2023-01-01T12:00:00",
-        table=5,
-        user_name="Test User",
-        user_email="test@example.com"
-    )
-    print("✅ Sale model creation successful")
-    print(f"   Sale: {sale.fudo_id} - Total: ${sale.total}")
-except Exception as e:
-    print(f"❌ Error creating sale model: {e}")
-
-try:
-    blacklist = Blacklist(
-        id=1,
-        user_id=1,
-        email="blocked@example.com",
-        nombre="Blocked User",
-        rut="98765432-1"
-    )
-    print("✅ Blacklist model creation successful")
-    print(f"   Blacklisted: {blacklist.nombre} ({blacklist.email})")
-except Exception as e:
-    print(f"❌ Error creating blacklist model: {e}")
-
-print("\n🎉 All model tests completed!")