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.
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.)
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.
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:
@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.
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
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
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.
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.