# Pmp Java Convert From Csharp

> 将用户提供或指定的 C#/.NET 业务代码转换为 PMP Java/Spring 实现，按原代码逐项保留业务逻辑并遵循目标仓库分层和命名约定。适用于明确要求 C# 转 Java、迁移 C# 业务逻辑或补全已有转换的任务；不适用于仅解释、只读对比、一般 Java 功能开发、框架升级或仅测试任务。

- Skill: `junxian12366/pmp-java-convert-from-csharp` (Agent Skill)
- Install (CLI): `npx skillmds@latest add junxian12366/pmp-java-convert-from-csharp`
- Raw SKILL.md: https://api.skillmd.com/api/skills/junxian12366/pmp-java-convert-from-csharp/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: JunXian12366 (https://skillmd.com/u/junxian12366)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/junxian12366/pmp-java-convert-from-csharp

---


# C# 转 PMP Java 业务逻辑

先读取目标仓库适用的项目指令。如果可以访问相对于本技能目录的 `..\..\copilot-instructions.md`，也应读取其中的共享约束；此处引用不会自动加载文件。以目标仓库实际源码、构建配置和适用指令为准，不要将通知服务的基础包或 Feign 分层机械套用到其他 PMP 服务。

## 输入与适用范围
- 必须有明确的转换授权、可访问的 C# 源码或代码片段，以及可确定的 Java 目标位置。仅缺少实质性信息时提问；不要凭空补全未提供的业务规则。
- 检查源方法的直接调用、模型、枚举、扩展方法和查询实现，必要时沿调用链追踪。源依赖不可访问时，说明缺失内容和影响，不得以空实现、固定返回值或 TODO 冒充完成。
- 只修改请求涉及的仓库和功能。跨仓库转换时先确定各层归属，不得自动扩大到其他服务。

## 操作步骤
1. 从原 C# 代码提取输入输出、默认值、校验、所有条件分支、过滤/排序/分组/分页规则、金额计算、异常路径及写入或通知等副作用。在工作上下文中建立源方法与 Java 实现的对应清单，不额外生成计划或说明文件。
2. 检查目标 controller、service 接口及实现、Feign 契约、model 和已有工具类；涉及数据服务时再检查相关 repository。搜索已有同类逻辑，复用现有类型与工具，遵循目标项目命名和构造器注入约定，不逐字翻译 C# 命名。
3. 先检查相关现有测试并在安全可行时建立基线。按业务职责完成所有受影响层的实现和接线，保留接口字段、枚举值、响应结构与错误处理；契约差异需明确授权。
4. 重点核对下列语言语义差异，按源行为实现，不机械替换语法。无法判断的业务差异应澄清，而不是自行选择默认值。
5. 使用现有 JUnit 5/Mockito/MockMvc 为有实际业务逻辑的类补充隔离回归测试，覆盖正常、边界、异常和关键分支；不为纯字段 DTO/VO 或无逻辑接口单独生成测试。
6. 全部受影响服务的代码完成后，集中执行相关编译和测试，避免逐文件反复编译。执行前确认外部依赖已模拟；未经明确批准不得启动应用或进行真实服务集成。
7. 再次逐项对照原 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 实现的对应关系、接口契约影响及经授权的行为差异。源逻辑覆盖和相关检查均完成才可声称完成；缺失源码、私有依赖解析失败或其他阻碍必须如实说明，不能将未执行或受阻的验证描述为成功。不得为解决依赖问题安装、更改或泄露凭据。


