From b131400aa91fb4838c006115f17aff8c85c3bc83 Mon Sep 17 00:00:00 2001 From: kennethcheng Date: Thu, 30 Apr 2026 13:42:51 +0800 Subject: [PATCH] =?UTF-8?q?fix(ledger):=20=E8=A1=A5=E5=85=A8=20getEffectiv?= =?UTF-8?q?ePrice=20=E5=A4=8D=E5=90=88=E6=9F=A5=E8=AF=A2=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=8E=86=E5=8F=B2=E4=BB=B7=E6=A0=BC?= =?UTF-8?q?=E8=B7=A8=E8=B5=84=E4=BA=A7=E4=B8=B2=E8=81=94=20Bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Memory.md | 7 ++++++- src/actions/snapshots.ts | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Memory.md b/Memory.md index 1959b15..f2b8c10 100644 --- a/Memory.md +++ b/Memory.md @@ -167,4 +167,9 @@ - 修复 `getHistoricalPositions` 和 `getEffectivePrice` 中的日期字符串生成逻辑:统一使用 `formatDateString(targetDate)`,确保 Drizzle 的 `lte` 查询中左右两边日期字符串格式一致(均为 `YYYY-MM-DD`),修复了 UTC 与本地时区混用导致的查询偏移。 - 修复 `reconstructPortfolioHistory` 主循环:while 条件与 `dateStr` 生成均改用 `formatDateString(currentDate)`,确保与 `getTodayInShanghai()` 返回格式完全一致。 - 在资产遍历循环中增加兜底防御逻辑:当 `getEffectivePrice` 返回 null 时,使用 `assetLatestPriceMap` 中缓存的 `latestPrice` 作为兜底价格,避免价格变量为 undefined 或沿用上一资产的值;同时修正了 `totalCostCny` 在 `priceStr` 为空时不应累加的 Bug。 -- 在 `allAssets` 查询中新增 `latestPrice` 字段,构建 `assetLatestPriceMap` 供兜底逻辑使用。 \ No newline at end of file +- 在 `allAssets` 查询中新增 `latestPrice` 字段,构建 `assetLatestPriceMap` 供兜底逻辑使用。 + +## 修复 getEffectivePrice 引擎中 Drizzle ORM 缺失 and(eq(assetId)) 的致命逻辑漏网 +- 修复 `getEffectivePrice` 引擎中 Drizzle ORM 查询条件未使用 `and()` 复合操作符的致命逻辑漏网,确保历史断点结转价格精准匹配单一资产。 +- 在 `src/actions/snapshots.ts` 顶部从 `drizzle-orm` 引入 `and` 操作符,将 `getEffectivePrice` 的 `where` 子句从两个独立的 `.where()` 链式调用重构为 `and(eq(assetPricesHistory.assetId, assetId), lte(assetPricesHistory.date, dateStr))` 的显式复合条件。 +- 修复后 `assetId` 条件与日期条件被绝对锁定在同一个 `AND` 逻辑块中,彻底杜绝了周末等非交易日历史节点价格跨资产串联的荒谬市值问题(如海尔被错误匹配 BTC 价格导致 3700 万市值)。 \ No newline at end of file diff --git a/src/actions/snapshots.ts b/src/actions/snapshots.ts index 016a9e0..afb1b0f 100644 --- a/src/actions/snapshots.ts +++ b/src/actions/snapshots.ts @@ -3,7 +3,7 @@ import { db } from '@/db'; import { portfolioSnapshots, transactions, assetPricesHistory, assets, exchangeRates } from '@/db/schema'; import { getPortfolioPositions } from './portfolio'; -import { asc, desc, eq, gte, lte, sql } from 'drizzle-orm'; +import { and, asc, desc, eq, gte, lte, sql } from 'drizzle-orm'; import Big from 'big.js'; function formatDateString(date: Date): string { @@ -194,8 +194,12 @@ export async function getEffectivePrice( price: assetPricesHistory.price, }) .from(assetPricesHistory) - .where(eq(assetPricesHistory.assetId, assetId)) - .where(lte(assetPricesHistory.date, dateStr)) + .where( + and( + eq(assetPricesHistory.assetId, assetId), + lte(assetPricesHistory.date, dateStr) + ) + ) .orderBy(desc(assetPricesHistory.date)) .limit(1);