Skip to content

Expand Slack Message for carrier.packet.completed Webhook #12

@fakebizprez

Description

@fakebizprez

Context

You are updating a Node.js application that formats MyCarrierPackets webhook events into rich Slack messages. The carrier.packet.completed webhook payload has been significantly expanded with additional data fields that should be displayed in the Slack notification.

Current Implementation

The current Slack message for carrier.packet.completed displays:

  • Carrier information (Legal Name, DBA, DOT Number, MC Number)
  • Packet details (Packet Type, Completion Date)
  • Customer information (Company Name, Customer ID)
  • A "View in MCP" button

Expanded Webhook Payload

The webhook now includes much richer data:

{
    "eventType": "carrier.packet.completed",
    "eventDateTime": "2025-04-29T22:16:41.5102923Z",
    "eventData": {
        "agreement": {
            "signatureDate": "2025-04-29T22:16:20.6352903",
            "signaturePerson": "MCP Test Carrier",
            "signaturePersonTitle": "President",
            "signaturePersonEmail": "[email protected]",
            "signaturePersonPhoneNumber": "9999999999",
            "agreementImageBlobName": "company-agreement/6/b7453f55-3f3b-454d-8726-89f746082a06",
            "ipAddress": {
                "address": "127.0.0.1",
                "city": "New York City",
                "region": "New York",
                "country": "United States of America"
            },
            "geolocation": {
                "latitude": 34.0544,
                "longitude": -118.244,
                "error": null,
                "method": "IPAddress"
            }
        },
        "carrier": {
            "dotNumber": 9999997,
            "docketNumber": "MC9999997",
            "legalName": "MCP TEST CARRIER 9999997",
            "dbaName": null
        },
        "customer": {
            "customerID": 6,
            "companyName": "MCP Test Customer"
        }
    }
}

New Fields Available:

  1. Agreement Information:

    • agreement.signatureDate - When the agreement was signed
    • agreement.signaturePerson - Name of the person who signed
    • agreement.signaturePersonTitle - Their title/role
    • agreement.signaturePersonEmail - Their email
    • agreement.signaturePersonPhoneNumber - Their phone number
    • agreement.agreementImageBlobName - Reference to the signed agreement image
  2. IP Address Information:

    • agreement.ipAddress.address - IP address used
    • agreement.ipAddress.city - City derived from IP
    • agreement.ipAddress.region - State/Province
    • agreement.ipAddress.country - Country
  3. Geolocation Data:

    • agreement.geolocation.latitude - Latitude coordinate
    • agreement.geolocation.longitude - Longitude coordinate
    • agreement.geolocation.method - How location was determined (enum: "DeviceOrBrowser" or "IPAddress")
    • agreement.geolocation.error - Any error in obtaining geolocation

Task

Update the formatPacketCompletedMessage function in utils/formatters.js to include these new fields in the Slack message blocks. The enhanced message should:

Requirements:

  1. Maintain Existing Structure - Keep the current header, carrier section, and customer section
  2. Add Agreement Signer Section - Display who signed the packet and their contact info
  3. Add Location Information - Show where the packet was signed from (city, region, country)
  4. Format for Readability - Use appropriate Slack Block Kit elements
  5. Handle Missing Data - Gracefully handle cases where optional fields might be null/undefined
  6. Preserve Existing Functionality - Keep the "View in MCP" button and color coding

Design Guidelines:

  • Use section blocks with fields arrays for structured data
  • Use context blocks for supplementary information (like geolocation method)
  • Format phone numbers for readability: (999) 999-9999
  • Format dates consistently: use new Date().toLocaleString() format
  • Use markdown formatting (*bold*) for field labels
  • Group related information logically
  • Consider adding a Google Maps link for the geolocation coordinates (optional)

Suggested Section Order:

  1. Header (existing)
  2. Divider (existing)
  3. Carrier Information (existing)
  4. Packet Details (existing)
  5. NEW: Agreement Signer Details
  6. NEW: Signature Location
  7. Customer Information (existing)
  8. Context/Timestamp (existing)
  9. Action Buttons (existing)

Example of New Sections to Add:

// Agreement Signer Section
const signerSection = {
  type: "section",
  fields: [
    {
      type: "mrkdwn",
      text: `*Signed By:* ${eventData.agreement?.signaturePerson || 'N/A'}`
    },
    {
      type: "mrkdwn",
      text: `*Title:* ${eventData.agreement?.signaturePersonTitle || 'N/A'}`
    },
    {
      type: "mrkdwn",
      text: `*Email:* ${eventData.agreement?.signaturePersonEmail || 'N/A'}`
    },
    {
      type: "mrkdwn",
      text: `*Phone:* ${formatPhoneNumber(eventData.agreement?.signaturePersonPhoneNumber) || 'N/A'}`
    }
  ]
};

// Location Section
const locationSection = {
  type: "section",
  fields: [
    {
      type: "mrkdwn",
      text: `*Location:* ${eventData.agreement?.ipAddress?.city || ''}, ${eventData.agreement?.ipAddress?.region || ''}, ${eventData.agreement?.ipAddress?.country || 'N/A'}`
    },
    {
      type: "mrkdwn",
      text: `*IP Address:* ${eventData.agreement?.ipAddress?.address || 'N/A'}`
    }
  ]
};

// Geolocation Context (if available)
const geolocationContext = eventData.agreement?.geolocation ? {
  type: "context",
  elements: [
    {
      type: "mrkdwn",
      text: `📍 Coordinates: ${eventData.agreement.geolocation.latitude}, ${eventData.agreement.geolocation.longitude} (via ${eventData.agreement.geolocation.method})`
    }
  ]
} : null;

Additional Considerations:

  • Add a helper function formatPhoneNumber(phone) to format phone numbers
  • Consider whether to show the agreementImageBlobName (probably not needed in Slack)
  • Handle the case where the entire agreement object might be missing (backward compatibility)
  • Test with both complete and partial payloads
  • Ensure the message doesn't become too cluttered

Expected Output

Provide the complete updated formatPacketCompletedMessage function with:

  1. All new sections integrated
  2. Proper null/undefined checking
  3. Helper functions if needed (like formatPhoneNumber)
  4. Comments explaining the new sections
  5. The complete blocks array with all sections in the proper order

Code Location

File: utils/formatters.js
Function: formatPacketCompletedMessage(eventType, formattedDate, eventData, carrierSection, customerSection, contextSection)

Backward Compatibility Note

Some webhooks may still arrive with the old payload structure (without the agreement object). Ensure the code handles both cases gracefully without breaking.

Metadata

Metadata

Assignees

No one assigned

    Labels

    codexenhancementNew feature or requestjuleshand task off to Jules

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions