OBPIH-6420 Undo edit functionality in cleared pick mode#4654
OBPIH-6420 Undo edit functionality in cleared pick mode#4654awalkowiak merged 4 commits intodevelopfrom
Conversation
jmiranda
left a comment
There was a problem hiding this comment.
@awalkowiak has final say on what needs to be changed here.
| "/api/picklists/$id/items/$itemId" { | ||
| controller = "picklistApi" | ||
| action = [DELETE: "revertPick"] | ||
| } |
There was a problem hiding this comment.
Yay. Just out of curiosity, do we know what happens when we hit this endpoint with a POST or PUT. I'm expecting a 405 Method Not Allowed.
|
|
||
| def revertPick() { | ||
| picklistService.revertPick(params.id, params.itemId) | ||
|
|
There was a problem hiding this comment.
See if you can add these as args to the action.
def revertPick(String id, String itemId) {
picklistService.revertPick(id, itemId)
}
|
|
||
| void revertPick(String id, String itemId) { | ||
| Picklist picklist = Picklist.get(id) | ||
| RequisitionItem requisitionItem = RequisitionItem.get(itemId) |
There was a problem hiding this comment.
The itemId argument must map to PicklistItem.id in order for the API to make sense. If we want to revert ALL picklist items for a requisition item, we'll need to think about this differently.
For now, we could have a few different methods to revert picks.
void revertPick(PicklistItem picklis) { ... }
void revertPick(PicklistItem picklistItem) { ... }
void revertPick(List<PicklistItem> picklistItems) {
picklistItems.each { PicklistItem picklistItem ->
revertPick(picklistItem)
}
}
void revertPick(RequisitionItem requisitionItem) {
revertPick(requisitionItem.picklistItems)
}
And this method would look like this ..
Picklist picklist = Picklist.get(id)
PicklistItem picklistItem = PicklistItem.get(itemId)
RequisitionItem requisitionItem = picklistItem.requisitionItem)
// Revert all picks for the given requisition item,
// disable refresh product availability on hibernate event
requisitionItem.disableRefresh = true
revertPick(requisitionItem)
// Or if we can't pass the disableRefresh from the parent, we could do something like this
//requisitionItem.picklistItems.each { it.disableRefresh = true }
//revertPick(requisitionItem)
// fire refresh event for the product (ignore bin locations)
productAvailabilityService.refreshProductAvailability(
picklist?.requisition?.origin?.id,
[requisitionItem?.product?.id],
[],
true) // can't remember if this should be
}
Or perhaps the API endpoint should look like this for now.
DELETE /api/stockMovementItems/:id/picklistItems
There was a problem hiding this comment.
Key points above
- Approach 1
- itemId should map to PicklistItem
- how you deal with getting from a picklist item to all picklist items for a requisition item is up to you
- when deleting picklist items we probably want to refresh product availability for the entire product, not just the bin locations that are effected.
- Approach 2
- Move the action to the StockMovementItemApiController to ensure a consistent / coherent URL scheme
- The other points are likely the same.
There was a problem hiding this comment.
@jmiranda Yup, I agree that the current solution with DELETE /api/picklists/$id/items/$itemId and passing requisition item id as itemId is not perfect and might be misleading or cause some confusion. When I was looking at the code I was thinking about moving the current revertPick (with some minor adjustments if needed) under DELETE /api/requisitionItems/:id/picklistItems or DELETE /api/stockMovementItems/:id/picklistItems (the first one was my first thought, but considering it is stock movement related, then I think the latter one is more suiting)
| void revertPick(String id, String itemId) { | ||
| Picklist picklist = Picklist.get(id) | ||
| RequisitionItem requisitionItem = RequisitionItem.get(itemId) | ||
| List<PicklistItem> picklistItemsToRemove = PicklistItem.findAllByRequisitionItem(requisitionItem) |
There was a problem hiding this comment.
Hopefully the requisitionItem already has an association to its picklistItems. There's probably going to be a lazy query here, but better to go through the model to avoid unnecessary queries.
There was a problem hiding this comment.
Should be just requisitionItem.picklistItems
|
|
||
| List<String> binLocations = [] | ||
| picklistItemsToRemove.each { | ||
| picklist.removeFromPicklistItems(it) |
There was a problem hiding this comment.
This will probably trigger a product availability refresh so we should try to disableRefresh before deleting.
There was a problem hiding this comment.
Yup, it has to be checked and disabled if needed.
| List<String> binLocations = [] | ||
| picklistItemsToRemove.each { | ||
| picklist.removeFromPicklistItems(it) | ||
| binLocations.add(it.binLocation?.id) |
There was a problem hiding this comment.
As discussed in Approach 1 above we might want to refresh at the product level, rather than at the bin location level to avoid any weird edge cases.
| picklist?.requisition?.origin?.id, | ||
| picklistItemsToRemove?.requisitionItem?.product?.id?.unique(), | ||
| binLocations, | ||
| false |
There was a problem hiding this comment.
As mentioned above, we probably want to force refresh on the product level.
// fire refresh event for the product (ignore bin locations)
productAvailabilityService.refreshProductAvailability(
picklist?.requisition?.origin?.id,
[requisitionItem?.product?.id],
[],
true) // can't remember if we should force refresh or not
}
@awalkowiak What do you think about that?
There was a problem hiding this comment.
@jmiranda Force refresh deletes the line from the table first, I think we don't have to do it here and just doing the line update is enough.
src/js/api/urls.js
Outdated
|
|
||
| export const PICKLIST_API = `${API}/picklists`; | ||
| export const PICKLIST_CLEAR = id => `${PICKLIST_API}/${id}/items`; | ||
| export const PICKLIST_REVERT_PICK = (id, itemId) => `${PICKLIST_CLEAR(id)}/${itemId}`; |
There was a problem hiding this comment.
We should be more obvious here to avoid confusion / regression later. If there's a baseUrl shared by multiple endpoints, let's define the base URL. Also
export const PICKLIST_API = `${API}/picklists`;
export const PICKLIST_ITEM_API = `${API}/picklists/${id}/items`;
export const PICKLIST_ITEM_CLEAR = id => `${PICKLIST_ITEMS_API}`;
export const PICKLIST_ITEM_REVERT = (id, itemId) => `${PICKLIST_ITEMS_API(id)}/${itemId}`;
There was a problem hiding this comment.
👍 this could be improved
|
|
||
| if (!picklist) { | ||
| throw new ObjectNotFoundException(id, Picklist.class.toString()) | ||
| } |
There was a problem hiding this comment.
I would call this just after attempting to get a picklist, to avoid some unnecessary queries (e.g. the one from 331th), if they are not gonna be used either way.
|
|
||
| void revertPick(String id, String itemId) { | ||
| Picklist picklist = Picklist.get(id) | ||
| RequisitionItem requisitionItem = RequisitionItem.get(itemId) |
There was a problem hiding this comment.
@jmiranda Yup, I agree that the current solution with DELETE /api/picklists/$id/items/$itemId and passing requisition item id as itemId is not perfect and might be misleading or cause some confusion. When I was looking at the code I was thinking about moving the current revertPick (with some minor adjustments if needed) under DELETE /api/requisitionItems/:id/picklistItems or DELETE /api/stockMovementItems/:id/picklistItems (the first one was my first thought, but considering it is stock movement related, then I think the latter one is more suiting)
| void revertPick(String id, String itemId) { | ||
| Picklist picklist = Picklist.get(id) | ||
| RequisitionItem requisitionItem = RequisitionItem.get(itemId) | ||
| List<PicklistItem> picklistItemsToRemove = PicklistItem.findAllByRequisitionItem(requisitionItem) |
There was a problem hiding this comment.
Should be just requisitionItem.picklistItems
|
|
||
| List<String> binLocations = [] | ||
| picklistItemsToRemove.each { | ||
| picklist.removeFromPicklistItems(it) |
There was a problem hiding this comment.
Yup, it has to be checked and disabled if needed.
|
|
||
| productAvailabilityService.refreshProductsAvailability( | ||
| picklist?.requisition?.origin?.id, | ||
| picklistItemsToRemove?.requisitionItem?.product?.id?.unique(), |
There was a problem hiding this comment.
If you have requisitionItem, then having [requisitionItem?.product?.id] is enough, because there is no way there will be different products for picklist items for the same requisition item.
| picklist?.requisition?.origin?.id, | ||
| picklistItemsToRemove?.requisitionItem?.product?.id?.unique(), | ||
| binLocations, | ||
| false |
There was a problem hiding this comment.
@jmiranda Force refresh deletes the line from the table first, I think we don't have to do it here and just doing the line update is enough.
src/js/api/urls.js
Outdated
|
|
||
| export const PICKLIST_API = `${API}/picklists`; | ||
| export const PICKLIST_CLEAR = id => `${PICKLIST_API}/${id}/items`; | ||
| export const PICKLIST_REVERT_PICK = (id, itemId) => `${PICKLIST_CLEAR(id)}/${itemId}`; |
There was a problem hiding this comment.
👍 this could be improved
| action = [DELETE: "clearPicklist"] | ||
| } | ||
|
|
||
| "/api/picklists/$id/items/$itemId" { |
There was a problem hiding this comment.
This endpoint needs to be improved changed as it was discussed in the comment in service and on slack
| } | ||
| } | ||
|
|
||
| void revertPick(String itemId) { |
There was a problem hiding this comment.
One minor thing. I think this should already take RequsitionItem as a param (or at least change the name of this param to requisitionItemId, so it is clear what it expects).
No description provided.