UNPKG

@accounter/server

Version:
72 lines (71 loc) 4.3 kB
import DataLoader from 'dataloader'; import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js'; import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js'; import { BusinessesProvider } from '../../financial-entities/providers/businesses.provider.js'; import { FinancialEntitiesProvider } from '../../financial-entities/providers/financial-entities.provider.js'; import { TaxCategoriesProvider } from '../../financial-entities/providers/tax-categories.provider.js'; import type { SecurityBusinessDescriptors, SecurityBusinessRow, SecurityIdentifierType } from '../types.js'; /** * A source's name for a security, *within an owner*. * * The owner is not optional: `(owner_id, identifier_type, identifier_value)` is what the relation * is unique on, and reads span the request's whole business scope. A key without it cannot * identify one security business. */ export type IdentifierKey = { ownerId: string; type: SecurityIdentifierType; value: string; }; export declare class SecurityBusinessesProvider { private db; private adminContextProvider; private financialEntitiesProvider; private businessesProvider; private taxCategoriesProvider; constructor(db: TenantAwareDBClient, adminContextProvider: AdminContextProvider, financialEntitiesProvider: FinancialEntitiesProvider, businessesProvider: BusinessesProvider, taxCategoriesProvider: TaxCategoriesProvider); private batchSecurityBusinessesByIds; getSecurityBusinessByIdLoader: DataLoader<string, import("../__generated__/security-businesses.types.js").IGetSecurityBusinessesByIdsResult | null, string>; private allSecurityBusinessesPromise; /** * Every security business of the acting tenant. Cached per request because charge typing and * account resolution ask for it on every transaction they touch. */ getAllSecurityBusinesses(): Promise<SecurityBusinessRow[]>; getAllSecurityBusinessIds(): Promise<Set<string>>; isSecurityBusiness(businessId: string): Promise<boolean>; private batchSecurityBusinessesByIdentifiers; getSecurityBusinessByIdentifierLoader: DataLoader<IdentifierKey, import("../__generated__/security-businesses.types.js").IGetAllSecurityBusinessesResult | null, string>; private batchIdentifiersByBusinessIds; getIdentifiersByBusinessIdLoader: DataLoader<string, import("../__generated__/security-businesses.types.js").IGetSecurityIdentifiersByBusinessIdsResult[], string>; /** The security businesses already created for these ISINs, keyed by ISIN. */ getSecurityBusinessesByIsins(isins: readonly string[]): Promise<Map<string, SecurityBusinessRow>>; private getSecurityBusinessByIsin; /** * The business a security is represented by, creating it on first sight. * * Idempotent by ISIN — see `createSecurityBusiness` for how a race is settled. */ ensureSecurityBusiness(descriptors: SecurityBusinessDescriptors): Promise<SecurityBusinessRow>; /** * The same for a batch, in one lookup: an ingest introduces a whole portfolio at once, and * asking per ISIN whether it exists costs a round trip for every security every scrape. * Only the ISINs with no business yet are created. */ ensureSecurityBusinesses(descriptorsList: readonly SecurityBusinessDescriptors[]): Promise<Map<string, SecurityBusinessRow>>; /** * Creates the business behind a security, assuming the caller has established there is none. * * Concurrent ingests race on the (owner_id, isin) unique index, and the loser rolls its whole * transaction back — financial entity and business included — then re-reads the winner's row, * so a race can't leave a half-built business behind. That fallback is also what makes the * caller's "there is none" only have to be true at the time it looked. * * Sort code, IRS code, country and tax category are inherited from the tenant's general * foreign-securities business, so a security behaves like it everywhere those fields drive * reporting. */ private createSecurityBusiness; linkIdentifier(businessId: string, identifierType: SecurityIdentifierType, identifierValue: string): Promise<void>; clearCache(): void; }