Permalink
Browse files

Onsite Patient Portal:

  1. To turn the portal on, toggle on Administration
      ->Globals->Connectors->'Enable Onsite Patient Portal'
  2. Set the portal web address at Administration->Globals
      ->Connectors->'Onsite Patient Portal Site Address'
      (this address is the links that gets emailed to
       patients)
  3. Portal is at openemr/patients/ directory
  4. To authorize a patient to use portals, need to
      set the following demographic entry to 'YES':
      Demographics->Choices->'Allow Patient Portal'.
      To allow emailing of the portal login
      credentials to the patient also need to
      set an email address in the patient
      demographics and need to set the following
      demographic entry to 'YES': Demographics
      ->Choices->'Allow Email'.
  5. Patient portal login credentials for patients can
      be created/reset in the patient summary screen
      at the 'Create/Reset Onsite Portal Credentials'
      button (button is located at the top of the summary
      screen).
  6. When click 'Save' in the portal login credentials
      screen, it will email the credentials to the patient
      and the credentials can also be printed out.
      (note that for email to work, patient needs to 1) ok email
       in demographics->choices, 2) have a email address entered
       in demographics, 3) an email address needs to
       be set in Administration->GLobals->Notifications
       ->'Patient Reminder Sender Email' )
  7. When a patient logs into the portal for the first
      time (or after credentials are reset), the patient
      will be forced to set another password.
  8. Portal features include the following:
      - Display of CCR and CCD reports.
      - Display of Labs
      - Display of Medications
      - Display of Allergies
      - Display of Appointments

  TODO:
   -Test the emailing functionality
   -The appointment settting feature by the patient is not
     yet ready. The find appt and find open slot scripts
     are still buggy and the extraneous stuff needs to be
     removed. When these scripts are ready, can then place
     the following global in Administration->Globals to turn
     on this feature: Administration->Globals->Connectors
      ->'Allow Patient Modification of Appointments'. Will
     also need to add following to the openemr_postcalendar_categories
     able, pc_catname column: Office Visit (Patient Scheduled)

Main Author: Cassian LUP <cassi.lup@gmail.com>
Contributing Authors: bradymiller
                      zhhealthcare
  • Loading branch information...
