Skip to content

OBPIH-6420 Undo edit functionality in cleared pick mode#4654

Merged
awalkowiak merged 4 commits intodevelopfrom
OBPIH-6420
Jun 11, 2024
Merged

OBPIH-6420 Undo edit functionality in cleared pick mode#4654
awalkowiak merged 4 commits intodevelopfrom
OBPIH-6420

Conversation

@alannadolny
Copy link
Collaborator

No description provided.

Copy link
Member

@jmiranda jmiranda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@awalkowiak has final say on what needs to be changed here.

"/api/picklists/$id/items/$itemId" {
controller = "picklistApi"
action = [DELETE: "revertPick"]
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be just requisitionItem.picklistItems


List<String> binLocations = []
picklistItemsToRemove.each {
picklist.removeFromPicklistItems(it)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will probably trigger a product availability refresh so we should try to disableRefresh before deleting.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, it has to be checked and disabled if needed.

List<String> binLocations = []
picklistItemsToRemove.each {
picklist.removeFromPicklistItems(it)
binLocations.add(it.binLocation?.id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.


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}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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}`;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 this could be improved


if (!picklist) {
throw new ObjectNotFoundException(id, Picklist.class.toString())
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be just requisitionItem.picklistItems


List<String> binLocations = []
picklistItemsToRemove.each {
picklist.removeFromPicklistItems(it)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, it has to be checked and disabled if needed.


productAvailabilityService.refreshProductsAvailability(
picklist?.requisition?.origin?.id,
picklistItemsToRemove?.requisitionItem?.product?.id?.unique(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.


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}`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 this could be improved

action = [DELETE: "clearPicklist"]
}

"/api/picklists/$id/items/$itemId" {
Copy link
Collaborator

@awalkowiak awalkowiak Jun 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint needs to be improved changed as it was discussed in the comment in service and on slack

@alannadolny alannadolny requested a review from awalkowiak June 10, 2024 10:01
}
}

void revertPick(String itemId) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

@awalkowiak awalkowiak merged commit 6d18a10 into develop Jun 11, 2024
@awalkowiak awalkowiak deleted the OBPIH-6420 branch June 11, 2024 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants