-
-
Notifications
You must be signed in to change notification settings - Fork 466
OBLS-310 Backend for Pick up allocation #5694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/obaf-integration
Are you sure you want to change the base?
Conversation
|
Totally first initial version of allocation API. I added support for AUTO/MANUAL modes. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## feature/obaf-integration #5694 +/- ##
==========================================================
Coverage ? 9.53%
Complexity ? 1343
==========================================================
Files ? 780
Lines ? 48765
Branches ? 11629
==========================================================
Hits ? 4651
Misses ? 43420
Partials ? 694 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
jmiranda
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The was a first pass code review from yesterday. Just got around to posting it. Sorry!
| stockMovementService.createOrUpdatePicklistItem( | ||
| orderItem.requisitionItem, | ||
| null, | ||
| InventoryItem.get(itemToAllocate.inventoryItemId), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use load() here so there's no database query. However, the only bummer is that we won't know if the record exists or not until we save the picklist item (which isn't a big deal as long as the validation for the picklist item works properly - i.e. fails if fks are null).
| } | ||
|
|
||
| if (mode.equalsIgnoreCase(AllocationType.AUTO.name())) { | ||
| stockMovementService.createPicklist(orderItem, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this creates a picklist if one does not exist?
@awalkowiak The one thing we haven't discussed / designed is whether the requisition / picklist state machine can handle the fact that items might not be allocated yet.
In other words, we usually move all items from state to state at the same time. The pickup allocation flow changes that as we'll have some items that have been allocated and others that have not. So there are going to be gaps in multiple state machine that require us to be somewhat defensive about moving ALL items from state to state.
An example would be a pick up order like this. We cannot move this order to "complete" until all items are either fulfilled (which probably means each item has been "staged" but i need to double check the requirements).
- Requisition Item 1
- Status: Staged
- Requested: 10
- Allocated: 10
- Picked: 10
- Staged: 10
- Requisition Item 2
- Status: Requested
- Requested: 5
- Allocated: 0
- Picked: 0
- Staged: 0
- Canceled: 0
- Requisition Item 3
- Status: Canceled due to stock out
- Requested: 2
- Allocated: 0
- Picked: 0
- Staged: 0
- Canceled: 2
| orderItem.requisitionItem, | ||
| null, | ||
| InventoryItem.get(itemToAllocate.inventoryItemId), | ||
| Location.get(itemToAllocate.binLocationId), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same
| } | ||
|
|
||
| void allocate(StockMovementItem orderItem, Map data = [:]) { | ||
| String mode = data.mode as AllocationType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be
AllocationType mode = data.mode as AllocationType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And what is AllocationType? Did we define that previously? I think I called this AllocationMode in the design, so let's go with that.
This looks great
That's fine for now. Getting allocation working in general is the key here so we can move forward with picking and staging. When you get a change, please create a ticket to add a separate AllocationService that calls an AllocationStrategy (FEFO, DISPLAY_FIRST, WAREHOUSE_FIRST, etc)? I'll probably need to add some additional specification to that ticket before you can get started but feel free to implement the display vs warehouse as you see fit. |
…etermine allocation quantity and statuses
| } | ||
|
|
||
| String getAllocationStatus() { | ||
| if (isAllocated()) return "ALLOCATED" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider any enum for these statuses? or extend the existing RequistionItemStatus enum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah an AllocationStatus enum sounds good
|
|
||
| outboundOrder.lineItems.each { StockMovementItem item -> | ||
| item.availableItems = stockMovementService.getAvailableItems(outboundOrder.origin, RequisitionItem.get(item.id), false) | ||
| item.allocationStatus = RequisitionItem.get(item.id).getAllocationStatus() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this probably can be refactored i.e. add new fields to StockMovementItem view domain class and set these fields during StockMovementItem creation (from RequisitionItem)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, probably it will not be that trivial as I initially thought. Data in RequisitionItem like quantity allocated, allocation status etc. are also calculated on the fly, they are not stored in Requisition Item entity so in stock-movement-item.sql I cannot just use "select requisition_item.quantity_allocated" etc.
I leave it as it is for now
jmiranda
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized my comments weren't posted yet. Sorry about that. I added these awhile ago.
| throw new IllegalArgumentException("Order item with id ${params.itemId} not found") | ||
| } | ||
|
|
||
| outboundOrderService.allocate(orderItem, jsonBody) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should just call this AllocationService. And I don't love the jsonBody being passed here. Let's make the arguments explicits or use the AllocationRequest class to pass in all of the properties need to make a decision.
AllocationResult allocate(AllocationRequest request)
The AllocationService should eventually delegate to allocation strategies as described in the PUA ticket. I don't think we necessarily need that just yet, but wanted to explain what will eventually happen.
Alos, the AllocationResult is a list of allocations. But we might just be call these Allocation or AllocationItems (instead of ItemToAllocate)
| if (mode.equalsIgnoreCase(AllocationType.AUTO.name())) { | ||
| stockMovementService.createPicklist(orderItem, false) | ||
| } else if (mode.equalsIgnoreCase(AllocationType.MANUAL.name())) { | ||
| List<ItemToAllocate> allocations = data.allocations as List<ItemToAllocate> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah let's just call it an Allocation for now
|
|
||
| outboundOrder.lineItems.each { StockMovementItem item -> | ||
| RequisitionItem requisitionItem = RequisitionItem.get(item.id) | ||
| item.availableItems = stockMovementService.getAvailableItems(outboundOrder.origin, requisitionItem, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fetching outboundOrder (StockMovement) first and then adding all required data to particular line item like availableItems, allocations, allocationStatus, quantityAllocated. Thanks to this when I trigger fetch order endpoint I have all required data which I need to display in the mobile application and I don't need to make multiple requests to fetch all needed data
| return outboundOrder | ||
| } | ||
|
|
||
| AllocationDetailsDto allocate(String requisitionItemId, AllocationType mode, List<AllocationDto> allocations) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it supports create and update. AllocationDto contains "id" field (PicklistItem id). When this id is sent by the mobile app it looks for existing picklist item, finds and updates it, otherwise picklistItem = null is sent to createOrUpdatePicklistItem method and new pick list item is created
|
@jmiranda @awalkowiak can you take a look at PR? I assume that can be much remarks requested from you to change but I tried to implement +/- first working version of PUA (backend + frontend). I shared the video on slack how it currently works and looks. You can take a look. I didn't test any special/edge cases etc. |
No description provided.