Page tree
Skip to end of metadata
Go to start of metadata
RolePersonComments
Solution ArchitectApproved
Java Lead
UI Lead
Product Owner


UXPROD-137 - Getting issue details... STATUS  - Move Holdings and/or Items

Requirements

This feature covers ability to move attached records and maintain existing relationships. When moving holdings to another instance, all associated items have to be moved as well. Bulk moving items and holdings. Ease of linking/relinking bib/holdings/item data. Part of the refined UX design of Inventory. Drag and drop is one possible solution.

BE Design

Connections between items, instances, holdings.

Possible scenarios and implementation:

1) Move item(s) between holdings

Changing of each moved item with new item.holdingsRecordId.

2) Move holdings with item(s) to another instance

Changing of each moved holding  with new holding.instanceId.

3) Move selected item(s) to a holdings in another instance

This case looks the same to 1). Changing of each moved item with new item.holdingsRecordId.

Bulk operation approach

High-level description

The UI-client sends a move request to endpoints POST /inventory/items/move or inventory/holdings/move API. The mod-inventory processes this request, retrieves each item/holding from item/holdings-storage, prepares a request for each item/holding update and sends it asynchronously to tstorage. The mod-inventory waits for all responses from mod-inventory-storage to be completed and populates a response. In case of errors in some of the updating requests in the mod-inventory-storage, the mod-inventory returns a response containing a list of errors for not updated items/holdings.

APIs

MethodPathProvided permissionsRequestResponseDescriptionNotes
POST

inventory/items/move

inventory.items.move.item.postMove201 CREATEDMove items to new holding


POSTinventory/holdings/moveinventory.holdings.move.item.postMove201 CREATEDMove holdings to new instance

Flow details

Sequence diagram:


Steps:

1) Send move request (it contains id of holding to which items should be moved and items ids).

2) Send GET items collection form item-storage.

3) Update retrieved items with new item.holdingsRecordId and send asynchronously update request to item-storage for each item.

4) Wait all responses, populate errors if some of request failed.

5) Return response to UI client.

6) Send move request (it contains id of instance to which holdings should be moved and holdings ids).

7) Send GET holdings collection form holdings-storage.

8) Update retrieved  holdings with new holding.instanceId and send asynchronously update request to holdings-storage for each holding.

9) Wait all responses, populate errors if some of request failed.

10) Return response to UI client.


Move schema:

FieldTypeRequiredNote
toUUIDtrueUnique identifier of instance/holding to which holdings/items to be moved
idsArray<UUID>trueArray of holding/item unique identifiers which will be moved to the new instance/holding


Business logic algorithm for mod-inventory:


  • No labels

