Skip to content

Commit

Permalink
Trunk-4444 Validate order overlap with scheduled date
Browse files Browse the repository at this point in the history
Trunk-4444 Implementing feedback on earlier commit

Trunk-4444 Adding void order check while checking overlapping schedule of orders

Trunk-4444 Moving checkoverlap method to OrderUtil
  • Loading branch information
Miss Beens authored and wluyima committed Aug 20, 2014
1 parent 64eec76 commit 7c1f690
Show file tree
Hide file tree
Showing 7 changed files with 387 additions and 3 deletions.
23 changes: 23 additions & 0 deletions api/src/main/java/org/openmrs/Order.java
Original file line number Diff line number Diff line change
Expand Up @@ -657,4 +657,27 @@ public boolean hasSameOrderableAs(Order otherOrder) {
}
return OpenmrsUtil.nullSafeEquals(this.getConcept(), otherOrder.getConcept());
}

/**
* A convenience method to return period start date for order.
* @since 1.10
*
* @should return scheduledDate if Urgency is Scheduled
* @should return dateActivated if Urgency is not Scheduled
*/
public Date getEffectiveStartDate() {
return this.urgency == Urgency.ON_SCHEDULED_DATE ? this.getScheduledDate() : this.getDateActivated();
}

/**
* A convenience method to return period end date for order.
* @since 1.10
*
* @should return dateStopped if dateStopped is not null
* @should return autoExpireDate if dateStopped is null
*/
public Date getEffectiveStopDate() {
return this.getDateStopped() != null ? this.getDateStopped() : this.getAutoExpireDate();
}

}
8 changes: 5 additions & 3 deletions api/src/main/java/org/openmrs/api/impl/OrderServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.openmrs.api.OrderService;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.OrderDAO;
import org.openmrs.order.OrderUtil;
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.OpenmrsUtil;
import org.springframework.transaction.annotation.Propagation;
Expand Down Expand Up @@ -93,7 +94,7 @@ public synchronized Order saveOrder(Order order, OrderContext orderContext) thro
if (order.getDateActivated() == null) {
order.setDateActivated(new Date());
}
//Reject if there is an active order for the same orderable
//Reject if there is an active order for the same orderable with overlapping schedule
boolean isDrugOrder = DrugOrder.class.isAssignableFrom(getActualType(order));
Concept concept = order.getConcept();
if (concept == null && isDrugOrder) {
Expand All @@ -110,8 +111,9 @@ public synchronized Order saveOrder(Order order, OrderContext orderContext) thro
if (!isDiscontinueOrReviseOrder(order)) {
List<Order> activeOrders = getActiveOrders(order.getPatient(), null, order.getCareSetting(), null);
for (Order activeOrder : activeOrders) {
if (order.hasSameOrderableAs(activeOrder)) {
throw new APIException("Cannot have more than one active order for the same orderable and care setting");
if (order.hasSameOrderableAs(activeOrder) && OrderUtil.checkScheduleOverlap(order, activeOrder)) {
throw new APIException(
"Cannot have more than one active order for the same orderable and care setting at same time");
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions api/src/main/java/org/openmrs/order/OrderUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Order;
import org.openmrs.OrderType;

/**
Expand Down Expand Up @@ -53,4 +54,41 @@ public static boolean isType(OrderType orderType1, OrderType orderType2) {
return false;
}

/**
* Checks whether schedule of this order overlaps with schedule of other order
*
* @since 1.10
* @param order1, order2 orders to match
* @should return false if any of the orders is voided
* @should return true if order1 and order2 do not have end date
* @should return true if order1 and order2 have same dates
* @should return false if order1 ends before order2 starts
* @should return false if order1 ends when order2 starts
* @should return false if order1 starts after order2
* @should return false if order1 starts when order2 ends
* @should return true if order1 stops after the order2 has already been activated
* @should return true if order1 starts when the order2 is active
* @should return true if order1 starts before order2 and ends after order2
*/
public static boolean checkScheduleOverlap(Order order1, Order order2) {
if (order1.getVoided() == true || order2.getVoided() == true) {
return false;
}
if (order2.getEffectiveStopDate() == null && order1.getEffectiveStopDate() == null) {
return true;
}

if (order2.getEffectiveStopDate() == null) {
return order1.getEffectiveStopDate().after(order2.getEffectiveStartDate());
}

if (order1.getEffectiveStopDate() == null) {
return order1.getEffectiveStartDate().after(order2.getEffectiveStartDate())
&& order1.getEffectiveStartDate().before(order2.getEffectiveStopDate());
}

return order1.getEffectiveStartDate().before(order2.getEffectiveStopDate())
&& order1.getEffectiveStopDate().after(order2.getEffectiveStartDate());
}

}
58 changes: 58 additions & 0 deletions api/src/test/java/org/openmrs/OrderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.List;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.junit.Test;
import org.openmrs.order.OrderUtilTest;
import org.openmrs.util.Reflect;
Expand Down Expand Up @@ -294,4 +295,61 @@ public void hasSameOrderableAs_shouldReturnTrueIfTheOrdersHaveTheSameConcept() t
otherOrder.setConcept(concept);
assertTrue(order.hasSameOrderableAs(otherOrder));
}

/**
* @verifies return scheduledDate if Urgency is Scheduled
* @see Order#getEffectiveStartDate
*/
@Test
public void getPeriodStartDate_shouldReturnScheduledDateWhenUrgencyIsScheduled() throws Exception {
Order order = new Order();
Date date = DateUtils.addDays(new Date(), 2);
order.setUrgency(Order.Urgency.ON_SCHEDULED_DATE);
order.setScheduledDate(date);
order.setDateActivated(new Date());

assertEquals(date, order.getEffectiveStartDate());
}

/**
* @verifies return dateActivated if Urgency is not Scheduled
* @see Order#getEffectiveStartDate
*/
@Test
public void getPeriodStartDate_shouldReturnDateActivatedWhenUrgencyIsNotScheduled() throws Exception {
Order order = new Order();
Date date = new Date();
order.setScheduledDate(DateUtils.addDays(date, 2));
order.setDateActivated(date);

assertEquals(date, order.getEffectiveStartDate());
}

/**
* @verifies return dateStopped if dateStopped is not null
* @see Order#getEffectiveStopDate
*/
@Test
public void getPeriodEndDate_shouldReturnDateStoppedWhenPresent() throws Exception {
Order order = new Order();
Date date = DateUtils.addDays(new Date(), 4);
OrderUtilTest.setDateStopped(order, date);
order.setAutoExpireDate(new Date());

assertEquals(date, order.getEffectiveStopDate());
}

/**
* @verifies return autoExpireDate if dateStopped is null
* @see Order#getEffectiveStopDate
*/
@Test
public void getPeriodEndDate_shouldReturnAutoExpireDateWhenDateStoppedIsNull() throws Exception {
Order order = new Order();
Date date = DateUtils.addDays(new Date(), 4);
order.setAutoExpireDate(date);

assertEquals(date, order.getEffectiveStopDate());
}

}
34 changes: 34 additions & 0 deletions api/src/test/java/org/openmrs/api/OrderServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.Locale;
import java.util.Set;

import org.apache.commons.lang3.time.DateUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -1547,6 +1548,39 @@ public void saveOrder_shouldNotChangeTheAutoExpireDateIfItHasATimeComponent() th
assertEquals(autoExpireDate, order.getAutoExpireDate());
}

/**
* @verifies pass if an active drug order for the same drug formulation exists beyond new order's schedule
* @see OrderService#saveOrder(org.openmrs.Order, OrderContext)
*/
@Test
public void saveOrder_shouldPassIfAnActiveDrugOrderForTheSameDrugFormulationExistsBeyondSchedule() throws Exception {
executeDataSet("org/openmrs/api/include/OrderServiceTest-DrugOrders.xml");
final Patient patient = patientService.getPatient(2);

DrugOrder existingOrder = (DrugOrder) orderService.getOrder(2000);
int initialActiveOrderCount = orderService.getActiveOrders(patient, null, null, null).size();

//New Drug order
DrugOrder order = new DrugOrder();
order.setPatient(patient);
order.setDrug(existingOrder.getDrug());
order.setEncounter(encounterService.getEncounter(6));
order.setOrderer(providerService.getProvider(1));
order.setCareSetting(existingOrder.getCareSetting());
order.setDosingType(DrugOrder.DosingType.FREE_TEXT);
order.setDosingInstructions("2 for 10 days");
order.setQuantity(10.0);
order.setQuantityUnits(conceptService.getConcept(51));
order.setNumRefills(2);
order.setUrgency(Order.Urgency.ON_SCHEDULED_DATE);

order.setScheduledDate(DateUtils.addDays(existingOrder.getDateStopped(), 1));

orderService.saveOrder(order, null);
List<Order> activeOrders = orderService.getActiveOrders(patient, null, null, null);
assertEquals(++initialActiveOrderCount, activeOrders.size());
}

/**
* @verifies find order type object given valid id
* @see OrderService#getOrderType(Integer)
Expand Down

0 comments on commit 7c1f690

Please sign in to comment.