Shyamnath commited on
Commit
80feb1b
·
0 Parent(s):

Initial commit with Git LFS

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +39 -0
  2. .gitignore +2 -0
  3. Dockerfile +32 -0
  4. HUGGINGFACE_README.md +75 -0
  5. README.md +0 -0
  6. app/__pycache__/database.cpython-311.pyc +0 -0
  7. app/__pycache__/database.cpython-312.pyc +0 -0
  8. app/__pycache__/database.cpython-313.pyc +0 -0
  9. app/__pycache__/firebase_config.cpython-312.pyc +0 -0
  10. app/__pycache__/main.cpython-311.pyc +0 -0
  11. app/__pycache__/main.cpython-312.pyc +0 -0
  12. app/__pycache__/main.cpython-313.pyc +0 -0
  13. app/database.py +204 -0
  14. app/main.py +126 -0
  15. app/models/__pycache__/dish.cpython-311.pyc +0 -0
  16. app/models/__pycache__/dish.cpython-312.pyc +0 -0
  17. app/models/__pycache__/feedback.cpython-311.pyc +0 -0
  18. app/models/__pycache__/feedback.cpython-312.pyc +0 -0
  19. app/models/__pycache__/inventory.cpython-311.pyc +0 -0
  20. app/models/__pycache__/loyalty.cpython-311.pyc +0 -0
  21. app/models/__pycache__/loyalty.cpython-312.pyc +0 -0
  22. app/models/__pycache__/order.cpython-311.pyc +0 -0
  23. app/models/__pycache__/order.cpython-312.pyc +0 -0
  24. app/models/__pycache__/selection_offer.cpython-311.pyc +0 -0
  25. app/models/__pycache__/selection_offer.cpython-312.pyc +0 -0
  26. app/models/__pycache__/settings.cpython-312.pyc +0 -0
  27. app/models/__pycache__/table.cpython-311.pyc +0 -0
  28. app/models/__pycache__/table.cpython-312.pyc +0 -0
  29. app/models/__pycache__/user.cpython-311.pyc +0 -0
  30. app/models/__pycache__/user.cpython-312.pyc +0 -0
  31. app/models/dish.py +36 -0
  32. app/models/feedback.py +22 -0
  33. app/models/loyalty.py +28 -0
  34. app/models/order.py +60 -0
  35. app/models/selection_offer.py +30 -0
  36. app/models/settings.py +34 -0
  37. app/models/table.py +33 -0
  38. app/models/user.py +39 -0
  39. app/routers/__pycache__/admin.cpython-311.pyc +0 -0
  40. app/routers/__pycache__/admin.cpython-312.pyc +0 -0
  41. app/routers/__pycache__/analytics.cpython-312.pyc +0 -0
  42. app/routers/__pycache__/chef.cpython-311.pyc +0 -0
  43. app/routers/__pycache__/chef.cpython-312.pyc +0 -0
  44. app/routers/__pycache__/customer.cpython-311.pyc +0 -0
  45. app/routers/__pycache__/customer.cpython-312.pyc +0 -0
  46. app/routers/__pycache__/feedback.cpython-311.pyc +0 -0
  47. app/routers/__pycache__/feedback.cpython-312.pyc +0 -0
  48. app/routers/__pycache__/loyalty.cpython-311.pyc +0 -0
  49. app/routers/__pycache__/loyalty.cpython-312.pyc +0 -0
  50. app/routers/__pycache__/selection_offer.cpython-311.pyc +0 -0
