Skip to content

Project Structure

The LMS is organized into four main directories: backend/, frontend/admin/, frontend/borrower/, and docs/.

Top-Level Layout

lms/
├── backend/                 # Django backend (API, business logic, database)
├── frontend/
│   ├── admin/               # Admin dashboard (react-admin)
│   └── borrower/            # Borrower self-service portal
├── docs/                    # MkDocs documentation site
├── docker-compose.yml       # Local development services
├── render.yaml              # Render.com deployment configuration
└── spec.md                  # Full system specification

Backend

The backend is a Django 5.x project using uv for package management.

Configuration (config/)

backend/config/
├── __init__.py
├── asgi.py                  # ASGI application (uvicorn)
├── celery.py                # Celery configuration + TenantTask base class
├── urls.py                  # URL routing (NinjaExtraAPI at /api/v1/)
└── settings/
    ├── base.py              # Shared settings (apps, middleware, DB, Celery, i18n)
    ├── development.py       # Debug, CORS, console email, eager Celery
    ├── production.py        # Security hardening, external services
    └── test.py              # Test overrides, in-memory cache, eager Celery

Applications (apps/)

22+ Django apps organized by domain. Each app follows the layered architecture convention:

backend/apps/
├── tenants/                 # Public schema: tenant + domain models
├── main/                    # Main schema: LMS home (admin, allauth)
├── auth/                    # Authentication controllers (allauth wrapper)
├── users/                   # Custom user model (main + tenant schemas)
├── borrowers/               # Borrower profiles, loan parties, identities, consents
├── programs/                # Lending programs, products, index rates
├── loans/                   # Loan records, lifecycle, draws, purchases
├── amortization/            # Amortization schedules + period management
├── payments/                # Payment processing + recurring payments
│   ├── authorizenet/        # Authorize.Net subapp (provider)
│   └── stripe/              # Stripe subapp (provider)
├── fees/                    # Fee schedules + fee management
├── servicing/               # Modifications, forbearance, deferments, PTP, payoff, suspense
├── collateral/              # Collateral items, liens, valuations
├── disbursements/           # Loan funding
├── collections/             # Delinquency, queues, dunning, collection actions
├── ledger/                  # Double-entry general ledger
├── documents/               # Document storage
│   ├── s3/                  # S3 subapp (provider)
│   └── local/               # Local filesystem subapp (provider)
├── portfolio/               # Portfolio management, snapshots, investors
├── reporting/               # Report generation
│   └── providers/           # Report generator implementations
├── compliance/              # Regulatory compliance
│   └── providers/           # Compliance rule implementations
├── communications/          # Templated messaging
│   ├── sendgrid/            # SendGrid subapp (provider)
│   ├── smtp/                # SMTP subapp (provider)
│   └── twilio/              # Twilio subapp (provider)
├── cases/                   # Case management, supercases, campaigns
├── operations/              # Event-sourced loan replay
├── providers/               # Provider config + registry
├── tasks/                   # Attachable task management
├── notes/                   # Attachable notes
├── webhooks/                # Webhook subscriptions + delivery
└── portal/                  # Borrower portal backend API (no models)

App Module Convention

Each app follows a consistent file layout:

apps/{module}/
├── __init__.py
├── apps.py                  # Django AppConfig
├── models.py                # Data models (fields, constraints, properties)
├── services.py              # Business logic (writes, orchestration)
├── selectors.py             # Read-only queries (complex querysets)
├── schemas.py               # Pydantic schemas (API input/output)
├── api.py                   # django-ninja-extra controllers (HTTP layer)
├── permissions.py           # Custom permission classes (optional)
├── admin.py                 # Django admin registration (optional)
├── providers/               # Protocol + implementations (optional)
│   ├── __init__.py          # Protocol definition + registry
│   └── ...                  # Provider implementations
├── signals.py               # Django signals (optional)
├── tasks.py                 # Celery tasks (optional)
├── baker_recipes.py         # model-bakery test fixture recipes (optional)
├── migrations/
└── tests/
    ├── test_services.py     # Service layer tests (primary focus)
    ├── test_selectors.py    # Selector/query tests
    └── test_api.py          # API integration tests

See Layered Architecture for how these layers interact.

Common Utilities (common/)

Shared utilities used across all apps. This package has no models and no migrations:

Module Purpose
models.py Base mixins: UUIDPrimaryKey, Timestamped, ExternalID, Archivable
schemas.py Base Pydantic schemas: BaseModelOut, ArchivableModelOut
controllers.py ReactAdminControllerMixin (pagination, sorting, filtering)
permissions.py RBAC permission classes: IsViewerOrAbove, IsCollectorOrAbove, etc.
rbac.py Role-to-permission mappings, RBAC permission list builder
validators.py Pydantic validators: email, phone, decimal, SSN, content type
contenttypes.py resolve_content_type() for generic FK resolution
formatting.py Locale-aware formatters: fmt_currency, fmt_date, etc.
pdf.py Jinja2 + WeasyPrint PDF rendering with locale-aware filters
tasks.py async_task_delay() for safe Celery dispatch from async code
selectors.py get_audit_history() generic pghistory query

