187 lines
6.8 KiB
Markdown
187 lines
6.8 KiB
Markdown
# Cargo Area Direction 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:** Convert warehouse 03 cargo-area codes from `1`–`8` to `A`–`H`, add configurable access directions, and apply those directions to dense-storage inbound and outbound candidate ordering.
|
||
|
||
**Architecture:** `bas_cargo_area_config` is the source of truth per warehouse and area. Direction values are `1` (small-to-large), `2` (large-to-small), and `3` (both ends); missing configuration falls back to `1` so other warehouses and existing behavior remain stable. Warehouse 03 cargo spaces are migrated transactionally, and both current allocation SQL paths join the configuration table.
|
||
|
||
**Tech Stack:** SQL Server, Spring Boot/Java 17, MyBatis XML, Vue 2, JUnit 5/AssertJ, Playwright
|
||
|
||
---
|
||
|
||
### Task 1: Define executable migration contracts
|
||
|
||
**Files:**
|
||
- Create: `ruoyi-admin/src/test/java/com/ruoyi/bas/cargospace/mapper/CargoAreaDirectionMigrationSqlTest.java`
|
||
- Modify: `ruoyi-admin/src/test/java/com/ruoyi/pda/mapper/PdaMapperSqlTest.java`
|
||
- Modify: `ruoyi-admin/src/test/java/com/ruoyi/bas/cargospace/mapper/BasCargoSpaceMapperSqlTest.java`
|
||
|
||
- [ ] **Step 1: Add migration assertions for table structure, A-H conversion, and seed directions**
|
||
|
||
```java
|
||
assertThat(sql)
|
||
.contains("create table dbo.bas_cargo_area_config")
|
||
.contains("direction_type")
|
||
.contains("nchar(unicode(n'a')")
|
||
.contains("n'a'", "n'h'");
|
||
```
|
||
|
||
- [ ] **Step 2: Add mapper assertions for all three direction branches**
|
||
|
||
```java
|
||
assertThat(lockSql)
|
||
.contains("bas_cargo_area_config")
|
||
.contains("when '1' then")
|
||
.contains("when direction_type = '2'")
|
||
.contains("when direction_type = '3'");
|
||
```
|
||
|
||
- [ ] **Step 3: Run focused tests before implementation**
|
||
|
||
Run: `mvn -pl ruoyi-admin -am -Dtest=CargoAreaDirectionMigrationSqlTest,PdaMapperSqlTest,BasCargoSpaceMapperSqlTest -Dsurefire.failIfNoSpecifiedTests=false test`
|
||
|
||
Expected: FAIL until the migration and mapper ordering exist.
|
||
|
||
### Task 2: Create and seed cargo-area direction configuration
|
||
|
||
**Files:**
|
||
- Create: `sql/20260714_cargo_area_direction.sql`
|
||
- Modify: `sql/20260714_warehouse_03_cargo_spaces.sql`
|
||
|
||
- [ ] **Step 1: Create the configuration table with a unique warehouse/area key**
|
||
|
||
```sql
|
||
CREATE TABLE dbo.bas_cargo_area_config (
|
||
id bigint IDENTITY(1,1) NOT NULL PRIMARY KEY,
|
||
warehouse_id nvarchar(80) NOT NULL,
|
||
cargo_area_code nvarchar(10) NOT NULL,
|
||
cargo_area_name nvarchar(80) NOT NULL,
|
||
direction_type nvarchar(2) NOT NULL,
|
||
is_active nchar(1) NOT NULL CONSTRAINT DF_bas_cargo_area_config_active DEFAULT N'1',
|
||
create_by nvarchar(64) NULL,
|
||
create_time datetime2(3) NULL,
|
||
update_by nvarchar(64) NULL,
|
||
update_time datetime2(3) NULL,
|
||
remark nvarchar(500) NULL,
|
||
CONSTRAINT UQ_bas_cargo_area_config UNIQUE (warehouse_id, cargo_area_code),
|
||
CONSTRAINT CK_bas_cargo_area_config_direction CHECK (direction_type IN (N'1', N'2', N'3'))
|
||
);
|
||
```
|
||
|
||
- [ ] **Step 2: Convert warehouse 03 numeric codes to letters transactionally**
|
||
|
||
```sql
|
||
UPDATE dbo.bas_cargo_space
|
||
SET this_cargo_area = NCHAR(UNICODE(N'A') + TRY_CONVERT(int, this_cargo_area) - 1)
|
||
WHERE warehouse_id = N'03'
|
||
AND TRY_CONVERT(int, this_cargo_area) BETWEEN 1 AND 8;
|
||
```
|
||
|
||
- [ ] **Step 3: Seed A-H with direction `1` to preserve current ordering**
|
||
|
||
```sql
|
||
INSERT INTO dbo.bas_cargo_area_config (warehouse_id, cargo_area_code, cargo_area_name, direction_type, is_active)
|
||
SELECT N'03', area_code, area_code + N'货区', N'1', N'1'
|
||
FROM (VALUES (N'A'),(N'B'),(N'C'),(N'D'),(N'E'),(N'F'),(N'G'),(N'H')) x(area_code);
|
||
```
|
||
|
||
- [ ] **Step 4: Make the warehouse-03 generator emit A-H directly**
|
||
|
||
Use `NCHAR(UNICODE(N'A') + area_number - 1)` instead of converting the area number to text.
|
||
|
||
### Task 3: Apply direction to inbound allocation
|
||
|
||
**Files:**
|
||
- Modify: `ruoyi-admin/src/main/resources/mapper/pda/PdaMapper.xml`
|
||
- Modify: `ruoyi-admin/src/main/resources/mapper/bas/BasCargoSpaceMapper.xml`
|
||
|
||
- [ ] **Step 1: Join active area configuration in the atomic WCS allocator**
|
||
|
||
```sql
|
||
LEFT JOIN bas_cargo_area_config cac
|
||
ON cac.warehouse_id = bcs.warehouse_id
|
||
AND cac.cargo_area_code = bcs.this_cargo_area
|
||
AND cac.is_active = N'1'
|
||
```
|
||
|
||
- [ ] **Step 2: Calculate each area's column bounds and order by direction**
|
||
|
||
```sql
|
||
CASE WHEN direction_type = N'1' THEN the_column END ASC,
|
||
CASE WHEN direction_type = N'2' THEN the_column END DESC,
|
||
CASE WHEN direction_type = N'3'
|
||
THEN CASE WHEN the_column - area_min_column <= area_max_column - the_column
|
||
THEN the_column - area_min_column ELSE area_max_column - the_column END
|
||
END ASC
|
||
```
|
||
|
||
- [ ] **Step 3: Apply identical fallback ordering to occupied-location reallocation**
|
||
|
||
Keep height priority and platoon balancing ahead of the direction-specific column order.
|
||
|
||
### Task 4: Apply direction to outbound inventory candidates
|
||
|
||
**Files:**
|
||
- Modify: `sql/out_stockout_flow.sql`
|
||
|
||
- [ ] **Step 1: Join area configuration and derive area bounds in manual allocation**
|
||
|
||
```sql
|
||
LEFT JOIN dbo.bas_cargo_area_config cac
|
||
ON cac.warehouse_id = bs.warehouse_id
|
||
AND cac.cargo_area_code = bcs.this_cargo_area
|
||
AND cac.is_active = N'1'
|
||
```
|
||
|
||
- [ ] **Step 2: Put direction ordering before FIFO tie breakers**
|
||
|
||
Order by configured column direction, then `bs.in_date`, `bs.cargo_space_id`, and `bsd.detail_id`.
|
||
|
||
- [ ] **Step 3: Apply the same ordering to automatic allocation cursor candidates**
|
||
|
||
Use the same `1`/`2`/`3` CASE expressions in both outbound procedures.
|
||
|
||
### Task 5: Update dense-map area labels
|
||
|
||
**Files:**
|
||
- Modify: `ruoyi-ui/src/views/kpi/plan/components/DenseCargoSpaceMap.vue`
|
||
- Modify: `scripts/verify_dense_cargo_space_plan.py`
|
||
|
||
- [ ] **Step 1: Display letter area codes without numeric padding or the old `Z` prefix**
|
||
|
||
```vue
|
||
<span v-if="activeLocation.thisCargoArea">货区 {{ activeLocation.thisCargoArea }}</span>
|
||
```
|
||
|
||
- [ ] **Step 2: Add browser assertions for A-H values**
|
||
|
||
Click an ordinary node and assert the footer contains `货区 A`–`货区 H`, never `区域 Z`.
|
||
|
||
### Task 6: Verify and deploy
|
||
|
||
**Files:**
|
||
- Verify: all files above
|
||
|
||
- [ ] **Step 1: Run focused backend tests**
|
||
|
||
Run: `mvn -pl ruoyi-admin -am -Dtest=CargoAreaDirectionMigrationSqlTest,PdaMapperSqlTest,BasCargoSpaceMapperSqlTest -Dsurefire.failIfNoSpecifiedTests=false test`
|
||
|
||
Expected: PASS.
|
||
|
||
- [ ] **Step 2: Execute the SQL migration in one database transaction**
|
||
|
||
Expected: warehouse 03 has exactly 1028 ordinary nodes with A-H and eight active configuration rows.
|
||
|
||
- [ ] **Step 3: Build the frontend**
|
||
|
||
Run: `cd ruoyi-ui && npm run build:prod`
|
||
|
||
Expected: build completes successfully.
|
||
|
||
- [ ] **Step 4: Run the dense-map browser verification**
|
||
|
||
Run: `python scripts/verify_dense_cargo_space_plan.py`
|
||
|
||
Expected: both floors render, no overflow occurs, A-H area labels display, and legacy warehouse rendering remains visible.
|