9.7 KiB
File Upload FileId Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Add a reusable file upload module that stores uploaded files under /home/tms/uploads, returns fileId, and keeps CISD initialization flowing through existing fileId fields.
Architecture: Introduce a small modules/file module with internal upload and query APIs, one metadata table, and a service that owns fileId generation plus filesystem persistence. Keep the init module unchanged at the API boundary except for sharing the same upload storage root and documenting the front-end workflow.
Tech Stack: Spring Boot MVC multipart upload, MyBatis-Plus repository pattern, Flyway SQL migration, JUnit 5
Task 1: Add file upload persistence contract
Files:
- Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/db/migration/V3__create_sys_file_record.sql - Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/entity/FileRecordEntity.java - Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/repository/FileRecordRepository.java - Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/mapper/file/FileRecordMapper.xml - Test:
/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java
Step 1: Write the failing test
Add a test that expects file metadata to be persisted with:
- generated
fileId - original file name
- absolute storage path
ACTIVEstatus
Step 2: Run test to verify it fails
Run: mvn -q -Dtest=FileServiceTest#shouldPersistUploadedFileMetadata test
Expected: FAIL because file module classes and table mapping do not exist.
Step 3: Write minimal implementation
Implement the entity, mapper/repository, and migration with only the fields needed by upload/query.
Step 4: Run test to verify it passes
Run: mvn -q -Dtest=FileServiceTest#shouldPersistUploadedFileMetadata test
Expected: PASS
Step 5: Commit
git add src/main/resources/db/migration/V3__create_sys_file_record.sql \
src/main/java/com/cisd/tms/modules/file/entity/FileRecordEntity.java \
src/main/java/com/cisd/tms/modules/file/repository/FileRecordRepository.java \
src/main/resources/mapper/file/FileRecordMapper.xml \
src/test/java/com/cisd/tms/modules/file/FileServiceTest.java
git commit -m "feat: add file upload persistence contract"
Task 2: Implement upload service
Files:
- Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/service/FileService.java - Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/dto/FileUploadResponse.java - Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/dto/FileDetailResponse.java - Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/common/config/properties/FileStorageProperties.java - Modify:
/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml - Modify:
/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example - Test:
/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java
Step 1: Write the failing test
Add tests that assert:
- uploaded file is saved under
<upload-base-dir>/<fileId>/<originalFilename> - blank file upload is rejected
- oversize upload is rejected
- returned DTO contains
fileId, size, storagePath
Step 2: Run test to verify it fails
Run: mvn -q -Dtest=FileServiceTest test
Expected: FAIL because service and properties do not exist.
Step 3: Write minimal implementation
Implement:
fileIdgeneration- file name sanitization
- directory creation
- file save
- metadata insert
- detail query by
fileId
Step 4: Run test to verify it passes
Run: mvn -q -Dtest=FileServiceTest test
Expected: PASS
Step 5: Commit
git add src/main/java/com/cisd/tms/modules/file/service/FileService.java \
src/main/java/com/cisd/tms/modules/file/dto/FileUploadResponse.java \
src/main/java/com/cisd/tms/modules/file/dto/FileDetailResponse.java \
src/main/java/com/cisd/tms/common/config/properties/FileStorageProperties.java \
src/main/resources/application.yml config/application.yml.example \
src/test/java/com/cisd/tms/modules/file/FileServiceTest.java
git commit -m "feat: implement file upload service"
Task 3: Expose internal file APIs
Files:
- Create:
/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/file/controller/internal/FileInternalController.java - Modify:
/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileServiceTest.java - Create:
/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java
Step 1: Write the failing test
Add controller tests for:
POST /api/v1/files/uploadGET /api/v1/files/{fileId}
Verify upload uses multipart, returns ApiResponse, and query returns stored metadata.
Step 2: Run test to verify it fails
Run: mvn -q -Dtest=FileInternalControllerTest test
Expected: FAIL because controller does not exist.
Step 3: Write minimal implementation
Expose two endpoints only:
- upload
- detail query
Keep them internal-only under /api/v1/files.
Step 4: Run test to verify it passes
Run: mvn -q -Dtest=FileInternalControllerTest test
Expected: PASS
Step 5: Commit
git add src/main/java/com/cisd/tms/modules/file/controller/internal/FileInternalController.java \
src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java \
src/test/java/com/cisd/tms/modules/file/FileServiceTest.java
git commit -m "feat: expose internal file upload api"
Task 4: Align init module with shared upload root and docs
Files:
- Modify:
/Users/waner/Work/CISD/文档/tms-framework/src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java - Modify:
/Users/waner/Work/CISD/文档/tms-framework/src/main/resources/application.yml - Modify:
/Users/waner/Work/CISD/文档/tms-framework/config/application.yml.example - Modify:
/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.yaml - Modify:
/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.json - Modify:
/Users/waner/Work/CISD/文档/tms-framework/README.md - Test:
/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java
Step 1: Write the failing test
Add or update tests to assert:
- init executor upload root matches the shared upload root config
- docs clearly state init APIs accept
fileId, not multipart files - README documents front-end flow: upload first, then create init task
Step 2: Run test to verify it fails
Run: mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentInitFileIdFlow test
Expected: FAIL because docs/config are not aligned yet.
Step 3: Write minimal implementation
Align configuration and docs without changing init request DTO semantics.
Step 4: Run test to verify it passes
Run: mvn -q -Dtest=ConfigurableInitStepExecutorTest#shouldDocumentInitFileIdFlow test
Expected: PASS
Step 5: Commit
git add src/main/java/com/cisd/tms/modules/init/config/InitExecutorProperties.java \
src/main/resources/application.yml config/application.yml.example \
docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json README.md \
src/test/java/com/cisd/tms/modules/init/executor/ConfigurableInitStepExecutorTest.java
git commit -m "docs: align init fileId flow with upload api"
Task 5: Add upload API OpenAPI spec
Files:
- Modify:
/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.yaml - Modify:
/Users/waner/Work/CISD/文档/tms-framework/docs/openapi/cisd-init.openapi.json - Test:
/Users/waner/Work/CISD/文档/tms-framework/src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java
Step 1: Write the failing test
Add a documentation test or assertion that the upload route and response fields are present in the OpenAPI output.
Step 2: Run test to verify it fails
Run: mvn -q -Dtest=FileInternalControllerTest#shouldDocumentUploadApi test
Expected: FAIL because the route is not documented yet.
Step 3: Write minimal implementation
Document:
- upload API
- query API
- multipart request
fileIdresponse- init API references to upload-first workflow
Step 4: Run test to verify it passes
Run: mvn -q -Dtest=FileInternalControllerTest#shouldDocumentUploadApi test
Expected: PASS
Step 5: Commit
git add docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json \
src/test/java/com/cisd/tms/modules/file/FileInternalControllerTest.java
git commit -m "docs: add file upload api spec"
Task 6: Final verification
Files:
- Verify only
Step 1: Run file module tests
Run: mvn -q -Dtest=FileServiceTest,FileInternalControllerTest test
Expected: PASS
Step 2: Run init-related tests
Run: mvn -q -Dtest=InitServiceTest,ConfigurableInitStepExecutorTest test
Expected: PASS
Step 3: Run compile
Run: mvn -q -DskipTests compile
Expected: PASS
Step 4: Review focused diff
Run: git diff -- src/main/java/com/cisd/tms/modules/file src/main/resources/db/migration/V3__create_sys_file_record.sql src/main/resources/mapper/file src/main/resources/application.yml config/application.yml.example README.md docs/openapi/cisd-init.openapi.yaml docs/openapi/cisd-init.openapi.json
Expected: only file upload module, config, README, and OpenAPI/doc alignment changes.