Filter non-RUB data at ingest, collapse per-currency collections into single RUB Money, drop currency from TbankPortfolioValuePoint, remove NON_RUB_ACTIVITY and screener currency filter. BREAKING CHANGE: per-currency API fields replaced with single RUB Money; stock screener currency param removed.
35 lines
1.4 KiB
TypeScript
35 lines
1.4 KiB
TypeScript
import { uncoveredOperationIntervals } from '../../operations/domain/operations-sync-plan';
|
|
|
|
const ZERO_MILLIS = 0;
|
|
const NEXT_MILLISECOND = 1;
|
|
|
|
export enum PerformanceUnavailableReason {
|
|
AccountValuationDatesDiffer = 'ACCOUNT_VALUATION_DATES_DIFFER',
|
|
AmbiguousReturn = 'AMBIGUOUS_RETURN',
|
|
HistoryStartUnknown = 'HISTORY_START_UNKNOWN',
|
|
IndexHistoryUnavailable = 'INDEX_HISTORY_UNAVAILABLE',
|
|
NoSolution = 'NO_SOLUTION',
|
|
OperationsHistoryIncomplete = 'OPERATIONS_HISTORY_INCOMPLETE',
|
|
PortfolioValuationIncomplete = 'PORTFOLIO_VALUATION_INCOMPLETE',
|
|
UnconfirmedTransfer = 'UNCONFIRMED_TRANSFER',
|
|
UnvaluedSecuritiesTransfer = 'UNVALUED_SECURITIES_TRANSFER',
|
|
}
|
|
|
|
export const performanceUnavailableReasons = Object.values(PerformanceUnavailableReason);
|
|
|
|
type Coverage = { asOf: Date; from: Date; to: Date };
|
|
|
|
/** Coverage is half-open and must include the instant of the last valuation. */
|
|
export function hasPerformanceCoverage(
|
|
accountId: string,
|
|
from: Date,
|
|
valuationAt: Date,
|
|
coverage: Coverage[],
|
|
): boolean {
|
|
if (from.valueOf() >= valuationAt.valueOf()) return false;
|
|
const end = new Date(valuationAt.valueOf() + NEXT_MILLISECOND);
|
|
if (!coverage.some((item) => item.asOf >= valuationAt && item.to > valuationAt)) return false;
|
|
const confirmed = coverage.map((item) => ({ accountId, from: item.from, to: item.to }));
|
|
return uncoveredOperationIntervals([{ accountId, from, to: end }], confirmed).length === ZERO_MILLIS;
|
|
}
|