Skip to content

Project to automate running salesforce workflows against a list of contacts

Notifications You must be signed in to change notification settings

BCIT-SSD-2020-21/industry-project-agilitek-frontend

Repository files navigation

📃 Agilitek Automation Project

GitHub issues GitHub stars

Heroku Deployment

Heroku Deployment with Auth

⚠️ Note: The current Beta version of the app with Auth has a bug specific to Login In with google Credentials. The google developer keys for the app are causing issue with user not being able to logout so Auth0 Dev keys are currently used; however, this causes the current problem that prompts the user to log back in whenever the page is refreshed.

💡 Motivation

For a user to be able to perform an action against a list of customer contacts that match a certain condition

🔔 Status

Complete

Installation

  • Install NPM (Npm Docs)
  • Install Git to your local machine (Git Docs)
  • Git clone repo
  • Navigate to the project folder with the command prompt: cd yourprojectfolder
npm install
npm start

📷 Screenshots

homePAge

details

newconfig

💻 Tech/FrameWorks

  • AWS (RDS, API Gateway, Lambda, EventBridge, Step Functions)
  • Node.js 14.15.4
  • NPM 6.14.10
  • PostgreSQL
  • React 17.0.2
  • Tailwind UI 0.3.2

📈 Feature List

TBD with input from team

Core Features

  • Create, view, pause or un-pause automation
  • Enter any SQL statment(as long as it returns a list of Salesforce Contact IDs)
  • User can select salesforce flow
  • User can select true false indicator indicating whether or not a user workflow can run on the same set of contacts multiple times
  • Show execution logs
  • Multiple automations

Nice-To-Have

  • Adding capability to "map" additional columns of the SQL statement output to additional "API Input Parameters"
  • Edit and delete automation
  • User authentication/authorization
  • Search functionality for user workflow page

Functional

  • User can create, view, pause or unpause automation
  • System queries the databases upon triggering automation
  • Contact ID's returned from SQL query are posted to Salesforce flow

Non-Functional

  • Multiple automations
  • Show output logs

Roles and Permission

  • User
    • Log in
    • Create automation(s)
    • Enter any SQL statement
    • Pick Salesforce Flow
    • True/False Indicator
    • View Execution Logs/current automations
    • (un)Pause a new automation

📰 Supporting Documents

Diagram

Mockup

Figma Mockup

ERD

SSD-Agilitek Fan Data Platfrom API Documentation

Salesforce Flow

GET

Get all flows from Salesforce

/salesforceflows

Sample response:

{
    "actions" : [
        {
            "label": "Create Opportunities",
            "name": "Create_Opportunities",
            "type": "FLOW",
            "url": "/services/data/v51.0/actions/custom/flow/Create_Opportunities"
        },
        {
            "label": "Create Opportunity",
            "name": "Create_Opportunity",
            "type": "FLOW",
            "url": "/services/data/v51.0/actions/custom/flow/Create_Opportunity"
        }
    ]
}

GET

Get flow inputs

/salesforceflows/flow

Sample query string parameter:

/salesforceflows/flow?flowUrl=/services/data/v51.0/actions/custom/flow/Create_Opportunity

OR

flowUrl=/services/data/v51.0/actions/custom/flow/Create_Opportunity

Sample response:

{
  "label": "ContactToProcess",
  "type": "STRING"
}

POST

Triggers custom Salesforce flows

/salesforceflows/flow

Sample body:

{
    "inputs": [
        {
            "contactId": "0034x000007DXthAAG"
        }
    ],
    "salesforceFlowName: "create_opportunity",
}

OR

{
    "inputs": [
        {
            "ContactsToProcess": [
                {
                    "attributes": {"type": "Contact"},
                    "Id" : "0034x000007DYA3AAO"
                },
                {
                    "attributes": {"type": "Contact"},
                    "Id" : "0034x000001c4YQAAY"
                },
                {
                    "attributes": {"type": "Contact"},
                    "Id" : "0034x000003YaRvAAK"
                }
            ]
        }
    ]
}

Sample response:

