Skip to content

Order stop/discontinue does not fire a *ServiceEvent for the stopped order (event-driven consumers see it as still active) #6197

Description

@dkayiwa

Summary

Stopping an order — via OrderService.discontinueOrder(...), or by saving a DISCONTINUE-action order, or auto-expiry — updates the original order's dateStopped / autoExpireDate, but fires no *ServiceEvent for that original order. Event-driven consumers therefore never learn that the order was stopped: the order continues to appear active. (The new discontinuation order itself is evented when created through saveOrder; the gap is specifically the state change on the order being stopped.)

Environment

Root cause

OrderServiceImpl.discontinueOrder(...) stops the previous order via a private stopOrder(...)saveOrderInternal(...) path, and saveOrder(...) does the same when it processes a DISCONTINUE order. Bytecode (2.9.0-SNAPSHOT):

OrderServiceImpl.discontinueOrder(Order, Concept, Date, Provider, Encounter):
   invokespecial  stopOrder:(Lorg/openmrs/Order;Ljava/util/Date;Z)V         // private — stops the original
   invokespecial  saveOrderInternal:(...)Lorg/openmrs/Order;                 // private — persists, no event

Because the stop is applied through the private saveOrderInternal (not the public, proxied saveOrder), the #6084 OpenmrsServiceEventAdvice never intercepts it → no SaveServiceEvent for the stopped order. discontinueOrder itself also does not match the advice's method-name pattern (save*/void*/unvoid*/retire*/unretire*/purge*).

Reproduction

  1. Create a test/drug order T (it fires SaveServiceEvent → consumer indexes it as active).
  2. Discontinue it (create a DISCONTINUE order whose previousOrder is T, or call discontinueOrder).
  3. Observe in core: T.dateStopped is now set. But no event fired for T.

Verified on the standalone: after discontinuing, the original order's dateStopped was populated in core, yet a consumer indexing dateStopped still showed the order with no stop date (i.e. active). The discontinuation order was indexed (it goes through saveOrder); only the original's state change was missed.

Impact

Any event-driven consumer that reflects order state (active-vs-stopped, dateStopped, autoExpireDate) goes stale on discontinue/auto-expire — e.g. a query for "active medications/orders" would still return a discontinued order. This is the same root pattern as #6194: a service operation mutates an indexed record without emitting a corresponding event.

Suggested fix

When an order is stopped, fire a SaveServiceEvent for the stopped order — e.g. route the stop through the public saveOrder (so the advice fires) or publish the event explicitly from stopOrder. Optionally also have the advice recognise discontinueOrder.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions