Skip to content

Unified Incident Opening Workflowยค

Date: October 10, 2025 Status: Current implementation

๐Ÿ“‹ Overviewยค

The incident opening workflow in FireFighter now uses a unified form for all incident priorities (P1-P5). This simplified workflow eliminates the need for incident type selection (Step 3) and uses dynamic field visibility based on selected impacts.

๐Ÿ”„ Key Changes from Previous Workflowยค

Before (Multiple Forms)ยค

  • 6 separate forms: 1 critical form + 5 RAID forms (Customer, Seller, Internal, Documentation, Feature Request)
  • STEP 3 required: Users had to select incident type for P4/P5
  • Static forms: Each form had fixed fields regardless of impact selection

After (Unified Form)ยค

  • 1 unified form: UnifiedIncidentForm handles all priorities
  • STEP 3 hidden: Automatically skipped since only one form type exists
  • Dynamic fields: Fields show/hide based on selected impacts

๐Ÿ“Š Complete Unified Workflowยค

PART 1: All Incidents (P1-P5)ยค

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ STEP 0: Intro                                               โ”‚
โ”‚ - Welcome message                                           โ”‚
โ”‚ - Warning if recent incidents in the last hour              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ STEP 1: Set Impacts (SelectImpactForm)                     โ”‚
โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€   โ”‚
โ”‚ Dynamic fields for each ImpactType:                        โ”‚
โ”‚  โ€ข Business Impact (HIGH/MEDIUM/LOW/LOWEST/NO)              โ”‚
โ”‚  โ€ข Operational Impact (HIGH/MEDIUM/LOW/LOWEST/NO)           โ”‚
โ”‚  โ€ข Technical Impact (HIGH/MEDIUM/LOW/LOWEST/NO)             โ”‚
โ”‚                                                             โ”‚
โ”‚ โ†’ Auto-calculates priority_value and response_type         โ”‚
โ”‚   - priority_value < 4 โ†’ response_type = "critical" (P1-P3) โ”‚
โ”‚   - priority_value >= 4 โ†’ response_type = "normal" (P4-P5)  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ STEP 2: Priority/SLA Display (Response Type Block)         โ”‚
โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€   โ”‚
โ”‚ Displays (non-editable):                                    โ”‚
โ”‚  โ€ข ๐Ÿ”ด๐ŸŸก๐ŸŸข Selected priority: P1/P2/P3/P4/P5 - Description    โ”‚
โ”‚  โ€ข โฑ๏ธ SLA: 15min / 30min / 1h / 2days / 5days             โ”‚
โ”‚  โ€ข :gear: Process: Slack+Jira or Jira only                 โ”‚
โ”‚  โ€ข :pushpin: Selected impacts: [detailed list]             โ”‚
โ”‚  โ€ข :warning: Critical warning (P1-P3 only)                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ STEP 3: Select Incident Type                               โ”‚
โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€   โ”‚
โ”‚ โšก AUTOMATICALLY HIDDEN โšก                                   โ”‚
โ”‚                                                             โ”‚
โ”‚ Since len(INCIDENT_TYPES[response_type]) == 1,             โ”‚
โ”‚ this step is skipped entirely.                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ STEP 4: Set Details (UnifiedIncidentFormSlack)             โ”‚
โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€   โ”‚
โ”‚ COMMON Fields (always shown):                               โ”‚
โ”‚  โ€ข incident_category (GroupedModelChoiceField)              โ”‚
โ”‚  โ€ข environment (ModelMultipleChoiceField) - ALL priorities  โ”‚
โ”‚  โ€ข platform (MultipleChoiceField, default ALL) - ALL        โ”‚
โ”‚  โ€ข title (CharField, 10-128 chars)                          โ”‚
โ”‚  โ€ข description (TextField, 10-1200 chars)                   โ”‚
โ”‚  โ€ข priority (HiddenInput - auto-determined)                 โ”‚
โ”‚                                                             โ”‚
โ”‚ CONDITIONAL Fields (based on response_type):                โ”‚
โ”‚  โ€ข suggested_team_routing (P4/P5 ONLY)                      โ”‚
โ”‚                                                             โ”‚
โ”‚ DYNAMIC Fields (based on selected impacts):                 โ”‚
โ”‚  IF Customer Impact selected:                               โ”‚
โ”‚    โ€ข zendesk_ticket_id (optional)                           โ”‚
โ”‚  IF Seller Impact selected:                                 โ”‚
โ”‚    โ€ข seller_contract_id (optional)                          โ”‚
โ”‚    โ€ข is_key_account (boolean)                               โ”‚
โ”‚    โ€ข is_seller_in_golden_list (boolean)                     โ”‚
โ”‚    โ€ข zoho_desk_ticket_id (optional)                         โ”‚
โ”‚  IF Employee Impact selected:                               โ”‚
โ”‚    โ€ข (no additional fields)                                 โ”‚
โ”‚                                                             โ”‚
โ”‚ Note: Multiple impact types can be selected simultaneously  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ STEP 5: Review & Submit                                    โ”‚
โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€   โ”‚
โ”‚ Displays (based on response_type):                          โ”‚
โ”‚  IF Critical (P1-P3):                                       โ”‚
โ”‚    โ€ข :slack: Dedicated Slack channel will be created        โ”‚
โ”‚    โ€ข ~X responders will be invited                          โ”‚
โ”‚    โ€ข :jira_new: Associated Jira ticket will be created      โ”‚
โ”‚    โ€ข :pagerduty: (if outside office hours)                  โ”‚
โ”‚  IF Normal (P4-P5):                                         โ”‚
โ”‚    โ€ข :jira_new: A Jira ticket will be created               โ”‚
โ”‚    โ€ข (NO Slack channel, NO PagerDuty)                       โ”‚
โ”‚                                                             โ”‚
โ”‚ Button: "Create the incident"                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“
                    [SUBMIT TRIGGERED]
                            โ†“
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ†“                                       โ†“
   [CRITICAL P1-P3]                        [NORMAL P4-P5]
        โ†“                                       โ†“
