Fred808 commited on
Commit
e0cef91
·
verified ·
1 Parent(s): 8a406ce

Delete pos_backend

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. pos_backend/.env +0 -0
  2. pos_backend/__init__.py +0 -3
  3. pos_backend/__pycache__/main.cpython-312.pyc +0 -0
  4. pos_backend/app/__init__.py +0 -3
  5. pos_backend/app/__pycache__/__init__.cpython-312.pyc +0 -0
  6. pos_backend/app/api/__init__.py +0 -1
  7. pos_backend/app/api/__pycache__/__init__.cpython-312.pyc +0 -0
  8. pos_backend/app/api/api_v1/__init__.py +0 -1
  9. pos_backend/app/api/api_v1/__pycache__/__init__.cpython-312.pyc +0 -0
  10. pos_backend/app/api/api_v1/__pycache__/api.cpython-312.pyc +0 -0
  11. pos_backend/app/api/api_v1/api.py +0 -10
  12. pos_backend/app/api/api_v1/endpoints/__init__.py +0 -1
  13. pos_backend/app/api/api_v1/endpoints/__pycache__/__init__.cpython-312.pyc +0 -0
  14. pos_backend/app/api/api_v1/endpoints/__pycache__/auth.cpython-312.pyc +0 -0
  15. pos_backend/app/api/api_v1/endpoints/__pycache__/menu.cpython-312.pyc +0 -0
  16. pos_backend/app/api/api_v1/endpoints/__pycache__/orders.cpython-312.pyc +0 -0
  17. pos_backend/app/api/api_v1/endpoints/__pycache__/payments.cpython-312.pyc +0 -0
  18. pos_backend/app/api/api_v1/endpoints/__pycache__/reports.cpython-312.pyc +0 -0
  19. pos_backend/app/api/api_v1/endpoints/auth.py +0 -13
  20. pos_backend/app/api/api_v1/endpoints/menu.py +0 -19
  21. pos_backend/app/api/api_v1/endpoints/orders.py +0 -36
  22. pos_backend/app/api/api_v1/endpoints/payments.py +0 -27
  23. pos_backend/app/api/api_v1/endpoints/reports.py +0 -36
  24. pos_backend/app/core/__pycache__/config.cpython-312.pyc +0 -0
  25. pos_backend/app/core/auth.py +0 -0
  26. pos_backend/app/core/config.py +0 -15
  27. pos_backend/app/core/database.py +0 -0
  28. pos_backend/app/core/dependencies.py +0 -0
  29. pos_backend/app/db/__pycache__/crud.cpython-312.pyc +0 -0
  30. pos_backend/app/db/__pycache__/database.cpython-312.pyc +0 -0
  31. pos_backend/app/db/crud.py +0 -200
  32. pos_backend/app/db/database.py +0 -83
  33. pos_backend/app/db/models.py +0 -0
  34. pos_backend/app/main.py +0 -72
  35. pos_backend/app/models/__pycache__/auth.cpython-312.pyc +0 -0
  36. pos_backend/app/models/__pycache__/database.cpython-312.pyc +0 -0
  37. pos_backend/app/models/__pycache__/menu.cpython-312.pyc +0 -0
  38. pos_backend/app/models/__pycache__/orders.cpython-312.pyc +0 -0
  39. pos_backend/app/models/__pycache__/payment.cpython-312.pyc +0 -0
  40. pos_backend/app/models/__pycache__/reports.cpython-312.pyc +0 -0
  41. pos_backend/app/models/auth.py +0 -17
  42. pos_backend/app/models/database.py +0 -72
  43. pos_backend/app/models/menu.py +0 -32
  44. pos_backend/app/models/orders.py +0 -37
  45. pos_backend/app/models/payment.py +0 -24
  46. pos_backend/app/models/payments.py +0 -42
  47. pos_backend/app/models/reports.py +0 -50
  48. pos_backend/app/routes/auth.py +0 -24
  49. pos_backend/app/routes/menu.py +0 -52
  50. pos_backend/app/routes/orders.py +0 -63
pos_backend/.env DELETED
File without changes
pos_backend/__init__.py DELETED
@@ -1,3 +0,0 @@
1
- """
2
- POS Backend Package
3
- """
 
 
 
 
pos_backend/__pycache__/main.cpython-312.pyc DELETED
Binary file (3.23 kB)
 
pos_backend/app/__init__.py DELETED
@@ -1,3 +0,0 @@
1
- """
2
- POS Backend Application Package
3
- """
 
 
 
 
pos_backend/app/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (218 Bytes)
 
pos_backend/app/api/__init__.py DELETED
@@ -1 +0,0 @@
1
- # Empty file to mark directory as Python package
 
 
pos_backend/app/api/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (172 Bytes)
 
pos_backend/app/api/api_v1/__init__.py DELETED
@@ -1 +0,0 @@
1
- # Empty file to mark directory as Python package
 
 
pos_backend/app/api/api_v1/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (179 Bytes)
 
pos_backend/app/api/api_v1/__pycache__/api.cpython-312.pyc DELETED
Binary file (931 Bytes)
 