37 Comments

  1. Viachaslau Khandramai, So it won't be a bulk operation, will UI initiate all requests? If so, will it initiate the requests one-by-one or in parallel? What will happen if browser page will be refreshed during the operation?

  2. Mikhail Fokanov I expect that UI will send requests in parallel. Mikita Siadykh, please, confirm.

  3. Mikhail Fokanov regarding to the question: What will happen if browser page will be refreshed during the operation?
    I think part of requests can be not processed and save assignment to original instances/holdings. In case of independent parallel requests we can't guarantee success/failure of bulk operation on the whole - only for separate request. Do we need to foresee such use case when user start page refreshing right after pressing Save button?


  4. Viachaslau Khandramai , it is definitely for PO to decide the right compromise between small possibility of having not consistent state, if browser is refreshed and efforts that will be spend to implement the request of bulk movement as back-end endpoint, which will call then in-parallel and provide results and errors to UI as the response. I'd prefer to go with latter option.

    1. Stephanie Buck could you please clarify use case when user starts page refreshing right after pressing Save button? DO we need to support such scenario?

      1. Hi Mikhail Fokanov and Viachaslau Khandramai I checked with the working group and it doesn't appear that this is a likely scenario. Once a user hits save, they expect it to go through. They would not refresh the browser in an attempt to "undo" a save action, and cannot think of a reason why they would refresh the browser immediately after saving. 

  5. I'm not familiar with the inventory roadmap/backlog... are there other features that would benefit from batch item/holding update API endpoints

  6. Personally, I think it might be worth considering process-oriented APIs for this feature rather than coordinating the various changes in the client (UI).

    Over the last couple of years, there has been a shift to describing more of the business logic in the back-end APIs rather than the reference UI.

    This would make the intent explicit, encapsulate the logic of how transfers are conducted and neatly side-step the conversation about whether there needs to be a business-logic level API for holdings.

    It also might partly mitigate the challenge that Mikhail Fokanovraised because there would only be a single request from the UI to the API for any given transfer (the challenge still exists within the bounds of the back-end).

    1. This is the route Acquisitions has gone for a few things... In general I support this compared to putting business logic in the UI.

  7. Craig McNally Marc Johnson Mikhail Fokanov

    could you please review possible bulk-operations approach.

    Thanks!

    1. I think to understand the overall design I need more context on what the intended experience is meant to be. For now, I'll comment on the specific HTTP aspects of the API design.

      I don't think that a PUT to the collection resource, e.g. PUT /inventory/items is appropriate. The HTTP specification states that

      the enclosed representation in a PUT request is defined as replacing the state of the target resource.

      I think that is difficult for collection resources because the intent is not to replace the contents of the entire collection only update part of it. I don't think it fits with the idea that

      a successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.

      I think that a more appropriate API could either be POST /inventory/items/{id}/transfer with a destination holdings record if each item is transferred independently or POST /inventory/items/transfer with a set of items and a destination holdings record.

      Personally, I prefer the former, it simplifies the API, makes success / failure and errors more explicit and allows the client to control concurrency as it chooses rather than relying on the server. I might be more inclined to choose the latter if partial success / failure was not acceptable.

      If the set based style is used, I think the use of 400 as a response status is potentially challenging as it suggests the client has made a mistake. If the request has already been validated (as described with the 422 response status), what later error would cause the request to be interpreted as invalid?

      As it seems that partial success / failure is acceptable, I think it might be more appropriate to respond with 200 with a response that explicitly states that which records succeeded and which failed, and why. I imagine there is a chance that some of those failures are due to server rather than client issues.

      Does that make sense?

      (I'm aware that Zak_Burkeand I have debated both of these topics recently and that FOLIO has no / limited guidance on design of this style of API)

      1. I agree that  POST /inventory/items/transfer would be better. It must be single call, because it should be one action from user perspective side.

        1. Mikhail Fokanov Thanks for your reply 

          It must be single call, because it should be one action from user perspective side

          Why must  it be a single call because the reference UI happens to provide an experience where this is a single action?

          1. If user start the operation (moving a bunch of items or holdings from from one screen to another via drug and drop) and then there is some electricity/connectivity problems with his computer. This bunch of items should be moved and or not moved, but it shouldn't be moved partially. 

            1. If user started the operation (moving a bunch of items or holdings from from one screen to another via drug and drop) and then there is some electricity/connectivity problems with his computer. This bunch of items should be moved and or not moved, but it shouldn't be moved partially. 

              Are we sure that this whole operation has to be atomically completed?

              The process flow diagram for the business logic suggests that partial success / failure is acceptable, it states that a 400 response would be sent with a list of the failures.

              1. Partial success/failure is acceptable if there is some database problem, but user will notified in such case and can he take appropriate actions.

    2. Also it should be mentioned, that for now there is no method PATCH in inventory in order to make partial update of entities. So there should be get methods prior to put methods.

      However it would be more appropriate to create additional story for core-functional for support of partial update of entities. I think this functionality, can be leveraged in many use cases.

      1. Mikhail Fokanov

        However it would be more appropriate to create additional story for core-functional for support of partial update of entities. I think this functionality, can be leveraged in many use cases.

        Sure. Partial updates of entities and PATCH have been an on/off discussion for a long time in FOLIO.

        In this case, are you referring to a partial update of a single record or updating a sub-set of a collection of records?

        For the latter, that is likely a discussion for the batch API standards conversation.

        1. Here it could be both. I'll go with single requests for now.

          1. I think I might have not followed the reasoning.

            How would partial updating of a single record help with this process?

            1. It will help not to request record and then sent it back with changed ids of instances/holdings, but doing it in one call. Because there could be some changes of the instance between these 2 calls, which would be overwritten.

              1. Mikhail Fokanov

                It will help not to request record and then sent it back with changed ids of instances/holdings, but doing it in one call. Because there could be some changes of the instance between these 2 calls, which would be overwritten.

                I don't follow. Please can you provide an example of a flow where the same instance could be replaced twice? Are you suggesting that the instance needs to change when the holdings or items are changed?

  8. Please could context be provided for what the intended user experience is for this feature. For example, when transferring holdings, is it intended that a user selects two or more holdings records at once, or are holdings records transferred one at a time?

    1. Marc Johnson  as I know user can select several holdings and move them to another instance

      Stephanie Buck could you please confirm?



      1. Mikita Siadykh and Marc Johnson, yes several holdings can be moved to another instance. Sometimes holdings will exist without items, and multiple copies of a title, held in different locations, originally attached to a serial record are being moved to a monographic record. 

        1. Stephanie Buck Thank you for your comment.

          yes several holdings can be moved to another instance.

          What should the user experience be if a user chose to move 4 of 7 holdings records from one instance to another and during that process only 3 of them successfully moved and 1 did not?

          What is the correct term for this process, is it transfer or re-link as the name of this page suggests, or move, which is the language you used in your comment?

          1. Marc Johnson the term I've been using is move because in this context transfer means to move. If only three of the four move successfully, the user should see a message confirming which holdings moved successfully, and which did not. This would be the same for moving multiple items. 

            1. Thanks Stephanie Buck

              The term I've been using is move because in this context transfer means to move.

              By this context do you mean this feature, or a specific example of this behaviour?

              If only three of the four move successfully, the user should see a message confirming which holdings moved successfully, and which did not. This would be the same for moving multiple items. 

              That suggests that each move is independent of each other and can succeed and fail separately?

              1. Marc Johnson for this feature, transfer = move. Happy to answer questions!

                Yes. If presented with an error, the user preference is to know what saved and what failed. There can be times when a user has combed through hundreds of items and/or holdings and selected which should move. To lose all of that work if one or two items fail to move would be awful. 

                1. Stephanie Buck

                  Happy to answer questions!

                  I'm glad, because I tend to be full of them. Sometimes I repeat them in different ways to make sure I've got my understanding right.

                  for this feature, transfer = move

                  Thank you. I wanted to make sure. Does that mean that the feature, stories and this document could use move instead of transfer?

                  I'm trying to understand which of move or transfer is the better (or preferred) term for this.

                  It is important because this design starts to express it in the system, and mismatches between the language experts use and the system or developers use causes confusion and slows development.

                  Yes. If presented with an error, the user preference is to know what saved and what failed. There can be times when a user has combed through hundreds of items and/or holdings and selected which should move. To lose all of that work if one or two items fail to move would be awful.

                  Mikhail Fokanov This suggests that the transfers/moves as a whole are not considered atomic, only each individual transfer/move and a set can partially succeed or fail. That might affect the choice between an API that operates on each individually or on the whole set.

                  1. Hi Marc Johnson. The use cases use the word move, as do the stories I've written so far. It's the term I've been using most.
                    The definition of transfer is to move from one place to another, which makes me think using move may be most appropriate as it's the root action. If we need to take either transfer or move out of current and future documentation, I'm happy to do so. 


                    1. Stephanie Buck

                      The use cases use the word move, as do the stories I've written so far. It's the term I've been using most.

                      Should we use move as the prominent term instead of transfer?

                      If we need to take either transfer or move out of current and future documentation, I'm happy to do so. 

                      I think we need to be clear which is the most prominent term (I'm currently considering them as synonyms, if they are separate, then we need to distinguish them).

                      If move is the most prominent, I think we should we change the title of this document and the linked UXPROD feature.

                      This may also impact the API design. I proposed the use of a transfer endpoint, I would change that to move instead.

                      1. Marc Johnson I have been using them as synonyms, but use move more frequently. 

                        1. Stephanie Buck

                          I have been using them as synonyms, but use move more frequently. 

                          Given that, it seems like move is the more prominent term and I think we should reflect that in the name of the feature, this document and the API design


                          cc: Mikhail FokanovViachaslau Khandramai

                          1. Marc Johnson , Mikhail Fokanov and Viachaslau Khandramai I have renamed the feature to Move Holdings and/or Items. Please let me know if there are other spots I should adjust.