Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FM2-136 : Fhir appointment resource initial implementation #29

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions fhir2-appnt-api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>appointments</artifactId>
<groupId>org.openmrs.module</groupId>
<version>1.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<groupId>org.openmrs.module</groupId>
<artifactId>fhir2-appointment-api</artifactId>
<version>${openmrsModuleFhirVersion}</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the version here inherit from the parent module, i.e., be tied to the Bahmni appointment module version rather than the FHIR module version?

<packaging>jar</packaging>
<name>FHIR Appointment API</name>

<dependencies>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}-api</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openmrs.module</groupId>
<artifactId>fhir2-api</artifactId>
<version>${openmrsModuleFhirVersion}</version>
</dependency>
<dependency>
<groupId>org.openmrs.api</groupId>
<artifactId>openmrs-api</artifactId>
<version>${openmrs.platform.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openmrs.api</groupId>
<artifactId>openmrs-api</artifactId>
<version>${openmrs.platform.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should define a version here, since Lombok isn't defined in the parent POM.

</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>${hamcrestCoreVersion}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.exparity</groupId>
<artifactId>hamcrest-date</artifactId>
<version>${hamcrestDateVersion}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>net.revelc.code</groupId>
<artifactId>impsort-maven-plugin</artifactId>
</plugin>
Comment on lines +69 to +84
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we use these plugins inside the FHIR2 module, I'd hesitate about using them here, since they aren't defined in the parent POM, so they're missing all the configuration we do. Also, that configuration may not align with Bahmni's coding standards.

</plugins>
</build>

<properties>
<hamcrestDateVersion>2.0.7</hamcrestDateVersion>
<hamcrestCoreVersion>2.2</hamcrestCoreVersion>
</properties>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.openmrs.module.fhirappnt.api;

import lombok.NoArgsConstructor;
import org.openmrs.module.fhir2.FhirConstants;

@NoArgsConstructor
public class AppointmentFhirConstants extends FhirConstants {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to extend FhirConstants and you already have fhir2-api as a dependency?


public static final String APPOINTMENT_SPECIALITY_VALUESET_URI = HL7_FHIR_VALUE_SET_PREFIX
+ "/c80-practice-codes";

public static final String APPOINTMENT_PARTICIPANT_TYPE = HL7_FHIR_VALUE_SET_PREFIX
+ "/encounter-participant-type";

public static final String APPOINTMENT_SERVICE_TYPE = HL7_FHIR_VALUE_SET_PREFIX
+ "/service-type";

public static final String OPENMRS_FHIR_EXT_HEALTH_CARE_SERVICE= "https://fhir.openmrs.org/ext/health-care-service";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.openmrs.module.fhirappnt.api.Impl;

import lombok.AccessLevel;
import lombok.Setter;
import org.openmrs.module.appointments.model.Appointment;
import org.openmrs.module.fhir2.api.FhirAppointmentService;
import org.openmrs.module.fhir2.api.dao.FhirAppointmentDao;
import org.openmrs.module.fhir2.api.translators.AppointmentTranslator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Primary
@Component
@Transactional
@Setter(AccessLevel.PACKAGE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't doing anything here if you define the setters (which is fine).

public class FhirBahmniAppointmentServiceImpl implements FhirAppointmentService {

@Autowired
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have setters defined, I would put the @Autowired annotation on them, rather than relying on field annotation.

private AppointmentTranslator<Appointment> appointmentTranslator;

@Autowired
private FhirAppointmentDao<Appointment> fhirAppointmentDao;

public void setFhirAppointmentDao(FhirAppointmentDao<Appointment> fhirAppointmentDao) {
this.fhirAppointmentDao = fhirAppointmentDao;
}

public void setAppointmentTranslator(AppointmentTranslator<Appointment> appointmentTranslator) {
this.appointmentTranslator = appointmentTranslator;
}

@Override
public org.hl7.fhir.r4.model.Appointment getAppointmentByUuid(String uuid) {
return appointmentTranslator.toFhirResource(fhirAppointmentDao.getAppointmentByUuid(uuid));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.openmrs.module.fhirappnt.api.dao.impl;

import lombok.AccessLevel;
import lombok.Setter;
import org.openmrs.module.appointments.model.Appointment;
import org.openmrs.module.appointments.service.AppointmentsService;
import org.openmrs.module.fhir2.api.dao.FhirAppointmentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Setter(AccessLevel.PACKAGE)
public class FhirAppointmentDaoImpl implements FhirAppointmentDao<Appointment> {

@Autowired
private AppointmentsService appointmentsService;

@Override
public Appointment getAppointmentByUuid(String uuid) {
return appointmentsService.getAppointmentByUuid(uuid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.openmrs.module.fhirappnt.api.translators;

import org.hl7.fhir.r4.model.Appointment;
import org.openmrs.module.fhir2.api.translators.OpenmrsFhirUpdatableTranslator;

public interface AppointmentParticipantTranslator<T> extends OpenmrsFhirUpdatableTranslator<T, Appointment.AppointmentParticipantComponent> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.openmrs.module.fhirappnt.api.translators;

import org.hl7.fhir.r4.model.CodeableConcept;
import org.openmrs.module.appointments.model.Speciality;
import org.openmrs.module.fhir2.api.translators.OpenmrsFhirUpdatableTranslator;

public interface AppointmentSpecialityTranslator extends OpenmrsFhirUpdatableTranslator<Speciality, CodeableConcept>{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.openmrs.module.fhirappnt.api.translators;

import org.hl7.fhir.r4.model.HealthcareService;
import org.openmrs.module.appointments.model.AppointmentServiceDefinition;
import org.openmrs.module.fhir2.api.translators.OpenmrsFhirUpdatableTranslator;

public interface HealthCareServiceTranslator extends OpenmrsFhirUpdatableTranslator<AppointmentServiceDefinition, HealthcareService> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.openmrs.module.fhirappnt.api.translators.impl;

import lombok.AccessLevel;
import lombok.Setter;
import org.hl7.fhir.r4.model.Appointment;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.openmrs.Patient;
import org.openmrs.module.fhir2.api.translators.PatientReferenceTranslator;
import org.openmrs.module.fhir2.api.translators.impl.AbstractReferenceHandlingTranslator;
import org.openmrs.module.fhirappnt.api.AppointmentFhirConstants;
import org.openmrs.module.fhirappnt.api.translators.AppointmentParticipantTranslator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Setter(AccessLevel.PACKAGE)
public class AppointmentPatientTranslatorImpl extends AbstractReferenceHandlingTranslator implements AppointmentParticipantTranslator<Patient> {

@Autowired
private PatientReferenceTranslator patientReferenceTranslator;

@Override
public Appointment.AppointmentParticipantComponent toFhirResource(Patient patient) {
if (patient == null) {
return null;
}
Appointment.AppointmentParticipantComponent participant = new Appointment.AppointmentParticipantComponent();
CodeableConcept role = new CodeableConcept();
role.addCoding(new Coding(AppointmentFhirConstants.APPOINTMENT_PARTICIPANT_TYPE, "Patient", "Patient"));
participant.setRequired(Appointment.ParticipantRequired.REQUIRED);
participant.setActor(patientReferenceTranslator.toFhirResource(patient));
participant.addType(role);
participant.setStatus(Appointment.ParticipationStatus.ACCEPTED);

return participant;
}

@Override
public Patient toOpenmrsType(Appointment.AppointmentParticipantComponent appointmentParticipantComponent) {
return toOpenmrsType(new Patient(), appointmentParticipantComponent);
}

@Override
public Patient toOpenmrsType(Patient patient, Appointment.AppointmentParticipantComponent appointmentParticipantComponent) {
if (appointmentParticipantComponent == null) {
return patient;
}

return patientReferenceTranslator.toOpenmrsType(appointmentParticipantComponent.getActor());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.openmrs.module.fhirappnt.api.translators.impl;

import lombok.AccessLevel;
import lombok.Setter;
import org.hl7.fhir.r4.model.Appointment;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.openmrs.Provider;
import org.openmrs.module.fhir2.api.dao.FhirPractitionerDao;
import org.openmrs.module.fhir2.api.translators.impl.AbstractReferenceHandlingTranslator;
import org.openmrs.module.fhirappnt.api.AppointmentFhirConstants;
import org.openmrs.module.fhirappnt.api.translators.AppointmentParticipantTranslator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Setter(AccessLevel.PACKAGE)
public class AppointmentPractitionerTranslatorImpl extends AbstractReferenceHandlingTranslator implements AppointmentParticipantTranslator<Provider> {

@Autowired
private FhirPractitionerDao practitionerDao;

@Override
public Appointment.AppointmentParticipantComponent toFhirResource(Provider provider) {
if (provider == null) {
return null;
}
Appointment.AppointmentParticipantComponent participant = new Appointment.AppointmentParticipantComponent();
CodeableConcept role = new CodeableConcept();
role.addCoding(new Coding(AppointmentFhirConstants.APPOINTMENT_PARTICIPANT_TYPE, "Practitioner", "Practitioner"));
participant.setRequired(Appointment.ParticipantRequired.OPTIONAL);
participant.setActor(createPractitionerReference(provider));
participant.addType(role);

return participant;
}

@Override
public Provider toOpenmrsType(Appointment.AppointmentParticipantComponent appointmentParticipantComponent) {
return toOpenmrsType(new Provider(), appointmentParticipantComponent);
}

@Override
public Provider toOpenmrsType(Provider appointmentProvider, Appointment.AppointmentParticipantComponent appointmentParticipantComponent) {
if (appointmentParticipantComponent == null) {
return appointmentProvider;
}

return practitionerDao.getProviderByUuid(getReferenceId(appointmentParticipantComponent.getActor()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.openmrs.module.fhirappnt.api.translators.impl;
import lombok.AccessLevel;
import lombok.Setter;
import org.hl7.fhir.r4.model.Appointment;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.openmrs.module.appointments.model.AppointmentProvider;
import org.openmrs.module.appointments.model.AppointmentProviderResponse;
import org.openmrs.module.fhir2.api.dao.FhirPractitionerDao;
import org.openmrs.module.fhir2.api.translators.impl.AbstractReferenceHandlingTranslator;
import org.openmrs.module.fhirappnt.api.AppointmentFhirConstants;
import org.openmrs.module.fhirappnt.api.translators.AppointmentParticipantTranslator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@Setter(AccessLevel.PACKAGE)
public class AppointmentProviderTranslatorImpl extends AbstractReferenceHandlingTranslator implements AppointmentParticipantTranslator<AppointmentProvider> {

@Autowired
private FhirPractitionerDao practitionerDao;

@Override
public Appointment.AppointmentParticipantComponent toFhirResource(AppointmentProvider appointmentProvider) {
if (appointmentProvider == null || appointmentProvider.getProvider() == null) {
return null;
}
Appointment.AppointmentParticipantComponent participant = new Appointment.AppointmentParticipantComponent();
CodeableConcept role = new CodeableConcept();
role.addCoding(new Coding(AppointmentFhirConstants.APPOINTMENT_PARTICIPANT_TYPE, "AppointmentPractitioner", "AppointmentPractitioner"));
participant.setRequired(Appointment.ParticipantRequired.OPTIONAL);
participant.setActor(createPractitionerReference(appointmentProvider.getProvider()));
participant.addType(role);

switch (appointmentProvider.getResponse()) {
case ACCEPTED:
return participant.setStatus(Appointment.ParticipationStatus.ACCEPTED);
case TENTATIVE:
return participant.setStatus(Appointment.ParticipationStatus.TENTATIVE);
case AWAITING:
return participant.setStatus(Appointment.ParticipationStatus.NEEDSACTION);
case REJECTED:
return participant.setStatus(Appointment.ParticipationStatus.DECLINED);
case CANCELLED:
return participant.setStatus(Appointment.ParticipationStatus.NULL);
}

return participant;
}

@Override
public AppointmentProvider toOpenmrsType(Appointment.AppointmentParticipantComponent appointmentParticipantComponent) {
return toOpenmrsType(new AppointmentProvider(), appointmentParticipantComponent);
}

@Override
public AppointmentProvider toOpenmrsType(AppointmentProvider appointmentProvider, Appointment.AppointmentParticipantComponent appointmentParticipantComponent) {
if (appointmentParticipantComponent == null) {
return appointmentProvider;
}
appointmentProvider.setProvider(practitionerDao.getProviderByUuid(getReferenceId(appointmentParticipantComponent.getActor())));
switch (appointmentParticipantComponent.getStatus()) {
case ACCEPTED:
appointmentProvider.setResponse(AppointmentProviderResponse.ACCEPTED);
case TENTATIVE:
appointmentProvider.setResponse(AppointmentProviderResponse.TENTATIVE);
case NEEDSACTION:
appointmentProvider.setResponse(AppointmentProviderResponse.AWAITING);
case DECLINED:
appointmentProvider.setResponse(AppointmentProviderResponse.REJECTED);
case NULL:
appointmentProvider.setResponse(AppointmentProviderResponse.CANCELLED);
}

return appointmentProvider;
}
}
Loading