mirror of
https://github.com/blackboxprogramming/BlackRoad-Operating-System.git
synced 2026-03-17 06:57:17 -05:00
Add complete automation SOP system for BlackRoad ERP
This implements the "Automate The Company" initiative with comprehensive
Standard Operating Procedures for GitHub + Salesforce + Asana integration.
New directory: sop/
├── workflows/ - End-to-end process documentation
│ ├── new-client-kickoff.md - Flagship workflow from deal → repos → Asana
│ └── release-pipeline.md - Deploy → update Salesforce + Asana
├── playbooks/ - Human-friendly checklists
│ └── brenda-new-client-checklist.md - Non-technical operator guide
├── salesforce/ - Salesforce automation specifications
│ ├── flows/opp-automation-onstagechange.md - Trigger on Closed Won
│ └── orchestrations/new-client-kickoff-orchestration.md - Multi-stage process
├── integrations/ - API integration specifications
│ ├── salesforce-to-github.md - Create repos from Salesforce
│ ├── github-to-salesforce.md - Update Salesforce after deploy
│ └── salesforce-to-asana.md - Create Asana projects from Salesforce
└── templates/ - Reusable templates
├── github-actions/ - CI/CD workflows (ci.yml, deploy.yml, safety.yml)
└── repo-template/ - Standard repo config (PR template, labels, branch protection)
Key Features:
- Event-driven automation (Closed Won → repos + Asana creation)
- GitHub Actions templates for CI/CD baseline
- Salesforce Flow & Orchestration specs
- Complete API integration documentation
- Operator-friendly playbooks
- Two-view approach (operator + engineer)
- No manual status syncing across systems
This provides the complete backbone for next-gen ERP automation.
This commit is contained in:
463
sop/salesforce/flows/opp-automation-onstagechange.md
Normal file
463
sop/salesforce/flows/opp-automation-onstagechange.md
Normal file
@@ -0,0 +1,463 @@
|
||||
# Salesforce Flow: Opportunity Automation on Stage Change
|
||||
|
||||
**API Name:** `Opp_Automation_OnStageChange`
|
||||
**Type:** Record-Triggered Flow (After Save)
|
||||
**Object:** Opportunity
|
||||
**Status:** Active
|
||||
**Last Updated:** 2025-11-17
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
This flow automates the creation of Project records and kickoff of the orchestration when an Opportunity moves to "Closed Won" stage.
|
||||
|
||||
**Business Value:**
|
||||
- Eliminates manual project setup
|
||||
- Ensures consistency across all new clients
|
||||
- Triggers downstream automation (GitHub, Asana)
|
||||
- Captures all required metadata at deal closure
|
||||
|
||||
---
|
||||
|
||||
## Trigger Configuration
|
||||
|
||||
### Object
|
||||
`Opportunity`
|
||||
|
||||
### Trigger Type
|
||||
**Record-Triggered Flow (After Save)**
|
||||
|
||||
### Trigger Criteria
|
||||
**When:** A record is updated
|
||||
**Condition Requirements:**
|
||||
- **StageName** changed
|
||||
- **StageName** equals "Closed Won"
|
||||
|
||||
**Entry Condition Logic:**
|
||||
```
|
||||
AND(
|
||||
ISCHANGED(StageName),
|
||||
TEXT(StageName) = "Closed Won"
|
||||
)
|
||||
```
|
||||
|
||||
### Optimization
|
||||
- ✅ Run asynchronously (Fast Field Updates) - **No** (need to create related records)
|
||||
- ✅ Trigger order - **1** (run first, before other flows)
|
||||
|
||||
---
|
||||
|
||||
## Flow Variables
|
||||
|
||||
Create these variables at the start:
|
||||
|
||||
| Variable Name | Type | Default Value | Description |
|
||||
|---------------|------|---------------|-------------|
|
||||
| `varProjectKey` | Text | null | Generated project key (e.g., ACME-X7K9) |
|
||||
| `varAccountSlug` | Text | null | Account name converted to slug |
|
||||
| `varRandomSuffix` | Text | null | 4-character random suffix |
|
||||
| `varProjectRecord` | Record (Project__c) | null | Created project record |
|
||||
| `varExistingProject` | Record Collection (Project__c) | null | Check for existing project |
|
||||
|
||||
---
|
||||
|
||||
## Flow Logic
|
||||
|
||||
### 1. Decision: Validate Required Fields
|
||||
|
||||
**Element Type:** Decision
|
||||
|
||||
**Criteria:**
|
||||
Check if all required fields are populated:
|
||||
|
||||
```
|
||||
AND(
|
||||
NOT(ISBLANK({!$Record.AccountId})),
|
||||
NOT(ISBLANK({!$Record.Primary_Domain__c})),
|
||||
NOT(ISBLANK({!$Record.Package_Type__c})),
|
||||
NOT(ISBLANK({!$Record.Service_Tier__c}))
|
||||
)
|
||||
```
|
||||
|
||||
**Outcomes:**
|
||||
- **Valid** → Continue to next step
|
||||
- **Invalid** → Send error notification and stop
|
||||
|
||||
---
|
||||
|
||||
### 2A. Path: Invalid - Send Error Notification
|
||||
|
||||
**Element Type:** Action - Send Email
|
||||
|
||||
**To:** Opportunity Owner
|
||||
**Subject:** `Action Required: Opportunity {!$Record.Name} Missing Information`
|
||||
**Body:**
|
||||
```
|
||||
The opportunity "{!$Record.Name}" was marked as Closed Won, but is missing required information:
|
||||
|
||||
Required Fields:
|
||||
- Account
|
||||
- Primary Domain
|
||||
- Package Type
|
||||
- Service Tier
|
||||
|
||||
Please update the opportunity and change the stage to "Closed Won" again to trigger automation.
|
||||
|
||||
Opportunity Link: {!$Record.Id}
|
||||
```
|
||||
|
||||
**Then:** Stop
|
||||
|
||||
---
|
||||
|
||||
### 2B. Path: Valid - Continue
|
||||
|
||||
#### Step 2.1: Check for Existing Project
|
||||
|
||||
**Element Type:** Get Records
|
||||
|
||||
**Object:** `Project__c`
|
||||
**Conditions:**
|
||||
- `Opportunity__c` equals `{!$Record.Id}`
|
||||
|
||||
**Store Output:** `varExistingProject`
|
||||
|
||||
---
|
||||
|
||||
#### Step 2.2: Decision: Project Already Exists?
|
||||
|
||||
**Criteria:**
|
||||
```
|
||||
NOT(ISNULL({!varExistingProject}))
|
||||
```
|
||||
|
||||
**Outcomes:**
|
||||
- **Exists** → Skip creation, update existing
|
||||
- **Does Not Exist** → Create new project
|
||||
|
||||
---
|
||||
|
||||
#### Step 2.3A: Path: Project Exists - Update It
|
||||
|
||||
**Element Type:** Update Records
|
||||
|
||||
**Record:** `{!varExistingProject[0]}`
|
||||
**Fields to Update:**
|
||||
- `Status__c` = "Setup In Progress"
|
||||
- `Updated_From_Opp__c` = `TODAY()`
|
||||
- `Service_Tier__c` = `{!$Record.Service_Tier__c}`
|
||||
- `Package_Type__c` = `{!$Record.Package_Type__c}`
|
||||
|
||||
**Then:** Skip to Step 3 (Launch Orchestration)
|
||||
|
||||
---
|
||||
|
||||
#### Step 2.3B: Path: Project Does Not Exist - Create It
|
||||
|
||||
##### Step 2.3B.1: Generate Account Slug
|
||||
|
||||
**Element Type:** Assignment
|
||||
|
||||
**Variable:** `varAccountSlug`
|
||||
**Operator:** Equals
|
||||
**Value:** Formula:
|
||||
```
|
||||
SUBSTITUTE(
|
||||
SUBSTITUTE(
|
||||
SUBSTITUTE(
|
||||
UPPER(LEFT({!$Record.Account.Name}, 10)),
|
||||
" ", "-"
|
||||
),
|
||||
".", ""
|
||||
),
|
||||
",", ""
|
||||
)
|
||||
```
|
||||
|
||||
**Purpose:** Convert "Acme Corp." → "ACME-CORP"
|
||||
|
||||
---
|
||||
|
||||
##### Step 2.3B.2: Generate Random Suffix
|
||||
|
||||
**Element Type:** Assignment
|
||||
|
||||
**Variable:** `varRandomSuffix`
|
||||
**Value:** Formula:
|
||||
```
|
||||
SUBSTITUTE(
|
||||
LEFT(TEXT(RAND()), 4),
|
||||
"0.", ""
|
||||
) & TEXT(FLOOR(RAND() * 10000))
|
||||
```
|
||||
|
||||
**Note:** Generates a 4-character alphanumeric suffix (simplified version; in production, use a more robust random generator or auto-number)
|
||||
|
||||
**Better Alternative:** Use Salesforce auto-number field on Project__c:
|
||||
- Field: `Project_Number__c` (Auto Number)
|
||||
- Format: `{0000}`
|
||||
- Starting Number: `1000`
|
||||
|
||||
---
|
||||
|
||||
##### Step 2.3B.3: Build Project Key
|
||||
|
||||
**Element Type:** Assignment
|
||||
|
||||
**Variable:** `varProjectKey`
|
||||
**Value:**
|
||||
```
|
||||
{!varAccountSlug} & "-" & TEXT({!$Record.Project_Number__c})
|
||||
```
|
||||
|
||||
**Example Output:** `ACME-1042`
|
||||
|
||||
---
|
||||
|
||||
##### Step 2.3B.4: Create Project Record
|
||||
|
||||
**Element Type:** Create Records
|
||||
|
||||
**Object:** `Project__c`
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field API Name | Value |
|
||||
|----------------|-------|
|
||||
| `Name` | `{!$Record.Account.Name} - {!varProjectKey}` |
|
||||
| `Project_Key__c` | `{!varProjectKey}` |
|
||||
| `Account__c` | `{!$Record.AccountId}` |
|
||||
| `Opportunity__c` | `{!$Record.Id}` |
|
||||
| `Primary_Domain__c` | `{!$Record.Primary_Domain__c}` |
|
||||
| `Package_Type__c` | `{!$Record.Package_Type__c}` |
|
||||
| `Service_Tier__c` | `{!$Record.Service_Tier__c}` |
|
||||
| `Start_Date__c` | `TODAY()` |
|
||||
| `Status__c` | `"Setup In Progress"` |
|
||||
| `Technical_Owner__c` | `{!$Record.OwnerId}` (or default to a user) |
|
||||
| `OwnerId` | `{!$Record.OwnerId}` |
|
||||
|
||||
**Store Output:** `varProjectRecord`
|
||||
|
||||
---
|
||||
|
||||
### 3. Launch Orchestration
|
||||
|
||||
**Element Type:** Action - Orchestration
|
||||
|
||||
**Orchestration Name:** `New_Client_Kickoff_Orchestration`
|
||||
|
||||
**Input Variables:**
|
||||
- `ProjectRecordId` = `{!varProjectRecord.Id}`
|
||||
- `OpportunityRecordId` = `{!$Record.Id}`
|
||||
- `AccountRecordId` = `{!$Record.AccountId}`
|
||||
|
||||
**Run Asynchronously:** Yes
|
||||
|
||||
---
|
||||
|
||||
### 4. Send Notification to Ops Team
|
||||
|
||||
**Element Type:** Action - Post to Chatter / Slack
|
||||
|
||||
**Option A: Chatter Post**
|
||||
```
|
||||
New project created! 🚀
|
||||
|
||||
Project: {!varProjectRecord.Name}
|
||||
Project Key: {!varProjectRecord.Project_Key__c}
|
||||
Account: {!$Record.Account.Name}
|
||||
Package: {!$Record.Package_Type__c}
|
||||
|
||||
Orchestration started. GitHub repos and Asana project will be created within 5-10 minutes.
|
||||
|
||||
Link: {!varProjectRecord.Id}
|
||||
```
|
||||
|
||||
**Option B: Slack (via HTTP Callout)**
|
||||
|
||||
See [Integration: Salesforce → Slack](../../integrations/salesforce-to-slack.md)
|
||||
|
||||
---
|
||||
|
||||
### 5. Update Opportunity with Project Link
|
||||
|
||||
**Element Type:** Update Records
|
||||
|
||||
**Record:** `{!$Record}`
|
||||
**Fields to Update:**
|
||||
- `Project__c` (Lookup field) = `{!varProjectRecord.Id}`
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Fault Path
|
||||
|
||||
If any step fails:
|
||||
|
||||
**Element Type:** Action - Create Case
|
||||
|
||||
**Fields:**
|
||||
- `Subject` = `"Automation Error: {!$Record.Name} Project Creation Failed"`
|
||||
- `Description` = `"Error creating project for opportunity: {!$Record.Id}\n\nError: {!$Flow.FaultMessage}"`
|
||||
- `Priority` = `"High"`
|
||||
- `Type` = `"Automation Bug"`
|
||||
- `OwnerId` = `<DevOps Queue ID>`
|
||||
|
||||
**Then:** Send email to DevOps team
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
Before activating:
|
||||
|
||||
- [ ] Test with valid opportunity (all fields populated)
|
||||
- [ ] Test with missing fields (verify error email)
|
||||
- [ ] Test with existing project (verify update path)
|
||||
- [ ] Verify project key generation (unique and correct format)
|
||||
- [ ] Verify orchestration kicks off
|
||||
- [ ] Check Chatter/Slack notification appears
|
||||
- [ ] Verify fault path (intentionally cause error)
|
||||
|
||||
---
|
||||
|
||||
## Required Salesforce Objects & Fields
|
||||
|
||||
### Opportunity Custom Fields
|
||||
|
||||
Add these to the Opportunity object if they don't exist:
|
||||
|
||||
| Field API Name | Type | Picklist Values | Description |
|
||||
|----------------|------|-----------------|-------------|
|
||||
| `Primary_Domain__c` | Text(80) | N/A | Client's desired subdomain |
|
||||
| `Package_Type__c` | Picklist | OS, Console, Custom | Product package purchased |
|
||||
| `Service_Tier__c` | Picklist | Starter, Pro, Enterprise | Service level |
|
||||
| `Project__c` | Lookup(Project__c) | N/A | Link to created project |
|
||||
|
||||
---
|
||||
|
||||
### Project Custom Object
|
||||
|
||||
Create this custom object:
|
||||
|
||||
**API Name:** `Project__c`
|
||||
**Label:** Project
|
||||
**Plural Label:** Projects
|
||||
**Record Name:** Project Name (Text)
|
||||
|
||||
#### Fields:
|
||||
|
||||
| Field API Name | Type | Length/Format | Unique | Required | Description |
|
||||
|----------------|------|---------------|--------|----------|-------------|
|
||||
| `Project_Key__c` | Text | 20 | ✅ Yes | ✅ Yes | Unique project identifier (e.g., ACME-1042) |
|
||||
| `Account__c` | Lookup(Account) | N/A | ❌ | ✅ | Related account |
|
||||
| `Opportunity__c` | Lookup(Opportunity) | N/A | ❌ | ✅ | Related opportunity |
|
||||
| `Primary_Domain__c` | Text | 80 | ❌ | ✅ | Client's subdomain |
|
||||
| `Package_Type__c` | Picklist | N/A | ❌ | ✅ | OS, Console, Custom |
|
||||
| `Service_Tier__c` | Picklist | N/A | ❌ | ✅ | Starter, Pro, Enterprise |
|
||||
| `Start_Date__c` | Date | N/A | ❌ | ✅ | Project start date |
|
||||
| `Status__c` | Picklist | N/A | ❌ | ✅ | Setup In Progress, Active, On Hold, Completed |
|
||||
| `Technical_Owner__c` | Lookup(User) | N/A | ❌ | ❌ | Lead developer |
|
||||
| `Backend_Repo_URL__c` | URL | 255 | ❌ | ❌ | GitHub backend repo |
|
||||
| `Frontend_Repo_URL__c` | URL | 255 | ❌ | ❌ | GitHub frontend repo |
|
||||
| `Ops_Repo_URL__c` | URL | 255 | ❌ | ❌ | GitHub ops repo |
|
||||
| `Asana_Project_URL__c` | URL | 255 | ❌ | ❌ | Asana project |
|
||||
| `Last_Deploy_At__c` | DateTime | N/A | ❌ | ❌ | Last deployment timestamp |
|
||||
| `Last_Deploy_SHA__c` | Text | 40 | ❌ | ❌ | Git commit SHA |
|
||||
| `Last_Deploy_Branch__c` | Text | 100 | ❌ | ❌ | Git branch |
|
||||
| `Last_Deploy_Actor__c` | Text | 100 | ❌ | ❌ | Who deployed |
|
||||
| `Deploy_Status__c` | Picklist | N/A | ❌ | ❌ | Success, Failed, Rollback |
|
||||
| `Environment__c` | Picklist | N/A | ❌ | ❌ | Staging, Production |
|
||||
| `Backend_URL__c` | URL | 255 | ❌ | ❌ | Production backend URL |
|
||||
| `Frontend_URL__c` | URL | 255 | ❌ | ❌ | Production frontend URL |
|
||||
| `Release_Notes_URL__c` | URL | 255 | ❌ | ❌ | Link to latest release notes |
|
||||
|
||||
#### Page Layouts:
|
||||
|
||||
Create page layout with sections:
|
||||
1. **Project Information** (Name, Project Key, Status, Dates)
|
||||
2. **Client Details** (Account, Opportunity, Primary Domain, Package, Tier)
|
||||
3. **Technical Details** (Technical Owner, Repo URLs, Asana URL)
|
||||
4. **Deployment Info** (Last Deploy fields, URLs)
|
||||
|
||||
---
|
||||
|
||||
## Deployment Instructions
|
||||
|
||||
### Step 1: Create Custom Objects & Fields
|
||||
|
||||
Use Salesforce Setup → Object Manager to create:
|
||||
- Project__c object with all fields listed above
|
||||
- Custom fields on Opportunity object
|
||||
|
||||
### Step 2: Create Named Credentials (for later integrations)
|
||||
|
||||
Setup → Named Credentials:
|
||||
- `GitHub_API` (for calling GitHub API)
|
||||
- `Asana_API` (for calling Asana API)
|
||||
- `Slack_Webhook` (for Slack notifications)
|
||||
|
||||
### Step 3: Build the Flow
|
||||
|
||||
1. Setup → Flows → New Flow
|
||||
2. Choose "Record-Triggered Flow"
|
||||
3. Configure trigger as specified above
|
||||
4. Build each element in order
|
||||
5. Save as "Opp_Automation_OnStageChange"
|
||||
6. Activate
|
||||
|
||||
### Step 4: Test in Sandbox
|
||||
|
||||
1. Create a test opportunity
|
||||
2. Fill all required fields
|
||||
3. Change stage to "Closed Won"
|
||||
4. Verify:
|
||||
- Project record created
|
||||
- Fields populated correctly
|
||||
- Notification sent
|
||||
- No errors in debug logs
|
||||
|
||||
### Step 5: Deploy to Production
|
||||
|
||||
Use Change Sets or Salesforce CLI:
|
||||
|
||||
```bash
|
||||
sf project deploy start \
|
||||
--source-dir force-app/main/default/flows/Opp_Automation_OnStageChange.flow-meta.xml \
|
||||
--target-org production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitoring & Maintenance
|
||||
|
||||
### Weekly:
|
||||
- Review flow error logs
|
||||
- Check for opportunities stuck in "Closed Won" without projects
|
||||
|
||||
### Monthly:
|
||||
- Review project key uniqueness
|
||||
- Audit project creation success rate (target: >98%)
|
||||
|
||||
### Quarterly:
|
||||
- Review and update picklist values
|
||||
- Optimize flow performance if needed
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Salesforce Orchestration: New Client Kickoff](../orchestrations/new-client-kickoff-orchestration.md)
|
||||
- [Workflow: New Client Kickoff](../../workflows/new-client-kickoff.md)
|
||||
- [Integration: Salesforce → GitHub](../../integrations/salesforce-to-github.md)
|
||||
- [Integration: Salesforce → Asana](../../integrations/salesforce-to-asana.md)
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
| Date | Version | Change | Author |
|
||||
|------|---------|--------|--------|
|
||||
| 2025-11-17 | 1.0 | Initial specification | Cece (Claude) |
|
||||
@@ -0,0 +1,642 @@
|
||||
# Salesforce Orchestration: New Client Kickoff
|
||||
|
||||
**API Name:** `New_Client_Kickoff_Orchestration`
|
||||
**Type:** Multi-Stage Orchestration
|
||||
**Status:** Active
|
||||
**Last Updated:** 2025-11-17
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
This orchestration coordinates the entire **end-to-end new client onboarding process** across multiple teams and systems, from deal closure to go-live.
|
||||
|
||||
**Key Benefits:**
|
||||
- Orchestrates cross-functional work (Sales, Engineering, Customer Success)
|
||||
- Enforces process consistency
|
||||
- Provides visibility into project status
|
||||
- Automates hand-offs between teams
|
||||
- Ensures nothing falls through the cracks
|
||||
|
||||
---
|
||||
|
||||
## Input Variables
|
||||
|
||||
| Variable Name | Type | Required | Description |
|
||||
|---------------|------|----------|-------------|
|
||||
| `ProjectRecordId` | Record ID | ✅ | ID of the Project__c record |
|
||||
| `OpportunityRecordId` | Record ID | ✅ | ID of the Opportunity |
|
||||
| `AccountRecordId` | Record ID | ✅ | ID of the Account |
|
||||
|
||||
---
|
||||
|
||||
## Stages Overview
|
||||
|
||||
```
|
||||
1. Sales Handoff (1-2 days)
|
||||
↓
|
||||
2. Technical Setup (3-5 days) ← KEY AUTOMATION STAGE
|
||||
↓
|
||||
3. Customer Onboarding (5-10 days)
|
||||
↓
|
||||
4. Review & Go-Live (2-3 days)
|
||||
```
|
||||
|
||||
**Total Timeline:** 11-20 days (varies by package complexity)
|
||||
|
||||
---
|
||||
|
||||
## Stage 1: Sales Handoff
|
||||
|
||||
**Owner:** Sales Operations
|
||||
**Duration:** 1-2 days
|
||||
**Status Field:** `Project__c.Status__c` = "Sales Handoff"
|
||||
|
||||
### Steps
|
||||
|
||||
#### Step 1.1: Send Welcome Email to Client
|
||||
|
||||
**Element Type:** Action - Send Email
|
||||
|
||||
**Template:** `Client_Welcome_Email`
|
||||
|
||||
**To:** Primary Contact from Opportunity
|
||||
**CC:** Account Executive, Account Owner
|
||||
**From:** ops@blackroad.com
|
||||
|
||||
**Merge Fields:**
|
||||
- `{!Account.Name}`
|
||||
- `{!Project.Project_Key__c}`
|
||||
- `{!Project.Package_Type__c}`
|
||||
- `{!Opportunity.Owner.Name}`
|
||||
|
||||
---
|
||||
|
||||
#### Step 1.2: Create Internal Kickoff Task
|
||||
|
||||
**Element Type:** Action - Create Task
|
||||
|
||||
**Assigned To:** Sales Operations Manager
|
||||
**Subject:** `Internal Kickoff: {!Project.Name}`
|
||||
**Due Date:** `TODAY() + 1`
|
||||
**Priority:** High
|
||||
|
||||
**Description:**
|
||||
```
|
||||
New project needs kickoff coordination:
|
||||
|
||||
Project: {!Project.Name}
|
||||
Project Key: {!Project.Project_Key__c}
|
||||
Account: {!Account.Name}
|
||||
Package: {!Project.Package_Type__c}
|
||||
Service Tier: {!Project.Service_Tier__c}
|
||||
|
||||
Action Required:
|
||||
- Verify all Opportunity fields are complete
|
||||
- Confirm primary contact is correct
|
||||
- Schedule kickoff call with client
|
||||
- Brief technical team on any special requirements
|
||||
|
||||
Salesforce Project: {!Project.Id}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Step 1.3: Wait for Approval
|
||||
|
||||
**Element Type:** Interactive Step - Screen Flow
|
||||
|
||||
**Screen:** "Sales Handoff Complete?"
|
||||
|
||||
**Fields:**
|
||||
- Checkbox: "Kickoff call scheduled"
|
||||
- Checkbox: "Client expectations set"
|
||||
- Checkbox: "Special requirements documented"
|
||||
- Text Area: "Notes for technical team"
|
||||
|
||||
**Assigned To:** Sales Operations Manager
|
||||
|
||||
**Completion Criteria:** All checkboxes checked
|
||||
|
||||
---
|
||||
|
||||
#### Step 1.4: Update Project Status
|
||||
|
||||
**Element Type:** Action - Update Records
|
||||
|
||||
**Record:** Project__c
|
||||
**Fields:**
|
||||
- `Status__c` = "Technical Setup"
|
||||
- `Sales_Handoff_Completed__c` = `TODAY()`
|
||||
- `Technical_Notes__c` = `{!Screen.Notes}`
|
||||
|
||||
---
|
||||
|
||||
## Stage 2: Technical Setup
|
||||
|
||||
**Owner:** DevOps / Engineering
|
||||
**Duration:** 3-5 days (mostly automated)
|
||||
**Status Field:** `Project__c.Status__c` = "Technical Setup"
|
||||
|
||||
### Steps
|
||||
|
||||
#### Step 2.1: Create GitHub Repositories
|
||||
|
||||
**Element Type:** Autolaunched Flow - HTTP Callout
|
||||
|
||||
**Named Credential:** `GitHub_API`
|
||||
**Endpoint:** `POST https://api.github.com/orgs/blackboxprogramming/repos`
|
||||
|
||||
**For Each Repo Type:** (Backend, Frontend, Ops)
|
||||
|
||||
**Payload:**
|
||||
```json
|
||||
{
|
||||
"name": "blackroad-{!Project.Project_Key__c}-{!RepoType}",
|
||||
"description": "{!Account.Name} - {!Project.Package_Type__c}",
|
||||
"private": true,
|
||||
"auto_init": true,
|
||||
"gitignore_template": "Python"
|
||||
}
|
||||
```
|
||||
|
||||
**Store Response:** Capture repo URLs
|
||||
|
||||
**Update Project Record:**
|
||||
- `Backend_Repo_URL__c` = Response.html_url (for backend)
|
||||
- `Frontend_Repo_URL__c` = Response.html_url (for frontend)
|
||||
- `Ops_Repo_URL__c` = Response.html_url (for ops)
|
||||
|
||||
**See:** [Integration: Salesforce → GitHub](../../integrations/salesforce-to-github.md) for detailed API specs
|
||||
|
||||
---
|
||||
|
||||
#### Step 2.2: Apply Repository Templates
|
||||
|
||||
**Element Type:** Autolaunched Flow - HTTP Callout (Multiple)
|
||||
|
||||
**For Each Repo:**
|
||||
|
||||
1. **Create Labels**
|
||||
- POST to `/repos/{owner}/{repo}/labels`
|
||||
- Apply standard label set from `labels.json`
|
||||
|
||||
2. **Apply Branch Protection**
|
||||
- PUT to `/repos/{owner}/{repo}/branches/main/protection`
|
||||
- Configure as per branch-protection spec
|
||||
|
||||
3. **Create Workflows**
|
||||
- POST to create files via GitHub API
|
||||
- Add `ci.yml`, `deploy.yml`, `safety.yml`
|
||||
|
||||
4. **Add Secrets**
|
||||
- POST to `/repos/{owner}/{repo}/actions/secrets`
|
||||
- Add: `PROJECT_KEY`, `SALESFORCE_INSTANCE_URL`, `SALESFORCE_ACCESS_TOKEN`
|
||||
|
||||
---
|
||||
|
||||
#### Step 2.3: Create Asana Project
|
||||
|
||||
**Element Type:** Autolaunched Flow - HTTP Callout
|
||||
|
||||
**Named Credential:** `Asana_API`
|
||||
**Endpoint:** `POST https://app.asana.com/api/1.0/projects`
|
||||
|
||||
**Payload:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"name": "{!Account.Name} - {!Project.Project_Key__c}",
|
||||
"workspace": "{!$Credential.Asana_API.Workspace_GID}",
|
||||
"team": "{!$Credential.Asana_API.Team_GID}",
|
||||
"notes": "Salesforce Project: {!Project.Id}\nRepos:\n- Backend: {!Project.Backend_Repo_URL__c}\n- Frontend: {!Project.Frontend_Repo_URL__c}\n- Ops: {!Project.Ops_Repo_URL__c}",
|
||||
"default_view": "board",
|
||||
"color": "light-green"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Store Response:** `{!AsanaProjectGID}`
|
||||
|
||||
**Update Project:**
|
||||
- `Asana_Project_URL__c` = `https://app.asana.com/0/{!AsanaProjectGID}/list`
|
||||
|
||||
**See:** [Integration: Salesforce → Asana](../../integrations/salesforce-to-asana.md) for detailed API specs
|
||||
|
||||
---
|
||||
|
||||
#### Step 2.4: Create Asana Sections & Tasks
|
||||
|
||||
**Element Type:** Loop + HTTP Callouts
|
||||
|
||||
**For Each Section:** (Discovery, Architecture, Build, Testing, Go-Live)
|
||||
|
||||
1. **Create Section:**
|
||||
```
|
||||
POST /projects/{!AsanaProjectGID}/sections
|
||||
{"data": {"name": "Discovery"}}
|
||||
```
|
||||
|
||||
2. **Create Tasks in Section:**
|
||||
|
||||
**Discovery Section:**
|
||||
- Task: "Confirm domain + DNS with client" → Assign to Sales Ops
|
||||
- Task: "Gather branding assets" → Assign to Design team
|
||||
|
||||
**Architecture Section:**
|
||||
- Task: "Wire up Railway/Cloudflare environments" → Assign to DevOps
|
||||
- Task: "Enable CI/CD secrets" → Assign to DevOps
|
||||
- Task: "Design database schema" → Assign to Backend team
|
||||
|
||||
**Build Section:**
|
||||
- Task: "Set up database and migrations" → Assign to Backend
|
||||
- Task: "Implement authentication" → Assign to Backend
|
||||
- Task: "Build core UI components" → Assign to Frontend
|
||||
|
||||
**Testing Section:**
|
||||
- Task: "Run end-to-end test suite" → Assign to QA
|
||||
- Task: "Security scan and review" → Assign to Security team
|
||||
|
||||
**Go-Live Section:**
|
||||
- Task: "Final client walkthrough" → Assign to Customer Success
|
||||
- Task: "Deploy to production" → Assign to DevOps
|
||||
|
||||
**Each Task Payload:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"name": "{!TaskName}",
|
||||
"projects": ["{!AsanaProjectGID}"],
|
||||
"memberships": [{"project": "{!AsanaProjectGID}", "section": "{!SectionGID}"}],
|
||||
"assignee": "{!AssigneeEmail}",
|
||||
"due_on": "{!CalculatedDueDate}",
|
||||
"notes": "Salesforce Project: {!Project.Id}\nGitHub Repos: {!Project.Backend_Repo_URL__c}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Step 2.5: Wait for Repositories to Be Verified
|
||||
|
||||
**Element Type:** Interactive Step - Approval
|
||||
|
||||
**Approver:** DevOps Manager
|
||||
**Approval Criteria:**
|
||||
- [ ] All 3 repos created and accessible
|
||||
- [ ] CI/CD workflows active
|
||||
- [ ] Branch protection enabled
|
||||
- [ ] Secrets configured
|
||||
|
||||
**Timeout:** 2 days
|
||||
**Escalation:** If not approved in 2 days, send alert to Engineering Manager
|
||||
|
||||
---
|
||||
|
||||
#### Step 2.6: Update Project Status
|
||||
|
||||
**Element Type:** Action - Update Records
|
||||
|
||||
**Record:** Project__c
|
||||
**Fields:**
|
||||
- `Status__c` = "Customer Onboarding"
|
||||
- `Technical_Setup_Completed__c` = `TODAY()`
|
||||
|
||||
---
|
||||
|
||||
## Stage 3: Customer Onboarding
|
||||
|
||||
**Owner:** Customer Success
|
||||
**Duration:** 5-10 days
|
||||
**Status Field:** `Project__c.Status__c` = "Customer Onboarding"
|
||||
|
||||
### Steps
|
||||
|
||||
#### Step 3.1: Schedule Kickoff Call
|
||||
|
||||
**Element Type:** Action - Create Event
|
||||
|
||||
**Assigned To:** Customer Success Manager
|
||||
**Invitees:**
|
||||
- Primary Contact (from Opportunity)
|
||||
- Technical Owner (from Project)
|
||||
- Account Executive
|
||||
|
||||
**Subject:** `Kickoff Call: {!Project.Name}`
|
||||
**Duration:** 1 hour
|
||||
**Due Date:** `TODAY() + 3`
|
||||
|
||||
**Description:**
|
||||
```
|
||||
Agenda:
|
||||
1. Introductions (5 min)
|
||||
2. Project overview and timeline (10 min)
|
||||
3. Requirements review (20 min)
|
||||
4. Q&A (20 min)
|
||||
5. Next steps (5 min)
|
||||
|
||||
Preparation:
|
||||
- Review Opportunity notes
|
||||
- Review Asana project board
|
||||
- Prepare questions about domain, branding, integrations
|
||||
|
||||
Links:
|
||||
- Salesforce Project: {!Project.Id}
|
||||
- Asana Board: {!Project.Asana_Project_URL__c}
|
||||
- GitHub Repos: {!Project.Backend_Repo_URL__c}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Step 3.2: Wait for Development Milestones
|
||||
|
||||
**Element Type:** Wait - Condition-Based
|
||||
|
||||
**Condition:**
|
||||
- At least 50% of Asana tasks in "Build" section marked complete
|
||||
**OR**
|
||||
- Project status manually changed
|
||||
**OR**
|
||||
- 10 days elapsed
|
||||
|
||||
**Check Frequency:** Daily
|
||||
|
||||
---
|
||||
|
||||
#### Step 3.3: Send Progress Update to Client
|
||||
|
||||
**Element Type:** Action - Send Email (every week)
|
||||
|
||||
**Template:** `Client_Progress_Update`
|
||||
|
||||
**To:** Primary Contact
|
||||
**CC:** Account Executive, Technical Owner
|
||||
|
||||
**Merge Fields:**
|
||||
- Progress summary from Asana
|
||||
- Link to staging environment (if available)
|
||||
- Next milestones
|
||||
|
||||
---
|
||||
|
||||
#### Step 3.4: Wait for Testing Complete
|
||||
|
||||
**Element Type:** Interactive Step - Checkbox
|
||||
|
||||
**Screen:** "Testing Complete?"
|
||||
|
||||
**Assigned To:** QA Lead
|
||||
|
||||
**Fields:**
|
||||
- [ ] All end-to-end tests pass
|
||||
- [ ] Security scan clean
|
||||
- [ ] Performance acceptable
|
||||
- [ ] Client UAT completed
|
||||
|
||||
---
|
||||
|
||||
#### Step 3.5: Update Project Status
|
||||
|
||||
**Element Type:** Action - Update Records
|
||||
|
||||
**Record:** Project__c
|
||||
**Fields:**
|
||||
- `Status__c` = "Review & Go-Live"
|
||||
- `Onboarding_Completed__c` = `TODAY()`
|
||||
|
||||
---
|
||||
|
||||
## Stage 4: Review & Go-Live
|
||||
|
||||
**Owner:** Customer Success + DevOps
|
||||
**Duration:** 2-3 days
|
||||
**Status Field:** `Project__c.Status__c` = "Review & Go-Live"
|
||||
|
||||
### Steps
|
||||
|
||||
#### Step 4.1: Final Client Walkthrough
|
||||
|
||||
**Element Type:** Action - Create Event
|
||||
|
||||
**Assigned To:** Customer Success Manager
|
||||
**Invitees:** Primary Contact, Technical Owner
|
||||
|
||||
**Subject:** `Final Review: {!Project.Name}`
|
||||
**Duration:** 30 minutes
|
||||
**Due Date:** `TODAY() + 1`
|
||||
|
||||
---
|
||||
|
||||
#### Step 4.2: Wait for Client Approval
|
||||
|
||||
**Element Type:** Interactive Step - Screen Flow
|
||||
|
||||
**Screen:** "Client Approval"
|
||||
|
||||
**Assigned To:** Customer Success Manager
|
||||
|
||||
**Fields:**
|
||||
- Radio: "Client approval status" (Approved / Needs Changes / Rejected)
|
||||
- Text Area: "Client feedback"
|
||||
- Checkbox: "Client trained on system"
|
||||
|
||||
**Conditional Logic:**
|
||||
- If "Needs Changes" → Loop back to Stage 3, Step 3.2
|
||||
- If "Rejected" → Escalate to Sales leadership
|
||||
- If "Approved" → Continue
|
||||
|
||||
---
|
||||
|
||||
#### Step 4.3: Production Deployment
|
||||
|
||||
**Element Type:** Action - Create Task
|
||||
|
||||
**Assigned To:** DevOps team
|
||||
**Subject:** `Deploy to Production: {!Project.Project_Key__c}`
|
||||
**Priority:** High
|
||||
**Due Date:** `TODAY() + 1`
|
||||
|
||||
**Description:**
|
||||
```
|
||||
Project is client-approved and ready for production deployment.
|
||||
|
||||
Action:
|
||||
1. Verify staging is stable
|
||||
2. Create production Railway/Cloudflare environments
|
||||
3. Merge to main and deploy (will trigger GitHub Actions)
|
||||
4. Verify health checks
|
||||
5. Mark this task complete
|
||||
|
||||
Links:
|
||||
- Asana Deploy Task: {!Project.Asana_Project_URL__c}
|
||||
- Backend Repo: {!Project.Backend_Repo_URL__c}
|
||||
- Ops Repo: {!Project.Ops_Repo_URL__c}
|
||||
|
||||
Note: Deployment will auto-update Salesforce Project record when complete.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Step 4.4: Wait for Deploy Task Complete
|
||||
|
||||
**Element Type:** Wait - Task Completion
|
||||
|
||||
**Wait For:** Task created in Step 4.3 to be marked complete
|
||||
|
||||
**Timeout:** 3 days
|
||||
**Escalation:** Alert Engineering Manager if not completed
|
||||
|
||||
---
|
||||
|
||||
#### Step 4.5: Send Go-Live Notification
|
||||
|
||||
**Element Type:** Action - Send Email
|
||||
|
||||
**Template:** `Client_GoLive_Notification`
|
||||
|
||||
**To:** Primary Contact
|
||||
**CC:** Account Executive, Customer Success Manager
|
||||
|
||||
**Merge Fields:**
|
||||
- Production URL: `{!Project.Frontend_URL__c}`
|
||||
- Support contact info
|
||||
- Documentation links
|
||||
|
||||
---
|
||||
|
||||
#### Step 4.6: Update Project Status to Active
|
||||
|
||||
**Element Type:** Action - Update Records
|
||||
|
||||
**Record:** Project__c
|
||||
**Fields:**
|
||||
- `Status__c` = "Active"
|
||||
- `Go_Live_Date__c` = `TODAY()`
|
||||
|
||||
---
|
||||
|
||||
#### Step 4.7: Create Success Metrics Dashboard
|
||||
|
||||
**Element Type:** Action - Create Dashboard (optional)
|
||||
|
||||
**Purpose:** Track ongoing project health
|
||||
|
||||
**Metrics:**
|
||||
- Deploy frequency
|
||||
- Error rates
|
||||
- Customer support tickets
|
||||
- Feature adoption
|
||||
|
||||
---
|
||||
|
||||
## Orchestration Complete
|
||||
|
||||
**Final Actions:**
|
||||
|
||||
1. **Post to Chatter:** Announce successful onboarding
|
||||
2. **Update Opportunity:** Set `Stage` = "Closed Won - Active"
|
||||
3. **Create Renewal Opportunity:** Schedule for renewal date
|
||||
4. **Archive Orchestration:** Store for audit trail
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
### If GitHub API Fails (Step 2.1-2.2)
|
||||
|
||||
1. Log error to Salesforce
|
||||
2. Create high-priority task for DevOps
|
||||
3. Send alert to #ops Slack
|
||||
4. Pause orchestration (manual resume after fix)
|
||||
|
||||
### If Asana API Fails (Step 2.3-2.4)
|
||||
|
||||
1. Log error
|
||||
2. Continue orchestration (Asana is nice-to-have)
|
||||
3. Create manual Asana project (via SOP)
|
||||
|
||||
### If Client Approval Rejected (Step 4.2)
|
||||
|
||||
1. Loop back to appropriate stage based on feedback
|
||||
2. Create issue in GitHub with client feedback
|
||||
3. Notify engineering team
|
||||
|
||||
---
|
||||
|
||||
## Monitoring & Metrics
|
||||
|
||||
### Track These KPIs:
|
||||
|
||||
| Metric | Target | Measured By |
|
||||
|--------|--------|-------------|
|
||||
| Time to First Commit | < 3 days from Closed Won | GitHub first commit timestamp |
|
||||
| Time to Go-Live | < 20 days from Closed Won | `Go_Live_Date__c` - `Start_Date__c` |
|
||||
| Orchestration Completion Rate | > 95% | Successful completions / total starts |
|
||||
| Stage Escalations | < 5% | Escalations triggered / total projects |
|
||||
| Client Approval First-Time Rate | > 80% | Approved without loops / total |
|
||||
|
||||
### Weekly Review:
|
||||
- How many orchestrations in flight?
|
||||
- Any stuck in a stage for > expected duration?
|
||||
- Any escalations or errors?
|
||||
|
||||
### Monthly Audit:
|
||||
- Review all completed orchestrations
|
||||
- Identify bottlenecks
|
||||
- Update stage durations based on actuals
|
||||
|
||||
---
|
||||
|
||||
## Deployment Instructions
|
||||
|
||||
### Prerequisites:
|
||||
1. Create all custom objects and fields (see Flow spec)
|
||||
2. Set up Named Credentials (GitHub, Asana, Slack)
|
||||
3. Create email templates
|
||||
4. Set up approval processes
|
||||
|
||||
### Build Orchestration:
|
||||
|
||||
1. **Setup → Orchestrator → New Orchestration**
|
||||
2. Name: `New_Client_Kickoff_Orchestration`
|
||||
3. Add stages (1-4) as specified
|
||||
4. For each stage, add steps as elements
|
||||
5. Configure inputs/outputs
|
||||
6. Set wait conditions
|
||||
7. Add error handlers
|
||||
8. Activate
|
||||
|
||||
### Test in Sandbox:
|
||||
|
||||
1. Create test opportunity
|
||||
2. Move to Closed Won
|
||||
3. Verify orchestration starts
|
||||
4. Walk through each stage
|
||||
5. Verify APIs called correctly
|
||||
6. Check error handling
|
||||
|
||||
### Deploy to Production:
|
||||
|
||||
```bash
|
||||
sf project deploy start \
|
||||
--source-dir force-app/main/default/orchestrations/New_Client_Kickoff_Orchestration.orchestration-meta.xml \
|
||||
--target-org production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Salesforce Flow: Opp_Automation_OnStageChange](../flows/opp-automation-onstagechange.md)
|
||||
- [Workflow: New Client Kickoff](../../workflows/new-client-kickoff.md)
|
||||
- [Integration: Salesforce → GitHub](../../integrations/salesforce-to-github.md)
|
||||
- [Integration: Salesforce → Asana](../../integrations/salesforce-to-asana.md)
|
||||
- [Playbook: Brenda's New Client Checklist](../../playbooks/brenda-new-client-checklist.md)
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
| Date | Version | Change | Author |
|
||||
|------|---------|--------|--------|
|
||||
| 2025-11-17 | 1.0 | Initial specification | Cece (Claude) |
|
||||
Reference in New Issue
Block a user