Files
docs/khata-app/lib/search/search_index.json

1 line
616 KiB
JSON

{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"domain","text":""},{"location":"#modules","title":"Modules","text":"<ul> <li>Domain</li> <li>Infra</li> <li>Interfaces</li> <li>Pipelines</li> </ul>"},{"location":"domain/","title":"Domain","text":"<ul> <li>Account</li> <li>Enrichment</li> <li>Entity</li> <li>Expense</li> <li>Fetch Pipeline</li> <li>Fetch Request</li> <li>Fetcher</li> <li>Report</li> <li>Tag</li> <li>Upload</li> <li>User</li> </ul>"},{"location":"domain/#domain","title":"domain","text":""},{"location":"domain/#domain--summary","title":"Summary","text":"<p>The Expenses Service domain layer: business knowledge, models, ports, enrichment and fetch pipelines, with zero I/O.</p> <p>The domain package holds the rules of the Expenses Service: pydantic models, abstract ports, and the enrichment/fetch pipeline logic. No module here touches the network, the database, or user-facing HTTP; all external effects flow through ports implemented by the infrastructure layer and injected at the composition root.</p>"},{"location":"domain/#domain--installation","title":"Installation","text":"<p>Install the Expenses Service with its development tooling:</p> <pre><code>pip install -e \".[dev]\"\n</code></pre>"},{"location":"domain/#domain--quick-start","title":"Quick start","text":"<p>Resolve the lazily cached entity enrichment pipeline and run it over a minimal state payload:</p> <pre><code>```python\nfrom domain.enrichment.entity.pipeline import get_entity_pipeline\n\npipeline = get_entity_pipeline()\nresult = pipeline.enrich({\"candidate\": {\"flags\": []}, \"tags\": []})\n```\n</code></pre>"},{"location":"domain/#domain--core-concepts","title":"Core concepts","text":"<ul> <li>Three-layer architecture: <code>interface</code> (OpenAPI/FastAPI routes) \u2192 <code>domain</code> (business rules, zero I/O) \u2192 <code>infra</code> (MongoDB, SSE, OCR, LLM providers). Each layer imports only the one below it.</li> <li>Models: pydantic schemas that validate the data the domain moves, from fetch requests to enriched expenses.</li> <li>Ports: abstract contracts the domain needs from the outside world; infrastructure implementations are injected via <code>hexa.build</code>.</li> <li>Enrichment: rule-driven pipelines (entity + tags) that turn raw descriptions into payees and tags.</li> <li>Fetch pipeline: extracts expenses from pdf, email, xlsx, csv and LlamaParse sources, then enriches and persists them.</li> </ul>"},{"location":"domain/#domain--notes","title":"Notes","text":"<p>Guarantees:</p> <ul> <li>Domain code performs zero I/O; persistence, OCR, LLM calls and streaming happen only through injected ports and adaptors.</li> </ul> <p>Lifecycle:</p> <ul> <li>The package is compiled statically by <code>doc-forge</code> from its GSDFC docstrings; source remains the single source of truth.</li> </ul>"},{"location":"domain/account/","title":"Account","text":"<ul> <li>Models</li> <li>Ports</li> </ul>"},{"location":"domain/account/#domain.account","title":"domain.account","text":""},{"location":"domain/account/#domain.account--summary","title":"Summary","text":"<p>Account domain: the Account aggregate, its Mongo document schema, and CRUD service wiring.</p>"},{"location":"domain/account/models/","title":"Models","text":""},{"location":"domain/account/models/#domain.account.models","title":"domain.account.models","text":""},{"location":"domain/account/models/#domain.account.models--summary","title":"Summary","text":"<p>Define the Account aggregate model shared by the service and storage layers.</p>"},{"location":"domain/account/models/#domain.account.models-classes","title":"Classes","text":""},{"location":"domain/account/models/#domain.account.models.Account","title":"Account","text":"<p> Bases: <code>BaseModel</code></p> <p>Account aggregate: banking details plus the owning user.</p> <p>Attributes:</p> Name Type Description <code>name</code> <code>str</code> <p>Display name of the account.</p> <code>number</code> <code>str</code> <p>Account number; empty when unknown.</p> <code>type</code> <code>str</code> <p>Account kind, e.g. <code>\"bank\"</code>.</p> <code>currency</code> <code>str</code> <p>Currency code the account operates in, e.g. <code>\"INR\"</code>.</p> <code>owner</code> <code>User</code> <p>User that owns the account.</p>"},{"location":"domain/account/ports/","title":"Ports","text":"<ul> <li>Db</li> <li>Service</li> </ul>"},{"location":"domain/account/ports/#domain.account.ports","title":"domain.account.ports","text":""},{"location":"domain/account/ports/#domain.account.ports--summary","title":"Summary","text":"<p>Port wiring for the account aggregate: Mongo repository and CRUD service wiring.</p>"},{"location":"domain/account/ports/db/","title":"Db","text":""},{"location":"domain/account/ports/db/#domain.account.ports.db","title":"domain.account.ports.db","text":""},{"location":"domain/account/ports/db/#domain.account.ports.db--summary","title":"Summary","text":"<p>Mongo persistence for accounts: document schema and repository factory.</p>"},{"location":"domain/account/ports/db/#domain.account.ports.db-classes","title":"Classes","text":""},{"location":"domain/account/ports/db/#domain.account.ports.db.AccountDocument","title":"AccountDocument","text":"<p> Bases: <code>Account</code>, <code>BaseDocument</code></p> <p>Mongo document form of :class:<code>Account</code> with a populated owner reference.</p> <p>Attributes:</p> Name Type Description <code>owner</code> <code>UserDocument</code> <p>Populated owner document stored as a reference.</p>"},{"location":"domain/account/ports/db/#domain.account.ports.db-functions","title":"Functions","text":""},{"location":"domain/account/ports/db/#domain.account.ports.db.create_account_repo","title":"create_account_repo","text":"<pre><code>create_account_repo(user_repo: Any = None)\n</code></pre> <p>Create a Mongo-backed account repository wired for owner population.</p> <p>Parameters:</p> Name Type Description Default <code>user_repo</code> <code>Any</code> <p>User repository used to populate the <code>owner</code> reference.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>Any</code> <p>Mongo-backed account repository configured with a replace-owner population rule.</p>"},{"location":"domain/account/ports/service/","title":"Service","text":""},{"location":"domain/account/ports/service/#domain.account.ports.service","title":"domain.account.ports.service","text":""},{"location":"domain/account/ports/service/#domain.account.ports.service--summary","title":"Summary","text":"<p>CRUD service wiring for the account aggregate via the hexa container.</p>"},{"location":"domain/account/ports/service/#domain.account.ports.service-classes","title":"Classes","text":""},{"location":"domain/account/ports/service/#domain.account.ports.service.AccountCrudsService","title":"AccountCrudsService","text":"<p> Bases: <code>CrudsServiceAdaptor[Account, AccountDocument]</code></p> <p>Account CRUD service resolving :class:<code>Account</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_account_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p>"},{"location":"domain/account/ports/service/#domain.account.ports.service-functions","title":"Functions","text":""},{"location":"domain/account/ports/service/#domain.account.ports.service.get_account_service","title":"get_account_service","text":"<pre><code>get_account_service(repo) -&gt; AccountCrudsService\n</code></pre> <p>Build an account CRUD service wired to <code>repo</code>.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>Any</code> <p>Mongo-backed account repository from :func:<code>create_account_repo</code>.</p> required <p>Returns:</p> Name Type Description <code>AccountCrudsService</code> <code>AccountCrudsService</code> <p>Ready-to-use account CRUD service.</p>"},{"location":"domain/enrichment/","title":"Enrichment","text":"<ul> <li>Entity</li> <li>Exceptions</li> <li>Models</li> <li>Nodes</li> <li>Tags</li> </ul>"},{"location":"domain/enrichment/#domain.enrichment","title":"domain.enrichment","text":""},{"location":"domain/enrichment/#domain.enrichment--summary","title":"Summary","text":"<p>Enrichment domain: rule-driven pipelines that resolve payee entities and tags from raw expense descriptions, backed by YAML pattern registries.</p> <p>Provides the shared pattern data models (<code>models</code>), the registry-aware pipeline node base (<code>nodes</code>), and two pipeline families: <code>entity</code> (entity/payee resolution) and <code>tags</code> (flag and tag attachment).</p>"},{"location":"domain/enrichment/#domain.enrichment--notes","title":"Notes","text":"<p>Guarantees:</p> <ul> <li>No network or persistence I/O happens in this package; flow is driven by the interface/infrastructure layers through the pipeline adaptors.</li> </ul> <p>Lifecycle:</p> <ul> <li>Each loader compiles a <code>dagpipe</code> graph from packaged resources and caches it per pipeline name; nodes are wired with their pattern registry and node config at load time.</li> </ul>"},{"location":"domain/enrichment/exceptions/","title":"Exceptions","text":""},{"location":"domain/enrichment/exceptions/#domain.enrichment.exceptions","title":"domain.enrichment.exceptions","text":""},{"location":"domain/enrichment/exceptions/#domain.enrichment.exceptions--summary","title":"Summary","text":"<p>Exception types raised by the enrichment domain when a tag alias cannot be resolved to a seeded tag.</p>"},{"location":"domain/enrichment/exceptions/#domain.enrichment.exceptions--notes","title":"Notes","text":"<p>Guarantees:</p> <ul> <li>Errors carry the offending tag name so the interface layer can prompt for manual seeding.</li> </ul>"},{"location":"domain/enrichment/exceptions/#domain.enrichment.exceptions-classes","title":"Classes","text":""},{"location":"domain/enrichment/exceptions/#domain.enrichment.exceptions.NewTagFoundError","title":"NewTagFoundError","text":"<pre><code>NewTagFoundError(tag_name: str)\n</code></pre> <p> Bases: <code>Exception</code></p> <p>Raised when an alias matches a tag name that has no seed entry.</p> <p>Attributes:</p> Name Type Description <code>tag_name</code> <code>str</code> <p>The tag name that matched but was not found.</p> <code>message</code> <code>str</code> <p>The message text passed to the exception base class, prompting manual seeding.</p>"},{"location":"domain/enrichment/models/","title":"Models","text":""},{"location":"domain/enrichment/models/#domain.enrichment.models","title":"domain.enrichment.models","text":""},{"location":"domain/enrichment/models/#domain.enrichment.models--summary","title":"Summary","text":"<p>Pydantic models for enrichment patterns: a discriminated union of pattern payloads (<code>Pattern</code>) and a versioned <code>PatternRegistry</code> lookup table compiled by the pipeline loaders.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models--notes","title":"Notes","text":"<p>Guarantees:</p> <ul> <li><code>Pattern</code> discriminates on the <code>type</code> field, so a payload whose marker does not match its shape fails pydantic validation.</li> </ul> <p>Lifecycle:</p> <ul> <li>Registries are assembled once per load from the packaged <code>resources/patterns/*.yaml</code> files and treated as read-only after construction.</li> </ul>"},{"location":"domain/enrichment/models/#domain.enrichment.models-classes","title":"Classes","text":""},{"location":"domain/enrichment/models/#domain.enrichment.models.ArrayPattern","title":"ArrayPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Ordered list pattern, e.g. negative candidate lists.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[ARRAY]</code> <p>Constant marker for this shape.</p> <code>array</code> <code>List</code> <p>The ordered list payload.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.BasePattern","title":"BasePattern","text":"<p> Bases: <code>BaseModel</code></p> <p>Base class for all pattern payloads.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>PatternType</code> <p>Discriminator identifying the concrete pattern shape.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.KeywordsPattern","title":"KeywordsPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Keyword list pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[KEYWORDS]</code> <p>Constant marker for this shape.</p> <code>items</code> <code>List[str]</code> <p>Keywords that match, in any order.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.MappingPattern","title":"MappingPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Key/value mapping pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[MAPPING]</code> <p>Constant marker for this shape.</p> <code>mapping</code> <code>Dict[str, Union[str, MappingValue, List]]</code> <p>Mapping keys to bare strings, structured values, or lists.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.MappingValue","title":"MappingValue","text":"<p> Bases: <code>BaseModel</code></p> <p>A single mapping entry value carrying an id and display name.</p> <p>Attributes:</p> Name Type Description <code>id</code> <code>str</code> <p>Stable identifier for the mapped value.</p> <code>name</code> <code>str</code> <p>Human-readable display name.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry","title":"PatternRegistry","text":"<p> Bases: <code>BaseModel</code></p> <p>Versioned registry of named enrichment patterns.</p> <p>Accessors dispatch on the runtime pattern type and raise <code>TypeError</code> when the stored pattern has a different shape than requested.</p> <p>Attributes:</p> Name Type Description <code>version</code> <code>int</code> <p>Registry schema version.</p> <code>patterns</code> <code>Dict[str, Pattern]</code> <p>Named patterns keyed by their registry name.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry-functions","title":"Functions","text":""},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.array","title":"array","text":"<pre><code>array(name: str) -&gt; List\n</code></pre> <p>Return the array payload of a named <code>ArrayPattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Name Type Description <code>List</code> <code>List</code> <p>The pattern's array payload.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>If the stored pattern is not an <code>ArrayPattern</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.get","title":"get","text":"<pre><code>get(name: str) -&gt; Pattern\n</code></pre> <p>Return the pattern registered under <code>name</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Name Type Description <code>Pattern</code> <code>Pattern</code> <p>The stored pattern payload.</p> <p>Raises:</p> Type Description <code>KeyError</code> <p>If no pattern is registered under <code>name</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.keywords","title":"keywords","text":"<pre><code>keywords(name: str) -&gt; List[str]\n</code></pre> <p>Return the keyword items of a named <code>KeywordsPattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: The pattern's item keywords.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>If the stored pattern is not a <code>KeywordsPattern</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.mapping","title":"mapping","text":"<pre><code>mapping(name: str) -&gt; Dict[str, str]\n</code></pre> <p>Return the mapping of a named <code>MappingPattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Type Description <code>Dict[str, str]</code> <p>Dict[str, str]: The pattern's key/value mapping.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>If the stored pattern is not a <code>MappingPattern</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.regex","title":"regex","text":"<pre><code>regex(name: str) -&gt; re.Pattern\n</code></pre> <p>Return the compiled regex of a named <code>RegexPattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Type Description <code>Pattern</code> <p>re.Pattern: The pattern's compiled regex.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>If the stored pattern is not a <code>RegexPattern</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.regex_list","title":"regex_list","text":"<pre><code>regex_list(name: str) -&gt; List[re.Pattern]\n</code></pre> <p>Return compiled regexes of a named <code>RegexListPattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Type Description <code>List[Pattern]</code> <p>List[re.Pattern]: The pattern's compiled regexes.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>If the stored pattern is not a <code>RegexListPattern</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.regex_map","title":"regex_map","text":"<pre><code>regex_map(name: str) -&gt; List[Tuple[re.Pattern, str]]\n</code></pre> <p>Return compiled regex/value pairs of a <code>RegexMapPattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Type Description <code>List[Tuple[Pattern, str]]</code> <p>List[Tuple[re.Pattern, str]]: Compiled regex and value pairs.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>If the stored pattern is not a <code>RegexMapPattern</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.rules","title":"rules","text":"<pre><code>rules(name: str) -&gt; List[Dict]\n</code></pre> <p>Return the rule list of a named <code>RulesPattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Type Description <code>List[Dict]</code> <p>List[Dict]: The pattern's rule dicts.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>If the stored pattern is not a <code>RulesPattern</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternRegistry.template","title":"template","text":"<pre><code>template(name: str) -&gt; str\n</code></pre> <p>Return the template string of a named <code>TemplatePattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Registry name of the pattern.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The pattern's template string.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>If the stored pattern is not a <code>TemplatePattern</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.PatternType","title":"PatternType","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Discriminator values selecting a concrete pattern shape.</p> <p>Attributes:</p> Name Type Description <code>KEYWORDS</code> <code>PatternType</code> <p>Keyword list pattern (<code>KeywordsPattern</code>).</p> <code>MAPPING</code> <code>PatternType</code> <p>Key/value mapping pattern (<code>MappingPattern</code>).</p> <code>ARRAY</code> <code>PatternType</code> <p>Plain array pattern (<code>ArrayPattern</code>).</p> <code>RULES</code> <code>PatternType</code> <p>Rule list pattern (<code>RulesPattern</code>).</p> <code>REGEX</code> <code>PatternType</code> <p>Single regex pattern (<code>RegexPattern</code>).</p> <code>REGEX_LIST</code> <code>PatternType</code> <p>List of regexes (<code>RegexListPattern</code>).</p> <code>REGEX_MAP</code> <code>PatternType</code> <p>Regex-to-value mapping (<code>RegexMapPattern</code>).</p> <code>TEMPLATE</code> <code>PatternType</code> <p>String template pattern (<code>TemplatePattern</code>).</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexListPattern","title":"RegexListPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>List of regular expressions pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[REGEX_LIST]</code> <p>Constant marker for this shape.</p> <code>patterns</code> <code>List[str]</code> <p>Regex sources compiled by <code>compile_all</code>.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexListPattern-functions","title":"Functions","text":""},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexListPattern.compile_all","title":"compile_all","text":"<pre><code>compile_all(flags: int = re.IGNORECASE) -&gt; List[re.Pattern]\n</code></pre> <p>Compile every regex source in this pattern.</p> <p>Parameters:</p> Name Type Description Default <code>flags</code> <code>int</code> <p>Regex flags passed to <code>re.compile</code>; defaults to <code>re.IGNORECASE</code>.</p> <code>IGNORECASE</code> <p>Returns:</p> Type Description <code>List[Pattern]</code> <p>List[re.Pattern]: One compiled regex per source.</p> <p>Raises:</p> Type Description <code>error</code> <p>If any source is not valid regex.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexMapPattern","title":"RegexMapPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Regex-to-value mapping pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[REGEX_MAP]</code> <p>Constant marker for this shape.</p> <code>mapping</code> <code>Dict[str, str]</code> <p>Regex sources mapped to match values.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexMapPattern-functions","title":"Functions","text":""},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexMapPattern.compile_all","title":"compile_all","text":"<pre><code>compile_all(\n flags: int = re.IGNORECASE,\n) -&gt; List[Tuple[re.Pattern, str]]\n</code></pre> <p>Compile every regex in the mapping paired with its value.</p> <p>Parameters:</p> Name Type Description Default <code>flags</code> <code>int</code> <p>Regex flags passed to <code>re.compile</code>; defaults to <code>re.IGNORECASE</code>.</p> <code>IGNORECASE</code> <p>Returns:</p> Type Description <code>List[Tuple[Pattern, str]]</code> <p>List[Tuple[re.Pattern, str]]: Compiled regex and value pairs.</p> <p>Raises:</p> Type Description <code>error</code> <p>If any source is not valid regex.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexPattern","title":"RegexPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Single regular expression pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[REGEX]</code> <p>Constant marker for this shape.</p> <code>pattern</code> <code>str</code> <p>Regex source used to compile a matcher.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexPattern-functions","title":"Functions","text":""},{"location":"domain/enrichment/models/#domain.enrichment.models.RegexPattern.compile","title":"compile","text":"<pre><code>compile(flags: int = re.IGNORECASE) -&gt; re.Pattern\n</code></pre> <p>Compile this pattern's regex source.</p> <p>Parameters:</p> Name Type Description Default <code>flags</code> <code>int</code> <p>Regex flags passed to <code>re.compile</code>; defaults to <code>re.IGNORECASE</code>.</p> <code>IGNORECASE</code> <p>Returns:</p> Type Description <code>Pattern</code> <p>re.Pattern: The compiled regex.</p> <p>Raises:</p> Type Description <code>error</code> <p>If <code>pattern</code> is not valid regex.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.RulesPattern","title":"RulesPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>List of rule dictionaries pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[RULES]</code> <p>Constant marker for this shape.</p> <code>rules</code> <code>List[Dict]</code> <p>Rule dicts consumed by flag/tag rule evaluators.</p>"},{"location":"domain/enrichment/models/#domain.enrichment.models.TemplatePattern","title":"TemplatePattern","text":"<p> Bases: <code>BasePattern</code></p> <p>String template pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[TEMPLATE]</code> <p>Constant marker for this shape.</p> <code>format</code> <code>str</code> <p>Template string returned by the registry accessor.</p>"},{"location":"domain/enrichment/nodes/","title":"Nodes","text":""},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes","title":"domain.enrichment.nodes","text":""},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes--summary","title":"Summary","text":"<p>Shared <code>dagpipe</code> nodes for the enrichment pipelines: a registry-aware node base class plus the amount-based flag evaluator.</p> <p>Nodes resolve pipeline state by forking into enriched states; concrete node sets live in the <code>entity</code> and <code>tags</code> subpackages.</p>"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes--notes","title":"Notes","text":"<p>Guarantees:</p> <ul> <li>Nodes never perform I/O; all decision inputs come from the injected pattern registry and node config.</li> </ul> <p>Lifecycle:</p> <ul> <li><code>set_registry</code> and <code>set_config</code> are invoked by the pipeline loaders when a pipeline is built and cached.</li> </ul>"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes-classes","title":"Classes","text":""},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.AmountBasedFlagNode","title":"AmountBasedFlagNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Attach amount-comparison flags derived from <code>raw.amount</code>.</p> <p>Evaluates the configured amount-based flag mapping (an array of flag tokens such as <code>amount_greater_than_500</code>) against the absolute amount in the state and appends each matching flag to <code>candidate.flags</code>.</p> Notes <p>Flags already present on the candidate are left untouched. When new flags are added the node forks the state with the updated flag list; otherwise it yields the state unchanged. Encoded values use underscores for the decimal point (e.g. <code>amount_equal_to_5_00</code>).</p>"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.AmountBasedFlagNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.AmountBasedFlagNode.amount_based_flag_mapping","title":"amount_based_flag_mapping <code>property</code>","text":"<pre><code>amount_based_flag_mapping\n</code></pre> <p>Return the configured amount-based flag tokens.</p> <p>Returns:</p> Type Description <p>The array of flag tokens from the mapped registry pattern.</p>"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.AmountBasedFlagNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.AmountBasedFlagNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.AmountBasedFlagNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Evaluate amount-based flags and yield updated states.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state carrying <code>raw.amount</code> and <code>candidate.flags</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>The updated state with new amount flags, or the input</p> <code>Iterable[State]</code> <p>state unchanged when nothing matched.</p>"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.AmountBasedFlagNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.AmountBasedFlagNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.RegistryNode","title":"RegistryNode","text":"<p> Bases: <code>Node</code>, <code>ABC</code></p> <p>Base node for enrichment pipelines.</p> <p>Subclasses receive a <code>PatternRegistry</code> and a node-specific config dict from the pipeline loader, and read their decision inputs through registry accessors.</p> Notes <p><code>set_registry</code> and <code>set_config</code> install instance-level values; the class defaults them to <code>None</code> until a loader wires a node.</p>"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.RegistryNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.RegistryNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.RegistryNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.RegistryNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/nodes/#domain.enrichment.nodes.RegistryNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/entity/","title":"Entity","text":"<ul> <li>Identity</li> <li>Pipeline</li> <li>Resolver</li> <li>Utils</li> </ul>"},{"location":"domain/enrichment/entity/#domain.enrichment.entity","title":"domain.enrichment.entity","text":""},{"location":"domain/enrichment/entity/#domain.enrichment.entity--summary","title":"Summary","text":"<p>Entity enrichment: pipeline loading and entity resolution nodes.</p> <p>The loader compiles the packaged <code>pipeline.yaml</code> and <code>patterns/*.yaml</code> resources into a cached <code>dagpipe</code> pipeline; the resolution nodes turn raw descriptions into a payee entity (id, name, type, logo) through aliases, normalized signals, candidates, and flag-driven rules.</p>"},{"location":"domain/enrichment/entity/identity/","title":"Identity","text":""},{"location":"domain/enrichment/entity/identity/#domain.enrichment.entity.identity","title":"domain.enrichment.entity.identity","text":""},{"location":"domain/enrichment/entity/identity/#domain.enrichment.entity.identity--summary","title":"Summary","text":"<p>Identity helpers for entity enrichment: text normalization, entity id derivation, candidate canonicalization, and entity state payload construction.</p>"},{"location":"domain/enrichment/entity/identity/#domain.enrichment.entity.identity-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/identity/#domain.enrichment.entity.identity.build_entity","title":"build_entity","text":"<pre><code>build_entity(\n name: str,\n entity_type: str = \"merchant\",\n entity_logo: str | None = None,\n) -&gt; dict\n</code></pre> <p>Build the entity payload spread into pipeline state.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Entity display name.</p> required <code>entity_type</code> <code>str</code> <p>Entity type, defaults to <code>\"merchant\"</code>.</p> <code>'merchant'</code> <code>entity_logo</code> <code>str | None</code> <p>Logo URL/path, or <code>None</code>.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>A payload mapping the <code>entity.*</code> keys accepted by</p> <code>dict</code> <p><code>dagpipe</code> state forks.</p>"},{"location":"domain/enrichment/entity/identity/#domain.enrichment.entity.identity.canonicalize_candidate","title":"canonicalize_candidate","text":"<pre><code>canonicalize_candidate(candidate: str | None) -&gt; str | None\n</code></pre> <p>Canonicalize a candidate value for comparisons.</p> <p>Parameters:</p> Name Type Description Default <code>candidate</code> <code>str | None</code> <p>Raw candidate string.</p> required <p>Returns:</p> Type Description <code>str | None</code> <p>str | None: The normalized candidate key, or <code>None</code> for falsy</p> <code>str | None</code> <p>input.</p>"},{"location":"domain/enrichment/entity/identity/#domain.enrichment.entity.identity.normalize_key","title":"normalize_key","text":"<pre><code>normalize_key(text: str | None) -&gt; str | None\n</code></pre> <p>Normalize arbitrary text to a comparison key.</p> <p>Applies NFKC unicode normalization, lower-cases, and strips surrounding whitespace.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str | None</code> <p>Text to normalize; <code>None</code> passes through.</p> required <p>Returns:</p> Type Description <code>str | None</code> <p>str | None: The normalized key, or <code>None</code> for <code>None</code> input.</p>"},{"location":"domain/enrichment/entity/identity/#domain.enrichment.entity.identity.to_entity_id","title":"to_entity_id","text":"<pre><code>to_entity_id(name: str | None) -&gt; str | None\n</code></pre> <p>Derive a stable slug id from a name.</p> <p>Empty/falsy names yield <code>None</code>. Non-alphanumeric runs are replaced with a single underscore and edge underscores are trimmed.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str | None</code> <p>Entity name to slugify.</p> required <p>Returns:</p> Type Description <code>str | None</code> <p>str | None: The slug id, or <code>None</code> when <code>name</code> is falsy.</p>"},{"location":"domain/enrichment/entity/pipeline/","title":"Pipeline","text":""},{"location":"domain/enrichment/entity/pipeline/#domain.enrichment.entity.pipeline","title":"domain.enrichment.entity.pipeline","text":""},{"location":"domain/enrichment/entity/pipeline/#domain.enrichment.entity.pipeline--summary","title":"Summary","text":"<p>Loader for the entity enrichment pipeline.</p> <p>Compiles the packaged <code>pipeline.yaml</code> plus the <code>patterns/*.yaml</code> registries into a cached <code>dagpipe</code> pipeline, wiring every registry-aware node with its registry and node config.</p>"},{"location":"domain/enrichment/entity/pipeline/#domain.enrichment.entity.pipeline-classes","title":"Classes","text":""},{"location":"domain/enrichment/entity/pipeline/#domain.enrichment.entity.pipeline-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/pipeline/#domain.enrichment.entity.pipeline.get_entity_pipeline","title":"get_entity_pipeline","text":"<pre><code>get_entity_pipeline()\n</code></pre> <p>Return the lazily cached entity pipeline.</p> <p>Builds (once) and reuses the pipeline across calls.</p> <p>Returns:</p> Type Description <p>The cached entity pipeline instance.</p>"},{"location":"domain/enrichment/entity/pipeline/#domain.enrichment.entity.pipeline.load","title":"load","text":"<pre><code>load() -&gt; Pipeline\n</code></pre> <p>Load and wire the entity enrichment pipeline.</p> <p>Reads the packaged <code>pipeline.yaml</code>, builds the pipeline graph, and installs the merged pattern registry and per-node config onto each node that supports it.</p> <p>Returns:</p> Name Type Description <code>Pipeline</code> <code>Pipeline</code> <p>The wired <code>dagpipe</code> pipeline.</p> <p>Raises:</p> Type Description <code>FileNotFoundError</code> <p>If the packaged <code>pipeline.yaml</code> is missing.</p>"},{"location":"domain/enrichment/entity/resolver/","title":"Resolver","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver","title":"domain.enrichment.entity.resolver","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver--summary","title":"Summary","text":"<p>Entity resolution nodes for the enrichment pipeline.</p> <p>Each node advances the entity candidate: alias-based entity assignment, description normalization, candidate extraction, flag-based candidate handling, flag-driven entity setting, and a final fallback.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver-classes","title":"Classes","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.CandidateBasedFlagsNode","title":"CandidateBasedFlagsNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Attach candidate-keyword flags derived from the candidate value.</p> <p>For each flag in the configured mapping, when any keyword appears in the (lower-cased) candidate value and the flag is not already present, the flag is appended to <code>candidate.flags</code>.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.CandidateBasedFlagsNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.CandidateBasedFlagsNode.candidate_based_flag_mapping","title":"candidate_based_flag_mapping <code>property</code>","text":"<pre><code>candidate_based_flag_mapping\n</code></pre> <p>Return the candidate-keyword flag mapping.</p> <p>Returns:</p> Type Description <p>The mapping dict from the registry.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.CandidateBasedFlagsNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.CandidateBasedFlagsNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.CandidateBasedFlagsNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Append matched candidate-keyword flags to the state.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state with a candidate value and flags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>The updated state, or the input state when no flag</p> <code>Iterable[State]</code> <p>changed.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.CandidateBasedFlagsNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.CandidateBasedFlagsNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode","title":"EntityAliasNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Resolve an entity directly from alias regexes.</p> <p>When <code>entity.name</code> is already set, or no candidate value exists, the state passes through unchanged. Otherwise the first alias regex that matches the candidate produces the entity payload with a confidence delta of <code>-0.25</code> and the <code>resolved_by=entity_alias</code> metadata marker.</p> Notes <p>A fork is yielded immediately on the first matching alias; no further aliases are considered.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode.default_logo_mapping","title":"default_logo_mapping <code>property</code>","text":"<pre><code>default_logo_mapping\n</code></pre> <p>Return the default logo mapping by entity type.</p> <p>Returns:</p> Type Description <p>The mapping dict from the registry, defaulting to</p> <p><code>ENTITY_DEFAULT_LOGO_MAPPING</code>.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode.entity_alias_regex","title":"entity_alias_regex <code>property</code>","text":"<pre><code>entity_alias_regex\n</code></pre> <p>Return the compiled alias regex/value pairs.</p> <p>Returns:</p> Type Description <p>The compiled regex-map entries from the registry.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode.entity_type_mapping","title":"entity_type_mapping <code>property</code>","text":"<pre><code>entity_type_mapping\n</code></pre> <p>Return the entity-type mapping for assigned entities.</p> <p>Returns:</p> Type Description <p>The mapping dict from the registry, defaulting to</p> <p><code>ENTITY_TYPE_MAPPING</code>.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Assign the entity from the first alias matching the candidate.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state with <code>candidate.value</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>The forked state with the entity payload, or the input</p> <code>Iterable[State]</code> <p>state when nothing matched.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.EntityAliasNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode","title":"ExtractCandidatesNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Extract entity candidates from the normalized signals.</p> <p>Produces a candidate per regex match and per <code>/</code>-split part; when nothing matched, falls back to canonicalized space-split items and finally to an empty (<code>-0.75</code>) fork. Negative candidates are skipped throughout.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode.candidate_regex","title":"candidate_regex <code>property</code>","text":"<pre><code>candidate_regex\n</code></pre> <p>Return the compiled candidate extraction regexes.</p> <p>Returns:</p> Type Description <p>The compiled regex list from the registry.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode.negative_candidates","title":"negative_candidates <code>property</code>","text":"<pre><code>negative_candidates\n</code></pre> <p>Return the negative candidate tokens to skip.</p> <p>Returns:</p> Type Description <p>The array of negative candidate strings from the registry.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield one state fork per extracted candidate.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state with populated <code>signals</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A forked state per candidate, each carrying</p> <code>Iterable[State]</code> <p><code>candidate.value</code>; or a single <code>-0.75</code> fork when no</p> <code>Iterable[State]</code> <p>candidate was found.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.ExtractCandidatesNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.FallbackNode","title":"FallbackNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Assign a last-resort entity when nothing resolved.</p> <p>Valid candidates become the merchant (<code>-0.25</code>); otherwise the entity falls back to <code>Unknown</code> with type <code>other</code> (<code>-0.50</code>), using the default logo paths.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.FallbackNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.FallbackNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.FallbackNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.FallbackNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Fork the state with a fallback entity.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state with an optional candidate value.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>The forked state with the fallback entity payload.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.FallbackNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.FallbackNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.NormalizeDescriptionNode","title":"NormalizeDescriptionNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Normalize the raw description into signal fields.</p> <p>Removes the amount/balance number sequences from the description and populates <code>signals.raw</code>, <code>signals.items</code> (space-split) and <code>signals.parts</code> (slash-split) for downstream nodes.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.NormalizeDescriptionNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.NormalizeDescriptionNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.NormalizeDescriptionNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.NormalizeDescriptionNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Fork the state with the normalized description signals.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state with <code>raw.description</code>, <code>raw.amount</code> and <code>raw.balance</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>The forked state carrying the derived signals.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.NormalizeDescriptionNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.NormalizeDescriptionNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode","title":"SetEntityNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Set the entity from flag-based entity rules.</p> <p>Each rule config may carry <code>all</code>/<code>any</code> conditions over the candidate flags; the first satisfied rule emits its <code>payee</code> as the entity with a <code>resolved_by=set_entity</code> marker. When no rule fires and no entity exists yet, a <code>-0.25</code> fork is yielded.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode.default_logo_mapping","title":"default_logo_mapping <code>property</code>","text":"<pre><code>default_logo_mapping\n</code></pre> <p>Return the default logo mapping by entity type.</p> <p>Returns:</p> Type Description <p>The mapping dict from the registry, defaulting to</p> <p><code>ENTITY_DEFAULT_LOGO_MAPPING</code>.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode.entity_type_mapping","title":"entity_type_mapping <code>property</code>","text":"<pre><code>entity_type_mapping\n</code></pre> <p>Return the entity-type mapping for assigned entities.</p> <p>Returns:</p> Type Description <p>The mapping dict from the registry, defaulting to</p> <p><code>ENTITY_TYPE_MAPPING</code>.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode.flags_based_entity_rules","title":"flags_based_entity_rules <code>property</code>","text":"<pre><code>flags_based_entity_rules\n</code></pre> <p>Return the flag-based entity rules.</p> <p>Returns:</p> Type Description <p>The rule list from the registry.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Apply flag-based entity rules and fork the entity state.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state with candidate flags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>The forked state with the entity payload when a rule</p> <code>Iterable[State]</code> <p>fires; the input state when an entity already exists; or a</p> <code>Iterable[State]</code> <p><code>-0.25</code> fork otherwise.</p>"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver.SetEntityNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/entity/resolver/#domain.enrichment.entity.resolver-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/utils/","title":"Utils","text":""},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils","title":"domain.enrichment.entity.utils","text":""},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils--summary","title":"Summary","text":"<p>Text utilities for entity enrichment: description normalization, number sequence removal, candidate validity checks, and candidate extraction.</p>"},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils-functions","title":"Functions","text":""},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils.extract_candidates","title":"extract_candidates","text":"<pre><code>extract_candidates(\n description: str,\n candidate_regexes: Iterable[re.Pattern],\n) -&gt; List[str]\n</code></pre> <p>Extract validated payee candidates from a description.</p> <p>For each regex, reads the <code>payee</code> named group, checks validity, and appends the normalized key.</p> <p>Parameters:</p> Name Type Description Default <code>description</code> <code>str</code> <p>Description text to scan.</p> required <code>candidate_regexes</code> <code>Iterable[Pattern]</code> <p>Compiled regexes exposing a <code>payee</code> named group.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Validated, normalized candidate keys.</p>"},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils.is_valid_candidate","title":"is_valid_candidate","text":"<pre><code>is_valid_candidate(candidate: str) -&gt; bool\n</code></pre> <p>Check whether a string is a plausible entity candidate.</p> <p>Rejects empty/short strings, pure-hex strings, and pure digits (unless exactly 10 digits); requires at least one letter.</p> <p>Parameters:</p> Name Type Description Default <code>candidate</code> <code>str</code> <p>Candidate string to validate.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when the candidate is usable.</p>"},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils.lookup_mapping","title":"lookup_mapping","text":"<pre><code>lookup_mapping(candidate: str, mapping: dict)\n</code></pre> <p>Look up candidate display names in a mapping.</p> <p>A normalized exact key match returns the single mapped name; otherwise returns every mapped name whose key is a substring of the candidate. Falsy candidates return <code>(None, None)</code>.</p> <p>Parameters:</p> Name Type Description Default <code>candidate</code> <code>str</code> <p>Candidate to look up.</p> required <code>mapping</code> <code>dict</code> <p>Mapping of normalized keys to <code>MappingValue</code> entries.</p> required <p>Returns:</p> Type Description <p>A single matching name, a list of substring matches, or</p> <p><code>(None, None)</code> for falsy candidates.</p>"},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils.normalize_description","title":"normalize_description","text":"<pre><code>normalize_description(text: str) -&gt; str\n</code></pre> <p>Normalize a description for downstream matching.</p> <p>Strips whitespace, drops <code>page N of M</code> markers, OCR hex blobs, separators, <code>@</code> and <code>.</code>, collapses runs of spaces, and lower-cases the result.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Raw description text.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The normalized, lower-cased description.</p>"},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils.normalize_money_str","title":"normalize_money_str","text":"<pre><code>normalize_money_str(x) -&gt; str\n</code></pre> <p>Format a number as a two-decimal string.</p> <p>Parameters:</p> Name Type Description Default <code>x</code> <p>Value coercible to <code>float</code>.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The number formatted to two decimals.</p>"},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils.normalize_person_handle","title":"normalize_person_handle","text":"<pre><code>normalize_person_handle(handle: str) -&gt; str\n</code></pre> <p>Normalize a UPI-style handle into a display name.</p> <p>Strips the <code>@</code> suffix and trailing digits, capitalizes word pieces (preserving known acronyms), and removes bracket characters; returns <code>\"\"</code> when the result is purely hex-like.</p> <p>Parameters:</p> Name Type Description Default <code>handle</code> <code>str</code> <p>Raw handle string.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The normalized person name (possibly empty).</p>"},{"location":"domain/enrichment/entity/utils/#domain.enrichment.entity.utils.remove_number_sequence","title":"remove_number_sequence","text":"<pre><code>remove_number_sequence(\n text: str, amt: str, bal: str\n) -&gt; str\n</code></pre> <p>Strip digit runs that echo the amount/balance.</p> <p>Builds a regex from the concatenated amount+balance digits and removes candidate runs within one edit of that digit string, collapsing the remaining whitespace.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Description text to clean.</p> required <code>amt</code> <code>str</code> <p>Transaction amount, formatted via <code>normalize_money_str</code>.</p> required <code>bal</code> <code>str</code> <p>Balance, formatted via <code>normalize_money_str</code>.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The cleaned description with echoed numbers removed.</p>"},{"location":"domain/enrichment/tags/","title":"Tags","text":"<ul> <li>Flags</li> <li>Pipeline</li> </ul>"},{"location":"domain/enrichment/tags/#domain.enrichment.tags","title":"domain.enrichment.tags","text":""},{"location":"domain/enrichment/tags/#domain.enrichment.tags--summary","title":"Summary","text":"<p>Tag enrichment: pipeline loading and flag/tag nodes.</p> <p>The loader compiles the packaged tag pipeline and pattern resources; the nodes attach entity-based flags and apply flag-based tag rules to a resolved entity.</p>"},{"location":"domain/enrichment/tags/flags/","title":"Flags","text":""},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags","title":"domain.enrichment.tags.flags","text":""},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags--summary","title":"Summary","text":"<p>Flag and tag nodes for the tag enrichment pipeline.</p> <p>Rules nodes derive entity-based flags from the resolved entity and apply flag-based rules to attach tags.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags-classes","title":"Classes","text":""},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.EntityBasedFlagsNode","title":"EntityBasedFlagsNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Attach entity-matched flags and reset the tag list.</p> <p>Keeps only the <code>amount_*</code> candidate flags and, for each entity-based flag whose keyword equals the lower-cased entity name, appends the flag. Always forks with the final flag list and an empty <code>tags</code> list.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.EntityBasedFlagsNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.EntityBasedFlagsNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.EntityBasedFlagsNode.entity_based_flag_mapping","title":"entity_based_flag_mapping <code>property</code>","text":"<pre><code>entity_based_flag_mapping\n</code></pre> <p>Return the entity-based flag mapping.</p> <p>Returns:</p> Type Description <p>The mapping dict from the registry.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.EntityBasedFlagsNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.EntityBasedFlagsNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Apply entity-matched flags to the state.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state with an entity name and candidate flags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>The forked state with updated flags and empty tags.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.EntityBasedFlagsNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.EntityBasedFlagsNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.SetTagsNode","title":"SetTagsNode","text":"<p> Bases: <code>RegistryNode</code></p> <p>Assign tags from flag-based tag rules.</p> <p>For each rule with <code>all</code>/<code>any</code> conditions satisfied by the candidate flags, appends the rule's emitted tags to the current tag list (avoiding duplicates) and forks when anything changed.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.SetTagsNode-attributes","title":"Attributes","text":""},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.SetTagsNode.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Return the node config installed by the pipeline loader.</p> <p>Returns:</p> Type Description <p>The node configuration dict, or <code>None</code> before wiring.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.SetTagsNode.flags_based_tags_rules","title":"flags_based_tags_rules <code>property</code>","text":"<pre><code>flags_based_tags_rules\n</code></pre> <p>Return the flag-based tag rules.</p> <p>Returns:</p> Type Description <p>The rule list from the registry.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.SetTagsNode-functions","title":"Functions","text":""},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.SetTagsNode.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Apply flag-based tag rules to the state.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Pipeline state with candidate flags and current tags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>The updated state, or the input state when no tag</p> <code>Iterable[State]</code> <p>changed.</p>"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.SetTagsNode.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Install the node-specific config on this node.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <p>The config dict read from the pipeline YAML for this node's id.</p> required"},{"location":"domain/enrichment/tags/flags/#domain.enrichment.tags.flags.SetTagsNode.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Install the pattern registry on this node.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <p>The <code>PatternRegistry</code> instance to use for lookups.</p> required"},{"location":"domain/enrichment/tags/pipeline/","title":"Pipeline","text":""},{"location":"domain/enrichment/tags/pipeline/#domain.enrichment.tags.pipeline","title":"domain.enrichment.tags.pipeline","text":""},{"location":"domain/enrichment/tags/pipeline/#domain.enrichment.tags.pipeline--summary","title":"Summary","text":"<p>Loader for the tag enrichment pipeline.</p> <p>Compiles the packaged tag <code>pipeline.yaml</code> plus <code>patterns/*.yaml</code> registries into a cached <code>dagpipe</code> pipeline, wiring every registry-aware node with its registry and node config.</p>"},{"location":"domain/enrichment/tags/pipeline/#domain.enrichment.tags.pipeline-classes","title":"Classes","text":""},{"location":"domain/enrichment/tags/pipeline/#domain.enrichment.tags.pipeline-functions","title":"Functions","text":""},{"location":"domain/enrichment/tags/pipeline/#domain.enrichment.tags.pipeline.get_tag_pipeline","title":"get_tag_pipeline","text":"<pre><code>get_tag_pipeline()\n</code></pre> <p>Return the lazily cached tag pipeline.</p> <p>Builds (once) and reuses the pipeline across calls.</p> <p>Returns:</p> Type Description <p>The cached tag pipeline instance.</p>"},{"location":"domain/enrichment/tags/pipeline/#domain.enrichment.tags.pipeline.load","title":"load","text":"<pre><code>load() -&gt; Pipeline\n</code></pre> <p>Load and wire the tag enrichment pipeline.</p> <p>Reads the packaged <code>pipeline.yaml</code>, builds the pipeline graph, and installs the merged pattern registry and per-node config onto each node that supports it.</p> <p>Returns:</p> Name Type Description <code>Pipeline</code> <code>Pipeline</code> <p>The wired <code>dagpipe</code> pipeline.</p> <p>Raises:</p> Type Description <code>FileNotFoundError</code> <p>If the packaged <code>pipeline.yaml</code> is missing.</p>"},{"location":"domain/entity/","title":"Entity","text":"<ul> <li>Models</li> <li>Ports</li> </ul>"},{"location":"domain/entity/#domain.entity","title":"domain.entity","text":""},{"location":"domain/entity/#domain.entity--summary","title":"Summary","text":"<p>Entity domain: the Entity aggregate, its Mongo document schema, enrichment adaptor, and CRUD service wiring.</p>"},{"location":"domain/entity/models/","title":"Models","text":""},{"location":"domain/entity/models/#domain.entity.models","title":"domain.entity.models","text":""},{"location":"domain/entity/models/#domain.entity.models--summary","title":"Summary","text":"<p>Define the Entity aggregate model with default-logo resolution.</p>"},{"location":"domain/entity/models/#domain.entity.models-classes","title":"Classes","text":""},{"location":"domain/entity/models/#domain.entity.models.Entity","title":"Entity","text":"<p> Bases: <code>BaseModel</code></p> <p>Entity (payee) model: a merchant, person, transfer, or other kind.</p> <p>Attributes:</p> Name Type Description <code>name</code> <code>str</code> <p>Display name of the entity.</p> <code>type</code> <code>str</code> <p>Entity kind used to pick the default logo, e.g. <code>\"merchant\"</code>.</p> <code>logo</code> <code>str | None</code> <p>Logo URL/path; filled with a per-type default when unset.</p> Notes <p>Guarantees: After validation, <code>logo</code> is always a non-empty value; a missing logo is replaced using :data:<code>DEFAULT_LOGO_MAP</code> keyed by <code>type</code>.</p>"},{"location":"domain/entity/ports/","title":"Ports","text":"<ul> <li>Db</li> <li>Enrichment</li> <li>Service</li> </ul>"},{"location":"domain/entity/ports/#domain.entity.ports","title":"domain.entity.ports","text":""},{"location":"domain/entity/ports/#domain.entity.ports--summary","title":"Summary","text":"<p>Port wiring for the entity aggregate: Mongo repository, enrichment adaptor, and CRUD service wiring.</p>"},{"location":"domain/entity/ports/db/","title":"Db","text":""},{"location":"domain/entity/ports/db/#domain.entity.ports.db","title":"domain.entity.ports.db","text":""},{"location":"domain/entity/ports/db/#domain.entity.ports.db--summary","title":"Summary","text":"<p>Mongo persistence for entities: document schema with an in-memory cache.</p>"},{"location":"domain/entity/ports/db/#domain.entity.ports.db-classes","title":"Classes","text":""},{"location":"domain/entity/ports/db/#domain.entity.ports.db.EntityDocument","title":"EntityDocument","text":"<p> Bases: <code>Entity</code>, <code>BaseDocument</code></p> <p>Mongo document form of :class:<code>Entity</code> read through an in-memory cache.</p>"},{"location":"domain/entity/ports/db/#domain.entity.ports.db-functions","title":"Functions","text":""},{"location":"domain/entity/ports/db/#domain.entity.ports.db.create_entity_repo","title":"create_entity_repo","text":"<pre><code>create_entity_repo()\n</code></pre> <p>Create a Mongo-backed entity repository with an in-memory cache.</p> <p>Returns:</p> Name Type Description <code>Any</code> <p>Mongo-backed entity repository using an in-memory cache backend.</p>"},{"location":"domain/entity/ports/enrichment/","title":"Enrichment","text":""},{"location":"domain/entity/ports/enrichment/#domain.entity.ports.enrichment","title":"domain.entity.ports.enrichment","text":""},{"location":"domain/entity/ports/enrichment/#domain.entity.ports.enrichment--summary","title":"Summary","text":"<p>Entity enrichment port: expose the shared entity enrichment pipeline as an async callable.</p>"},{"location":"domain/entity/ports/enrichment/#domain.entity.ports.enrichment-classes","title":"Classes","text":""},{"location":"domain/entity/ports/enrichment/#domain.entity.ports.enrichment.EntityEnrichmentAdaptor","title":"EntityEnrichmentAdaptor","text":"<pre><code>EntityEnrichmentAdaptor(**kwargs)\n</code></pre> <p>Adaptor exposing the entity enrichment pipeline as an async callable.</p> <p>Initialize the adaptor with the shared entity pipeline.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <code>dict</code> <p>Ignored; kept for dependency-injection compatibility.</p> <code>{}</code>"},{"location":"domain/entity/ports/enrichment/#domain.entity.ports.enrichment.EntityEnrichmentAdaptor-functions","title":"Functions","text":""},{"location":"domain/entity/ports/enrichment/#domain.entity.ports.enrichment.EntityEnrichmentAdaptor.__call__","title":"__call__ <code>async</code>","text":"<pre><code>__call__(payload: dict) -&gt; dict\n</code></pre> <p>Run the entity enrichment pipeline on <code>payload</code>.</p> <p>Parameters:</p> Name Type Description Default <code>payload</code> <code>dict</code> <p>Enrichment input, e.g. payee text and hints.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Enriched payload carrying the resolved entity information.</p>"},{"location":"domain/entity/ports/enrichment/#domain.entity.ports.enrichment-functions","title":"Functions","text":""},{"location":"domain/entity/ports/enrichment/#domain.entity.ports.enrichment.get_entity_enrichment_svc","title":"get_entity_enrichment_svc","text":"<pre><code>get_entity_enrichment_svc(\n **kwargs,\n) -&gt; EntityEnrichmentAdaptor\n</code></pre> <p>Build an entity enrichment service adaptor.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <code>dict</code> <p>Passed through to the adaptor constructor.</p> <code>{}</code> <p>Returns:</p> Name Type Description <code>EntityEnrichmentAdaptor</code> <code>EntityEnrichmentAdaptor</code> <p>Ready-to-use entity enrichment adaptor.</p>"},{"location":"domain/entity/ports/service/","title":"Service","text":""},{"location":"domain/entity/ports/service/#domain.entity.ports.service","title":"domain.entity.ports.service","text":""},{"location":"domain/entity/ports/service/#domain.entity.ports.service--summary","title":"Summary","text":"<p>CRUD service wiring for the entity aggregate via the hexa container.</p>"},{"location":"domain/entity/ports/service/#domain.entity.ports.service-classes","title":"Classes","text":""},{"location":"domain/entity/ports/service/#domain.entity.ports.service.EntityCrudsService","title":"EntityCrudsService","text":"<p> Bases: <code>CrudsServiceAdaptor[Entity, EntityDocument]</code></p> <p>Entity CRUD service resolving :class:<code>Entity</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_entity_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p>"},{"location":"domain/entity/ports/service/#domain.entity.ports.service-functions","title":"Functions","text":""},{"location":"domain/entity/ports/service/#domain.entity.ports.service.get_entity_service","title":"get_entity_service","text":"<pre><code>get_entity_service(repo) -&gt; EntityCrudsService\n</code></pre> <p>Build an entity CRUD service wired to <code>repo</code>.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>Any</code> <p>Mongo-backed entity repository from :func:<code>create_entity_repo</code>.</p> required <p>Returns:</p> Name Type Description <code>EntityCrudsService</code> <code>EntityCrudsService</code> <p>Ready-to-use entity CRUD service.</p>"},{"location":"domain/expense/","title":"Expense","text":"<ul> <li>Models</li> <li>Ports</li> </ul>"},{"location":"domain/expense/#domain.expense","title":"domain.expense","text":""},{"location":"domain/expense/#domain.expense--summary","title":"Summary","text":"<p>Expense domain: the Expense aggregate, converters, Mongo document schema, and CRUD service wiring.</p>"},{"location":"domain/expense/models/","title":"Models","text":""},{"location":"domain/expense/models/#domain.expense.models","title":"domain.expense.models","text":""},{"location":"domain/expense/models/#domain.expense.models--summary","title":"Summary","text":"<p>Define the Expense aggregate model (entity, account, tags, and amount) shared across layers.</p>"},{"location":"domain/expense/models/#domain.expense.models-classes","title":"Classes","text":""},{"location":"domain/expense/models/#domain.expense.models.Expense","title":"Expense","text":"<p> Bases: <code>BaseModel</code></p> <p>Expense transaction linking an entity, account, and tags.</p> <p>Attributes:</p> Name Type Description <code>entity</code> <code>Entity</code> <p>Payee entity the expense was incurred with.</p> <code>amount</code> <code>float</code> <p>Transaction amount.</p> <code>account</code> <code>Account</code> <p>Account the expense was paid from.</p> <code>tags</code> <code>List[Tag]</code> <p>Tags classified against the expense.</p> <code>occurred_at</code> <code>str</code> <p>Date the expense occurred, as DD-MM-YYYY.</p> <code>fetch_request</code> <code>Optional[str]</code> <p>ID of the fetch request that produced the expense; <code>None</code> when not sourced from a request.</p>"},{"location":"domain/expense/ports/","title":"Ports","text":"<ul> <li>Converters</li> <li>Db</li> <li>Service</li> </ul>"},{"location":"domain/expense/ports/#domain.expense.ports","title":"domain.expense.ports","text":""},{"location":"domain/expense/ports/#domain.expense.ports--summary","title":"Summary","text":"<p>Port wiring for expenses: converters, Mongo repository, and CRUD service wiring.</p>"},{"location":"domain/expense/ports/converters/","title":"Converters","text":""},{"location":"domain/expense/ports/converters/#domain.expense.ports.converters","title":"domain.expense.ports.converters","text":""},{"location":"domain/expense/ports/converters/#domain.expense.ports.converters--summary","title":"Summary","text":"<p>Converters bridging enriched fetch-request output and Expense aggregates for MongoDB storage.</p>"},{"location":"domain/expense/ports/converters/#domain.expense.ports.converters-classes","title":"Classes","text":""},{"location":"domain/expense/ports/converters/#domain.expense.ports.converters-functions","title":"Functions","text":""},{"location":"domain/expense/ports/converters/#domain.expense.ports.converters.enriched_to_expenses","title":"enriched_to_expenses <code>async</code>","text":"<pre><code>enriched_to_expenses(\n enriched_list: List[EnrichedExpense],\n fetch_request: FetchRequest,\n entity_svc,\n tag_svc,\n fetch_request_id: Optional[str] = None,\n) -&gt; List[Expense]\n</code></pre> <p>Convert enriched expenses into Expense aggregates ready for storage.</p> <p>Each enriched expense is expanded into an Expense referencing the account of <code>fetch_request</code> and resolved entity and tag objects.</p> <p>Parameters:</p> Name Type Description Default <code>enriched_list</code> <code>List[EnrichedExpense]</code> <p>Enriched expenses to convert.</p> required <code>fetch_request</code> <code>FetchRequest</code> <p>Fetch request providing the source account.</p> required <code>entity_svc</code> <code>Any</code> <p>Entity CRUD service used to resolve or create payees.</p> required <code>tag_svc</code> <code>Any</code> <p>Tag CRUD service used to resolve tags by name.</p> required <code>fetch_request_id</code> <code>Optional[str]</code> <p>Fetch request ID recorded on expenses; falls back to <code>fetch_request.id</code> when omitted.</p> <code>None</code> <p>Returns:</p> Type Description <code>List[Expense]</code> <p>List[Expense]: Converted expense aggregates.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When an enriched tag name does not exist.</p>"},{"location":"domain/expense/ports/converters/#domain.expense.ports.converters.expense_to_storage","title":"expense_to_storage","text":"<pre><code>expense_to_storage(expense: Expense) -&gt; None\n</code></pre> <p>Convert Expense FK fields to ObjectIds in-place for MongoDB storage.</p> <p>Raises ValueError if any FK field lacks an ObjectId \u2014 prevents storing embedded subdocuments instead of references.</p> <p>Parameters:</p> Name Type Description Default <code>expense</code> <code>Expense</code> <p>Expense to normalize for storage.</p> required <p>Raises:</p> Type Description <code>ValueError</code> <p>When <code>entity</code>, <code>account</code>, or any tag lacks an ObjectId.</p>"},{"location":"domain/expense/ports/db/","title":"Db","text":""},{"location":"domain/expense/ports/db/#domain.expense.ports.db","title":"domain.expense.ports.db","text":""},{"location":"domain/expense/ports/db/#domain.expense.ports.db--summary","title":"Summary","text":"<p>Mongo persistence for expenses: document schema with populated references and repository factory.</p>"},{"location":"domain/expense/ports/db/#domain.expense.ports.db-classes","title":"Classes","text":""},{"location":"domain/expense/ports/db/#domain.expense.ports.db.ExpenseDocument","title":"ExpenseDocument","text":"<p> Bases: <code>Expense</code>, <code>BaseDocument</code></p> <p>Mongo document form of :class:<code>Expense</code> with populated references.</p> <p>Attributes:</p> Name Type Description <code>entity</code> <code>EntityDocument</code> <p>Populated payee entity document.</p> <code>account</code> <code>AccountDocument</code> <p>Populated account document.</p> <code>tags</code> <code>List[TagDocument]</code> <p>Populated tag documents.</p>"},{"location":"domain/expense/ports/db/#domain.expense.ports.db-functions","title":"Functions","text":""},{"location":"domain/expense/ports/db/#domain.expense.ports.db.create_expense_repo","title":"create_expense_repo","text":"<pre><code>create_expense_repo(\n entity_repo: Any, account_repo: Any, tag_repo: Any\n)\n</code></pre> <p>Create a Mongo-backed expense repository wired for reference population.</p> <p>Parameters:</p> Name Type Description Default <code>entity_repo</code> <code>Any</code> <p>Entity repository used to populate <code>entity</code>.</p> required <code>account_repo</code> <code>Any</code> <p>Account repository used to populate <code>account</code>.</p> required <code>tag_repo</code> <code>Any</code> <p>Tag repository used to populate <code>tags</code>.</p> required <p>Returns:</p> Name Type Description <code>Any</code> <p>Mongo-backed expense repository configured with entity, account, and tag population rules.</p>"},{"location":"domain/expense/ports/service/","title":"Service","text":""},{"location":"domain/expense/ports/service/#domain.expense.ports.service","title":"domain.expense.ports.service","text":""},{"location":"domain/expense/ports/service/#domain.expense.ports.service--summary","title":"Summary","text":"<p>CRUD service wiring for the expense aggregate via the hexa container.</p>"},{"location":"domain/expense/ports/service/#domain.expense.ports.service-classes","title":"Classes","text":""},{"location":"domain/expense/ports/service/#domain.expense.ports.service.ExpenseCrudsService","title":"ExpenseCrudsService","text":"<p> Bases: <code>CrudsServiceAdaptor[Expense, ExpenseDocument]</code></p> <p>Expense CRUD service resolving :class:<code>Expense</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_expense_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p>"},{"location":"domain/expense/ports/service/#domain.expense.ports.service-functions","title":"Functions","text":""},{"location":"domain/expense/ports/service/#domain.expense.ports.service.get_expense_service","title":"get_expense_service","text":"<pre><code>get_expense_service(repo) -&gt; ExpenseCrudsService\n</code></pre> <p>Build an expense CRUD service wired to <code>repo</code>.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>Any</code> <p>Mongo-backed expense repository from :func:<code>create_expense_repo</code>.</p> required <p>Returns:</p> Name Type Description <code>ExpenseCrudsService</code> <code>ExpenseCrudsService</code> <p>Ready-to-use expense CRUD service.</p>"},{"location":"domain/fetch_pipeline/","title":"Fetch Pipeline","text":"<ul> <li>Models</li> <li>Ports</li> <li>Utils</li> </ul>"},{"location":"domain/fetch_pipeline/#domain.fetch_pipeline","title":"domain.fetch_pipeline","text":""},{"location":"domain/fetch_pipeline/#domain.fetch_pipeline--summary","title":"Summary","text":"<p>Fetch pipeline domain: orchestrates expense extraction from bank statement sources.</p> <p>Covers extraction-stage driving (pdf, email, tabular, llama), ambiguity pausing, enrichment, expense persistence, and progress-event streaming, plus the models and ports the orchestrator depends on.</p>"},{"location":"domain/fetch_pipeline/models/","title":"Models","text":""},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models","title":"domain.fetch_pipeline.models","text":""},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models--summary","title":"Summary","text":"<p>Data models for fetch pipeline progress reporting and ambiguity resolution.</p>"},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models-classes","title":"Classes","text":""},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models.Ambiguity","title":"Ambiguity","text":"<p> Bases: <code>BaseModel</code></p> <p>Record of an ambiguity pause awaiting resolution.</p> <p>Attributes:</p> Name Type Description <code>fetch_request_id</code> <code>PyObjectId</code> <p>Owning fetch request.</p> <code>step_index</code> <code>int</code> <p>Pipeline stage index at which the pause occurred.</p> <code>line</code> <code>str</code> <p>Raw OCR line that triggered the ambiguity.</p> <code>ocr_amount</code> <code>float</code> <p>Amount read from the OCR line.</p> <code>ocr_balance</code> <code>float</code> <p>Balance read from the OCR line.</p> <code>prev_balance</code> <code>float</code> <p>Balance carried into the ambiguous transaction.</p> <code>candidates</code> <code>List[AmbiguityCandidate]</code> <p>Amount/balance candidates offered for resolution.</p> <code>chosen</code> <code>Optional[AmbiguityCandidate]</code> <p>Candidate selected by the resolver, if any.</p> <code>resolved_at</code> <code>Optional[str]</code> <p>ISO timestamp of resolution, if resolved.</p> <code>status</code> <code>str</code> <p>Lifecycle status, defaulting to <code>\"pending\"</code>.</p>"},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models.AmbiguityCandidate","title":"AmbiguityCandidate","text":"<p> Bases: <code>BaseModel</code></p> <p>Amount/balance pair offered as a resolution candidate.</p> <p>Attributes:</p> Name Type Description <code>amount</code> <code>float</code> <p>Candidate transaction amount.</p> <code>balance</code> <code>float</code> <p>Candidate balance after the transaction.</p>"},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models.ProgressEvent","title":"ProgressEvent","text":"<p> Bases: <code>BaseModel</code></p> <p>SSE progress event emitted while a fetch request runs.</p> <p>Attributes:</p> Name Type Description <code>fetch_request_id</code> <code>str</code> <p>Owning fetch request id.</p> <code>step</code> <code>str</code> <p>Progress step name.</p> <code>status</code> <code>str</code> <p>Progress status value.</p> <code>message</code> <code>ProgressMessage</code> <p>Detail payload; defaults to an empty message.</p> <code>timestamp</code> <code>str</code> <p>ISO timestamp of the event.</p>"},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models.ProgressMessage","title":"ProgressMessage","text":"<p> Bases: <code>BaseModel</code></p> <p>Optional detail payload attached to a progress event.</p> <p>Attributes:</p> Name Type Description <code>lines</code> <code>Optional[int]</code> <p>Count of raw lines processed.</p> <code>blocks</code> <code>Optional[int]</code> <p>Count of transaction blocks produced.</p> <code>count</code> <code>Optional[int]</code> <p>Count of items at the current step.</p> <code>unit</code> <code>Optional[str]</code> <p>Unit label for <code>count</code>.</p> <code>raw_ocr_line</code> <code>Optional[str]</code> <p>Raw OCR line, e.g. the ambiguous line.</p> <code>error</code> <code>Optional[str]</code> <p>Error message when the step failed.</p>"},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models.ProgressStatus","title":"ProgressStatus","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Lifecycle status values for a progress step.</p> <p>Attributes:</p> Name Type Description <code>STARTED</code> <code>ProgressStatus</code> <p>Step began.</p> <code>COMPLETED</code> <code>ProgressStatus</code> <p>Step finished.</p> <code>SKIPPED</code> <code>ProgressStatus</code> <p>Step was not needed.</p> <code>PAUSED</code> <code>ProgressStatus</code> <p>Step paused for ambiguity resolution.</p> <code>PROGRESS</code> <code>ProgressStatus</code> <p>Step is in progress.</p> <code>FAILED</code> <code>ProgressStatus</code> <p>Step failed.</p>"},{"location":"domain/fetch_pipeline/models/#domain.fetch_pipeline.models.ProgressStep","title":"ProgressStep","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Pipeline stage names used in progress events.</p> <p>Attributes:</p> Name Type Description <code>RAW_LINES</code> <code>ProgressStep</code> <p>Raw OCR line extraction step.</p> <code>TXN_BLOCKS</code> <code>ProgressStep</code> <p>Transaction block grouping step.</p> <code>TXN_DICTS</code> <code>ProgressStep</code> <p>Transaction dict construction step.</p> <code>RESUME_EXTRACT</code> <code>ProgressStep</code> <p>Resume-from-saved-stages step.</p> <code>EXTRACT</code> <code>ProgressStep</code> <p>Continued extraction step.</p> <code>PAUSED</code> <code>ProgressStep</code> <p>Ambiguity pause state.</p> <code>RAW_EXPENSES</code> <code>ProgressStep</code> <p>Raw expense materialization step.</p> <code>ENRICH_ENTITY</code> <code>ProgressStep</code> <p>Entity enrichment step.</p> <code>ENRICH_TAGS</code> <code>ProgressStep</code> <p>Tag enrichment step.</p> <code>SAVE_EXPENSES</code> <code>ProgressStep</code> <p>Expense persistence step.</p>"},{"location":"domain/fetch_pipeline/ports/","title":"Ports","text":"<ul> <li>Db</li> <li>Enrichment</li> <li>Messaging</li> <li>Service</li> </ul>"},{"location":"domain/fetch_pipeline/ports/#domain.fetch_pipeline.ports","title":"domain.fetch_pipeline.ports","text":""},{"location":"domain/fetch_pipeline/ports/#domain.fetch_pipeline.ports--summary","title":"Summary","text":"<p>Ports for the fetch pipeline domain.</p> <p>Thin adaptors and factories binding persistence, enrichment, messaging and service infrastructure to the domain models.</p>"},{"location":"domain/fetch_pipeline/ports/db/","title":"Db","text":""},{"location":"domain/fetch_pipeline/ports/db/#domain.fetch_pipeline.ports.db","title":"domain.fetch_pipeline.ports.db","text":""},{"location":"domain/fetch_pipeline/ports/db/#domain.fetch_pipeline.ports.db--summary","title":"Summary","text":"<p>Persistence port for fetch pipeline ambiguity records.</p> <p>Maps the <code>Ambiguity</code> model to a Mongo-backed document and exposes a repo factory for the <code>ambiguities</code> collection.</p>"},{"location":"domain/fetch_pipeline/ports/db/#domain.fetch_pipeline.ports.db-classes","title":"Classes","text":""},{"location":"domain/fetch_pipeline/ports/db/#domain.fetch_pipeline.ports.db.AmbiguityDocument","title":"AmbiguityDocument","text":"<p> Bases: <code>Ambiguity</code>, <code>BaseDocument</code></p> <p>Mongo document for ambiguity records.</p> <p>Combines the domain <code>Ambiguity</code> model with the <code>mongo_ops</code> document base for repository persistence.</p>"},{"location":"domain/fetch_pipeline/ports/db/#domain.fetch_pipeline.ports.db-functions","title":"Functions","text":""},{"location":"domain/fetch_pipeline/ports/db/#domain.fetch_pipeline.ports.db.create_ambiguity_repo","title":"create_ambiguity_repo","text":"<pre><code>create_ambiguity_repo()\n</code></pre> <p>Create the ambiguity repository backed by Mongo.</p> <p>Returns:</p> Type Description <p>Repository over the <code>ambiguities</code> collection.</p>"},{"location":"domain/fetch_pipeline/ports/enrichment/","title":"Enrichment","text":""},{"location":"domain/fetch_pipeline/ports/enrichment/#domain.fetch_pipeline.ports.enrichment","title":"domain.fetch_pipeline.ports.enrichment","text":""},{"location":"domain/fetch_pipeline/ports/enrichment/#domain.fetch_pipeline.ports.enrichment--summary","title":"Summary","text":"<p>Enrichment port for the fetch pipeline: orchestrates entity and tag pipelines over raw expenses.</p> <p>Adapts the domain fetch-request models to the enrichment pipeline state payloads and back to enriched expenses.</p>"},{"location":"domain/fetch_pipeline/ports/enrichment/#domain.fetch_pipeline.ports.enrichment-classes","title":"Classes","text":""},{"location":"domain/fetch_pipeline/ports/enrichment/#domain.fetch_pipeline.ports.enrichment.EnrichmentOrchestratorAdaptor","title":"EnrichmentOrchestratorAdaptor","text":"<pre><code>EnrichmentOrchestratorAdaptor(\n *, entity_pipeline=None, tags_pipeline=None\n)\n</code></pre> <p>Drive entity and tag enrichment for raw expenses.</p> <p>Runs the entity pipeline over a raw expense state payload, builds an <code>EnrichedExpense</code>, then runs the tags pipeline over its payload and fills the tag list.</p> <p>Attributes:</p> Name Type Description <code>entity_pipeline</code> <p>Pipeline resolving the payee entity; defaults to the cached entity pipeline.</p> <code>tags_pipeline</code> <p>Pipeline resolving tags; defaults to the cached tags pipeline.</p>"},{"location":"domain/fetch_pipeline/ports/enrichment/#domain.fetch_pipeline.ports.enrichment.EnrichmentOrchestratorAdaptor-functions","title":"Functions","text":""},{"location":"domain/fetch_pipeline/ports/enrichment/#domain.fetch_pipeline.ports.enrichment.EnrichmentOrchestratorAdaptor.enrich","title":"enrich <code>async</code>","text":"<pre><code>enrich(raw: RawExpense) -&gt; EnrichedExpense\n</code></pre> <p>Enrich a raw expense into an enriched expense.</p> <p>Parameters:</p> Name Type Description Default <code>raw</code> <code>RawExpense</code> <p>Raw expense parsed from the statement.</p> required <p>Returns:</p> Name Type Description <code>EnrichedExpense</code> <code>EnrichedExpense</code> <p>The enriched expense with payee, entity</p> <code>EnrichedExpense</code> <p>metadata and tags.</p>"},{"location":"domain/fetch_pipeline/ports/enrichment/#domain.fetch_pipeline.ports.enrichment-functions","title":"Functions","text":""},{"location":"domain/fetch_pipeline/ports/enrichment/#domain.fetch_pipeline.ports.enrichment.get_enrichment_orchestrator","title":"get_enrichment_orchestrator","text":"<pre><code>get_enrichment_orchestrator(\n **kwargs,\n) -&gt; EnrichmentOrchestratorAdaptor\n</code></pre> <p>Build an enrichment orchestrator adaptor.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Optional <code>entity_pipeline</code> / <code>tags_pipeline</code> overrides.</p> <code>{}</code> <p>Returns:</p> Name Type Description <code>EnrichmentOrchestratorAdaptor</code> <code>EnrichmentOrchestratorAdaptor</code> <p>A configured orchestrator.</p>"},{"location":"domain/fetch_pipeline/ports/messaging/","title":"Messaging","text":""},{"location":"domain/fetch_pipeline/ports/messaging/#domain.fetch_pipeline.ports.messaging","title":"domain.fetch_pipeline.ports.messaging","text":""},{"location":"domain/fetch_pipeline/ports/messaging/#domain.fetch_pipeline.ports.messaging--summary","title":"Summary","text":"<p>Messaging port for fetch pipeline progress events.</p> <p>Wraps the SSE in-memory bus used to stream progress to connected clients.</p>"},{"location":"domain/fetch_pipeline/ports/messaging/#domain.fetch_pipeline.ports.messaging-classes","title":"Classes","text":""},{"location":"domain/fetch_pipeline/ports/messaging/#domain.fetch_pipeline.ports.messaging.ProgressEventBus","title":"ProgressEventBus","text":"<pre><code>ProgressEventBus()\n</code></pre> <p>Publish and replay progress events for a fetch request.</p> Notes <p>Backed by an <code>SSEInMemoryBus[ProgressEvent]</code>; events are kept in memory only.</p>"},{"location":"domain/fetch_pipeline/ports/messaging/#domain.fetch_pipeline.ports.messaging.ProgressEventBus-functions","title":"Functions","text":""},{"location":"domain/fetch_pipeline/ports/messaging/#domain.fetch_pipeline.ports.messaging.ProgressEventBus.get_events","title":"get_events","text":"<pre><code>get_events(fr_id: str) -&gt; List[ProgressEvent]\n</code></pre> <p>Return the events published for a fetch request.</p> <p>Parameters:</p> Name Type Description Default <code>fr_id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Type Description <code>List[ProgressEvent]</code> <p>List[ProgressEvent]: Events seen for that request.</p>"},{"location":"domain/fetch_pipeline/ports/messaging/#domain.fetch_pipeline.ports.messaging.ProgressEventBus.publish","title":"publish <code>async</code>","text":"<pre><code>publish(event: ProgressEvent) -&gt; None\n</code></pre> <p>Publish a progress event to subscribers.</p> <p>Parameters:</p> Name Type Description Default <code>event</code> <code>ProgressEvent</code> <p>The event to broadcast.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"domain/fetch_pipeline/ports/service/","title":"Service","text":""},{"location":"domain/fetch_pipeline/ports/service/#domain.fetch_pipeline.ports.service","title":"domain.fetch_pipeline.ports.service","text":""},{"location":"domain/fetch_pipeline/ports/service/#domain.fetch_pipeline.ports.service--summary","title":"Summary","text":"<p>Service port for fetch pipeline ambiguity CRUD.</p> <p>Exposes a Hexa-built CRUD service over the ambiguity model/document.</p>"},{"location":"domain/fetch_pipeline/ports/service/#domain.fetch_pipeline.ports.service-classes","title":"Classes","text":""},{"location":"domain/fetch_pipeline/ports/service/#domain.fetch_pipeline.ports.service.AmbiguityCrudsService","title":"AmbiguityCrudsService","text":"<p> Bases: <code>CrudsServiceAdaptor[Ambiguity, AmbiguityDocument]</code></p> <p>CRUD service for ambiguity records.</p> <p>Attributes:</p> Name Type Description <code>model</code> <code>Ambiguity</code> <p>Domain model class.</p> <code>schema</code> <code>AmbiguityDocument</code> <p>Persistence document class.</p>"},{"location":"domain/fetch_pipeline/ports/service/#domain.fetch_pipeline.ports.service-functions","title":"Functions","text":""},{"location":"domain/fetch_pipeline/ports/service/#domain.fetch_pipeline.ports.service.get_ambiguity_service","title":"get_ambiguity_service","text":"<pre><code>get_ambiguity_service(repo) -&gt; AmbiguityCrudsService\n</code></pre> <p>Build the ambiguity CRUD service bound to a repo.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <p>Repository instance used for persistence.</p> required <p>Returns:</p> Name Type Description <code>AmbiguityCrudsService</code> <code>AmbiguityCrudsService</code> <p>The wired service.</p>"},{"location":"domain/fetch_pipeline/utils/","title":"Utils","text":"<ul> <li>Ocr</li> <li>Pipeline</li> </ul>"},{"location":"domain/fetch_pipeline/utils/#domain.fetch_pipeline.utils","title":"domain.fetch_pipeline.utils","text":""},{"location":"domain/fetch_pipeline/utils/#domain.fetch_pipeline.utils--summary","title":"Summary","text":"<p>Utility helpers for the fetch pipeline: OCR text handling and pipeline stage driving.</p>"},{"location":"domain/fetch_pipeline/utils/ocr/","title":"Ocr","text":""},{"location":"domain/fetch_pipeline/utils/ocr/#domain.fetch_pipeline.utils.ocr","title":"domain.fetch_pipeline.utils.ocr","text":""},{"location":"domain/fetch_pipeline/utils/ocr/#domain.fetch_pipeline.utils.ocr--summary","title":"Summary","text":"<p>OCR helpers for statement images and PDFs.</p> <p>Covers number cleaning, tesseract text normalization, PDF rasterization, and per-page OCR with optional binarization.</p>"},{"location":"domain/fetch_pipeline/utils/ocr/#domain.fetch_pipeline.utils.ocr-functions","title":"Functions","text":""},{"location":"domain/fetch_pipeline/utils/ocr/#domain.fetch_pipeline.utils.ocr.clean_num","title":"clean_num","text":"<pre><code>clean_num(s: str) -&gt; float\n</code></pre> <p>Parse a numeric token into a float amount.</p> <p>Strips non-digits and divides by the correct power of ten based on the recorded decimal part; a token without digits yields <code>0.0</code>.</p> <p>Parameters:</p> Name Type Description Default <code>s</code> <code>str</code> <p>Raw numeric string.</p> required <p>Returns:</p> Name Type Description <code>float</code> <code>float</code> <p>Parsed value.</p>"},{"location":"domain/fetch_pipeline/utils/ocr/#domain.fetch_pipeline.utils.ocr.normalize","title":"normalize","text":"<pre><code>normalize(text: str) -&gt; str\n</code></pre> <p>Normalize a raw OCR string for parsing.</p> <p>Fixes a tesseract digit misread, expands pipes to spaces, trims stray punctuation from the leading edge (including the replacement character), and removes commas.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Raw OCR output.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Normalized text.</p>"},{"location":"domain/fetch_pipeline/utils/ocr/#domain.fetch_pipeline.utils.ocr.ocr_all_pages","title":"ocr_all_pages","text":"<pre><code>ocr_all_pages(\n pdf_bytes: bytes, covert_to_image: bool = None\n) -&gt; list\n</code></pre> <p>OCR every page of a PDF in a temporary directory.</p> <p>With <code>covert_to_image</code> pages are binarized and OCRed with the numeric-mode OEM 3 config; otherwise they are OCRed with the default PSM 6 config.</p> <p>Parameters:</p> Name Type Description Default <code>pdf_bytes</code> <code>bytes</code> <p>Raw PDF content.</p> required <code>covert_to_image</code> <code>bool</code> <p>When truthy, binarize pages to images before OCR.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>list</code> <code>list</code> <p>OCR text, one string per page.</p>"},{"location":"domain/fetch_pipeline/utils/ocr/#domain.fetch_pipeline.utils.ocr.rasterize_pdf","title":"rasterize_pdf","text":"<pre><code>rasterize_pdf(\n pdf_bytes: bytes, out_dir: str, dpi: int = 300\n) -&gt; list\n</code></pre> <p>Rasterize a PDF into per-page JPEGs.</p> <p>Writes the bytes as <code>input.pdf</code> in <code>out_dir</code> and invokes <code>pdftoppm</code> at the requested DPI.</p> <p>Parameters:</p> Name Type Description Default <code>pdf_bytes</code> <code>bytes</code> <p>Raw PDF content.</p> required <code>out_dir</code> <code>str</code> <p>Directory used to write the PDF and JPEG outputs.</p> required <code>dpi</code> <code>int</code> <p>Rasterization resolution, defaults to 300.</p> <code>300</code> <p>Returns:</p> Name Type Description <code>list</code> <code>list</code> <p>Sorted list of JPEG path strings.</p> <p>Raises:</p> Type Description <code>CalledProcessError</code> <p>If <code>pdftoppm</code> fails.</p>"},{"location":"domain/fetch_pipeline/utils/pipeline/","title":"Pipeline","text":""},{"location":"domain/fetch_pipeline/utils/pipeline/#domain.fetch_pipeline.utils.pipeline","title":"domain.fetch_pipeline.utils.pipeline","text":""},{"location":"domain/fetch_pipeline/utils/pipeline/#domain.fetch_pipeline.utils.pipeline--summary","title":"Summary","text":"<p>Pipeline orchestration for fetch requests.</p> <p>Drives extraction stages (pdf, email, tabular, llama), persists partial output on every stage, pauses on ambiguity, enriches raw expenses, saves expense documents, and emits SSE progress events. The orchestrator depends on injected services and the fetch pipeline ports.</p>"},{"location":"domain/fetch_pipeline/utils/pipeline/#domain.fetch_pipeline.utils.pipeline--notes","title":"Notes","text":"<p>Guarantees:</p> <ul> <li>The orchestrator never touches I/O infrastructure directly; fetch, persistence, enrichment and messaging all flow through the injected services and ports.</li> </ul> <p>Lifecycle:</p> <ul> <li>A pause re-raises <code>PauseForResolution</code> after saving the paused request state; the caller decides whether to resume later.</li> </ul>"},{"location":"domain/fetch_pipeline/utils/pipeline/#domain.fetch_pipeline.utils.pipeline-classes","title":"Classes","text":""},{"location":"domain/fetch_pipeline/utils/pipeline/#domain.fetch_pipeline.utils.pipeline.PipelineOrchestrator","title":"PipelineOrchestrator","text":"<pre><code>PipelineOrchestrator(\n fr_svc,\n ambiguity_svc,\n expense_svc,\n pdf_fetcher: PdfFetcher,\n email_fetcher: EmailFetcher,\n xlsx_fetcher: XlsxFetcher,\n csv_fetcher: CsvFetcher,\n sse: ProgressEventBus,\n pause_on_ambiguity: bool = True,\n resolver: Optional[Callable] = None,\n resolved_choices: Optional[dict] = None,\n entity_svc=None,\n tag_svc=None,\n cache_store=None,\n)\n</code></pre> <p>Orchestrate extraction, enrichment and persistence for a fetch request.</p> <p>Drives the extraction root over fetched content, persists partial stage output, pauses on ambiguity, enriches raw expenses, saves expense documents through the injected services, and streams progress events via the SSE bus.</p> <p>Attributes:</p> Name Type Description <code>fr_svc</code> <p>Fetch request service used to read and save the request.</p> <code>ambiguity_svc</code> <p>Service persisting ambiguity records.</p> <code>expense_svc</code> <p>Service creating expense documents.</p> <code>pdf_fetcher</code> <code>PdfFetcher</code> <p>Fetcher for PDF sources.</p> <code>email_fetcher</code> <code>EmailFetcher</code> <p>Fetcher for email sources.</p> <code>xlsx_fetcher</code> <code>XlsxFetcher</code> <p>Fetcher for xlsx sources.</p> <code>csv_fetcher</code> <code>CsvFetcher</code> <p>Fetcher for csv sources.</p> <code>sse</code> <code>ProgressEventBus</code> <p>Bus streaming progress events.</p> <code>pause_on_ambiguity</code> <code>bool</code> <p>Whether ambiguity is paused for resolution.</p> <code>resolver</code> <p>Optional ambiguity resolver callback.</p> <code>resolved_choices</code> <code>dict</code> <p>Pre-chosen ambiguity resolutions.</p> <code>entity_svc</code> <p>Optional entity service used for expense creation.</p> <code>tag_svc</code> <p>Optional tag service used for expense creation.</p> <code>cache_store</code> <p>Optional read-cache store invalidated after saving.</p>"},{"location":"domain/fetch_pipeline/utils/pipeline/#domain.fetch_pipeline.utils.pipeline.PipelineOrchestrator-functions","title":"Functions","text":""},{"location":"domain/fetch_pipeline/utils/pipeline/#domain.fetch_pipeline.utils.pipeline.PipelineOrchestrator.run_pipeline","title":"run_pipeline <code>async</code>","text":"<pre><code>run_pipeline(fr_id: str) -&gt; None\n</code></pre> <p>Run the full fetch pipeline for a request.</p> <p>Reads the request, builds the extractor, fetches content, extracts raw expenses, enriches them, and persists expense documents.</p> <p>Parameters:</p> Name Type Description Default <code>fr_id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p> Notes <p>An ambiguity pause is re-raised as <code>PauseForResolution</code> after the paused state has been saved.</p>"},{"location":"domain/fetch_pipeline/utils/pipeline/#domain.fetch_pipeline.utils.pipeline-functions","title":"Functions","text":""},{"location":"domain/fetch_request/","title":"Fetch Request","text":"<ul> <li>Models</li> <li>Ports</li> </ul>"},{"location":"domain/fetch_request/#domain.fetch_request","title":"domain.fetch_request","text":""},{"location":"domain/fetch_request/#domain.fetch_request--summary","title":"Summary","text":"<p>Fetch request domain: models and ports describing statement fetch requests.</p> <p>Covers the fetch request aggregate (source, account, pipeline, trust fallback), raw/enriched expense models, and the persistence and service ports used by the fetch pipeline.</p>"},{"location":"domain/fetch_request/models/","title":"Models","text":""},{"location":"domain/fetch_request/models/#domain.fetch_request.models","title":"domain.fetch_request.models","text":""},{"location":"domain/fetch_request/models/#domain.fetch_request.models--summary","title":"Summary","text":"<p>Models for fetch requests: source variety, direction and pipeline enums, raw/enriched expenses, and the fetch request aggregate.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models-classes","title":"Classes","text":""},{"location":"domain/fetch_request/models/#domain.fetch_request.models.Bank","title":"Bank","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Supported statement banks.</p> <p>Attributes:</p> Name Type Description <code>AXIS</code> <code>Bank</code> <p>Axis Bank.</p> <code>ICICI</code> <code>Bank</code> <p>ICICI Bank.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.CsvSource","title":"CsvSource","text":"<p> Bases: <code>FileSource</code></p> <p>CSV file source.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[CSV]</code> <p>Constant source type marker.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.Direction","title":"Direction","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Cashflow direction of a transaction.</p> <p>Attributes:</p> Name Type Description <code>DEBIT</code> <code>Direction</code> <p>Money out of the account.</p> <code>CREDIT</code> <code>Direction</code> <p>Money into the account.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.EmailSource","title":"EmailSource","text":"<p> Bases: <code>Source</code></p> <p>Email statement source.</p> <p>Attributes:</p> Name Type Description <code>from_email</code> <code>str</code> <p>Sender address filter.</p> <code>subject</code> <code>str</code> <p>Subject line filter.</p> <code>raw_terms</code> <code>List[str]</code> <p>Free-text search terms.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.EnrichedExpense","title":"EnrichedExpense","text":"<p> Bases: <code>BaseModel</code></p> <p>Raw expense with enrichment results attached.</p> <p>Attributes:</p> Name Type Description <code>raw_expense</code> <code>RawExpense</code> <p>The source raw expense.</p> <code>payee</code> <code>str</code> <p>Resolved payee/entity name.</p> <code>entity_type</code> <code>str</code> <p>Entity type, defaulting to merchant.</p> <code>entity_logo</code> <code>str | None</code> <p>Logo path/url, if any.</p> <code>tags</code> <code>List[str]</code> <p>Resolved tags.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.FetchRequest","title":"FetchRequest","text":"<p> Bases: <code>BaseModel</code></p> <p>A request to fetch and process a statement.</p> <p>Attributes:</p> Name Type Description <code>source</code> <code>Union[EmailSource, PdfSource, XlsxSource, CsvSource, FileSource]</code> <p>Statement source describing how to fetch the data.</p> <code>account</code> <code>Account</code> <p>Account the statement belongs to.</p> <code>start_date</code> <code>datetime</code> <p>Statement window start.</p> <code>end_date</code> <code>datetime</code> <p>Statement window end.</p> <code>status</code> <code>str</code> <p>Processing status, defaulting to pending.</p> <code>pipeline</code> <code>Pipeline</code> <p>Extraction pipeline to use.</p> <code>trust_fallback</code> <code>Optional[TrustFallback]</code> <p>Optional balance-chain trust policy.</p> <code>fingerprint</code> <code>str</code> <p>Deduplication fingerprint for the request.</p> <code>completed_at</code> <code>Optional[datetime]</code> <p>Completion timestamp, if finished.</p> <code>error_message</code> <code>Optional[str]</code> <p>Failure message, if failed.</p> <code>retry_count</code> <code>int</code> <p>Number of retries attempted.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.FileSource","title":"FileSource","text":"<p> Bases: <code>Source</code></p> <p>File-based statement source.</p> <p>Attributes:</p> Name Type Description <code>path</code> <code>str</code> <p>Path to the uploaded file.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.PdfSource","title":"PdfSource","text":"<p> Bases: <code>FileSource</code></p> <p>PDF file source.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[PDF]</code> <p>Constant source type marker.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.Pipeline","title":"Pipeline","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Extraction pipeline choice for a fetch request.</p> <p>Attributes:</p> Name Type Description <code>HEURISTIC</code> <code>Pipeline</code> <p>Rule/heuristic extraction pipeline.</p> <code>LLM</code> <code>Pipeline</code> <p>LLM-assisted extraction pipeline.</p> <code>LLAMA_PARSE</code> <code>Pipeline</code> <p>LlamaParse table-direct extraction pipeline.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.RawExpense","title":"RawExpense","text":"<p> Bases: <code>BaseModel</code></p> <p>A single transaction parsed from a statement.</p> <p>Attributes:</p> Name Type Description <code>date</code> <code>str</code> <p>Expense date as DD-MM-YYYY.</p> <code>amount</code> <code>float</code> <p>Transaction amount.</p> <code>balance</code> <code>float</code> <p>Account balance after transaction.</p> <code>description</code> <code>str</code> <p>Complete reconstructed transaction description.</p> <code>raw_lines</code> <code>List[str]</code> <p>Raw OCR/text lines that form this transaction.</p> <code>direction</code> <code>Direction</code> <p>Either <code>Direction.DEBIT</code> or <code>Direction.CREDIT</code>.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.Source","title":"Source","text":"<p> Bases: <code>BaseModel</code></p> <p>Base statement source carrying extraction progress state.</p> <p>Attributes:</p> Name Type Description <code>bank</code> <code>Bank</code> <p>Statement bank, defaulting to <code>Bank.ICICI</code>.</p> <code>type</code> <code>SourceType</code> <p>Source kind discriminator.</p> <code>raw_lines</code> <code>List[str]</code> <p>Raw OCR/text lines extracted so far.</p> <code>txn_blocks</code> <code>Dict[str, Any]</code> <p>Transaction blocks keyed by order id.</p> <code>txn_dicts</code> <code>List[RawExpense]</code> <p>Parsed raw expenses.</p> <code>enrichment_dicts</code> <code>List[EnrichedExpense]</code> <p>Enriched expenses.</p> <code>txn_dicts_count</code> <code>int</code> <p>Number of parsed raw expenses.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.SourceType","title":"SourceType","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Statement source kinds.</p> <p>Attributes:</p> Name Type Description <code>FILE</code> <code>SourceType</code> <p>Generic file source.</p> <code>EMAIL</code> <code>SourceType</code> <p>Email source.</p> <code>PDF</code> <code>SourceType</code> <p>PDF file source.</p> <code>XLSX</code> <code>SourceType</code> <p>Spreadsheet source.</p> <code>CSV</code> <code>SourceType</code> <p>CSV source.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.TrustFallback","title":"TrustFallback","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Per-FetchRequest policy for broken balance chains.</p> <p>When set, resolution skips OCR-style candidate guesswork entirely and always trusts the configured column: - AMOUNT: keep the transaction amount, derive balance as prev \u00b1 amount. - BALANCE: keep the stated balance, derive amount from the balance delta.</p> <p>Attributes:</p> Name Type Description <code>AMOUNT</code> <code>TrustFallback</code> <p>Trust the transaction amount; balance is derived as prev \u00b1 amount.</p> <code>BALANCE</code> <code>TrustFallback</code> <p>Trust the stated balance; amount is derived from the balance delta.</p>"},{"location":"domain/fetch_request/models/#domain.fetch_request.models.XlsxSource","title":"XlsxSource","text":"<p> Bases: <code>FileSource</code></p> <p>XLSX file source.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[XLSX]</code> <p>Constant source type marker.</p>"},{"location":"domain/fetch_request/ports/","title":"Ports","text":"<ul> <li>Db</li> <li>Service</li> </ul>"},{"location":"domain/fetch_request/ports/#domain.fetch_request.ports","title":"domain.fetch_request.ports","text":""},{"location":"domain/fetch_request/ports/#domain.fetch_request.ports--summary","title":"Summary","text":"<p>Ports for the fetch request domain.</p> <p>Thin adaptors and factories binding the Mongo-backed fetch request document and the Hexa-built CRUD service to the domain model.</p>"},{"location":"domain/fetch_request/ports/db/","title":"Db","text":""},{"location":"domain/fetch_request/ports/db/#domain.fetch_request.ports.db","title":"domain.fetch_request.ports.db","text":""},{"location":"domain/fetch_request/ports/db/#domain.fetch_request.ports.db--summary","title":"Summary","text":"<p>Persistence port for fetch requests.</p> <p>Maps the <code>FetchRequest</code> model (with a populated account reference) to a Mongo-backed document and exposes the repo factory with population rules.</p>"},{"location":"domain/fetch_request/ports/db/#domain.fetch_request.ports.db-classes","title":"Classes","text":""},{"location":"domain/fetch_request/ports/db/#domain.fetch_request.ports.db.FetchRequestDocument","title":"FetchRequestDocument","text":"<p> Bases: <code>FetchRequest</code>, <code>BaseDocument</code></p> <p>Mongo document for fetch requests.</p> <p>Attributes:</p> Name Type Description <code>account</code> <code>AccountDocument</code> <p>Populated account reference.</p>"},{"location":"domain/fetch_request/ports/db/#domain.fetch_request.ports.db-functions","title":"Functions","text":""},{"location":"domain/fetch_request/ports/db/#domain.fetch_request.ports.db.create_fetch_request_repo","title":"create_fetch_request_repo","text":"<pre><code>create_fetch_request_repo(\n account_repo: Any = None, user_repo: Any = None\n)\n</code></pre> <p>Create the fetch request repository with account population.</p> <p>Parameters:</p> Name Type Description Default <code>account_repo</code> <code>Any</code> <p>Repository used to populate <code>account</code> references.</p> <code>None</code> <code>user_repo</code> <code>Any</code> <p>Reserved for user population; currently unused.</p> <code>None</code> <p>Returns:</p> Type Description <p>Repository over the <code>fetch_requests</code> collection configured with</p> <p>population rules.</p>"},{"location":"domain/fetch_request/ports/service/","title":"Service","text":""},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service","title":"domain.fetch_request.ports.service","text":""},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service--summary","title":"Summary","text":"<p>Service port for fetch requests.</p> <p>Exposes a Hexa-built CRUD service with stage-saving helpers used by the fetch pipeline orchestrator.</p>"},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service-classes","title":"Classes","text":""},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service.FetchRequestCrudsService","title":"FetchRequestCrudsService","text":"<p> Bases: <code>CrudsServiceAdaptor[FetchRequest, FetchRequestDocument]</code></p> <p>CRUD service for fetch requests with pipeline stage helpers.</p> <p>Attributes:</p> Name Type Description <code>model</code> <code>FetchRequest</code> <p>Domain model class.</p> <code>schema</code> <code>FetchRequestDocument</code> <p>Persistence document class.</p>"},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service.FetchRequestCrudsService-functions","title":"Functions","text":""},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service.FetchRequestCrudsService.save_enrichment","title":"save_enrichment <code>async</code>","text":"<pre><code>save_enrichment(\n id: PyObjectId, enrichment_dicts: list\n) -&gt; None\n</code></pre> <p>Persist the enriched expense dicts on the request source.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>enrichment_dicts</code> <code>list</code> <p>Enriched expense dicts.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service.FetchRequestCrudsService.save_raw_lines","title":"save_raw_lines <code>async</code>","text":"<pre><code>save_raw_lines(id: PyObjectId, raw_lines: list) -&gt; None\n</code></pre> <p>Persist the extracted raw lines on the request source.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>raw_lines</code> <code>list</code> <p>Raw OCR/text lines.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service.FetchRequestCrudsService.save_txn_blocks","title":"save_txn_blocks <code>async</code>","text":"<pre><code>save_txn_blocks(id: PyObjectId, txn_blocks: dict) -&gt; None\n</code></pre> <p>Persist the extracted transaction blocks on the request source.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>txn_blocks</code> <code>dict</code> <p>Transaction blocks keyed by order id.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service.FetchRequestCrudsService.save_txn_dicts","title":"save_txn_dicts <code>async</code>","text":"<pre><code>save_txn_dicts(\n id: PyObjectId, txn_dicts: list, txn_dicts_count: int\n) -&gt; None\n</code></pre> <p>Persist the parsed transaction dicts and count on the request source.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>txn_dicts</code> <code>list</code> <p>Raw expense dicts.</p> required <code>txn_dicts_count</code> <code>int</code> <p>Number of parsed transaction dicts.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service.FetchRequestCrudsService.update_status","title":"update_status <code>async</code>","text":"<pre><code>update_status(\n id: PyObjectId,\n status: str,\n error_message: Optional[str] = None,\n retry_count: Optional[int] = None,\n) -&gt; bool\n</code></pre> <p>Update the request status, optionally carrying failure detail.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>status</code> <code>str</code> <p>New status value.</p> required <code>error_message</code> <code>Optional[str]</code> <p>Message recorded when failing.</p> <code>None</code> <code>retry_count</code> <code>Optional[int]</code> <p>Retry counter recorded when failing.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was patched.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>If <code>status == \"failed\"</code> and either <code>error_message</code> or <code>retry_count</code> is <code>None</code>.</p>"},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service-functions","title":"Functions","text":""},{"location":"domain/fetch_request/ports/service/#domain.fetch_request.ports.service.get_fetch_request_service","title":"get_fetch_request_service","text":"<pre><code>get_fetch_request_service(repo) -&gt; FetchRequestCrudsService\n</code></pre> <p>Build the fetch request CRUD service bound to a repo.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <p>Repository instance used for persistence.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestCrudsService</code> <code>FetchRequestCrudsService</code> <p>The wired service.</p>"},{"location":"domain/fetcher/","title":"Fetcher","text":"<ul> <li>Ports</li> </ul>"},{"location":"domain/fetcher/#domain.fetcher","title":"domain.fetcher","text":""},{"location":"domain/fetcher/#domain.fetcher--summary","title":"Summary","text":"<p>Fetcher domain: adaptors that pull raw statements from email, spreadsheet, and PDF sources.</p>"},{"location":"domain/fetcher/ports/","title":"Ports","text":"<ul> <li>Email</li> <li>File</li> <li>Pdf</li> </ul>"},{"location":"domain/fetcher/ports/#domain.fetcher.ports","title":"domain.fetcher.ports","text":""},{"location":"domain/fetcher/ports/#domain.fetcher.ports--summary","title":"Summary","text":"<p>Port wiring for the fetcher domain: email, spreadsheet, and PDF fetchers.</p>"},{"location":"domain/fetcher/ports/email/","title":"Email","text":""},{"location":"domain/fetcher/ports/email/#domain.fetcher.ports.email","title":"domain.fetcher.ports.email","text":""},{"location":"domain/fetcher/ports/email/#domain.fetcher.ports.email--summary","title":"Summary","text":"<p>Email fetcher: pull statement messages from Gmail and convert them to omniread content.</p>"},{"location":"domain/fetcher/ports/email/#domain.fetcher.ports.email-classes","title":"Classes","text":""},{"location":"domain/fetcher/ports/email/#domain.fetcher.ports.email.EmailFetcher","title":"EmailFetcher","text":"<pre><code>EmailFetcher(\n credentials_path: str,\n token_path: str,\n scopes: List[str],\n)\n</code></pre> <p>Fetch emails through Gmail and convert each message to :class:<code>Content</code>.</p> Notes <p>Lifecycle: Construction performs OAuth credential resolution once; a missing or expired token is refreshed automatically by the credential store.</p> <p>Initialize the Gmail-backed email reader.</p> <p>Parameters:</p> Name Type Description Default <code>credentials_path</code> <code>str</code> <p>Path to the OAuth client credentials JSON.</p> required <code>token_path</code> <code>str</code> <p>Path to the persisted OAuth token pickle.</p> required <code>scopes</code> <code>List[str]</code> <p>OAuth scopes to request.</p> required"},{"location":"domain/fetcher/ports/email/#domain.fetcher.ports.email.EmailFetcher-functions","title":"Functions","text":""},{"location":"domain/fetcher/ports/email/#domain.fetcher.ports.email.EmailFetcher.fetch","title":"fetch","text":"<pre><code>fetch(query: str) -&gt; List[Content]\n</code></pre> <p>Return every message matching the Gmail <code>query</code> as content.</p> <p>Parameters:</p> Name Type Description Default <code>query</code> <code>str</code> <p>Gmail search query, e.g. <code>from:x label:statements</code>.</p> required <p>Returns:</p> Type Description <code>List[Content]</code> <p>List[Content]: HTML content per matching message.</p>"},{"location":"domain/fetcher/ports/file/","title":"File","text":""},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file","title":"domain.fetcher.ports.file","text":""},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file--summary","title":"Summary","text":"<p>File fetchers: read spreadsheet statements (XLSX, CSV) into omniread content.</p>"},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file-classes","title":"Classes","text":""},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file.CsvFetcher","title":"CsvFetcher","text":"<pre><code>CsvFetcher()\n</code></pre> <p>Fetch a statement from a CSV file through a filesystem scraper.</p>"},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file.CsvFetcher-functions","title":"Functions","text":""},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file.CsvFetcher.fetch","title":"fetch <code>async</code>","text":"<pre><code>fetch(csv_path: Path) -&gt; Content\n</code></pre> <p>Read the statement content of <code>csv_path</code>.</p> <p>Parameters:</p> Name Type Description Default <code>csv_path</code> <code>Path</code> <p>Filesystem path to the CSV file.</p> required <p>Returns:</p> Name Type Description <code>Content</code> <code>Content</code> <p>Extracted statement content.</p>"},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file.XlsxFetcher","title":"XlsxFetcher","text":"<pre><code>XlsxFetcher()\n</code></pre> <p>Fetch a statement from an XLSX file through a filesystem scraper.</p>"},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file.XlsxFetcher-functions","title":"Functions","text":""},{"location":"domain/fetcher/ports/file/#domain.fetcher.ports.file.XlsxFetcher.fetch","title":"fetch <code>async</code>","text":"<pre><code>fetch(xlsx_path: Path) -&gt; Content\n</code></pre> <p>Read the statement content of <code>xlsx_path</code>.</p> <p>Parameters:</p> Name Type Description Default <code>xlsx_path</code> <code>Path</code> <p>Filesystem path to the XLSX file.</p> required <p>Returns:</p> Name Type Description <code>Content</code> <code>Content</code> <p>Extracted statement content.</p>"},{"location":"domain/fetcher/ports/pdf/","title":"Pdf","text":""},{"location":"domain/fetcher/ports/pdf/#domain.fetcher.ports.pdf","title":"domain.fetcher.ports.pdf","text":""},{"location":"domain/fetcher/ports/pdf/#domain.fetcher.ports.pdf--summary","title":"Summary","text":"<p>PDF fetcher: read statement PDFs into omniread content.</p>"},{"location":"domain/fetcher/ports/pdf/#domain.fetcher.ports.pdf-classes","title":"Classes","text":""},{"location":"domain/fetcher/ports/pdf/#domain.fetcher.ports.pdf.PdfFetcher","title":"PdfFetcher","text":"<pre><code>PdfFetcher()\n</code></pre> <p>Fetch a statement from a PDF file through a filesystem scraper.</p>"},{"location":"domain/fetcher/ports/pdf/#domain.fetcher.ports.pdf.PdfFetcher-functions","title":"Functions","text":""},{"location":"domain/fetcher/ports/pdf/#domain.fetcher.ports.pdf.PdfFetcher.fetch","title":"fetch <code>async</code>","text":"<pre><code>fetch(pdf_path: Path) -&gt; Content\n</code></pre> <p>Read the statement content of <code>pdf_path</code>.</p> <p>Parameters:</p> Name Type Description Default <code>pdf_path</code> <code>Path</code> <p>Filesystem path to the PDF file.</p> required <p>Returns:</p> Name Type Description <code>Content</code> <code>Content</code> <p>Extracted statement content.</p>"},{"location":"domain/report/","title":"Report","text":"<ul> <li>Models</li> <li>Ports</li> </ul>"},{"location":"domain/report/#domain.report","title":"domain.report","text":""},{"location":"domain/report/#domain.report--summary","title":"Summary","text":"<p>Report domain: snapshot query and cube models, sparse cube store, and the report service.</p>"},{"location":"domain/report/models/","title":"Models","text":""},{"location":"domain/report/models/#domain.report.models","title":"domain.report.models","text":""},{"location":"domain/report/models/#domain.report.models--summary","title":"Summary","text":"<p>Report domain models: snapshot query, cube series, and API response.</p> <p>Pure models plus date/period helpers consumed by the report service. Functions here are side-effect free; they only parse, normalize, and validate report definitions and period labels.</p>"},{"location":"domain/report/models/#domain.report.models-classes","title":"Classes","text":""},{"location":"domain/report/models/#domain.report.models.Report","title":"Report","text":"<p> Bases: <code>BaseModel</code></p> <p>API response for a sliced report view.</p> <p>Attributes:</p> Name Type Description <code>id</code> <code>str</code> <p>Snapshot ID the view was served from.</p> <code>name</code> <code>str</code> <p>Snapshot name.</p> <code>query</code> <code>ReportQuery</code> <p>Normalized query the snapshot was built from.</p> <code>generated_at</code> <code>str</code> <p>ISO-8601 timestamp of cube generation.</p> <code>created_at</code> <code>str</code> <p>ISO-8601 timestamp of snapshot creation.</p> <code>flow</code> <code>str</code> <p>Flow the view was sliced to.</p> <code>granularities</code> <code>List[str]</code> <p>Granularities present in the view.</p> <code>period_ids</code> <code>List[str]</code> <p>All period IDs available, sorted chronologically.</p> <code>payees</code> <code>List[str]</code> <p>Every payee present in the cube.</p> <code>tags</code> <code>List[str]</code> <p>Every tag path present in the cube.</p> <code>buckets</code> <code>List[ReportBucket]</code> <p>Buckets forming the sliced view.</p>"},{"location":"domain/report/models/#domain.report.models.ReportBucket","title":"ReportBucket","text":"<p> Bases: <code>BaseModel</code></p> <p>A flow x group-dimension slice of a report, keyed per granularity.</p> <p>Attributes:</p> Name Type Description <code>flow</code> <code>str</code> <p>Flow this bucket covers, e.g. <code>\"inflows\"</code>.</p> <code>group_key</code> <code>Dict[str, List[str]]</code> <p>Dimension filters defining the bucket.</p> <code>series</code> <code>Dict[str, List[ReportPeriod]]</code> <p>Periods per granularity.</p>"},{"location":"domain/report/models/#domain.report.models.ReportMetrics","title":"ReportMetrics","text":"<p> Bases: <code>BaseModel</code></p> <p>Aggregated metrics over a slice of transactions.</p> <p>Attributes:</p> Name Type Description <code>outflows</code> <code>float</code> <p>Sum of absolute negative amounts.</p> <code>inflows</code> <code>float</code> <p>Sum of positive amounts.</p> <code>sum</code> <code>float</code> <p>Net total of all amounts.</p> <code>count</code> <code>int</code> <p>Number of transactions contributing amounts.</p> <code>avg</code> <code>float</code> <p>Mean transaction amount.</p> <code>min</code> <code>float</code> <p>Minimum transaction amount.</p> <code>max</code> <code>float</code> <p>Maximum transaction amount.</p> <code>first_date</code> <code>Optional[str]</code> <p>Earliest transaction date, DD-MM-YYYY.</p> <code>last_date</code> <code>Optional[str]</code> <p>Latest transaction date, DD-MM-YYYY.</p> <code>cadence</code> <code>Optional[float]</code> <p>Mean gap in days between consecutive dates.</p> <code>frequency</code> <code>Optional[float]</code> <p>Frequency per day derived from cadence.</p>"},{"location":"domain/report/models/#domain.report.models.ReportPeriod","title":"ReportPeriod","text":"<p> Bases: <code>BaseModel</code></p> <p>One period slice of a cube level: metrics plus the contributing transactions.</p> <p>Attributes:</p> Name Type Description <code>period_id</code> <code>str</code> <p>Canonical period label.</p> <code>start</code> <code>Optional[str]</code> <p>Inclusive ISO start boundary.</p> <code>end</code> <code>Optional[str]</code> <p>Exclusive ISO end boundary.</p> <code>metrics</code> <code>ReportMetrics</code> <p>Aggregated metrics for the period.</p> <code>txns</code> <code>List[Any]</code> <p>Transactions contributing to the period.</p>"},{"location":"domain/report/models/#domain.report.models.ReportQuery","title":"ReportQuery","text":"<p> Bases: <code>BaseModel</code></p> <p>Definition of a report snapshot. Bounds the data set; dimensions are sliced at read time.</p> <p>Attributes:</p> Name Type Description <code>name</code> <code>str</code> <p>Snapshot name; empty for an auto-generated name.</p> <code>granularities</code> <code>List[str]</code> <p>Granularities to precompute in the cube.</p> <code>group_dims</code> <code>List[str]</code> <p>Dimensions to group by, e.g. <code>\"payee\"</code>, <code>\"tag\"</code>.</p> <code>flow</code> <code>str</code> <p>Flow filter: inflows, outflows, or both.</p> <code>accounts</code> <code>Optional[List[str]]</code> <p>Account names to include; all when <code>None</code>.</p> <code>ignore_self</code> <code>bool</code> <p>Exclude self-transfer tagged expenses.</p> <code>start_date</code> <code>str</code> <p>Inclusive start boundary, DD-MM-YYYY.</p> <code>end_date</code> <code>str</code> <p>Inclusive end boundary, DD-MM-YYYY.</p> <code>min_amount</code> <code>Optional[float]</code> <p>Minimum absolute amount to include.</p> <code>max_amount</code> <code>Optional[float]</code> <p>Maximum absolute amount to include.</p>"},{"location":"domain/report/models/#domain.report.models.ReportSnapshot","title":"ReportSnapshot","text":"<p> Bases: <code>BaseModel</code></p> <p>Stored metadata for a precomputed report cube.</p> <p>Attributes:</p> Name Type Description <code>name</code> <code>str</code> <p>Snapshot name.</p> <code>query</code> <code>ReportQuery</code> <p>Normalized query the cube was built from.</p> <code>signature</code> <code>str</code> <p>Canonical fingerprint of the normalized query.</p> <code>generated_at</code> <code>str</code> <p>ISO-8601 timestamp of cube generation.</p>"},{"location":"domain/report/models/#domain.report.models-functions","title":"Functions","text":""},{"location":"domain/report/models/#domain.report.models.compute_metrics","title":"compute_metrics","text":"<pre><code>compute_metrics(txns: List[dict]) -&gt; ReportMetrics\n</code></pre> <p>Compute aggregate metrics over a list of transaction dicts.</p> <p>Parameters:</p> Name Type Description Default <code>txns</code> <code>List[dict]</code> <p>Transactions with <code>amount</code> and <code>occurred_at</code> keys.</p> required <p>Returns:</p> Name Type Description <code>ReportMetrics</code> <code>ReportMetrics</code> <p>Aggregated metrics; empty (zeroed) metrics when no amounts are present.</p>"},{"location":"domain/report/models/#domain.report.models.expand_tag_hierarchy","title":"expand_tag_hierarchy","text":"<pre><code>expand_tag_hierarchy(tag_path: str) -&gt; List[str]\n</code></pre> <p>Given 'food,restaurants' return ['food', 'food,restaurants'] (every ancestor prefix).</p> <p>Parameters:</p> Name Type Description Default <code>tag_path</code> <code>str</code> <p>Comma-joined tag hierarchy path, or <code>\"untagged\"</code>.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Every ancestor prefix of the path, or <code>[\"untagged\"]</code>.</p>"},{"location":"domain/report/models/#domain.report.models.normalize_date","title":"normalize_date","text":"<pre><code>normalize_date(value: str) -&gt; str\n</code></pre> <p>Canonicalize a date to the DD-MM-YYYY format (no time).</p> <p>Parameters:</p> Name Type Description Default <code>value</code> <code>str</code> <p>Date string in any supported input format.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Date in canonical DD-MM-YYYY form.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When the value cannot be parsed as a date.</p>"},{"location":"domain/report/models/#domain.report.models.normalize_granularities","title":"normalize_granularities","text":"<pre><code>normalize_granularities(\n values: Optional[Union[str, Sequence[str]]] = None,\n) -&gt; List[str]\n</code></pre> <p>Canonicalize + validate the granularities to precompute. Empty/default -&gt; all period types.</p> <p>Parameters:</p> Name Type Description Default <code>values</code> <code>Optional[Union[str, Sequence[str]]]</code> <p>Granularity names, a single name, or <code>None</code> for the defaults.</p> <code>None</code> <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Deduplicated, canonical granularity names.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When a value is not a supported granularity.</p>"},{"location":"domain/report/models/#domain.report.models.normalize_period_label","title":"normalize_period_label","text":"<pre><code>normalize_period_label(value: str, granularity: str) -&gt; str\n</code></pre> <p>Canonicalize a period label to the period_key format for a granularity.</p> <p>Parameters:</p> Name Type Description Default <code>value</code> <code>str</code> <p>Raw period label, e.g. <code>W03-2024</code> or <code>Q2-2024</code>.</p> required <code>granularity</code> <code>str</code> <p>Granularity the label belongs to.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Canonical period label, or the input unchanged when it cannot be normalized.</p>"},{"location":"domain/report/models/#domain.report.models.parse_date","title":"parse_date","text":"<pre><code>parse_date(value: str) -&gt; Optional[datetime.date]\n</code></pre> <p>Parse a date string into a date, else <code>None</code>.</p> <p>Parameters:</p> Name Type Description Default <code>value</code> <code>str</code> <p>Date string in DD-MM-YYYY, YYYY-MM-DD, or DD/MM/YYYY form.</p> required <p>Returns:</p> Type Description <code>Optional[date]</code> <p>Optional[datetime.date]: The parsed date, or <code>None</code> when unparseable.</p>"},{"location":"domain/report/models/#domain.report.models.period_bounds","title":"period_bounds","text":"<pre><code>period_bounds(dt: datetime.date, period_type: str)\n</code></pre> <p>Calendar (start, end) boundaries for a period, as dates. <code>end</code> is exclusive.</p> <p>Parameters:</p> Name Type Description Default <code>dt</code> <code>date</code> <p>Any date inside the period.</p> required <code>period_type</code> <code>str</code> <p>Granularity: daily, weekly, monthly, quarterly, or yearly.</p> required <p>Returns:</p> Name Type Description <code>tuple</code> <p><code>(start, end)</code> date boundaries; <code>end</code> is exclusive.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When the period type is unknown.</p>"},{"location":"domain/report/models/#domain.report.models.period_key","title":"period_key","text":"<pre><code>period_key(dt: datetime.date, period_type: str) -&gt; str\n</code></pre> <p>Return the period label containing <code>dt</code> for a granularity.</p> <p>Parameters:</p> Name Type Description Default <code>dt</code> <code>date</code> <p>Date to bucket.</p> required <code>period_type</code> <code>str</code> <p>Granularity: daily, weekly, monthly, quarterly, yearly, or all.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Canonical period label for the given granularity.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When the period type is unknown.</p>"},{"location":"domain/report/models/#domain.report.models.period_sort_key","title":"period_sort_key","text":"<pre><code>period_sort_key(label: str)\n</code></pre> <p>Chronological sort key for a concrete period label (within one granularity).</p> <p>Parameters:</p> Name Type Description Default <code>label</code> <code>str</code> <p>Period label, e.g. <code>2024-W03</code>, <code>2024-Jun</code>, or <code>2024</code>.</p> required <p>Returns:</p> Name Type Description <code>tuple</code> <p>Sort key of <code>(year, sub)</code> where <code>sub</code> ranks within the year.</p>"},{"location":"domain/report/models/#domain.report.models.quarterly_label","title":"quarterly_label","text":"<pre><code>quarterly_label(year: int, quarter: int) -&gt; str\n</code></pre> <p>Build the canonical label for a calendar quarter.</p> <p>Parameters:</p> Name Type Description Default <code>year</code> <code>int</code> <p>Four-digit calendar year.</p> required <code>quarter</code> <code>int</code> <p>Quarter number in <code>1..4</code>.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Quarterly label, e.g. <code>2024-Apr-Jun</code>.</p>"},{"location":"domain/report/models/#domain.report.models.range_label","title":"range_label","text":"<pre><code>range_label(\n start_date: str = \"\", end_date: str = \"\"\n) -&gt; str\n</code></pre> <p>Build the <code>start:end</code> range label for a date window ('' when unbounded).</p> <p>Parameters:</p> Name Type Description Default <code>start_date</code> <code>str</code> <p>Start boundary date; empty for unbounded start.</p> <code>''</code> <code>end_date</code> <code>str</code> <p>End boundary date; empty for unbounded end.</p> <code>''</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p><code>start:end</code> label, or an empty string when both bounds are empty.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When the start date is after the end date.</p>"},{"location":"domain/report/ports/","title":"Ports","text":"<ul> <li>Db</li> <li>Service</li> <li>Store</li> </ul>"},{"location":"domain/report/ports/#domain.report.ports","title":"domain.report.ports","text":""},{"location":"domain/report/ports/#domain.report.ports--summary","title":"Summary","text":"<p>Port wiring for reports: Mongo repository, cube store, and the report service.</p>"},{"location":"domain/report/ports/db/","title":"Db","text":""},{"location":"domain/report/ports/db/#domain.report.ports.db","title":"domain.report.ports.db","text":""},{"location":"domain/report/ports/db/#domain.report.ports.db--summary","title":"Summary","text":"<p>Mongo persistence for report snapshots: document schema and repository factory.</p>"},{"location":"domain/report/ports/db/#domain.report.ports.db-classes","title":"Classes","text":""},{"location":"domain/report/ports/db/#domain.report.ports.db.ReportSnapshotDocument","title":"ReportSnapshotDocument","text":"<p> Bases: <code>ReportSnapshot</code>, <code>BaseDocument</code></p> <p>Mongo document form of :class:<code>ReportSnapshot</code> storing the cube metadata.</p>"},{"location":"domain/report/ports/db/#domain.report.ports.db-functions","title":"Functions","text":""},{"location":"domain/report/ports/db/#domain.report.ports.db.create_report_repo","title":"create_report_repo","text":"<pre><code>create_report_repo()\n</code></pre> <p>Create a Mongo-backed report snapshot repository.</p> <p>Returns:</p> Name Type Description <code>Any</code> <p>Mongo-backed report snapshot repository.</p>"},{"location":"domain/report/ports/service/","title":"Service","text":""},{"location":"domain/report/ports/service/#domain.report.ports.service","title":"domain.report.ports.service","text":""},{"location":"domain/report/ports/service/#domain.report.ports.service--summary","title":"Summary","text":"<p>Report service: validate snapshot queries, precompute sparse cubes, and synthesize sliced report views.</p> <p>A snapshot is keyed by the canonical signature of its normalized query; the sparse cube data lives in the configured :class:<code>ReportStore</code> while snapshot metadata is persisted through the report repository.</p>"},{"location":"domain/report/ports/service/#domain.report.ports.service-classes","title":"Classes","text":""},{"location":"domain/report/ports/service/#domain.report.ports.service.ReportService","title":"ReportService","text":"<pre><code>ReportService(\n expense_svc: ExpenseCrudsService,\n tag_svc: TagCrudsService,\n store: ReportStore,\n report_repo=None,\n)\n</code></pre> <p>Build, persist, and serve precomputed report snapshots.</p> Notes <p>Instances are created by :func:<code>get_report_service</code>. The service scans expenses in batches, expands tag hierarchies, and persists period series into the configured :class:<code>ReportStore</code>.</p> <p>Initialize the report service with its dependencies.</p> <p>Parameters:</p> Name Type Description Default <code>expense_svc</code> <code>ExpenseCrudsService</code> <p>Expense CRUD service used as the cube source.</p> required <code>tag_svc</code> <code>TagCrudsService</code> <p>Tag CRUD service used to expand tag hierarchies and resolve ignore tags.</p> required <code>store</code> <code>ReportStore</code> <p>Key-value store for cube period data.</p> required <code>report_repo</code> <code>Any</code> <p>Report snapshot repository; defaults to :func:<code>create_report_repo</code> when omitted.</p> <code>None</code>"},{"location":"domain/report/ports/service/#domain.report.ports.service.ReportService-functions","title":"Functions","text":""},{"location":"domain/report/ports/service/#domain.report.ports.service.ReportService.delete_snapshot","title":"delete_snapshot <code>async</code>","text":"<pre><code>delete_snapshot(report_id: str) -&gt; bool\n</code></pre> <p>Delete a snapshot and all of its cube keys from the store.</p> <p>Parameters:</p> Name Type Description Default <code>report_id</code> <code>str</code> <p>Snapshot ID to delete.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when the snapshot existed and was deleted.</p>"},{"location":"domain/report/ports/service/#domain.report.ports.service.ReportService.fetch_report","title":"fetch_report <code>async</code>","text":"<pre><code>fetch_report(\n report_id: str,\n granularities: Optional[List[str]] = None,\n period_ids: Optional[List[str]] = None,\n flow: str = \"outflows\",\n payees: Optional[List[str]] = None,\n tags: Optional[List[str]] = None,\n) -&gt; Optional[Report]\n</code></pre> <p>Slice a stored snapshot into a report API response.</p> <p><code>\"*\"</code> in <code>payees</code> or <code>tags</code> expands to every value stored in the cube meta.</p> <p>Parameters:</p> Name Type Description Default <code>report_id</code> <code>str</code> <p>Snapshot ID to slice.</p> required <code>granularities</code> <code>Optional[List[str]]</code> <p>Granularities to include; defaults to the snapshot's own.</p> <code>None</code> <code>period_ids</code> <code>Optional[List[str]]</code> <p>Period labels to filter to.</p> <code>None</code> <code>flow</code> <code>str</code> <p>Flow to serve; <code>both</code> includes inflows and outflows.</p> <code>'outflows'</code> <code>payees</code> <code>Optional[List[str]]</code> <p>Payee filters applied per bucket.</p> <code>None</code> <code>tags</code> <code>Optional[List[str]]</code> <p>Tag path filters applied per bucket.</p> <code>None</code> <p>Returns:</p> Type Description <code>Optional[Report]</code> <p>Optional[Report]: The sliced report view, or <code>None</code> when the snapshot does not exist.</p>"},{"location":"domain/report/ports/service/#domain.report.ports.service.ReportService.generate_snapshot","title":"generate_snapshot <code>async</code>","text":"<pre><code>generate_snapshot(\n query: ReportQuery,\n) -&gt; ReportSnapshotDocument\n</code></pre> <p>Validate a query and return an existing or newly built snapshot.</p> <p>If a snapshot with the same canonical signature already exists it is returned directly; otherwise a fresh cube is built and persisted.</p> <p>Parameters:</p> Name Type Description Default <code>query</code> <code>ReportQuery</code> <p>Raw snapshot definition.</p> required <p>Returns:</p> Name Type Description <code>ReportSnapshotDocument</code> <code>ReportSnapshotDocument</code> <p>The existing or newly created snapshot.</p>"},{"location":"domain/report/ports/service/#domain.report.ports.service.ReportService.list_snapshots","title":"list_snapshots <code>async</code>","text":"<pre><code>list_snapshots(\n offset: int = 0, limit: int = DEFAULT_LIMIT\n) -&gt; List[ReportSnapshotDocument]\n</code></pre> <p>List stored snapshots, newest first.</p> <p>Parameters:</p> Name Type Description Default <code>offset</code> <code>int</code> <p>Number of snapshots to skip.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of snapshots to return.</p> <code>DEFAULT_LIMIT</code> <p>Returns:</p> Type Description <code>List[ReportSnapshotDocument]</code> <p>List[ReportSnapshotDocument]: Snapshots ordered by creation time, newest first.</p>"},{"location":"domain/report/ports/service/#domain.report.ports.service-functions","title":"Functions","text":""},{"location":"domain/report/ports/service/#domain.report.ports.service.get_report_service","title":"get_report_service","text":"<pre><code>get_report_service(\n expense_svc, tag_svc, store, report_repo=None\n) -&gt; ReportService\n</code></pre> <p>Build a report service with the given dependencies.</p> <p>Parameters:</p> Name Type Description Default <code>expense_svc</code> <code>Any</code> <p>Expense CRUD service used as the cube source.</p> required <code>tag_svc</code> <code>Any</code> <p>Tag CRUD service used to expand tag hierarchies.</p> required <code>store</code> <code>Any</code> <p>Report store backing cube data.</p> required <code>report_repo</code> <code>Any</code> <p>Report snapshot repository; defaults to :func:<code>create_report_repo</code> when omitted.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>ReportService</code> <code>ReportService</code> <p>Ready-to-use report service.</p>"},{"location":"domain/report/ports/service/#domain.report.ports.service.query_signature","title":"query_signature","text":"<pre><code>query_signature(query: ReportQuery) -&gt; str\n</code></pre> <p>Canonical fingerprint of a snapshot definition (list order-insensitive).</p> <p>Parameters:</p> Name Type Description Default <code>query</code> <code>ReportQuery</code> <p>Snapshot definition to fingerprint.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>SHA-256 hex digest of the normalized definition.</p>"},{"location":"domain/report/ports/store/","title":"Store","text":""},{"location":"domain/report/ports/store/#domain.report.ports.store","title":"domain.report.ports.store","text":""},{"location":"domain/report/ports/store/#domain.report.ports.store--summary","title":"Summary","text":"<p>Sparse key-value store that backs precomputed report cubes outside Mongo.</p> <p>Implementations should map each method onto a persistent backend (e.g. Redis); every method below raises <code>NotImplementedError</code> in the base class until overridden.</p>"},{"location":"domain/report/ports/store/#domain.report.ports.store-classes","title":"Classes","text":""},{"location":"domain/report/ports/store/#domain.report.ports.store.ReportStore","title":"ReportStore","text":"<p>String key-value store used to persist report cube data.</p> <p>Methods are asynchronous; all raise <code>NotImplementedError</code> in this base class and are expected to be overridden by concrete backends.</p>"},{"location":"domain/report/ports/store/#domain.report.ports.store.ReportStore-functions","title":"Functions","text":""},{"location":"domain/report/ports/store/#domain.report.ports.store.ReportStore.clear","title":"clear <code>async</code>","text":"<pre><code>clear() -&gt; None\n</code></pre> <p>Remove every entry this store holds.</p> <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>Base class contract.</p>"},{"location":"domain/report/ports/store/#domain.report.ports.store.ReportStore.close","title":"close <code>async</code>","text":"<pre><code>close() -&gt; None\n</code></pre> <p>Release any resources held by the store.</p> <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>Base class contract.</p>"},{"location":"domain/report/ports/store/#domain.report.ports.store.ReportStore.delete","title":"delete <code>async</code>","text":"<pre><code>delete(key: str) -&gt; None\n</code></pre> <p>Remove the entry stored under <code>key</code>.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Storage key to remove.</p> required <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>Base class contract.</p>"},{"location":"domain/report/ports/store/#domain.report.ports.store.ReportStore.get","title":"get <code>async</code>","text":"<pre><code>get(key: str) -&gt; Optional[str]\n</code></pre> <p>Return the value stored under <code>key</code>, or <code>None</code> when absent.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Storage key.</p> required <p>Returns:</p> Type Description <code>Optional[str]</code> <p>Optional[str]: Stored value, or <code>None</code>.</p> <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>Base class contract.</p>"},{"location":"domain/report/ports/store/#domain.report.ports.store.ReportStore.scan","title":"scan <code>async</code>","text":"<pre><code>scan(pattern: str) -&gt; List[str]\n</code></pre> <p>Return every stored key matching <code>pattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>pattern</code> <code>str</code> <p>Key pattern, e.g. <code>cube:abc:*</code>.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Matching keys.</p> <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>Base class contract.</p>"},{"location":"domain/report/ports/store/#domain.report.ports.store.ReportStore.set","title":"set <code>async</code>","text":"<pre><code>set(key: str, value: str) -&gt; None\n</code></pre> <p>Store <code>value</code> under <code>key</code>, overwriting any existing entry.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Storage key.</p> required <code>value</code> <code>str</code> <p>Value to store.</p> required <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>Base class contract.</p>"},{"location":"domain/tag/","title":"Tag","text":"<ul> <li>Models</li> <li>Ports</li> </ul>"},{"location":"domain/tag/#domain.tag","title":"domain.tag","text":""},{"location":"domain/tag/#domain.tag--summary","title":"Summary","text":"<p>Tag domain: the Tag aggregate, Mongo document schema, enrichment adaptor, and CRUD service wiring.</p>"},{"location":"domain/tag/models/","title":"Models","text":""},{"location":"domain/tag/models/#domain.tag.models","title":"domain.tag.models","text":""},{"location":"domain/tag/models/#domain.tag.models--summary","title":"Summary","text":"<p>Define the Tag aggregate model shared by the service and storage layers.</p>"},{"location":"domain/tag/models/#domain.tag.models-classes","title":"Classes","text":""},{"location":"domain/tag/models/#domain.tag.models.Tag","title":"Tag","text":"<p> Bases: <code>BaseModel</code></p> <p>Tag aggregate: a named classification label, optionally nested.</p> <p>Attributes:</p> Name Type Description <code>name</code> <code>str</code> <p>Tag name, e.g. <code>\"food\"</code>.</p> <code>icon</code> <code>str</code> <p>Icon key rendered for the tag.</p> <code>parent_id</code> <code>Optional[str]</code> <p>ID of the parent tag; <code>None</code> for a root tag.</p>"},{"location":"domain/tag/ports/","title":"Ports","text":"<ul> <li>Db</li> <li>Enrichment</li> <li>Service</li> </ul>"},{"location":"domain/tag/ports/#domain.tag.ports","title":"domain.tag.ports","text":""},{"location":"domain/tag/ports/#domain.tag.ports--summary","title":"Summary","text":"<p>Port wiring for the tag aggregate: Mongo repository, enrichment adaptor, and CRUD service wiring.</p>"},{"location":"domain/tag/ports/db/","title":"Db","text":""},{"location":"domain/tag/ports/db/#domain.tag.ports.db","title":"domain.tag.ports.db","text":""},{"location":"domain/tag/ports/db/#domain.tag.ports.db--summary","title":"Summary","text":"<p>Mongo persistence for tags: document schema with an in-memory cache.</p>"},{"location":"domain/tag/ports/db/#domain.tag.ports.db-classes","title":"Classes","text":""},{"location":"domain/tag/ports/db/#domain.tag.ports.db.TagDocument","title":"TagDocument","text":"<p> Bases: <code>Tag</code>, <code>BaseDocument</code></p> <p>Mongo document form of :class:<code>Tag</code> read through an in-memory cache.</p>"},{"location":"domain/tag/ports/db/#domain.tag.ports.db-functions","title":"Functions","text":""},{"location":"domain/tag/ports/db/#domain.tag.ports.db.create_tag_repo","title":"create_tag_repo","text":"<pre><code>create_tag_repo()\n</code></pre> <p>Create a Mongo-backed tag repository with an in-memory cache.</p> <p>Returns:</p> Name Type Description <code>Any</code> <p>Mongo-backed tag repository using an in-memory cache backend.</p>"},{"location":"domain/tag/ports/enrichment/","title":"Enrichment","text":""},{"location":"domain/tag/ports/enrichment/#domain.tag.ports.enrichment","title":"domain.tag.ports.enrichment","text":""},{"location":"domain/tag/ports/enrichment/#domain.tag.ports.enrichment--summary","title":"Summary","text":"<p>Tag enrichment port: expose the shared tag enrichment pipeline as an async callable.</p>"},{"location":"domain/tag/ports/enrichment/#domain.tag.ports.enrichment-classes","title":"Classes","text":""},{"location":"domain/tag/ports/enrichment/#domain.tag.ports.enrichment.TagEnrichmentAdaptor","title":"TagEnrichmentAdaptor","text":"<pre><code>TagEnrichmentAdaptor(**kwargs)\n</code></pre> <p>Adaptor exposing the tag enrichment pipeline as an async callable.</p> <p>Initialize the adaptor with the shared tags pipeline.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <code>dict</code> <p>Ignored; kept for dependency-injection compatibility.</p> <code>{}</code>"},{"location":"domain/tag/ports/enrichment/#domain.tag.ports.enrichment.TagEnrichmentAdaptor-functions","title":"Functions","text":""},{"location":"domain/tag/ports/enrichment/#domain.tag.ports.enrichment.TagEnrichmentAdaptor.__call__","title":"__call__ <code>async</code>","text":"<pre><code>__call__(payload: dict) -&gt; dict\n</code></pre> <p>Run the tag enrichment pipeline on <code>payload</code>.</p> <p>Defaults the <code>tags</code> key to <code>[\"misc\"]</code> when the pipeline produces nothing.</p> <p>Parameters:</p> Name Type Description Default <code>payload</code> <code>dict</code> <p>Enrichment input, e.g. expense text and hints.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Enriched payload whose <code>tags</code> list is always non-empty.</p>"},{"location":"domain/tag/ports/enrichment/#domain.tag.ports.enrichment-functions","title":"Functions","text":""},{"location":"domain/tag/ports/enrichment/#domain.tag.ports.enrichment.get_tag_enrichment_svc","title":"get_tag_enrichment_svc","text":"<pre><code>get_tag_enrichment_svc(**kwargs) -&gt; TagEnrichmentAdaptor\n</code></pre> <p>Build a tag enrichment service adaptor.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <code>dict</code> <p>Passed through to the adaptor constructor.</p> <code>{}</code> <p>Returns:</p> Name Type Description <code>TagEnrichmentAdaptor</code> <code>TagEnrichmentAdaptor</code> <p>Ready-to-use tag enrichment adaptor.</p>"},{"location":"domain/tag/ports/service/","title":"Service","text":""},{"location":"domain/tag/ports/service/#domain.tag.ports.service","title":"domain.tag.ports.service","text":""},{"location":"domain/tag/ports/service/#domain.tag.ports.service--summary","title":"Summary","text":"<p>CRUD service wiring for the tag aggregate via the hexa container.</p>"},{"location":"domain/tag/ports/service/#domain.tag.ports.service-classes","title":"Classes","text":""},{"location":"domain/tag/ports/service/#domain.tag.ports.service.TagCrudsService","title":"TagCrudsService","text":"<p> Bases: <code>CrudsServiceAdaptor[Tag, TagDocument]</code></p> <p>Tag CRUD service resolving :class:<code>Tag</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_tag_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type. An additional lookup helper <code>get_by_names</code> is provided.</p>"},{"location":"domain/tag/ports/service/#domain.tag.ports.service.TagCrudsService-functions","title":"Functions","text":""},{"location":"domain/tag/ports/service/#domain.tag.ports.service.TagCrudsService.get_by_names","title":"get_by_names <code>async</code>","text":"<pre><code>get_by_names(names: list[str])\n</code></pre> <p>Return tags whose names match any of the provided values.</p> <p>Parameters:</p> Name Type Description Default <code>names</code> <code>list[str]</code> <p>Tag names to look up.</p> required <p>Returns:</p> Name Type Description <code>list</code> <p>Matching tag documents.</p>"},{"location":"domain/tag/ports/service/#domain.tag.ports.service-functions","title":"Functions","text":""},{"location":"domain/tag/ports/service/#domain.tag.ports.service.get_tag_service","title":"get_tag_service","text":"<pre><code>get_tag_service(repo) -&gt; TagCrudsService\n</code></pre> <p>Build a tag CRUD service wired to <code>repo</code>.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>Any</code> <p>Mongo-backed tag repository from :func:<code>create_tag_repo</code>.</p> required <p>Returns:</p> Name Type Description <code>TagCrudsService</code> <code>TagCrudsService</code> <p>Ready-to-use tag CRUD service.</p>"},{"location":"domain/upload/","title":"Upload","text":"<ul> <li>Models</li> <li>Ports</li> </ul>"},{"location":"domain/upload/#domain.upload","title":"domain.upload","text":""},{"location":"domain/upload/#domain.upload--summary","title":"Summary","text":"<p>Upload domain: the UploadResult model, Mongo document schema, and CRUD service wiring.</p>"},{"location":"domain/upload/models/","title":"Models","text":""},{"location":"domain/upload/models/#domain.upload.models","title":"domain.upload.models","text":""},{"location":"domain/upload/models/#domain.upload.models--summary","title":"Summary","text":"<p>Define the UploadResult model returned after storing an uploaded file.</p>"},{"location":"domain/upload/models/#domain.upload.models-classes","title":"Classes","text":""},{"location":"domain/upload/models/#domain.upload.models.UploadResult","title":"UploadResult","text":"<p> Bases: <code>BaseModel</code></p> <p>Metadata describing a stored file upload.</p> <p>Attributes:</p> Name Type Description <code>original_filename</code> <code>str</code> <p>Name of the file as uploaded by the client.</p> <code>saved_as</code> <code>str</code> <p>Name the file was stored under on disk.</p> <code>content_type</code> <code>str</code> <p>MIME type of the uploaded file.</p> <code>url</code> <code>str</code> <p>Public URL serving the stored file.</p> <code>absolute_path</code> <code>str</code> <p>Absolute filesystem path of the stored file.</p>"},{"location":"domain/upload/ports/","title":"Ports","text":"<ul> <li>Db</li> <li>Service</li> </ul>"},{"location":"domain/upload/ports/#domain.upload.ports","title":"domain.upload.ports","text":""},{"location":"domain/upload/ports/#domain.upload.ports--summary","title":"Summary","text":"<p>Port wiring for uploads: Mongo repository and CRUD service wiring.</p>"},{"location":"domain/upload/ports/db/","title":"Db","text":""},{"location":"domain/upload/ports/db/#domain.upload.ports.db","title":"domain.upload.ports.db","text":""},{"location":"domain/upload/ports/db/#domain.upload.ports.db--summary","title":"Summary","text":"<p>Mongo persistence for upload results: document schema and repository factory.</p>"},{"location":"domain/upload/ports/db/#domain.upload.ports.db-classes","title":"Classes","text":""},{"location":"domain/upload/ports/db/#domain.upload.ports.db.UploadResultDocument","title":"UploadResultDocument","text":"<p> Bases: <code>UploadResult</code>, <code>BaseDocument</code></p> <p>Mongo document form of :class:<code>UploadResult</code>.</p>"},{"location":"domain/upload/ports/db/#domain.upload.ports.db-functions","title":"Functions","text":""},{"location":"domain/upload/ports/db/#domain.upload.ports.db.create_upload_repo","title":"create_upload_repo","text":"<pre><code>create_upload_repo()\n</code></pre> <p>Create a Mongo-backed upload result repository.</p> <p>Returns:</p> Name Type Description <code>Any</code> <p>Mongo-backed upload result repository.</p>"},{"location":"domain/upload/ports/service/","title":"Service","text":""},{"location":"domain/upload/ports/service/#domain.upload.ports.service","title":"domain.upload.ports.service","text":""},{"location":"domain/upload/ports/service/#domain.upload.ports.service--summary","title":"Summary","text":"<p>CRUD service wiring for upload results via the hexa container.</p>"},{"location":"domain/upload/ports/service/#domain.upload.ports.service-classes","title":"Classes","text":""},{"location":"domain/upload/ports/service/#domain.upload.ports.service.UploadCrudsService","title":"UploadCrudsService","text":"<p> Bases: <code>CrudsServiceAdaptor[UploadResult, UploadResultDocument]</code></p> <p>Upload result CRUD service resolving :class:<code>UploadResult</code> documents.</p> Notes <p>Instances are created by :func:<code>get_upload_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p>"},{"location":"domain/upload/ports/service/#domain.upload.ports.service-functions","title":"Functions","text":""},{"location":"domain/upload/ports/service/#domain.upload.ports.service.get_upload_service","title":"get_upload_service","text":"<pre><code>get_upload_service(repo) -&gt; UploadCrudsService\n</code></pre> <p>Build an upload result CRUD service wired to <code>repo</code>.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>Any</code> <p>Mongo-backed upload repository from :func:<code>create_upload_repo</code>.</p> required <p>Returns:</p> Name Type Description <code>UploadCrudsService</code> <code>UploadCrudsService</code> <p>Ready-to-use upload result CRUD service.</p>"},{"location":"domain/user/","title":"User","text":"<ul> <li>Models</li> <li>Ports</li> </ul>"},{"location":"domain/user/#domain.user","title":"domain.user","text":""},{"location":"domain/user/#domain.user--summary","title":"Summary","text":"<p>User domain: the User aggregate, Mongo document schema, and CRUD service wiring.</p>"},{"location":"domain/user/models/","title":"Models","text":""},{"location":"domain/user/models/#domain.user.models","title":"domain.user.models","text":""},{"location":"domain/user/models/#domain.user.models--summary","title":"Summary","text":"<p>Define the User aggregate model shared by the service and storage layers.</p>"},{"location":"domain/user/models/#domain.user.models-classes","title":"Classes","text":""},{"location":"domain/user/models/#domain.user.models.User","title":"User","text":"<p> Bases: <code>BaseModel</code></p> <p>User aggregate: identity information for an account owner.</p> <p>Attributes:</p> Name Type Description <code>name</code> <code>str</code> <p>Display name of the user; empty when unknown.</p> <code>username</code> <code>str</code> <p>Unique username of the user.</p> <code>email</code> <code>str</code> <p>Email address of the user.</p>"},{"location":"domain/user/ports/","title":"Ports","text":"<ul> <li>Db</li> <li>Service</li> </ul>"},{"location":"domain/user/ports/#domain.user.ports","title":"domain.user.ports","text":""},{"location":"domain/user/ports/#domain.user.ports--summary","title":"Summary","text":"<p>Port wiring for the user aggregate: Mongo repository and CRUD service wiring.</p>"},{"location":"domain/user/ports/db/","title":"Db","text":""},{"location":"domain/user/ports/db/#domain.user.ports.db","title":"domain.user.ports.db","text":""},{"location":"domain/user/ports/db/#domain.user.ports.db--summary","title":"Summary","text":"<p>Mongo persistence for users: document schema and repository factory.</p>"},{"location":"domain/user/ports/db/#domain.user.ports.db-classes","title":"Classes","text":""},{"location":"domain/user/ports/db/#domain.user.ports.db.UserDocument","title":"UserDocument","text":"<p> Bases: <code>User</code>, <code>BaseDocument</code></p> <p>Mongo document form of :class:<code>User</code>.</p>"},{"location":"domain/user/ports/db/#domain.user.ports.db-functions","title":"Functions","text":""},{"location":"domain/user/ports/db/#domain.user.ports.db.create_user_repo","title":"create_user_repo","text":"<pre><code>create_user_repo()\n</code></pre> <p>Create a Mongo-backed user repository.</p> <p>Returns:</p> Name Type Description <code>Any</code> <p>Mongo-backed user repository.</p>"},{"location":"domain/user/ports/service/","title":"Service","text":""},{"location":"domain/user/ports/service/#domain.user.ports.service","title":"domain.user.ports.service","text":""},{"location":"domain/user/ports/service/#domain.user.ports.service--summary","title":"Summary","text":"<p>CRUD service wiring for the user aggregate via the hexa container.</p>"},{"location":"domain/user/ports/service/#domain.user.ports.service-classes","title":"Classes","text":""},{"location":"domain/user/ports/service/#domain.user.ports.service.UserCrudsService","title":"UserCrudsService","text":"<p> Bases: <code>CrudsServiceAdaptor[User, UserDocument]</code></p> <p>User CRUD service resolving :class:<code>User</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_user_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p>"},{"location":"domain/user/ports/service/#domain.user.ports.service-functions","title":"Functions","text":""},{"location":"domain/user/ports/service/#domain.user.ports.service.get_user_service","title":"get_user_service","text":"<pre><code>get_user_service(repo) -&gt; UserCrudsService\n</code></pre> <p>Build a user CRUD service wired to <code>repo</code>.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>Any</code> <p>Mongo-backed user repository from :func:<code>create_user_repo</code>.</p> required <p>Returns:</p> Name Type Description <code>UserCrudsService</code> <code>UserCrudsService</code> <p>Ready-to-use user CRUD service.</p>"},{"location":"infra/","title":"Infra","text":"<ul> <li>Adapters</li> <li>Db</li> <li>Http Cache</li> <li>Llm</li> </ul>"},{"location":"infra/#infra","title":"infra","text":""},{"location":"infra/#infra--summary","title":"Summary","text":"<p>Infrastructure layer for the Expenses Service.</p> <p>Provide adapters, database repositories, and LLM provider pools that implement the ports declared by the domain layer.</p>"},{"location":"infra/http_cache/","title":"Http Cache","text":""},{"location":"infra/http_cache/#infra.http_cache","title":"infra.http_cache","text":""},{"location":"infra/http_cache/#infra.http_cache--summary","title":"Summary","text":"<p>Domain-agnostic HTTP response cache.</p> <p>A thin Redis-backed response cache that wraps route handlers as a decorator.</p> Example <pre><code>from infra.http_cache import cache_response\n\n@cache_response(ttl=60)\nasync def list_entities(request, skip: int = 0, limit: int = 100):\n ...\n</code></pre> Notes <p>The cache is independent of the report cache (<code>apicache:*</code> vs <code>report:*</code> key namespaces) and of Mongo's cached repositories \u2014 it operates directly on the endpoint. Cached responses expire via TTL (default <code>settings.cache_ttl</code>). When no <code>http_cache_store</code> is wired on <code>request.app.state.db_resources</code> the decorator is a no-op pass-through, so applying/removing it is safe and trivial.</p>"},{"location":"infra/http_cache/#infra.http_cache-classes","title":"Classes","text":""},{"location":"infra/http_cache/#infra.http_cache.HttpCacheStore","title":"HttpCacheStore","text":"<pre><code>HttpCacheStore(\n url: str = \"redis://localhost:6379/0\",\n decode_responses: bool = True,\n)\n</code></pre> <p>Store string responses in Redis with TTL under the <code>apicache:</code> key space.</p> <p>Attributes:</p> Name Type Description <code>_redis</code> <code>Redis</code> <p>Asynchronous Redis client bound to the configured URL.</p> <p>Initialize the store with a Redis connection.</p> <p>Parameters:</p> Name Type Description Default <code>url</code> <code>str</code> <p>Redis connection URL.</p> <code>'redis://localhost:6379/0'</code> <code>decode_responses</code> <code>bool</code> <p>Whether Redis returns decoded strings.</p> <code>True</code>"},{"location":"infra/http_cache/#infra.http_cache.HttpCacheStore-functions","title":"Functions","text":""},{"location":"infra/http_cache/#infra.http_cache.HttpCacheStore.close","title":"close <code>async</code>","text":"<pre><code>close() -&gt; None\n</code></pre> <p>Close the underlying Redis connection.</p>"},{"location":"infra/http_cache/#infra.http_cache.HttpCacheStore.delete","title":"delete <code>async</code>","text":"<pre><code>delete(key: str) -&gt; None\n</code></pre> <p>Delete the value stored at <code>key</code>.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Cache key to remove.</p> required"},{"location":"infra/http_cache/#infra.http_cache.HttpCacheStore.generation","title":"generation <code>async</code>","text":"<pre><code>generation(resource: str) -&gt; str\n</code></pre> <p>Return the current generation counter for a resource namespace.</p> <p>Parameters:</p> Name Type Description Default <code>resource</code> <code>str</code> <p>Resource namespace to read.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generation counter, or <code>\"0\"</code> when unset.</p>"},{"location":"infra/http_cache/#infra.http_cache.HttpCacheStore.get","title":"get <code>async</code>","text":"<pre><code>get(key: str) -&gt; Optional[str]\n</code></pre> <p>Read the value stored at <code>key</code>.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Cache key to read.</p> required <p>Returns:</p> Type Description <code>Optional[str]</code> <p>Optional[str]: Cached value, or <code>None</code> when absent.</p>"},{"location":"infra/http_cache/#infra.http_cache.HttpCacheStore.invalidate","title":"invalidate <code>async</code>","text":"<pre><code>invalidate(*resources: str) -&gt; None\n</code></pre> <p>Invalidate all cached responses for the given resource namespaces.</p> <p>Parameters:</p> Name Type Description Default <code>*resources</code> <code>str</code> <p>Resource namespaces to invalidate.</p> <code>()</code> Notes <p>Bumps each namespace's generation counter so existing entries become unreachable immediately; Redis reclaims them at TTL expiry.</p>"},{"location":"infra/http_cache/#infra.http_cache.HttpCacheStore.set","title":"set <code>async</code>","text":"<pre><code>set(key: str, value: str, ttl: int) -&gt; None\n</code></pre> <p>Store <code>value</code> at <code>key</code> with a TTL.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Cache key to write.</p> required <code>value</code> <code>str</code> <p>Serialized value to persist.</p> required <code>ttl</code> <code>int</code> <p>Lifetime in seconds.</p> required"},{"location":"infra/http_cache/#infra.http_cache-functions","title":"Functions","text":""},{"location":"infra/http_cache/#infra.http_cache.cache_response","title":"cache_response","text":"<pre><code>cache_response(ttl: Optional[int] = None) -&gt; Callable\n</code></pre> <p>Decorate a GET-style route handler to cache its JSON response.</p> <p>Parameters:</p> Name Type Description Default <code>ttl</code> <code>Optional[int]</code> <p>Cache lifetime in seconds; defaults to <code>settings.cache_ttl</code>.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>Callable</code> <code>Callable</code> <p>Decorator that wraps the route handler.</p> Notes <p>The wrapped handler must accept a <code>request: Request</code> parameter (as every openapi_first handler does). Responses that are already a <code>fastapi.Response</code> (for example 204) are returned untouched and never cached. When no <code>http_cache_store</code> is wired on <code>request.app.state.db_resources</code> the decorator passes through to the handler without caching.</p>"},{"location":"infra/adapters/","title":"Adapters","text":"<ul> <li>Redis</li> <li>Service</li> <li>Sse</li> </ul>"},{"location":"infra/adapters/#infra.adapters","title":"infra.adapters","text":""},{"location":"infra/adapters/#infra.adapters--summary","title":"Summary","text":"<p>Infrastructure adapters for the Expenses Service.</p> <p>Group concrete adapter implementations for report storage, CRUD services, and in-memory SSE event publication.</p>"},{"location":"infra/adapters/redis/","title":"Redis","text":""},{"location":"infra/adapters/redis/#infra.adapters.redis","title":"infra.adapters.redis","text":""},{"location":"infra/adapters/redis/#infra.adapters.redis--summary","title":"Summary","text":"<p>Redis-backed implementation of the report store port.</p> <p>Persist and scan report payloads in Redis under the <code>report:*</code> key space.</p>"},{"location":"infra/adapters/redis/#infra.adapters.redis-classes","title":"Classes","text":""},{"location":"infra/adapters/redis/#infra.adapters.redis.RedisStoreAdaptor","title":"RedisStoreAdaptor","text":"<pre><code>RedisStoreAdaptor(\n url: str = \"redis://localhost:6379/0\",\n decode_responses: bool = True,\n)\n</code></pre> <p> Bases: <code>ReportStore</code></p> <p>Adapt a Redis client to the report store port.</p> <p>Attributes:</p> Name Type Description <code>_redis</code> <code>Redis</code> <p>Asynchronous Redis client bound to the configured URL.</p> <p>Initialize the adaptor with a Redis connection.</p> <p>Parameters:</p> Name Type Description Default <code>url</code> <code>str</code> <p>Redis connection URL.</p> <code>'redis://localhost:6379/0'</code> <code>decode_responses</code> <code>bool</code> <p>Whether Redis returns decoded strings.</p> <code>True</code>"},{"location":"infra/adapters/redis/#infra.adapters.redis.RedisStoreAdaptor-functions","title":"Functions","text":""},{"location":"infra/adapters/redis/#infra.adapters.redis.RedisStoreAdaptor.clear","title":"clear <code>async</code>","text":"<pre><code>clear() -&gt; None\n</code></pre> <p>Delete every report key from the store.</p> Notes <p>Scans <code>REPORT_PREFIX</code> and removes all matching keys in one call.</p>"},{"location":"infra/adapters/redis/#infra.adapters.redis.RedisStoreAdaptor.close","title":"close <code>async</code>","text":"<pre><code>close() -&gt; None\n</code></pre> <p>Close the underlying Redis connection.</p>"},{"location":"infra/adapters/redis/#infra.adapters.redis.RedisStoreAdaptor.delete","title":"delete <code>async</code>","text":"<pre><code>delete(key: str) -&gt; None\n</code></pre> <p>Delete the value stored at <code>key</code>.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Redis key to remove.</p> required"},{"location":"infra/adapters/redis/#infra.adapters.redis.RedisStoreAdaptor.get","title":"get <code>async</code>","text":"<pre><code>get(key: str) -&gt; Optional[str]\n</code></pre> <p>Read the value stored at <code>key</code>.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Redis key to read.</p> required <p>Returns:</p> Type Description <code>Optional[str]</code> <p>Optional[str]: Stored value, or <code>None</code> when the key is absent.</p>"},{"location":"infra/adapters/redis/#infra.adapters.redis.RedisStoreAdaptor.scan","title":"scan <code>async</code>","text":"<pre><code>scan(pattern: str) -&gt; List[str]\n</code></pre> <p>List keys matching <code>pattern</code>.</p> <p>Parameters:</p> Name Type Description Default <code>pattern</code> <code>str</code> <p>Glob-style key pattern.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Matching keys.</p>"},{"location":"infra/adapters/redis/#infra.adapters.redis.RedisStoreAdaptor.set","title":"set <code>async</code>","text":"<pre><code>set(key: str, value: str) -&gt; None\n</code></pre> <p>Store <code>value</code> at <code>key</code>.</p> <p>Parameters:</p> Name Type Description Default <code>key</code> <code>str</code> <p>Redis key to write.</p> required <code>value</code> <code>str</code> <p>Serialized value to persist.</p> required"},{"location":"infra/adapters/service/","title":"Service","text":""},{"location":"infra/adapters/service/#infra.adapters.service","title":"infra.adapters.service","text":""},{"location":"infra/adapters/service/#infra.adapters.service--summary","title":"Summary","text":"<p>Generic CRUD service adaptor over a Mongo repository.</p> <p>Bridge pydantic models and mongo-ops documents, exposing create, read, update, patch, delete, and search operations for every domain that needs them.</p>"},{"location":"infra/adapters/service/#infra.adapters.service-classes","title":"Classes","text":""},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor","title":"CrudsServiceAdaptor","text":"<pre><code>CrudsServiceAdaptor(*, repo=None)\n</code></pre> <p> Bases: <code>Generic[Model, Schema]</code></p> <p>Adapt a generic Mongo repository to a model/schema CRUD service.</p> <p>Attributes:</p> Name Type Description <code>repo</code> <code>BaseRepository</code> <p>Repository backing all CRUD operations.</p> <code>model</code> <code>Type[Model]</code> <p>Pydantic model type handled by this service.</p> <code>schema</code> <code>Type[Schema]</code> <p>Document schema type persisted by the repository.</p> <p>Initialize the adaptor with a backing repository.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>BaseRepository</code> <p>Repository used for all operations.</p> <code>None</code>"},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor-functions","title":"Functions","text":""},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor.create","title":"create <code>async</code>","text":"<pre><code>create(data: Model | dict) -&gt; Schema\n</code></pre> <p>Create a document from a model or raw mapping.</p> <p>Parameters:</p> Name Type Description Default <code>data</code> <code>Model | dict</code> <p>Model instance or field mapping to persist.</p> required <p>Returns:</p> Name Type Description <code>Schema</code> <code>Schema</code> <p>Persisted document.</p>"},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor.delete","title":"delete <code>async</code>","text":"<pre><code>delete(id: PyObjectId) -&gt; bool\n</code></pre> <p>Delete a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was deleted.</p>"},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor.model_to_dict","title":"model_to_dict <code>staticmethod</code>","text":"<pre><code>model_to_dict(model_obj: Model) -&gt; dict\n</code></pre> <p>Serialize a model into a sparse dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>model_obj</code> <code>Model</code> <p>Model instance to serialize.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Fields that are set and not <code>None</code>.</p>"},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor.patch","title":"patch <code>async</code>","text":"<pre><code>patch(id: PyObjectId, data: dict) -&gt; Schema | None\n</code></pre> <p>Partially update a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>dict</code> <p>Fields to patch.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor.read","title":"read <code>async</code>","text":"<pre><code>read(id: PyObjectId) -&gt; Schema | None\n</code></pre> <p>Read a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Matching document, or <code>None</code> when absent.</p>"},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor.search","title":"search <code>async</code>","text":"<pre><code>search(\n filter: dict | None = None, *args, **kwargs\n) -&gt; list[Schema]\n</code></pre> <p>List documents matching an optional filter.</p> <p>Parameters:</p> Name Type Description Default <code>filter</code> <code>dict | None</code> <p>Query filter passed to the repository.</p> <code>None</code> <p>Returns:</p> Type Description <code>list[Schema]</code> <p>list[Schema]: Matching documents.</p> Notes <p>Extra positional and keyword arguments are forwarded to the repository.</p>"},{"location":"infra/adapters/service/#infra.adapters.service.CrudsServiceAdaptor.update","title":"update <code>async</code>","text":"<pre><code>update(id: PyObjectId, data: Model | dict) -&gt; Schema | None\n</code></pre> <p>Replace a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>Model | dict</code> <p>Replacement model or field mapping.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"infra/adapters/sse/","title":"Sse","text":""},{"location":"infra/adapters/sse/#infra.adapters.sse","title":"infra.adapters.sse","text":""},{"location":"infra/adapters/sse/#infra.adapters.sse--summary","title":"Summary","text":"<p>SSEInMemoryBus \u2014 in-memory event bus for SSE progress events.</p> <p>Buffer published progress events so they can be replayed per fetch request.</p>"},{"location":"infra/adapters/sse/#infra.adapters.sse-classes","title":"Classes","text":""},{"location":"infra/adapters/sse/#infra.adapters.sse.SSEInMemoryBus","title":"SSEInMemoryBus","text":"<pre><code>SSEInMemoryBus()\n</code></pre> <p> Bases: <code>Generic[T]</code></p> <p>Buffer SSE progress events in memory.</p> <p>Attributes:</p> Name Type Description <code>_events</code> <code>List[T]</code> <p>Events published since the last clear.</p> <p>Initialize an empty event buffer.</p>"},{"location":"infra/adapters/sse/#infra.adapters.sse.SSEInMemoryBus-functions","title":"Functions","text":""},{"location":"infra/adapters/sse/#infra.adapters.sse.SSEInMemoryBus.clear","title":"clear","text":"<pre><code>clear() -&gt; None\n</code></pre> <p>Remove all buffered events.</p>"},{"location":"infra/adapters/sse/#infra.adapters.sse.SSEInMemoryBus.get_events","title":"get_events","text":"<pre><code>get_events(fr_id: str) -&gt; List[T]\n</code></pre> <p>Return buffered events for a fetch request.</p> <p>Parameters:</p> Name Type Description Default <code>fr_id</code> <code>str</code> <p>Fetch request identifier to filter by.</p> required <p>Returns:</p> Type Description <code>List[T]</code> <p>List[T]: Events whose <code>fetch_request_id</code> equals <code>fr_id</code>.</p>"},{"location":"infra/adapters/sse/#infra.adapters.sse.SSEInMemoryBus.publish","title":"publish <code>async</code>","text":"<pre><code>publish(event: T) -&gt; None\n</code></pre> <p>Append an event to the buffer.</p> <p>Parameters:</p> Name Type Description Default <code>event</code> <code>T</code> <p>Event to append.</p> required"},{"location":"infra/db/","title":"Db","text":"<ul> <li>Repos</li> <li>Setup</li> </ul>"},{"location":"infra/db/#infra.db","title":"infra.db","text":""},{"location":"infra/db/#infra.db--summary","title":"Summary","text":"<p>Database infrastructure for the Expenses Service.</p> <p>Bundle connection setup and generic repository factories used by the infrastructure adapters.</p>"},{"location":"infra/db/setup/","title":"Setup","text":""},{"location":"infra/db/setup/#infra.db.setup","title":"infra.db.setup","text":""},{"location":"infra/db/setup/#infra.db.setup--summary","title":"Summary","text":"<p>Database setup \u2014 connection lifecycle only. No domain imports.</p> <p>Connect and disconnect the shared Mongo connection manager at application startup and shutdown.</p>"},{"location":"infra/db/setup/#infra.db.setup-functions","title":"Functions","text":""},{"location":"infra/db/setup/#infra.db.setup.setup_database","title":"setup_database <code>async</code>","text":"<pre><code>setup_database(uri: str, db_name: str)\n</code></pre> <p>Connect the shared Mongo connection manager.</p> <p>Parameters:</p> Name Type Description Default <code>uri</code> <code>str</code> <p>Mongo connection URI.</p> required <code>db_name</code> <code>str</code> <p>Target database name.</p> required"},{"location":"infra/db/setup/#infra.db.setup.shutdown_database","title":"shutdown_database <code>async</code>","text":"<pre><code>shutdown_database()\n</code></pre> <p>Disconnect the shared Mongo connection manager.</p>"},{"location":"infra/db/repos/","title":"Repos","text":"<ul> <li>Mongo</li> <li>Pgsql</li> </ul>"},{"location":"infra/db/repos/#infra.db.repos","title":"infra.db.repos","text":""},{"location":"infra/db/repos/#infra.db.repos--summary","title":"Summary","text":"<p>Generic database repository factories.</p> <p>Expose the MongoDB repository factory and a PostgreSQL placeholder used by domain adapters.</p>"},{"location":"infra/db/repos/mongo/","title":"Mongo","text":""},{"location":"infra/db/repos/mongo/#infra.db.repos.mongo","title":"infra.db.repos.mongo","text":""},{"location":"infra/db/repos/mongo/#infra.db.repos.mongo--summary","title":"Summary","text":"<p>Generic MongoDB CRUD repo \u2014 single implementation for all domains.</p> <p>Select a concrete mongo-ops repository (base, cached, or populating) from the options supplied to the factory.</p>"},{"location":"infra/db/repos/pgsql/","title":"Pgsql","text":""},{"location":"infra/db/repos/pgsql/#infra.db.repos.pgsql","title":"infra.db.repos.pgsql","text":""},{"location":"infra/db/repos/pgsql/#infra.db.repos.pgsql--summary","title":"Summary","text":"<p>Generic PostGres CRUD repo \u2014 single implementation for all domains.</p> <p>Placeholder factory for future PostgreSQL repository support.</p>"},{"location":"infra/llm/","title":"Llm","text":"<ul> <li>Httpx Client</li> <li>Model</li> <li>Pool</li> <li>Providers</li> <li>Setup</li> </ul>"},{"location":"infra/llm/#infra.llm","title":"infra.llm","text":""},{"location":"infra/llm/#infra.llm--summary","title":"Summary","text":"<p>LLM infrastructure for the Expenses Service.</p> <p>Provide HTTP client ports, retry pools, provider configuration, and statement parsing adaptors.</p>"},{"location":"infra/llm/httpx_client/","title":"Httpx Client","text":""},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client","title":"infra.llm.httpx_client","text":""},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client--summary","title":"Summary","text":"<p>HTTP client ports for OpenAI-compatible chat completion endpoints.</p> <p>Provide synchronous and asynchronous httpx wrappers that issue chat completion requests with bearer authentication.</p>"},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client-classes","title":"Classes","text":""},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client.AsyncClientPort","title":"AsyncClientPort","text":"<pre><code>AsyncClientPort(\n api_key: str = \"\",\n endpoint: str = \"\",\n timeout: float = 60.0,\n)\n</code></pre> <p>Asynchronous httpx client for chat completion APIs.</p> <p>Attributes:</p> Name Type Description <code>api_key</code> <code>str</code> <p>Bearer token used for authentication.</p> <code>endpoint</code> <code>str</code> <p>Base URL of the completions API.</p> <code>timeout</code> <code>float</code> <p>Request timeout in seconds.</p> <code>_http_client</code> <code>AsyncClient</code> <p>Underlying asynchronous HTTP client.</p> <p>Initialize the asynchronous client.</p> <p>Parameters:</p> Name Type Description Default <code>api_key</code> <code>str</code> <p>Bearer token used for authentication.</p> <code>''</code> <code>endpoint</code> <code>str</code> <p>Base URL of the completions API.</p> <code>''</code> <code>timeout</code> <code>float</code> <p>Request timeout in seconds.</p> <code>60.0</code>"},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client.AsyncClientPort-functions","title":"Functions","text":""},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client.AsyncClientPort.aclose","title":"aclose <code>async</code>","text":"<pre><code>aclose()\n</code></pre> <p>Close the underlying asynchronous HTTP client.</p>"},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client.AsyncClientPort.chat_completion","title":"chat_completion <code>async</code>","text":"<pre><code>chat_completion(\n model: str,\n messages: list,\n temperature: float = 0.0,\n max_tokens: int = 4096,\n) -&gt; dict\n</code></pre> <p>Send an asynchronous chat completion request.</p> <p>Parameters:</p> Name Type Description Default <code>model</code> <code>str</code> <p>Model identifier to invoke.</p> required <code>messages</code> <code>list</code> <p>Chat messages in API format.</p> required <code>temperature</code> <code>float</code> <p>Sampling temperature.</p> <code>0.0</code> <code>max_tokens</code> <code>int</code> <p>Maximum tokens to generate.</p> <code>4096</code> <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Decoded JSON response body.</p>"},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client.SyncClientPort","title":"SyncClientPort","text":"<pre><code>SyncClientPort(\n api_key: str = \"\",\n endpoint: str = \"\",\n timeout: float = 60.0,\n)\n</code></pre> <p>Synchronous httpx client for chat completion APIs.</p> <p>Attributes:</p> Name Type Description <code>api_key</code> <code>str</code> <p>Bearer token used for authentication.</p> <code>endpoint</code> <code>str</code> <p>Base URL of the completions API.</p> <code>timeout</code> <code>float</code> <p>Request timeout in seconds.</p> <code>_client</code> <code>Client</code> <p>Underlying synchronous HTTP client.</p> <p>Initialize the synchronous client.</p> <p>Parameters:</p> Name Type Description Default <code>api_key</code> <code>str</code> <p>Bearer token used for authentication.</p> <code>''</code> <code>endpoint</code> <code>str</code> <p>Base URL of the completions API.</p> <code>''</code> <code>timeout</code> <code>float</code> <p>Request timeout in seconds.</p> <code>60.0</code>"},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client.SyncClientPort-functions","title":"Functions","text":""},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client.SyncClientPort.chat_completion","title":"chat_completion","text":"<pre><code>chat_completion(\n model: str,\n messages: list,\n temperature: float = 0.0,\n max_tokens: int = 4096,\n) -&gt; dict\n</code></pre> <p>Send a chat completion request.</p> <p>Parameters:</p> Name Type Description Default <code>model</code> <code>str</code> <p>Model identifier to invoke.</p> required <code>messages</code> <code>list</code> <p>Chat messages in API format.</p> required <code>temperature</code> <code>float</code> <p>Sampling temperature.</p> <code>0.0</code> <code>max_tokens</code> <code>int</code> <p>Maximum tokens to generate.</p> <code>4096</code> <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Decoded JSON response body.</p>"},{"location":"infra/llm/httpx_client/#infra.llm.httpx_client.SyncClientPort.close","title":"close","text":"<pre><code>close()\n</code></pre> <p>Close the underlying HTTP client.</p>"},{"location":"infra/llm/model/","title":"Model","text":""},{"location":"infra/llm/model/#infra.llm.model","title":"infra.llm.model","text":""},{"location":"infra/llm/model/#infra.llm.model--summary","title":"Summary","text":"<p>Dataclass describing an LLM model and its retry policy.</p> <p>Carry the model identifier, provider name, and the retry, rate-limit, token, and timeout settings used by the pool retry loop.</p>"},{"location":"infra/llm/model/#infra.llm.model-classes","title":"Classes","text":""},{"location":"infra/llm/model/#infra.llm.model.ModelPort","title":"ModelPort <code>dataclass</code>","text":"<pre><code>ModelPort(\n name: str,\n provider: str,\n max_retries: int = 3,\n retry_delay: float = 2.0,\n rate_limit_delay: float = 1.0,\n max_tokens: int = 4096,\n timeout: float = 120.0,\n)\n</code></pre> <p>Describe an LLM model and its request policy.</p> <p>Attributes:</p> Name Type Description <code>name</code> <code>str</code> <p>Provider-specific model identifier.</p> <code>provider</code> <code>str</code> <p>Provider key (for example <code>groq</code>).</p> <code>max_retries</code> <code>int</code> <p>Number of retry attempts per request.</p> <code>retry_delay</code> <code>float</code> <p>Seconds to wait between attempts.</p> <code>rate_limit_delay</code> <code>float</code> <p>Seconds to wait before each call.</p> <code>max_tokens</code> <code>int</code> <p>Maximum tokens to request from the model.</p> <code>timeout</code> <code>float</code> <p>Request timeout in seconds.</p>"},{"location":"infra/llm/pool/","title":"Pool","text":""},{"location":"infra/llm/pool/#infra.llm.pool","title":"infra.llm.pool","text":""},{"location":"infra/llm/pool/#infra.llm.pool--summary","title":"Summary","text":"<p>LLM pool adaptors with retry, rotation, and HTTP error handling.</p> <p>Rotate through configured model ports, retrying failed chat completions and translating provider errors into <code>RuntimeError</code> failures.</p>"},{"location":"infra/llm/pool/#infra.llm.pool-classes","title":"Classes","text":""},{"location":"infra/llm/pool/#infra.llm.pool.AsyncPoolAdaptor","title":"AsyncPoolAdaptor","text":"<pre><code>AsyncPoolAdaptor(**kwargs)\n</code></pre> <p>Asynchronous LLM pool with model rotation.</p> <p>Attributes:</p> Name Type Description <code>httpx_client</code> <code>AsyncClientPort</code> <p>Client used for requests.</p> <code>models</code> <code>list</code> <p>Model ports available for rotation.</p> <p>Initialize the pool from keyword configuration.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Configuration; <code>httpx_client</code> and <code>models</code> are consumed, remaining keys become instance attributes.</p> <code>{}</code>"},{"location":"infra/llm/pool/#infra.llm.pool.AsyncPoolAdaptor-functions","title":"Functions","text":""},{"location":"infra/llm/pool/#infra.llm.pool.AsyncPoolAdaptor.aclose","title":"aclose <code>async</code>","text":"<pre><code>aclose()\n</code></pre> <p>Close the underlying asynchronous HTTP client.</p>"},{"location":"infra/llm/pool/#infra.llm.pool.AsyncPoolAdaptor.generate","title":"generate <code>async</code>","text":"<pre><code>generate(\n prompt: str,\n system_prompt: Optional[str] = None,\n max_tokens: Optional[int] = None,\n models: Optional[list] = None,\n) -&gt; str\n</code></pre> <p>Generate text for a prompt asynchronously.</p> <p>Parameters:</p> Name Type Description Default <code>prompt</code> <code>str</code> <p>User prompt text.</p> required <code>system_prompt</code> <code>Optional[str]</code> <p>Optional system instruction.</p> <code>None</code> <code>max_tokens</code> <code>Optional[int]</code> <p>Token cap overriding model defaults.</p> <code>None</code> <code>models</code> <code>Optional[list]</code> <p>Model ports overriding the pool defaults.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generated content.</p>"},{"location":"infra/llm/pool/#infra.llm.pool.PoolAdaptor","title":"PoolAdaptor","text":"<pre><code>PoolAdaptor(**kwargs)\n</code></pre> <p>Synchronous LLM pool with model rotation.</p> <p>Attributes:</p> Name Type Description <code>httpx_client</code> <code>SyncClientPort</code> <p>Client used for requests.</p> <code>models</code> <code>list</code> <p>Model ports available for rotation.</p> <p>Initialize the pool from keyword configuration.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Configuration; <code>httpx_client</code> and <code>models</code> are consumed, remaining keys become instance attributes.</p> <code>{}</code>"},{"location":"infra/llm/pool/#infra.llm.pool.PoolAdaptor-functions","title":"Functions","text":""},{"location":"infra/llm/pool/#infra.llm.pool.PoolAdaptor.close","title":"close","text":"<pre><code>close()\n</code></pre> <p>Close the underlying HTTP client.</p>"},{"location":"infra/llm/pool/#infra.llm.pool.PoolAdaptor.generate","title":"generate","text":"<pre><code>generate(\n prompt: str,\n system_prompt: Optional[str] = None,\n max_tokens: Optional[int] = None,\n models: Optional[list] = None,\n) -&gt; str\n</code></pre> <p>Generate text for a prompt.</p> <p>Parameters:</p> Name Type Description Default <code>prompt</code> <code>str</code> <p>User prompt text.</p> required <code>system_prompt</code> <code>Optional[str]</code> <p>Optional system instruction.</p> <code>None</code> <code>max_tokens</code> <code>Optional[int]</code> <p>Token cap overriding model defaults.</p> <code>None</code> <code>models</code> <code>Optional[list]</code> <p>Model ports overriding the pool defaults.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generated content.</p>"},{"location":"infra/llm/setup/","title":"Setup","text":""},{"location":"infra/llm/setup/#infra.llm.setup","title":"infra.llm.setup","text":""},{"location":"infra/llm/setup/#infra.llm.setup--summary","title":"Summary","text":"<p>LLM pool factories resolved from configuration.</p> <p>Import and instantiate the provider-specific synchronous or asynchronous pool selected by the <code>LLM_PROVIDER</code> environment variable.</p>"},{"location":"infra/llm/setup/#infra.llm.setup-classes","title":"Classes","text":""},{"location":"infra/llm/setup/#infra.llm.setup-functions","title":"Functions","text":""},{"location":"infra/llm/setup/#infra.llm.setup.setup_async_pool","title":"setup_async_pool","text":"<pre><code>setup_async_pool(provider: str = None) -&gt; AsyncPoolAdaptor\n</code></pre> <p>Build an asynchronous pool for the selected provider.</p> <p>Parameters:</p> Name Type Description Default <code>provider</code> <code>str</code> <p>Provider key; defaults to <code>LLM_PROVIDER</code> or <code>open_router</code>.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>AsyncPoolAdaptor</code> <code>AsyncPoolAdaptor</code> <p>Configured asynchronous pool.</p>"},{"location":"infra/llm/setup/#infra.llm.setup.setup_sync_pool","title":"setup_sync_pool","text":"<pre><code>setup_sync_pool(provider: str = None) -&gt; PoolAdaptor\n</code></pre> <p>Build a synchronous pool for the selected provider.</p> <p>Parameters:</p> Name Type Description Default <code>provider</code> <code>str</code> <p>Provider key; defaults to <code>LLM_PROVIDER</code> or <code>open_router</code>.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>PoolAdaptor</code> <code>PoolAdaptor</code> <p>Configured synchronous pool.</p>"},{"location":"infra/llm/providers/","title":"Providers","text":"<ul> <li>Groq</li> <li>Llama Parser</li> <li>Open Ai</li> <li>Open Router</li> </ul>"},{"location":"infra/llm/providers/#infra.llm.providers","title":"infra.llm.providers","text":""},{"location":"infra/llm/providers/#infra.llm.providers--summary","title":"Summary","text":"<p>LLM provider integrations.</p> <p>Namespace for provider-specific configuration, model ports, and pool adaptors.</p>"},{"location":"infra/llm/providers/groq/","title":"Groq","text":"<ul> <li>Config</li> <li>Models</li> <li>Pool</li> </ul>"},{"location":"infra/llm/providers/groq/#infra.llm.providers.groq","title":"infra.llm.providers.groq","text":""},{"location":"infra/llm/providers/groq/#infra.llm.providers.groq--summary","title":"Summary","text":"<p>Groq LLM provider integration.</p> <p>Expose Groq configuration, model ports, and synchronous/asynchronous pools.</p>"},{"location":"infra/llm/providers/groq/config/","title":"Config","text":""},{"location":"infra/llm/providers/groq/config/#infra.llm.providers.groq.config","title":"infra.llm.providers.groq.config","text":""},{"location":"infra/llm/providers/groq/config/#infra.llm.providers.groq.config--summary","title":"Summary","text":"<p>Groq provider configuration loaded from the environment.</p> <p>Read the Groq API key and endpoint used by the Groq pool adaptors.</p>"},{"location":"infra/llm/providers/groq/config/#infra.llm.providers.groq.config-classes","title":"Classes","text":""},{"location":"infra/llm/providers/groq/config/#infra.llm.providers.groq.config.GroqConfig","title":"GroqConfig","text":"<pre><code>GroqConfig()\n</code></pre> <p>Hold Groq provider credentials and endpoint.</p> <p>Attributes:</p> Name Type Description <code>api_key</code> <code>str</code> <p>Groq API key from <code>GROQ_API_KEY</code> or <code>LLM_API_KEY</code>.</p> <code>endpoint</code> <code>str</code> <p>Groq API base URL.</p> <p>Load Groq configuration from environment variables.</p>"},{"location":"infra/llm/providers/groq/config/#infra.llm.providers.groq.config.GroqConfig-functions","title":"Functions","text":""},{"location":"infra/llm/providers/groq/models/","title":"Models","text":""},{"location":"infra/llm/providers/groq/models/#infra.llm.providers.groq.models","title":"infra.llm.providers.groq.models","text":""},{"location":"infra/llm/providers/groq/models/#infra.llm.providers.groq.models--summary","title":"Summary","text":"<p>Groq model port definitions.</p> <p>Expose the default Groq model identifiers used by the Groq pool adaptors.</p>"},{"location":"infra/llm/providers/groq/models/#infra.llm.providers.groq.models-classes","title":"Classes","text":""},{"location":"infra/llm/providers/groq/models/#infra.llm.providers.groq.models-functions","title":"Functions","text":""},{"location":"infra/llm/providers/groq/models/#infra.llm.providers.groq.models.create_model_ports","title":"create_model_ports","text":"<pre><code>create_model_ports()\n</code></pre> <p>Create the default Groq model ports.</p> <p>Returns:</p> Name Type Description <code>list</code> <p>Model ports for the supported Groq models.</p>"},{"location":"infra/llm/providers/groq/pool/","title":"Pool","text":""},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool","title":"infra.llm.providers.groq.pool","text":""},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool--summary","title":"Summary","text":"<p>Groq pool adaptors.</p> <p>Wire Groq configuration and model ports into the synchronous and asynchronous LLM pool adaptors.</p>"},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool-classes","title":"Classes","text":""},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool.AsyncGroqPool","title":"AsyncGroqPool","text":"<pre><code>AsyncGroqPool(**kwargs)\n</code></pre> <p> Bases: <code>AsyncPoolAdaptor</code></p> <p>Asynchronous LLM pool backed by Groq.</p> <p>Initialize the pool with Groq defaults.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Overrides for the client and model ports.</p> <code>{}</code>"},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool.AsyncGroqPool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool.AsyncGroqPool.aclose","title":"aclose <code>async</code>","text":"<pre><code>aclose()\n</code></pre> <p>Close the underlying asynchronous HTTP client.</p>"},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool.AsyncGroqPool.generate","title":"generate <code>async</code>","text":"<pre><code>generate(\n prompt: str,\n system_prompt: Optional[str] = None,\n max_tokens: Optional[int] = None,\n models: Optional[list] = None,\n) -&gt; str\n</code></pre> <p>Generate text for a prompt asynchronously.</p> <p>Parameters:</p> Name Type Description Default <code>prompt</code> <code>str</code> <p>User prompt text.</p> required <code>system_prompt</code> <code>Optional[str]</code> <p>Optional system instruction.</p> <code>None</code> <code>max_tokens</code> <code>Optional[int]</code> <p>Token cap overriding model defaults.</p> <code>None</code> <code>models</code> <code>Optional[list]</code> <p>Model ports overriding the pool defaults.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generated content.</p>"},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool.SyncGroqPool","title":"SyncGroqPool","text":"<pre><code>SyncGroqPool(**kwargs)\n</code></pre> <p> Bases: <code>PoolAdaptor</code></p> <p>Synchronous LLM pool backed by Groq.</p> <p>Initialize the pool with Groq defaults.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Overrides for the client and model ports.</p> <code>{}</code>"},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool.SyncGroqPool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool.SyncGroqPool.close","title":"close","text":"<pre><code>close()\n</code></pre> <p>Close the underlying HTTP client.</p>"},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool.SyncGroqPool.generate","title":"generate","text":"<pre><code>generate(\n prompt: str,\n system_prompt: Optional[str] = None,\n max_tokens: Optional[int] = None,\n models: Optional[list] = None,\n) -&gt; str\n</code></pre> <p>Generate text for a prompt.</p> <p>Parameters:</p> Name Type Description Default <code>prompt</code> <code>str</code> <p>User prompt text.</p> required <code>system_prompt</code> <code>Optional[str]</code> <p>Optional system instruction.</p> <code>None</code> <code>max_tokens</code> <code>Optional[int]</code> <p>Token cap overriding model defaults.</p> <code>None</code> <code>models</code> <code>Optional[list]</code> <p>Model ports overriding the pool defaults.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generated content.</p>"},{"location":"infra/llm/providers/groq/pool/#infra.llm.providers.groq.pool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/llama_parser/","title":"Llama Parser","text":"<ul> <li>Config</li> <li>Models</li> <li>Pool</li> </ul>"},{"location":"infra/llm/providers/llama_parser/#infra.llm.providers.llama_parser","title":"infra.llm.providers.llama_parser","text":""},{"location":"infra/llm/providers/llama_parser/#infra.llm.providers.llama_parser--summary","title":"Summary","text":"<p>LlamaCloud statement parser integration.</p> <p>Expose parser configuration, extraction models, and the parser pool adaptor.</p>"},{"location":"infra/llm/providers/llama_parser/config/","title":"Config","text":""},{"location":"infra/llm/providers/llama_parser/config/#infra.llm.providers.llama_parser.config","title":"infra.llm.providers.llama_parser.config","text":""},{"location":"infra/llm/providers/llama_parser/config/#infra.llm.providers.llama_parser.config--summary","title":"Summary","text":"<p>LlamaCloud parser configuration loaded from the environment.</p> <p>Read the LlamaCloud API key used by the parser adaptor.</p>"},{"location":"infra/llm/providers/llama_parser/config/#infra.llm.providers.llama_parser.config-classes","title":"Classes","text":""},{"location":"infra/llm/providers/llama_parser/config/#infra.llm.providers.llama_parser.config.LlamaParserConfig","title":"LlamaParserConfig","text":"<pre><code>LlamaParserConfig()\n</code></pre> <p>Hold LlamaCloud parser credentials.</p> <p>Attributes:</p> Name Type Description <code>api_key</code> <code>str</code> <p>LlamaCloud API key from <code>LLAMA_CLOUD_API_KEY</code>.</p> <p>Load parser configuration from environment variables.</p>"},{"location":"infra/llm/providers/llama_parser/config/#infra.llm.providers.llama_parser.config.LlamaParserConfig-functions","title":"Functions","text":""},{"location":"infra/llm/providers/llama_parser/models/","title":"Models","text":""},{"location":"infra/llm/providers/llama_parser/models/#infra.llm.providers.llama_parser.models","title":"infra.llm.providers.llama_parser.models","text":""},{"location":"infra/llm/providers/llama_parser/models/#infra.llm.providers.llama_parser.models--summary","title":"Summary","text":"<p>Pydantic models for statement extraction results.</p> <p>Define the transaction schema returned by LlamaCloud extraction and the default extraction configuration.</p>"},{"location":"infra/llm/providers/llama_parser/models/#infra.llm.providers.llama_parser.models-classes","title":"Classes","text":""},{"location":"infra/llm/providers/llama_parser/models/#infra.llm.providers.llama_parser.models.Direction","title":"Direction","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Transaction direction.</p> <p>Attributes:</p> Name Type Description <code>DEBIT</code> <code>str</code> <p>Debit transaction direction.</p> <code>CREDIT</code> <code>str</code> <p>Credit transaction direction.</p>"},{"location":"infra/llm/providers/llama_parser/models/#infra.llm.providers.llama_parser.models.RawExpense","title":"RawExpense","text":"<p> Bases: <code>BaseModel</code></p> <p>A single extracted statement transaction.</p> <p>Attributes:</p> Name Type Description <code>date</code> <code>str</code> <p>Expense date as DD-MM-YYYY.</p> <code>amount</code> <code>float</code> <p>Transaction amount.</p> <code>balance</code> <code>float</code> <p>Account balance after transaction.</p> <code>description</code> <code>str</code> <p>Complete reconstructed transaction description.</p> <code>raw_lines</code> <code>List[str]</code> <p>Raw OCR/text lines that form this transaction.</p> <code>direction</code> <code>Direction</code> <p>Either DEBIT or CREDIT.</p>"},{"location":"infra/llm/providers/llama_parser/models/#infra.llm.providers.llama_parser.models.Statement","title":"Statement","text":"<p> Bases: <code>BaseModel</code></p> <p>Extraction result containing parsed transactions.</p> <p>Attributes:</p> Name Type Description <code>transactions</code> <code>List[RawExpense]</code> <p>Extracted transactions.</p>"},{"location":"infra/llm/providers/llama_parser/pool/","title":"Pool","text":""},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool","title":"infra.llm.providers.llama_parser.pool","text":""},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool--summary","title":"Summary","text":"<p>LlamaCloud statement parser adaptor.</p> <p>Upload a statement PDF to LlamaCloud for extraction, or replay a cached CSV, returning normalized transaction dictionaries.</p>"},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool-classes","title":"Classes","text":""},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.AsyncLlamaParserPool","title":"AsyncLlamaParserPool","text":"<pre><code>AsyncLlamaParserPool(**kwargs)\n</code></pre> <p> Bases: <code>LlamaParserAdaptor</code></p> <p>LLM parser pool configured from the environment.</p> <p>Initialize the pool with configuration defaults.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Overrides passed to the parser adaptor.</p> <code>{}</code>"},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.AsyncLlamaParserPool-attributes","title":"Attributes","text":""},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.AsyncLlamaParserPool.client","title":"client <code>property</code>","text":"<pre><code>client: AsyncLlamaCloud\n</code></pre> <p>Return the lazily initialized LlamaCloud client.</p> <p>Returns:</p> Name Type Description <code>AsyncLlamaCloud</code> <code>AsyncLlamaCloud</code> <p>Authenticated LlamaCloud client.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When no API key is configured.</p>"},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.AsyncLlamaParserPool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.AsyncLlamaParserPool.aclose","title":"aclose <code>async</code>","text":"<pre><code>aclose()\n</code></pre> <p>Close the LlamaCloud client if it was created.</p>"},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.AsyncLlamaParserPool.generate_statement","title":"generate_statement <code>async</code>","text":"<pre><code>generate_statement(\n filepath: Union[str, os.PathLike],\n cached: Optional[Union[str, os.PathLike]] = None,\n) -&gt; List[dict]\n</code></pre> <p>Extract transactions from a statement PDF.</p> <p>When <code>cached</code> points to a CSV previously exported by <code>scripts/llama_txns_extractor.py</code>, read it and validate each row into RawExpense models instead of calling LlamaCloud.</p> <p>Parameters:</p> Name Type Description Default <code>filepath</code> <code>Union[str, PathLike]</code> <p>Path to the statement PDF.</p> required <code>cached</code> <code>Optional[Union[str, PathLike]]</code> <p>Path to a cached CSV export.</p> <code>None</code> <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Extracted transaction dictionaries.</p>"},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.LlamaParserAdaptor","title":"LlamaParserAdaptor","text":"<pre><code>LlamaParserAdaptor(**kwargs)\n</code></pre> <p>Extract transactions through the LlamaCloud API.</p> <p>Attributes:</p> Name Type Description <code>api_key</code> <code>str</code> <p>LlamaCloud API key.</p> <code>extract_config</code> <code>dict</code> <p>Extraction configuration payload.</p> <code>_client</code> <code>Optional[AsyncLlamaCloud]</code> <p>Lazily created API client.</p> <p>Initialize the parser adaptor.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Configuration; <code>api_key</code> and <code>extract_config</code> are consumed, remaining keys become instance attributes.</p> <code>{}</code>"},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.LlamaParserAdaptor-attributes","title":"Attributes","text":""},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.LlamaParserAdaptor.client","title":"client <code>property</code>","text":"<pre><code>client: AsyncLlamaCloud\n</code></pre> <p>Return the lazily initialized LlamaCloud client.</p> <p>Returns:</p> Name Type Description <code>AsyncLlamaCloud</code> <code>AsyncLlamaCloud</code> <p>Authenticated LlamaCloud client.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When no API key is configured.</p>"},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.LlamaParserAdaptor-functions","title":"Functions","text":""},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.LlamaParserAdaptor.aclose","title":"aclose <code>async</code>","text":"<pre><code>aclose()\n</code></pre> <p>Close the LlamaCloud client if it was created.</p>"},{"location":"infra/llm/providers/llama_parser/pool/#infra.llm.providers.llama_parser.pool.LlamaParserAdaptor.generate_statement","title":"generate_statement <code>async</code>","text":"<pre><code>generate_statement(\n filepath: Union[str, os.PathLike],\n cached: Optional[Union[str, os.PathLike]] = None,\n) -&gt; List[dict]\n</code></pre> <p>Extract transactions from a statement PDF.</p> <p>When <code>cached</code> points to a CSV previously exported by <code>scripts/llama_txns_extractor.py</code>, read it and validate each row into RawExpense models instead of calling LlamaCloud.</p> <p>Parameters:</p> Name Type Description Default <code>filepath</code> <code>Union[str, PathLike]</code> <p>Path to the statement PDF.</p> required <code>cached</code> <code>Optional[Union[str, PathLike]]</code> <p>Path to a cached CSV export.</p> <code>None</code> <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Extracted transaction dictionaries.</p>"},{"location":"infra/llm/providers/open_ai/","title":"Open Ai","text":"<ul> <li>Config</li> <li>Models</li> <li>Pool</li> </ul>"},{"location":"infra/llm/providers/open_ai/#infra.llm.providers.open_ai","title":"infra.llm.providers.open_ai","text":""},{"location":"infra/llm/providers/open_ai/#infra.llm.providers.open_ai--summary","title":"Summary","text":"<p>OpenAI LLM provider integration.</p> <p>Expose OpenAI configuration, model ports, and synchronous/asynchronous pools.</p>"},{"location":"infra/llm/providers/open_ai/config/","title":"Config","text":""},{"location":"infra/llm/providers/open_ai/config/#infra.llm.providers.open_ai.config","title":"infra.llm.providers.open_ai.config","text":""},{"location":"infra/llm/providers/open_ai/config/#infra.llm.providers.open_ai.config--summary","title":"Summary","text":"<p>OpenAI provider configuration loaded from the environment.</p> <p>Read the OpenAI API key and endpoint used by the OpenAI pool adaptors.</p>"},{"location":"infra/llm/providers/open_ai/config/#infra.llm.providers.open_ai.config-classes","title":"Classes","text":""},{"location":"infra/llm/providers/open_ai/config/#infra.llm.providers.open_ai.config.OpenAiConfig","title":"OpenAiConfig","text":"<pre><code>OpenAiConfig()\n</code></pre> <p>Hold OpenAI provider credentials and endpoint.</p> <p>Attributes:</p> Name Type Description <code>api_key</code> <code>str</code> <p>OpenAI API key from <code>OPENAI_API_KEY</code>.</p> <code>endpoint</code> <code>str</code> <p>OpenAI API base URL.</p> <p>Load OpenAI configuration from environment variables.</p>"},{"location":"infra/llm/providers/open_ai/config/#infra.llm.providers.open_ai.config.OpenAiConfig-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_ai/models/","title":"Models","text":""},{"location":"infra/llm/providers/open_ai/models/#infra.llm.providers.open_ai.models","title":"infra.llm.providers.open_ai.models","text":""},{"location":"infra/llm/providers/open_ai/models/#infra.llm.providers.open_ai.models--summary","title":"Summary","text":"<p>OpenAI model port definitions.</p> <p>Expose the default OpenAI model identifiers used by the OpenAI pool adaptors.</p>"},{"location":"infra/llm/providers/open_ai/models/#infra.llm.providers.open_ai.models-classes","title":"Classes","text":""},{"location":"infra/llm/providers/open_ai/models/#infra.llm.providers.open_ai.models-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_ai/models/#infra.llm.providers.open_ai.models.create_model_ports","title":"create_model_ports","text":"<pre><code>create_model_ports()\n</code></pre> <p>Create the default OpenAI model ports.</p> <p>Returns:</p> Name Type Description <code>list</code> <p>Model ports for the supported OpenAI models.</p>"},{"location":"infra/llm/providers/open_ai/pool/","title":"Pool","text":""},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool","title":"infra.llm.providers.open_ai.pool","text":""},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool--summary","title":"Summary","text":"<p>OpenAI pool adaptors.</p> <p>Wire OpenAI configuration and model ports into the synchronous and asynchronous LLM pool adaptors.</p>"},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool-classes","title":"Classes","text":""},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool.AsyncOpenAiPool","title":"AsyncOpenAiPool","text":"<pre><code>AsyncOpenAiPool(**kwargs)\n</code></pre> <p> Bases: <code>AsyncPoolAdaptor</code></p> <p>Asynchronous LLM pool backed by OpenAI.</p> <p>Initialize the pool with OpenAI defaults.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Overrides for the client and model ports.</p> <code>{}</code>"},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool.AsyncOpenAiPool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool.AsyncOpenAiPool.aclose","title":"aclose <code>async</code>","text":"<pre><code>aclose()\n</code></pre> <p>Close the underlying asynchronous HTTP client.</p>"},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool.AsyncOpenAiPool.generate","title":"generate <code>async</code>","text":"<pre><code>generate(\n prompt: str,\n system_prompt: Optional[str] = None,\n max_tokens: Optional[int] = None,\n models: Optional[list] = None,\n) -&gt; str\n</code></pre> <p>Generate text for a prompt asynchronously.</p> <p>Parameters:</p> Name Type Description Default <code>prompt</code> <code>str</code> <p>User prompt text.</p> required <code>system_prompt</code> <code>Optional[str]</code> <p>Optional system instruction.</p> <code>None</code> <code>max_tokens</code> <code>Optional[int]</code> <p>Token cap overriding model defaults.</p> <code>None</code> <code>models</code> <code>Optional[list]</code> <p>Model ports overriding the pool defaults.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generated content.</p>"},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool.SyncOpenAiPool","title":"SyncOpenAiPool","text":"<pre><code>SyncOpenAiPool(**kwargs)\n</code></pre> <p> Bases: <code>PoolAdaptor</code></p> <p>Synchronous LLM pool backed by OpenAI.</p> <p>Initialize the pool with OpenAI defaults.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Overrides for the client and model ports.</p> <code>{}</code>"},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool.SyncOpenAiPool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool.SyncOpenAiPool.close","title":"close","text":"<pre><code>close()\n</code></pre> <p>Close the underlying HTTP client.</p>"},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool.SyncOpenAiPool.generate","title":"generate","text":"<pre><code>generate(\n prompt: str,\n system_prompt: Optional[str] = None,\n max_tokens: Optional[int] = None,\n models: Optional[list] = None,\n) -&gt; str\n</code></pre> <p>Generate text for a prompt.</p> <p>Parameters:</p> Name Type Description Default <code>prompt</code> <code>str</code> <p>User prompt text.</p> required <code>system_prompt</code> <code>Optional[str]</code> <p>Optional system instruction.</p> <code>None</code> <code>max_tokens</code> <code>Optional[int]</code> <p>Token cap overriding model defaults.</p> <code>None</code> <code>models</code> <code>Optional[list]</code> <p>Model ports overriding the pool defaults.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generated content.</p>"},{"location":"infra/llm/providers/open_ai/pool/#infra.llm.providers.open_ai.pool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_router/","title":"Open Router","text":"<ul> <li>Config</li> <li>Models</li> <li>Pool</li> </ul>"},{"location":"infra/llm/providers/open_router/#infra.llm.providers.open_router","title":"infra.llm.providers.open_router","text":""},{"location":"infra/llm/providers/open_router/#infra.llm.providers.open_router--summary","title":"Summary","text":"<p>OpenRouter LLM provider integration.</p> <p>Expose OpenRouter configuration, model ports, and synchronous/asynchronous pools.</p>"},{"location":"infra/llm/providers/open_router/config/","title":"Config","text":""},{"location":"infra/llm/providers/open_router/config/#infra.llm.providers.open_router.config","title":"infra.llm.providers.open_router.config","text":""},{"location":"infra/llm/providers/open_router/config/#infra.llm.providers.open_router.config--summary","title":"Summary","text":"<p>OpenRouter provider configuration loaded from the environment.</p> <p>Read the OpenRouter API key and endpoint used by the OpenRouter pool adaptors.</p>"},{"location":"infra/llm/providers/open_router/config/#infra.llm.providers.open_router.config-classes","title":"Classes","text":""},{"location":"infra/llm/providers/open_router/config/#infra.llm.providers.open_router.config.OpenRouterConfig","title":"OpenRouterConfig","text":"<pre><code>OpenRouterConfig()\n</code></pre> <p>Hold OpenRouter provider credentials and endpoint.</p> <p>Attributes:</p> Name Type Description <code>api_key</code> <code>str</code> <p>OpenRouter API key from <code>OPENROUTER_API_KEY</code> or <code>LLM_API_KEY</code>.</p> <code>endpoint</code> <code>str</code> <p>OpenRouter API base URL.</p> <p>Load OpenRouter configuration from environment variables.</p>"},{"location":"infra/llm/providers/open_router/config/#infra.llm.providers.open_router.config.OpenRouterConfig-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_router/models/","title":"Models","text":""},{"location":"infra/llm/providers/open_router/models/#infra.llm.providers.open_router.models","title":"infra.llm.providers.open_router.models","text":""},{"location":"infra/llm/providers/open_router/models/#infra.llm.providers.open_router.models--summary","title":"Summary","text":"<p>OpenRouter model port definitions.</p> <p>Expose the default OpenRouter model identifiers used by the OpenRouter pool adaptors.</p>"},{"location":"infra/llm/providers/open_router/models/#infra.llm.providers.open_router.models-classes","title":"Classes","text":""},{"location":"infra/llm/providers/open_router/models/#infra.llm.providers.open_router.models-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_router/models/#infra.llm.providers.open_router.models.create_model_ports","title":"create_model_ports","text":"<pre><code>create_model_ports()\n</code></pre> <p>Create the default OpenRouter model ports.</p> <p>Returns:</p> Name Type Description <code>list</code> <p>Model ports for the supported OpenRouter models.</p>"},{"location":"infra/llm/providers/open_router/pool/","title":"Pool","text":""},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool","title":"infra.llm.providers.open_router.pool","text":""},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool--summary","title":"Summary","text":"<p>OpenRouter pool adaptors.</p> <p>Wire OpenRouter configuration and model ports into the synchronous and asynchronous LLM pool adaptors.</p>"},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool-classes","title":"Classes","text":""},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool.AsyncOpenRouterPool","title":"AsyncOpenRouterPool","text":"<pre><code>AsyncOpenRouterPool(**kwargs)\n</code></pre> <p> Bases: <code>AsyncPoolAdaptor</code></p> <p>Asynchronous LLM pool backed by OpenRouter.</p> <p>Initialize the pool with OpenRouter defaults.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Overrides for the client and model ports.</p> <code>{}</code>"},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool.AsyncOpenRouterPool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool.AsyncOpenRouterPool.aclose","title":"aclose <code>async</code>","text":"<pre><code>aclose()\n</code></pre> <p>Close the underlying asynchronous HTTP client.</p>"},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool.AsyncOpenRouterPool.generate","title":"generate <code>async</code>","text":"<pre><code>generate(\n prompt: str,\n system_prompt: Optional[str] = None,\n max_tokens: Optional[int] = None,\n models: Optional[list] = None,\n) -&gt; str\n</code></pre> <p>Generate text for a prompt asynchronously.</p> <p>Parameters:</p> Name Type Description Default <code>prompt</code> <code>str</code> <p>User prompt text.</p> required <code>system_prompt</code> <code>Optional[str]</code> <p>Optional system instruction.</p> <code>None</code> <code>max_tokens</code> <code>Optional[int]</code> <p>Token cap overriding model defaults.</p> <code>None</code> <code>models</code> <code>Optional[list]</code> <p>Model ports overriding the pool defaults.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generated content.</p>"},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool.SyncOpenRouterPool","title":"SyncOpenRouterPool","text":"<pre><code>SyncOpenRouterPool(**kwargs)\n</code></pre> <p> Bases: <code>PoolAdaptor</code></p> <p>Synchronous LLM pool backed by OpenRouter.</p> <p>Initialize the pool with OpenRouter defaults.</p> <p>Parameters:</p> Name Type Description Default <code>**kwargs</code> <p>Overrides for the client and model ports.</p> <code>{}</code>"},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool.SyncOpenRouterPool-functions","title":"Functions","text":""},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool.SyncOpenRouterPool.close","title":"close","text":"<pre><code>close()\n</code></pre> <p>Close the underlying HTTP client.</p>"},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool.SyncOpenRouterPool.generate","title":"generate","text":"<pre><code>generate(\n prompt: str,\n system_prompt: Optional[str] = None,\n max_tokens: Optional[int] = None,\n models: Optional[list] = None,\n) -&gt; str\n</code></pre> <p>Generate text for a prompt.</p> <p>Parameters:</p> Name Type Description Default <code>prompt</code> <code>str</code> <p>User prompt text.</p> required <code>system_prompt</code> <code>Optional[str]</code> <p>Optional system instruction.</p> <code>None</code> <code>max_tokens</code> <code>Optional[int]</code> <p>Token cap overriding model defaults.</p> <code>None</code> <code>models</code> <code>Optional[list]</code> <p>Model ports overriding the pool defaults.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Generated content.</p>"},{"location":"infra/llm/providers/open_router/pool/#infra.llm.providers.open_router.pool-functions","title":"Functions","text":""},{"location":"interfaces/","title":"Interfaces","text":"<ul> <li>Account</li> <li>Ambiguity</li> <li>Auth</li> <li>Entity</li> <li>Expense</li> <li>Fetch Request</li> <li>Openapi</li> <li>Report</li> <li>Tag</li> <li>Upload</li> <li>User</li> </ul>"},{"location":"interfaces/#interfaces","title":"interfaces","text":""},{"location":"interfaces/#interfaces--summary","title":"Summary","text":"<p>Thin entry points for the Aetoskia Expenses Service: FastAPI route handlers wired to openapi.yaml operationIds, SSE handlers, and CLI commands. Handlers stay thin and delegate to domain services; business logic lives in the domain layer.</p>"},{"location":"interfaces/auth/","title":"Auth","text":""},{"location":"interfaces/auth/#interfaces.auth","title":"interfaces.auth","text":""},{"location":"interfaces/auth/#interfaces.auth--summary","title":"Summary","text":"<p>Auth interface: thin FastAPI entry points related to authentication, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/openapi/","title":"Openapi","text":""},{"location":"interfaces/openapi/#interfaces.openapi","title":"interfaces.openapi","text":""},{"location":"interfaces/openapi/#interfaces.openapi--summary","title":"Summary","text":"<p>All handler functions \u2014 names must match openapi.yaml operationId values. The OpenAPI-first router resolves each operation to a handler by name, so this module re-exports every route handler from the subpackages into one flat namespace.</p>"},{"location":"interfaces/openapi/#interfaces.openapi-classes","title":"Classes","text":""},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService","title":"AccountCrudsService","text":"<pre><code>AccountCrudsService(*, repo=None)\n</code></pre> <p> Bases: <code>CrudsServiceAdaptor[Account, AccountDocument]</code></p> <p>Account CRUD service resolving :class:<code>Account</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_account_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p> <p>Initialize the adaptor with a backing repository.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>BaseRepository</code> <p>Repository used for all operations.</p> <code>None</code>"},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService.create","title":"create <code>async</code>","text":"<pre><code>create(data: Model | dict) -&gt; Schema\n</code></pre> <p>Create a document from a model or raw mapping.</p> <p>Parameters:</p> Name Type Description Default <code>data</code> <code>Model | dict</code> <p>Model instance or field mapping to persist.</p> required <p>Returns:</p> Name Type Description <code>Schema</code> <code>Schema</code> <p>Persisted document.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService.delete","title":"delete <code>async</code>","text":"<pre><code>delete(id: PyObjectId) -&gt; bool\n</code></pre> <p>Delete a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was deleted.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService.model_to_dict","title":"model_to_dict <code>staticmethod</code>","text":"<pre><code>model_to_dict(model_obj: Model) -&gt; dict\n</code></pre> <p>Serialize a model into a sparse dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>model_obj</code> <code>Model</code> <p>Model instance to serialize.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Fields that are set and not <code>None</code>.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService.patch","title":"patch <code>async</code>","text":"<pre><code>patch(id: PyObjectId, data: dict) -&gt; Schema | None\n</code></pre> <p>Partially update a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>dict</code> <p>Fields to patch.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService.read","title":"read <code>async</code>","text":"<pre><code>read(id: PyObjectId) -&gt; Schema | None\n</code></pre> <p>Read a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Matching document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService.search","title":"search <code>async</code>","text":"<pre><code>search(\n filter: dict | None = None, *args, **kwargs\n) -&gt; list[Schema]\n</code></pre> <p>List documents matching an optional filter.</p> <p>Parameters:</p> Name Type Description Default <code>filter</code> <code>dict | None</code> <p>Query filter passed to the repository.</p> <code>None</code> <p>Returns:</p> Type Description <code>list[Schema]</code> <p>list[Schema]: Matching documents.</p> Notes <p>Extra positional and keyword arguments are forwarded to the repository.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.AccountCrudsService.update","title":"update <code>async</code>","text":"<pre><code>update(id: PyObjectId, data: Model | dict) -&gt; Schema | None\n</code></pre> <p>Replace a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>Model | dict</code> <p>Replacement model or field mapping.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService","title":"EntityCrudsService","text":"<pre><code>EntityCrudsService(*, repo=None)\n</code></pre> <p> Bases: <code>CrudsServiceAdaptor[Entity, EntityDocument]</code></p> <p>Entity CRUD service resolving :class:<code>Entity</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_entity_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p> <p>Initialize the adaptor with a backing repository.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>BaseRepository</code> <p>Repository used for all operations.</p> <code>None</code>"},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService.create","title":"create <code>async</code>","text":"<pre><code>create(data: Model | dict) -&gt; Schema\n</code></pre> <p>Create a document from a model or raw mapping.</p> <p>Parameters:</p> Name Type Description Default <code>data</code> <code>Model | dict</code> <p>Model instance or field mapping to persist.</p> required <p>Returns:</p> Name Type Description <code>Schema</code> <code>Schema</code> <p>Persisted document.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService.delete","title":"delete <code>async</code>","text":"<pre><code>delete(id: PyObjectId) -&gt; bool\n</code></pre> <p>Delete a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was deleted.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService.model_to_dict","title":"model_to_dict <code>staticmethod</code>","text":"<pre><code>model_to_dict(model_obj: Model) -&gt; dict\n</code></pre> <p>Serialize a model into a sparse dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>model_obj</code> <code>Model</code> <p>Model instance to serialize.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Fields that are set and not <code>None</code>.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService.patch","title":"patch <code>async</code>","text":"<pre><code>patch(id: PyObjectId, data: dict) -&gt; Schema | None\n</code></pre> <p>Partially update a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>dict</code> <p>Fields to patch.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService.read","title":"read <code>async</code>","text":"<pre><code>read(id: PyObjectId) -&gt; Schema | None\n</code></pre> <p>Read a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Matching document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService.search","title":"search <code>async</code>","text":"<pre><code>search(\n filter: dict | None = None, *args, **kwargs\n) -&gt; list[Schema]\n</code></pre> <p>List documents matching an optional filter.</p> <p>Parameters:</p> Name Type Description Default <code>filter</code> <code>dict | None</code> <p>Query filter passed to the repository.</p> <code>None</code> <p>Returns:</p> Type Description <code>list[Schema]</code> <p>list[Schema]: Matching documents.</p> Notes <p>Extra positional and keyword arguments are forwarded to the repository.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.EntityCrudsService.update","title":"update <code>async</code>","text":"<pre><code>update(id: PyObjectId, data: Model | dict) -&gt; Schema | None\n</code></pre> <p>Replace a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>Model | dict</code> <p>Replacement model or field mapping.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService","title":"ExpenseCrudsService","text":"<pre><code>ExpenseCrudsService(*, repo=None)\n</code></pre> <p> Bases: <code>CrudsServiceAdaptor[Expense, ExpenseDocument]</code></p> <p>Expense CRUD service resolving :class:<code>Expense</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_expense_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p> <p>Initialize the adaptor with a backing repository.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>BaseRepository</code> <p>Repository used for all operations.</p> <code>None</code>"},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService.create","title":"create <code>async</code>","text":"<pre><code>create(data: Model | dict) -&gt; Schema\n</code></pre> <p>Create a document from a model or raw mapping.</p> <p>Parameters:</p> Name Type Description Default <code>data</code> <code>Model | dict</code> <p>Model instance or field mapping to persist.</p> required <p>Returns:</p> Name Type Description <code>Schema</code> <code>Schema</code> <p>Persisted document.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService.delete","title":"delete <code>async</code>","text":"<pre><code>delete(id: PyObjectId) -&gt; bool\n</code></pre> <p>Delete a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was deleted.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService.model_to_dict","title":"model_to_dict <code>staticmethod</code>","text":"<pre><code>model_to_dict(model_obj: Model) -&gt; dict\n</code></pre> <p>Serialize a model into a sparse dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>model_obj</code> <code>Model</code> <p>Model instance to serialize.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Fields that are set and not <code>None</code>.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService.patch","title":"patch <code>async</code>","text":"<pre><code>patch(id: PyObjectId, data: dict) -&gt; Schema | None\n</code></pre> <p>Partially update a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>dict</code> <p>Fields to patch.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService.read","title":"read <code>async</code>","text":"<pre><code>read(id: PyObjectId) -&gt; Schema | None\n</code></pre> <p>Read a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Matching document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService.search","title":"search <code>async</code>","text":"<pre><code>search(\n filter: dict | None = None, *args, **kwargs\n) -&gt; list[Schema]\n</code></pre> <p>List documents matching an optional filter.</p> <p>Parameters:</p> Name Type Description Default <code>filter</code> <code>dict | None</code> <p>Query filter passed to the repository.</p> <code>None</code> <p>Returns:</p> Type Description <code>list[Schema]</code> <p>list[Schema]: Matching documents.</p> Notes <p>Extra positional and keyword arguments are forwarded to the repository.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ExpenseCrudsService.update","title":"update <code>async</code>","text":"<pre><code>update(id: PyObjectId, data: Model | dict) -&gt; Schema | None\n</code></pre> <p>Replace a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>Model | dict</code> <p>Replacement model or field mapping.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService","title":"FetchRequestCrudsService","text":"<pre><code>FetchRequestCrudsService(*, repo=None)\n</code></pre> <p> Bases: <code>CrudsServiceAdaptor[FetchRequest, FetchRequestDocument]</code></p> <p>CRUD service for fetch requests with pipeline stage helpers.</p> <p>Attributes:</p> Name Type Description <code>model</code> <code>FetchRequest</code> <p>Domain model class.</p> <code>schema</code> <code>FetchRequestDocument</code> <p>Persistence document class.</p> <p>Initialize the adaptor with a backing repository.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>BaseRepository</code> <p>Repository used for all operations.</p> <code>None</code>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.create","title":"create <code>async</code>","text":"<pre><code>create(data: Model | dict) -&gt; Schema\n</code></pre> <p>Create a document from a model or raw mapping.</p> <p>Parameters:</p> Name Type Description Default <code>data</code> <code>Model | dict</code> <p>Model instance or field mapping to persist.</p> required <p>Returns:</p> Name Type Description <code>Schema</code> <code>Schema</code> <p>Persisted document.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.delete","title":"delete <code>async</code>","text":"<pre><code>delete(id: PyObjectId) -&gt; bool\n</code></pre> <p>Delete a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was deleted.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.model_to_dict","title":"model_to_dict <code>staticmethod</code>","text":"<pre><code>model_to_dict(model_obj: Model) -&gt; dict\n</code></pre> <p>Serialize a model into a sparse dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>model_obj</code> <code>Model</code> <p>Model instance to serialize.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Fields that are set and not <code>None</code>.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.patch","title":"patch <code>async</code>","text":"<pre><code>patch(id: PyObjectId, data: dict) -&gt; Schema | None\n</code></pre> <p>Partially update a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>dict</code> <p>Fields to patch.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.read","title":"read <code>async</code>","text":"<pre><code>read(id: PyObjectId) -&gt; Schema | None\n</code></pre> <p>Read a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Matching document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.save_enrichment","title":"save_enrichment <code>async</code>","text":"<pre><code>save_enrichment(\n id: PyObjectId, enrichment_dicts: list\n) -&gt; None\n</code></pre> <p>Persist the enriched expense dicts on the request source.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>enrichment_dicts</code> <code>list</code> <p>Enriched expense dicts.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.save_raw_lines","title":"save_raw_lines <code>async</code>","text":"<pre><code>save_raw_lines(id: PyObjectId, raw_lines: list) -&gt; None\n</code></pre> <p>Persist the extracted raw lines on the request source.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>raw_lines</code> <code>list</code> <p>Raw OCR/text lines.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.save_txn_blocks","title":"save_txn_blocks <code>async</code>","text":"<pre><code>save_txn_blocks(id: PyObjectId, txn_blocks: dict) -&gt; None\n</code></pre> <p>Persist the extracted transaction blocks on the request source.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>txn_blocks</code> <code>dict</code> <p>Transaction blocks keyed by order id.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.save_txn_dicts","title":"save_txn_dicts <code>async</code>","text":"<pre><code>save_txn_dicts(\n id: PyObjectId, txn_dicts: list, txn_dicts_count: int\n) -&gt; None\n</code></pre> <p>Persist the parsed transaction dicts and count on the request source.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>txn_dicts</code> <code>list</code> <p>Raw expense dicts.</p> required <code>txn_dicts_count</code> <code>int</code> <p>Number of parsed transaction dicts.</p> required <p>Returns:</p> Name Type Description <code>None</code> <code>None</code> <p>Nothing.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.search","title":"search <code>async</code>","text":"<pre><code>search(\n filter: dict | None = None, *args, **kwargs\n) -&gt; list[Schema]\n</code></pre> <p>List documents matching an optional filter.</p> <p>Parameters:</p> Name Type Description Default <code>filter</code> <code>dict | None</code> <p>Query filter passed to the repository.</p> <code>None</code> <p>Returns:</p> Type Description <code>list[Schema]</code> <p>list[Schema]: Matching documents.</p> Notes <p>Extra positional and keyword arguments are forwarded to the repository.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.update","title":"update <code>async</code>","text":"<pre><code>update(id: PyObjectId, data: Model | dict) -&gt; Schema | None\n</code></pre> <p>Replace a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>Model | dict</code> <p>Replacement model or field mapping.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.FetchRequestCrudsService.update_status","title":"update_status <code>async</code>","text":"<pre><code>update_status(\n id: PyObjectId,\n status: str,\n error_message: Optional[str] = None,\n retry_count: Optional[int] = None,\n) -&gt; bool\n</code></pre> <p>Update the request status, optionally carrying failure detail.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Fetch request id.</p> required <code>status</code> <code>str</code> <p>New status value.</p> required <code>error_message</code> <code>Optional[str]</code> <p>Message recorded when failing.</p> <code>None</code> <code>retry_count</code> <code>Optional[int]</code> <p>Retry counter recorded when failing.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was patched.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>If <code>status == \"failed\"</code> and either <code>error_message</code> or <code>retry_count</code> is <code>None</code>.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ReportQuery","title":"ReportQuery","text":"<p> Bases: <code>BaseModel</code></p> <p>Definition of a report snapshot. Bounds the data set; dimensions are sliced at read time.</p> <p>Attributes:</p> Name Type Description <code>name</code> <code>str</code> <p>Snapshot name; empty for an auto-generated name.</p> <code>granularities</code> <code>List[str]</code> <p>Granularities to precompute in the cube.</p> <code>group_dims</code> <code>List[str]</code> <p>Dimensions to group by, e.g. <code>\"payee\"</code>, <code>\"tag\"</code>.</p> <code>flow</code> <code>str</code> <p>Flow filter: inflows, outflows, or both.</p> <code>accounts</code> <code>Optional[List[str]]</code> <p>Account names to include; all when <code>None</code>.</p> <code>ignore_self</code> <code>bool</code> <p>Exclude self-transfer tagged expenses.</p> <code>start_date</code> <code>str</code> <p>Inclusive start boundary, DD-MM-YYYY.</p> <code>end_date</code> <code>str</code> <p>Inclusive end boundary, DD-MM-YYYY.</p> <code>min_amount</code> <code>Optional[float]</code> <p>Minimum absolute amount to include.</p> <code>max_amount</code> <code>Optional[float]</code> <p>Maximum absolute amount to include.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ReportService","title":"ReportService","text":"<pre><code>ReportService(\n expense_svc: ExpenseCrudsService,\n tag_svc: TagCrudsService,\n store: ReportStore,\n report_repo=None,\n)\n</code></pre> <p>Build, persist, and serve precomputed report snapshots.</p> Notes <p>Instances are created by :func:<code>get_report_service</code>. The service scans expenses in batches, expands tag hierarchies, and persists period series into the configured :class:<code>ReportStore</code>.</p> <p>Initialize the report service with its dependencies.</p> <p>Parameters:</p> Name Type Description Default <code>expense_svc</code> <code>ExpenseCrudsService</code> <p>Expense CRUD service used as the cube source.</p> required <code>tag_svc</code> <code>TagCrudsService</code> <p>Tag CRUD service used to expand tag hierarchies and resolve ignore tags.</p> required <code>store</code> <code>ReportStore</code> <p>Key-value store for cube period data.</p> required <code>report_repo</code> <code>Any</code> <p>Report snapshot repository; defaults to :func:<code>create_report_repo</code> when omitted.</p> <code>None</code>"},{"location":"interfaces/openapi/#interfaces.openapi.ReportService-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.ReportService.delete_snapshot","title":"delete_snapshot <code>async</code>","text":"<pre><code>delete_snapshot(report_id: str) -&gt; bool\n</code></pre> <p>Delete a snapshot and all of its cube keys from the store.</p> <p>Parameters:</p> Name Type Description Default <code>report_id</code> <code>str</code> <p>Snapshot ID to delete.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when the snapshot existed and was deleted.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ReportService.fetch_report","title":"fetch_report <code>async</code>","text":"<pre><code>fetch_report(\n report_id: str,\n granularities: Optional[List[str]] = None,\n period_ids: Optional[List[str]] = None,\n flow: str = \"outflows\",\n payees: Optional[List[str]] = None,\n tags: Optional[List[str]] = None,\n) -&gt; Optional[Report]\n</code></pre> <p>Slice a stored snapshot into a report API response.</p> <p><code>\"*\"</code> in <code>payees</code> or <code>tags</code> expands to every value stored in the cube meta.</p> <p>Parameters:</p> Name Type Description Default <code>report_id</code> <code>str</code> <p>Snapshot ID to slice.</p> required <code>granularities</code> <code>Optional[List[str]]</code> <p>Granularities to include; defaults to the snapshot's own.</p> <code>None</code> <code>period_ids</code> <code>Optional[List[str]]</code> <p>Period labels to filter to.</p> <code>None</code> <code>flow</code> <code>str</code> <p>Flow to serve; <code>both</code> includes inflows and outflows.</p> <code>'outflows'</code> <code>payees</code> <code>Optional[List[str]]</code> <p>Payee filters applied per bucket.</p> <code>None</code> <code>tags</code> <code>Optional[List[str]]</code> <p>Tag path filters applied per bucket.</p> <code>None</code> <p>Returns:</p> Type Description <code>Optional[Report]</code> <p>Optional[Report]: The sliced report view, or <code>None</code> when the snapshot does not exist.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ReportService.generate_snapshot","title":"generate_snapshot <code>async</code>","text":"<pre><code>generate_snapshot(\n query: ReportQuery,\n) -&gt; ReportSnapshotDocument\n</code></pre> <p>Validate a query and return an existing or newly built snapshot.</p> <p>If a snapshot with the same canonical signature already exists it is returned directly; otherwise a fresh cube is built and persisted.</p> <p>Parameters:</p> Name Type Description Default <code>query</code> <code>ReportQuery</code> <p>Raw snapshot definition.</p> required <p>Returns:</p> Name Type Description <code>ReportSnapshotDocument</code> <code>ReportSnapshotDocument</code> <p>The existing or newly created snapshot.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.ReportService.list_snapshots","title":"list_snapshots <code>async</code>","text":"<pre><code>list_snapshots(\n offset: int = 0, limit: int = DEFAULT_LIMIT\n) -&gt; List[ReportSnapshotDocument]\n</code></pre> <p>List stored snapshots, newest first.</p> <p>Parameters:</p> Name Type Description Default <code>offset</code> <code>int</code> <p>Number of snapshots to skip.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of snapshots to return.</p> <code>DEFAULT_LIMIT</code> <p>Returns:</p> Type Description <code>List[ReportSnapshotDocument]</code> <p>List[ReportSnapshotDocument]: Snapshots ordered by creation time, newest first.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService","title":"TagCrudsService","text":"<pre><code>TagCrudsService(*, repo=None)\n</code></pre> <p> Bases: <code>CrudsServiceAdaptor[Tag, TagDocument]</code></p> <p>Tag CRUD service resolving :class:<code>Tag</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_tag_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type. An additional lookup helper <code>get_by_names</code> is provided.</p> <p>Initialize the adaptor with a backing repository.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>BaseRepository</code> <p>Repository used for all operations.</p> <code>None</code>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService.create","title":"create <code>async</code>","text":"<pre><code>create(data: Model | dict) -&gt; Schema\n</code></pre> <p>Create a document from a model or raw mapping.</p> <p>Parameters:</p> Name Type Description Default <code>data</code> <code>Model | dict</code> <p>Model instance or field mapping to persist.</p> required <p>Returns:</p> Name Type Description <code>Schema</code> <code>Schema</code> <p>Persisted document.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService.delete","title":"delete <code>async</code>","text":"<pre><code>delete(id: PyObjectId) -&gt; bool\n</code></pre> <p>Delete a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was deleted.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService.get_by_names","title":"get_by_names <code>async</code>","text":"<pre><code>get_by_names(names: list[str])\n</code></pre> <p>Return tags whose names match any of the provided values.</p> <p>Parameters:</p> Name Type Description Default <code>names</code> <code>list[str]</code> <p>Tag names to look up.</p> required <p>Returns:</p> Name Type Description <code>list</code> <p>Matching tag documents.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService.model_to_dict","title":"model_to_dict <code>staticmethod</code>","text":"<pre><code>model_to_dict(model_obj: Model) -&gt; dict\n</code></pre> <p>Serialize a model into a sparse dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>model_obj</code> <code>Model</code> <p>Model instance to serialize.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Fields that are set and not <code>None</code>.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService.patch","title":"patch <code>async</code>","text":"<pre><code>patch(id: PyObjectId, data: dict) -&gt; Schema | None\n</code></pre> <p>Partially update a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>dict</code> <p>Fields to patch.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService.read","title":"read <code>async</code>","text":"<pre><code>read(id: PyObjectId) -&gt; Schema | None\n</code></pre> <p>Read a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Matching document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService.search","title":"search <code>async</code>","text":"<pre><code>search(\n filter: dict | None = None, *args, **kwargs\n) -&gt; list[Schema]\n</code></pre> <p>List documents matching an optional filter.</p> <p>Parameters:</p> Name Type Description Default <code>filter</code> <code>dict | None</code> <p>Query filter passed to the repository.</p> <code>None</code> <p>Returns:</p> Type Description <code>list[Schema]</code> <p>list[Schema]: Matching documents.</p> Notes <p>Extra positional and keyword arguments are forwarded to the repository.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.TagCrudsService.update","title":"update <code>async</code>","text":"<pre><code>update(id: PyObjectId, data: Model | dict) -&gt; Schema | None\n</code></pre> <p>Replace a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>Model | dict</code> <p>Replacement model or field mapping.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService","title":"UploadCrudsService","text":"<pre><code>UploadCrudsService(*, repo=None)\n</code></pre> <p> Bases: <code>CrudsServiceAdaptor[UploadResult, UploadResultDocument]</code></p> <p>Upload result CRUD service resolving :class:<code>UploadResult</code> documents.</p> Notes <p>Instances are created by :func:<code>get_upload_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p> <p>Initialize the adaptor with a backing repository.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>BaseRepository</code> <p>Repository used for all operations.</p> <code>None</code>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService.create","title":"create <code>async</code>","text":"<pre><code>create(data: Model | dict) -&gt; Schema\n</code></pre> <p>Create a document from a model or raw mapping.</p> <p>Parameters:</p> Name Type Description Default <code>data</code> <code>Model | dict</code> <p>Model instance or field mapping to persist.</p> required <p>Returns:</p> Name Type Description <code>Schema</code> <code>Schema</code> <p>Persisted document.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService.delete","title":"delete <code>async</code>","text":"<pre><code>delete(id: PyObjectId) -&gt; bool\n</code></pre> <p>Delete a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was deleted.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService.model_to_dict","title":"model_to_dict <code>staticmethod</code>","text":"<pre><code>model_to_dict(model_obj: Model) -&gt; dict\n</code></pre> <p>Serialize a model into a sparse dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>model_obj</code> <code>Model</code> <p>Model instance to serialize.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Fields that are set and not <code>None</code>.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService.patch","title":"patch <code>async</code>","text":"<pre><code>patch(id: PyObjectId, data: dict) -&gt; Schema | None\n</code></pre> <p>Partially update a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>dict</code> <p>Fields to patch.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService.read","title":"read <code>async</code>","text":"<pre><code>read(id: PyObjectId) -&gt; Schema | None\n</code></pre> <p>Read a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Matching document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService.search","title":"search <code>async</code>","text":"<pre><code>search(\n filter: dict | None = None, *args, **kwargs\n) -&gt; list[Schema]\n</code></pre> <p>List documents matching an optional filter.</p> <p>Parameters:</p> Name Type Description Default <code>filter</code> <code>dict | None</code> <p>Query filter passed to the repository.</p> <code>None</code> <p>Returns:</p> Type Description <code>list[Schema]</code> <p>list[Schema]: Matching documents.</p> Notes <p>Extra positional and keyword arguments are forwarded to the repository.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadCrudsService.update","title":"update <code>async</code>","text":"<pre><code>update(id: PyObjectId, data: Model | dict) -&gt; Schema | None\n</code></pre> <p>Replace a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>Model | dict</code> <p>Replacement model or field mapping.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UploadResult","title":"UploadResult","text":"<p> Bases: <code>BaseModel</code></p> <p>Metadata describing a stored file upload.</p> <p>Attributes:</p> Name Type Description <code>original_filename</code> <code>str</code> <p>Name of the file as uploaded by the client.</p> <code>saved_as</code> <code>str</code> <p>Name the file was stored under on disk.</p> <code>content_type</code> <code>str</code> <p>MIME type of the uploaded file.</p> <code>url</code> <code>str</code> <p>Public URL serving the stored file.</p> <code>absolute_path</code> <code>str</code> <p>Absolute filesystem path of the stored file.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService","title":"UserCrudsService","text":"<pre><code>UserCrudsService(*, repo=None)\n</code></pre> <p> Bases: <code>CrudsServiceAdaptor[User, UserDocument]</code></p> <p>User CRUD service resolving :class:<code>User</code> documents from a repo.</p> Notes <p>Instances are created by :func:<code>get_user_service</code>. The <code>model</code> and <code>schema</code> class attributes bind the domain model and its document type.</p> <p>Initialize the adaptor with a backing repository.</p> <p>Parameters:</p> Name Type Description Default <code>repo</code> <code>BaseRepository</code> <p>Repository used for all operations.</p> <code>None</code>"},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService.create","title":"create <code>async</code>","text":"<pre><code>create(data: Model | dict) -&gt; Schema\n</code></pre> <p>Create a document from a model or raw mapping.</p> <p>Parameters:</p> Name Type Description Default <code>data</code> <code>Model | dict</code> <p>Model instance or field mapping to persist.</p> required <p>Returns:</p> Name Type Description <code>Schema</code> <code>Schema</code> <p>Persisted document.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService.delete","title":"delete <code>async</code>","text":"<pre><code>delete(id: PyObjectId) -&gt; bool\n</code></pre> <p>Delete a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p><code>True</code> when a document was deleted.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService.model_to_dict","title":"model_to_dict <code>staticmethod</code>","text":"<pre><code>model_to_dict(model_obj: Model) -&gt; dict\n</code></pre> <p>Serialize a model into a sparse dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>model_obj</code> <code>Model</code> <p>Model instance to serialize.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Fields that are set and not <code>None</code>.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService.patch","title":"patch <code>async</code>","text":"<pre><code>patch(id: PyObjectId, data: dict) -&gt; Schema | None\n</code></pre> <p>Partially update a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>dict</code> <p>Fields to patch.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService.read","title":"read <code>async</code>","text":"<pre><code>read(id: PyObjectId) -&gt; Schema | None\n</code></pre> <p>Read a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Matching document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService.search","title":"search <code>async</code>","text":"<pre><code>search(\n filter: dict | None = None, *args, **kwargs\n) -&gt; list[Schema]\n</code></pre> <p>List documents matching an optional filter.</p> <p>Parameters:</p> Name Type Description Default <code>filter</code> <code>dict | None</code> <p>Query filter passed to the repository.</p> <code>None</code> <p>Returns:</p> Type Description <code>list[Schema]</code> <p>list[Schema]: Matching documents.</p> Notes <p>Extra positional and keyword arguments are forwarded to the repository.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.UserCrudsService.update","title":"update <code>async</code>","text":"<pre><code>update(id: PyObjectId, data: Model | dict) -&gt; Schema | None\n</code></pre> <p>Replace a document by primary key.</p> <p>Parameters:</p> Name Type Description Default <code>id</code> <code>PyObjectId</code> <p>Document identifier.</p> required <code>data</code> <code>Model | dict</code> <p>Replacement model or field mapping.</p> required <p>Returns:</p> Type Description <code>Schema | None</code> <p>Schema | None: Updated document, or <code>None</code> when absent.</p>"},{"location":"interfaces/openapi/#interfaces.openapi-functions","title":"Functions","text":""},{"location":"interfaces/openapi/#interfaces.openapi.cache_response","title":"cache_response","text":"<pre><code>cache_response(ttl: Optional[int] = None) -&gt; Callable\n</code></pre> <p>Decorate a GET-style route handler to cache its JSON response.</p> <p>Parameters:</p> Name Type Description Default <code>ttl</code> <code>Optional[int]</code> <p>Cache lifetime in seconds; defaults to <code>settings.cache_ttl</code>.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>Callable</code> <code>Callable</code> <p>Decorator that wraps the route handler.</p> Notes <p>The wrapped handler must accept a <code>request: Request</code> parameter (as every openapi_first handler does). Responses that are already a <code>fastapi.Response</code> (for example 204) are returned untouched and never cached. When no <code>http_cache_store</code> is wired on <code>request.app.state.db_resources</code> the decorator passes through to the handler without caching.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.create_account","title":"create_account <code>async</code>","text":"<pre><code>create_account(request: Request, body: dict)\n</code></pre> <p>Create a new account.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Account payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>AccountDocument</code> <p>The created account.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.create_entity","title":"create_entity <code>async</code>","text":"<pre><code>create_entity(request: Request, body: dict)\n</code></pre> <p>Create a new entity.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Entity payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>EntityDocument</code> <p>The created entity.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.create_expense","title":"create_expense <code>async</code>","text":"<pre><code>create_expense(request: Request, body: dict)\n</code></pre> <p>Create a new expense.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Expense payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>ExpenseDocument</code> <p>The created expense.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.create_fetch_request","title":"create_fetch_request <code>async</code>","text":"<pre><code>create_fetch_request(request: Request, body: dict)\n</code></pre> <p>Create a new fetch request.</p> <p>A stable fingerprint is derived from the source payload and stored on the document when the payload does not already provide one.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Fetch request payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestDocument</code> <p>The created fetch request.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.create_report","title":"create_report <code>async</code>","text":"<pre><code>create_report(request: Request, body: dict)\n</code></pre> <p>Generate a report snapshot from a query definition.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Report query payload; validated into a ReportQuery.</p> required <p>Returns:</p> Name Type Description <code>ReportSnapshotDocument</code> <p>The generated snapshot.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>400 when the query payload is invalid.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.create_tag","title":"create_tag <code>async</code>","text":"<pre><code>create_tag(request: Request, body: dict)\n</code></pre> <p>Create a new tag.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Tag payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>TagDocument</code> <p>The created tag.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.create_user","title":"create_user <code>async</code>","text":"<pre><code>create_user(request: Request, body: dict)\n</code></pre> <p>Create a new user.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>User payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>UserDocument</code> <p>The created user.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.delete_account","title":"delete_account <code>async</code>","text":"<pre><code>delete_account(request: Request, id: str)\n</code></pre> <p>Delete an account by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Account id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no account matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.delete_entity","title":"delete_entity <code>async</code>","text":"<pre><code>delete_entity(request: Request, id: str)\n</code></pre> <p>Delete an entity by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Entity id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no entity matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.delete_expense","title":"delete_expense <code>async</code>","text":"<pre><code>delete_expense(request: Request, id: str)\n</code></pre> <p>Delete an expense by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Expense id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no expense matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.delete_fetch_request","title":"delete_fetch_request <code>async</code>","text":"<pre><code>delete_fetch_request(request: Request, id: str)\n</code></pre> <p>Delete a fetch request and its dependent data.</p> <p>Cascades deletes to related expenses and ambiguities, removes the fetch request, and invalidates the expenses HTTP cache.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no fetch request matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.delete_report","title":"delete_report <code>async</code>","text":"<pre><code>delete_report(request: Request, id: str)\n</code></pre> <p>Delete a report snapshot by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Report snapshot id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when the snapshot does not exist.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.delete_tag","title":"delete_tag <code>async</code>","text":"<pre><code>delete_tag(request: Request, id: str)\n</code></pre> <p>Delete a tag by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Tag id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no tag matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_account","title":"get_account <code>async</code>","text":"<pre><code>get_account(request: Request, id: str)\n</code></pre> <p>Get an account by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Account id.</p> required <p>Returns:</p> Name Type Description <code>AccountDocument</code> <p>The matching account.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no account matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_current_user","title":"get_current_user <code>async</code>","text":"<pre><code>get_current_user(request: Request)\n</code></pre> <p>Get the profile of the authenticated user.</p> <p>Reads the principal from request.state and creates the profile on first access when it does not exist yet.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries the authenticated user and app.state.db_resources.</p> required <p>Returns:</p> Name Type Description <code>UserDocument</code> <p>The current user's profile.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>401 when the request is not authenticated.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_entity","title":"get_entity <code>async</code>","text":"<pre><code>get_entity(request: Request, id: str)\n</code></pre> <p>Get an entity by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Entity id.</p> required <p>Returns:</p> Name Type Description <code>EntityDocument</code> <p>The matching entity.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no entity matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_expense","title":"get_expense <code>async</code>","text":"<pre><code>get_expense(request: Request, id: str)\n</code></pre> <p>Get an expense by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Expense id.</p> required <p>Returns:</p> Name Type Description <code>ExpenseDocument</code> <p>The matching expense.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no expense matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_fetch_request","title":"get_fetch_request <code>async</code>","text":"<pre><code>get_fetch_request(request: Request, id: str)\n</code></pre> <p>Get a fetch request by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestDocument</code> <p>The matching fetch request.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no fetch request matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_report","title":"get_report <code>async</code>","text":"<pre><code>get_report(\n request: Request,\n id: str,\n granularity: Optional[List[str]] = Query(None),\n period_ids: Optional[List[str]] = Query(None),\n flow: str = \"outflows\",\n payee: Optional[List[str]] = Query(None),\n tags: Optional[List[str]] = Query(None),\n)\n</code></pre> <p>Fetch a report snapshot with optional granularity, flow, and filter overrides.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Report snapshot id.</p> required <code>granularity</code> <code>Optional[List[str]]</code> <p>Granularities to materialize; empty means the snapshot's default set.</p> <code>Query(None)</code> <code>period_ids</code> <code>Optional[List[str]]</code> <p>Period labels to constrain output.</p> <code>Query(None)</code> <code>flow</code> <code>str</code> <p>Flow filter of inflows, outflows, or both. Defaults to outflows.</p> <code>'outflows'</code> <code>payee</code> <code>Optional[List[str]]</code> <p>Payee names to include.</p> <code>Query(None)</code> <code>tags</code> <code>Optional[List[str]]</code> <p>Tag paths to include.</p> <code>Query(None)</code> <p>Returns:</p> Name Type Description <code>Report</code> <p>The fetched report.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>400 when the report arguments are invalid.</p> <code>HTTPException</code> <p>404 when the snapshot does not exist.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_tag","title":"get_tag <code>async</code>","text":"<pre><code>get_tag(request: Request, id: str)\n</code></pre> <p>Get a tag by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Tag id.</p> required <p>Returns:</p> Name Type Description <code>TagDocument</code> <p>The matching tag.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no tag matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_uploaded_file","title":"get_uploaded_file <code>async</code>","text":"<pre><code>get_uploaded_file(request: Request, filepath: str)\n</code></pre> <p>Serve an uploaded file from disk.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request.</p> required <code>filepath</code> <code>str</code> <p>Relative path of the file under UPLOAD_DIR.</p> required <p>Returns:</p> Name Type Description <code>FileResponse</code> <p>The requested file with its original filename.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when the file does not exist.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.get_user","title":"get_user <code>async</code>","text":"<pre><code>get_user(request: Request, id: str)\n</code></pre> <p>Get a user by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>User id.</p> required <p>Returns:</p> Name Type Description <code>UserDocument</code> <p>The matching user.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no user matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_accounts","title":"list_accounts <code>async</code>","text":"<pre><code>list_accounts(\n request: Request, skip: int = 0, limit: int = 100\n)\n</code></pre> <p>List accounts with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>skip</code> <code>int</code> <p>Number of accounts to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of accounts to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[AccountDocument]: Matching accounts from AccountCrudsService.search.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_ambiguities","title":"list_ambiguities <code>async</code>","text":"<pre><code>list_ambiguities(request: Request, id: str)\n</code></pre> <p>List pending ambiguities for a fetch request.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Name Type Description <code>list</code> <p>Pending ambiguity documents from the ambiguity service.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_entities","title":"list_entities <code>async</code>","text":"<pre><code>list_entities(\n request: Request, skip: int = 0, limit: int = 100\n)\n</code></pre> <p>List entities with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>skip</code> <code>int</code> <p>Number of entities to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of entities to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[EntityDocument]: Matching entities from EntityCrudsService.search.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_expenses","title":"list_expenses <code>async</code>","text":"<pre><code>list_expenses(\n request: Request,\n offset: int = 0,\n limit: int = 10,\n start_date: str = \"\",\n end_date: str = \"\",\n)\n</code></pre> <p>List expenses with pagination, excluding self-transfers.</p> <p>Expenses tagged with a self-transfer tag are filtered out. The start_date and end_date parameters are accepted by the signature but not applied to the underlying search filter.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>offset</code> <code>int</code> <p>Number of expenses to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of expenses to return. Defaults to 10.</p> <code>10</code> <code>start_date</code> <code>str</code> <p>Accepted date-range start; not applied to the search.</p> <code>''</code> <code>end_date</code> <code>str</code> <p>Accepted date-range end; not applied to the search.</p> <code>''</code> <p>Returns:</p> Type Description <p>list[ExpenseDocument]: Matching expenses from ExpenseCrudsService.search.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_fetch_requests","title":"list_fetch_requests <code>async</code>","text":"<pre><code>list_fetch_requests(\n request: Request, offset: int = 0, limit: int = 100\n)\n</code></pre> <p>List fetch requests with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>offset</code> <code>int</code> <p>Number of fetch requests to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of fetch requests to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[FetchRequestDocument]: Matching fetch requests from the service.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_reports","title":"list_reports <code>async</code>","text":"<pre><code>list_reports(\n request: Request, offset: int = 0, limit: int = 100\n)\n</code></pre> <p>List report snapshots with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>offset</code> <code>int</code> <p>Number of snapshots to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of snapshots to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[ReportSnapshotDocument]: Matching snapshots from the report service.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_tags","title":"list_tags <code>async</code>","text":"<pre><code>list_tags(\n request: Request, skip: int = 0, limit: int = 1000\n)\n</code></pre> <p>List tags with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>skip</code> <code>int</code> <p>Number of tags to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of tags to return. Defaults to 1000.</p> <code>1000</code> <p>Returns:</p> Type Description <p>list[TagDocument]: Matching tags from TagCrudsService.search.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_uploads","title":"list_uploads <code>async</code>","text":"<pre><code>list_uploads(request: Request)\n</code></pre> <p>List all upload records.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <p>Returns:</p> Type Description <p>list[UploadDocument]: All uploads from the upload service.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.list_users","title":"list_users <code>async</code>","text":"<pre><code>list_users(\n request: Request, skip: int = 0, limit: int = 100\n)\n</code></pre> <p>List users with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>skip</code> <code>int</code> <p>Number of users to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of users to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[UserDocument]: Matching users from UserCrudsService.search.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.resolve_ambiguity","title":"resolve_ambiguity <code>async</code>","text":"<pre><code>resolve_ambiguity(request: Request, id: str, body: dict)\n</code></pre> <p>Resolve an ambiguity by choosing one of its candidates.</p> <p>Marks the ambiguity resolved, then requeues the parent fetch request when no pending ambiguities remain and the fetch request is paused.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Ambiguity id.</p> required <code>body</code> <code>dict</code> <p>Resolution payload; must contain the chosen candidate.</p> required <p>Returns:</p> Type Description <p>Updated ambiguity document.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>400 when the chosen candidate is missing.</p> <code>HTTPException</code> <p>404 when the ambiguity is not found.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.stream_fetch_events","title":"stream_fetch_events <code>async</code>","text":"<pre><code>stream_fetch_events(request: Request, id: str)\n</code></pre> <p>Stream progress events for a fetch request as server-sent events.</p> <p>If the SSE bus is not configured on app.state.db_resources an empty events list is returned. Otherwise a <code>text/event-stream</code> response is yielded, polling the bus every 500 ms until the client disconnects.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Type Description <p>StreamingResponse | dict: SSE stream, or <code>{\"events\": []}</code> when the bus</p> <p>is unavailable.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.update_account","title":"update_account <code>async</code>","text":"<pre><code>update_account(request: Request, id: str, body: dict)\n</code></pre> <p>Update an account by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Account id.</p> required <code>body</code> <code>dict</code> <p>Fields to update, forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>AccountDocument</code> <p>The updated account.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no account matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.update_current_user","title":"update_current_user <code>async</code>","text":"<pre><code>update_current_user(request: Request, body: dict)\n</code></pre> <p>Update the profile of the authenticated user.</p> <p>Creates the profile on first access, then applies the update payload.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries the authenticated user and app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Fields to update on the current user's profile.</p> required <p>Returns:</p> Name Type Description <code>UserDocument</code> <p>The updated profile.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>401 when the request is not authenticated.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.update_entity","title":"update_entity <code>async</code>","text":"<pre><code>update_entity(request: Request, id: str, body: dict)\n</code></pre> <p>Update an entity by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Entity id.</p> required <code>body</code> <code>dict</code> <p>Fields to update, forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>EntityDocument</code> <p>The updated entity.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no entity matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.update_expense","title":"update_expense <code>async</code>","text":"<pre><code>update_expense(request: Request, id: str, body: dict)\n</code></pre> <p>Update an expense by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Expense id.</p> required <code>body</code> <code>dict</code> <p>Fields to update, forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>ExpenseDocument</code> <p>The updated expense.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no expense matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.update_fetch_request","title":"update_fetch_request <code>async</code>","text":"<pre><code>update_fetch_request(request: Request, id: str, body: dict)\n</code></pre> <p>Patch a fetch request's status and retry bookkeeping.</p> <p>Delegates to FetchRequestCrudsService.update_status with the status, error_message, and retry_count fields from the payload, then returns the refreshed document.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <code>body</code> <code>dict</code> <p>Payload with status, error_message, and retry_count fields.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestDocument</code> <p>The refreshed fetch request.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no fetch request matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.update_fetch_request_put","title":"update_fetch_request_put <code>async</code>","text":"<pre><code>update_fetch_request_put(\n request: Request, id: str, body: dict\n)\n</code></pre> <p>Replace a fetch request by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <code>body</code> <code>dict</code> <p>Full fetch request payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestDocument</code> <p>The updated fetch request.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no fetch request matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.update_tag","title":"update_tag <code>async</code>","text":"<pre><code>update_tag(request: Request, id: str, body: dict)\n</code></pre> <p>Update a tag by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Tag id.</p> required <code>body</code> <code>dict</code> <p>Fields to update, forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>TagDocument</code> <p>The updated tag.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no tag matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.upload_entity_logo","title":"upload_entity_logo <code>async</code>","text":"<pre><code>upload_entity_logo(\n request: Request, id: str, file: UploadFile\n)\n</code></pre> <p>Upload a logo for an entity and persist it to the logo directory.</p> <p>The file contents are hashed to derive a stable filename, written under LOGO_DIR, and the entity's logo field is updated with the served URL.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Entity id.</p> required <code>file</code> <code>UploadFile</code> <p>Uploaded logo image.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <p>A mapping with keys id, url, logo, and status.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no entity matches the id.</p>"},{"location":"interfaces/openapi/#interfaces.openapi.upload_file","title":"upload_file <code>async</code>","text":"<pre><code>upload_file(request: Request)\n</code></pre> <p>Upload a raw request body as a file.</p> <p>The filename is parsed from the content-disposition header (defaulting to <code>upload</code>) and combined with a content hash to form the stored filename under UPLOAD_DIR. The resulting UploadResult is persisted via the upload service.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries the body, content type, and app.state.db_resources.</p> required <p>Returns:</p> Name Type Description <code>UploadDocument</code> <p>The created upload record.</p>"},{"location":"interfaces/account/","title":"Account","text":"<ul> <li>Routes</li> </ul>"},{"location":"interfaces/account/#interfaces.account","title":"interfaces.account","text":""},{"location":"interfaces/account/#interfaces.account--summary","title":"Summary","text":"<p>Account interface: thin FastAPI route handlers for the account resource, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/account/routes/","title":"Routes","text":""},{"location":"interfaces/account/routes/#interfaces.account.routes","title":"interfaces.account.routes","text":""},{"location":"interfaces/account/routes/#interfaces.account.routes--summary","title":"Summary","text":"<p>Account REST handlers \u2014 thin API entry points for the account resource, wired to openapi.yaml operationIds by the OpenAPI-first router. All handlers delegate to AccountCrudsService via request.app.state.db_resources.</p>"},{"location":"interfaces/account/routes/#interfaces.account.routes-classes","title":"Classes","text":""},{"location":"interfaces/account/routes/#interfaces.account.routes-functions","title":"Functions","text":""},{"location":"interfaces/account/routes/#interfaces.account.routes.create_account","title":"create_account <code>async</code>","text":"<pre><code>create_account(request: Request, body: dict)\n</code></pre> <p>Create a new account.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Account payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>AccountDocument</code> <p>The created account.</p>"},{"location":"interfaces/account/routes/#interfaces.account.routes.delete_account","title":"delete_account <code>async</code>","text":"<pre><code>delete_account(request: Request, id: str)\n</code></pre> <p>Delete an account by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Account id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no account matches the id.</p>"},{"location":"interfaces/account/routes/#interfaces.account.routes.get_account","title":"get_account <code>async</code>","text":"<pre><code>get_account(request: Request, id: str)\n</code></pre> <p>Get an account by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Account id.</p> required <p>Returns:</p> Name Type Description <code>AccountDocument</code> <p>The matching account.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no account matches the id.</p>"},{"location":"interfaces/account/routes/#interfaces.account.routes.list_accounts","title":"list_accounts <code>async</code>","text":"<pre><code>list_accounts(\n request: Request, skip: int = 0, limit: int = 100\n)\n</code></pre> <p>List accounts with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>skip</code> <code>int</code> <p>Number of accounts to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of accounts to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[AccountDocument]: Matching accounts from AccountCrudsService.search.</p>"},{"location":"interfaces/account/routes/#interfaces.account.routes.update_account","title":"update_account <code>async</code>","text":"<pre><code>update_account(request: Request, id: str, body: dict)\n</code></pre> <p>Update an account by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Account id.</p> required <code>body</code> <code>dict</code> <p>Fields to update, forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>AccountDocument</code> <p>The updated account.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no account matches the id.</p>"},{"location":"interfaces/ambiguity/","title":"Ambiguity","text":"<ul> <li>Routes</li> </ul>"},{"location":"interfaces/ambiguity/#interfaces.ambiguity","title":"interfaces.ambiguity","text":""},{"location":"interfaces/ambiguity/#interfaces.ambiguity--summary","title":"Summary","text":"<p>Ambiguity interface: thin FastAPI route handlers for the ambiguity resource, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/ambiguity/routes/","title":"Routes","text":""},{"location":"interfaces/ambiguity/routes/#interfaces.ambiguity.routes","title":"interfaces.ambiguity.routes","text":""},{"location":"interfaces/ambiguity/routes/#interfaces.ambiguity.routes--summary","title":"Summary","text":"<p>Ambiguity REST handlers \u2014 thin API entry points for the ambiguity resource, wired to openapi.yaml operationIds by the OpenAPI-first router. Resolution updates the ambiguity and requeues the parent fetch request when no pending ambiguities remain.</p>"},{"location":"interfaces/ambiguity/routes/#interfaces.ambiguity.routes-functions","title":"Functions","text":""},{"location":"interfaces/ambiguity/routes/#interfaces.ambiguity.routes.resolve_ambiguity","title":"resolve_ambiguity <code>async</code>","text":"<pre><code>resolve_ambiguity(request: Request, id: str, body: dict)\n</code></pre> <p>Resolve an ambiguity by choosing one of its candidates.</p> <p>Marks the ambiguity resolved, then requeues the parent fetch request when no pending ambiguities remain and the fetch request is paused.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Ambiguity id.</p> required <code>body</code> <code>dict</code> <p>Resolution payload; must contain the chosen candidate.</p> required <p>Returns:</p> Type Description <p>Updated ambiguity document.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>400 when the chosen candidate is missing.</p> <code>HTTPException</code> <p>404 when the ambiguity is not found.</p>"},{"location":"interfaces/entity/","title":"Entity","text":"<ul> <li>Routes</li> </ul>"},{"location":"interfaces/entity/#interfaces.entity","title":"interfaces.entity","text":""},{"location":"interfaces/entity/#interfaces.entity--summary","title":"Summary","text":"<p>Entity interface: thin FastAPI route handlers for the entity resource, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/entity/routes/","title":"Routes","text":""},{"location":"interfaces/entity/routes/#interfaces.entity.routes","title":"interfaces.entity.routes","text":""},{"location":"interfaces/entity/routes/#interfaces.entity.routes--summary","title":"Summary","text":"<p>Entity REST handlers \u2014 thin API entry points for the entity resource, wired to openapi.yaml operationIds by the OpenAPI-first router. All handlers delegate to EntityCrudsService via request.app.state.db_resources.</p>"},{"location":"interfaces/entity/routes/#interfaces.entity.routes-classes","title":"Classes","text":""},{"location":"interfaces/entity/routes/#interfaces.entity.routes-functions","title":"Functions","text":""},{"location":"interfaces/entity/routes/#interfaces.entity.routes.create_entity","title":"create_entity <code>async</code>","text":"<pre><code>create_entity(request: Request, body: dict)\n</code></pre> <p>Create a new entity.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Entity payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>EntityDocument</code> <p>The created entity.</p>"},{"location":"interfaces/entity/routes/#interfaces.entity.routes.delete_entity","title":"delete_entity <code>async</code>","text":"<pre><code>delete_entity(request: Request, id: str)\n</code></pre> <p>Delete an entity by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Entity id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no entity matches the id.</p>"},{"location":"interfaces/entity/routes/#interfaces.entity.routes.get_entity","title":"get_entity <code>async</code>","text":"<pre><code>get_entity(request: Request, id: str)\n</code></pre> <p>Get an entity by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Entity id.</p> required <p>Returns:</p> Name Type Description <code>EntityDocument</code> <p>The matching entity.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no entity matches the id.</p>"},{"location":"interfaces/entity/routes/#interfaces.entity.routes.list_entities","title":"list_entities <code>async</code>","text":"<pre><code>list_entities(\n request: Request, skip: int = 0, limit: int = 100\n)\n</code></pre> <p>List entities with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>skip</code> <code>int</code> <p>Number of entities to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of entities to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[EntityDocument]: Matching entities from EntityCrudsService.search.</p>"},{"location":"interfaces/entity/routes/#interfaces.entity.routes.update_entity","title":"update_entity <code>async</code>","text":"<pre><code>update_entity(request: Request, id: str, body: dict)\n</code></pre> <p>Update an entity by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Entity id.</p> required <code>body</code> <code>dict</code> <p>Fields to update, forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>EntityDocument</code> <p>The updated entity.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no entity matches the id.</p>"},{"location":"interfaces/entity/routes/#interfaces.entity.routes.upload_entity_logo","title":"upload_entity_logo <code>async</code>","text":"<pre><code>upload_entity_logo(\n request: Request, id: str, file: UploadFile\n)\n</code></pre> <p>Upload a logo for an entity and persist it to the logo directory.</p> <p>The file contents are hashed to derive a stable filename, written under LOGO_DIR, and the entity's logo field is updated with the served URL.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Entity id.</p> required <code>file</code> <code>UploadFile</code> <p>Uploaded logo image.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <p>A mapping with keys id, url, logo, and status.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no entity matches the id.</p>"},{"location":"interfaces/expense/","title":"Expense","text":"<ul> <li>Routes</li> </ul>"},{"location":"interfaces/expense/#interfaces.expense","title":"interfaces.expense","text":""},{"location":"interfaces/expense/#interfaces.expense--summary","title":"Summary","text":"<p>Expense interface: thin FastAPI route handlers for the expense resource, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/expense/routes/","title":"Routes","text":""},{"location":"interfaces/expense/routes/#interfaces.expense.routes","title":"interfaces.expense.routes","text":""},{"location":"interfaces/expense/routes/#interfaces.expense.routes--summary","title":"Summary","text":"<p>Expense REST handlers \u2014 thin API entry points for the expense resource, wired to openapi.yaml operationIds by the OpenAPI-first router. All handlers delegate to ExpenseCrudsService via request.app.state.db_resources.</p>"},{"location":"interfaces/expense/routes/#interfaces.expense.routes-classes","title":"Classes","text":""},{"location":"interfaces/expense/routes/#interfaces.expense.routes-functions","title":"Functions","text":""},{"location":"interfaces/expense/routes/#interfaces.expense.routes.create_expense","title":"create_expense <code>async</code>","text":"<pre><code>create_expense(request: Request, body: dict)\n</code></pre> <p>Create a new expense.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Expense payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>ExpenseDocument</code> <p>The created expense.</p>"},{"location":"interfaces/expense/routes/#interfaces.expense.routes.delete_expense","title":"delete_expense <code>async</code>","text":"<pre><code>delete_expense(request: Request, id: str)\n</code></pre> <p>Delete an expense by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Expense id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no expense matches the id.</p>"},{"location":"interfaces/expense/routes/#interfaces.expense.routes.get_expense","title":"get_expense <code>async</code>","text":"<pre><code>get_expense(request: Request, id: str)\n</code></pre> <p>Get an expense by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Expense id.</p> required <p>Returns:</p> Name Type Description <code>ExpenseDocument</code> <p>The matching expense.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no expense matches the id.</p>"},{"location":"interfaces/expense/routes/#interfaces.expense.routes.list_expenses","title":"list_expenses <code>async</code>","text":"<pre><code>list_expenses(\n request: Request,\n offset: int = 0,\n limit: int = 10,\n start_date: str = \"\",\n end_date: str = \"\",\n)\n</code></pre> <p>List expenses with pagination, excluding self-transfers.</p> <p>Expenses tagged with a self-transfer tag are filtered out. The start_date and end_date parameters are accepted by the signature but not applied to the underlying search filter.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>offset</code> <code>int</code> <p>Number of expenses to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of expenses to return. Defaults to 10.</p> <code>10</code> <code>start_date</code> <code>str</code> <p>Accepted date-range start; not applied to the search.</p> <code>''</code> <code>end_date</code> <code>str</code> <p>Accepted date-range end; not applied to the search.</p> <code>''</code> <p>Returns:</p> Type Description <p>list[ExpenseDocument]: Matching expenses from ExpenseCrudsService.search.</p>"},{"location":"interfaces/expense/routes/#interfaces.expense.routes.update_expense","title":"update_expense <code>async</code>","text":"<pre><code>update_expense(request: Request, id: str, body: dict)\n</code></pre> <p>Update an expense by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Expense id.</p> required <code>body</code> <code>dict</code> <p>Fields to update, forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>ExpenseDocument</code> <p>The updated expense.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no expense matches the id.</p>"},{"location":"interfaces/fetch_request/","title":"Fetch Request","text":"<ul> <li>Cli</li> <li>Routes</li> <li>Sse</li> </ul>"},{"location":"interfaces/fetch_request/#interfaces.fetch_request","title":"interfaces.fetch_request","text":""},{"location":"interfaces/fetch_request/#interfaces.fetch_request--summary","title":"Summary","text":"<p>Fetch request interface: thin FastAPI route handlers, SSE handlers, and a CLI for the fetch request resource, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/fetch_request/routes/","title":"Routes","text":""},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes","title":"interfaces.fetch_request.routes","text":""},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes--summary","title":"Summary","text":"<p>Fetch request REST handlers \u2014 thin API entry points for the fetch request resource, wired to openapi.yaml operationIds by the OpenAPI-first router. Deletion cascades to related expenses, ambiguities, and the HTTP cache.</p>"},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes-classes","title":"Classes","text":""},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes-functions","title":"Functions","text":""},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes.create_fetch_request","title":"create_fetch_request <code>async</code>","text":"<pre><code>create_fetch_request(request: Request, body: dict)\n</code></pre> <p>Create a new fetch request.</p> <p>A stable fingerprint is derived from the source payload and stored on the document when the payload does not already provide one.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Fetch request payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestDocument</code> <p>The created fetch request.</p>"},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes.delete_fetch_request","title":"delete_fetch_request <code>async</code>","text":"<pre><code>delete_fetch_request(request: Request, id: str)\n</code></pre> <p>Delete a fetch request and its dependent data.</p> <p>Cascades deletes to related expenses and ambiguities, removes the fetch request, and invalidates the expenses HTTP cache.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no fetch request matches the id.</p>"},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes.get_fetch_request","title":"get_fetch_request <code>async</code>","text":"<pre><code>get_fetch_request(request: Request, id: str)\n</code></pre> <p>Get a fetch request by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestDocument</code> <p>The matching fetch request.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no fetch request matches the id.</p>"},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes.list_fetch_requests","title":"list_fetch_requests <code>async</code>","text":"<pre><code>list_fetch_requests(\n request: Request, offset: int = 0, limit: int = 100\n)\n</code></pre> <p>List fetch requests with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>offset</code> <code>int</code> <p>Number of fetch requests to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of fetch requests to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[FetchRequestDocument]: Matching fetch requests from the service.</p>"},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes.update_fetch_request","title":"update_fetch_request <code>async</code>","text":"<pre><code>update_fetch_request(request: Request, id: str, body: dict)\n</code></pre> <p>Patch a fetch request's status and retry bookkeeping.</p> <p>Delegates to FetchRequestCrudsService.update_status with the status, error_message, and retry_count fields from the payload, then returns the refreshed document.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <code>body</code> <code>dict</code> <p>Payload with status, error_message, and retry_count fields.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestDocument</code> <p>The refreshed fetch request.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no fetch request matches the id.</p>"},{"location":"interfaces/fetch_request/routes/#interfaces.fetch_request.routes.update_fetch_request_put","title":"update_fetch_request_put <code>async</code>","text":"<pre><code>update_fetch_request_put(\n request: Request, id: str, body: dict\n)\n</code></pre> <p>Replace a fetch request by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <code>body</code> <code>dict</code> <p>Full fetch request payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>FetchRequestDocument</code> <p>The updated fetch request.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no fetch request matches the id.</p>"},{"location":"interfaces/fetch_request/sse/","title":"Sse","text":""},{"location":"interfaces/fetch_request/sse/#interfaces.fetch_request.sse","title":"interfaces.fetch_request.sse","text":""},{"location":"interfaces/fetch_request/sse/#interfaces.fetch_request.sse--summary","title":"Summary","text":"<p>Fetch request SSE handlers \u2014 real-time progress events and ambiguity listing for a given fetch request. Events are streamed via an SSE bus; ambiguities are queried directly from the ambiguity service.</p>"},{"location":"interfaces/fetch_request/sse/#interfaces.fetch_request.sse-functions","title":"Functions","text":""},{"location":"interfaces/fetch_request/sse/#interfaces.fetch_request.sse.list_ambiguities","title":"list_ambiguities <code>async</code>","text":"<pre><code>list_ambiguities(request: Request, id: str)\n</code></pre> <p>List pending ambiguities for a fetch request.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Name Type Description <code>list</code> <p>Pending ambiguity documents from the ambiguity service.</p>"},{"location":"interfaces/fetch_request/sse/#interfaces.fetch_request.sse.stream_fetch_events","title":"stream_fetch_events <code>async</code>","text":"<pre><code>stream_fetch_events(request: Request, id: str)\n</code></pre> <p>Stream progress events for a fetch request as server-sent events.</p> <p>If the SSE bus is not configured on app.state.db_resources an empty events list is returned. Otherwise a <code>text/event-stream</code> response is yielded, polling the bus every 500 ms until the client disconnects.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Fetch request id.</p> required <p>Returns:</p> Type Description <p>StreamingResponse | dict: SSE stream, or <code>{\"events\": []}</code> when the bus</p> <p>is unavailable.</p>"},{"location":"interfaces/fetch_request/cli/","title":"Cli","text":"<ul> <li> Main </li> <li>Commands</li> <li>Run</li> </ul>"},{"location":"interfaces/fetch_request/cli/#interfaces.fetch_request.cli","title":"interfaces.fetch_request.cli","text":""},{"location":"interfaces/fetch_request/cli/#interfaces.fetch_request.cli--summary","title":"Summary","text":"<p>Fetch request CLI package: argparse-driven command entry point (main), subcommand implementations (commands), and the pipeline runner (run).</p>"},{"location":"interfaces/fetch_request/cli/__main__/","title":"Main","text":""},{"location":"interfaces/fetch_request/cli/__main__/#interfaces.fetch_request.cli.__main__","title":"interfaces.fetch_request.cli.__main__","text":""},{"location":"interfaces/fetch_request/cli/__main__/#interfaces.fetch_request.cli.__main__--summary","title":"Summary","text":"<p>CLI for FetchRequest management \u2014 list, get, create, run, resolve, retry.</p> <p>Example:</p> <pre><code>```python\npython -m interfaces.fetch_request.cli list\npython -m interfaces.fetch_request.cli get &lt;id&gt;\npython -m interfaces.fetch_request.cli create-file --account \"ICICI Savings\" --path ./stmt.pdf --start-date 2025-04-01 --end-date 2026-03-31\npython -m interfaces.fetch_request.cli run &lt;id&gt;\npython -m interfaces.fetch_request.cli ambiguities &lt;fr_id&gt;\npython -m interfaces.fetch_request.cli resolve &lt;fr_id&gt;\npython -m interfaces.fetch_request.cli retry &lt;id&gt;\n```\n</code></pre>"},{"location":"interfaces/fetch_request/cli/__main__/#interfaces.fetch_request.cli.__main__-classes","title":"Classes","text":""},{"location":"interfaces/fetch_request/cli/__main__/#interfaces.fetch_request.cli.__main__-functions","title":"Functions","text":""},{"location":"interfaces/fetch_request/cli/__main__/#interfaces.fetch_request.cli.__main__.main","title":"main <code>async</code>","text":"<pre><code>main()\n</code></pre> <p>Run the FetchRequest CLI: parse arguments, dispatch to a subcommand.</p> <p>Initializes the application resources before dispatch and shuts them down afterwards.</p>"},{"location":"interfaces/fetch_request/cli/commands/","title":"Commands","text":""},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands","title":"interfaces.fetch_request.cli.commands","text":""},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands--summary","title":"Summary","text":"<p>Subcommand implementations: list, get, create-file, create-email, ambiguities, resolve, retry. Each <code>cmd_*</code> function receives the parsed argparse namespace and prints its result to stdout.</p>"},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands-classes","title":"Classes","text":""},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands-functions","title":"Functions","text":""},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands.cmd_ambiguities","title":"cmd_ambiguities <code>async</code>","text":"<pre><code>cmd_ambiguities(args)\n</code></pre> <p>List ambiguities for a fetch request, optionally cleaning them.</p> <p>Parameters:</p> Name Type Description Default <code>args</code> <p>Parsed argparse namespace with fr_id, status, clean, and yes fields.</p> required"},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands.cmd_create_email","title":"cmd_create_email <code>async</code>","text":"<pre><code>cmd_create_email(args)\n</code></pre> <p>Create an email-based fetch request.</p> <p>Requires an existing account and user; parses the date range, builds an EmailSource, and persists the created fetch request.</p> <p>Parameters:</p> Name Type Description Default <code>args</code> <p>Parsed argparse namespace with account, user, from-email, bank, subject, raw-terms, start-date, and end-date fields.</p> required"},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands.cmd_create_file","title":"cmd_create_file <code>async</code>","text":"<pre><code>cmd_create_file(args)\n</code></pre> <p>Create a file-based fetch request.</p> <p>Requires an existing account and user; parses the date range, builds a FileSource, and persists the created fetch request.</p> <p>Parameters:</p> Name Type Description Default <code>args</code> <p>Parsed argparse namespace with account, user, path, bank, start-date, and end-date fields.</p> required"},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands.cmd_get","title":"cmd_get <code>async</code>","text":"<pre><code>cmd_get(args)\n</code></pre> <p>Show details of a single fetch request.</p> <p>Parameters:</p> Name Type Description Default <code>args</code> <p>Parsed argparse namespace with the id field.</p> required"},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands.cmd_list","title":"cmd_list <code>async</code>","text":"<pre><code>cmd_list(args)\n</code></pre> <p>List fetch requests, optionally filtered by status and account.</p> <p>Parameters:</p> Name Type Description Default <code>args</code> <p>Parsed argparse namespace with status, account, and limit fields.</p> required"},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands.cmd_resolve","title":"cmd_resolve <code>async</code>","text":"<pre><code>cmd_resolve(args)\n</code></pre> <p>Resolve ambiguities, interactively or directly by amount and balance.</p> <p>Parameters:</p> Name Type Description Default <code>args</code> <p>Parsed argparse namespace with fr_id, ambiguity-id, amount, and balance fields.</p> required"},{"location":"interfaces/fetch_request/cli/commands/#interfaces.fetch_request.cli.commands.cmd_retry","title":"cmd_retry <code>async</code>","text":"<pre><code>cmd_retry(args)\n</code></pre> <p>Reset a failed or paused fetch request back to pending.</p> <p>Optionally clears extracted data such as raw_lines and txn_blocks.</p> <p>Parameters:</p> Name Type Description Default <code>args</code> <p>Parsed argparse namespace with the id and reset-data fields.</p> required"},{"location":"interfaces/fetch_request/cli/run/","title":"Run","text":""},{"location":"interfaces/fetch_request/cli/run/#interfaces.fetch_request.cli.run","title":"interfaces.fetch_request.cli.run","text":""},{"location":"interfaces/fetch_request/cli/run/#interfaces.fetch_request.cli.run--summary","title":"Summary","text":"<p>Pipeline runner subcommand \u2014 drives _extract \u2192 _enrich \u2192 _process_expenses with a --till guard that stops the run after a given stage.</p>"},{"location":"interfaces/fetch_request/cli/run/#interfaces.fetch_request.cli.run-classes","title":"Classes","text":""},{"location":"interfaces/fetch_request/cli/run/#interfaces.fetch_request.cli.run-functions","title":"Functions","text":""},{"location":"interfaces/fetch_request/cli/run/#interfaces.fetch_request.cli.run.cmd_run","title":"cmd_run <code>async</code>","text":"<pre><code>cmd_run(args)\n</code></pre> <p>Run the pipeline for a fetch request using parsed CLI arguments.</p> <p>Parameters:</p> Name Type Description Default <code>args</code> <p>Parsed argparse namespace with id, till, force, and resume fields.</p> required"},{"location":"interfaces/fetch_request/cli/run/#interfaces.fetch_request.cli.run.run_pipeline","title":"run_pipeline <code>async</code>","text":"<pre><code>run_pipeline(\n fr_id: str,\n *,\n till: str = \"expense\",\n force: bool = False,\n resume: bool = False,\n splitter=None\n)\n</code></pre> <p>Run the extraction pipeline for a fetch request.</p> <p>Fetches the source content, extracts raw expenses, enriches them, and saves them as expenses, stopping between stages when <code>till</code> asks for it.</p> <p>Parameters:</p> Name Type Description Default <code>fr_id</code> <code>str</code> <p>Fetch request id.</p> required <code>till</code> <code>str</code> <p>Stop stage: raw, enriched, or expense. Defaults to expense.</p> <code>'expense'</code> <code>force</code> <code>bool</code> <p>Reset to pending and clear extraction data before running. Defaults to False.</p> <code>False</code> <code>resume</code> <code>bool</code> <p>Load previously resolved choices before running. Defaults to False.</p> <code>False</code> <code>splitter</code> <p>Optional custom splitter injected into the extractor.</p> <code>None</code>"},{"location":"interfaces/report/","title":"Report","text":"<ul> <li>Routes</li> </ul>"},{"location":"interfaces/report/#interfaces.report","title":"interfaces.report","text":""},{"location":"interfaces/report/#interfaces.report--summary","title":"Summary","text":"<p>Reports interface: thin API entry points for the reports resource.</p>"},{"location":"interfaces/report/routes/","title":"Routes","text":""},{"location":"interfaces/report/routes/#interfaces.report.routes","title":"interfaces.report.routes","text":""},{"location":"interfaces/report/routes/#interfaces.report.routes--summary","title":"Summary","text":"<p>Report REST handlers \u2014 thin API entry points for the reports resource, wired to openapi.yaml operationIds by the OpenAPI-first router. All handlers delegate to ReportService via request.app.state.db_resources and translate domain validation errors into 400 responses.</p>"},{"location":"interfaces/report/routes/#interfaces.report.routes-classes","title":"Classes","text":""},{"location":"interfaces/report/routes/#interfaces.report.routes-functions","title":"Functions","text":""},{"location":"interfaces/report/routes/#interfaces.report.routes.create_report","title":"create_report <code>async</code>","text":"<pre><code>create_report(request: Request, body: dict)\n</code></pre> <p>Generate a report snapshot from a query definition.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Report query payload; validated into a ReportQuery.</p> required <p>Returns:</p> Name Type Description <code>ReportSnapshotDocument</code> <p>The generated snapshot.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>400 when the query payload is invalid.</p>"},{"location":"interfaces/report/routes/#interfaces.report.routes.delete_report","title":"delete_report <code>async</code>","text":"<pre><code>delete_report(request: Request, id: str)\n</code></pre> <p>Delete a report snapshot by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Report snapshot id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when the snapshot does not exist.</p>"},{"location":"interfaces/report/routes/#interfaces.report.routes.get_report","title":"get_report <code>async</code>","text":"<pre><code>get_report(\n request: Request,\n id: str,\n granularity: Optional[List[str]] = Query(None),\n period_ids: Optional[List[str]] = Query(None),\n flow: str = \"outflows\",\n payee: Optional[List[str]] = Query(None),\n tags: Optional[List[str]] = Query(None),\n)\n</code></pre> <p>Fetch a report snapshot with optional granularity, flow, and filter overrides.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Report snapshot id.</p> required <code>granularity</code> <code>Optional[List[str]]</code> <p>Granularities to materialize; empty means the snapshot's default set.</p> <code>Query(None)</code> <code>period_ids</code> <code>Optional[List[str]]</code> <p>Period labels to constrain output.</p> <code>Query(None)</code> <code>flow</code> <code>str</code> <p>Flow filter of inflows, outflows, or both. Defaults to outflows.</p> <code>'outflows'</code> <code>payee</code> <code>Optional[List[str]]</code> <p>Payee names to include.</p> <code>Query(None)</code> <code>tags</code> <code>Optional[List[str]]</code> <p>Tag paths to include.</p> <code>Query(None)</code> <p>Returns:</p> Name Type Description <code>Report</code> <p>The fetched report.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>400 when the report arguments are invalid.</p> <code>HTTPException</code> <p>404 when the snapshot does not exist.</p>"},{"location":"interfaces/report/routes/#interfaces.report.routes.list_reports","title":"list_reports <code>async</code>","text":"<pre><code>list_reports(\n request: Request, offset: int = 0, limit: int = 100\n)\n</code></pre> <p>List report snapshots with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>offset</code> <code>int</code> <p>Number of snapshots to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of snapshots to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[ReportSnapshotDocument]: Matching snapshots from the report service.</p>"},{"location":"interfaces/tag/","title":"Tag","text":"<ul> <li>Routes</li> </ul>"},{"location":"interfaces/tag/#interfaces.tag","title":"interfaces.tag","text":""},{"location":"interfaces/tag/#interfaces.tag--summary","title":"Summary","text":"<p>Tag interface: thin FastAPI route handlers for the tag resource, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/tag/routes/","title":"Routes","text":""},{"location":"interfaces/tag/routes/#interfaces.tag.routes","title":"interfaces.tag.routes","text":""},{"location":"interfaces/tag/routes/#interfaces.tag.routes--summary","title":"Summary","text":"<p>Tag REST handlers \u2014 thin API entry points for the tag resource, wired to openapi.yaml operationIds by the OpenAPI-first router. All handlers delegate to TagCrudsService via request.app.state.db_resources.</p>"},{"location":"interfaces/tag/routes/#interfaces.tag.routes-classes","title":"Classes","text":""},{"location":"interfaces/tag/routes/#interfaces.tag.routes-functions","title":"Functions","text":""},{"location":"interfaces/tag/routes/#interfaces.tag.routes.create_tag","title":"create_tag <code>async</code>","text":"<pre><code>create_tag(request: Request, body: dict)\n</code></pre> <p>Create a new tag.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Tag payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>TagDocument</code> <p>The created tag.</p>"},{"location":"interfaces/tag/routes/#interfaces.tag.routes.delete_tag","title":"delete_tag <code>async</code>","text":"<pre><code>delete_tag(request: Request, id: str)\n</code></pre> <p>Delete a tag by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Tag id.</p> required <p>Returns:</p> Name Type Description <code>Response</code> <p>Empty 204 response on successful delete.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no tag matches the id.</p>"},{"location":"interfaces/tag/routes/#interfaces.tag.routes.get_tag","title":"get_tag <code>async</code>","text":"<pre><code>get_tag(request: Request, id: str)\n</code></pre> <p>Get a tag by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Tag id.</p> required <p>Returns:</p> Name Type Description <code>TagDocument</code> <p>The matching tag.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no tag matches the id.</p>"},{"location":"interfaces/tag/routes/#interfaces.tag.routes.list_tags","title":"list_tags <code>async</code>","text":"<pre><code>list_tags(\n request: Request, skip: int = 0, limit: int = 1000\n)\n</code></pre> <p>List tags with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>skip</code> <code>int</code> <p>Number of tags to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of tags to return. Defaults to 1000.</p> <code>1000</code> <p>Returns:</p> Type Description <p>list[TagDocument]: Matching tags from TagCrudsService.search.</p>"},{"location":"interfaces/tag/routes/#interfaces.tag.routes.update_tag","title":"update_tag <code>async</code>","text":"<pre><code>update_tag(request: Request, id: str, body: dict)\n</code></pre> <p>Update a tag by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>Tag id.</p> required <code>body</code> <code>dict</code> <p>Fields to update, forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>TagDocument</code> <p>The updated tag.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no tag matches the id.</p>"},{"location":"interfaces/upload/","title":"Upload","text":"<ul> <li>Routes</li> </ul>"},{"location":"interfaces/upload/#interfaces.upload","title":"interfaces.upload","text":""},{"location":"interfaces/upload/#interfaces.upload--summary","title":"Summary","text":"<p>Upload interface: thin FastAPI route handlers for the upload resource, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/upload/routes/","title":"Routes","text":""},{"location":"interfaces/upload/routes/#interfaces.upload.routes","title":"interfaces.upload.routes","text":""},{"location":"interfaces/upload/routes/#interfaces.upload.routes--summary","title":"Summary","text":"<p>Upload REST handlers \u2014 thin API entry points for the upload resource, wired to openapi.yaml operationIds by the OpenAPI-first router. Files are persisted under UPLOAD_DIR and a name-hashed copy is registered with the upload service.</p>"},{"location":"interfaces/upload/routes/#interfaces.upload.routes-classes","title":"Classes","text":""},{"location":"interfaces/upload/routes/#interfaces.upload.routes-functions","title":"Functions","text":""},{"location":"interfaces/upload/routes/#interfaces.upload.routes.get_uploaded_file","title":"get_uploaded_file <code>async</code>","text":"<pre><code>get_uploaded_file(request: Request, filepath: str)\n</code></pre> <p>Serve an uploaded file from disk.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request.</p> required <code>filepath</code> <code>str</code> <p>Relative path of the file under UPLOAD_DIR.</p> required <p>Returns:</p> Name Type Description <code>FileResponse</code> <p>The requested file with its original filename.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when the file does not exist.</p>"},{"location":"interfaces/upload/routes/#interfaces.upload.routes.list_uploads","title":"list_uploads <code>async</code>","text":"<pre><code>list_uploads(request: Request)\n</code></pre> <p>List all upload records.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <p>Returns:</p> Type Description <p>list[UploadDocument]: All uploads from the upload service.</p>"},{"location":"interfaces/upload/routes/#interfaces.upload.routes.upload_file","title":"upload_file <code>async</code>","text":"<pre><code>upload_file(request: Request)\n</code></pre> <p>Upload a raw request body as a file.</p> <p>The filename is parsed from the content-disposition header (defaulting to <code>upload</code>) and combined with a content hash to form the stored filename under UPLOAD_DIR. The resulting UploadResult is persisted via the upload service.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries the body, content type, and app.state.db_resources.</p> required <p>Returns:</p> Name Type Description <code>UploadDocument</code> <p>The created upload record.</p>"},{"location":"interfaces/user/","title":"User","text":"<ul> <li>Routes</li> </ul>"},{"location":"interfaces/user/#interfaces.user","title":"interfaces.user","text":""},{"location":"interfaces/user/#interfaces.user--summary","title":"Summary","text":"<p>User interface: thin FastAPI route handlers for the user resource, wired to openapi.yaml operationIds by the OpenAPI-first router.</p>"},{"location":"interfaces/user/routes/","title":"Routes","text":""},{"location":"interfaces/user/routes/#interfaces.user.routes","title":"interfaces.user.routes","text":""},{"location":"interfaces/user/routes/#interfaces.user.routes--summary","title":"Summary","text":"<p>User REST handlers \u2014 thin API entry points for the user resource, wired to openapi.yaml operationIds by the OpenAPI-first router. Current-user handlers read the authenticated principal from request.state and create the profile on first access.</p>"},{"location":"interfaces/user/routes/#interfaces.user.routes-classes","title":"Classes","text":""},{"location":"interfaces/user/routes/#interfaces.user.routes-functions","title":"Functions","text":""},{"location":"interfaces/user/routes/#interfaces.user.routes.create_user","title":"create_user <code>async</code>","text":"<pre><code>create_user(request: Request, body: dict)\n</code></pre> <p>Create a new user.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>User payload forwarded to the service.</p> required <p>Returns:</p> Name Type Description <code>UserDocument</code> <p>The created user.</p>"},{"location":"interfaces/user/routes/#interfaces.user.routes.get_current_user","title":"get_current_user <code>async</code>","text":"<pre><code>get_current_user(request: Request)\n</code></pre> <p>Get the profile of the authenticated user.</p> <p>Reads the principal from request.state and creates the profile on first access when it does not exist yet.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries the authenticated user and app.state.db_resources.</p> required <p>Returns:</p> Name Type Description <code>UserDocument</code> <p>The current user's profile.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>401 when the request is not authenticated.</p>"},{"location":"interfaces/user/routes/#interfaces.user.routes.get_user","title":"get_user <code>async</code>","text":"<pre><code>get_user(request: Request, id: str)\n</code></pre> <p>Get a user by id.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>id</code> <code>str</code> <p>User id.</p> required <p>Returns:</p> Name Type Description <code>UserDocument</code> <p>The matching user.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>404 when no user matches the id.</p>"},{"location":"interfaces/user/routes/#interfaces.user.routes.list_users","title":"list_users <code>async</code>","text":"<pre><code>list_users(\n request: Request, skip: int = 0, limit: int = 100\n)\n</code></pre> <p>List users with pagination.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries app.state.db_resources.</p> required <code>skip</code> <code>int</code> <p>Number of users to skip (offset). Defaults to 0.</p> <code>0</code> <code>limit</code> <code>int</code> <p>Maximum number of users to return. Defaults to 100.</p> <code>100</code> <p>Returns:</p> Type Description <p>list[UserDocument]: Matching users from UserCrudsService.search.</p>"},{"location":"interfaces/user/routes/#interfaces.user.routes.update_current_user","title":"update_current_user <code>async</code>","text":"<pre><code>update_current_user(request: Request, body: dict)\n</code></pre> <p>Update the profile of the authenticated user.</p> <p>Creates the profile on first access, then applies the update payload.</p> <p>Parameters:</p> Name Type Description Default <code>request</code> <code>Request</code> <p>Incoming HTTP request; carries the authenticated user and app.state.db_resources.</p> required <code>body</code> <code>dict</code> <p>Fields to update on the current user's profile.</p> required <p>Returns:</p> Name Type Description <code>UserDocument</code> <p>The updated profile.</p> <p>Raises:</p> Type Description <code>HTTPException</code> <p>401 when the request is not authenticated.</p>"},{"location":"pipelines/","title":"Pipelines","text":"<ul> <li>Enrichment</li> <li>Extraction</li> </ul>"},{"location":"pipelines/#pipelines","title":"pipelines","text":""},{"location":"pipelines/#pipelines--summary","title":"Summary","text":"<p>Top-level <code>pipelines</code> package for the khata-app Expenses Service backend.</p>"},{"location":"pipelines/#pipelines--notes","title":"Notes","text":"<p>Pipeline families live in dedicated subpackages. The enrichment family lives under <code>pipelines.enrichment</code> and is documented there; keep this package free of implementation modules.</p>"},{"location":"pipelines/enrichment/","title":"Enrichment","text":"<ul> <li>Entity</li> <li>Shared</li> <li>Tags</li> </ul>"},{"location":"pipelines/enrichment/#pipelines.enrichment","title":"pipelines.enrichment","text":""},{"location":"pipelines/enrichment/#pipelines.enrichment--summary","title":"Summary","text":"<p>Enrichment pipelines (entity + tags) as hexa-wired dagpipe graphs.</p>"},{"location":"pipelines/enrichment/#pipelines.enrichment--notes","title":"Notes","text":"<p><code>get_entity_pipeline</code> / <code>get_tags_pipeline</code> return memoized, fully assembled roots \u2014 hexa wiring + pattern registry + dagpipe <code>Engine</code> \u2014 matching the OG <code>domain/enrichment</code> adaptors' behaviour.</p>"},{"location":"pipelines/enrichment/#pipelines.enrichment-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/#pipelines.enrichment-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/#pipelines.enrichment.get_entity_pipeline","title":"get_entity_pipeline","text":"<pre><code>get_entity_pipeline()\n</code></pre> <p>Build and memoize the entity enrichment pipeline root.</p> <p>Returns:</p> Name Type Description <code>ImplEntityPipeline</code> <p>The assembled entity pipeline root.</p>"},{"location":"pipelines/enrichment/#pipelines.enrichment.get_tags_pipeline","title":"get_tags_pipeline","text":"<pre><code>get_tags_pipeline()\n</code></pre> <p>Build and memoize the tags enrichment pipeline root.</p> <p>Returns:</p> Name Type Description <code>ImplTagsPipeline</code> <p>The assembled tags pipeline root.</p>"},{"location":"pipelines/enrichment/entity/","title":"Entity","text":"<ul> <li>Abc</li> <li>Impl</li> </ul>"},{"location":"pipelines/enrichment/entity/#pipelines.enrichment.entity","title":"pipelines.enrichment.entity","text":""},{"location":"pipelines/enrichment/entity/#pipelines.enrichment.entity--summary","title":"Summary","text":"<p>Entity enrichment family (hexa-wired dagpipe graph).</p>"},{"location":"pipelines/enrichment/entity/#pipelines.enrichment.entity--notes","title":"Notes","text":"<p>Houses the abstract contracts (<code>abc.py</code>), the concrete dagpipe stage nodes and root (<code>impl.py</code>) and the runtime resources (<code>resources/</code>) for the entity family.</p>"},{"location":"pipelines/enrichment/entity/abc/","title":"Abc","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc","title":"pipelines.enrichment.entity.abc","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc--summary","title":"Summary","text":"<p>Abstract contracts for the entity enrichment family (no implementation).</p> <p>The entity family is the classic dagpipe chain:</p> <pre><code>normalize \u2192 extract_candidates \u2192 candidate_flags \u2192 amount_flags \u2192\nset_entity \u2192 entity_alias \u2192 fallback\n</code></pre> <p>Each stage port is a dagpipe <code>Node</code> whose <code>resolve</code> yields forked <code>State</code>s carrying confidence. <code>EntityPipeline</code> (the hexa root) wires the stage slots and runs the graph through a dagpipe <code>Engine</code>; <code>EntityFinalizePort</code> turns the terminal states into the entity result dict.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.CandidateFlagsPort","title":"CandidateFlagsPort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>candidate.value \u2192 candidate.flags via CANDIDATE_BASED_FLAG_MAPPING.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.CandidateFlagsPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.CandidateFlagsPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.CandidateFlagsPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.CandidateFlagsPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield forks with <code>candidate.flags</code> updated from the candidate value.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state carrying <code>candidate</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states with <code>candidate.flags</code> populated.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.CandidateFlagsPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.CandidateFlagsPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityAliasPort","title":"EntityAliasPort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>candidate.value \u2192 entity via ENTITY_ALIAS_REGEX (when name not set).</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityAliasPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityAliasPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityAliasPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityAliasPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield the aliased <code>entity</code> fork from the candidate value.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state carrying a candidate value.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states with the aliased <code>entity</code>.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityAliasPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityAliasPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityFinalizePort","title":"EntityFinalizePort","text":"<p> Bases: <code>FinalizePort</code>, <code>ABC</code></p> <p>terminal states \u2192 {entity.name, entity.id, entity.type, ...}.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityFinalizePort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityFinalizePort.process","title":"process <code>abstractmethod</code>","text":"<pre><code>process(states: List) -&gt; dict\n</code></pre> <p>Build the entity result dict from the terminal states.</p> <p>Parameters:</p> Name Type Description Default <code>states</code> <code>List</code> <p>Terminal states from the dagpipe graph.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>The entity result dict.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityPipeline","title":"EntityPipeline","text":"<p> Bases: <code>ABC</code></p> <p>Root \u2014 wires normalize \u2192 \u2026 \u2192 fallback, then runs the dagpipe graph.</p> <p>Attributes:</p> Name Type Description <code>normalize</code> <code>NormalizePort</code> <p>Normalize stage port.</p> <code>extract_candidates</code> <code>ExtractCandidatesPort</code> <p>Extract-candidates stage port.</p> <code>candidate_flags</code> <code>CandidateFlagsPort</code> <p>Candidate-flags stage port.</p> <code>amount_flags</code> <code>AmountFlagsPort</code> <p>Amount-flags stage port.</p> <code>set_entity</code> <code>SetEntityPort</code> <p>Set-entity stage port.</p> <code>entity_alias</code> <code>EntityAliasPort</code> <p>Entity-alias stage port.</p> <code>fallback</code> <code>FallbackPort</code> <p>Fallback stage port.</p> <code>finalize</code> <code>EntityFinalizePort</code> <p>Terminal finalize port.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityPipeline-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.EntityPipeline.enrich","title":"enrich <code>abstractmethod</code>","text":"<pre><code>enrich(payload: dict) -&gt; dict\n</code></pre> <p>Enrich a raw transaction payload into an entity result.</p> <p>Parameters:</p> Name Type Description Default <code>payload</code> <code>dict</code> <p>Raw transaction payload.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>The entity result dict.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.ExtractCandidatesPort","title":"ExtractCandidatesPort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>signals \u2192 candidate.value forks (confidence penalties on fallbacks).</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.ExtractCandidatesPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.ExtractCandidatesPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.ExtractCandidatesPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.ExtractCandidatesPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield <code>candidate.value</code> forks, penalizing fallback candidates.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state carrying <code>signals</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states carrying a <code>candidate.value</code>.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.ExtractCandidatesPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.ExtractCandidatesPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.FallbackPort","title":"FallbackPort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>Terminal \u2014 merchant/person fallback or Unknown.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.FallbackPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.FallbackPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.FallbackPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.FallbackPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield the terminal fallback <code>entity</code> fork.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming terminal dagpipe state.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states with the fallback <code>entity</code>.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.FallbackPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.FallbackPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.NormalizePort","title":"NormalizePort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>raw.description \u2192 signals (raw/items/parts), stripping number sequences.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.NormalizePort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.NormalizePort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.NormalizePort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.NormalizePort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield the normalized <code>signals</code> fork of the incoming state.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state carrying <code>raw.description</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states carrying the normalized <code>signals</code>.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.NormalizePort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.NormalizePort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.SetEntityPort","title":"SetEntityPort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>candidate.flags \u2192 entity via FLAGS_BASED_ENTITY_RULES.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.SetEntityPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.SetEntityPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.SetEntityPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.SetEntityPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield the resolved <code>entity</code> fork from candidate flags.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state carrying candidate flags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states carrying the resolved <code>entity</code>.</p>"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.SetEntityPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/abc/#pipelines.enrichment.entity.abc.SetEntityPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/impl/","title":"Impl","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl","title":"pipelines.enrichment.entity.impl","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl--summary","title":"Summary","text":"<p>Concrete entity-family implementations (dagpipe stage nodes + root).</p> <p>Stage bodies are ports of <code>domain/enrichment/entity/resolver.py</code>, keeping the exact fork/confidence semantics. The root <code>ImplEntityPipeline.enrich</code> runs the hexa-wired stage graph through a dagpipe <code>Engine</code> (assembled in <code>shared/loader.py</code>) and delegates terminal processing to <code>ImplEntityFinalizePort</code> (port of <code>EntityStatesProcessorAdaptor</code>).</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplCandidateFlagsPort","title":"ImplCandidateFlagsPort","text":"<p> Bases: <code>CandidateFlagsPort</code></p> <p>Candidate-flags stage: keyword matches append candidate-based flags.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplCandidateFlagsPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplCandidateFlagsPort.candidate_based_flag_mapping","title":"candidate_based_flag_mapping <code>property</code>","text":"<pre><code>candidate_based_flag_mapping\n</code></pre> <p>Keyword \u2192 flag mapping used for candidate flagging.</p> <p>Returns:</p> Name Type Description <code>dict</code> <p>The candidate-based flag mapping.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplCandidateFlagsPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplCandidateFlagsPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplCandidateFlagsPort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Append candidate flags whose keywords appear in the candidate value.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming state carrying a candidate value and flags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A fork with updated <code>candidate.flags</code> when flags changed, else the unmodified state.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplCandidateFlagsPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplCandidateFlagsPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort","title":"ImplEntityAliasPort","text":"<p> Bases: <code>EntityAliasPort</code></p> <p>Entity-alias stage: resolve the entity from the candidate via aliases.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort.default_logo_mapping","title":"default_logo_mapping <code>property</code>","text":"<pre><code>default_logo_mapping\n</code></pre> <p>Entity type \u2192 default logo mapping.</p> <p>Returns:</p> Name Type Description <code>dict</code> <p>The default logo mapping.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort.entity_alias_regex","title":"entity_alias_regex <code>property</code>","text":"<pre><code>entity_alias_regex\n</code></pre> <p>Alias regex \u2192 name pairs used for entity resolution.</p> <p>Returns:</p> Type Description <p>List[Tuple[re.Pattern, str]]: Compiled (regex, name) pairs.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort.entity_type_mapping","title":"entity_type_mapping <code>property</code>","text":"<pre><code>entity_type_mapping\n</code></pre> <p>Entity id \u2192 type mapping used for entity resolution.</p> <p>Returns:</p> Name Type Description <code>dict</code> <p>The entity type mapping.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Resolve the entity from the candidate value via alias regexes.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming state carrying a candidate value.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A fork with the aliased entity payload, or the unmodified state when the name is already set or no alias matches.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityAliasPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityFinalizePort","title":"ImplEntityFinalizePort","text":"<p> Bases: <code>EntityFinalizePort</code></p> <p>Finalize terminal states into the entity result dict.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityFinalizePort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityFinalizePort.process","title":"process","text":"<pre><code>process(states: List) -&gt; dict\n</code></pre> <p>Build the entity result dict from the best terminal state.</p> <p>Parameters:</p> Name Type Description Default <code>states</code> <code>List</code> <p>Terminal states from the dagpipe graph.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>The entity result dict (name, id, type, logo, raw_candidate, candidate flags and tags).</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityPipeline","title":"ImplEntityPipeline","text":"<p> Bases: <code>EntityPipeline</code></p> <p>Concrete entity pipeline root wiring the stage ports.</p> <p>Attributes:</p> Name Type Description <code>normalize</code> <code>ImplNormalizePort</code> <p>Normalize stage port.</p> <code>extract_candidates</code> <code>ImplExtractCandidatesPort</code> <p>Extract-candidates port.</p> <code>candidate_flags</code> <code>ImplCandidateFlagsPort</code> <p>Candidate-flags port.</p> <code>amount_flags</code> <code>ImplAmountFlagsPort</code> <p>Amount-flags port.</p> <code>set_entity</code> <code>ImplSetEntityPort</code> <p>Set-entity port.</p> <code>entity_alias</code> <code>ImplEntityAliasPort</code> <p>Entity-alias port.</p> <code>fallback</code> <code>ImplFallbackPort</code> <p>Fallback port.</p> <code>finalize</code> <code>ImplEntityFinalizePort</code> <p>Terminal finalize port.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityPipeline-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplEntityPipeline.enrich","title":"enrich","text":"<pre><code>enrich(payload: dict) -&gt; dict\n</code></pre> <p>Run the entity graph on a raw payload and finalize the result.</p> <p>Parameters:</p> Name Type Description Default <code>payload</code> <code>dict</code> <p>Raw transaction payload.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>The entity result dict from the finalize port.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort","title":"ImplExtractCandidatesPort","text":"<p> Bases: <code>ExtractCandidatesPort</code></p> <p>Extract-candidates stage: signals \u2192 candidate value forks with penalties.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort.candidate_regex","title":"candidate_regex <code>property</code>","text":"<pre><code>candidate_regex\n</code></pre> <p>Candidate extraction regexes from the pattern registry.</p> <p>Returns:</p> Type Description <p>List[re.Pattern]: Compiled candidate extraction regexes.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort.negative_candidates","title":"negative_candidates <code>property</code>","text":"<pre><code>negative_candidates\n</code></pre> <p>Tokens excluded from candidate extraction.</p> <p>Returns:</p> Name Type Description <code>List</code> <p>The registered negative candidate tokens.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield candidate-value forks from signals, penalizing fallbacks.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming state carrying <code>signals</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forks carrying <code>candidate.value</code> for each accepted candidate (parts/items fallbacks penalized), or a single penalized fork when nothing matches.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplExtractCandidatesPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplFallbackPort","title":"ImplFallbackPort","text":"<p> Bases: <code>FallbackPort</code></p> <p>Terminal fallback stage: candidate merchant/person, else Unknown.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplFallbackPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplFallbackPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplFallbackPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplFallbackPort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Assign the terminal fallback entity when none was resolved.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming terminal state.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A fork carrying the fallback entity (candidate, Unknown, or the already-resolved entity).</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplFallbackPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplFallbackPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplNormalizePort","title":"ImplNormalizePort","text":"<p> Bases: <code>NormalizePort</code></p> <p>Normalize stage: strip number sequences, then build raw/items/parts signals.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplNormalizePort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplNormalizePort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplNormalizePort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplNormalizePort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Clean <code>raw.description</code> and yield a single <code>signals</code> fork.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming state carrying <code>raw.description</code> and the <code>raw.amount</code>/<code>raw.balance</code> values.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A single fork populating <code>signals.raw</code>, <code>signals.items</code> and <code>signals.parts</code>.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplNormalizePort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplNormalizePort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort","title":"ImplSetEntityPort","text":"<p> Bases: <code>SetEntityPort</code></p> <p>Set-entity stage: resolve the entity from candidate flags via rules.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort.default_logo_mapping","title":"default_logo_mapping <code>property</code>","text":"<pre><code>default_logo_mapping\n</code></pre> <p>Entity type \u2192 default logo mapping.</p> <p>Returns:</p> Name Type Description <code>dict</code> <p>The default logo mapping.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort.entity_type_mapping","title":"entity_type_mapping <code>property</code>","text":"<pre><code>entity_type_mapping\n</code></pre> <p>Entity id \u2192 type mapping used for entity resolution.</p> <p>Returns:</p> Name Type Description <code>dict</code> <p>The entity type mapping.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort.flags_based_entity_rules","title":"flags_based_entity_rules <code>property</code>","text":"<pre><code>flags_based_entity_rules\n</code></pre> <p>Flag-matching rules that emit the resolved entity.</p> <p>Returns:</p> Type Description <p>List[Dict]: The ordered entity rules.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Resolve the entity from candidate flags using the first matching rule.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming state carrying candidate flags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A fork with the resolved entity payload, the unmodified state when an entity name is already set, or a penalized fork when unresolvable.</p>"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl.ImplSetEntityPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/entity/impl/#pipelines.enrichment.entity.impl-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/","title":"Shared","text":"<ul> <li>Identity</li> <li>Impl</li> <li>Loader</li> <li>Models</li> <li>Ports</li> <li>Registry</li> <li>Utils</li> </ul>"},{"location":"pipelines/enrichment/shared/#pipelines.enrichment.shared","title":"pipelines.enrichment.shared","text":""},{"location":"pipelines/enrichment/shared/#pipelines.enrichment.shared--summary","title":"Summary","text":"<p>Shared enrichment core: models, identity, utils, ports, loader, registry.</p>"},{"location":"pipelines/enrichment/shared/#pipelines.enrichment.shared--notes","title":"Notes","text":"<p>These modules are shared by the <code>entity</code> and <code>tags</code> enrichment families.</p>"},{"location":"pipelines/enrichment/shared/identity/","title":"Identity","text":""},{"location":"pipelines/enrichment/shared/identity/#pipelines.enrichment.shared.identity","title":"pipelines.enrichment.shared.identity","text":""},{"location":"pipelines/enrichment/shared/identity/#pipelines.enrichment.shared.identity--summary","title":"Summary","text":"<p>Entity identity helpers (port of <code>domain/enrichment/entity/identity.py</code>).</p>"},{"location":"pipelines/enrichment/shared/identity/#pipelines.enrichment.shared.identity-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/identity/#pipelines.enrichment.shared.identity.build_entity","title":"build_entity","text":"<pre><code>build_entity(\n name: str,\n entity_type: str = \"merchant\",\n entity_logo: str | None = None,\n) -&gt; dict\n</code></pre> <p>Build the entity payload dict from name, type and logo.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Entity display name.</p> required <code>entity_type</code> <code>str</code> <p>Entity type key, defaults to \"merchant\".</p> <code>'merchant'</code> <code>entity_logo</code> <code>str | None</code> <p>Logo URL, or None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>Entity payload with <code>entity.id</code>, <code>entity.name</code>, <code>entity.type</code> and <code>entity.logo</code> keys.</p>"},{"location":"pipelines/enrichment/shared/identity/#pipelines.enrichment.shared.identity.canonicalize_candidate","title":"canonicalize_candidate","text":"<pre><code>canonicalize_candidate(candidate: str | None) -&gt; str | None\n</code></pre> <p>Canonicalize a candidate value via <code>normalize_key</code>.</p> <p>Parameters:</p> Name Type Description Default <code>candidate</code> <code>str | None</code> <p>Raw candidate, or None/empty.</p> required <p>Returns:</p> Type Description <code>str | None</code> <p>str | None: The normalized candidate, or None when <code>candidate</code> is empty.</p>"},{"location":"pipelines/enrichment/shared/identity/#pipelines.enrichment.shared.identity.normalize_key","title":"normalize_key","text":"<pre><code>normalize_key(text: str | None) -&gt; str | None\n</code></pre> <p>Normalize a key: NFKC, lowercase and stripped.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str | None</code> <p>Raw key, or None.</p> required <p>Returns:</p> Type Description <code>str | None</code> <p>str | None: The normalized key, or None when <code>text</code> is None.</p>"},{"location":"pipelines/enrichment/shared/identity/#pipelines.enrichment.shared.identity.to_entity_id","title":"to_entity_id","text":"<pre><code>to_entity_id(name: str | None) -&gt; str | None\n</code></pre> <p>Build the canonical snake-cased entity id from a name.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str | None</code> <p>Raw entity name, or None/empty.</p> required <p>Returns:</p> Type Description <code>str | None</code> <p>str | None: The snake-cased entity id, or None when <code>name</code> is empty.</p>"},{"location":"pipelines/enrichment/shared/impl/","title":"Impl","text":""},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl","title":"pipelines.enrichment.shared.impl","text":""},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl--summary","title":"Summary","text":"<p>Concrete shared enrichment ports.</p> <p><code>ImplAmountFlagsPort</code> is the port of <code>domain.enrichment.nodes.AmountBasedFlagNode</code> \u2014 used by both the entity and tags families.</p>"},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl.ImplAmountFlagsPort","title":"ImplAmountFlagsPort","text":"<p> Bases: <code>AmountFlagsPort</code></p> <p>Amount-flags stage: map the amount to <code>amount_*</code> candidate flags.</p> Notes <p>Shared by the entity and tags families; the amount-flag name encodes the comparison (e.g. <code>amount_greater_than_500</code>, <code>amount_within_5_500</code>).</p>"},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl.ImplAmountFlagsPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl.ImplAmountFlagsPort.amount_based_flag_mapping","title":"amount_based_flag_mapping <code>property</code>","text":"<pre><code>amount_based_flag_mapping\n</code></pre> <p>Flag names to evaluate, taken from the registry.</p> <p>Returns:</p> Name Type Description <code>List</code> <p>The registered amount-flag names.</p>"},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl.ImplAmountFlagsPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl.ImplAmountFlagsPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl.ImplAmountFlagsPort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Evaluate the amount-based flags and append the matches.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming state carrying <code>raw.amount</code> and <code>candidate.flags</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A fork with <code>candidate.flags</code> updated when flags were appended, else the unmodified state.</p>"},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl.ImplAmountFlagsPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/shared/impl/#pipelines.enrichment.shared.impl.ImplAmountFlagsPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/shared/loader/","title":"Loader","text":""},{"location":"pipelines/enrichment/shared/loader/#pipelines.enrichment.shared.loader","title":"pipelines.enrichment.shared.loader","text":""},{"location":"pipelines/enrichment/shared/loader/#pipelines.enrichment.shared.loader--summary","title":"Summary","text":"<p>Assemble a hexa-wired enrichment port tree into a runnable dagpipe graph.</p> <p>Flow (mirrors <code>domain/enrichment/{entity,tags}/pipeline.py#load</code>, but hexa replaces the class-path import/instantiation and the dagpipe spec is consumed for its schema/graph/per-node config):</p> <ol> <li><code>hexa.build(root_cls)</code> instantiates and wires every stage port slot.</li> <li>The family <code>resources/patterns/*.yaml</code> files merge into a <code>PatternRegistry</code>.</li> <li>Each stage port (slot name == dagpipe node id) gets <code>set_registry</code> + <code>set_config</code> from the family <code>resources/pipeline.yaml</code>.</li> <li>The dagpipe <code>schema:</code> builds a <code>State</code> subclass, <code>graph:</code> builds the <code>Graph</code>, and the <code>Engine</code> is created.</li> <li>The Engine + State class are attached to the wired root for <code>enrich()</code>.</li> </ol>"},{"location":"pipelines/enrichment/shared/loader/#pipelines.enrichment.shared.loader-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/shared/loader/#pipelines.enrichment.shared.loader-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/loader/#pipelines.enrichment.shared.loader.load","title":"load","text":"<pre><code>load(root_cls: type, resources_dir: Path)\n</code></pre> <p>Build the wired root + dagpipe runtime; attach engine/state_cls to root.</p> <p>Parameters:</p> Name Type Description Default <code>root_cls</code> <code>type</code> <p>Composition root class to hexa-build.</p> required <code>resources_dir</code> <code>Path</code> <p>Family resources directory containing <code>pipeline.yaml</code> and <code>patterns/</code>.</p> required <p>Returns:</p> Name Type Description <code>object</code> <p>The wired root instance with <code>_engine</code>/<code>_state_cls</code> attached.</p> <p>Raises:</p> Type Description <code>FileNotFoundError</code> <p>When <code>pipeline.yaml</code> does not exist.</p>"},{"location":"pipelines/enrichment/shared/models/","title":"Models","text":""},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models","title":"pipelines.enrichment.shared.models","text":""},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models--summary","title":"Summary","text":"<p>Pattern model family + <code>PatternRegistry</code> (port of <code>domain/enrichment/models.py</code>).</p> <p>The registry is loaded from the family <code>resources/patterns/*.yaml</code> files and injected into every dagpipe stage node via <code>set_registry</code>.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.ArrayPattern","title":"ArrayPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Array pattern: a plain list of values.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[ARRAY]</code> <p>Fixed discriminator.</p> <code>array</code> <code>List</code> <p>Plain value list.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.BasePattern","title":"BasePattern","text":"<p> Bases: <code>BaseModel</code></p> <p>Base model for all patterns: a discriminated <code>type</code> tag.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>PatternType</code> <p>Pattern kind discriminator.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.KeywordsPattern","title":"KeywordsPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Keywords pattern: a flat list of keywords.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[KEYWORDS]</code> <p>Fixed discriminator.</p> <code>items</code> <code>List[str]</code> <p>Keyword list.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.MappingPattern","title":"MappingPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Enumerated <code>mapping</code> of token \u2192 value.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[MAPPING]</code> <p>Fixed discriminator.</p> <code>mapping</code> <code>Dict[str, Union[str, MappingValue, List]]</code> <p>Token mapping.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.MappingValue","title":"MappingValue","text":"<p> Bases: <code>BaseModel</code></p> <p>Named value inside a mapping pattern.</p> <p>Attributes:</p> Name Type Description <code>id</code> <code>str</code> <p>Mapping key id.</p> <code>name</code> <code>str</code> <p>Display name.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry","title":"PatternRegistry","text":"<p> Bases: <code>BaseModel</code></p> <p>Loaded pattern registry injected into dagpipe stage nodes.</p> <p>Attributes:</p> Name Type Description <code>version</code> <code>int</code> <p>Registry schema version.</p> <code>patterns</code> <code>Dict[str, Pattern]</code> <p>Name \u2192 pattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.array","title":"array","text":"<pre><code>array(name: str) -&gt; List\n</code></pre> <p>Return the raw array of an ArrayPattern.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Name Type Description <code>List</code> <code>List</code> <p>The array items.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When the pattern is not an ArrayPattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.get","title":"get","text":"<pre><code>get(name: str) -&gt; Pattern\n</code></pre> <p>Look up a pattern by name.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Name Type Description <code>Pattern</code> <code>Pattern</code> <p>The stored pattern object.</p> <p>Raises:</p> Type Description <code>KeyError</code> <p>When the pattern name is not registered.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.keywords","title":"keywords","text":"<pre><code>keywords(name: str) -&gt; List[str]\n</code></pre> <p>Return the keyword list of a KeywordsPattern.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: The keyword items.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When the pattern is not a KeywordsPattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.mapping","title":"mapping","text":"<pre><code>mapping(name: str) -&gt; Dict[str, str]\n</code></pre> <p>Return the token mapping of a MappingPattern.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Type Description <code>Dict[str, str]</code> <p>Dict[str, str]: The mapping dict.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When the pattern is not a MappingPattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.regex","title":"regex","text":"<pre><code>regex(name: str) -&gt; re.Pattern\n</code></pre> <p>Return the compiled regex of a RegexPattern.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Type Description <code>Pattern</code> <p>re.Pattern: The compiled regex.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When the pattern is not a RegexPattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.regex_list","title":"regex_list","text":"<pre><code>regex_list(name: str) -&gt; List[re.Pattern]\n</code></pre> <p>Return the compiled regexes of a RegexListPattern.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Type Description <code>List[Pattern]</code> <p>List[re.Pattern]: The compiled regexes.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When the pattern is not a RegexListPattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.regex_map","title":"regex_map","text":"<pre><code>regex_map(name: str) -&gt; List[Tuple[re.Pattern, str]]\n</code></pre> <p>Return the compiled <code>(regex, value)</code> pairs of a RegexMapPattern.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Type Description <code>List[Tuple[Pattern, str]]</code> <p>List[Tuple[re.Pattern, str]]: The compiled pairs.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When the pattern is not a RegexMapPattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.rules","title":"rules","text":"<pre><code>rules(name: str) -&gt; List[Dict]\n</code></pre> <p>Return the rule list of a RulesPattern.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Type Description <code>List[Dict]</code> <p>List[Dict]: The ordered rules.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When the pattern is not a RulesPattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternRegistry.template","title":"template","text":"<pre><code>template(name: str) -&gt; str\n</code></pre> <p>Return the format string of a TemplatePattern.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Pattern name.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The template format string.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When the pattern is not a TemplatePattern.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.PatternType","title":"PatternType","text":"<p> Bases: <code>str</code>, <code>Enum</code></p> <p>Supported pattern kinds loaded from the family pattern files.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexListPattern","title":"RegexListPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>List-of-regexes pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[REGEX_LIST]</code> <p>Fixed discriminator.</p> <code>patterns</code> <code>List[str]</code> <p>Regex sources.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexListPattern-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexListPattern.compile_all","title":"compile_all","text":"<pre><code>compile_all(flags: int = re.IGNORECASE) -&gt; List[re.Pattern]\n</code></pre> <p>Compile every regex source.</p> <p>Parameters:</p> Name Type Description Default <code>flags</code> <code>int</code> <p>Compile flags, default <code>re.IGNORECASE</code>.</p> <code>IGNORECASE</code> <p>Returns:</p> Type Description <code>List[Pattern]</code> <p>List[re.Pattern]: The compiled regexes.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexMapPattern","title":"RegexMapPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Regex \u2192 value mapping pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[REGEX_MAP]</code> <p>Fixed discriminator.</p> <code>mapping</code> <code>Dict[str, str]</code> <p>Regex source \u2192 value.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexMapPattern-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexMapPattern.compile_all","title":"compile_all","text":"<pre><code>compile_all(\n flags: int = re.IGNORECASE,\n) -&gt; List[Tuple[re.Pattern, str]]\n</code></pre> <p>Pre-compile the mapping into <code>(regex, value)</code> pairs.</p> <p>Parameters:</p> Name Type Description Default <code>flags</code> <code>int</code> <p>Compile flags, default <code>re.IGNORECASE</code>.</p> <code>IGNORECASE</code> <p>Returns:</p> Type Description <code>List[Tuple[Pattern, str]]</code> <p>List[Tuple[re.Pattern, str]]: The compiled pairs.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexPattern","title":"RegexPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Single-regex pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[REGEX]</code> <p>Fixed discriminator.</p> <code>pattern</code> <code>str</code> <p>Regex source.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexPattern-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RegexPattern.compile","title":"compile","text":"<pre><code>compile(flags: int = re.IGNORECASE) -&gt; re.Pattern\n</code></pre> <p>Compile the regex pattern.</p> <p>Parameters:</p> Name Type Description Default <code>flags</code> <code>int</code> <p>Compile flags, default <code>re.IGNORECASE</code>.</p> <code>IGNORECASE</code> <p>Returns:</p> Type Description <code>Pattern</code> <p>re.Pattern: The compiled regex.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.RulesPattern","title":"RulesPattern","text":"<p> Bases: <code>BasePattern</code></p> <p>Rule-set pattern: ordered flag rules with emit payloads.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[RULES]</code> <p>Fixed discriminator.</p> <code>rules</code> <code>List[Dict]</code> <p>Ordered rule dicts.</p>"},{"location":"pipelines/enrichment/shared/models/#pipelines.enrichment.shared.models.TemplatePattern","title":"TemplatePattern","text":"<p> Bases: <code>BasePattern</code></p> <p>String-template pattern.</p> <p>Attributes:</p> Name Type Description <code>type</code> <code>Literal[TEMPLATE]</code> <p>Fixed discriminator.</p> <code>format</code> <code>str</code> <p>Format/template string.</p>"},{"location":"pipelines/enrichment/shared/ports/","title":"Ports","text":""},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports","title":"pipelines.enrichment.shared.ports","text":""},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports--summary","title":"Summary","text":"<p>Shared enrichment port contracts.</p> <p>Stage ports are dagpipe <code>Node</code>s: <code>hexa.build()</code> wires their instances on a family root, the shared loader injects the pattern registry + per-node config, and a dagpipe <code>Engine</code> executes them. <code>FinalizePort</code> is the terminal state processor (confidence sort + result dict building).</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.AmountFlagsPort","title":"AmountFlagsPort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>amount \u2192 amount_* candidate flags (shared by entity and tags families).</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.AmountFlagsPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.AmountFlagsPort.amount_based_flag_mapping","title":"amount_based_flag_mapping <code>property</code>","text":"<pre><code>amount_based_flag_mapping\n</code></pre> <p>Flag names to evaluate, taken from the registry.</p> <p>Returns:</p> Name Type Description <code>List</code> <p>The registered amount-flag names.</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.AmountFlagsPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.AmountFlagsPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.AmountFlagsPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield the forked states with <code>amount_*</code> flags applied.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state carrying the amount.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states carrying the updated candidate flags.</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.AmountFlagsPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.AmountFlagsPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.FinalizePort","title":"FinalizePort","text":"<p> Bases: <code>ABC</code></p> <p>Terminal state processor: confidence sort then build the result dict.</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.FinalizePort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.FinalizePort.process","title":"process <code>abstractmethod</code>","text":"<pre><code>process(states: list) -&gt; dict\n</code></pre> <p>Build the result dict from the terminal states.</p> <p>Parameters:</p> Name Type Description Default <code>states</code> <code>list</code> <p>Terminal states from the dagpipe graph.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>The generated result dict.</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.RegistryPort","title":"RegistryPort","text":"<p> Bases: <code>Node</code>, <code>ABC</code></p> <p>dagpipe node with injectable PatternRegistry + per-node config.</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.RegistryPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.RegistryPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.RegistryPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.RegistryPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield the forked states carrying this stage's output.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states carrying the stage output.</p>"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.RegistryPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/shared/ports/#pipelines.enrichment.shared.ports.RegistryPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/shared/registry/","title":"Registry","text":""},{"location":"pipelines/enrichment/shared/registry/#pipelines.enrichment.shared.registry","title":"pipelines.enrichment.shared.registry","text":""},{"location":"pipelines/enrichment/shared/registry/#pipelines.enrichment.shared.registry--summary","title":"Summary","text":"<p>Registry mapping enrichment family \u2192 composition root.</p> <p>Enrichment has two families (<code>entity</code>, <code>tags</code>); each has a single default root (no per-bank variants) so the family is the root, living in the family's <code>impl.py</code>. Callers use <code>resolve_enrichment_root</code> instead of hand-rolled maps.</p>"},{"location":"pipelines/enrichment/shared/registry/#pipelines.enrichment.shared.registry-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/shared/registry/#pipelines.enrichment.shared.registry-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/registry/#pipelines.enrichment.shared.registry.known_enrichment_roots","title":"known_enrichment_roots","text":"<pre><code>known_enrichment_roots() -&gt; list\n</code></pre> <p>List the registered enrichment family names.</p> <p>Returns:</p> Name Type Description <code>list</code> <code>list</code> <p>The known family names.</p>"},{"location":"pipelines/enrichment/shared/registry/#pipelines.enrichment.shared.registry.resolve_enrichment_root","title":"resolve_enrichment_root","text":"<pre><code>resolve_enrichment_root(family: str) -&gt; type\n</code></pre> <p>Return the composition root class for an enrichment family.</p> <p>Parameters:</p> Name Type Description Default <code>family</code> <code>str</code> <p>Enrichment family name (\"entity\" or \"tags\").</p> required <p>Returns:</p> Name Type Description <code>type</code> <code>type</code> <p>The composition root class for the family.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When the family has no registered enrichment root.</p>"},{"location":"pipelines/enrichment/shared/utils/","title":"Utils","text":""},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils","title":"pipelines.enrichment.shared.utils","text":""},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils--summary","title":"Summary","text":"<p>Description/candidate utilities (port of <code>domain/enrichment/entity/utils.py</code>).</p>"},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils.extract_candidates","title":"extract_candidates","text":"<pre><code>extract_candidates(\n description: str,\n candidate_regexes: Iterable[re.Pattern],\n) -&gt; List[str]\n</code></pre> <p>Extract valid payee candidates from a description.</p> <p>Parameters:</p> Name Type Description Default <code>description</code> <code>str</code> <p>Raw description text.</p> required <code>candidate_regexes</code> <code>Iterable[Pattern]</code> <p>Compiled extraction regexes.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: The normalized valid candidates.</p>"},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils.is_valid_candidate","title":"is_valid_candidate","text":"<pre><code>is_valid_candidate(candidate: str) -&gt; bool\n</code></pre> <p>Return True when a candidate looks like a plausible payee.</p> <p>Parameters:</p> Name Type Description Default <code>candidate</code> <code>str</code> <p>Extracted candidate value.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <code>bool</code> <p>True when the candidate passes the length/content heuristics.</p>"},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils.lookup_mapping","title":"lookup_mapping","text":"<pre><code>lookup_mapping(candidate: str, mapping: dict)\n</code></pre> <p>Look up mapping values for a candidate token.</p> <p>Parameters:</p> Name Type Description Default <code>candidate</code> <code>str</code> <p>Candidate token.</p> required <code>mapping</code> <code>dict</code> <p>Mapping dict of key \u2192 MappingValue.</p> required <p>Returns:</p> Name Type Description <code>list</code> <p>Matching value names, or <code>(None, None)</code> when the candidate is empty.</p>"},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils.normalize_description","title":"normalize_description","text":"<pre><code>normalize_description(text: str) -&gt; str\n</code></pre> <p>Normalize a description: separators \u2192 space, lowercase, drop OCR noise.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Raw description.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The normalized lowercase description.</p>"},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils.normalize_money_str","title":"normalize_money_str","text":"<pre><code>normalize_money_str(x) -&gt; str\n</code></pre> <p>Format a numeric value as a fixed two-decimal string.</p> <p>Parameters:</p> Name Type Description Default <code>x</code> <code>float</code> <p>Value coercible to float.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The value formatted to exactly two decimals.</p>"},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils.normalize_person_handle","title":"normalize_person_handle","text":"<pre><code>normalize_person_handle(handle: str) -&gt; str\n</code></pre> <p>Normalize a person/UPI handle into a capitalized display name.</p> <p>Parameters:</p> Name Type Description Default <code>handle</code> <code>str</code> <p>Raw handle (may carry a UPI suffix or trailing digits).</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The cleaned handle, or \"\" when only hex characters remain.</p>"},{"location":"pipelines/enrichment/shared/utils/#pipelines.enrichment.shared.utils.remove_number_sequence","title":"remove_number_sequence","text":"<pre><code>remove_number_sequence(\n text: str, amt: str, bal: str\n) -&gt; str\n</code></pre> <p>Strip amount/balance digit sequences from a description.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Description text.</p> required <code>amt</code> <code>str</code> <p>Amount value.</p> required <code>bal</code> <code>str</code> <p>Balance value.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>The cleaned, whitespace-collapsed description.</p>"},{"location":"pipelines/enrichment/tags/","title":"Tags","text":"<ul> <li>Abc</li> <li>Impl</li> </ul>"},{"location":"pipelines/enrichment/tags/#pipelines.enrichment.tags","title":"pipelines.enrichment.tags","text":""},{"location":"pipelines/enrichment/tags/#pipelines.enrichment.tags--summary","title":"Summary","text":"<p>Tags enrichment family (hexa-wired dagpipe graph).</p>"},{"location":"pipelines/enrichment/tags/#pipelines.enrichment.tags--notes","title":"Notes","text":"<p>Houses the abstract contracts (<code>abc.py</code>), the concrete dagpipe stage nodes and root (<code>impl.py</code>) and the runtime resources (<code>resources/</code>) for the tags family.</p>"},{"location":"pipelines/enrichment/tags/abc/","title":"Abc","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc","title":"pipelines.enrichment.tags.abc","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc--summary","title":"Summary","text":"<p>Abstract contracts for the tags enrichment family (no implementation).</p> <p>The tags family chains resolved entities into tags:</p> <pre><code>amount_flags \u2192 entity_flags \u2192 set_tags\n</code></pre> <p>It consumes the output of the entity family (<code>entity.name</code> + amount) and emits <code>tags</code>. <code>TagsPipeline</code> is the hexa root; <code>TagsFinalizePort</code> dedupes tags and defaults to <code>[\"misc\"]</code>.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.EntityFlagsPort","title":"EntityFlagsPort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>entity.name + candidate.flags \u2192 entity_* flags via ENTITY_BASED_FLAG_MAPPING.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.EntityFlagsPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.EntityFlagsPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.EntityFlagsPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.EntityFlagsPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield forks with <code>entity_*</code> flags appended from the entity name.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state carrying <code>entity.name</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states carrying updated candidate flags.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.EntityFlagsPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.EntityFlagsPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.SetTagsPort","title":"SetTagsPort","text":"<p> Bases: <code>RegistryPort</code>, <code>ABC</code></p> <p>candidate.flags \u2192 tags via FLAGS_BASED_TAGS_RULES.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.SetTagsPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.SetTagsPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.SetTagsPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.SetTagsPort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Yield forks with <code>tags</code> populated from candidate flags.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming dagpipe state carrying candidate flags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>Forked states carrying the emitted <code>tags</code>.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.SetTagsPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.SetTagsPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.TagsFinalizePort","title":"TagsFinalizePort","text":"<p> Bases: <code>FinalizePort</code>, <code>ABC</code></p> <p>terminal states \u2192 {\"tags\": [...]} (deduped, default [\"misc\"]).</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.TagsFinalizePort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.TagsFinalizePort.process","title":"process <code>abstractmethod</code>","text":"<pre><code>process(states: List) -&gt; dict\n</code></pre> <p>Build the tags result dict from the terminal states.</p> <p>Parameters:</p> Name Type Description Default <code>states</code> <code>List</code> <p>Terminal states from the dagpipe graph.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>The tags result dict.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.TagsPipeline","title":"TagsPipeline","text":"<p> Bases: <code>ABC</code></p> <p>Root \u2014 wires amount_flags \u2192 entity_flags \u2192 set_tags, then runs the graph.</p> <p>Attributes:</p> Name Type Description <code>amount_flags</code> <code>AmountFlagsPort</code> <p>Amount-flags stage port.</p> <code>entity_flags</code> <code>EntityFlagsPort</code> <p>Entity-flags stage port.</p> <code>set_tags</code> <code>SetTagsPort</code> <p>Set-tags stage port.</p> <code>finalize</code> <code>TagsFinalizePort</code> <p>Terminal finalize port.</p>"},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.TagsPipeline-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/tags/abc/#pipelines.enrichment.tags.abc.TagsPipeline.enrich","title":"enrich <code>abstractmethod</code>","text":"<pre><code>enrich(payload: dict) -&gt; dict\n</code></pre> <p>Enrich an entity payload into a tags result.</p> <p>Parameters:</p> Name Type Description Default <code>payload</code> <code>dict</code> <p>Payload carrying <code>entity.name</code> and the amount.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>The tags result dict.</p>"},{"location":"pipelines/enrichment/tags/impl/","title":"Impl","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl","title":"pipelines.enrichment.tags.impl","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl--summary","title":"Summary","text":"<p>Concrete tags-family implementations (dagpipe stage nodes + root).</p> <p>Stage bodies are ports of <code>domain/enrichment/tags/flags.py</code>. The root <code>ImplTagsPipeline.enrich</code> runs the hexa-wired stage graph through a dagpipe <code>Engine</code> and delegates terminal processing to <code>ImplTagsFinalizePort</code> (port of <code>TagStatesProcessorAdaptor</code>).</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl-classes","title":"Classes","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplEntityFlagsPort","title":"ImplEntityFlagsPort","text":"<p> Bases: <code>EntityFlagsPort</code></p> <p>Entity-flags stage: append <code>entity_*</code> flags from the entity name.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplEntityFlagsPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplEntityFlagsPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplEntityFlagsPort.entity_based_flag_mapping","title":"entity_based_flag_mapping <code>property</code>","text":"<pre><code>entity_based_flag_mapping\n</code></pre> <p>Entity name \u2192 flag mapping used for entity flagging.</p> <p>Returns:</p> Name Type Description <code>dict</code> <p>The entity-based flag mapping.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplEntityFlagsPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplEntityFlagsPort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Append matching <code>entity_*</code> flags and reset <code>tags</code>.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming state carrying <code>entity.name</code> and <code>candidate.flags</code>.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A fork with updated <code>candidate.flags</code> and empty <code>tags</code>, or the unmodified state when no entity name is set.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplEntityFlagsPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplEntityFlagsPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplSetTagsPort","title":"ImplSetTagsPort","text":"<p> Bases: <code>SetTagsPort</code></p> <p>Set-tags stage: emit tags from the matching flag rules.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplSetTagsPort-attributes","title":"Attributes","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplSetTagsPort.config","title":"config <code>property</code>","text":"<pre><code>config\n</code></pre> <p>Per-node config injected via <code>set_config</code>.</p> <p>Returns:</p> Type Description <p>dict | None: The per-node config, or None before injection.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplSetTagsPort.flags_based_tags_rules","title":"flags_based_tags_rules <code>property</code>","text":"<pre><code>flags_based_tags_rules\n</code></pre> <p>Flag-matching rules that emit tags.</p> <p>Returns:</p> Type Description <p>List[Dict]: The ordered tag rules.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplSetTagsPort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplSetTagsPort.resolve","title":"resolve","text":"<pre><code>resolve(state: State) -&gt; Iterable[State]\n</code></pre> <p>Append tags emitted by the first matching flag rules.</p> <p>Parameters:</p> Name Type Description Default <code>state</code> <code>State</code> <p>Incoming state carrying candidate flags and tags.</p> required <p>Yields:</p> Name Type Description <code>State</code> <code>Iterable[State]</code> <p>A fork with <code>tags</code> updated when rules matched, else the unmodified state.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplSetTagsPort.set_config","title":"set_config","text":"<pre><code>set_config(config)\n</code></pre> <p>Inject the per-node config.</p> <p>Parameters:</p> Name Type Description Default <code>config</code> <code>dict</code> <p>Per-node config from the dagpipe spec.</p> required"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplSetTagsPort.set_registry","title":"set_registry","text":"<pre><code>set_registry(registry)\n</code></pre> <p>Inject the merged pattern registry.</p> <p>Parameters:</p> Name Type Description Default <code>registry</code> <code>PatternRegistry</code> <p>The merged pattern registry.</p> required"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplTagsFinalizePort","title":"ImplTagsFinalizePort","text":"<p> Bases: <code>TagsFinalizePort</code></p> <p>Finalize terminal states into the tags result dict.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplTagsFinalizePort-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplTagsFinalizePort.process","title":"process","text":"<pre><code>process(states: List) -&gt; dict\n</code></pre> <p>Build the tags result dict, deduped and order-preserving.</p> <p>Parameters:</p> Name Type Description Default <code>states</code> <code>List</code> <p>Terminal states from the dagpipe graph.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p><code>{\"tags\": [...]}</code> with unique tags.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplTagsPipeline","title":"ImplTagsPipeline","text":"<p> Bases: <code>TagsPipeline</code></p> <p>Concrete tags pipeline root wiring the stage ports.</p> <p>Attributes:</p> Name Type Description <code>amount_flags</code> <code>ImplAmountFlagsPort</code> <p>Amount-flags stage port.</p> <code>entity_flags</code> <code>ImplEntityFlagsPort</code> <p>Entity-flags stage port.</p> <code>set_tags</code> <code>ImplSetTagsPort</code> <p>Set-tags stage port.</p> <code>finalize</code> <code>ImplTagsFinalizePort</code> <p>Terminal finalize port.</p>"},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplTagsPipeline-functions","title":"Functions","text":""},{"location":"pipelines/enrichment/tags/impl/#pipelines.enrichment.tags.impl.ImplTagsPipeline.enrich","title":"enrich","text":"<pre><code>enrich(payload: dict) -&gt; dict\n</code></pre> <p>Run the tags graph on an entity payload and finalize the result.</p> <p>Parameters:</p> Name Type Description Default <code>payload</code> <code>dict</code> <p>Payload carrying <code>entity.name</code> and the amount.</p> required <p>Returns:</p> Name Type Description <code>dict</code> <code>dict</code> <p>The tags result dict from the finalize port.</p>"},{"location":"pipelines/extraction/","title":"Extraction","text":"<ul> <li>Csv</li> <li>Email</li> <li>Llama</li> <li>Pdf</li> <li>Shared</li> <li>Xlsx</li> </ul>"},{"location":"pipelines/extraction/#pipelines.extraction","title":"pipelines.extraction","text":""},{"location":"pipelines/extraction/#pipelines.extraction--summary","title":"Summary","text":"<p>Extraction pipelines, organized per source family.</p> <pre><code>pipeline \u2192 extraction \u2192 type [pdf,email,csv,xlsx,llama] \u2192 {pipeline.yaml, abc.py, impl.py, banks/}\n</code></pre> <p>Shared leaf contracts and cross-family machinery live in <code>shared/</code>; the registry mapping <code>(source_type, bank, pipeline) \u2192 root</code> lives in <code>shared/registry.py</code>.</p>"},{"location":"pipelines/extraction/csv/","title":"Csv","text":"<ul> <li>Abc</li> <li>Banks</li> <li>Impl</li> </ul>"},{"location":"pipelines/extraction/csv/#pipelines.extraction.csv","title":"pipelines.extraction.csv","text":""},{"location":"pipelines/extraction/csv/#pipelines.extraction.csv--summary","title":"Summary","text":"<p>csv (direct table) extraction family.</p>"},{"location":"pipelines/extraction/csv/abc/","title":"Abc","text":""},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc","title":"pipelines.extraction.csv.abc","text":""},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc--summary","title":"Summary","text":"<p>Abstract contracts for the csv (direct table) extraction graph.</p> <p>The csv family is a \"direct table\" pipeline \u2014 no OCR, no buckets, no ambiguity. It shares the tabular core (<code>shared/tabular.py</code>) with xlsx: only the table reader differs (csv rows vs xlsx worksheet rows). Bank-specific readers live under <code>banks/</code>.</p>"},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc-classes","title":"Classes","text":""},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc.CsvExtractionPipeline","title":"CsvExtractionPipeline","text":"<p> Bases: <code>TabularExtractionPipeline</code></p> <p>csv-family root \u2014 pins only the reader; chain shared with xlsx.</p> Slot annotations <p>source: ExtractionSource ingest, table_reader, txn_dicts, raw_expense</p> <p>Attributes:</p> Name Type Description <code>source</code> <code>ExtractionSource</code> <p>The extraction source descriptor.</p> <code>table_reader</code> <code>CsvTableReaderPort</code> <p>Csv table reader stage.</p>"},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc.CsvExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc.CsvExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the direct-table extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc.CsvTableReaderPort","title":"CsvTableReaderPort","text":"<p> Bases: <code>TableReaderPort</code></p> <p>content \u2192 list of typed records read from a csv statement file.</p>"},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc.CsvTableReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/csv/abc/#pipelines.extraction.csv.abc.CsvTableReaderPort.read","title":"read","text":"<pre><code>read(content) -&gt; List[dict]\n</code></pre> <p>Read typed records from a csv statement file.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content (bytes, Content, dict, or str).</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Typed table records.</p>"},{"location":"pipelines/extraction/csv/impl/","title":"Impl","text":""},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl","title":"pipelines.extraction.csv.impl","text":""},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl--summary","title":"Summary","text":"<p>Concrete csv-family implementations.</p> <p><code>ImplCsvTableReaderPort</code> reads csv rows with the omniread csv parser and runs them through the shared <code>TableParserMixin</code> (header location / aliases / typed conversion) to emit typed records. The chain (records \u2192 balance-adjusted txn dicts \u2192 raw expenses) is the shared tabular core.</p>"},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl-classes","title":"Classes","text":""},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl.ImplCsvExtractionPipeline","title":"ImplCsvExtractionPipeline","text":"<p> Bases: <code>CsvExtractionPipeline</code></p> <p>Concrete csv graph root.</p> <p>Attributes:</p> Name Type Description <code>ingest</code> <code>ImplIngestPort</code> <p>Ingest stage.</p> <code>table_reader</code> <code>ImplCsvTableReaderPort</code> <p>Csv table reader stage.</p> <code>txn_dicts</code> <code>ImplTabularTxnDictsPort</code> <p>Shared tabular txn-dicts stage.</p> <code>raw_expense</code> <code>ImplRawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl.ImplCsvExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl.ImplCsvExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the direct-table extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl.ImplCsvTableReaderPort","title":"ImplCsvTableReaderPort","text":"<p> Bases: <code>TableParserMixin</code>, <code>CsvTableReaderPort</code></p> <p>Concrete csv reader \u2014 omniread csv parser + shared <code>TableParserMixin</code>.</p>"},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl.ImplCsvTableReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/csv/impl/#pipelines.extraction.csv.impl.ImplCsvTableReaderPort.read","title":"read","text":"<pre><code>read(content) -&gt; List[dict]\n</code></pre> <p>Read typed records from csv content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content (Content, bytes, or dict).</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Typed table records.</p>"},{"location":"pipelines/extraction/csv/banks/","title":"Banks","text":"<ul> <li>Axis</li> <li>Icici</li> </ul>"},{"location":"pipelines/extraction/csv/banks/#pipelines.extraction.csv.banks","title":"pipelines.extraction.csv.banks","text":""},{"location":"pipelines/extraction/csv/banks/#pipelines.extraction.csv.banks--summary","title":"Summary","text":"<p>csv family \u2014 bank-specific ports and pipeline roots.</p>"},{"location":"pipelines/extraction/csv/banks/axis/","title":"Axis","text":""},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis","title":"pipelines.extraction.csv.banks.axis","text":""},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis--summary","title":"Summary","text":"<p>Axis bank-specific port implementations (csv table path).</p> <p>Faithful port of <code>domain/extraction/banks/axis/csv.py</code>:</p> <ul> <li>uses the shared <code>TableParserMixin</code> (icici-style header/alias logic),</li> <li>overrides <code>column_aliases</code> with the Axis DR/CR inversion \u2014 credits (salary, refunds, interest) arrive under DR with the balance rising and spends under CR with it falling (verified by balance-chain replay).</li> </ul> <p><code>AxisCsvExtractionPipeline</code> pins the reader; ordering/balance policy stays in the shared tabular txn_dicts stage.</p>"},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis-classes","title":"Classes","text":""},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis.AxisCsvExtractionPipeline","title":"AxisCsvExtractionPipeline","text":"<p> Bases: <code>ImplCsvExtractionPipeline</code></p> <p>Axis csv graph root \u2014 pins the Axis reader.</p> <p>Attributes:</p> Name Type Description <code>table_reader</code> <code>AxisCsvTableReaderPort</code> <p>Axis csv reader stage.</p>"},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis.AxisCsvExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis.AxisCsvExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the direct-table extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis.AxisCsvTableReaderPort","title":"AxisCsvTableReaderPort","text":"<p> Bases: <code>ImplCsvTableReaderPort</code></p> <p>Axis csv reader \u2014 DR/CR inverted column aliases.</p> <p>Attributes:</p> Name Type Description <code>column_aliases</code> <code>Dict[str, List[str]]</code> <p>Axis DR/CR-inverted aliases.</p> <code>required_columns</code> <code>tuple</code> <p>Required columns for header matching.</p>"},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis.AxisCsvTableReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/csv/banks/axis/#pipelines.extraction.csv.banks.axis.AxisCsvTableReaderPort.read","title":"read","text":"<pre><code>read(content) -&gt; List[dict]\n</code></pre> <p>Read typed records from csv content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content (Content, bytes, or dict).</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Typed table records.</p>"},{"location":"pipelines/extraction/csv/banks/icici/","title":"Icici","text":""},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici","title":"pipelines.extraction.csv.banks.icici","text":""},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici--summary","title":"Summary","text":"<p>Icici bank-specific port implementations (csv table path).</p> <p>Faithful port of <code>domain/extraction/banks/icici/csv.py</code>: shares all table logic with xlsx via the shared <code>TableParserMixin</code> (default icici aliases).</p> <p><code>IciciCsvExtractionPipeline</code> pins the reader; ordering/balance policy stays in the shared tabular txn_dicts stage.</p>"},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici-classes","title":"Classes","text":""},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici.IciciCsvExtractionPipeline","title":"IciciCsvExtractionPipeline","text":"<p> Bases: <code>ImplCsvExtractionPipeline</code></p> <p>Icici csv graph root \u2014 pins the Icici reader.</p> <p>Attributes:</p> Name Type Description <code>table_reader</code> <code>IciciCsvTableReaderPort</code> <p>Icici csv reader stage.</p>"},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici.IciciCsvExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici.IciciCsvExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the direct-table extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici.IciciCsvTableReaderPort","title":"IciciCsvTableReaderPort","text":"<p> Bases: <code>ImplCsvTableReaderPort</code></p> <p>Icici csv reader \u2014 inherits the default (icici) column aliases.</p>"},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici.IciciCsvTableReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/csv/banks/icici/#pipelines.extraction.csv.banks.icici.IciciCsvTableReaderPort.read","title":"read","text":"<pre><code>read(content) -&gt; List[dict]\n</code></pre> <p>Read typed records from csv content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content (Content, bytes, or dict).</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Typed table records.</p>"},{"location":"pipelines/extraction/email/","title":"Email","text":"<ul> <li>Abc</li> <li>Banks</li> <li>Impl</li> </ul>"},{"location":"pipelines/extraction/email/#pipelines.extraction.email","title":"pipelines.extraction.email","text":""},{"location":"pipelines/extraction/email/#pipelines.extraction.email--summary","title":"Summary","text":"<p>email (message) extraction family.</p>"},{"location":"pipelines/extraction/email/abc/","title":"Abc","text":""},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc","title":"pipelines.extraction.email.abc","text":""},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc--summary","title":"Summary","text":"<p>Abstract contracts for the email (message) extraction graph (no implementation).</p> <p>Email is NOT the OCR text chain. A message is self-contained \u2014 one HTML email maps to one transaction, so the chain is deliberately slim:</p> <pre><code>ingest \u2192 message_reader \u2192 message_parser \u2192 raw_expense\n</code></pre> <ul> <li>MessageReaderPort : content (Content/list/bytes) \u2192 list of flattened message texts (BeautifulSoup flatten of each email).</li> <li>MessageParserPort : message text \u2192 one txn dict (bank-specific regexes: Axis charged-to / debited-credited, Icici credited / refund / reversal).</li> <li>EmailExtractionPipeline : graph root (shared staged <code>run</code> lives in the concrete impl).</li> </ul> <p>No bucket finding, splitting, or ambiguity resolution happens here.</p>"},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc-classes","title":"Classes","text":""},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.EmailExtractionPipeline","title":"EmailExtractionPipeline","text":"<p> Bases: <code>ABC</code></p> <p>Root \u2014 wires ingest \u2192 message_reader \u2192 message_parser \u2192 raw_expense.</p> <p>Attributes:</p> Name Type Description <code>source</code> <code>ExtractionSource</code> <p>The extraction source descriptor.</p> <code>pipeline</code> <code>str</code> <p>Pipeline tag; defaults to \"heuristic\".</p> <code>ingest</code> <code>IngestPort</code> <p>Ingest stage.</p> <code>message_reader</code> <code>MessageReaderPort</code> <p>Message-reading stage.</p> <code>message_parser</code> <code>MessageParserPort</code> <p>Message-parsing stage.</p> <code>raw_expense</code> <code>RawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.EmailExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.EmailExtractionPipeline.run","title":"run <code>abstractmethod</code>","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the email extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.MessageParserPort","title":"MessageParserPort","text":"<p> Bases: <code>ABC</code></p> <p>message text \u2192 one txn dict (date/particulars/amount/balance/direction).</p>"},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.MessageParserPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.MessageParserPort.parse","title":"parse <code>abstractmethod</code>","text":"<pre><code>parse(message: str) -&gt; Dict[str, Any]\n</code></pre> <p>Parse one message into a txn dict.</p> <p>Parameters:</p> Name Type Description Default <code>message</code> <code>str</code> <p>Flattened message text.</p> required <p>Returns:</p> Type Description <code>Dict[str, Any]</code> <p>Dict[str, Any]: Txn dict with date/particulars/amount/balance/</p> <code>Dict[str, Any]</code> <p>direction keys.</p>"},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.MessageReaderPort","title":"MessageReaderPort","text":"<p> Bases: <code>ABC</code></p> <p>content \u2192 list of flattened message texts.</p>"},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.MessageReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/abc/#pipelines.extraction.email.abc.MessageReaderPort.extract","title":"extract <code>abstractmethod</code>","text":"<pre><code>extract(content) -&gt; List[str]\n</code></pre> <p>Flatten content into message texts.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Content (list, bytes, dict, or a single source).</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Flattened message texts.</p>"},{"location":"pipelines/extraction/email/impl/","title":"Impl","text":""},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl","title":"pipelines.extraction.email.impl","text":""},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl--summary","title":"Summary","text":"<p>Concrete email-family implementations.</p> <p>Faithful port of the OG email adaptors (domain/extraction/banks/{axis,icici}/email.py): a BeautifulSoup flatten of each HTML message into one text blob, then a bank-specific regex parse into a single transaction. <code>ImplMessageReaderPort</code> is shared; <code>ImplMessageParserPort</code> carries the shared description-slicing helper and the per-bank modules subclass it with their own regex/date rules.</p>"},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl-classes","title":"Classes","text":""},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplEmailExtractionPipeline","title":"ImplEmailExtractionPipeline","text":"<p> Bases: <code>EmailExtractionPipeline</code></p> <p>Concrete email graph root.</p> <p>Attributes:</p> Name Type Description <code>pipeline</code> <code>str</code> <p>Pipeline tag (\"heuristic\").</p> <code>ingest</code> <code>ImplIngestPort</code> <p>Ingest stage.</p> <code>message_reader</code> <code>ImplMessageReaderPort</code> <p>Message-reading stage.</p> <code>message_parser</code> <code>ImplMessageParserPort</code> <p>Message-parsing stage.</p> <code>raw_expense</code> <code>ImplRawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplEmailExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplEmailExtractionPipeline.run","title":"run","text":"<pre><code>run(source)\n</code></pre> <p>Run the email extraction chain end-to-end.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <p>List of raw expense records.</p>"},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplMessageParserPort","title":"ImplMessageParserPort","text":"<p> Bases: <code>MessageParserPort</code></p> <p>Base email parser: shared description-slicing; banks implement parse.</p> <p>Attributes:</p> Name Type Description <code>description_starts</code> <code>List[str]</code> <p>Markers where descriptions begin.</p> <code>description_ends</code> <code>List[str]</code> <p>Markers where descriptions end.</p>"},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplMessageParserPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplMessageParserPort.parse","title":"parse","text":"<pre><code>parse(message: str)\n</code></pre> <p>Parse one message into a txn dict.</p> <p>Parameters:</p> Name Type Description Default <code>message</code> <code>str</code> <p>Flattened message text.</p> required <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>Always; subclasses must implement <code>parse</code>.</p>"},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplMessageReaderPort","title":"ImplMessageReaderPort","text":"<p> Bases: <code>MessageReaderPort</code></p> <p>Concrete message reader \u2014 HTML flattens each message to text.</p>"},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplMessageReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/impl/#pipelines.extraction.email.impl.ImplMessageReaderPort.extract","title":"extract","text":"<pre><code>extract(content) -&gt; List[str]\n</code></pre> <p>Flatten each message source into text.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Content, list/tuple of sources, or a single source.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Flattened message texts.</p>"},{"location":"pipelines/extraction/email/banks/","title":"Banks","text":"<ul> <li>Axis</li> <li>Icici</li> </ul>"},{"location":"pipelines/extraction/email/banks/#pipelines.extraction.email.banks","title":"pipelines.extraction.email.banks","text":""},{"location":"pipelines/extraction/email/banks/#pipelines.extraction.email.banks--summary","title":"Summary","text":"<p>email family \u2014 bank-specific ports and pipeline roots.</p>"},{"location":"pipelines/extraction/email/banks/axis/","title":"Axis","text":""},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis","title":"pipelines.extraction.email.banks.axis","text":""},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis--summary","title":"Summary","text":"<p>Axis bank-specific port implementations (email message path).</p> <p>Faithful port of <code>domain/extraction/banks/axis/email.py</code> (<code>AxisTransactionParserAdaptor.parse</code>): INR amount, debited/credited direction, DD-MM-YYYY timestamped date, and a description sliced between <code>Axis Bank Credit Card Transaction:</code> and the trailing spam markers.</p>"},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis-classes","title":"Classes","text":""},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis.AxisEmailExtractionPipeline","title":"AxisEmailExtractionPipeline","text":"<p> Bases: <code>ImplEmailExtractionPipeline</code></p> <p>Axis email graph root \u2014 pins the Axis message parser.</p> <p>Attributes:</p> Name Type Description <code>message_parser</code> <code>AxisMessageParserPort</code> <p>Axis message parser.</p>"},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis.AxisEmailExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis.AxisEmailExtractionPipeline.run","title":"run","text":"<pre><code>run(source)\n</code></pre> <p>Run the email extraction chain end-to-end.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <p>List of raw expense records.</p>"},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis.AxisMessageParserPort","title":"AxisMessageParserPort","text":"<p> Bases: <code>ImplMessageParserPort</code></p> <p>Axis email parser \u2014 INR amount, debited/credited, timestamped date.</p> <p>Attributes:</p> Name Type Description <code>description_starts</code> <code>List[str]</code> <p>Axis description start markers.</p> <code>description_ends</code> <code>List[str]</code> <p>Axis description end markers.</p>"},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis.AxisMessageParserPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/banks/axis/#pipelines.extraction.email.banks.axis.AxisMessageParserPort.parse","title":"parse","text":"<pre><code>parse(message: str)\n</code></pre> <p>Parse an Axis message into one txn dict.</p> <p>Parameters:</p> Name Type Description Default <code>message</code> <code>str</code> <p>Flattened message text.</p> required <p>Returns:</p> Type Description <p>Txn dict with txn_date, particulars, amount, balance, direction.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When the amount or transaction date is not found.</p>"},{"location":"pipelines/extraction/email/banks/icici/","title":"Icici","text":""},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici","title":"pipelines.extraction.email.banks.icici","text":""},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici--summary","title":"Summary","text":"<p>Icici bank-specific port implementations (email message path).</p> <p>Faithful port of <code>domain/extraction/banks/icici/email.py</code> (<code>IciciTransactionParserAdaptor.parse</code>): INR amount, credited/refund/ reversal direction, <code>on &lt;Mon DD, YYYY&gt; at &lt;HH:MM:SS&gt;</code> date formatting to DD-MM-YYYY, and a description sliced between <code>Info:</code> and the available credit-limit footer.</p>"},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici-classes","title":"Classes","text":""},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici.IciciEmailExtractionPipeline","title":"IciciEmailExtractionPipeline","text":"<p> Bases: <code>ImplEmailExtractionPipeline</code></p> <p>Icici email graph root \u2014 pins the Icici message parser.</p> <p>Attributes:</p> Name Type Description <code>message_parser</code> <code>IciciMessageParserPort</code> <p>Icici message parser.</p>"},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici.IciciEmailExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici.IciciEmailExtractionPipeline.run","title":"run","text":"<pre><code>run(source)\n</code></pre> <p>Run the email extraction chain end-to-end.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <p>List of raw expense records.</p>"},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici.IciciMessageParserPort","title":"IciciMessageParserPort","text":"<p> Bases: <code>ImplMessageParserPort</code></p> <p>Icici email parser \u2014 credited/refund/reversal direction, DD-MM-YYYY.</p> <p>Attributes:</p> Name Type Description <code>description_starts</code> <code>List[str]</code> <p>Icici description start markers.</p> <code>description_ends</code> <code>List[str]</code> <p>Icici description end markers.</p>"},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici.IciciMessageParserPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/email/banks/icici/#pipelines.extraction.email.banks.icici.IciciMessageParserPort.parse","title":"parse","text":"<pre><code>parse(message: str)\n</code></pre> <p>Parse an Icici message into one txn dict.</p> <p>Parameters:</p> Name Type Description Default <code>message</code> <code>str</code> <p>Flattened message text.</p> required <p>Returns:</p> Type Description <p>Txn dict with txn_date, particulars, amount, balance, direction.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When the amount or transaction date is not found.</p>"},{"location":"pipelines/extraction/llama/","title":"Llama","text":"<ul> <li>Abc</li> <li>Banks</li> <li>Impl</li> </ul>"},{"location":"pipelines/extraction/llama/#pipelines.extraction.llama","title":"pipelines.extraction.llama","text":""},{"location":"pipelines/extraction/llama/#pipelines.extraction.llama--summary","title":"Summary","text":"<p>Llama (structured-objects) extraction family.</p>"},{"location":"pipelines/extraction/llama/abc/","title":"Abc","text":""},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc","title":"pipelines.extraction.llama.abc","text":""},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc--summary","title":"Summary","text":"<p>Abstract contracts for the llama (structured-objects) extraction graph.</p> <p>The llama family is \"tabular-like\" but the front stage differs: instead of reading table rows it starts from a LIST OF ALREADY-STRUCTURED OBJECTS (one per transaction \u2014 what LlamaCloud returns, or the cached fixture CSV standing in for it). The downstream stages reuse the shared core:</p> <ul> <li><code>LlamaObjectsReaderPort</code> : list of objects -&gt; filtered records (drops B/F marker rows + pre-marker header rows, port of OG <code>BucketFinderAdaptor.filter_txn_rows</code>).</li> <li><code>LlamaExtractionPipeline</code>: root matching the tabular run-driver shape, but routed through <code>objects_reader</code> instead of <code>table_reader</code>. It reuses <code>ImplIngestPort</code> (list pass-through), <code>ObjectsTxnDictsPort</code> (stated balances trusted) and <code>ImplRawExpensePort</code>.</li> </ul> <p>Bank-specific wiring lives under <code>banks/</code>.</p>"},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc-classes","title":"Classes","text":""},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc.LlamaExtractionPipeline","title":"LlamaExtractionPipeline","text":"<p> Bases: <code>ABC</code></p> <p>Root \u2014 objects chain: ingest \u2192 objects_reader \u2192 txn_dicts \u2192 raw_expense.</p> Slot annotations <p>source: ExtractionSource ingest: IngestPort objects_reader: LlamaObjectsReaderPort txn_dicts: ObjectsTxnDictsPort raw_expense: RawExpensePort</p> <p>Attributes:</p> Name Type Description <code>source</code> <code>ExtractionSource</code> <p>The extraction source descriptor.</p> <code>pipeline</code> <code>str</code> <p>Pipeline tag (\"llama\").</p> <code>ingest</code> <code>IngestPort</code> <p>Ingest stage.</p> <code>objects_reader</code> <code>LlamaObjectsReaderPort</code> <p>Objects-reading stage.</p> <code>txn_dicts</code> <code>ObjectsTxnDictsPort</code> <p>Objects-to-txn-dicts stage.</p> <code>raw_expense</code> <code>RawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc.LlamaExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc.LlamaExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the llama objects extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc.LlamaObjectsReaderPort","title":"LlamaObjectsReaderPort","text":"<p> Bases: <code>ABC</code></p> <p>list of structured objects \u2192 list of filtered records (in order).</p>"},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc.LlamaObjectsReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/llama/abc/#pipelines.extraction.llama.abc.LlamaObjectsReaderPort.read","title":"read <code>abstractmethod</code>","text":"<pre><code>read(objects) -&gt; List[Dict[str, Any]]\n</code></pre> <p>Read structured objects, dropping marker and header rows.</p> <p>Parameters:</p> Name Type Description Default <code>objects</code> <p>List of structured statement objects.</p> required <p>Returns:</p> Type Description <code>List[Dict[str, Any]]</code> <p>List[Dict[str, Any]]: Filtered records in order.</p>"},{"location":"pipelines/extraction/llama/impl/","title":"Impl","text":""},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl","title":"pipelines.extraction.llama.impl","text":""},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl--summary","title":"Summary","text":"<p>Concrete llama-family implementations.</p> <p><code>ImplLlamaObjectsReaderPort</code> receives the list of already-structured statement objects (the equivalent of the LlamaCloud extract result) and applies the row-level bucket filter \u2014 B/F marker rows and any rows before the first marker are dropped, mirroring OG <code>domain.extraction.adaptors.txn_blocks.BucketFinderAdaptor.filter_txn_rows</code>. The downstream chain (objects \u2192 txn dicts \u2192 raw expenses) is the shared core: <code>ImplTxnDictsObjectsPort</code> (stated balances trusted) + <code>ImplRawExpensePort</code>.</p>"},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl-classes","title":"Classes","text":""},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl.ImplLlamaExtractionPipeline","title":"ImplLlamaExtractionPipeline","text":"<p> Bases: <code>LlamaExtractionPipeline</code></p> <p>Concrete llama graph root.</p> <p>Attributes:</p> Name Type Description <code>ingest</code> <code>ImplIngestPort</code> <p>Ingest stage.</p> <code>objects_reader</code> <code>ImplLlamaObjectsReaderPort</code> <p>Objects-reading stage.</p> <code>txn_dicts</code> <code>ImplObjectsTxnDictsPort</code> <p>Objects-to-txn-dicts stage.</p> <code>raw_expense</code> <code>ImplRawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl.ImplLlamaExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl.ImplLlamaExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the llama objects extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl.ImplLlamaObjectsReaderPort","title":"ImplLlamaObjectsReaderPort","text":"<p> Bases: <code>LlamaObjectsReaderPort</code></p> <p>Drop B/F marker rows + pre-marker header rows from a statement list.</p> <p>Mirrors the OG bucket finder contract exactly: markers are <code>B/F</code> / <code>BIF</code> / <code>B|F</code> matched against each object's description (upper-cased). With <code>limit_first</code> only the first (primary) bucket is kept (default <code>False</code>, like the OG lama service; the icici bank module overrides it to <code>True</code> to match the icici OG CONFIG). Statements without a marker row pass through.</p> <p>Attributes:</p> Name Type Description <code>bf_markers</code> <code>tuple</code> <p>Marker tokens identifying bucket boundaries.</p> <code>limit_first</code> <code>bool</code> <p>Keep only the first bucket.</p>"},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl.ImplLlamaObjectsReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl.ImplLlamaObjectsReaderPort.filter_objects","title":"filter_objects","text":"<pre><code>filter_objects(\n objects: List[Any], *, limit_first: bool = False\n) -&gt; List[dict]\n</code></pre> <p>Filter objects to rows between balance-forward marker rows.</p> <p>Parameters:</p> Name Type Description Default <code>objects</code> <code>List[Any]</code> <p>Structured statement objects.</p> required <code>limit_first</code> <code>bool</code> <p>Keep only the first bucket. Defaults to False.</p> <code>False</code> <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Records between (and after) marker rows.</p>"},{"location":"pipelines/extraction/llama/impl/#pipelines.extraction.llama.impl.ImplLlamaObjectsReaderPort.read","title":"read","text":"<pre><code>read(objects) -&gt; List[dict]\n</code></pre> <p>Read structured objects, applying the row-level bucket filter.</p> <p>Parameters:</p> Name Type Description Default <code>objects</code> <p>List of structured statement objects.</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Filtered records in order.</p>"},{"location":"pipelines/extraction/llama/banks/","title":"Banks","text":"<ul> <li>Icici</li> </ul>"},{"location":"pipelines/extraction/llama/banks/#pipelines.extraction.llama.banks","title":"pipelines.extraction.llama.banks","text":""},{"location":"pipelines/extraction/llama/banks/#pipelines.extraction.llama.banks--summary","title":"Summary","text":"<p>Llama-family bank-specific wiring.</p>"},{"location":"pipelines/extraction/llama/banks/icici/","title":"Icici","text":""},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici","title":"pipelines.extraction.llama.banks.icici","text":""},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici--summary","title":"Summary","text":"<p>Icici bank-specific port implementations (llama objects path).</p> <p>The llama objects are already normalized per-transaction (date / amount / balance / description / direction), so there is no bank-specific column logic. <code>IciciLlamaObjectsReaderPort</code> mirrors the icici OG bank CONFIG <code>{\"limit_first\": True}</code> (keeps only the primary account bucket), matching the 223-txn llama run stored in the DB. <code>IciciLlamaExtractionPipeline</code> pins the reader; the shared objects policy (stated balances trusted) is identical across banks.</p>"},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici-classes","title":"Classes","text":""},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici.IciciLlamaExtractionPipeline","title":"IciciLlamaExtractionPipeline","text":"<p> Bases: <code>ImplLlamaExtractionPipeline</code></p> <p>Icici llama graph root \u2014 pins the Icici objects reader.</p> <p>Attributes:</p> Name Type Description <code>objects_reader</code> <code>IciciLlamaObjectsReaderPort</code> <p>Icici objects reader.</p>"},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici.IciciLlamaExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici.IciciLlamaExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the llama objects extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici.IciciLlamaObjectsReaderPort","title":"IciciLlamaObjectsReaderPort","text":"<p> Bases: <code>ImplLlamaObjectsReaderPort</code></p> <p>Icici llama objects reader \u2014 primary bucket only (OG icici CONFIG).</p> <p>Attributes:</p> Name Type Description <code>limit_first</code> <code>bool</code> <p>Whether to keep only the primary bucket.</p>"},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici.IciciLlamaObjectsReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici.IciciLlamaObjectsReaderPort.filter_objects","title":"filter_objects","text":"<pre><code>filter_objects(\n objects: List[Any], *, limit_first: bool = False\n) -&gt; List[dict]\n</code></pre> <p>Filter objects to rows between balance-forward marker rows.</p> <p>Parameters:</p> Name Type Description Default <code>objects</code> <code>List[Any]</code> <p>Structured statement objects.</p> required <code>limit_first</code> <code>bool</code> <p>Keep only the first bucket. Defaults to False.</p> <code>False</code> <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Records between (and after) marker rows.</p>"},{"location":"pipelines/extraction/llama/banks/icici/#pipelines.extraction.llama.banks.icici.IciciLlamaObjectsReaderPort.read","title":"read","text":"<pre><code>read(objects) -&gt; List[dict]\n</code></pre> <p>Read structured objects, applying the row-level bucket filter.</p> <p>Parameters:</p> Name Type Description Default <code>objects</code> <p>List of structured statement objects.</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Filtered records in order.</p>"},{"location":"pipelines/extraction/pdf/","title":"Pdf","text":"<ul> <li>Abc</li> <li>Banks</li> <li>Impl</li> <li>Llm</li> </ul>"},{"location":"pipelines/extraction/pdf/#pipelines.extraction.pdf","title":"pipelines.extraction.pdf","text":""},{"location":"pipelines/extraction/pdf/#pipelines.extraction.pdf--summary","title":"Summary","text":"<p>pdf (OCR text) extraction family.</p>"},{"location":"pipelines/extraction/pdf/abc/","title":"Abc","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc","title":"pipelines.extraction.pdf.abc","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc--summary","title":"Summary","text":"<p>Abstract contracts for the pdf (OCR text) extraction graph (no implementation).</p> <p>The pdf family is the classic heuristic text chain:</p> <pre><code>ingest \u2192 raw_lines \u2192 txn_blocks \u2192 txn_dicts \u2192 raw_expense\n</code></pre> <p>Non-PDF families (email / csv / xlsx) do NOT extend this root \u2014 they have their own stage chains (see <code>email/abc.py</code> and <code>shared/tabular.py</code>).</p> <p>The annotations on each class declare WHAT it needs. Concrete implementations (re)declare the same port slots with CONCRETE types to inform which implementation is used, and implement the @abstractmethod bodies.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc-classes","title":"Classes","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.BucketFinderPort","title":"BucketFinderPort","text":"<p> Bases: <code>ABC</code></p> <p>Divide raw_lines into account buckets at B/F markers.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>NumberPort</code> <p>Number extraction leaf.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.BucketFinderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.BucketFinderPort.get_opening_balance_buckets","title":"get_opening_balance_buckets <code>abstractmethod</code>","text":"<pre><code>get_opening_balance_buckets(\n lines: List[str],\n *,\n limit_first: bool = False,\n line_offset: int = 0\n) -&gt; List[tuple]\n</code></pre> <p>Divide raw lines into account buckets at B/F markers.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <code>List[str]</code> <p>Raw text lines.</p> required <code>limit_first</code> <code>bool</code> <p>Keep only the first bucket. Defaults to False.</p> <code>False</code> <code>line_offset</code> <code>int</code> <p>Offset added to starting indices. Defaults to 0.</p> <code>0</code> <p>Returns:</p> Type Description <code>List[tuple]</code> <p>List[tuple]: <code>(start, end, opening_balance)</code> bucket triples.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.PDFExtractionPipeline","title":"PDFExtractionPipeline","text":"<p> Bases: <code>ABC</code></p> <p>Root \u2014 wires ingest \u2192 raw_lines \u2192 txn_blocks \u2192 txn_dicts \u2192 raw_expenses.</p> <p>Attributes:</p> Name Type Description <code>source</code> <code>ExtractionSource</code> <p>The extraction source descriptor.</p> <code>pipeline</code> <code>str</code> <p>Pipeline tag; defaults to \"heuristic\".</p> <code>trust_fallback</code> <p>Fallback policy for amount/balance trust.</p> <code>ingest</code> <code>IngestPort</code> <p>Ingest stage.</p> <code>raw_lines</code> <code>RawLinesPort</code> <p>Raw-lines stage.</p> <code>txn_blocks</code> <code>TxnBlocksPort</code> <p>Txn-blocks stage.</p> <code>txn_dicts</code> <code>TxnDictsPort</code> <p>Txn-dicts stage.</p> <code>raw_expense</code> <code>RawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.PDFExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.PDFExtractionPipeline.run","title":"run <code>abstractmethod</code>","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the pdf extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.RawLinesPort","title":"RawLinesPort","text":"<p> Bases: <code>ABC</code></p> <p>content \u2192 list of raw text lines.</p> <p>Attributes:</p> Name Type Description <code>covert_to_image</code> <code>bool</code> <p>Whether to binarize pages via image conversion.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.RawLinesPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.RawLinesPort.extract","title":"extract <code>abstractmethod</code>","text":"<pre><code>extract(content) -&gt; List[str]\n</code></pre> <p>Extract raw OCR text lines from content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content payload.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Raw text lines.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.SplitterPort","title":"SplitterPort","text":"<p> Bases: <code>ABC</code></p> <p>Split bucket line-groups into transaction blocks.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>NumberPort</code> <p>Number extraction leaf.</p> <code>date</code> <code>DatePort</code> <p>Date parsing leaf.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.SplitterPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.SplitterPort.split_blocks","title":"split_blocks <code>abstractmethod</code>","text":"<pre><code>split_blocks(\n lines: List[str],\n *,\n has_header: bool = False,\n min_numbers: int = 3,\n detect_date_ranges: bool = False\n) -&gt; List[str]\n</code></pre> <p>Split bucket line-groups into transaction blocks.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <code>List[str]</code> <p>Lines belonging to one account bucket.</p> required <code>has_header</code> <code>bool</code> <p>Whether a header precedes the rows.</p> <code>False</code> <code>min_numbers</code> <code>int</code> <p>Minimum numbers for a split.</p> <code>3</code> <code>detect_date_ranges</code> <code>bool</code> <p>Detect date-range lines.</p> <code>False</code> <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Transaction block texts.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TransactionParserPort","title":"TransactionParserPort","text":"<p> Bases: <code>ABC</code></p> <p>Parse one transaction block into a structured dict.</p> <p>Attributes:</p> Name Type Description <code>min_numbers</code> <code>int</code> <p>Minimum numbers for a block.</p> <code>amount_index</code> <code>int</code> <p>Index of the amount in the number list.</p> <code>balance_index</code> <code>int</code> <p>Index of the balance in the number list.</p> <code>number</code> <code>NumberPort</code> <p>Number extraction leaf.</p> <code>date</code> <code>DatePort</code> <p>Date parsing leaf.</p> <code>desc</code> <code>DescPort</code> <p>Description extraction leaf.</p> <code>amount_balance</code> <code>AmountBalancePort</code> <p>Amount/balance resolution leaf.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TransactionParserPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TransactionParserPort.parse","title":"parse <code>abstractmethod</code>","text":"<pre><code>parse(\n txn_text: str, prev_date_str, prev_balance: float\n) -&gt; Dict[str, Any]\n</code></pre> <p>Parse one transaction block into a structured dict.</p> <p>Parameters:</p> Name Type Description Default <code>txn_text</code> <code>str</code> <p>Transaction block text.</p> required <code>prev_date_str</code> <p>Previous transaction date string.</p> required <code>prev_balance</code> <code>float</code> <p>Running balance from the previous transaction.</p> required <p>Returns:</p> Type Description <code>Dict[str, Any]</code> <p>Dict[str, Any]: Parsed transaction dict.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TxnBlocksPort","title":"TxnBlocksPort","text":"<p> Bases: <code>ABC</code></p> <p>raw_lines \u2192 txn_blocks (opening_balance \u2192 list[block strings]).</p> <p>Attributes:</p> Name Type Description <code>has_header</code> <code>bool</code> <p>Whether a header precedes the rows.</p> <code>min_numbers</code> <code>int</code> <p>Minimum numbers for block splitting.</p> <code>detect_date_ranges</code> <code>bool</code> <p>Detect date-range lines.</p> <code>limit_first</code> <code>bool</code> <p>Keep only the first bucket.</p> <code>line_offset</code> <code>int</code> <p>Offset added to starting indices.</p> <code>bucket_finder</code> <code>BucketFinderPort</code> <p>Bucket-finding stage.</p> <code>splitter</code> <code>SplitterPort</code> <p>Block-splitting stage.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TxnBlocksPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TxnBlocksPort.extract","title":"extract <code>abstractmethod</code>","text":"<pre><code>extract(raw_lines: List[str]) -&gt; Dict[float, List[str]]\n</code></pre> <p>Extract txn blocks keyed by opening balance.</p> <p>Parameters:</p> Name Type Description Default <code>raw_lines</code> <code>List[str]</code> <p>Raw OCR text lines.</p> required <p>Returns:</p> Type Description <code>Dict[float, List[str]]</code> <p>Dict[float, List[str]]: Opening balance \u2192 block texts.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TxnDictsPort","title":"TxnDictsPort","text":"<p> Bases: <code>ABC</code></p> <p>txn_blocks \u2192 list of structured txn dicts.</p> <p>Attributes:</p> Name Type Description <code>min_numbers</code> <code>int</code> <p>Minimum numbers for a block.</p> <code>amount_index</code> <code>int</code> <p>Index of the amount in the number list.</p> <code>balance_index</code> <code>int</code> <p>Index of the balance in the number list.</p> <code>parser</code> <code>TransactionParserPort</code> <p>Transaction parsing stage.</p>"},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TxnDictsPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/abc/#pipelines.extraction.pdf.abc.TxnDictsPort.extract","title":"extract <code>abstractmethod</code>","text":"<pre><code>extract(txn_blocks: Dict[float, List[str]]) -&gt; Any\n</code></pre> <p>Extract structured txn dicts from txn blocks.</p> <p>Parameters:</p> Name Type Description Default <code>txn_blocks</code> <code>Dict[float, List[str]]</code> <p>Opening balance \u2192 block texts.</p> required <p>Returns:</p> Name Type Description <code>Any</code> <code>Any</code> <p>List of txn dicts.</p>"},{"location":"pipelines/extraction/pdf/impl/","title":"Impl","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl","title":"pipelines.extraction.pdf.impl","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl--summary","title":"Summary","text":"<p>Concrete pdf-family implementations.</p> <p>The pdf family is the OCR text chain; each concrete class REDECLARES its port slots with CONCRETE types \u2014 this pinned typing is what informs the ports to be used, exactly as in the old <code>pipelines/extraction_pipeline_impl.py</code>.</p> <p>This models the real <code>domain/extraction</code> pdf path as a hexa composition tree:</p> <ul> <li>ImplDatePort : port of domain.extraction.ports.date.DatePort</li> <li>ImplBucketFinderPort: port of BucketFinderAdaptor.get_opening_balance_buckets</li> <li>ImplSplitterPort : port of TransactionSplitterAdaptor.split_blocks</li> <li>ImplTransactionParserPort: port of TransactionParserAdaptor.parse</li> <li>ImplRawLinesPort : port of PdfRawLinesAdaptor (ocr_all_pages + normalize)</li> </ul>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl-classes","title":"Classes","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplAmbiguityPort","title":"ImplAmbiguityPort","text":"<pre><code>ImplAmbiguityPort(\n fetch_request_id: str = \"\",\n pause_on_ambiguity: bool = True,\n resolved_choices: Optional[dict] = None,\n resolver: Optional[Callable] = None,\n)\n</code></pre> <p> Bases: <code>AmbiguityPort</code>, <code>AmbiguityHandler</code></p> <p>Concrete ambiguity leaf \u2014 delegates to <code>AmbiguityHandler</code>.</p> <p>Initialize the ambiguity handler.</p> <p>Parameters:</p> Name Type Description Default <code>fetch_request_id</code> <code>str</code> <p>Identifier correlating this resolution to a fetch request. Defaults to <code>\"\"</code>.</p> <code>''</code> <code>pause_on_ambiguity</code> <code>bool</code> <p>Whether to raise <code>PauseForResolution</code> when unresolved. Defaults to <code>True</code>.</p> <code>True</code> <code>resolved_choices</code> <code>Optional[dict]</code> <p>Prior choices keyed by candidate key. Defaults to <code>None</code> (becomes an empty dict).</p> <code>None</code> <code>resolver</code> <code>Optional[Callable]</code> <p>Optional resolver hook. Defaults to <code>None</code>.</p> <code>None</code>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplAmbiguityPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplAmbiguityPort.resolve_ambiguity","title":"resolve_ambiguity","text":"<pre><code>resolve_ambiguity(\n line,\n ocr_amount,\n ocr_balance,\n prev_balance,\n candidates=None,\n)\n</code></pre> <p>Resolve ambiguity via <code>AmbiguityHandler.resolve_ambiguity</code>.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <p>Raw transaction line.</p> required <code>ocr_amount</code> <p>OCR amount.</p> required <code>ocr_balance</code> <p>OCR balance.</p> required <code>prev_balance</code> <p>Previous transaction balance.</p> required <code>candidates</code> <p>Candidate (amount, balance) pairs; default <code>set()</code>.</p> <code>None</code> <p>Returns:</p> Type Description <p>Set with the chosen pair, or <code>None</code>.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplAmountBalancePort","title":"ImplAmountBalancePort","text":"<p> Bases: <code>AmountBalancePort</code></p> <p>Concrete amount/balance leaf \u2014 resolves via <code>ResolutionContext</code>.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>ImplNumberPort</code> <p>Number extraction leaf.</p> <code>ambiguity</code> <code>ImplAmbiguityPort</code> <p>Ambiguity resolution leaf.</p> <code>handler</code> <code>Optional[AmbiguityHandler]</code> <p>Optional override handler.</p> <code>trust_fallback</code> <code>Optional[str]</code> <p>Fallback policy.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplAmountBalancePort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplAmountBalancePort.adjust_balance","title":"adjust_balance","text":"<pre><code>adjust_balance(balance: float, line: str) -&gt; float\n</code></pre> <p>Adjust an OCR balance (no-op base).</p> <p>Parameters:</p> Name Type Description Default <code>balance</code> <code>float</code> <p>OCR balance.</p> required <code>line</code> <code>str</code> <p>Transaction line.</p> required <p>Returns:</p> Name Type Description <code>float</code> <code>float</code> <p>The balance, unmodified.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplAmountBalancePort.missing_number_candidates","title":"missing_number_candidates","text":"<pre><code>missing_number_candidates(ctx)\n</code></pre> <p>Provide candidates for one-number lines (no-op base).</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <p>The active <code>ResolutionContext</code>.</p> required <p>Returns:</p> Type Description <p>None.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplAmountBalancePort.resolve","title":"resolve","text":"<pre><code>resolve(amount, balance, prev_balance, line, numbers=None)\n</code></pre> <p>Resolve (amount, balance) via <code>ResolutionContext</code>.</p> <p>Parameters:</p> Name Type Description Default <code>amount</code> <p>OCR amount.</p> required <code>balance</code> <p>OCR balance (adjusted first).</p> required <code>prev_balance</code> <p>Previous transaction balance.</p> required <code>line</code> <p>Raw transaction line.</p> required <code>numbers</code> <p>Extracted numbers; default None.</p> <code>None</code> <p>Returns:</p> Type Description <p>(signed amount, resolved balance) tuple.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplBucketFinderPort","title":"ImplBucketFinderPort","text":"<p> Bases: <code>BucketFinderPort</code></p> <p>Concrete bucket finder \u2014 splits raw lines at B/F and opening markers.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>ImplNumberPort</code> <p>Number extraction leaf.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplBucketFinderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplBucketFinderPort.get_opening_balance_buckets","title":"get_opening_balance_buckets","text":"<pre><code>get_opening_balance_buckets(\n lines, *, limit_first=False, line_offset=0\n)\n</code></pre> <p>Divide raw lines into opening-balance buckets.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <p>Raw text lines.</p> required <code>limit_first</code> <p>Keep only the first bucket.</p> <code>False</code> <code>line_offset</code> <p>Offset added to starting indices.</p> <code>0</code> <p>Returns:</p> Type Description <p>List of <code>(start, end, opening_balance)</code> triples.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort","title":"ImplDatePort","text":"<p> Bases: <code>DatePort</code></p> <p>Concrete date leaf: parse, split, reconcile, and reorder dates.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort.get_dates","title":"get_dates","text":"<pre><code>get_dates(line: str) -&gt; Optional[Tuple[str, str]]\n</code></pre> <p>Extract the leading date and text tail from a line.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line.</p> required <p>Returns:</p> Type Description <code>Optional[Tuple[str, str]]</code> <p>Optional[Tuple[str, str]]: <code>(date_str, date_tail)</code> or <code>None</code>.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort.parse_date","title":"parse_date","text":"<pre><code>parse_date(date_str: str) -&gt; datetime.date\n</code></pre> <p>Parse <code>DD-MM-YYYY</code> (or <code>DD/MM/YYYY</code>) into a date.</p> <p>Parameters:</p> Name Type Description Default <code>date_str</code> <code>str</code> <p>Date string.</p> required <p>Returns:</p> Type Description <code>date</code> <p>datetime.date: The parsed date.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort.reconcile_date","title":"reconcile_date","text":"<pre><code>reconcile_date(\n date_str: str, prev_date_str: Optional[str]\n) -&gt; str\n</code></pre> <p>Reconcile an OCR date against the previous transaction date.</p> <p>Parameters:</p> Name Type Description Default <code>date_str</code> <code>str</code> <p>OCR date string.</p> required <code>prev_date_str</code> <code>Optional[str]</code> <p>Previous transaction date string.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Reconciliated date as <code>DD-MM-YYYY</code>.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort.reconcile_date_full","title":"reconcile_date_full","text":"<pre><code>reconcile_date_full(\n date_str: str, prev: datetime.date\n) -&gt; Optional[str]\n</code></pre> <p>Reconcile a date string against a full reference date.</p> <p>Parameters:</p> Name Type Description Default <code>date_str</code> <code>str</code> <p>OCR date string.</p> required <code>prev</code> <code>date</code> <p>Previous transaction date.</p> required <p>Returns:</p> Type Description <code>Optional[str]</code> <p>Optional[str]: Reconciliated <code>DD-MM-YYYY</code> string or <code>None</code>.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort.reconcile_date_partial","title":"reconcile_date_partial","text":"<pre><code>reconcile_date_partial(\n date_str: str, prev: datetime.date\n) -&gt; Optional[str]\n</code></pre> <p>Reconcile a partial <code>MM-YYYY</code> date against a reference date.</p> <p>Parameters:</p> Name Type Description Default <code>date_str</code> <code>str</code> <p>Partial OCR date string.</p> required <code>prev</code> <code>date</code> <p>Previous transaction date.</p> required <p>Returns:</p> Type Description <code>Optional[str]</code> <p>Optional[str]: Reconciliated <code>DD-MM-YYYY</code> string or <code>None</code>.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort.reorder_lines_by_date","title":"reorder_lines_by_date","text":"<pre><code>reorder_lines_by_date(txn_lines: List[str]) -&gt; List[str]\n</code></pre> <p>Move the dated line to the front of a transaction block.</p> <p>Parameters:</p> Name Type Description Default <code>txn_lines</code> <code>List[str]</code> <p>Transaction block lines.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Reordered lines.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When no dated line is present in the block.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDatePort.split_line_by_date","title":"split_line_by_date","text":"<pre><code>split_line_by_date(line: str) -&gt; List[str]\n</code></pre> <p>Split a merged line into segments at date boundaries.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Possibly merged OCR line.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Line segments split at date boundaries.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDescPort","title":"ImplDescPort","text":"<p> Bases: <code>DescPort</code></p> <p>Concrete description leaf \u2014 slices at the first starter marker.</p> <p>Attributes:</p> Name Type Description <code>starters</code> <code>Optional[List[str]]</code> <p>Description starter markers.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDescPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDescPort.extract_description","title":"extract_description","text":"<pre><code>extract_description(description: str) -&gt; str\n</code></pre> <p>Extract and clean the transaction description.</p> <p>Parameters:</p> Name Type Description Default <code>description</code> <code>str</code> <p>Raw description text.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Cleaned description.</p> <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>When no starters are configured.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplDescPort.fix_ocr","title":"fix_ocr","text":"<pre><code>fix_ocr(text: str) -&gt; str\n</code></pre> <p>Fix OCR artifacts in the description text (no-op base).</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Text to fix.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Fixed text.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplNumberPort","title":"ImplNumberPort","text":"<p> Bases: <code>NumberPort</code></p> <p>Concrete number leaf \u2014 prefers trailing decimals, else the last numbers.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplNumberPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplNumberPort.get_numbers","title":"get_numbers","text":"<pre><code>get_numbers(line: str) -&gt; List[float]\n</code></pre> <p>Extract monetary numbers, preferring trailing decimals.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>List[float]</code> <p>List[float]: Cleaned monetary numbers.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplNumberPort.get_opening_balance","title":"get_opening_balance","text":"<pre><code>get_opening_balance(line: str) -&gt; Optional[float]\n</code></pre> <p>Return the last number as the opening balance.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>Optional[float]</code> <p>Optional[float]: The last number, else <code>None</code>.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplPDFExtractionPipeline","title":"ImplPDFExtractionPipeline","text":"<p> Bases: <code>PDFExtractionPipeline</code></p> <p>Concrete pdf graph root.</p> <p>Attributes:</p> Name Type Description <code>pipeline</code> <code>str</code> <p>Pipeline tag (\"heuristic\").</p> <code>trust_fallback</code> <p>Fallback policy for amount/balance trust.</p> <code>ingest</code> <code>ImplIngestPort</code> <p>Ingest stage.</p> <code>raw_lines</code> <code>ImplRawLinesPort</code> <p>Raw-lines stage.</p> <code>txn_blocks</code> <code>ImplTxnBlocksPort</code> <p>Txn-blocks stage.</p> <code>txn_dicts</code> <code>ImplTxnDictsPort</code> <p>Txn-dicts stage.</p> <code>raw_expense</code> <code>ImplRawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplPDFExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplPDFExtractionPipeline.run","title":"run","text":"<pre><code>run(source)\n</code></pre> <p>Run the pdf extraction chain end-to-end.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <p>List of raw expense records.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplRawLinesPort","title":"ImplRawLinesPort","text":"<p> Bases: <code>RawLinesPort</code></p> <p>Concrete raw-lines leaf \u2014 OCRs PDF bytes into text lines.</p> <p>Attributes:</p> Name Type Description <code>covert_to_image</code> <code>bool</code> <p>Binarize pages via image conversion.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplRawLinesPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplRawLinesPort.extract","title":"extract","text":"<pre><code>extract(content)\n</code></pre> <p>Extract raw OCR text lines from content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>PDF bytes, Content, or dict payload.</p> required <p>Returns:</p> Type Description <p>List of raw text lines.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When content is not PDF bytes or Content with <code>.raw</code>.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplSplitterPort","title":"ImplSplitterPort","text":"<p> Bases: <code>SplitterPort</code></p> <p>Concrete splitter \u2014 splits bucket lines into transaction blocks.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>ImplNumberPort</code> <p>Number extraction leaf.</p> <code>date</code> <code>ImplDatePort</code> <p>Date parsing leaf.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplSplitterPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplSplitterPort.split_blocks","title":"split_blocks","text":"<pre><code>split_blocks(\n lines,\n *,\n has_header=False,\n min_numbers=3,\n detect_date_ranges=False\n)\n</code></pre> <p>Split bucket lines into transaction blocks.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <p>Bucket lines.</p> required <code>has_header</code> <p>Whether a header precedes the rows.</p> <code>False</code> <code>min_numbers</code> <p>Minimum numbers for a split.</p> <code>3</code> <code>detect_date_ranges</code> <p>Detect date-range lines.</p> <code>False</code> <p>Returns:</p> Type Description <p>List of transaction block texts.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTransactionParserPort","title":"ImplTransactionParserPort","text":"<p> Bases: <code>TransactionParserPort</code></p> <p>Concrete transaction parser \u2014 one block to one txn dict.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>ImplNumberPort</code> <p>Number extraction leaf.</p> <code>date</code> <code>ImplDatePort</code> <p>Date parsing leaf.</p> <code>desc</code> <code>ImplDescPort</code> <p>Description extraction leaf.</p> <code>amount_balance</code> <code>ImplAmountBalancePort</code> <p>Amount/balance resolution leaf.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTransactionParserPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTransactionParserPort.parse","title":"parse","text":"<pre><code>parse(txn_text, prev_date_str, prev_balance)\n</code></pre> <p>Parse a transaction block into a txn dict.</p> <p>Parameters:</p> Name Type Description Default <code>txn_text</code> <p>Transaction block text.</p> required <code>prev_date_str</code> <p>Previous transaction date string.</p> required <code>prev_balance</code> <p>Running balance from the previous transaction.</p> required <p>Returns:</p> Type Description <p>Txn dict, or <code>None</code> when the block has no usable date/numbers.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTxnBlocksPort","title":"ImplTxnBlocksPort","text":"<p> Bases: <code>TxnBlocksPort</code></p> <p>Concrete txn-blocks stage \u2014 buckets plus per-bucket splitting.</p> <p>Attributes:</p> Name Type Description <code>bucket_finder</code> <code>ImplBucketFinderPort</code> <p>Bucket-finding leaf.</p> <code>splitter</code> <code>ImplSplitterPort</code> <p>Block-splitting leaf.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTxnBlocksPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTxnBlocksPort.extract","title":"extract","text":"<pre><code>extract(raw_lines)\n</code></pre> <p>Extract txn blocks keyed by opening balance.</p> <p>Parameters:</p> Name Type Description Default <code>raw_lines</code> <p>Raw OCR text lines.</p> required <p>Returns:</p> Type Description <p>Dict[float, List[str]]: Opening balance \u2192 block texts.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTxnDictsPort","title":"ImplTxnDictsPort","text":"<p> Bases: <code>TxnDictsPort</code></p> <p>Concrete txn-dicts stage \u2014 parses blocks in balance-chained order.</p> <p>Attributes:</p> Name Type Description <code>parser</code> <code>ImplTransactionParserPort</code> <p>Transaction parsing leaf.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTxnDictsPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ImplTxnDictsPort.extract","title":"extract","text":"<pre><code>extract(txn_blocks)\n</code></pre> <p>Extract balance-chained txn dicts from blocks.</p> <p>Parameters:</p> Name Type Description Default <code>txn_blocks</code> <p>Opening balance \u2192 block texts.</p> required <p>Returns:</p> Type Description <p>List of txn dicts.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.clean_num","title":"clean_num","text":"<pre><code>clean_num(s: str) -&gt; float\n</code></pre> <p>Port of domain.extraction.ports.pdf.clean_num.</p> <p>Parameters:</p> Name Type Description Default <code>s</code> <code>str</code> <p>Numeric string to clean.</p> required <p>Returns:</p> Name Type Description <code>float</code> <code>float</code> <p>Parsed numeric value; <code>0.0</code> when the string has no digits.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.normalize","title":"normalize","text":"<pre><code>normalize(text: str) -&gt; str\n</code></pre> <p>Normalize OCR text: fix artifacts, strip separators, drop commas.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Raw OCR text.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Normalized text.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.ocr_all_pages","title":"ocr_all_pages","text":"<pre><code>ocr_all_pages(\n pdf_bytes: bytes, covert_to_image: bool = None\n) -&gt; list\n</code></pre> <p>Run OCR over every PDF page, returning per-page text.</p> <p>Parameters:</p> Name Type Description Default <code>pdf_bytes</code> <code>bytes</code> <p>PDF file bytes.</p> required <code>covert_to_image</code> <code>bool</code> <p>Binarize pages through image conversion.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>list</code> <code>list</code> <p>One OCR text string per page.</p> <p>Raises:</p> Type Description <code>ImportError</code> <p>When pytesseract/Pillow are unavailable.</p>"},{"location":"pipelines/extraction/pdf/impl/#pipelines.extraction.pdf.impl.rasterize_pdf","title":"rasterize_pdf","text":"<pre><code>rasterize_pdf(\n pdf_bytes: bytes, out_dir: str, dpi: int = 300\n) -&gt; list\n</code></pre> <p>Rasterize PDF bytes into JPEG page images via pdftoppm.</p> <p>Parameters:</p> Name Type Description Default <code>pdf_bytes</code> <code>bytes</code> <p>PDF file bytes.</p> required <code>out_dir</code> <code>str</code> <p>Directory to write the PDF and page images.</p> required <code>dpi</code> <code>int</code> <p>Render resolution. Defaults to 300.</p> <code>300</code> <p>Returns:</p> Name Type Description <code>list</code> <code>list</code> <p>Sorted list of generated JPEG page paths.</p>"},{"location":"pipelines/extraction/pdf/llm/","title":"Llm","text":""},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm","title":"pipelines.extraction.pdf.llm","text":""},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm--summary","title":"Summary","text":"<p>LLM splitter variant of the pdf family (impl-layer, bank-agnostic).</p> <p><code>LLMSplitterPort</code> is a faithful port of <code>TransactionSplitterLLMAdaptor</code> (domain/extraction/adaptors/txn_blocks.py) using <code>SyncOpenRouterPool</code>. It swaps into the pdf chain exactly where <code>ImplSplitterPort</code> sits, so the rest of the tree (raw_lines \u2192 txn_blocks \u2192 txn_dicts \u2192 raw_expense) is unchanged.</p> <p><code>LLMPdfExtractionPipeline</code> re-pins only the <code>txn_blocks.splitter</code> slot.</p>"},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm-classes","title":"Classes","text":""},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMPdfExtractionPipeline","title":"LLMPdfExtractionPipeline","text":"<p> Bases: <code>ImplPDFExtractionPipeline</code></p> <p>PDF root with the LLM splitter swapped into the txn-blocks stage.</p> <p>Attributes:</p> Name Type Description <code>txn_blocks</code> <code>LLMTxnBlocksPort</code> <p>Txn-blocks stage with LLM splitter.</p>"},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMPdfExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMPdfExtractionPipeline.run","title":"run","text":"<pre><code>run(source)\n</code></pre> <p>Run the pdf extraction chain end-to-end.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <p>List of raw expense records.</p>"},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMSplitterPort","title":"LLMSplitterPort","text":"<pre><code>LLMSplitterPort(pool=None, **kwargs)\n</code></pre> <p> Bases: <code>SplitterPort</code></p> <p>LLM-backed splitter that groups lines into transactions via prompts.</p> <p>Attributes:</p> Name Type Description <code>DATE_RE</code> <code>Pattern[str]</code> <p>Compiled regex matching leading <code>DD-MM-YYYY</code> dates.</p> <code>number</code> <code>ImplNumberPort</code> <p>Number extraction leaf.</p> <code>date</code> <code>ImplDatePort</code> <p>Date parsing leaf.</p> <code>GROUP_PROMPT</code> <code>str</code> <p>Prompt grouping indices into transactions.</p> <code>RESOLVE_PROMPT</code> <code>str</code> <p>Prompt resolving cross-batch conflicts.</p> <code>MAX_CONFLICT_LOOPS</code> <code>int</code> <p>Max conflict resolution loops.</p> <code>BATCH_MERGE</code> <code>int</code> <p>Date lines per batch.</p> <p>Initialize the splitter with an LLM pool.</p> <p>Parameters:</p> Name Type Description Default <code>pool</code> <p>LLM pool; defaults to a new <code>SyncOpenRouterPool</code>.</p> <code>None</code> <code>**kwargs</code> <p>Passed through to the base class.</p> <code>{}</code>"},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMSplitterPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMSplitterPort.clean_raw_lines","title":"clean_raw_lines <code>staticmethod</code>","text":"<pre><code>clean_raw_lines(raw_lines: List[str]) -&gt; List[str]\n</code></pre> <p>Clean raw lines: strip trailing noise and drop <code>Page</code> lines.</p> <p>Parameters:</p> Name Type Description Default <code>raw_lines</code> <code>List[str]</code> <p>Raw OCR lines.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Cleaned lines.</p>"},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMSplitterPort.split_blocks","title":"split_blocks","text":"<pre><code>split_blocks(\n lines,\n *,\n has_header=False,\n min_numbers=3,\n detect_date_ranges=False\n)\n</code></pre> <p>Group lines into transaction blocks via the LLM.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <p>Raw OCR lines.</p> required <code>has_header</code> <p>Whether a header precedes the rows.</p> <code>False</code> <code>min_numbers</code> <p>Minimum numbers for a block.</p> <code>3</code> <code>detect_date_ranges</code> <p>Detect date-range lines.</p> <code>False</code> <p>Returns:</p> Type Description <p>List of transaction block texts.</p>"},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMSplitterPort.strip_headers","title":"strip_headers <code>staticmethod</code>","text":"<pre><code>strip_headers(raw_lines: List[str]) -&gt; List[str]\n</code></pre> <p>Drop header lines preceding the first date line.</p> <p>Parameters:</p> Name Type Description Default <code>raw_lines</code> <code>List[str]</code> <p>Raw OCR lines.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Lines with headers removed.</p>"},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMTxnBlocksPort","title":"LLMTxnBlocksPort","text":"<p> Bases: <code>ImplTxnBlocksPort</code></p> <p>Txn-blocks stage re-pinning the splitter to the LLM variant.</p> <p>Attributes:</p> Name Type Description <code>splitter</code> <code>LLMSplitterPort</code> <p>LLM-backed splitter.</p>"},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMTxnBlocksPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/llm/#pipelines.extraction.pdf.llm.LLMTxnBlocksPort.extract","title":"extract","text":"<pre><code>extract(raw_lines)\n</code></pre> <p>Extract txn blocks keyed by opening balance.</p> <p>Parameters:</p> Name Type Description Default <code>raw_lines</code> <p>Raw OCR text lines.</p> required <p>Returns:</p> Type Description <p>Dict[float, List[str]]: Opening balance \u2192 block texts.</p>"},{"location":"pipelines/extraction/pdf/banks/","title":"Banks","text":"<ul> <li>Axis</li> <li>Icici</li> </ul>"},{"location":"pipelines/extraction/pdf/banks/#pipelines.extraction.pdf.banks","title":"pipelines.extraction.pdf.banks","text":""},{"location":"pipelines/extraction/pdf/banks/#pipelines.extraction.pdf.banks--summary","title":"Summary","text":"<p>pdf family \u2014 bank-specific ports and pipeline roots.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/","title":"Axis","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis","title":"pipelines.extraction.pdf.banks.axis","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis--summary","title":"Summary","text":"<p>Axis bank-specific port implementations (pdf statement path).</p> <p>Banks EXTEND the concrete <code>Impl*</code> classes \u2014 they never reinvent the ABC contracts. Each Axis* class overrides only the behavior that DIFFERS from the common <code>Impl*</code>; anything shared is inherited. The pipeline root <code>AxisPdfExtractionPipeline</code> pins only the stage slots that differ.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis-classes","title":"Classes","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisAmountBalancePort","title":"AxisAmountBalancePort","text":"<p> Bases: <code>ImplAmountBalancePort</code></p> <p>Axis amount/balance leaf \u2014 pins the Axis number leaf.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisAmountBalancePort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisAmountBalancePort.adjust_balance","title":"adjust_balance","text":"<pre><code>adjust_balance(balance: float, line: str) -&gt; float\n</code></pre> <p>Adjust an OCR balance (no-op base).</p> <p>Parameters:</p> Name Type Description Default <code>balance</code> <code>float</code> <p>OCR balance.</p> required <code>line</code> <code>str</code> <p>Transaction line.</p> required <p>Returns:</p> Name Type Description <code>float</code> <code>float</code> <p>The balance, unmodified.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisAmountBalancePort.missing_number_candidates","title":"missing_number_candidates","text":"<pre><code>missing_number_candidates(ctx)\n</code></pre> <p>Provide candidates for one-number lines (no-op base).</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <p>The active <code>ResolutionContext</code>.</p> required <p>Returns:</p> Type Description <p>None.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisAmountBalancePort.resolve","title":"resolve","text":"<pre><code>resolve(amount, balance, prev_balance, line, numbers=None)\n</code></pre> <p>Resolve (amount, balance) via <code>ResolutionContext</code>.</p> <p>Parameters:</p> Name Type Description Default <code>amount</code> <p>OCR amount.</p> required <code>balance</code> <p>OCR balance (adjusted first).</p> required <code>prev_balance</code> <p>Previous transaction balance.</p> required <code>line</code> <p>Raw transaction line.</p> required <code>numbers</code> <p>Extracted numbers; default None.</p> <code>None</code> <p>Returns:</p> Type Description <p>(signed amount, resolved balance) tuple.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisBucketFinderPort","title":"AxisBucketFinderPort","text":"<p> Bases: <code>ImplBucketFinderPort</code></p> <p>Axis bucket finder \u2014 pins the Axis number leaf.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisBucketFinderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisBucketFinderPort.get_opening_balance_buckets","title":"get_opening_balance_buckets","text":"<pre><code>get_opening_balance_buckets(\n lines, *, limit_first=False, line_offset=0\n)\n</code></pre> <p>Divide raw lines into opening-balance buckets.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <p>Raw text lines.</p> required <code>limit_first</code> <p>Keep only the first bucket.</p> <code>False</code> <code>line_offset</code> <p>Offset added to starting indices.</p> <code>0</code> <p>Returns:</p> Type Description <p>List of <code>(start, end, opening_balance)</code> triples.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisDescPort","title":"AxisDescPort","text":"<p> Bases: <code>ImplDescPort</code></p> <p>Axis description leaf \u2014 slices at UPI/IMPS/NEFT/ACH/2A markers.</p> <p>Attributes:</p> Name Type Description <code>starters</code> <code>List[str]</code> <p>Description starter markers.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisDescPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisDescPort.extract_description","title":"extract_description","text":"<pre><code>extract_description(description: str) -&gt; str\n</code></pre> <p>Extract and clean the transaction description.</p> <p>Parameters:</p> Name Type Description Default <code>description</code> <code>str</code> <p>Raw description text.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Cleaned description.</p> <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>When no starters are configured.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisDescPort.fix_ocr","title":"fix_ocr","text":"<pre><code>fix_ocr(text: str) -&gt; str\n</code></pre> <p>Fix OCR artifacts in the description text (no-op base).</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Text to fix.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Fixed text.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisNumberPort","title":"AxisNumberPort","text":"<p> Bases: <code>ImplNumberPort</code></p> <p>Axis number leaf \u2014 returns every number in the line.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisNumberPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisNumberPort.get_numbers","title":"get_numbers","text":"<pre><code>get_numbers(line: str) -&gt; List[float]\n</code></pre> <p>Extract every cleaned number from the line.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>List[float]</code> <p>List[float]: All cleaned numbers in the line.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisNumberPort.get_opening_balance","title":"get_opening_balance","text":"<pre><code>get_opening_balance(line: str) -&gt; Optional[float]\n</code></pre> <p>Return the last number as the opening balance.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>Optional[float]</code> <p>Optional[float]: The last number, else <code>None</code>.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisPdfExtractionPipeline","title":"AxisPdfExtractionPipeline","text":"<p> Bases: <code>ImplPDFExtractionPipeline</code></p> <p>Axis pdf graph root \u2014 pins the Axis txn-blocks and txn-dicts stages.</p> <p>Attributes:</p> Name Type Description <code>txn_blocks</code> <code>AxisTxnBlocksPort</code> <p>Axis txn-blocks stage.</p> <code>txn_dicts</code> <code>AxisTxnDictsPort</code> <p>Axis txn-dicts stage.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisPdfExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisPdfExtractionPipeline.run","title":"run","text":"<pre><code>run(source)\n</code></pre> <p>Run the pdf extraction chain end-to-end.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <p>List of raw expense records.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisSplitterPort","title":"AxisSplitterPort","text":"<p> Bases: <code>ImplSplitterPort</code></p> <p>Axis splitter \u2014 pins the Axis number leaf.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisSplitterPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisSplitterPort.split_blocks","title":"split_blocks","text":"<pre><code>split_blocks(\n lines,\n *,\n has_header=False,\n min_numbers=3,\n detect_date_ranges=False\n)\n</code></pre> <p>Split bucket lines into transaction blocks.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <p>Bucket lines.</p> required <code>has_header</code> <p>Whether a header precedes the rows.</p> <code>False</code> <code>min_numbers</code> <p>Minimum numbers for a split.</p> <code>3</code> <code>detect_date_ranges</code> <p>Detect date-range lines.</p> <code>False</code> <p>Returns:</p> Type Description <p>List of transaction block texts.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTransactionParserPort","title":"AxisTransactionParserPort","text":"<p> Bases: <code>ImplTransactionParserPort</code></p> <p>Axis transaction parser \u2014 pins Axis-stage leaves and min_numbers=2.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>AxisNumberPort</code> <p>Axis number leaf.</p> <code>desc</code> <code>AxisDescPort</code> <p>Axis description leaf.</p> <code>amount_balance</code> <code>AxisAmountBalancePort</code> <p>Axis amount/balance leaf.</p> <code>min_numbers</code> <code>int</code> <p>Minimum numbers for a block.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTransactionParserPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTransactionParserPort.parse","title":"parse","text":"<pre><code>parse(txn_text, prev_date_str, prev_balance)\n</code></pre> <p>Parse a transaction block into a txn dict.</p> <p>Parameters:</p> Name Type Description Default <code>txn_text</code> <p>Transaction block text.</p> required <code>prev_date_str</code> <p>Previous transaction date string.</p> required <code>prev_balance</code> <p>Running balance from the previous transaction.</p> required <p>Returns:</p> Type Description <p>Txn dict, or <code>None</code> when the block has no usable date/numbers.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTxnBlocksPort","title":"AxisTxnBlocksPort","text":"<p> Bases: <code>ImplTxnBlocksPort</code></p> <p>Axis txn-blocks stage \u2014 header-scanning, date-range, min_numbers=2.</p> <p>Attributes:</p> Name Type Description <code>bucket_finder</code> <code>AxisBucketFinderPort</code> <p>Axis bucket finder.</p> <code>splitter</code> <code>AxisSplitterPort</code> <p>Axis splitter.</p> <code>has_header</code> <code>bool</code> <p>Header scan enabled.</p> <code>min_numbers</code> <code>int</code> <p>Minimum numbers for a block.</p> <code>detect_date_ranges</code> <code>bool</code> <p>Date-range detection enabled.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTxnBlocksPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTxnBlocksPort.extract","title":"extract","text":"<pre><code>extract(raw_lines)\n</code></pre> <p>Extract txn blocks keyed by opening balance.</p> <p>Parameters:</p> Name Type Description Default <code>raw_lines</code> <p>Raw OCR text lines.</p> required <p>Returns:</p> Type Description <p>Dict[float, List[str]]: Opening balance \u2192 block texts.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTxnDictsPort","title":"AxisTxnDictsPort","text":"<p> Bases: <code>ImplTxnDictsPort</code></p> <p>Axis txn-dicts stage \u2014 pins the Axis transaction parser.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTxnDictsPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis.AxisTxnDictsPort.extract","title":"extract","text":"<pre><code>extract(txn_blocks)\n</code></pre> <p>Extract balance-chained txn dicts from blocks.</p> <p>Parameters:</p> Name Type Description Default <code>txn_blocks</code> <p>Opening balance \u2192 block texts.</p> required <p>Returns:</p> Type Description <p>List of txn dicts.</p>"},{"location":"pipelines/extraction/pdf/banks/axis/#pipelines.extraction.pdf.banks.axis-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/","title":"Icici","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici","title":"pipelines.extraction.pdf.banks.icici","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici--summary","title":"Summary","text":"<p>Icici bank-specific port implementations (pdf statement path).</p> <p>Banks EXTEND the concrete <code>Impl*</code> classes \u2014 they never reinvent the ABC contracts. Each Icici* class overrides only the behavior that DIFFERS from the common <code>Impl*</code>; anything shared is inherited.</p> <p>Derived from the real <code>domain/extraction/banks/icici/pdf.py</code>:</p> <ul> <li>NumberPort : Icici get_numbers returns decimals[-2:] (last 2)</li> <li>DescPort : Icici STARTTERS + fix_ocr OCR replacements</li> <li>AmountBalancePort : Icici adjust_balance negates balances flagged as negative by OCR brackets (the executed diff)</li> <li>TxnBlocksPort : Icici CONFIG (min_numbers=2, limit_first=True, line_offset=1, detect_date_ranges=True) as class attrs.</li> <li>RawLinesPort : Icici CONFIG covert_to_image=True (image-binarized OCR).</li> <li>missing_number_candidates : the Icici one-number hook, called live by ResolutionContext (Option B) \u2014 with only one OCR number, try it as either the amount or the balance.</li> </ul>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici-classes","title":"Classes","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciAmountBalancePort","title":"IciciAmountBalancePort","text":"<p> Bases: <code>ImplAmountBalancePort</code></p> <p>Icici amount/balance leaf \u2014 negates bracketed OCR balances.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>IciciNumberPort</code> <p>Icici number leaf.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciAmountBalancePort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciAmountBalancePort.adjust_balance","title":"adjust_balance","text":"<pre><code>adjust_balance(balance: float, line: str) -&gt; float\n</code></pre> <p>Negate a balance flagged as negative by OCR brackets.</p> <p>Parameters:</p> Name Type Description Default <code>balance</code> <code>float</code> <p>OCR balance.</p> required <code>line</code> <code>str</code> <p>Transaction line.</p> required <p>Returns:</p> Name Type Description <code>float</code> <code>float</code> <p>Negated balance when a bracket marker is present, else the</p> <code>float</code> <p>balance unchanged.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciAmountBalancePort.missing_number_candidates","title":"missing_number_candidates","text":"<pre><code>missing_number_candidates(ctx)\n</code></pre> <p>Provide one-number candidates: the number as amount or as balance.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <p>The active <code>ResolutionContext</code>.</p> required <p>Returns:</p> Type Description <p>Set of <code>(amount, balance)</code> candidate pairs.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciAmountBalancePort.resolve","title":"resolve","text":"<pre><code>resolve(amount, balance, prev_balance, line, numbers=None)\n</code></pre> <p>Resolve (amount, balance) via <code>ResolutionContext</code>.</p> <p>Parameters:</p> Name Type Description Default <code>amount</code> <p>OCR amount.</p> required <code>balance</code> <p>OCR balance (adjusted first).</p> required <code>prev_balance</code> <p>Previous transaction balance.</p> required <code>line</code> <p>Raw transaction line.</p> required <code>numbers</code> <p>Extracted numbers; default None.</p> <code>None</code> <p>Returns:</p> Type Description <p>(signed amount, resolved balance) tuple.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciBucketFinderPort","title":"IciciBucketFinderPort","text":"<p> Bases: <code>ImplBucketFinderPort</code></p> <p>Icici bucket finder \u2014 pins the Icici number leaf.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciBucketFinderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciBucketFinderPort.get_opening_balance_buckets","title":"get_opening_balance_buckets","text":"<pre><code>get_opening_balance_buckets(\n lines, *, limit_first=False, line_offset=0\n)\n</code></pre> <p>Divide raw lines into opening-balance buckets.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <p>Raw text lines.</p> required <code>limit_first</code> <p>Keep only the first bucket.</p> <code>False</code> <code>line_offset</code> <p>Offset added to starting indices.</p> <code>0</code> <p>Returns:</p> Type Description <p>List of <code>(start, end, opening_balance)</code> triples.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciDescPort","title":"IciciDescPort","text":"<p> Bases: <code>ImplDescPort</code></p> <p>Icici description leaf \u2014 slices at Icici markers and fixes OCR typos.</p> <p>Attributes:</p> Name Type Description <code>starters</code> <code>Optional[List[str]]</code> <p>Description starter markers.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciDescPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciDescPort.extract_description","title":"extract_description","text":"<pre><code>extract_description(description: str) -&gt; str\n</code></pre> <p>Extract and clean the transaction description.</p> <p>Parameters:</p> Name Type Description Default <code>description</code> <code>str</code> <p>Raw description text.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Cleaned description.</p> <p>Raises:</p> Type Description <code>NotImplementedError</code> <p>When no starters are configured.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciDescPort.fix_ocr","title":"fix_ocr","text":"<pre><code>fix_ocr(text: str) -&gt; str\n</code></pre> <p>Fix common Icici OCR typos in the description text.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Text to fix.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Text with OCR replacements applied.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciNumberPort","title":"IciciNumberPort","text":"<p> Bases: <code>ImplNumberPort</code></p> <p>Icici number leaf \u2014 prefers the last two decimal numbers.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciNumberPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciNumberPort.get_numbers","title":"get_numbers","text":"<pre><code>get_numbers(line: str) -&gt; List[float]\n</code></pre> <p>Extract monetary numbers, preferring trailing decimals.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>List[float]</code> <p>List[float]: Cleaned monetary numbers.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciNumberPort.get_opening_balance","title":"get_opening_balance","text":"<pre><code>get_opening_balance(line: str) -&gt; Optional[float]\n</code></pre> <p>Return the last number as the opening balance.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>Optional[float]</code> <p>Optional[float]: The last number, else <code>None</code>.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciPdfExtractionPipeline","title":"IciciPdfExtractionPipeline","text":"<p> Bases: <code>ImplPDFExtractionPipeline</code></p> <p>Icici pdf graph root \u2014 pins raw-lines, txn-blocks, and txn-dicts stages.</p> <p>Attributes:</p> Name Type Description <code>raw_lines</code> <code>IciciRawLinesPort</code> <p>Icici raw-lines stage.</p> <code>txn_blocks</code> <code>IciciTxnBlocksPort</code> <p>Icici txn-blocks stage.</p> <code>txn_dicts</code> <code>IciciTxnDictsPort</code> <p>Icici txn-dicts stage.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciPdfExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciPdfExtractionPipeline.run","title":"run","text":"<pre><code>run(source)\n</code></pre> <p>Run the pdf extraction chain end-to-end.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <p>List of raw expense records.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciRawLinesPort","title":"IciciRawLinesPort","text":"<p> Bases: <code>ImplRawLinesPort</code></p> <p>Icici raw-lines leaf \u2014 binarized OCR.</p> <p>Attributes:</p> Name Type Description <code>covert_to_image</code> <code>bool</code> <p>Binarize pages via image conversion.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciRawLinesPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciRawLinesPort.extract","title":"extract","text":"<pre><code>extract(content)\n</code></pre> <p>Extract raw OCR text lines from content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>PDF bytes, Content, or dict payload.</p> required <p>Returns:</p> Type Description <p>List of raw text lines.</p> <p>Raises:</p> Type Description <code>TypeError</code> <p>When content is not PDF bytes or Content with <code>.raw</code>.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciSplitterPort","title":"IciciSplitterPort","text":"<p> Bases: <code>ImplSplitterPort</code></p> <p>Icici splitter \u2014 pins the Icici number leaf.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciSplitterPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciSplitterPort.split_blocks","title":"split_blocks","text":"<pre><code>split_blocks(\n lines,\n *,\n has_header=False,\n min_numbers=3,\n detect_date_ranges=False\n)\n</code></pre> <p>Split bucket lines into transaction blocks.</p> <p>Parameters:</p> Name Type Description Default <code>lines</code> <p>Bucket lines.</p> required <code>has_header</code> <p>Whether a header precedes the rows.</p> <code>False</code> <code>min_numbers</code> <p>Minimum numbers for a split.</p> <code>3</code> <code>detect_date_ranges</code> <p>Detect date-range lines.</p> <code>False</code> <p>Returns:</p> Type Description <p>List of transaction block texts.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTransactionParserPort","title":"IciciTransactionParserPort","text":"<p> Bases: <code>ImplTransactionParserPort</code></p> <p>Icici transaction parser \u2014 pins Icici-stage leaves and indices.</p> <p>Attributes:</p> Name Type Description <code>number</code> <code>IciciNumberPort</code> <p>Icici number leaf.</p> <code>desc</code> <code>IciciDescPort</code> <p>Icici description leaf.</p> <code>amount_balance</code> <code>IciciAmountBalancePort</code> <p>Icici amount/balance leaf.</p> <code>min_numbers</code> <code>int</code> <p>Minimum numbers for a block.</p> <code>amount_index</code> <code>int</code> <p>Index of the amount in the number list.</p> <code>balance_index</code> <code>int</code> <p>Index of the balance in the number list.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTransactionParserPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTransactionParserPort.parse","title":"parse","text":"<pre><code>parse(txn_text, prev_date_str, prev_balance)\n</code></pre> <p>Parse a transaction block into a txn dict.</p> <p>Parameters:</p> Name Type Description Default <code>txn_text</code> <p>Transaction block text.</p> required <code>prev_date_str</code> <p>Previous transaction date string.</p> required <code>prev_balance</code> <p>Running balance from the previous transaction.</p> required <p>Returns:</p> Type Description <p>Txn dict, or <code>None</code> when the block has no usable date/numbers.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTxnBlocksPort","title":"IciciTxnBlocksPort","text":"<p> Bases: <code>ImplTxnBlocksPort</code></p> <p>Icici txn-blocks stage \u2014 min_numbers=2, first bucket only.</p> <p>Attributes:</p> Name Type Description <code>bucket_finder</code> <code>IciciBucketFinderPort</code> <p>Icici bucket finder.</p> <code>splitter</code> <code>IciciSplitterPort</code> <p>Icici splitter.</p> <code>min_numbers</code> <code>int</code> <p>Minimum numbers for a block.</p> <code>limit_first</code> <code>bool</code> <p>Keep only the first bucket.</p> <code>line_offset</code> <code>int</code> <p>Offset added to starting indices.</p> <code>detect_date_ranges</code> <code>bool</code> <p>Date-range detection enabled.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTxnBlocksPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTxnBlocksPort.extract","title":"extract","text":"<pre><code>extract(raw_lines)\n</code></pre> <p>Extract txn blocks keyed by opening balance.</p> <p>Parameters:</p> Name Type Description Default <code>raw_lines</code> <p>Raw OCR text lines.</p> required <p>Returns:</p> Type Description <p>Dict[float, List[str]]: Opening balance \u2192 block texts.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTxnDictsPort","title":"IciciTxnDictsPort","text":"<p> Bases: <code>ImplTxnDictsPort</code></p> <p>Icici txn-dicts stage \u2014 pins the Icici transaction parser.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTxnDictsPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici.IciciTxnDictsPort.extract","title":"extract","text":"<pre><code>extract(txn_blocks)\n</code></pre> <p>Extract balance-chained txn dicts from blocks.</p> <p>Parameters:</p> Name Type Description Default <code>txn_blocks</code> <p>Opening balance \u2192 block texts.</p> required <p>Returns:</p> Type Description <p>List of txn dicts.</p>"},{"location":"pipelines/extraction/pdf/banks/icici/#pipelines.extraction.pdf.banks.icici-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/","title":"Shared","text":"<ul> <li>Ambiguity</li> <li>Impl</li> <li>Ports</li> <li>Registry</li> <li>Tabular</li> </ul>"},{"location":"pipelines/extraction/shared/#pipelines.extraction.shared","title":"pipelines.extraction.shared","text":""},{"location":"pipelines/extraction/shared/#pipelines.extraction.shared--summary","title":"Summary","text":"<p>Shared leaf contracts + cross-family machinery.</p>"},{"location":"pipelines/extraction/shared/ambiguity/","title":"Ambiguity","text":""},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity","title":"pipelines.extraction.shared.ambiguity","text":""},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity--summary","title":"Summary","text":"<p>Ambiguity resolution \u2014 faithful port of domain.extraction.ambiguity.</p> <p>Candidate generation and three-mode dispatch, ported verbatim so the hexa PDF path matches OG logic. The LLM-specific resolver is kept as an optional hook (<code>resolver</code>); pause/CLI behaviour is preserved via <code>PauseForResolution</code>.</p>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity-classes","title":"Classes","text":""},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.AmbiguityHandler","title":"AmbiguityHandler","text":"<pre><code>AmbiguityHandler(\n fetch_request_id: str = \"\",\n pause_on_ambiguity: bool = True,\n resolved_choices: Optional[dict] = None,\n resolver: Optional[Callable] = None,\n)\n</code></pre> <p>Three-mode ambiguity dispatcher: resolved_choices -&gt; resolver -&gt; pause -&gt; CLI.</p> <p>Attributes:</p> Name Type Description <code>fetch_request_id</code> <code>str</code> <p>Identifier correlating this resolution to a fetch request.</p> <code>pause_on_ambiguity</code> <code>bool</code> <p>Whether to raise <code>PauseForResolution</code> when unresolved.</p> <code>resolved_choices</code> <code>dict</code> <p>Cache of previously resolved candidate keys.</p> <code>resolver</code> <code>Optional[Callable]</code> <p>Optional LLM/machine resolver hook.</p> <p>Initialize the ambiguity handler.</p> <p>Parameters:</p> Name Type Description Default <code>fetch_request_id</code> <code>str</code> <p>Identifier correlating this resolution to a fetch request. Defaults to <code>\"\"</code>.</p> <code>''</code> <code>pause_on_ambiguity</code> <code>bool</code> <p>Whether to raise <code>PauseForResolution</code> when unresolved. Defaults to <code>True</code>.</p> <code>True</code> <code>resolved_choices</code> <code>Optional[dict]</code> <p>Prior choices keyed by candidate key. Defaults to <code>None</code> (becomes an empty dict).</p> <code>None</code> <code>resolver</code> <code>Optional[Callable]</code> <p>Optional resolver hook. Defaults to <code>None</code>.</p> <code>None</code>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.AmbiguityHandler-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.AmbiguityHandler.resolve_ambiguity","title":"resolve_ambiguity","text":"<pre><code>resolve_ambiguity(\n line, ocr_amount, ocr_balance, prev_balance, candidates\n)\n</code></pre> <p>Resolve ambiguous amount/balance candidate pairs.</p> <p>Validates the candidate pairs against the running balance and returns the unique valid interpretation. When multiple valid interpretations remain it consults <code>resolved_choices</code>, then the optional <code>resolver</code> hook, then either raises <code>PauseForResolution</code> or falls back to CLI resolution.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <p>Raw transaction line being resolved.</p> required <code>ocr_amount</code> <p>OCR-extracted amount.</p> required <code>ocr_balance</code> <p>OCR-extracted balance.</p> required <code>prev_balance</code> <p>Running balance from the previous transaction.</p> required <code>candidates</code> <p>Collection of candidate (amount, balance) pairs.</p> required <p>Returns:</p> Type Description <p>Set of a single (amount, balance) pair, or <code>None</code> when no valid</p> <p>interpretation exists.</p> <p>Raises:</p> Type Description <code>PauseForResolution</code> <p>When multiple interpretations remain and <code>pause_on_ambiguity</code> is enabled.</p>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.AmbiguousCandidateFound","title":"AmbiguousCandidateFound","text":"<pre><code>AmbiguousCandidateFound(candidates: set)\n</code></pre> <p> Bases: <code>ValueError</code></p> <p>Raised when candidate generation produces multiple valid interpretations.</p> <p>Attributes:</p> Name Type Description <code>candidates</code> <code>set</code> <p>Ambiguous candidate (amount, balance) pairs.</p>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.AmountBalanceNotFound","title":"AmountBalanceNotFound","text":"<p> Bases: <code>ValueError</code></p> <p>Raised when no valid amount/balance interpretation can be found.</p>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.PauseForResolution","title":"PauseForResolution","text":"<pre><code>PauseForResolution(\n line,\n ocr_amount,\n ocr_balance,\n prev_balance,\n candidates,\n fetch_request_id: str = \"\",\n)\n</code></pre> <p> Bases: <code>Exception</code></p> <p>Signal that ambiguous candidates need human resolution.</p> <p>Attributes:</p> Name Type Description <code>line</code> <p>Raw transaction line being resolved.</p> <code>ocr_amount</code> <p>OCR-extracted amount.</p> <code>ocr_balance</code> <p>OCR-extracted balance.</p> <code>prev_balance</code> <p>Running balance from the previous transaction.</p> <code>candidates</code> <p>Candidate (amount, balance) pairs.</p> <code>fetch_request_id</code> <code>str</code> <p>Fetch request ID used for correlation.</p>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.ResolutionContext","title":"ResolutionContext","text":"<pre><code>ResolutionContext(\n amount,\n balance,\n prev_balance,\n line,\n numbers,\n handler=None,\n trust_fallback=None,\n missing_number_candidates=None,\n)\n</code></pre> <p>Resolves amount/balance pairs, generating candidates when direct validation fails.</p> <p>Attributes:</p> Name Type Description <code>amount</code> <code>float</code> <p>Absolute-rounded OCR amount.</p> <code>balance</code> <code>float</code> <p>Rounded OCR balance.</p> <code>prev_balance</code> <code>float</code> <p>Rounded running balance.</p> <code>line</code> <p>Raw transaction line being resolved.</p> <code>numbers</code> <p>Extracted numbers from the transaction line.</p> <code>tolerance</code> <code>float</code> <p>Allowed rounding difference.</p> <code>handler</code> <p>Optional <code>AmbiguityHandler</code> used when ambiguity surfaces.</p> <code>trust_fallback</code> <p>Optional fallback policy (<code>\"amount\"</code> or <code>\"balance\"</code>).</p> <code>missing_number_candidates</code> <p>Optional candidate hook for one-number lines.</p> <code>adjustors</code> <p>Ordered list of candidate generator callables.</p> <p>Initialize a resolution context.</p> <p>Parameters:</p> Name Type Description Default <code>amount</code> <p>OCR-extracted transaction amount.</p> required <code>balance</code> <p>OCR-extracted closing balance.</p> required <code>prev_balance</code> <p>Running balance from the previous transaction.</p> required <code>line</code> <p>Raw transaction line being resolved.</p> required <code>numbers</code> <p>Extracted numbers from the transaction line.</p> required <code>handler</code> <p>Optional <code>AmbiguityHandler</code> for ambiguous candidates.</p> <code>None</code> <code>trust_fallback</code> <p>Optional fallback policy (<code>\"amount\"</code> or <code>\"balance\"</code>).</p> <code>None</code> <code>missing_number_candidates</code> <p>Optional callable providing candidates for one-number lines.</p> <code>None</code>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.ResolutionContext-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.ResolutionContext.resolve","title":"resolve","text":"<pre><code>resolve()\n</code></pre> <p>Resolve to a validated (amount, balance) pair.</p> <p>Applies direct sign validation first, then trust fallbacks, then walks the ordered candidate generators. Raises when nothing reconciles.</p> <p>Returns:</p> Type Description <p>Two-tuple of signed amount and validated balance.</p> <p>Raises:</p> Type Description <code>AmountBalanceNotFound</code> <p>When no candidate interpretation reconciles with the running balance.</p>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.clean_num","title":"clean_num","text":"<pre><code>clean_num(s: str) -&gt; float\n</code></pre> <p>Convert a numeric string to a float, handling decimals and paise.</p> <p>A bare integer string is treated as paise (divided by 100); strings with a decimal point use the decimal part directly.</p> <p>Parameters:</p> Name Type Description Default <code>s</code> <code>str</code> <p>Numeric string to clean.</p> required <p>Returns:</p> Name Type Description <code>float</code> <code>float</code> <p>Parsed numeric value; <code>0.0</code> when the string has no digits.</p>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.get_numbers","title":"get_numbers","text":"<pre><code>get_numbers(text: str) -&gt; List[float]\n</code></pre> <p>Extract monetary numbers from OCR/text lines.</p> <p>Parameters:</p> Name Type Description Default <code>text</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>List[float]</code> <p>List[float]: Cleaned numeric values found in the text.</p>"},{"location":"pipelines/extraction/shared/ambiguity/#pipelines.extraction.shared.ambiguity.validate_signs","title":"validate_signs","text":"<pre><code>validate_signs(\n amount, balance, prev_balance, tolerance=1.0\n)\n</code></pre> <p>Validate a (amount, balance) interpretation against the running balance.</p> <p>Parameters:</p> Name Type Description Default <code>amount</code> <p>OCR-extracted transaction amount.</p> required <code>balance</code> <p>OCR-extracted closing balance.</p> required <code>prev_balance</code> <p>Running balance from the previous transaction.</p> required <code>tolerance</code> <code>float</code> <p>Allowed rounding difference. Defaults to 1.0.</p> <code>1.0</code> <p>Returns:</p> Type Description <p>Two-tuple of signed amount and validated balance, or <code>(None, None)</code></p> <p>when no sign combination reconciles with the running balance.</p>"},{"location":"pipelines/extraction/shared/impl/","title":"Impl","text":""},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl","title":"pipelines.extraction.shared.impl","text":""},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl--summary","title":"Summary","text":"<p>Shared concrete implementations used by every extraction family.</p> <p>Only genuinely family-agnostic ports live here:</p> <ul> <li><code>ImplIngestPort</code> : bytes/dict/Content/list/str -&gt; content payload. This is what families receive as their first stage output.</li> <li><code>ImplRawExpensePort</code> : txn_dicts -&gt; list[RawExpense] (terminal).</li> </ul> <p>Every other implementation is homed in the family it belongs to (<code>pdf/impl.py</code>, <code>email/impl.py</code>, <code>csv/impl.py</code>, <code>xlsx/impl.py</code>).</p>"},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl-classes","title":"Classes","text":""},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl.ImplIngestPort","title":"ImplIngestPort","text":"<p> Bases: <code>IngestPort</code></p> <p>Materialize an <code>ExtractionSource</code> into a concrete content payload.</p> <p>Attributes:</p> Name Type Description <code>source_type</code> <code>str</code> <p>Source-type tag declared by the concrete root.</p>"},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl.ImplIngestPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl.ImplIngestPort.materialize","title":"materialize","text":"<pre><code>materialize(source)\n</code></pre> <p>Convert a raw source into a concrete content payload.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw source (with <code>raw</code>, bytes, dict, list, or str).</p> required <p>Returns:</p> Type Description <p>Concrete payload: the source itself, <code>{\"raw\": bytes}</code>, a dict, a</p> <p>list, or <code>{\"content\": str}</code> depending on the source shape.</p>"},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl.ImplRawExpensePort","title":"ImplRawExpensePort","text":"<p> Bases: <code>RawExpensePort</code></p> <p>Build raw expense records from txn dicts (terminal stage).</p>"},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl.ImplRawExpensePort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/impl/#pipelines.extraction.shared.impl.ImplRawExpensePort.build","title":"build","text":"<pre><code>build(txn_dicts)\n</code></pre> <p>Map structured txn dicts onto the raw-expense shape.</p> <p>Parameters:</p> Name Type Description Default <code>txn_dicts</code> <p>List of structured transaction dicts.</p> required <p>Returns:</p> Type Description <p>List of raw expense dicts keyed by date, amount, balance,</p> <p>description, and direction.</p>"},{"location":"pipelines/extraction/shared/ports/","title":"Ports","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports","title":"pipelines.extraction.shared.ports","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports--summary","title":"Summary","text":"<p>Shared leaf contracts for every extraction family (no implementation).</p> <p>These ports are genuinely common across the pdf / email / csv / xlsx families:</p> <ul> <li>NumberPort / DatePort / DescPort / AmbiguityPort / AmountBalancePort : text-oriented parsing leaves, exercised by the pdf (and future) families.</li> <li>IngestPort : turn an ExtractionSource into something concrete each family can consume (bytes, Content, dict, ...).</li> <li>RawExpensePort : terminal mapping txn_dicts -&gt; list[RawExpense].</li> </ul> <p>Concrete implementations (re)declare the same slots with CONCRETE types in the per-family <code>impl.py</code> modules and in the per-bank modules; <code>hexa.build()</code> reads the merged MRO annotations and wires everything.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports-classes","title":"Classes","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.AmbiguityPort","title":"AmbiguityPort","text":"<p> Bases: <code>ABC</code></p> <p>Resolve ambiguous amount/balance interpretations.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.AmbiguityPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.AmbiguityPort.resolve_ambiguity","title":"resolve_ambiguity <code>abstractmethod</code>","text":"<pre><code>resolve_ambiguity(\n line: str,\n ocr_amount: float,\n ocr_balance: float,\n prev_balance: float,\n) -&gt; Any\n</code></pre> <p>Resolve ambiguous amount/balance interpretations.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Raw transaction line.</p> required <code>ocr_amount</code> <code>float</code> <p>OCR-extracted amount.</p> required <code>ocr_balance</code> <code>float</code> <p>OCR-extracted balance.</p> required <code>prev_balance</code> <code>float</code> <p>Running balance from the previous transaction.</p> required <p>Returns:</p> Name Type Description <code>Any</code> <code>Any</code> <p>Resolution result (concrete per implementation).</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.AmountBalancePort","title":"AmountBalancePort","text":"<p> Bases: <code>ABC</code></p> <p>Validate + resolve a txn amount against the running balance.</p> <p>Attributes:</p> Name Type Description <code>trust_fallback</code> <code>Optional[str]</code> <p>Fallback policy (\"amount\" or \"balance\").</p> <code>number</code> <code>NumberPort</code> <p>Number extraction leaf.</p> <code>ambiguity</code> <code>AmbiguityPort</code> <p>Ambiguity resolution leaf.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.AmountBalancePort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.AmountBalancePort.resolve","title":"resolve <code>abstractmethod</code>","text":"<pre><code>resolve(\n amount: float,\n balance: float,\n prev_balance: float,\n line: str,\n numbers: Optional[List[float]] = None,\n) -&gt; Tuple[float, float]\n</code></pre> <p>Validate and resolve a transaction amount against the balance.</p> <p>Parameters:</p> Name Type Description Default <code>amount</code> <code>float</code> <p>OCR-extracted amount.</p> required <code>balance</code> <code>float</code> <p>OCR-extracted balance.</p> required <code>prev_balance</code> <code>float</code> <p>Running balance from the previous transaction.</p> required <code>line</code> <code>str</code> <p>Raw transaction line.</p> required <code>numbers</code> <code>Optional[List[float]]</code> <p>Extracted numbers; default None.</p> <code>None</code> <p>Returns:</p> Type Description <code>Tuple[float, float]</code> <p>Tuple[float, float]: (signed amount, resolved balance).</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DatePort","title":"DatePort","text":"<p> Bases: <code>ABC</code></p> <p>Detect, parse and reconcile transaction dates.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DatePort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DatePort.get_dates","title":"get_dates <code>abstractmethod</code>","text":"<pre><code>get_dates(line: str) -&gt; Optional[Tuple[str, str]]\n</code></pre> <p>Extract the leading date and the remaining line tail.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>Optional[Tuple[str, str]]</code> <p>Optional[Tuple[str, str]]: <code>(date_str, date_tail)</code> when a date</p> <code>Optional[Tuple[str, str]]</code> <p>leads the line, else <code>None</code>.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DatePort.parse_date","title":"parse_date <code>abstractmethod</code>","text":"<pre><code>parse_date(date_str: str) -&gt; datetime.date\n</code></pre> <p>Parse a date string into a <code>date</code>.</p> <p>Parameters:</p> Name Type Description Default <code>date_str</code> <code>str</code> <p>Date string, commonly <code>DD-MM-YYYY</code>.</p> required <p>Returns:</p> Type Description <code>date</code> <p>datetime.date: The parsed date.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DatePort.reconcile_date","title":"reconcile_date <code>abstractmethod</code>","text":"<pre><code>reconcile_date(\n date_str: str, prev_date_str: Optional[str]\n) -&gt; str\n</code></pre> <p>Reconcile an OCR date against the previous transaction date.</p> <p>Parameters:</p> Name Type Description Default <code>date_str</code> <code>str</code> <p>OCR-extracted date string.</p> required <code>prev_date_str</code> <code>Optional[str]</code> <p>Previous transaction date string.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Reconciliated date as <code>DD-MM-YYYY</code>.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DatePort.reorder_lines_by_date","title":"reorder_lines_by_date <code>abstractmethod</code>","text":"<pre><code>reorder_lines_by_date(txn_lines: List[str]) -&gt; List[str]\n</code></pre> <p>Reorder block lines so the dated line leads.</p> <p>Parameters:</p> Name Type Description Default <code>txn_lines</code> <code>List[str]</code> <p>Transaction block lines.</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Lines with the dated line moved to the front.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DatePort.split_line_by_date","title":"split_line_by_date <code>abstractmethod</code>","text":"<pre><code>split_line_by_date(line: str) -&gt; List[str]\n</code></pre> <p>Split a line into segments at date boundaries.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line (possibly two transactions merged).</p> required <p>Returns:</p> Type Description <code>List[str]</code> <p>List[str]: Line segments split at date boundaries.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DescPort","title":"DescPort","text":"<p> Bases: <code>ABC</code></p> <p>Extract a clean transaction description.</p> <p>Attributes:</p> Name Type Description <code>starters</code> <code>List[str]</code> <p>Description starter markers to slice at.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DescPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.DescPort.extract_description","title":"extract_description <code>abstractmethod</code>","text":"<pre><code>extract_description(description: str) -&gt; str\n</code></pre> <p>Extract and clean the transaction description.</p> <p>Parameters:</p> Name Type Description Default <code>description</code> <code>str</code> <p>Raw description text.</p> required <p>Returns:</p> Name Type Description <code>str</code> <code>str</code> <p>Cleaned description.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.ExtractionSource","title":"ExtractionSource <code>dataclass</code>","text":"<pre><code>ExtractionSource(\n source_type: str,\n bank: str,\n pipeline: str,\n path: Optional[str],\n trust_fallback: Optional[str],\n)\n</code></pre> <p>Nested attribute struct describing where to pull content from.</p> <p>Attributes:</p> Name Type Description <code>source_type</code> <code>str</code> <p>Source family tag (pdf, email, csv, xlsx, llama).</p> <code>bank</code> <code>str</code> <p>Bank tag (axis, icici).</p> <code>pipeline</code> <code>str</code> <p>Pipeline tag (heuristic, llm, tabular).</p> <code>path</code> <code>Optional[str]</code> <p>Path to the source content, when applicable.</p> <code>trust_fallback</code> <code>Optional[str]</code> <p>Fallback policy for amount/balance trust.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.IngestPort","title":"IngestPort","text":"<p> Bases: <code>ABC</code></p> <p>Turn an ExtractionSource into a concrete content payload.</p> <p>Attributes:</p> Name Type Description <code>source_type</code> <code>str</code> <p>Source-type tag declared by the concrete root.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.IngestPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.IngestPort.materialize","title":"materialize <code>abstractmethod</code>","text":"<pre><code>materialize(source) -&gt; Any\n</code></pre> <p>Convert a raw source into a concrete content payload.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw source (via <code>ExtractionSource</code>) to materialize.</p> required <p>Returns:</p> Name Type Description <code>Any</code> <code>Any</code> <p>Concrete payload (bytes, Content, dict, list, or str).</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.NumberPort","title":"NumberPort","text":"<p> Bases: <code>ABC</code></p> <p>Extract monetary numbers from OCR/text lines.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.NumberPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.NumberPort.get_numbers","title":"get_numbers <code>abstractmethod</code>","text":"<pre><code>get_numbers(line: str) -&gt; List[float]\n</code></pre> <p>Extract monetary numbers from a line.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>List[float]</code> <p>List[float]: Cleaned monetary numbers found in the line.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.NumberPort.get_opening_balance","title":"get_opening_balance <code>abstractmethod</code>","text":"<pre><code>get_opening_balance(line: str) -&gt; Optional[float]\n</code></pre> <p>Extract the opening balance from a line.</p> <p>Parameters:</p> Name Type Description Default <code>line</code> <code>str</code> <p>Text line to scan.</p> required <p>Returns:</p> Type Description <code>Optional[float]</code> <p>Optional[float]: The opening balance when found, else <code>None</code>.</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.RawExpensePort","title":"RawExpensePort","text":"<p> Bases: <code>ABC</code></p> <p>txn_dicts \u2192 list[RawExpense], balance-chained (terminal).</p>"},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.RawExpensePort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/ports/#pipelines.extraction.shared.ports.RawExpensePort.build","title":"build <code>abstractmethod</code>","text":"<pre><code>build(txn_dicts) -&gt; List[Any]\n</code></pre> <p>Build raw expenses from txn dicts (terminal stage).</p> <p>Parameters:</p> Name Type Description Default <code>txn_dicts</code> <p>List of structured transaction dicts.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/shared/registry/","title":"Registry","text":""},{"location":"pipelines/extraction/shared/registry/#pipelines.extraction.shared.registry","title":"pipelines.extraction.shared.registry","text":""},{"location":"pipelines/extraction/shared/registry/#pipelines.extraction.shared.registry--summary","title":"Summary","text":"<p>Registry mapping (source_type, bank, pipeline) \u2192 composition root.</p> <p>Each family's <code>banks/</code> module defines its concrete root (e.g. <code>AxisPdfExtractionPipeline</code>); this module is the single lookup used by callers (the fetch-request scripts) instead of hand-rolled <code>_BANK_TO_ROOT</code> maps.</p>"},{"location":"pipelines/extraction/shared/registry/#pipelines.extraction.shared.registry-classes","title":"Classes","text":""},{"location":"pipelines/extraction/shared/registry/#pipelines.extraction.shared.registry-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/registry/#pipelines.extraction.shared.registry.known_roots","title":"known_roots","text":"<pre><code>known_roots() -&gt; list\n</code></pre> <p>List every registered (source_type, bank, pipeline) triple.</p> <p>Returns:</p> Name Type Description <code>list</code> <code>list</code> <p>List of <code>(source_type, bank, pipeline)</code> tuples.</p>"},{"location":"pipelines/extraction/shared/registry/#pipelines.extraction.shared.registry.resolve_root","title":"resolve_root","text":"<pre><code>resolve_root(\n source_type: str, bank: str, pipeline: str = \"heuristic\"\n) -&gt; type\n</code></pre> <p>Return the composition root class for (source_type, bank, pipeline).</p> <p>Parameters:</p> Name Type Description Default <code>source_type</code> <code>str</code> <p>Source family (pdf, email, csv, xlsx, llama).</p> required <code>bank</code> <code>str</code> <p>Bank tag (axis, icici).</p> required <code>pipeline</code> <code>str</code> <p>Pipeline tag; defaults to \"heuristic\".</p> <code>'heuristic'</code> <p>Returns:</p> Name Type Description <code>type</code> <code>type</code> <p>The composition root class for the triple.</p> <p>Raises:</p> Type Description <code>ValueError</code> <p>When no root is registered for the triple.</p>"},{"location":"pipelines/extraction/shared/tabular/","title":"Tabular","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular","title":"pipelines.extraction.shared.tabular","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular--summary","title":"Summary","text":"<p>Shared tabular extraction core (csv + xlsx families).</p> <p>Both the csv and xlsx families are \"direct table\" pipelines: the bank parser emits the exact typed table and the pipeline owns all policy \u2014 signs come from the withdrawal/deposit columns and balances are adjusted as we go so the emitted sequence is always balance-chained. No number extraction, bucket finding, splitting, or ambiguity resolution occurs (unlike the pdf family).</p> <p>Shared here (both families import from this module):</p> <ul> <li><code>TableReaderPort</code> : abstract contract, implemented per format/bank.</li> <li><code>TabularTxnDictsPort</code> : abstract contract for records -&gt; txn dicts.</li> <li><code>TabularExtractionPipeline</code>: the graph root (ingest -&gt; table_reader -&gt; txn_dicts -&gt; raw_expense) with a concrete <code>run</code> driving the three shared stages.</li> <li><code>signed_amount</code> / <code>adjust_balances</code> / <code>tabular_to_txn_dict</code> : the balance-chain policy, ported from OG <code>domain.extraction.pipelines.tabular</code>.</li> <li><code>objects_to_txn_dict</code> / <code>ObjectsTxnDictsPort</code> : the llama-family variant \u2014 already-structured statement objects map straight to txn dicts with their STATED balances trusted (no re-chaining), ported from OG <code>domain.extraction.pipelines.llama_parser.to_txn_dict</code>.</li> <li><code>TableParserMixin</code> : format-agnostic header/alias/typing logic, ported from OG <code>IciciTableParserMixin</code> (homed with the icici xlsx parser); the axis csv reader overrides its <code>column_aliases</code> (DR/CR inversion).</li> </ul>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular-classes","title":"Classes","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ImplObjectsTxnDictsPort","title":"ImplObjectsTxnDictsPort","text":"<p> Bases: <code>ObjectsTxnDictsPort</code></p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ImplObjectsTxnDictsPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ImplObjectsTxnDictsPort.build","title":"build","text":"<pre><code>build(objects)\n</code></pre> <p>Build txn dicts from already-structured objects (impl).</p> <p>Parameters:</p> Name Type Description Default <code>objects</code> <p>Structured statement objects.</p> required <p>Returns:</p> Type Description <p>List of txn dicts.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ImplTabularTxnDictsPort","title":"ImplTabularTxnDictsPort","text":"<p> Bases: <code>TabularTxnDictsPort</code></p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ImplTabularTxnDictsPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ImplTabularTxnDictsPort.build","title":"build","text":"<pre><code>build(records)\n</code></pre> <p>Build balance-chained txn dicts from typed records (impl).</p> <p>Parameters:</p> Name Type Description Default <code>records</code> <p>Typed table records.</p> required <p>Returns:</p> Type Description <p>List of txn dicts.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ObjectsTxnDictsPort","title":"ObjectsTxnDictsPort","text":"<p> Bases: <code>ABC</code></p> <p>already-structured objects \u2192 list of txn dicts (stated balances trusted).</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ObjectsTxnDictsPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.ObjectsTxnDictsPort.build","title":"build <code>abstractmethod</code>","text":"<pre><code>build(\n objects: List[Dict[str, Any]],\n) -&gt; List[Dict[str, Any]]\n</code></pre> <p>Build txn dicts from already-structured objects.</p> <p>Parameters:</p> Name Type Description Default <code>objects</code> <code>List[Dict[str, Any]]</code> <p>Structured statement objects.</p> required <p>Returns:</p> Type Description <code>List[Dict[str, Any]]</code> <p>List[Dict[str, Any]]: Txn dicts.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TableParserMixin","title":"TableParserMixin","text":"<p>Format-agnostic typed table reading shared by csv and xlsx readers.</p> <p>Default aliases/required columns model the icici export; the axis csv reader overrides <code>column_aliases</code> (with the DR/CR inversion).</p> <p>Attributes:</p> Name Type Description <code>column_aliases</code> <code>Dict[str, List[str]]</code> <p>Alias lookup for header matching.</p> <code>max_header_scan</code> <code>int</code> <p>Max rows scanned for the header row.</p> <code>required_columns</code> <code>Tuple[str, ...]</code> <p>Columns that must be present.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TableReaderPort","title":"TableReaderPort","text":"<p> Bases: <code>ABC</code></p> <p>content \u2192 list of typed table records (in sheet/file order).</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TableReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TableReaderPort.read","title":"read <code>abstractmethod</code>","text":"<pre><code>read(content) -&gt; List[Dict[str, Any]]\n</code></pre> <p>Read typed table records from content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content payload.</p> required <p>Returns:</p> Type Description <code>List[Dict[str, Any]]</code> <p>List[Dict[str, Any]]: Typed table records in source order.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TabularExtractionPipeline","title":"TabularExtractionPipeline","text":"<p> Bases: <code>ABC</code></p> <p>Root \u2014 direct-table chain: ingest \u2192 table_reader \u2192 txn_dicts \u2192 raw_expense.</p> <p>Attributes:</p> Name Type Description <code>source</code> <code>ExtractionSource</code> <p>The extraction source descriptor.</p> <code>pipeline</code> <code>str</code> <p>Pipeline tag; defaults to \"tabular\".</p> <code>ingest</code> <code>IngestPort</code> <p>Ingest stage.</p> <code>table_reader</code> <code>TableReaderPort</code> <p>Table reading stage.</p> <code>txn_dicts</code> <code>TabularTxnDictsPort</code> <p>Txn-dict building stage.</p> <code>raw_expense</code> <code>RawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TabularExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TabularExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the direct-table extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TabularTxnDictsPort","title":"TabularTxnDictsPort","text":"<p> Bases: <code>ABC</code></p> <p>records \u2192 list of txn dicts, balance-chained (terminal rules live here).</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TabularTxnDictsPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.TabularTxnDictsPort.build","title":"build <code>abstractmethod</code>","text":"<pre><code>build(\n records: List[Dict[str, Any]],\n) -&gt; List[Dict[str, Any]]\n</code></pre> <p>Build balance-chained txn dicts from typed records.</p> <p>Parameters:</p> Name Type Description Default <code>records</code> <code>List[Dict[str, Any]]</code> <p>Typed table records.</p> required <p>Returns:</p> Type Description <code>List[Dict[str, Any]]</code> <p>List[Dict[str, Any]]: Txn dicts.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular-functions","title":"Functions","text":""},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.adjust_balances","title":"adjust_balances","text":"<pre><code>adjust_balances(\n records: List[Dict[str, Any]],\n) -&gt; List[Dict[str, Any]]\n</code></pre> <p>Walk records in table order, correcting balances to the running chain.</p> <p>The first record anchors on its stated balance. Every subsequent record keeps its stated balance only when it continues the chain exactly; otherwise the balance is adjusted to <code>prev + amount</code>.</p> <p>Parameters:</p> Name Type Description Default <code>records</code> <code>List[Dict[str, Any]]</code> <p>Records in table order to chain.</p> required <p>Returns:</p> Type Description <code>List[Dict[str, Any]]</code> <p>List[Dict[str, Any]]: The same records with corrected balances.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.objects_to_txn_dict","title":"objects_to_txn_dict","text":"<pre><code>objects_to_txn_dict(obj: Dict[str, Any]) -&gt; Dict[str, Any]\n</code></pre> <p>Map an already-structured statement object onto the txn-dict shape.</p> <p>Faithful port of OG <code>domain.extraction.pipelines.llama_parser.to_txn_dict</code>: the object already carries a signed-able amount plus an explicit direction (DEBIT/CREDIT), so the balance is TRUSTED as stated \u2014 no re-chaining, unlike the tabular policy. Direction handling accepts the enum instance, <code>\"Direction.CREDIT\"</code>-style prefixed strings, and any casing, mirroring the OG helper.</p> <p>Parameters:</p> Name Type Description Default <code>obj</code> <code>Dict[str, Any]</code> <p>Structured statement object.</p> required <p>Returns:</p> Type Description <code>Dict[str, Any]</code> <p>Dict[str, Any]: Txn dict with txn_date, particulars, amount, balance,</p> <code>Dict[str, Any]</code> <p>and direction keys.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.signed_amount","title":"signed_amount","text":"<pre><code>signed_amount(record: Dict[str, Any]) -&gt; float\n</code></pre> <p>Compute the signed amount from deposit minus withdrawal.</p> <p>Parameters:</p> Name Type Description Default <code>record</code> <code>Dict[str, Any]</code> <p>Typed table record.</p> required <p>Returns:</p> Name Type Description <code>float</code> <code>float</code> <p>Deposit minus withdrawal, rounded to 2 places.</p>"},{"location":"pipelines/extraction/shared/tabular/#pipelines.extraction.shared.tabular.tabular_to_txn_dict","title":"tabular_to_txn_dict","text":"<pre><code>tabular_to_txn_dict(\n record: Dict[str, Any],\n) -&gt; Dict[str, Any]\n</code></pre> <p>Map a typed table record onto the standard txn-dict shape.</p> <p>Parameters:</p> Name Type Description Default <code>record</code> <code>Dict[str, Any]</code> <p>Typed, balance-chained table record.</p> required <p>Returns:</p> Type Description <code>Dict[str, Any]</code> <p>Dict[str, Any]: Txn dict with txn_date, particulars, amount, balance,</p> <code>Dict[str, Any]</code> <p>and direction keys.</p>"},{"location":"pipelines/extraction/xlsx/","title":"Xlsx","text":"<ul> <li>Abc</li> <li>Banks</li> <li>Impl</li> </ul>"},{"location":"pipelines/extraction/xlsx/#pipelines.extraction.xlsx","title":"pipelines.extraction.xlsx","text":""},{"location":"pipelines/extraction/xlsx/#pipelines.extraction.xlsx--summary","title":"Summary","text":"<p>xlsx (direct table) extraction family.</p>"},{"location":"pipelines/extraction/xlsx/abc/","title":"Abc","text":""},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc","title":"pipelines.extraction.xlsx.abc","text":""},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc--summary","title":"Summary","text":"<p>Abstract contracts for the xlsx (direct table) extraction graph.</p> <p>The xlsx family is a \"direct table\" pipeline \u2014 no OCR, no buckets, no ambiguity. It shares the tabular core (<code>shared/tabular.py</code>) with csv: only the table reader differs (xlsx worksheet rows vs csv rows). Bank-specific readers live under <code>banks/</code>.</p>"},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc-classes","title":"Classes","text":""},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc.XlsxExtractionPipeline","title":"XlsxExtractionPipeline","text":"<p> Bases: <code>TabularExtractionPipeline</code></p> <p>xlsx-family root \u2014 pins only the reader; chain shared with csv.</p> Slot annotations <p>source: ExtractionSource ingest, table_reader, txn_dicts, raw_expense</p> <p>Attributes:</p> Name Type Description <code>source</code> <code>ExtractionSource</code> <p>The extraction source descriptor.</p> <code>table_reader</code> <code>XlsxTableReaderPort</code> <p>Xlsx table reader stage.</p>"},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc.XlsxExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc.XlsxExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the direct-table extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc.XlsxTableReaderPort","title":"XlsxTableReaderPort","text":"<p> Bases: <code>TableReaderPort</code></p> <p>content \u2192 list of typed records read from an xlsx statement sheet.</p>"},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc.XlsxTableReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/xlsx/abc/#pipelines.extraction.xlsx.abc.XlsxTableReaderPort.read","title":"read","text":"<pre><code>read(content) -&gt; List[dict]\n</code></pre> <p>Read typed records from an xlsx statement sheet.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content (bytes, Content, dict, or str).</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Typed table records.</p>"},{"location":"pipelines/extraction/xlsx/impl/","title":"Impl","text":""},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl","title":"pipelines.extraction.xlsx.impl","text":""},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl--summary","title":"Summary","text":"<p>Concrete xlsx-family implementations.</p> <p><code>ImplXlsxTableReaderPort</code> reads typed worksheet rows (via the omniread xlsx parser's workbook) and runs them through the shared <code>TableParserMixin</code> to emit typed records. The chain (records \u2192 balance-adjusted txn dicts \u2192 raw expenses) is the shared tabular core.</p>"},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl-classes","title":"Classes","text":""},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl.ImplXlsxExtractionPipeline","title":"ImplXlsxExtractionPipeline","text":"<p> Bases: <code>XlsxExtractionPipeline</code></p> <p>Concrete xlsx graph root.</p> <p>Attributes:</p> Name Type Description <code>ingest</code> <code>ImplIngestPort</code> <p>Ingest stage.</p> <code>table_reader</code> <code>ImplXlsxTableReaderPort</code> <p>Xlsx table reader stage.</p> <code>txn_dicts</code> <code>ImplTabularTxnDictsPort</code> <p>Shared tabular txn-dicts stage.</p> <code>raw_expense</code> <code>ImplRawExpensePort</code> <p>Terminal raw-expense stage.</p>"},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl.ImplXlsxExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl.ImplXlsxExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the direct-table extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl.ImplXlsxTableReaderPort","title":"ImplXlsxTableReaderPort","text":"<p> Bases: <code>TableParserMixin</code>, <code>XlsxTableReaderPort</code></p> <p>Concrete xlsx reader \u2014 omniread xlsx parser + shared <code>TableParserMixin</code>.</p> <p>Attributes:</p> Name Type Description <code>max_header_scan</code> <code>int</code> <p>Max rows scanned for the header row.</p>"},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl.ImplXlsxTableReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/xlsx/impl/#pipelines.extraction.xlsx.impl.ImplXlsxTableReaderPort.read","title":"read","text":"<pre><code>read(content) -&gt; List[dict]\n</code></pre> <p>Read typed records from xlsx content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content (Content, bytes, or dict).</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Typed table records.</p>"},{"location":"pipelines/extraction/xlsx/banks/","title":"Banks","text":"<ul> <li>Icici</li> </ul>"},{"location":"pipelines/extraction/xlsx/banks/#pipelines.extraction.xlsx.banks","title":"pipelines.extraction.xlsx.banks","text":""},{"location":"pipelines/extraction/xlsx/banks/#pipelines.extraction.xlsx.banks--summary","title":"Summary","text":"<p>xlsx family \u2014 bank-specific ports and pipeline roots.</p>"},{"location":"pipelines/extraction/xlsx/banks/icici/","title":"Icici","text":""},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici","title":"pipelines.extraction.xlsx.banks.icici","text":""},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici--summary","title":"Summary","text":"<p>Icici bank-specific port implementations (xlsx table path).</p> <p>Faithful port of <code>domain/extraction/banks/icici/xlsx.py</code>: the xlsx reader uses the shared <code>TableParserMixin</code> (default icici aliases) over typed worksheet rows. Ordering/balance policy stays in the shared tabular txn_dicts stage.</p>"},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici-classes","title":"Classes","text":""},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici.IciciXlsxExtractionPipeline","title":"IciciXlsxExtractionPipeline","text":"<p> Bases: <code>ImplXlsxExtractionPipeline</code></p> <p>Icici xlsx graph root \u2014 pins the Icici reader.</p> <p>Attributes:</p> Name Type Description <code>table_reader</code> <code>IciciXlsxTableReaderPort</code> <p>Icici xlsx reader stage.</p>"},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici.IciciXlsxExtractionPipeline-functions","title":"Functions","text":""},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici.IciciXlsxExtractionPipeline.run","title":"run","text":"<pre><code>run(source) -&gt; List[Any]\n</code></pre> <p>Run the direct-table extraction chain.</p> <p>Parameters:</p> Name Type Description Default <code>source</code> <p>Raw extraction source.</p> required <p>Returns:</p> Type Description <code>List[Any]</code> <p>List[Any]: Raw expense records.</p>"},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici.IciciXlsxTableReaderPort","title":"IciciXlsxTableReaderPort","text":"<p> Bases: <code>ImplXlsxTableReaderPort</code></p> <p>Icici xlsx reader \u2014 inherits the default (icici) column aliases.</p>"},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici.IciciXlsxTableReaderPort-functions","title":"Functions","text":""},{"location":"pipelines/extraction/xlsx/banks/icici/#pipelines.extraction.xlsx.banks.icici.IciciXlsxTableReaderPort.read","title":"read","text":"<pre><code>read(content) -&gt; List[dict]\n</code></pre> <p>Read typed records from xlsx content.</p> <p>Parameters:</p> Name Type Description Default <code>content</code> <p>Materialized content (Content, bytes, or dict).</p> required <p>Returns:</p> Type Description <code>List[dict]</code> <p>List[dict]: Typed table records.</p>"}]}