feat(market-index): store MOEX index closes with confirmed coverage (WealthLedger/main#54)
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import type { MoexIndexClose } from '#src/integrations/moex/moex.client';
|
||||
|
||||
import { PrismaService } from '#src/prisma/prisma.service';
|
||||
|
||||
@Injectable()
|
||||
export class MarketIndexRepository {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async read(secid: 'IMOEX' | 'MCFTRR', from: string, to: string) {
|
||||
const [closes, state] = await Promise.all([
|
||||
this.prisma.marketIndexDailyClose.findMany({
|
||||
where: { secid, tradeDate: { gte: from, lte: to } },
|
||||
orderBy: { tradeDate: 'asc' },
|
||||
}),
|
||||
this.prisma.marketIndexSyncState.findUnique({ where: { secid } }),
|
||||
]);
|
||||
return { closes, state };
|
||||
}
|
||||
|
||||
async attempt(secid: 'IMOEX' | 'MCFTRR', at: Date) {
|
||||
await this.prisma.marketIndexSyncState.upsert({
|
||||
where: { secid }, create: { secid, lastAttemptAt: at }, update: { lastAttemptAt: at },
|
||||
});
|
||||
}
|
||||
|
||||
// coveredTo is the `till` MOEX answered for: a close for today that is not
|
||||
// published yet is re-checked by the service while the last close < to.
|
||||
async save(secid: 'IMOEX' | 'MCFTRR', closes: MoexIndexClose[], from: string, to: string, at: Date) {
|
||||
await this.prisma.$transaction(async (tx) => {
|
||||
for (const close of closes) {
|
||||
await tx.marketIndexDailyClose.upsert({
|
||||
where: { secid_tradeDate: { secid, tradeDate: close.tradeDate } },
|
||||
create: { secid, ...close },
|
||||
update: { close: close.close },
|
||||
});
|
||||
}
|
||||
const state = await tx.marketIndexSyncState.findUniqueOrThrow({ where: { secid } });
|
||||
const joined = Boolean(state.coveredFrom && state.coveredTo &&
|
||||
from <= state.coveredTo && to >= state.coveredFrom);
|
||||
await tx.marketIndexSyncState.update({
|
||||
where: { secid },
|
||||
data: {
|
||||
lastSuccessAt: at,
|
||||
coveredFrom: joined && state.coveredFrom && state.coveredFrom < from ? state.coveredFrom : from,
|
||||
coveredTo: joined && state.coveredTo && state.coveredTo > to ? state.coveredTo : to,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user