.gitattributes ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.db filter=lfs diff=lfs merge=lfs -text
37
+ *.jpg filter=lfs diff=lfs merge=lfs -text
38
+ *.jpeg filter=lfs diff=lfs merge=lfs -text
39
+ *.webp filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .venv/
2
+ /frontend/node_modules/
Dockerfile ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use Python 3.10 slim image as base
2
+ FROM python:3.10-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /code
6
+
7
+ # Install system dependencies
8
+ RUN apt-get update && apt-get install -y \
9
+ build-essential \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # Copy requirements first to leverage Docker cache
13
+ COPY requirements.txt .
14
+
15
+ # Install Python dependencies
16
+ RUN pip install --no-cache-dir -r requirements.txt
17
+
18
+ # Copy the rest of the application
19
+ COPY app app/
20
+ COPY templates templates/
21
+ COPY run.py .
22
+ COPY tabble_new.db .
23
+
24
+ # Set environment variables
25
+ ENV PORT=7860
26
+ ENV HOST=0.0.0.0
27
+
28
+ # Expose the port
29
+ EXPOSE 7860
30
+
31
+ # Command to run the application
32
+ CMD ["python", "run.py"]
HUGGINGFACE_README.md ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Deploying to Hugging Face Spaces
2
+
3
+ This guide explains how to deploy the FastAPI backend to Hugging Face Spaces using Docker.
4
+
5
+ ## Prerequisites
6
+
7
+ 1. A Hugging Face account
8
+ 2. Git installed on your machine
9
+ 3. Docker installed (for local testing)
10
+
11
+ ## Steps to Deploy
12
+
13
+ 1. Create a new Space on Hugging Face:
14
+ - Go to https://huggingface.co/spaces
15
+ - Click "Create new Space"
16
+ - Select "Docker" as the SDK
17
+ - Choose a name for your space
18
+ - Set visibility (public/private)
19
+
20
+ 2. Clone the new Space repository:
21
+ ```bash
22
+ git clone https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME
23
+ ```
24
+
25
+ 3. Copy the following files to the cloned repository:
26
+ - `Dockerfile`
27
+ - `requirements.txt`
28
+ - `app/` directory
29
+ - `templates/` directory
30
+ - `run.py`
31
+ - `tabble_new.db`
32
+
33
+ 4. Update your environment variables:
34
+ - Go to your Space's Settings
35
+ - Add any necessary environment variables
36
+ - Make sure to add any sensitive information as secrets
37
+
38
+ 5. Commit and push your changes:
39
+ ```bash
40
+ git add .
41
+ git commit -m "Initial commit"
42
+ git push
43
+ ```
44
+
45
+ ## Local Testing
46
+
47
+ Before deploying to Hugging Face, you can test locally using Docker Compose:
48
+
49
+ 1. Build and run the container:
50
+ ```bash
51
+ docker-compose up --build
52
+ ```
53
+
54
+ 2. Access the API at `http://localhost:7860`
55
+
56
+ ## Important Notes
57
+
58
+ 1. The Dockerfile uses port 7860 as required by Hugging Face Spaces
59
+ 2. Make sure your database is properly initialized before deployment
60
+ 3. Static files and images should be stored in the appropriate directories
61
+ 4. Any changes to the code require a new commit and push to update the Space
62
+
63
+ ## Monitoring
64
+
65
+ - Monitor your Space's logs through the Hugging Face interface
66
+ - Check the Space's metrics for usage statistics
67
+ - Use the Space's terminal for debugging if needed
68
+
69
+ ## Troubleshooting
70
+
71
+ If you encounter issues:
72
+ 1. Check the Space's logs for error messages
73
+ 2. Verify all environment variables are set correctly
74
+ 3. Ensure all required files are present in the repository
75
+ 4. Test the application locally using Docker Compose before deploying
README.md ADDED
Binary file (2.77 kB). View file
 
app/__pycache__/database.cpython-311.pyc ADDED
Binary file (11.3 kB). View file
 
app/__pycache__/database.cpython-312.pyc ADDED
Binary file (10.9 kB). View file
 
app/__pycache__/database.cpython-313.pyc ADDED
Binary file (3.34 kB). View file
 
app/__pycache__/firebase_config.cpython-312.pyc ADDED
Binary file (1.7 kB). View file
 
app/__pycache__/main.cpython-311.pyc ADDED
Binary file (5.26 kB). View file
 
app/__pycache__/main.cpython-312.pyc ADDED
Binary file (6.03 kB). View file
 
app/__pycache__/main.cpython-313.pyc ADDED
Binary file (4.54 kB). View file
 
app/database.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import (
2
+ create_engine,
3
+ Column,
4
+ Integer,
5
+ String,
6
+ Float,
7
+ ForeignKey,
8
+ DateTime,
9
+ Text,
10
+ Boolean,
11
+ )
12
+ from sqlalchemy.ext.declarative import declarative_base
13
+ from sqlalchemy.orm import sessionmaker, relationship
14
+ from datetime import datetime, timezone
15
+ import os
16
+
17
+ # Database connection - Using SQLite
18
+ DATABASE_URL = "sqlite:///./tabble_new.db" # Using the new database with offers feature
19
+ engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
20
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
21
+ Base = declarative_base()
22
+
23
+
24
+ # Database models
25
+ class Dish(Base):
26
+ __tablename__ = "dishes"
27
+
28
+ id = Column(Integer, primary_key=True, index=True)
29
+ name = Column(String, index=True)
30
+ description = Column(Text, nullable=True)
31
+ category = Column(String, index=True)
32
+ price = Column(Float)
33
+ quantity = Column(Integer, default=0)
34
+ image_path = Column(String, nullable=True)
35
+ discount = Column(Float, default=0) # Discount amount (percentage)
36
+ is_offer = Column(Integer, default=0) # 0 = not an offer, 1 = is an offer
37
+ is_special = Column(Integer, default=0) # 0 = not special, 1 = today's special
38
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
39
+ updated_at = Column(
40
+ DateTime,
41
+ default=lambda: datetime.now(timezone.utc),
42
+ onupdate=lambda: datetime.now(timezone.utc),
43
+ )
44
+
45
+ # Relationship with OrderItem
46
+ order_items = relationship("OrderItem", back_populates="dish")
47
+
48
+
49
+ class Order(Base):
50
+ __tablename__ = "orders"
51
+
52
+ id = Column(Integer, primary_key=True, index=True)
53
+ table_number = Column(Integer)
54
+ unique_id = Column(String, index=True)
55
+ person_id = Column(Integer, ForeignKey("persons.id"), nullable=True)
56
+ status = Column(String, default="pending") # pending, completed, paid
57
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
58
+ updated_at = Column(
59
+ DateTime,
60
+ default=lambda: datetime.now(timezone.utc),
61
+ onupdate=lambda: datetime.now(timezone.utc),
62
+ )
63
+
64
+ # Relationships
65
+ items = relationship("OrderItem", back_populates="order")
66
+ person = relationship("Person", back_populates="orders")
67
+
68
+
69
+ class Person(Base):
70
+ __tablename__ = "persons"
71
+
72
+ id = Column(Integer, primary_key=True, index=True)
73
+ username = Column(String, unique=True, index=True)
74
+ password = Column(String)
75
+ phone_number = Column(String, unique=True, index=True, nullable=True) # Added phone number field
76
+ visit_count = Column(Integer, default=1)
77
+ last_visit = Column(DateTime, default=lambda: datetime.now(timezone.utc))
78
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
79
+
80
+ # Relationship with Order
81
+ orders = relationship("Order", back_populates="person")
82
+
83
+
84
+ class OrderItem(Base):
85
+ __tablename__ = "order_items"
86
+
87
+ id = Column(Integer, primary_key=True, index=True)
88
+ order_id = Column(Integer, ForeignKey("orders.id"))
89
+ dish_id = Column(Integer, ForeignKey("dishes.id"))
90
+ quantity = Column(Integer, default=1)
91
+ remarks = Column(Text, nullable=True)
92
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
93
+
94
+ # Relationships
95
+ order = relationship("Order", back_populates="items")
96
+ dish = relationship("Dish", back_populates="order_items")
97
+
98
+
99
+ class Feedback(Base):
100
+ __tablename__ = "feedback"
101
+
102
+ id = Column(Integer, primary_key=True, index=True)
103
+ order_id = Column(Integer, ForeignKey("orders.id"))
104
+ person_id = Column(Integer, ForeignKey("persons.id"), nullable=True)
105
+ rating = Column(Integer) # 1-5 stars
106
+ comment = Column(Text, nullable=True)
107
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
108
+
109
+ # Relationships
110
+ order = relationship("Order")
111
+ person = relationship("Person")
112
+
113
+
114
+ class LoyaltyProgram(Base):
115
+ __tablename__ = "loyalty_program"
116
+
117
+ id = Column(Integer, primary_key=True, index=True)
118
+ visit_count = Column(Integer, unique=True) # Number of visits required
119
+ discount_percentage = Column(Float) # Discount percentage
120
+ is_active = Column(Boolean, default=True) # Whether this loyalty tier is active
121
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
122
+ updated_at = Column(
123
+ DateTime,
124
+ default=lambda: datetime.now(timezone.utc),
125
+ onupdate=lambda: datetime.now(timezone.utc),
126
+ )
127
+
128
+
129
+ class SelectionOffer(Base):
130
+ __tablename__ = "selection_offers"
131
+
132
+ id = Column(Integer, primary_key=True, index=True)
133
+ min_amount = Column(Float) # Minimum order amount to qualify
134
+ discount_amount = Column(Float) # Fixed discount amount to apply
135
+ is_active = Column(Boolean, default=True) # Whether this offer is active
136
+ description = Column(String, nullable=True) # Optional description of the offer
137
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
138
+ updated_at = Column(
139
+ DateTime,
140
+ default=lambda: datetime.now(timezone.utc),
141
+ onupdate=lambda: datetime.now(timezone.utc),
142
+ )
143
+
144
+
145
+ class Table(Base):
146
+ __tablename__ = "tables"
147
+
148
+ id = Column(Integer, primary_key=True, index=True)
149
+ table_number = Column(Integer, unique=True) # Table number
150
+ is_occupied = Column(
151
+ Boolean, default=False
152
+ ) # Whether the table is currently occupied
153
+ current_order_id = Column(
154
+ Integer, ForeignKey("orders.id"), nullable=True
155
+ ) # Current active order
156
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
157
+ updated_at = Column(
158
+ DateTime,
159
+ default=lambda: datetime.now(timezone.utc),
160
+ onupdate=lambda: datetime.now(timezone.utc),
161
+ )
162
+
163
+ # Relationship to current order
164
+ current_order = relationship("Order", foreign_keys=[current_order_id])
165
+
166
+
167
+ class Settings(Base):
168
+ __tablename__ = "settings"
169
+
170
+ id = Column(Integer, primary_key=True, index=True)
171
+ hotel_name = Column(String, nullable=False, default="Tabble Hotel")
172
+ address = Column(String, nullable=True)
173
+ contact_number = Column(String, nullable=True)
174
+ email = Column(String, nullable=True)
175
+ tax_id = Column(String, nullable=True)
176
+ logo_path = Column(String, nullable=True)
177
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
178
+ updated_at = Column(
179
+ DateTime,
180
+ default=lambda: datetime.now(timezone.utc),
181
+ onupdate=lambda: datetime.now(timezone.utc),
182
+ )
183
+
184
+
185
+ # Create tables
186
+ def create_tables():
187
+ # Drop the selection_offers table if it exists to force recreation
188
+ try:
189
+ SelectionOffer.__table__.drop(engine)
190
+ print("Dropped selection_offers table to recreate it with the correct schema")
191
+ except:
192
+ print("Could not drop selection_offers table, it might not exist yet")
193
+
194
+ # Create all tables
195
+ Base.metadata.create_all(bind=engine)
196
+
197
+
198
+ # Get database session
199
+ def get_db():
200
+ db = SessionLocal()
201
+ try:
202
+ yield db
203
+ finally:
204
+ db.close()
app/main.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Request, Depends
2
+ from fastapi.staticfiles import StaticFiles
3
+ from fastapi.templating import Jinja2Templates
4
+ from fastapi.responses import HTMLResponse, RedirectResponse, FileResponse
5
+ from fastapi.middleware.cors import CORSMiddleware
6
+ from sqlalchemy.orm import Session
7
+ import uvicorn
8
+ import os
9
+
10
+ from .database import get_db, create_tables
11
+ from .routers import chef, customer, admin, feedback, loyalty, selection_offer, table, analytics, settings
12
+
13
+ # Create FastAPI app
14
+ app = FastAPI(title="Tabble - Hotel Management App")
15
+
16
+ # Add CORS middleware to allow cross-origin requests
17
+ app.add_middleware(
18
+ CORSMiddleware,
19
+ allow_origins=["*"], # Allow all origins
20
+ allow_credentials=True,
21
+ allow_methods=["*"], # Allow all methods
22
+ allow_headers=["*"], # Allow all headers
23
+ )
24
+
25
+ # Mount static files
26
+ app.mount("/static", StaticFiles(directory="app/static"), name="static")
27
+
28
+ # Setup templates
29
+ templates = Jinja2Templates(directory="templates")
30
+
31
+ # Include routers
32
+ app.include_router(chef.router)
33
+ app.include_router(customer.router)
34
+ app.include_router(admin.router)
35
+ app.include_router(feedback.router)
36
+ app.include_router(loyalty.router)
37
+ app.include_router(selection_offer.router)
38
+ app.include_router(table.router)
39
+ app.include_router(analytics.router)
40
+ app.include_router(settings.router)
41
+
42
+ # Create database tables
43
+ create_tables()
44
+
45
+ # Check if we have the React build folder
46
+ react_build_dir = "frontend/build"
47
+ has_react_build = os.path.isdir(react_build_dir)
48
+
49
+ if has_react_build:
50
+ # Mount the React build folder
51
+ app.mount("/", StaticFiles(directory=react_build_dir, html=True), name="react")
52
+
53
+
54
+ # Root route - serve React app in production, otherwise serve index.html template
55
+ @app.get("/", response_class=HTMLResponse)
56
+ async def root(request: Request):
57
+ if has_react_build:
58
+ return FileResponse(f"{react_build_dir}/index.html")
59
+ return templates.TemplateResponse("index.html", {"request": request})
60
+
61
+
62
+ # Chef page
63
+ @app.get("/chef", response_class=HTMLResponse)
64
+ async def chef_page(request: Request):
65
+ return templates.TemplateResponse("chef/index.html", {"request": request})
66
+
67
+
68
+ # Chef orders page
69
+ @app.get("/chef/orders", response_class=HTMLResponse)
70
+ async def chef_orders_page(request: Request):
71
+ return templates.TemplateResponse("chef/orders.html", {"request": request})
72
+
73
+
74
+ # Customer login page
75
+ @app.get("/customer", response_class=HTMLResponse)
76
+ async def customer_login_page(request: Request):
77
+ return templates.TemplateResponse("customer/login.html", {"request": request})
78
+
79
+
80
+ # Customer menu page
81
+ @app.get("/customer/menu", response_class=HTMLResponse)
82
+ async def customer_menu_page(request: Request, table_number: int, unique_id: str):
83
+ return templates.TemplateResponse(
84
+ "customer/menu.html",
85
+ {"request": request, "table_number": table_number, "unique_id": unique_id},
86
+ )
87
+
88
+
89
+ # Admin page
90
+ @app.get("/admin", response_class=HTMLResponse)
91
+ async def admin_page(request: Request):
92
+ return templates.TemplateResponse("admin/index.html", {"request": request})
93
+
94
+
95
+ # Admin dishes page
96
+ @app.get("/admin/dishes", response_class=HTMLResponse)
97
+ async def admin_dishes_page(request: Request):
98
+ return templates.TemplateResponse("admin/dishes.html", {"request": request})
99
+
100
+
101
+ # Analysis page
102
+ @app.get("/analysis", response_class=HTMLResponse)
103
+ async def analysis_page(request: Request):
104
+ return templates.TemplateResponse("analysis/index.html", {"request": request})
105
+
106
+
107
+ # Chef analysis page
108
+ @app.get("/analysis/chef", response_class=HTMLResponse)
109
+ async def chef_analysis_page(request: Request):
110
+ return templates.TemplateResponse("analysis/chef.html", {"request": request})
111
+
112
+
113
+ # Customer analysis page
114
+ @app.get("/analysis/customer", response_class=HTMLResponse)
115
+ async def customer_analysis_page(request: Request):
116
+ return templates.TemplateResponse("analysis/customer.html", {"request": request})
117
+
118
+
119
+ # Dish analysis page
120
+ @app.get("/analysis/dish", response_class=HTMLResponse)
121
+ async def dish_analysis_page(request: Request):
122
+ return templates.TemplateResponse("analysis/dish.html", {"request": request})
123
+
124
+
125
+ if __name__ == "__main__":
126
+ uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)
app/models/__pycache__/dish.cpython-311.pyc ADDED
Binary file (2.51 kB). View file
 
app/models/__pycache__/dish.cpython-312.pyc ADDED
Binary file (1.99 kB). View file
 
app/models/__pycache__/feedback.cpython-311.pyc ADDED
Binary file (1.48 kB). View file
 
app/models/__pycache__/feedback.cpython-312.pyc ADDED
Binary file (1.19 kB). View file
 
app/models/__pycache__/inventory.cpython-311.pyc ADDED
Binary file (2.4 kB). View file
 
app/models/__pycache__/loyalty.cpython-311.pyc ADDED
Binary file (1.91 kB). View file
 
app/models/__pycache__/loyalty.cpython-312.pyc ADDED
Binary file (1.53 kB). View file
 
app/models/__pycache__/order.cpython-311.pyc ADDED
Binary file (3.63 kB). View file
 
app/models/__pycache__/order.cpython-312.pyc ADDED
Binary file (2.94 kB). View file
 
app/models/__pycache__/selection_offer.cpython-311.pyc ADDED
Binary file (2.04 kB). View file
 
app/models/__pycache__/selection_offer.cpython-312.pyc ADDED
Binary file (1.63 kB). View file
 
app/models/__pycache__/settings.cpython-312.pyc ADDED
Binary file (1.78 kB). View file
 
app/models/__pycache__/table.cpython-311.pyc ADDED
Binary file (2.16 kB). View file
 
