difference voided and discontinued order

Hello :slight_smile:

I need a little help understanding the differences in

voided and discontinued

in the context of Order.

I understand that when discontinuing an order, a new discontinuation order is created with the previous one attached under previousOrder and the dateStopped is set.

With voiding an order thats not happening is it? I think only voided=true and voidedBy, dateVoided are set.

But why do both exist? They do seem pretty similar. Is it that with discontinuing you can pass a concept as reason?

1 Like

Discontinuing an order is an action that constitutes an order from a physician, so the API creates an Order instance to represent this action because there might be need to communicate the discontinuation to downstream system that might have acted on the order. On the other hand voiding an order is not an orderable action really that comes from a physician but rather something a data entry clerk might do to cancel something they should probably never have entered into the system which is the equivalent of deleting it from the system and doesn’t probably need to be communicated to downstream systems. So the API has to distinguish between these two notions i.e where a physician is saying stop taking this medication Vs a data entry clerk cancelling a bad entry that should never have happened.

2 Likes

Just what I needed, very clear thanks!!

I can see this distinction in the required privileges in the OrderService (void needs delete, discontinue needs add and edit privilege).

For the communication to other systems: if order creation leads to an hl7 order message to an other system, voiding should also be communicated.

The good thing is that your statement started with 'if… ’ because the API doesn’t actually have any feature that acts on orders e.g sending an hl7 message to another system, but I would Imagine that anyone that writes a module or another application that acts on orders would take care of doing the right thing based on whether an Order was discontinued Vs voided, it’s up to them to make sure that both actions are communicated and for sure they’d require different action paths to be taken but that’s not for the order entry API to worry about as long as it makes a distinction between the two in the way it represents them under the hood.

Hi @wyclif,

related to this topic I ran into following “issue”:

On openmrs 2.0.x latest

I created a RadiologyOrder (is a TestOrder which is an Order) with Urgency ON_SCHEDULED_DATE and a date in the future. So this Order is not voided, not discontinued and its scheduled date in the future; I checked that this is true assertFalse(order.isActive())

I then try to discontinue it with orderService.discontinueOrder()

And get the following error message:

“Cannot discontinue an order that is already stopped, expired or voided”

Now my questions:

  1. why cant I discontinue an order that is not yet active?
  2. I assume this is intended, so I guess in this case cancellation of such an order would be done via the orderService.voidOrder(Order order, String voidReason) operation, am I right?
  3. orderService.voidOrder(Order order, String voidReason) does not do any checking (active, already voided, discontinued, …) therefore the separate PrivilegeConstants.DELETE_ORDERS since its a serious operation.
  4. the message seems a bit misleading since in this case the order is in non of the 3 states mentioned, it is not yet active. What do you say, shall we refine the message?

Thanks a lot for your clarifications! This will serve others well in the future :slight_smile:

A scheduled order for the future should be considered by the API as an active order and assertFalse(order.isActive()) should fail for it, determining if an order is active or not is purely based on dateActivated, dateStopped and expiryDate, so it means you didn’t set one of these 3 properly.

And how come I can discontinue an order that I create the same way (set the same fields) with the only difference being scheduledDate null and urgency = Routine/Emergency. I just don’t get the reasoning behind the design of the behavior.

Because scheduleDate is only used when urgency is set to ON_SCHEDULED_DATE, for other urgency values it is ignored

Just to clarify things, when we first refactored the Order entry API in 1.10, a scheduled order was considered as active because Order.isActive called Order.isFuture() which was deprecated anways, it didn’t use scheduled date field and this behavior is true in 1.11.x code which I was looking at all along when I first replied to this post. In 2.0.x and master, isActive was changed to call isStarted() since isFuture was removed which seems wrong because isActive() now returns false for a scheduled order.

So yes @teleivo you’re right that there is an issue here. I personally do believe a scheduled order should be considered as active but not started and one should be able to discontinue it, we probably need to fix this before we release 2.0.x.

@maany I think this might be a blocker to 2.0 release

1 Like

Wow, thanks for the clarification!! Totally agree! I also feel that a scheduled order should be considered active but not started. I could contribute if you make this a jira issue

@darius and others do you agree that a scheduled order should be considered as active? It would be nice if this fix makes it into Platform 2.0

We should be careful about the word “active” and try to avoid using it, because it’s confusing. And “active” should have no bearing on whether the order can be discontinued.

In the real-time API you should be able to discontinue any order that is (a) activated*, and (b) not expired, stopped, or voided. (Via the retrospective API you should also be allowed to discontinue an order that is expired today, as long as you discontinue it before its autoexpire date.)

Note that in our API today, every order is always activated. In some future version of the API we will introduce draft orders, and when we do that you shouldn’t be able to discontinue a draft order (i.e. a non-activated order).

So, a scheduled order should be considered activated (everything should be considered activated), and thus you should be able to discontinue/stop it.

I think these lines are wrong: https://github.com/openmrs/openmrs-core/blob/2.0.0-beta/api/src/main/java/org/openmrs/api/impl/OrderServiceImpl.java#L752-L754

and what about this then

isnt this also wrong? since a scheduled order isActive() = false

That is an example of why “active” is a confusing term, and we should try to avoid it.

“Active” means (intuitively to me) “being applied to the patient now”

“Activated” means approximately “signed, and should be applied to the patient as instructed”.

An order that is signed, recorded, and set to start next week is activated but not active.

So, I believe that implementation of isActive is correct, for my intuitive understanding of the word active, which is not the same thing as activated.

Personally I would love it if we could deprecate this isActive method and replace it with one that behaves the same way but is named clearly so that it won’t be confused with “activated”. I haven’t been able to come up with a good name though. Maybe isStartedAndStillActive. :slight_smile:

1 Like

with your explanation the behavior totally makes sense to me.

what about simply renaming isActive() => isActiveAndStarted() I think this would suffice to tell the user of the api that it takes both “active” and “started” into account with respect to now or the given date.

would then also another convenience method make sense that checks if an order is:

(a) activated*, and (b) not expired, stopped, or voided.

?

so this can be used in https://github.com/openmrs/openmrs-core/blob/2.0.0-beta/api/src/main/java/org/openmrs/api/impl/OrderServiceImpl.java#L752-L754

and it would also be very handy for users of the order entry api to check whether the order can be discontinued (this way I can for ex. hide discontinuation form in my order form is this method returns false).

name proposal: isActivated not sure if that would be clear enough :yum:

I think you may have said “active” when you mean “activated” :slight_smile:

The current isActive() method is checking: started && not expired && not stopped. So I don’t think it works to rename this to isActiveAndStarted(). How about renaming it to isStartedAndStillActive() or isStartedAndNotFinished()?

I would think that “isActivated” is the getter for the activated property. So I would think the convenience method you’re describing at the end should be isActivatedAndStillActive() or isActivatedAndNotFinished()

agree :slight_smile:

I like isStartedAndNotFinished() and isActivatedAndNotFinished() seems good to me.

is this something that should be discussed in a design call? Or how should we proceed? I am interested in implementing this.

Since I was on vacation and only joined this conversation late… What OpenMRS versions are we talking about here?

Of the top of my head i would think these method changes are things we should do in platform 2.0.

The specific bugfix of course can be backported further…

-Darius (by phone)

yes I am talking about platform 2.0

I prefer renaming isActive to isActivated, @darius there is no activated field on Order, I think you’re referring to dateActivated. I agree that isActive is not intuitive enough, it actually sounds to imply isStarted()