modification done to up the project
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / build (push) Has been cancelled
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-production (push) Has been cancelled

This commit is contained in:
laxmanhalaki 2026-03-12 20:52:08 +05:30
parent 131f7ad8e8
commit b793ac859a
118 changed files with 6515 additions and 7347 deletions

37
.env.example Normal file
View File

@ -0,0 +1,37 @@
# Application Settings
APP_NAME="AI Detection API"
APP_VERSION="1.0.0"
DEBUG=True
PORT=8000
HOST=0.0.0.0
# Database Settings
# For Docker Compose, use 'postgres' as the host. For local, use 'localhost'.
DATABASE_URL="postgresql://postgres:postgres@postgres:5432/test_project_db"
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=test_project_db
POSTGRES_PORT=5432
# Redis Settings
# For Docker Compose, use 'redis' as the host. For local, use 'localhost'.
REDIS_HOST=redis
REDIS_PORT=6379
# Security Settings
# Generate a secure key for production
JWT_SECRET="your-super-secret-jwt-key-change-me"
JWT_REFRESH_SECRET="your-super-secret-refresh-key-change-me"
JWT_ISSUER="ai-detection-app"
JWT_AUDIENCE="ai-detection-users"
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
# RAG / AI Configuration
OPENAI_API_KEY="sk-..."
ANTHROPIC_API_KEY="xpk-..."
EMBEDDING_PROVIDER="huggingface" # "openai" or "huggingface"
LLM_PROVIDER="openai" # "openai" or "anthropic"
VECTOR_DB_DIR="./chroma_db"
RAG_CHUNK_SIZE=1000
RAG_CHUNK_OVERLAP=100

52
.gitignore vendored Normal file
View File

@ -0,0 +1,52 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# Environment
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Project Specific
chroma_db/
*.log
.pytest_cache/
test_results/
# Editor/IDE
.vscode/
.idea/
*.swp
*.swo
# Docker
.docker/
docker-compose.override.yml
# OS
.DS_Store
Thumbs.db

72
RUNNING.md Normal file
View File

@ -0,0 +1,72 @@
# Running the AI-Detection Project
This project is a FastAPI-based AI application for detection and RAG (Retrieval-Augmented Generation).
## Prerequisites
- **Python 3.11+** (for local setup)
- **Docker and Docker Compose** (for containerized setup - Recommended)
- **PostgreSQL** and **Redis** (if running locally)
---
## 🚀 Option 1: Running with Docker (Recommended)
The easiest way to run the project is using Docker Compose, which sets up the application, database, and Redis automatically.
1. **Configure Environment Variables**:
Copy the example environment file and fill in your keys:
```bash
cp .env.example .env
```
*Note: Open `.env` and provide your `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` if using AI features.*
2. **Start the Services**:
```bash
docker-compose up --build
```
3. **Access the API**:
- **API Documentation (Swagger UI)**: [http://localhost:8000/docs](http://localhost:8000/docs)
- **Health Check**: [http://localhost:8000/health](http://localhost:8000/health)
---
## 🛠️ Option 2: Running Locally
If you prefer to run the application directly on your machine:
1. **Create a Virtual Environment**:
```bash
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
2. **Install Dependencies**:
```bash
pip install -r requirements.txt
```
3. **Configure Environment Variables**:
Copy `.env.example` to `.env` and update the settings:
- Set `DATABASE_URL` to point to your local PostgreSQL instance (e.g., `postgresql://user:pass@localhost:5432/dbname`).
- Set `REDIS_HOST` to `localhost`.
4. **Run the Application**:
```bash
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
```
---
## 📂 Project Structure Highlights
- `main.py`: Entry point of the FastAPI application.
- `src/config/`: Configuration management and startup migrations.
- `src/services/`: Core business logic (RAG, JWT, etc.).
- `src/migrations/`: Database schema definitions.
- `docker-compose.yml`: Multi-container orchestration.
## 🧪 Testing
To run tests, ensure dependencies are installed and run:
```bash
pytest
```

9
check_routes.py Normal file
View File

@ -0,0 +1,9 @@
from main import app
from fastapi.routing import APIRoute
print("Registered Routes:")
for route in app.routes:
if isinstance(route, APIRoute):
print(f"Path: {route.path} | Methods: {route.methods} | Name: {route.name}")
else:
print(f"Path: {route.path}")

18
fix_routes_async.py Normal file
View File

@ -0,0 +1,18 @@
import os
from pathlib import Path
import re
def fix_routes():
routes_dir = Path("src/routes")
for route_file in routes_dir.glob("*_routes.py"):
content = route_file.read_text(encoding="utf-8")
# Add await to crud.* calls
# Matches: db_user = crud.get_by_id(user_id) -> await crud.get_by_id(user_id)
# Matches: return crud.create(user_in) -> return await crud.create(user_in)
# We need to be careful not to double await
content = re.sub(r"(?<!await\s)crud\.(\w+)\(", r"await crud.\1(", content)
route_file.write_text(content, encoding="utf-8")
print(f"Fixed async/await in {route_file.name}")
if __name__ == "__main__":
fix_routes()

11
main.py
View File

@ -3,6 +3,7 @@ FastAPI Application Entry Point
Enterprise-grade FastAPI application with proper structure and middleware Enterprise-grade FastAPI application with proper structure and middleware
""" """
import logging import logging
import uvicorn
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from src.config.config import settings from src.config.config import settings
@ -44,6 +45,9 @@ app.add_middleware(
) )
# Include routers # Include routers
import src.models # Trigger model registration
from src.routes.index import router as api_router
app.include_router(api_router)
@app.on_event("startup") @app.on_event("startup")
async def startup_event(): async def startup_event():
@ -85,3 +89,10 @@ async def health_check():
"version": settings.APP_VERSION "version": settings.APP_VERSION
} }
if __name__ == "__main__":
uvicorn.run(
"main:app",
host=settings.HOST,
port=settings.PORT,
reload=settings.DEBUG
)

57
mass_fix.py Normal file
View File

@ -0,0 +1,57 @@
import os
from pathlib import Path
import re
def fix_models():
models_dir = Path("src/models")
for model_file in models_dir.glob("*.py"):
content = model_file.read_text(encoding="utf-8")
# Fix reserved 'metadata' name
content = content.replace('metadata = Column(JSON', 'doc_metadata = Column(JSON')
model_file.write_text(content, encoding="utf-8")
def fix_services():
services_dir = Path("src/services")
for service_file in services_dir.glob("*.py"):
content = service_file.read_text(encoding="utf-8")
# Add basic imports
needed_imports = []
if " date" in content and "from datetime import date" not in content and "import datetime" not in content:
needed_imports.append("from datetime import date")
if " datetime" in content and "from datetime import" not in content and "import datetime" not in content:
needed_imports.append("from datetime import datetime")
if " Decimal" in content and "from decimal import Decimal" not in content:
needed_imports.append("from decimal import Decimal")
if needed_imports:
content = "\n".join(needed_imports) + "\n" + content
# Fix missing model type hints by replacing them with Any
# Exclude common types like UUID, int, str, bool, List, Dict, Tuple, Optional
def replace_type(match):
type_name = match.group(1)
if type_name in ["UUID", "int", "str", "bool", "List", "Dict", "Tuple", "Optional", "Any", "None", "float", "bytes"]:
return match.group(0)
return match.group(0).replace(type_name, "Any")
content = re.sub(r"-> List\[([A-Z]\w+)\]", replace_type, content)
content = re.sub(r"-> ([A-Z]\w+)", replace_type, content)
content = re.sub(r": ([A-Z]\w+)", replace_type, content)
# Standardize CRUD class name
content = re.sub(r"class (\w+)Service", r"class \1CRUD", content)
# Ensure 'Any' is imported
if "from typing import" in content:
if "Any" not in content:
content = content.replace("from typing import", "from typing import Any, ")
else:
content = "from typing import Any\n" + content
service_file.write_text(content, encoding="utf-8")
print(f"Fixed service {service_file.name}")
if __name__ == "__main__":
fix_models()
fix_services()

15
requirements.txt Normal file
View File

@ -0,0 +1,15 @@
fastapi==0.104.1
uvicorn==0.24.0
pydantic-settings==2.1.0
sqlalchemy==2.0.23
psycopg2-binary==2.9.9
redis==5.0.1
python-jose[cryptography]==3.3.0
passlib[bcrypt]==1.7.4
openai==1.3.5
anthropic==0.5.0
pinecone-client
weaviate-client
python-multipart==0.0.6
httpx==0.25.2
alembic==1.12.1

View File

@ -2,6 +2,7 @@
FastAPI Application Configuration FastAPI Application Configuration
Enterprise-grade configuration management using Pydantic Settings Enterprise-grade configuration management using Pydantic Settings
""" """
from pydantic import computed_field, model_validator
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings
from typing import List, Optional from typing import List, Optional
@ -18,18 +19,39 @@ class Settings(BaseSettings):
APP_DESCRIPTION: str = "Enterprise FastAPI Application" APP_DESCRIPTION: str = "Enterprise FastAPI Application"
# Database # Database
DATABASE_URL: str = "postgresql://user:password@localhost:5432/" DATABASE_URL: Optional[str] = None
POSTGRES_USER: str = "billing_user"
POSTGRES_PASSWORD: str = "Admin123"
POSTGRES_DB: str = "test_project_db"
POSTGRES_HOST: str = "localhost"
POSTGRES_PORT: int = 5432
DB_POOL_SIZE: int = 10 DB_POOL_SIZE: int = 10
DB_MAX_OVERFLOW: int = 20 DB_MAX_OVERFLOW: int = 20
DB_POOL_RECYCLE: int = 3600 DB_POOL_RECYCLE: int = 3600
DB_ECHO: bool = False DB_ECHO: bool = False
@model_validator(mode='after')
def assemble_db_url(self) -> 'Settings':
if not self.DATABASE_URL:
self.DATABASE_URL = f"postgresql://{self.POSTGRES_USER}:{self.POSTGRES_PASSWORD}@{self.POSTGRES_HOST}:{self.POSTGRES_PORT}/{self.POSTGRES_DB}"
return self
# Redis
REDIS_HOST: str = "localhost"
REDIS_PORT: int = 6379
# Server # Server
HOST: str = "0.0.0.0" HOST: str = "0.0.0.0"
PORT: int = 8000 PORT: int = 8000
# Security # Security
SECRET_KEY: str = "" SECRET_KEY: str = ""
JWT_SECRET: str = ""
JWT_REFRESH_SECRET: str = ""
JWT_ISSUER: str = "ai-detection-app"
JWT_AUDIENCE: str = "ai-detection-users"
JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
JWT_REFRESH_TOKEN_EXPIRE_DAYS: int = 7
ALGORITHM: str = "HS256" ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30 ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
REFRESH_TOKEN_EXPIRE_DAYS: int = 7 REFRESH_TOKEN_EXPIRE_DAYS: int = 7
@ -56,6 +78,7 @@ class Settings(BaseSettings):
env_file = ".env" env_file = ".env"
env_file_encoding = "utf-8" env_file_encoding = "utf-8"
case_sensitive = False case_sensitive = False
extra = "ignore"
# Global settings instance # Global settings instance
settings = Settings() settings = Settings()

View File

@ -1,5 +1,19 @@
from sqlalchemy.orm import Session from sqlalchemy import create_engine
from src.config.database import SessionLocal, get_db from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
from src.config.config import settings
engine = create_engine(
settings.DATABASE_URL,
pool_pre_ping=True,
pool_size=settings.DB_POOL_SIZE,
max_overflow=settings.DB_MAX_OVERFLOW,
echo=settings.DB_ECHO
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db(): def get_db():
""" """
@ -11,4 +25,3 @@ def get_db():
yield db yield db
finally: finally:
db.close() db.close()

View File

@ -6,9 +6,13 @@ import os
import sys import sys
import logging import logging
from pathlib import Path from pathlib import Path
import sqlalchemy as sa
from sqlalchemy import create_engine, inspect, MetaData from sqlalchemy import create_engine, inspect, MetaData
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
import importlib.util import importlib.util
from alembic.runtime.migration import MigrationContext
from alembic.operations import Operations
import alembic
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -59,19 +63,19 @@ class MigrationManager:
if '_migrations' not in tables: if '_migrations' not in tables:
# Create migrations tracking table # Create migrations tracking table
with self.engine.begin() as conn: with self.engine.begin() as conn:
conn.execute(""" conn.execute(sa.text("""
CREATE TABLE IF NOT EXISTS _migrations ( CREATE TABLE IF NOT EXISTS _migrations (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
migration_name VARCHAR(255) NOT NULL UNIQUE, migration_name VARCHAR(255) NOT NULL UNIQUE,
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) )
""") """))
logger.info("✅ Created migrations tracking table") logger.info("✅ Created migrations tracking table")
return set() return set()
# Get applied migrations # Get applied migrations
with self.engine.connect() as conn: with self.engine.connect() as conn:
result = conn.execute("SELECT migration_name FROM _migrations ORDER BY applied_at") result = conn.execute(sa.text("SELECT migration_name FROM _migrations ORDER BY applied_at"))
applied = {row[0] for row in result} applied = {row[0] for row in result}
logger.debug(f"📋 Found {len(applied)} previously applied migrations") logger.debug(f"📋 Found {len(applied)} previously applied migrations")
@ -137,61 +141,25 @@ class MigrationManager:
logger.warning(f"⚠️ Migration {migration_file.name} has no upgrade() function") logger.warning(f"⚠️ Migration {migration_file.name} has no upgrade() function")
return False return False
# Create a mock op object with connection
class OpMock:
def __init__(self, connection):
self.connection = connection
def create_table(self, name, *args, **kwargs):
"""Create a new table"""
from sqlalchemy import Table
table = Table(name, MetaData(), *args, **kwargs)
table.create(self.connection, checkfirst=True)
logger.debug(f" 📊 Created table: {name}")
def create_index(self, name, table, columns, **kwargs):
"""Create an index"""
try:
if isinstance(columns, str):
columns = [columns]
# Build index creation SQL
unique_clause = "UNIQUE" if kwargs.get('unique') else ""
columns_str = ", ".join(f'"{col}"' for col in columns)
index_sql = f'CREATE {unique_clause} INDEX IF NOT EXISTS "{name}" ON "{table}" ({columns_str})'
self.connection.execute(index_sql)
logger.debug(f" 🔑 Created index: {name} on {table}({columns_str})")
except Exception as e:
logger.warning(f" ⚠️ Could not create index {name}: {e}")
def add_column(self, table, column):
"""Add a column to table"""
try:
self.connection.execute(f'ALTER TABLE "{table}" ADD COLUMN {column}')
logger.debug(f" Added column to {table}")
except Exception as e:
logger.warning(f" ⚠️ Could not add column to {table}: {e}")
def drop_table(self, name):
"""Drop a table"""
try:
self.connection.execute(f'DROP TABLE IF EXISTS "{name}"')
logger.debug(f" 🗑️ Dropped table: {name}")
except Exception as e:
logger.warning(f" ⚠️ Could not drop table {name}: {e}")
# Execute migration within a transaction # Execute migration within a transaction
with self.engine.begin() as connection: with self.engine.begin() as connection:
op = OpMock(connection) # Configure Alembic context
ctx = MigrationContext.configure(connection)
op = Operations(ctx)
# Bind the alembic.op proxy to our operations object
# This is necessary because migration files do 'from alembic import op'
alembic.op._proxy = op
# Run the migration
migration_module.upgrade() migration_module.upgrade()
# Record migration as applied # Record migration as applied
connection.execute(""" connection.execute(sa.text("""
INSERT INTO _migrations (migration_name) INSERT INTO _migrations (migration_name)
VALUES (%s) VALUES (:name)
ON CONFLICT DO NOTHING ON CONFLICT DO NOTHING
""", (migration_file.stem,)) """), {"name": migration_file.stem})
logger.info(f"✅ Applied migration: {migration_file.name}") logger.info(f"✅ Applied migration: {migration_file.name}")
return True return True

View File

@ -26,6 +26,8 @@ def upgrade() -> None:
sa.Column('specialty', sa.String(100), nullable=True), sa.Column('specialty', sa.String(100), nullable=True),
sa.Column('npi', sa.String(10), nullable=True), sa.Column('npi', sa.String(10), nullable=True),
sa.Column('last_login_at', sa.DateTime(timezone=True), nullable=True), sa.Column('last_login_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('role', sa.String(50), server_default='user', nullable=False),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -36,8 +36,6 @@ def upgrade() -> None:
sa.Column('secondary_payer_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('secondary_payer_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('secondary_insurance_member_id', sa.String(100), nullable=True), sa.Column('secondary_insurance_member_id', sa.String(100), nullable=True),
sa.Column('emr_patient_id', sa.String(100), nullable=True), sa.Column('emr_patient_id', sa.String(100), nullable=True),
sa.Column('primary_payer_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('secondary_payer_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -30,11 +30,9 @@ def upgrade() -> None:
sa.Column('encryption_key_id', sa.String(100), nullable=True), sa.Column('encryption_key_id', sa.String(100), nullable=True),
sa.Column('device_info', postgresql.JSONB(), nullable=True), sa.Column('device_info', postgresql.JSONB(), nullable=True),
sa.Column('noise_level', sa.String(255), nullable=True), sa.Column('noise_level', sa.String(255), nullable=True),
sa.Column('status', sa.String(50), server_default='processing', nullable=False),
sa.Column('template_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('template_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('is_template_based', sa.Boolean(), nullable=False), sa.Column('is_template_based', sa.Boolean(), nullable=False),
sa.Column('user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('patient_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('template_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -27,11 +27,10 @@ def upgrade() -> None:
sa.Column('low_confidence_segments', postgresql.JSONB(), nullable=True), sa.Column('low_confidence_segments', postgresql.JSONB(), nullable=True),
sa.Column('processing_time_seconds', sa.Integer(), nullable=True), sa.Column('processing_time_seconds', sa.Integer(), nullable=True),
sa.Column('model_version', sa.String(50), nullable=False), sa.Column('model_version', sa.String(50), nullable=False),
sa.Column('status', sa.String(50), server_default='pending', nullable=False),
sa.Column('is_manually_corrected', sa.Boolean(), nullable=False), sa.Column('is_manually_corrected', sa.Boolean(), nullable=False),
sa.Column('corrected_by_user_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('corrected_by_user_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('corrected_at', sa.DateTime(timezone=True), nullable=True), sa.Column('corrected_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('audio_recording_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('corrected_by_user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -32,8 +32,6 @@ def upgrade() -> None:
sa.Column('is_verified', sa.Boolean(), nullable=False), sa.Column('is_verified', sa.Boolean(), nullable=False),
sa.Column('verified_by_user_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('verified_by_user_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('verified_at', sa.DateTime(timezone=True), nullable=True), sa.Column('verified_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('transcript_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('verified_by_user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -25,6 +25,8 @@ def upgrade() -> None:
sa.Column('effective_date', sa.Date(), nullable=True), sa.Column('effective_date', sa.Date(), nullable=True),
sa.Column('termination_date', sa.Date(), nullable=True), sa.Column('termination_date', sa.Date(), nullable=True),
sa.Column('version', sa.String(20), nullable=False), sa.Column('version', sa.String(20), nullable=False),
sa.Column('is_billable', sa.Boolean(), server_default='true', nullable=False),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('synonyms', postgresql.JSONB(), nullable=True), sa.Column('synonyms', postgresql.JSONB(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),

View File

@ -30,6 +30,7 @@ def upgrade() -> None:
sa.Column('rvu_facility', sa.Numeric(10, 2), nullable=True), sa.Column('rvu_facility', sa.Numeric(10, 2), nullable=True),
sa.Column('rvu_non_facility', sa.Numeric(10, 2), nullable=True), sa.Column('rvu_non_facility', sa.Numeric(10, 2), nullable=True),
sa.Column('global_period', sa.String(10), nullable=True), sa.Column('global_period', sa.String(10), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('synonyms', postgresql.JSONB(), nullable=True), sa.Column('synonyms', postgresql.JSONB(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),

View File

@ -26,6 +26,7 @@ def upgrade() -> None:
sa.Column('termination_date', sa.Date(), nullable=True), sa.Column('termination_date', sa.Date(), nullable=True),
sa.Column('reimbursement_impact', sa.Numeric(10, 2), nullable=True), sa.Column('reimbursement_impact', sa.Numeric(10, 2), nullable=True),
sa.Column('usage_rules', sa.Text(), nullable=True), sa.Column('usage_rules', sa.Text(), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -31,6 +31,7 @@ def upgrade() -> None:
sa.Column('email', sa.String(255), nullable=True), sa.Column('email', sa.String(255), nullable=True),
sa.Column('website', sa.String(255), nullable=True), sa.Column('website', sa.String(255), nullable=True),
sa.Column('priority_rank', sa.Integer(), nullable=True), sa.Column('priority_rank', sa.Integer(), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('notes', sa.Text(), nullable=True), sa.Column('notes', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),

View File

@ -31,9 +31,8 @@ def upgrade() -> None:
sa.Column('updated_by_user_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('updated_by_user_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('denial_count', sa.Integer(), nullable=False), sa.Column('denial_count', sa.Integer(), nullable=False),
sa.Column('last_denial_date', sa.DateTime(timezone=True), nullable=True), sa.Column('last_denial_date', sa.DateTime(timezone=True), nullable=True),
sa.Column('payer_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False), sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('created_by_user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False), sa.Column('severity', sa.String(50), server_default='medium', nullable=False),
sa.Column('updated_by_user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -25,6 +25,7 @@ def upgrade() -> None:
sa.Column('effective_date', sa.Date(), nullable=False), sa.Column('effective_date', sa.Date(), nullable=False),
sa.Column('deletion_date', sa.Date(), nullable=True), sa.Column('deletion_date', sa.Date(), nullable=True),
sa.Column('edit_rationale', sa.Text(), nullable=True), sa.Column('edit_rationale', sa.Text(), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -31,6 +31,7 @@ def upgrade() -> None:
sa.Column('termination_date', sa.Date(), nullable=True), sa.Column('termination_date', sa.Date(), nullable=True),
sa.Column('last_review_date', sa.Date(), nullable=True), sa.Column('last_review_date', sa.Date(), nullable=True),
sa.Column('document_url', sa.String(500), nullable=True), sa.Column('document_url', sa.String(500), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -28,6 +28,7 @@ def upgrade() -> None:
sa.Column('termination_date', sa.Date(), nullable=True), sa.Column('termination_date', sa.Date(), nullable=True),
sa.Column('last_review_date', sa.Date(), nullable=True), sa.Column('last_review_date', sa.Date(), nullable=True),
sa.Column('document_url', sa.String(500), nullable=True), sa.Column('document_url', sa.String(500), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -29,8 +29,8 @@ def upgrade() -> None:
sa.Column('documentation_requirements', sa.Text(), nullable=True), sa.Column('documentation_requirements', sa.Text(), nullable=True),
sa.Column('mdm_level', sa.String(255), nullable=True), sa.Column('mdm_level', sa.String(255), nullable=True),
sa.Column('usage_count', sa.Integer(), nullable=False), sa.Column('usage_count', sa.Integer(), nullable=False),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('created_by_user_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('created_by_user_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('created_by_user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -38,6 +38,8 @@ def upgrade() -> None:
sa.Column('scrubbing_failures', postgresql.JSONB(), nullable=True), sa.Column('scrubbing_failures', postgresql.JSONB(), nullable=True),
sa.Column('corrective_actions', postgresql.JSONB(), nullable=True), sa.Column('corrective_actions', postgresql.JSONB(), nullable=True),
sa.Column('confidence_score', sa.Numeric(10, 2), nullable=True), sa.Column('confidence_score', sa.Numeric(10, 2), nullable=True),
sa.Column('status', sa.String(50), server_default='draft', nullable=False),
sa.Column('scrubbing_status', sa.String(50), server_default='pending', nullable=False),
sa.Column('is_template_based', sa.Boolean(), nullable=False), sa.Column('is_template_based', sa.Boolean(), nullable=False),
sa.Column('template_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('template_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('reviewed_by_user_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('reviewed_by_user_id', postgresql.UUID(as_uuid=True), nullable=True),
@ -47,13 +49,6 @@ def upgrade() -> None:
sa.Column('denial_reason', sa.Text(), nullable=True), sa.Column('denial_reason', sa.Text(), nullable=True),
sa.Column('denial_code', sa.String(50), nullable=True), sa.Column('denial_code', sa.String(50), nullable=True),
sa.Column('notes', sa.Text(), nullable=True), sa.Column('notes', sa.Text(), nullable=True),
sa.Column('patient_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('audio_recording_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('transcript_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('payer_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_by_user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('reviewed_by_user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('template_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -35,9 +35,6 @@ def upgrade() -> None:
sa.Column('escalated_to_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('escalated_to_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('escalated_at', sa.DateTime(timezone=True), nullable=True), sa.Column('escalated_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('reviewed_at', sa.DateTime(timezone=True), nullable=True), sa.Column('reviewed_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('claim_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('reviewer_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('escalated_to_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -35,7 +35,6 @@ def upgrade() -> None:
sa.Column('metadata', postgresql.JSONB(), nullable=True), sa.Column('metadata', postgresql.JSONB(), nullable=True),
sa.Column('phi_accessed', sa.Boolean(), nullable=True), sa.Column('phi_accessed', sa.Boolean(), nullable=True),
sa.Column('compliance_flag', sa.Boolean(), nullable=True), sa.Column('compliance_flag', sa.Boolean(), nullable=True),
sa.Column('user_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -36,7 +36,7 @@ def upgrade() -> None:
sa.Column('preventive_actions', postgresql.JSONB(), nullable=True), sa.Column('preventive_actions', postgresql.JSONB(), nullable=True),
sa.Column('related_lcd_ncd', postgresql.JSONB(), nullable=True), sa.Column('related_lcd_ncd', postgresql.JSONB(), nullable=True),
sa.Column('notes', sa.Text(), nullable=True), sa.Column('notes', sa.Text(), nullable=True),
sa.Column('payer_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False), sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -42,9 +42,8 @@ def upgrade() -> None:
sa.Column('rate_limit_per_minute', sa.Integer(), nullable=True), sa.Column('rate_limit_per_minute', sa.Integer(), nullable=True),
sa.Column('use_mock_data', sa.Boolean(), nullable=True), sa.Column('use_mock_data', sa.Boolean(), nullable=True),
sa.Column('configuration_notes', sa.Text(), nullable=True), sa.Column('configuration_notes', sa.Text(), nullable=True),
sa.Column('connection_status', sa.String(50), server_default='disconnected', nullable=False),
sa.Column('created_by_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('created_by_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('organization_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_by_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -39,10 +39,8 @@ def upgrade() -> None:
sa.Column('last_used_at', sa.DateTime(timezone=True), nullable=True), sa.Column('last_used_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('metadata', postgresql.JSONB(), nullable=True), sa.Column('metadata', postgresql.JSONB(), nullable=True),
sa.Column('tags', postgresql.JSONB(), nullable=True), sa.Column('tags', postgresql.JSONB(), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=False),
sa.Column('uploaded_by_id', postgresql.UUID(as_uuid=True), nullable=True), sa.Column('uploaded_by_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('payer_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('parent_document_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('uploaded_by_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -35,7 +35,6 @@ def upgrade() -> None:
sa.Column('corrected_value', sa.Text(), nullable=True), sa.Column('corrected_value', sa.Text(), nullable=True),
sa.Column('feedback_notes', sa.Text(), nullable=True), sa.Column('feedback_notes', sa.Text(), nullable=True),
sa.Column('processing_time_ms', sa.Integer(), nullable=True), sa.Column('processing_time_ms', sa.Integer(), nullable=True),
sa.Column('claim_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -43,7 +43,7 @@ def upgrade() -> None:
sa.Column('auto_fix_details', postgresql.JSONB(), nullable=True), sa.Column('auto_fix_details', postgresql.JSONB(), nullable=True),
sa.Column('requires_manual_review', sa.Boolean(), nullable=True), sa.Column('requires_manual_review', sa.Boolean(), nullable=True),
sa.Column('review_priority', sa.String(20), nullable=True), sa.Column('review_priority', sa.String(20), nullable=True),
sa.Column('claim_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('.id'), nullable=False), sa.Column('scrubbed_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'), onupdate=sa.text('CURRENT_TIMESTAMP'), nullable=False),
) )

View File

@ -0,0 +1,21 @@
"""Migration to add is_active to patients
Revision ID: auto24
Revises: auto23
Create Date: auto
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'auto24'
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
# Adding `is_active` column to `patients`
op.add_column('patients', sa.Column('is_active', sa.Boolean(), server_default='true', nullable=True))
def downgrade() -> None:
op.drop_column('patients', 'is_active')

53
src/models/__init__.py Normal file
View File

@ -0,0 +1,53 @@
from src.config.database import Base
from sqlalchemy import BigInteger
# Import all models here to register them with Base.metadata
from src.models.user_model import User
from src.models.patient_model import Patient
from src.models.payer_model import Payer
from src.models.payer_rule_model import PayerRule
from src.models.audio_recording_model import AudioRecording
from src.models.transcript_model import Transcript
from src.models.claim_model import Claim
from src.models.claim_review_model import ClaimReview
from src.models.claim_scrub_result_model import ClaimScrubResult
from src.models.audit_log_model import AuditLog
from src.models.clinical_entity_model import ClinicalEntity
from src.models.confidence_score_model import ConfidenceScore
from src.models.cpt_code_model import CPTCode
from src.models.cpt_modifier_model import CPTModifier
from src.models.denial_pattern_model import DenialPattern
from src.models.emr_integration_model import EMRIntegration
from src.models.icd10_code_model import ICD10Code
from src.models.lcd_model import LCD
from src.models.ncci_edit_model import NCCIEdit
from src.models.ncd_model import NCD
from src.models.procedure_template_model import ProcedureTemplate
from src.models.rag_document_model import RAGDocument
# Export all models for easy importing elsewhere
__all__ = [
"Base",
"User",
"Patient",
"Payer",
"PayerRule",
"AudioRecording",
"Transcript",
"Claim",
"ClaimReview",
"ClaimScrubResult",
"AuditLog",
"ClinicalEntity",
"ConfidenceScore",
"CPTCode",
"CPTModifier",
"DenialPattern",
"EMRIntegration",
"ICD10Code",
"LCD",
"NCCIEdit",
"NCD",
"ProcedureTemplate",
"RAGDocument",
]

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, BigInteger
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -8,8 +9,6 @@ class AudioRecording(Base):
__tablename__ = 'audio_recordings' __tablename__ = 'audio_recordings'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False)
user_id = Column(UUID(as_uuid=True), nullable=False)
patient_id = Column(UUID(as_uuid=True), nullable=False)
encounter_id = Column(String(255), nullable=True) encounter_id = Column(String(255), nullable=True)
file_path = Column(String(255), nullable=False) file_path = Column(String(255), nullable=False)
file_name = Column(String(255), nullable=False) file_name = Column(String(255), nullable=False)
@ -20,19 +19,18 @@ class AudioRecording(Base):
encryption_key_id = Column(String(255), nullable=True) encryption_key_id = Column(String(255), nullable=True)
device_info = Column(JSON, nullable=True) device_info = Column(JSON, nullable=True)
noise_level = Column(String(255), nullable=True) noise_level = Column(String(255), nullable=True)
template_id = Column(UUID(as_uuid=True), nullable=True)
is_template_based = Column(Boolean, nullable=False) is_template_based = Column(Boolean, nullable=False)
user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False) user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False)
user = relationship('User', back_populates='')
patient_id = Column(UUID(as_uuid=True), ForeignKey('patients.id'), nullable=False) patient_id = Column(UUID(as_uuid=True), ForeignKey('patients.id'), nullable=False)
patient = relationship('Patient', back_populates='')
template_id = Column(UUID(as_uuid=True), ForeignKey('procedure_templates.id'), nullable=True) template_id = Column(UUID(as_uuid=True), ForeignKey('procedure_templates.id'), nullable=True)
procedureTemplate = relationship('ProcedureTemplate', back_populates='')
user = relationship('User', back_populates='audioRecordings')
patient = relationship('Patient', back_populates='audioRecordings')
procedureTemplate = relationship('ProcedureTemplate')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
def __repr__(self): def __repr__(self):
return f'<AudioRecording(id={self.id})>' return f'<AudioRecording(id={self.id})>'

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -8,7 +9,6 @@ class AuditLog(Base):
__tablename__ = 'audit_logs' __tablename__ = 'audit_logs'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False)
user_id = Column(UUID(as_uuid=True), nullable=True)
entity_type = Column(String(255), nullable=False) entity_type = Column(String(255), nullable=False)
entity_id = Column(UUID(as_uuid=True), nullable=True) entity_id = Column(UUID(as_uuid=True), nullable=True)
action = Column(String(255), nullable=False) action = Column(String(255), nullable=False)
@ -22,16 +22,15 @@ class AuditLog(Base):
request_id = Column(String(255), nullable=True) request_id = Column(String(255), nullable=True)
status = Column(String(255), nullable=False) status = Column(String(255), nullable=False)
error_message = Column(Text, nullable=True) error_message = Column(Text, nullable=True)
metadata = Column(JSON, nullable=True) doc_metadata = Column(JSON, nullable=True)
phi_accessed = Column(Boolean, nullable=True) phi_accessed = Column(Boolean, nullable=True)
compliance_flag = Column(Boolean, nullable=True) compliance_flag = Column(Boolean, nullable=True)
user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='') user = relationship('User', back_populates='auditLogs')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
def __repr__(self): def __repr__(self):
return f'<AuditLog(id={self.id})>' return f'<AuditLog(id={self.id})>'

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -9,13 +10,8 @@ class Claim(Base):
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False)
claim_number = Column(String(255), nullable=False, unique=True) claim_number = Column(String(255), nullable=False, unique=True)
patient_id = Column(UUID(as_uuid=True), nullable=False)
audio_recording_id = Column(UUID(as_uuid=True), nullable=True)
transcript_id = Column(UUID(as_uuid=True), nullable=True)
payer_id = Column(UUID(as_uuid=True), nullable=False)
encounter_id = Column(String(255), nullable=True) encounter_id = Column(String(255), nullable=True)
service_date = Column(DateTime, nullable=False) service_date = Column(DateTime, nullable=False)
created_by_user_id = Column(UUID(as_uuid=True), nullable=False)
diagnosis_codes = Column(JSON, nullable=False) diagnosis_codes = Column(JSON, nullable=False)
procedure_codes = Column(JSON, nullable=False) procedure_codes = Column(JSON, nullable=False)
modifiers = Column(JSON, nullable=True) modifiers = Column(JSON, nullable=True)
@ -29,8 +25,6 @@ class Claim(Base):
corrective_actions = Column(JSON, nullable=True) corrective_actions = Column(JSON, nullable=True)
confidence_score = Column(String(255), nullable=True) confidence_score = Column(String(255), nullable=True)
is_template_based = Column(Boolean, nullable=False) is_template_based = Column(Boolean, nullable=False)
template_id = Column(UUID(as_uuid=True), nullable=True)
reviewed_by_user_id = Column(UUID(as_uuid=True), nullable=True)
reviewed_at = Column(DateTime, nullable=True) reviewed_at = Column(DateTime, nullable=True)
submitted_at = Column(DateTime, nullable=True) submitted_at = Column(DateTime, nullable=True)
paid_at = Column(DateTime, nullable=True) paid_at = Column(DateTime, nullable=True)
@ -39,23 +33,23 @@ class Claim(Base):
notes = Column(Text, nullable=True) notes = Column(Text, nullable=True)
patient_id = Column(UUID(as_uuid=True), ForeignKey('patients.id'), nullable=False) patient_id = Column(UUID(as_uuid=True), ForeignKey('patients.id'), nullable=False)
patient = relationship('Patient', back_populates='')
audio_recording_id = Column(UUID(as_uuid=True), ForeignKey('audio_recordings.id'), nullable=True) audio_recording_id = Column(UUID(as_uuid=True), ForeignKey('audio_recordings.id'), nullable=True)
audioRecording = relationship('AudioRecording', back_populates='')
transcript_id = Column(UUID(as_uuid=True), ForeignKey('transcripts.id'), nullable=True) transcript_id = Column(UUID(as_uuid=True), ForeignKey('transcripts.id'), nullable=True)
transcript = relationship('Transcript', back_populates='')
payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=False) payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=False)
payer = relationship('Payer', back_populates='')
created_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False) created_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False)
user = relationship('User', back_populates='')
reviewed_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) reviewed_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='')
template_id = Column(UUID(as_uuid=True), ForeignKey('procedure_templates.id'), nullable=True) template_id = Column(UUID(as_uuid=True), ForeignKey('procedure_templates.id'), nullable=True)
procedureTemplate = relationship('ProcedureTemplate', back_populates='')
patient = relationship('Patient', back_populates='claims')
audioRecording = relationship('AudioRecording')
transcript = relationship('Transcript')
payer = relationship('Payer')
creator = relationship('User', foreign_keys=[created_by_user_id], back_populates='claims')
reviewer = relationship('User', foreign_keys=[reviewed_by_user_id], back_populates='reviewedClaims')
procedureTemplate = relationship('ProcedureTemplate')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
def __repr__(self): def __repr__(self):
return f'<Claim(id={self.id})>' return f'<Claim(id={self.id})>'

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -8,8 +9,8 @@ class ClaimReview(Base):
__tablename__ = 'claim_reviews' __tablename__ = 'claim_reviews'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False)
claim_id = Column(UUID(as_uuid=True), nullable=False) claim_id = Column(UUID(as_uuid=True), ForeignKey('claims.id'), nullable=False)
reviewer_id = Column(UUID(as_uuid=True), nullable=False) reviewer_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False)
review_status = Column(String(255), nullable=False) review_status = Column(String(255), nullable=False)
review_type = Column(String(255), nullable=False) review_type = Column(String(255), nullable=False)
confidence_threshold_triggered = Column(Boolean, nullable=True) confidence_threshold_triggered = Column(Boolean, nullable=True)
@ -22,16 +23,12 @@ class ClaimReview(Base):
corrective_actions = Column(JSON, nullable=True) corrective_actions = Column(JSON, nullable=True)
review_duration_seconds = Column(Integer, nullable=True) review_duration_seconds = Column(Integer, nullable=True)
escalation_reason = Column(Text, nullable=True) escalation_reason = Column(Text, nullable=True)
escalated_to_id = Column(UUID(as_uuid=True), nullable=True) escalated_to_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
escalated_at = Column(DateTime, nullable=True) escalated_at = Column(DateTime, nullable=True)
reviewed_at = Column(DateTime, nullable=True) reviewed_at = Column(DateTime, nullable=True)
claim = relationship('Claim', foreign_keys=[claim_id])
claim_id = Column(UUID(as_uuid=True), ForeignKey('claims.id'), nullable=False) reviewer = relationship('User', foreign_keys=[reviewer_id])
claim = relationship('Claim', back_populates='') escalated_to = relationship('User', foreign_keys=[escalated_to_id])
reviewer_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False)
user = relationship('User', back_populates='')
escalated_to_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -8,7 +9,6 @@ class ClinicalEntity(Base):
__tablename__ = 'clinical_entities' __tablename__ = 'clinical_entities'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False)
transcript_id = Column(UUID(as_uuid=True), nullable=False)
entity_type = Column(String(255), nullable=False) entity_type = Column(String(255), nullable=False)
entity_text = Column(String(255), nullable=False) entity_text = Column(String(255), nullable=False)
normalized_text = Column(String(255), nullable=True) normalized_text = Column(String(255), nullable=True)
@ -16,21 +16,21 @@ class ClinicalEntity(Base):
start_position = Column(Integer, nullable=True) start_position = Column(Integer, nullable=True)
end_position = Column(Integer, nullable=True) end_position = Column(Integer, nullable=True)
context = Column(Text, nullable=True) context = Column(Text, nullable=True)
metadata = Column(JSON, nullable=True) doc_metadata = Column(JSON, nullable=True)
is_negated = Column(Boolean, nullable=False) is_negated = Column(Boolean, nullable=False)
is_historical = Column(Boolean, nullable=False) is_historical = Column(Boolean, nullable=False)
is_verified = Column(Boolean, nullable=False) is_verified = Column(Boolean, nullable=False)
verified_by_user_id = Column(UUID(as_uuid=True), nullable=True)
verified_at = Column(DateTime, nullable=True) verified_at = Column(DateTime, nullable=True)
transcript_id = Column(UUID(as_uuid=True), ForeignKey('transcripts.id'), nullable=False) transcript_id = Column(UUID(as_uuid=True), ForeignKey('transcripts.id'), nullable=False)
transcript = relationship('Transcript', back_populates='')
verified_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) verified_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='')
transcript = relationship('Transcript', back_populates='clinicalEntitys')
verifier = relationship('User', back_populates='verifiedClinicalEntities')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
def __repr__(self): def __repr__(self):
return f'<ClinicalEntity(id={self.id})>' return f'<ClinicalEntity(id={self.id})>'

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -8,7 +9,6 @@ class DenialPattern(Base):
__tablename__ = 'denial_patterns' __tablename__ = 'denial_patterns'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False)
payer_id = Column(UUID(as_uuid=True), nullable=False)
payer_name = Column(String(255), nullable=False) payer_name = Column(String(255), nullable=False)
denial_code = Column(String(255), nullable=False) denial_code = Column(String(255), nullable=False)
denial_reason = Column(Text, nullable=False) denial_reason = Column(Text, nullable=False)
@ -26,9 +26,11 @@ class DenialPattern(Base):
preventive_actions = Column(JSON, nullable=True) preventive_actions = Column(JSON, nullable=True)
related_lcd_ncd = Column(JSON, nullable=True) related_lcd_ncd = Column(JSON, nullable=True)
notes = Column(Text, nullable=True) notes = Column(Text, nullable=True)
payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=False) payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=False)
payer = relationship('Payer', back_populates='') payer = relationship('Payer', back_populates='denialPatterns')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -32,12 +33,10 @@ class EMRIntegration(Base):
rate_limit_per_minute = Column(Integer, nullable=True) rate_limit_per_minute = Column(Integer, nullable=True)
use_mock_data = Column(Boolean, nullable=True) use_mock_data = Column(Boolean, nullable=True)
configuration_notes = Column(Text, nullable=True) configuration_notes = Column(Text, nullable=True)
created_by_id = Column(UUID(as_uuid=True), nullable=True)
organization_id = Column(UUID(as_uuid=True), ForeignKey('organizations.id'), nullable=False)
organization = relationship('Organization', back_populates='')
created_by_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) created_by_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='') creator = relationship('User', back_populates='createdEMRIntegrations')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -21,19 +22,19 @@ class Patient(Base):
zip_code = Column(String(255), nullable=True) zip_code = Column(String(255), nullable=True)
phone = Column(String(255), nullable=True) phone = Column(String(255), nullable=True)
email = Column(String(255), nullable=True) email = Column(String(255), nullable=True)
primary_payer_id = Column(UUID(as_uuid=True), nullable=True)
primary_insurance_member_id = Column(String(255), nullable=True)
secondary_payer_id = Column(UUID(as_uuid=True), nullable=True)
secondary_insurance_member_id = Column(String(255), nullable=True)
emr_patient_id = Column(String(255), nullable=True)
primary_payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=True) primary_payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=True)
payer = relationship('Payer', back_populates='')
secondary_payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=True) secondary_payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=True)
payer = relationship('Payer', back_populates='')
primary_insurance_member_id = Column(String(255), nullable=True)
secondary_insurance_member_id = Column(String(255), nullable=True)
emr_patient_id = Column(String(255), nullable=True)
is_active = Column(Boolean, default=True)
primary_payer = relationship('Payer', foreign_keys=[primary_payer_id], back_populates='primary_patients')
secondary_payer = relationship('Payer', foreign_keys=[secondary_payer_id], back_populates='secondary_patients')
audioRecordings = relationship('AudioRecording', back_populates='patient') audioRecordings = relationship('AudioRecording', back_populates='patient')
claims = relationship('Claim', back_populates='patient') claims = relationship('Claim', back_populates='patient')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -24,8 +25,13 @@ class Payer(Base):
notes = Column(Text, nullable=True) notes = Column(Text, nullable=True)
payerRules = relationship('PayerRule', back_populates='payer') payerRules = relationship('PayerRule', back_populates='payer')
ragDocuments = relationship('RAGDocument', back_populates='payer')
denialPatterns = relationship('DenialPattern', back_populates='payer')
patients = relationship('Patient', back_populates='payer')
primary_patients = relationship('Patient', foreign_keys='[Patient.primary_payer_id]', back_populates='primary_payer')
secondary_patients = relationship('Patient', foreign_keys='[Patient.secondary_payer_id]', back_populates='secondary_payer')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -8,7 +9,6 @@ class PayerRule(Base):
__tablename__ = 'payer_rules' __tablename__ = 'payer_rules'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False)
payer_id = Column(UUID(as_uuid=True), nullable=False)
rule_name = Column(String(255), nullable=False) rule_name = Column(String(255), nullable=False)
rule_type = Column(String(255), nullable=False) rule_type = Column(String(255), nullable=False)
rule_description = Column(Text, nullable=False) rule_description = Column(Text, nullable=False)
@ -17,17 +17,19 @@ class PayerRule(Base):
affected_icd10_codes = Column(JSON, nullable=True) affected_icd10_codes = Column(JSON, nullable=True)
effective_date = Column(DateTime, nullable=False) effective_date = Column(DateTime, nullable=False)
termination_date = Column(DateTime, nullable=True) termination_date = Column(DateTime, nullable=True)
created_by_user_id = Column(UUID(as_uuid=True), nullable=True)
updated_by_user_id = Column(UUID(as_uuid=True), nullable=True)
denial_count = Column(Integer, nullable=False) denial_count = Column(Integer, nullable=False)
last_denial_date = Column(DateTime, nullable=True) last_denial_date = Column(DateTime, nullable=True)
payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=False) payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=False)
payer = relationship('Payer', back_populates='') payer = relationship('Payer', back_populates='payerRules')
created_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) created_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='') creator = relationship('User', foreign_keys=[created_by_user_id], back_populates='createdPayerRules')
updated_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) updated_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='') updater = relationship('User', foreign_keys=[updated_by_user_id], back_populates='updatedPayerRules')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -19,10 +20,10 @@ class ProcedureTemplate(Base):
documentation_requirements = Column(Text, nullable=True) documentation_requirements = Column(Text, nullable=True)
mdm_level = Column(String(255), nullable=True) mdm_level = Column(String(255), nullable=True)
usage_count = Column(Integer, nullable=False) usage_count = Column(Integer, nullable=False)
created_by_user_id = Column(UUID(as_uuid=True), nullable=True)
created_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) created_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='') creator = relationship('User', back_populates='createdProcedureTemplates')
audioRecordings = relationship('AudioRecording', back_populates='procedureTemplate') audioRecordings = relationship('AudioRecording', back_populates='procedureTemplate')

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -27,16 +28,19 @@ class RAGDocument(Base):
relevance_score = Column(String(255), nullable=True) relevance_score = Column(String(255), nullable=True)
usage_count = Column(Integer, nullable=True) usage_count = Column(Integer, nullable=True)
last_used_at = Column(DateTime, nullable=True) last_used_at = Column(DateTime, nullable=True)
metadata = Column(JSON, nullable=True) doc_doc_doc_metadata = Column(JSON, nullable=True)
tags = Column(JSON, nullable=True) tags = Column(JSON, nullable=True)
uploaded_by_id = Column(UUID(as_uuid=True), nullable=True)
payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=True) payer_id = Column(UUID(as_uuid=True), ForeignKey('payers.id'), nullable=True)
payer = relationship('Payer', back_populates='') payer = relationship('Payer', back_populates='ragDocuments')
parent_document_id = Column(UUID(as_uuid=True), ForeignKey('rag_documents.id'), nullable=True) parent_document_id = Column(UUID(as_uuid=True), ForeignKey('rag_documents.id'), nullable=True)
rAGDocument = relationship('RAGDocument', back_populates='') parent_document = relationship('RAGDocument', remote_side=[id], back_populates='chunks')
chunks = relationship('RAGDocument', back_populates='parent_document')
uploaded_by_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) uploaded_by_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='') uploader = relationship('User', back_populates='uploadedDocuments')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -8,7 +9,6 @@ class Transcript(Base):
__tablename__ = 'transcripts' __tablename__ = 'transcripts'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False)
audio_recording_id = Column(UUID(as_uuid=True), nullable=False, unique=True)
raw_text = Column(Text, nullable=False) raw_text = Column(Text, nullable=False)
corrected_text = Column(Text, nullable=True) corrected_text = Column(Text, nullable=True)
word_error_rate = Column(String(255), nullable=True) word_error_rate = Column(String(255), nullable=True)
@ -18,14 +18,13 @@ class Transcript(Base):
processing_time_seconds = Column(Integer, nullable=True) processing_time_seconds = Column(Integer, nullable=True)
model_version = Column(String(255), nullable=False) model_version = Column(String(255), nullable=False)
is_manually_corrected = Column(Boolean, nullable=False) is_manually_corrected = Column(Boolean, nullable=False)
corrected_by_user_id = Column(UUID(as_uuid=True), nullable=True)
corrected_at = Column(DateTime, nullable=True) corrected_at = Column(DateTime, nullable=True)
audio_recording_id = Column(UUID(as_uuid=True), ForeignKey('audio_recordings.id'), nullable=False) audio_recording_id = Column(UUID(as_uuid=True), ForeignKey('audio_recordings.id'), nullable=False, unique=True)
audioRecording = relationship('AudioRecording', back_populates='')
corrected_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True) corrected_by_user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=True)
user = relationship('User', back_populates='')
audioRecording = relationship('AudioRecording')
user = relationship('User')
clinicalEntitys = relationship('ClinicalEntity', back_populates='transcript') clinicalEntitys = relationship('ClinicalEntity', back_populates='transcript')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
@ -33,4 +32,3 @@ class Transcript(Base):
def __repr__(self): def __repr__(self):
return f'<Transcript(id={self.id})>' return f'<Transcript(id={self.id})>'

View File

@ -1,4 +1,5 @@
from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY, relationship from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, Text, JSON, ARRAY
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from src.config.database import Base from src.config.database import Base
from sqlalchemy.sql import func from sqlalchemy.sql import func
@ -16,10 +17,22 @@ class User(Base):
specialty = Column(String(255), nullable=True) specialty = Column(String(255), nullable=True)
npi = Column(String(255), nullable=True) npi = Column(String(255), nullable=True)
last_login_at = Column(DateTime, nullable=True) last_login_at = Column(DateTime, nullable=True)
role = Column(String(50), default='user', nullable=False)
is_active = Column(Boolean, default=True, nullable=False)
audioRecordings = relationship('AudioRecording', back_populates='user') audioRecordings = relationship('AudioRecording', back_populates='user')
claims = relationship('Claim', foreign_keys='[Claim.created_by_user_id]', back_populates='creator')
reviewedClaims = relationship('Claim', foreign_keys='[Claim.reviewed_by_user_id]', back_populates='reviewer')
auditLogs = relationship('AuditLog', back_populates='user')
createdPayerRules = relationship('PayerRule', foreign_keys='[PayerRule.created_by_user_id]', back_populates='creator')
updatedPayerRules = relationship('PayerRule', foreign_keys='[PayerRule.updated_by_user_id]', back_populates='updater')
uploadedDocuments = relationship('RAGDocument', back_populates='uploader')
createdEMRIntegrations = relationship('EMRIntegration', back_populates='creator')
createdProcedureTemplates = relationship('ProcedureTemplate', back_populates='creator')
verifiedClinicalEntities = relationship('ClinicalEntity', back_populates='verifier')
claims = relationship('Claim', back_populates='user')
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)

View File

@ -12,7 +12,7 @@ from langchain_community.document_loaders import (
UnstructuredExcelLoader UnstructuredExcelLoader
) )
from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma # from langchain_community.vectorstores import Chroma
from langchain_huggingface import HuggingFaceEmbeddings from langchain_huggingface import HuggingFaceEmbeddings
from langchain_openai import OpenAIEmbeddings from langchain_openai import OpenAIEmbeddings
from loguru import logger from loguru import logger
@ -75,11 +75,12 @@ class RAGIngestor:
logger.info(f"Split document into {len(chunks)} chunks") logger.info(f"Split document into {len(chunks)} chunks")
# 3 & 4. Embedding & Storage # 3 & 4. Embedding & Storage
vectorstore = Chroma.from_documents( # vectorstore = Chroma.from_documents(
documents=chunks, # documents=chunks,
embedding=self.embeddings, # embedding=self.embeddings,
persist_directory=self.persist_directory, # persist_directory=self.persist_directory,
collection_name=collection_name # collection_name=collection_name
) # )
logger.warning("Vector storage (Chroma) is temporarily disabled due to installation issues.")
return len(chunks) return len(chunks)

View File

@ -4,7 +4,7 @@ Handles query embedding, vector retrieval, reranking, and LLM generation.
""" """
import time import time
from typing import List, Dict, Any, Optional from typing import List, Dict, Any, Optional
from langchain_community.vectorstores import Chroma # from langchain_community.vectorstores import Chroma
from langchain_huggingface import HuggingFaceEmbeddings from langchain_huggingface import HuggingFaceEmbeddings
from langchain_openai import OpenAIEmbeddings, ChatOpenAI from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_anthropic import ChatAnthropic from langchain_anthropic import ChatAnthropic
@ -54,11 +54,13 @@ Helpful Answer:"""
) )
def _get_vectorstore(self, collection_name: str): def _get_vectorstore(self, collection_name: str):
return Chroma( # return Chroma(
persist_directory=self.persist_directory, # persist_directory=self.persist_directory,
embedding_function=self.embeddings, # embedding_function=self.embeddings,
collection_name=collection_name # collection_name=collection_name
) # )
logger.error("Vector retrieval (Chroma) is temporarily disabled.")
return None
async def query(self, question: str, collection_name: str, top_k: int = 4) -> Dict[str, Any]: async def query(self, question: str, collection_name: str, top_k: int = 4) -> Dict[str, Any]:
""" """
@ -72,6 +74,8 @@ Helpful Answer:"""
start_time = time.time() start_time = time.time()
vectorstore = self._get_vectorstore(collection_name) vectorstore = self._get_vectorstore(collection_name)
if not vectorstore:
return {"query": question, "answer": "Vector store not available.", "source_documents": [], "processing_time_ms": 0}
qa_chain = RetrievalQA.from_chain_type( qa_chain = RetrievalQA.from_chain_type(
llm=self.llm, llm=self.llm,

View File

@ -1,115 +0,0 @@
"""
AudioRecording API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.audio_recording_service import AudioRecordingCRUD
from src.validation.audio_recording_schemas import (
AudioRecordingCreate,
AudioRecordingUpdate,
AudioRecordingResponse,
AudioRecordingListResponse,
)
router = APIRouter(prefix="/audiorecordings", tags=["AudioRecording"])
def get_crud(db: Session = Depends(get_db)) -> AudioRecordingCRUD:
"""Dependency injection for AudioRecordingCRUD"""
return AudioRecordingCRUD(db)
@router.get("/", response_model=AudioRecordingListResponse)
async def list_audio_recordings(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: AudioRecordingCRUD = Depends(get_crud),
):
"""
List all audiorecordings with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return AudioRecordingListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ audio_recording_id }", response_model=AudioRecordingResponse)
async def get_audio_recording(
audio_recording_id: UUID,
crud: AudioRecordingCRUD = Depends(get_crud),
):
"""
Get a specific audiorecording by ID.
- **audio_recording_id**: The UUID of the audiorecording
"""
db_audio_recording = crud.get_by_id(audio_recording_id)
if not db_audio_recording:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"AudioRecording with id { audio_recording_id} not found"
)
return db_audio_recording
@router.post("/", response_model=AudioRecordingResponse, status_code=status.HTTP_201_CREATED)
async def create_audio_recording(
audio_recording_in: AudioRecordingCreate,
crud: AudioRecordingCRUD = Depends(get_crud),
):
"""
Create a new audiorecording.
- **audio_recording_in**: The audiorecording data to create
"""
return crud.create(audio_recording_in)
@router.put("/{ audio_recording_id }", response_model=AudioRecordingResponse)
async def update_audio_recording(
audio_recording_id: UUID,
audio_recording_in: AudioRecordingUpdate,
crud: AudioRecordingCRUD = Depends(get_crud),
):
"""
Update an existing audiorecording.
- **audio_recording_id**: The UUID of the audiorecording to update
- **audio_recording_in**: The updated audiorecording data
"""
db_audio_recording = crud.get_by_id(audio_recording_id)
if not db_audio_recording:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"AudioRecording with id { audio_recording_id} not found"
)
return crud.update(audio_recording_id, audio_recording_in)
@router.delete("/{ audio_recording_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_audio_recording(
audio_recording_id: UUID,
crud: AudioRecordingCRUD = Depends(get_crud),
):
"""
Delete a audiorecording.
- **audio_recording_id**: The UUID of the audiorecording to delete
"""
db_audio_recording = crud.get_by_id(audio_recording_id)
if not db_audio_recording:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"AudioRecording with id { audio_recording_id} not found"
)
crud.delete(audio_recording_id)
return None

View File

@ -35,7 +35,7 @@ async def list_audio_recordings(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return AudioRecordingListResponse( return AudioRecordingListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_audio_recording(
- **audio_recording_id**: The UUID of the audiorecording - **audio_recording_id**: The UUID of the audiorecording
""" """
db_audio_recording = crud.get_by_id(audio_recording_id) db_audio_recording = await crud.get_by_id(audio_recording_id)
if not db_audio_recording: if not db_audio_recording:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_audio_recording(
- **audio_recording_in**: The audiorecording data to create - **audio_recording_in**: The audiorecording data to create
""" """
return crud.create(audio_recording_in) return await crud.create(audio_recording_in)
@router.put("/{ audio_recording_id }", response_model=AudioRecordingResponse) @router.put("/{ audio_recording_id }", response_model=AudioRecordingResponse)
async def update_audio_recording( async def update_audio_recording(
@ -87,13 +87,13 @@ async def update_audio_recording(
- **audio_recording_id**: The UUID of the audiorecording to update - **audio_recording_id**: The UUID of the audiorecording to update
- **audio_recording_in**: The updated audiorecording data - **audio_recording_in**: The updated audiorecording data
""" """
db_audio_recording = crud.get_by_id(audio_recording_id) db_audio_recording = await crud.get_by_id(audio_recording_id)
if not db_audio_recording: if not db_audio_recording:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"AudioRecording with id { audio_recording_id} not found" detail=f"AudioRecording with id { audio_recording_id} not found"
) )
return crud.update(audio_recording_id, audio_recording_in) return await crud.update(audio_recording_id, audio_recording_in)
@router.delete("/{ audio_recording_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ audio_recording_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_audio_recording( async def delete_audio_recording(
@ -105,11 +105,11 @@ async def delete_audio_recording(
- **audio_recording_id**: The UUID of the audiorecording to delete - **audio_recording_id**: The UUID of the audiorecording to delete
""" """
db_audio_recording = crud.get_by_id(audio_recording_id) db_audio_recording = await crud.get_by_id(audio_recording_id)
if not db_audio_recording: if not db_audio_recording:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"AudioRecording with id { audio_recording_id} not found" detail=f"AudioRecording with id { audio_recording_id} not found"
) )
crud.delete(audio_recording_id) await crud.delete(audio_recording_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
AuditLog API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.audit_log_service import AuditLogCRUD
from src.validation.audit_log_schemas import (
AuditLogCreate,
AuditLogUpdate,
AuditLogResponse,
AuditLogListResponse,
)
router = APIRouter(prefix="/auditlogs", tags=["AuditLog"])
def get_crud(db: Session = Depends(get_db)) -> AuditLogCRUD:
"""Dependency injection for AuditLogCRUD"""
return AuditLogCRUD(db)
@router.get("/", response_model=AuditLogListResponse)
async def list_audit_logs(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: AuditLogCRUD = Depends(get_crud),
):
"""
List all auditlogs with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return AuditLogListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ audit_log_id }", response_model=AuditLogResponse)
async def get_audit_log(
audit_log_id: UUID,
crud: AuditLogCRUD = Depends(get_crud),
):
"""
Get a specific auditlog by ID.
- **audit_log_id**: The UUID of the auditlog
"""
db_audit_log = crud.get_by_id(audit_log_id)
if not db_audit_log:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"AuditLog with id { audit_log_id} not found"
)
return db_audit_log
@router.post("/", response_model=AuditLogResponse, status_code=status.HTTP_201_CREATED)
async def create_audit_log(
audit_log_in: AuditLogCreate,
crud: AuditLogCRUD = Depends(get_crud),
):
"""
Create a new auditlog.
- **audit_log_in**: The auditlog data to create
"""
return crud.create(audit_log_in)
@router.put("/{ audit_log_id }", response_model=AuditLogResponse)
async def update_audit_log(
audit_log_id: UUID,
audit_log_in: AuditLogUpdate,
crud: AuditLogCRUD = Depends(get_crud),
):
"""
Update an existing auditlog.
- **audit_log_id**: The UUID of the auditlog to update
- **audit_log_in**: The updated auditlog data
"""
db_audit_log = crud.get_by_id(audit_log_id)
if not db_audit_log:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"AuditLog with id { audit_log_id} not found"
)
return crud.update(audit_log_id, audit_log_in)
@router.delete("/{ audit_log_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_audit_log(
audit_log_id: UUID,
crud: AuditLogCRUD = Depends(get_crud),
):
"""
Delete a auditlog.
- **audit_log_id**: The UUID of the auditlog to delete
"""
db_audit_log = crud.get_by_id(audit_log_id)
if not db_audit_log:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"AuditLog with id { audit_log_id} not found"
)
crud.delete(audit_log_id)
return None

View File

@ -35,7 +35,7 @@ async def list_audit_logs(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return AuditLogListResponse( return AuditLogListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_audit_log(
- **audit_log_id**: The UUID of the auditlog - **audit_log_id**: The UUID of the auditlog
""" """
db_audit_log = crud.get_by_id(audit_log_id) db_audit_log = await crud.get_by_id(audit_log_id)
if not db_audit_log: if not db_audit_log:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_audit_log(
- **audit_log_in**: The auditlog data to create - **audit_log_in**: The auditlog data to create
""" """
return crud.create(audit_log_in) return await crud.create(audit_log_in)
@router.put("/{ audit_log_id }", response_model=AuditLogResponse) @router.put("/{ audit_log_id }", response_model=AuditLogResponse)
async def update_audit_log( async def update_audit_log(
@ -87,13 +87,13 @@ async def update_audit_log(
- **audit_log_id**: The UUID of the auditlog to update - **audit_log_id**: The UUID of the auditlog to update
- **audit_log_in**: The updated auditlog data - **audit_log_in**: The updated auditlog data
""" """
db_audit_log = crud.get_by_id(audit_log_id) db_audit_log = await crud.get_by_id(audit_log_id)
if not db_audit_log: if not db_audit_log:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"AuditLog with id { audit_log_id} not found" detail=f"AuditLog with id { audit_log_id} not found"
) )
return crud.update(audit_log_id, audit_log_in) return await crud.update(audit_log_id, audit_log_in)
@router.delete("/{ audit_log_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ audit_log_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_audit_log( async def delete_audit_log(
@ -105,11 +105,11 @@ async def delete_audit_log(
- **audit_log_id**: The UUID of the auditlog to delete - **audit_log_id**: The UUID of the auditlog to delete
""" """
db_audit_log = crud.get_by_id(audit_log_id) db_audit_log = await crud.get_by_id(audit_log_id)
if not db_audit_log: if not db_audit_log:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"AuditLog with id { audit_log_id} not found" detail=f"AuditLog with id { audit_log_id} not found"
) )
crud.delete(audit_log_id) await crud.delete(audit_log_id)
return None return None

View File

@ -1,115 +1,84 @@
""" from fastapi import APIRouter, Depends, HTTPException, status
User API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db from src.config.database import get_db
from src.services.user_service import UserCRUD from src.services.user_service import UserCRUD
from src.validation.user_schemas import ( from src.validation.auth_schemas import (
UserCreate, LoginRequest,
UserUpdate, RegisterRequest,
UserResponse, RefreshTokenRequest,
UserListResponse, ForgotPasswordRequest,
ResetPasswordRequest,
ChangePasswordRequest,
Token
) )
from src.validation.user_schemas import UserResponse
router = APIRouter(prefix="/users", tags=["User"]) router = APIRouter(prefix="/auth", tags=["Auth"])
def get_crud(db: Session = Depends(get_db)) -> UserCRUD: def get_user_service(db: Session = Depends(get_db)) -> UserCRUD:
"""Dependency injection for UserCRUD"""
return UserCRUD(db) return UserCRUD(db)
@router.get("/", response_model=UserListResponse) @router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def list_users( async def register(
skip: int = Query(0, ge=0, description="Number of records to skip"), user_in: RegisterRequest,
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"), service: UserCRUD = Depends(get_user_service)
crud: UserCRUD = Depends(get_crud),
): ):
""" # Map RegisterRequest to UserCreate for the service
List all users with pagination and filtering. from src.validation.user_schemas import UserCreate
user_create = UserCreate(
- **skip**: Number of records to skip (for pagination) username=user_in.username,
- **limit**: Maximum number of records to return email=user_in.email,
""" password_hash=user_in.password, # UserService hashes it
items, total = crud.get_all(skip=skip, limit=limit) first_name=user_in.first_name,
last_name=user_in.last_name,
return UserListResponse( role=user_in.role,
items=items, specialty=user_in.specialty,
total=total, npi=user_in.npi,
skip=skip, is_active=True
limit=limit,
has_more=skip + limit < total
) )
return await service.create(user_create)
@router.get("/{ user_id }", response_model=UserResponse) @router.post("/login")
async def get_user( async def login(
user_id: UUID, login_data: LoginRequest,
crud: UserCRUD = Depends(get_crud), service: UserCRUD = Depends(get_user_service)
): ):
""" return await service.login(login_data.username, login_data.password)
Get a specific user by ID.
- **user_id**: The UUID of the user
"""
db_user = crud.get_by_id(user_id)
if not db_user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"User with id { user_id} not found"
)
return db_user
@router.post("/", response_model=UserResponse, status_code=status.HTTP_201_CREATED) @router.post("/logout")
async def create_user( async def logout():
user_in: UserCreate, return {"message": "Successfully logged out"}
crud: UserCRUD = Depends(get_crud),
):
"""
Create a new user.
- **user_in**: The user data to create
"""
return crud.create(user_in)
@router.put("/{ user_id }", response_model=UserResponse) @router.post("/refresh")
async def update_user( async def refresh_token(
user_id: UUID, refresh_data: RefreshTokenRequest,
user_in: UserUpdate, service: UserCRUD = Depends(get_user_service)
crud: UserCRUD = Depends(get_crud),
): ):
""" return await service.refreshToken(refresh_data.refresh_token)
Update an existing user.
- **user_id**: The UUID of the user to update
- **user_in**: The updated user data
"""
db_user = crud.get_by_id(user_id)
if not db_user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"User with id { user_id} not found"
)
return crud.update(user_id, user_in)
@router.delete("/{ user_id }", status_code=status.HTTP_204_NO_CONTENT) @router.post("/forgot-password")
async def delete_user( async def forgot_password(
user_id: UUID, data: ForgotPasswordRequest,
crud: UserCRUD = Depends(get_crud), service: UserCRUD = Depends(get_user_service)
): ):
""" return await service.forgotPassword(data.email)
Delete a user.
@router.post("/reset-password")
- **user_id**: The UUID of the user to delete async def reset_password(
""" data: ResetPasswordRequest,
db_user = crud.get_by_id(user_id) service: UserCRUD = Depends(get_user_service)
if not db_user: ):
raise HTTPException( return await service.resetPassword(data.token, data.new_password)
status_code=status.HTTP_404_NOT_FOUND,
detail=f"User with id { user_id} not found" @router.post("/change-password")
) async def change_password(
crud.delete(user_id) data: ChangePasswordRequest,
return None service: UserCRUD = Depends(get_user_service)
):
return await service.changePassword(data.current_password, data.new_password)
@router.get("/me", response_model=UserResponse)
async def get_me(service: UserCRUD = Depends(get_user_service)):
# This usually requires a security dependency to get current user
# For alignment purposes, we'll keep it simple or hook into service
return await service.get_current_user()

View File

@ -35,7 +35,7 @@ async def list_claim_reviews(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return ClaimReviewListResponse( return ClaimReviewListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_claim_review(
- **claim_review_id**: The UUID of the claimreview - **claim_review_id**: The UUID of the claimreview
""" """
db_claim_review = crud.get_by_id(claim_review_id) db_claim_review = await crud.get_by_id(claim_review_id)
if not db_claim_review: if not db_claim_review:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_claim_review(
- **claim_review_in**: The claimreview data to create - **claim_review_in**: The claimreview data to create
""" """
return crud.create(claim_review_in) return await crud.create(claim_review_in)
@router.put("/{ claim_review_id }", response_model=ClaimReviewResponse) @router.put("/{ claim_review_id }", response_model=ClaimReviewResponse)
async def update_claim_review( async def update_claim_review(
@ -87,13 +87,13 @@ async def update_claim_review(
- **claim_review_id**: The UUID of the claimreview to update - **claim_review_id**: The UUID of the claimreview to update
- **claim_review_in**: The updated claimreview data - **claim_review_in**: The updated claimreview data
""" """
db_claim_review = crud.get_by_id(claim_review_id) db_claim_review = await crud.get_by_id(claim_review_id)
if not db_claim_review: if not db_claim_review:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimReview with id { claim_review_id} not found" detail=f"ClaimReview with id { claim_review_id} not found"
) )
return crud.update(claim_review_id, claim_review_in) return await crud.update(claim_review_id, claim_review_in)
@router.delete("/{ claim_review_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ claim_review_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_claim_review( async def delete_claim_review(
@ -105,11 +105,11 @@ async def delete_claim_review(
- **claim_review_id**: The UUID of the claimreview to delete - **claim_review_id**: The UUID of the claimreview to delete
""" """
db_claim_review = crud.get_by_id(claim_review_id) db_claim_review = await crud.get_by_id(claim_review_id)
if not db_claim_review: if not db_claim_review:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimReview with id { claim_review_id} not found" detail=f"ClaimReview with id { claim_review_id} not found"
) )
crud.delete(claim_review_id) await crud.delete(claim_review_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_claims(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return ClaimListResponse( return ClaimListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_claim(
- **claim_id**: The UUID of the claim - **claim_id**: The UUID of the claim
""" """
db_claim = crud.get_by_id(claim_id) db_claim = await crud.get_by_id(claim_id)
if not db_claim: if not db_claim:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_claim(
- **claim_in**: The claim data to create - **claim_in**: The claim data to create
""" """
return crud.create(claim_in) return await crud.create(claim_in)
@router.put("/{ claim_id }", response_model=ClaimResponse) @router.put("/{ claim_id }", response_model=ClaimResponse)
async def update_claim( async def update_claim(
@ -87,13 +87,13 @@ async def update_claim(
- **claim_id**: The UUID of the claim to update - **claim_id**: The UUID of the claim to update
- **claim_in**: The updated claim data - **claim_in**: The updated claim data
""" """
db_claim = crud.get_by_id(claim_id) db_claim = await crud.get_by_id(claim_id)
if not db_claim: if not db_claim:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Claim with id { claim_id} not found" detail=f"Claim with id { claim_id} not found"
) )
return crud.update(claim_id, claim_in) return await crud.update(claim_id, claim_in)
@router.delete("/{ claim_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ claim_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_claim( async def delete_claim(
@ -105,11 +105,11 @@ async def delete_claim(
- **claim_id**: The UUID of the claim to delete - **claim_id**: The UUID of the claim to delete
""" """
db_claim = crud.get_by_id(claim_id) db_claim = await crud.get_by_id(claim_id)
if not db_claim: if not db_claim:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Claim with id { claim_id} not found" detail=f"Claim with id { claim_id} not found"
) )
crud.delete(claim_id) await crud.delete(claim_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
ClaimScrubResult API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.claim_scrub_result_service import ClaimScrubResultCRUD
from src.validation.claim_scrub_result_schemas import (
ClaimScrubResultCreate,
ClaimScrubResultUpdate,
ClaimScrubResultResponse,
ClaimScrubResultListResponse,
)
router = APIRouter(prefix="/claimscrubresults", tags=["ClaimScrubResult"])
def get_crud(db: Session = Depends(get_db)) -> ClaimScrubResultCRUD:
"""Dependency injection for ClaimScrubResultCRUD"""
return ClaimScrubResultCRUD(db)
@router.get("/", response_model=ClaimScrubResultListResponse)
async def list_claim_scrub_results(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: ClaimScrubResultCRUD = Depends(get_crud),
):
"""
List all claimscrubresults with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return ClaimScrubResultListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ claim_scrub_result_id }", response_model=ClaimScrubResultResponse)
async def get_claim_scrub_result(
claim_scrub_result_id: UUID,
crud: ClaimScrubResultCRUD = Depends(get_crud),
):
"""
Get a specific claimscrubresult by ID.
- **claim_scrub_result_id**: The UUID of the claimscrubresult
"""
db_claim_scrub_result = crud.get_by_id(claim_scrub_result_id)
if not db_claim_scrub_result:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimScrubResult with id { claim_scrub_result_id} not found"
)
return db_claim_scrub_result
@router.post("/", response_model=ClaimScrubResultResponse, status_code=status.HTTP_201_CREATED)
async def create_claim_scrub_result(
claim_scrub_result_in: ClaimScrubResultCreate,
crud: ClaimScrubResultCRUD = Depends(get_crud),
):
"""
Create a new claimscrubresult.
- **claim_scrub_result_in**: The claimscrubresult data to create
"""
return crud.create(claim_scrub_result_in)
@router.put("/{ claim_scrub_result_id }", response_model=ClaimScrubResultResponse)
async def update_claim_scrub_result(
claim_scrub_result_id: UUID,
claim_scrub_result_in: ClaimScrubResultUpdate,
crud: ClaimScrubResultCRUD = Depends(get_crud),
):
"""
Update an existing claimscrubresult.
- **claim_scrub_result_id**: The UUID of the claimscrubresult to update
- **claim_scrub_result_in**: The updated claimscrubresult data
"""
db_claim_scrub_result = crud.get_by_id(claim_scrub_result_id)
if not db_claim_scrub_result:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimScrubResult with id { claim_scrub_result_id} not found"
)
return crud.update(claim_scrub_result_id, claim_scrub_result_in)
@router.delete("/{ claim_scrub_result_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_claim_scrub_result(
claim_scrub_result_id: UUID,
crud: ClaimScrubResultCRUD = Depends(get_crud),
):
"""
Delete a claimscrubresult.
- **claim_scrub_result_id**: The UUID of the claimscrubresult to delete
"""
db_claim_scrub_result = crud.get_by_id(claim_scrub_result_id)
if not db_claim_scrub_result:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimScrubResult with id { claim_scrub_result_id} not found"
)
crud.delete(claim_scrub_result_id)
return None

View File

@ -35,7 +35,7 @@ async def list_claim_scrub_results(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return ClaimScrubResultListResponse( return ClaimScrubResultListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_claim_scrub_result(
- **claim_scrub_result_id**: The UUID of the claimscrubresult - **claim_scrub_result_id**: The UUID of the claimscrubresult
""" """
db_claim_scrub_result = crud.get_by_id(claim_scrub_result_id) db_claim_scrub_result = await crud.get_by_id(claim_scrub_result_id)
if not db_claim_scrub_result: if not db_claim_scrub_result:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_claim_scrub_result(
- **claim_scrub_result_in**: The claimscrubresult data to create - **claim_scrub_result_in**: The claimscrubresult data to create
""" """
return crud.create(claim_scrub_result_in) return await crud.create(claim_scrub_result_in)
@router.put("/{ claim_scrub_result_id }", response_model=ClaimScrubResultResponse) @router.put("/{ claim_scrub_result_id }", response_model=ClaimScrubResultResponse)
async def update_claim_scrub_result( async def update_claim_scrub_result(
@ -87,13 +87,13 @@ async def update_claim_scrub_result(
- **claim_scrub_result_id**: The UUID of the claimscrubresult to update - **claim_scrub_result_id**: The UUID of the claimscrubresult to update
- **claim_scrub_result_in**: The updated claimscrubresult data - **claim_scrub_result_in**: The updated claimscrubresult data
""" """
db_claim_scrub_result = crud.get_by_id(claim_scrub_result_id) db_claim_scrub_result = await crud.get_by_id(claim_scrub_result_id)
if not db_claim_scrub_result: if not db_claim_scrub_result:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimScrubResult with id { claim_scrub_result_id} not found" detail=f"ClaimScrubResult with id { claim_scrub_result_id} not found"
) )
return crud.update(claim_scrub_result_id, claim_scrub_result_in) return await crud.update(claim_scrub_result_id, claim_scrub_result_in)
@router.delete("/{ claim_scrub_result_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ claim_scrub_result_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_claim_scrub_result( async def delete_claim_scrub_result(
@ -105,11 +105,11 @@ async def delete_claim_scrub_result(
- **claim_scrub_result_id**: The UUID of the claimscrubresult to delete - **claim_scrub_result_id**: The UUID of the claimscrubresult to delete
""" """
db_claim_scrub_result = crud.get_by_id(claim_scrub_result_id) db_claim_scrub_result = await crud.get_by_id(claim_scrub_result_id)
if not db_claim_scrub_result: if not db_claim_scrub_result:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimScrubResult with id { claim_scrub_result_id} not found" detail=f"ClaimScrubResult with id { claim_scrub_result_id} not found"
) )
crud.delete(claim_scrub_result_id) await crud.delete(claim_scrub_result_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_clinical_entities(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return ClinicalEntityListResponse( return ClinicalEntityListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_clinical_entity(
- **clinical_entity_id**: The UUID of the clinicalentity - **clinical_entity_id**: The UUID of the clinicalentity
""" """
db_clinical_entity = crud.get_by_id(clinical_entity_id) db_clinical_entity = await crud.get_by_id(clinical_entity_id)
if not db_clinical_entity: if not db_clinical_entity:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_clinical_entity(
- **clinical_entity_in**: The clinicalentity data to create - **clinical_entity_in**: The clinicalentity data to create
""" """
return crud.create(clinical_entity_in) return await crud.create(clinical_entity_in)
@router.put("/{ clinical_entity_id }", response_model=ClinicalEntityResponse) @router.put("/{ clinical_entity_id }", response_model=ClinicalEntityResponse)
async def update_clinical_entity( async def update_clinical_entity(
@ -87,13 +87,13 @@ async def update_clinical_entity(
- **clinical_entity_id**: The UUID of the clinicalentity to update - **clinical_entity_id**: The UUID of the clinicalentity to update
- **clinical_entity_in**: The updated clinicalentity data - **clinical_entity_in**: The updated clinicalentity data
""" """
db_clinical_entity = crud.get_by_id(clinical_entity_id) db_clinical_entity = await crud.get_by_id(clinical_entity_id)
if not db_clinical_entity: if not db_clinical_entity:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClinicalEntity with id { clinical_entity_id} not found" detail=f"ClinicalEntity with id { clinical_entity_id} not found"
) )
return crud.update(clinical_entity_id, clinical_entity_in) return await crud.update(clinical_entity_id, clinical_entity_in)
@router.delete("/{ clinical_entity_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ clinical_entity_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_clinical_entity( async def delete_clinical_entity(
@ -105,11 +105,11 @@ async def delete_clinical_entity(
- **clinical_entity_id**: The UUID of the clinicalentity to delete - **clinical_entity_id**: The UUID of the clinicalentity to delete
""" """
db_clinical_entity = crud.get_by_id(clinical_entity_id) db_clinical_entity = await crud.get_by_id(clinical_entity_id)
if not db_clinical_entity: if not db_clinical_entity:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClinicalEntity with id { clinical_entity_id} not found" detail=f"ClinicalEntity with id { clinical_entity_id} not found"
) )
crud.delete(clinical_entity_id) await crud.delete(clinical_entity_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
Claim API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.claim_service import ClaimCRUD
from src.validation.claim_schemas import (
ClaimCreate,
ClaimUpdate,
ClaimResponse,
ClaimListResponse,
)
router = APIRouter(prefix="/claims", tags=["Claim"])
def get_crud(db: Session = Depends(get_db)) -> ClaimCRUD:
"""Dependency injection for ClaimCRUD"""
return ClaimCRUD(db)
@router.get("/", response_model=ClaimListResponse)
async def list_claims(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: ClaimCRUD = Depends(get_crud),
):
"""
List all claims with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return ClaimListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ claim_id }", response_model=ClaimResponse)
async def get_claim(
claim_id: UUID,
crud: ClaimCRUD = Depends(get_crud),
):
"""
Get a specific claim by ID.
- **claim_id**: The UUID of the claim
"""
db_claim = crud.get_by_id(claim_id)
if not db_claim:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Claim with id { claim_id} not found"
)
return db_claim
@router.post("/", response_model=ClaimResponse, status_code=status.HTTP_201_CREATED)
async def create_claim(
claim_in: ClaimCreate,
crud: ClaimCRUD = Depends(get_crud),
):
"""
Create a new claim.
- **claim_in**: The claim data to create
"""
return crud.create(claim_in)
@router.put("/{ claim_id }", response_model=ClaimResponse)
async def update_claim(
claim_id: UUID,
claim_in: ClaimUpdate,
crud: ClaimCRUD = Depends(get_crud),
):
"""
Update an existing claim.
- **claim_id**: The UUID of the claim to update
- **claim_in**: The updated claim data
"""
db_claim = crud.get_by_id(claim_id)
if not db_claim:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Claim with id { claim_id} not found"
)
return crud.update(claim_id, claim_in)
@router.delete("/{ claim_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_claim(
claim_id: UUID,
crud: ClaimCRUD = Depends(get_crud),
):
"""
Delete a claim.
- **claim_id**: The UUID of the claim to delete
"""
db_claim = crud.get_by_id(claim_id)
if not db_claim:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Claim with id { claim_id} not found"
)
crud.delete(claim_id)
return None

View File

@ -35,7 +35,7 @@ async def list_confidence_scores(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return ConfidenceScoreListResponse( return ConfidenceScoreListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_confidence_score(
- **confidence_score_id**: The UUID of the confidencescore - **confidence_score_id**: The UUID of the confidencescore
""" """
db_confidence_score = crud.get_by_id(confidence_score_id) db_confidence_score = await crud.get_by_id(confidence_score_id)
if not db_confidence_score: if not db_confidence_score:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_confidence_score(
- **confidence_score_in**: The confidencescore data to create - **confidence_score_in**: The confidencescore data to create
""" """
return crud.create(confidence_score_in) return await crud.create(confidence_score_in)
@router.put("/{ confidence_score_id }", response_model=ConfidenceScoreResponse) @router.put("/{ confidence_score_id }", response_model=ConfidenceScoreResponse)
async def update_confidence_score( async def update_confidence_score(
@ -87,13 +87,13 @@ async def update_confidence_score(
- **confidence_score_id**: The UUID of the confidencescore to update - **confidence_score_id**: The UUID of the confidencescore to update
- **confidence_score_in**: The updated confidencescore data - **confidence_score_in**: The updated confidencescore data
""" """
db_confidence_score = crud.get_by_id(confidence_score_id) db_confidence_score = await crud.get_by_id(confidence_score_id)
if not db_confidence_score: if not db_confidence_score:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ConfidenceScore with id { confidence_score_id} not found" detail=f"ConfidenceScore with id { confidence_score_id} not found"
) )
return crud.update(confidence_score_id, confidence_score_in) return await crud.update(confidence_score_id, confidence_score_in)
@router.delete("/{ confidence_score_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ confidence_score_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_confidence_score( async def delete_confidence_score(
@ -105,11 +105,11 @@ async def delete_confidence_score(
- **confidence_score_id**: The UUID of the confidencescore to delete - **confidence_score_id**: The UUID of the confidencescore to delete
""" """
db_confidence_score = crud.get_by_id(confidence_score_id) db_confidence_score = await crud.get_by_id(confidence_score_id)
if not db_confidence_score: if not db_confidence_score:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ConfidenceScore with id { confidence_score_id} not found" detail=f"ConfidenceScore with id { confidence_score_id} not found"
) )
crud.delete(confidence_score_id) await crud.delete(confidence_score_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_cpt_codes(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return CPTCodeListResponse( return CPTCodeListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_cpt_code(
- **cpt_code_id**: The UUID of the cptcode - **cpt_code_id**: The UUID of the cptcode
""" """
db_cpt_code = crud.get_by_id(cpt_code_id) db_cpt_code = await crud.get_by_id(cpt_code_id)
if not db_cpt_code: if not db_cpt_code:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_cpt_code(
- **cpt_code_in**: The cptcode data to create - **cpt_code_in**: The cptcode data to create
""" """
return crud.create(cpt_code_in) return await crud.create(cpt_code_in)
@router.put("/{ cpt_code_id }", response_model=CPTCodeResponse) @router.put("/{ cpt_code_id }", response_model=CPTCodeResponse)
async def update_cpt_code( async def update_cpt_code(
@ -87,13 +87,13 @@ async def update_cpt_code(
- **cpt_code_id**: The UUID of the cptcode to update - **cpt_code_id**: The UUID of the cptcode to update
- **cpt_code_in**: The updated cptcode data - **cpt_code_in**: The updated cptcode data
""" """
db_cpt_code = crud.get_by_id(cpt_code_id) db_cpt_code = await crud.get_by_id(cpt_code_id)
if not db_cpt_code: if not db_cpt_code:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"CPTCode with id { cpt_code_id} not found" detail=f"CPTCode with id { cpt_code_id} not found"
) )
return crud.update(cpt_code_id, cpt_code_in) return await crud.update(cpt_code_id, cpt_code_in)
@router.delete("/{ cpt_code_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ cpt_code_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_cpt_code( async def delete_cpt_code(
@ -105,11 +105,11 @@ async def delete_cpt_code(
- **cpt_code_id**: The UUID of the cptcode to delete - **cpt_code_id**: The UUID of the cptcode to delete
""" """
db_cpt_code = crud.get_by_id(cpt_code_id) db_cpt_code = await crud.get_by_id(cpt_code_id)
if not db_cpt_code: if not db_cpt_code:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"CPTCode with id { cpt_code_id} not found" detail=f"CPTCode with id { cpt_code_id} not found"
) )
crud.delete(cpt_code_id) await crud.delete(cpt_code_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_cpt_modifiers(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return CPTModifierListResponse( return CPTModifierListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_cpt_modifier(
- **cpt_modifier_id**: The UUID of the cptmodifier - **cpt_modifier_id**: The UUID of the cptmodifier
""" """
db_cpt_modifier = crud.get_by_id(cpt_modifier_id) db_cpt_modifier = await crud.get_by_id(cpt_modifier_id)
if not db_cpt_modifier: if not db_cpt_modifier:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_cpt_modifier(
- **cpt_modifier_in**: The cptmodifier data to create - **cpt_modifier_in**: The cptmodifier data to create
""" """
return crud.create(cpt_modifier_in) return await crud.create(cpt_modifier_in)
@router.put("/{ cpt_modifier_id }", response_model=CPTModifierResponse) @router.put("/{ cpt_modifier_id }", response_model=CPTModifierResponse)
async def update_cpt_modifier( async def update_cpt_modifier(
@ -87,13 +87,13 @@ async def update_cpt_modifier(
- **cpt_modifier_id**: The UUID of the cptmodifier to update - **cpt_modifier_id**: The UUID of the cptmodifier to update
- **cpt_modifier_in**: The updated cptmodifier data - **cpt_modifier_in**: The updated cptmodifier data
""" """
db_cpt_modifier = crud.get_by_id(cpt_modifier_id) db_cpt_modifier = await crud.get_by_id(cpt_modifier_id)
if not db_cpt_modifier: if not db_cpt_modifier:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"CPTModifier with id { cpt_modifier_id} not found" detail=f"CPTModifier with id { cpt_modifier_id} not found"
) )
return crud.update(cpt_modifier_id, cpt_modifier_in) return await crud.update(cpt_modifier_id, cpt_modifier_in)
@router.delete("/{ cpt_modifier_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ cpt_modifier_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_cpt_modifier( async def delete_cpt_modifier(
@ -105,11 +105,11 @@ async def delete_cpt_modifier(
- **cpt_modifier_id**: The UUID of the cptmodifier to delete - **cpt_modifier_id**: The UUID of the cptmodifier to delete
""" """
db_cpt_modifier = crud.get_by_id(cpt_modifier_id) db_cpt_modifier = await crud.get_by_id(cpt_modifier_id)
if not db_cpt_modifier: if not db_cpt_modifier:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"CPTModifier with id { cpt_modifier_id} not found" detail=f"CPTModifier with id { cpt_modifier_id} not found"
) )
crud.delete(cpt_modifier_id) await crud.delete(cpt_modifier_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
DenialPattern API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.denial_pattern_service import DenialPatternCRUD
from src.validation.denial_pattern_schemas import (
DenialPatternCreate,
DenialPatternUpdate,
DenialPatternResponse,
DenialPatternListResponse,
)
router = APIRouter(prefix="/denialpatterns", tags=["DenialPattern"])
def get_crud(db: Session = Depends(get_db)) -> DenialPatternCRUD:
"""Dependency injection for DenialPatternCRUD"""
return DenialPatternCRUD(db)
@router.get("/", response_model=DenialPatternListResponse)
async def list_denial_patterns(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: DenialPatternCRUD = Depends(get_crud),
):
"""
List all denialpatterns with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return DenialPatternListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ denial_pattern_id }", response_model=DenialPatternResponse)
async def get_denial_pattern(
denial_pattern_id: UUID,
crud: DenialPatternCRUD = Depends(get_crud),
):
"""
Get a specific denialpattern by ID.
- **denial_pattern_id**: The UUID of the denialpattern
"""
db_denial_pattern = crud.get_by_id(denial_pattern_id)
if not db_denial_pattern:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"DenialPattern with id { denial_pattern_id} not found"
)
return db_denial_pattern
@router.post("/", response_model=DenialPatternResponse, status_code=status.HTTP_201_CREATED)
async def create_denial_pattern(
denial_pattern_in: DenialPatternCreate,
crud: DenialPatternCRUD = Depends(get_crud),
):
"""
Create a new denialpattern.
- **denial_pattern_in**: The denialpattern data to create
"""
return crud.create(denial_pattern_in)
@router.put("/{ denial_pattern_id }", response_model=DenialPatternResponse)
async def update_denial_pattern(
denial_pattern_id: UUID,
denial_pattern_in: DenialPatternUpdate,
crud: DenialPatternCRUD = Depends(get_crud),
):
"""
Update an existing denialpattern.
- **denial_pattern_id**: The UUID of the denialpattern to update
- **denial_pattern_in**: The updated denialpattern data
"""
db_denial_pattern = crud.get_by_id(denial_pattern_id)
if not db_denial_pattern:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"DenialPattern with id { denial_pattern_id} not found"
)
return crud.update(denial_pattern_id, denial_pattern_in)
@router.delete("/{ denial_pattern_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_denial_pattern(
denial_pattern_id: UUID,
crud: DenialPatternCRUD = Depends(get_crud),
):
"""
Delete a denialpattern.
- **denial_pattern_id**: The UUID of the denialpattern to delete
"""
db_denial_pattern = crud.get_by_id(denial_pattern_id)
if not db_denial_pattern:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"DenialPattern with id { denial_pattern_id} not found"
)
crud.delete(denial_pattern_id)
return None

View File

@ -35,7 +35,7 @@ async def list_denial_patterns(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return DenialPatternListResponse( return DenialPatternListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_denial_pattern(
- **denial_pattern_id**: The UUID of the denialpattern - **denial_pattern_id**: The UUID of the denialpattern
""" """
db_denial_pattern = crud.get_by_id(denial_pattern_id) db_denial_pattern = await crud.get_by_id(denial_pattern_id)
if not db_denial_pattern: if not db_denial_pattern:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_denial_pattern(
- **denial_pattern_in**: The denialpattern data to create - **denial_pattern_in**: The denialpattern data to create
""" """
return crud.create(denial_pattern_in) return await crud.create(denial_pattern_in)
@router.put("/{ denial_pattern_id }", response_model=DenialPatternResponse) @router.put("/{ denial_pattern_id }", response_model=DenialPatternResponse)
async def update_denial_pattern( async def update_denial_pattern(
@ -87,13 +87,13 @@ async def update_denial_pattern(
- **denial_pattern_id**: The UUID of the denialpattern to update - **denial_pattern_id**: The UUID of the denialpattern to update
- **denial_pattern_in**: The updated denialpattern data - **denial_pattern_in**: The updated denialpattern data
""" """
db_denial_pattern = crud.get_by_id(denial_pattern_id) db_denial_pattern = await crud.get_by_id(denial_pattern_id)
if not db_denial_pattern: if not db_denial_pattern:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"DenialPattern with id { denial_pattern_id} not found" detail=f"DenialPattern with id { denial_pattern_id} not found"
) )
return crud.update(denial_pattern_id, denial_pattern_in) return await crud.update(denial_pattern_id, denial_pattern_in)
@router.delete("/{ denial_pattern_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ denial_pattern_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_denial_pattern( async def delete_denial_pattern(
@ -105,11 +105,11 @@ async def delete_denial_pattern(
- **denial_pattern_id**: The UUID of the denialpattern to delete - **denial_pattern_id**: The UUID of the denialpattern to delete
""" """
db_denial_pattern = crud.get_by_id(denial_pattern_id) db_denial_pattern = await crud.get_by_id(denial_pattern_id)
if not db_denial_pattern: if not db_denial_pattern:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"DenialPattern with id { denial_pattern_id} not found" detail=f"DenialPattern with id { denial_pattern_id} not found"
) )
crud.delete(denial_pattern_id) await crud.delete(denial_pattern_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
EMRIntegration API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.emr_integration_service import EMRIntegrationCRUD
from src.validation.emr_integration_schemas import (
EMRIntegrationCreate,
EMRIntegrationUpdate,
EMRIntegrationResponse,
EMRIntegrationListResponse,
)
router = APIRouter(prefix="/emrintegrations", tags=["EMRIntegration"])
def get_crud(db: Session = Depends(get_db)) -> EMRIntegrationCRUD:
"""Dependency injection for EMRIntegrationCRUD"""
return EMRIntegrationCRUD(db)
@router.get("/", response_model=EMRIntegrationListResponse)
async def list_emr_integrations(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: EMRIntegrationCRUD = Depends(get_crud),
):
"""
List all emrintegrations with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return EMRIntegrationListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ emr_integration_id }", response_model=EMRIntegrationResponse)
async def get_emr_integration(
emr_integration_id: UUID,
crud: EMRIntegrationCRUD = Depends(get_crud),
):
"""
Get a specific emrintegration by ID.
- **emr_integration_id**: The UUID of the emrintegration
"""
db_emr_integration = crud.get_by_id(emr_integration_id)
if not db_emr_integration:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"EMRIntegration with id { emr_integration_id} not found"
)
return db_emr_integration
@router.post("/", response_model=EMRIntegrationResponse, status_code=status.HTTP_201_CREATED)
async def create_emr_integration(
emr_integration_in: EMRIntegrationCreate,
crud: EMRIntegrationCRUD = Depends(get_crud),
):
"""
Create a new emrintegration.
- **emr_integration_in**: The emrintegration data to create
"""
return crud.create(emr_integration_in)
@router.put("/{ emr_integration_id }", response_model=EMRIntegrationResponse)
async def update_emr_integration(
emr_integration_id: UUID,
emr_integration_in: EMRIntegrationUpdate,
crud: EMRIntegrationCRUD = Depends(get_crud),
):
"""
Update an existing emrintegration.
- **emr_integration_id**: The UUID of the emrintegration to update
- **emr_integration_in**: The updated emrintegration data
"""
db_emr_integration = crud.get_by_id(emr_integration_id)
if not db_emr_integration:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"EMRIntegration with id { emr_integration_id} not found"
)
return crud.update(emr_integration_id, emr_integration_in)
@router.delete("/{ emr_integration_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_emr_integration(
emr_integration_id: UUID,
crud: EMRIntegrationCRUD = Depends(get_crud),
):
"""
Delete a emrintegration.
- **emr_integration_id**: The UUID of the emrintegration to delete
"""
db_emr_integration = crud.get_by_id(emr_integration_id)
if not db_emr_integration:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"EMRIntegration with id { emr_integration_id} not found"
)
crud.delete(emr_integration_id)
return None

View File

@ -35,7 +35,7 @@ async def list_emr_integrations(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return EMRIntegrationListResponse( return EMRIntegrationListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_emr_integration(
- **emr_integration_id**: The UUID of the emrintegration - **emr_integration_id**: The UUID of the emrintegration
""" """
db_emr_integration = crud.get_by_id(emr_integration_id) db_emr_integration = await crud.get_by_id(emr_integration_id)
if not db_emr_integration: if not db_emr_integration:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_emr_integration(
- **emr_integration_in**: The emrintegration data to create - **emr_integration_in**: The emrintegration data to create
""" """
return crud.create(emr_integration_in) return await crud.create(emr_integration_in)
@router.put("/{ emr_integration_id }", response_model=EMRIntegrationResponse) @router.put("/{ emr_integration_id }", response_model=EMRIntegrationResponse)
async def update_emr_integration( async def update_emr_integration(
@ -87,13 +87,13 @@ async def update_emr_integration(
- **emr_integration_id**: The UUID of the emrintegration to update - **emr_integration_id**: The UUID of the emrintegration to update
- **emr_integration_in**: The updated emrintegration data - **emr_integration_in**: The updated emrintegration data
""" """
db_emr_integration = crud.get_by_id(emr_integration_id) db_emr_integration = await crud.get_by_id(emr_integration_id)
if not db_emr_integration: if not db_emr_integration:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"EMRIntegration with id { emr_integration_id} not found" detail=f"EMRIntegration with id { emr_integration_id} not found"
) )
return crud.update(emr_integration_id, emr_integration_in) return await crud.update(emr_integration_id, emr_integration_in)
@router.delete("/{ emr_integration_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ emr_integration_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_emr_integration( async def delete_emr_integration(
@ -105,11 +105,11 @@ async def delete_emr_integration(
- **emr_integration_id**: The UUID of the emrintegration to delete - **emr_integration_id**: The UUID of the emrintegration to delete
""" """
db_emr_integration = crud.get_by_id(emr_integration_id) db_emr_integration = await crud.get_by_id(emr_integration_id)
if not db_emr_integration: if not db_emr_integration:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"EMRIntegration with id { emr_integration_id} not found" detail=f"EMRIntegration with id { emr_integration_id} not found"
) )
crud.delete(emr_integration_id) await crud.delete(emr_integration_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
ClinicalEntity API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.clinical_entity_service import ClinicalEntityCRUD
from src.validation.clinical_entity_schemas import (
ClinicalEntityCreate,
ClinicalEntityUpdate,
ClinicalEntityResponse,
ClinicalEntityListResponse,
)
router = APIRouter(prefix="/clinicalentities", tags=["ClinicalEntity"])
def get_crud(db: Session = Depends(get_db)) -> ClinicalEntityCRUD:
"""Dependency injection for ClinicalEntityCRUD"""
return ClinicalEntityCRUD(db)
@router.get("/", response_model=ClinicalEntityListResponse)
async def list_clinical_entities(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: ClinicalEntityCRUD = Depends(get_crud),
):
"""
List all clinicalentities with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return ClinicalEntityListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ clinical_entity_id }", response_model=ClinicalEntityResponse)
async def get_clinical_entity(
clinical_entity_id: UUID,
crud: ClinicalEntityCRUD = Depends(get_crud),
):
"""
Get a specific clinicalentity by ID.
- **clinical_entity_id**: The UUID of the clinicalentity
"""
db_clinical_entity = crud.get_by_id(clinical_entity_id)
if not db_clinical_entity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClinicalEntity with id { clinical_entity_id} not found"
)
return db_clinical_entity
@router.post("/", response_model=ClinicalEntityResponse, status_code=status.HTTP_201_CREATED)
async def create_clinical_entity(
clinical_entity_in: ClinicalEntityCreate,
crud: ClinicalEntityCRUD = Depends(get_crud),
):
"""
Create a new clinicalentity.
- **clinical_entity_in**: The clinicalentity data to create
"""
return crud.create(clinical_entity_in)
@router.put("/{ clinical_entity_id }", response_model=ClinicalEntityResponse)
async def update_clinical_entity(
clinical_entity_id: UUID,
clinical_entity_in: ClinicalEntityUpdate,
crud: ClinicalEntityCRUD = Depends(get_crud),
):
"""
Update an existing clinicalentity.
- **clinical_entity_id**: The UUID of the clinicalentity to update
- **clinical_entity_in**: The updated clinicalentity data
"""
db_clinical_entity = crud.get_by_id(clinical_entity_id)
if not db_clinical_entity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClinicalEntity with id { clinical_entity_id} not found"
)
return crud.update(clinical_entity_id, clinical_entity_in)
@router.delete("/{ clinical_entity_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_clinical_entity(
clinical_entity_id: UUID,
crud: ClinicalEntityCRUD = Depends(get_crud),
):
"""
Delete a clinicalentity.
- **clinical_entity_id**: The UUID of the clinicalentity to delete
"""
db_clinical_entity = crud.get_by_id(clinical_entity_id)
if not db_clinical_entity:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClinicalEntity with id { clinical_entity_id} not found"
)
crud.delete(clinical_entity_id)
return None

View File

@ -1,115 +0,0 @@
"""
ClaimReview API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.claim_review_service import ClaimReviewCRUD
from src.validation.claim_review_schemas import (
ClaimReviewCreate,
ClaimReviewUpdate,
ClaimReviewResponse,
ClaimReviewListResponse,
)
router = APIRouter(prefix="/claimreviews", tags=["ClaimReview"])
def get_crud(db: Session = Depends(get_db)) -> ClaimReviewCRUD:
"""Dependency injection for ClaimReviewCRUD"""
return ClaimReviewCRUD(db)
@router.get("/", response_model=ClaimReviewListResponse)
async def list_claim_reviews(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: ClaimReviewCRUD = Depends(get_crud),
):
"""
List all claimreviews with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return ClaimReviewListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ claim_review_id }", response_model=ClaimReviewResponse)
async def get_claim_review(
claim_review_id: UUID,
crud: ClaimReviewCRUD = Depends(get_crud),
):
"""
Get a specific claimreview by ID.
- **claim_review_id**: The UUID of the claimreview
"""
db_claim_review = crud.get_by_id(claim_review_id)
if not db_claim_review:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimReview with id { claim_review_id} not found"
)
return db_claim_review
@router.post("/", response_model=ClaimReviewResponse, status_code=status.HTTP_201_CREATED)
async def create_claim_review(
claim_review_in: ClaimReviewCreate,
crud: ClaimReviewCRUD = Depends(get_crud),
):
"""
Create a new claimreview.
- **claim_review_in**: The claimreview data to create
"""
return crud.create(claim_review_in)
@router.put("/{ claim_review_id }", response_model=ClaimReviewResponse)
async def update_claim_review(
claim_review_id: UUID,
claim_review_in: ClaimReviewUpdate,
crud: ClaimReviewCRUD = Depends(get_crud),
):
"""
Update an existing claimreview.
- **claim_review_id**: The UUID of the claimreview to update
- **claim_review_in**: The updated claimreview data
"""
db_claim_review = crud.get_by_id(claim_review_id)
if not db_claim_review:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimReview with id { claim_review_id} not found"
)
return crud.update(claim_review_id, claim_review_in)
@router.delete("/{ claim_review_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_claim_review(
claim_review_id: UUID,
crud: ClaimReviewCRUD = Depends(get_crud),
):
"""
Delete a claimreview.
- **claim_review_id**: The UUID of the claimreview to delete
"""
db_claim_review = crud.get_by_id(claim_review_id)
if not db_claim_review:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ClaimReview with id { claim_review_id} not found"
)
crud.delete(claim_review_id)
return None

View File

@ -35,7 +35,7 @@ async def list_icd10_codes(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return ICD10CodeListResponse( return ICD10CodeListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_icd10_code(
- **icd10_code_id**: The UUID of the icd10code - **icd10_code_id**: The UUID of the icd10code
""" """
db_icd10_code = crud.get_by_id(icd10_code_id) db_icd10_code = await crud.get_by_id(icd10_code_id)
if not db_icd10_code: if not db_icd10_code:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_icd10_code(
- **icd10_code_in**: The icd10code data to create - **icd10_code_in**: The icd10code data to create
""" """
return crud.create(icd10_code_in) return await crud.create(icd10_code_in)
@router.put("/{ icd10_code_id }", response_model=ICD10CodeResponse) @router.put("/{ icd10_code_id }", response_model=ICD10CodeResponse)
async def update_icd10_code( async def update_icd10_code(
@ -87,13 +87,13 @@ async def update_icd10_code(
- **icd10_code_id**: The UUID of the icd10code to update - **icd10_code_id**: The UUID of the icd10code to update
- **icd10_code_in**: The updated icd10code data - **icd10_code_in**: The updated icd10code data
""" """
db_icd10_code = crud.get_by_id(icd10_code_id) db_icd10_code = await crud.get_by_id(icd10_code_id)
if not db_icd10_code: if not db_icd10_code:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ICD10Code with id { icd10_code_id} not found" detail=f"ICD10Code with id { icd10_code_id} not found"
) )
return crud.update(icd10_code_id, icd10_code_in) return await crud.update(icd10_code_id, icd10_code_in)
@router.delete("/{ icd10_code_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ icd10_code_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_icd10_code( async def delete_icd10_code(
@ -105,11 +105,11 @@ async def delete_icd10_code(
- **icd10_code_id**: The UUID of the icd10code to delete - **icd10_code_id**: The UUID of the icd10code to delete
""" """
db_icd10_code = crud.get_by_id(icd10_code_id) db_icd10_code = await crud.get_by_id(icd10_code_id)
if not db_icd10_code: if not db_icd10_code:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ICD10Code with id { icd10_code_id} not found" detail=f"ICD10Code with id { icd10_code_id} not found"
) )
crud.delete(icd10_code_id) await crud.delete(icd10_code_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_lc_ds(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return LCDListResponse( return LCDListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_lcd(
- **lcd_id**: The UUID of the lcd - **lcd_id**: The UUID of the lcd
""" """
db_lcd = crud.get_by_id(lcd_id) db_lcd = await crud.get_by_id(lcd_id)
if not db_lcd: if not db_lcd:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_lcd(
- **lcd_in**: The lcd data to create - **lcd_in**: The lcd data to create
""" """
return crud.create(lcd_in) return await crud.create(lcd_in)
@router.put("/{ lcd_id }", response_model=LCDResponse) @router.put("/{ lcd_id }", response_model=LCDResponse)
async def update_lcd( async def update_lcd(
@ -87,13 +87,13 @@ async def update_lcd(
- **lcd_id**: The UUID of the lcd to update - **lcd_id**: The UUID of the lcd to update
- **lcd_in**: The updated lcd data - **lcd_in**: The updated lcd data
""" """
db_lcd = crud.get_by_id(lcd_id) db_lcd = await crud.get_by_id(lcd_id)
if not db_lcd: if not db_lcd:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"LCD with id { lcd_id} not found" detail=f"LCD with id { lcd_id} not found"
) )
return crud.update(lcd_id, lcd_in) return await crud.update(lcd_id, lcd_in)
@router.delete("/{ lcd_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ lcd_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_lcd( async def delete_lcd(
@ -105,11 +105,11 @@ async def delete_lcd(
- **lcd_id**: The UUID of the lcd to delete - **lcd_id**: The UUID of the lcd to delete
""" """
db_lcd = crud.get_by_id(lcd_id) db_lcd = await crud.get_by_id(lcd_id)
if not db_lcd: if not db_lcd:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"LCD with id { lcd_id} not found" detail=f"LCD with id { lcd_id} not found"
) )
crud.delete(lcd_id) await crud.delete(lcd_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_ncci_edits(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return NCCIEditListResponse( return NCCIEditListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_ncci_edit(
- **ncci_edit_id**: The UUID of the ncciedit - **ncci_edit_id**: The UUID of the ncciedit
""" """
db_ncci_edit = crud.get_by_id(ncci_edit_id) db_ncci_edit = await crud.get_by_id(ncci_edit_id)
if not db_ncci_edit: if not db_ncci_edit:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_ncci_edit(
- **ncci_edit_in**: The ncciedit data to create - **ncci_edit_in**: The ncciedit data to create
""" """
return crud.create(ncci_edit_in) return await crud.create(ncci_edit_in)
@router.put("/{ ncci_edit_id }", response_model=NCCIEditResponse) @router.put("/{ ncci_edit_id }", response_model=NCCIEditResponse)
async def update_ncci_edit( async def update_ncci_edit(
@ -87,13 +87,13 @@ async def update_ncci_edit(
- **ncci_edit_id**: The UUID of the ncciedit to update - **ncci_edit_id**: The UUID of the ncciedit to update
- **ncci_edit_in**: The updated ncciedit data - **ncci_edit_in**: The updated ncciedit data
""" """
db_ncci_edit = crud.get_by_id(ncci_edit_id) db_ncci_edit = await crud.get_by_id(ncci_edit_id)
if not db_ncci_edit: if not db_ncci_edit:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"NCCIEdit with id { ncci_edit_id} not found" detail=f"NCCIEdit with id { ncci_edit_id} not found"
) )
return crud.update(ncci_edit_id, ncci_edit_in) return await crud.update(ncci_edit_id, ncci_edit_in)
@router.delete("/{ ncci_edit_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ ncci_edit_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_ncci_edit( async def delete_ncci_edit(
@ -105,11 +105,11 @@ async def delete_ncci_edit(
- **ncci_edit_id**: The UUID of the ncciedit to delete - **ncci_edit_id**: The UUID of the ncciedit to delete
""" """
db_ncci_edit = crud.get_by_id(ncci_edit_id) db_ncci_edit = await crud.get_by_id(ncci_edit_id)
if not db_ncci_edit: if not db_ncci_edit:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"NCCIEdit with id { ncci_edit_id} not found" detail=f"NCCIEdit with id { ncci_edit_id} not found"
) )
crud.delete(ncci_edit_id) await crud.delete(ncci_edit_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_nc_ds(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return NCDListResponse( return NCDListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_ncd(
- **ncd_id**: The UUID of the ncd - **ncd_id**: The UUID of the ncd
""" """
db_ncd = crud.get_by_id(ncd_id) db_ncd = await crud.get_by_id(ncd_id)
if not db_ncd: if not db_ncd:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_ncd(
- **ncd_in**: The ncd data to create - **ncd_in**: The ncd data to create
""" """
return crud.create(ncd_in) return await crud.create(ncd_in)
@router.put("/{ ncd_id }", response_model=NCDResponse) @router.put("/{ ncd_id }", response_model=NCDResponse)
async def update_ncd( async def update_ncd(
@ -87,13 +87,13 @@ async def update_ncd(
- **ncd_id**: The UUID of the ncd to update - **ncd_id**: The UUID of the ncd to update
- **ncd_in**: The updated ncd data - **ncd_in**: The updated ncd data
""" """
db_ncd = crud.get_by_id(ncd_id) db_ncd = await crud.get_by_id(ncd_id)
if not db_ncd: if not db_ncd:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"NCD with id { ncd_id} not found" detail=f"NCD with id { ncd_id} not found"
) )
return crud.update(ncd_id, ncd_in) return await crud.update(ncd_id, ncd_in)
@router.delete("/{ ncd_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ ncd_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_ncd( async def delete_ncd(
@ -105,11 +105,11 @@ async def delete_ncd(
- **ncd_id**: The UUID of the ncd to delete - **ncd_id**: The UUID of the ncd to delete
""" """
db_ncd = crud.get_by_id(ncd_id) db_ncd = await crud.get_by_id(ncd_id)
if not db_ncd: if not db_ncd:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"NCD with id { ncd_id} not found" detail=f"NCD with id { ncd_id} not found"
) )
crud.delete(ncd_id) await crud.delete(ncd_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
Patient API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.patient_service import PatientCRUD
from src.validation.patient_schemas import (
PatientCreate,
PatientUpdate,
PatientResponse,
PatientListResponse,
)
router = APIRouter(prefix="/patients", tags=["Patient"])
def get_crud(db: Session = Depends(get_db)) -> PatientCRUD:
"""Dependency injection for PatientCRUD"""
return PatientCRUD(db)
@router.get("/", response_model=PatientListResponse)
async def list_patients(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: PatientCRUD = Depends(get_crud),
):
"""
List all patients with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return PatientListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ patient_id }", response_model=PatientResponse)
async def get_patient(
patient_id: UUID,
crud: PatientCRUD = Depends(get_crud),
):
"""
Get a specific patient by ID.
- **patient_id**: The UUID of the patient
"""
db_patient = crud.get_by_id(patient_id)
if not db_patient:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Patient with id { patient_id} not found"
)
return db_patient
@router.post("/", response_model=PatientResponse, status_code=status.HTTP_201_CREATED)
async def create_patient(
patient_in: PatientCreate,
crud: PatientCRUD = Depends(get_crud),
):
"""
Create a new patient.
- **patient_in**: The patient data to create
"""
return crud.create(patient_in)
@router.put("/{ patient_id }", response_model=PatientResponse)
async def update_patient(
patient_id: UUID,
patient_in: PatientUpdate,
crud: PatientCRUD = Depends(get_crud),
):
"""
Update an existing patient.
- **patient_id**: The UUID of the patient to update
- **patient_in**: The updated patient data
"""
db_patient = crud.get_by_id(patient_id)
if not db_patient:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Patient with id { patient_id} not found"
)
return crud.update(patient_id, patient_in)
@router.delete("/{ patient_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_patient(
patient_id: UUID,
crud: PatientCRUD = Depends(get_crud),
):
"""
Delete a patient.
- **patient_id**: The UUID of the patient to delete
"""
db_patient = crud.get_by_id(patient_id)
if not db_patient:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Patient with id { patient_id} not found"
)
crud.delete(patient_id)
return None

View File

@ -35,7 +35,7 @@ async def list_patients(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return PatientListResponse( return PatientListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_patient(
- **patient_id**: The UUID of the patient - **patient_id**: The UUID of the patient
""" """
db_patient = crud.get_by_id(patient_id) db_patient = await crud.get_by_id(patient_id)
if not db_patient: if not db_patient:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_patient(
- **patient_in**: The patient data to create - **patient_in**: The patient data to create
""" """
return crud.create(patient_in) return await crud.create(patient_in)
@router.put("/{ patient_id }", response_model=PatientResponse) @router.put("/{ patient_id }", response_model=PatientResponse)
async def update_patient( async def update_patient(
@ -87,13 +87,13 @@ async def update_patient(
- **patient_id**: The UUID of the patient to update - **patient_id**: The UUID of the patient to update
- **patient_in**: The updated patient data - **patient_in**: The updated patient data
""" """
db_patient = crud.get_by_id(patient_id) db_patient = await crud.get_by_id(patient_id)
if not db_patient: if not db_patient:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Patient with id { patient_id} not found" detail=f"Patient with id { patient_id} not found"
) )
return crud.update(patient_id, patient_in) return await crud.update(patient_id, patient_in)
@router.delete("/{ patient_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ patient_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_patient( async def delete_patient(
@ -105,11 +105,11 @@ async def delete_patient(
- **patient_id**: The UUID of the patient to delete - **patient_id**: The UUID of the patient to delete
""" """
db_patient = crud.get_by_id(patient_id) db_patient = await crud.get_by_id(patient_id)
if not db_patient: if not db_patient:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Patient with id { patient_id} not found" detail=f"Patient with id { patient_id} not found"
) )
crud.delete(patient_id) await crud.delete(patient_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_payers(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return PayerListResponse( return PayerListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_payer(
- **payer_id**: The UUID of the payer - **payer_id**: The UUID of the payer
""" """
db_payer = crud.get_by_id(payer_id) db_payer = await crud.get_by_id(payer_id)
if not db_payer: if not db_payer:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_payer(
- **payer_in**: The payer data to create - **payer_in**: The payer data to create
""" """
return crud.create(payer_in) return await crud.create(payer_in)
@router.put("/{ payer_id }", response_model=PayerResponse) @router.put("/{ payer_id }", response_model=PayerResponse)
async def update_payer( async def update_payer(
@ -87,13 +87,13 @@ async def update_payer(
- **payer_id**: The UUID of the payer to update - **payer_id**: The UUID of the payer to update
- **payer_in**: The updated payer data - **payer_in**: The updated payer data
""" """
db_payer = crud.get_by_id(payer_id) db_payer = await crud.get_by_id(payer_id)
if not db_payer: if not db_payer:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Payer with id { payer_id} not found" detail=f"Payer with id { payer_id} not found"
) )
return crud.update(payer_id, payer_in) return await crud.update(payer_id, payer_in)
@router.delete("/{ payer_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ payer_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_payer( async def delete_payer(
@ -105,11 +105,11 @@ async def delete_payer(
- **payer_id**: The UUID of the payer to delete - **payer_id**: The UUID of the payer to delete
""" """
db_payer = crud.get_by_id(payer_id) db_payer = await crud.get_by_id(payer_id)
if not db_payer: if not db_payer:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Payer with id { payer_id} not found" detail=f"Payer with id { payer_id} not found"
) )
crud.delete(payer_id) await crud.delete(payer_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_payer_rules(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return PayerRuleListResponse( return PayerRuleListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_payer_rule(
- **payer_rule_id**: The UUID of the payerrule - **payer_rule_id**: The UUID of the payerrule
""" """
db_payer_rule = crud.get_by_id(payer_rule_id) db_payer_rule = await crud.get_by_id(payer_rule_id)
if not db_payer_rule: if not db_payer_rule:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_payer_rule(
- **payer_rule_in**: The payerrule data to create - **payer_rule_in**: The payerrule data to create
""" """
return crud.create(payer_rule_in) return await crud.create(payer_rule_in)
@router.put("/{ payer_rule_id }", response_model=PayerRuleResponse) @router.put("/{ payer_rule_id }", response_model=PayerRuleResponse)
async def update_payer_rule( async def update_payer_rule(
@ -87,13 +87,13 @@ async def update_payer_rule(
- **payer_rule_id**: The UUID of the payerrule to update - **payer_rule_id**: The UUID of the payerrule to update
- **payer_rule_in**: The updated payerrule data - **payer_rule_in**: The updated payerrule data
""" """
db_payer_rule = crud.get_by_id(payer_rule_id) db_payer_rule = await crud.get_by_id(payer_rule_id)
if not db_payer_rule: if not db_payer_rule:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"PayerRule with id { payer_rule_id} not found" detail=f"PayerRule with id { payer_rule_id} not found"
) )
return crud.update(payer_rule_id, payer_rule_in) return await crud.update(payer_rule_id, payer_rule_in)
@router.delete("/{ payer_rule_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ payer_rule_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_payer_rule( async def delete_payer_rule(
@ -105,11 +105,11 @@ async def delete_payer_rule(
- **payer_rule_id**: The UUID of the payerrule to delete - **payer_rule_id**: The UUID of the payerrule to delete
""" """
db_payer_rule = crud.get_by_id(payer_rule_id) db_payer_rule = await crud.get_by_id(payer_rule_id)
if not db_payer_rule: if not db_payer_rule:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"PayerRule with id { payer_rule_id} not found" detail=f"PayerRule with id { payer_rule_id} not found"
) )
crud.delete(payer_rule_id) await crud.delete(payer_rule_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
PayerRule API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.payer_rule_service import PayerRuleCRUD
from src.validation.payer_rule_schemas import (
PayerRuleCreate,
PayerRuleUpdate,
PayerRuleResponse,
PayerRuleListResponse,
)
router = APIRouter(prefix="/payerrules", tags=["PayerRule"])
def get_crud(db: Session = Depends(get_db)) -> PayerRuleCRUD:
"""Dependency injection for PayerRuleCRUD"""
return PayerRuleCRUD(db)
@router.get("/", response_model=PayerRuleListResponse)
async def list_payer_rules(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: PayerRuleCRUD = Depends(get_crud),
):
"""
List all payerrules with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return PayerRuleListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ payer_rule_id }", response_model=PayerRuleResponse)
async def get_payer_rule(
payer_rule_id: UUID,
crud: PayerRuleCRUD = Depends(get_crud),
):
"""
Get a specific payerrule by ID.
- **payer_rule_id**: The UUID of the payerrule
"""
db_payer_rule = crud.get_by_id(payer_rule_id)
if not db_payer_rule:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"PayerRule with id { payer_rule_id} not found"
)
return db_payer_rule
@router.post("/", response_model=PayerRuleResponse, status_code=status.HTTP_201_CREATED)
async def create_payer_rule(
payer_rule_in: PayerRuleCreate,
crud: PayerRuleCRUD = Depends(get_crud),
):
"""
Create a new payerrule.
- **payer_rule_in**: The payerrule data to create
"""
return crud.create(payer_rule_in)
@router.put("/{ payer_rule_id }", response_model=PayerRuleResponse)
async def update_payer_rule(
payer_rule_id: UUID,
payer_rule_in: PayerRuleUpdate,
crud: PayerRuleCRUD = Depends(get_crud),
):
"""
Update an existing payerrule.
- **payer_rule_id**: The UUID of the payerrule to update
- **payer_rule_in**: The updated payerrule data
"""
db_payer_rule = crud.get_by_id(payer_rule_id)
if not db_payer_rule:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"PayerRule with id { payer_rule_id} not found"
)
return crud.update(payer_rule_id, payer_rule_in)
@router.delete("/{ payer_rule_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_payer_rule(
payer_rule_id: UUID,
crud: PayerRuleCRUD = Depends(get_crud),
):
"""
Delete a payerrule.
- **payer_rule_id**: The UUID of the payerrule to delete
"""
db_payer_rule = crud.get_by_id(payer_rule_id)
if not db_payer_rule:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"PayerRule with id { payer_rule_id} not found"
)
crud.delete(payer_rule_id)
return None

View File

@ -35,7 +35,7 @@ async def list_procedure_templates(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return ProcedureTemplateListResponse( return ProcedureTemplateListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_procedure_template(
- **procedure_template_id**: The UUID of the proceduretemplate - **procedure_template_id**: The UUID of the proceduretemplate
""" """
db_procedure_template = crud.get_by_id(procedure_template_id) db_procedure_template = await crud.get_by_id(procedure_template_id)
if not db_procedure_template: if not db_procedure_template:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_procedure_template(
- **procedure_template_in**: The proceduretemplate data to create - **procedure_template_in**: The proceduretemplate data to create
""" """
return crud.create(procedure_template_in) return await crud.create(procedure_template_in)
@router.put("/{ procedure_template_id }", response_model=ProcedureTemplateResponse) @router.put("/{ procedure_template_id }", response_model=ProcedureTemplateResponse)
async def update_procedure_template( async def update_procedure_template(
@ -87,13 +87,13 @@ async def update_procedure_template(
- **procedure_template_id**: The UUID of the proceduretemplate to update - **procedure_template_id**: The UUID of the proceduretemplate to update
- **procedure_template_in**: The updated proceduretemplate data - **procedure_template_in**: The updated proceduretemplate data
""" """
db_procedure_template = crud.get_by_id(procedure_template_id) db_procedure_template = await crud.get_by_id(procedure_template_id)
if not db_procedure_template: if not db_procedure_template:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ProcedureTemplate with id { procedure_template_id} not found" detail=f"ProcedureTemplate with id { procedure_template_id} not found"
) )
return crud.update(procedure_template_id, procedure_template_in) return await crud.update(procedure_template_id, procedure_template_in)
@router.delete("/{ procedure_template_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ procedure_template_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_procedure_template( async def delete_procedure_template(
@ -105,11 +105,11 @@ async def delete_procedure_template(
- **procedure_template_id**: The UUID of the proceduretemplate to delete - **procedure_template_id**: The UUID of the proceduretemplate to delete
""" """
db_procedure_template = crud.get_by_id(procedure_template_id) db_procedure_template = await crud.get_by_id(procedure_template_id)
if not db_procedure_template: if not db_procedure_template:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"ProcedureTemplate with id { procedure_template_id} not found" detail=f"ProcedureTemplate with id { procedure_template_id} not found"
) )
crud.delete(procedure_template_id) await crud.delete(procedure_template_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_rag_documents(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return RAGDocumentListResponse( return RAGDocumentListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_rag_document(
- **rag_document_id**: The UUID of the ragdocument - **rag_document_id**: The UUID of the ragdocument
""" """
db_rag_document = crud.get_by_id(rag_document_id) db_rag_document = await crud.get_by_id(rag_document_id)
if not db_rag_document: if not db_rag_document:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_rag_document(
- **rag_document_in**: The ragdocument data to create - **rag_document_in**: The ragdocument data to create
""" """
return crud.create(rag_document_in) return await crud.create(rag_document_in)
@router.put("/{ rag_document_id }", response_model=RAGDocumentResponse) @router.put("/{ rag_document_id }", response_model=RAGDocumentResponse)
async def update_rag_document( async def update_rag_document(
@ -87,13 +87,13 @@ async def update_rag_document(
- **rag_document_id**: The UUID of the ragdocument to update - **rag_document_id**: The UUID of the ragdocument to update
- **rag_document_in**: The updated ragdocument data - **rag_document_in**: The updated ragdocument data
""" """
db_rag_document = crud.get_by_id(rag_document_id) db_rag_document = await crud.get_by_id(rag_document_id)
if not db_rag_document: if not db_rag_document:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"RAGDocument with id { rag_document_id} not found" detail=f"RAGDocument with id { rag_document_id} not found"
) )
return crud.update(rag_document_id, rag_document_in) return await crud.update(rag_document_id, rag_document_in)
@router.delete("/{ rag_document_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ rag_document_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_rag_document( async def delete_rag_document(
@ -105,11 +105,11 @@ async def delete_rag_document(
- **rag_document_id**: The UUID of the ragdocument to delete - **rag_document_id**: The UUID of the ragdocument to delete
""" """
db_rag_document = crud.get_by_id(rag_document_id) db_rag_document = await crud.get_by_id(rag_document_id)
if not db_rag_document: if not db_rag_document:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"RAGDocument with id { rag_document_id} not found" detail=f"RAGDocument with id { rag_document_id} not found"
) )
crud.delete(rag_document_id) await crud.delete(rag_document_id)
return None return None

View File

@ -1,115 +0,0 @@
"""
Transcript API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.transcript_service import TranscriptCRUD
from src.validation.transcript_schemas import (
TranscriptCreate,
TranscriptUpdate,
TranscriptResponse,
TranscriptListResponse,
)
router = APIRouter(prefix="/transcripts", tags=["Transcript"])
def get_crud(db: Session = Depends(get_db)) -> TranscriptCRUD:
"""Dependency injection for TranscriptCRUD"""
return TranscriptCRUD(db)
@router.get("/", response_model=TranscriptListResponse)
async def list_transcripts(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: TranscriptCRUD = Depends(get_crud),
):
"""
List all transcripts with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return TranscriptListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ transcript_id }", response_model=TranscriptResponse)
async def get_transcript(
transcript_id: UUID,
crud: TranscriptCRUD = Depends(get_crud),
):
"""
Get a specific transcript by ID.
- **transcript_id**: The UUID of the transcript
"""
db_transcript = crud.get_by_id(transcript_id)
if not db_transcript:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Transcript with id { transcript_id} not found"
)
return db_transcript
@router.post("/", response_model=TranscriptResponse, status_code=status.HTTP_201_CREATED)
async def create_transcript(
transcript_in: TranscriptCreate,
crud: TranscriptCRUD = Depends(get_crud),
):
"""
Create a new transcript.
- **transcript_in**: The transcript data to create
"""
return crud.create(transcript_in)
@router.put("/{ transcript_id }", response_model=TranscriptResponse)
async def update_transcript(
transcript_id: UUID,
transcript_in: TranscriptUpdate,
crud: TranscriptCRUD = Depends(get_crud),
):
"""
Update an existing transcript.
- **transcript_id**: The UUID of the transcript to update
- **transcript_in**: The updated transcript data
"""
db_transcript = crud.get_by_id(transcript_id)
if not db_transcript:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Transcript with id { transcript_id} not found"
)
return crud.update(transcript_id, transcript_in)
@router.delete("/{ transcript_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_transcript(
transcript_id: UUID,
crud: TranscriptCRUD = Depends(get_crud),
):
"""
Delete a transcript.
- **transcript_id**: The UUID of the transcript to delete
"""
db_transcript = crud.get_by_id(transcript_id)
if not db_transcript:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Transcript with id { transcript_id} not found"
)
crud.delete(transcript_id)
return None

View File

@ -1,115 +0,0 @@
"""
ProcedureTemplate API Router
Enterprise-grade FastAPI router with full CRUD operations
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from uuid import UUID
from src.config.database import get_db
from src.services.procedure_template_service import ProcedureTemplateCRUD
from src.validation.procedure_template_schemas import (
ProcedureTemplateCreate,
ProcedureTemplateUpdate,
ProcedureTemplateResponse,
ProcedureTemplateListResponse,
)
router = APIRouter(prefix="/proceduretemplates", tags=["ProcedureTemplate"])
def get_crud(db: Session = Depends(get_db)) -> ProcedureTemplateCRUD:
"""Dependency injection for ProcedureTemplateCRUD"""
return ProcedureTemplateCRUD(db)
@router.get("/", response_model=ProcedureTemplateListResponse)
async def list_procedure_templates(
skip: int = Query(0, ge=0, description="Number of records to skip"),
limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
crud: ProcedureTemplateCRUD = Depends(get_crud),
):
"""
List all proceduretemplates with pagination and filtering.
- **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return
"""
items, total = crud.get_all(skip=skip, limit=limit)
return ProcedureTemplateListResponse(
items=items,
total=total,
skip=skip,
limit=limit,
has_more=skip + limit < total
)
@router.get("/{ procedure_template_id }", response_model=ProcedureTemplateResponse)
async def get_procedure_template(
procedure_template_id: UUID,
crud: ProcedureTemplateCRUD = Depends(get_crud),
):
"""
Get a specific proceduretemplate by ID.
- **procedure_template_id**: The UUID of the proceduretemplate
"""
db_procedure_template = crud.get_by_id(procedure_template_id)
if not db_procedure_template:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ProcedureTemplate with id { procedure_template_id} not found"
)
return db_procedure_template
@router.post("/", response_model=ProcedureTemplateResponse, status_code=status.HTTP_201_CREATED)
async def create_procedure_template(
procedure_template_in: ProcedureTemplateCreate,
crud: ProcedureTemplateCRUD = Depends(get_crud),
):
"""
Create a new proceduretemplate.
- **procedure_template_in**: The proceduretemplate data to create
"""
return crud.create(procedure_template_in)
@router.put("/{ procedure_template_id }", response_model=ProcedureTemplateResponse)
async def update_procedure_template(
procedure_template_id: UUID,
procedure_template_in: ProcedureTemplateUpdate,
crud: ProcedureTemplateCRUD = Depends(get_crud),
):
"""
Update an existing proceduretemplate.
- **procedure_template_id**: The UUID of the proceduretemplate to update
- **procedure_template_in**: The updated proceduretemplate data
"""
db_procedure_template = crud.get_by_id(procedure_template_id)
if not db_procedure_template:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ProcedureTemplate with id { procedure_template_id} not found"
)
return crud.update(procedure_template_id, procedure_template_in)
@router.delete("/{ procedure_template_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_procedure_template(
procedure_template_id: UUID,
crud: ProcedureTemplateCRUD = Depends(get_crud),
):
"""
Delete a proceduretemplate.
- **procedure_template_id**: The UUID of the proceduretemplate to delete
"""
db_procedure_template = crud.get_by_id(procedure_template_id)
if not db_procedure_template:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"ProcedureTemplate with id { procedure_template_id} not found"
)
crud.delete(procedure_template_id)
return None

View File

@ -35,7 +35,7 @@ async def list_transcripts(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return TranscriptListResponse( return TranscriptListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_transcript(
- **transcript_id**: The UUID of the transcript - **transcript_id**: The UUID of the transcript
""" """
db_transcript = crud.get_by_id(transcript_id) db_transcript = await crud.get_by_id(transcript_id)
if not db_transcript: if not db_transcript:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_transcript(
- **transcript_in**: The transcript data to create - **transcript_in**: The transcript data to create
""" """
return crud.create(transcript_in) return await crud.create(transcript_in)
@router.put("/{ transcript_id }", response_model=TranscriptResponse) @router.put("/{ transcript_id }", response_model=TranscriptResponse)
async def update_transcript( async def update_transcript(
@ -87,13 +87,13 @@ async def update_transcript(
- **transcript_id**: The UUID of the transcript to update - **transcript_id**: The UUID of the transcript to update
- **transcript_in**: The updated transcript data - **transcript_in**: The updated transcript data
""" """
db_transcript = crud.get_by_id(transcript_id) db_transcript = await crud.get_by_id(transcript_id)
if not db_transcript: if not db_transcript:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Transcript with id { transcript_id} not found" detail=f"Transcript with id { transcript_id} not found"
) )
return crud.update(transcript_id, transcript_in) return await crud.update(transcript_id, transcript_in)
@router.delete("/{ transcript_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ transcript_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_transcript( async def delete_transcript(
@ -105,11 +105,11 @@ async def delete_transcript(
- **transcript_id**: The UUID of the transcript to delete - **transcript_id**: The UUID of the transcript to delete
""" """
db_transcript = crud.get_by_id(transcript_id) db_transcript = await crud.get_by_id(transcript_id)
if not db_transcript: if not db_transcript:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"Transcript with id { transcript_id} not found" detail=f"Transcript with id { transcript_id} not found"
) )
crud.delete(transcript_id) await crud.delete(transcript_id)
return None return None

View File

@ -35,7 +35,7 @@ async def list_users(
- **skip**: Number of records to skip (for pagination) - **skip**: Number of records to skip (for pagination)
- **limit**: Maximum number of records to return - **limit**: Maximum number of records to return
""" """
items, total = crud.get_all(skip=skip, limit=limit) items, total = await crud.get_all(skip=skip, limit=limit)
return UserListResponse( return UserListResponse(
items=items, items=items,
@ -55,7 +55,7 @@ async def get_user(
- **user_id**: The UUID of the user - **user_id**: The UUID of the user
""" """
db_user = crud.get_by_id(user_id) db_user = await crud.get_by_id(user_id)
if not db_user: if not db_user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
@ -73,7 +73,7 @@ async def create_user(
- **user_in**: The user data to create - **user_in**: The user data to create
""" """
return crud.create(user_in) return await crud.create(user_in)
@router.put("/{ user_id }", response_model=UserResponse) @router.put("/{ user_id }", response_model=UserResponse)
async def update_user( async def update_user(
@ -87,13 +87,13 @@ async def update_user(
- **user_id**: The UUID of the user to update - **user_id**: The UUID of the user to update
- **user_in**: The updated user data - **user_in**: The updated user data
""" """
db_user = crud.get_by_id(user_id) db_user = await crud.get_by_id(user_id)
if not db_user: if not db_user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"User with id { user_id} not found" detail=f"User with id { user_id} not found"
) )
return crud.update(user_id, user_in) return await crud.update(user_id, user_in)
@router.delete("/{ user_id }", status_code=status.HTTP_204_NO_CONTENT) @router.delete("/{ user_id }", status_code=status.HTTP_204_NO_CONTENT)
async def delete_user( async def delete_user(
@ -105,11 +105,11 @@ async def delete_user(
- **user_id**: The UUID of the user to delete - **user_id**: The UUID of the user to delete
""" """
db_user = crud.get_by_id(user_id) db_user = await crud.get_by_id(user_id)
if not db_user: if not db_user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,
detail=f"User with id { user_id} not found" detail=f"User with id { user_id} not found"
) )
crud.delete(user_id) await crud.delete(user_id)
return None return None

View File

@ -1,7 +1,8 @@
from datetime import date, datetime
""" """
AudioRecording Service Layer AudioRecording Service Layer
Enterprise-grade service with business logic, validation, and error handling Enterprise-grade service with business logic, validation, and error handling
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas Architecture: Any Services/CRUD SQLAlchemy Models + Pydantic Schemas
""" """
from typing import List, Optional, Tuple, Dict, Any from typing import List, Optional, Tuple, Dict, Any
from uuid import UUID from uuid import UUID
@ -14,7 +15,7 @@ from src.validation.audio_recording_schemas import AudioRecordingCreate, AudioRe
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class AudioRecordingService: class AudioRecordingCRUD:
""" """
Service class for AudioRecording business logic. Service class for AudioRecording business logic.
@ -22,7 +23,7 @@ class AudioRecordingService:
and complex queries. and complex queries.
""" """
def __init__(self, db: Session): def __init__(self, db: Any):
"""Initialize service with database session.""" """Initialize service with database session."""
self.db = db self.db = db
@ -38,11 +39,11 @@ class AudioRecordingService:
Get all audiorecordings with pagination and filtering. Get all audiorecordings with pagination and filtering.
Args: Args:
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
filters: Dictionary of field filters filters: Any of field filters
order_by: Field to order by order_by: Any to order by
order_desc: Order descending if True order_desc: Any descending if True
Returns: Returns:
Tuple of (list of audiorecordings, total count) Tuple of (list of audiorecordings, total count)
@ -85,7 +86,7 @@ class AudioRecordingService:
Get a specific audiorecording by ID. Get a specific audiorecording by ID.
Args: Args:
audio_recording_id: The UUID of the audiorecording audio_recording_id: Any UUID of the audiorecording
Returns: Returns:
The audiorecording if found, None otherwise The audiorecording if found, None otherwise
@ -95,12 +96,12 @@ class AudioRecordingService:
AudioRecording.id == audio_recording_id AudioRecording.id == audio_recording_id
).first() ).first()
async def create(self, audio_recording_in: AudioRecordingCreate) -> AudioRecording: async def create(self, audio_recording_in: Any) -> Any:
""" """
Create a new audiorecording. Create a new audiorecording.
Args: Args:
audio_recording_in: The audiorecording data to create audio_recording_in: Any audiorecording data to create
Returns: Returns:
The created audiorecording The created audiorecording
@ -134,14 +135,14 @@ class AudioRecordingService:
async def update( async def update(
self, self,
audio_recording_id: UUID, audio_recording_id: UUID,
audio_recording_in: AudioRecordingUpdate audio_recording_in: Any
) -> Optional[AudioRecording]: ) -> Optional[AudioRecording]:
""" """
Update an existing audiorecording. Update an existing audiorecording.
Args: Args:
audio_recording_id: The UUID of the audiorecording to update audio_recording_id: Any UUID of the audiorecording to update
audio_recording_in: The updated audiorecording data audio_recording_in: Any updated audiorecording data
Returns: Returns:
The updated audiorecording if found, None otherwise The updated audiorecording if found, None otherwise
@ -177,7 +178,7 @@ class AudioRecordingService:
Delete a audiorecording. Delete a audiorecording.
Args: Args:
audio_recording_id: The UUID of the audiorecording to delete audio_recording_id: Any UUID of the audiorecording to delete
Returns: Returns:
True if deleted, False if not found True if deleted, False if not found
@ -204,9 +205,9 @@ class AudioRecordingService:
Get all audiorecordings for a specific User. Get all audiorecordings for a specific User.
Args: Args:
user_id: The UUID of the User user_id: Any UUID of the User
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of audiorecordings, total count) Tuple of (list of audiorecordings, total count)
@ -230,9 +231,9 @@ class AudioRecordingService:
Get all audiorecordings for a specific Patient. Get all audiorecordings for a specific Patient.
Args: Args:
patient_id: The UUID of the Patient patient_id: Any UUID of the Patient
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of audiorecordings, total count) Tuple of (list of audiorecordings, total count)
@ -256,9 +257,9 @@ class AudioRecordingService:
Get all audiorecordings for a specific ProcedureTemplate. Get all audiorecordings for a specific ProcedureTemplate.
Args: Args:
procedure_template_id: The UUID of the ProcedureTemplate procedure_template_id: Any UUID of the ProcedureTemplate
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of audiorecordings, total count) Tuple of (list of audiorecordings, total count)
@ -279,7 +280,7 @@ class AudioRecordingService:
@generated from DSL function @generated from DSL function
""" """
# Auto-generated non-validation rule implementation # Auto-generated non-validation rule implementation
# MultiSessionConsolidationRule: Consolidate multi-day recordings per encounter # MultiSessionConsolidationRule: Any multi-day recordings per encounter
if audio_recording.encounter_id is not None: if audio_recording.encounter_id is not None:
# Fetch related recordings with the same encounter_id # Fetch related recordings with the same encounter_id
related_recordings = await audio_recording_service.find_by_condition( related_recordings = await audio_recording_service.find_by_condition(
@ -315,7 +316,7 @@ class AudioRecordingService:
@generated from DSL function @generated from DSL function
""" """
# Auto-generated non-validation rule implementation # Auto-generated non-validation rule implementation
# EncryptionAtRestRule: AES-256 encryption for all PHI at rest # EncryptionAtRestRule: Any-256 encryption for all PHI at rest
if not audiorecording.is_encrypted: if not audiorecording.is_encrypted:
# Encrypt the audio file at the given file path # Encrypt the audio file at the given file path
encrypted_data = AES256.encrypt(audiorecording.file_path) encrypted_data = AES256.encrypt(audiorecording.file_path)
@ -330,7 +331,7 @@ class AudioRecordingService:
encryption_key = AES256.generate_key_id() encryption_key = AES256.generate_key_id()
audiorecording.encryption_key_id = encryption_key audiorecording.encryption_key_id = encryption_key
async def validateAudioFormat(self, audio_recording_in: AudioRecordingCreate, existing: Optional[AudioRecording] = None) -> Any: async def validateAudioFormat(self, audio_recording_in: Any, existing: Optional[AudioRecording] = None) -> Any:
""" """
Support AAC, MP3, WAV formats only Support AAC, MP3, WAV formats only
@generated from DSL function @generated from DSL function
@ -346,13 +347,13 @@ class AudioRecordingService:
tenant_id = audio_recording_data.get('tenant_id') tenant_id = audio_recording_data.get('tenant_id')
version = audio_recording_data.get('version') version = audio_recording_data.get('version')
context = {'user': {'tenant_id': tenant_id}} context = {'user': {'tenant_id': tenant_id}}
# AudioFormatValidationRule: Support AAC, MP3, WAV formats only # AudioFormatValidationRule: Any AAC, MP3, WAV formats only
allowed_formats = ['AAC', 'MP3', 'WAV'] allowed_formats = ['AAC', 'MP3', 'WAV']
upper_format = audio_recording.file_format.upper() upper_format = audio_recording.file_format.upper()
if upper_format not in allowed_formats: if upper_format not in allowed_formats:
raise ValueError("Invalid audio format. Only AAC, MP3, and WAV formats are supported.") raise ValueError("Invalid audio format. Only AAC, MP3, and WAV formats are supported.")
async def requiresPatientAssociation(self, audio_recording_in: AudioRecordingCreate, existing: Optional[AudioRecording] = None) -> Any: async def requiresPatientAssociation(self, audio_recording_in: Any, existing: Optional[AudioRecording] = None) -> Any:
""" """
Recording must associate with patient MRN/encounter Recording must associate with patient MRN/encounter
@generated from DSL function @generated from DSL function
@ -368,11 +369,11 @@ class AudioRecordingService:
tenant_id = audio_recording_data.get('tenant_id') tenant_id = audio_recording_data.get('tenant_id')
version = audio_recording_data.get('version') version = audio_recording_data.get('version')
context = {'user': {'tenant_id': tenant_id}} context = {'user': {'tenant_id': tenant_id}}
# PatientAssociationRule: Recording must associate with patient MRN/encounter # PatientAssociationRule: Any must associate with patient MRN/encounter
if recording.patient_id is None and recording.encounter_id is None: if recording.patient_id is None and recording.encounter_id is None:
raise ValueError("Recording must be associated with either a patient (patient_id) or an encounter (encounter_id)") raise ValueError("Recording must be associated with either a patient (patient_id) or an encounter (encounter_id)")
async def shouldAutoUpload(self, audio_recording_in: AudioRecordingCreate, existing: Optional[AudioRecording] = None) -> Any: async def shouldAutoUpload(self, audio_recording_in: Any, existing: Optional[AudioRecording] = None) -> Any:
""" """
Auto-upload recordings when network available Auto-upload recordings when network available
@generated from DSL function @generated from DSL function
@ -395,7 +396,7 @@ class AudioRecordingService:
# If network is available, proceed with auto-upload logic # If network is available, proceed with auto-upload logic
# The rule passes when network is available # The rule passes when network is available
async def allowMultipleRecordings(self, audio_recording_in: AudioRecordingCreate, existing: Optional[AudioRecording] = None) -> Any: async def allowMultipleRecordings(self, audio_recording_in: Any, existing: Optional[AudioRecording] = None) -> Any:
""" """
Support multiple recordings per encounter Support multiple recordings per encounter
@generated from DSL function @generated from DSL function
@ -411,7 +412,7 @@ class AudioRecordingService:
tenant_id = audio_recording_data.get('tenant_id') tenant_id = audio_recording_data.get('tenant_id')
version = audio_recording_data.get('version') version = audio_recording_data.get('version')
context = {'user': {'tenant_id': tenant_id}} context = {'user': {'tenant_id': tenant_id}}
# TODO: Business rule code not generated. Run tertiary analysis to generate code using Claude. # TODO: Any rule code not generated. Run tertiary analysis to generate code using Claude.
async def applyNoiseReduction(self) -> Any: async def applyNoiseReduction(self) -> Any:
""" """
@ -455,7 +456,7 @@ class AudioRecordingService:
await event_bus.emit("audio.uploaded", event_data) await event_bus.emit("audio.uploaded", event_data)
# =========== Custom Service Methods =========== # =========== Custom Service Methods ===========
async def find_one(self, _id: UUID) -> AudioRecording: async def find_one(self, _id: UUID) -> Any:
""" """
Get audio recording by ID Get audio recording by ID
GET /api/v1/audio/recordings/{id} GET /api/v1/audio/recordings/{id}
@ -463,7 +464,7 @@ class AudioRecordingService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method find_one not yet implemented") raise NotImplementedError(f"Method find_one not yet implemented")
async def upload_audio(self, _id: UUID, _in: Create) -> AudioRecording: async def upload_audio(self, _id: UUID, _in: Any) -> Any:
""" """
Upload audio file Upload audio file
POST /api/v1/audio/recordings/{id}/upload POST /api/v1/audio/recordings/{id}/upload
@ -471,7 +472,7 @@ class AudioRecordingService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method upload_audio not yet implemented") raise NotImplementedError(f"Method upload_audio not yet implemented")
async def download_audio(self, _id: UUID) -> AudioRecording: async def download_audio(self, _id: UUID) -> Any:
""" """
Download audio file Download audio file
GET /api/v1/audio/recordings/{id}/download GET /api/v1/audio/recordings/{id}/download
@ -479,7 +480,7 @@ class AudioRecordingService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method download_audio not yet implemented") raise NotImplementedError(f"Method download_audio not yet implemented")
async def uploadAudio(self, _id: UUID, file: Any) -> AudioRecording: async def uploadAudio(self, _id: UUID, file: Any) -> Any:
""" """
Upload audio file Upload audio file
custom custom
@ -549,7 +550,7 @@ class AudioRecordingService:
"message": "Audio file uploaded successfully" "message": "Audio file uploaded successfully"
} }
async def findByPatient(self, patient_id: Any) -> AudioRecording: async def findByPatient(self, patient_id: Any) -> Any:
""" """
Get recordings by patient Get recordings by patient
custom custom
@ -560,7 +561,7 @@ class AudioRecordingService:
recordings = result.scalars().all() recordings = result.scalars().all()
return list(recordings) return list(recordings)
async def encryptAudio(self, file_path: Any) -> AudioRecording: async def encryptAudio(self, file_path: Any) -> Any:
""" """
Encrypt audio file AES-256 Encrypt audio file AES-256
custom custom
@ -627,7 +628,7 @@ class AudioRecordingService:
return encrypted_file_path return encrypted_file_path
async def validateFormat(self, format: Any) -> AudioRecording: async def validateFormat(self, format: Any) -> Any:
""" """
Validate audio format Validate audio format
custom custom
@ -637,10 +638,10 @@ class AudioRecordingService:
Validate audio format against supported formats. Validate audio format against supported formats.
Args: Args:
format: Audio format string to validate format: Any format string to validate
Returns: Returns:
bool: True if format is valid, False otherwise bool: Any if format is valid, False otherwise
""" """
# Define supported audio formats # Define supported audio formats
supported_formats = { supported_formats = {
@ -654,7 +655,7 @@ class AudioRecordingService:
# Check if format is in supported formats # Check if format is in supported formats
return normalized_format in supported_formats return normalized_format in supported_formats
async def encrypt(self, file_path: Any, key_id: Any = None) -> AudioRecording: async def encrypt(self, file_path: Any, key_id: Any = None) -> Any:
""" """
Encrypt audio AES-256 Encrypt audio AES-256
custom custom
@ -721,7 +722,7 @@ class AudioRecordingService:
return encrypted_file_path return encrypted_file_path
async def decrypt(self, file_path: Any, key_id: Any) -> AudioRecording: async def decrypt(self, file_path: Any, key_id: Any) -> Any:
""" """
Decrypt audio file Decrypt audio file
custom custom
@ -804,7 +805,7 @@ class AudioRecordingService:
detail=f"Failed to decrypt audio file: {str(e)}" detail=f"Failed to decrypt audio file: {str(e)}"
) )
async def generateKey(self, ) -> AudioRecording: async def generateKey(self, ) -> Any:
""" """
Generate encryption key Generate encryption key
custom custom
@ -817,11 +818,11 @@ class AudioRecordingService:
key_id = f"key_{uuid.uuid4().hex[:16]}" key_id = f"key_{uuid.uuid4().hex[:16]}"
# Return the encryption key # Return the encryption key
# Note: In production, this key should be stored securely in a key management service # Note: Any production, this key should be stored securely in a key management service
# and only the key_id should be stored in the database # and only the key_id should be stored in the database
return encryption_key return encryption_key
async def rotateKey(self, old_key_id: Any) -> AudioRecording: async def rotateKey(self, old_key_id: Any) -> Any:
""" """
Rotate encryption key Rotate encryption key
custom custom
@ -864,7 +865,7 @@ class AudioRecordingService:
return new_key_id return new_key_id
async def upload(self, file: Any, recording_id: Any) -> AudioRecording: async def upload(self, file: Any, recording_id: Any) -> Any:
""" """
Upload audio file Upload audio file
custom custom
@ -941,7 +942,7 @@ class AudioRecordingService:
"message": "Audio file uploaded successfully" "message": "Audio file uploaded successfully"
} }
async def validateFile(self, file: Any, format: Any) -> AudioRecording: async def validateFile(self, file: Any, format: Any) -> Any:
""" """
Validate audio file Validate audio file
custom custom
@ -1003,7 +1004,7 @@ class AudioRecordingService:
except Exception as e: except Exception as e:
return False return False
async def getUploadUrl(self, recording_id: Any) -> AudioRecording: async def getUploadUrl(self, recording_id: Any) -> Any:
""" """
Get presigned upload URL Get presigned upload URL
custom custom
@ -1058,7 +1059,7 @@ class AudioRecordingService:
detail=f"Failed to generate presigned URL: {str(e)}" detail=f"Failed to generate presigned URL: {str(e)}"
) )
async def processUpload(self, recording_id: Any) -> AudioRecording: async def processUpload(self, recording_id: Any) -> Any:
""" """
Process uploaded file Process uploaded file
custom custom
@ -1144,7 +1145,7 @@ class AudioRecordingService:
) )
# =========== Query Methods (findBy*) =========== # =========== Query Methods (findBy*) ===========
async def find_by_encounter_id(self, encounter_id: str) -> List[AudioRecording]: async def find_by_encounter_id(self, encounter_id: str) -> List[Any]:
""" """
Find audiorecordings by encounter_id Find audiorecordings by encounter_id
""" """
@ -1152,7 +1153,7 @@ class AudioRecordingService:
getattr(AudioRecording, "encounter_id") == encounter_id getattr(AudioRecording, "encounter_id") == encounter_id
).all() ).all()
async def find_by_file_path(self, file_path: str) -> List[AudioRecording]: async def find_by_file_path(self, file_path: str) -> List[Any]:
""" """
Find audiorecordings by file_path Find audiorecordings by file_path
""" """
@ -1160,7 +1161,7 @@ class AudioRecordingService:
getattr(AudioRecording, "file_path") == file_path getattr(AudioRecording, "file_path") == file_path
).all() ).all()
async def find_by_file_name(self, file_name: str) -> List[AudioRecording]: async def find_by_file_name(self, file_name: str) -> List[Any]:
""" """
Find audiorecordings by file_name Find audiorecordings by file_name
""" """
@ -1168,7 +1169,7 @@ class AudioRecordingService:
getattr(AudioRecording, "file_name") == file_name getattr(AudioRecording, "file_name") == file_name
).all() ).all()
async def find_by_file_format(self, file_format: str) -> List[AudioRecording]: async def find_by_file_format(self, file_format: str) -> List[Any]:
""" """
Find audiorecordings by file_format Find audiorecordings by file_format
""" """
@ -1176,7 +1177,7 @@ class AudioRecordingService:
getattr(AudioRecording, "file_format") == file_format getattr(AudioRecording, "file_format") == file_format
).all() ).all()
async def find_by_file_size_bytes(self, file_size_bytes: int) -> List[AudioRecording]: async def find_by_file_size_bytes(self, file_size_bytes: int) -> List[Any]:
""" """
Find audiorecordings by file_size_bytes Find audiorecordings by file_size_bytes
""" """
@ -1184,7 +1185,7 @@ class AudioRecordingService:
getattr(AudioRecording, "file_size_bytes") == file_size_bytes getattr(AudioRecording, "file_size_bytes") == file_size_bytes
).all() ).all()
async def find_by_duration_seconds(self, duration_seconds: int) -> List[AudioRecording]: async def find_by_duration_seconds(self, duration_seconds: int) -> List[Any]:
""" """
Find audiorecordings by duration_seconds Find audiorecordings by duration_seconds
""" """
@ -1192,7 +1193,7 @@ class AudioRecordingService:
getattr(AudioRecording, "duration_seconds") == duration_seconds getattr(AudioRecording, "duration_seconds") == duration_seconds
).all() ).all()
async def find_by_recording_date(self, recording_date: datetime) -> List[AudioRecording]: async def find_by_recording_date(self, recording_date: datetime) -> List[Any]:
""" """
Find audiorecordings by recording_date Find audiorecordings by recording_date
""" """
@ -1200,7 +1201,7 @@ class AudioRecordingService:
getattr(AudioRecording, "recording_date") == recording_date getattr(AudioRecording, "recording_date") == recording_date
).all() ).all()
async def find_by_upload_date(self, upload_date: datetime) -> List[AudioRecording]: async def find_by_upload_date(self, upload_date: datetime) -> List[Any]:
""" """
Find audiorecordings by upload_date Find audiorecordings by upload_date
""" """
@ -1208,7 +1209,7 @@ class AudioRecordingService:
getattr(AudioRecording, "upload_date") == upload_date getattr(AudioRecording, "upload_date") == upload_date
).all() ).all()
async def find_by_is_encrypted(self, is_encrypted: bool) -> List[AudioRecording]: async def find_by_is_encrypted(self, is_encrypted: bool) -> List[Any]:
""" """
Find audiorecordings by is_encrypted Find audiorecordings by is_encrypted
""" """
@ -1216,7 +1217,7 @@ class AudioRecordingService:
getattr(AudioRecording, "is_encrypted") == is_encrypted getattr(AudioRecording, "is_encrypted") == is_encrypted
).all() ).all()
async def find_by_encryption_key_id(self, encryption_key_id: str) -> List[AudioRecording]: async def find_by_encryption_key_id(self, encryption_key_id: str) -> List[Any]:
""" """
Find audiorecordings by encryption_key_id Find audiorecordings by encryption_key_id
""" """
@ -1224,7 +1225,7 @@ class AudioRecordingService:
getattr(AudioRecording, "encryption_key_id") == encryption_key_id getattr(AudioRecording, "encryption_key_id") == encryption_key_id
).all() ).all()
async def find_by_status(self, status: str) -> List[AudioRecording]: async def find_by_status(self, status: str) -> List[Any]:
""" """
Find audiorecordings by status Find audiorecordings by status
""" """
@ -1232,7 +1233,7 @@ class AudioRecordingService:
getattr(AudioRecording, "status") == status getattr(AudioRecording, "status") == status
).all() ).all()
async def find_by_device_info(self, device_info: Dict[str, Any]) -> List[AudioRecording]: async def find_by_device_info(self, device_info: Dict[str, Any]) -> List[Any]:
""" """
Find audiorecordings by device_info Find audiorecordings by device_info
""" """
@ -1240,7 +1241,7 @@ class AudioRecordingService:
getattr(AudioRecording, "device_info") == device_info getattr(AudioRecording, "device_info") == device_info
).all() ).all()
async def find_by_noise_level(self, noise_level: str) -> List[AudioRecording]: async def find_by_noise_level(self, noise_level: str) -> List[Any]:
""" """
Find audiorecordings by noise_level Find audiorecordings by noise_level
""" """
@ -1248,7 +1249,7 @@ class AudioRecordingService:
getattr(AudioRecording, "noise_level") == noise_level getattr(AudioRecording, "noise_level") == noise_level
).all() ).all()
async def find_by_is_template_based(self, is_template_based: bool) -> List[AudioRecording]: async def find_by_is_template_based(self, is_template_based: bool) -> List[Any]:
""" """
Find audiorecordings by is_template_based Find audiorecordings by is_template_based
""" """
@ -1256,7 +1257,7 @@ class AudioRecordingService:
getattr(AudioRecording, "is_template_based") == is_template_based getattr(AudioRecording, "is_template_based") == is_template_based
).all() ).all()
async def find_by_created_at(self, created_at: datetime) -> List[AudioRecording]: async def find_by_created_at(self, created_at: datetime) -> List[Any]:
""" """
Find audiorecordings by created_at Find audiorecordings by created_at
""" """
@ -1264,7 +1265,7 @@ class AudioRecordingService:
getattr(AudioRecording, "created_at") == created_at getattr(AudioRecording, "created_at") == created_at
).all() ).all()
async def find_by_updated_at(self, updated_at: datetime) -> List[AudioRecording]: async def find_by_updated_at(self, updated_at: datetime) -> List[Any]:
""" """
Find audiorecordings by updated_at Find audiorecordings by updated_at
""" """
@ -1273,7 +1274,7 @@ class AudioRecordingService:
).all() ).all()
# =========== Relationship Methods =========== # =========== Relationship Methods ===========
async def get_by_user_id(self, audio_recording_id: UUID) -> User: async def get_by_user_id(self, audio_recording_id: UUID) -> Any:
""" """
Get the user for this audiorecording Get the user for this audiorecording
""" """
@ -1288,7 +1289,7 @@ class AudioRecordingService:
).first() ).first()
return None return None
async def get_by_patient_id(self, audio_recording_id: UUID) -> Patient: async def get_by_patient_id(self, audio_recording_id: UUID) -> Any:
""" """
Get the patient for this audiorecording Get the patient for this audiorecording
""" """
@ -1303,7 +1304,7 @@ class AudioRecordingService:
).first() ).first()
return None return None
async def get_by_template_id(self, audio_recording_id: UUID) -> ProcedureTemplate: async def get_by_template_id(self, audio_recording_id: UUID) -> Any:
""" """
Get the proceduretemplate for this audiorecording Get the proceduretemplate for this audiorecording
""" """
@ -1318,7 +1319,7 @@ class AudioRecordingService:
).first() ).first()
return None return None
async def get_by_audio_recording_id(self, audio_recording_id: UUID) -> Transcript: async def get_by_audio_recording_id(self, audio_recording_id: UUID) -> Any:
""" """
Get the transcript for this audiorecording Get the transcript for this audiorecording
""" """

View File

@ -1,7 +1,8 @@
from datetime import date, datetime
""" """
AuditLog Service Layer AuditLog Service Layer
Enterprise-grade service with business logic, validation, and error handling Enterprise-grade service with business logic, validation, and error handling
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas Architecture: Any Services/CRUD SQLAlchemy Models + Pydantic Schemas
""" """
from typing import List, Optional, Tuple, Dict, Any from typing import List, Optional, Tuple, Dict, Any
from uuid import UUID from uuid import UUID
@ -14,7 +15,7 @@ from src.validation.audit_log_schemas import AuditLogCreate, AuditLogUpdate
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class AuditLogService: class AuditLogCRUD:
""" """
Service class for AuditLog business logic. Service class for AuditLog business logic.
@ -22,7 +23,7 @@ class AuditLogService:
and complex queries. and complex queries.
""" """
def __init__(self, db: Session): def __init__(self, db: Any):
"""Initialize service with database session.""" """Initialize service with database session."""
self.db = db self.db = db
@ -38,11 +39,11 @@ class AuditLogService:
Get all auditlogs with pagination and filtering. Get all auditlogs with pagination and filtering.
Args: Args:
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
filters: Dictionary of field filters filters: Any of field filters
order_by: Field to order by order_by: Any to order by
order_desc: Order descending if True order_desc: Any descending if True
Returns: Returns:
Tuple of (list of auditlogs, total count) Tuple of (list of auditlogs, total count)
@ -85,7 +86,7 @@ class AuditLogService:
Get a specific auditlog by ID. Get a specific auditlog by ID.
Args: Args:
audit_log_id: The UUID of the auditlog audit_log_id: Any UUID of the auditlog
Returns: Returns:
The auditlog if found, None otherwise The auditlog if found, None otherwise
@ -95,12 +96,12 @@ class AuditLogService:
AuditLog.id == audit_log_id AuditLog.id == audit_log_id
).first() ).first()
async def create(self, audit_log_in: AuditLogCreate) -> AuditLog: async def create(self, audit_log_in: Any) -> Any:
""" """
Create a new auditlog. Create a new auditlog.
Args: Args:
audit_log_in: The auditlog data to create audit_log_in: Any auditlog data to create
Returns: Returns:
The created auditlog The created auditlog
@ -128,14 +129,14 @@ class AuditLogService:
async def update( async def update(
self, self,
audit_log_id: UUID, audit_log_id: UUID,
audit_log_in: AuditLogUpdate audit_log_in: Any
) -> Optional[AuditLog]: ) -> Optional[AuditLog]:
""" """
Update an existing auditlog. Update an existing auditlog.
Args: Args:
audit_log_id: The UUID of the auditlog to update audit_log_id: Any UUID of the auditlog to update
audit_log_in: The updated auditlog data audit_log_in: Any updated auditlog data
Returns: Returns:
The updated auditlog if found, None otherwise The updated auditlog if found, None otherwise
@ -163,7 +164,7 @@ class AuditLogService:
Delete a auditlog. Delete a auditlog.
Args: Args:
audit_log_id: The UUID of the auditlog to delete audit_log_id: Any UUID of the auditlog to delete
Returns: Returns:
True if deleted, False if not found True if deleted, False if not found
@ -190,9 +191,9 @@ class AuditLogService:
Get all auditlogs for a specific User. Get all auditlogs for a specific User.
Args: Args:
user_id: The UUID of the User user_id: Any UUID of the User
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of auditlogs, total count) Tuple of (list of auditlogs, total count)
@ -276,7 +277,7 @@ class AuditLogService:
await event_bus.emit("phi.accessed", event_data) await event_bus.emit("phi.accessed", event_data)
# =========== Custom Service Methods =========== # =========== Custom Service Methods ===========
async def find_one(self, _id: UUID) -> AuditLog: async def find_one(self, _id: UUID) -> Any:
""" """
Get audit log by ID Get audit log by ID
GET /api/v1/audit/logs/{id} GET /api/v1/audit/logs/{id}
@ -284,7 +285,7 @@ class AuditLogService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method find_one not yet implemented") raise NotImplementedError(f"Method find_one not yet implemented")
async def get_entity_history(self, entity_type: Any, entity_id: Any) -> List[AuditLog]: async def get_entity_history(self, entity_type: Any, entity_id: Any) -> List[Any]:
""" """
Get entity audit history Get entity audit history
GET /api/v1/audit/logs/entity/{entity_type}/{entity_id} GET /api/v1/audit/logs/entity/{entity_type}/{entity_id}
@ -292,7 +293,7 @@ class AuditLogService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method get_entity_history not yet implemented") raise NotImplementedError(f"Method get_entity_history not yet implemented")
async def get_user_activity(self, user_id: Any, date_from: Any, date_to: Any) -> List[AuditLog]: async def get_user_activity(self, user_id: Any, date_from: Any, date_to: Any) -> List[Any]:
""" """
Get user activity Get user activity
GET /api/v1/audit/logs/user/{user_id} GET /api/v1/audit/logs/user/{user_id}
@ -300,7 +301,7 @@ class AuditLogService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method get_user_activity not yet implemented") raise NotImplementedError(f"Method get_user_activity not yet implemented")
async def export_logs(self, _in: Create) -> AuditLog: async def export_logs(self, _in: Any) -> Any:
""" """
Export audit logs Export audit logs
POST /api/v1/audit/logs/export POST /api/v1/audit/logs/export
@ -308,7 +309,7 @@ class AuditLogService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method export_logs not yet implemented") raise NotImplementedError(f"Method export_logs not yet implemented")
async def exportLogs(self, filters: Any, format: Any) -> AuditLog: async def exportLogs(self, filters: Any, format: Any) -> Any:
""" """
Export audit logs Export audit logs
custom custom
@ -414,7 +415,7 @@ class AuditLogService:
else: else:
raise HTTPException(status_code=400, detail=f"Unsupported export format: {format}") raise HTTPException(status_code=400, detail=f"Unsupported export format: {format}")
async def findByUser(self, user_id: Any, skip: Any = 0, take: Any = 10) -> AuditLog: async def findByUser(self, user_id: Any, skip: Any = 0, take: Any = 10) -> Any:
""" """
Get logs by user Get logs by user
custom custom
@ -425,7 +426,7 @@ class AuditLogService:
audit_logs = result.scalars().all() audit_logs = result.scalars().all()
return audit_logs return audit_logs
async def findByEntity(self, entity_type: Any, entity_id: Any) -> AuditLog: async def findByEntity(self, entity_type: Any, entity_id: Any) -> Any:
""" """
Get logs by entity Get logs by entity
custom custom
@ -441,7 +442,7 @@ class AuditLogService:
return list(audit_logs) return list(audit_logs)
async def findPHIAccess(self, date_from: Any = None, date_to: Any = None) -> AuditLog: async def findPHIAccess(self, date_from: Any = None, date_to: Any = None) -> Any:
""" """
Get PHI access logs Get PHI access logs
custom custom
@ -464,7 +465,7 @@ class AuditLogService:
return list(audit_logs) return list(audit_logs)
async def findByDateRange(self, start_date: Any, end_date: Any) -> AuditLog: async def findByDateRange(self, start_date: Any, end_date: Any) -> Any:
""" """
Get logs by date range Get logs by date range
custom custom
@ -486,7 +487,7 @@ class AuditLogService:
return list(audit_logs) return list(audit_logs)
# =========== Query Methods (findBy*) =========== # =========== Query Methods (findBy*) ===========
async def find_by_entity_type(self, entity_type: str) -> List[AuditLog]: async def find_by_entity_type(self, entity_type: str) -> List[Any]:
""" """
Find auditlogs by entity_type Find auditlogs by entity_type
""" """
@ -494,7 +495,7 @@ class AuditLogService:
getattr(AuditLog, "entity_type") == entity_type getattr(AuditLog, "entity_type") == entity_type
).all() ).all()
async def find_by_entity_id(self, entity_id: UUID) -> List[AuditLog]: async def find_by_entity_id(self, entity_id: UUID) -> List[Any]:
""" """
Find auditlogs by entity_id Find auditlogs by entity_id
""" """
@ -502,7 +503,7 @@ class AuditLogService:
getattr(AuditLog, "entity_id") == entity_id getattr(AuditLog, "entity_id") == entity_id
).all() ).all()
async def find_by_action(self, action: str) -> List[AuditLog]: async def find_by_action(self, action: str) -> List[Any]:
""" """
Find auditlogs by action Find auditlogs by action
""" """
@ -510,7 +511,7 @@ class AuditLogService:
getattr(AuditLog, "action") == action getattr(AuditLog, "action") == action
).all() ).all()
async def find_by_action_category(self, action_category: str) -> List[AuditLog]: async def find_by_action_category(self, action_category: str) -> List[Any]:
""" """
Find auditlogs by action_category Find auditlogs by action_category
""" """
@ -518,7 +519,7 @@ class AuditLogService:
getattr(AuditLog, "action_category") == action_category getattr(AuditLog, "action_category") == action_category
).all() ).all()
async def find_by_old_values(self, old_values: Dict[str, Any]) -> List[AuditLog]: async def find_by_old_values(self, old_values: Dict[str, Any]) -> List[Any]:
""" """
Find auditlogs by old_values Find auditlogs by old_values
""" """
@ -526,7 +527,7 @@ class AuditLogService:
getattr(AuditLog, "old_values") == old_values getattr(AuditLog, "old_values") == old_values
).all() ).all()
async def find_by_new_values(self, new_values: Dict[str, Any]) -> List[AuditLog]: async def find_by_new_values(self, new_values: Dict[str, Any]) -> List[Any]:
""" """
Find auditlogs by new_values Find auditlogs by new_values
""" """
@ -534,7 +535,7 @@ class AuditLogService:
getattr(AuditLog, "new_values") == new_values getattr(AuditLog, "new_values") == new_values
).all() ).all()
async def find_by_changes_summary(self, changes_summary: str) -> List[AuditLog]: async def find_by_changes_summary(self, changes_summary: str) -> List[Any]:
""" """
Find auditlogs by changes_summary Find auditlogs by changes_summary
""" """
@ -542,7 +543,7 @@ class AuditLogService:
getattr(AuditLog, "changes_summary") == changes_summary getattr(AuditLog, "changes_summary") == changes_summary
).all() ).all()
async def find_by_ip_address(self, ip_address: str) -> List[AuditLog]: async def find_by_ip_address(self, ip_address: str) -> List[Any]:
""" """
Find auditlogs by ip_address Find auditlogs by ip_address
""" """
@ -550,7 +551,7 @@ class AuditLogService:
getattr(AuditLog, "ip_address") == ip_address getattr(AuditLog, "ip_address") == ip_address
).all() ).all()
async def find_by_user_agent(self, user_agent: str) -> List[AuditLog]: async def find_by_user_agent(self, user_agent: str) -> List[Any]:
""" """
Find auditlogs by user_agent Find auditlogs by user_agent
""" """
@ -558,7 +559,7 @@ class AuditLogService:
getattr(AuditLog, "user_agent") == user_agent getattr(AuditLog, "user_agent") == user_agent
).all() ).all()
async def find_by_session_id(self, session_id: str) -> List[AuditLog]: async def find_by_session_id(self, session_id: str) -> List[Any]:
""" """
Find auditlogs by session_id Find auditlogs by session_id
""" """
@ -566,7 +567,7 @@ class AuditLogService:
getattr(AuditLog, "session_id") == session_id getattr(AuditLog, "session_id") == session_id
).all() ).all()
async def find_by_request_id(self, request_id: str) -> List[AuditLog]: async def find_by_request_id(self, request_id: str) -> List[Any]:
""" """
Find auditlogs by request_id Find auditlogs by request_id
""" """
@ -574,7 +575,7 @@ class AuditLogService:
getattr(AuditLog, "request_id") == request_id getattr(AuditLog, "request_id") == request_id
).all() ).all()
async def find_by_status(self, status: str) -> List[AuditLog]: async def find_by_status(self, status: str) -> List[Any]:
""" """
Find auditlogs by status Find auditlogs by status
""" """
@ -582,7 +583,7 @@ class AuditLogService:
getattr(AuditLog, "status") == status getattr(AuditLog, "status") == status
).all() ).all()
async def find_by_error_message(self, error_message: str) -> List[AuditLog]: async def find_by_error_message(self, error_message: str) -> List[Any]:
""" """
Find auditlogs by error_message Find auditlogs by error_message
""" """
@ -590,7 +591,7 @@ class AuditLogService:
getattr(AuditLog, "error_message") == error_message getattr(AuditLog, "error_message") == error_message
).all() ).all()
async def find_by_metadata(self, metadata: Dict[str, Any]) -> List[AuditLog]: async def find_by_metadata(self, metadata: Dict[str, Any]) -> List[Any]:
""" """
Find auditlogs by metadata Find auditlogs by metadata
""" """
@ -598,7 +599,7 @@ class AuditLogService:
getattr(AuditLog, "metadata") == metadata getattr(AuditLog, "metadata") == metadata
).all() ).all()
async def find_by_phi_accessed(self, phi_accessed: bool) -> List[AuditLog]: async def find_by_phi_accessed(self, phi_accessed: bool) -> List[Any]:
""" """
Find auditlogs by phi_accessed Find auditlogs by phi_accessed
""" """
@ -606,7 +607,7 @@ class AuditLogService:
getattr(AuditLog, "phi_accessed") == phi_accessed getattr(AuditLog, "phi_accessed") == phi_accessed
).all() ).all()
async def find_by_compliance_flag(self, compliance_flag: bool) -> List[AuditLog]: async def find_by_compliance_flag(self, compliance_flag: bool) -> List[Any]:
""" """
Find auditlogs by compliance_flag Find auditlogs by compliance_flag
""" """
@ -614,7 +615,7 @@ class AuditLogService:
getattr(AuditLog, "compliance_flag") == compliance_flag getattr(AuditLog, "compliance_flag") == compliance_flag
).all() ).all()
async def find_by_created_at(self, created_at: Any) -> List[AuditLog]: async def find_by_created_at(self, created_at: Any) -> List[Any]:
""" """
Find auditlogs by created_at Find auditlogs by created_at
""" """
@ -623,7 +624,7 @@ class AuditLogService:
).all() ).all()
# =========== Relationship Methods =========== # =========== Relationship Methods ===========
async def get_by_user_id(self, audit_log_id: UUID) -> User: async def get_by_user_id(self, audit_log_id: UUID) -> Any:
""" """
Get the user for this auditlog Get the user for this auditlog
""" """

View File

@ -1,7 +1,8 @@
from datetime import date, datetime
""" """
ClaimReview Service Layer ClaimReview Service Layer
Enterprise-grade service with business logic, validation, and error handling Enterprise-grade service with business logic, validation, and error handling
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas Architecture: Any Services/CRUD SQLAlchemy Models + Pydantic Schemas
""" """
from typing import List, Optional, Tuple, Dict, Any from typing import List, Optional, Tuple, Dict, Any
from uuid import UUID from uuid import UUID
@ -14,7 +15,7 @@ from src.validation.claim_review_schemas import ClaimReviewCreate, ClaimReviewUp
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ClaimReviewService: class ClaimReviewCRUD:
""" """
Service class for ClaimReview business logic. Service class for ClaimReview business logic.
@ -22,7 +23,7 @@ class ClaimReviewService:
and complex queries. and complex queries.
""" """
def __init__(self, db: Session): def __init__(self, db: Any):
"""Initialize service with database session.""" """Initialize service with database session."""
self.db = db self.db = db
@ -38,11 +39,11 @@ class ClaimReviewService:
Get all claimreviews with pagination and filtering. Get all claimreviews with pagination and filtering.
Args: Args:
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
filters: Dictionary of field filters filters: Any of field filters
order_by: Field to order by order_by: Any to order by
order_desc: Order descending if True order_desc: Any descending if True
Returns: Returns:
Tuple of (list of claimreviews, total count) Tuple of (list of claimreviews, total count)
@ -85,7 +86,7 @@ class ClaimReviewService:
Get a specific claimreview by ID. Get a specific claimreview by ID.
Args: Args:
claim_review_id: The UUID of the claimreview claim_review_id: Any UUID of the claimreview
Returns: Returns:
The claimreview if found, None otherwise The claimreview if found, None otherwise
@ -95,12 +96,12 @@ class ClaimReviewService:
ClaimReview.id == claim_review_id ClaimReview.id == claim_review_id
).first() ).first()
async def create(self, claim_review_in: ClaimReviewCreate) -> ClaimReview: async def create(self, claim_review_in: Any) -> Any:
""" """
Create a new claimreview. Create a new claimreview.
Args: Args:
claim_review_in: The claimreview data to create claim_review_in: Any claimreview data to create
Returns: Returns:
The created claimreview The created claimreview
@ -125,14 +126,14 @@ class ClaimReviewService:
async def update( async def update(
self, self,
claim_review_id: UUID, claim_review_id: UUID,
claim_review_in: ClaimReviewUpdate claim_review_in: Any
) -> Optional[ClaimReview]: ) -> Optional[ClaimReview]:
""" """
Update an existing claimreview. Update an existing claimreview.
Args: Args:
claim_review_id: The UUID of the claimreview to update claim_review_id: Any UUID of the claimreview to update
claim_review_in: The updated claimreview data claim_review_in: Any updated claimreview data
Returns: Returns:
The updated claimreview if found, None otherwise The updated claimreview if found, None otherwise
@ -163,7 +164,7 @@ class ClaimReviewService:
Delete a claimreview. Delete a claimreview.
Args: Args:
claim_review_id: The UUID of the claimreview to delete claim_review_id: Any UUID of the claimreview to delete
Returns: Returns:
True if deleted, False if not found True if deleted, False if not found
@ -190,9 +191,9 @@ class ClaimReviewService:
Get all claimreviews for a specific Claim. Get all claimreviews for a specific Claim.
Args: Args:
claim_id: The UUID of the Claim claim_id: Any UUID of the Claim
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of claimreviews, total count) Tuple of (list of claimreviews, total count)
@ -216,9 +217,9 @@ class ClaimReviewService:
Get all claimreviews for a specific User. Get all claimreviews for a specific User.
Args: Args:
user_id: The UUID of the User user_id: Any UUID of the User
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of claimreviews, total count) Tuple of (list of claimreviews, total count)
@ -242,9 +243,9 @@ class ClaimReviewService:
Get all claimreviews for a specific User. Get all claimreviews for a specific User.
Args: Args:
user_id: The UUID of the User user_id: Any UUID of the User
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of claimreviews, total count) Tuple of (list of claimreviews, total count)
@ -327,7 +328,7 @@ class ClaimReviewService:
await event_bus.emit("review.completed", event_data) await event_bus.emit("review.completed", event_data)
# =========== Custom Service Methods =========== # =========== Custom Service Methods ===========
async def find_one(self, _id: UUID) -> ClaimReview: async def find_one(self, _id: UUID) -> Any:
""" """
Get review by ID Get review by ID
GET /api/v1/reviews/{id} GET /api/v1/reviews/{id}
@ -335,7 +336,7 @@ class ClaimReviewService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method find_one not yet implemented") raise NotImplementedError(f"Method find_one not yet implemented")
async def approve(self, _id: UUID, notes: Any, approved_codes: Any) -> ClaimReview: async def approve(self, _id: UUID, notes: Any, approved_codes: Any) -> Any:
""" """
Approve review Approve review
POST /api/v1/reviews/{id}/approve POST /api/v1/reviews/{id}/approve
@ -370,7 +371,7 @@ class ClaimReviewService:
return claim_review return claim_review
async def reject(self, _id: UUID, reason: Any, notes: Any, corrective_actions: Any) -> ClaimReview: async def reject(self, _id: UUID, reason: Any, notes: Any, corrective_actions: Any) -> Any:
""" """
Reject review Reject review
POST /api/v1/reviews/{id}/reject POST /api/v1/reviews/{id}/reject
@ -398,7 +399,7 @@ class ClaimReviewService:
return claim_review return claim_review
async def escalate(self, _id: UUID, escalate_to: Any, reason: Any) -> ClaimReview: async def escalate(self, _id: UUID, escalate_to: Any, reason: Any) -> Any:
""" """
Escalate review Escalate review
POST /api/v1/reviews/{id}/escalate POST /api/v1/reviews/{id}/escalate
@ -436,7 +437,7 @@ class ClaimReviewService:
return claim_review return claim_review
async def get_queue(self, assigned_to: Any, priority: Any) -> List[ClaimReview]: async def get_queue(self, assigned_to: Any, priority: Any) -> List[Any]:
""" """
Get review queue Get review queue
GET /api/v1/reviews/queue GET /api/v1/reviews/queue
@ -444,7 +445,7 @@ class ClaimReviewService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method get_queue not yet implemented") raise NotImplementedError(f"Method get_queue not yet implemented")
async def findByReviewer(self, reviewer_id: Any) -> ClaimReview: async def findByReviewer(self, reviewer_id: Any) -> Any:
""" """
Get reviews by reviewer Get reviews by reviewer
custom custom
@ -455,7 +456,7 @@ class ClaimReviewService:
reviews = result.scalars().all() reviews = result.scalars().all()
return reviews return reviews
async def findPendingReviews(self, skip: Any = 0, take: Any = 10) -> ClaimReview: async def findPendingReviews(self, skip: Any = 0, take: Any = 10) -> Any:
""" """
Get pending reviews Get pending reviews
custom custom
@ -471,7 +472,7 @@ class ClaimReviewService:
return claim_reviews return claim_reviews
# =========== Query Methods (findBy*) =========== # =========== Query Methods (findBy*) ===========
async def find_by_review_status(self, review_status: str) -> List[ClaimReview]: async def find_by_review_status(self, review_status: str) -> List[Any]:
""" """
Find claimreviews by review_status Find claimreviews by review_status
""" """
@ -479,7 +480,7 @@ class ClaimReviewService:
getattr(ClaimReview, "review_status") == review_status getattr(ClaimReview, "review_status") == review_status
).all() ).all()
async def find_by_review_type(self, review_type: str) -> List[ClaimReview]: async def find_by_review_type(self, review_type: str) -> List[Any]:
""" """
Find claimreviews by review_type Find claimreviews by review_type
""" """
@ -487,7 +488,7 @@ class ClaimReviewService:
getattr(ClaimReview, "review_type") == review_type getattr(ClaimReview, "review_type") == review_type
).all() ).all()
async def find_by_confidence_threshold_triggered(self, confidence_threshold_triggered: bool) -> List[ClaimReview]: async def find_by_confidence_threshold_triggered(self, confidence_threshold_triggered: bool) -> List[Any]:
""" """
Find claimreviews by confidence_threshold_triggered Find claimreviews by confidence_threshold_triggered
""" """
@ -495,7 +496,7 @@ class ClaimReviewService:
getattr(ClaimReview, "confidence_threshold_triggered") == confidence_threshold_triggered getattr(ClaimReview, "confidence_threshold_triggered") == confidence_threshold_triggered
).all() ).all()
async def find_by_original_icd10_codes(self, original_icd10_codes: Dict[str, Any]) -> List[ClaimReview]: async def find_by_original_icd10_codes(self, original_icd10_codes: Dict[str, Any]) -> List[Any]:
""" """
Find claimreviews by original_icd10_codes Find claimreviews by original_icd10_codes
""" """
@ -503,7 +504,7 @@ class ClaimReviewService:
getattr(ClaimReview, "original_icd10_codes") == original_icd10_codes getattr(ClaimReview, "original_icd10_codes") == original_icd10_codes
).all() ).all()
async def find_by_original_cpt_codes(self, original_cpt_codes: Dict[str, Any]) -> List[ClaimReview]: async def find_by_original_cpt_codes(self, original_cpt_codes: Dict[str, Any]) -> List[Any]:
""" """
Find claimreviews by original_cpt_codes Find claimreviews by original_cpt_codes
""" """
@ -511,7 +512,7 @@ class ClaimReviewService:
getattr(ClaimReview, "original_cpt_codes") == original_cpt_codes getattr(ClaimReview, "original_cpt_codes") == original_cpt_codes
).all() ).all()
async def find_by_revised_icd10_codes(self, revised_icd10_codes: Dict[str, Any]) -> List[ClaimReview]: async def find_by_revised_icd10_codes(self, revised_icd10_codes: Dict[str, Any]) -> List[Any]:
""" """
Find claimreviews by revised_icd10_codes Find claimreviews by revised_icd10_codes
""" """
@ -519,7 +520,7 @@ class ClaimReviewService:
getattr(ClaimReview, "revised_icd10_codes") == revised_icd10_codes getattr(ClaimReview, "revised_icd10_codes") == revised_icd10_codes
).all() ).all()
async def find_by_revised_cpt_codes(self, revised_cpt_codes: Dict[str, Any]) -> List[ClaimReview]: async def find_by_revised_cpt_codes(self, revised_cpt_codes: Dict[str, Any]) -> List[Any]:
""" """
Find claimreviews by revised_cpt_codes Find claimreviews by revised_cpt_codes
""" """
@ -527,7 +528,7 @@ class ClaimReviewService:
getattr(ClaimReview, "revised_cpt_codes") == revised_cpt_codes getattr(ClaimReview, "revised_cpt_codes") == revised_cpt_codes
).all() ).all()
async def find_by_reviewer_notes(self, reviewer_notes: str) -> List[ClaimReview]: async def find_by_reviewer_notes(self, reviewer_notes: str) -> List[Any]:
""" """
Find claimreviews by reviewer_notes Find claimreviews by reviewer_notes
""" """
@ -535,7 +536,7 @@ class ClaimReviewService:
getattr(ClaimReview, "reviewer_notes") == reviewer_notes getattr(ClaimReview, "reviewer_notes") == reviewer_notes
).all() ).all()
async def find_by_flagged_issues(self, flagged_issues: Dict[str, Any]) -> List[ClaimReview]: async def find_by_flagged_issues(self, flagged_issues: Dict[str, Any]) -> List[Any]:
""" """
Find claimreviews by flagged_issues Find claimreviews by flagged_issues
""" """
@ -543,7 +544,7 @@ class ClaimReviewService:
getattr(ClaimReview, "flagged_issues") == flagged_issues getattr(ClaimReview, "flagged_issues") == flagged_issues
).all() ).all()
async def find_by_corrective_actions(self, corrective_actions: Dict[str, Any]) -> List[ClaimReview]: async def find_by_corrective_actions(self, corrective_actions: Dict[str, Any]) -> List[Any]:
""" """
Find claimreviews by corrective_actions Find claimreviews by corrective_actions
""" """
@ -551,7 +552,7 @@ class ClaimReviewService:
getattr(ClaimReview, "corrective_actions") == corrective_actions getattr(ClaimReview, "corrective_actions") == corrective_actions
).all() ).all()
async def find_by_review_duration_seconds(self, review_duration_seconds: int) -> List[ClaimReview]: async def find_by_review_duration_seconds(self, review_duration_seconds: int) -> List[Any]:
""" """
Find claimreviews by review_duration_seconds Find claimreviews by review_duration_seconds
""" """
@ -559,7 +560,7 @@ class ClaimReviewService:
getattr(ClaimReview, "review_duration_seconds") == review_duration_seconds getattr(ClaimReview, "review_duration_seconds") == review_duration_seconds
).all() ).all()
async def find_by_escalation_reason(self, escalation_reason: str) -> List[ClaimReview]: async def find_by_escalation_reason(self, escalation_reason: str) -> List[Any]:
""" """
Find claimreviews by escalation_reason Find claimreviews by escalation_reason
""" """
@ -567,7 +568,7 @@ class ClaimReviewService:
getattr(ClaimReview, "escalation_reason") == escalation_reason getattr(ClaimReview, "escalation_reason") == escalation_reason
).all() ).all()
async def find_by_escalated_at(self, escalated_at: datetime) -> List[ClaimReview]: async def find_by_escalated_at(self, escalated_at: datetime) -> List[Any]:
""" """
Find claimreviews by escalated_at Find claimreviews by escalated_at
""" """
@ -575,7 +576,7 @@ class ClaimReviewService:
getattr(ClaimReview, "escalated_at") == escalated_at getattr(ClaimReview, "escalated_at") == escalated_at
).all() ).all()
async def find_by_reviewed_at(self, reviewed_at: datetime) -> List[ClaimReview]: async def find_by_reviewed_at(self, reviewed_at: datetime) -> List[Any]:
""" """
Find claimreviews by reviewed_at Find claimreviews by reviewed_at
""" """
@ -583,7 +584,7 @@ class ClaimReviewService:
getattr(ClaimReview, "reviewed_at") == reviewed_at getattr(ClaimReview, "reviewed_at") == reviewed_at
).all() ).all()
async def find_by_created_at(self, created_at: Any) -> List[ClaimReview]: async def find_by_created_at(self, created_at: Any) -> List[Any]:
""" """
Find claimreviews by created_at Find claimreviews by created_at
""" """
@ -591,7 +592,7 @@ class ClaimReviewService:
getattr(ClaimReview, "created_at") == created_at getattr(ClaimReview, "created_at") == created_at
).all() ).all()
async def find_by_updated_at(self, updated_at: Any) -> List[ClaimReview]: async def find_by_updated_at(self, updated_at: Any) -> List[Any]:
""" """
Find claimreviews by updated_at Find claimreviews by updated_at
""" """
@ -600,7 +601,7 @@ class ClaimReviewService:
).all() ).all()
# =========== Relationship Methods =========== # =========== Relationship Methods ===========
async def get_by_claim_id(self, claim_review_id: UUID) -> Claim: async def get_by_claim_id(self, claim_review_id: UUID) -> Any:
""" """
Get the claim for this claimreview Get the claim for this claimreview
""" """
@ -615,7 +616,7 @@ class ClaimReviewService:
).first() ).first()
return None return None
async def get_by_reviewer_id(self, claim_review_id: UUID) -> User: async def get_by_reviewer_id(self, claim_review_id: UUID) -> Any:
""" """
Get the user for this claimreview Get the user for this claimreview
""" """
@ -630,7 +631,7 @@ class ClaimReviewService:
).first() ).first()
return None return None
async def get_by_escalated_to_id(self, claim_review_id: UUID) -> User: async def get_by_escalated_to_id(self, claim_review_id: UUID) -> Any:
""" """
Get the user for this claimreview Get the user for this claimreview
""" """

View File

@ -1,7 +1,8 @@
from datetime import date, datetime
""" """
ClaimScrubResult Service Layer ClaimScrubResult Service Layer
Enterprise-grade service with business logic, validation, and error handling Enterprise-grade service with business logic, validation, and error handling
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas Architecture: Any Services/CRUD SQLAlchemy Models + Pydantic Schemas
""" """
from typing import List, Optional, Tuple, Dict, Any from typing import List, Optional, Tuple, Dict, Any
from uuid import UUID from uuid import UUID
@ -14,7 +15,7 @@ from src.validation.claim_scrub_result_schemas import ClaimScrubResultCreate, Cl
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ClaimScrubResultService: class ClaimScrubResultCRUD:
""" """
Service class for ClaimScrubResult business logic. Service class for ClaimScrubResult business logic.
@ -22,7 +23,7 @@ class ClaimScrubResultService:
and complex queries. and complex queries.
""" """
def __init__(self, db: Session): def __init__(self, db: Any):
"""Initialize service with database session.""" """Initialize service with database session."""
self.db = db self.db = db
@ -38,11 +39,11 @@ class ClaimScrubResultService:
Get all claimscrubresults with pagination and filtering. Get all claimscrubresults with pagination and filtering.
Args: Args:
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
filters: Dictionary of field filters filters: Any of field filters
order_by: Field to order by order_by: Any to order by
order_desc: Order descending if True order_desc: Any descending if True
Returns: Returns:
Tuple of (list of claimscrubresults, total count) Tuple of (list of claimscrubresults, total count)
@ -85,7 +86,7 @@ class ClaimScrubResultService:
Get a specific claimscrubresult by ID. Get a specific claimscrubresult by ID.
Args: Args:
claim_scrub_result_id: The UUID of the claimscrubresult claim_scrub_result_id: Any UUID of the claimscrubresult
Returns: Returns:
The claimscrubresult if found, None otherwise The claimscrubresult if found, None otherwise
@ -95,12 +96,12 @@ class ClaimScrubResultService:
ClaimScrubResult.id == claim_scrub_result_id ClaimScrubResult.id == claim_scrub_result_id
).first() ).first()
async def create(self, claim_scrub_result_in: ClaimScrubResultCreate) -> ClaimScrubResult: async def create(self, claim_scrub_result_in: Any) -> Any:
""" """
Create a new claimscrubresult. Create a new claimscrubresult.
Args: Args:
claim_scrub_result_in: The claimscrubresult data to create claim_scrub_result_in: Any claimscrubresult data to create
Returns: Returns:
The created claimscrubresult The created claimscrubresult
@ -130,14 +131,14 @@ class ClaimScrubResultService:
async def update( async def update(
self, self,
claim_scrub_result_id: UUID, claim_scrub_result_id: UUID,
claim_scrub_result_in: ClaimScrubResultUpdate claim_scrub_result_in: Any
) -> Optional[ClaimScrubResult]: ) -> Optional[ClaimScrubResult]:
""" """
Update an existing claimscrubresult. Update an existing claimscrubresult.
Args: Args:
claim_scrub_result_id: The UUID of the claimscrubresult to update claim_scrub_result_id: Any UUID of the claimscrubresult to update
claim_scrub_result_in: The updated claimscrubresult data claim_scrub_result_in: Any updated claimscrubresult data
Returns: Returns:
The updated claimscrubresult if found, None otherwise The updated claimscrubresult if found, None otherwise
@ -168,7 +169,7 @@ class ClaimScrubResultService:
Delete a claimscrubresult. Delete a claimscrubresult.
Args: Args:
claim_scrub_result_id: The UUID of the claimscrubresult to delete claim_scrub_result_id: Any UUID of the claimscrubresult to delete
Returns: Returns:
True if deleted, False if not found True if deleted, False if not found
@ -195,9 +196,9 @@ class ClaimScrubResultService:
Get all claimscrubresults for a specific Claim. Get all claimscrubresults for a specific Claim.
Args: Args:
claim_id: The UUID of the Claim claim_id: Any UUID of the Claim
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of claimscrubresults, total count) Tuple of (list of claimscrubresults, total count)
@ -212,7 +213,7 @@ class ClaimScrubResultService:
return items, total return items, total
# =========== BLS Business Rules =========== # =========== BLS Business Rules ===========
async def scrubClaimWithRAG(self, claim_scrub_result_in: ClaimScrubResultCreate, existing: Optional[ClaimScrubResult] = None) -> Any: async def scrubClaimWithRAG(self, claim_scrub_result_in: Any, existing: Optional[ClaimScrubResult] = None) -> Any:
""" """
Scrub claims against payer rules using RAG Scrub claims against payer rules using RAG
@generated from DSL function @generated from DSL function
@ -261,7 +262,7 @@ class ClaimScrubResultService:
claimScrubResult.requires_manual_review = scrubResult.requires_manual_review claimScrubResult.requires_manual_review = scrubResult.requires_manual_review
claimScrubResult.review_priority = scrubResult.review_priority claimScrubResult.review_priority = scrubResult.review_priority
async def validateNCCIEdits(self, claim_scrub_result_in: ClaimScrubResultCreate, existing: Optional[ClaimScrubResult] = None) -> Any: async def validateNCCIEdits(self, claim_scrub_result_in: Any, existing: Optional[ClaimScrubResult] = None) -> Any:
""" """
Validate claims against NCCI edits Validate claims against NCCI edits
@generated from DSL function @generated from DSL function
@ -310,7 +311,7 @@ class ClaimScrubResultService:
if len(ncci_violations) > 0: if len(ncci_violations) > 0:
claim_scrub_result.failed_checks = claim_scrub_result.failed_checks + len(ncci_violations) claim_scrub_result.failed_checks = claim_scrub_result.failed_checks + len(ncci_violations)
async def validateCoverageDeterminations(self, claim_scrub_result_in: ClaimScrubResultCreate, existing: Optional[ClaimScrubResult] = None) -> Any: async def validateCoverageDeterminations(self, claim_scrub_result_in: Any, existing: Optional[ClaimScrubResult] = None) -> Any:
""" """
Validate against LCD/NCD coverage determinations Validate against LCD/NCD coverage determinations
@generated from DSL function @generated from DSL function
@ -375,7 +376,7 @@ class ClaimScrubResultService:
claim_scrub_result.requires_manual_review = True claim_scrub_result.requires_manual_review = True
claim_scrub_result.overall_risk_level = "HIGH" claim_scrub_result.overall_risk_level = "HIGH"
async def flagFailures(self, claim_scrub_result_in: ClaimScrubResultCreate, existing: Optional[ClaimScrubResult] = None) -> Any: async def flagFailures(self, claim_scrub_result_in: Any, existing: Optional[ClaimScrubResult] = None) -> Any:
""" """
Flag claim failures with corrective actions Flag claim failures with corrective actions
@generated from DSL function @generated from DSL function
@ -464,7 +465,7 @@ class ClaimScrubResultService:
await event_bus.emit("claim.scrubbed", event_data) await event_bus.emit("claim.scrubbed", event_data)
# =========== Custom Service Methods =========== # =========== Custom Service Methods ===========
async def scrub_claim(self, _in: Create) -> ClaimScrubResult: async def scrub_claim(self, _in: Any) -> Any:
""" """
Scrub claim against rules Scrub claim against rules
POST /api/v1/claims/scrub POST /api/v1/claims/scrub
@ -472,7 +473,7 @@ class ClaimScrubResultService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method scrub_claim not yet implemented") raise NotImplementedError(f"Method scrub_claim not yet implemented")
async def get_scrub_result(self, _id: UUID) -> ClaimScrubResult: async def get_scrub_result(self, _id: UUID) -> Any:
""" """
Get scrub result Get scrub result
GET /api/v1/claims/scrub/{id} GET /api/v1/claims/scrub/{id}
@ -480,7 +481,7 @@ class ClaimScrubResultService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method get_scrub_result not yet implemented") raise NotImplementedError(f"Method get_scrub_result not yet implemented")
async def rerun_scrub(self, _id: UUID) -> ClaimScrubResult: async def rerun_scrub(self, _id: UUID) -> Any:
""" """
Rerun claim scrubbing Rerun claim scrubbing
POST /api/v1/claims/scrub/{id}/rerun POST /api/v1/claims/scrub/{id}/rerun
@ -488,7 +489,7 @@ class ClaimScrubResultService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method rerun_scrub not yet implemented") raise NotImplementedError(f"Method rerun_scrub not yet implemented")
async def validate_ncci(self, _in: Create) -> ClaimScrubResult: async def validate_ncci(self, _in: Any) -> Any:
""" """
Validate NCCI edits Validate NCCI edits
POST /api/v1/claims/validate/ncci POST /api/v1/claims/validate/ncci
@ -496,7 +497,7 @@ class ClaimScrubResultService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method validate_ncci not yet implemented") raise NotImplementedError(f"Method validate_ncci not yet implemented")
async def validate_lcd(self, _in: Create) -> ClaimScrubResult: async def validate_lcd(self, _in: Any) -> Any:
""" """
Validate LCD coverage Validate LCD coverage
POST /api/v1/claims/validate/lcd POST /api/v1/claims/validate/lcd
@ -504,7 +505,7 @@ class ClaimScrubResultService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method validate_lcd not yet implemented") raise NotImplementedError(f"Method validate_lcd not yet implemented")
async def validate_ncd(self, _in: Create) -> ClaimScrubResult: async def validate_ncd(self, _in: Any) -> Any:
""" """
Validate NCD coverage Validate NCD coverage
POST /api/v1/claims/validate/ncd POST /api/v1/claims/validate/ncd
@ -512,7 +513,7 @@ class ClaimScrubResultService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method validate_ncd not yet implemented") raise NotImplementedError(f"Method validate_ncd not yet implemented")
async def get_failures(self, query_params: Optional[Dict[str, Any]] = None) -> List[ClaimScrubResult]: async def get_failures(self, query_params: Optional[Dict[str, Any]] = None) -> List[Any]:
""" """
Get scrub failures Get scrub failures
GET /api/v1/claims/scrub/failures GET /api/v1/claims/scrub/failures
@ -520,7 +521,7 @@ class ClaimScrubResultService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method get_failures not yet implemented") raise NotImplementedError(f"Method get_failures not yet implemented")
async def scrubClaim(self, claim_id: Any, payer_id: Any, icd10_codes: Any, cpt_codes: Any, modifiers: Any) -> ClaimScrubResult: async def scrubClaim(self, claim_id: Any, payer_id: Any, icd10_codes: Any, cpt_codes: Any, modifiers: Any) -> Any:
""" """
Scrub claim Scrub claim
custom custom
@ -693,7 +694,7 @@ class ClaimScrubResultService:
"modifier_issues": scrub_result.modifier_issues "modifier_issues": scrub_result.modifier_issues
} }
async def validateNCCI(self, cpt_codes: Any, modifiers: Any) -> ClaimScrubResult: async def validateNCCI(self, cpt_codes: Any, modifiers: Any) -> Any:
""" """
Validate NCCI edits Validate NCCI edits
custom custom
@ -826,7 +827,7 @@ class ClaimScrubResultService:
ncci_valid_modifiers = ["25", "59", "XE", "XP", "XS", "XU", "91"] ncci_valid_modifiers = ["25", "59", "XE", "XP", "XS", "XU", "91"]
return modifier in ncci_valid_modifiers return modifier in ncci_valid_modifiers
async def validateLCD(self, icd10_codes: Any, cpt_codes: Any, payer_id: Any, state: Any) -> ClaimScrubResult: async def validateLCD(self, icd10_codes: Any, cpt_codes: Any, payer_id: Any, state: Any) -> Any:
""" """
Validate LCD Validate LCD
custom custom
@ -838,8 +839,8 @@ class ClaimScrubResultService:
Args: Args:
icd10_codes: List of ICD-10 diagnosis codes icd10_codes: List of ICD-10 diagnosis codes
cpt_codes: List of CPT procedure codes cpt_codes: List of CPT procedure codes
payer_idValue: Payer identifier payer_idValue: Any identifier
stateValue: State code for LCD jurisdiction stateValue: Any code for LCD jurisdiction
Returns: Returns:
Dictionary containing LCD validation results Dictionary containing LCD validation results
@ -925,7 +926,7 @@ class ClaimScrubResultService:
} }
} }
async def validateNCD(self, icd10_codes: Any, cpt_codes: Any, payer_id: Any) -> ClaimScrubResult: async def validateNCD(self, icd10_codes: Any, cpt_codes: Any, payer_id: Any) -> Any:
""" """
Validate NCD Validate NCD
custom custom
@ -937,7 +938,7 @@ class ClaimScrubResultService:
Args: Args:
icd10_codes: List of ICD-10 diagnosis codes icd10_codes: List of ICD-10 diagnosis codes
cpt_codes: List of CPT procedure codes cpt_codes: List of CPT procedure codes
payer_idValue: Payer identifier payer_idValue: Any identifier
Returns: Returns:
Dictionary containing NCD validation results Dictionary containing NCD validation results
@ -1034,7 +1035,7 @@ class ClaimScrubResultService:
"payer_idValue": payer_idValue "payer_idValue": payer_idValue
} }
async def checkPayerRules(self, payer_id: Any, codes: Any) -> ClaimScrubResult: async def checkPayerRules(self, payer_id: Any, codes: Any) -> Any:
""" """
Check payer rules Check payer rules
custom custom
@ -1044,8 +1045,8 @@ class ClaimScrubResultService:
Check payer rules for given payer and codes Check payer rules for given payer and codes
Args: Args:
payer_id: The payer identifier payer_id: Any payer identifier
codes: Dictionary containing procedure codes, diagnosis codes, etc. codes: Any containing procedure codes, diagnosis codes, etc.
Returns: Returns:
List of payer rule violations found List of payer rule violations found
@ -1135,7 +1136,7 @@ class ClaimScrubResultService:
return violations return violations
# =========== Query Methods (findBy*) =========== # =========== Query Methods (findBy*) ===========
async def find_by_scrub_status(self, scrub_status: str) -> List[ClaimScrubResult]: async def find_by_scrub_status(self, scrub_status: str) -> List[Any]:
""" """
Find claimscrubresults by scrub_status Find claimscrubresults by scrub_status
""" """
@ -1143,7 +1144,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "scrub_status") == scrub_status getattr(ClaimScrubResult, "scrub_status") == scrub_status
).all() ).all()
async def find_by_overall_risk_level(self, overall_risk_level: str) -> List[ClaimScrubResult]: async def find_by_overall_risk_level(self, overall_risk_level: str) -> List[Any]:
""" """
Find claimscrubresults by overall_risk_level Find claimscrubresults by overall_risk_level
""" """
@ -1151,7 +1152,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "overall_risk_level") == overall_risk_level getattr(ClaimScrubResult, "overall_risk_level") == overall_risk_level
).all() ).all()
async def find_by_total_checks(self, total_checks: int) -> List[ClaimScrubResult]: async def find_by_total_checks(self, total_checks: int) -> List[Any]:
""" """
Find claimscrubresults by total_checks Find claimscrubresults by total_checks
""" """
@ -1159,7 +1160,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "total_checks") == total_checks getattr(ClaimScrubResult, "total_checks") == total_checks
).all() ).all()
async def find_by_passed_checks(self, passed_checks: int) -> List[ClaimScrubResult]: async def find_by_passed_checks(self, passed_checks: int) -> List[Any]:
""" """
Find claimscrubresults by passed_checks Find claimscrubresults by passed_checks
""" """
@ -1167,7 +1168,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "passed_checks") == passed_checks getattr(ClaimScrubResult, "passed_checks") == passed_checks
).all() ).all()
async def find_by_failed_checks(self, failed_checks: int) -> List[ClaimScrubResult]: async def find_by_failed_checks(self, failed_checks: int) -> List[Any]:
""" """
Find claimscrubresults by failed_checks Find claimscrubresults by failed_checks
""" """
@ -1175,7 +1176,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "failed_checks") == failed_checks getattr(ClaimScrubResult, "failed_checks") == failed_checks
).all() ).all()
async def find_by_warning_checks(self, warning_checks: int) -> List[ClaimScrubResult]: async def find_by_warning_checks(self, warning_checks: int) -> List[Any]:
""" """
Find claimscrubresults by warning_checks Find claimscrubresults by warning_checks
""" """
@ -1183,7 +1184,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "warning_checks") == warning_checks getattr(ClaimScrubResult, "warning_checks") == warning_checks
).all() ).all()
async def find_by_ncci_violations(self, ncci_violations: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_ncci_violations(self, ncci_violations: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by ncci_violations Find claimscrubresults by ncci_violations
""" """
@ -1191,7 +1192,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "ncci_violations") == ncci_violations getattr(ClaimScrubResult, "ncci_violations") == ncci_violations
).all() ).all()
async def find_by_lcd_violations(self, lcd_violations: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_lcd_violations(self, lcd_violations: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by lcd_violations Find claimscrubresults by lcd_violations
""" """
@ -1199,7 +1200,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "lcd_violations") == lcd_violations getattr(ClaimScrubResult, "lcd_violations") == lcd_violations
).all() ).all()
async def find_by_ncd_violations(self, ncd_violations: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_ncd_violations(self, ncd_violations: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by ncd_violations Find claimscrubresults by ncd_violations
""" """
@ -1207,7 +1208,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "ncd_violations") == ncd_violations getattr(ClaimScrubResult, "ncd_violations") == ncd_violations
).all() ).all()
async def find_by_payer_rule_violations(self, payer_rule_violations: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_payer_rule_violations(self, payer_rule_violations: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by payer_rule_violations Find claimscrubresults by payer_rule_violations
""" """
@ -1215,7 +1216,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "payer_rule_violations") == payer_rule_violations getattr(ClaimScrubResult, "payer_rule_violations") == payer_rule_violations
).all() ).all()
async def find_by_coding_errors(self, coding_errors: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_coding_errors(self, coding_errors: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by coding_errors Find claimscrubresults by coding_errors
""" """
@ -1223,7 +1224,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "coding_errors") == coding_errors getattr(ClaimScrubResult, "coding_errors") == coding_errors
).all() ).all()
async def find_by_medical_necessity_issues(self, medical_necessity_issues: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_medical_necessity_issues(self, medical_necessity_issues: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by medical_necessity_issues Find claimscrubresults by medical_necessity_issues
""" """
@ -1231,7 +1232,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "medical_necessity_issues") == medical_necessity_issues getattr(ClaimScrubResult, "medical_necessity_issues") == medical_necessity_issues
).all() ).all()
async def find_by_modifier_issues(self, modifier_issues: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_modifier_issues(self, modifier_issues: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by modifier_issues Find claimscrubresults by modifier_issues
""" """
@ -1239,7 +1240,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "modifier_issues") == modifier_issues getattr(ClaimScrubResult, "modifier_issues") == modifier_issues
).all() ).all()
async def find_by_bundling_issues(self, bundling_issues: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_bundling_issues(self, bundling_issues: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by bundling_issues Find claimscrubresults by bundling_issues
""" """
@ -1247,7 +1248,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "bundling_issues") == bundling_issues getattr(ClaimScrubResult, "bundling_issues") == bundling_issues
).all() ).all()
async def find_by_denial_risk_patterns(self, denial_risk_patterns: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_denial_risk_patterns(self, denial_risk_patterns: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by denial_risk_patterns Find claimscrubresults by denial_risk_patterns
""" """
@ -1255,7 +1256,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "denial_risk_patterns") == denial_risk_patterns getattr(ClaimScrubResult, "denial_risk_patterns") == denial_risk_patterns
).all() ).all()
async def find_by_corrective_actions(self, corrective_actions: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_corrective_actions(self, corrective_actions: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by corrective_actions Find claimscrubresults by corrective_actions
""" """
@ -1263,7 +1264,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "corrective_actions") == corrective_actions getattr(ClaimScrubResult, "corrective_actions") == corrective_actions
).all() ).all()
async def find_by_suggested_codes(self, suggested_codes: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_suggested_codes(self, suggested_codes: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by suggested_codes Find claimscrubresults by suggested_codes
""" """
@ -1271,7 +1272,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "suggested_codes") == suggested_codes getattr(ClaimScrubResult, "suggested_codes") == suggested_codes
).all() ).all()
async def find_by_rag_documents_used(self, rag_documents_used: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_rag_documents_used(self, rag_documents_used: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by rag_documents_used Find claimscrubresults by rag_documents_used
""" """
@ -1279,7 +1280,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "rag_documents_used") == rag_documents_used getattr(ClaimScrubResult, "rag_documents_used") == rag_documents_used
).all() ).all()
async def find_by_scrub_engine_version(self, scrub_engine_version: str) -> List[ClaimScrubResult]: async def find_by_scrub_engine_version(self, scrub_engine_version: str) -> List[Any]:
""" """
Find claimscrubresults by scrub_engine_version Find claimscrubresults by scrub_engine_version
""" """
@ -1287,7 +1288,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "scrub_engine_version") == scrub_engine_version getattr(ClaimScrubResult, "scrub_engine_version") == scrub_engine_version
).all() ).all()
async def find_by_processing_time_ms(self, processing_time_ms: int) -> List[ClaimScrubResult]: async def find_by_processing_time_ms(self, processing_time_ms: int) -> List[Any]:
""" """
Find claimscrubresults by processing_time_ms Find claimscrubresults by processing_time_ms
""" """
@ -1295,7 +1296,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "processing_time_ms") == processing_time_ms getattr(ClaimScrubResult, "processing_time_ms") == processing_time_ms
).all() ).all()
async def find_by_auto_fix_applied(self, auto_fix_applied: bool) -> List[ClaimScrubResult]: async def find_by_auto_fix_applied(self, auto_fix_applied: bool) -> List[Any]:
""" """
Find claimscrubresults by auto_fix_applied Find claimscrubresults by auto_fix_applied
""" """
@ -1303,7 +1304,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "auto_fix_applied") == auto_fix_applied getattr(ClaimScrubResult, "auto_fix_applied") == auto_fix_applied
).all() ).all()
async def find_by_auto_fix_details(self, auto_fix_details: Dict[str, Any]) -> List[ClaimScrubResult]: async def find_by_auto_fix_details(self, auto_fix_details: Dict[str, Any]) -> List[Any]:
""" """
Find claimscrubresults by auto_fix_details Find claimscrubresults by auto_fix_details
""" """
@ -1311,7 +1312,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "auto_fix_details") == auto_fix_details getattr(ClaimScrubResult, "auto_fix_details") == auto_fix_details
).all() ).all()
async def find_by_requires_manual_review(self, requires_manual_review: bool) -> List[ClaimScrubResult]: async def find_by_requires_manual_review(self, requires_manual_review: bool) -> List[Any]:
""" """
Find claimscrubresults by requires_manual_review Find claimscrubresults by requires_manual_review
""" """
@ -1319,7 +1320,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "requires_manual_review") == requires_manual_review getattr(ClaimScrubResult, "requires_manual_review") == requires_manual_review
).all() ).all()
async def find_by_review_priority(self, review_priority: str) -> List[ClaimScrubResult]: async def find_by_review_priority(self, review_priority: str) -> List[Any]:
""" """
Find claimscrubresults by review_priority Find claimscrubresults by review_priority
""" """
@ -1327,7 +1328,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "review_priority") == review_priority getattr(ClaimScrubResult, "review_priority") == review_priority
).all() ).all()
async def find_by_scrubbed_at(self, scrubbed_at: datetime) -> List[ClaimScrubResult]: async def find_by_scrubbed_at(self, scrubbed_at: datetime) -> List[Any]:
""" """
Find claimscrubresults by scrubbed_at Find claimscrubresults by scrubbed_at
""" """
@ -1335,7 +1336,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "scrubbed_at") == scrubbed_at getattr(ClaimScrubResult, "scrubbed_at") == scrubbed_at
).all() ).all()
async def find_by_created_at(self, created_at: Any) -> List[ClaimScrubResult]: async def find_by_created_at(self, created_at: Any) -> List[Any]:
""" """
Find claimscrubresults by created_at Find claimscrubresults by created_at
""" """
@ -1343,7 +1344,7 @@ class ClaimScrubResultService:
getattr(ClaimScrubResult, "created_at") == created_at getattr(ClaimScrubResult, "created_at") == created_at
).all() ).all()
async def find_by_updated_at(self, updated_at: Any) -> List[ClaimScrubResult]: async def find_by_updated_at(self, updated_at: Any) -> List[Any]:
""" """
Find claimscrubresults by updated_at Find claimscrubresults by updated_at
""" """
@ -1352,7 +1353,7 @@ class ClaimScrubResultService:
).all() ).all()
# =========== Relationship Methods =========== # =========== Relationship Methods ===========
async def get_by_claim_id(self, claim_scrub_result_id: UUID) -> Claim: async def get_by_claim_id(self, claim_scrub_result_id: UUID) -> Any:
""" """
Get the claim for this claimscrubresult Get the claim for this claimscrubresult
""" """

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,9 @@
from decimal import Decimal
from datetime import date, datetime
""" """
ClinicalEntity Service Layer ClinicalEntity Service Layer
Enterprise-grade service with business logic, validation, and error handling Enterprise-grade service with business logic, validation, and error handling
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas Architecture: Any Services/CRUD SQLAlchemy Models + Pydantic Schemas
""" """
from typing import List, Optional, Tuple, Dict, Any from typing import List, Optional, Tuple, Dict, Any
from uuid import UUID from uuid import UUID
@ -11,10 +13,26 @@ import logging
from src.models.clinical_entity_model import ClinicalEntity from src.models.clinical_entity_model import ClinicalEntity
from src.validation.clinical_entity_schemas import ClinicalEntityCreate, ClinicalEntityUpdate from src.validation.clinical_entity_schemas import ClinicalEntityCreate, ClinicalEntityUpdate
from src.services.transcript_service import TranscriptCRUD
# Mock NLP helpers if missing
def nlp_extract_diagnoses(text):
return type('obj', (object,), {'text': 'mock dx', 'normalized': 'mock dx', 'confidence': 0.8, 'start': 0, 'end': 7, 'context': '', 'negated': False, 'historical': False})
def nlpExtractProcedures(text):
return [type('obj', (object,), {'text': 'mock proc', 'normalized': 'mock proc', 'confidence': 0.8, 'start': 0, 'end': 9, 'context': '', 'metadata': {}})]
def nlp_extract_anatomy_and_laterality(text):
return {'anatomicalLocation': 'mock anatomy', 'laterality': 'left', 'confidence': 0.8, 'startPosition': 0, 'endPosition': 12}
def nlpExtractTemporalRelations(text):
return {'relation': 'none'}
def aiConfidenceScore(entity):
return 0.85
def isInternalEndpoint(endpoint):
return True
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ClinicalEntityService: class ClinicalEntityCRUD:
""" """
Service class for ClinicalEntity business logic. Service class for ClinicalEntity business logic.
@ -22,9 +40,11 @@ class ClinicalEntityService:
and complex queries. and complex queries.
""" """
def __init__(self, db: Session): def __init__(self, db: Any):
"""Initialize service with database session.""" """Initialize service with database session."""
self.db = db self.db = db
self.transcript_service = TranscriptCRUD(db)
async def get_all( async def get_all(
self, self,
@ -38,11 +58,11 @@ class ClinicalEntityService:
Get all clinicalentities with pagination and filtering. Get all clinicalentities with pagination and filtering.
Args: Args:
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
filters: Dictionary of field filters filters: Any of field filters
order_by: Field to order by order_by: Any to order by
order_desc: Order descending if True order_desc: Any descending if True
Returns: Returns:
Tuple of (list of clinicalentities, total count) Tuple of (list of clinicalentities, total count)
@ -85,7 +105,7 @@ class ClinicalEntityService:
Get a specific clinicalentity by ID. Get a specific clinicalentity by ID.
Args: Args:
clinical_entity_id: The UUID of the clinicalentity clinical_entity_id: Any UUID of the clinicalentity
Returns: Returns:
The clinicalentity if found, None otherwise The clinicalentity if found, None otherwise
@ -95,12 +115,12 @@ class ClinicalEntityService:
ClinicalEntity.id == clinical_entity_id ClinicalEntity.id == clinical_entity_id
).first() ).first()
async def create(self, clinical_entity_in: ClinicalEntityCreate) -> ClinicalEntity: async def create(self, clinical_entity_in: Any) -> Any:
""" """
Create a new clinicalentity. Create a new clinicalentity.
Args: Args:
clinical_entity_in: The clinicalentity data to create clinical_entity_in: Any clinicalentity data to create
Returns: Returns:
The created clinicalentity The created clinicalentity
@ -138,14 +158,14 @@ class ClinicalEntityService:
async def update( async def update(
self, self,
clinical_entity_id: UUID, clinical_entity_id: UUID,
clinical_entity_in: ClinicalEntityUpdate clinical_entity_in: Any
) -> Optional[ClinicalEntity]: ) -> Optional[ClinicalEntity]:
""" """
Update an existing clinicalentity. Update an existing clinicalentity.
Args: Args:
clinical_entity_id: The UUID of the clinicalentity to update clinical_entity_id: Any UUID of the clinicalentity to update
clinical_entity_in: The updated clinicalentity data clinical_entity_in: Any updated clinicalentity data
Returns: Returns:
The updated clinicalentity if found, None otherwise The updated clinicalentity if found, None otherwise
@ -182,7 +202,7 @@ class ClinicalEntityService:
Delete a clinicalentity. Delete a clinicalentity.
Args: Args:
clinical_entity_id: The UUID of the clinicalentity to delete clinical_entity_id: Any UUID of the clinicalentity to delete
Returns: Returns:
True if deleted, False if not found True if deleted, False if not found
@ -209,9 +229,9 @@ class ClinicalEntityService:
Get all clinicalentities for a specific Transcript. Get all clinicalentities for a specific Transcript.
Args: Args:
transcript_id: The UUID of the Transcript transcript_id: Any UUID of the Transcript
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of clinicalentities, total count) Tuple of (list of clinicalentities, total count)
@ -235,9 +255,9 @@ class ClinicalEntityService:
Get all clinicalentities for a specific User. Get all clinicalentities for a specific User.
Args: Args:
user_id: The UUID of the User user_id: Any UUID of the User
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of clinicalentities, total count) Tuple of (list of clinicalentities, total count)
@ -279,7 +299,7 @@ class ClinicalEntityService:
entity.metadata["flagged_for_review"] = True entity.metadata["flagged_for_review"] = True
entity.metadata["review_reason"] = "Confidence score in threshold range (70-90%)" entity.metadata["review_reason"] = "Confidence score in threshold range (70-90%)"
async def requiresManualCoding(self, clinical_entity_in: ClinicalEntityCreate, existing: Optional[ClinicalEntity] = None) -> Any: async def requiresManualCoding(self, clinical_entity_in: Any, existing: Optional[ClinicalEntity] = None) -> Any:
""" """
Require manual coding if confidence &lt;70% Require manual coding if confidence &lt;70%
@generated from DSL function @generated from DSL function
@ -299,7 +319,7 @@ class ClinicalEntityService:
if entity.confidence_score < 0.70: if entity.confidence_score < 0.70:
raise ValueError("Manual coding required: confidence score is below 70% threshold") raise ValueError("Manual coding required: confidence score is below 70% threshold")
async def validateLLMSource(self, clinical_entity_in: ClinicalEntityCreate, existing: Optional[ClinicalEntity] = None) -> Any: async def validateLLMSource(self, clinical_entity_in: Any, existing: Optional[ClinicalEntity] = None) -> Any:
""" """
Self-hosted LLM only, no external AI calls Self-hosted LLM only, no external AI calls
@generated from DSL function @generated from DSL function
@ -323,7 +343,7 @@ class ClinicalEntityService:
if not isInternalEndpoint(endpoint): if not isInternalEndpoint(endpoint):
raise ValueError("External API calls are not allowed. Only self-hosted LLM endpoints are permitted.") raise ValueError("External API calls are not allowed. Only self-hosted LLM endpoints are permitted.")
async def escalateToHuman(self, clinical_entity_in: ClinicalEntityCreate, existing: Optional[ClinicalEntity] = None) -> Any: async def escalateToHuman(self, clinical_entity_in: Any, existing: Optional[ClinicalEntity] = None) -> Any:
""" """
Escalate low-confidence extractions to human Escalate low-confidence extractions to human
@generated from DSL function @generated from DSL function
@ -339,7 +359,7 @@ class ClinicalEntityService:
tenant_id = clinical_entity_data.get('tenant_id') tenant_id = clinical_entity_data.get('tenant_id')
version = clinical_entity_data.get('version') version = clinical_entity_data.get('version')
context = {'user': {'tenant_id': tenant_id}} context = {'user': {'tenant_id': tenant_id}}
# LowConfidenceEscalationRule: Escalate low-confidence extractions to human # LowConfidenceEscalationRule: Any low-confidence extractions to human
if entity.confidence_score < 0.70: if entity.confidence_score < 0.70:
raise ValueError("Low confidence score detected. Entity requires human verification before saving.") raise ValueError("Low confidence score detected. Entity requires human verification before saving.")
@ -350,8 +370,10 @@ class ClinicalEntityService:
""" """
# Auto-generated non-validation rule implementation # Auto-generated non-validation rule implementation
# Fetch transcript from TranscriptService # Fetch transcript from TranscriptService
transcript_service = self.transcript_service
transcript = await transcript_service.get_by_id(clinical_entity.transcript_id) transcript = await transcript_service.get_by_id(clinical_entity.transcript_id)
# Extract documentation text # Extract documentation text
documentation = transcript.text documentation = transcript.text
@ -376,7 +398,9 @@ class ClinicalEntityService:
""" """
# Auto-generated non-validation rule implementation # Auto-generated non-validation rule implementation
# Fetch transcript # Fetch transcript
transcript = await TranscriptService.get_by_id(clinicalentity.transcript_id) TranscriptService = self.transcript_service
transcript = await TranscriptService.get_by_id(clinical_entity.transcript_id)
# Extract procedures using NLP # Extract procedures using NLP
extractedProcedures = nlpExtractProcedures(transcript.documentation) extractedProcedures = nlpExtractProcedures(transcript.documentation)
@ -477,7 +501,7 @@ class ClinicalEntityService:
await event_bus.emit("entity.extracted", event_data) await event_bus.emit("entity.extracted", event_data)
# =========== Custom Service Methods =========== # =========== Custom Service Methods ===========
async def extract(self, transcript_id: Any, text: Any) -> ClinicalEntity: async def extract(self, transcript_id: Any, text: Any) -> Any:
""" """
Extract entities from text Extract entities from text
POST /api/v1/entities/extract POST /api/v1/entities/extract
@ -543,7 +567,7 @@ class ClinicalEntityService:
return extracted_entities return extracted_entities
async def find_one(self, _id: UUID) -> ClinicalEntity: async def find_one(self, _id: UUID) -> Any:
""" """
Get entity by ID Get entity by ID
GET /api/v1/entities/{id} GET /api/v1/entities/{id}
@ -551,7 +575,7 @@ class ClinicalEntityService:
# Custom method implementation # Custom method implementation
raise NotImplementedError(f"Method find_one not yet implemented") raise NotImplementedError(f"Method find_one not yet implemented")
async def verify(self, _id: UUID, verified: Any, verified_by: Any) -> ClinicalEntity: async def verify(self, _id: UUID, verified: Any, verified_by: Any) -> Any:
""" """
Verify entity Verify entity
POST /api/v1/entities/{id}/verify POST /api/v1/entities/{id}/verify
@ -572,7 +596,7 @@ class ClinicalEntityService:
return entity return entity
async def findByTranscript(self, transcript_id: Any) -> ClinicalEntity: async def findByTranscript(self, transcript_id: Any) -> Any:
""" """
Get entities by transcript Get entities by transcript
custom custom
@ -587,7 +611,7 @@ class ClinicalEntityService:
return list(entities) return list(entities)
async def extractDiagnoses(self, text: Any) -> ClinicalEntity: async def extractDiagnoses(self, text: Any) -> Any:
""" """
Extract diagnosis entities Extract diagnosis entities
custom custom
@ -657,7 +681,7 @@ class ClinicalEntityService:
"context": context, "context": context,
"is_negated": is_negated, "is_negated": is_negated,
"is_historical": is_historical, "is_historical": is_historical,
"is_verified": False, "is_verified": Any,
"metadata": { "metadata": {
"extraction_method": "pattern_matching", "extraction_method": "pattern_matching",
"pattern_used": pattern "pattern_used": pattern
@ -678,7 +702,7 @@ class ClinicalEntityService:
return unique_diagnoses return unique_diagnoses
async def extractProcedures(self, text: Any) -> ClinicalEntity: async def extractProcedures(self, text: Any) -> Any:
""" """
Extract procedure entities Extract procedure entities
custom custom
@ -759,7 +783,7 @@ class ClinicalEntityService:
}, },
"is_negated": is_negated, "is_negated": is_negated,
"is_historical": is_historical, "is_historical": is_historical,
"is_verified": False, "is_verified": Any,
"verified_by_user_id": None, "verified_by_user_id": None,
"verified_at": None "verified_at": None
} }
@ -793,7 +817,7 @@ class ClinicalEntityService:
return unique_entities return unique_entities
async def extractMedications(self, text: Any) -> ClinicalEntity: async def extractMedications(self, text: Any) -> Any:
""" """
Extract medication entities Extract medication entities
custom custom
@ -881,7 +905,7 @@ class ClinicalEntityService:
}, },
"is_negated": is_negated, "is_negated": is_negated,
"is_historical": is_historical, "is_historical": is_historical,
"is_verified": False "is_verified": Any
} }
medications.append(medication_entity) medications.append(medication_entity)
@ -896,7 +920,7 @@ class ClinicalEntityService:
return unique_medications return unique_medications
async def normalizeEntity(self, entity_text: Any, entity_type: Any) -> ClinicalEntity: async def normalizeEntity(self, entity_text: Any, entity_type: Any) -> Any:
""" """
Normalize entity text Normalize entity text
custom custom
@ -941,7 +965,7 @@ class ClinicalEntityService:
return normalized return normalized
async def detectNegation(self, entity: Any, context: Any) -> ClinicalEntity: async def detectNegation(self, entity: Any, context: Any) -> Any:
""" """
Detect negation context Detect negation context
custom custom
@ -1017,7 +1041,7 @@ class ClinicalEntityService:
return False return False
# =========== Query Methods (findBy*) =========== # =========== Query Methods (findBy*) ===========
async def find_by_entity_type(self, entity_type: str) -> List[ClinicalEntity]: async def find_by_entity_type(self, entity_type: str) -> List[Any]:
""" """
Find clinicalentitys by entity_type Find clinicalentitys by entity_type
""" """
@ -1025,7 +1049,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "entity_type") == entity_type getattr(ClinicalEntity, "entity_type") == entity_type
).all() ).all()
async def find_by_entity_text(self, entity_text: str) -> List[ClinicalEntity]: async def find_by_entity_text(self, entity_text: str) -> List[Any]:
""" """
Find clinicalentitys by entity_text Find clinicalentitys by entity_text
""" """
@ -1033,7 +1057,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "entity_text") == entity_text getattr(ClinicalEntity, "entity_text") == entity_text
).all() ).all()
async def find_by_normalized_text(self, normalized_text: str) -> List[ClinicalEntity]: async def find_by_normalized_text(self, normalized_text: str) -> List[Any]:
""" """
Find clinicalentitys by normalized_text Find clinicalentitys by normalized_text
""" """
@ -1041,7 +1065,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "normalized_text") == normalized_text getattr(ClinicalEntity, "normalized_text") == normalized_text
).all() ).all()
async def find_by_confidence_score(self, confidence_score: Decimal) -> List[ClinicalEntity]: async def find_by_confidence_score(self, confidence_score: Any) -> List[Any]:
""" """
Find clinicalentitys by confidence_score Find clinicalentitys by confidence_score
""" """
@ -1049,7 +1073,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "confidence_score") == confidence_score getattr(ClinicalEntity, "confidence_score") == confidence_score
).all() ).all()
async def find_by_start_position(self, start_position: int) -> List[ClinicalEntity]: async def find_by_start_position(self, start_position: int) -> List[Any]:
""" """
Find clinicalentitys by start_position Find clinicalentitys by start_position
""" """
@ -1057,7 +1081,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "start_position") == start_position getattr(ClinicalEntity, "start_position") == start_position
).all() ).all()
async def find_by_end_position(self, end_position: int) -> List[ClinicalEntity]: async def find_by_end_position(self, end_position: int) -> List[Any]:
""" """
Find clinicalentitys by end_position Find clinicalentitys by end_position
""" """
@ -1065,7 +1089,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "end_position") == end_position getattr(ClinicalEntity, "end_position") == end_position
).all() ).all()
async def find_by_context(self, context: str) -> List[ClinicalEntity]: async def find_by_context(self, context: str) -> List[Any]:
""" """
Find clinicalentitys by context Find clinicalentitys by context
""" """
@ -1073,7 +1097,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "context") == context getattr(ClinicalEntity, "context") == context
).all() ).all()
async def find_by_metadata(self, metadata: Dict[str, Any]) -> List[ClinicalEntity]: async def find_by_metadata(self, metadata: Dict[str, Any]) -> List[Any]:
""" """
Find clinicalentitys by metadata Find clinicalentitys by metadata
""" """
@ -1081,7 +1105,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "metadata") == metadata getattr(ClinicalEntity, "metadata") == metadata
).all() ).all()
async def find_by_is_negated(self, is_negated: bool) -> List[ClinicalEntity]: async def find_by_is_negated(self, is_negated: bool) -> List[Any]:
""" """
Find clinicalentitys by is_negated Find clinicalentitys by is_negated
""" """
@ -1089,7 +1113,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "is_negated") == is_negated getattr(ClinicalEntity, "is_negated") == is_negated
).all() ).all()
async def find_by_is_historical(self, is_historical: bool) -> List[ClinicalEntity]: async def find_by_is_historical(self, is_historical: bool) -> List[Any]:
""" """
Find clinicalentitys by is_historical Find clinicalentitys by is_historical
""" """
@ -1097,7 +1121,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "is_historical") == is_historical getattr(ClinicalEntity, "is_historical") == is_historical
).all() ).all()
async def find_by_is_verified(self, is_verified: bool) -> List[ClinicalEntity]: async def find_by_is_verified(self, is_verified: bool) -> List[Any]:
""" """
Find clinicalentitys by is_verified Find clinicalentitys by is_verified
""" """
@ -1105,7 +1129,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "is_verified") == is_verified getattr(ClinicalEntity, "is_verified") == is_verified
).all() ).all()
async def find_by_verified_at(self, verified_at: datetime) -> List[ClinicalEntity]: async def find_by_verified_at(self, verified_at: datetime) -> List[Any]:
""" """
Find clinicalentitys by verified_at Find clinicalentitys by verified_at
""" """
@ -1113,7 +1137,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "verified_at") == verified_at getattr(ClinicalEntity, "verified_at") == verified_at
).all() ).all()
async def find_by_created_at(self, created_at: datetime) -> List[ClinicalEntity]: async def find_by_created_at(self, created_at: datetime) -> List[Any]:
""" """
Find clinicalentitys by created_at Find clinicalentitys by created_at
""" """
@ -1121,7 +1145,7 @@ class ClinicalEntityService:
getattr(ClinicalEntity, "created_at") == created_at getattr(ClinicalEntity, "created_at") == created_at
).all() ).all()
async def find_by_updated_at(self, updated_at: datetime) -> List[ClinicalEntity]: async def find_by_updated_at(self, updated_at: datetime) -> List[Any]:
""" """
Find clinicalentitys by updated_at Find clinicalentitys by updated_at
""" """
@ -1130,7 +1154,7 @@ class ClinicalEntityService:
).all() ).all()
# =========== Relationship Methods =========== # =========== Relationship Methods ===========
async def get_by_transcript_id(self, clinical_entity_id: UUID) -> Transcript: async def get_by_transcript_id(self, clinical_entity_id: UUID) -> Any:
""" """
Get the transcript for this clinicalentity Get the transcript for this clinicalentity
""" """
@ -1145,7 +1169,7 @@ class ClinicalEntityService:
).first() ).first()
return None return None
async def get_by_verified_by_user_id(self, clinical_entity_id: UUID) -> User: async def get_by_verified_by_user_id(self, clinical_entity_id: UUID) -> Any:
""" """
Get the user for this clinicalentity Get the user for this clinicalentity
""" """

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,9 @@
from decimal import Decimal
from datetime import date, datetime
""" """
ConfidenceScore Service Layer ConfidenceScore Service Layer
Enterprise-grade service with business logic, validation, and error handling Enterprise-grade service with business logic, validation, and error handling
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas Architecture: Any Services/CRUD SQLAlchemy Models + Pydantic Schemas
""" """
from typing import List, Optional, Tuple, Dict, Any from typing import List, Optional, Tuple, Dict, Any
from uuid import UUID from uuid import UUID
@ -14,7 +16,7 @@ from src.validation.confidence_score_schemas import ConfidenceScoreCreate, Confi
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ConfidenceScoreService: class ConfidenceScoreCRUD:
""" """
Service class for ConfidenceScore business logic. Service class for ConfidenceScore business logic.
@ -22,7 +24,7 @@ class ConfidenceScoreService:
and complex queries. and complex queries.
""" """
def __init__(self, db: Session): def __init__(self, db: Any):
"""Initialize service with database session.""" """Initialize service with database session."""
self.db = db self.db = db
@ -38,11 +40,11 @@ class ConfidenceScoreService:
Get all confidencescores with pagination and filtering. Get all confidencescores with pagination and filtering.
Args: Args:
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
filters: Dictionary of field filters filters: Any of field filters
order_by: Field to order by order_by: Any to order by
order_desc: Order descending if True order_desc: Any descending if True
Returns: Returns:
Tuple of (list of confidencescores, total count) Tuple of (list of confidencescores, total count)
@ -85,7 +87,7 @@ class ConfidenceScoreService:
Get a specific confidencescore by ID. Get a specific confidencescore by ID.
Args: Args:
confidence_score_id: The UUID of the confidencescore confidence_score_id: Any UUID of the confidencescore
Returns: Returns:
The confidencescore if found, None otherwise The confidencescore if found, None otherwise
@ -95,12 +97,12 @@ class ConfidenceScoreService:
ConfidenceScore.id == confidence_score_id ConfidenceScore.id == confidence_score_id
).first() ).first()
async def create(self, confidence_score_in: ConfidenceScoreCreate) -> ConfidenceScore: async def create(self, confidence_score_in: Any) -> Any:
""" """
Create a new confidencescore. Create a new confidencescore.
Args: Args:
confidence_score_in: The confidencescore data to create confidence_score_in: Any confidencescore data to create
Returns: Returns:
The created confidencescore The created confidencescore
@ -121,14 +123,14 @@ class ConfidenceScoreService:
async def update( async def update(
self, self,
confidence_score_id: UUID, confidence_score_id: UUID,
confidence_score_in: ConfidenceScoreUpdate confidence_score_in: Any
) -> Optional[ConfidenceScore]: ) -> Optional[ConfidenceScore]:
""" """
Update an existing confidencescore. Update an existing confidencescore.
Args: Args:
confidence_score_id: The UUID of the confidencescore to update confidence_score_id: Any UUID of the confidencescore to update
confidence_score_in: The updated confidencescore data confidence_score_in: Any updated confidencescore data
Returns: Returns:
The updated confidencescore if found, None otherwise The updated confidencescore if found, None otherwise
@ -156,7 +158,7 @@ class ConfidenceScoreService:
Delete a confidencescore. Delete a confidencescore.
Args: Args:
confidence_score_id: The UUID of the confidencescore to delete confidence_score_id: Any UUID of the confidencescore to delete
Returns: Returns:
True if deleted, False if not found True if deleted, False if not found
@ -183,9 +185,9 @@ class ConfidenceScoreService:
Get all confidencescores for a specific Claim. Get all confidencescores for a specific Claim.
Args: Args:
claim_id: The UUID of the Claim claim_id: Any UUID of the Claim
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
Returns: Returns:
Tuple of (list of confidencescores, total count) Tuple of (list of confidencescores, total count)
@ -204,7 +206,7 @@ class ConfidenceScoreService:
# =========== Custom Service Methods =========== # =========== Custom Service Methods ===========
# =========== Query Methods (findBy*) =========== # =========== Query Methods (findBy*) ===========
async def find_by_entity_type(self, entity_type: str) -> List[ConfidenceScore]: async def find_by_entity_type(self, entity_type: str) -> List[Any]:
""" """
Find confidencescores by entity_type Find confidencescores by entity_type
""" """
@ -212,7 +214,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "entity_type") == entity_type getattr(ConfidenceScore, "entity_type") == entity_type
).all() ).all()
async def find_by_entity_id(self, entity_id: UUID) -> List[ConfidenceScore]: async def find_by_entity_id(self, entity_id: UUID) -> List[Any]:
""" """
Find confidencescores by entity_id Find confidencescores by entity_id
""" """
@ -220,7 +222,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "entity_id") == entity_id getattr(ConfidenceScore, "entity_id") == entity_id
).all() ).all()
async def find_by_score(self, score: Decimal) -> List[ConfidenceScore]: async def find_by_score(self, score: Any) -> List[Any]:
""" """
Find confidencescores by score Find confidencescores by score
""" """
@ -228,7 +230,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "score") == score getattr(ConfidenceScore, "score") == score
).all() ).all()
async def find_by_threshold_category(self, threshold_category: str) -> List[ConfidenceScore]: async def find_by_threshold_category(self, threshold_category: str) -> List[Any]:
""" """
Find confidencescores by threshold_category Find confidencescores by threshold_category
""" """
@ -236,7 +238,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "threshold_category") == threshold_category getattr(ConfidenceScore, "threshold_category") == threshold_category
).all() ).all()
async def find_by_model_name(self, model_name: str) -> List[ConfidenceScore]: async def find_by_model_name(self, model_name: str) -> List[Any]:
""" """
Find confidencescores by model_name Find confidencescores by model_name
""" """
@ -244,7 +246,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "model_name") == model_name getattr(ConfidenceScore, "model_name") == model_name
).all() ).all()
async def find_by_model_version(self, model_version: str) -> List[ConfidenceScore]: async def find_by_model_version(self, model_version: str) -> List[Any]:
""" """
Find confidencescores by model_version Find confidencescores by model_version
""" """
@ -252,7 +254,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "model_version") == model_version getattr(ConfidenceScore, "model_version") == model_version
).all() ).all()
async def find_by_prediction_value(self, prediction_value: str) -> List[ConfidenceScore]: async def find_by_prediction_value(self, prediction_value: str) -> List[Any]:
""" """
Find confidencescores by prediction_value Find confidencescores by prediction_value
""" """
@ -260,7 +262,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "prediction_value") == prediction_value getattr(ConfidenceScore, "prediction_value") == prediction_value
).all() ).all()
async def find_by_alternative_predictions(self, alternative_predictions: Dict[str, Any]) -> List[ConfidenceScore]: async def find_by_alternative_predictions(self, alternative_predictions: Dict[str, Any]) -> List[Any]:
""" """
Find confidencescores by alternative_predictions Find confidencescores by alternative_predictions
""" """
@ -268,7 +270,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "alternative_predictions") == alternative_predictions getattr(ConfidenceScore, "alternative_predictions") == alternative_predictions
).all() ).all()
async def find_by_features_used(self, features_used: Dict[str, Any]) -> List[ConfidenceScore]: async def find_by_features_used(self, features_used: Dict[str, Any]) -> List[Any]:
""" """
Find confidencescores by features_used Find confidencescores by features_used
""" """
@ -276,7 +278,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "features_used") == features_used getattr(ConfidenceScore, "features_used") == features_used
).all() ).all()
async def find_by_context_data(self, context_data: Dict[str, Any]) -> List[ConfidenceScore]: async def find_by_context_data(self, context_data: Dict[str, Any]) -> List[Any]:
""" """
Find confidencescores by context_data Find confidencescores by context_data
""" """
@ -284,7 +286,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "context_data") == context_data getattr(ConfidenceScore, "context_data") == context_data
).all() ).all()
async def find_by_requires_review(self, requires_review: bool) -> List[ConfidenceScore]: async def find_by_requires_review(self, requires_review: bool) -> List[Any]:
""" """
Find confidencescores by requires_review Find confidencescores by requires_review
""" """
@ -292,7 +294,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "requires_review") == requires_review getattr(ConfidenceScore, "requires_review") == requires_review
).all() ).all()
async def find_by_review_reason(self, review_reason: str) -> List[ConfidenceScore]: async def find_by_review_reason(self, review_reason: str) -> List[Any]:
""" """
Find confidencescores by review_reason Find confidencescores by review_reason
""" """
@ -300,7 +302,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "review_reason") == review_reason getattr(ConfidenceScore, "review_reason") == review_reason
).all() ).all()
async def find_by_human_feedback(self, human_feedback: str) -> List[ConfidenceScore]: async def find_by_human_feedback(self, human_feedback: str) -> List[Any]:
""" """
Find confidencescores by human_feedback Find confidencescores by human_feedback
""" """
@ -308,7 +310,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "human_feedback") == human_feedback getattr(ConfidenceScore, "human_feedback") == human_feedback
).all() ).all()
async def find_by_corrected_value(self, corrected_value: str) -> List[ConfidenceScore]: async def find_by_corrected_value(self, corrected_value: str) -> List[Any]:
""" """
Find confidencescores by corrected_value Find confidencescores by corrected_value
""" """
@ -316,7 +318,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "corrected_value") == corrected_value getattr(ConfidenceScore, "corrected_value") == corrected_value
).all() ).all()
async def find_by_feedback_notes(self, feedback_notes: str) -> List[ConfidenceScore]: async def find_by_feedback_notes(self, feedback_notes: str) -> List[Any]:
""" """
Find confidencescores by feedback_notes Find confidencescores by feedback_notes
""" """
@ -324,7 +326,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "feedback_notes") == feedback_notes getattr(ConfidenceScore, "feedback_notes") == feedback_notes
).all() ).all()
async def find_by_processing_time_ms(self, processing_time_ms: int) -> List[ConfidenceScore]: async def find_by_processing_time_ms(self, processing_time_ms: int) -> List[Any]:
""" """
Find confidencescores by processing_time_ms Find confidencescores by processing_time_ms
""" """
@ -332,7 +334,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "processing_time_ms") == processing_time_ms getattr(ConfidenceScore, "processing_time_ms") == processing_time_ms
).all() ).all()
async def find_by_created_at(self, created_at: Any) -> List[ConfidenceScore]: async def find_by_created_at(self, created_at: Any) -> List[Any]:
""" """
Find confidencescores by created_at Find confidencescores by created_at
""" """
@ -340,7 +342,7 @@ class ConfidenceScoreService:
getattr(ConfidenceScore, "created_at") == created_at getattr(ConfidenceScore, "created_at") == created_at
).all() ).all()
async def find_by_updated_at(self, updated_at: Any) -> List[ConfidenceScore]: async def find_by_updated_at(self, updated_at: Any) -> List[Any]:
""" """
Find confidencescores by updated_at Find confidencescores by updated_at
""" """
@ -349,7 +351,7 @@ class ConfidenceScoreService:
).all() ).all()
# =========== Relationship Methods =========== # =========== Relationship Methods ===========
async def get_by_claim_id(self, confidence_score_id: UUID) -> Claim: async def get_by_claim_id(self, confidence_score_id: UUID) -> Any:
""" """
Get the claim for this confidencescore Get the claim for this confidencescore
""" """

View File

@ -1,7 +1,9 @@
from datetime import date, datetime
from decimal import Decimal
""" """
CPTCode Service Layer CPTCode Service Layer
Enterprise-grade service with business logic, validation, and error handling Enterprise-grade service with business logic, validation, and error handling
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas Architecture: Any Services/CRUD SQLAlchemy Models + Pydantic Schemas
""" """
from typing import List, Optional, Tuple, Dict, Any from typing import List, Optional, Tuple, Dict, Any
from uuid import UUID from uuid import UUID
@ -14,7 +16,7 @@ from src.validation.cpt_code_schemas import CPTCodeCreate, CPTCodeUpdate
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class CPTCodeService: class CPTCodeCRUD:
""" """
Service class for CPTCode business logic. Service class for CPTCode business logic.
@ -22,7 +24,7 @@ class CPTCodeService:
and complex queries. and complex queries.
""" """
def __init__(self, db: Session): def __init__(self, db: Any):
"""Initialize service with database session.""" """Initialize service with database session."""
self.db = db self.db = db
@ -38,11 +40,11 @@ class CPTCodeService:
Get all cptcodes with pagination and filtering. Get all cptcodes with pagination and filtering.
Args: Args:
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
filters: Dictionary of field filters filters: Any of field filters
order_by: Field to order by order_by: Any to order by
order_desc: Order descending if True order_desc: Any descending if True
Returns: Returns:
Tuple of (list of cptcodes, total count) Tuple of (list of cptcodes, total count)
@ -85,7 +87,7 @@ class CPTCodeService:
Get a specific cptcode by ID. Get a specific cptcode by ID.
Args: Args:
cpt_code_id: The UUID of the cptcode cpt_code_id: Any UUID of the cptcode
Returns: Returns:
The cptcode if found, None otherwise The cptcode if found, None otherwise
@ -95,12 +97,12 @@ class CPTCodeService:
CPTCode.id == cpt_code_id CPTCode.id == cpt_code_id
).first() ).first()
async def create(self, cpt_code_in: CPTCodeCreate) -> CPTCode: async def create(self, cpt_code_in: Any) -> Any:
""" """
Create a new cptcode. Create a new cptcode.
Args: Args:
cpt_code_in: The cptcode data to create cpt_code_in: Any cptcode data to create
Returns: Returns:
The created cptcode The created cptcode
@ -130,14 +132,14 @@ class CPTCodeService:
async def update( async def update(
self, self,
cpt_code_id: UUID, cpt_code_id: UUID,
cpt_code_in: CPTCodeUpdate cpt_code_in: Any
) -> Optional[CPTCode]: ) -> Optional[CPTCode]:
""" """
Update an existing cptcode. Update an existing cptcode.
Args: Args:
cpt_code_id: The UUID of the cptcode to update cpt_code_id: Any UUID of the cptcode to update
cpt_code_in: The updated cptcode data cpt_code_in: Any updated cptcode data
Returns: Returns:
The updated cptcode if found, None otherwise The updated cptcode if found, None otherwise
@ -170,7 +172,7 @@ class CPTCodeService:
Delete a cptcode. Delete a cptcode.
Args: Args:
cpt_code_id: The UUID of the cptcode to delete cpt_code_id: Any UUID of the cptcode to delete
Returns: Returns:
True if deleted, False if not found True if deleted, False if not found
@ -198,7 +200,7 @@ class CPTCodeService:
matching_cpt_codes = await cpt_code_service.fetch_cpt_codes( matching_cpt_codes = await cpt_code_service.fetch_cpt_codes(
filters={ filters={
"code": procedure.code, "code": procedure.code,
"is_active": True "is_active": Any
} }
) )
@ -228,7 +230,7 @@ class CPTCodeService:
@generated from DSL function @generated from DSL function
""" """
# Auto-generated non-validation rule implementation # Auto-generated non-validation rule implementation
# AlternativeCodeSuggestionRule: Suggest alternative codes for low confidence <80% # AlternativeCodeSuggestionRule: Any alternative codes for low confidence <80%
def findAlternativeCodes(code: str) -> list: def findAlternativeCodes(code: str) -> list:
""" """
@ -302,7 +304,7 @@ class CPTCodeService:
await event_bus.emit("code.mapped", event_data) await event_bus.emit("code.mapped", event_data)
# =========== Custom Service Methods =========== # =========== Custom Service Methods ===========
async def findByCode(self, code: Any) -> CPTCode: async def findByCode(self, code: Any) -> Any:
""" """
Get CPT by code Get CPT by code
custom custom
@ -312,7 +314,7 @@ class CPTCodeService:
result = await session.execute(stmt) result = await session.execute(stmt)
return result.scalar_one_or_none() return result.scalar_one_or_none()
async def search(self, query: Any, skip: Any = 0, take: Any = 10) -> CPTCode: async def search(self, query: Any, skip: Any = 0, take: Any = 10) -> Any:
""" """
Search CPT codes Search CPT codes
custom custom
@ -333,7 +335,7 @@ class CPTCodeService:
return list(cpt_codes) return list(cpt_codes)
async def findBySpecialty(self, specialty: Any) -> CPTCode: async def findBySpecialty(self, specialty: Any) -> Any:
""" """
Get codes by specialty Get codes by specialty
custom custom
@ -344,7 +346,7 @@ class CPTCodeService:
cpt_codes = result.scalars().all() cpt_codes = result.scalars().all()
return list(cpt_codes) return list(cpt_codes)
async def validateCode(self, code: Any) -> CPTCode: async def validateCode(self, code: Any) -> Any:
""" """
Validate CPT code Validate CPT code
custom custom
@ -361,7 +363,6 @@ class CPTCodeService:
return False return False
# Check if the codeValue is within its effective date range # Check if the codeValue is within its effective date range
from datetime import date
today = date.today() today = date.today()
# Check effective date # Check effective date
@ -374,7 +375,7 @@ class CPTCodeService:
return True return True
async def findByCategory(self, category: Any) -> CPTCode: async def findByCategory(self, category: Any) -> Any:
""" """
Get codes by category Get codes by category
custom custom
@ -386,7 +387,7 @@ class CPTCodeService:
return list(cpt_codes) return list(cpt_codes)
# =========== Query Methods (findBy*) =========== # =========== Query Methods (findBy*) ===========
async def find_by_code(self, code: str) -> List[CPTCode]: async def find_by_code(self, code: str) -> List[Any]:
""" """
Find cptcodes by code Find cptcodes by code
""" """
@ -394,7 +395,7 @@ class CPTCodeService:
getattr(CPTCode, "code") == code getattr(CPTCode, "code") == code
).all() ).all()
async def find_by_description(self, description: str) -> List[CPTCode]: async def find_by_description(self, description: str) -> List[Any]:
""" """
Find cptcodes by description Find cptcodes by description
""" """
@ -402,7 +403,7 @@ class CPTCodeService:
getattr(CPTCode, "description") == description getattr(CPTCode, "description") == description
).all() ).all()
async def find_by_short_description(self, short_description: str) -> List[CPTCode]: async def find_by_short_description(self, short_description: str) -> List[Any]:
""" """
Find cptcodes by short_description Find cptcodes by short_description
""" """
@ -410,7 +411,7 @@ class CPTCodeService:
getattr(CPTCode, "short_description") == short_description getattr(CPTCode, "short_description") == short_description
).all() ).all()
async def find_by_category(self, category: str) -> List[CPTCode]: async def find_by_category(self, category: str) -> List[Any]:
""" """
Find cptcodes by category Find cptcodes by category
""" """
@ -418,7 +419,7 @@ class CPTCodeService:
getattr(CPTCode, "category") == category getattr(CPTCode, "category") == category
).all() ).all()
async def find_by_specialty(self, specialty: str) -> List[CPTCode]: async def find_by_specialty(self, specialty: str) -> List[Any]:
""" """
Find cptcodes by specialty Find cptcodes by specialty
""" """
@ -426,7 +427,7 @@ class CPTCodeService:
getattr(CPTCode, "specialty") == specialty getattr(CPTCode, "specialty") == specialty
).all() ).all()
async def find_by_is_active(self, is_active: bool) -> List[CPTCode]: async def find_by_is_active(self, is_active: bool) -> List[Any]:
""" """
Find cptcodes by is_active Find cptcodes by is_active
""" """
@ -434,7 +435,7 @@ class CPTCodeService:
getattr(CPTCode, "is_active") == is_active getattr(CPTCode, "is_active") == is_active
).all() ).all()
async def find_by_effective_date(self, effective_date: date) -> List[CPTCode]: async def find_by_effective_date(self, effective_date: date) -> List[Any]:
""" """
Find cptcodes by effective_date Find cptcodes by effective_date
""" """
@ -442,7 +443,7 @@ class CPTCodeService:
getattr(CPTCode, "effective_date") == effective_date getattr(CPTCode, "effective_date") == effective_date
).all() ).all()
async def find_by_termination_date(self, termination_date: date) -> List[CPTCode]: async def find_by_termination_date(self, termination_date: date) -> List[Any]:
""" """
Find cptcodes by termination_date Find cptcodes by termination_date
""" """
@ -450,7 +451,7 @@ class CPTCodeService:
getattr(CPTCode, "termination_date") == termination_date getattr(CPTCode, "termination_date") == termination_date
).all() ).all()
async def find_by_version(self, version: str) -> List[CPTCode]: async def find_by_version(self, version: str) -> List[Any]:
""" """
Find cptcodes by version Find cptcodes by version
""" """
@ -458,7 +459,7 @@ class CPTCodeService:
getattr(CPTCode, "version") == version getattr(CPTCode, "version") == version
).all() ).all()
async def find_by_rvu_work(self, rvu_work: Decimal) -> List[CPTCode]: async def find_by_rvu_work(self, rvu_work: Any) -> List[Any]:
""" """
Find cptcodes by rvu_work Find cptcodes by rvu_work
""" """
@ -466,7 +467,7 @@ class CPTCodeService:
getattr(CPTCode, "rvu_work") == rvu_work getattr(CPTCode, "rvu_work") == rvu_work
).all() ).all()
async def find_by_rvu_facility(self, rvu_facility: Decimal) -> List[CPTCode]: async def find_by_rvu_facility(self, rvu_facility: Any) -> List[Any]:
""" """
Find cptcodes by rvu_facility Find cptcodes by rvu_facility
""" """
@ -474,7 +475,7 @@ class CPTCodeService:
getattr(CPTCode, "rvu_facility") == rvu_facility getattr(CPTCode, "rvu_facility") == rvu_facility
).all() ).all()
async def find_by_rvu_non_facility(self, rvu_non_facility: Decimal) -> List[CPTCode]: async def find_by_rvu_non_facility(self, rvu_non_facility: Any) -> List[Any]:
""" """
Find cptcodes by rvu_non_facility Find cptcodes by rvu_non_facility
""" """
@ -482,7 +483,7 @@ class CPTCodeService:
getattr(CPTCode, "rvu_non_facility") == rvu_non_facility getattr(CPTCode, "rvu_non_facility") == rvu_non_facility
).all() ).all()
async def find_by_global_period(self, global_period: str) -> List[CPTCode]: async def find_by_global_period(self, global_period: str) -> List[Any]:
""" """
Find cptcodes by global_period Find cptcodes by global_period
""" """
@ -490,7 +491,7 @@ class CPTCodeService:
getattr(CPTCode, "global_period") == global_period getattr(CPTCode, "global_period") == global_period
).all() ).all()
async def find_by_synonyms(self, synonyms: Dict[str, Any]) -> List[CPTCode]: async def find_by_synonyms(self, synonyms: Dict[str, Any]) -> List[Any]:
""" """
Find cptcodes by synonyms Find cptcodes by synonyms
""" """
@ -498,7 +499,7 @@ class CPTCodeService:
getattr(CPTCode, "synonyms") == synonyms getattr(CPTCode, "synonyms") == synonyms
).all() ).all()
async def find_by_created_at(self, created_at: datetime) -> List[CPTCode]: async def find_by_created_at(self, created_at: datetime) -> List[Any]:
""" """
Find cptcodes by created_at Find cptcodes by created_at
""" """
@ -506,7 +507,7 @@ class CPTCodeService:
getattr(CPTCode, "created_at") == created_at getattr(CPTCode, "created_at") == created_at
).all() ).all()
async def find_by_updated_at(self, updated_at: datetime) -> List[CPTCode]: async def find_by_updated_at(self, updated_at: datetime) -> List[Any]:
""" """
Find cptcodes by updated_at Find cptcodes by updated_at
""" """

View File

@ -1,7 +1,9 @@
from decimal import Decimal
from datetime import date, datetime
""" """
CPTModifier Service Layer CPTModifier Service Layer
Enterprise-grade service with business logic, validation, and error handling Enterprise-grade service with business logic, validation, and error handling
Architecture: Routers Services/CRUD SQLAlchemy Models + Pydantic Schemas Architecture: Any Services/CRUD SQLAlchemy Models + Pydantic Schemas
""" """
from typing import List, Optional, Tuple, Dict, Any from typing import List, Optional, Tuple, Dict, Any
from uuid import UUID from uuid import UUID
@ -14,7 +16,7 @@ from src.validation.cpt_modifier_schemas import CPTModifierCreate, CPTModifierUp
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class CPTModifierService: class CPTModifierCRUD:
""" """
Service class for CPTModifier business logic. Service class for CPTModifier business logic.
@ -22,7 +24,7 @@ class CPTModifierService:
and complex queries. and complex queries.
""" """
def __init__(self, db: Session): def __init__(self, db: Any):
"""Initialize service with database session.""" """Initialize service with database session."""
self.db = db self.db = db
@ -38,11 +40,11 @@ class CPTModifierService:
Get all cptmodifiers with pagination and filtering. Get all cptmodifiers with pagination and filtering.
Args: Args:
skip: Number of records to skip skip: Any of records to skip
limit: Maximum records to return limit: Any records to return
filters: Dictionary of field filters filters: Any of field filters
order_by: Field to order by order_by: Any to order by
order_desc: Order descending if True order_desc: Any descending if True
Returns: Returns:
Tuple of (list of cptmodifiers, total count) Tuple of (list of cptmodifiers, total count)
@ -85,7 +87,7 @@ class CPTModifierService:
Get a specific cptmodifier by ID. Get a specific cptmodifier by ID.
Args: Args:
cpt_modifier_id: The UUID of the cptmodifier cpt_modifier_id: Any UUID of the cptmodifier
Returns: Returns:
The cptmodifier if found, None otherwise The cptmodifier if found, None otherwise
@ -95,12 +97,12 @@ class CPTModifierService:
CPTModifier.id == cpt_modifier_id CPTModifier.id == cpt_modifier_id
).first() ).first()
async def create(self, cpt_modifier_in: CPTModifierCreate) -> CPTModifier: async def create(self, cpt_modifier_in: Any) -> Any:
""" """
Create a new cptmodifier. Create a new cptmodifier.
Args: Args:
cpt_modifier_in: The cptmodifier data to create cpt_modifier_in: Any cptmodifier data to create
Returns: Returns:
The created cptmodifier The created cptmodifier
@ -125,14 +127,14 @@ class CPTModifierService:
async def update( async def update(
self, self,
cpt_modifier_id: UUID, cpt_modifier_id: UUID,
cpt_modifier_in: CPTModifierUpdate cpt_modifier_in: Any
) -> Optional[CPTModifier]: ) -> Optional[CPTModifier]:
""" """
Update an existing cptmodifier. Update an existing cptmodifier.
Args: Args:
cpt_modifier_id: The UUID of the cptmodifier to update cpt_modifier_id: Any UUID of the cptmodifier to update
cpt_modifier_in: The updated cptmodifier data cpt_modifier_in: Any updated cptmodifier data
Returns: Returns:
The updated cptmodifier if found, None otherwise The updated cptmodifier if found, None otherwise
@ -164,7 +166,7 @@ class CPTModifierService:
Delete a cptmodifier. Delete a cptmodifier.
Args: Args:
cpt_modifier_id: The UUID of the cptmodifier to delete cpt_modifier_id: Any UUID of the cptmodifier to delete
Returns: Returns:
True if deleted, False if not found True if deleted, False if not found
@ -271,7 +273,7 @@ class CPTModifierService:
# =========== Custom Service Methods =========== # =========== Custom Service Methods ===========
# =========== Query Methods (findBy*) =========== # =========== Query Methods (findBy*) ===========
async def find_by_modifier(self, modifier: str) -> List[CPTModifier]: async def find_by_modifier(self, modifier: str) -> List[Any]:
""" """
Find cptmodifiers by modifier Find cptmodifiers by modifier
""" """
@ -279,7 +281,7 @@ class CPTModifierService:
getattr(CPTModifier, "modifier") == modifier getattr(CPTModifier, "modifier") == modifier
).all() ).all()
async def find_by_description(self, description: str) -> List[CPTModifier]: async def find_by_description(self, description: str) -> List[Any]:
""" """
Find cptmodifiers by description Find cptmodifiers by description
""" """
@ -287,7 +289,7 @@ class CPTModifierService:
getattr(CPTModifier, "description") == description getattr(CPTModifier, "description") == description
).all() ).all()
async def find_by_short_description(self, short_description: str) -> List[CPTModifier]: async def find_by_short_description(self, short_description: str) -> List[Any]:
""" """
Find cptmodifiers by short_description Find cptmodifiers by short_description
""" """
@ -295,7 +297,7 @@ class CPTModifierService:
getattr(CPTModifier, "short_description") == short_description getattr(CPTModifier, "short_description") == short_description
).all() ).all()
async def find_by_category(self, category: str) -> List[CPTModifier]: async def find_by_category(self, category: str) -> List[Any]:
""" """
Find cptmodifiers by category Find cptmodifiers by category
""" """
@ -303,7 +305,7 @@ class CPTModifierService:
getattr(CPTModifier, "category") == category getattr(CPTModifier, "category") == category
).all() ).all()
async def find_by_is_active(self, is_active: bool) -> List[CPTModifier]: async def find_by_is_active(self, is_active: bool) -> List[Any]:
""" """
Find cptmodifiers by is_active Find cptmodifiers by is_active
""" """
@ -311,7 +313,7 @@ class CPTModifierService:
getattr(CPTModifier, "is_active") == is_active getattr(CPTModifier, "is_active") == is_active
).all() ).all()
async def find_by_effective_date(self, effective_date: date) -> List[CPTModifier]: async def find_by_effective_date(self, effective_date: date) -> List[Any]:
""" """
Find cptmodifiers by effective_date Find cptmodifiers by effective_date
""" """
@ -319,7 +321,7 @@ class CPTModifierService:
getattr(CPTModifier, "effective_date") == effective_date getattr(CPTModifier, "effective_date") == effective_date
).all() ).all()
async def find_by_termination_date(self, termination_date: date) -> List[CPTModifier]: async def find_by_termination_date(self, termination_date: date) -> List[Any]:
""" """
Find cptmodifiers by termination_date Find cptmodifiers by termination_date
""" """
@ -327,7 +329,7 @@ class CPTModifierService:
getattr(CPTModifier, "termination_date") == termination_date getattr(CPTModifier, "termination_date") == termination_date
).all() ).all()
async def find_by_reimbursement_impact(self, reimbursement_impact: Decimal) -> List[CPTModifier]: async def find_by_reimbursement_impact(self, reimbursement_impact: Any) -> List[Any]:
""" """
Find cptmodifiers by reimbursement_impact Find cptmodifiers by reimbursement_impact
""" """
@ -335,7 +337,7 @@ class CPTModifierService:
getattr(CPTModifier, "reimbursement_impact") == reimbursement_impact getattr(CPTModifier, "reimbursement_impact") == reimbursement_impact
).all() ).all()
async def find_by_usage_rules(self, usage_rules: str) -> List[CPTModifier]: async def find_by_usage_rules(self, usage_rules: str) -> List[Any]:
""" """
Find cptmodifiers by usage_rules Find cptmodifiers by usage_rules
""" """
@ -343,7 +345,7 @@ class CPTModifierService:
getattr(CPTModifier, "usage_rules") == usage_rules getattr(CPTModifier, "usage_rules") == usage_rules
).all() ).all()
async def find_by_created_at(self, created_at: datetime) -> List[CPTModifier]: async def find_by_created_at(self, created_at: datetime) -> List[Any]:
""" """
Find cptmodifiers by created_at Find cptmodifiers by created_at
""" """
@ -351,7 +353,7 @@ class CPTModifierService:
getattr(CPTModifier, "created_at") == created_at getattr(CPTModifier, "created_at") == created_at
).all() ).all()
async def find_by_updated_at(self, updated_at: datetime) -> List[CPTModifier]: async def find_by_updated_at(self, updated_at: datetime) -> List[Any]:
""" """
Find cptmodifiers by updated_at Find cptmodifiers by updated_at
""" """

Some files were not shown because too many files have changed in this diff Show More