Files
ccdi/doc/requirements/plans/2026-02-06-ccdi_purchase_transaction.md
2026-02-09 14:28:25 +08:00

1211 lines
33 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 员工采购交易信息管理功能实施计划
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**目标:** 构建完整的员工采购交易信息管理模块支持CRUD操作、分页查询、异步导入导出、批量删除等功能
**架构:** 基于若依框架前后端分离架构后端使用MyBatis Plus + EasyExcel + Redis实现异步导入前端使用Vue 2 + Element UI
**技术栈:**
- 后端: Spring Boot 3.5.8, MyBatis Plus 3.5.10, EasyExcel, Redis
- 前端: Vue 2.6.12, Element UI 2.15.14, Axios
- 数据库: MySQL 8.2.0
---
## 前置条件
### 参考文档
- 员工招聘信息模块: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/**/CcdiStaffRecruitment*`
- 员工异步导入实现: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiEmployeeImportServiceImpl.java`
- 数据库表定义: `doc/docs/ccdi_purchase_transaction.csv`
### 数据库表结构
```sql
CREATE TABLE `ccdi_purchase_transaction` (
`purchase_id` VARCHAR(32) NOT NULL COMMENT '采购事项ID',
`purchase_category` VARCHAR(50) NOT NULL COMMENT '采购类别',
`project_name` VARCHAR(200) DEFAULT NULL COMMENT '项目名称',
`subject_name` VARCHAR(200) NOT NULL COMMENT '标的物名称',
`subject_desc` TEXT COMMENT '标的物描述',
`purchase_qty` DECIMAL(12,4) NOT NULL DEFAULT 1 COMMENT '采购数量',
`budget_amount` DECIMAL(18,2) NOT NULL COMMENT '预算金额',
`bid_amount` DECIMAL(18,2) DEFAULT NULL COMMENT '中标金额',
`actual_amount` DECIMAL(18,2) DEFAULT NULL COMMENT '实际采购金额',
`contract_amount` DECIMAL(18,2) DEFAULT NULL COMMENT '合同金额',
`settlement_amount` DECIMAL(18,2) DEFAULT NULL COMMENT '结算金额',
`purchase_method` VARCHAR(50) NOT NULL COMMENT '采购方式',
`supplier_name` VARCHAR(200) DEFAULT NULL COMMENT '中标供应商名称',
`contact_person` VARCHAR(50) DEFAULT NULL COMMENT '供应商联系人',
`contact_phone` VARCHAR(20) DEFAULT NULL COMMENT '供应商联系电话',
`supplier_uscc` VARCHAR(18) DEFAULT NULL COMMENT '供应商统一信用代码',
`supplier_bank_account` VARCHAR(50) DEFAULT NULL COMMENT '供应商银行账户',
`apply_date` DATE NOT NULL COMMENT '采购申请日期',
`plan_approve_date` DATE DEFAULT NULL COMMENT '采购计划批准日期',
`announce_date` DATE DEFAULT NULL COMMENT '采购公告发布日期',
`bid_open_date` DATE DEFAULT NULL COMMENT '开标日期',
`contract_sign_date` DATE DEFAULT NULL COMMENT '合同签订日期',
`expected_delivery_date` DATE DEFAULT NULL COMMENT '预计交货日期',
`actual_delivery_date` DATE DEFAULT NULL COMMENT '实际交货日期',
`acceptance_date` DATE DEFAULT NULL COMMENT '验收日期',
`settlement_date` DATE DEFAULT NULL COMMENT '结算日期',
`applicant_id` VARCHAR(7) NOT NULL COMMENT '申请人工号',
`applicant_name` VARCHAR(50) NOT NULL COMMENT '申请人姓名',
`apply_department` VARCHAR(100) NOT NULL COMMENT '申请部门',
`purchase_leader_id` VARCHAR(7) DEFAULT NULL COMMENT '采购负责人工号',
`purchase_leader_name` VARCHAR(50) DEFAULT NULL COMMENT '采购负责人姓名',
`purchase_department` VARCHAR(100) DEFAULT NULL COMMENT '采购部门',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`created_by` VARCHAR(50) NOT NULL COMMENT '创建人',
`updated_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人',
PRIMARY KEY (`purchase_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工采购交易信息表';
```
---
## Task 1: 创建数据库表
**Files:**
- Modify: 执行SQL创建表
**Step 1: 连接数据库并创建表**
使用MCP连接MySQL数据库:
```bash
# 使用 mcp__mysql__connect_db 连接到数据库
# 然后执行上面的CREATE TABLE语句
```
**Step 2: 验证表创建**
```sql
SHOW CREATE TABLE ccdi_purchase_transaction;
```
Expected: 表结构正确创建
**Step 3: Commit**
```bash
git add sql/
git commit -m "feat: 添加员工采购交易信息表"
```
---
## Task 2: 创建实体类
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiPurchaseTransaction.java`
**Step 1: 创建实体类**
```java
package com.ruoyi.ccdi.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 员工采购交易信息对象 ccdi_purchase_transaction
*
* @author ruoyi
* @date 2026-02-06
*/
@Data
public class CcdiPurchaseTransaction implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 采购事项ID */
@TableId(type = IdType.INPUT)
private String purchaseId;
/** 采购类别 */
private String purchaseCategory;
/** 项目名称 */
private String projectName;
/** 标的物名称 */
private String subjectName;
/** 标的物描述 */
private String subjectDesc;
/** 采购数量 */
private BigDecimal purchaseQty;
/** 预算金额 */
private BigDecimal budgetAmount;
/** 中标金额 */
private BigDecimal bidAmount;
/** 实际采购金额 */
private BigDecimal actualAmount;
/** 合同金额 */
private BigDecimal contractAmount;
/** 结算金额 */
private BigDecimal settlementAmount;
/** 采购方式 */
private String purchaseMethod;
/** 中标供应商名称 */
private String supplierName;
/** 供应商联系人 */
private String contactPerson;
/** 供应商联系电话 */
private String contactPhone;
/** 供应商统一信用代码 */
private String supplierUscc;
/** 供应商银行账户 */
private String supplierBankAccount;
/** 采购申请日期 */
private LocalDate applyDate;
/** 采购计划批准日期 */
private LocalDate planApproveDate;
/** 采购公告发布日期 */
private LocalDate announceDate;
/** 开标日期 */
private LocalDate bidOpenDate;
/** 合同签订日期 */
private LocalDate contractSignDate;
/** 预计交货日期 */
private LocalDate expectedDeliveryDate;
/** 实际交货日期 */
private LocalDate actualDeliveryDate;
/** 验收日期 */
private LocalDate acceptanceDate;
/** 结算日期 */
private LocalDate settlementDate;
/** 申请人工号 */
private String applicantId;
/** 申请人姓名 */
private String applicantName;
/** 申请部门 */
private String applyDepartment;
/** 采购负责人工号 */
private String purchaseLeaderId;
/** 采购负责人姓名 */
private String purchaseLeaderName;
/** 采购部门 */
private String purchaseDepartment;
/** 创建时间 */
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/** 更新时间 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/** 创建人 */
@TableField(fill = FieldFill.INSERT)
private String createdBy;
/** 更新人 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updatedBy;
}
```
**Step 2: 验证编译**
```bash
cd ruoyi-ccdi
mvn compile -pl . -am
```
Expected: 编译成功,无错误
**Step 3: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/CcdiPurchaseTransaction.java
git commit -m "feat: 添加采购交易信息实体类"
```
---
## Task 3: 创建查询DTO
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionQueryDTO.java`
**Step 1: 创建查询DTO**
```java
package com.ruoyi.ccdi.domain.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
/**
* 采购交易信息查询DTO
*
* @author ruoyi
* @date 2026-02-06
*/
@Data
@Schema(description = "采购交易信息查询条件")
public class CcdiPurchaseTransactionQueryDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 项目名称 */
@Schema(description = "项目名称")
private String projectName;
/** 标的物名称 */
@Schema(description = "标的物名称")
private String subjectName;
/** 申请人姓名 */
@Schema(description = "申请人姓名")
private String applicantName;
/** 申请人工号 */
@Schema(description = "申请人工号")
private String applicantId;
/** 申请日期-开始 */
@Schema(description = "申请日期-开始")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate applyDateStart;
/** 申请日期-结束 */
@Schema(description = "申请日期-结束")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate applyDateEnd;
}
```
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionQueryDTO.java
git commit -m "feat: 添加采购交易查询DTO"
```
---
## Task 4: 创建新增DTO
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionAddDTO.java`
**Step 1: 创建新增DTO包含验证注解**
```java
package com.ruoyi.ccdi.domain.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* 采购交易信息新增DTO
*
* @author ruoyi
* @date 2026-02-06
*/
@Data
@Schema(description = "采购交易信息新增")
public class CcdiPurchaseTransactionAddDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "采购事项ID")
@NotBlank(message = "采购事项ID不能为空")
@Size(max = 32, message = "采购事项ID长度不能超过32个字符")
private String purchaseId;
@Schema(description = "采购类别")
@NotBlank(message = "采购类别不能为空")
@Size(max = 50, message = "采购类别长度不能超过50个字符")
private String purchaseCategory;
@Schema(description = "项目名称")
@Size(max = 200, message = "项目名称长度不能超过200个字符")
private String projectName;
@Schema(description = "标的物名称")
@NotBlank(message = "标的物名称不能为空")
@Size(max = 200, message = "标的物名称长度不能超过200个字符")
private String subjectName;
@Schema(description = "标的物描述")
private String subjectDesc;
@Schema(description = "采购数量")
@NotNull(message = "采购数量不能为空")
@DecimalMin(value = "0.0001", message = "采购数量必须大于0")
private BigDecimal purchaseQty;
@Schema(description = "预算金额")
@NotNull(message = "预算金额不能为空")
@DecimalMin(value = "0.01", message = "预算金额必须大于0")
private BigDecimal budgetAmount;
@Schema(description = "中标金额")
@DecimalMin(value = "0", message = "中标金额不能为负数")
private BigDecimal bidAmount;
@Schema(description = "实际采购金额")
@DecimalMin(value = "0", message = "实际采购金额不能为负数")
private BigDecimal actualAmount;
@Schema(description = "合同金额")
@DecimalMin(value = "0", message = "合同金额不能为负数")
private BigDecimal contractAmount;
@Schema(description = "结算金额")
@DecimalMin(value = "0", message = "结算金额不能为负数")
private BigDecimal settlementAmount;
@Schema(description = "采购方式")
@NotBlank(message = "采购方式不能为空")
@Size(max = 50, message = "采购方式长度不能超过50个字符")
private String purchaseMethod;
@Schema(description = "中标供应商名称")
@Size(max = 200, message = "中标供应商名称长度不能超过200个字符")
private String supplierName;
@Schema(description = "供应商联系人")
@Size(max = 50, message = "供应商联系人长度不能超过50个字符")
private String contactPerson;
@Schema(description = "供应商联系电话")
@Size(max = 20, message = "供应商联系电话长度不能超过20个字符")
private String contactPhone;
@Schema(description = "供应商统一信用代码")
@Size(max = 18, message = "供应商统一信用代码长度不能超过18个字符")
private String supplierUscc;
@Schema(description = "供应商银行账户")
@Size(max = 50, message = "供应商银行账户长度不能超过50个字符")
private String supplierBankAccount;
@Schema(description = "采购申请日期")
@NotNull(message = "采购申请日期不能为空")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate applyDate;
@Schema(description = "采购计划批准日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate planApproveDate;
@Schema(description = "采购公告发布日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate announceDate;
@Schema(description = "开标日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate bidOpenDate;
@Schema(description = "合同签订日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate contractSignDate;
@Schema(description = "预计交货日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate expectedDeliveryDate;
@Schema(description = "实际交货日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate actualDeliveryDate;
@Schema(description = "验收日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate acceptanceDate;
@Schema(description = "结算日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate settlementDate;
@Schema(description = "申请人工号")
@NotBlank(message = "申请人工号不能为空")
@Pattern(regexp = "^\\d{7}$", message = "申请人工号必须为7位数字")
private String applicantId;
@Schema(description = "申请人姓名")
@NotBlank(message = "申请人姓名不能为空")
@Size(max = 50, message = "申请人姓名长度不能超过50个字符")
private String applicantName;
@Schema(description = "申请部门")
@NotBlank(message = "申请部门不能为空")
@Size(max = 100, message = "申请部门长度不能超过100个字符")
private String applyDepartment;
@Schema(description = "采购负责人工号")
@Pattern(regexp = "^\\d{7}$", message = "采购负责人工号必须为7位数字")
private String purchaseLeaderId;
@Schema(description = "采购负责人姓名")
@Size(max = 50, message = "采购负责人姓名长度不能超过50个字符")
private String purchaseLeaderName;
@Schema(description = "采购部门")
@Size(max = 100, message = "采购部门长度不能超过100个字符")
private String purchaseDepartment;
}
```
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionAddDTO.java
git commit -m "feat: 添加采购交易新增DTO"
```
---
## Task 5: 创建编辑DTO
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionEditDTO.java`
**Step 1: 创建编辑DTO**
复制AddDTO的内容,修改类名和类注释,所有验证注解保持不变。
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiPurchaseTransactionEditDTO.java
git commit -m "feat: 添加采购交易编辑DTO"
```
---
## Task 6: 创建VO类
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiPurchaseTransactionVO.java`
**Step 1: 创建VO类**
```java
package com.ruoyi.ccdi.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 采购交易信息VO
*
* @author ruoyi
* @date 2026-02-06
*/
@Data
@Schema(description = "采购交易信息")
public class CcdiPurchaseTransactionVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "采购事项ID")
private String purchaseId;
@Schema(description = "采购类别")
private String purchaseCategory;
@Schema(description = "项目名称")
private String projectName;
@Schema(description = "标的物名称")
private String subjectName;
@Schema(description = "标的物描述")
private String subjectDesc;
@Schema(description = "采购数量")
private BigDecimal purchaseQty;
@Schema(description = "预算金额")
private BigDecimal budgetAmount;
@Schema(description = "中标金额")
private BigDecimal bidAmount;
@Schema(description = "实际采购金额")
private BigDecimal actualAmount;
@Schema(description = "合同金额")
private BigDecimal contractAmount;
@Schema(description = "结算金额")
private BigDecimal settlementAmount;
@Schema(description = "采购方式")
private String purchaseMethod;
@Schema(description = "中标供应商名称")
private String supplierName;
@Schema(description = "供应商联系人")
private String contactPerson;
@Schema(description = "供应商联系电话")
private String contactPhone;
@Schema(description = "供应商统一信用代码")
private String supplierUscc;
@Schema(description = "供应商银行账户")
private String supplierBankAccount;
@Schema(description = "采购申请日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate applyDate;
@Schema(description = "采购计划批准日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate planApproveDate;
@Schema(description = "采购公告发布日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate announceDate;
@Schema(description = "开标日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate bidOpenDate;
@Schema(description = "合同签订日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate contractSignDate;
@Schema(description = "预计交货日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate expectedDeliveryDate;
@Schema(description = "实际交货日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate actualDeliveryDate;
@Schema(description = "验收日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate acceptanceDate;
@Schema(description = "结算日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate settlementDate;
@Schema(description = "申请人工号")
private String applicantId;
@Schema(description = "申请人姓名")
private String applicantName;
@Schema(description = "申请部门")
private String applyDepartment;
@Schema(description = "采购负责人工号")
private String purchaseLeaderId;
@Schema(description = "采购负责人姓名")
private String purchaseLeaderName;
@Schema(description = "采购部门")
private String purchaseDepartment;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@Schema(description = "更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@Schema(description = "创建人")
private String createdBy;
@Schema(description = "更新人")
private String updatedBy;
}
```
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/vo/CcdiPurchaseTransactionVO.java
git commit -m "feat: 添加采购交易VO类"
```
---
## Task 7: 创建Excel导入导出类
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiPurchaseTransactionExcel.java`
**Step 1: 创建Excel类**
参考 `CcdiStaffRecruitmentExcel.java`为36个字段添加 `@ExcelProperty``@ColumnWidth``@Required` 注解。必填字段purchaseId, purchaseCategory, subjectName, purchaseQty, budgetAmount, purchaseMethod, applyDate, applicantId, applicantName, applyDepartment。
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiPurchaseTransactionExcel.java
git commit -m "feat: 添加采购交易Excel类"
```
---
## Task 8: 创建Mapper接口
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiPurchaseTransactionMapper.java`
**Step 1: 创建Mapper接口**
```java
package com.ruoyi.ccdi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.domain.CcdiPurchaseTransaction;
import com.ruoyi.ccdi.domain.dto.CcdiPurchaseTransactionQueryDTO;
import com.ruoyi.ccdi.domain.vo.CcdiPurchaseTransactionVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 采购交易信息 数据层
*
* @author ruoyi
* @date 2026-02-06
*/
public interface CcdiPurchaseTransactionMapper extends BaseMapper<CcdiPurchaseTransaction> {
/**
* 分页查询采购交易列表
*/
Page<CcdiPurchaseTransactionVO> selectTransactionPage(@Param("page") Page<CcdiPurchaseTransactionVO> page,
@Param("query") CcdiPurchaseTransactionQueryDTO queryDTO);
/**
* 查询采购交易详情
*/
CcdiPurchaseTransactionVO selectTransactionById(@Param("purchaseId") String purchaseId);
/**
* 批量插入
*/
int insertBatch(@Param("list") List<CcdiPurchaseTransaction> list);
/**
* 批量更新(先删除再插入)
*/
int insertOrUpdateBatch(@Param("list") List<CcdiPurchaseTransaction> list);
}
```
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiPurchaseTransactionMapper.java
git commit -m "feat: 添加采购交易Mapper接口"
```
---
## Task 9: 创建Mapper XML文件
**Files:**
- Create: `ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiPurchaseTransactionMapper.xml`
**Step 1: 创建XML映射文件**
参考 `CcdiStaffRecruitmentMapper.xml`编写SQL映射:
- selectTransactionPage: 分页查询,支持项目名称、标的物名称、申请人、日期范围查询
- selectTransactionById: 根据ID查询详情
- insertBatch: 批量插入
- insertOrUpdateBatch: 批量更新(先删除再插入)
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiPurchaseTransactionMapper.xml
git commit -m "feat: 添加采购交易Mapper XML"
```
---
## Task 10: 创建Service接口
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiPurchaseTransactionService.java`
**Step 1: 创建Service接口**
参考 `ICcdiStaffRecruitmentService.java`,定义以下方法:
- selectTransactionList
- selectTransactionPage
- selectTransactionListForExport
- selectTransactionById
- insertTransaction
- updateTransaction
- deleteTransactionByIds
- importTransaction (返回taskId)
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiPurchaseTransactionService.java
git commit -m "feat: 添加采购交易Service接口"
```
---
## Task 11: 创建异步导入Service接口
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiPurchaseTransactionImportService.java`
**Step 1: 创建异步导入Service接口**
参考 `ICcdiEmployeeImportService.java`,定义方法:
- importTransactionAsync
- getImportStatus
- getImportFailures
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/ICcdiPurchaseTransactionImportService.java
git commit -m "feat: 添加采购交易异步导入Service接口"
```
---
## Task 12: 创建Service实现类
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionServiceImpl.java`
**Step 1: 创建Service实现**
参考 `CcdiStaffRecruitmentServiceImpl.java`实现所有CRUD方法和importTransaction方法(初始化Redis状态,调用异步服务)。
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionServiceImpl.java
git commit -m "feat: 添加采购交易Service实现"
```
---
## Task 13: 创建异步导入Service实现类
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionImportServiceImpl.java`
**Step 1: 创建异步导入实现**
参考 `CcdiEmployeeImportServiceImpl.java`,实现:
- @Async + @Transactional 注解
- importTransactionAsync方法(接收userName参数)
- 数据分类(新记录/更新记录/失败记录)
- 批量插入和更新
- Redis状态管理
- 数据验证逻辑
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiPurchaseTransactionImportServiceImpl.java
git commit -m "feat: 添加采购交易异步导入Service实现"
```
---
## Task 14: 创建Controller控制器
**Files:**
- Create: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiPurchaseTransactionController.java`
**Step 1: 创建Controller**
参考 `CcdiStaffRecruitmentController.java``CcdiEmployeeController.java`,实现接口:
- GET /list - 分页查询
- GET /{purchaseId} - 查询详情
- POST / - 新增
- PUT / - 修改
- DELETE /{purchaseIds} - 删除
- POST /export - 导出
- POST /importTemplate - 下载模板
- POST /importData - 异步导入
- GET /importStatus/{taskId} - 查询导入状态
- GET /importFailures/{taskId} - 查询失败记录
添加完整的Swagger注解。
**Step 2: Commit**
```bash
git add ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiPurchaseTransactionController.java
git commit -m "feat: 添加采购交易Controller"
```
---
## Task 15: 创建前端API文件
**Files:**
- Create: `ruoyi-ui/src/api/ccdiPurchaseTransaction.js`
**Step 1: 创建API定义**
```javascript
import request from '@/utils/request'
// 查询采购交易列表
export function listTransaction(query) {
return request({
url: '/ccdi/purchaseTransaction/list',
method: 'get',
params: query
})
}
// 查询采购交易详情
export function getTransaction(purchaseId) {
return request({
url: '/ccdi/purchaseTransaction/' + purchaseId,
method: 'get'
})
}
// 新增采购交易
export function addTransaction(data) {
return request({
url: '/ccdi/purchaseTransaction',
method: 'post',
data: data
})
}
// 修改采购交易
export function updateTransaction(data) {
return request({
url: '/ccdi/purchaseTransaction',
method: 'put',
data: data
})
}
// 删除采购交易
export function delTransaction(purchaseIds) {
return request({
url: '/ccdi/purchaseTransaction/' + purchaseIds,
method: 'delete'
})
}
// 导出采购交易
export function exportTransaction(query) {
return request({
url: '/ccdi/purchaseTransaction/export',
method: 'post',
params: query
})
}
// 下载导入模板
export function importTemplate() {
return request({
url: '/ccdi/purchaseTransaction/importTemplate',
method: 'post'
})
}
// 导入采购交易
export function importData(file, updateSupport) {
const formData = new FormData()
formData.append('file', file)
formData.append('updateSupport', updateSupport)
return request({
url: '/ccdi/purchaseTransaction/importData',
method: 'post',
data: formData
})
}
// 查询导入状态
export function getImportStatus(taskId) {
return request({
url: '/ccdi/purchaseTransaction/importStatus/' + taskId,
method: 'get'
})
}
// 查询导入失败记录
export function getImportFailures(taskId, pageNum, pageSize) {
return request({
url: '/ccdi/purchaseTransaction/importFailures/' + taskId,
method: 'get',
params: { pageNum, pageSize }
})
}
```
**Step 2: Commit**
```bash
git add ruoyi-ui/src/api/ccdiPurchaseTransaction.js
git commit -m "feat: 添加采购交易前端API"
```
---
## Task 16: 创建前端页面组件
**Files:**
- Create: `ruoyi-ui/src/views/ccdiPurchaseTransaction/index.vue`
**Step 1: 创建页面组件**
参考 `ruoyi-ui/src/views/ccdiStaffRecruitment/index.vue`,实现:
- 查询表单(项目名称、标的物名称、申请人、日期范围)
- 列表表格(13个字段 + 操作列)
- 新增/编辑对话框
- 导入对话框(支持异步导入状态轮询)
- 删除确认
**Step 2: Commit**
```bash
git add ruoyi-ui/src/views/ccdiPurchaseTransaction/index.vue
git commit -m "feat: 添加采购交易管理页面"
```
---
## Task 17: 配置菜单和权限
**Files:**
- Modify: 数据库菜单表
**Step 1: 添加菜单数据**
执行SQL:
```sql
-- 添加采购交易管理菜单
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES
('采购交易管理', (SELECT menu_id FROM sys_menu WHERE menu_name='CCDI管理' AND parent_id=0), 5, 'purchaseTransaction', 'ccdiPurchaseTransaction/index', 1, 0, 'C', '0', '0', 'ccdi:purchaseTransaction:list', 'shopping', 'admin', NOW(), '', NULL, '采购交易信息管理菜单');
-- 获取刚插入的菜单ID
SET @menu_id = LAST_INSERT_ID();
-- 添加按钮权限
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) VALUES
('采购交易查询', @menu_id, 1, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:query', '#', 'admin', NOW(), ''),
('采购交易新增', @menu_id, 2, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:add', '#', 'admin', NOW(), ''),
('采购交易修改', @menu_id, 3, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:edit', '#', 'admin', NOW(), ''),
('采购交易删除', @menu_id, 4, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:remove', '#', 'admin', NOW(), ''),
('采购交易导出', @menu_id, 5, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:export', '#', 'admin', NOW(), ''),
('采购交易导入', @menu_id, 6, '', '', 1, 0, 'F', '0', '0', 'ccdi:purchaseTransaction:import', '#', 'admin', NOW(), '');
```
**Step 2: Commit**
```bash
git add sql/
git commit -m "feat: 配置采购交易管理菜单和权限"
```
---
## Task 18: 生成测试脚本
**Files:**
- Create: `test/test_purchase_transaction_api.ps1`
**Step 1: 创建测试脚本**
参考 `test/test_employee_api.ps1`,编写完整的测试脚本:
- 登录获取token
- 测试分页查询
- 测试新增
- 测试查询详情
- 测试修改
- 测试删除
- 测试导入
- 测试导出
**Step 2: Commit**
```bash
git add test/test_purchase_transaction_api.ps1
git commit -m "test: 添加采购交易API测试脚本"
```
---
## Task 19: 运行测试并生成报告
**Step 1: 运行测试脚本**
```powershell
cd test
./test_purchase_transaction_api.ps1 > test_report_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt
```
**Step 2: 验证所有接口正常**
Expected: 所有测试用例通过
**Step 3: 保存测试报告**
将测试报告保存到 `doc/test-data/purchase_transaction/` 目录。
**Step 4: Commit**
```bash
git add doc/test-data/purchase_transaction/
git commit -m "test: 添加采购交易测试报告"
```
---
## Task 20: 生成API文档
**Files:**
- Create: `doc/api/ccdi_purchase_transaction_api.md`
**Step 1: 导出Swagger API文档**
访问 http://localhost:8080/swagger-ui/index.html导出采购交易管理的API文档。
**Step 2: 整理为Markdown格式**
整理所有接口的请求参数、响应格式、示例。
**Step 3: Commit**
```bash
git add doc/api/ccdi_purchase_transaction_api.md
git commit -m "docs: 添加采购交易API文档"
```
---
## Task 21: 最终验证和清理
**Step 1: 完整功能测试**
1. 启动后端服务
2. 启动前端服务
3. 登录系统
4. 导航到采购交易管理菜单
5. 测试所有功能:
- 列表查询
- 新增记录
- 编辑记录
- 删除记录
- 批量删除
- 导入功能(含异步状态轮询)
- 导出功能
**Step 2: 代码审查**
检查:
- 所有DTO验证注解完整
- 所有Swagger注解完整
- 异常处理完善
- 日志记录完整
- 审计字段正确填充
**Step 3: 性能测试**
测试批量导入1000条数据的性能。
**Step 4: 最终Commit**
```bash
git add .
git commit -m "feat: 完成采购交易信息管理功能开发"
```
---
## 实施注意事项
1. **必填字段**: purchaseId, purchaseCategory, subjectName, purchaseQty, budgetAmount, purchaseMethod, applyDate, applicantId, applicantName, applyDepartment
2. **异步导入**: 使用@Async + @Transactional + Redis
3. **批量操作**: 每批500条记录
4. **更新策略**: 先批量删除,再批量插入
5. **数据验证**: Jakarta Validation + 自定义业务验证
6. **审计字段**: 使用@TableField(fill = FieldFill.INSERT/INSERT_UPDATE)
7. **错误处理**: 只返回失败记录,不返回成功记录
8. **导入轮询**: 每2秒轮询一次状态
## 参考文件
- 员工招聘信息模块: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/**/CcdiStaffRecruitment*`
- 员工异步导入: `ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiEmployeeImportServiceImpl.java`
- 前端页面: `ruoyi-ui/src/views/ccdiStaffRecruitment/index.vue`
- 测试脚本: `test/test_employee_api.ps1`