Whatsapp ERP Integration Methods

Overview

The WhatsApp-ERP Integration Flow Documentation provides a comprehensive explanation of a Node-RED flow designed to facilitate seamless communication between WhatsApp and an ERP system.

Mapping of Phone number and Email from ERP using API

1. Get User List from ERP API

Type: Function Node
Description: This node constructs an HTTP GET request to the ERP system's API endpoint that provides a list of user data containing email and phone information.
Function Content:


const apiUrl = 'http://192.168.X.XX/api/method/your_custom_method';
msg.url = apiUrl;
msg.method = "GET";
return msg;
    

2. GET User List from ERP

Type: HTTP Request Node
Description: This node sends the previously constructed HTTP GET request to the ERP system and awaits the response.
Node Settings:


Method: set by msg.method
Headers:
  Authorization: apiKey:apiSecret
  Content-Type: application/json
    

Make sure to replace apiKey and apiSecret to your own api key and api secret.

3. Mapping Phone and Email

Type: Function Node
Description: This node processes the user data received from the ERP API response. It maps WhatsApp phone numbers to corresponding email addresses.
Function Content:


const userList = msg.payload.message;
const phoneNumberToEmail = {};

for (const user of userList) {
    const phoneNum = `@6${user.phone}`;
    const email = `${user.email}`;

    if (phoneNum && email) {
        phoneNumberToEmail[phoneNum] = email;
    }
}

global.set('phoneNumberToEmail', phoneNumberToEmail);

return msg;
    

How It Works

  1. The flow begins with the "Get User List from ERP API" node, which sends an HTTP GET request to the ERP API to retrieve user data containing email and phone information.
  2. The response from the ERP API is received by the "GET User List from ERP" node, which extracts the user data from the API response.
  3. The user data is then processed by the "Mapping Phone and Email" node. This node iterates through the user list, constructs a mapping of WhatsApp phone numbers to email addresses, and stores this mapping in the global context variable named "phoneNumberToEmail."

Note Taking from Whatsapp

1. Personal Task, Issue and Note

Type: Function Node
Description: This node is responsible for processing incoming WhatsApp messages and extracting relevant information based on keywords such as "#task," "#issue," or notes. The extracted information is used to create payloads for different ERP document types.
Function Content:


// Retrieve the mapping from the context
const phoneNumberToEmail = global.get('phoneNumberToEmail');

// Specify the URL for sending the request 
const baseUrl = "http://192.168.X.XX/api/resource/";
let requestUrl = "";

// Check if msg.message._data.author exists
if (msg.message && msg.message._data && msg.message._data.author || msg.message && msg.message._data && !msg.message._data.author && msg.message.hasQuotedMsg) {
    return null;
} else {
    // Check if msg.payload is defined
    if (typeof msg.payload === 'undefined' || msg.payload === null) {
        return null;
    }

    // Split the payload into words 
    const words = msg.payload.split(" ");

    // Check if the last word is "task" or "issue" 
    const lastWord = words[words.length - 1].toLowerCase();

    if (lastWord === "#task") {
        const task_description = words.slice(0, -1).join(" "); // Exclude the last word 

        // Get the sender phone number and change it to email
        const sender = "@" + msg.from;
        const assigned_by_sender = phoneNumberToEmail[sender] || "";
        const assigned_to_self = phoneNumberToEmail[sender] || "";

        // Create a new payload for ToDo doctype 
        const todoPayload = {
            allocated_to: assigned_to_self,
            description: task_description,
            reference_type: "Task", // Set the reference_type field to "Task"
            assigned_by: assigned_by_sender
        };

        // Set the request URL for ToDo doctype 
        requestUrl = baseUrl + "ToDo";
        //requestUrl = baseUrl + "Task";

        // Set the modified payload for ToDo doctype 
        msg.payload = todoPayload;
    } else if (lastWord === "#issue") {
        // Extract subject and description for Issue doctype 
        let issue_subject = "";
        let issue_description = "";

        // Check for "-" character in the payload
        const dashIndex = words.indexOf("-");
        if (dashIndex !== -1 && dashIndex < words.length - 2) {
            // Split the payload based on "-"
            issue_subject = words.slice(0, dashIndex).join(" ");
            issue_description = words.slice(dashIndex + 1, -1).join(" ");
        } else {
            // If there is no dash character, consider the entire payload (except the last word) as the subject
            issue_subject = words.slice(0, -1).join(" ");
            issue_description = words.slice(0, -1).join(" ");
        }

        // Create a new payload for Issue doctype 
        const issuePayload = {
            subject: issue_subject,
            description: issue_description
        };

        // Set the request URL for Issue doctype 
        requestUrl = baseUrl + "Issue";

        // Set the modified payload for Issue doctype 
        msg.payload = issuePayload;
    } else {
        // Extract subject and description for Note doctype 
        const note_title = words.slice(0, -1).join(" ");
        const note_description = words.slice(0, -1).join(" ");

        // Create a new payload for Notes doctype 
        const notesPayload = {
            title: note_title,
            content: note_description,
        };

        // Set the request URL for Notes doctype 
        requestUrl = baseUrl + "Note";

        // Set the modified payload for Notes doctype 
        msg.payload = notesPayload;
    }

    msg.url = requestUrl;
    msg.method = "POST";
    return msg;
}
    

