Contacts & Leads
What this module does
Before someone becomes an active client with a Case, they exist in Orchid as either a Lead (an inquiry) or a Contact (a reviewed applicant who hasn’t been matched yet). This module manages the early pipeline: capturing inquiries, reviewing applicants, screening them, and (if accepted) converting them into Users with active Cases.
Business value
Not everyone who inquires to a fertility agency becomes a client. Agencies need to track who has applied, where they are in the review process, and why some applicants are rejected. This module gives agencies a structured pipeline for managing the top of their funnel.
Key files
Directoryorchid/
Directorymodels/
- contact.py 48 KB — Contact, ContactDocument, ContactEmail, ContactLog, ContactNote
- lead.py ContactLead, ContactLeadRequest
Directoryviews/
- admin_contacts.py 20 KB — contact management admin UI
- contact_lead.py 11 KB — lead/preview views
- admin_screening.py 1 KB — screening workflow UI
Directoryapi/
- admin.py — contact API operations (mixed into the 379 KB admin API)
The pipeline
flowchart LR Inquiry["External inquiry\n(website form, phone, referral)"] Inquiry --> Lead["ContactLead\n(no login)"] Lead --> |"Agency reviews"| Contact["Contact\n(no login yet)"] Contact --> |"Screening passes"| User["User\n(has login, active case)"] Contact --> |"DQ'd or rejected"| Archived["Contact archived"] Lead --> |"Spam / not qualified"| Ignored["Lead ignored"]Contacts vs. Users — a critical distinction
Contact and User are completely different models in different files:
Contact | User | |
|---|---|---|
| Model file | orchid/models/contact.py | orchid/models/user.py |
| Has login? | No | Yes |
| Has a Case? | No (pre-case) | Yes |
| Stage | Application / screening | Active journey |
A Contact becomes a User when the agency accepts them and creates their account. After that point, the Contact record still exists as a historical reference, but the User record is the primary record.
ContactLead — the very first step
A ContactLead is the lightest-weight record. It is created when:
- Someone fills out an inquiry form on the agency’s website
- An agency staff member manually logs a phone inquiry
- An external referral arrives
ContactLead has only basic info: name, email, phone, inquiry type, and when it arrived. No login, no profile, no case.
ContactLeadRequest is a supplemental record that stores the full data from the lead’s initial inquiry form submission.
Contact records
A Contact is a richer record created after an agency decides a lead is worth pursuing. It includes:
- Full personal information
ContactNoterecords (staff notes about the contact)ContactEmailrecords (manually logged emails, separate from EmailSync)ContactLogrecords (audit trail of status changes)ContactDocumentrecords (uploaded documents)
Screening
The screening workflow is accessible at /admin/screening. It provides an admin UI for:
- Reviewing pending applications
- Running DQ checks against
AgencyDQSettings - Flagging applicants for further review
- Approving or rejecting contacts
There is no dedicated Screening model — screening state is tracked through Contact status fields and ContactLog entries.
Converting a contact to a user
When a contact is accepted, agency staff:
- Create a
Useraccount for the contact - Create an initial
Case(orCasePartyif matching them to an existing case) - Send the user their login credentials
This is done through the admin UI, not programmatically in the typical flow. The User model has a contact_id field (on some user types) that links back to the originating Contact record.