Permalink
Browse files

Implement direct message receive and background services manager, tak…

…e 1.

 1. Background Service Manager Framework
    --Documentation provided in the main library/ajax/execute_background_services.php script.
    --Report at Administration->Reports->Services->Background Services
 2. Direct Message Receive
    --Service built on top of the Background Service Manager Framework
    --Can be set/modified in Administration->Globals->Connectors (bottom section)
    --Log can be viewed at Administration->Reports->Services->Direct Message Log
    --Added support for importing of documents with no patient mapping. GUI for
      this is at Miscellaneous->New Documents.
    --Added support for sending pnotes with no patient mapping.
    --Added support for service bots to enable storage of documents,
      sending of messages and accurate logging by services.

 Miscellaneous mods: Changed the Administration->Services to Administration->Codes in left_nav menu.
                     (to avoid confusion with the Services reports)
  • Loading branch information...
1 parent 27bcb1b commit 0621077296e58ad7cca2371f4e1d5b5688a30415 @lcmaas lcmaas committed with bradymiller Feb 11, 2013
View
@@ -25,6 +25,7 @@
*/
require_once(dirname(__FILE__) . "/../library/log.inc");
+require_once(dirname(__FILE__) . "/../library/sql.inc");
/*
* Connect to a phiMail Direct Messaging server and transmit
@@ -54,84 +55,109 @@ function transmitCCD($ccd,$recipient,$requested_by) {
$fp=@fsockopen($server,$phimail_server['port']);
if ($fp===false) return("$config_err 3");
@fwrite($fp,"AUTH $phimail_username $phimail_password\n");
- @fflush($fp);
- $ret=@fgets($fp,256);
+ fflush($fp);
+ $ret=fgets($fp,256);
if($ret!="OK\n") {
- @fwrite($fp,"BYE\n");
- @fclose($fp);
+ fwrite($fp,"BYE\n");
+ fclose($fp);
return("$config_err 4");
}
- @fwrite($fp,"TO $recipient\n");
- @fflush($fp);
- $ret=@fgets($fp,256);
+ fwrite($fp,"TO $recipient\n");
+ fflush($fp);
+ $ret=fgets($fp,256);
if($ret!="OK\n") {
- @fwrite($fp,"BYE\n");
- @fclose($fp);
+ fwrite($fp,"BYE\n");
+ fclose($fp);
return( xl("Delivery is not currently permitted to the specified Direct Address.") );
}
- $ret=@fgets($fp,1024); //ignore extra server data
+ $ret=fgets($fp,1024); //ignore extra server data
if($requested_by=="patient")
$text_out = xl("Delivery of the attached clinical document was requested by the patient.");
else
$text_out = xl("A clinical document is attached.");
$text_len=strlen($text_out);
- @fwrite($fp,"TEXT $text_len\n");
- @fflush($fp);
+ fwrite($fp,"TEXT $text_len\n");
+ fflush($fp);
$ret=@fgets($fp,256);
if($ret!="BEGIN\n") {
- @fwrite($fp,"BYE\n");
- @fclose($fp);
+ fwrite($fp,"BYE\n");
+ fclose($fp);
return("$config_err 5");
}
- @fwrite($fp,$text_out);
- @fflush($fp);
+ fwrite($fp,$text_out);
+ fflush($fp);
$ret=@fgets($fp,256);
if($ret!="OK\n") {
- @fwrite($fp,"BYE\n");
- @fclose($fp);
+ fwrite($fp,"BYE\n");
+ fclose($fp);
return("$config_err 6");
}
$ccd_out=$ccd->saveXml();
$ccd_len=strlen($ccd_out);
- @fwrite($fp,"CDA $ccd_len\n");
- @fflush($fp);
- $ret=@fgets($fp,256);
+ fwrite($fp,"CDA $ccd_len\n");
+ fflush($fp);
+ $ret=fgets($fp,256);
if($ret!="BEGIN\n") {
- @fwrite($fp,"BYE\n");
- @fclose($fp);
+ fwrite($fp,"BYE\n");
+ fclose($fp);
return("$config_err 7");
}
- @fwrite($fp,$ccd_out);
- @fflush($fp);
- $ret=@fgets($fp,256);
+ fwrite($fp,$ccd_out);
+ fflush($fp);
+ $ret=fgets($fp,256);
if($ret!="OK\n") {
- @fwrite($fp,"BYE\n");
- @fclose($fp);
+ fwrite($fp,"BYE\n");
+ fclose($fp);
return("$config_err 8");
}
- @fwrite($fp,"SEND\n");
- @fflush($fp);
- $ret=@fgets($fp,256);
- @fwrite($fp,"BYE\n");
- @fclose($fp);
+ fwrite($fp,"SEND\n");
+ fflush($fp);
+ $ret=fgets($fp,256);
+ fwrite($fp,"BYE\n");
+ fclose($fp);
+
+ if($requested_by=="patient") {
+ $reqBy="portal-user";
+ $sql = "SELECT id FROM users WHERE username='portal-user'";
+ if (($r = sqlStatementNoLog($sql)) === FALSE ||
+ ($u = sqlFetchArray($r)) === FALSE) {
+ $reqID = 1; //default if we don't have a service user
+ } else {
+ $reqID = $u['id'];
+ }
- if(substr($ret,5)=="ERROR")
+ } else {
+ $reqBy=$_SESSION['authUser'];
+ $reqID=$_SESSION['authUserID'];
+ }
+
+ if(substr($ret,5)=="ERROR") {
+ //log the failure
+ newEvent("transmit-ccd",$reqBy,$_SESSION['authProvider'],0,$ret,$pid);
return( xl("The message could not be sent at this time."));
+ }
/**
* If we get here, the message was successfully sent and the return
* value $ret is of the form "QUEUED recipient message-id" which
* is suitable for logging.
- *
*/
- if($requested_by=="patient")
- newEvent("transmit-ccd","portal-user",$_SESSION['authProvider'],1,$ret,$pid);
- else
- newEvent("transmit-ccd",$_SESSION['authUser'],$_SESSION['authProvider'],1,$ret,$pid);
+ $msg_id=explode(" ",trim($ret),4);
+ if($msg_id[0]!="QUEUED" || !isset($msg_id[2])) { //unexpected response
+ $ret = "UNEXPECTED RESPONSE: " . $ret;
+ newEvent("transmit-ccd",$reqBy,$_SESSION['authProvider'],0,$ret,$pid);
+ return( xl("There was a problem sending the message."));
+ }
+ newEvent("transmit-ccd",$reqBy,$_SESSION['authProvider'],1,$ret,$pid);
+ $adodb=$GLOBALS['adodb']['db'];
+ $sql="INSERT INTO direct_message_log (msg_type,msg_id,sender,recipient,status,status_ts,patient_id,user_id) " .
+ "VALUES ('S', ?, ?, ?, 'S', NOW(), ?, ?)";
+ $res=@sqlStatementNoLog($sql,array($msg_id[2],$phimail_username,$recipient,$pid,$reqID));
+
return("SUCCESS");
}
@@ -56,7 +56,9 @@ function upload_action($patient_id,$category_id) {
}
//Upload multiple files on single click
- function upload_action_process() {
+ //2013-02-10 EMR Direct: added $non_HTTP_owner to allow storage of Direct Message attachments
+ //through this mechanism, and is set to the user_id for the background process adding the document
+ function upload_action_process($non_HTTP_owner=false) {
$couchDB = false;
$harddisk = false;
if($GLOBALS['document_storage_method']==0){
@@ -178,7 +180,8 @@ function upload_action_process() {
if($harddisk == true){
$uploadSuccess = false;
- if(move_uploaded_file($_FILES['file']['tmp_name'][$key],$this->file_path.$fname)){
+ $move_cmd = ($non_HTTP_owner ? "rename" : "move_uploaded_file");
+ if($move_cmd($_FILES['file']['tmp_name'][$key],$this->file_path.$fname)){
$uploadSuccess = true;
}
else{
@@ -204,7 +207,7 @@ function upload_action_process() {
$d->mimetype = $_FILES['file']['type'][$key];
}
$d->size = $_FILES['file']['size'][$key];
- $d->owner = $_SESSION['authUserID'];
+ $d->owner = $non_HTTP_owner ? $non_HTTP_owner : $_SESSION['authUserID'];
$sha1Hash = sha1_file( $this->file_path.$fname );
if($couchDB == true){
//Removing the temporary file which is used to create the hash
@@ -372,6 +372,10 @@ function(data) {
// run updater every 60 seconds
var repeater = setTimeout("getReminderCount()", 60000);
});
+ //piggy-back on this repeater to run other background-services
+ //this is a silent task manager that returns no output
+ $.post("<?php echo $GLOBALS['webroot']; ?>/library/ajax/execute_background_services.php",
+ { skip_timeout_reset: "1", ajax: "1" });
}
$(document).ready(function (){
@@ -1094,7 +1098,7 @@ function selpopup(selobj) {
<?php if (acl_check('admin', 'users' )) genMiscLink('RTop','adm','0',xl('Users'),'usergroup/usergroup_admin.php'); ?>
<?php genTreeLink('RTop','pwd','Users Password Change'); ?>
<?php if (acl_check('admin', 'practice' )) genMiscLink('RTop','adm','0',xl('Practice'),'../controller.php?practice_settings'); ?>
- <?php if (acl_check('admin', 'superbill')) genTreeLink('RTop','sup',xl('Services')); ?>
+ <?php if (acl_check('admin', 'superbill')) genTreeLink('RTop','sup',xl('Codes')); ?>
<?php if (acl_check('admin', 'super' )) genMiscLink('RTop','adm','0',xl('Layouts'),'super/edit_layout.php'); ?>
<?php if (acl_check('admin', 'super' )) genMiscLink('RTop','adm','0',xl('Lists'),'super/edit_list.php'); ?>
<?php if (acl_check('admin', 'acl' )) genMiscLink('RTop','adm','0',xl('ACL'),'usergroup/adminacl.php'); ?>
@@ -1122,6 +1126,7 @@ function selpopup(selobj) {
<?php genTreeLink('RTop','ono',xl('Ofc Notes')); ?>
<?php genMiscLink('RTop','adm','0',xl('BatchCom'),'batchcom/batchcom.php'); ?>
<?php genMiscLink('RTop','prf','0',xl('Preferences'),'super/edit_globals.php?mode=user'); ?>
+ <?php if(acl_check('patients','docs')) genMiscLink('RTop','adm','0',xl('New Documents'),'../controller.php?document&list&patient_id=0'); ?>
</ul>
</li>
@@ -1247,7 +1252,7 @@ function selpopup(selobj) {
<?php
// Changed the target URL from practice settings -> Practice Settings - Pharmacy... Dec 09,09 .. Visolve ... This replaces empty frame with Pharmacy window
if (acl_check('admin', 'practice' )) genMiscLink('RTop','adm','0',xl('Practice'),'../controller.php?practice_settings&pharmacy&action=list'); ?>
- <?php if (acl_check('admin', 'superbill')) genTreeLink('RTop','sup',xl('Services')); ?>
+ <?php if (acl_check('admin', 'superbill')) genTreeLink('RTop','sup',xl('Codes')); ?>
<?php if (acl_check('admin', 'super' )) genMiscLink('RTop','adm','0',xl('Layouts'),'super/edit_layout.php'); ?>
<?php if (acl_check('admin', 'super' )) genMiscLink('RTop','adm','0',xl('Lists'),'super/edit_list.php'); ?>
<?php if (acl_check('admin', 'acl' )) genMiscLink('RTop','adm','0',xl('ACL'),'usergroup/adminacl.php'); ?>
@@ -1380,6 +1385,15 @@ function selpopup(selobj) {
?>
</ul>
</li>
+ <?php if (acl_check('admin','super')) { ?>
+ <li><a class="collapsed_lv2"><span><?php echo xlt('Services') ?></span></a>
+ <ul>
+ <?php genMiscLink('RTop','rep','0',xl('Background Services'),'reports/background_services.php'); ?>
+ <?php genMiscLink('RTop','rep','0',xl('Direct Message Log'),'reports/direct_message_log.php'); ?>
+ </ul>
+ </li>
+ <?php } ?>
+
<?php // genTreeLink('RTop','rep','Other'); ?>
</ul>
</li>
@@ -1395,6 +1409,7 @@ function selpopup(selobj) {
<?php genMiscLink('RTop','adm','0',xl('BatchCom'),'batchcom/batchcom.php'); ?>
<?php genTreeLink('RTop','pwd',xl('Password')); ?>
<?php genMiscLink('RTop','prf','0',xl('Preferences'),'super/edit_globals.php?mode=user'); ?>
+ <?php if(acl_check('patients','docs')) genMiscLink('RTop','adm','0',xl('New Documents'),'../controller.php?document&list&patient_id=00'); ?>
</ul>
</li>
@@ -5,14 +5,17 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
+ *
+ * 2013/02/08 Minor tweaks by EMR Direct to allow integration with Direct messaging
*/
+
//SANITIZE ALL ESCAPES
$sanitize_all_escapes=true;
//STOP FAKE REGISTER GLOBALS
$fake_register_globals=false;
-require_once('../../globals.php');
+require_once("../../globals.php");
require_once("$srcdir/pnotes.inc");
require_once("$srcdir/patient.inc");
require_once("$srcdir/acl.inc");
@@ -141,16 +144,20 @@
}
}
} break;
+ case "savePatient":
case "save" : {
// Update alert.
$noteid = $_POST['noteid'];
$form_message_status = $_POST['form_message_status'];
- updatePnoteMessageStatus($noteid,$form_message_status);
+ $reply_to = $_POST['reply_to'];
+ if ($task=="save")
+ updatePnoteMessageStatus($noteid,$form_message_status);
+ else
+ updatePnotePatient($noteid,$reply_to);
$task = "edit";
$note = $_POST['note'];
$title = $_POST['form_note_type'];
$assigned_to = $_POST['assigned_to'];
- $reply_to = $_POST['reply_to'];
}
case "edit" : {
if ($noteid == "") {
@@ -232,7 +239,7 @@
</tr>
<tr>
<td class='text' align='center'>
- <?php if ($task != "addnew") { ?>
+ <?php if ($task != "addnew" && $result['pid']!=0) { ?>
<a class="patLink" onclick="goPid('<?php echo attr($result['pid']);?>')"><?php echo htmlspecialchars( xl('Patient'), ENT_NOQUOTES); ?>:</a>
<?php } else { ?>
<b class='<?php echo ($task=="addnew"?"required":"") ?>'><?php echo htmlspecialchars( xl('Patient'), ENT_NOQUOTES); ?>:</b>
@@ -246,7 +253,11 @@
if ($patientname == '') {
$patientname = xl('Click to select');
} ?>
- <input type='text' size='10' name='form_patient' style='width:150px;<?php echo ($task=="addnew"?"cursor:pointer;cursor:hand;":"") ?>' value='<?php echo htmlspecialchars($patientname, ENT_QUOTES); ?>' <?php echo ($task=="addnew"?"onclick='sel_patient()' readonly":"disabled") ?> title='<?php echo ($task=="addnew"?(htmlspecialchars( xl('Click to select patient'), ENT_QUOTES)):"") ?>' />
+ <input type='text' size='10' name='form_patient' style='width:150px;<?php
+ echo ($task=="addnew"?"cursor:pointer;cursor:hand;":"") ?>' value='<?php
+ echo htmlspecialchars($patientname, ENT_QUOTES); ?>' <?php
+ echo (($task=="addnew" || $result['pid']==0) ? "onclick='sel_patient()' readonly":"disabled") ?> title='<?php
+ echo ($task=="addnew"?(htmlspecialchars( xl('Click to select patient'), ENT_QUOTES)):"") ?>' />
<input type='hidden' name='reply_to' id='reply_to' value='<?php echo htmlspecialchars( $reply_to, ENT_QUOTES) ?>' />
&nbsp; &nbsp;
<b><?php echo htmlspecialchars( xl('Status'), ENT_NOQUOTES); ?>:</b>
@@ -302,7 +313,7 @@
var NewNote = function () {
top.restoreSession();
- if (document.forms[0].reply_to.value.length == 0) {
+ if (document.forms[0].reply_to.value.length == 0 || document.forms[0].reply_to.value == '0') {
alert('<?php echo htmlspecialchars( xl('Please choose a patient'), ENT_QUOTES); ?>');
}
else if (document.forms[0].assigned_to.value.length == 0) {
@@ -338,6 +349,13 @@ function setpatient(pid, lname, fname, dob) {
var f = document.forms[0];
f.form_patient.value = lname + ', ' + fname;
f.reply_to.value = pid;
+<?php if ($noteid) { ?>
+ //used when direct messaging service inserts a pnote with indeterminate patient
+ //to allow the user to assign the message to a patient.
+ top.restoreSession();
+ $("#task").val("savePatient");
+ $("#new_note").submit();
+<?php } ?>
}
// This invokes the find-patient popup.
@@ -439,9 +457,13 @@ function addtolist(sel){
$name .= ", " . $myrow['users_fname'];
}
$patient = $myrow['pid'];
- $patient = $myrow['patient_data_lname'];
- if ($myrow['patient_data_fname']) {
- $patient .= ", " . $myrow['patient_data_fname'];
+ if ($patient>0) {
+ $patient = $myrow['patient_data_lname'];
+ if ($myrow['patient_data_fname']) {
+ $patient .= ", " . $myrow['patient_data_fname'];
+ }
+ } else {
+ $patient = "* Patient must be set manually *";
}
$count++;
echo "
Oops, something went wrong. Retry.

0 comments on commit 0621077

Please sign in to comment.