2. Delay

Type: Delay Node
Description: This node introduces a delay of 5 seconds to ensure that the payload is processed after a short pause. This delay is useful to allow time for the previous payload modifications to take effect before sending the request to the ERP system.
Node Settings:


Pause Type: Delay
Timeout: 5 seconds
    

3. Share the private document to the sender

Type: Function Node
Description: This node prepares a payload to share the private document (note) with the sender. It includes the sender's email and necessary permissions for reading and writing the shared document. This ensures that the sender can access the document and collaborate on it within the ERP system.
Function Content:


// Retrieve the mapping from the context
const phoneNumberToEmail = global.get('phoneNumberToEmail');

// Specify the URL for sending the request 
const baseUrl = "http://192.168.X.XX/api/resource/DocShare";

const docname = msg.payload.title;

// Get the sender phone number and change it to email
const sender = "@" + msg.from;
const user_email = phoneNumberToEmail[sender] || "";

const NotePayload = {
    user: user_email,
    share_doctype: "Note",
    share_name: docname,
    read: 1,
    write: 1
}

msg.payload = NotePayload;
msg.url = baseUrl;
msg.method = "POST";
return msg;
    

4. Send to ERP

Type: HTTP Request Node
Description: This node sends the prepared payload to the ERP system for further processing. It uses the POST method to send the data to the specified URL in the ERP system, facilitating the creation and sharing of documents based on the processed WhatsApp messages.
Node Settings:


Method: Use
Headers:
  Authorization: Token apiKey:apiSecret
  Content-Type: application/json
    

How Assigning Tasks and Rasising Issue Works

  1. The flow begins with the "Task, Issue and Note" node, which receives incoming WhatsApp messages. It processes the messages to determine the type of document to create (task, issue, or note) in the ERP system.
  2. The processed payload is then passed to the "Delay" node, which introduces a 5-second delay. This delay ensures that any changes made to the payload have time to take effect.
  3. Following the delay, the "Share the private document to the sender" node constructs a payload to share the processed document (note) with the original sender. The payload defines sharing settings and permissions.
  4. Finally, the "Send to ERP" node performs an HTTP POST request to send the prepared payload to the ERP system. The ERP system processes the payload to create the appropriate document type and enable sharing with the sender.

Assigning Task and Raising Issue in Whatsapp Group

1. Chats In

Type: Chats In Node
Description: This node acts as the entry point for incoming WhatsApp messages. It triggers the flow whenever relevant events, such as new messages, updates, or call notifications, occur in the specified WhatsApp chats.

2. Filter Group Messages

Type: Function Node
Description: This node filters and processes messages from specific target groups. It ensures that only messages from predefined groups are processed further, while others are discarded.
Function Content:


// Retrieve the mapping from the context
const phoneNumberToEmail = global.get('phoneNumberToEmail');

// Specify group's chatID 
const targetGroupId = ["your_whatsapp_group_chatId"];

// Specify the URL for sending the request
const baseUrl = "http://192.168.X.XX/api/resource/";
let requestUrl = "";

