Context
Override functionality allows the user to perform an action that should be otherwise blocked.
Currently, there's only one type of check-out override - when the item is not loanable, we can make a call to POST /circulation/override-check-out-by-barcode to override this block and create a loan. There is also an endpoint for overriding renewals of items that are not renewable, declared lost, aged to lost etc. (POST /circulation/override-renewal-by-barcode).
Requirements
Users need to be able to apply different kinds of overrides in multiple steps. Specifically, override of patron blocks will be added (https://issues.folio.org/browse/UXPROD-1130) as well as override of item blocks (https://issues.folio.org/browse/UXPROD-2127). The desired check-out flow should look like this:
- During a check-out, the user should be able to override patron blocks first (right after the patron is selected) and then start checking out items to the selected patron.
- In case when any of the check-outs are blocked for reasons other than patron block (item is not loanable, item limit block etc.), the user makes decisions about overriding those blocks separately, but patron blocks should be overridden automatically (because it has been already decided on the previous step).
- If there are multiple blocks that prevent an item from being borrowed, the whole list of reasons why this item can't be checked out should be displayed. The user should be able to review and override all of them in one go (with the appropriate permissions, of course).
Proposed changes to mod-circulation
Get rid of the "override" endpoints.
These endpoints should be removed:
- POST /circulation/override-check-out-by-barcode
- POST /circulation/override-renewal-by-barcode
Endpoints that are responsible for regular borrowing, requests and renewals will also be responsible for overrides now:
- POST /circulation/check-out-by-barcode
- POST /circulation/override-renewal-by-barcode
- POST /circulation/renew-by-id
- POST /circulation/requests
- PUT /circulation/requests
UI might need to make two calls to the same endpoint in order to complete the action. First - to get the list of overridable blocks, second - to override these block after user's decision.
Return full list of overridable blocks
Endpoints (1-5) should return a full list of blocks that have to be overridden in order for action to be completed. When checking for blocks these processes shouldn't fail immediately when they find the first block. They should check for all blocks instead and include the results in the response. Typically, in case of an error the response structure looks like this:
{ "errors" : [ { "message" : "Error message", "parameters" : [ { "key" : "key-1", "value" : "value-1" }, ... ] } ] }
Two parameters need to be added to the parameters array:
- key: "overridable", value: boolean
UI needs to know whether it's even possible to complete the action by overriding the blocks (there may be other reasons that make it impossible). This value should only be true in case when the only reason for the action to fail is one or more overridable blocks. If there's a block that can't be overridden because the user doesn't have sufficient permissions or can't be overridden at all - the value should be false. - key: "blocks", value: array of strings
A list of blocks that need to be overridden. This parameter may be omitted if overridable=false - the user won't be able to complete the action by overriding blocks anyway.
Expect a list of blocks that user wants to override
Request bodies of endpoints (1-5) need to include a list of blocks that the requester wants to override. New (optional) field should be added to JSON schemas:
"overrideBlocks": { "description": "Blocks that need to be overridden", "type": "array", "items":{ "type": "string", "enum": [ "patron-limit", "item-limit", "item-not-loanable" ] } }
List of the appropriate blocks may be dependent on the endpoint.
In case when this parameter is included in the request, the server should override all of the specified blocks if the user has sufficient permissions.
Managing permissions
Each overridable action will be associated with a user permission that is required in order to override this action. These permissions need to be part of permissionsDesired rather than permissionsRequired which will allow to handle them in the code. For example, new permissions for POST /circulation/check-out-by-barcode:
"permissionsDesired": [ "circulation.override-patron-block", "circulation.override-item-limit-block", "circulation.override-item-not-loanable-block" ]