Change Requisition adjustment reasons to come from Stock Service

Description

The Requisition Service and UI should be converted to use the reason endpoints in the Stock Management service, not the ones in ReferenceData (which will be deprecated in a subsequent ticket and eventually removed). This ticket is about the UI, the Snapshot in Requisition, and Requisition calling Stock Management for Reasons. The data migration for this is split into a separate ticket OLMIS-2830.

Background
See https://openlmis.atlassian.net/wiki/display/OP/Connecting+Stock+Management+and+Requisition+Services

Snapshot Approach
When a Requisition is initiated, its data structure needs to 'snapshot' the list of possible adjustment reasons for that program and facility type at the time it was initiated. The requisition service and its DTOs will need to change to grab the list of possible reasons from the Stock Service API and store that inside the Requisition object as a static 'snapshot'. The UI will need to change to use that new part of the Requisition object as its source for the list of reasons, NOT by making a UI call to fetch the list of reasons from another REST API (used to be in referencedata; we are migrating it to stockmanagement). This snapshot approach is critical for offline usage of the Requisition form.

Edge Cases

  • We need to test out Requisitions that were pre-existing before this new feature, including Requisitions that may be cached in a local UI and also users who are using an old Cached version of the OpenLMIS UI app:

    • Here is the Happy Path: Requisition A was initiated before this feature. It did not have a snapshot of reasons until the Requisition service was upgraded and the data migration () added the Snapshot list of reasons. After this upgrade, a user sits down to work on Requisition A. They open a new browser window and use the new Requisition UI. Their UI will try to load Requisition A from the Requisition Service API. The Requisition will include the valid snapshot list of reasons and send that to the client browser. That snapshot was created during the data migration in OLMIS-2830. The user will make edits using the new Reason list snapshot, and then they will save Requisition A to the server.

    • Requisition B is the same as A, but imagine some user's local browser has a cached copy of Requisition B from before the feature (no snapshot in their local cached copy). They continue to make edits saved to the local cache but not saved to the server. After the feature is rolled out, their browser uses the new OpenLMIS UI app which looks for a list of reasons in the Requisition snapshot. Whenever they attempt to save their local requisition to the server, at that point the Requisition service will see the timestamp of the server copy is newer than their local copy, and it will catch this error and return a helpful message. I propose we give them a red error similar to the existing one for when they are trying to save a Requisition where the server has a newer copy. We basically require these users to manually re-do their work. I believe this edge case will happen for a very small number of users in the real world if the upgrade is applied at a good time during their periodic Requisition cycle.

    • Requisition B-PLUS is just like B, but imagine that a user's browser still has the old version of the OpenLMIS UI app. And their browser also has the old cached version of the Requisition. They might continue to work on it for a few revisions (saved locally into their browser cache) using the old UI code and old Requisition object. When their old browser app comes online again, they will try to save, and the Requisition service will give them the same error mentioned in B (the scenario just above). The only difference is their app is still the old UI app, so any special error message or handling code we write in this ticket will not be running for this user. So hopefully our previous code that shows errors will allow them to see the error. They will not be able to fix and re-save their requisition with a proper list of Reasons until they actually refresh/reload and start running the new OpenLMIS UI app in their browser.

    • Requisition C is a requisition from 12 months ago that is already totally finished (released). It is historical and nobody is going to edit it again. No user is ever going to re-save this requisition (it is a historical requisition that is only being viewed, not edited). All of the adjustments, the numbers and totals in line items, all appear to be the same to the end user. But the source of the UUIDs behind the scenes is now pointing to the list of reasons that was migrated into the Stock Service.

    • Requisition D is just like Requisition A. A supervisory node user loaded it for review before the feature is in place (before the system is upgraded). They have a local cached copy. After that, the system is upgraded and the feature is in place. Now the supervisor logs in and views their (cached) requisition. At this moment, they approve it. Their browser app calls /requisition/approve status change /requisition/{id} update endpoint. As in scenario B, the user gets a message that a newer version of the Requisition is on the server. They will need to re-load the new requisition, review that one, and they can Approve that one. The data should appear the same in the new one, but its UUIDs and Snapshot data structure will be there.

    • Requisition E is just like Requisition A. But before the system was upgraded, a user had already started filling out Total Losses and Adjustments. So those adjustments all use UUIDs of the OLD reasons in ReferenceData service. After the upgrade, we want all Losses and Adjustments to use UUIDs of the new list of reasons in the Snapshot which are UUIDs pointing to reasons from Stock Management. This is a data migration issue that is handled in ticket OLMIS-2830. We do not need to handle this Requisition E edge case here.

    • Any other edge cases?

  • The snapshot can become out-of-date between the time a requisition is Initiated and the time it is Submitted/Authorized/Approved/Released. A few specific edge cases:

    • Requisition Q is initiated. Next an administrator adds a new Reason Y or assigns Reason Y to the program. The user never knows Reason Y is an option. They save and submit their work without Reason Y (we should confirm that snapshot feature works and they truly should not see Reason Y as an option). Later when the requisition gets its last approval, the Requisition service will send data to the stock service. Reason Y will not be used, and that is not a problem. Stock service will save the stock events.

    • Requisition P is initiated when Reason X is active for this program. Next, an administrator de-activates Reason X or un-assigns it from the program. After that, the user continues working on Requisition P which still has the snapshot list. User adds some adjustments for product quantities using Reason X. The user is able to save their requisition, and even Submit it. But later when the Requisition is approved (final approval), the Requisition service will try to push those adjustment quantities to the Stock service. The Stock service will respond with an error something like "Cannot save stock information: the reason ___ is not active for program ___. Update your data to use an active reason and try again." At that point, they might need to reject the requisition so the facility staff can update it to change their adjustments to use the current stock reasons, not Reason X. Otherwise they will not be able to move the requisition to the final approval status. This edge case will not be implemented until the future ticket where we actually push data into Stock Service. But for now in this ticket we still want to test that even when the list of valid reasons changes, the Requisition still keeps the Snapshot list from the time it was Initiated.

    • Requisition R is initiated with Reason Z which is called "Donated". Next, an administrator renames Reason Z from "Donated" to "Gave it away". The user should totally see the old name ("Donated") on this requisition because of the snapshot. But if the user initiates a whole new Requisition after this point, they should see Reason Z appear as "Gave it away". Either way, the data uses the correct UUID, but the name is part of the Snapshot. Later during OLMIS-2834, when the data is saved to Stock service it will only use the UUID so both requisition's adjustment reasons will look the same from the stock service's perspective.

  • Any other edge cases?