_trigger_critical_incident_workflow    _trigger_normal_incident_workflow
        โ†“                                       โ†“
  Create Incident object                Prepare fields (prepare_jira_fields):
  Save impacts                           - Extract environments, platforms
  Create Slack channel                   - Compute business_impact
  Create Jira ticket                     - Gather optional fields
  Invite responders                     Create Jira (jira_client.create_issue)
  Alert PagerDuty (if needed)            - Passes ALL custom fields
                                        Process ticket (process_jira_issue):
                                         - Save impacts, set watchers
                                         - Alert Slack

๐ŸŽฏ Dynamic Field Visibility Logicยค

Decision Tree for Field Displayยค

START: User selects impacts in STEP 1
    โ†“
Calculate priority_value โ†’ Determine response_type
    โ†“
Build visible_fields list:
    โ”œโ”€ ALWAYS include: title, description, incident_category,
    โ”‚                  environment, platform, priority
    โ†“
IF response_type == "normal" (P4/P5):
    โ”œโ”€ ADD: suggested_team_routing
    โ†“
FOR EACH selected impact:
    โ”œโ”€ IF customers_impact != NONE:
    โ”‚    โ””โ”€ ADD: zendesk_ticket_id
    โ”œโ”€ IF sellers_impact != NONE:
    โ”‚    โ””โ”€ ADD: seller_contract_id, is_key_account,
    โ”‚             is_seller_in_golden_list, zoho_desk_ticket_id
    โ””โ”€ IF employees_impact != NONE:
         โ””โ”€ (no additional fields)
    โ†“
Remove all fields NOT in visible_fields from form
    โ†“
Display final form with only relevant fields

Example Scenariosยค

Scenario 1: P1 Critical with Customer Impact

Response Type: critical
Impacts: customers_impact = HIGH

Visible Fields:
โœ… title, description, incident_category
โœ… environment (multiple), platform (multiple)
โœ… priority (hidden)
โœ… zendesk_ticket_id (customer impact)
โŒ suggested_team_routing (not P4/P5)
โŒ seller fields (no seller impact)

Scenario 2: P4 Normal with Seller + Customer Impact

Response Type: normal
Impacts: sellers_impact = MEDIUM, customers_impact = LOW

Visible Fields:
โœ… title, description, incident_category
โœ… environment (multiple), platform (multiple)
โœ… priority (hidden)
โœ… suggested_team_routing (P4/P5)
โœ… zendesk_ticket_id (customer impact)
โœ… seller_contract_id, is_key_account, etc. (seller impact)

Scenario 3: P5 Normal with Employee Impact Only

Response Type: normal
Impacts: employees_impact = LOW

Visible Fields:
โœ… title, description, incident_category
โœ… environment (multiple), platform (multiple)
โœ… priority (hidden)
โœ… suggested_team_routing (P4/P5)
โŒ customer fields (no customer impact)
โŒ seller fields (no seller impact)


๐Ÿ”ง Technical Implementationยค

Core Filesยค

1. Unified Form (Django)ยค

File: src/firefighter/incidents/forms/unified_incident.py

