Automate issuer overlay creation from ticker searches
This commit is contained in:
@@ -55,6 +55,10 @@ function createHydrationResult(): TaxonomyHydrationResult {
|
||||
kpi_row_count: 0,
|
||||
unmapped_row_count: 0,
|
||||
material_unmapped_row_count: 0,
|
||||
residual_primary_count: 0,
|
||||
residual_disclosure_count: 0,
|
||||
unsupported_concept_count: 0,
|
||||
issuer_overlay_match_count: 0,
|
||||
warnings: ["rust_warning"],
|
||||
},
|
||||
xbrl_validation: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
TaxonomyHydrationInput,
|
||||
TaxonomyHydrationResult,
|
||||
} from "@/lib/server/taxonomy/types";
|
||||
import type { IssuerOverlayDefinition } from "@/lib/server/db/schema";
|
||||
import { __parserClientInternals } from "@/lib/server/taxonomy/parser-client";
|
||||
|
||||
function streamFromText(text: string) {
|
||||
@@ -81,6 +82,10 @@ function sampleHydrationResult(): TaxonomyHydrationResult {
|
||||
kpi_row_count: 0,
|
||||
unmapped_row_count: 0,
|
||||
material_unmapped_row_count: 0,
|
||||
residual_primary_count: 0,
|
||||
residual_disclosure_count: 0,
|
||||
unsupported_concept_count: 0,
|
||||
issuer_overlay_match_count: 0,
|
||||
warnings: [],
|
||||
},
|
||||
xbrl_validation: {
|
||||
@@ -103,6 +108,22 @@ function sampleInput(): TaxonomyHydrationInput {
|
||||
};
|
||||
}
|
||||
|
||||
function sampleOverlay(): IssuerOverlayDefinition {
|
||||
return {
|
||||
version: "fiscal-v1",
|
||||
ticker: "AAPL",
|
||||
pack: "core",
|
||||
mappings: [
|
||||
{
|
||||
surface_key: "revenue",
|
||||
statement: "income",
|
||||
allowed_source_concepts: ["aapl:ServicesRevenue"],
|
||||
allowed_authoritative_concepts: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const passThroughTimeout = ((handler: TimerHandler, timeout?: number) =>
|
||||
globalThis.setTimeout(
|
||||
handler,
|
||||
@@ -156,6 +177,47 @@ describe("parser client", () => {
|
||||
expect(result.parser_engine).toBe("fiscal-xbrl");
|
||||
expect(stdinWrite).toHaveBeenCalledTimes(1);
|
||||
expect(stdinEnd).toHaveBeenCalledTimes(1);
|
||||
const [firstCall] = stdinWrite.mock.calls as unknown[][];
|
||||
const firstWrite = firstCall?.[0];
|
||||
expect(firstWrite).toBeDefined();
|
||||
const payload = JSON.parse(
|
||||
new TextDecoder().decode(firstWrite as unknown as Uint8Array),
|
||||
) as { issuerOverlay?: IssuerOverlayDefinition | null };
|
||||
expect(payload.issuerOverlay).toBeNull();
|
||||
});
|
||||
|
||||
it("includes issuer overlay payload when provided", async () => {
|
||||
const stdinWrite = mock(() => {});
|
||||
|
||||
await __parserClientInternals.hydrateFromSidecarImpl(
|
||||
{
|
||||
...sampleInput(),
|
||||
issuerOverlay: sampleOverlay(),
|
||||
},
|
||||
{
|
||||
existsSync: () => true,
|
||||
spawn: mock(() => ({
|
||||
stdin: {
|
||||
write: stdinWrite,
|
||||
end: () => {},
|
||||
},
|
||||
stdout: streamFromText(JSON.stringify(sampleHydrationResult())),
|
||||
stderr: streamFromText(""),
|
||||
exited: Promise.resolve(0),
|
||||
kill: mock(() => {}),
|
||||
})) as never,
|
||||
setTimeout: passThroughTimeout,
|
||||
clearTimeout,
|
||||
},
|
||||
);
|
||||
|
||||
const [firstCall] = stdinWrite.mock.calls as unknown[][];
|
||||
const firstWrite = firstCall?.[0];
|
||||
expect(firstWrite).toBeDefined();
|
||||
const payload = JSON.parse(
|
||||
new TextDecoder().decode(firstWrite as unknown as Uint8Array),
|
||||
) as { issuerOverlay?: IssuerOverlayDefinition | null };
|
||||
expect(payload.issuerOverlay).toEqual(sampleOverlay());
|
||||
});
|
||||
|
||||
it("throws when the sidecar exits non-zero", async () => {
|
||||
|
||||
@@ -32,7 +32,7 @@ function candidateBinaryPaths() {
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveFiscalXbrlBinary() {
|
||||
function resolveFiscalXbrlBinary() {
|
||||
return resolveFiscalXbrlBinaryWithDeps({
|
||||
existsSync,
|
||||
});
|
||||
@@ -93,6 +93,7 @@ async function hydrateFromSidecarImpl(
|
||||
filingType: input.filingType,
|
||||
filingUrl: input.filingUrl,
|
||||
primaryDocument: input.primaryDocument,
|
||||
issuerOverlay: input.issuerOverlay ?? null,
|
||||
cacheDir:
|
||||
process.env.FISCAL_XBRL_CACHE_DIR ??
|
||||
join(process.cwd(), ".cache", "xbrl"),
|
||||
|
||||
@@ -2,6 +2,7 @@ import type {
|
||||
Filing,
|
||||
FinancialStatementKind,
|
||||
MetricValidationResult,
|
||||
TickerAutomationSource,
|
||||
} from "@/lib/types";
|
||||
import type { ComputedDefinition } from "@/lib/generated";
|
||||
import type {
|
||||
@@ -10,6 +11,7 @@ import type {
|
||||
FilingTaxonomyPeriod,
|
||||
FilingTaxonomySource,
|
||||
} from "@/lib/server/repos/filing-taxonomy";
|
||||
import type { IssuerOverlayDefinition } from "@/lib/server/db/schema";
|
||||
|
||||
export type TaxonomyAsset = {
|
||||
asset_type: FilingTaxonomyAssetType;
|
||||
@@ -20,9 +22,9 @@ export type TaxonomyAsset = {
|
||||
is_selected: boolean;
|
||||
};
|
||||
|
||||
export type TaxonomyNamespaceMap = Record<string, string>;
|
||||
type TaxonomyNamespaceMap = Record<string, string>;
|
||||
|
||||
export type TaxonomyContext = {
|
||||
type TaxonomyContext = {
|
||||
id: string;
|
||||
entityIdentifier: string | null;
|
||||
entityScheme: string | null;
|
||||
@@ -40,7 +42,7 @@ export type TaxonomyContext = {
|
||||
} | null;
|
||||
};
|
||||
|
||||
export type TaxonomyUnit = {
|
||||
type TaxonomyUnit = {
|
||||
id: string;
|
||||
measure: string | null;
|
||||
};
|
||||
@@ -65,7 +67,7 @@ export type TaxonomyFact = {
|
||||
sourceFile: string | null;
|
||||
};
|
||||
|
||||
export type TaxonomyPresentationConcept = {
|
||||
type TaxonomyPresentationConcept = {
|
||||
conceptKey: string;
|
||||
qname: string;
|
||||
roleUri: string;
|
||||
@@ -157,7 +159,7 @@ export type TaxonomyHydrationSurfaceRow = {
|
||||
formula_key: string | null;
|
||||
has_dimensions: boolean;
|
||||
resolved_source_row_keys: Record<string, string | null>;
|
||||
statement?: "income" | "balance" | "cash_flow";
|
||||
statement?: "income" | "balance" | "cash_flow" | "equity" | "disclosure";
|
||||
detail_count?: number;
|
||||
resolution_method?:
|
||||
| "direct"
|
||||
@@ -206,6 +208,10 @@ export type TaxonomyHydrationNormalizationSummary = {
|
||||
kpi_row_count: number;
|
||||
unmapped_row_count: number;
|
||||
material_unmapped_row_count: number;
|
||||
residual_primary_count: number;
|
||||
residual_disclosure_count: number;
|
||||
unsupported_concept_count: number;
|
||||
issuer_overlay_match_count: number;
|
||||
warnings: string[];
|
||||
};
|
||||
|
||||
@@ -223,6 +229,12 @@ export type TaxonomyHydrationInput = {
|
||||
filingType: "10-K" | "10-Q";
|
||||
filingUrl: string | null;
|
||||
primaryDocument: string | null;
|
||||
issuerOverlay?: IssuerOverlayDefinition | null;
|
||||
};
|
||||
|
||||
export type TickerAutomationRequest = {
|
||||
ticker: string;
|
||||
source: TickerAutomationSource;
|
||||
};
|
||||
|
||||
export type TaxonomyHydrationResult = {
|
||||
|
||||
Reference in New Issue
Block a user