---
alwaysApply: true
path: backend/**
---

# 后端开发规范

## 核心原则
- **禁止**在代码中添加 TODO/FIXME/XXX 注释
- **禁止**返回 mock 数据或硬编码的假数据
- **禁止**在 API 调用失败时返回默认值作为 fallback
- 所有功能必须完整实现，确保代码可以正常运行

## 项目范围
- **平台**: 仅支持 Polymarket
- **包名**: `com.wrbug.polymarketbot`

## 实体类规范
```kotlin
@Entity
@Table(name = "example_table")
data class ExampleEntity(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null,  // ✅ 正确：使用可空类型
    
    @Column(name = "created_at", nullable = false)
    val createdAt: Long = System.currentTimeMillis(),  // ✅ 使用 Long 时间戳
    
    @Column(name = "amount", nullable = false, precision = 20, scale = 8)
    val amount: BigDecimal = BigDecimal.ZERO  // ✅ 使用 BigDecimal
)
```

**规则**:
- ID 字段必须使用 `Long? = null`
- 时间字段使用 `Long` 时间戳（毫秒）
- 数值字段使用 `BigDecimal`
- **禁止**使用 `LocalDateTime` 或 `Double`

## 配置文件规范
- **必须**使用 `application.properties` 格式（禁止 `application.yml`）
- 使用 `${ENV_VAR:default}` 引用环境变量

## 代码规范

### Controller
- **禁止**使用 `suspend`
- 使用 `runBlocking` 调用 suspend 方法
- 统一使用 `@PostMapping`

### Service
- 可以使用 `suspend` 方法
- 使用 `@Transactional` 管理事务
- 使用构造函数注入依赖

### Repository
- 继承 `JpaRepository<Entity, Long>`
- 使用 Spring Data JPA 方法命名规范

## API 接口规范

### 统一响应格式
```json
{
  "code": 0,
  "data": {},
  "msg": ""
}
```

### 错误码范围
- `0`: 成功
- `1001-1999`: 参数错误
- `2001-2999`: 认证/权限错误
- `3001-3999`: 资源不存在
- `4001-4999`: 业务逻辑错误
- `5001-5999`: 服务器内部错误

### Controller 示例
```kotlin
@RestController
@RequestMapping("/api/example")
class ExampleController(
    private val exampleService: ExampleService,
    private val messageSource: MessageSource
) {
    @PostMapping("/list")
    fun getList(@RequestBody request: ExampleListRequest): ResponseEntity<ApiResponse<ExampleListResponse>> {
        return try {
            val data = runBlocking { exampleService.getList(request) }
            ResponseEntity.ok(ApiResponse.success(data))
        } catch (e: Exception) {
            logger.error("Failed to get list", e)
            ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, messageSource))
        }
    }
}
```

## 数值计算
```kotlin
val amount = "0.5".toSafeBigDecimal()
val total = amount.add("0.4".toSafeBigDecimal())

if (total.lt(BigDecimal.ONE)) {
    // 业务逻辑
}
```

## JSON 解析规范

### 使用扩展函数（推荐）
- **优先**使用扩展函数 `fromJson<T>()` 和 `toJson()`，禁止直接使用 `Gson`
- 扩展函数提供了类型安全的解析，使用方便

```kotlin
// ✅ 正确：使用扩展函数（推荐）
val json = "{\"name\":\"test\"}"
val obj = json.fromJson<MyDataClass>()
val jsonStr = obj.toJson()

// ✅ 也可以：使用 JsonUtils 类（兼容旧代码）
val obj = jsonUtils.fromJson<MyDataClass>(json)

// ❌ 错误：直接使用 Gson
val obj = gson.fromJson(json, MyDataClass::class.java)
```

### 扩展函数列表
- `String?.fromJson<T>()` - 解析 JSON 字符串为对象（支持泛型）
- `JsonElement?.fromJson<T>()` - 解析 JsonElement 为对象（支持泛型）
- `Any?.toJson()` - 将对象转换为 JSON 字符串
- `String?.parseStringArray()` - 解析 JSON 字符串数组

### JsonUtils 类
- `JsonUtils` 主要用于初始化全局 Gson 实例，供扩展函数使用
- 保留 `parseStringArray()` 方法用于兼容旧代码
- 不推荐直接使用 `JsonUtils` 的方法，优先使用扩展函数

### Data Class 规范
- **所有 data class 字段必须提供默认值**
- 可空字段使用 `? = null`
- 非空字段提供合适的默认值（空字符串、空集合、默认数值等）

```kotlin
// ✅ 正确：所有字段都有默认值
data class MyDto(
    val name: String = "",
    val age: Int = 0,
    val tags: List<String> = emptyList(),
    val optional: String? = null
)

// ❌ 错误：缺少默认值
data class MyDto(
    val name: String,  // 缺少默认值
    val age: Int = 0
)
```

## Side 判断规范
**禁止**使用 "YES"/"NO" 字符串判断 side

```kotlin
// ❌ 错误
if (side != null && side.uppercase() == "NO") { }

// ✅ 正确
if (outcomeIndex != null && outcomeIndex == 1) { }
```

## 多语言规范
- **禁止**硬编码中文或英文错误消息
- **必须**使用 `ErrorCode` 枚举和 `MessageSource`

```kotlin
// ❌ 错误
return ResponseEntity.ok(ApiResponse.paramError("配置ID不能为空"))

// ✅ 正确
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_EMPTY, messageSource))
```

### 多语言支持范围
1. **API 响应消息**: 使用 `ErrorCode` + `MessageSource`
2. **日志消息**: 可使用中文或英文
3. **代码注释**: 建议使用中文
4. **数据库字段**: 使用英文（snake_case）

## HTTP 客户端
- 使用 Retrofit + OkHttp
- 使用拦截器处理认证

## 跟单系统需求
参考文档: `docs/copy-trading-requirements.md`

核心功能:
- 账户管理（私钥导入，多账户）
- Leader 管理
- 订单同步与执行
- 跟单配置管理
- 风险控制
- 跟单记录与统计

## 禁止事项

### 代码质量
- ❌ 禁止使用 `!!` 除非有明确原因
- ❌ 禁止忽略异常
- ❌ 禁止硬编码配置值
- ❌ 禁止提交敏感信息到 Git

### 类型
- ❌ 禁止使用 `Double` 进行数值计算
- ❌ 禁止使用 `LocalDateTime` 存储时间
- ❌ 禁止实体类 ID 使用非空默认值
- ❌ 禁止直接使用 `Gson`（必须使用 `JsonUtils`）
- ❌ 禁止 data class 字段缺少默认值

### API 接口
- ❌ 禁止使用 GET/PUT/DELETE（统一使用 POST）
- ❌ 禁止返回不符合统一格式的响应
- ❌ 禁止在响应中直接返回 Map 类型

### Side 判断
- ❌ 禁止使用 "YES"/"NO" 字符串判断 side
- ✅ 必须使用 `outcomeIndex` 判断

### 数据源
- ❌ 禁止直接返回 mock 数据
- ❌ 禁止在 API 调用失败时返回 mock 数据
- ✅ 所有数据必须来自真实 API 或数据库查询
