Intake Pipeline Flowchart | RE-volv

Intake Pipeline Flowchart

What happens when a nonprofit submits the intake form

User action
System (Django)
Salesforce
Email (SES)
Decision check
Fallback/Error
1

User fills out Intake Form

/solar/apply/ — Contact info, nonprofit details, mission, motivations, file uploads (IRS letter, utility bills)

2

Form Validates & Saves to Database

Security scan on uploaded files → Save all text data to PostgreSQL IntakeSubmission → Audit log created

Data is SAFE in database — even if everything below fails, nothing is lost
3

User Redirected to Calendly Page

/solar/apply/schedule-call/?sid=123&source=intake-form
Calendly prefilled with name + email + UTM tracking. User sees "Application Received!" instantly.

↓ Meanwhile, async tasks fire in background (Celery + Redis)
4

Background Tasks (Celery Worker)

All tasks run async — user doesn't wait. Retries 3x on failure.

Task Chain 1: Salesforce

☁️
Create Lead in Salesforce with all mapped fields (27 fields) → returns lead_id
Post-Lead tasks (chained after Lead created):
📎
Upload files to SF Notes & Attachments (ContentVersion → ContentDocumentLink)
🔗
Generate pre-underwriting token → push URL to Lead Pre_underwriting_Form_URL__c

Task 2: Confirmation Email

📧
Send "Application Received" email via Amazon SES with Calendly "Schedule Your Call" button

Task 3: Campaign Monitor

📬
If user opted in → add to Campaign Monitor subscriber list with source tracking

Task 4: Staff Notification

🔔
Email notification to staff with all submission data

If SF file upload fails after 3 retries: Marked as UPLOAD FAILED on the submission's files record for staff follow-up

If SF Lead creation fails: Marked as sf_status=failed → retry from Django admin

5

Pre-Underwriting Form Email Sent

User receives email with unique token link: /forms/<uuid>/
Link expires in 30 days. Automated reminders on Day 2, 5, 10, 17, 24.

6

User Fills Out Pre-Underwriting Form

Financial docs (990s, bank statements), EIN, roof info, governance, signer details, demographics

7

Check: Has Lead Been Converted?

Queries Salesforce: SELECT IsConverted, ConvertedOpportunityId FROM Lead WHERE Id = '...'

Not Converted (still a Lead)

☁️
Update Lead with 11 pre-underwriting fields
📎
Attach files to Lead Notes & Attachments

Converted (has Opportunity)

☁️
Update Opportunity with 11 pre-underwriting fields
📎
Attach files to Opportunity Notes & Attachments
Resilient update: If one field fails (bad value, char limit), other fields still push. Failed fields logged in Audit Log.
8

Impact Data Survey Email Sent

"Almost There! One More Step" email with impact survey token link.
Impact survey URL also pushed to Lead: Impact_data_Form_URL__c

9

User Fills Out Impact Data Survey

Mission, savings usage, community impact, board of directors, employees, social media, marketing preferences

10

Check: Has Lead Been Converted?

Not Converted (still a Lead)

💾
Save to DB only — no Lead fields for impact survey
📎
Files still attach to Lead (carry over when converted)
Data syncs to Opportunity when Lead is converted later

Converted (has Opportunity)

☁️
Update Opportunity with 16 impact survey fields
📎
Attach files to Opportunity Notes & Attachments
11

All Forms Complete!

"You're All Set!" email sent → User sees completion page → Staff reviews in Salesforce & Django admin

Data Safety Summary

Form text dataPostgreSQL (always saved first)
Uploaded filesSalesforce Files (ContentVersion + ContentDocumentLink)
Lead/Opportunity fieldsPushed field-by-field (partial success OK)
EmailsAmazon SES with 3x retry
Newsletter opt-inCampaign Monitor with source tracking
Async tasksRedis queue with AOF persistence → Celery worker with auto-restart
Failed integrationsTracked per-submission → retry from Django admin