Documentation
fsds/stack-and-shipment-creation-without-load-numbers.md
Plan: Allow Stack and Shipment Creation Without Load Numbers
Problem
When Oracle XML files don't have <load_nbr> elements, the entire stack AND shipment creation is skipped, causing all camera read OBLPN lookups to fail. This is overly restrictive since:
- Stacks (OBLPNs) are physical containers that exist independently of load assignments
- Shipments can be identified by OBLPN instead of load number
- The validation docs treat missing load numbers as warnings, not failures
Solution Overview
Modify OracleProcessor.ProcessShippingInfoAsync to:
- Always create stacks when we have a valid OBLPN
- Create shipments using OBLPN as the primary identifier when load number is missing
- Add load number as an additional identifier when available
Files to Modify
Primary: engines/bbu/src/Acsis.Dynaplex.Engines.Bbu/Services/OracleProcessor.cs
Change 1: Restructure ProcessShippingInfoAsync (lines ~940-990)
Current flow:
if (loadNumber missing) {
log warning, skip everything
} else {
create shipment → create stack → allocate
}
New flow:
// Always create stack if we have OBLPN
stackItem = await UpsertStackItemAsync(...)
// Create shipment using OBLPN or LoadNumber as identifier
shipmentResult = await UpsertShipmentAsync(...) // Modified method
// Link stack to shipment if both exist
if (stackItem != null && shipmentResult != null) {
await EnsureStackAllocationAsync(...)
await SyncStackProductItemsAsync(...)
}
Change 2: Modify UpsertShipmentForLoadAsync → UpsertShipmentAsync
Rename and modify the method to:
- Accept OBLPN as a required parameter
- Accept loadNumber as optional
- Use OBLPN as TrackingNumber when loadNumber is missing
- Look up existing shipments by OBLPN first, then by loadNumber
- Store both identifiers when available
New signature:
private async Task<LoadShipmentResult?> UpsertShipmentAsync(
string oblpn, // Required - always have this
string? loadNumber, // Optional
string? manifestNumber,
Guid? sourceLocationId,
int itemQuantity,
IReadOnlyList<DeliveryPlan> deliveryPlans,
string? trackingNumber,
string? carrierCode,
CancellationToken cancellationToken
)
Lookup logic:
- First try to find by OBLPN identifier (PRIMARY_OBLPN)
- If not found and loadNumber provided, try by LOAD_NUMBER
- Create new if neither found
TrackingNumber assignment:
- Always use OBLPN (consistent identifier regardless of loadNumber presence)
Change 3: Update UpsertStackItemAsync call site
Move the call outside the loadNumber check so it always executes when we have a valid OBLPN.
Change 4: Fix misleading success log (line ~983)
Move "Successfully imported entities for OBLPN" log inside the actual success path, not after the if/else block.
Implementation Steps
Rename method:
UpsertShipmentForLoadAsync→UpsertShipmentAsync- Update signature to take OBLPN as required, loadNumber as optional
- Update all call sites
Update lookup logic in
UpsertShipmentAsync:- Add OBLPN-based lookup using
IdentifierTypeCodes.PrimaryOblpn - Keep loadNumber lookup as fallback
- Ensure both identifiers are stored
- Add OBLPN-based lookup using
Restructure ProcessShippingInfoAsync:
- Move
UpsertStackItemAsynccall before/outside the shipment creation - Update shipment creation to use new method signature
- Ensure stack allocation only happens when both stack and shipment exist
- Move
Fix logging:
- Add debug log showing which identifier was used
- Fix the misleading "Successfully imported" log placement
Testing Considerations
- Test with Oracle XML that has: OBLPN only, LoadNumber only, both, neither
- Verify camera read lookups succeed when stacks are created
- Verify shipment-stack allocation works correctly
- Check that existing data with load numbers still works
Risks & Mitigations
| Risk | Mitigation |
|---|---|
| Duplicate shipments if same OBLPN processed twice | Existing upsert pattern handles this via identifier lookup |
| Breaking existing data with load numbers | Lookup checks both identifiers, existing data unaffected |
| ShipmentLifecycleProcessor expects certain data | Stack and shipment allocation remain unchanged |