# Employee Asset Maintenance Backend Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

**Goal:** Add backend support for employee asset maintenance, including aggregated employee detail/save, employee-asset cascade delete by employee family ID card, and asynchronous asset import that auto-resolves the owning employee from the asset holder ID card.

**Architecture:** Keep employee maintenance on the existing `CcdiBaseStaff` aggregate, and introduce a new `CcdiAssetInfo` resource in `ccdi-info-collection`. Asset rows use `family_id` for the owning employee ID card and `person_id` for the actual holder ID card. Employee add/edit/detail/delete will orchestrate asset persistence by `family_id` inside transactions, while asset import will mirror the existing employee import flow and resolve `family_id` from either the employee table or the employee family-relation table.

**Tech Stack:** Java 21, Spring Boot 3, MyBatis Plus, XML mapper SQL, EasyExcel, Redis, Maven

---

### Task 1: Add the asset table SQL and document the data contract

**Files:**
- Create: `sql/2026-03-12_ccdi_asset_info.sql`
- Review: `assets/资产信息表.csv`
- Review: `docs/plans/2026-03-12-employee-asset-maintenance-design.md`

**Step 1: Write the SQL script**

Create `ccdi_asset_info` with:

- `asset_id BIGINT` auto increment primary key
- `family_id VARCHAR(18)` storing owning employee `id_card`
- `person_id VARCHAR(18)` storing actual asset holder `id_card`
- business columns from the approved design
- audit columns `create_by`, `create_time`, `update_by`, `update_time`
- indexes `idx_family_id`, `idx_person_id`, and `idx_asset_main_type`

**Step 2: Verify the script matches the approved constraints**

Confirm the script:

- does not include `asset_id` in any import-facing note
- keeps the field names `family_id` and `person_id`
- stores owning employee linkage in `family_id`
- stores actual holder linkage in `person_id`

**Step 3: Commit**

```bash
git add sql/2026-03-12_ccdi_asset_info.sql docs/plans/2026-03-12-employee-asset-maintenance-design.md
git commit -m "新增员工资产信息设计与建表脚本"
```

### Task 2: Add the asset domain, DTO, VO, Excel, and mapper skeletons

**Files:**
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/CcdiAssetInfo.java`
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiAssetInfoDTO.java`
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiAssetInfoVO.java`
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiAssetInfoExcel.java`
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/AssetImportFailureVO.java`
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/mapper/CcdiAssetInfoMapper.java`
- Create: `ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiAssetInfoMapper.xml`

**Step 1: Create the entity**

Model `CcdiAssetInfo` with MyBatis Plus annotations and audit fields consistent with existing `CcdiBaseStaff`.

**Step 2: Create request and response objects**

Add one DTO for nested employee-form submission and one VO for employee detail response.

**Step 3: Create the Excel and failure record objects**

`CcdiAssetInfoExcel` must exclude `asset_id` and include `person_id`.

It must not require `family_id` in the import template because `family_id` is resolved automatically during import.

**Step 4: Create mapper methods**

Define methods for:

- query by `family_id`
- delete by `family_id`
- delete by `family_id` list
- query by `person_id`
- batch insert
- import lookup by employee `id_card`
- import lookup by employee family-relation ID card

### Task 3: Extend employee DTO and VO aggregation

**Files:**
- Modify: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiBaseStaffAddDTO.java`
- Modify: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiBaseStaffEditDTO.java`
- Modify: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiBaseStaffVO.java`
- Test: `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffServiceAssetAggregationTest.java`

**Step 1: Write the failing test**

Add a focused service test that asserts employee detail, add DTO, and edit DTO support `assetInfoList`.

**Step 2: Run test to verify it fails**

Run:

```bash
mvn test -Dtest=CcdiBaseStaffServiceAssetAggregationTest
```

Expected: FAIL because `assetInfoList` does not exist yet.

**Step 3: Add the aggregate fields**

Add `List<CcdiAssetInfoDTO>` to add/edit DTOs and `List<CcdiAssetInfoVO>` to the employee VO.

**Step 4: Run test to verify it passes**

Run:

```bash
mvn test -Dtest=CcdiBaseStaffServiceAssetAggregationTest
```

Expected: PASS

### Task 4: Add asset service interfaces and focused persistence methods

**Files:**
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiAssetInfoService.java`
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiAssetInfoImportService.java`
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiAssetInfoServiceImpl.java`
- Test: `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiAssetInfoServiceImplTest.java`

**Step 1: Write the failing test**

Cover these behaviors:

- query all assets by `family_id`
- replace all assets for one employee
- delete assets by one or more employee ID cards
- ignore empty rows when replacing assets
- preserve `person_id` as the actual holder while forcing `family_id` to the owning employee ID card

**Step 2: Run test to verify it fails**

Run:

```bash
mvn test -Dtest=CcdiAssetInfoServiceImplTest
```

Expected: FAIL because the asset service does not exist yet.

**Step 3: Implement minimal service logic**

Implement methods:

- `selectByFamilyId`
- `replaceByFamilyId`
- `deleteByFamilyId`
- `deleteByFamilyIds`

Use batch delete + batch insert.

