feat: create precious metals by grams and show optional purchase profit

This commit is contained in:
陈煜 committed 2026-10-03 22:43:59 +08:00
1 parent 027a8c1b6a
commit 0491f515fe
22 files changed
+570 -105

No files matched your search

+51 -2
View File
@@ -1,7 +1,11 @@
{
"tableCount": 16,
"columnCount": 150,
"tableCount": 17,
"columnCount": 159,
"tables": [
{
"TABLE_NAME": "_prisma_migrations",
"TABLE_COMMENT": "Prisma 数据库迁移执行记录,由迁移引擎管理"
},
{
"TABLE_NAME": "agentauthorization",
"TABLE_COMMENT": "短期 OAuth 授权请求及一次性授权码摘要"
@@ -68,6 +72,46 @@
}
],
"columns": [
{
"TABLE_NAME": "_prisma_migrations",
"COLUMN_NAME": "id",
"COLUMN_COMMENT": "迁移执行唯一标识"
},
{
"TABLE_NAME": "_prisma_migrations",
"COLUMN_NAME": "checksum",
"COLUMN_COMMENT": "迁移文件 SHA-256 校验摘要"
},
{
"TABLE_NAME": "_prisma_migrations",
"COLUMN_NAME": "finished_at",
"COLUMN_COMMENT": "迁移成功完成时间"
},
{
"TABLE_NAME": "_prisma_migrations",
"COLUMN_NAME": "migration_name",
"COLUMN_COMMENT": "迁移目录名称"
},
{
"TABLE_NAME": "_prisma_migrations",
"COLUMN_NAME": "logs",
"COLUMN_COMMENT": "迁移引擎错误和诊断信息"
},
{
"TABLE_NAME": "_prisma_migrations",
"COLUMN_NAME": "rolled_back_at",
"COLUMN_COMMENT": "迁移标记回滚时间"
},
{
"TABLE_NAME": "_prisma_migrations",
"COLUMN_NAME": "started_at",
"COLUMN_COMMENT": "迁移开始时间"
},
{
"TABLE_NAME": "_prisma_migrations",
"COLUMN_NAME": "applied_steps_count",
"COLUMN_COMMENT": "已执行步骤数量"
},
{
"TABLE_NAME": "agentauthorization",
"COLUMN_NAME": "id",
@@ -503,6 +547,11 @@
"COLUMN_NAME": "autoValuation",
"COLUMN_COMMENT": "是否随每日价格更新自动记录估值"
},
{
"TABLE_NAME": "position",
"COLUMN_NAME": "metalCostPerGram",
"COLUMN_COMMENT": "买入时每克实物成本,原币;空值表示不计算盈亏"
},
{
"TABLE_NAME": "positionlink",
"COLUMN_NAME": "id",
+3 -2
View File
@@ -2,7 +2,7 @@
盘点来源:App.tsx、Calendar、SchedulePanel、MetalPanel、IconLibrary、TransferForm、DebtPaymentForm、GroupOrderList 及所有 API Controller 路由。架构沿用 NestJS/Express/Prisma/MySQL/Zod,不新增消费账本或 AI 框架。
验证记号:**M** `test/mcp.test.ts` 第一组真实官方 SDK/MySQL;**C** 第二组并发/图标/密码修改;**O** 第三组 OAuth;**R** 原 17 组真实 REST/MySQL 回归;**U** 原单元计算/行情/ZIP 测试。均有实际业务断言。M 中公共刷新验证无需要更新资产时的真实调用;外部行情响应和失败回退由 U 验证,未声称行情供应商稳定可用。
验证记号:**M** `test/mcp.test.ts` 第一组真实官方 SDK/MySQL;**C** 第二组并发/图标/密码修改;**O** 第三组 OAuth;**R** 18 组真实 REST/MySQL 回归;**U** 原单元计算/行情/ZIP 测试。均有实际业务断言。M 中公共刷新验证无需要更新资产时的真实调用;外部行情响应和失败回退由 U 验证,未声称行情供应商稳定可用。
普通写入需要 draft 或 write,且受用户 readonly/draft/direct 策略约束;敏感操作额外要求 sensitive 并强制网页确认。所有写入工具要求幂等键和 expectedState。每项都先检查可信用户归属;annotations 不替代权限。
@@ -11,6 +11,7 @@
| 账户/独立资产/债务列表 GET positions | positions_list:kind、名称、归档、方向、币种、分组、排序、offset/limit | read | 无 | M:查询、重名、分页和外用户隔离 |
| 项目详情 GET positions/:id | position_get | read | 隐藏项目须连接独立网页解锁 | M:当前余额、隐藏/外用户拒绝 |
| 创建项目 POST positions | position_create,保留账户/资产/债务初始绝对余额语义 | draft/write | 策略决定草稿或直接 | M/C:3 类对象、重复调用、无效金额、并发 |
| 按克数创建贵金属 POST metals/holdings | metal_holding_create | draft/write | 策略 | M/R/U:无报价待估值、现有报价估值、可选成本盈亏、旧备份 |
| 元数据、分类、分组、图标、归档/恢复、隐藏、计入开关 PATCH positions/:id | position_update,完整 metadata;币种与方向固定 | draft/write | 策略 | M:分组、归档禁止金额更新与恢复;R:隐藏和开关 |
| 分组拖拽排序 PATCH settings | settings_update.accountGroupOrder | draft/write | 策略 | M/R:持久化、排序、备份 |
| 类别选项、名称与分组配置 | position_create/update;positions_list 读取现有值,Schema/描述提供规则 | read + draft/write | 策略 | M/R;当前没有独立分类/分组实体 CRUD |
@@ -33,7 +34,7 @@
| 金银报价与状态 GET metals | metals_prices,最近 100 条 | read | 无;查询 MCP 不触发隐式自动更新 | M/U/R |
| 金银报价刷新 POST metals/refresh | metals_refresh | draft/write | 策略,沿用自动估值 | M:无配置资产调用;U:外部响应和失败回退 |
| 每克报价手动回退 POST metals/prices | metal_price_set,Decimal 价格 | draft/write | 策略 | M/R/U:手动优先、精确估值 |
| 克数、品种、纯度、自动估价 PUT metals/:id | metal_configure | draft/write | 策略 | M/R/U:估值历史和去重 |
| 克数、品种、纯度、买入成本、自动估价 PUT metals/:id | metal_configure | draft/write | 策略 | M/R/U:估值历史和去重 |
| 应用估价 POST metals/:id/value | metal_value | draft/write | 策略 | M/R/U |
| 收支月日历 GET calendar | calendar_month,YYYY-MM | read | 无 | M/R/U |
| 单日日历明细 GET calendar/day | calendar_day,业务日和分页 | read | 无 | M/R/U:历史修改、转账排除、Decimal |
+7 -1
View File
@@ -13,6 +13,12 @@
密码只在网站填写。账号或密码修改后其他连接撤销,当前发起连接只保留 5 分钟 read 权限以读取完成结果,不可刷新;需要重新授权才能继续写入。隐藏资产解锁仅持续 5 分钟并限定当前连接,网站的解锁不自动授予 Agent。
## 贵金属按克数接入
新增 `metal_holding_create`:name、currency、metalType(gold/silver)、metalGrams、metalPurity、autoValuation、date,买入价 metalCostPerGram 可省略或 null;无需填写金额或市场价格。写入仍需 expectedState 和 idempotencyKey,并遵循写入策略。有对应业务日或更早报价时复用估值逻辑创建历史,没有报价时返回 valuationAvailable=false,查询总额 complete=false 与 missingValuations。position_get/list 返回可选 metalCost 和 metalProfit,均为原币十进制字符串。成本按实物重量计算,市场价值按重量×纯度×每克纯金属报价计算。
metal_configure 省略 metalCostPerGram 保留旧成本,传 null 清除。克数或成本修改与其他写入一样参与并发状态校验;盈亏由共享业务服务计算,不存储额外浮点累计值。[更新与验证](update-metal-grams-2026-10-03.md)。
## 开发启动与环境
```powershell
@@ -130,6 +136,6 @@ location /api/ {
主要修改:原 8 个业务模块及 auth 抽取 BusinessService;database 增加事务上下文;新增 `src/mcp/{oauth,catalogue,operations,files,management,transport}.ts`;设置页新增 AgentConnections;SDK 精确版本和 pnpm lock;新增真实 MCP 测试及只读 probe。
实际通过:前后端 typecheck/build、35 项原单元检查、17 组真实 REST/MySQL 回归、3 组真实官方 MCP SDK 端到端检查,以及 mcp:probe(发现 48 个工具)。新迁移 deploy 成功,实际 MySQL 16 张应用表、150 个字段注释完整。测试真实连接 MySQL,使用随机临时用户并清理,未替代现有 REST 回归。端到端文件传输、事务回滚、归属、金额精度、幂等、并发、失效/撤销和 OAuth 均在测试中检查;外部行情源的正常和失败路径由原业务单元测试验证,不保证外部报价服务实时可用。
实际通过:前后端 typecheck/build、36 项单元检查、18 组真实 REST/MySQL 回归、3 组真实官方 MCP SDK 端到端检查,工具发现验证 49 个工具(原 mcp:probe 的 48 个工具上增加 metal_holding_create)。新迁移 deploy 成功,实际 MySQL 17 张表(含 Prisma 迁移表)、159 个字段注释完整。测试真实连接 MySQL,使用随机临时用户并清理,未替代现有 REST 回归。端到端文件传输、事务回滚、归属、金额精度、幂等、并发、失效/撤销和 OAuth 均在测试中检查;外部行情源的正常和失败路径由原业务单元测试验证,不保证外部报价服务实时可用。
部署未执行;未推送代码;其他客户端及实际 HTTPS/代理兼容性尚未验证。
+29
View File
@@ -0,0 +1,29 @@
# 贵金属克数与数据库注释更新
独立资产新增弹窗选择「贵金属」后,填写黄金/白银、克数、纯度、原币和业务时间,无需填写金额或市场单价。默认随参考价自动估值;没有有效报价时为「待估值」,总览提示不完整,不把未知价值作为已知零值。后续自动/手动报价继续沿用现有 MetalsService 和历史逻辑。
买入价为可选的每克实物成本(原币)。成本 = 总克数 × 买入价;估值 = 总克数 × 纯度 × 对应币种纯金属每克报价;盈亏 = 当前估值 − 成本。全程 Decimal,金额 8 位小数四舍五入;每克成本最多 12 位整数、12 位小数且必须大于零。它是估值盈亏,不包含未记录的税费/已实现卖出收益。省略或清空价格不显示盈亏,缺少估值时盈亏待定。旧贵金属资产可在详情补充成本。
## 服务、备份和 MCP
REST POST /api/metals/holdings 与 MCP metal_holding_create 共用 MetalsBusinessService.create;无需 amount。现有 PUT /api/metals/:id 与 metal_configure 接受可选 metalCostPerGram,省略保留、null 清除。position 查询返回 valuationAvailable、metalCost、metalProfit。前端只展示服务端结果,不以 Number 计算盈亏。
ZIP v8 增加可选成本字段,既有备份缺少字段仍可验证恢复;配置、成本和估值历史保持用户隔离。新 MCP 工具遵循服务端草稿、确认、幂等与并发规则,工具总数为 49。
## 迁移和启动
- 20261003120000_metal_cost:Position 增加可空 DECIMAL(24,12) metalCostPerGram,附中文字段注释,不回填未知成本。
- 20261003130000_migration_comments:为 Prisma 自己的迁移表和 8 个字段补齐注释,保持实际类型、可空性和默认值。
- 前一 MCP 提交已新增 20261003090000_agent_access、20261003100000_agent_audit、20261003110000_agent_comments。
全部 migration deploy 已在当前 MySQL 实际执行,累计 22 个迁移。scripts/check-comments.cjs 验证所有 17 张表、159 个字段均有注释,清单见 database-comments.json。无新增环境变量;启动命令见 [MCP 文档](mcp.md)。先暂停 API,再 db:generate、db:migrate,然后 dev;不使用 reset。
## 实际验证
- 前后端 typecheck/build 通过。
- 36 项单元测试通过:待估值完整性、精确克数成本、行情/失败回退、原计算和 ZIP 等。
- 18 组真实 REST/MySQL 测试通过:无价格克数创建、拥有报价创建、精确盈亏、成本保留/清除、外用户拒绝、无效克数拒绝、新备份恢复和旧备份兼容,以及原业务回归。
- 3 组官方 SDK/MySQL MCP 测试通过:包含新增克数工具真实写入和查询;原 OAuth、确认、幂等、并发与失败回滚继续通过。
- 登录后的新增弹窗尚未通过浏览器人工端到端验证:自动审批拒绝临时测试账号登录,等待用户授权。已有 MCP 管理页在前一阶段已浏览器验证。无其他商业 Agent 客户端或生产代理部署验证。
本次不部署、不推送、不改本地 .env,也不把图片保存进 docs。