pos_backend/app/api/api_v1/api.py DELETED
@@ -1,10 +0,0 @@
1
- from fastapi import APIRouter
2
- from app.api.api_v1.endpoints import auth, menu, orders, payments, reports
3
-
4
- api_router = APIRouter()
5
-
6
- api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
7
- api_router.include_router(menu.router, prefix="/menu", tags=["menu"])
8
- api_router.include_router(orders.router, prefix="/orders", tags=["orders"])
9
- api_router.include_router(payments.router, prefix="/payments", tags=["payments"])
10
- api_router.include_router(reports.router, prefix="/reports", tags=["reports"])
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/api/api_v1/endpoints/__init__.py DELETED
@@ -1 +0,0 @@
1
- # Empty file to mark directory as Python package
 
 
pos_backend/app/api/api_v1/endpoints/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (189 Bytes)
 
pos_backend/app/api/api_v1/endpoints/__pycache__/auth.cpython-312.pyc DELETED
Binary file (1.15 kB)
 
pos_backend/app/api/api_v1/endpoints/__pycache__/menu.cpython-312.pyc DELETED
Binary file (1.52 kB)
 
pos_backend/app/api/api_v1/endpoints/__pycache__/orders.cpython-312.pyc DELETED
Binary file (2.44 kB)
 
pos_backend/app/api/api_v1/endpoints/__pycache__/payments.cpython-312.pyc DELETED
Binary file (1.71 kB)
 
pos_backend/app/api/api_v1/endpoints/__pycache__/reports.cpython-312.pyc DELETED
Binary file (1.38 kB)
 