app/models/__pycache__/table.cpython-312.pyc ADDED
Binary file (1.71 kB). View file
 
app/models/__pycache__/user.cpython-311.pyc ADDED
Binary file (1.68 kB). View file
 
app/models/__pycache__/user.cpython-312.pyc ADDED
Binary file (2.13 kB). View file
 
app/models/dish.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+ class DishBase(BaseModel):
6
+ name: str
7
+ description: Optional[str] = None
8
+ category: str
9
+ price: float
10
+ quantity: int
11
+ discount: Optional[float] = 0
12
+ is_offer: Optional[int] = 0
13
+ is_special: Optional[int] = 0
14
+
15
+ class DishCreate(DishBase):
16
+ pass
17
+
18
+ class DishUpdate(DishBase):
19
+ name: Optional[str] = None
20
+ description: Optional[str] = None
21
+ category: Optional[str] = None
22
+ price: Optional[float] = None
23
+ quantity: Optional[int] = None
24
+ image_path: Optional[str] = None
25
+ discount: Optional[float] = None
26
+ is_offer: Optional[int] = None
27
+ is_special: Optional[int] = None
28
+
29
+ class Dish(DishBase):
30
+ id: int
31
+ image_path: Optional[str] = None
32
+ created_at: datetime
33
+ updated_at: datetime
34
+
35
+ class Config:
36
+ from_attributes = True # Updated from orm_mode for Pydantic V2
app/models/feedback.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+
6
+ class FeedbackBase(BaseModel):
7
+ order_id: int
8
+ rating: int
9
+ comment: Optional[str] = None
10
+ person_id: Optional[int] = None
11
+
12
+
13
+ class FeedbackCreate(FeedbackBase):
14
+ pass
15
+
16
+
17
+ class Feedback(FeedbackBase):
18
+ id: int
19
+ created_at: datetime
20
+
21
+ class Config:
22
+ from_attributes = True # Updated from orm_mode for Pydantic V2
app/models/loyalty.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+
6
+ class LoyaltyProgramBase(BaseModel):
7
+ visit_count: int
8
+ discount_percentage: float
9
+ is_active: bool = True
10
+
11
+
12
+ class LoyaltyProgramCreate(LoyaltyProgramBase):
13
+ pass
14
+
15
+
16
+ class LoyaltyProgramUpdate(BaseModel):
17
+ visit_count: Optional[int] = None
18
+ discount_percentage: Optional[float] = None
19
+ is_active: Optional[bool] = None
20
+
21
+
22
+ class LoyaltyProgram(LoyaltyProgramBase):
23
+ id: int
24
+ created_at: datetime
25
+ updated_at: datetime
26
+
27
+ class Config:
28
+ from_attributes = True # Updated from orm_mode for Pydantic V2
app/models/order.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import List, Optional
3
+ from datetime import datetime
4
+ from .dish import Dish
5
+
6
+
7
+ class OrderItemBase(BaseModel):
8
+ dish_id: int
9
+ quantity: int = 1
10
+ remarks: Optional[str] = None
11
+
12
+
13
+ class OrderItemCreate(OrderItemBase):
14
+ pass
15
+
16
+
17
+ class OrderItem(OrderItemBase):
18
+ id: int
19
+ order_id: int
20
+ created_at: datetime
21
+ dish: Optional[Dish] = None
22
+
23
+ # Add dish_name property to ensure it's always available
24
+ @property
25
+ def dish_name(self) -> str:
26
+ if self.dish:
27
+ return self.dish.name
28
+ return "Unknown Dish"
29
+
30
+ class Config:
31
+ from_attributes = True # Updated from orm_mode for Pydantic V2
32
+
33
+
34
+ class OrderBase(BaseModel):
35
+ table_number: int
36
+ unique_id: str
37
+
38
+
39
+ class OrderCreate(OrderBase):
40
+ items: List[OrderItemCreate]
41
+ username: Optional[str] = None
42
+ password: Optional[str] = None
43
+
44
+
45
+ class OrderUpdate(BaseModel):
46
+ status: str
47
+
48
+
49
+ class Order(OrderBase):
50
+ id: int
51
+ status: str
52
+ created_at: datetime
53
+ updated_at: datetime
54
+ items: List[OrderItem] = []
55
+ person_id: Optional[int] = None
56
+ person_name: Optional[str] = None
57
+ visit_count: Optional[int] = None
58
+
59
+ class Config:
60
+ from_attributes = True # Updated from orm_mode for Pydantic V2
app/models/selection_offer.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+
6
+ class SelectionOfferBase(BaseModel):
7
+ min_amount: float
8
+ discount_amount: float
9
+ is_active: bool = True
10
+ description: Optional[str] = None
11
+
12
+
13
+ class SelectionOfferCreate(SelectionOfferBase):
14
+ pass
15
+
16
+
17
+ class SelectionOfferUpdate(BaseModel):
18
+ min_amount: Optional[float] = None
19
+ discount_amount: Optional[float] = None
20
+ is_active: Optional[bool] = None
21
+ description: Optional[str] = None
22
+
23
+
24
+ class SelectionOffer(SelectionOfferBase):
25
+ id: int
26
+ created_at: datetime
27
+ updated_at: datetime
28
+
29
+ class Config:
30
+ from_attributes = True # Updated from orm_mode for Pydantic V2
app/models/settings.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+
6
+ class SettingsBase(BaseModel):
7
+ hotel_name: str
8
+ address: Optional[str] = None
9
+ contact_number: Optional[str] = None
10
+ email: Optional[str] = None
11
+ tax_id: Optional[str] = None
12
+ logo_path: Optional[str] = None
13
+
14
+
15
+ class SettingsCreate(SettingsBase):
16
+ pass
17
+
18
+
19
+ class SettingsUpdate(BaseModel):
20
+ hotel_name: Optional[str] = None
21
+ address: Optional[str] = None
22
+ contact_number: Optional[str] = None
23
+ email: Optional[str] = None
24
+ tax_id: Optional[str] = None
25
+ logo_path: Optional[str] = None
26
+
27
+
28
+ class Settings(SettingsBase):
29
+ id: int
30
+ created_at: datetime
31
+ updated_at: datetime
32
+
33
+ class Config:
34
+ from_attributes = True # Updated from orm_mode for Pydantic V2
app/models/table.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+
6
+ class TableBase(BaseModel):
7
+ table_number: int
8
+ is_occupied: bool = False
9
+ current_order_id: Optional[int] = None
10
+
11
+
12
+ class TableCreate(TableBase):
13
+ pass
14
+
15
+
16
+ class TableUpdate(BaseModel):
17
+ is_occupied: Optional[bool] = None
18
+ current_order_id: Optional[int] = None
19
+
20
+
21
+ class Table(TableBase):
22
+ id: int
23
+ created_at: datetime
24
+ updated_at: datetime
25
+
26
+ class Config:
27
+ from_attributes = True # Updated from orm_mode for Pydantic V2
28
+
29
+
30
+ class TableStatus(BaseModel):
31
+ total_tables: int
32
+ occupied_tables: int
33
+ free_tables: int
app/models/user.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+ class PersonBase(BaseModel):
6
+ username: str
7
+
8
+ class PersonCreate(PersonBase):
9
+ password: str
10
+ table_number: int
11
+ phone_number: Optional[str] = None
12
+
13
+ class PersonLogin(PersonBase):
14
+ password: str
15
+ table_number: int
16
+
17
+ class PhoneAuthRequest(BaseModel):
18
+ phone_number: str
19
+ table_number: int
20
+
21
+ class PhoneVerifyRequest(BaseModel):
22
+ phone_number: str
23
+ verification_code: str
24
+ table_number: int
25
+
26
+ class UsernameRequest(BaseModel):
27
+ phone_number: str
28
+ username: str
29
+ table_number: int
30
+
31
+ class Person(PersonBase):
32
+ id: int
33
+ visit_count: int
34
+ last_visit: datetime
35
+ created_at: datetime
36
+ phone_number: Optional[str] = None
37
+
38
+ class Config:
39
+ from_attributes = True # Updated from orm_mode for Pydantic V2
app/routers/__pycache__/admin.cpython-311.pyc ADDED
Binary file (14.4 kB). View file
 
app/routers/__pycache__/admin.cpython-312.pyc ADDED
Binary file (18.9 kB). View file
 
app/routers/__pycache__/analytics.cpython-312.pyc ADDED
Binary file (25 kB). View file
 
app/routers/__pycache__/chef.cpython-311.pyc ADDED
Binary file (2.91 kB). View file
 
app/routers/__pycache__/chef.cpython-312.pyc ADDED
Binary file (2.5 kB). View file
 
app/routers/__pycache__/customer.cpython-311.pyc ADDED
Binary file (13.2 kB). View file
 
app/routers/__pycache__/customer.cpython-312.pyc ADDED
Binary file (20 kB). View file
 
app/routers/__pycache__/feedback.cpython-311.pyc ADDED
Binary file (4.06 kB). View file
 
app/routers/__pycache__/feedback.cpython-312.pyc ADDED
Binary file (3.55 kB). View file
 
app/routers/__pycache__/loyalty.cpython-311.pyc ADDED
Binary file (7.25 kB). View file
 
app/routers/__pycache__/loyalty.cpython-312.pyc ADDED
Binary file (6.62 kB). View file
 
app/routers/__pycache__/selection_offer.cpython-311.pyc ADDED
Binary file (7.57 kB). View file