# 数据与同步

## 核心实体

- `user`：用户。
- `device`：设备。
- `ledger`：账本。
- `ledger_member`：账本成员。
- `ledger_invitation`：账本邀请。
- `category`：分类。
- `entry`：账目。
- `sync_operation`：同步操作。

## 账本字段

- `id`
- `name`
- `visibility`：`private` 或 `shared`。
- `owner_id`
- `created_at`
- `updated_at`
- `deleted_at`

## 成员字段

- `ledger_id`
- `user_id`
- `role`：`owner` 或 `member`。
- `joined_at`
- `removed_at`

## 邀请字段

- `id`
- `ledger_id`
- `token`
- `created_by`
- `expires_at`
- `accepted_by`
- `accepted_at`
- `revoked_at`

## 权限规则

- 用户只能同步自己有成员关系的账本。
- 独享账本只有 owner 一名成员。
- 共享账本可以有多名成员。
- `owner` 可以邀请和移除成员。
- `member` 可以查看和记账。
- 首版不做单条账目权限。

## 账目字段

- `id`：客户端生成 UUID。
- `ledger_id`
- `type`：`expense` 或 `income`。
- `amount`：金额，整数分。
- `category_id`
- `occurred_at`
- `note`
- `created_by`
- `updated_by`
- `created_at`
- `updated_at`
- `deleted_at`
- `version`

## 同步原则

- 客户端先写 IndexedDB，界面立即成功。
- 每次本地变更生成一个 `operation_id`。
- 同步 API 必须幂等。
- 服务端保存账本变更日志。
- 客户端用游标拉取增量。
- 同步范围必须按账本成员权限过滤。

## 同步流程

1. 用户新增、编辑或删除账目。
2. 客户端写 IndexedDB。
3. 客户端写本地同步队列。
4. 网络可用时推送队列。
5. 服务端按 `operation_id` 去重并应用。
6. 客户端拉取远端增量。
7. 客户端合并到 IndexedDB。

## 冲突策略

- 新增记录基本无冲突，ID 由客户端生成。
- 删除使用软删除。
- 同一条账目被多人离线修改时，首版最后写入胜出。
- 不做字段级合并。
- 冲突历史和人工选择版本后置。

冲突示例：

- 手机 A 和手机 B 都同步过同一笔账：`午餐 100 元`。
- 两台手机同时离线。
- 手机 A 改成 `120 CNY`。
- 手机 B 改成 `110 CNY` 或修改分类。
- 两台手机恢复网络后上传。
- 服务端必须决定最终版本。
