Files
FTC25009/docs/superpowers/plans/2026-07-14-project-no-traceability.md

8.0 KiB

Project Number Traceability 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: Add a standalone project_no field and preserve it from inbound document creation through inbound details, job details, and inventory master/detail records.

Architecture: The inbound master form is the single input point. The backend copies the master value to every inbound detail, SQL Server procedures carry the detail value into job details and inventory rows, and Java/MyBatis models expose the value consistently as projectNo. Archive tables receive the same column because current completion procedures archive with INSERT ... SELECT *.

Tech Stack: Vue 2 + Element UI, Spring Boot/Java 17, MyBatis XML, SQL Server, JUnit 5/Mockito/AssertJ


Task 1: Lock down the project-number propagation contract

Files:

  • Modify: ruoyi-admin/src/test/java/com/ruoyi/in/stockin/service/impl/InStockinServiceImplTest.java

  • Modify: ruoyi-admin/src/test/java/com/ruoyi/in/job/mapper/MydoJobMapperSqlTest.java

  • Create: ruoyi-admin/src/test/java/com/ruoyi/in/stockin/mapper/ProjectNoMapperSqlTest.java

  • Step 1: Add a service test that verifies the master project number is copied to each inbound detail

saveDTO.setProjectNo("PRJ-001");
service.saveInStockinWithDetails(saveDTO);
assertThat(detailCaptor.getValue().getProjectNo()).isEqualTo("PRJ-001");
  • Step 2: Add mapper/procedure text tests for all required columns and transfers
assertThat(inStockinMapperXml).contains("project_no", "#{projectNo}");
assertThat(jobDetailMapperXml).contains("project_no", "#{projectNo}");
assertThat(stockMapperXml).contains("project_no", "#{projectNo}");
assertThat(projectMigrationSql)
    .contains("in_stockin", "in_stockin_detail", "mydo_job_detail")
    .contains("bas_stock", "bas_stock_detail");
  • Step 3: Run focused tests and verify they fail before implementation

Run: mvn -pl ruoyi-admin -Dtest=InStockinServiceImplTest,ProjectNoMapperSqlTest,MydoJobMapperSqlTest test

Expected: FAIL because projectNo properties, SQL mappings, and migration do not exist yet.

Task 2: Add the database migration and procedure propagation

Files:

  • Create: sql/20260714_project_no_traceability.sql

  • Modify: sql/proc_add_in_job_trace.sql

  • Modify: sql/bas_stock_master_detail.sql

  • Step 1: Add nullable project-number columns idempotently

IF COL_LENGTH(N'dbo.in_stockin', N'project_no') IS NULL
    ALTER TABLE dbo.in_stockin ADD project_no nvarchar(80) NULL;

Repeat for in_stockin_detail, in_stockin_finish, in_stockin_detail_finish, mydo_job_detail, mydo_job_detail_finish, bas_stock, and bas_stock_detail.

  • Step 2: Backfill existing traceable rows
UPDATE d
SET d.project_no = h.project_no
FROM dbo.in_stockin_detail d
JOIN dbo.in_stockin h ON h.stockin_id = d.stockin_id
WHERE d.project_no IS NULL AND h.project_no IS NOT NULL;

Backfill job details from inbound details, inventory details from job/inbound details, and inventory masters from their inventory details.

  • Step 3: Update proc_add_in_job to copy in_stockin_detail.project_no into mydo_job_detail.project_no
SELECT ..., d.project_no
FROM dbo.in_tray_msg tm
LEFT JOIN dbo.in_stockin_detail d ON tm.stockin_detail_id = d.stockin_detail_id;

INSERT INTO dbo.mydo_job_detail (..., project_no)
VALUES (..., @project_no);
  • Step 4: Update proc_complete_in_job to copy the job detail project number into inventory master and detail rows
INSERT INTO bas_stock (..., project_no)
VALUES (..., @project_no);