1 parent 19c79d7 commit e1971d804ff107c682a92e2570785a4379b191e1 @cassilup cassilup committed with bradymiller May 18, 2011
View
@@ -31,10 +31,26 @@
//STOP FAKE REGISTER GLOBALS
$fake_register_globals=false;
//
-
+
+// check if using the patient portal
+//(if so, then use the portal authorization)
+if (isset($_GET['portal_auth'])) {
+ $landingpage = "../patients/index.php";
+ session_start();
+ if ( isset($_SESSION['pid']) && isset($_SESSION['patient_portal_onsite']) ) {
+ $pid = $_SESSION['pid'];
+ $ignoreAuth=true;
+ global $ignoreAuth;
+ }
+ else {
+ session_destroy();
+ header('Location: '.$landingpage.'?w');
+ exit;
+ }
+}
+
require_once(dirname(__FILE__) . "/../interface/globals.php");
require_once(dirname(__FILE__) . "/../library/sql-ccr.inc");
-require_once(dirname(__FILE__) . "/../library/sql.inc");
require_once(dirname(__FILE__) . "/uuid.php");
function createCCR($action,$raw="no"){
@@ -387,18 +387,15 @@ function show_date_fun(){
// check/uncheck all Forms of an encounter
$(".encounter").click(function() { SelectForms($(this)); });
-});
-$(document).ready(
-function(){
$(".generateCCR").click(
- function() {
- if(document.getElementById('show_date').checked == true){
- if(document.getElementById('Start').value == '' || document.getElementById('End').value == ''){
- alert('<?php echo addslashes( xl('Please select a start date and end date')) ?>');
- return false;
- }
- }
+ function() {
+ if(document.getElementById('show_date').checked == true){
+ if(document.getElementById('Start').value == '' || document.getElementById('End').value == ''){
+ alert('<?php echo addslashes( xl('Please select a start date and end date')) ?>');
+ return false;
+ }
+ }
var ccrAction = document.getElementsByName('ccrAction');
ccrAction[0].value = 'generate';
var raw = document.getElementsByName('raw');
@@ -430,6 +427,12 @@ function() {
});
$(".generateCCR_download_p").click(
function() {
+ if(document.getElementById('show_date').checked == true){
+ if(document.getElementById('Start').value == '' || document.getElementById('End').value == ''){
+ alert('<?php echo addslashes( xl('Please select a start date and end date')) ?>');
+ return false;
+ }
+ }
var ccrAction = document.getElementsByName('ccrAction');
ccrAction[0].value = 'generate';
var raw = document.getElementsByName('raw');
@@ -0,0 +1,195 @@
+<?php
+// +-----------------------------------------------------------------------------+
+// Copyright (C) 2011 Z&H Consultancy Services Private Limited <sam@zhservices.com>
+//
+//
+// This program is free software; you can redistribute it and/or
+// 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.
+//
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+//
+// A copy of the GNU General Public License is included along with this program:
+// openemr/interface/login/GnuGPL.html
+// For more information write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Author: Eldho Chacko <eldho@zhservices.com>
+// Jacob T Paul <jacob@zhservices.com>
+// Paul Simon <paul@zhservices.com>
+//
+// +------------------------------------------------------------------------------+
+
+//SANITIZE ALL ESCAPES
+$sanitize_all_escapes=true;
+//
+
+//STOP FAKE REGISTER GLOBALS
+$fake_register_globals=false;
+//
+ require_once("../../globals.php");
+ require_once("$srcdir/sql.inc");
+ require_once("$srcdir/formdata.inc.php");
+ require_once("$srcdir/sha1.js");
+ require_once("$srcdir/classes/class.phpmailer.php");
+
+// Collect portalsite parameter (either off for offsite or on for onsite); only allow off or on
+isset($_GET['portalsite']) ? $portalsite = $_GET['portalsite'] : $portalsite = "off";
+if ($portalsite != "off" && $portalsite != "on") $portalsite = "off";
+
+ $row = sqlQuery("SELECT pd.*,pao.portal_username,pao.portal_pwd,pao.portal_pwd_status FROM patient_data AS pd LEFT OUTER JOIN patient_access_" . add_escape_custom($portalsite) . "site AS pao ON pd.pid=pao.pid WHERE pd.pid=?",array($pid));
+
+function generatePassword($length=6, $strength=1) {
+ $consonants = 'bdghjmnpqrstvzacefiklowxy';
+ $numbers = '0234561789';
+ $specials = '@#$%';
+
+
+ $password = '';
+ $alt = time() % 2;
+ for ($i = 0; $i < $length/3; $i++) {
+ if ($alt == 1) {
+ $password .= $consonants[(rand() % strlen($consonants))].$numbers[(rand() % strlen($numbers))].$specials[(rand() % strlen($specials))];
+ $alt = 0;
+ } else {
+ $password .= $numbers[(rand() % strlen($numbers))].$specials[(rand() % strlen($specials))].$consonants[(rand() % strlen($consonants))];
+ $alt = 1;
+ }
+ }
+ return $password;
+}
+
+function validEmail($email){
+ if(eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $email)) {
+ return true;
+ }
+ return false;
+}
+
+function messageCreate($patient_id,$uname,$pass){
+ $message = htmlspecialchars( xl("Patient Portal Web Address"),ENT_NOQUOTES) . ":<br>" .
+ "<a href='" . htmlspecialchars($GLOBALS['portal_onsite_address'],ENT_QUOTES) . "'>" .
+ htmlspecialchars($GLOBALS['portal_onsite_address'],ENT_NOQUOTES) . "</a><br><br>" .
+ htmlspecialchars(xl("User Name"),ENT_NOQUOTES) . ": " .
+ htmlspecialchars($uname,ENT_NOQUOTES) . "<br><br>" .
+ htmlspecialchars(xl("Password"),ENT_NOQUOTES) . ": " .
+ htmlspecialchars($pass,ENT_NOQUOTES) . "<br><br>";
+ return $message;
+}
+
+function emailLogin($patient_id,$message){
+ $patientData = sqlQuery("SELECT * FROM `patient_data` WHERE `pid`=?", array($pid) );
+ if ( $patientData['hipaa_allowemail'] != "YES" || empty($patientData['email']) || empty($GLOBALS['patient_reminder_sender_email']) ) {
+ return false;
+ }
+ if (!(validEmail($patientData['email']))) {
+ return false;
+ }
+ if (!(validEmail($GLOBALS['patient_reminder_sender_email']))) {
+ return false;
+ }
+
+ $mail = new PHPMailer();
+ $pt_name=$patientData['fname'].' '.$patientData['lname'];
+ $pt_email=$patientData['email'];
+ $email_subject=xl('Access Your Patient Portal');
+ $email_sender=$GLOBALS['patient_reminder_sender_email'];
+ $mail->AddReplyTo($email_sender, $email_sender);
+ $mail->SetFrom($email_sender, $email_sender);
+ $mail->AddAddress($pt_email, $pt_name);
+ $mail->Subject = $email_subject;
+ $mail->MsgHTML("<html><body><div class='wrapper'>".$message."</div></body></html>");
+ $mail->IsHTML(true);
+ $mail->AltBody = $message;
+
+ if ($mail->Send()) {
+ return true;
+ } else {
+ $email_status = $mail->ErrorInfo;
+ error_log("EMAIL ERROR: ".$email_status,0);
+ return false;
+ }
+}
+
+function displayLogin($patient_id,$message,$emailFlag){
+ $patientData = sqlQuery("SELECT * FROM `patient_data` WHERE `pid`=?", array($pid) );
+ if ($emailFlag) {
+ $message = "<br><br>" .
+ htmlspecialchars(xl("Email was sent to following address"),ENT_NOQUOTES) . ": " .
+ htmlspecialchars($patientData['email'],ENT_NOQUOTES) .
+ $message;
+ }
+ echo "<html><body onload='window.print();'>" . $message . "</body></html>";
+}
+
+if(isset($_REQUEST['form_save']) && $_REQUEST['form_save']=='SUBMIT'){
+ $res = sqlStatement("SELECT * FROM patient_access_" . add_escape_custom($portalsite) . "site WHERE pid=?",array($pid));
+ if(sqlNumRows($res)){
+ sqlStatement("UPDATE patient_access_" . add_escape_custom($portalsite) . "site SET portal_username=?,portal_pwd=?,portal_pwd_status=0 WHERE pid=?",array($_REQUEST['uname'],$_REQUEST['authpwd'],$pid));
+ }
+ else{
+ sqlStatement("INSERT INTO patient_access_" . add_escape_custom($portalsite) . "site SET portal_username=?,portal_pwd=?,portal_pwd_status=0,pid=?",array($_REQUEST['uname'],$_REQUEST['authpwd'],$pid));
+ }
+
+ // Create the message
+ $message = messageCreate($pid,$_REQUEST['uname'],$_REQUEST['pwd']);
+ // Email and display/print the message
+ if ( emailLogin($pid,$message) ) {
+ // email was sent
+ displayLogin($pid,$message,true);
+ }
+ else {
+ // email wasn't sent
+ displayLogin($pid,$message,false);
+ }
+ exit;
+} ?>
+
+<html>
+<head>
+<link rel="stylesheet" href="<?php echo $css_header;?>" type="text/css">
+<script type="text/javascript">
+function convertPass(){
+ document.getElementById('authpwd').value=SHA1(document.getElementById('pwd').value);
+ document.getElementById('form_save').value='SUBMIT';
+ top.restoreSession();
+ document.forms[0].submit();
+}
+</script>
+</head>
+<body class="body_top">
+ <form name="portallogin" action="" method="POST">
+ <table align="center" style="margin-top:10px">
+ <tr class="text">
+ <th colspan="5" align="center"><?php echo htmlspecialchars(xl("Generate Username And Password For")." ".$row['fname'],ENT_QUOTES);?></th>
+ </tr>
+ <tr class="text">
+ <td><?php echo htmlspecialchars(xl('User Name').':',ENT_QUOTES);?></td>
+ <td><input type="text" name="uname" value="<?php if($row['portal_username']) echo htmlspecialchars($row['portal_username'],ENT_QUOTES); else echo htmlspecialchars($row['fname'].$row['id'],ENT_QUOTES);?>" size="10" readonly></td>
+ </tr>
+ <tr class="text">
+ <td><?php echo htmlspecialchars(xl('Password').':',ENT_QUOTES);?></td>
+ <?php
+ $pwd = generatePassword();
+ ?>
+ <input type="hidden" name="authpwd" id="authpwd">
+ <td><input type="text" name="pwd" id="pwd" value="<?php echo htmlspecialchars($pwd,ENT_QUOTES);?>" size="10" readonly></td>
+ <td><a href="#" class="css_button" onclick="top.restoreSession(); javascript:document.location.reload()"><span><?php echo htmlspecialchars(xl('Change'),ENT_QUOTES);?></span></a></td>
+ </tr>
+ <tr class="text">
+ <td><input type="hidden" name="form_save" id="form_save"></td>
+ <td colspan="5" align="center">
+ <a href="#" class="css_button" onclick="return convertPass()"><span><?php echo htmlspecialchars(xl('Save'),ENT_QUOTES);?></span></a>
+ <input type="hidden" name="form_cancel" id="form_cancel">
+ <a href="#" class="css_button" onclick="top.restoreSession(); parent.$.fn.fancybox.close();"><span><?php echo htmlspecialchars(xl('Cancel'),ENT_QUOTES);?></span></a>
+ </td>
+ </tr>
+ </table>
+ </form>
+</body>
@@ -299,6 +299,14 @@ function toggleIndicator(target,div) {
'centerOnScroll' : false,
'autoscale' : true
});
+// special size for patient portal
+ $(".small_modal").fancybox( {
+ 'overlayOpacity' : 0.0,
+ 'showCloseButton' : true,
+ 'frameHeight' : 180,
+ 'frameWidth' : 380,
+ 'centerOnScroll' : false
+ });
});
@@ -348,6 +356,45 @@ function toggleIndicator(target,div) {
"<span>".htmlspecialchars(xl('Delete'),ENT_NOQUOTES).
"</span></a></td>";
}
+ //Patient Portal
+ $portalUserSetting = true; //flag to see if patient has authorized access to portal
+ if($GLOBALS['portal_onsite_enable'] && $GLOBALS['portal_onsite_address']){
+ $portalStatus = sqlQuery("SELECT allow_patient_portal FROM patient_data WHERE pid=?",array($pid));
+ if ($portalStatus['allow_patient_portal']=='YES') {
+ $portalLogin = sqlQuery("SELECT pid FROM `patient_access_onsite` WHERE `pid`=?", array($pid));
+ echo "<td style='padding-left:1em;'><a class='css_button iframe small_modal' href='create_portallogin.php?portalsite=on&patient=" . htmlspecialchars($pid,ENT_QUOTES) . "' onclick='top.restoreSession()'>";
+ if (empty($portalLogin)) {
+ echo "<span>".htmlspecialchars(xl('Create Onsite Portal Credentials'),ENT_NOQUOTES)."</span></a></td>";
+ }
+ else {
+ echo "<span>".htmlspecialchars(xl('Reset Onsite Portal Credentials'),ENT_NOQUOTES)."</span></a></td>";
+ }
+ }
+ else {
+ $portalUserSetting = false;
+ }
+ }
+ if($GLOBALS['portal_offsite_enable'] && $GLOBALS['portal_offsite_address']){
+ $portalStatus = sqlQuery("SELECT allow_patient_portal FROM patient_data WHERE pid=?",array($pid));
+ if ($portalStatus['allow_patient_portal']=='YES') {
+ $portalLogin = sqlQuery("SELECT pid FROM `patient_access_offsite` WHERE `pid`=?", array($pid));
+ echo "<td style='padding-left:1em;'><a class='css_button iframe small_modal' href='create_portallogin.php?portalsite=off&patient=" . htmlspecialchars($pid,ENT_QUOTES) . "' onclick='top.restoreSession()'>";
+ if (empty($portalLogin)) {
+ "<span>".htmlspecialchars(xl('Create Offsite Portal Credentials'),ENT_NOQUOTES)."</span></a></td>";
+ }
+ else {
+ "<span>".htmlspecialchars(xl('Reset Offsite Portal Credentials'),ENT_NOQUOTES)."</span></a></td>";
+ }
+ }
+ else {
+ $portalUserSetting = false;
+ }
+ }
+ if (!($portalUserSetting)) {
+ // Show that the patient has not authorized portal access
+ echo "<td style='padding-left:1em;'>" . htmlspecialchars( xl('Patient has not authorized the Patient Portal.'), ENT_NOQUOTES) . "</td>";
+ }
+ //Patient Portal
// If patient is deceased, then show this (along with the number of days patient has been deceased for)
$days_deceased = is_patient_deceased($pid);
@@ -1212,6 +1212,20 @@
xl('Https link for the OpenEMR Support LLC Lab Exchange Service.')
),
+ 'portal_onsite_enable' => array(
+ xl('Enable Onsite Patient Portal'),
+ 'bool', // data type
+ '0',
+ xl('Enable Onsite Patient Portal.')
+ ),
+
+ 'portal_onsite_address' => array(
+ xl('Onsite Patient Portal Site Address'),
+ 'text', // data type
+ 'https://your_web_site.com/openemr/patients',
+ xl('Website link for the Onsite Patient Portal.')
+ ),
+
),
);
Oops, something went wrong.

0 comments on commit e1971d8

Please sign in to comment.