Spaces:
Sleeping
SwiftOps Backend API
Field Service Management Platform - FastAPI Backend
A scalable, production-ready FastAPI backend for managing field service operations including ticket management, payroll processing, inventory tracking, and financial workflows.
ποΈ Architecture Overview
backend/
βββ app/
β βββ __init__.py
β βββ main.py # FastAPI application entry point
β βββ config.py # Configuration management (env vars, settings)
β β
β βββ api/ # API Layer - HTTP endpoints
β β βββ __init__.py
β β βββ deps.py # Shared dependencies (auth, db session)
β β βββ v1/ # API version 1
β β β βββ __init__.py
β β β βββ router.py # Main router aggregator
β β β βββ auth.py # Authentication endpoints
β β β βββ users.py # User management
β β β βββ projects.py # Project CRUD
β β β βββ tickets.py # Ticket operations
β β β βββ assignments.py # Ticket assignment logic
β β β βββ payroll.py # Payroll generation & management
β β β βββ inventory.py # Inventory tracking
β β β βββ finance.py # Financial transactions
β β β βββ customers.py # Customer management
β β β βββ subscriptions.py # Subscription lifecycle
β β β βββ incidents.py # Support incidents
β β β βββ sales_orders.py # Sales order processing
β β β βββ analytics.py # Dashboard & reporting
β β β βββ webhooks.py # Payment gateway webhooks
β β β
β β βββ websockets/ # WebSocket endpoints
β β βββ __init__.py
β β βββ location.py # Real-time location tracking
β β βββ notifications.py # Real-time notifications
β β
β βββ core/ # Core Business Logic
β β βββ __init__.py
β β βββ auth.py # JWT handling, password hashing
β β βββ security.py # RLS, permissions, RBAC
β β βββ exceptions.py # Custom exception classes
β β βββ middleware.py # Custom middleware (logging, CORS)
β β
β βββ services/ # Business Logic Layer
β β βββ __init__.py
β β βββ ticket_service.py # Ticket lifecycle, assignment logic
β β βββ payroll_service.py # Payroll calculation, generation
β β βββ inventory_service.py # Inventory allocation, tracking
β β βββ finance_service.py # Transaction workflows, approvals
β β βββ sla_service.py # SLA calculation, monitoring
β β βββ location_service.py # GPS validation, distance calculation
β β βββ notification_service.py # Email, SMS, push notifications
β β βββ payment_service.py # Payment gateway integration
β β βββ subscription_service.py # Subscription activation, lifecycle
β β βββ analytics_service.py # Metrics, dashboard data
β β
β βββ models/ # SQLAlchemy ORM Models
β β βββ __init__.py
β β βββ base.py # Base model with common fields
β β βββ user.py # User, UserFinancialAccounts
β β βββ organization.py # Clients, Contractors
β β βββ project.py # Projects, ProjectTeam, ProjectRoles
β β βββ ticket.py # Tickets, TicketAssignments, TicketStatusHistory
β β βββ customer.py # Customers, SalesOrders, Subscriptions
β β βββ incident.py # Incidents
β β βββ inventory.py # ProjectInventory, InventoryAssignments
β β βββ finance.py # ProjectFinance, UserPayroll, PaymentLogs
β β βββ timesheet.py # Timesheets
β β βββ document.py # Documents
β β
β βββ schemas/ # Pydantic Schemas (Request/Response)
β β βββ __init__.py
β β βββ user.py # UserCreate, UserUpdate, UserResponse
β β βββ project.py # ProjectCreate, ProjectUpdate, ProjectResponse
β β βββ ticket.py # TicketCreate, TicketUpdate, TicketResponse
β β βββ payroll.py # PayrollCreate, PayrollCalculation
β β βββ inventory.py # InventoryAssignment, InventoryDistribution
β β βββ finance.py # TransactionCreate, TransactionApproval
β β βββ common.py # Shared schemas (Pagination, Filters)
β β
β βββ repositories/ # Data Access Layer (Repository Pattern)
β β βββ __init__.py
β β βββ base.py # Base repository with CRUD operations
β β βββ user_repository.py # User-specific queries
β β βββ ticket_repository.py # Ticket-specific queries
β β βββ payroll_repository.py # Payroll-specific queries
β β βββ finance_repository.py # Finance-specific queries
β β
β βββ tasks/ # Background Tasks (Celery)
β β βββ __init__.py
β β βββ celery_app.py # Celery configuration
β β βββ payroll_tasks.py # Weekly payroll generation
β β βββ sla_tasks.py # SLA monitoring, alerts
β β βββ notification_tasks.py # Send emails, SMS
β β βββ invoice_tasks.py # Generate contractor invoices
β β βββ analytics_tasks.py # Pre-compute dashboard metrics
β β
β βββ integrations/ # External Service Integrations
β β βββ __init__.py
β β βββ supabase.py # Supabase client (Auth, Storage, Realtime)
β β βββ mpesa.py # M-Pesa payment gateway
β β βββ google_maps.py # Google Maps API (geocoding, distance)
β β βββ sms_provider.py # SMS gateway (Africa's Talking, Twilio)
β β βββ email_provider.py # Email service (SendGrid, AWS SES)
β β βββ storage.py # File storage (Supabase Storage, S3)
β β
β βββ utils/ # Utility Functions
β β βββ __init__.py
β β βββ date_utils.py # Date/time helpers
β β βββ location_utils.py # GPS calculations, distance
β β βββ validation.py # Custom validators
β β βββ formatters.py # Data formatting helpers
β β βββ constants.py # Application constants
β β
β βββ db/ # Database Configuration
β βββ __init__.py
β βββ session.py # Database session management
β βββ base.py # Base class for all models
β βββ migrations/ # Alembic migrations
β βββ versions/
β
βββ tests/ # Test Suite
β βββ __init__.py
β βββ conftest.py # Pytest fixtures
β βββ unit/ # Unit tests
β β βββ test_services/
β β βββ test_repositories/
β β βββ test_utils/
β βββ integration/ # Integration tests
β β βββ test_api/
β β βββ test_tasks/
β βββ e2e/ # End-to-end tests
β
βββ scripts/ # Utility Scripts
β βββ seed_data.py # Seed database with test data
β βββ generate_payroll.py # Manual payroll generation
β βββ migrate_data.py # Data migration scripts
β
βββ .env.example # Environment variables template
βββ .gitignore
βββ requirements.txt # Python dependencies
βββ pyproject.toml # Poetry configuration (alternative)
βββ Dockerfile # Docker container definition
βββ docker-compose.yml # Local development setup
βββ README.md # This file
π― Core Functions & Responsibilities
1. Authentication & Authorization
Module: app/api/v1/auth.py, app/core/auth.py, app/core/security.py
Functions:
- User login/logout (JWT token generation)
- Password reset flow
- Role-based access control (RBAC)
- Row-level security (RLS) enforcement
- Multi-tenancy isolation (client/contractor scoping)
Supabase Integration:
- Uses Supabase Auth for user authentication
- Validates JWT tokens from Supabase
- Syncs user roles with custom
Userstable
2. Ticket Management
Module: app/services/ticket_service.py, app/api/v1/tickets.py
Functions:
- Create tickets from sales orders, incidents, or tasks
- Ticket assignment logic (manual, auto-assignment)
- Limit self-assignment to 3 tickets per agent
- Status transitions with validation
- SLA deadline calculation and monitoring
- GPS-based arrival verification
- Ticket completion workflow
Business Rules:
# Example: Ticket Assignment Logic
def assign_ticket(ticket_id, user_id):
# 1. Check user has < 3 active assignments
# 2. Verify user is in project team
# 3. Check user's region matches ticket region
# 4. Create TicketAssignment record
# 5. Update ticket status to 'assigned'
# 6. Send notification to agent
# 7. Update SLA target date
3. Payroll Processing
Module: app/services/payroll_service.py, app/api/v1/payroll.py
Functions:
- Weekly payroll generation (automated via Celery)
- Calculate earnings based on compensation type:
- Flat rate (fixed weekly amount)
- Commission (% of package price)
- Hybrid (base + commission)
- Hourly (based on timesheet hours)
- Apply deductions (advances, penalties)
- Generate payroll reports
- Mark payroll as paid with payment reference
Business Rules:
# Example: Payroll Calculation
def calculate_payroll(user_id, project_id, period_start, period_end):
role = get_user_project_role(user_id, project_id)
tickets_closed = count_tickets_closed(user_id, period_start, period_end)
hours_worked = sum_timesheet_hours(user_id, period_start, period_end)
if role.compensation_type == 'flat_rate':
earnings = role.flat_rate_amount
elif role.compensation_type == 'commission':
earnings = sum_ticket_values(tickets) * role.commission_percentage
elif role.compensation_type == 'hybrid':
earnings = role.base_amount + (sum_ticket_values(tickets) * role.commission_percentage)
elif role.compensation_type == 'hourly':
earnings = hours_worked * role.hourly_rate
deductions = get_user_deductions(user_id, period_start, period_end)
total = earnings - deductions
return create_payroll_record(...)
4. Inventory Management
Module: app/services/inventory_service.py, app/api/v1/inventory.py
Functions:
- Allocate inventory to regional hubs
- Issue equipment to field agents
- Track serial numbers and unit identifiers
- Prevent duplicate assignments (same serial issued twice)
- Handle returns (tools) and installations (equipment)
- Optimistic locking for concurrent updates
- Inventory reconciliation reports
Business Rules:
# Example: Inventory Assignment
def assign_inventory_to_agent(distribution_id, user_id, unit_identifier):
# 1. Check unit_identifier not already assigned
# 2. Verify quantity_available > 0
# 3. Check user is in same region as distribution
# 4. Create InventoryAssignment record
# 5. Update distribution.quantity_issued
# 6. Use optimistic locking (version field)
5. Financial Management
Module: app/services/finance_service.py, app/api/v1/finance.py
Functions:
- Record project expenses (inflows/outflows)
- Approval workflow (pending β approved β paid)
- Link to entities (tickets, payroll, invoices)
- Payment gateway integration (M-Pesa, bank transfers)
- Transaction reconciliation
- Financial reporting and audit trails
Business Rules:
# Example: Expense Approval Workflow
def approve_expense(expense_id, approver_id):
# 1. Check approver has 'dispatcher' or 'project_manager' role
# 2. Verify expense is in 'pending' status
# 3. Validate location_verified = TRUE (if required)
# 4. Update status to 'approved'
# 5. Create ProjectFinance record
# 6. Send notification to incurred_by_user
6. Location Tracking
Module: app/services/location_service.py, app/api/websockets/location.py
Functions:
- Real-time GPS tracking via WebSocket
- Validate agent arrival at customer site
- Calculate distance between agent and customer
- Journey tracking (breadcrumb trail)
- Fraud detection (impossible travel speeds)
- Update user current location
Business Rules:
# Example: Arrival Verification
def verify_arrival(ticket_id, agent_location):
ticket = get_ticket(ticket_id)
customer_location = get_customer_location(ticket.customer_id)
distance = calculate_distance(agent_location, customer_location)
if distance <= 100: # Within 100 meters
mark_arrived(ticket_id, agent_location, verified=True)
else:
mark_arrived(ticket_id, agent_location, verified=False)
7. SLA Monitoring
Module: app/services/sla_service.py, app/tasks/sla_tasks.py
Functions:
- Calculate SLA deadlines based on priority
- Monitor tickets approaching deadline
- Send alerts to managers and agents
- Mark tickets as SLA violated
- Generate SLA compliance reports
Background Task (runs every hour):
@celery_app.task
def monitor_sla_violations():
# 1. Find tickets with sla_target_date < now() and status != 'completed'
# 2. Mark sla_violated = TRUE
# 3. Send notifications to project managers
# 4. Log SLA violation event
8. Payment Gateway Integration
Module: app/services/payment_service.py, app/integrations/mpesa.py
Functions:
- Initiate M-Pesa payments (B2C, B2B)
- Handle payment callbacks/webhooks
- Retry failed payments
- Log all payment attempts (PaymentLogs)
- Reconcile payments with transactions
Webhook Handler:
@router.post("/webhooks/mpesa")
async def mpesa_callback(payload: dict):
# 1. Validate webhook signature
# 2. Parse payment result
# 3. Update ProjectFinance status
# 4. Create PaymentLog entry
# 5. Send notification to user
9. Subscription Management
Module: app/services/subscription_service.py, app/api/v1/subscriptions.py
Functions:
- Activate subscriptions after installation
- Validate activation requirements (dynamic per project)
- Manage subscription lifecycle (active, suspended, cancelled)
- Link subscriptions to tickets and sales orders
Business Rules:
# Example: Subscription Activation
def activate_subscription(subscription_id, activation_data):
subscription = get_subscription(subscription_id)
project = get_project(subscription.project_id)
# Validate dynamic activation requirements
for requirement in project.activation_requirements:
if requirement['required'] and requirement['field'] not in activation_data:
raise ValidationError(f"Missing required field: {requirement['label']}")
# Update subscription
subscription.status = 'active'
subscription.activation_date = date.today()
subscription.activation_details = activation_data
subscription.activated_by_user_id = current_user.id
10. Analytics & Reporting
Module: app/services/analytics_service.py, app/api/v1/analytics.py
Functions:
- Dashboard metrics (tickets, revenue, SLA compliance)
- Agent performance reports
- Project financial summaries
- Inventory utilization reports
- Pre-computed aggregations (via Celery)
Background Task (runs daily):
@celery_app.task
def compute_daily_metrics():
# 1. Calculate tickets closed per agent
# 2. Compute average completion time
# 3. Calculate SLA compliance rate
# 4. Store in cache (Redis)
π Supabase Integration Points
1. Authentication
# app/integrations/supabase.py
from supabase import create_client
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
# Verify JWT token from frontend
def verify_token(token: str):
user = supabase.auth.get_user(token)
return user
2. Storage (File Uploads)
# Upload ticket photos, receipts
def upload_document(file, bucket="documents"):
path = f"{user_id}/{ticket_id}/{filename}"
supabase.storage.from_(bucket).upload(path, file)
return supabase.storage.from_(bucket).get_public_url(path)
3. Realtime (WebSocket)
# Subscribe to ticket updates
supabase.realtime.channel('tickets')
.on('postgres_changes',
event='UPDATE',
schema='public',
table='Tickets',
callback=handle_ticket_update)
.subscribe()
4. Database (Direct Queries)
# Use Supabase client for simple queries (optional)
# For complex queries, use SQLAlchemy ORM
tickets = supabase.table('Tickets').select('*').eq('status', 'open').execute()
π Getting Started
Prerequisites
- Python 3.11+
- PostgreSQL 15+ (Supabase)
- Redis (for caching and Celery)
- Docker & Docker Compose (optional)
Installation
- Clone the repository
git clone <repo-url>
cd backend
- Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
- Install dependencies
pip install -r requirements.txt
- Set up environment variables
cp .env.example .env
# Edit .env with your Supabase credentials
- Run database migrations
alembic upgrade head
- Start the development server
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
- Start Celery worker (in separate terminal)
celery -A app.tasks.celery_app worker --loglevel=info
- Start Celery beat (scheduler, in separate terminal)
celery -A app.tasks.celery_app beat --loglevel=info
π³ Docker Setup
# Start all services (API, Celery, Redis)
docker-compose up -d
# View logs
docker-compose logs -f api
# Stop services
docker-compose down
π Environment Variables
# .env.example
# Application
APP_NAME=SwiftOps API
APP_VERSION=1.0.0
DEBUG=True
ENVIRONMENT=development
# Database (Supabase PostgreSQL)
DATABASE_URL=postgresql://user:password@host:5432/dbname
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-anon-key
SUPABASE_SERVICE_KEY=your-service-role-key
# JWT
SECRET_KEY=your-secret-key-here
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
# Redis
REDIS_URL=redis://localhost:6379/0
# Celery
CELERY_BROKER_URL=redis://localhost:6379/0
CELERY_RESULT_BACKEND=redis://localhost:6379/0
# Payment Gateways
MPESA_CONSUMER_KEY=your-mpesa-key
MPESA_CONSUMER_SECRET=your-mpesa-secret
MPESA_SHORTCODE=174379
MPESA_PASSKEY=your-passkey
# Google Maps
GOOGLE_MAPS_API_KEY=your-google-maps-key
# SMS Provider (Africa's Talking)
AFRICASTALKING_USERNAME=your-username
AFRICASTALKING_API_KEY=your-api-key
# Email Provider (SendGrid)
SENDGRID_API_KEY=your-sendgrid-key
FROM_EMAIL=noreply@swiftops.com
# File Storage
STORAGE_PROVIDER=supabase # or 's3'
AWS_ACCESS_KEY_ID=your-aws-key
AWS_SECRET_ACCESS_KEY=your-aws-secret
AWS_S3_BUCKET=your-bucket-name
π§ͺ Testing
# Run all tests
pytest
# Run with coverage
pytest --cov=app --cov-report=html
# Run specific test file
pytest tests/unit/test_services/test_payroll_service.py
# Run integration tests only
pytest tests/integration/
π API Documentation
Once the server is running, visit:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- OpenAPI JSON: http://localhost:8000/openapi.json
ποΈ Design Patterns & Best Practices
1. Repository Pattern
Separates data access logic from business logic.
# app/repositories/ticket_repository.py
class TicketRepository:
def get_by_id(self, ticket_id: UUID) -> Ticket:
return db.query(Ticket).filter(Ticket.id == ticket_id).first()
def get_open_tickets(self, project_id: UUID) -> List[Ticket]:
return db.query(Ticket).filter(
Ticket.project_id == project_id,
Ticket.status == 'open',
Ticket.deleted_at.is_(None)
).all()
2. Service Layer Pattern
Encapsulates business logic.
# app/services/ticket_service.py
class TicketService:
def __init__(self, ticket_repo: TicketRepository):
self.ticket_repo = ticket_repo
def assign_ticket(self, ticket_id: UUID, user_id: UUID):
# Business logic here
ticket = self.ticket_repo.get_by_id(ticket_id)
self._validate_assignment(ticket, user_id)
assignment = self._create_assignment(ticket, user_id)
self._send_notification(user_id, ticket)
return assignment
3. Dependency Injection
Use FastAPI's dependency injection system.
# app/api/deps.py
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
def get_current_user(token: str = Depends(oauth2_scheme)):
# Validate token and return user
return user
# Usage in endpoint
@router.get("/tickets")
def get_tickets(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
return ticket_service.get_tickets(db, current_user)
4. Optimistic Locking
Prevent concurrent update conflicts.
def update_inventory_distribution(distribution_id, updates, version):
distribution = db.query(ProjectInventoryDistribution).filter(
ProjectInventoryDistribution.id == distribution_id,
ProjectInventoryDistribution.version == version
).first()
if not distribution:
raise ConcurrentUpdateError("Record was modified by another user")
# Apply updates
distribution.quantity_issued += updates.quantity
distribution.version += 1
db.commit()
5. Soft Deletes
Always filter out soft-deleted records.
# Base repository method
def get_active(self, model_class):
return db.query(model_class).filter(model_class.deleted_at.is_(None))
π Security Considerations
Row-Level Security (RLS)
- Enforce tenant isolation at database level
- Use Supabase RLS policies
API Rate Limiting
- Implement rate limiting per client/user
- Use Redis for rate limit tracking
Input Validation
- Use Pydantic schemas for all inputs
- Validate file uploads (type, size)
Audit Logging
- Log all financial transactions
- Track who created/updated records
Secrets Management
- Never commit secrets to git
- Use environment variables or secret managers
π Scalability Considerations
Database Connection Pooling
- Use SQLAlchemy connection pool
- Configure pool size based on load
Caching Strategy
- Cache frequently accessed data (Redis)
- Invalidate cache on updates
Background Jobs
- Offload heavy tasks to Celery
- Use task queues for async processing
Horizontal Scaling
- Stateless API design
- Load balance across multiple instances
Database Optimization
- Use indexes effectively
- Monitor slow queries
- Consider read replicas for reporting
π€ Contributing
- Create a feature branch
- Write tests for new features
- Follow PEP 8 style guide
- Update documentation
- Submit pull request
π License
[Your License Here]
π Support
For questions or issues, contact: [your-email@example.com]