// Check if the incoming message is from the target group 
if (targetGroupId.includes(msg.chatID)) {
    if (msg.message && msg.message.hasMedia){
        return null;
    }else{
        // Split the payload into words 
        const words = msg.payload.split(/ |\n/);

        // Check if the last word is "task" or "issue" 
        const lastWord = words[words.length - 1].toLowerCase();

        if (lastWord === "#task") {
            // Extract phone number, subject, and description 
            const phoneNumber = words[0];
            const task_description = words.slice(1, -1).join(" "); // Exclude the last word 

            // Replace the phone number with the corresponding email address (if available) 
            const email = phoneNumberToEmail[phoneNumber] || "";

            //get the sender phone number and change it to email
            const sender = "@" + msg.from;
            const assigned_by_sender = phoneNumberToEmail[sender] || "";

            // Modify the phoneNumber to remove "@" and add "+"
            const formattedPhoneNumber = phoneNumber.replace("@", "+");

            msg.toNumber = formattedPhoneNumber;
            msg.messagecontent = task_description;

            // Create a new payload for ToDo doctype 
            const todoPayload = {
                allocated_to: email,
                description: task_description,
                reference_type: "Task", // Set the reference_type field to "Task"
                assigned_by: assigned_by_sender
            };

            // Set the request URL for ToDo doctype 
            requestUrl = baseUrl + "ToDo"

            // Set the modified payload for ToDo doctype 
            msg.payload = todoPayload;
        } else if (lastWord === "#issue") {
            // Extract subject and description for Issue doctype 
            let issue_subject = "";
            let issue_description = "";

            // Check for "-" character in the payload
            const dashIndex = words.indexOf("-");
            if (dashIndex !== -1 && dashIndex < words.length - 2) {
                // Split the payload based on "-"
                issue_subject = words.slice(0, dashIndex).join(" ");
                issue_description = words.slice(dashIndex + 1, -1).join(" ");
            } else {
                // If there is no dash character, consider the entire payload (except the last word) as the subject
                issue_subject = words.slice(0, -1).join(" ");
                issue_description = words.slice(0, -1).join(" ");
            }

            msg.toNumber = null;

            // Create a new payload for Issue doctype 
            const issuePayload = {
                subject: issue_subject,
                description: issue_description
            };

            // Set the request URL for Issue doctype 
            requestUrl = baseUrl + "Issue";

            // Set the modified payload for Issue doctype 
            msg.payload = issuePayload;
        } else {
            return null; // Discard the message if the last word is neither "task" nor "issue" 
        }

        msg.url = requestUrl;
        msg.method = "POST";

        return msg; // Pass the modified message through
    } 
} else {
    return null; // Discard the message 
}
    

3. Send to ERP

Type: HTTP Request Node
Description: This node sends the prepared payload to the ERP system for further processing. The payload includes data extracted from the processed WhatsApp message, such as task descriptions or issue details.
Node Settings:


Method: set by msg.method
Headers:
  Authorization: Token apiKey:apiSecret
  Content-Type: application/json
    

4. Send to Task Assignee

Type: Function Node
Description: This node prepares a response fro Whatsapp message that is sent back to the task assignee. It constructs a message containing the task details and a link to the ERP system for more information.
Function Content:


// Function node to check if msg.toNumber is null or not
if (msg.toNumber !== null) {
    if (msg.payload && msg.payload.data && msg.payload.data.name) {
        const todoID = msg.payload.data.name;
        const msgContent = msg.messagecontent;
        const link = "https://erp.example.my/app/todo/" + todoID;

        // msg.toNumber is not null, return its value
        msg.payload = `You have been assigned to a task ${todoID}:\n\n${msgContent}.\n\nFor more information, please go to: ${link}`;
        return msg;
    } else {
        return null;
    }
} else {
    return null;
}
    

5. Chats Out

Type: Chats Out Node
Description: This node handles outgoing messages and sends responses back to the WhatsApp chats. It enables communication with users by sending notifications and task details directly to the assignees.

How Assisgning Task and Raising Issue in Whatsapp Group Works

  1. The "Chats In" node monitors predefined WhatsApp chats for incoming messages, updates, and other events.
  2. The "Filter Group Messages" node processes messages from specific target groups while discarding messages from other groups.
  3. For messages related to tasks or issues, the node extracts relevant information, such as task descriptions or issue details.
  4. The extracted data is then sent to the "Send to ERP" node as a payload for further processing in the ERP system.
  5. The ERP system processes the payload and creates the appropriate documents (tasks, issues) based on the incoming messages.
  6. If the message is related to a task, the "Send to Task Assignee" node prepares a response message containing task details and a link to the ERP system.
  7. The "Chats Out" node sends the response message back to the task assignee via the WhatsApp chat.