pos_backend/app/api/api_v1/endpoints/auth.py DELETED
@@ -1,13 +0,0 @@
1
- from fastapi import APIRouter, Depends, HTTPException
2
- from app.services.auth_service import authenticate_user, create_access_token
3
- from app.models.auth import LoginRequest, LoginResponse
4
-
5
- router = APIRouter()
6
-
7
- @router.post("/login", response_model=LoginResponse)
8
- async def login(user_data: LoginRequest):
9
- user = await authenticate_user(user_data.email, user_data.password)
10
- if not user:
11
- raise HTTPException(status_code=401, detail="Invalid credentials")
12
- access_token = create_access_token(data={"sub": user.email})
13
- return LoginResponse(access_token=access_token, token_type="bearer", user=user)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/api/api_v1/endpoints/menu.py DELETED
@@ -1,19 +0,0 @@
1
- from fastapi import APIRouter, Depends, HTTPException, status
2
- from app.services.menu_service import MenuService
3
- from app.models.menu import MenuItem, Category
4
- from typing import List
5
-
6
- router = APIRouter()
7
- menu_service = MenuService()
8
-
9
- @router.get("/items", response_model=List[MenuItem])
10
- async def get_menu_items():
11
- return await menu_service.get_menu_items()
12
-
13
- @router.post("/items", response_model=MenuItem, status_code=status.HTTP_201_CREATED)
14
- async def create_menu_item(item: MenuItem):
15
- return await menu_service.create_menu_item(item)
16
-
17
- @router.get("/categories", response_model=List[Category])
18
- async def get_categories():
19
- return await menu_service.get_categories()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/api/api_v1/endpoints/orders.py DELETED
@@ -1,36 +0,0 @@
1
- from fastapi import APIRouter, HTTPException, status, Depends
2
- from app.services.order_service import OrderService
3
- from app.models.orders import Order, OrderStatus
4
- from typing import List
5
-
6
- router = APIRouter()
7
-
8
- @router.post("/", response_model=Order, status_code=status.HTTP_201_CREATED)
9
- async def create_order(order: Order, service: OrderService = Depends(OrderService)):
10
- return await service.create_order(order)
11
-
12
- @router.get("/{order_id}", response_model=Order)
13
- async def get_order(order_id: int, service: OrderService = Depends(OrderService)):
14
- return await service.get_order(order_id)
15
-
16
- @router.put("/{order_id}/status", response_model=Order)
17
- async def update_order_status(
18
- order_id: int,
19
- status: OrderStatus,
20
- service: OrderService = Depends(OrderService)
21
- ):
22
- return await service.update_status(order_id, status)
23
-
24
- @router.get("/status/{status}", response_model=List[Order])
25
- async def get_orders_by_status(
26
- status: OrderStatus,
27
- service: OrderService = Depends(OrderService)
28
- ):
29
- return await service.get_orders_by_status(status)
30
-
31
- @router.get("/daily/{date}", response_model=List[Order])
32
- async def get_daily_orders(
33
- date: str,
34
- service: OrderService = Depends(OrderService)
35
- ):
36
- return await service.get_daily_orders(date)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/api/api_v1/endpoints/payments.py DELETED
@@ -1,27 +0,0 @@
1
- from fastapi import APIRouter, HTTPException, status, Depends
2
- from app.services.payment_service import PaymentService
3
- from app.models.payment import Payment, PaymentStatus
4
-
5
- router = APIRouter()
6
-
7
- @router.post("/", response_model=Payment, status_code=status.HTTP_201_CREATED)
8
- async def process_payment(
9
- payment: Payment,
10
- service: PaymentService = Depends(PaymentService)
11
- ):
12
- return await service.process_payment(payment)
13
-
14
- @router.get("/{payment_id}", response_model=Payment)
15
- async def get_payment(
16
- payment_id: int,
17
- service: PaymentService = Depends(PaymentService)
18
- ):
19
- return await service.get_payment(payment_id)
20
-
21
- @router.put("/{payment_id}/status", response_model=Payment)
22
- async def update_payment_status(
23
- payment_id: int,
24
- status: PaymentStatus,
25
- service: PaymentService = Depends(PaymentService)
26
- ):
27
- return await service.update_status(payment_id, status)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/api/api_v1/endpoints/reports.py DELETED
@@ -1,36 +0,0 @@
1
- from fastapi import APIRouter, Depends
2
- from app.services.report_service import ReportService
3
- from app.models.reports import DailyReport, WeeklyReport
4
- from datetime import date
5
- from fastapi.responses import JSONResponse
6
- from fastapi import HTTPException, status
7
-
8
- router = APIRouter()
9
-
10
- @router.get("/daily/{date}", response_model=DailyReport)
11
- async def get_daily_report(
12
- date: date,
13
- service: ReportService = Depends(ReportService)
14
- ):
15
- try:
16
- return await service.generate_daily_report(date.isoformat())
17
- except Exception as e:
18
- raise HTTPException(
19
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
20
- detail=f"Failed to generate daily report: {str(e)}"
21
- )
22
-
23
- @router.get("/weekly", response_model=WeeklyReport)
24
- async def get_weekly_report(
25
- end_date: date = None,
26
- service: ReportService = Depends(ReportService)
27
- ):
28
- try:
29
- return await service.generate_weekly_report(
30
- end_date.isoformat() if end_date else None
31
- )
32
- except Exception as e:
33
- raise HTTPException(
34
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
35
- detail=f"Failed to generate weekly report: {str(e)}"
36
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/core/__pycache__/config.cpython-312.pyc DELETED
Binary file (1.16 kB)
 
pos_backend/app/core/auth.py DELETED
File without changes
pos_backend/app/core/config.py DELETED
@@ -1,15 +0,0 @@
1
- from pydantic_settings import BaseSettings
2
-
3
- class Settings(BaseSettings):
4
- PROJECT_NAME: str = "POS Backend"
5
- API_V1_STR: str = "/api/v1"
6
- SECRET_KEY: str = "your-secret-key-here"
7
- ALGORITHM: str = "HS256"
8
- ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
9
- REFRESH_TOKEN_EXPIRE_DAYS: int = 7
10
- DATABASE_URL: str = "postgresql+asyncpg://postgres.juycnkjuzylnbruwaqmp:Lovyelias5584.@aws-0-eu-central-1.pooler.supabase.com:5432/postgres"
11
-
12
- class Config:
13
- env_file = ".env"
14
-
15
- settings = Settings()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/core/database.py DELETED
File without changes
pos_backend/app/core/dependencies.py DELETED
File without changes
pos_backend/app/db/__pycache__/crud.cpython-312.pyc DELETED
Binary file (14.6 kB)
 
pos_backend/app/db/__pycache__/database.cpython-312.pyc DELETED
Binary file (4.76 kB)
 
pos_backend/app/db/crud.py DELETED
@@ -1,200 +0,0 @@
1
- from sqlalchemy.ext.asyncio import AsyncSession
2
- from sqlalchemy import select, update, delete, and_, func
3
- from sqlalchemy.orm import selectinload
4
- from ..models.database import MenuItem, Order, Payment, User, Category, OrderItem
5
- from ..models.orders import OrderStatus
6
- from ..models.payment import PaymentStatus
7
- from typing import List, Optional, Dict
8
- from datetime import datetime
9
-
10
- # User Operations
11
- async def get_user_by_email(db: AsyncSession, email: str) -> Optional[User]:
12
- result = await db.execute(select(User).where(User.email == email))
13
- return result.scalar_one_or_none()
14
-
15
- async def create_user(db: AsyncSession, user: User) -> User:
16
- db.add(user)
17
- await db.commit()
18
- await db.refresh(user)
19
- return user
20
-
21
- # Menu Operations
22
- async def get_menu_items(db: AsyncSession) -> List[MenuItem]:
23
- result = await db.execute(
24
- select(MenuItem).options(selectinload(MenuItem.category))
25
- )
26
- return result.scalars().all()
27
-
28
- async def get_menu_item_by_id(db: AsyncSession, item_id: int) -> Optional[MenuItem]:
29
- result = await db.execute(
30
- select(MenuItem)
31
- .options(selectinload(MenuItem.category))
32
- .where(MenuItem.id == item_id)
33
- )
34
- return result.scalar_one_or_none()
35
-
36
- async def create_menu_item_db(db: AsyncSession, item: MenuItem) -> MenuItem:
37
- db.add(item)
38
- await db.commit()
39
- await db.refresh(item)
40
- return item
41
-
42
- async def update_menu_item_db(db: AsyncSession, item_id: int, item: MenuItem) -> Optional[MenuItem]:
43
- query = update(MenuItem).where(MenuItem.id == item_id).values(**item.dict(exclude={'id'}))
44
- await db.execute(query)
45
- await db.commit()
46
- return await get_menu_item_by_id(db, item_id)
47
-
48
- async def delete_menu_item_db(db: AsyncSession, item_id: int) -> bool:
49
- query = delete(MenuItem).where(MenuItem.id == item_id)
50
- result = await db.execute(query)
51
- await db.commit()
52
- return result.rowcount > 0
53
-
54
- async def get_categories_db(db: AsyncSession) -> List[Category]:
55
- result = await db.execute(select(Category))
56
- return result.scalars().all()
57
-
58
- # Order Operations
59
- async def create_order_db(db: AsyncSession, order: Order) -> Order:
60
- db.add(order)
61
- await db.commit()
62
- await db.refresh(order)
63
- return order
64
-
65
- async def get_order_by_id(db: AsyncSession, order_id: int) -> Optional[Order]:
66
- result = await db.execute(
67
- select(Order)
68
- .options(selectinload(Order.items))
69
- .where(Order.id == order_id)
70
- )
71
- return result.scalar_one_or_none()
72
-
73
- async def update_order_status(db: AsyncSession, order_id: int, new_status: OrderStatus) -> Order:
74
- """Update the status of an order."""
75
- query = update(Order).where(Order.id == order_id).values(status=new_status)
76
- await db.execute(query)
77
- await db.commit()
78
- return await get_order_by_id(db, order_id)
79
-
80
- async def get_orders_by_status(db: AsyncSession, status: OrderStatus) -> List[Order]:
81
- """Get all orders with a specific status."""
82
- result = await db.execute(
83
- select(Order)
84
- .options(selectinload(Order.items))
85
- .where(Order.status == status)
86
- .order_by(Order.created_at.desc())
87
- )
88
- return result.scalars().all()
89
-
90
- async def get_orders_by_date_range(db: AsyncSession, start_date: str, end_date: str) -> List[Order]:
91
- """Get orders within a date range."""
92
- start = datetime.strptime(start_date, "%Y-%m-%d")
93
- end = datetime.strptime(end_date, "%Y-%m-%d").replace(hour=23, minute=59, second=59)
94
-
95
- result = await db.execute(
96
- select(Order)
97
- .options(selectinload(Order.items))
98
- .where(and_(Order.created_at >= start, Order.created_at <= end))
99
- .order_by(Order.created_at.desc())
100
- )
101
- return result.scalars().all()
102
-
103
- # Payment Operations
104
- async def create_payment_db(db: AsyncSession, payment: Payment) -> Payment:
105
- db.add(payment)
106
- await db.commit()
107
- await db.refresh(payment)
108
- return payment
109
-
110
- async def get_payment_by_id(db: AsyncSession, payment_id: int) -> Optional[Payment]:
111
- result = await db.execute(select(Payment).where(Payment.id == payment_id))
112
- return result.scalar_one_or_none()
113
-
114
- async def update_payment_status(db: AsyncSession, payment_id: int, new_status: PaymentStatus) -> Optional[Payment]:
115
- """Update the status of a payment transaction."""
116
- query = (
117
- update(Payment)
118
- .where(Payment.id == payment_id)
119
- .values(
120
- status=new_status,
121
- updated_at=datetime.utcnow()
122
- )
123
- )
124
- await db.execute(query)
125
- await db.commit()
126
- return await get_payment_by_id(db, payment_id)
127
-
128
- # Report Operations
129
- async def get_sales_by_date_range(db: AsyncSession, start_date: str, end_date: str) -> List[Order]:
130
- """Get all sales within a date range."""
131
- start = datetime.fromisoformat(start_date)
132
- end = datetime.fromisoformat(end_date).replace(hour=23, minute=59, second=59)
133
-
134
- result = await db.execute(
135
- select(Order)
136
- .options(selectinload(Order.items))
137
- .where(
138
- and_(
139
- Order.created_at >= start,
140
- Order.created_at <= end,
141
- Order.status == OrderStatus.COMPLETED
142
- )
143
- )
144
- .order_by(Order.created_at.desc())
145
- )
146
- return result.scalars().all()
147
-
148
- async def get_top_selling_items(db: AsyncSession, date: str, limit: int = 5) -> List[Dict]:
149
- """Get top selling items for a specific date."""
150
- day_start = datetime.fromisoformat(date)
151
- day_end = day_start.replace(hour=23, minute=59, second=59)
152
-
153
- result = await db.execute(
154
- select(
155
- MenuItem.name,
156
- func.sum(OrderItem.quantity).label('total_quantity'),
157
- func.sum(OrderItem.quantity * OrderItem.unit_price).label('total_revenue')
158
- )
159
- .join(OrderItem, MenuItem.id == OrderItem.menu_item_id)
160
- .join(Order, OrderItem.order_id == Order.id)
161
- .where(
162
- and_(
163
- Order.created_at >= day_start,
164
- Order.created_at <= day_end,
165
- Order.status == OrderStatus.COMPLETED
166
- )
167
- )
168
- .group_by(MenuItem.id, MenuItem.name)
169
- .order_by(func.sum(OrderItem.quantity).desc())
170
- .limit(limit)
171
- )
172
-
173
- return [
174
- {
175
- "item_name": row[0],
176
- "quantity_sold": row[1],
177
- "total_revenue": row[2]
178
- }
179
- for row in result.all()
180
- ]
181
-
182
- async def get_daily_revenue(db: AsyncSession, date: str) -> float:
183
- """Get total revenue for a specific date."""
184
- day_start = datetime.fromisoformat(date)
185
- day_end = day_start.replace(hour=23, minute=59, second=59)
186
-
187
- result = await db.execute(
188
- select(func.sum(Payment.amount))
189
- .join(Order, Payment.order_id == Order.id)
190
- .where(
191
- and_(
192
- Payment.created_at >= day_start,
193
- Payment.created_at <= day_end,
194
- Payment.status == PaymentStatus.COMPLETED
195
- )
196
- )
197
- )
198
-
199
- total = result.scalar_one_or_none()
200
- return float(total) if total is not None else 0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/db/database.py DELETED
@@ -1,83 +0,0 @@
1
- from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
2
- from sqlalchemy.orm import DeclarativeBase
3
- from sqlalchemy import text
4
- from ..core.config import settings
5
- import logging
6
- import ssl
7
- import platform
8
- import asyncio
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
- def get_ssl_context():
13
- """Create an SSL context for database connection."""
14
- ssl_context = ssl.create_default_context()
15
- ssl_context.check_hostname = False
16
- ssl_context.verify_mode = ssl.CERT_NONE
17
- return ssl_context
18
-
19
- # Configure Windows-specific event loop policy
20
- if platform.system() == 'Windows':
21
- asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
22
-
23
- # Create async engine with connection pooling
24
- engine = create_async_engine(
25
- settings.DATABASE_URL,
26
- echo=True,
27
- pool_pre_ping=True,
28
- pool_size=20,
29
- max_overflow=10,
30
- pool_timeout=30,
31
- connect_args={
32
- "ssl": get_ssl_context(),
33
- "server_settings": {
34
- "application_name": "pos_backend",
35
- "statement_timeout": "60000", # 60 seconds
36
- }
37
- }
38
- )
39
-
40
- # Create async session maker with pooling configuration
41
- async_session_maker = async_sessionmaker(
42
- engine,
43
- class_=AsyncSession,
44
- expire_on_commit=False,
45
- autocommit=False,
46
- autoflush=False
47
- )
48
-
49
- class Base(DeclarativeBase):
50
- pass
51
-
52
- async def verify_connection():
53
- try:
54
- async with engine.connect() as conn:
55
- await conn.execute(text("SELECT 1"))
56
- logger.info("Database connection verified successfully")
57
- return True
58
- except Exception as e:
59
- logger.error(f"Database connection failed: {str(e)}")
60
- raise
61
-
62
- async def get_db():
63
- async with async_session_maker() as session:
64
- try:
65
- await verify_connection()
66
- yield session
67
- await session.commit()
68
- except Exception as e:
69
- logger.error(f"Database session error: {str(e)}")
70
- await session.rollback()
71
- raise
72
- finally:
73
- await session.close()
74
-
75
- async def init_db():
76
- try:
77
- await verify_connection()
78
- async with engine.begin() as conn:
79
- await conn.run_sync(Base.metadata.create_all)
80
- logger.info("Database initialized successfully")
81
- except Exception as e:
82
- logger.error(f"Database initialization failed: {str(e)}")
83
- raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/db/models.py DELETED
File without changes
pos_backend/app/main.py DELETED
@@ -1,72 +0,0 @@
1
- import os
2
- import sys
3
- from pathlib import Path
4
- from fastapi import FastAPI, HTTPException
5
- from fastapi.middleware.cors import CORSMiddleware
6
- from fastapi.responses import JSONResponse
7
- from .core.config import settings
8
- from .api.api_v1.api import api_router
9
- from .db.database import init_db
10
- import logging
11
- import asyncio
12
-
13
- # Set up Python path
14
- BASE_DIR = Path(__file__).resolve().parent.parent
15
- sys.path.append(str(BASE_DIR))
16
-
17
- # Configure logging
18
- logging.basicConfig(level=logging.INFO)
19
- logger = logging.getLogger(__name__)
20
-
21
- def create_app() -> FastAPI:
22
- app = FastAPI(
23
- title=settings.PROJECT_NAME,
24
- openapi_url=f"{settings.API_V1_STR}/openapi.json"
25
- )
26
-
27
- # Configure CORS
28
- app.add_middleware(
29
- CORSMiddleware,
30
- allow_origins=["*"],
31
- allow_credentials=True,
32
- allow_methods=["*"],
33
- allow_headers=["*"],
34
- )
35
-
36
- # Include API router
37
- app.include_router(api_router, prefix=settings.API_V1_STR)
38
-
39
- @app.exception_handler(HTTPException)
40
- async def http_exception_handler(request, exc):
41
- return JSONResponse(
42
- status_code=exc.status_code,
43
- content={"detail": exc.detail}
44
- )
45
-
46
- @app.get("/")
47
- async def root():
48
- return {"message": "POS Backend API", "version": "1.0.0"}
49
-
50
- @app.on_event("startup")
51
- async def startup_event():
52
- try:
53
- await init_db()
54
- logger.info("Database initialized successfully")
55
- except Exception as e:
56
- logger.error(f"Failed to initialize database: {e}")
57
- raise
58
-
59
- return app
60
-
61
- app = create_app()
62
-
63
- if __name__ == "__main__":
64
- import uvicorn
65
-
66
- uvicorn.run(
67
- "app.main:app",
68
- host="0.0.0.0",
69
- port=8000,
70
- reload=True,
71
- log_level="info"
72
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/models/__pycache__/auth.cpython-312.pyc DELETED
Binary file (1.16 kB)
 
pos_backend/app/models/__pycache__/database.cpython-312.pyc DELETED
Binary file (3.99 kB)
 
pos_backend/app/models/__pycache__/menu.cpython-312.pyc DELETED
Binary file (1.78 kB)
 
pos_backend/app/models/__pycache__/orders.cpython-312.pyc DELETED
Binary file (2.05 kB)
 
pos_backend/app/models/__pycache__/payment.cpython-312.pyc DELETED
Binary file (1.51 kB)
 
pos_backend/app/models/__pycache__/reports.cpython-312.pyc DELETED
Binary file (2.82 kB)
 
pos_backend/app/models/auth.py DELETED
@@ -1,17 +0,0 @@
1
- from pydantic import BaseModel, EmailStr, Field
2
- from typing import Optional
3
-
4
- class LoginRequest(BaseModel):
5
- email: EmailStr
6
- password: str = Field(..., min_length=6)
7
-
8
- class LoginResponse(BaseModel):
9
- access_token: str
10
- token_type: str
11
- user: 'UserProfile'
12
-
13
- class UserProfile(BaseModel):
14
- id: Optional[int] = None
15
- email: EmailStr
16
- full_name: str
17
- role: str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/models/database.py DELETED
@@ -1,72 +0,0 @@
1
- from sqlalchemy import Column, Integer, String, Float, ForeignKey, DateTime, Boolean, JSON, Enum
2
- from sqlalchemy.orm import relationship
3
- from datetime import datetime
4
- from .menu import CategoryType
5
- from ..db.database import Base
6
-
7
- class User(Base):
8
- __tablename__ = "users"
9
-
10
- id = Column(Integer, primary_key=True, index=True)
11
- email = Column(String, unique=True, index=True)
12
- full_name = Column(String)
13
- hashed_password = Column(String)
14
- role = Column(String)
15
- created_at = Column(DateTime, default=datetime.utcnow)
16
-
17
- class Category(Base):
18
- __tablename__ = "categories"
19
-
20
- id = Column(Integer, primary_key=True, index=True)
21
- name = Column(String, index=True)
22
- type = Column(Enum(CategoryType))
23
- description = Column(String, nullable=True)
24
- items = relationship("MenuItem", back_populates="category")
25
-
26
- class MenuItem(Base):
27
- __tablename__ = "menu_items"
28
-
29
- id = Column(Integer, primary_key=True, index=True)
30
- name = Column(String, index=True)
31
- description = Column(String, nullable=True)
32
- price = Column(Float)
33
- category_id = Column(Integer, ForeignKey("categories.id"))
34
- image_url = Column(String, nullable=True)
35
- is_available = Column(Boolean, default=True)
36
- allergens = Column(JSON, nullable=True)
37
- preparation_time = Column(Integer, nullable=True)
38
- category = relationship("Category", back_populates="items")
39
-
40
- class Order(Base):
41
- __tablename__ = "orders"
42
-
43
- id = Column(Integer, primary_key=True, index=True)
44
- user_id = Column(Integer, ForeignKey("users.id"))
45
- total_amount = Column(Float)
46
- status = Column(String)
47
- created_at = Column(DateTime, default=datetime.utcnow)
48
- items = relationship("OrderItem", back_populates="order")
49
- payment = relationship("Payment", back_populates="order")
50
-
51
- class OrderItem(Base):
52
- __tablename__ = "order_items"
53
-
54
- id = Column(Integer, primary_key=True, index=True)
55
- order_id = Column(Integer, ForeignKey("orders.id"))
56
- menu_item_id = Column(Integer, ForeignKey("menu_items.id"))
57
- quantity = Column(Integer)
58
- unit_price = Column(Float)
59
- order = relationship("Order", back_populates="items")
60
- menu_item = relationship("MenuItem")
61
-
62
- class Payment(Base):
63
- __tablename__ = "payments"
64
-
65
- id = Column(Integer, primary_key=True, index=True)
66
- order_id = Column(Integer, ForeignKey("orders.id"))
67
- amount = Column(Float)
68
- method = Column(String)
69
- status = Column(String)
70
- transaction_id = Column(String, nullable=True)
71
- created_at = Column(DateTime, default=datetime.utcnow)
72
- order = relationship("Order", back_populates="payment")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/models/menu.py DELETED
@@ -1,32 +0,0 @@
1
- from pydantic import BaseModel, Field
2
- from typing import Optional, List
3
- from decimal import Decimal
4
- from enum import Enum
5
-
6
- class CategoryType(str, Enum):
7
- SOUPS = "soups" # For Egusi, Efo riro, Ogbono, etc.
8
- SWALLOW = "swallow" # For Pounded yam, Amala, Eba, etc.
9
- RICE_DISHES = "rice_dishes" # For Jollof rice, Fried rice, Native rice
10
- PROTEINS = "proteins" # For Suya, Asun, Grilled fish, etc.
11
- SMALL_CHOPS = "small_chops" # For Puff puff, Samosa, Spring rolls
12
- PEPPER_SOUP = "pepper_soup" # For various pepper soup varieties
13
- SIDES = "sides" # For Plantains, Moin moin, etc.
14
- DRINKS = "drinks" # For Nigerian drinks and beverages
15
-
16
- class Category(BaseModel):
17
- id: Optional[int] = None
18
- name: str
19
- type: CategoryType
20
- description: Optional[str] = None
21
-
22
- class MenuItem(BaseModel):
23
- id: Optional[int] = None
24
- name: str
25
- description: Optional[str] = None
26
- price: Decimal = Field(..., gt=0)
27
- category_id: int
28
- image_url: Optional[str] = None
29
- is_available: bool = True
30
- allergens: Optional[List[str]] = None
31
- preparation_time: Optional[int] = None # in minutes
32
- calories: Optional[int] = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/models/orders.py DELETED
@@ -1,37 +0,0 @@
1
- from pydantic import BaseModel
2
- from typing import List, Optional
3
- from datetime import datetime
4
- from enum import Enum
5
-
6
- class OrderStatus(str, Enum):
7
- PENDING = "pending"
8
- PREPARING = "preparing"
9
- READY = "ready"
10
- DELIVERED = "delivered"
11
- CANCELLED = "cancelled"
12
-
13
- class OrderItem(BaseModel):
14
- menu_item_id: int
15
- quantity: int
16
- unit_price: float
17
- notes: Optional[str] = None
18
-
19
- class Order(BaseModel):
20
- id: Optional[int] = None
21
- customer_id: int
22
- items: List[OrderItem]
23
- total_amount: float
24
- status: OrderStatus
25
- created_at: datetime
26
- updated_at: Optional[datetime] = None
27
-
28
- class OrderDetails(Order):
29
- payment_status: str
30
- server_name: str
31
- table_number: Optional[int] = None
32
-
33
- class OrderStats(BaseModel):
34
- total_orders: int
35
- total_revenue: float
36
- average_order_value: float
37
- orders_by_status: dict[OrderStatus, int]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/models/payment.py DELETED
@@ -1,24 +0,0 @@
1
- from enum import Enum
2
- from pydantic import BaseModel, Field
3
- from datetime import datetime
4
- from typing import Optional
5
-
6
- class PaymentMethod(str, Enum):
7
- CASH = "cash"
8
- CARD = "card"
9
-
10
- class PaymentStatus(str, Enum):
11
- PENDING = "pending"
12
- PROCESSING = "processing"
13
- COMPLETED = "completed"
14
- FAILED = "failed"
15
-
16
- class Payment(BaseModel):
17
- id: Optional[int] = None
18
- order_id: int
19
- amount: float = Field(..., gt=0)
20
- method: PaymentMethod
21
- status: PaymentStatus = PaymentStatus.PENDING
22
- transaction_id: Optional[str] = None
23
- created_at: datetime = Field(default_factory=datetime.utcnow)
24
- updated_at: Optional[datetime] = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/models/payments.py DELETED
@@ -1,42 +0,0 @@
1
- from pydantic import BaseModel
2
- from typing import Optional
3
- from datetime import datetime
4
- from decimal import Decimal
5
- from enum import Enum
6
-
7
- class PaymentMethod(str, Enum):
8
- CASH = "cash"
9
- CREDIT_CARD = "credit_card"
10
- DEBIT_CARD = "debit_card"
11
- MOBILE_PAYMENT = "mobile_payment"
12
-
13
- class PaymentStatus(str, Enum):
14
- PENDING = "pending"
15
- PROCESSING = "processing"
16
- COMPLETED = "completed"
17
- FAILED = "failed"
18
- REFUNDED = "refunded"
19
-
20
- class PaymentSession(BaseModel):
21
- id: str
22
- order_id: int
23
- amount: Decimal
24
- payment_method: PaymentMethod
25
- status: PaymentStatus
26
- created_at: datetime
27
-
28
- class PaymentVerification(BaseModel):
29
- payment_id: str
30
- verification_code: str
31
- status: PaymentStatus
32
- message: Optional[str] = None
33
-
34
- class Transaction(BaseModel):
35
- id: str
36
- order_id: int
37
- amount: Decimal
38
- payment_method: PaymentMethod
39
- status: PaymentStatus
40
- created_at: datetime
41
- updated_at: Optional[datetime] = None
42
- reference_id: Optional[str] = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/models/reports.py DELETED
@@ -1,50 +0,0 @@
1
- from pydantic import BaseModel
2
- from typing import Dict, List
3
- from datetime import datetime
4
- from decimal import Decimal
5
-
6
- class TopSellingItem(BaseModel):
7
- item_name: str
8
- quantity_sold: int
9
- total_revenue: float
10
-
11
- class DailyReport(BaseModel):
12
- date: str
13
- total_sales: int
14
- total_revenue: float
15
- top_selling_items: List[TopSellingItem]
16
-
17
- class DailyBreakdown(BaseModel):
18
- date: str
19
- revenue: float
20
-
21
- class WeeklyReport(BaseModel):
22
- period: str
23
- total_sales: int
24
- daily_breakdown: List[DailyBreakdown]
25
-
26
- # Future report models
27
- class SalesReport(BaseModel):
28
- total_sales: Decimal
29
- sales_by_category: Dict[str, Decimal]
30
- sales_by_item: Dict[str, Decimal]
31
- sales_by_hour: Dict[int, Decimal]
32
- average_order_value: Decimal
33
- peak_hours: List[int]
34
- period_start: datetime
35
- period_end: datetime
36
-
37
- class InventoryReport(BaseModel):
38
- items_in_stock: Dict[str, int]
39
- low_stock_items: List[str]
40
- out_of_stock_items: List[str]
41
- total_inventory_value: Decimal
42
- last_updated: datetime
43
-
44
- class PerformanceMetrics(BaseModel):
45
- order_fulfillment_time: Dict[str, float] # avg time in minutes by order type
46
- server_performance: Dict[str, Dict[str, float]] # metrics by server
47
- customer_satisfaction: float
48
- busy_periods: List[Dict[str, str]]
49
- period_start: datetime
50
- period_end: datetime
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/routes/auth.py DELETED
@@ -1,24 +0,0 @@
1
- from fastapi import APIRouter, Depends, HTTPException
2
- from fastapi.security import OAuth2PasswordRequestForm
3
- from ..models.auth import LoginRequest, LoginResponse, UserProfile
4
- from ..core.auth import get_current_user
5
- from ..services.auth_service import authenticate_user, create_access_token
6
-
7
- router = APIRouter(prefix="/api/auth", tags=["auth"])
8
-
9
- @router.post("/login", response_model=LoginResponse)
10
- async def login(form_data: OAuth2PasswordRequestForm = Depends()):
11
- user = await authenticate_user(form_data.username, form_data.password)
12
- if not user:
13
- raise HTTPException(status_code=401, detail="Incorrect email or password")
14
- access_token = create_access_token(data={"sub": user.email})
15
- return LoginResponse(access_token=access_token)
16
-
17
- @router.post("/logout")
18
- async def logout(current_user = Depends(get_current_user)):
19
- # TODO: Implement token blacklisting or session invalidation
20
- return {"message": "Successfully logged out"}
21
-
22
- @router.get("/profile", response_model=UserProfile)
23
- async def get_profile(current_user = Depends(get_current_user)):
24
- return current_user
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/routes/menu.py DELETED
@@ -1,52 +0,0 @@
1
- from fastapi import APIRouter, Depends, HTTPException
2
- from typing import List
3
- from ..models.menu import MenuItem, Category
4
- from ..core.auth import get_current_user
5
- from ..services.menu_service import MenuService
6
-
7
- router = APIRouter(prefix="/api/menu", tags=["menu"])
8
-
9
- @router.get("", response_model=List[MenuItem])
10
- async def get_menu_items(
11
- current_user = Depends(get_current_user),
12
- menu_service: MenuService = Depends()
13
- ):
14
- return await menu_service.get_menu_items()
15
-
16
- @router.post("", response_model=MenuItem)
17
- async def create_menu_item(
18
- item: MenuItem,
19
- current_user = Depends(get_current_user),
20
- menu_service: MenuService = Depends()
21
- ):
22
- return await menu_service.create_menu_item(item)
23
-
24
- @router.put("/{item_id}", response_model=MenuItem)
25
- async def update_menu_item(
26
- item_id: int,
27
- item: MenuItem,
28
- current_user = Depends(get_current_user),
29
- menu_service: MenuService = Depends()
30
- ):
31
- updated_item = await menu_service.update_menu_item(item_id, item)
32
- if not updated_item:
33
- raise HTTPException(status_code=404, detail="Menu item not found")
34
- return updated_item
35
-
36
- @router.delete("/{item_id}")
37
- async def delete_menu_item(
38
- item_id: int,
39
- current_user = Depends(get_current_user),
40
- menu_service: MenuService = Depends()
41
- ):
42
- success = await menu_service.delete_menu_item(item_id)
43
- if not success:
44
- raise HTTPException(status_code=404, detail="Menu item not found")
45
- return {"message": "Menu item deleted successfully"}
46
-
47
- @router.get("/categories", response_model=List[Category])
48
- async def get_categories(
49
- current_user = Depends(get_current_user),
50
- menu_service: MenuService = Depends()
51
- ):
52
- return await menu_service.get_categories()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pos_backend/app/routes/orders.py DELETED
@@ -1,63 +0,0 @@
1
- from fastapi import APIRouter, Depends, HTTPException
2
- from typing import List
3
- from ..models.orders import Order, OrderDetails, OrderStats
4
- from ..core.auth import get_current_user
5
- from ..services.order_service import OrderService
6
-
7
- router = APIRouter(prefix="/api/orders", tags=["orders"])
8
-
9
- @router.get("", response_model=List[Order])
10
- async def get_orders(
11
- current_user = Depends(get_current_user),
12
- order_service: OrderService = Depends()
13
- ):
14
- return await order_service.get_orders()
15
-
16
- @router.post("", response_model=Order)
17
- async def create_order(
18
- order: Order,
19
- current_user = Depends(get_current_user),
20
- order_service: OrderService = Depends()
21
- ):
22
- return await order_service.create_order(order)
23
-
24
- @router.get("/{order_id}", response_model=OrderDetails)
25
- async def get_order(
26
- order_id: int,
27
- current_user = Depends(get_current_user),
28
- order_service: OrderService = Depends()
29
- ):
30
- order = await order_service.get_order(order_id)
31
- if not order:
32
- raise HTTPException(status_code=404, detail="Order not found")
33
- return order
34
-
35
- @router.put("/{order_id}", response_model=Order)
36
- async def update_order(
37
- order_id: int,
38
- order: Order,
39
- current_user = Depends(get_current_user),
40
- order_service: OrderService = Depends()
41
- ):
42
- updated_order = await order_service.update_order(order_id, order)
43
- if not updated_order:
44
- raise HTTPException(status_code=404, detail="Order not found")
45
- return updated_order
46
-
47
- @router.delete("/{order_id}")
48
- async def delete_order(
49
- order_id: int,
50
- current_user = Depends(get_current_user),
51
- order_service: OrderService = Depends()
52
- ):
53
- success = await order_service.delete_order(order_id)
54
- if not success:
55
- raise HTTPException(status_code=404, detail="Order not found")
56
- return {"message": "Order deleted successfully"}
57
-
58
- @router.get("/stats", response_model=OrderStats)
59
- async def get_order_stats(
60
- current_user = Depends(get_current_user),
61
- order_service: OrderService = Depends()
62
- ):
63
- return await order_service.get_stats()