feat: 完善WCS调度、库存追溯和出库分配

This commit is contained in:
zgw
2026-07-15 16:24:07 +08:00
parent 9d3aa7a3bd
commit 66ac268524
101 changed files with 12596 additions and 669 deletions

View File

@@ -0,0 +1,186 @@
# 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.