Skip to content

Commit

Permalink
TRUNK-4133 - Implement discontinueOrder API in OrderService.
Browse files Browse the repository at this point in the history
TRUNK-4133 - Modify OrderService.saveOrder(Order order) to correctly handle discontinue orders

Minor documentation change

TRUNK-4133 - Ensure discontinue and discontinued orders have the same concept

TRUNK-4133 - Changes based on review comments.
Add annotations for junit tests.
Some extra documentation.
Remove unnecessary executeDataset calls in OrderServiceTest
Make concept for discontinuation a normal concept, not a numeric
Additional assert statements
  • Loading branch information
Vinay Venu authored and wluyima committed Jan 29, 2014
1 parent 73cb57c commit 4e98261
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 5 deletions.
20 changes: 20 additions & 0 deletions api/src/main/java/org/openmrs/Order.java
Expand Up @@ -529,4 +529,24 @@ public CareSetting getCareSetting() {
public void setCareSetting(CareSetting careSetting) {
this.careSetting = careSetting;
}

/**
* Creates a discontinuation order for this order, sets the previousOrder and action fields,
* note that the discontinuation order needs to be saved for the discontinuation to take effect
*
* @return the newly created order
* @since 1.10
* @should set previousOrder on new order
* @should set action to discontinue on new order
* @should set this care setting to new order
*/
public Order cloneForDiscontinuing() {
Order newOrder = new Order();
newOrder.setCareSetting(this.getCareSetting());
newOrder.setConcept(this.getConcept());
newOrder.setAction(Action.DISCONTINUE);
newOrder.setPreviousOrder(this);

return newOrder;
}
}
39 changes: 36 additions & 3 deletions api/src/main/java/org/openmrs/api/OrderService.java
Expand Up @@ -48,7 +48,10 @@ public interface OrderService extends OpenmrsService {
* @throws APIException
* @should not save order if order doesnt validate
* @should save discontinued reason non coded
*/
* @should discontinue existing active order if new order being saved with action to discontinue
* @should discontinue previousOrder if it is not already discontinued
* @should fail if concept in previous order does not match this concept
*/
@Authorized( { PrivilegeConstants.EDIT_ORDERS, PrivilegeConstants.ADD_ORDERS })
public Order saveOrder(Order order) throws APIException;

Expand Down Expand Up @@ -224,8 +227,8 @@ public <Ord extends Order> List<Ord> getActiveOrders(Patient patient, Class<Ord>
Date asOfDate);

/**
* Retrieve care setting by type
*
* Retrieve care setting
*
* @param careSettingId
* @return the care setting
* @since 1.10
Expand All @@ -241,4 +244,34 @@ public <Ord extends Order> List<Ord> getActiveOrders(Patient patient, Class<Ord>
* @should return the order frequency that matched the specified id
*/
public OrderFrequency getOrderFrequency(Integer orderFrequencyId);

/**
* Discontinues an order.
* Creates a new order that discontinues the orderToDiscontinue
*
* @param orderToDiscontinue
* @param reasonCoded
* @param discontinueDate
* @return the new order that discontinued orderToDiscontinue
* @throws APIException if the <code>action</code> of orderToDiscontinue is <code>Order.Action.DISCONTINUE</code>
* @since 1.10
* @should populate correct attributes on the discontinue and discontinued orders
* @should fail for a discontinue order
*/
public Order discontinueOrder(Order orderToDiscontinue, Concept reasonCoded, Date discontinueDate);

/**
* Discontinues an order.
* Creates a new order that discontinues the orderToDiscontinue.
*
* @param orderToDiscontinue
* @param reasonNonCoded
* @param discontinueDate
* @return the new order that discontinued orderToDiscontinue
* @throws APIException if the <code>action</code> of orderToDiscontinue is <code>Order.Action.DISCONTINUE</code>
* @since 1.10
* @should populate correct attributes on the discontinue and discontinued orders
* @should fail for a discontinue order
*/
public Order discontinueOrder(Order orderToDiscontinue, String reasonNonCoded, Date discontinueDate);
}
82 changes: 82 additions & 0 deletions api/src/main/java/org/openmrs/api/impl/OrderServiceImpl.java
Expand Up @@ -69,6 +69,7 @@ public void setOrderDAO(OrderDAO dao) {
*/
public Order saveOrder(Order order) throws APIException {
if (order.getOrderId() == null) {
discontinueExistingOrdersIfRequired(order);
//TODO call module registered order number generators
//and if there is none, use the default below
try {
Expand All @@ -83,6 +84,46 @@ public Order saveOrder(Order order) throws APIException {

return dao.saveOrder(order);
}

/**
* If this is a discontinue order, ensure that the previous order is discontinued.
* If a previousOrder is present, then ensure this is discontinued.
* If no previousOrder is present, then try to find a previousOrder and discontinue it.
* If cannot find a previousOrder, throw exception
*
* @param order
*/
private void discontinueExistingOrdersIfRequired(Order order) {
//Ignore and return if this is not an order to discontinue
if (!Order.Action.DISCONTINUE.equals(order.getAction()))
return;

//Discontinue previousOrder if it is not already
Order previousOrder = order.getPreviousOrder();
if (previousOrder != null) {
if (!previousOrder.getConcept().equals(order.getConcept())) {

This comment has been minimized.

Copy link
@wluyima

wluyima Jan 30, 2014

Member

Am starting to think we need to improve this if this is a drug order, we need to check for the order with the same drug and not just the generic concept unless drug is null

throw new APIException("Concept of previous order and this order should be the same");
}

if (previousOrder.getDateStopped() == null) {
discontinue(previousOrder, order.getStartDate());
}
return;
}

//Discontinue the first found order corresponding to this DC order.
List<? extends Order> orders = getActiveOrders(order.getPatient(), order.getClass(), order.getCareSetting(), null);
for (Order activeOrder : orders) {
if (activeOrder.getConcept().equals(order.getConcept())) {

This comment has been minimized.

Copy link
@wluyima

wluyima Jan 30, 2014

Member

Same here, in case of drug orders we need to check for the order with the same drug and not just the generic concept unless drug is null, not so @djazayeri and @bmamlin

This comment has been minimized.

Copy link
@djazayeri

djazayeri Jan 30, 2014

Member

You are correct. I believe that a DC order to discontinue a DrugOrder needs to itself be a DrugOrder. So the cloneForDiscontinuation method above needs to be in Order, but be overridden in the DrugOrder subclass.

order.setPreviousOrder(activeOrder);
discontinue(activeOrder, order.getStartDate());
return;
}
}

throw new APIException("Could not find an active order with the concept " + order.getConcept()
+ " to discontinue. ");
}

/**
* @see org.openmrs.api.OrderService#purgeOrder(org.openmrs.Order)
Expand Down Expand Up @@ -272,4 +313,45 @@ public CareSetting getCareSetting(Integer careSettingId) {
public OrderFrequency getOrderFrequency(Integer orderFrequencyId) {
return dao.getOrderFrequency(orderFrequencyId);
}

/**
* @see org.openmrs.api.OrderService#discontinueOrder(org.openmrs.Order, org.openmrs.Concept, java.util.Date)
*/
@Override
public Order discontinueOrder(Order orderToDiscontinue, Concept reasonCoded, Date discontinueDate) {
discontinue(orderToDiscontinue, discontinueDate);

Order newOrder = orderToDiscontinue.cloneForDiscontinuing();
newOrder.setDiscontinuedReason(reasonCoded);

return saveOrder(newOrder);
}

/**
* @see org.openmrs.api.OrderService#discontinueOrder(org.openmrs.Order, String, java.util.Date)
*/
@Override
public Order discontinueOrder(Order orderToDiscontinue, String reasonNonCoded, Date discontinueDate) {
discontinue(orderToDiscontinue, discontinueDate);

Order newOrder = orderToDiscontinue.cloneForDiscontinuing();
newOrder.setDiscontinuedReasonNonCoded(reasonNonCoded);

return saveOrder(newOrder);
}

/**
* Make necessary checks, set necessary fields for discontinuing <code>orderToDiscontinue</code> and save.
*
* @param orderToDiscontinue
* @param discontinueDate
*/
private void discontinue(Order orderToDiscontinue, Date discontinueDate) {
if (orderToDiscontinue.getAction().equals(Order.Action.DISCONTINUE)) {
throw new APIException("An order with action " + Order.Action.DISCONTINUE + " cannot be discontinued. ");
}

orderToDiscontinue.setDateStopped(discontinueDate);
saveOrder(orderToDiscontinue);
}
}
48 changes: 47 additions & 1 deletion api/src/test/java/org/openmrs/OrderTest.java
Expand Up @@ -14,10 +14,13 @@
package org.openmrs;

import org.junit.Test;
import org.openmrs.test.Verifies;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.UUID;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

Expand Down Expand Up @@ -90,5 +93,48 @@ public void shouldIsCurrent() throws Exception {
assertTrue("should be current between startDate and dateStopped", o.isCurrent(ymd.parse("2007-10-26")));
assertFalse("shouldn't be current after dateStopped", o.isCurrent(ymd.parse("2007-11-26")));
}


/**
* @see {@link Order#cloneForDiscontinuing()}
*/
@Test
@Verifies(value = "set previousOrder on new order", method = "cloneForDiscontinuing(Order)")
public void cloneForDiscontinuing_shouldSetPreviousOrderOnNewOrder() {
Order anOrder = new Order();
anOrder.setUuid(UUID.randomUUID().toString());

Order orderThatCanDiscontinueTheOrder = anOrder.cloneForDiscontinuing();

assertEquals("should set previous order to anOrder", orderThatCanDiscontinueTheOrder.getPreviousOrder(), anOrder);
}

/**
* @see {@link Order#cloneForDiscontinuing()}
*/
@Test
@Verifies(value = "set action to discontinue on new order", method = "cloneForDiscontinuing(Order)")
public void cloneForDiscontinuing_shouldSetActionToDiscontinueOnNewOrder() {
Order anOrder = new Order();
anOrder.setUuid(UUID.randomUUID().toString());

Order orderThatCanDiscontinueTheOrder = anOrder.cloneForDiscontinuing();

assertEquals("should set new order action to new", orderThatCanDiscontinueTheOrder.getAction(),
Order.Action.DISCONTINUE);
}

/**
* @see {@link Order#cloneForDiscontinuing()}
*/
@Test
@Verifies(value = "set this care setting to new order", method = "cloneForDiscontinuing(Order)")
public void cloneForDiscontinuing_shouldSetThisCareSettingToNewOrder() {
Order anOrder = new Order();
CareSetting careSetting = new CareSetting();
anOrder.setCareSetting(careSetting);

Order orderThatCanDiscontinueTheOrder = anOrder.cloneForDiscontinuing();

assertEquals(anOrder.getCareSetting(), orderThatCanDiscontinueTheOrder.getCareSetting());
}
}

0 comments on commit 4e98261

Please sign in to comment.