Test Infrastructure

backend/
├── conftest.py              # Root conftest (tenant setup, user factories)
└── tests/                   # Integration tests (if any)

The root conftest.py provides:

  • test_tenant --- Session-scoped fixture creating a test tenant + domain
  • tenant_schema --- Autouse fixture activating the test tenant schema for every test
  • user_factory / user / api_user --- User creation helpers with configurable roles
  • Connection cleanup fixtures to prevent ResourceWarning and teardown errors

Frontend (Admin Dashboard)

The admin dashboard at frontend/admin/ is a react-admin single-page application:

frontend/admin/src/
├── App.tsx                  # react-admin <Admin> with all resources
├── main.tsx                 # Entry point
├── admin/                   # Resource screens (50+ directories)
│   ├── Layout.tsx           # Admin layout with sidebar
│   ├── Menu.tsx             # Permission-gated navigation menu
│   ├── Dashboard.tsx        # Dashboard with stats and charts
│   ├── LoginPage.tsx        # Login page
│   ├── permissions.ts       # hasPermission() utility
│   ├── theme.ts             # MUI theme
│   └── {resource}/          # One directory per resource
│       ├── index.ts         # Barrel export + icon
│       ├── {Resource}List.tsx
│       ├── {Resource}Show.tsx
│       ├── {Resource}Create.tsx
│       ├── {Resource}Edit.tsx
│       └── __tests__/
├── components/              # Shared components
│   ├── MoneyField.tsx       # Currency formatting
│   ├── MoneyInput.tsx       # Currency input
│   ├── StatusField.tsx      # Status chip
│   ├── PercentField.tsx     # Percentage display
│   ├── FullNameField.tsx    # First + last name
│   ├── ActionButton.tsx     # Action with confirmation dialog
│   └── NestedAuditHistory.tsx
├── providers/
│   ├── dataProvider.ts      # Extended data provider (action, getNestedList, createNested)
│   ├── authProvider.ts      # Session-based auth
│   └── i18nProvider.ts      # English/Spanish
├── utils/
│   └── format.ts            # humanize(), formatMoney(), STATUS_COLORS
├── types.ts                 # TypeScript interfaces + choice constants
└── test-utils.tsx           # renderWithAdmin(), renderWithRecord()

Frontend (Borrower Portal)

The borrower portal at frontend/borrower/ is a standalone React SPA using MUI and React Query:

frontend/borrower/src/
├── App.tsx                  # Routes + QueryClient + AuthProvider + ThemeProvider
├── main.tsx                 # Entry point
├── api/
│   ├── client.ts            # HTTP utility (apiFetch, CSRF, ApiHttpError)
│   ├── auth.ts              # Session auth (login, logout, getMe)
│   └── portal.ts            # Portal API functions (41 functions)
├── contexts/
│   └── AuthContext.tsx       # Auth state (borrower, login, logout)
├── hooks/                   # React Query hooks (one per domain)
│   ├── usePortalApi.ts      # Dashboard and loan queries
│   ├── usePayments.ts       # Payment queries and mutations
│   ├── useAutopay.ts        # Autopay management
│   ├── useInstruments.ts    # Payment instrument management
│   ├── useDocuments.ts      # Document queries and upload
│   ├── useProfile.ts        # Profile queries and mutations
│   ├── useCases.ts          # Support case management
│   ├── useHardship.ts       # Hardship applications
│   └── useBranding.ts       # Tenant branding query
├── pages/                   # 17 page components
├── components/              # 25+ shared components
├── layouts/
│   ├── AuthLayout.tsx       # Centered card layout (login, reset)
│   └── PortalLayout.tsx     # AppBar + sidebar + main content
├── utils/
│   └── format.ts            # Formatting utilities
├── types.ts                 # TypeScript interfaces
└── test-utils.tsx           # Test helpers

Documentation

docs/
├── mkdocs.yml               # MkDocs configuration (nav, theme, extensions)
├── pyproject.toml            # Python deps (mkdocs, mkdocs-material)
└── src/                      # Markdown source files
    ├── index.md              # Homepage
    ├── getting-started/      # Installation, configuration, quick start
    ├── architecture/         # System design documentation
    ├── domain/               # Business domain documentation
    └── reference/            # Reference tables and enums

Configuration Files

File Purpose
backend/pyproject.toml Python dependencies (uv)
frontend/admin/package.json Admin dashboard dependencies (npm)
frontend/borrower/package.json Borrower portal dependencies (npm)
docs/pyproject.toml Documentation dependencies (uv)
docker-compose.yml Local development services
render.yaml Render.com deployment configuration
.github/workflows/ci.yml CI/CD pipeline (lint, test, build)

See Also