Adding "Order Status" to Orders

Continuing the discussion from "Order Tracking" OWA/module:

I just started writing this and then @burke posted a nice summary on the other thread so I’ll repost that here and add some more details:

Introduce Order.fulfillerStatus now, enun with possible statuses:

  • received - order fulfiller has received the request
  • exception - an error or exception occurred during processing
  • completed - the request has been completed by fulfiller

Design details:

  • Fully mutable field (Question: should it require order to be activated and not expired/stopped? or do we allow back-entry)
  • in Java: order.setFulfillerStatus(xyz); orderService.saveOrder(order);
  • in REST: POST …/order/uuid {fulfillerStatus:“received”}

Consider also introducing Order.status (aligning with FHIR status fields), enum with possible states:

  • draft - unsigned, work in progress
  • active - order that may be acted upon
  • completed - all activity related to the request has been completed
  • stopped - request terminated

Design details (this needs more fleshing out):

  • Don’t allow direct access to modify “status” but rather API with logic:

  • Status “Draft” only allowed if “dateActivated” is null; if status is “Draft” and “dateActivated” is set, status is changed to “Active”; interceptor needs to be changed so that draft orders are completely mutable

  • “Active” status should be set based on current logic defined in isActive

  • “Completed” (only allow to set from active status); add an OrderService.completeOrder(Order, Date) method analogous to OrderService.discontinueOrder(…)

Some additional thoughts during the discussion:

  • We haven’t yet modeled how we would handle orders needing cosign.

  • Verbal orders will be deferred. Would be active and probably have a separate property to track authorizing signature.

  • We would not plan on supporting on hold or suspended (risk of medical errors, encourage stop and re-write instead).

  • We would not plan on implementing FHIR’s cancelled or entered in error statuses (close enough to OpenMRS voiding).

  • We wouldn’t support unknown status (would use null for this if needed later).

Rereading this, I’m still not convinced we need to add “status” as a discreet property of Order (at least not yet)… draft, active, and stopped can all currently be derived based on the dateActivated and dateStopped properties on Order. The only new functionality here would be the “completed” status.

I’ve created a ticket for adding the “fulfillerStatus” field to order:

One question… are there any other states we want to add besides:

  • received
  • completed
  • exception

Should we look at existing dispensing or LIMS systems to see what types of statuses they may return?

Take care, Mark

Just thinking about the workflow from the EMR perspective, the only other think I might consider is “processing” (or “in_progress”), in case the fulfiller wants to distinguish between “received” and this.

(Sounds like a nice-to-have more than a requirement though.)

Agreed… it’s actually more in line with the status we need anyway… I’ve added it to the enum.

Poking around FHIR a bit more, see

registered	Registered	The existence of the report is registered, but there is nothing yet available.
partial	Partial	This is a partial (e.g. initial, interim or preliminary) report: data in the report may be incomplete or unverified.
  preliminary	Preliminary	Verified early results are available, but not all results are final.
final	Final	The report is complete and verified by an authorized person.
amended	Amended	Subsequent to being final, the report has been modified. This includes any change in the results, diagnosis, narrative text, or other content of a report that has been issued.
  corrected	Corrected	Subsequent to being final, the report has been modified to correct an error in the report or referenced results.
  appended	Appended	Subsequent to being final, the report has been modified by adding new content. The existing content is unchanged.
cancelled	Cancelled	The report is unavailable because the measurement was not started or not completed (also sometimes called "aborted").
entered-in-error	Entered in Error	The report has been withdrawn following a previous final release. This electronic record should never have existed, though it is possible that real-world decisions were based on it. (If real-world activity has occurred, the status should be "cancelled" rather than "entered-in-error".)
unknown	Unknown	The authoring system does not know which of the status values currently applies for this request. Note: This concept is not to be used for "other" - one of the listed statuses is presumed to apply, it's just not known which one.


Code	Display	Definition
proposed	Proposed	The request has been proposed.
draft	Draft	The request is in preliminary form prior to being sent.
planned	Planned	The request has been planned.
requested	Requested	The request has been placed.
active	Active	The request is 'actionable', but not all actions that are implied by it have occurred yet.
on-hold	On-Hold	Actions implied by the request have been temporarily halted, but are expected to continue later. May also be called "suspended".
completed	Completed	All actions that are implied by the order have occurred and no continuation is planned (this will rarely be made explicit).
cancelled	Cancelled	The request has been withdrawn and is no longer actionable.
entered-in-error	Entered in Error	The request was entered in error and voided.

We probably want to support the equivalent of “preliminary” from lab requests and “on-hold” from nutrition.

In our nomenclature preliminary might be “partially_completed”. Or we should consider if we can align our nomenclature closer to something in FHIR.

I had looked at some of these as well… the “final” and “amended” are actually statuses we use in our PACS integration and seem pretty standard, but seemed to specific for a field on a generic order.