class UnifiedIncidentForm(CreateIncidentFormBase):
    """Unified form for all incident types and priorities (P1-P5)."""

    def get_visible_fields_for_impacts(
        self, impacts_data: dict[str, ImpactLevel], response_type: str
    ) -> list[str]:
        """Determine which fields should be visible based on impacts."""
        # Returns list of field names that should be displayed

    def trigger_incident_workflow(
        self, creator: User, impacts_data: dict[str, ImpactLevel],
        response_type: str = "critical"
    ) -> None:
        """Trigger appropriate workflow based on response type."""
        if response_type == "critical":
            self._trigger_critical_incident_workflow(creator, impacts_data)
        else:
            self._trigger_normal_incident_workflow(creator, impacts_data)

2. Slack Form Wrapperยค

File: src/firefighter/slack/views/modals/opening/details/unified.py

class UnifiedIncidentFormSlack(UnifiedIncidentForm):
    """Slack version with Slack-specific field configurations."""

    def __init__(self, *args, impacts_data=None, response_type="critical", **kwargs):
        super().__init__(*args, **kwargs)
        self._impacts_data = impacts_data or {}
        self._response_type = response_type
        self._configure_field_visibility()  # Hide/show fields dynamically

    def _configure_field_visibility(self):
        """Remove fields that shouldn't be visible."""
        visible_fields = self.get_visible_fields_for_impacts(
            self._impacts_data, self._response_type
        )
        for field_name in list(self.fields.keys()):
            if field_name not in visible_fields:
                del self.fields[field_name]

3. Configuration Registrationยค

File: src/firefighter/raid/apps.py

INCIDENT_TYPES["normal"] = {
    "normal": {
        "label": "Normal",
        "slack_form": OpeningUnifiedModal,
    },
}
# Since len() == 1, STEP 3 is automatically hidden

File: src/firefighter/slack/views/modals/open.py

INCIDENT_TYPES["critical"] = {
    "critical": {
        "label": "Critical",
        "slack_form": OpeningUnifiedModal,
    },
}
# Same unified form used for both critical and normal

๐Ÿ“Œ Key Benefitsยค

1. Simplified User Experienceยค

  • No more incident type selection for P4/P5 incidents
  • Fewer steps in the workflow (4 instead of 5)
  • Contextual fields only show what's relevant

2. Reduced Code Complexityยค

  • 1 form instead of 6: UnifiedIncidentForm replaces all previous forms
  • Single source of truth: All incident creation logic in one place
  • Easier maintenance: Changes apply to all incident types

3. Flexible Field Managementยค

  • Dynamic visibility: Fields adapt to user selections
  • Multiple impacts: Can combine customer + seller impacts
  • Consistent behavior: Same form structure for all priorities

4. Preserved Functionalityยค

  • โœ… All Jira ticket creation logic preserved
  • โœ… All Slack notifications preserved
  • โœ… All validation rules preserved
  • โœ… All workflow integrations preserved

๐Ÿ”„ Migration from Old Workflowยค

Removed Componentsยค

Component Status Replacement
CreateNormalIncidentFormBase โŒ Deleted UnifiedIncidentForm
CreateNormalCustomerIncidentForm โŒ Deleted UnifiedIncidentForm
CreateRaidSellerForm โŒ Deleted UnifiedIncidentForm
CreateRaidInternalForm โŒ Deleted UnifiedIncidentForm
CreateRaidDocumentationForm โŒ Deleted Not supported
CreateRaidFeatureRequestForm โŒ Deleted Not supported
CreateIncidentFormSlack (critical) โŒ Deleted UnifiedIncidentFormSlack
raid/views/open_normal.py โŒ Deleted opening/details/unified.py

Preserved Componentsยค

Component Location Purpose
prepare_jira_fields() raid/forms.py Centralize all Jira field preparation (GT-1334 fix)
PlatformChoices raid/forms.py Platform enum (FR/DE/IT/ES/UK/ALL/Internal)
initial_priority() raid/forms.py Get default priority
process_jira_issue() raid/forms.py Create Jira ticket + impacts
get_business_impact() raid/forms.py Calculate business impact
alert_slack_new_jira_ticket() raid/forms.py Send Slack notifications
set_jira_ticket_watchers_raid() raid/forms.py Add Jira watchers
get_partner_alert_conversations() raid/forms.py Find partner Slack channels
get_internal_alert_conversations() raid/forms.py Find internal Slack channels

Deprecated Featuresยค

No longer supported: - โŒ Documentation Request incidents (P4/P5) - โŒ Feature Request incidents (P4/P5)

Rationale: These were specialized types that can be handled through standard P4/P5 internal incidents.


๐Ÿงช Testingยค

Tests for the unified form should be added in:

tests/test_incidents/test_forms/test_unified_incident.py

Existing utility function tests remain in:

tests/test_raid/test_raid_forms.py