From 4c9188bda998dea8bc779076be200c734fea716c Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 4 Mar 2026 16:04:33 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=E4=B8=BA=E9=93=B6=E8=A1=8C?= =?UTF-8?q?=E6=B5=81=E6=B0=B4=E8=A1=A8=E6=B7=BB=E5=8A=A0=20project=5Fid=20?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/ccdi_bank_statement_add_project_id.sql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 sql/ccdi_bank_statement_add_project_id.sql diff --git a/sql/ccdi_bank_statement_add_project_id.sql b/sql/ccdi_bank_statement_add_project_id.sql new file mode 100644 index 0000000..db42cfd --- /dev/null +++ b/sql/ccdi_bank_statement_add_project_id.sql @@ -0,0 +1,14 @@ +-- 为 ccdi_bank_statement 表添加 project_id 字段 +-- 用途:关联项目ID,实现流水数据与项目的业务关联 +-- 作者:系统自动生成 +-- 日期:2026-03-04 + +USE ccdi; + +-- 添加 project_id 字段 +ALTER TABLE `ccdi_bank_statement` +ADD COLUMN `project_id` bigint(20) DEFAULT NULL COMMENT '关联项目ID' AFTER `bank_statement_id`; + +-- 添加索引以提升查询性能 +ALTER TABLE `ccdi_bank_statement` +ADD INDEX `idx_project_id` (`project_id`); From 4755e6fea3be657ff82684b949b1d70e35b7b29d Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 4 Mar 2026 16:05:47 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=E5=88=9B=E5=BB=BA=E9=93=B6?= =?UTF-8?q?=E8=A1=8C=E6=B5=81=E6=B0=B4=E5=AE=9E=E4=BD=93=E7=B1=BB=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/entity/CcdiBankStatement.java | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java new file mode 100644 index 0000000..a53f389 --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java @@ -0,0 +1,163 @@ +package com.ruoyi.ccdi.project.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 银行流水对象 ccdi_bank_statement + * + * @author ruoyi + * @date 2026-03-04 + */ +@Data +@TableName("ccdi_bank_statement") +public class CcdiBankStatement implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + // ===== 主键和关联字段 ===== + + /** 流水ID */ + @TableId(type = IdType.AUTO) + private Long bankStatementId; + + /** 关联项目ID(业务字段) */ + private Long projectId; + + /** 企业ID */ + private Integer leId; + + /** 账号ID */ + private Long accountId; + + /** 项目id(保留原有字段) */ + private Integer groupId; + + // ===== 账号信息 ===== + + /** 企业账号名称 */ + private String leAccountName; + + /** 企业银行账号 */ + private String leAccountNo; + + /** 账号日期ID */ + private Integer accountingDateId; + + /** 账号日期 */ + private String accountingDate; + + /** 交易日期 */ + private String trxDate; + + /** 币种 */ + private String currency; + + // ===== 交易金额 ===== + + /** 付款金额 */ + private BigDecimal amountDr; + + /** 收款金额 */ + private BigDecimal amountCr; + + /** 余额 */ + private BigDecimal amountBalance; + + // ===== 交易类型和标志 ===== + + /** 交易类型 */ + private String cashType; + + /** 交易标志位 */ + private String trxFlag; + + /** 分类ID */ + private Integer trxType; + + /** 异常类型 */ + private String exceptionType; + + /** 是否为内部交易 */ + private Integer internalFlag; + + // ===== 对手方信息 ===== + + /** 对手方企业ID */ + private Integer customerLeId; + + /** 对手方企业名称 */ + private String customerAccountName; + + /** 对手方账号 */ + private String customerAccountNo; + + /** 对手方银行 */ + private String customerBank; + + /** 对手方备注 */ + private String customerReference; + + // ===== 摘要和备注 ===== + + /** 用户交易摘要 */ + private String userMemo; + + /** 银行交易摘要 */ + private String bankComments; + + /** 银行交易号 */ + private String bankTrxNumber; + + // ===== 银行信息 ===== + + /** 所属银行缩写 */ + private String bank; + + // ===== 批次和上传信息 ===== + + /** 上传logId */ + private Integer batchId; + + /** 每次上传在文件中的line */ + private Integer batchSequence; + + // ===== 附加字段 ===== + + /** meta json(固定为null) */ + private String metaJson; + + /** 是否包含余额 */ + private Integer noBalance; + + /** 初始余额 */ + private Integer beginBalance; + + /** 结束余额 */ + private Integer endBalance; + + /** 覆盖标识 */ + private Long overrideBsId; + + /** 交易方式 */ + private String paymentMethod; + + /** 身份证号 */ + private String cretNo; + + // ===== 审计字段 ===== + + /** 创建时间 */ + private Date createDate; + + /** 创建者 */ + private Long createdBy; +} From 92ca798e99e9640912316fbbcb508ffe85678919 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 4 Mar 2026 16:08:33 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20.gitignore=20?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=BF=BD=E7=95=A5=E6=B5=8B=E8=AF=95=E6=BA=90?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 01893db..ac26973 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,12 @@ nul # Git Worktrees .worktrees/ -test/ +# Test output directories (not source code) +**/target/test-classes/ +**/target/surefire-reports/ + +# Test data files (keep test source code) +*.test.log !*/build/*.java !*/build/*.html From 638795e09676c07e604f1e50539710c47828fd3b Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 4 Mar 2026 16:08:46 +0800 Subject: [PATCH 4/7] =?UTF-8?q?test:=20=E6=B7=BB=E5=8A=A0=E9=93=B6?= =?UTF-8?q?=E8=A1=8C=E6=B5=81=E6=B0=B4=E8=BD=AC=E6=8D=A2=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/entity/CcdiBankStatementTest.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 ccdi-project/src/test/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatementTest.java diff --git a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatementTest.java b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatementTest.java new file mode 100644 index 0000000..4be7e86 --- /dev/null +++ b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatementTest.java @@ -0,0 +1,94 @@ +package com.ruoyi.ccdi.project.domain.entity; + +import com.ruoyi.lsfx.domain.response.GetBankStatementResponse.BankStatementItem; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * 银行流水实体类测试 + * + * @author ruoyi + * @date 2026-03-04 + */ +class CcdiBankStatementTest { + + @Test + void testFromResponse_Success() { + // 准备测试数据 + BankStatementItem item = new BankStatementItem(); + item.setBankStatementId(123456L); + item.setLeId(100); + item.setAccountId(200L); + item.setLeName("测试企业"); + item.setAccountMaskNo("6222****1234"); + item.setDrAmount(new BigDecimal("1000.00")); + item.setCrAmount(new BigDecimal("500.00")); + item.setBalanceAmount(new BigDecimal("5000.00")); + item.setTrxDate("2026-03-04"); + item.setCustomerAccountMaskNo("6228****5678"); + + // 执行转换 + CcdiBankStatement entity = CcdiBankStatement.fromResponse(item); + + // 验证结果 + assertNotNull(entity, "转换结果不应为null"); + assertEquals(123456L, entity.getBankStatementId(), "流水ID应该匹配"); + assertEquals(100, entity.getLeId(), "企业ID应该匹配"); + assertEquals(200L, entity.getAccountId(), "账号ID应该匹配"); + assertEquals("测试企业", entity.getLeAccountName(), "企业名称应该匹配"); + + // 验证手动映射的字段 + assertEquals("6222****1234", entity.getLeAccountNo(), "企业账号应该从 accountMaskNo 映射"); + assertEquals("6228****5678", entity.getCustomerAccountNo(), "对手方账号应该从 customerAccountMaskNo 映射"); + + // 验证金额字段 + assertEquals(new BigDecimal("1000.00"), entity.getAmountDr(), "付款金额应该匹配"); + assertEquals(new BigDecimal("500.00"), entity.getAmountCr(), "收款金额应该匹配"); + assertEquals(new BigDecimal("5000.00"), entity.getAmountBalance(), "余额应该匹配"); + + // 验证特殊字段 + assertNull(entity.getMetaJson(), "metaJson 应该强制为 null"); + assertNull(entity.getProjectId(), "projectId 应该为 null(需要 Service 层设置)"); + } + + @Test + void testFromResponse_Null() { + // 测试空值处理 + CcdiBankStatement entity = CcdiBankStatement.fromResponse(null); + + // 验证返回 null + assertNull(entity, "传入 null 应该返回 null"); + } + + @Test + void testFromResponse_EmptyObject() { + // 测试空对象转换 + BankStatementItem item = new BankStatementItem(); + + // 执行转换 + CcdiBankStatement entity = CcdiBankStatement.fromResponse(item); + + // 验证不会抛出异常 + assertNotNull(entity, "空对象转换结果不应为 null"); + assertNull(entity.getMetaJson(), "metaJson 应该为 null"); + } + + @Test + void testFromResponse_FieldTypeCompatibility() { + // 测试字段类型兼容性 + BankStatementItem item = new BankStatementItem(); + item.setInternalFlag(1); // Integer 类型 + item.setTransTypeId(100); // Integer 类型 + + // 执行转换 + CcdiBankStatement entity = CcdiBankStatement.fromResponse(item); + + // 验证类型转换正确 + assertNotNull(entity, "转换结果不应为 null"); + assertEquals(1, entity.getInternalFlag(), "Integer 类型应该正确复制"); + assertEquals(100, entity.getTrxType(), "Integer 类型应该正确复制"); + } +} From a727119f519a44108af841271d3f0456edf7713e Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 4 Mar 2026 16:14:17 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E9=93=B6?= =?UTF-8?q?=E8=A1=8C=E6=B5=81=E6=B0=B4=E8=BD=AC=E6=8D=A2=E6=96=B9=E6=B3=95?= =?UTF-8?q?=20fromResponse()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/entity/CcdiBankStatement.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java index a53f389..6fdb0bf 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java @@ -3,7 +3,11 @@ package com.ruoyi.ccdi.project.domain.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.ruoyi.lsfx.domain.response.GetBankStatementResponse.BankStatementItem; import lombok.Data; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import java.io.Serial; import java.io.Serializable; @@ -20,6 +24,8 @@ import java.util.Date; @TableName("ccdi_bank_statement") public class CcdiBankStatement implements Serializable { + private static final Logger log = LoggerFactory.getLogger(CcdiBankStatement.class); + @Serial private static final long serialVersionUID = 1L; @@ -160,4 +166,48 @@ public class CcdiBankStatement implements Serializable { /** 创建者 */ private Long createdBy; + + /** + * 从流水分析接口响应转换为实体 + * + * @param item 流水分析接口返回的流水项 + * @return 流水实体,如果 item 为 null 则返回 null + */ + public static CcdiBankStatement fromResponse(BankStatementItem item) { + // 1. 空值检查 + if (item == null) { + log.warn("流水项为空,无法转换"); + return null; + } + + try { + // 2. 创建实体对象 + CcdiBankStatement entity = new CcdiBankStatement(); + + // 3. 使用 BeanUtils 复制同名字段 + BeanUtils.copyProperties(item, entity); + + // 4. 手动映射字段名不一致的情况 + entity.setLeAccountNo(item.getAccountMaskNo()); + entity.setCustomerAccountNo(item.getCustomerAccountMaskNo()); + entity.setLeAccountName(item.getLeName()); + entity.setAmountDr(item.getDrAmount()); + entity.setAmountCr(item.getCrAmount()); + entity.setAmountBalance(item.getBalanceAmount()); + entity.setTrxFlag(item.getTransFlag()); + entity.setTrxType(item.getTransTypeId()); + entity.setCustomerLeId(item.getCustomerId()); + entity.setCustomerAccountName(item.getCustomerName()); + + // 5. 特殊字段处理 + entity.setMetaJson(null); // 根据文档要求强制设为 null + + // 注意:project_id 需要在 Service 层根据业务逻辑设置 + + return entity; + } catch (Exception e) { + log.error("流水数据转换失败, bankStatementId={}", item.getBankStatementId(), e); + throw new RuntimeException("流水数据转换失败", e); + } + } } From ac21ca122513902e26aaad5b92d8a13cbe15bc26 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 4 Mar 2026 16:14:57 +0800 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20=E5=88=9B=E5=BB=BA=E9=93=B6?= =?UTF-8?q?=E8=A1=8C=E6=B5=81=E6=B0=B4=20Mapper=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/CcdiBankStatementMapper.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapper.java diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapper.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapper.java new file mode 100644 index 0000000..2f2262c --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapper.java @@ -0,0 +1,24 @@ +package com.ruoyi.ccdi.project.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.ccdi.project.domain.entity.CcdiBankStatement; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 银行流水Mapper接口 + * + * @author ruoyi + * @date 2026-03-04 + */ +public interface CcdiBankStatementMapper extends BaseMapper { + + /** + * 批量插入银行流水 + * + * @param list 银行流水列表 + * @return 插入记录数 + */ + int insertBatch(@Param("list") List list); +} From 6ca5aa4812703ddd6f718fc8f55c73e7f95eaf19 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 4 Mar 2026 16:16:03 +0800 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=E5=88=9B=E5=BB=BA=E9=93=B6?= =?UTF-8?q?=E8=A1=8C=E6=B5=81=E6=B0=B4=20Mapper=20XML=20=E6=98=A0=E5=B0=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ccdi/project/CcdiBankStatementMapper.xml | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml diff --git a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml new file mode 100644 index 0000000..c8c22dd --- /dev/null +++ b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select bank_statement_id, project_id, LE_ID, ACCOUNT_ID, group_id, + LE_ACCOUNT_NAME, LE_ACCOUNT_NO, ACCOUNTING_DATE_ID, ACCOUNTING_DATE, + TRX_DATE, CURRENCY, AMOUNT_DR, AMOUNT_CR, AMOUNT_BALANCE, + CASH_TYPE, CUSTOMER_LE_ID, CUSTOMER_ACCOUNT_NAME, CUSTOMER_ACCOUNT_NO, + customer_bank, customer_reference, USER_MEMO, BANK_COMMENTS, + BANK_TRX_NUMBER, BANK, TRX_FLAG, TRX_TYPE, EXCEPTION_TYPE, + internal_flag, batch_id, batch_sequence, CREATE_DATE, created_by, + meta_json, no_balance, begin_balance, end_balance, + override_bs_id, payment_method, cret_no + from ccdi_bank_statement + + + + insert into ccdi_bank_statement ( + project_id, LE_ID, ACCOUNT_ID, group_id, + LE_ACCOUNT_NAME, LE_ACCOUNT_NO, ACCOUNTING_DATE_ID, ACCOUNTING_DATE, + TRX_DATE, CURRENCY, AMOUNT_DR, AMOUNT_CR, AMOUNT_BALANCE, + CASH_TYPE, CUSTOMER_LE_ID, CUSTOMER_ACCOUNT_NAME, CUSTOMER_ACCOUNT_NO, + customer_bank, customer_reference, USER_MEMO, BANK_COMMENTS, + BANK_TRX_NUMBER, BANK, TRX_FLAG, TRX_TYPE, EXCEPTION_TYPE, + internal_flag, batch_id, batch_sequence, CREATE_DATE, created_by, + meta_json, no_balance, begin_balance, end_balance, + override_bs_id, payment_method, cret_no + ) values + + ( + #{item.projectId}, #{item.leId}, #{item.accountId}, #{item.groupId}, + #{item.leAccountName}, #{item.leAccountNo}, #{item.accountingDateId}, #{item.accountingDate}, + #{item.trxDate}, #{item.currency}, #{item.amountDr}, #{item.amountCr}, #{item.amountBalance}, + #{item.cashType}, #{item.customerLeId}, #{item.customerAccountName}, #{item.customerAccountNo}, + #{item.customerBank}, #{item.customerReference}, #{item.userMemo}, #{item.bankComments}, + #{item.bankTrxNumber}, #{item.bank}, #{item.trxFlag}, #{item.trxType}, #{item.exceptionType}, + #{item.internalFlag}, #{item.batchId}, #{item.batchSequence}, #{item.createDate}, #{item.createdBy}, + #{item.metaJson}, #{item.noBalance}, #{item.beginBalance}, #{item.endBalance}, + #{item.overrideBsId}, #{item.paymentMethod}, #{item.cretNo} + ) + + + +