**Step 4: Run test to verify it passes**

Run:

```bash
mvn test -Dtest=CcdiAssetInfoServiceImplTest
```

Expected: PASS

### Task 5: Update employee service to aggregate asset query and transactional save

**Files:**
- Modify: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiBaseStaffService.java`
- Modify: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiBaseStaffServiceImpl.java`
- Modify: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiBaseStaffController.java`
- Test: `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffServiceImplTest.java`

**Step 1: Write the failing test**

Add or extend service tests for:

- add employee with multiple assets
- edit employee and replace assets
- edit employee with changed `id_card`
- detail query returns `assetInfoList`
- delete employee cascades asset deletion
- employee self-owned asset uses `family_id = person_id = employee.idCard`
- employee family asset uses `family_id = employee.idCard` and `person_id = relative.idCard`

**Step 2: Run test to verify it fails**

Run:

```bash
mvn test -Dtest=CcdiBaseStaffServiceImplTest
```

Expected: FAIL because employee service does not yet coordinate asset persistence.

**Step 3: Implement the aggregate behavior**

Update `CcdiBaseStaffServiceImpl` to:

- inject `ICcdiAssetInfoService`
- load assets during detail query by `family_id = employee.id_card`
- save employee first, then replace assets by current employee `id_card`
- for each asset row, set `family_id = employee.id_card` and preserve submitted `person_id`
- capture old `id_card` during edit and clean old asset records when it changes
- delete asset rows before deleting employee rows

**Step 4: Run the focused test again**

Run:

```bash
mvn test -Dtest=CcdiBaseStaffServiceImplTest
```

Expected: PASS

### Task 6: Add asset import controller and async import service

**Files:**
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiAssetInfoController.java`
- Create: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiAssetInfoImportServiceImpl.java`
- Modify: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiAssetInfoImportService.java`
- Test: `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiAssetInfoImportServiceImplTest.java`

**Step 1: Write the failing test**

Cover:

- import template entity excludes `asset_id`
- import template does not require `family_id`
- import resolves `family_id` when `person_id` matches an employee `id_card`
- import resolves `family_id` when `person_id` matches an employee family-relation ID card
- import fails when `person_id` does not match either an employee or an employee family-relation ID card
- import fails when one `person_id` maps to multiple employees
- import stores failure records only for bad rows
- import status and failure list use dedicated asset task keys

**Step 2: Run test to verify it fails**

Run:

```bash
mvn test -Dtest=CcdiAssetInfoImportServiceImplTest
```

Expected: FAIL because no asset import pipeline exists yet.

**Step 3: Implement the import flow**

Mirror the employee import design with asset-specific names:

- Redis key prefix `import:assetInfo:`
- asynchronous import execution
- failure record caching for 7 days
- controller endpoints for template, upload, status, and failures
- resolve `family_id` automatically from `person_id`

**Step 4: Run the focused test again**

Run:

```bash
mvn test -Dtest=CcdiAssetInfoImportServiceImplTest
```

Expected: PASS

### Task 7: Add mapper XML SQL for batch asset operations

**Files:**
- Modify: `ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiAssetInfoMapper.xml`
- Test: `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/mapper/CcdiAssetInfoMapperTest.java`

**Step 1: Write the failing test**

Verify:

- select by `family_id`
- select by `person_id`
- batch insert multiple assets
- delete by one `family_id`
- delete by multiple `family_id` values
- employee existence lookup by `id_card`
- employee family-relation existence lookup by relative `id_card`

**Step 2: Run test to verify it fails**

Run:

```bash
mvn test -Dtest=CcdiAssetInfoMapperTest
```

Expected: FAIL because the mapper XML SQL is incomplete.

**Step 3: Implement minimal XML SQL**

Add:

- result map
- select by `family_id`
- select by `person_id`
- delete by `family_id`
- delete by `family_id` list
- batch insert
- employee existence lookup
- employee family-relation lookup

**Step 4: Run the mapper test**

Run:

```bash
mvn test -Dtest=CcdiAssetInfoMapperTest
```

Expected: PASS

### Task 8: Verify the backend changes end to end

**Files:**
- Modify: `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/`
- Modify: `ccdi-info-collection/src/main/resources/mapper/info/collection/`
- Modify: `sql/2026-03-12_ccdi_asset_info.sql`

**Step 1: Run focused backend tests**

Run:

```bash
mvn test -Dtest=CcdiBaseStaffServiceAssetAggregationTest,CcdiAssetInfoServiceImplTest,CcdiBaseStaffServiceImplTest,CcdiAssetInfoImportServiceImplTest,CcdiAssetInfoMapperTest
```

Expected: all focused tests pass.

**Step 2: Run module compile verification**

Run:

```bash
mvn clean compile
```

Expected: compile succeeds without Java or mapper XML errors.

**Step 3: Commit**

```bash
git add sql/2026-03-12_ccdi_asset_info.sql ccdi-info-collection/src/main/java/com/ruoyi/info/collection ccdi-info-collection/src/main/resources/mapper/info/collection docs/plans/2026-03-12-employee-asset-maintenance-backend-implementation.md
git commit -m "新增员工资产信息后端实施计划"
```
