C# 转 PMP Java 业务逻辑
先读取目标仓库适用的项目指令。如果可以访问相对于本技能目录的 ..\..\copilot-instructions.md,也应读取其中的共享约束;此处引用不会自动加载文件。以目标仓库实际源码、构建配置和适用指令为准,不要将通知服务的基础包或 Feign 分层机械套用到其他 PMP 服务。
输入与适用范围
- 必须有明确的转换授权、可访问的 C# 源码或代码片段,以及可确定的 Java 目标位置。仅缺少实质性信息时提问;不要凭空补全未提供的业务规则。
- 检查源方法的直接调用、模型、枚举、扩展方法和查询实现,必要时沿调用链追踪。源依赖不可访问时,说明缺失内容和影响,不得以空实现、固定返回值或 TODO 冒充完成。
- 只修改请求涉及的仓库和功能。跨仓库转换时先确定各层归属,不得自动扩大到其他服务。
操作步骤
- 从原 C# 代码提取输入输出、默认值、校验、所有条件分支、过滤/排序/分组/分页规则、金额计算、异常路径及写入或通知等副作用。在工作上下文中建立源方法与 Java 实现的对应清单,不额外生成计划或说明文件。
- 检查目标 controller、service 接口及实现、Feign 契约、model 和已有工具类;涉及数据服务时再检查相关 repository。搜索已有同类逻辑,复用现有类型与工具,遵循目标项目命名和构造器注入约定,不逐字翻译 C# 命名。
- 先检查相关现有测试并在安全可行时建立基线。按业务职责完成所有受影响层的实现和接线,保留接口字段、枚举值、响应结构与错误处理;契约差异需明确授权。
- 重点核对下列语言语义差异,按源行为实现,不机械替换语法。无法判断的业务差异应澄清,而不是自行选择默认值。
- 使用现有 JUnit 5/Mockito/MockMvc 为有实际业务逻辑的类补充隔离回归测试,覆盖正常、边界、异常和关键分支;不为纯字段 DTO/VO 或无逻辑接口单独生成测试。
- 全部受影响服务的代码完成后,集中执行相关编译和测试,避免逐文件反复编译。执行前确认外部依赖已模拟;未经明确批准不得启动应用或进行真实服务集成。
- 再次逐项对照原 C# 源码和需求,检查调用链、条件分支、计算顺序、边界、副作用及跨层字段传递,避免逻辑遗漏。检查差异,保留无关改动和未跟踪文件。
C# 与 Java 语义核对
- 空值与默认值:区分 nullable、默认值、空字符串和空集合;核对
??、?.、FirstOrDefault、SingleOrDefault在零条和多条结果时的行为,不能随意改为取第一条或返回空对象。 - 数值:金额和 C#
decimal使用合适的BigDecimal运算,明确精度、除法和舍入规则;保留整数除法和溢出处理语义,不使用double中转金额,数值相等判断须考虑 scale。 - 日期:按业务语义选择
LocalDate、LocalDateTime、Instant等,核对时区、日期截断、区间开闭边界、月末和闰年;不得把本地时间与 UTC 混用。 - 查询与集合:保留 LINQ/EF 的过滤、连接、去重、排序、分组、聚合和分页先后顺序,核对空集合聚合、重复键、空值比较和数据库排序规则;不能默认 Java Stream 与数据库查询语义相同。
- 字符串与枚举:核对大小写、空白、文化区域、格式化、枚举数值及 JSON 表示;字符串值比较不用
==,枚举不以 ordinal 替代原业务编码。 - 执行与资源:核对
async/await的执行顺序、异常传播、取消、事务边界和using/IDisposable资源释放;不为匹配语法擅自引入异步线程、重试或新的事务边界。
任务边界
- 不要把解释说明类请求变成实现任务。
- 此技能负责 C# 业务转换,不执行语言/框架升级或云平台迁移,也不擅自修正与转换无关的原代码问题。
- 不要仅因存在某项依赖就引入持久化或消息架构。
- 外部数据访问沿用目标服务既有 Feign 委托;只有目标数据服务确有仓储职责时才实现 repository,不在通知或业务服务中新增本地数据库/JPA 层。
- 保持公共接口契约不变,除非所请求的行为确实需要变更且已获得明确授权。
- 不增加宽泛异常捕获、静默降级或成功形状的兜底返回;沿用现有异常处理,不记录密钥或敏感载荷。
- 在
pmp-data-lease中新增/修改仓储查询时,禁止使用@Query的 HQL/JPQL/原生 SQL 字符串(含join fetch);一律通过XxxRepositoryCustom/XxxRepositoryImpl+CriteriaBuilder实现,详见共享约束文件。 - 涉及"当前日期"默认值的设置(如查询参数缺省时补默认报表日期等)一律放在
pmp-service-lease层完成,不要放在pmp-channel-lease层;且必须通过com.spl.pmp.service.lease.utils.DateUtils.getCurrentLocalDate()获取当前日期,禁止直接使用LocalDate.now()。 - 编写/修改代码时不要自动添加注释或
@Schema(description = ...)等接口文档注解;仅在用户明确要求时才添加。 - 遵守 SonarQube 常见规则:不要使用
record等受限标识符作为变量/参数名(S6213);日期字面量优先使用java.time.Month等枚举常量而非裸整数(S8694)。 - 代码中不要使用带完整包名的内联类引用(如
com.spl.pmp.service.lease.report.utils.AsposeExcelUtils.CellStyleConfig);应通过import引入类型后使用简名(嵌套类沿用项目既有写法,如import ...AsposeExcelUtils;后使用AsposeExcelUtils.CellStyleConfig)。 - 在 Feign 客户端接口(如
LeaseDataClient/LeaseServiceClient/LeaseReportServiceClient)中新增方法时,一律追加到接口末尾(最后一个已有方法之后、右花括号之前),不要插入到已有方法中间。
证据与完成标准
交付时简要说明完成的转换、源代码与 Java 实现的对应关系、接口契约影响及经授权的行为差异。源逻辑覆盖和相关检查均完成才可声称完成;缺失源码、私有依赖解析失败或其他阻碍必须如实说明,不能将未执行或受阻的验证描述为成功。不得为解决依赖问题安装、更改或泄露凭据。