Skip to content

Commit

Permalink
BAH-1093 : Tele-consultation feature merge (Bahmni#44)
Browse files Browse the repository at this point in the history
* SM: add github actions placeholder for stream3/master

* Added missing "steps:"

* SM: test yml

* SM: renamed github actions workflow

* SM: pipeline build project

* CON-19 |  Gracil/Hamza | Add isTeleconsultationEnabled field to the appointment module

* SM: dirty file to trigger github actions

* Packaging instruction added to README file

* [Kaleeaswari] Script to create java package and push to octopus library

* [Kaleeaswari] Script to create java package and push to octopus library

* [Kaleeaswari] Script to create java package and push to octopus library

* [Kaleeaswari] Script to create java package and push to octopus library

* [Kaleeaswari] Script to create java package and push to octopus library

* [Kaleeaswari] Fixing github actions ci file syntax issues

* [Kaleeaswari] Fixing github actions ci file syntax issues

* [Kaleeaswari] [WIP] Package appointments jar to octopus

* [Kaleeaswari] [WIP] Package appointments jar to octopus

* [Kaleeaswari] [WIP] Package appointments jar to octopus

* [Kaleeaswari] [WIP] Package appointments jar to octopus

* [Kaleeaswari] [WIP] Fixing java jar location in server

* [Kaleeaswari] [WIP] Adding deployment script

* [Kaleeaswari] Deploying app to the environment - Extracting test to separate task

* SM, DL: templated/standardised octo CLI commands

* Removing mvn test so that strange maven behaviour is overlooked

* Removing mvn test so that strange maven behaviour is overlooked

* Temporary test to see if changes are reflected in app on env

* Revert temp test

* [Hamza] Email link to patient when teleconsultation enabled

* [Hamza][Bahmni#91] Email sent to patient based on template (tests pending)

* [Hamza][Bahmni#91] Implemented email content variation (with/without provider)

* [Hamza][Bahmni#56] Add email-notification dependency through S3 bucket

* [Hamza][Bahmni#56] Dependency for email pulled from S3 bucket via pom.xml

* [vishal]  add rename isTeleconsulationEnabled to teleconslutation

* [vishal]  remove unused column is-teleconsultation-enabled

* Monica/Natheesh | Bahmni#119 Addressed no email id attribute and relevant changes.

Co-authored-by: Natheeshkumar <[email protected]>

* Shankar: Adding appointment_service UUID
to query to fetch upcoming appointments

* Praveena/Swati - 95 - Fix liquibase migration error on load

* Praveena | Removed github actions before merging to Bahmni product

* Praveena|Swati - Modified dependency repo for Email notification

* Revert "Praveena | Removed github actions before merging to Bahmni product"

This reverts commit 5449b92d7f0f888faaf9eb0c825538f6432ed03a.

* Praveena | Removed github actions before merging to Bahmni product

* Swati/Praveena- implementation of review comments

* Swati/Praveena: Review comments changes

* Swati/Praveena: Review comments changes

* Praveena/Swati | Teleconsultation review comments

Co-authored-by: Steve M <[email protected]>
Co-authored-by: smorris-TW <[email protected]>
Co-authored-by: Gracil Benedict <[email protected]>
Co-authored-by: Katia Bondar <[email protected]>
Co-authored-by: kaleeaswari <[email protected]>
Co-authored-by: Deedee <deedee>
Co-authored-by: Hamza <[email protected]>
Co-authored-by: Hamza <[email protected]>
Co-authored-by: Monica Rajendran <[email protected]>
Co-authored-by: Natheeshkumar <[email protected]>
Co-authored-by: Shanky <[email protected]>
Co-authored-by: swatigogia2020 <[email protected]>
  • Loading branch information
12 people authored Nov 30, 2020
1 parent fa22355 commit fa6b5a1
Show file tree
Hide file tree
Showing 27 changed files with 579 additions and 37 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
openmrs-module-appointments
==========================
Openmrs Module Appointment Backend
=================================
This repository acts as the back end for the **Bahmni Appointment Scheduling**.

## Packaging
```mvn clean package -Duser.timezone=IST```

Description
-----------
Module for scheduling and managing appointments.

The output is the OMOD file:
```openmrs-module-appointments/omod/target/appointments-[VERSION].omod```
5 changes: 5 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bahmni.module</groupId>
<artifactId>email-notification-omod</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.openmrs.module.appointments.event;

import org.openmrs.module.appointments.model.Appointment;
import org.springframework.context.ApplicationEvent;

public class TeleconsultationAppointmentSavedEvent extends ApplicationEvent {
private Appointment appointment;

public TeleconsultationAppointmentSavedEvent(Appointment appointment) {
super(appointment);
this.appointment = appointment;
}

public Appointment getAppointment() {
return appointment;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class Appointment extends BaseOpenmrsData implements Serializable {
private Date startDateTime;
private Date endDateTime;
private AppointmentKind appointmentKind;
private Boolean teleconsultation;
private AppointmentStatus status;
private String comments;
private Set<AppointmentProvider> providers;
Expand Down Expand Up @@ -201,5 +202,17 @@ public Boolean isFutureAppointment() {
public boolean isSameAppointment(Appointment appointment) {
return this.getUuid().equals(appointment.getUuid());
}

public void setTeleconsultation(Boolean teleconsultation) {
this.teleconsultation = teleconsultation;
}

public Boolean getTeleconsultation(){
return teleconsultation;
}

public Boolean isEmailIdAvailable() {
return this.patient.getAttribute("email") != null ? true : false;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.openmrs.module.appointments.service;

import org.bahmni.module.email.notification.EmailNotificationException;
import org.openmrs.module.appointments.model.Appointment;

public interface TeleconsultationAppointmentNotificationService {
void sendTeleconsultationAppointmentLinkEmail(Appointment appointment) throws EmailNotificationException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.openmrs.module.appointments.conflicts.AppointmentConflict;
import org.openmrs.module.appointments.dao.AppointmentAuditDao;
import org.openmrs.module.appointments.dao.AppointmentDao;
import org.openmrs.module.appointments.event.TeleconsultationAppointmentSavedEvent;
import org.openmrs.module.appointments.helper.AppointmentServiceHelper;
import org.openmrs.module.appointments.model.Appointment;
import org.openmrs.module.appointments.model.AppointmentAudit;
Expand All @@ -22,6 +23,8 @@
import org.openmrs.module.appointments.service.AppointmentsService;
import org.openmrs.module.appointments.validator.AppointmentStatusChangeValidator;
import org.openmrs.module.appointments.validator.AppointmentValidator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
Expand All @@ -43,7 +46,7 @@
import static org.openmrs.module.appointments.util.DateUtil.getStartOfDay;


public class AppointmentsServiceImpl implements AppointmentsService {
public class AppointmentsServiceImpl implements AppointmentsService, ApplicationEventPublisherAware {

private static final String PRIVILEGES_EXCEPTION_CODE = "error.privilegesRequired";
private Log log = LogFactory.getLog(this.getClass());
Expand All @@ -61,6 +64,8 @@ public class AppointmentsServiceImpl implements AppointmentsService {

private List<AppointmentConflict> appointmentConflicts;

private ApplicationEventPublisher applicationEventPublisher;

public void setAppointmentDao(AppointmentDao appointmentDao) {
this.appointmentDao = appointmentDao;
}
Expand All @@ -81,6 +86,10 @@ public void setAppointmentServiceHelper(AppointmentServiceHelper appointmentServ
this.appointmentServiceHelper = appointmentServiceHelper;
}

public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}

public void setEditAppointmentValidators(List<AppointmentValidator> editAppointmentValidators) {
this.editAppointmentValidators = editAppointmentValidators;
}
Expand Down Expand Up @@ -112,6 +121,11 @@ public Appointment validateAndSave(Appointment appointment) throws APIException
validate(appointment, appointmentValidators);
appointmentServiceHelper.checkAndAssignAppointmentNumber(appointment);
save(appointment);
// TODO: #92 - remove null checking after adding a default value
if (appointment.getTeleconsultation() != null &&
appointment.getTeleconsultation()) {
applicationEventPublisher.publishEvent(new TeleconsultationAppointmentSavedEvent(appointment));
}
return appointment;
}

Expand Down Expand Up @@ -374,4 +388,5 @@ private void createAndSetAppointmentAudit(Appointment appointment) {
Set<AppointmentAudit> appointmentAudits = appointment.getAppointmentAudits();
appointmentAudits.addAll(new HashSet<>(Collections.singleton(appointmentAudit)));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.openmrs.module.appointments.service.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bahmni.module.email.notification.EmailNotificationException;
import org.bahmni.module.email.notification.service.EmailNotificationService;
import org.openmrs.Patient;
import org.openmrs.PersonAttribute;
import org.openmrs.api.context.Context;
import org.openmrs.module.appointments.model.Appointment;
import org.openmrs.module.appointments.model.AppointmentProvider;
import org.openmrs.module.appointments.service.TeleconsultationAppointmentNotificationService;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class TeleconsultationAppointmentNotificationServiceImpl implements TeleconsultationAppointmentNotificationService {
private final static String EMAIL_SUBJECT = "teleconsultation.appointment.email.subject";
private final static String EMAIL_BODY = "teleconsultation.appointment.email.body";

private Log log = LogFactory.getLog(this.getClass());

private EmailNotificationService emailNotificationService;

private TeleconsultationAppointmentService teleconsultationAppointmentService = new TeleconsultationAppointmentService();

public TeleconsultationAppointmentNotificationServiceImpl() {}
public TeleconsultationAppointmentNotificationServiceImpl(
EmailNotificationService emailNotificationService) {
this.emailNotificationService = emailNotificationService;
}

public void sendTeleconsultationAppointmentLinkEmail(Appointment appointment) throws EmailNotificationException {
String link = teleconsultationAppointmentService.getTeleconsultationURL(appointment);
Patient patient = appointment.getPatient();
PersonAttribute patientEmailAttribute = patient.getAttribute("email");
if (patientEmailAttribute != null) {
String email = patientEmailAttribute.getValue();
String patientName = appointment.getPatient().getGivenName();
String doctor = "";
if(appointment.getProviders() != null) {
AppointmentProvider provider = appointment.getProviders().iterator().next();
doctor = " with Dr. " + provider.getProvider().getPerson().getGivenName();
}
Date appointmentStart = appointment.getStartDateTime();
String day = new SimpleDateFormat("EEEE").format(appointmentStart);
String date = new SimpleDateFormat("dd/MM/yy").format(appointmentStart);
String time = new SimpleDateFormat("hh:mm a").format(appointmentStart);
emailNotificationService.send(
Context.getMessageSourceService().getMessage(EMAIL_SUBJECT, null, null),
Context.getMessageSourceService().getMessage(
EMAIL_BODY,
new Object[]{
patientName,
doctor,
day,
date,
time,
link
},
null
),
new String[] { email },
null,
null);
} else {
log.warn("Attempting to send an email to a patient without an email address");
}
}

public void setEmailNotificationService(EmailNotificationService emailNotificationService) {
this.emailNotificationService = emailNotificationService;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.openmrs.module.appointments.service.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bahmni.module.email.notification.EmailNotificationException;
import org.openmrs.module.appointments.event.TeleconsultationAppointmentSavedEvent;
import org.openmrs.module.appointments.service.TeleconsultationAppointmentNotificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class TeleconsultationAppointmentSavedEventListener implements ApplicationListener<TeleconsultationAppointmentSavedEvent> {

private Log log = LogFactory.getLog(this.getClass());

@Autowired
private TeleconsultationAppointmentNotificationService emailNotificationService;

public TeleconsultationAppointmentSavedEventListener() {}
public TeleconsultationAppointmentSavedEventListener(TeleconsultationAppointmentNotificationService emailNotificationService) {
this.emailNotificationService = emailNotificationService;
}

@Override
public void onApplicationEvent(TeleconsultationAppointmentSavedEvent event) {
try {
emailNotificationService.sendTeleconsultationAppointmentLinkEmail(event.getAppointment());
} catch (EmailNotificationException e) {
log.error("Unable to send teleconsultation appointment email notification", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.openmrs.module.appointments.service.impl;

import org.openmrs.module.appointments.model.Appointment;

public class TeleconsultationAppointmentService {

private final static String BASE_URL = "https://meet.jit.si/";

public String getTeleconsultationURL(Appointment appointment) {
return BASE_URL + appointment.getUuid();
}
}
1 change: 1 addition & 0 deletions api/src/main/resources/Appointment.hbm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<many-to-one name="location" class="org.openmrs.Location" column="location_id"/>
<property name="startDateTime" type="java.util.Date" column="start_date_time"/>
<property name="endDateTime" type="java.util.Date" column="end_date_time"/>
<property name="teleconsultation" type="java.lang.Boolean" column="teleconsultation"/>
<property name="appointmentKind" column="appointment_kind">
<type name="org.hibernate.type.EnumType">
<param name="enumClass">org.openmrs.module.appointments.model.AppointmentKind</param>
Expand Down
33 changes: 33 additions & 0 deletions api/src/main/resources/liquibase.xml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,20 @@
</sql>
</changeSet>

<changeSet id="create-column-teleconsultation-202008241355" author="Vishal">
<preConditions onFail="MARK_RAN">
<tableExists tableName="patient_appointment" />
<not>
<columnExists tableName="patient_appointment" columnName="teleconsultation" />
</not>
</preConditions>
<addColumn tableName="patient_appointment">
<column name="teleconsultation" type="boolean" >
<constraints nullable="false" />
</column>
</addColumn>
</changeSet>

<changeSet id="drop_index_on_appointment_service_table-201707251710" author="Santhosh, Maharjun">
<preConditions onFail="MARK_RAN">
<tableExists tableName="appointment_service"/>
Expand Down Expand Up @@ -342,6 +356,14 @@
<sqlFile path="patientUpcomingAppointments.sql"/>
</changeSet>

<changeSet id="global-property-upcoming-appointments-sql-update" author="Shankar, Mahesh">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="1">select count(*) from global_property where property='bahmni.sqlGet.upComingAppointments'</sqlCheck>
</preConditions>
<comment>Updating query to fetch upcoming appointments for patient</comment>
<sqlFile path="patientUpcomingAppointments_v2.sql"/>
</changeSet>

<changeSet id="Create-Available-for-appointments-201712121212-2" author="Maharjun, Saikumar">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">
Expand Down Expand Up @@ -576,4 +598,15 @@
<column name="description" value="URL pattern to use for published Recurring appointment events. Default is /openmrs/ws/rest/v1/recurring-appointments?uuid={uuid}. If you change default value, please add your custom implementation for the given URL"/>
</insert>
</changeSet>
<changeSet id="default-202009011116" author="Deedee Lee">
<preConditions>
<sqlCheck expectedResult="0">
SELECT COUNT(*) FROM person_attribute_type where name = 'email';
</sqlCheck>
</preConditions>
<comment> Add email address in registration page </comment>
<sql>
INSERT INTO person_attribute_type (name, description, format, searchable, creator, date_created, retired, uuid) VALUES ('email', 'Email Address', 'java.lang.String', '1', 1, now(), 0, uuid());
</sql>
</changeSet>
</databaseChangeLog>
8 changes: 8 additions & 0 deletions api/src/main/resources/messages.properties
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
${project.parent.artifactId}.title=Bahmni Appointment Scheduling

teleconsultation.appointment.email.subject=Teleconsultation appointment confirmed
teleconsultation.appointment.email.body=Hi {0},\
<p>Your teleconsultation appointment{1} has been confirmed!<br>\
The appointment time is on <b>{2}, {3} at {4}</b>.<br>\
The teleconsultation link is: <a href="{5}">{5}</a><br>\
If you have any questions, please reach out to hospital administration for assistance.<br>\
See you soon!
8 changes: 7 additions & 1 deletion api/src/main/resources/moduleApplicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@
</property>
</bean>


<bean id="defaultEditAppointmentValidator" class="org.openmrs.module.appointments.validator.impl.DefaultEditAppointmentValidator">
<property name="appointmentDao">
<ref bean="appointmentDao"/>
Expand Down Expand Up @@ -238,4 +237,11 @@
<ref bean="sessionFactory"/>
</property>
</bean>

<bean id="teleconsultationAppointmentNotificationService" class="org.openmrs.module.appointments.service.impl.TeleconsultationAppointmentNotificationServiceImpl">
<property name="emailNotificationService">
<ref bean="emailNotificationService"/>
</property>
</bean>

</beans>
23 changes: 23 additions & 0 deletions api/src/main/resources/patientUpcomingAppointments_v2.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
UPDATE global_property
SET property_value= "SELECT
app_service.uuid,
app_service.name AS `DASHBOARD_APPOINTMENTS_SERVICE_KEY`,
app_service_type.name AS `DASHBOARD_APPOINTMENTS_SERVICE_TYPE_KEY`,
DATE_FORMAT(start_date_time, \"%d/%m/%Y\") AS `DASHBOARD_APPOINTMENTS_DATE_KEY`,
CONCAT(DATE_FORMAT(start_date_time, \"%l:%i %p\"), \" - \", DATE_FORMAT(end_date_time, \"%l:%i %p\")) AS `DASHBOARD_APPOINTMENTS_SLOT_KEY`,
CONCAT(pn.given_name, ' ', pn.family_name) AS `DASHBOARD_APPOINTMENTS_PROVIDER_KEY`,
pa.status AS `DASHBOARD_APPOINTMENTS_STATUS_KEY`
FROM
patient_appointment pa
JOIN person p ON p.person_id = pa.patient_id AND pa.voided IS FALSE
JOIN appointment_service app_service
ON app_service.appointment_service_id = pa.appointment_service_id AND app_service.voided IS FALSE
LEFT JOIN provider prov ON prov.provider_id = pa.provider_id AND prov.retired IS FALSE
LEFT JOIN person_name pn ON pn.person_id = prov.person_id AND pn.voided IS FALSE
LEFT JOIN appointment_service_type app_service_type
ON app_service_type.appointment_service_type_id = pa.appointment_service_type_id
WHERE p.uuid = ${patientUuid} AND
start_date_time >= CURDATE() AND
(app_service_type.voided IS FALSE OR app_service_type.voided IS NULL)
ORDER BY start_date_time ASC;"
WHERE property='bahmni.sqlGet.upComingAppointments'
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
import org.openmrs.web.test.BaseModuleWebContextSensitiveTest;

@org.springframework.test.context.ContextConfiguration(locations = {"classpath:TestingApplicationContext.xml"}, inheritLocations = true)
public class BaseIntegrationTest extends BaseModuleWebContextSensitiveTest {
public abstract class BaseIntegrationTest extends BaseModuleWebContextSensitiveTest {
}
Loading

0 comments on commit fa6b5a1

Please sign in to comment.