[
    {
        "actionName": "Create_Opportunity",
        "errors": null,
        "isSuccess": true,
        "outputValues": {
            "recordId": null,
            "Flow__InterviewStatus": "Finished"
        }
    }
]

OR

[
    {
        "actionName": "Create_Opportunities",
        "errors": null,
        "isSuccess": true,
        "outputValues": null
    }
]

GET

Get metadata for sObject type

/salesforceflows/metadata

Sample query string parameter:

/salesforceflows/metadata?sObjectType=Contact

OR

sObjectType=Contact

Sample response:

{
  "metadata": [
    {
      "aggregatable": true,
      "aiPredictionField": false,
      "autoNumber": false,
      "byteLength": 18,
      "calculated": false,
      "calculatedFormula": null,
      "cascadeDelete": false,
      "caseSensitive": false,
      "compoundFieldName": null,
      "controllerName": null,
      "createable": false,
      "custom": false,
      "defaultValue": null,
      "defaultValueFormula": null,
      "defaultedOnCreate": true,
      "dependentPicklist": false,
      "deprecatedAndHidden": false,
      "digits": 0,
      "displayLocationInDecimal": false,
      "encrypted": false,
      "externalId": false,
      "extraTypeInfo": null,
      "filterable": true,
      "filteredLookupInfo": null,
      "formulaTreatNullNumberAsZero": false,
      "groupable": true,
      "highScaleNumber": false,
      "htmlFormatted": false,
      "idLookup": true,
      "inlineHelpText": null,
      "label": "Contact ID",
      "length": 18,
      "mask": null,
      "maskType": null,
      "name": "Id",
      "nameField": false,
      "namePointing": false,
      "nillable": false,
      "permissionable": false,
      "picklistValues": [],
      "polymorphicForeignKey": false,
      "precision": 0,
      "queryByDistance": false,
      "referenceTargetField": null,
      "referenceTo": [],
      "relationshipName": null,
      "relationshipOrder": null,
      "restrictedDelete": false,
      "restrictedPicklist": false,
      "scale": 0,
      "searchPrefilterable": false,
      "soapType": "tns:ID",
      "sortable": true,
      "type": "id",
      "unique": false,
      "updateable": false,
      "writeRequiresMasterRead": false
    },
    ...
}

Database

GET

Get all database tables

/database

Sample response:

{
   "statusCode":200,
   "body":[
      {
         "table_name":"SalesforceContacts"
      },
      {
         "table_name":"contact_workflows"
      },
      {
         "table_name":"workflows"
      },
      {
         "table_name":"workflow_logs"
      },
      {
         "table_name":"users"
      }
   ],
   "headers":{
      "Access-Control-Allow-Origin":"*",
      "Access-Control-Allow-Headers":"*"
   }
}

GET

Get all columns from a table

/database/{table_name}/columns

Sample URL parameter:

/database/users/columns

Sample response:

[
  {
    "column_name": "salesforce_id"
  },
  {
    "column_name": "first_name"
  },
  {
    "column_name": "last_name"
  }
]

My Workflow

GET

Get all workflows

/myworkflows

Sample response:

[
  {
    "id": 20,
    "flow_url": "/services/data/v51.0/actions/custom/flow/Create_Opportunity",
    "name": "www",
    "description": "",
    "table": "SalesforceContacts",
    "column": "id",
    "label": "ContactToProcess",
    "type": "STRING",
    "sobject_type": "undefined",
    "where_clause": "length(title) > 0",
    "mapping": {},
    "run_again": true,
    "active": true,
    "pk_column": "id"
  },
  {
    "id": 8,
    "flow_url": "/services/data/v51.0/actions/custom/flow/Create_Opportunities",
    "name": "Test Create_Opportunity",
    "description": "undefined",
    "table": "SalesforceContacts",
    "column": "",
    "label": "ContactsToProcess",
    "type": "SOBJECT",
    "sobject_type": "Contact",
    "where_clause": "length(email) > 0",
    "mapping": {
      "OtherAddress": "lastmodifieddate",
      "OtherStreet": "lastmodifiedbyid",
      "Name": "fan_type__c",
      "Id": "id"
    },
    "run_again": true,
    "active": true,
    "pk_column": "id"
  }
]

POST

Create a new workflow

/myworkflows

Sample body:

{
   "name":"My Test Workflow",
   "desc":"Some automation",
   "flowUrl":"/services/data/v51.0/actions/custom/flow/Create_Opportunities",
   "table":"SalesforceContacts",
   "column":"",
   "label":"ContactsToProcess",
   "type":"SOBJECT",
   "sObjectType":"Contact",
   "whereClause":"length(email) > 0",
   "mapping":{
      "Id":"id",
      "Title":"title"
   },
   "active":true,
   "runAgain":true
}

Sample response:

{
   "statusCode":200,
   "body":{
      "command":"INSERT",
      "rowCount":1,
      "oid":0,
      "rows":[],
      "fields":[],
      "_types":{
         "_types":{
            "arrayParser":{

            },
            "builtins":{
               "BOOL":16,
               "BYTEA":17,
               "CHAR":18,
                ...
            }
         },
         "text":{},
         "binary":{}
      },
      "RowCtor":null,
      "rowAsArray":false
   },
   "headers":{
      "Access-Control-Allow-Origin":"*",
      "Access-Control-Allow-Headers":"*"
   }
}

GET

Get workflow logs

/myworkflows/logs/{id+}

Sample URL parameter:

/myworkflows/logs/8

Sample response:

[
  {
    "id": 13,
    "workflow_id": 8,
    "action_name": "Create_Opportunity",
    "time_of_completion": "2021-05-03T18:23:01.267Z",
    "is_flow_successful": true
  },
  {
    "id": 15,
    "workflow_id": 8,
    "action_name": "Create_Opportunity",
    "time_of_completion": "2021-05-03T18:25:51.146Z",
    "is_flow_successful": true
  }
]

DELETE

Delete a workflow

/myworkflows/{id+}

Sample URL parameter:

/myworkflows/23

Sample response

{
   "Access-Control-Allow-Origin":"*",
   "Access-Control-Allow-Headers":"*",
   "X-Amzn-Trace-Id":"Root=1-60930ed6-9c95119c8a4e9068020833b3;Sampled=0"
}

GET

Get a workflow

/myworkflows/{id+}

Sample URL parameter:

/myworkflows/13

Sample response:

{
  "id": 13,
  "flow_url": "/services/data/v51.0/actions/custom/flow/Create_Opportunities",
  "name": "Test test 123",
  "description": "undefined",
  "table": "SalesforceContacts",
  "column": "",
  "label": "ContactsToProcess",
  "type": "SOBJECT",
  "sobject_type": "Contact",
  "where_clause": "length(title) > 0",
  "mapping": {
    "MasterRecordId": "assistantphone",
    "AccountId": "createddate",
    "Id": "id"
  },
  "run_again": true,
  "active": true,
  "pk_column": "id"
}

PUT

Update a workflow

/myworkflows/{id+}

Sample URL paramter:

/myworkflows/13

Sample body:

{
  "name": "My Test Workflow",
  "desc": "Some automation",
  "flowUrl": "/services/data/v51.0/actions/custom/flow/Create_Opportunities",
  "table": "SalesforceContacts",
  "column": "",
  "label": "ContactsToProcess",
  "type": "SOBJECT",
  "sObjectType": "Contact",
  "whereClause": "length(email) > 0",
  "mapping": {
    "Id": "id",
    "Title": "title"
  },
  "active": true,
  "runAgain": true
}

Sample response:

{
  "command": "UPDATE",
  "rowCount": 1,
  "oid": null,
  "rows": [],
  "fields": [],
  "_types": {
    "_types": {
      "arrayParser": {},
      "builtins": {
        "BOOL": 16,
        "BYTEA": 17,
        "CHAR": 18,
         ...
      }
    },
    "text": {},
    "binary": {}
  },
  "RowCtor": null,
  "rowAsArray": false
}

🎉 Credits

Created by: Leanne Sall, Gökay Abay, Nick Charvat, Steven Lai, Yaroslav Naft. In partnership with Agilitek Solutions

🔒 License

GitHub license

About

Project to automate running salesforce workflows against a list of contacts

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published