Files
FTC25009/docs/superpowers/plans/2026-07-14-dense-inbound-lane-allocation.md

192 lines
12 KiB
Markdown

# 03 Warehouse Dense Inbound Lane Allocation Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Configure deterministic A-H cargo-area directions and make warehouse 03 allocate dense-storage lanes by empty tray, raw-material identity, or project number without mixing incompatible cargo in one `group_coding` lane.
**Architecture:** Resolve the exact inbound job and its details into a typed storage profile before selecting a location. For warehouse 03, serialize allocation by warehouse and roadway, evaluate completed stock plus active/reserved inbound jobs for every lane, choose a compatible existing lane before a new empty lane (empty trays use lane-level pseudo-random selection), and then choose the next slot using the configured cargo-area direction. Other warehouses retain the current location selection behavior.
**Tech Stack:** Java 17, Spring Boot, MyBatis XML, SQL Server application locks and CTEs, JUnit 5, Mockito, AssertJ, Maven.
---
## File map
- Create `ruoyi-admin/src/main/java/com/ruoyi/in/job/domain/InboundStorageProfile.java`: immutable four-mode storage profile and mapper-parameter export.
- Modify `ruoyi-admin/src/main/java/com/ruoyi/in/job/domain/MydoJob.java`: transient profile fields used by occupied-location reallocation.
- Modify `ruoyi-admin/src/main/java/com/ruoyi/in/job/service/IMydoJobService.java`: expose profile resolution for the WCS location request path.
- Modify `ruoyi-admin/src/main/java/com/ruoyi/in/job/service/impl/MydoJobServiceImpl.java`: validate exact job details and resolve the four storage modes; attach the same profile during occupied-location reallocation.
- Modify `ruoyi-admin/src/main/java/com/ruoyi/pda/service/impl/PdaServiceImpl.java`: apply dense profile rules only to warehouse 03 and acquire the roadway allocation lock before choosing a new slot.
- Modify `ruoyi-admin/src/main/java/com/ruoyi/pda/mapper/PdaMapper.java`: add the roadway-lock mapper contract.
- Modify `ruoyi-admin/src/main/resources/mapper/pda/PdaMapper.xml`: add roadway serialization and lane-aware atomic selection.
- Modify `ruoyi-admin/src/main/resources/mapper/bas/BasCargoSpaceMapper.xml`: apply the same compatibility and direction rules to occupied-location reallocation.
- Modify `sql/20260714_cargo_area_direction.sql`: make the default warehouse 03 directions A/B/C/E ascending and D/F/G/H descending.
- Create `sql/20260714_warehouse_03_inbound_lane_allocation.sql`: idempotently apply the final direction configuration and supporting indexes to an already-migrated database.
- Modify focused JUnit tests under `ruoyi-admin/src/test/java/com/ruoyi/pda` and `ruoyi-admin/src/test/java/com/ruoyi/in/job`: prove profile validation, lock order, lane compatibility, randomization scope, and the reallocation guard.
### Task 1: Define and validate the four inbound storage profiles
**Files:**
- Create: `ruoyi-admin/src/main/java/com/ruoyi/in/job/domain/InboundStorageProfile.java`
- Modify: `ruoyi-admin/src/main/java/com/ruoyi/in/job/service/IMydoJobService.java`
- Modify: `ruoyi-admin/src/main/java/com/ruoyi/in/job/service/impl/MydoJobServiceImpl.java`
- Test: `ruoyi-admin/src/test/java/com/ruoyi/in/job/service/impl/MydoJobServiceImplTest.java`
- [ ] **Step 1: Write failing service tests**
Add tests that resolve these exact inputs: `KTP0001` to `EMPTY_TRAY`; purchase type `1` with blank project to `RAW_PRODUCT`; purchase type `1` with one nonblank project to `PROJECT`; production type `2` with one nonblank project to `PROJECT`. Add rejection tests for mixed product code/name in a projectless purchase tray, mixed project numbers, production without project number, missing job/details/stock-in bill, and unsupported inbound type.
- [ ] **Step 2: Run the focused tests and verify failure**
Run: `mvn -pl ruoyi-admin -Dtest=MydoJobServiceImplTest test`
Expected: FAIL because `InboundStorageProfile` and `resolveInboundStorageProfile` do not exist.
- [ ] **Step 3: Implement the profile value object and resolver**
Define modes `EMPTY_TRAY`, `RAW_PRODUCT`, and `PROJECT`; preserve `inType`, `jobId`, trimmed `projectNo`, `productId`, and `productName`. Resolve the exact latest inbound job for the tray and warehouse, load all details by `jobId`, and use the referenced `in_stockin.in_type`. Treat empty trays by the `KTP0001` detail identity; require one exact `productId + productName` pair for projectless purchase; require one nonblank project for project purchase and production.
- [ ] **Step 4: Run focused tests and verify pass**
Run: `mvn -pl ruoyi-admin -Dtest=MydoJobServiceImplTest test`
Expected: PASS.
### Task 2: Serialize warehouse 03 lane allocation
**Files:**
- Modify: `ruoyi-admin/src/main/java/com/ruoyi/pda/mapper/PdaMapper.java`
- Modify: `ruoyi-admin/src/main/resources/mapper/pda/PdaMapper.xml`
- Modify: `ruoyi-admin/src/main/java/com/ruoyi/pda/service/impl/PdaServiceImpl.java`
- Test: `ruoyi-admin/src/test/java/com/ruoyi/pda/mapper/PdaMapperSqlTest.java`
- Test: `ruoyi-admin/src/test/java/com/ruoyi/pda/service/impl/PdaServiceImplTest.java`
- [ ] **Step 1: Write failing lock and parameter tests**
Assert that warehouse 03 resolves and forwards `v_job_id`, `v_storage_mode`, `v_project_no`, `v_product_id`, `v_product_name`, and `v_in_type`; that other warehouses do not require a profile; and that a second transaction-owned application lock uses warehouse plus roadway and is acquired only after the existing tray lock and locked-location lookup.
- [ ] **Step 2: Run the focused tests and verify failure**
Run: `mvn -pl ruoyi-admin -Dtest=PdaServiceImplTest,PdaMapperSqlTest test`
Expected: FAIL because the profile parameters and roadway lock are absent.
- [ ] **Step 3: Implement the roadway lock and service orchestration**
Keep the existing warehouse+tray lock for idempotency. If no location is already locked and `warehouseId` is `03`, resolve the storage profile, add it to the selection map, then acquire `sp_getapplock` with resource `wms:inbound-roadway:<hash(warehouse,roadway)>`, `Exclusive`, `Transaction`, and a 10-second timeout. Do not change other warehouses' current selection inputs or behavior.
- [ ] **Step 4: Run focused tests and verify pass**
Run: `mvn -pl ruoyi-admin -Dtest=PdaServiceImplTest,PdaMapperSqlTest test`
Expected: PASS.
### Task 3: Select a compatible `group_coding` lane atomically
**Files:**
- Modify: `ruoyi-admin/src/main/resources/mapper/pda/PdaMapper.xml`
- Test: `ruoyi-admin/src/test/java/com/ruoyi/pda/mapper/PdaMapperSqlTest.java`
- [ ] **Step 1: Write failing SQL contract tests**
Assert the warehouse 03 SQL requires nonblank `group_coding`, reads positive-quantity `bas_stock + bas_stock_detail`, reads active `mydo_job + mydo_job_detail`, recognizes status-3 reserved slots by tray even before the job location is written back, excludes the current job, and rejects unknown occupied slots. Assert exact compatibility by mode: only `KTP0001` for empty trays, only projectless purchase rows with equal trimmed product code and name for `RAW_PRODUCT`, and only equal nonblank project numbers for `PROJECT`.
- [ ] **Step 2: Assert ranking and randomization rules**
Require project and raw-material allocation to prefer a compatible occupied lane over an empty lane and consolidate into the most-filled compatible lane. Require empty trays to randomize once per lane using `CHECKSUM(group_coding, tray_code)`, never once per slot. Require the slot inside the selected lane to retain height priority and configured direction order.
- [ ] **Step 3: Run the mapper test and verify failure**
Run: `mvn -pl ruoyi-admin -Dtest=PdaMapperSqlTest test`
Expected: FAIL because the current SQL ranks individual empty slots and never inspects lane contents.
- [ ] **Step 4: Implement the SQL Server CTE-based candidate update**
Build profiled occupancy from completed stock, active inbound jobs with assigned locations, and status-3 reservations joined by tray. Add an unknown profile for an occupied slot without traceable data so the lane fails closed. Aggregate by `group_coding`, retain only fully compatible lanes, rank lanes before slots, and perform one guarded `UPDATE ... WITH (UPDLOCK, READPAST, ROWLOCK)` from the chosen candidate. Keep the old candidate query under the non-03 branch.
- [ ] **Step 5: Run the mapper test and verify pass**
Run: `mvn -pl ruoyi-admin -Dtest=PdaMapperSqlTest test`
Expected: PASS.
### Task 4: Preserve lane rules during occupied-location reallocation
**Files:**
- Modify: `ruoyi-admin/src/main/java/com/ruoyi/in/job/domain/MydoJob.java`
- Modify: `ruoyi-admin/src/main/java/com/ruoyi/in/job/service/impl/MydoJobServiceImpl.java`
- Modify: `ruoyi-admin/src/main/resources/mapper/bas/BasCargoSpaceMapper.xml`
- Test: `ruoyi-admin/src/test/java/com/ruoyi/in/job/service/impl/MydoJobServiceImplTest.java`
- Test: `ruoyi-admin/src/test/java/com/ruoyi/bas/cargospace/mapper/BasCargoSpaceMapperSqlTest.java`
- [ ] **Step 1: Write failing reallocation tests**
Assert that `handleWcsPutOccupiedException` resolves the exact job's storage profile before marking the old location, attaches the profile fields to the mapper query, and aborts without changing location when the profile is invalid. Assert the reallocation SQL uses stock, active/reserved jobs, current-job exclusion, compatibility, and `group_coding` ranking.
- [ ] **Step 2: Run focused tests and verify failure**
Run: `mvn -pl ruoyi-admin -Dtest=MydoJobServiceImplTest,BasCargoSpaceMapperSqlTest test`
Expected: FAIL because reallocation currently uses only tray type, height, and direction.
- [ ] **Step 3: Reuse the profile and lane predicate**
Resolve the exact job before the old location becomes status `5`, copy the profile to transient `MydoJob` fields, and make `selectAvailableInboundCargoSpaceInRoadway` use the same warehouse-03 lane-compatibility and ranking rules. Keep its existing behavior for other warehouses.
- [ ] **Step 4: Run focused tests and verify pass**
Run: `mvn -pl ruoyi-admin -Dtest=MydoJobServiceImplTest,BasCargoSpaceMapperSqlTest test`
Expected: PASS.
### Task 5: Apply deterministic A-H direction configuration
**Files:**
- Modify: `sql/20260714_cargo_area_direction.sql`
- Create: `sql/20260714_warehouse_03_inbound_lane_allocation.sql`
- Modify: `ruoyi-admin/src/test/java/com/ruoyi/bas/cargospace/mapper/CargoAreaDirectionMigrationSqlTest.java`
- [ ] **Step 1: Write the failing direction migration test**
Assert final values `A=1`, `B=1`, `C=1`, `D=2`, `E=1`, `F=2`, `G=2`, and `H=2`, with active state `1`, and assert the migration is idempotent.
- [ ] **Step 2: Run the focused test and verify failure**
Run: `mvn -pl ruoyi-admin -Dtest=CargoAreaDirectionMigrationSqlTest test`
Expected: FAIL because all eight current defaults are direction `1`.
- [ ] **Step 3: Implement and apply the migration**
Use a `MERGE`/guarded update inside `TRY/CATCH` transaction handling. Preserve the existing table and unrelated warehouses. Add only supporting nonclustered indexes that are absent. Execute against the configured disposable/current schema and query the eight rows afterward.
- [ ] **Step 4: Run the direction test and verify pass**
Run: `mvn -pl ruoyi-admin -Dtest=CargoAreaDirectionMigrationSqlTest test`
Expected: PASS.
### Task 6: End-to-end verification and completion audit
**Files:**
- Verify all files above; no additional production changes unless a failing check exposes a gap.
- [ ] **Step 1: Run all backend tests**
Run: `mvn test`
Expected: BUILD SUCCESS with every test passing.
- [ ] **Step 2: Run synthetic SQL business scenarios in a rollback transaction**
Create isolated warehouse-03 fixture lanes and prove: empty tray chooses only empty/empty-tray lanes; projectless raw material rejects a different code or name; purchase project and production project accept the same project lane and reject another project; active jobs and status-3 reservations block incompatible allocations; each A-H area returns its configured first column. Roll back all fixture data.
- [ ] **Step 3: Verify the deployed direction rows**
Query `bas_cargo_area_config` for warehouse `03` ordered A-H and confirm `1,1,1,2,1,2,2,2`.
- [ ] **Step 4: Audit every explicit requirement**
Map each of the four user modes, the two inbound types, all eight directions, other-warehouse preservation, completed/in-flight occupancy, and concurrent allocation to a passing test or database result. Do not mark completion if any item lacks direct evidence.