from fastapi import FastAPI, HTTPException, Depends, WebSocket from fastapi.security import OAuth2PasswordBearer from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import List, Annotated, Optional from sustApp.models.models import Base, Members, Payments from sustApp.models.database import engine, SessionLocal from sqlalchemy.orm import Session from datetime import datetime import asyncio import logging #http://127.0.0.1:8000/docs -> swagger like ui #ngrok http http://localhost:8000 app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"} #oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") Base.metadata.create_all(bind=engine) origins = [ "http://localhost.tiangolo.com", "https://localhost.tiangolo.com", "http://localhost", "http://localhost:8080", "http://localhost:3000", "http://localhost:5173", ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Store active WebSocket connections connected_clients = [] # Custom logging handler to send logs via WebSocket class WebSocketHandler(logging.Handler): def emit(self, record): log_message = self.format(record) # Send to all connected clients asyncio.create_task(broadcast_log(log_message)) # Set up logging logger = logging.getLogger("app") logger.setLevel(logging.INFO) ws_handler = WebSocketHandler() logger.addHandler(ws_handler) @app.websocket("/ws/logs") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() connected_clients.append(websocket) try: while True: await websocket.receive_text() except: connected_clients.remove(websocket) async def broadcast_log(message): for client in connected_clients[:]: # Copy list to avoid modification during iteration try: await client.send_json({ "type": "log", "message": message, "timestamp": asyncio.get_event_loop().time() }) except: connected_clients.remove(client) @app.get("/test") async def test_endpoint(): logger.info("This is a test log message from backend!") return {"message": "Check your browser console"} class User(BaseModel): username: str email: str | None = None full_name: str | None = None disabled: bool | None = None class DeliveryBase(BaseModel): delivery_date: datetime delivered_by: int class PaymentBase(BaseModel): payment_date: datetime class MemberBase(BaseModel): member_count: int member_firstname: str member_firstname_spouse: str | None = None member_surname: str member_suffix: str | None = None member_street: str member_streetnumber: str | None = None member_email: str | None = None member_zip: int member_city: str member_active: bool member_gender: str | None = None member_connected: int | None = None member_printed: bool #member_coordinates: #payments: Optional[List[PaymentBase]] member_deliveries: Optional[List[DeliveryBase]] #deliveries: Mapped[List["DeliveryBase"]] = relationship() current_state_code: str | None = None current_state_name: str | None = None def get_db(): db = SessionLocal() try: yield db finally: db.close() db_dependency = Annotated[Session, Depends(get_db)] @app.get("/members/", response_model=List[MemberBase]) async def read_members(db: db_dependency, skip: int = 0, limit: int = 100 ): members = db.query(Members).offset(skip).limit(limit).all() if not members: raise HTTPException(status_code=400, detail='No members') return members @app.get("/activememberscount/", response_model=int) async def read_activememberscount(db: db_dependency): count = db.query(Members).filter(Members.member_active == True).count() logger.info("This is a test log message from backend!") return count @app.get("/member/{member_id}") async def read_member(member_id: int, db: db_dependency): #, token: Annotated[str, Depends(oauth2_scheme)]): result = db.query(Members).join(Members.current_state).filter(Members.id == member_id).first() if not result: raise HTTPException(status_code=400, detail='Member does not exist') print(f"Member: {result.member_surname}") print(f"State: {result.current_state.state_name}") print(f"Description: {result.current_state.description}") return result @app.get("/payments/{member_id}") async def read_payments(member_id: int, db: db_dependency): result = db.query(Members).filter(Members.id == member_id).all() if not result: raise HTTPException(status_code=400, detail=f'No payments found for member {member_id}') return result @app.post("/members/") async def create_member(member: MemberBase, db: db_dependency): #db_member = models.Members(**member.model_dump()) db_member = Members(member_firstname=member.member_firstname, member_surname=member.member_surname, member_active=member.member_active) db.add(db_member) db.commit() @app.post("/fullmembers/") async def create_members(members: List[MemberBase], db: db_dependency): for member in members: db_member = Members(member_count=member.member_count, member_firstname=member.member_firstname, member_firstname_spouse=member.member_firstname_spouse, member_surname=member.member_surname, member_suffix=member.member_suffix, member_street=member.member_street, member_streetnumber=member.member_streetnumber, member_email=member.member_email, member_zip=member.member_zip, member_city=member.member_city, member_active=member.member_active, member_gender=member.member_gender, member_connected=member.member_connected) db.add(db_member) #db.commit() #db.refresh(db_member) if not member.payments is None: for payment in member.payments: db_payment = Payments(payment_date=payment.payment_date, member_id=db_member.id) db.add(db_payment) db.commit()