The “nutrition” status is a “request” status and so has fields we definitely wouldn’t want to include in a fulfiller message, like draft, planned, etc…

“On-hold” and “partially-completedly” do seem reasonable though, though I wonder if “on-hold” is good enough, or we want to have both?

I think the partially-completed use case is more important, so I wouldn’t coalesce that into “on hold”.

(On Hold is really more of an internal filler process that’s not really relevant in the EMR, whereas Preliminary or Partial results is something that provides clinical value in the EMR, i.e. telling the doctor they can go look something up in the chart.)

The nutrition request statuses are order (request) statuses – in the purview of placer, not filler.

The diagnostic report status is closer to the list relevant for a filler to manage.

What you want for filler status is closer to the diagnostic report and obs.status. Another example is our prior plans for handling obs exceptions.

As you’ve surmised, we should probably be aligning with FHIR’s ObservationStatus. But those apply to the result, so aren’t a perfect fit for the request.

  • registered == received
  • preliminary: more relevant for the result than the request, but could represent partially fulfilled
  • final == completed
  • cancelled: could lump exceptions into this, but I’d prefer to distinguish cancelled vs a problem occurred

It would be nice to have an “in process” to distinguish between received and actually being worked on.

Hello everyone,

I just started working on issue TRUNK-5400 and I am wondering about a few things. Perhaps @mogoodrich or some other people discussing in this thread can maybe give me a hand.

In the ticket I am not reading anything about the business logic that should be applied. Is there any logical sequence or forbidden transition in the context of the fulfillerStatus. To me it looks like just for Order.status this has been further defined:

“Completed” (only allow to set from active status); add an OrderService.completeOrder(Order, Date) method analogous to OrderService.discontinueOrder(…)

So it is correct to just create a getter() and setter() method for fulfillerStatus without any further more complex logic or is there any logic that should be applied?

@fruether just a getter and setter is fine… but there’s another bigger issue here.

The thought was that FulfillerStatus and FulfillerComment should be mutable… ie, you should be able to change these without having to clone and create an order. However, the API enforces that you can’t re-save an existing order:

Did we have a way or strategy to work around this? I feel like we must have discussed this on the design call, because I was aware that it would likely be an issue, but I can’t find any notes and/or remember it:

Am I forgetting something obvious here? :slight_smile: @darius @mseaton @burke

@mogoodrich Thanks for the quick and detailed response.

While testing I noticed that the order was immutable but I did not really remembered that this behaviour should be changed…although it was described in the ticket

Well I can’t really decide what design to choose. Is there a chance that this will be discussed and decided soon? Perhaps till the end of the month.

Anyways, an option would be to only allow changes of the status. This would mean that only these attributes can be changed in an existing order. All other changes would still lead into a fail. Would that be a way to go?

Yes, only the fulfiller status and fufiller comment should become mutable… all other changes would still lead to fail. I don’t know if there’s an easy way to do this, however.

Take care, Mark

The failOnExistingOrder method is pretty trivial right now:

private void failOnExistingOrder(Order order) {
	if (order.getOrderId() != null) {
		throw new UnchangeableObjectException("Order.cannot.edit.existing");

I see the following option

In case it is not null I will request the database to show me the object that was saved under this ID. Then I compare both objects by an equalExceptState method, which requests that all attributes are equal except for fulfillerStatus

@mogoodrich How would you like this idea?

Another option would be to mark objects that are persisted by a local attribute or in a global hasmap. In case it is persisted the set() methods will not work any more. Except for the methods that are changing the state. That way an object would not be able to be changed

I would prefer the earlier approach. Assuming requesting the database is not a thing that should be avoided

I haven’t fully followed this conversation, but are you looking for this?

i.e. just add another entry to MUTABLE_PROPERTY_NAMES?

thank @darius… that is definitely something we’d have to change…

the issue is that on top of that the saveOrder method fails if you try to change an existing order:

@fruether I would be up for just modifying the failOnExistingOrder as you suggest, but, beyond that the saveOrder method has a lot of other existing business logic that assumes that an order is “new” and I suspect we’d run into other issues.

@darius @burke what do you think about adding a updateOrder(Order order) service method that just calls dao.saveOrder(order) without any of the business logic? We could document that this method should only be used to modify the mutable properties (and will fail hard if you do otherwise).

The Order resource in REST web services would have to be modified to use this service method in the “update” use case, but this seems doable.


Take care, Mark

If you want a field to be mutable you just add it to this array

I would suggest looking at how dateStopped is implemented, and do something analogous.

(@wyclif could you give a more detailed pointer to something which shows how to extend your design with this new property?)

It’s not much, if you add a new property status to Order class and want it to be mutable, all that needs to be done is add it to this array, if you look at that array, you will notice dateStopped is actually one of them.