Migration
This feature is moving the source of data between services. So a production data migration is necessary: OLMIS-2830. This is a related ticket and will be worked on at the same time, because we cannot release any new version of OpenLMIS without the data migration being done along with this ticket. That data migration ticket has additional edge cases related to migration of data.

Major Change
This change needs to be part of a major version number change for the Requisition service and presumably for Requisition UI. It needs to be mentioned in the CHANGELOG for the effected components. We will also (next ticket) be marking the "old" Requisition Adjustment Reason endpoints in Reference Data as deprecated; see OLMIS-2831.

Acceptance Criteria

  • Requisition service will pull valid adjustment reasons from Stock service (change which endpoints; at this point Requisition will not call the reason endpoints in ReferenceData any more)

  • Requisition service will snapshot valid adjustment reasons locally upon initiation of a requisition

  • Requistion UI will use the snapshot list of reasons provided by the Requisition service

  • Update requisition demo data so that all requisitions have reasons in all their adjustments pointing to UUIDs in the Stock reason list for the appropriate program, not to ReferenceData reasons.

  • Update requisition demo data so that all requisitions have snapshot of all stock adjustment reasons they can use

  • Implement the Snapshot approach

  • Test all the edge cases mentioned above (developers and QA please review and decide which of these are automated tests versus which are manual tests)

  • CHANGELOG documentation of this and move target in gradle.properties to major version -SNAPSHOT

Activity

Show:
Paweł Gesek
August 29, 2017, 8:39 AM

I am closing, we will verify Requisition P in

Brandon Bowersox-Johnson
August 30, 2017, 12:27 AM

Regarding this remaining question from Paweł Albecki:

When requisition is be rejected, should it make new snapshot of reasons? There was nothing about it in ticket description but it looks like this is how it should work and adding it will be easy since we have already all logic in initiate endpoint.

My answer is No. We do not want to re-initiate the snapshot of reasons when a requisition is rejected. That has a bunch of other side effects and complexity that we do not want. It also violates the purpose of the "snapshot" which is that it is a static point in time. So when a requisition is rejected, the users who have permission to actually edit the requisition will simply need to take out any adjustments that had the old reasons in them (that is a pain but it will happen very infrequently if ever). We won't actually re-initiate a new snapshot of reasons. We won't do anything to automate this until or unless it becomes a request in the future.

Paweł Albecki
August 31, 2017, 10:05 AM
Edited
Brandon Bowersox-Johnson
August 31, 2017, 7:12 PM

The Requisition Q video looks great! Thank you again!

Paweł Albecki
August 31, 2017, 9:50 PM
Edited

Thanks
Last two videos:
Requisition P: https://youtu.be/JP1u3ZYSvWs
Requisition R: https://youtu.be/SH63EUaF6n0

cc

Flagged

Assignee

Paweł Albecki

Reporter

Brandon Bowersox-Johnson

Labels

Story Points

8

Time tracking

0m

Time remaining

0m

Epic Link

Components

Sprint

None

Fix versions

Priority

Major