Move Stage Automation Processor
Overview
The Move Stage automation automatically moves deals to a different pipeline stage. It validates both stages are in the same pipeline and emits real-time socket events for UI updates.
Source File: queue-manager/queues/deals/automations/stage.js
Triggered By: queue-manager/services/deals/automations.js
Business Impact: CRITICAL - Deal progression
Processing Logic
sequenceDiagram
participant AUTO as Automation Service
participant QUEUE as Stage Queue
participant DEAL as Deals
participant STAGE as Pipeline Stages
participant SOCKET as WebSocket
AUTO->>QUEUE: Add automation job
QUEUE->>STAGE: Validate target stage exists
STAGE-->>QUEUE: Stage data (with pipeline_id)
loop For Each Deal
QUEUE->>DEAL: Validate same pipeline
alt Same Pipeline
QUEUE->>DEAL: Update stage_id
QUEUE->>SOCKET: Emit stage change event
QUEUE->>DEAL: Mark automation triggered
else Different Pipeline
QUEUE->>QUEUE: Skip (error)
end
end
Key Features
Stage Validation
const toStageID = automation.data.stage_id;
const toStageData = await PipelineStage.findById(toStageID).lean();
if (!toStageData) {
throw new Error('Stage does not exist.');
}
const toStagePipelineID = toStageData.pipeline_id;
Pipeline Verification
const fromStagePipelineID = deal.pipeline_id;
if (fromStagePipelineID.toString() !== toStagePipelineID.toString()) {
throw new Error('Both stages are not in same pipeline.');
}
Stage Update
await Deal.findByIdAndUpdate(dealID, {
stage_id: toStageID,
last_updated_by: userID,
});
Real-Time Updates
socketEmit({
event: 'deal:stage:changed',
room: `account:${accountID}`,
data: {
deal: dealID,
from_stage: fromStageID,
to_stage: toStageID,
},
});
Collections Used
Input: deal-automation
Validation: pipeline-stage
Query: deal
Update: deal (stage_id field)
Use Cases
Example 1: Auto-Progress Qualified Leads
// Automation
{
stage_id: "contacted",
action: "move_stage",
data: {
stage_id: "qualified"
},
delay: 172800 // 2 days
}
// Result: Leads auto-progress from "contacted" to "qualified" after 2 days
Example 2: Fast-Track Hot Leads
// Automation
{
stage_id: "new_lead",
action: "move_stage",
data: {
stage_id: "demo_scheduled"
},
delay: 0 // Immediate
}
// Result: Hot leads immediately move to demo scheduling
Example 3: Timeout Non-Responsive
// Automation
{
stage_id: "awaiting_response",
action: "move_stage",
data: {
stage_id: "cold"
},
delay: 604800 // 7 days
}
// Result: Deals with no response for 7 days moved to cold stage
Automation Chain
Moving to a new stage can trigger other automations:
// Stage 1: "contacted" → auto-move to "qualified" (2 days)
// Stage 2: "qualified" → send email, create reminder
// Stage 3: "qualified" → auto-move to "proposal" (5 days)
This creates a complete automation sequence.
Pipeline Restriction
Why Same Pipeline Only?
- Data Integrity: Stages have pipeline-specific configurations
- Lost Context: Moving across pipelines loses stage history
- Business Logic: Different pipelines represent different sales processes
Example Error
// Deal in "Sales Pipeline"
pipeline_id: pipelineA
// Trying to move to stage in "Support Pipeline"
stage_id: stageB (pipeline_id: pipelineB)
// Result: Error - "Both stages are not in same pipeline."
Real-Time Events
Socket Event Structure
{
event: 'deal:stage:changed',
room: 'account:123',
data: {
deal: dealID,
from_stage: fromStageID,
to_stage: toStageID,
automation: true
}
}
UI Impact
- Kanban Board: Deal card moves between columns
- Deal Detail: Stage badge updates
- Activity Feed: Stage change logged
- Notifications: Followers notified
Error Handling
Common Errors
- Stage Doesn't Exist: Target stage deleted
- Different Pipeline: Stages not in same pipeline
- Deal Not Found: Deal was deleted
- Permission Error: User lacks stage access
Error Response
{
deal: dealID,
from_stage: fromStageID,
to_stage: toStageID,
message: "Both stages are not in same pipeline.",
additional_info: {...}
}
Performance
Execution Time: 150-400ms per deal
Socket Emit: Real-time (0-50ms)
Complexity: MEDIUM
Lines of Code: 191