Skip to main content
Glama
ASXRND

MCP Weather & Accruals Server

by ASXRND
main.py4.99 kB
from fastapi import FastAPI, HTTPException from fastapi.encoders import jsonable_encoder from decimal import Decimal from .db import database, metadata, engine from .models import users, accruals from .schemas import UserCreate, User, AccrualCreate, Accrual, AccrualStats, AccrualUpdate from .crud import ( create_user, get_users, create_accrual, get_accruals, get_accrual_stats, update_accrual, delete_accrual, ) from typing import Optional app = FastAPI(title="Accruals API", version="0.2.0") @app.on_event("startup") async def startup(): # создаём таблицы если их нет (sync через SQLAlchemy engine) metadata.create_all(bind=engine) await database.connect() @app.on_event("shutdown") async def shutdown(): await database.disconnect() @app.get("/") async def root(): return {"message": "Accruals API server is running"} @app.get("/health") async def health(): """Health endpoint для готовности/жизни сервиса""" try: await database.fetch_one("SELECT 1") except Exception: raise HTTPException(status_code=503, detail="database unavailable") return {"status": "ok"} # ===== Users endpoints ===== @app.post("/users/", response_model=User) async def api_create_user(user: UserCreate): existing = await database.fetch_one(users.select().where(users.c.email == user.email)) if existing: raise HTTPException(status_code=400, detail="Email already registered") created = await create_user(user) return created @app.get("/users/") async def api_get_users(): results = await get_users() return results # ===== Accruals endpoints ===== @app.post("/accruals/") async def api_create_accrual(accrual: AccrualCreate): """Create a new accrual record""" existing = await database.fetch_one( accruals.select().where(accruals.c.id_accrual == accrual.id_accrual) ) if existing: raise HTTPException(status_code=400, detail="Accrual with this id_accrual already exists") created = await create_accrual(accrual) return created @app.put("/accruals/{id_accrual}") async def api_update_accrual(id_accrual: str, accrual: AccrualUpdate): """Update an existing accrual by id_accrual""" existing = await database.fetch_one( accruals.select().where(accruals.c.id_accrual == id_accrual) ) if not existing: raise HTTPException(status_code=404, detail="Accrual not found") updates = accrual.dict(exclude_unset=True) if not updates: raise HTTPException(status_code=400, detail="No fields to update") updated = await update_accrual(id_accrual, updates) if not updated: raise HTTPException(status_code=500, detail="Failed to update accrual") return updated @app.delete("/accruals/{id_accrual}") async def api_delete_accrual(id_accrual: str): """Delete accrual by id_accrual""" existing = await database.fetch_one( accruals.select().where(accruals.c.id_accrual == id_accrual) ) if not existing: raise HTTPException(status_code=404, detail="Accrual not found") await delete_accrual(id_accrual) return {"status": "deleted", "id_accrual": id_accrual} @app.get("/accruals/") async def api_get_accruals( skip: int = 0, limit: int = 100, service_group: Optional[str] = None, sales_platform: Optional[str] = None, accrual_type: Optional[str] = None, ): """Get accruals with optional filtering""" results = await get_accruals( skip=skip, limit=limit, service_group=service_group, sales_platform=sales_platform, accrual_type=accrual_type, ) # `results` are `databases` Record objects which are not JSON-serializable # Convert each Record to a plain dict and ensure types (Decimal) are encoded try: list_of_dicts = [dict(r) for r in results] except Exception: # Fallback: try jsonable_encoder directly (can still fail for unknown types) list_of_dicts = jsonable_encoder(results) return jsonable_encoder(list_of_dicts) @app.get("/stats/summary", response_model=dict) async def api_get_summary_stats( service_group: Optional[str] = None, sales_platform: Optional[str] = None, accrual_type: Optional[str] = None, ): """Get overall statistics for all accruals (with optional filters)""" return await get_accrual_stats( service_group=service_group, sales_platform=sales_platform, accrual_type=accrual_type, ) @app.get("/stats/accruals", response_model=dict) async def api_get_filtered_stats( service_group: Optional[str] = None, sales_platform: Optional[str] = None, accrual_type: Optional[str] = None, ): """Get statistics for accruals with optional filters""" return await get_accrual_stats( service_group=service_group, sales_platform=sales_platform, accrual_type=accrual_type, )

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ASXRND/MCP_deepseek'

If you have feedback or need assistance with the MCP directory API, please join our Discord server