import type { VrLike } from './clients.js'; export type OwnerKind = 'person' | 'company'; export type OwnerConfidenceTier = 'HIGH' | 'LOW'; export interface OwnerConfidence { tier: OwnerConfidenceTier; score: number; basis: 'NAME_AND_BIRTH_YEAR' | 'NAME_ONLY' | 'COMPANY_ICO'; ambiguous: boolean; } export interface OwnerEntry { kind: OwnerKind; name: string | null; ico: string | null; person_id: string | null; birth_year: number | null; share: string | null; share_percent: number | null; type: string | null; role: string | null; valid_from: string | null; confidence: OwnerConfidence; namesake_flag: boolean; } export interface OwnershipNode { ico: string; name: string | null; depth: number; path: string[]; cycle: boolean; owners: OwnerEntry[]; children: OwnershipNode[]; } export interface OwnersResult { query: { ico: string; max_depth: number; }; as_of: string | null; source: 'vr'; root: OwnershipNode; direct_owners: OwnerEntry[]; chains: string[][]; warnings: string[]; } export declare const OWNERSHIP_ROLE_FILTER_SQL = "\n r.valid_to IS NULL\n AND r.share_type IS NOT NULL\n AND (\n r.share_type ILIKE '%spole%'\n OR r.share_type ILIKE '%akcion%'\n )\n"; export declare const OWNERS_SQL = "\nWITH RECURSIVE owner_nodes_raw AS (\n SELECT\n c.ico,\n c.name,\n c.source_dataset,\n 0::int AS depth,\n ARRAY[c.ico]::text[] AS path,\n false AS cycle\n FROM vr.companies c\n WHERE c.ico = $1\n\n UNION ALL\n\n SELECT\n owner_edge.member_ico AS ico,\n mc.name,\n mc.source_dataset,\n n.depth + 1 AS depth,\n n.path || owner_edge.member_ico,\n owner_edge.member_ico = ANY(n.path) AS cycle\n FROM owner_nodes_raw n\n JOIN LATERAL (\n SELECT DISTINCT r.member_ico\n FROM vr.roles r\n WHERE r.company_ico = n.ico\n AND \n r.valid_to IS NULL\n AND r.share_type IS NOT NULL\n AND (\n r.share_type ILIKE '%spole%'\n OR r.share_type ILIKE '%akcion%'\n )\n\n AND r.member_ico IS NOT NULL\n ) owner_edge ON true\n LEFT JOIN vr.companies mc ON mc.ico = owner_edge.member_ico\n WHERE n.depth < $2\n AND n.cycle = false\n),\nowner_nodes AS (\n SELECT DISTINCT ON (path) *\n FROM owner_nodes_raw\n ORDER BY path, depth\n),\nperson_name_counts AS (\n SELECT\n p.full_name,\n extract(year FROM p.birth_date)::int AS birth_year,\n count(*)::int AS same_name_birth_year_count\n FROM vr.persons p\n JOIN (\n SELECT DISTINCT\n owner_person.full_name,\n extract(year FROM owner_person.birth_date)::int AS birth_year\n FROM owner_nodes n\n JOIN vr.roles r ON r.company_ico = n.ico AND \n r.valid_to IS NULL\n AND r.share_type IS NOT NULL\n AND (\n r.share_type ILIKE '%spole%'\n OR r.share_type ILIKE '%akcion%'\n )\n\n JOIN vr.persons owner_person ON owner_person.id = r.person_id\n WHERE r.member_ico IS NULL\n ) owner_names\n ON owner_names.full_name = p.full_name\n AND owner_names.birth_year IS NOT DISTINCT FROM extract(year FROM p.birth_date)::int\n GROUP BY p.full_name, extract(year FROM p.birth_date)::int\n)\nSELECT\n n.ico,\n n.name,\n n.source_dataset,\n n.depth,\n n.path,\n n.cycle,\n asof.finished_at AS as_of,\n COALESCE(o.owners, '[]'::jsonb) AS owners\nFROM owner_nodes n\nLEFT JOIN LATERAL (\n SELECT il.finished_at\n FROM vr.import_log il\n WHERE il.dataset = n.source_dataset\n AND il.status = 'done'\n ORDER BY il.finished_at DESC NULLS LAST\n LIMIT 1\n) asof ON true\nLEFT JOIN LATERAL (\n -- Dedup vlastn\u00EDk\u016F na IDENTITU (member_ico u firem; jm\u00E9no+rok u osob/ciz\u00EDch\n -- entit). VR raw data maj\u00ED duplicitn\u00ED role \u0159\u00E1dky (re-ingest + historie) li\u0161\u00EDc\u00ED\n -- se valid_from/role \u2192 DISTINCT na cel\u00E9m objektu je NEslou\u010D\u00ED. DISTINCT ON\n -- identitu, bereme nejnov\u011Bj\u0161\u00ED z\u00E1znam (valid_from DESC).\n SELECT jsonb_agg(d.owner_obj) AS owners\n FROM (\n SELECT DISTINCT ON (COALESCE(r.member_ico, lower(trim(p.full_name)) || '|' || COALESCE(extract(year FROM p.birth_date)::text, '')))\n jsonb_build_object(\n 'kind', CASE WHEN r.member_ico IS NULL THEN 'person' ELSE 'company' END,\n 'name', COALESCE(mc.name, p.full_name),\n 'ico', r.member_ico,\n 'person_id', CASE WHEN r.member_ico IS NULL THEN p.id::text ELSE NULL END,\n 'birth_year', CASE WHEN r.member_ico IS NULL THEN extract(year FROM p.birth_date)::int ELSE NULL END,\n 'share', r.share_type,\n 'type', split_part(r.share_type, ' | ', 1),\n 'role', r.role,\n 'valid_from', r.valid_from,\n 'namesake_flag', CASE WHEN r.member_ico IS NULL THEN COALESCE(pnc.same_name_birth_year_count, 0) > 1 ELSE false END\n ) AS owner_obj\n FROM vr.roles r\n LEFT JOIN vr.persons p ON p.id = r.person_id\n LEFT JOIN vr.companies mc ON mc.ico = r.member_ico\n LEFT JOIN person_name_counts pnc\n ON pnc.full_name = p.full_name\n AND pnc.birth_year IS NOT DISTINCT FROM extract(year FROM p.birth_date)::int\n WHERE r.company_ico = n.ico\n AND \n r.valid_to IS NULL\n AND r.share_type IS NOT NULL\n AND (\n r.share_type ILIKE '%spole%'\n OR r.share_type ILIKE '%akcion%'\n )\n\n AND r.person_id IS NOT NULL\n ORDER BY COALESCE(r.member_ico, lower(trim(p.full_name)) || '|' || COALESCE(extract(year FROM p.birth_date)::text, '')),\n r.valid_from DESC NULLS LAST\n ) d\n) o ON true\nORDER BY n.depth, n.path\n"; export declare function lookupOwners(vr: VrLike, input: { ico: string; maxDepth?: number; }): Promise; export declare function buildOwnersMarkdown(result: OwnersResult): string; //# sourceMappingURL=vr-owners.d.ts.map