stock-portfolio_byQwen3.6/src/actions/snapshots.ts

105 lines
2.4 KiB
TypeScript

'use server';
import { db } from '@/db';
import { portfolioSnapshots } from '@/db/schema';
import { getPortfolioPositions } from './portfolio';
import { eq, sql } from 'drizzle-orm';
import Big from 'big.js';
function getTodayInShanghai(): string {
const now = new Date();
const utcStr = now.toLocaleString('en-US', { timeZone: 'UTC' });
const utcDate = new Date(utcStr);
const shanghaiOffset = 8 * 60 * 60 * 1000;
const shanghaiDate = new Date(utcDate.getTime() + shanghaiOffset);
const year = shanghaiDate.getFullYear();
const month = String(shanghaiDate.getMonth() + 1).padStart(2, '0');
const day = String(shanghaiDate.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
export async function recordDailySnapshot() {
const positions = await getPortfolioPositions();
const totalValueCny = positions.reduce(
(sum, pos) => sum.plus(pos.cnyValue || '0'),
new Big(0)
).toString();
const totalCostCny = positions.reduce(
(sum, pos) => sum.plus(pos.totalCostCny || '0'),
new Big(0)
).toString();
const dateStr = getTodayInShanghai();
const existing = await db
.select()
.from(portfolioSnapshots)
.where(eq(portfolioSnapshots.date, dateStr))
.limit(1);
const now = new Date();
if (existing.length > 0) {
await db
.update(portfolioSnapshots)
.set({
totalValueCny,
totalCostCny,
updatedAt: now,
})
.where(eq(portfolioSnapshots.date, dateStr));
return {
success: true,
action: 'updated',
date: dateStr,
totalValueCny,
totalCostCny,
};
}
await db
.insert(portfolioSnapshots)
.values({
date: dateStr,
totalValueCny,
totalCostCny,
createdAt: now,
updatedAt: now,
});
return {
success: true,
action: 'inserted',
date: dateStr,
totalValueCny,
totalCostCny,
};
}
export async function getSnapshots(params?: {
limit?: number;
startDate?: string;
endDate?: string;
}) {
const { limit = 365, startDate, endDate } = params || {};
let query = db
.select()
.from(portfolioSnapshots)
.orderBy(sql`"${date}" DESC`);
if (startDate) {
query = query.where(sql`"${date}" >= ${startDate}`);
}
if (endDate) {
query = query.where(sql`"${date}" <= ${endDate}`);
}
const snapshots = await query.limit(limit);
return snapshots.reverse();
}