INSERT INTO bas_stock_detail (..., project_no)
VALUES (..., @project_no);
  • Step 5: Keep baseline procedure scripts consistent with the deployable migration

Update the existing standalone procedure scripts with the same cursor variables, selected columns, and insert columns.

Task 3: Expose projectNo in backend entities and MyBatis mappings

Files:

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/in/stockin/domain/InStockin.java

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/in/sotckindetail/domain/InStockinDetail.java

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/in/jobdetail/domain/MydoJobDetail.java

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/bas/stock/domain/BasStock.java

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/bas/stock/domain/BasStockDetail.java

  • Modify: ruoyi-admin/src/main/resources/mapper/in/InStockinMapper.xml

  • Modify: ruoyi-admin/src/main/resources/mapper/in/InStockinDetailMapper.xml

  • Modify: ruoyi-admin/src/main/resources/mapper/in/MydoJobDetailMapper.xml

  • Modify: ruoyi-admin/src/main/resources/mapper/bas/BasStockMapper.xml

  • Modify: ruoyi-admin/src/main/resources/mapper/bas/BasStockDetailMapper.xml

  • Step 1: Add the Java property to all five domain models

/** 项目号 */
@Excel(name = "项目号")
private String projectNo;

public String getProjectNo() { return projectNo; }
public void setProjectNo(String projectNo) { this.projectNo = projectNo; }
  • Step 2: Add project_no to every result map, select list, query filter, insert, and update section
<result property="projectNo" column="project_no" />
<if test="projectNo != null and projectNo != ''">project_no,</if>
<if test="projectNo != null and projectNo != ''">#{projectNo},</if>
  • Step 3: Run mapper contract tests

Run: mvn -pl ruoyi-admin -Dtest=ProjectNoMapperSqlTest test

Expected: PASS.

Task 4: Copy the master project number to inbound details and support the create form

Files:

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/in/stockin/service/impl/InStockinServiceImpl.java

  • Modify: ruoyi-ui/src/views/in/add/index.vue

  • Step 1: Enforce server-side master-to-detail copying

detail.setStockinId(saveDTO.getStockinId());
detail.setProjectNo(saveDTO.getProjectNo());
  • Step 2: Add the project-number input to the main inbound form
<el-form-item label="项目号" prop="projectNo">
  <el-input v-model="mainForm.projectNo" placeholder="请输入项目号" clearable />
</el-form-item>
  • Step 3: Include projectNo in the form model and detail payload
mainForm: { projectNo: null }
// detail DTO
projectNo: this.mainForm.projectNo
  • Step 4: Run the inbound service test

Run: mvn -pl ruoyi-admin -Dtest=InStockinServiceImplTest test

Expected: PASS and the captured detail contains the master projectNo.

Task 5: Preserve project number when jobs are created from existing inventory

Files:

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/out/location/service/impl/LocationOutboundServiceImpl.java

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/pd/stockpd/service/impl/PdStockpdServiceImpl.java

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/pda/service/impl/PdaServiceImpl.java

  • Step 1: Copy inventory-detail project numbers into outbound and inventory job details

jobDetail.setProjectNo(stockDetail.getProjectNo());
  • Step 2: Include projectNo in inventory material map queries used for return jobs and copy it into return-job details
returnDetail.setProjectNo(mapString(material, "projectNo"));
  • Step 3: Run focused service tests

Run: mvn -pl ruoyi-admin -Dtest=LocationOutboundServiceImplTest,PdStockpdServiceImplTest,PdaServiceImplTest test

Expected: PASS.

Task 6: Verify the end-to-end change

Files:

  • Verify: all files listed above

  • Step 1: Run all backend tests

Run: mvn -pl ruoyi-admin test

Expected: BUILD SUCCESS.

  • Step 2: Build the frontend production bundle

Run: cd ruoyi-ui && npm run build:prod

Expected: Build completes successfully.

  • Step 3: Inspect the final diff for unrelated or overwritten work

Run: git diff --check && git status --short

Expected: no whitespace errors; existing user changes remain intact.