|
|
@ -30,7 +30,7 @@ import { |
|
|
import type { Granularity, UserWithSettings } from '@ghostfolio/common/types'; |
|
|
import type { Granularity, UserWithSettings } from '@ghostfolio/common/types'; |
|
|
|
|
|
|
|
|
import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common'; |
|
|
import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common'; |
|
|
import { DataSource, MarketData, SymbolProfile } from '@prisma/client'; |
|
|
import { DataSource, MarketData, Prisma, SymbolProfile } from '@prisma/client'; |
|
|
import { Big } from 'big.js'; |
|
|
import { Big } from 'big.js'; |
|
|
import { eachDayOfInterval, format, isValid } from 'date-fns'; |
|
|
import { eachDayOfInterval, format, isValid } from 'date-fns'; |
|
|
import { groupBy, isEmpty, isNumber, uniqWith } from 'lodash'; |
|
|
import { groupBy, isEmpty, isNumber, uniqWith } from 'lodash'; |
|
|
@ -347,36 +347,35 @@ export class DataProviderService implements OnModuleInit { |
|
|
|
|
|
|
|
|
const granularityQuery = |
|
|
const granularityQuery = |
|
|
aGranularity === 'month' |
|
|
aGranularity === 'month' |
|
|
? `AND (date_part('day', date) = 1 OR date >= TIMESTAMP 'yesterday')` |
|
|
? Prisma.sql`AND (date_part('day', date) = 1 OR date >= TIMESTAMP 'yesterday')` |
|
|
: ''; |
|
|
: Prisma.empty; |
|
|
|
|
|
|
|
|
const rangeQuery = |
|
|
const rangeQuery = |
|
|
from && to |
|
|
from && to |
|
|
? `AND date >= '${format(from, DATE_FORMAT)}' AND date <= '${format( |
|
|
? Prisma.sql`AND date >= ${format(from, DATE_FORMAT)}::timestamp AND date <= ${format( |
|
|
to, |
|
|
to, |
|
|
DATE_FORMAT |
|
|
DATE_FORMAT |
|
|
)}'` |
|
|
)}::timestamp` |
|
|
: ''; |
|
|
: Prisma.empty; |
|
|
|
|
|
|
|
|
const dataSources = aItems.map(({ dataSource }) => { |
|
|
const dataSources = aItems.map(({ dataSource }) => { |
|
|
return dataSource; |
|
|
return dataSource; |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
const symbols = aItems.map(({ symbol }) => { |
|
|
const symbols = aItems.map(({ symbol }) => { |
|
|
return symbol; |
|
|
return symbol; |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
const queryRaw = ` |
|
|
const marketDataByGranularity: MarketData[] = await this.prismaService |
|
|
SELECT * |
|
|
.$queryRaw` |
|
|
FROM "MarketData" |
|
|
SELECT * |
|
|
WHERE "dataSource" IN ('${dataSources.join(`','`)}') |
|
|
FROM "MarketData" |
|
|
AND "symbol" IN ('${symbols.join( |
|
|
WHERE "dataSource"::text IN (${Prisma.join(dataSources)}) |
|
|
`','` |
|
|
AND "symbol" IN (${Prisma.join(symbols)}) |
|
|
)}') ${granularityQuery} ${rangeQuery} |
|
|
${granularityQuery} |
|
|
ORDER BY date;`;
|
|
|
${rangeQuery} |
|
|
|
|
|
ORDER BY date;`;
|
|
|
const marketDataByGranularity: MarketData[] = |
|
|
|
|
|
await this.prismaService.$queryRawUnsafe(queryRaw); |
|
|
|
|
|
|
|
|
|
|
|
response = marketDataByGranularity.reduce((r, marketData) => { |
|
|
response = marketDataByGranularity.reduce((r, marketData) => { |
|
|
const { date, marketPrice, symbol } = marketData; |
|
|
const { date, marketPrice, symbol } = marketData; |
|
|
|