Skip to content

Conversation

@druchniewicz
Copy link
Collaborator

No description provided.

@github-actions github-actions bot added the domain: backend Changes or discussions relating to the backend server label Dec 18, 2025
@druchniewicz
Copy link
Collaborator Author

Totally first initial version of allocation API.

I added support for AUTO/MANUAL modes.
In AUTO mode I just create pick list based on order item (without distinction between display/warehouse pick).
in MANUAL mode I create pick list based on array of allocations where one object contains inventoryItemId, binLocationId, quantity).

@druchniewicz druchniewicz changed the title OBLS-310 Allocation API for PUA [WIP] OBLS-310 Allocation API for PUA Dec 18, 2025
@druchniewicz druchniewicz marked this pull request as draft December 18, 2025 23:39
@codecov
Copy link

codecov bot commented Dec 18, 2025

Codecov Report

❌ Patch coverage is 5.03597% with 132 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (feature/obaf-integration@7ce4dc5). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...h/warehouse/outboundOrder/AllocationService.groovy 0.00% 84 Missing ⚠️
...se/outboundOrder/OutboundOrderApiController.groovy 0.00% 24 Missing ⚠️
...g/pih/warehouse/requisition/RequisitionItem.groovy 0.00% 15 Missing ⚠️
...ovy/org/pih/warehouse/api/StockMovementItem.groovy 0.00% 3 Missing ⚠️
...-app/domain/org/pih/warehouse/core/Location.groovy 66.66% 2 Missing ⚠️
...ih/warehouse/outboundOrder/AllocationStrategy.java 0.00% 2 Missing ⚠️
...arehouse/outboundOrder/AllocationDetailsDto.groovy 0.00% 1 Missing ⚠️
...g/pih/warehouse/outboundOrder/AllocationDto.groovy 0.00% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

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

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

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

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

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

Copy link
Member

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.

@jmiranda
Copy link
Member

Totally first initial version of allocation API.

This looks great

(without distinction between display/warehouse pick).

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.

@github-actions github-actions bot added domain: l10n Changes or discussions relating to localization & Internationalization stakeholder: vvg Issues or topics relating to VVG (velocity vehicle group) labels Dec 22, 2025
}

String getAllocationStatus() {
if (isAllocated()) return "ALLOCATED"
Copy link
Collaborator Author

@druchniewicz druchniewicz Jan 7, 2026

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

Copy link
Member

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

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)

Copy link
Member

Choose a reason for hiding this comment

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

+1

Copy link
Collaborator Author

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

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.

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

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

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

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

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

@druchniewicz druchniewicz marked this pull request as ready for review January 9, 2026 18:19
@druchniewicz druchniewicz changed the title [WIP] OBLS-310 Allocation API for PUA OBLS-310 Allocation API for PUA Jan 9, 2026
@druchniewicz druchniewicz changed the title OBLS-310 Allocation API for PUA OBLS-310 Allocation backend for PUA Jan 9, 2026
@druchniewicz druchniewicz changed the title OBLS-310 Allocation backend for PUA OBLS-310 Backend for Pick up allocation Jan 9, 2026
@druchniewicz druchniewicz requested a review from jmiranda January 9, 2026 18:20
@druchniewicz
Copy link
Collaborator Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: backend Changes or discussions relating to the backend server domain: l10n Changes or discussions relating to localization & Internationalization stakeholder: vvg Issues or topics relating to VVG (velocity vehicle group)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants