External users submit info to case from email

From pmusers
Jump to: navigation, search

Web Services can be used to allow external users to participate in a case. In this example, a potential customer can fill out a Web Entry form to get a estimate how much it will cost to roof a building. After a user in ProcessMaker calculates the estimated cost of the job, and an email is sent to the customer containing an HTML form. In this form, the customer can select how to continue the case in a dropdown box and click on a button to submit the form. Then web services are used to send the values entered by the user to the case and then route on the case to the next task. Conditions in an exclusive gateway will check for the variables submitted by the customer to either end the case or route it the next task where the case can continue.


Process: Consult_external_user_via_email-1.pmx (right click and select Save Link As)
Version: 1.0 (2019-01-08)
Author: Amos Batto (amosbatto@yahoo.com)
Tested in: ProcessMaker 3.3.0 Community in Debian 9.5 with PHP 5.6.37


Create the following process to send roofing estimates to customers:

RoofingEstimateProcess.png

Then, create the following DynaForm which will be used as the Web Entry form to start the process:

RequestRoofingEstimateWebEntry.png

Then, create another Dynaform where a registered user in ProcessMaker will calculate the estimated price of the roofing job:

CalculateRoofingEstimate.png

Set this Dynaform as a step in the first task in the process.

Then, create the following email template, which will send the estimated price to the customer:

EmailTemplateToSendRoofingEstimate.png

The HTML code for this template contains:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
</head>
<body>
<p>Dear @#firstName @#lastName,</p>
<p>Thank you for requesting an estimate from ShingleRight Inc.</p>
<p>We charge approximately $@#estimatedPrice to roof&nbsp;@#squareFeetRoof square feet with @#roofType_label.</p>
<p>This price may be adjusted according to the height of the building, slope of roof, and other factors which need to be evaluated on site. Would you like us to contact you?</p>
<form action="http://172.16.1.29:330/sendResponseToCase.php" method="post">
<input name="case_id" value="@#caseId" type="hidden" /> 
<input name="del_index" value="@#delIndex" type="hidden" /> 
<input name="user_id" value="@#userId" type="hidden" /> 
<b>Your Response</b><br />
<select name="customerResponse" required="required">
<option value="">--select--</option>
<option value="call">Please telephone me!</option>
<option value="email">Please email me!</option>
<option value="not_interested">No thanks, I'm not interested</option>
</select><br /> 
<b>Additional Comments</b><br /> 
<textarea name="customerComments"></textarea><br /><br /> 
<input value="Submit" type="submit" />
</form>
<p></p>
</body>
</html>

Notice that the <form> contains a "Submit" button. When the customer clicks it will be submitted as a POST to a custom PHP file.

Then, create the following trigger which will send out the above email:

if (!preg_match('/^[a-zA-Z0-9_\.]+@[a-zA-Z0-9_\.]+$/', @@email)) {
	//if not a valid email, then email manager to review it:
	PMFSendMessage(@@APPLICATION, 'admin@example.com', 'manager@example.com', '', '',
	   'Invalid email in case#'.@@APP_NUMBER, 'invalid_email.html');
}
else {
   $taskTitle = 'Get customer feedback'; //set to title of task
   $aTasks = PMFGetUidFromText($taskTitle, 'TAS_TITLE', @@PROCESS, 'en');
   $taskId = $aTasks[0];
   $sql = "SELECT * FROM APP_CACHE_VIEW WHERE APP_UID='".@@APPLICATION.
	   "' AND TAS_UID='$taskId' ORDER BY DEL_INDEX DESC";
   $aResult = executeQuery($sql);

   if (empty($aResult)) {
	   throw new Exception("Enable to find task with query: $sql");
   }
	
   $aVars = array(
	'caseId'  => $aResult[1]['APP_UID'],
	'delIndex'=> $aResult[1]['DEL_INDEX'],
	'userId'  => $aResult[1]['USR_UID']
   );
   
   @@aVars = $aVars;
	
   @@emailRet = PMFSendMessage(@@APPLICATION, 'admin@example.com', @@email, '', '',
	   'Roofing estimate from ShingleRight Inc.', 'roofing_estimate.html', $aVars);
}

Set this trigger to fire after routing in the "Calculate estimate" task, which is the first one in the process. If fired after routing, then the record for the next task which is "Get customer feedback" already exists in the database so it can be looked up with executeQuery().

Then, create the following PHP file to process the form submitted by the customer from his/her email:

<?php
/*************************
sendResponseToCase.php uses web services to send variables to the case 
which were submitted by the external user from a form in an email. 
Then it routes on the case to an exclusive gateway that either ends the case or continues it  
**************************/
ini_set("soap.wsdl_cache_enabled", "0");
ini_set('error_reporting', E_ALL); //uncomment to debug
ini_set('display_errors', True);  //uncomment to debug

if (empty($_POST['customerResponse'])) {
   die("<html><body>Please select your response to the roofing estimate and resubmit.</body></html>");
};  


$client = new SoapClient('http://172.16.1.29:330/sysworkflow/en/neoclassic/services/wsdl2');
$username = 'admin';
$password = 'md5:' . hash('sha256','admin');
$params = array(array('userid'=>$username, 'password'=>$password));
$result = $client->__SoapCall('login', $params);

if ($result->status_code == 0) {
    $sessionId = $result->message;
} else {
    die("<html><body><pre> Unable to connect to ProcessMaker.\n" .
        "Error Message: $result->message </pre></body></html>");
}      

class variableStruct {
    public $name;
    public $value;
}

$response = new variableStruct();
$response->name = "customerResponse";
$response->value = $_POST['customerResponse'];

$comments = new variableStruct();
$comments->name = "customerComments";
$comments->value = $_POST['customerComments'];

$aVars = array($response, $comments);
$params = array(array('sessionId'=>$sessionId, 'caseId'=>$_POST['case_id'], 'variables'=>$aVars));
$result = $client->__SoapCall('sendVariables', $params);

if ($result->status_code != 0) {
   die("<html><body><pre>Error: $result->message </pre></body></html>");
}

//Use routeCase() to route the case using the case variable @@customerResponse in the gateway's condition
$params = array(array(
   'sessionId' => $sessionId,
   'caseId'    => $_POST['case_id'], 
   'delIndex'  => $_POST['del_index']
));
$result = $client->__SoapCall('routeCase', $params);

if ($result->status_code == 0)
   print "<html><body><p>Thank you for your response. We will contact you shortly.</p>\n</body></html>";
else
   print "<html><body><pre>Error routing case: $result->message \n</pre></body></html>";

?>

Make sure to change the email address admin@example.com to the same email account which is registered in Admin > Settings > Email Servers or it might be treated as spam by the email provider.

Save this file to the workflow/public_html/ directory in the ProcessMaker server. For example, on a manual install on a Linux server, the path would be something like: /opt/processmaker/workflow/public_html/sendResponseToCase.php

Now, customers can start new cases by filling out the Web Entry form:

RequestRoofingEstimateInWebEntry.png

Users in ProcessMaker can calculated the estimated price for the roofing job:

EnterTheEstimatedCostOfRoofingJobInCase.png

After the first task in the case is completed, the following email will be sent to the customer:

EmailGetResponseFromCustomerForRoofing.png

When the customer fills out the form in his/her email and submits it, the following message should be displayed:

ResponsefromPhpScriptForSubmittingFromEmail.png

If the user selected "No Thanks" in the "Response" dropdown box, then the case will terminate. Otherwise, the case will continue to the "Negotiate Contract" task.