Adding "Order Status" to Orders

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 https://www.hl7.org/fhir/valueset-diagnostic-report-status.html

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.

And https://www.hl7.org/fhir/valueset-nutrition-request-status.html

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:

https://wiki.openmrs.org/display/RES/2018-05-07+Design+Forum

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.

Thoughts?

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.

@wyclif… right, but you can’t do something like this:

order.setDateStopped(new Date())
orderService.saveOrder(order)

… because the saveOrder method explicitly fails when trying to operate on an order already being persisted:

@darius there’s not a great analogy for stopOrder… there’s a utility method for changing the stopOrder, but it’s private and it looks like there’s no way to just individually change the stop date… the stopOrder method is only called via other workflow methods like discontinueOrder, etc…

I could make something called "updateOrderFulfillerStatus(Order, OrderStatus, String comment), but our main use case will be to access/update this property RESTfully… so I guess I’d need make a new endpoint for this… seems like it would be simpler/cleaner to just create a new updateOrder method that could, in the end, could additionally be used for any other fields we add that we want to be mutable.

Take care, Mark

Peeking at the current code I think the addition that’s inline with the current design, would be to add a new method like you suggest (e.g. updateOrderFulfillerStatus), which behind the scenes calls saveOrderInternal.

Personally, for REST I like the idea of making this appear like a subresource of Order (because it’s meant to be set completely independently of the order itself, e.g. you shouldn’t set it at order creation time).

Is that method updateOrderFulfillerStatus supposed to have a check implemented that only the Order was changed in regards to the OrderStatus and not any other attribute changed it values compared to the previous version @mogoodrich @darius ?

Otherwise, this feature could be used to also change other attributes that are supposed to not change.

If this is specified I would be able to implement it.