Spaces:
Build error
Build error
Vo Minh Vu
commited on
Commit
·
738ecfc
1
Parent(s):
6c670dd
Upload chat with gemini api
Browse files- .vscode/launch.json +8 -0
- app.py +114 -18
- src/__init__.py +2 -2
- src/__pycache__/__init__.cpython-313.pyc +0 -0
- src/__pycache__/chat.cpython-313.pyc +0 -0
- src/chat.py +291 -275
- src/core/__pycache__/function_definitions.cpython-313.pyc +0 -0
- src/core/function_definitions.py +220 -18
- src/database/__pycache__/db_connection.cpython-313.pyc +0 -0
- src/database/__pycache__/models.cpython-313.pyc +0 -0
- src/database/__pycache__/querries.cpython-313.pyc +0 -0
- src/database/db_connection.py +1 -1
- src/database/generate_models.py +61 -0
- src/database/models.py +584 -91
- src/database/querries.py +138 -160
- src/services/__pycache__/chat_service.cpython-313.pyc +0 -0
- src/services/chat_service.py +23 -36
.vscode/launch.json
CHANGED
|
@@ -12,6 +12,14 @@
|
|
| 12 |
"console": "integratedTerminal",
|
| 13 |
"justMyCode": true
|
| 14 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
{
|
| 16 |
"name": "Python: Attach to chat.py",
|
| 17 |
"type": "debugpy",
|
|
|
|
| 12 |
"console": "integratedTerminal",
|
| 13 |
"justMyCode": true
|
| 14 |
},
|
| 15 |
+
{
|
| 16 |
+
"name": "Python: app.py",
|
| 17 |
+
"type": "debugpy",
|
| 18 |
+
"request": "launch",
|
| 19 |
+
"program": "${workspaceFolder}/app.py",
|
| 20 |
+
"console": "integratedTerminal",
|
| 21 |
+
"justMyCode": true
|
| 22 |
+
},
|
| 23 |
{
|
| 24 |
"name": "Python: Attach to chat.py",
|
| 25 |
"type": "debugpy",
|
app.py
CHANGED
|
@@ -1,10 +1,9 @@
|
|
| 1 |
-
import
|
| 2 |
-
from transformers import pipeline, AutoTokenizer
|
| 3 |
-
from gradio import Blocks, Textbox, Button, Row, Column
|
| 4 |
import os
|
| 5 |
import logging
|
|
|
|
| 6 |
from dotenv import load_dotenv
|
| 7 |
-
from src.chat import
|
| 8 |
from src.database.init_db import init_db
|
| 9 |
from src.database.db_connection import get_db_engine
|
| 10 |
|
|
@@ -19,43 +18,140 @@ load_dotenv()
|
|
| 19 |
def setup_database():
|
| 20 |
"""Initialize the database at application startup"""
|
| 21 |
logger.info("Initializing database...")
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
# Gradio UI
|
| 28 |
def create_ui():
|
| 29 |
with Blocks() as app:
|
|
|
|
|
|
|
| 30 |
|
| 31 |
with Row():
|
| 32 |
-
with Column():
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
return app
|
| 44 |
|
| 45 |
if __name__ == "__main__":
|
| 46 |
# Ensure database is set up before starting the application
|
| 47 |
-
setup_database()
|
| 48 |
|
| 49 |
# Check if database connection is working
|
| 50 |
engine = get_db_engine()
|
| 51 |
if engine is None:
|
| 52 |
logger.error("Failed to connect to database. Please check your connection settings.")
|
|
|
|
| 53 |
else:
|
| 54 |
logger.info("Successfully connected to database")
|
| 55 |
|
| 56 |
# Launch the Gradio app
|
| 57 |
app = create_ui()
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
|
| 61 |
|
|
|
|
| 1 |
+
from gradio import Blocks, Chatbot, TextArea, Button, Row, Column, State
|
|
|
|
|
|
|
| 2 |
import os
|
| 3 |
import logging
|
| 4 |
+
import traceback
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
+
from src.chat import generate_response
|
| 7 |
from src.database.init_db import init_db
|
| 8 |
from src.database.db_connection import get_db_engine
|
| 9 |
|
|
|
|
| 18 |
def setup_database():
|
| 19 |
"""Initialize the database at application startup"""
|
| 20 |
logger.info("Initializing database...")
|
| 21 |
+
try:
|
| 22 |
+
if init_db():
|
| 23 |
+
logger.info("Database initialized successfully")
|
| 24 |
+
return True
|
| 25 |
+
else:
|
| 26 |
+
logger.error("Failed to initialize database")
|
| 27 |
+
return False
|
| 28 |
+
except Exception as e:
|
| 29 |
+
logger.error(f"Database initialization error: {str(e)}")
|
| 30 |
+
logger.debug(traceback.format_exc())
|
| 31 |
+
return False
|
| 32 |
+
|
| 33 |
+
# Update chat.py to support conversation history
|
| 34 |
+
def update_chat_for_multi_turn():
|
| 35 |
+
"""
|
| 36 |
+
Helper function to handle conversation state for multi-turn chat.
|
| 37 |
+
This handles reconstruction of conversation context for the model.
|
| 38 |
+
"""
|
| 39 |
+
# This is handled in the respond function below
|
| 40 |
+
pass
|
| 41 |
|
| 42 |
# Gradio UI
|
| 43 |
def create_ui():
|
| 44 |
with Blocks() as app:
|
| 45 |
+
# Initialize conversation state
|
| 46 |
+
chat_history = State([])
|
| 47 |
|
| 48 |
with Row():
|
| 49 |
+
with Column(scale=6):
|
| 50 |
+
# Replace Textbox with Chatbot for multi-turn conversation
|
| 51 |
+
chatbot = Chatbot(
|
| 52 |
+
label="Business Interior Design Assistant",
|
| 53 |
+
height=500,
|
| 54 |
+
bubble_full_width=False,
|
| 55 |
+
show_copy_button=True
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
with Row():
|
| 59 |
+
user_input = TextArea(
|
| 60 |
+
placeholder="Type your message here...",
|
| 61 |
+
lines=2,
|
| 62 |
+
label="Your Message",
|
| 63 |
+
scale=5
|
| 64 |
+
)
|
| 65 |
+
submit_button = Button("Send", scale=1)
|
| 66 |
+
|
| 67 |
+
# Add a clear chat button for better UX
|
| 68 |
+
clear_button = Button("Clear Conversation")
|
| 69 |
+
|
| 70 |
+
def respond(message, history, chat_state):
|
| 71 |
+
"""Process user input and update conversation with error handling"""
|
| 72 |
+
if not message.strip():
|
| 73 |
+
return history, chat_state, ""
|
| 74 |
+
|
| 75 |
+
try:
|
| 76 |
+
# Generate response with conversation history context
|
| 77 |
+
try:
|
| 78 |
+
# Check if we need to reset Gemini chat context
|
| 79 |
+
# Currently Gemini chat manages its own state, but
|
| 80 |
+
# we're keeping our own history for resilience
|
| 81 |
+
response = generate_response(message)
|
| 82 |
+
|
| 83 |
+
# Update the visible chat UI
|
| 84 |
+
history.append((message, response))
|
| 85 |
+
|
| 86 |
+
except Exception as e:
|
| 87 |
+
error_msg = f"I apologize, but I encountered an error: {str(e)}"
|
| 88 |
+
logger.error(f"Error generating response: {str(e)}")
|
| 89 |
+
logger.debug(traceback.format_exc())
|
| 90 |
+
|
| 91 |
+
# Add error message to chat history
|
| 92 |
+
history.append((message, error_msg))
|
| 93 |
+
|
| 94 |
+
return history, chat_state, ""
|
| 95 |
+
|
| 96 |
+
except Exception as e:
|
| 97 |
+
logger.error(f"Error in respond function: {str(e)}")
|
| 98 |
+
logger.debug(traceback.format_exc())
|
| 99 |
+
|
| 100 |
+
error_msg = "I apologize, but something went wrong with our conversation system."
|
| 101 |
+
history.append((message, error_msg))
|
| 102 |
+
return history, chat_state, ""
|
| 103 |
+
|
| 104 |
+
def clear_chat():
|
| 105 |
+
"""Clear the conversation history"""
|
| 106 |
+
return [], []
|
| 107 |
|
| 108 |
+
# Connect UI components to functions
|
| 109 |
+
submit_button.click(
|
| 110 |
+
respond,
|
| 111 |
+
inputs=[user_input, chatbot, chat_history],
|
| 112 |
+
outputs=[chatbot, chat_history, user_input],
|
| 113 |
+
api_name="chat"
|
| 114 |
+
)
|
| 115 |
|
| 116 |
+
# Enable pressing Enter to send messages
|
| 117 |
+
user_input.submit(
|
| 118 |
+
respond,
|
| 119 |
+
inputs=[user_input, chatbot, chat_history],
|
| 120 |
+
outputs=[chatbot, chat_history, user_input]
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
clear_button.click(
|
| 124 |
+
clear_chat,
|
| 125 |
+
outputs=[chatbot, chat_history]
|
| 126 |
+
)
|
| 127 |
|
| 128 |
return app
|
| 129 |
|
| 130 |
if __name__ == "__main__":
|
| 131 |
# Ensure database is set up before starting the application
|
| 132 |
+
db_setup_success = setup_database()
|
| 133 |
|
| 134 |
# Check if database connection is working
|
| 135 |
engine = get_db_engine()
|
| 136 |
if engine is None:
|
| 137 |
logger.error("Failed to connect to database. Please check your connection settings.")
|
| 138 |
+
logger.warning("Application will continue with limited database functionality")
|
| 139 |
else:
|
| 140 |
logger.info("Successfully connected to database")
|
| 141 |
|
| 142 |
# Launch the Gradio app
|
| 143 |
app = create_ui()
|
| 144 |
+
|
| 145 |
+
# Configure for different deployment environments
|
| 146 |
+
server_name = os.getenv("SERVER_NAME", "127.0.0.1")
|
| 147 |
+
server_port = int(os.getenv("PORT", 7860))
|
| 148 |
+
share = os.getenv("SHARE_APP", "true").lower() == "true"
|
| 149 |
+
|
| 150 |
+
app.launch(
|
| 151 |
+
server_name=server_name,
|
| 152 |
+
server_port=server_port,
|
| 153 |
+
share=share
|
| 154 |
+
)
|
| 155 |
|
| 156 |
|
| 157 |
|
src/__init__.py
CHANGED
|
@@ -19,5 +19,5 @@ __version__ = '0.1.0'
|
|
| 19 |
__author__ = 'Business Interior Team'
|
| 20 |
|
| 21 |
# Import key modules for simplified access
|
| 22 |
-
from src.core.function_definitions import
|
| 23 |
-
from src.services.chat_service import calculate_office_space,
|
|
|
|
| 19 |
__author__ = 'Business Interior Team'
|
| 20 |
|
| 21 |
# Import key modules for simplified access
|
| 22 |
+
from src.core.function_definitions import calculate_office_space, get_all_categories
|
| 23 |
+
from src.services.chat_service import calculate_office_space, get_all_categories
|
src/__pycache__/__init__.cpython-313.pyc
CHANGED
|
Binary files a/src/__pycache__/__init__.cpython-313.pyc and b/src/__pycache__/__init__.cpython-313.pyc differ
|
|
|
src/__pycache__/chat.cpython-313.pyc
CHANGED
|
Binary files a/src/__pycache__/chat.cpython-313.pyc and b/src/__pycache__/chat.cpython-313.pyc differ
|
|
|
src/chat.py
CHANGED
|
@@ -1,321 +1,337 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
-
|
| 13 |
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
# "properties": {
|
| 20 |
-
# "furniture_items": {
|
| 21 |
-
# "type": "array",
|
| 22 |
-
# "items": {
|
| 23 |
-
# "type": "string",
|
| 24 |
-
# "description": "List of furniture items to calculate space for (e.g., desk, chair).",
|
| 25 |
-
# },
|
| 26 |
-
# },
|
| 27 |
-
# },
|
| 28 |
-
# "required": ["furniture_items"],
|
| 29 |
-
# },
|
| 30 |
-
# }
|
| 31 |
-
|
| 32 |
-
# get_product_recommendations = {
|
| 33 |
-
# "name": "get_product_recommendations",
|
| 34 |
-
# "description": "Get product recommendations based on the user's preferences.",
|
| 35 |
-
# "parameters": {
|
| 36 |
-
# "type": "object",
|
| 37 |
-
# "properties": {
|
| 38 |
-
# "product_type": {
|
| 39 |
-
# "type": "string",
|
| 40 |
-
# "description": "The type of product to recommend (e.g., chair, desk).",
|
| 41 |
-
# },
|
| 42 |
-
# "style": {
|
| 43 |
-
# "type": "string",
|
| 44 |
-
# "description": "The style of the product (e.g., modern, classic).",
|
| 45 |
-
# },
|
| 46 |
-
# "budget": {
|
| 47 |
-
# "type": "number",
|
| 48 |
-
# "description": "The budget for the product recommendations.",
|
| 49 |
-
# },
|
| 50 |
-
# },
|
| 51 |
-
# "required": ["product_type", "style"],
|
| 52 |
-
# },
|
| 53 |
-
# }
|
| 54 |
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
# "properties": {},
|
| 61 |
-
# "required": [],
|
| 62 |
-
# },
|
| 63 |
-
# }
|
| 64 |
|
| 65 |
|
| 66 |
-
#
|
| 67 |
-
|
| 68 |
-
|
|
|
|
| 69 |
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
# }
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
-
|
| 78 |
-
#
|
| 79 |
-
|
| 80 |
-
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
#
|
|
|
|
| 86 |
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
#
|
| 90 |
-
|
| 91 |
-
# elif function_name == "get_product_recommendations":
|
| 92 |
-
# return d_get_product_recommendations(
|
| 93 |
-
# arguments.get("product_type", ""),
|
| 94 |
-
# arguments.get("style", ""),
|
| 95 |
-
# arguments.get("budget", None),
|
| 96 |
-
# )
|
| 97 |
-
# elif function_name == "get_all_categories":
|
| 98 |
-
# return d_get_all_categories()
|
| 99 |
-
# else:
|
| 100 |
-
# raise ValueError(f"Unknown function: {function_name}")
|
| 101 |
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
# function_name = tool_call.name
|
| 107 |
-
# arguments = tool_call.args
|
| 108 |
|
| 109 |
-
|
| 110 |
-
# return tool_call, result
|
| 111 |
-
# else:
|
| 112 |
-
# # No function call detected, return the text response
|
| 113 |
-
# return None, None
|
| 114 |
|
| 115 |
-
|
| 116 |
-
#
|
| 117 |
-
#
|
| 118 |
-
#
|
| 119 |
-
|
| 120 |
-
#
|
| 121 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
-
#
|
| 124 |
-
#
|
| 125 |
-
#
|
| 126 |
-
#
|
|
|
|
| 127 |
|
| 128 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
#
|
| 133 |
-
|
| 134 |
|
| 135 |
-
|
| 136 |
|
| 137 |
-
#
|
| 138 |
-
|
| 139 |
-
|
| 140 |
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
|
| 152 |
|
| 153 |
-
import torch
|
| 154 |
-
import json
|
| 155 |
-
import re
|
| 156 |
-
from transformers import pipeline
|
| 157 |
-
from typing import List, Dict, Any, Optional
|
| 158 |
|
| 159 |
-
# Function definitions that will be available to the model
|
| 160 |
-
FUNCTION_DEFINITIONS = [
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
]
|
| 210 |
|
| 211 |
-
def create_function_calling_prompt(user_query: str, functions: List[Dict[str, Any]]) -> str:
|
| 212 |
-
|
| 213 |
|
| 214 |
-
|
| 215 |
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
|
| 229 |
-
|
| 230 |
|
| 231 |
-
|
| 232 |
-
|
| 233 |
|
| 234 |
-
|
| 235 |
|
| 236 |
-
def extract_function_call(generated_text: str) -> Optional[Dict[str, Any]]:
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
|
| 252 |
-
|
| 253 |
|
| 254 |
-
def execute_function(function_name: str, parameters: Dict[str, Any]) -> str:
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
|
| 267 |
-
|
| 268 |
|
| 269 |
-
# Load the model
|
| 270 |
-
model_id = "meta-llama/Llama-3.2-1B"
|
| 271 |
|
| 272 |
-
pipe = pipeline(
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
)
|
| 282 |
|
| 283 |
-
# Example usage
|
| 284 |
-
def process_query(user_query: str) -> str:
|
| 285 |
-
|
| 286 |
-
|
| 287 |
|
| 288 |
-
|
| 289 |
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
|
| 294 |
-
|
| 295 |
-
|
| 296 |
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
|
| 302 |
-
|
| 303 |
-
|
| 304 |
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
|
| 313 |
-
# Test with some example queries
|
| 314 |
-
queries = [
|
| 315 |
-
|
| 316 |
-
]
|
| 317 |
|
| 318 |
-
for query in queries:
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
|
|
|
| 1 |
+
from google import genai
|
| 2 |
+
from google.genai import types
|
| 3 |
+
import os
|
| 4 |
+
from dotenv import load_dotenv
|
| 5 |
+
import json
|
| 6 |
+
from src.core.function_definitions import (
|
| 7 |
+
calculate_office_space,
|
| 8 |
+
get_top_sales_products,
|
| 9 |
+
get_all_categories,
|
| 10 |
+
get_product_information_by_name,
|
| 11 |
+
find_products_by_price_range,
|
| 12 |
+
)
|
| 13 |
+
from src.services.chat_service import (
|
| 14 |
+
calculate_office_space as d_calculate_office_space,
|
| 15 |
+
get_all_categories as d_get_all_categories,
|
| 16 |
+
get_top_sales_products as d_get_top_sales_products,
|
| 17 |
+
get_product_information_by_name as d_get_product_information_by_name,
|
| 18 |
+
get_product_by_price_range as d_get_product_by_price_range,
|
| 19 |
+
)
|
| 20 |
|
| 21 |
+
load_dotenv()
|
| 22 |
|
| 23 |
+
chat_tools = [
|
| 24 |
+
types.Tool(function_declarations=[calculate_office_space,
|
| 25 |
+
get_top_sales_products, get_all_categories, get_product_information_by_name,
|
| 26 |
+
find_products_by_price_range],),
|
| 27 |
+
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
config = {
|
| 30 |
+
"tools": chat_tools,
|
| 31 |
+
"automatic_function_calling": {"disable": True},
|
| 32 |
+
"tool_config": {"function_calling_config": {"mode": "any"}},
|
| 33 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
|
| 36 |
+
# Config the client - Fix typo in environment variable name
|
| 37 |
+
client = genai.Client(
|
| 38 |
+
api_key=os.getenv("GEMINI_API_KEY"),
|
| 39 |
+
)
|
| 40 |
|
| 41 |
+
chat = client.chats.create(
|
| 42 |
+
model="gemini-2.0-flash",
|
| 43 |
+
config=config,
|
| 44 |
+
)
|
|
|
|
| 45 |
|
| 46 |
+
def handle_function_call(function_name, arguments):
|
| 47 |
+
# Handle the function call here
|
| 48 |
+
if function_name == "calculate_office_space":
|
| 49 |
+
return d_calculate_office_space(arguments.get("furniture_items", []))
|
| 50 |
+
elif function_name == "get_top_sales_products":
|
| 51 |
+
return d_get_top_sales_products(
|
| 52 |
+
arguments.get("category", ""),
|
| 53 |
+
arguments.get("limit", 5)
|
| 54 |
+
)
|
| 55 |
+
elif function_name == "get_all_categories":
|
| 56 |
+
return d_get_all_categories()
|
| 57 |
+
elif function_name == "get_product_information_by_name":
|
| 58 |
+
return d_get_product_information_by_name(
|
| 59 |
+
arguments.get("product_name", "")
|
| 60 |
+
)
|
| 61 |
+
elif function_name == "find_products_by_price_range":
|
| 62 |
+
return d_get_product_by_price_range(
|
| 63 |
+
arguments.get("category", None),
|
| 64 |
+
arguments.get("min_price", 0),
|
| 65 |
+
arguments.get("max_price", 0)
|
| 66 |
+
)
|
| 67 |
+
else:
|
| 68 |
+
raise ValueError(f"Unknown function: {function_name}")
|
| 69 |
|
| 70 |
+
def detect_and_extract_function_call(response):
|
| 71 |
+
# Check if response has function call
|
| 72 |
+
if hasattr(response.candidates[0].content.parts[0], 'function_call'):
|
| 73 |
+
tool_call = response.candidates[0].content.parts[0].function_call
|
| 74 |
+
function_name = tool_call.name
|
| 75 |
+
arguments = tool_call.args
|
| 76 |
|
| 77 |
+
result = handle_function_call(function_name, arguments)
|
| 78 |
+
return tool_call, result
|
| 79 |
+
else:
|
| 80 |
+
# No function call detected, return the text response
|
| 81 |
+
return None, None
|
| 82 |
|
| 83 |
+
def generate_natural_language_response(tool_call, function_response_part):
|
| 84 |
+
contents = []
|
| 85 |
+
contents.append(types.Content(role="model", parts=[types.Part(function_call=tool_call)])) # Append the model's function call message
|
| 86 |
+
contents.append(types.Content(role="user", parts=[function_response_part])) # Append the function response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
+
final_response = client.models.generate_content(
|
| 89 |
+
model="gemini-2.0-flash",
|
| 90 |
+
contents=contents,
|
| 91 |
+
)
|
|
|
|
|
|
|
| 92 |
|
| 93 |
+
print("Tool call:", tool_call)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
+
return final_response.text
|
| 96 |
+
# Extract function name and arguments for context
|
| 97 |
+
# function_name = tool_call.name
|
| 98 |
+
# function_arguments = tool_call.args
|
| 99 |
+
|
| 100 |
+
# # Create a system prompt to guide the model
|
| 101 |
+
# system_prompt = types.Content(
|
| 102 |
+
# role="system",
|
| 103 |
+
# parts=[types.Part(text="""
|
| 104 |
+
# You are a helpful assistant for a business interior design company.
|
| 105 |
+
# When presenting data from function calls:
|
| 106 |
+
# - Format the information in a readable, conversational way
|
| 107 |
+
# - Explain what the data means in the context of interior design
|
| 108 |
+
# - Make helpful suggestions based on the results
|
| 109 |
+
# - Use professional but friendly language
|
| 110 |
+
# - If the data is a list, present it in a structured format
|
| 111 |
+
# - Don't mention that you called a function, just present the information naturally
|
| 112 |
+
# """)]
|
| 113 |
+
# )
|
| 114 |
+
|
| 115 |
+
# # Create model's function call message
|
| 116 |
+
# function_call_content = types.Content(
|
| 117 |
+
# role="model",
|
| 118 |
+
# parts=[types.Part(function_call=tool_call)]
|
| 119 |
+
# )
|
| 120 |
+
|
| 121 |
+
# # Handle different result types for better presentation
|
| 122 |
+
# user_content = types.Content(
|
| 123 |
+
# role="user",
|
| 124 |
+
# parts=[function_response_part]
|
| 125 |
+
# )
|
| 126 |
+
|
| 127 |
+
# # Build the full conversation context
|
| 128 |
+
# contents = [
|
| 129 |
+
# system_prompt,
|
| 130 |
+
# function_call_content,
|
| 131 |
+
# user_content
|
| 132 |
+
# ]
|
| 133 |
|
| 134 |
+
# # Generate the natural language response
|
| 135 |
+
# final_response = client.models.generate_content(
|
| 136 |
+
# model="gemini-2.0-flash",
|
| 137 |
+
# contents=contents,
|
| 138 |
+
# )
|
| 139 |
|
| 140 |
+
# # Log debugging information
|
| 141 |
+
# print(f"Function call: {function_name}({json.dumps(function_arguments, indent=2)})")
|
| 142 |
+
# print(f"Function result type: {type(function_result)}")
|
| 143 |
+
|
| 144 |
+
# return final_response.text
|
| 145 |
|
| 146 |
+
def generate_response(input_text):
|
| 147 |
+
try:
|
| 148 |
+
# Call the chat model with the input text
|
| 149 |
+
model_response = chat.send_message(input_text)
|
| 150 |
|
| 151 |
+
tool_call, function_result = detect_and_extract_function_call(model_response)
|
| 152 |
|
| 153 |
+
# If no function call was detected, return the text response
|
| 154 |
+
if tool_call is None:
|
| 155 |
+
return model_response.text
|
| 156 |
|
| 157 |
+
function_response_part = types.Part.from_function_response(
|
| 158 |
+
name=tool_call.name,
|
| 159 |
+
response={"result": function_result},
|
| 160 |
+
)
|
| 161 |
|
| 162 |
+
natural_response = generate_natural_language_response(tool_call, function_response_part)
|
| 163 |
+
return natural_response
|
| 164 |
+
except Exception as e:
|
| 165 |
+
print(f"Error generating response: {e}")
|
| 166 |
+
return f"I'm sorry, there was an error processing your request: {str(e)}"
|
| 167 |
|
| 168 |
|
| 169 |
+
# import torch
|
| 170 |
+
# import json
|
| 171 |
+
# import re
|
| 172 |
+
# from transformers import pipeline
|
| 173 |
+
# from typing import List, Dict, Any, Optional
|
| 174 |
|
| 175 |
+
# # Function definitions that will be available to the model
|
| 176 |
+
# FUNCTION_DEFINITIONS = [
|
| 177 |
+
# {
|
| 178 |
+
# "name": "get_product_information",
|
| 179 |
+
# "description": "Get information about a specific interior product",
|
| 180 |
+
# "parameters": {
|
| 181 |
+
# "type": "object",
|
| 182 |
+
# "properties": {
|
| 183 |
+
# "product_id": {
|
| 184 |
+
# "type": "string",
|
| 185 |
+
# "description": "ID of the product to look up"
|
| 186 |
+
# },
|
| 187 |
+
# "details_required": {
|
| 188 |
+
# "type": "array",
|
| 189 |
+
# "items": {
|
| 190 |
+
# "type": "string",
|
| 191 |
+
# "enum": ["price", "dimensions", "materials", "availability", "color_options"]
|
| 192 |
+
# },
|
| 193 |
+
# "description": "What product details are needed"
|
| 194 |
+
# }
|
| 195 |
+
# },
|
| 196 |
+
# "required": ["product_id"]
|
| 197 |
+
# }
|
| 198 |
+
# },
|
| 199 |
+
# {
|
| 200 |
+
# "name": "search_products",
|
| 201 |
+
# "description": "Search for interior products based on criteria",
|
| 202 |
+
# "parameters": {
|
| 203 |
+
# "type": "object",
|
| 204 |
+
# "properties": {
|
| 205 |
+
# "category": {
|
| 206 |
+
# "type": "string",
|
| 207 |
+
# "description": "Product category (e.g., sofa, table, chair, lamp)"
|
| 208 |
+
# },
|
| 209 |
+
# "price_range": {
|
| 210 |
+
# "type": "object",
|
| 211 |
+
# "properties": {
|
| 212 |
+
# "min": {"type": "number"},
|
| 213 |
+
# "max": {"type": "number"}
|
| 214 |
+
# },
|
| 215 |
+
# "description": "Price range for the products"
|
| 216 |
+
# },
|
| 217 |
+
# "style": {
|
| 218 |
+
# "type": "string",
|
| 219 |
+
# "description": "Design style (e.g., modern, traditional, industrial)"
|
| 220 |
+
# }
|
| 221 |
+
# },
|
| 222 |
+
# "required": ["category"]
|
| 223 |
+
# }
|
| 224 |
+
# }
|
| 225 |
+
# ]
|
| 226 |
|
| 227 |
+
# def create_function_calling_prompt(user_query: str, functions: List[Dict[str, Any]]) -> str:
|
| 228 |
+
# """Create a prompt for the model that includes function calling instructions"""
|
| 229 |
|
| 230 |
+
# functions_str = json.dumps(functions, indent=2)
|
| 231 |
|
| 232 |
+
# prompt = f"""You are a helpful assistant for a business interior design company.
|
| 233 |
+
# You have access to the following functions: {functions_str}
|
| 234 |
+
# If the user's request can be fulfilled using one of these functions, generate a response in the following JSON format:
|
| 235 |
+
# {{
|
| 236 |
+
# "function_call": {{
|
| 237 |
+
# "name": "function_name",
|
| 238 |
+
# "parameters": {{
|
| 239 |
+
# "param1": "value1",
|
| 240 |
+
# "param2": "value2"
|
| 241 |
+
# }}
|
| 242 |
+
# }}
|
| 243 |
+
# }}
|
| 244 |
|
| 245 |
+
# If no function is needed, respond conversationally.
|
| 246 |
|
| 247 |
+
# User: {user_query}
|
| 248 |
+
# Assistant:"""
|
| 249 |
|
| 250 |
+
# return prompt
|
| 251 |
|
| 252 |
+
# def extract_function_call(generated_text: str) -> Optional[Dict[str, Any]]:
|
| 253 |
+
# """Extract the function call from the generated text"""
|
| 254 |
+
# # Look for JSON-like patterns in the output
|
| 255 |
+
# pattern = r'(\{[\s\S]*\})'
|
| 256 |
+
# match = re.search(pattern, generated_text)
|
| 257 |
|
| 258 |
+
# if match:
|
| 259 |
+
# try:
|
| 260 |
+
# # Try to parse as JSON
|
| 261 |
+
# json_str = match.group(1)
|
| 262 |
+
# result = json.loads(json_str)
|
| 263 |
+
# if "function_call" in result:
|
| 264 |
+
# return result["function_call"]
|
| 265 |
+
# except json.JSONDecodeError:
|
| 266 |
+
# pass
|
| 267 |
|
| 268 |
+
# return None
|
| 269 |
|
| 270 |
+
# def execute_function(function_name: str, parameters: Dict[str, Any]) -> str:
|
| 271 |
+
# """Execute the specified function with the given parameters"""
|
| 272 |
+
# # In a real implementation, these functions would connect to your database or APIs
|
| 273 |
+
# if function_name == "get_product_information":
|
| 274 |
+
# # Simulate product information retrieval
|
| 275 |
+
# product_id = parameters.get("product_id")
|
| 276 |
+
# return f"Retrieved information for product {product_id}: Price: $1,299, Material: Leather, Availability: In stock"
|
| 277 |
|
| 278 |
+
# elif function_name == "search_products":
|
| 279 |
+
# # Simulate product search
|
| 280 |
+
# category = parameters.get("category")
|
| 281 |
+
# return f"Found 5 {category} products matching your criteria. Would you like to see the results?"
|
| 282 |
|
| 283 |
+
# return "Function execution failed. Please try again."
|
| 284 |
|
| 285 |
+
# # Load the model
|
| 286 |
+
# model_id = "meta-llama/Llama-3.2-1B"
|
| 287 |
|
| 288 |
+
# pipe = pipeline(
|
| 289 |
+
# "text-generation",
|
| 290 |
+
# model=model_id,
|
| 291 |
+
# torch_dtype=torch.bfloat16,
|
| 292 |
+
# device_map="auto",
|
| 293 |
+
# max_new_tokens=800, # Increase token limit for detailed responses
|
| 294 |
+
# do_sample=True,
|
| 295 |
+
# temperature=0.2, # Lower temperature for more deterministic outputs
|
| 296 |
+
# top_p=0.95 # Control diversity while maintaining structure
|
| 297 |
+
# )
|
| 298 |
|
| 299 |
+
# # Example usage
|
| 300 |
+
# def process_query(user_query: str) -> str:
|
| 301 |
+
# # Create the prompt with function specifications
|
| 302 |
+
# prompt = create_function_calling_prompt(user_query, FUNCTION_DEFINITIONS)
|
| 303 |
|
| 304 |
+
# print(f"Prompt: {prompt}")
|
| 305 |
|
| 306 |
+
# # Generate response from the model
|
| 307 |
+
# result = pipe(prompt)
|
| 308 |
+
# generated_text = result[0]['generated_text']
|
| 309 |
|
| 310 |
+
# # Try to extract a function call
|
| 311 |
+
# function_call = extract_function_call(generated_text)
|
| 312 |
|
| 313 |
+
# if function_call:
|
| 314 |
+
# # If a function call was detected, execute it
|
| 315 |
+
# function_name = function_call.get("name")
|
| 316 |
+
# parameters = function_call.get("parameters", {})
|
| 317 |
|
| 318 |
+
# print(f"Detected function call: {function_name}")
|
| 319 |
+
# print(f"Parameters: {parameters}")
|
| 320 |
|
| 321 |
+
# # Execute the function and return result
|
| 322 |
+
# return execute_function(function_name, parameters)
|
| 323 |
+
# else:
|
| 324 |
+
# # Return the normal conversational response
|
| 325 |
+
# # Extract just the assistant's response
|
| 326 |
+
# assistant_response = generated_text.split("Assistant:")[-1].strip()
|
| 327 |
+
# return assistant_response
|
| 328 |
|
| 329 |
+
# # Test with some example queries
|
| 330 |
+
# queries = [
|
| 331 |
+
# "I need information about product ID FUR-2345",
|
| 332 |
+
# ]
|
| 333 |
|
| 334 |
+
# for query in queries:
|
| 335 |
+
# print(f"\nUser: {query}")
|
| 336 |
+
# response = process_query(query)
|
| 337 |
+
# print(f"Response: {response}")
|
src/core/__pycache__/function_definitions.cpython-313.pyc
CHANGED
|
Binary files a/src/core/__pycache__/function_definitions.cpython-313.pyc and b/src/core/__pycache__/function_definitions.cpython-313.pyc differ
|
|
|
src/core/function_definitions.py
CHANGED
|
@@ -1,43 +1,245 @@
|
|
| 1 |
import json
|
| 2 |
|
| 3 |
-
|
| 4 |
-
"name": "
|
| 5 |
-
"description": "Calculate the office space needed for
|
| 6 |
"parameters": {
|
| 7 |
"type": "object",
|
| 8 |
"properties": {
|
| 9 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
"type": "integer",
|
| 11 |
-
"description": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
},
|
| 13 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
"type": "number",
|
| 15 |
-
"description": "
|
| 16 |
},
|
| 17 |
},
|
| 18 |
-
"required": ["
|
| 19 |
},
|
| 20 |
}
|
| 21 |
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
"
|
|
|
|
| 25 |
"parameters": {
|
| 26 |
"type": "object",
|
| 27 |
"properties": {
|
| 28 |
"product_type": {
|
| 29 |
"type": "string",
|
| 30 |
-
"description": "
|
| 31 |
},
|
| 32 |
-
"
|
| 33 |
-
"type": "
|
| 34 |
-
"description": "
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
},
|
| 36 |
-
"
|
| 37 |
"type": "number",
|
| 38 |
-
"description": "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
},
|
| 40 |
},
|
| 41 |
-
"required": ["
|
| 42 |
},
|
| 43 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import json
|
| 2 |
|
| 3 |
+
calculate_office_space = {
|
| 4 |
+
"name": "calculate_office_space",
|
| 5 |
+
"description": "Calculate the office space needed for furniture items.",
|
| 6 |
"parameters": {
|
| 7 |
"type": "object",
|
| 8 |
"properties": {
|
| 9 |
+
"furniture_items": {
|
| 10 |
+
"type": "array",
|
| 11 |
+
"items": {
|
| 12 |
+
"type": "object",
|
| 13 |
+
"properties": {
|
| 14 |
+
"item_name": {
|
| 15 |
+
"type": "string",
|
| 16 |
+
"description": "Name of the furniture item (e.g., desk, chair).",
|
| 17 |
+
},
|
| 18 |
+
"quantity": {
|
| 19 |
+
"type": "integer",
|
| 20 |
+
"description": "Number of items needed.",
|
| 21 |
+
},
|
| 22 |
+
},
|
| 23 |
+
"required": ["item_name", "quantity"],
|
| 24 |
+
},
|
| 25 |
+
"description": "List of furniture items and their quantities.",
|
| 26 |
+
},
|
| 27 |
+
},
|
| 28 |
+
"required": ["furniture_items"],
|
| 29 |
+
},
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
get_top_sales_products = {
|
| 33 |
+
"name": "get_top_sales_products",
|
| 34 |
+
"description": "Get top-selling products based on sales data.",
|
| 35 |
+
"parameters": {
|
| 36 |
+
"type": "object",
|
| 37 |
+
"properties": {
|
| 38 |
+
"category": {
|
| 39 |
+
"type": "string",
|
| 40 |
+
"description": "Category of products to filter by (e.g., 'furniture', 'decor').",
|
| 41 |
+
},
|
| 42 |
+
"limit": {
|
| 43 |
"type": "integer",
|
| 44 |
+
"description": "Number of top-selling products to return.",
|
| 45 |
+
},
|
| 46 |
+
},
|
| 47 |
+
"required": ["category", "limit"],
|
| 48 |
+
},
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
get_all_categories = {
|
| 52 |
+
"name": "get_all_categories",
|
| 53 |
+
"description": "Get all available categories of products.",
|
| 54 |
+
"parameters": {
|
| 55 |
+
"type": "object",
|
| 56 |
+
"properties": {},
|
| 57 |
+
"required": [],
|
| 58 |
+
},
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
get_product_information_by_name = {
|
| 62 |
+
"name": "get_product_information_by_name",
|
| 63 |
+
"description": "Get product information by name.",
|
| 64 |
+
"parameters": {
|
| 65 |
+
"type": "object",
|
| 66 |
+
"properties": {
|
| 67 |
+
"product_name": {
|
| 68 |
+
"type": "string",
|
| 69 |
+
"description": "Name of the product to retrieve information for.",
|
| 70 |
+
},
|
| 71 |
+
},
|
| 72 |
+
"required": ["product_name"],
|
| 73 |
+
},
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
get_product_recommendations = {
|
| 77 |
+
"name": "get_product_recommendations",
|
| 78 |
+
"description": "Get personalized product recommendations based on needs.",
|
| 79 |
+
"parameters": {
|
| 80 |
+
"type": "object",
|
| 81 |
+
"properties": {
|
| 82 |
+
"office_size": {
|
| 83 |
+
"type": "integer",
|
| 84 |
+
"description": "Size of the office in square feet.",
|
| 85 |
+
},
|
| 86 |
+
"employee_count": {
|
| 87 |
+
"type": "integer",
|
| 88 |
+
"description": "Number of employees to accommodate.",
|
| 89 |
+
},
|
| 90 |
+
"style_preference": {
|
| 91 |
+
"type": "string",
|
| 92 |
+
"description": "Preferred style (e.g., 'modern', 'traditional', 'minimalist').",
|
| 93 |
+
},
|
| 94 |
+
},
|
| 95 |
+
"required": ["office_size", "employee_count"],
|
| 96 |
+
},
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
request_custom_quote = {
|
| 100 |
+
"name": "request_custom_quote",
|
| 101 |
+
"description": "Request a custom quote for bulk orders or custom furniture.",
|
| 102 |
+
"parameters": {
|
| 103 |
+
"type": "object",
|
| 104 |
+
"properties": {
|
| 105 |
+
"product_details": {
|
| 106 |
+
"type": "array",
|
| 107 |
+
"items": {
|
| 108 |
+
"type": "object",
|
| 109 |
+
"properties": {
|
| 110 |
+
"product_name": {
|
| 111 |
+
"type": "string",
|
| 112 |
+
"description": "Name of the product.",
|
| 113 |
+
},
|
| 114 |
+
"quantity": {
|
| 115 |
+
"type": "integer",
|
| 116 |
+
"description": "Quantity needed.",
|
| 117 |
+
},
|
| 118 |
+
"customization": {
|
| 119 |
+
"type": "string",
|
| 120 |
+
"description": "Any customization requirements.",
|
| 121 |
+
},
|
| 122 |
+
},
|
| 123 |
+
"required": ["product_name", "quantity"],
|
| 124 |
+
},
|
| 125 |
+
"description": "List of products for the quote.",
|
| 126 |
},
|
| 127 |
+
"contact_information": {
|
| 128 |
+
"type": "object",
|
| 129 |
+
"properties": {
|
| 130 |
+
"name": {
|
| 131 |
+
"type": "string",
|
| 132 |
+
"description": "Contact person's name.",
|
| 133 |
+
},
|
| 134 |
+
"email": {
|
| 135 |
+
"type": "string",
|
| 136 |
+
"description": "Contact email address.",
|
| 137 |
+
},
|
| 138 |
+
"phone": {
|
| 139 |
+
"type": "string",
|
| 140 |
+
"description": "Contact phone number.",
|
| 141 |
+
},
|
| 142 |
+
},
|
| 143 |
+
"required": ["name", "email"],
|
| 144 |
+
},
|
| 145 |
+
},
|
| 146 |
+
"required": ["product_details", "contact_information"],
|
| 147 |
+
},
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
check_product_availability = {
|
| 151 |
+
"name": "check_product_availability",
|
| 152 |
+
"description": "Check if products are in stock and available for purchase.",
|
| 153 |
+
"parameters": {
|
| 154 |
+
"type": "object",
|
| 155 |
+
"properties": {
|
| 156 |
+
"product_name": {
|
| 157 |
+
"type": "string",
|
| 158 |
+
"description": "Name of the product to check availability for.",
|
| 159 |
+
},
|
| 160 |
+
"quantity": {
|
| 161 |
+
"type": "integer",
|
| 162 |
+
"description": "Quantity needed.",
|
| 163 |
+
},
|
| 164 |
+
},
|
| 165 |
+
"required": ["product_name", "quantity"],
|
| 166 |
+
},
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
find_products_by_price_range = {
|
| 170 |
+
"name": "find_products_by_price_range",
|
| 171 |
+
"description": "Find products within a specific price range.",
|
| 172 |
+
"parameters": {
|
| 173 |
+
"type": "object",
|
| 174 |
+
"properties": {
|
| 175 |
+
"category": {
|
| 176 |
+
"type": "string",
|
| 177 |
+
"description": "Category of products to search within.",
|
| 178 |
+
},
|
| 179 |
+
"min_price": {
|
| 180 |
+
"type": "number",
|
| 181 |
+
"description": "Minimum price (in dollars).",
|
| 182 |
+
},
|
| 183 |
+
"max_price": {
|
| 184 |
"type": "number",
|
| 185 |
+
"description": "Maximum price (in dollars).",
|
| 186 |
},
|
| 187 |
},
|
| 188 |
+
"required": ["min_price", "max_price"],
|
| 189 |
},
|
| 190 |
}
|
| 191 |
|
| 192 |
+
|
| 193 |
+
find_products_by_dimension = {
|
| 194 |
+
"name": "find_products_by_dimension",
|
| 195 |
+
"description": "Find furniture that fits specific spatial requirements.",
|
| 196 |
"parameters": {
|
| 197 |
"type": "object",
|
| 198 |
"properties": {
|
| 199 |
"product_type": {
|
| 200 |
"type": "string",
|
| 201 |
+
"description": "Type of product (e.g., 'desk', 'bookshelf').",
|
| 202 |
},
|
| 203 |
+
"max_width": {
|
| 204 |
+
"type": "number",
|
| 205 |
+
"description": "Maximum width in inches.",
|
| 206 |
+
},
|
| 207 |
+
"max_depth": {
|
| 208 |
+
"type": "number",
|
| 209 |
+
"description": "Maximum depth in inches.",
|
| 210 |
},
|
| 211 |
+
"max_height": {
|
| 212 |
"type": "number",
|
| 213 |
+
"description": "Maximum height in inches.",
|
| 214 |
+
},
|
| 215 |
+
},
|
| 216 |
+
"required": ["product_type"],
|
| 217 |
+
},
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
get_product_reviews = {
|
| 221 |
+
"name": "get_product_reviews",
|
| 222 |
+
"description": "Get customer reviews for a specific product.",
|
| 223 |
+
"parameters": {
|
| 224 |
+
"type": "object",
|
| 225 |
+
"properties": {
|
| 226 |
+
"product_id": {
|
| 227 |
+
"type": "string",
|
| 228 |
+
"description": "ID of the product to get reviews for.",
|
| 229 |
+
},
|
| 230 |
+
"limit": {
|
| 231 |
+
"type": "integer",
|
| 232 |
+
"description": "Maximum number of reviews to return.",
|
| 233 |
+
},
|
| 234 |
+
"min_rating": {
|
| 235 |
+
"type": "integer",
|
| 236 |
+
"description": "Minimum rating (1-5) to filter by.",
|
| 237 |
},
|
| 238 |
},
|
| 239 |
+
"required": ["product_id"],
|
| 240 |
},
|
| 241 |
}
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
__all__ = ["calculate_office_space", "get_product_recommendations", "get_all_categories", "get_top_sales_products", "get_product_information_by_name"]
|
src/database/__pycache__/db_connection.cpython-313.pyc
CHANGED
|
Binary files a/src/database/__pycache__/db_connection.cpython-313.pyc and b/src/database/__pycache__/db_connection.cpython-313.pyc differ
|
|
|
src/database/__pycache__/models.cpython-313.pyc
CHANGED
|
Binary files a/src/database/__pycache__/models.cpython-313.pyc and b/src/database/__pycache__/models.cpython-313.pyc differ
|
|
|
src/database/__pycache__/querries.cpython-313.pyc
CHANGED
|
Binary files a/src/database/__pycache__/querries.cpython-313.pyc and b/src/database/__pycache__/querries.cpython-313.pyc differ
|
|
|
src/database/db_connection.py
CHANGED
|
@@ -55,7 +55,7 @@ def get_db_engine():
|
|
| 55 |
|
| 56 |
# The direct pyodbc connection approach for macOS
|
| 57 |
# Use DSN-less connection which is more reliable on macOS with Azure SQL
|
| 58 |
-
conn_str = f'DRIVER={{ODBC Driver 18 for SQL Server}};SERVER={server};DATABASE=
|
| 59 |
|
| 60 |
# Create connection string for SQLAlchemy
|
| 61 |
connection_url = f"mssql+pyodbc:///?odbc_connect={urllib.parse.quote_plus(conn_str)}"
|
|
|
|
| 55 |
|
| 56 |
# The direct pyodbc connection approach for macOS
|
| 57 |
# Use DSN-less connection which is more reliable on macOS with Azure SQL
|
| 58 |
+
conn_str = f'DRIVER={{ODBC Driver 18 for SQL Server}};SERVER={server};DATABASE=INTERIOR_SHOPPING;UID={username};PWD={quoted_password};Encrypt=yes;TrustServerCertificate=yes;Connection Timeout=30;'
|
| 59 |
|
| 60 |
# Create connection string for SQLAlchemy
|
| 61 |
connection_url = f"mssql+pyodbc:///?odbc_connect={urllib.parse.quote_plus(conn_str)}"
|
src/database/generate_models.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
import urllib.parse
|
| 5 |
+
|
| 6 |
+
# Load environment variables
|
| 7 |
+
load_dotenv()
|
| 8 |
+
|
| 9 |
+
# Get connection parameters from environment variables
|
| 10 |
+
server = os.getenv("SQL_SERVER")
|
| 11 |
+
database = os.getenv("SQL_DATABASE")
|
| 12 |
+
username = os.getenv("SQL_USERNAME")
|
| 13 |
+
password = os.getenv("SQL_PASSWORD")
|
| 14 |
+
|
| 15 |
+
if not all([server, database, username, password]):
|
| 16 |
+
print("Error: SQL connection parameters not found in environment variables")
|
| 17 |
+
sys.exit(1)
|
| 18 |
+
|
| 19 |
+
# Clean the server name (remove 'tcp:' prefix if present)
|
| 20 |
+
if server.startswith('tcp:'):
|
| 21 |
+
server = server[4:]
|
| 22 |
+
|
| 23 |
+
# URL encode the password to handle special characters
|
| 24 |
+
quoted_password = urllib.parse.quote_plus(password)
|
| 25 |
+
|
| 26 |
+
# Create the connection string based on the driver availability
|
| 27 |
+
try:
|
| 28 |
+
import pyodbc
|
| 29 |
+
print("Using pyodbc driver for connection")
|
| 30 |
+
|
| 31 |
+
# Create ODBC connection string
|
| 32 |
+
conn_str = f'DRIVER={{ODBC Driver 18 for SQL Server}};SERVER={server};DATABASE={database};UID={username};PWD={quoted_password}'
|
| 33 |
+
connection_url = f"mssql+pyodbc:///?odbc_connect={urllib.parse.quote_plus(conn_str)}"
|
| 34 |
+
except ImportError:
|
| 35 |
+
try:
|
| 36 |
+
import pymssql
|
| 37 |
+
print("Using pymssql driver for connection")
|
| 38 |
+
|
| 39 |
+
# Parse server and port if needed
|
| 40 |
+
if ',' in server:
|
| 41 |
+
server_parts = server.split(',')
|
| 42 |
+
host = server_parts[0]
|
| 43 |
+
port = int(server_parts[1]) if len(server_parts) > 1 else 1433
|
| 44 |
+
else:
|
| 45 |
+
host = server
|
| 46 |
+
port = 1433
|
| 47 |
+
|
| 48 |
+
connection_url = f"mssql+pymssql://{username}:{password}@{host}:{port}/{database}"
|
| 49 |
+
except ImportError:
|
| 50 |
+
print("Error: Neither pyodbc nor pymssql is installed")
|
| 51 |
+
sys.exit(1)
|
| 52 |
+
|
| 53 |
+
# Print the command to run (without password)
|
| 54 |
+
safe_connection_url = connection_url.replace(quoted_password, "********")
|
| 55 |
+
print(f"Running sqlacodegen with connection: {safe_connection_url}")
|
| 56 |
+
|
| 57 |
+
# Execute sqlacodegen
|
| 58 |
+
command = f"sqlacodegen --outfile=src/database/models.py '{connection_url}'"
|
| 59 |
+
print("Generating models...")
|
| 60 |
+
os.system(command)
|
| 61 |
+
print("Models generated successfully in src/database/models.py")
|
src/database/models.py
CHANGED
|
@@ -1,96 +1,589 @@
|
|
| 1 |
-
from
|
| 2 |
-
|
| 3 |
-
from sqlalchemy
|
|
|
|
|
|
|
| 4 |
import datetime
|
|
|
|
| 5 |
import uuid
|
| 6 |
-
from sqlalchemy.dialects.mssql import UNIQUEIDENTIFIER
|
| 7 |
|
| 8 |
-
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
| 13 |
__tablename__ = 'AspNetUsers'
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import List, Optional
|
| 2 |
+
|
| 3 |
+
from sqlalchemy import BigInteger, Boolean, Column, DECIMAL, Date, ForeignKeyConstraint, Identity, Index, Integer, PrimaryKeyConstraint, Table, Unicode, Uuid, text
|
| 4 |
+
from sqlalchemy.dialects.mssql import DATETIME2, DATETIMEOFFSET
|
| 5 |
+
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
|
| 6 |
import datetime
|
| 7 |
+
import decimal
|
| 8 |
import uuid
|
|
|
|
| 9 |
|
| 10 |
+
class Base(DeclarativeBase):
|
| 11 |
+
pass
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class AspNetRoles(Base):
|
| 15 |
+
__tablename__ = 'AspNetRoles'
|
| 16 |
+
__table_args__ = (
|
| 17 |
+
PrimaryKeyConstraint('Id', name='PK_AspNetRoles'),
|
| 18 |
+
Index('RoleNameIndex', 'NormalizedName', unique=True)
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 22 |
+
Name: Mapped[Optional[str]] = mapped_column(Unicode(256, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 23 |
+
NormalizedName: Mapped[Optional[str]] = mapped_column(Unicode(256, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 24 |
+
ConcurrencyStamp: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 25 |
|
| 26 |
+
AspNetUsers: Mapped[List['AspNetUsers']] = relationship('AspNetUsers', secondary='AspNetUserRoles', back_populates='AspNetRoles_')
|
| 27 |
+
AspNetRoleClaims: Mapped[List['AspNetRoleClaims']] = relationship('AspNetRoleClaims', back_populates='AspNetRoles_')
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class AspNetUsers(Base):
|
| 31 |
__tablename__ = 'AspNetUsers'
|
| 32 |
+
__table_args__ = (
|
| 33 |
+
PrimaryKeyConstraint('Id', name='PK_AspNetUsers'),
|
| 34 |
+
Index('EmailIndex', 'NormalizedEmail'),
|
| 35 |
+
Index('UserNameIndex', 'NormalizedUserName', unique=True)
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 39 |
+
Name: Mapped[str] = mapped_column(Unicode(100, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 40 |
+
IsActive: Mapped[bool] = mapped_column(Boolean, server_default=text('(CONVERT([bit],(1)))'))
|
| 41 |
+
CustomerPoints: Mapped[int] = mapped_column(Integer, server_default=text('((0))'))
|
| 42 |
+
CustomerLevel: Mapped[int] = mapped_column(Integer, server_default=text('((0))'))
|
| 43 |
+
UserName: Mapped[str] = mapped_column(Unicode(50, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 44 |
+
Email: Mapped[str] = mapped_column(Unicode(100, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 45 |
+
EmailConfirmed: Mapped[bool] = mapped_column(Boolean)
|
| 46 |
+
PasswordHash: Mapped[str] = mapped_column(Unicode(100, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 47 |
+
PhoneNumber: Mapped[str] = mapped_column(Unicode(15, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 48 |
+
PhoneNumberConfirmed: Mapped[bool] = mapped_column(Boolean)
|
| 49 |
+
TwoFactorEnabled: Mapped[bool] = mapped_column(Boolean)
|
| 50 |
+
LockoutEnabled: Mapped[bool] = mapped_column(Boolean)
|
| 51 |
+
AccessFailedCount: Mapped[int] = mapped_column(Integer)
|
| 52 |
+
ImageUrl: Mapped[Optional[str]] = mapped_column(Unicode(200, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 53 |
+
DateOfBirth: Mapped[Optional[datetime.date]] = mapped_column(Date)
|
| 54 |
+
NormalizedUserName: Mapped[Optional[str]] = mapped_column(Unicode(256, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 55 |
+
NormalizedEmail: Mapped[Optional[str]] = mapped_column(Unicode(256, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 56 |
+
SecurityStamp: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 57 |
+
ConcurrencyStamp: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 58 |
+
LockoutEnd: Mapped[Optional[datetime.datetime]] = mapped_column(DATETIMEOFFSET)
|
| 59 |
+
|
| 60 |
+
AspNetRoles_: Mapped[List['AspNetRoles']] = relationship('AspNetRoles', secondary='AspNetUserRoles', back_populates='AspNetUsers')
|
| 61 |
+
Addresses: Mapped[List['Addresses']] = relationship('Addresses', back_populates='AspNetUsers_')
|
| 62 |
+
AspNetUserClaims: Mapped[List['AspNetUserClaims']] = relationship('AspNetUserClaims', back_populates='AspNetUsers_')
|
| 63 |
+
AspNetUserLogins: Mapped[List['AspNetUserLogins']] = relationship('AspNetUserLogins', back_populates='AspNetUsers_')
|
| 64 |
+
AspNetUserTokens: Mapped[List['AspNetUserTokens']] = relationship('AspNetUserTokens', back_populates='AspNetUsers_')
|
| 65 |
+
Payments: Mapped[List['Payments']] = relationship('Payments', back_populates='AspNetUsers_')
|
| 66 |
+
Orders: Mapped[List['Orders']] = relationship('Orders', back_populates='AspNetUsers_')
|
| 67 |
+
Reviews: Mapped[List['Reviews']] = relationship('Reviews', back_populates='AspNetUsers_')
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
class Attributes(Base):
|
| 71 |
+
__tablename__ = 'Attributes'
|
| 72 |
+
__table_args__ = (
|
| 73 |
+
PrimaryKeyConstraint('Id', name='PK_Attributes'),
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 77 |
+
Name: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 78 |
+
Type: Mapped[int] = mapped_column(Integer)
|
| 79 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 80 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 81 |
+
|
| 82 |
+
CategoryAttributes: Mapped[List['CategoryAttributes']] = relationship('CategoryAttributes', back_populates='Attributes_')
|
| 83 |
+
AttributeValues: Mapped[List['AttributeValues']] = relationship('AttributeValues', back_populates='Attributes_')
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
class Categories(Base):
|
| 87 |
+
__tablename__ = 'Categories'
|
| 88 |
+
__table_args__ = (
|
| 89 |
+
ForeignKeyConstraint(['ParentCategoryId'], ['Categories.Id'], name='FK_Categories_Categories_ParentCategoryId'),
|
| 90 |
+
PrimaryKeyConstraint('Id', name='PK_Categories'),
|
| 91 |
+
Index('IX_Categories_ParentCategoryId', 'ParentCategoryId')
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 95 |
+
Name: Mapped[str] = mapped_column(Unicode(100, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 96 |
+
Slug: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 97 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 98 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 99 |
+
Description: Mapped[Optional[str]] = mapped_column(Unicode(500, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 100 |
+
ImageUrl: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 101 |
+
ParentCategoryId: Mapped[Optional[uuid.UUID]] = mapped_column(Uuid)
|
| 102 |
+
|
| 103 |
+
Categories: Mapped[Optional['Categories']] = relationship('Categories', remote_side=[Id], back_populates='Categories_reverse')
|
| 104 |
+
Categories_reverse: Mapped[List['Categories']] = relationship('Categories', remote_side=[ParentCategoryId], back_populates='Categories')
|
| 105 |
+
CategoryAttributes: Mapped[List['CategoryAttributes']] = relationship('CategoryAttributes', back_populates='Categories_')
|
| 106 |
+
Products: Mapped[List['Products']] = relationship('Products', back_populates='Categories_')
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
class Combos(Base):
|
| 110 |
+
__tablename__ = 'Combos'
|
| 111 |
+
__table_args__ = (
|
| 112 |
+
PrimaryKeyConstraint('Id', name='PK_Combos'),
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 116 |
+
Name: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 117 |
+
Description: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 118 |
+
DiscountPercentage: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 119 |
+
IsActive: Mapped[bool] = mapped_column(Boolean)
|
| 120 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 121 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 122 |
+
|
| 123 |
+
ProductCombos: Mapped[List['ProductCombos']] = relationship('ProductCombos', back_populates='Combos_')
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
class Placements(Base):
|
| 127 |
+
__tablename__ = 'Placements'
|
| 128 |
+
__table_args__ = (
|
| 129 |
+
PrimaryKeyConstraint('Id', name='PK_Placements'),
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 133 |
+
Name: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 134 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 135 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 136 |
+
Description: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 137 |
+
|
| 138 |
+
Products: Mapped[List['Products']] = relationship('Products', back_populates='Placements_')
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
class Promotions(Base):
|
| 142 |
+
__tablename__ = 'Promotions'
|
| 143 |
+
__table_args__ = (
|
| 144 |
+
PrimaryKeyConstraint('Id', name='PK_Promotions'),
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 148 |
+
Name: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 149 |
+
Code: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 150 |
+
DiscountPercentage: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 151 |
+
StartDate: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 152 |
+
EndDate: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 153 |
+
IsActive: Mapped[bool] = mapped_column(Boolean)
|
| 154 |
+
Ussage: Mapped[int] = mapped_column(Integer)
|
| 155 |
+
CustomerLevel: Mapped[int] = mapped_column(Integer)
|
| 156 |
+
Type: Mapped[int] = mapped_column(Integer)
|
| 157 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 158 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 159 |
+
Description: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 160 |
+
ProductIds: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 161 |
+
|
| 162 |
+
Products: Mapped[List['Products']] = relationship('Products', secondary='ProductPromotion', back_populates='Promotions_')
|
| 163 |
+
Orders: Mapped[List['Orders']] = relationship('Orders', back_populates='Promotions_')
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
class VerificationCodes(Base):
|
| 167 |
+
__tablename__ = 'VerificationCodes'
|
| 168 |
+
__table_args__ = (
|
| 169 |
+
PrimaryKeyConstraint('Id', name='PK_VerificationCodes'),
|
| 170 |
+
)
|
| 171 |
+
|
| 172 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 173 |
+
Code: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 174 |
+
Email: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 175 |
+
ExpirationDate: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 176 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 177 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
class EFMigrationsHistory(Base):
|
| 181 |
+
__tablename__ = '__EFMigrationsHistory'
|
| 182 |
+
__table_args__ = (
|
| 183 |
+
PrimaryKeyConstraint('MigrationId', name='PK___EFMigrationsHistory'),
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
MigrationId: Mapped[str] = mapped_column(Unicode(150, 'SQL_Latin1_General_CP1_CI_AS'), primary_key=True)
|
| 187 |
+
ProductVersion: Mapped[str] = mapped_column(Unicode(32, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
class Addresses(Base):
|
| 191 |
+
__tablename__ = 'Addresses'
|
| 192 |
+
__table_args__ = (
|
| 193 |
+
ForeignKeyConstraint(['UserId'], ['AspNetUsers.Id'], ondelete='CASCADE', name='FK_Addresses_AspNetUsers_UserId'),
|
| 194 |
+
PrimaryKeyConstraint('Id', name='PK_Addresses'),
|
| 195 |
+
Index('IX_Addresses_UserId', 'UserId')
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 199 |
+
IsDefault: Mapped[bool] = mapped_column(Boolean)
|
| 200 |
+
UserId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 201 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 202 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 203 |
+
Street: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 204 |
+
District: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 205 |
+
City: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 206 |
+
PostalCode: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 207 |
+
Country: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 208 |
+
Ward: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 209 |
+
|
| 210 |
+
AspNetUsers_: Mapped['AspNetUsers'] = relationship('AspNetUsers', back_populates='Addresses')
|
| 211 |
+
Orders: Mapped[List['Orders']] = relationship('Orders', back_populates='Addresses_')
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
class AspNetRoleClaims(Base):
|
| 215 |
+
__tablename__ = 'AspNetRoleClaims'
|
| 216 |
+
__table_args__ = (
|
| 217 |
+
ForeignKeyConstraint(['RoleId'], ['AspNetRoles.Id'], ondelete='CASCADE', name='FK_AspNetRoleClaims_AspNetRoles_RoleId'),
|
| 218 |
+
PrimaryKeyConstraint('Id', name='PK_AspNetRoleClaims'),
|
| 219 |
+
Index('IX_AspNetRoleClaims_RoleId', 'RoleId')
|
| 220 |
+
)
|
| 221 |
+
|
| 222 |
+
Id: Mapped[int] = mapped_column(Integer, Identity(start=1, increment=1), primary_key=True)
|
| 223 |
+
RoleId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 224 |
+
ClaimType: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 225 |
+
ClaimValue: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 226 |
+
|
| 227 |
+
AspNetRoles_: Mapped['AspNetRoles'] = relationship('AspNetRoles', back_populates='AspNetRoleClaims')
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
class AspNetUserClaims(Base):
|
| 231 |
+
__tablename__ = 'AspNetUserClaims'
|
| 232 |
+
__table_args__ = (
|
| 233 |
+
ForeignKeyConstraint(['UserId'], ['AspNetUsers.Id'], ondelete='CASCADE', name='FK_AspNetUserClaims_AspNetUsers_UserId'),
|
| 234 |
+
PrimaryKeyConstraint('Id', name='PK_AspNetUserClaims'),
|
| 235 |
+
Index('IX_AspNetUserClaims_UserId', 'UserId')
|
| 236 |
+
)
|
| 237 |
+
|
| 238 |
+
Id: Mapped[int] = mapped_column(Integer, Identity(start=1, increment=1), primary_key=True)
|
| 239 |
+
UserId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 240 |
+
ClaimType: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 241 |
+
ClaimValue: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 242 |
+
|
| 243 |
+
AspNetUsers_: Mapped['AspNetUsers'] = relationship('AspNetUsers', back_populates='AspNetUserClaims')
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
class AspNetUserLogins(Base):
|
| 247 |
+
__tablename__ = 'AspNetUserLogins'
|
| 248 |
+
__table_args__ = (
|
| 249 |
+
ForeignKeyConstraint(['UserId'], ['AspNetUsers.Id'], ondelete='CASCADE', name='FK_AspNetUserLogins_AspNetUsers_UserId'),
|
| 250 |
+
PrimaryKeyConstraint('LoginProvider', 'ProviderKey', name='PK_AspNetUserLogins'),
|
| 251 |
+
Index('IX_AspNetUserLogins_UserId', 'UserId')
|
| 252 |
+
)
|
| 253 |
+
|
| 254 |
+
LoginProvider: Mapped[str] = mapped_column(Unicode(450, 'SQL_Latin1_General_CP1_CI_AS'), primary_key=True)
|
| 255 |
+
ProviderKey: Mapped[str] = mapped_column(Unicode(450, 'SQL_Latin1_General_CP1_CI_AS'), primary_key=True)
|
| 256 |
+
UserId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 257 |
+
ProviderDisplayName: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 258 |
+
|
| 259 |
+
AspNetUsers_: Mapped['AspNetUsers'] = relationship('AspNetUsers', back_populates='AspNetUserLogins')
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
t_AspNetUserRoles = Table(
|
| 263 |
+
'AspNetUserRoles', Base.metadata,
|
| 264 |
+
Column('UserId', Uuid, primary_key=True, nullable=False),
|
| 265 |
+
Column('RoleId', Uuid, primary_key=True, nullable=False),
|
| 266 |
+
ForeignKeyConstraint(['RoleId'], ['AspNetRoles.Id'], ondelete='CASCADE', name='FK_AspNetUserRoles_AspNetRoles_RoleId'),
|
| 267 |
+
ForeignKeyConstraint(['UserId'], ['AspNetUsers.Id'], ondelete='CASCADE', name='FK_AspNetUserRoles_AspNetUsers_UserId'),
|
| 268 |
+
PrimaryKeyConstraint('UserId', 'RoleId', name='PK_AspNetUserRoles'),
|
| 269 |
+
Index('IX_AspNetUserRoles_RoleId', 'RoleId')
|
| 270 |
+
)
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
class AspNetUserTokens(Base):
|
| 274 |
+
__tablename__ = 'AspNetUserTokens'
|
| 275 |
+
__table_args__ = (
|
| 276 |
+
ForeignKeyConstraint(['UserId'], ['AspNetUsers.Id'], ondelete='CASCADE', name='FK_AspNetUserTokens_AspNetUsers_UserId'),
|
| 277 |
+
PrimaryKeyConstraint('UserId', 'LoginProvider', 'Name', name='PK_AspNetUserTokens')
|
| 278 |
+
)
|
| 279 |
+
|
| 280 |
+
UserId: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 281 |
+
LoginProvider: Mapped[str] = mapped_column(Unicode(450, 'SQL_Latin1_General_CP1_CI_AS'), primary_key=True)
|
| 282 |
+
Name: Mapped[str] = mapped_column(Unicode(450, 'SQL_Latin1_General_CP1_CI_AS'), primary_key=True)
|
| 283 |
+
Value: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 284 |
+
|
| 285 |
+
AspNetUsers_: Mapped['AspNetUsers'] = relationship('AspNetUsers', back_populates='AspNetUserTokens')
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
class CategoryAttributes(Base):
|
| 289 |
+
__tablename__ = 'CategoryAttributes'
|
| 290 |
+
__table_args__ = (
|
| 291 |
+
ForeignKeyConstraint(['AttributeId'], ['Attributes.Id'], ondelete='CASCADE', name='FK_CategoryAttributes_Attributes_AttributeId'),
|
| 292 |
+
ForeignKeyConstraint(['CategoryId'], ['Categories.Id'], ondelete='CASCADE', name='FK_CategoryAttributes_Categories_CategoryId'),
|
| 293 |
+
PrimaryKeyConstraint('Id', name='PK_CategoryAttributes'),
|
| 294 |
+
Index('IX_CategoryAttributes_AttributeId', 'AttributeId'),
|
| 295 |
+
Index('IX_CategoryAttributes_CategoryId', 'CategoryId')
|
| 296 |
+
)
|
| 297 |
+
|
| 298 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 299 |
+
CategoryId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 300 |
+
AttributeId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 301 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 302 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 303 |
+
|
| 304 |
+
Attributes_: Mapped['Attributes'] = relationship('Attributes', back_populates='CategoryAttributes')
|
| 305 |
+
Categories_: Mapped['Categories'] = relationship('Categories', back_populates='CategoryAttributes')
|
| 306 |
+
|
| 307 |
+
|
| 308 |
+
class Payments(Base):
|
| 309 |
+
__tablename__ = 'Payments'
|
| 310 |
+
__table_args__ = (
|
| 311 |
+
ForeignKeyConstraint(['UserId'], ['AspNetUsers.Id'], ondelete='CASCADE', name='FK_Payments_AspNetUsers_UserId'),
|
| 312 |
+
PrimaryKeyConstraint('Id', name='PK_Payments'),
|
| 313 |
+
Index('IX_Payments_UserId', 'UserId')
|
| 314 |
+
)
|
| 315 |
+
|
| 316 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 317 |
+
CardHolderName: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 318 |
+
CardNumber: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 319 |
+
CardType: Mapped[str] = mapped_column(Unicode(20, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 320 |
+
ExpirationDate: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 321 |
+
Method: Mapped[str] = mapped_column(Unicode(20, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 322 |
+
IsDefault: Mapped[bool] = mapped_column(Boolean, server_default=text('(CONVERT([bit],(0)))'))
|
| 323 |
+
UserId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 324 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 325 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 326 |
+
|
| 327 |
+
AspNetUsers_: Mapped['AspNetUsers'] = relationship('AspNetUsers', back_populates='Payments')
|
| 328 |
+
Orders: Mapped[List['Orders']] = relationship('Orders', back_populates='Payments_')
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
class Products(Base):
|
| 332 |
+
__tablename__ = 'Products'
|
| 333 |
+
__table_args__ = (
|
| 334 |
+
ForeignKeyConstraint(['CategoryId'], ['Categories.Id'], ondelete='CASCADE', name='FK_Products_Categories_CategoryId'),
|
| 335 |
+
ForeignKeyConstraint(['PlacementId'], ['Placements.Id'], ondelete='CASCADE', name='FK_Products_Placements_PlacementId'),
|
| 336 |
+
PrimaryKeyConstraint('Id', name='PK_Products'),
|
| 337 |
+
Index('IX_Products_CategoryId', 'CategoryId'),
|
| 338 |
+
Index('IX_Products_PlacementId', 'PlacementId')
|
| 339 |
+
)
|
| 340 |
+
|
| 341 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 342 |
+
Name: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 343 |
+
Price: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 344 |
+
Description: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 345 |
+
IsActive: Mapped[bool] = mapped_column(Boolean)
|
| 346 |
+
CategoryId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 347 |
+
PlacementId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 348 |
+
Status: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 349 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 350 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 351 |
+
ImageUrl: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 352 |
+
|
| 353 |
+
Categories_: Mapped['Categories'] = relationship('Categories', back_populates='Products')
|
| 354 |
+
Placements_: Mapped['Placements'] = relationship('Placements', back_populates='Products')
|
| 355 |
+
Promotions_: Mapped[List['Promotions']] = relationship('Promotions', secondary='ProductPromotion', back_populates='Products')
|
| 356 |
+
AttributeValues: Mapped[List['AttributeValues']] = relationship('AttributeValues', back_populates='Products_')
|
| 357 |
+
ProductCombos: Mapped[List['ProductCombos']] = relationship('ProductCombos', back_populates='Products_')
|
| 358 |
+
Variants: Mapped[List['Variants']] = relationship('Variants', back_populates='Products_')
|
| 359 |
+
|
| 360 |
+
|
| 361 |
+
class AttributeValues(Base):
|
| 362 |
+
__tablename__ = 'AttributeValues'
|
| 363 |
+
__table_args__ = (
|
| 364 |
+
ForeignKeyConstraint(['AttributeId'], ['Attributes.Id'], ondelete='CASCADE', name='FK_AttributeValues_Attributes_AttributeId'),
|
| 365 |
+
ForeignKeyConstraint(['ProductId'], ['Products.Id'], name='FK_AttributeValues_Products_ProductId'),
|
| 366 |
+
PrimaryKeyConstraint('Id', name='PK_AttributeValues'),
|
| 367 |
+
Index('IX_AttributeValues_AttributeId', 'AttributeId'),
|
| 368 |
+
Index('IX_AttributeValues_ProductId', 'ProductId')
|
| 369 |
+
)
|
| 370 |
+
|
| 371 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 372 |
+
Value: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 373 |
+
AttributeId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 374 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 375 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 376 |
+
ProductId: Mapped[Optional[uuid.UUID]] = mapped_column(Uuid)
|
| 377 |
+
|
| 378 |
+
Attributes_: Mapped['Attributes'] = relationship('Attributes', back_populates='AttributeValues')
|
| 379 |
+
Products_: Mapped[Optional['Products']] = relationship('Products', back_populates='AttributeValues')
|
| 380 |
+
VariantAttributes: Mapped[List['VariantAttributes']] = relationship('VariantAttributes', back_populates='AttributeValues_')
|
| 381 |
+
|
| 382 |
+
|
| 383 |
+
class Orders(Base):
|
| 384 |
+
__tablename__ = 'Orders'
|
| 385 |
+
__table_args__ = (
|
| 386 |
+
ForeignKeyConstraint(['AddressId'], ['Addresses.Id'], name='FK_Orders_Addresses_AddressId'),
|
| 387 |
+
ForeignKeyConstraint(['PaymentId'], ['Payments.Id'], name='FK_Orders_Payments_PaymentId'),
|
| 388 |
+
ForeignKeyConstraint(['PromotionId'], ['Promotions.Id'], name='FK_Orders_Promotions_PromotionId'),
|
| 389 |
+
ForeignKeyConstraint(['UserId'], ['AspNetUsers.Id'], name='FK_Orders_AspNetUsers_UserId'),
|
| 390 |
+
PrimaryKeyConstraint('Id', name='PK_Orders'),
|
| 391 |
+
Index('IX_Orders_AddressId', 'AddressId'),
|
| 392 |
+
Index('IX_Orders_PaymentId', 'PaymentId'),
|
| 393 |
+
Index('IX_Orders_PromotionId', 'PromotionId'),
|
| 394 |
+
Index('IX_Orders_UserId', 'UserId')
|
| 395 |
+
)
|
| 396 |
+
|
| 397 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 398 |
+
UserId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 399 |
+
AddressId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 400 |
+
Status: Mapped[int] = mapped_column(Integer)
|
| 401 |
+
TotalPrice: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 402 |
+
Discount: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 403 |
+
FinalPrice: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 404 |
+
OrderDate: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 405 |
+
PaymentMethod: Mapped[int] = mapped_column(Integer)
|
| 406 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 407 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 408 |
+
PromotionId: Mapped[Optional[uuid.UUID]] = mapped_column(Uuid)
|
| 409 |
+
Note: Mapped[Optional[str]] = mapped_column(Unicode(500, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 410 |
+
PaymentId: Mapped[Optional[uuid.UUID]] = mapped_column(Uuid)
|
| 411 |
+
ShippingCode: Mapped[Optional[str]] = mapped_column(Unicode(50, 'SQL_Latin1_General_CP1_CI_AS'))
|
| 412 |
+
ShippingRate: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 413 |
+
PaymentLinkId: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 414 |
+
PaymentLinkUrl: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 415 |
+
PaymentOrderCode: Mapped[Optional[int]] = mapped_column(BigInteger)
|
| 416 |
+
|
| 417 |
+
Addresses_: Mapped['Addresses'] = relationship('Addresses', back_populates='Orders')
|
| 418 |
+
Payments_: Mapped[Optional['Payments']] = relationship('Payments', back_populates='Orders')
|
| 419 |
+
Promotions_: Mapped[Optional['Promotions']] = relationship('Promotions', back_populates='Orders')
|
| 420 |
+
AspNetUsers_: Mapped['AspNetUsers'] = relationship('AspNetUsers', back_populates='Orders')
|
| 421 |
+
OrderDetails: Mapped[List['OrderDetails']] = relationship('OrderDetails', back_populates='Orders_')
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
class ProductCombos(Base):
|
| 425 |
+
__tablename__ = 'ProductCombos'
|
| 426 |
+
__table_args__ = (
|
| 427 |
+
ForeignKeyConstraint(['ComboId'], ['Combos.Id'], ondelete='CASCADE', name='FK_ProductCombos_Combos_ComboId'),
|
| 428 |
+
ForeignKeyConstraint(['ProductId'], ['Products.Id'], ondelete='CASCADE', name='FK_ProductCombos_Products_ProductId'),
|
| 429 |
+
PrimaryKeyConstraint('Id', name='PK_ProductCombos'),
|
| 430 |
+
Index('IX_ProductCombos_ComboId', 'ComboId'),
|
| 431 |
+
Index('IX_ProductCombos_ProductId', 'ProductId')
|
| 432 |
+
)
|
| 433 |
+
|
| 434 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 435 |
+
ProductId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 436 |
+
ComboId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 437 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 438 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 439 |
+
|
| 440 |
+
Combos_: Mapped['Combos'] = relationship('Combos', back_populates='ProductCombos')
|
| 441 |
+
Products_: Mapped['Products'] = relationship('Products', back_populates='ProductCombos')
|
| 442 |
+
|
| 443 |
+
|
| 444 |
+
t_ProductPromotion = Table(
|
| 445 |
+
'ProductPromotion', Base.metadata,
|
| 446 |
+
Column('ProductsId', Uuid, primary_key=True, nullable=False),
|
| 447 |
+
Column('PromotionsId', Uuid, primary_key=True, nullable=False),
|
| 448 |
+
ForeignKeyConstraint(['ProductsId'], ['Products.Id'], ondelete='CASCADE', name='FK_ProductPromotion_Products_ProductsId'),
|
| 449 |
+
ForeignKeyConstraint(['PromotionsId'], ['Promotions.Id'], ondelete='CASCADE', name='FK_ProductPromotion_Promotions_PromotionsId'),
|
| 450 |
+
PrimaryKeyConstraint('ProductsId', 'PromotionsId', name='PK_ProductPromotion'),
|
| 451 |
+
Index('IX_ProductPromotion_PromotionsId', 'PromotionsId')
|
| 452 |
+
)
|
| 453 |
+
|
| 454 |
+
|
| 455 |
+
class Variants(Base):
|
| 456 |
+
__tablename__ = 'Variants'
|
| 457 |
+
__table_args__ = (
|
| 458 |
+
ForeignKeyConstraint(['ProductId'], ['Products.Id'], name='FK_Variants_Products_ProductId'),
|
| 459 |
+
PrimaryKeyConstraint('Id', name='PK_Variants'),
|
| 460 |
+
Index('IX_Variants_ProductId', 'ProductId')
|
| 461 |
+
)
|
| 462 |
+
|
| 463 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 464 |
+
ImageUrls: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 465 |
+
PriceAdjustment: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 466 |
+
Stock: Mapped[int] = mapped_column(Integer)
|
| 467 |
+
IsActive: Mapped[bool] = mapped_column(Boolean)
|
| 468 |
+
Sku: Mapped[str] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 469 |
+
ProductId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 470 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 471 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 472 |
+
|
| 473 |
+
Products_: Mapped['Products'] = relationship('Products', back_populates='Variants')
|
| 474 |
+
GoodReceivedNotes: Mapped[List['GoodReceivedNotes']] = relationship('GoodReceivedNotes', back_populates='Variants_')
|
| 475 |
+
OrderDetails: Mapped[List['OrderDetails']] = relationship('OrderDetails', back_populates='Variants_')
|
| 476 |
+
VariantAttributes: Mapped[List['VariantAttributes']] = relationship('VariantAttributes', back_populates='Variants_')
|
| 477 |
+
GoodReceivedItems: Mapped[List['GoodReceivedItems']] = relationship('GoodReceivedItems', back_populates='Variants_')
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
class GoodReceivedNotes(Base):
|
| 481 |
+
__tablename__ = 'GoodReceivedNotes'
|
| 482 |
+
__table_args__ = (
|
| 483 |
+
ForeignKeyConstraint(['VariantId'], ['Variants.Id'], name='FK_GoodReceivedNotes_Variants_VariantId'),
|
| 484 |
+
PrimaryKeyConstraint('Id', name='PK_GoodReceivedNotes'),
|
| 485 |
+
Index('IX_GoodReceivedNotes_VariantId', 'VariantId')
|
| 486 |
+
)
|
| 487 |
+
|
| 488 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 489 |
+
ReceivedDate: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 490 |
+
Quantity: Mapped[int] = mapped_column(Integer)
|
| 491 |
+
TotalCost: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 492 |
+
ShippingCost: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 493 |
+
Status: Mapped[int] = mapped_column(Integer)
|
| 494 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 495 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 496 |
+
Note: Mapped[Optional[str]] = mapped_column(Unicode(collation='SQL_Latin1_General_CP1_CI_AS'))
|
| 497 |
+
VariantId: Mapped[Optional[uuid.UUID]] = mapped_column(Uuid)
|
| 498 |
+
|
| 499 |
+
Variants_: Mapped[Optional['Variants']] = relationship('Variants', back_populates='GoodReceivedNotes')
|
| 500 |
+
GoodReceivedItems: Mapped[List['GoodReceivedItems']] = relationship('GoodReceivedItems', back_populates='GoodReceivedNotes_')
|
| 501 |
+
|
| 502 |
+
|
| 503 |
+
class OrderDetails(Base):
|
| 504 |
+
__tablename__ = 'OrderDetails'
|
| 505 |
+
__table_args__ = (
|
| 506 |
+
ForeignKeyConstraint(['OrderId'], ['Orders.Id'], name='FK_OrderDetails_Orders_OrderId'),
|
| 507 |
+
ForeignKeyConstraint(['VariantId'], ['Variants.Id'], name='FK_OrderDetails_Variants_VariantId'),
|
| 508 |
+
PrimaryKeyConstraint('Id', name='PK_OrderDetails'),
|
| 509 |
+
Index('IX_OrderDetails_OrderId', 'OrderId'),
|
| 510 |
+
Index('IX_OrderDetails_VariantId', 'VariantId')
|
| 511 |
+
)
|
| 512 |
+
|
| 513 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 514 |
+
OrderId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 515 |
+
VariantId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 516 |
+
Quantity: Mapped[int] = mapped_column(Integer, server_default=text('((1))'))
|
| 517 |
+
UnitPrice: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2), server_default=text('((0.0))'))
|
| 518 |
+
TotalPrice: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2), server_default=text('((0.0))'))
|
| 519 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 520 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 521 |
+
|
| 522 |
+
Orders_: Mapped['Orders'] = relationship('Orders', back_populates='OrderDetails')
|
| 523 |
+
Variants_: Mapped['Variants'] = relationship('Variants', back_populates='OrderDetails')
|
| 524 |
+
Reviews: Mapped[List['Reviews']] = relationship('Reviews', back_populates='OrderDetails_')
|
| 525 |
+
|
| 526 |
+
|
| 527 |
+
class VariantAttributes(Base):
|
| 528 |
+
__tablename__ = 'VariantAttributes'
|
| 529 |
+
__table_args__ = (
|
| 530 |
+
ForeignKeyConstraint(['AttributeValueId'], ['AttributeValues.Id'], name='FK_VariantAttributes_AttributeValues_AttributeValueId'),
|
| 531 |
+
ForeignKeyConstraint(['VariantId'], ['Variants.Id'], ondelete='CASCADE', name='FK_VariantAttributes_Variants_VariantId'),
|
| 532 |
+
PrimaryKeyConstraint('Id', name='PK_VariantAttributes'),
|
| 533 |
+
Index('IX_VariantAttributes_AttributeValueId', 'AttributeValueId'),
|
| 534 |
+
Index('IX_VariantAttributes_VariantId', 'VariantId')
|
| 535 |
+
)
|
| 536 |
+
|
| 537 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 538 |
+
VariantId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 539 |
+
AttributeValueId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 540 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 541 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 542 |
+
|
| 543 |
+
AttributeValues_: Mapped['AttributeValues'] = relationship('AttributeValues', back_populates='VariantAttributes')
|
| 544 |
+
Variants_: Mapped['Variants'] = relationship('Variants', back_populates='VariantAttributes')
|
| 545 |
+
|
| 546 |
+
|
| 547 |
+
class GoodReceivedItems(Base):
|
| 548 |
+
__tablename__ = 'GoodReceivedItems'
|
| 549 |
+
__table_args__ = (
|
| 550 |
+
ForeignKeyConstraint(['GoodReceivedNoteId'], ['GoodReceivedNotes.Id'], ondelete='CASCADE', name='FK_GoodReceivedItems_GoodReceivedNotes_GoodReceivedNoteId'),
|
| 551 |
+
ForeignKeyConstraint(['VariantId'], ['Variants.Id'], ondelete='CASCADE', name='FK_GoodReceivedItems_Variants_VariantId'),
|
| 552 |
+
PrimaryKeyConstraint('Id', name='PK_GoodReceivedItems'),
|
| 553 |
+
Index('IX_GoodReceivedItems_GoodReceivedNoteId', 'GoodReceivedNoteId'),
|
| 554 |
+
Index('IX_GoodReceivedItems_VariantId', 'VariantId')
|
| 555 |
+
)
|
| 556 |
+
|
| 557 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 558 |
+
VariantId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 559 |
+
GoodReceivedNoteId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 560 |
+
Quantity: Mapped[int] = mapped_column(Integer)
|
| 561 |
+
UnitCost: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 562 |
+
TotalCost: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 563 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 564 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 565 |
+
|
| 566 |
+
GoodReceivedNotes_: Mapped['GoodReceivedNotes'] = relationship('GoodReceivedNotes', back_populates='GoodReceivedItems')
|
| 567 |
+
Variants_: Mapped['Variants'] = relationship('Variants', back_populates='GoodReceivedItems')
|
| 568 |
+
|
| 569 |
+
|
| 570 |
+
class Reviews(Base):
|
| 571 |
+
__tablename__ = 'Reviews'
|
| 572 |
+
__table_args__ = (
|
| 573 |
+
ForeignKeyConstraint(['OrderDetailId'], ['OrderDetails.Id'], ondelete='CASCADE', name='FK_Reviews_OrderDetails_OrderDetailId'),
|
| 574 |
+
ForeignKeyConstraint(['UserId'], ['AspNetUsers.Id'], name='FK_Reviews_AspNetUsers_UserId'),
|
| 575 |
+
PrimaryKeyConstraint('Id', name='PK_Reviews'),
|
| 576 |
+
Index('IX_Reviews_OrderDetailId', 'OrderDetailId'),
|
| 577 |
+
Index('IX_Reviews_UserId', 'UserId')
|
| 578 |
+
)
|
| 579 |
+
|
| 580 |
+
Id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
|
| 581 |
+
Rating: Mapped[decimal.Decimal] = mapped_column(DECIMAL(18, 2))
|
| 582 |
+
ReviewText: Mapped[str] = mapped_column(Unicode(1000, 'SQL_Latin1_General_CP1_CI_AS'), server_default=text("(N'')"))
|
| 583 |
+
OrderDetailId: Mapped[uuid.UUID] = mapped_column(Uuid)
|
| 584 |
+
CreatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 585 |
+
UpdatedAt: Mapped[datetime.datetime] = mapped_column(DATETIME2)
|
| 586 |
+
UserId: Mapped[Optional[uuid.UUID]] = mapped_column(Uuid)
|
| 587 |
+
|
| 588 |
+
OrderDetails_: Mapped['OrderDetails'] = relationship('OrderDetails', back_populates='Reviews')
|
| 589 |
+
AspNetUsers_: Mapped[Optional['AspNetUsers']] = relationship('AspNetUsers', back_populates='Reviews')
|
src/database/querries.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
|
|
| 1 |
from sqlalchemy.orm import Session
|
| 2 |
from sqlalchemy.exc import SQLAlchemyError
|
| 3 |
import logging
|
| 4 |
import uuid
|
| 5 |
from src.database.db_connection import create_session
|
| 6 |
-
from src.database.models import
|
| 7 |
|
| 8 |
# Set up logging
|
| 9 |
logger = logging.getLogger(__name__)
|
|
@@ -47,7 +48,7 @@ def get_all_categories(session=None):
|
|
| 47 |
try:
|
| 48 |
# Using SQLAlchemy to query distinct product names
|
| 49 |
from sqlalchemy import text
|
| 50 |
-
result = session.execute(text("SELECT DISTINCT
|
| 51 |
categories = [row[0] for row in result.fetchall()]
|
| 52 |
|
| 53 |
return {
|
|
@@ -104,18 +105,7 @@ def get_all_products(session=None):
|
|
| 104 |
if close_session:
|
| 105 |
session.close()
|
| 106 |
|
| 107 |
-
|
| 108 |
-
def get_user_by_id(user_id, session=None):
|
| 109 |
-
"""
|
| 110 |
-
Get a user by their ID.
|
| 111 |
-
|
| 112 |
-
Args:
|
| 113 |
-
user_id (str or UUID): The ID of the user to retrieve.
|
| 114 |
-
session (Session, optional): SQLAlchemy session.
|
| 115 |
-
|
| 116 |
-
Returns:
|
| 117 |
-
dict: A dictionary containing the user or error information
|
| 118 |
-
"""
|
| 119 |
close_session = False
|
| 120 |
|
| 121 |
if session is None:
|
|
@@ -124,105 +114,50 @@ def get_user_by_id(user_id, session=None):
|
|
| 124 |
return session_result
|
| 125 |
session = session_result["session"]
|
| 126 |
close_session = True
|
| 127 |
-
|
| 128 |
try:
|
| 129 |
-
#
|
| 130 |
-
if
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
"success": False,
|
| 135 |
-
"error": "Invalid user ID format"
|
| 136 |
-
}
|
| 137 |
-
|
| 138 |
-
user = session.query(User).filter(User.id == user_id).first()
|
| 139 |
-
|
| 140 |
-
if user:
|
| 141 |
-
return {
|
| 142 |
-
"success": True,
|
| 143 |
-
"user": user
|
| 144 |
-
}
|
| 145 |
-
else:
|
| 146 |
-
return {
|
| 147 |
-
"success": False,
|
| 148 |
-
"error": f"User with ID {user_id} not found"
|
| 149 |
-
}
|
| 150 |
-
except SQLAlchemyError as e:
|
| 151 |
-
logger.error(f"Error fetching user: {str(e)}")
|
| 152 |
-
return {
|
| 153 |
-
"success": False,
|
| 154 |
-
"error": f"Error fetching user: {str(e)}"
|
| 155 |
-
}
|
| 156 |
-
finally:
|
| 157 |
-
if close_session:
|
| 158 |
-
session.close()
|
| 159 |
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
Args:
|
| 166 |
-
user_id (str or UUID): The ID of the user.
|
| 167 |
-
limit (int): The maximum number of chats to retrieve.
|
| 168 |
-
offset (int): The offset for pagination.
|
| 169 |
-
session (Session, optional): SQLAlchemy session.
|
| 170 |
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
"""
|
| 174 |
-
close_session = False
|
| 175 |
-
|
| 176 |
-
if session is None:
|
| 177 |
-
session_result = create_session()
|
| 178 |
-
if not session_result.get("success"):
|
| 179 |
-
return session_result
|
| 180 |
-
session = session_result["session"]
|
| 181 |
-
close_session = True
|
| 182 |
-
|
| 183 |
-
try:
|
| 184 |
-
# Ensure user_id is a valid UUID
|
| 185 |
-
if isinstance(user_id, str):
|
| 186 |
-
user_id = parse_uuid(user_id)
|
| 187 |
-
if not user_id:
|
| 188 |
-
return {
|
| 189 |
-
"success": False,
|
| 190 |
-
"error": "Invalid user ID format"
|
| 191 |
-
}
|
| 192 |
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
|
| 198 |
return {
|
| 199 |
"success": True,
|
| 200 |
-
"
|
| 201 |
}
|
| 202 |
except SQLAlchemyError as e:
|
| 203 |
-
logger.error(f"Error fetching
|
| 204 |
return {
|
| 205 |
"success": False,
|
| 206 |
-
"error": f"Error fetching
|
| 207 |
}
|
| 208 |
finally:
|
| 209 |
if close_session:
|
| 210 |
session.close()
|
| 211 |
|
| 212 |
-
|
| 213 |
-
def get_messages_by_chat_id(chat_id, limit=50, offset=0, session=None):
|
| 214 |
-
"""
|
| 215 |
-
Get messages for a specific chat.
|
| 216 |
-
|
| 217 |
-
Args:
|
| 218 |
-
chat_id (str or UUID): The ID of the chat.
|
| 219 |
-
limit (int): The maximum number of messages to retrieve.
|
| 220 |
-
offset (int): The offset for pagination.
|
| 221 |
-
session (Session, optional): SQLAlchemy session.
|
| 222 |
-
|
| 223 |
-
Returns:
|
| 224 |
-
dict: A dictionary containing the messages or error information
|
| 225 |
-
"""
|
| 226 |
close_session = False
|
| 227 |
|
| 228 |
if session is None:
|
|
@@ -231,47 +166,78 @@ def get_messages_by_chat_id(chat_id, limit=50, offset=0, session=None):
|
|
| 231 |
return session_result
|
| 232 |
session = session_result["session"]
|
| 233 |
close_session = True
|
| 234 |
-
|
| 235 |
try:
|
| 236 |
-
#
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 244 |
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
|
| 249 |
return {
|
| 250 |
"success": True,
|
| 251 |
-
"
|
| 252 |
}
|
| 253 |
except SQLAlchemyError as e:
|
| 254 |
-
logger.error(f"Error fetching
|
| 255 |
return {
|
| 256 |
"success": False,
|
| 257 |
-
"error": f"Error fetching
|
| 258 |
}
|
| 259 |
finally:
|
| 260 |
if close_session:
|
| 261 |
session.close()
|
| 262 |
|
| 263 |
-
#
|
| 264 |
-
def
|
| 265 |
"""
|
| 266 |
-
|
| 267 |
|
| 268 |
Args:
|
| 269 |
-
user_id (str or UUID): The ID of the user.
|
| 270 |
-
title (str): The title of the chat.
|
| 271 |
session (Session, optional): SQLAlchemy session.
|
| 272 |
|
| 273 |
Returns:
|
| 274 |
-
dict: A dictionary containing the
|
| 275 |
"""
|
| 276 |
close_session = False
|
| 277 |
|
|
@@ -292,39 +258,39 @@ def create_chat(user_id, title="New Chat", session=None):
|
|
| 292 |
"error": "Invalid user ID format"
|
| 293 |
}
|
| 294 |
|
| 295 |
-
|
| 296 |
-
new_chat = Chat(user_id=user_id, title=title)
|
| 297 |
-
session.add(new_chat)
|
| 298 |
-
session.commit()
|
| 299 |
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 304 |
except SQLAlchemyError as e:
|
| 305 |
-
|
| 306 |
-
logger.error(f"Error creating chat: {str(e)}")
|
| 307 |
return {
|
| 308 |
"success": False,
|
| 309 |
-
"error": f"Error
|
| 310 |
}
|
| 311 |
finally:
|
| 312 |
if close_session:
|
| 313 |
session.close()
|
| 314 |
|
| 315 |
-
|
| 316 |
-
def add_message(chat_id, content, role, session=None):
|
| 317 |
"""
|
| 318 |
-
|
| 319 |
|
| 320 |
Args:
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
role (str): The role of the message (user, assistant, etc.).
|
| 324 |
session (Session, optional): SQLAlchemy session.
|
| 325 |
|
| 326 |
Returns:
|
| 327 |
-
dict: A dictionary containing the
|
| 328 |
"""
|
| 329 |
close_session = False
|
| 330 |
|
|
@@ -336,37 +302,49 @@ def add_message(chat_id, content, role, session=None):
|
|
| 336 |
close_session = True
|
| 337 |
|
| 338 |
try:
|
| 339 |
-
#
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 358 |
|
| 359 |
return {
|
| 360 |
"success": True,
|
| 361 |
-
"
|
| 362 |
}
|
| 363 |
except SQLAlchemyError as e:
|
| 364 |
-
|
| 365 |
-
logger.error(f"Error adding message: {str(e)}")
|
| 366 |
return {
|
| 367 |
"success": False,
|
| 368 |
-
"error": f"Error
|
| 369 |
}
|
| 370 |
finally:
|
| 371 |
if close_session:
|
| 372 |
-
session.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sqlalchemy import func
|
| 2 |
from sqlalchemy.orm import Session
|
| 3 |
from sqlalchemy.exc import SQLAlchemyError
|
| 4 |
import logging
|
| 5 |
import uuid
|
| 6 |
from src.database.db_connection import create_session
|
| 7 |
+
from src.database.models import AspNetUsers, Products, Categories, Variants, OrderDetails, Orders, Placements, Attributes, AttributeValues, VariantAttributes
|
| 8 |
|
| 9 |
# Set up logging
|
| 10 |
logger = logging.getLogger(__name__)
|
|
|
|
| 48 |
try:
|
| 49 |
# Using SQLAlchemy to query distinct product names
|
| 50 |
from sqlalchemy import text
|
| 51 |
+
result = session.execute(text("SELECT DISTINCT Name FROM Categories"))
|
| 52 |
categories = [row[0] for row in result.fetchall()]
|
| 53 |
|
| 54 |
return {
|
|
|
|
| 105 |
if close_session:
|
| 106 |
session.close()
|
| 107 |
|
| 108 |
+
def get_product_by_price_range(category = None, min_price = None, max_price = None, session=None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
close_session = False
|
| 110 |
|
| 111 |
if session is None:
|
|
|
|
| 114 |
return session_result
|
| 115 |
session = session_result["session"]
|
| 116 |
close_session = True
|
| 117 |
+
|
| 118 |
try:
|
| 119 |
+
# Using SQLAlchemy to query products by price range and category
|
| 120 |
+
if min_price is None:
|
| 121 |
+
min_price = 0
|
| 122 |
+
if max_price is None:
|
| 123 |
+
max_price = float('inf')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
+
query = session.query(Products).filter(
|
| 126 |
+
Products.Price >= min_price,
|
| 127 |
+
Products.Price <= max_price
|
| 128 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
+
if category:
|
| 131 |
+
query = query.filter(Products.CategoryId == category)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
|
| 133 |
+
result = query.all()
|
| 134 |
+
|
| 135 |
+
products = []
|
| 136 |
+
for row in result:
|
| 137 |
+
product_dict = {
|
| 138 |
+
"product": {
|
| 139 |
+
"name": row.Name,
|
| 140 |
+
"description": row.Description,
|
| 141 |
+
"price": float(row.Price),
|
| 142 |
+
},
|
| 143 |
+
}
|
| 144 |
+
products.append(product_dict)
|
| 145 |
|
| 146 |
return {
|
| 147 |
"success": True,
|
| 148 |
+
"results": products
|
| 149 |
}
|
| 150 |
except SQLAlchemyError as e:
|
| 151 |
+
logger.error(f"Error fetching products by price range: {str(e)}")
|
| 152 |
return {
|
| 153 |
"success": False,
|
| 154 |
+
"error": f"Error fetching products by price range: {str(e)}"
|
| 155 |
}
|
| 156 |
finally:
|
| 157 |
if close_session:
|
| 158 |
session.close()
|
| 159 |
|
| 160 |
+
def get_product_information_by_name(product_name, session=None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
close_session = False
|
| 162 |
|
| 163 |
if session is None:
|
|
|
|
| 166 |
return session_result
|
| 167 |
session = session_result["session"]
|
| 168 |
close_session = True
|
| 169 |
+
|
| 170 |
try:
|
| 171 |
+
# Using SQLAlchemy to query product information by name
|
| 172 |
+
query = session.query(
|
| 173 |
+
Products,
|
| 174 |
+
Categories,
|
| 175 |
+
Placements,
|
| 176 |
+
Variants,
|
| 177 |
+
VariantAttributes,
|
| 178 |
+
AttributeValues,
|
| 179 |
+
Attributes
|
| 180 |
+
).join(
|
| 181 |
+
Categories, Products.CategoryId == Categories.Id
|
| 182 |
+
).join(
|
| 183 |
+
Placements, Products.PlacementId == Placements.Id
|
| 184 |
+
).join(
|
| 185 |
+
Variants, Products.Id == Variants.ProductId
|
| 186 |
+
).join(
|
| 187 |
+
VariantAttributes, Variants.Id == VariantAttributes.VariantId
|
| 188 |
+
).join(
|
| 189 |
+
AttributeValues, VariantAttributes.AttributeValueId == AttributeValues.Id
|
| 190 |
+
).join(
|
| 191 |
+
Attributes, AttributeValues.AttributeId == Attributes.Id
|
| 192 |
+
).filter(
|
| 193 |
+
Products.Name == product_name
|
| 194 |
+
)
|
| 195 |
+
|
| 196 |
+
result = query.all()
|
| 197 |
|
| 198 |
+
# Transform the result into a dictionary format
|
| 199 |
+
products = []
|
| 200 |
+
for row in result:
|
| 201 |
+
product_dict = {
|
| 202 |
+
"product": {
|
| 203 |
+
"name": row.Products.Name,
|
| 204 |
+
"description": row.Products.Description,
|
| 205 |
+
"price": float(row.Products.Price),
|
| 206 |
+
"category": row.Categories.Name,
|
| 207 |
+
"placement": row.Placements.Name,
|
| 208 |
+
},
|
| 209 |
+
"attribute": {
|
| 210 |
+
"name": row.Attributes.Name,
|
| 211 |
+
"value": row.AttributeValues.Value
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
products.append(product_dict)
|
| 215 |
|
| 216 |
return {
|
| 217 |
"success": True,
|
| 218 |
+
"results": products
|
| 219 |
}
|
| 220 |
except SQLAlchemyError as e:
|
| 221 |
+
logger.error(f"Error fetching product information: {str(e)}")
|
| 222 |
return {
|
| 223 |
"success": False,
|
| 224 |
+
"error": f"Error fetching product information: {str(e)}"
|
| 225 |
}
|
| 226 |
finally:
|
| 227 |
if close_session:
|
| 228 |
session.close()
|
| 229 |
|
| 230 |
+
# User-related queries
|
| 231 |
+
def get_user_by_id(user_id, session=None):
|
| 232 |
"""
|
| 233 |
+
Get a user by their ID.
|
| 234 |
|
| 235 |
Args:
|
| 236 |
+
user_id (str or UUID): The ID of the user to retrieve.
|
|
|
|
| 237 |
session (Session, optional): SQLAlchemy session.
|
| 238 |
|
| 239 |
Returns:
|
| 240 |
+
dict: A dictionary containing the user or error information
|
| 241 |
"""
|
| 242 |
close_session = False
|
| 243 |
|
|
|
|
| 258 |
"error": "Invalid user ID format"
|
| 259 |
}
|
| 260 |
|
| 261 |
+
user = session.query(AspNetUsers).filter(AspNetUsers.id == user_id).first()
|
|
|
|
|
|
|
|
|
|
| 262 |
|
| 263 |
+
if user:
|
| 264 |
+
return {
|
| 265 |
+
"success": True,
|
| 266 |
+
"user": user
|
| 267 |
+
}
|
| 268 |
+
else:
|
| 269 |
+
return {
|
| 270 |
+
"success": False,
|
| 271 |
+
"error": f"User with ID {user_id} not found"
|
| 272 |
+
}
|
| 273 |
except SQLAlchemyError as e:
|
| 274 |
+
logger.error(f"Error fetching user: {str(e)}")
|
|
|
|
| 275 |
return {
|
| 276 |
"success": False,
|
| 277 |
+
"error": f"Error fetching user: {str(e)}"
|
| 278 |
}
|
| 279 |
finally:
|
| 280 |
if close_session:
|
| 281 |
session.close()
|
| 282 |
|
| 283 |
+
def get_top_sale_products(category, limit=10, session=None):
|
|
|
|
| 284 |
"""
|
| 285 |
+
Get top-selling products based on sales data.
|
| 286 |
|
| 287 |
Args:
|
| 288 |
+
category (str): The category of products to filter by.
|
| 289 |
+
limit (int): The maximum number of top-selling products to return.
|
|
|
|
| 290 |
session (Session, optional): SQLAlchemy session.
|
| 291 |
|
| 292 |
Returns:
|
| 293 |
+
dict: A dictionary containing the top-selling products or error information
|
| 294 |
"""
|
| 295 |
close_session = False
|
| 296 |
|
|
|
|
| 302 |
close_session = True
|
| 303 |
|
| 304 |
try:
|
| 305 |
+
# Using SQLAlchemy to query top-selling products
|
| 306 |
+
result = session.execute(Categories.__table__.join(
|
| 307 |
+
Products, Categories.Id == Products.CategoryId
|
| 308 |
+
).join(
|
| 309 |
+
Variants, Products.Id== Variants.ProductId
|
| 310 |
+
).join(
|
| 311 |
+
OrderDetails, Variants.Id == OrderDetails.VariantId
|
| 312 |
+
).join(
|
| 313 |
+
Orders, OrderDetails.OrderId == Orders.Id
|
| 314 |
+
).
|
| 315 |
+
filter(
|
| 316 |
+
Categories.Name == category
|
| 317 |
+
).group_by(
|
| 318 |
+
Products.Id
|
| 319 |
+
).order_by(
|
| 320 |
+
func.sum(OrderDetails.Quantity).desc()
|
| 321 |
+
).limit(limit))
|
| 322 |
+
|
| 323 |
+
print(f"Query executed: {result}")
|
| 324 |
+
|
| 325 |
+
top_sales_products = [dict(row._mapping) for row in result.fetchall()]
|
| 326 |
+
|
| 327 |
+
print(f"Top-selling products in category '{category}': {top_sales_products}")
|
| 328 |
|
| 329 |
return {
|
| 330 |
"success": True,
|
| 331 |
+
"top_sales_products": top_sales_products
|
| 332 |
}
|
| 333 |
except SQLAlchemyError as e:
|
| 334 |
+
logger.error(f"Error fetching top-selling products: {str(e)}")
|
|
|
|
| 335 |
return {
|
| 336 |
"success": False,
|
| 337 |
+
"error": f"Error fetching top-selling products: {str(e)}"
|
| 338 |
}
|
| 339 |
finally:
|
| 340 |
if close_session:
|
| 341 |
+
session.close()
|
| 342 |
+
|
| 343 |
+
top_products = [dict(row._mapping) for row in result.fetchall()]
|
| 344 |
+
|
| 345 |
+
return {
|
| 346 |
+
"success": True,
|
| 347 |
+
"top_products": top_products
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
|
src/services/__pycache__/chat_service.cpython-313.pyc
CHANGED
|
Binary files a/src/services/__pycache__/chat_service.cpython-313.pyc and b/src/services/__pycache__/chat_service.cpython-313.pyc differ
|
|
|
src/services/chat_service.py
CHANGED
|
@@ -16,51 +16,27 @@ def calculate_office_space(furniture_items):
|
|
| 16 |
}
|
| 17 |
|
| 18 |
total_space = 0
|
| 19 |
-
|
| 20 |
for item in furniture_items:
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
| 23 |
else:
|
| 24 |
-
|
| 25 |
|
| 26 |
result = {
|
| 27 |
"total_space": total_space,
|
| 28 |
-
"unknown_items":
|
| 29 |
}
|
| 30 |
|
| 31 |
return result
|
| 32 |
|
| 33 |
-
def
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
{"name": "Sleek Executive Chair", "price": 499, "description": "Premium modern chair with memory foam padding"}
|
| 39 |
-
],
|
| 40 |
-
"classic": [
|
| 41 |
-
{"name": "Leather Executive Chair", "price": 399, "description": "Traditional leather chair with brass accents"},
|
| 42 |
-
{"name": "Wooden Armchair", "price": 299, "description": "Solid wood chair with cushioned seat"}
|
| 43 |
-
]
|
| 44 |
-
},
|
| 45 |
-
"desk": {
|
| 46 |
-
"modern": [
|
| 47 |
-
{"name": "Glass Computer Desk", "price": 349, "description": "Minimalist glass desk with metal frame"},
|
| 48 |
-
{"name": "Adjustable Standing Desk", "price": 649, "description": "Electric height-adjustable modern desk"}
|
| 49 |
-
],
|
| 50 |
-
"classic": [
|
| 51 |
-
{"name": "Executive Wooden Desk", "price": 799, "description": "Mahogany desk with classic design"},
|
| 52 |
-
{"name": "Traditional Writing Desk", "price": 459, "description": "Solid wood desk with drawers"}
|
| 53 |
-
]
|
| 54 |
-
}
|
| 55 |
-
}
|
| 56 |
-
|
| 57 |
-
if product_type.lower() in catalog:
|
| 58 |
-
products = catalog[product_type][style]
|
| 59 |
-
|
| 60 |
-
if budget is not None:
|
| 61 |
-
products = [product for product in products if product["price"] <= budget]
|
| 62 |
-
|
| 63 |
-
return products
|
| 64 |
|
| 65 |
def get_all_categories():
|
| 66 |
# Import the database function at the function level to avoid circular imports
|
|
@@ -68,3 +44,14 @@ def get_all_categories():
|
|
| 68 |
all_categories = db_get_all_categories()
|
| 69 |
return all_categories
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
}
|
| 17 |
|
| 18 |
total_space = 0
|
| 19 |
+
unknown_items = []
|
| 20 |
for item in furniture_items:
|
| 21 |
+
item_name = item.get("item_name", "").lower()
|
| 22 |
+
quantity = item.get("quantity", 0)
|
| 23 |
+
if item_name in space_requirements:
|
| 24 |
+
total_space += space_requirements[item_name] * quantity
|
| 25 |
else:
|
| 26 |
+
unknown_items.append(item_name)
|
| 27 |
|
| 28 |
result = {
|
| 29 |
"total_space": total_space,
|
| 30 |
+
"unknown_items": unknown_items
|
| 31 |
}
|
| 32 |
|
| 33 |
return result
|
| 34 |
|
| 35 |
+
def get_top_sales_products(category, limit):
|
| 36 |
+
# Import the database function at the function level to avoid circular imports
|
| 37 |
+
from src.database.querries import get_top_sale_products
|
| 38 |
+
top_sales = get_top_sale_products(category, limit)
|
| 39 |
+
return top_sales
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
def get_all_categories():
|
| 42 |
# Import the database function at the function level to avoid circular imports
|
|
|
|
| 44 |
all_categories = db_get_all_categories()
|
| 45 |
return all_categories
|
| 46 |
|
| 47 |
+
def get_product_information_by_name(product_name):
|
| 48 |
+
# Import the database function at the function level to avoid circular imports
|
| 49 |
+
from src.database.querries import get_product_information_by_name as db_get_product_information_by_name
|
| 50 |
+
product_info = db_get_product_information_by_name(product_name)
|
| 51 |
+
return product_info
|
| 52 |
+
|
| 53 |
+
def get_product_by_price_range(category, min_price, max_price):
|
| 54 |
+
# Import the database function at the function level to avoid circular imports
|
| 55 |
+
from src.database.querries import get_product_by_price_range as db_get_product_by_price_range
|
| 56 |
+
products = db_get_product_by_price_range(category, min_price, max_price)
|
| 57 |
+
return products
|