Open-MFD CRM Developer Guide
Welcome to the development team! This guide will help you understand the architecture, project structure, and development workflow of Open-MFD CRM.
๐๏ธ Architecture Overview
Open-MFD is built as a lightweight, portable Python application using the following core components:
- Frontend: Streamlit handles the UI and state management.
- Database: SQLite is used for local data storage.
- Logic: Custom Python modules in
src/modules/handle calculations and database interactions.
๐ Project Structure
open_mfd_crm/
โโโ data/ # Local data storage (DB, backups, documents)
โโโ docs/ # MkDocs source files (index, guides)
โโโ src/
โ โโโ app.py # Application entry point
โ โโโ assets/ # UI assets (images, logos)
โ โโโ modules/
โ โ โโโ db/ # Data access layer (Repositories)
โ โ โ โโโ clients.py # Client & CAN CRUD
โ โ โ โโโ connection.py # DB connection pooling
โ โ โ โโโ database.py # Main Repository class
โ โ โ โโโ documents.py # Document metadata logic
โ โ โ โโโ folios.py # Folio-specific CRUD
โ โ โ โโโ notes.py # Meeting notes storage
โ โ โ โโโ schema.py # SQL DDL and migrations
โ โ โ โโโ tasks.py # CRM task engine
โ โ โ โโโ transactions.py # Trade entry & portfolio pulls
โ โ โโโ bulk_import.py # Multi-format onboarding logic
โ โ โโโ calculations.py # Pure financial math (XIRR, Gains)
โ โ โโโ constants.py # Shared enums and types
โ โ โโโ database.py # Legacy Facade (Shim)
โ โ โโโ mfu_api.py # MFU API integration (Development)
โ โโโ ui/ # Streamlit view components
โ โโโ can_management.py # CAN association UI
โ โโโ client_form.py # Onboarding forms
โ โโโ components.py # Core UI widgets
โ โโโ dashboard.py # Landing & Analytics view
โ โโโ documents_view.py # Document management UI
โ โโโ notes_view.py # Meeting interaction log
โ โโโ tasks_view.py # Global & Client task tables
โ โโโ transaction_form.py # Trade entry forms
โโโ .env # Environment configuration
โโโ mkdocs.yml # Site configuration
โโโ requirements.txt # Python dependencies
๐ ๏ธ Development Setup
1. Prerequisites
- Python 3.9 or higher.
pip(Python package manager).
2. Installation
Clone the repository and install the dependencies:
pip install -r requirements.txt
3. Environment Configuration
Create a .env file in the root directory (the app will auto-generate one if missing):
DB_PATH=open_mfd.db
4. Running the App
python src/app.py
๐๏ธ Core Design Patterns
1. Repository Pattern
Instead of a single SQL file, logic is split by domain (clients, transactions, tasks, etc.) inside src/modules/db/. Each repository inherits from BaseRepository for connection handling.
2. Facade Pattern
src/modules/database.py acts as a single entry point (Facade). It composes all specialized repositories, allowing legacy code to call db.add_client() without knowing it's delegated to db.clients.add_client().
3. Pure Math Logic
src/modules/calculations.py contains no SQL. It accepts DataFrames from the TransactionRepository and returns mathematical results, making it easy to unit test.
๐๏ธ Database Schema Design
Open-MFD uses a relational schema designed to maintain clean separation between client profiles, their investment structures (folios), and actual transaction history.
Entity Relationship Diagram
erDiagram
CLIENTS ||--o{ CLIENT_CANS : "has multiple"
CLIENTS ||--o{ DOCUMENTS : "uploads"
CLIENTS ||--o{ NOTES : "logs"
CLIENTS ||--o{ TASKS : "assigned"
CLIENT_CANS ||--o{ FOLIOS : "owns"
FOLIOS ||--o{ TRANSACTIONS : "contains"
SCHEMES ||--o{ TRANSACTIONS : "referenced in"
CLIENTS {
integer client_id PK
string name
string pan
string email
string phone
boolean kyc_status
string pan_card_url
timestamp onboarding_date
}
CLIENT_CANS {
integer id PK
integer client_id FK
string can_number
string can_description
timestamp created_at
}
FOLIOS {
integer folio_id PK
integer can_id FK
string folio_number
string amc_name
boolean is_active
}
TRANSACTIONS {
integer trans_id PK
integer folio_id FK
integer scheme_id FK
date date
string type "PURCHASE|REDEMPTION|SIP|..."
float amount
float units
float nav_at_purchase
string order_number
}
SCHEMES {
integer scheme_id PK
string scheme_code UK
string rta_code
string scheme_name
string category
float current_nav
}
NOTES {
integer id PK
integer client_id FK
string content
string category
timestamp created_at
}
DOCUMENTS {
integer doc_id PK
integer client_id FK
string file_name
string file_path
string doc_type
timestamp uploaded_at
}
TASKS {
integer id PK
integer client_id FK
string description
date due_date
string status
priority priority
}
Table Definitions & Logic
clients: The central entity. All CAN numbers are managed via theclient_canstable.client_cans: Stores multiple CANs per client. Includes acan_descriptionfor labeling. Each CAN can independently own folios.folios: Belongs to a specific CAN (can_idFK โclient_cans.id), not directly to a client. This reflects the real-world MFU model where a folio is registered under a CAN.schemes: A master list of Mutual Fund schemes. Transactions reference these to avoid data duplication and ensure consistent naming.transactions: The ledger of all financial movements. It links a specificschemeto a specificfolio.documents: Stores metadata for files.notes&tasks: CRM interaction data.notestracks meeting logs whiletasksmanages the workflow for signatures and reviews.
๐ฆ Building for Distribution
We use PyInstaller (via scripts in build_scripts/) to create "no-install" portable versions for Windows and Linux.
- To build for Windows: python build_scripts/build_windows.py
- This bundles the Python interpreter, dependencies, and the app into a single distributable ZIP.
๐งช Testing
We use separate verification scripts for testing core modules:
- test_db.py: Verifies the Repository/Facade integrity and backward compatibility.
- test_calc.py: Verifies financial calculations using mock DataFrames.
- test_scalability.py: Stress tests the DB layer with thousands of records.
Always run these tests before submitting a Pull Request.