Files
2026-07-09 14:24:46 +08:00

33 lines
3.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# coin_account — 金币 + 现金余额快照
> 模型 `app/models/wallet.py` · 仓库 `app/repositories/wallet.py` · 接口 [wallet-account](../api/wallet/wallet-account.md) · [← 索引](./README.md) · [总览](./OVERVIEW.md)
一用户一行的余额快照,App「资产卡 / 钱包」读它展示。每次余额变动都另写一笔流水(`coin_transaction` / `cash_transaction`)并记 `balance_after`,出问题逐笔回溯。`user_id` 既是主键也是外键(一对一)。详见 [总览 §四 资金模型](./OVERVIEW.md#四资金模型金币--现金--提现三层)。
## 用在哪 / 增删改查
- **C(插入)**:`get_or_create_account` 懒建 —— 用户第一次发生金币动作(签到/任务/看广告/admin 发币/兑换/提现)时建一行空账户(全 0)。从未发生过金币动作的用户**没有这行**(读接口按 0 兜底)。
- **U(更新)**:几乎所有钱相关动作都更新它 —— 发金币(签到/任务/看广告/admin)`coin_balance += `、兑现金 `coin_balance = / cash_balance_cents += `、发起提现 `cash_balance_cents = `(带条件原子 UPDATE 防超额)、提现退款 `cash_balance_cents += `
- **D**:无。
- **R**:`GET /wallet/account`(钱包余额卡)、admin 用户 360 概览。
## 字段
| 列 | 类型 | 约束 / 默认 | 说明(取值 / join) |
|---|---|---|---|
| `user_id` | Integer | **PK + FK→user.id** | 用户(一用户一行);既是主键也是外键 |
| `coin_balance` | Integer | NOT NULL, default 0 | 当前金币余额(个数);= 历次 `coin_transaction.amount` 之和 |
| `cash_balance_cents` | Integer | NOT NULL, default 0 | 当前现金余额(分,**金币兑换账本**);= 历次 `cash_transaction.amount_cents` 之和 |
| `invite_cash_balance_cents` | Integer | NOT NULL, default 0 | 当前**邀请奖励金**余额(分,与现金物理隔离的第二本现金账);= 历次 [`invite_cash_transaction`](./invite_cash_transaction.md)`.amount_cents` 之和。好友比价并下单发奖入账(#113),`source=invite_cash` 提现出账(#121) |
| `total_coin_earned` | Integer | NOT NULL, default 0 | 累计赚取金币(**只增不减**,仅正向 grant 累加),用于"历史总收益"展示 |
| `updated_at` | DateTime(tz) | server_default now(), onupdate now() | 最后更新时间 |
## 关系 / Join Key
- `user_id``user.id`(一对一)。
-`coin_transaction` / `cash_transaction` 无外键直连,靠 `user_id` 关联;快照 = 流水累加值,流水的 `balance_after*` 应等于当时的快照余额(对账依据)。
## 索引与约束
- PK `user_id`(同时是 FK→user.id)。
## 注意
- **唯一发金币入口** `wallet.grant_coins`:更新本表 + 写 `coin_transaction`,**不 commit**,由调用方同事务提交(发币与业务记录原子化)。邀请奖励金同款:**唯一变动入口 `wallet.grant_invite_cash`**(更新 `invite_cash_balance_cents` + 写 `invite_cash_transaction`)。
- 扣现金用 `UPDATE ... WHERE <对应余额列> >= amount` 原子条件扣减(按提现 `source``cash_balance_cents``invite_cash_balance_cents`),并发/重试不会超额。