Source code for aeat.application.ledger._evidence_split
"""Deterministic child-amount derivation for evidence-driven splits.The model proposes per-child *proportions* (fractions); the system derives theper-child euro amounts in :func:`derive_child_amounts` so they sum EXACTLY to theparent gross to the cent (the remainder lands on the last child). The model neveremits a euro amount (``llm-selects-system-derives-tax-numbers``). This bridges:func:`~aeat.application.ledger._llm_classification.suggest_evidence_split` to:func:`~aeat.application.ledger._actions_split_merge.split_transaction`, whosechildren must sum to the parent magnitude exactly."""from__future__importannotationsfromcollections.abcimportSequencefromdecimalimportDecimalfrom...core.moneyimportround_to_cents__all__=["derive_child_amounts"]
[docs]defderive_child_amounts(gross:Decimal,proportions:Sequence[Decimal])->tuple[Decimal,...]:"""Split ``gross`` into per-child amounts matching ``proportions``. Each amount is :func:`~aeat.core.money.round_to_cents` applied to ``gross * proportion``; the final child absorbs the rounding remainder so the amounts sum to ``gross`` exactly. Flow direction is inherited from the parent transaction outside this helper, never encoded in the amount sign. Args: gross: The parent transaction gross as a non-negative magnitude. proportions: Per-child fractions (each in ``(0, 1]``, summing to ~1.0). A single proportion (``1.0``) is the "no split warranted" verdict and yields ``(gross,)`` — the whole amount on one child. The caller (:func:`~aeat.application.ledger._llm_classification.suggest_evidence_split`) surfaces that verdict for review and never drives a one-way split through :func:`~aeat.application.ledger._actions_split_merge.split_transaction`; :func:`~aeat.application.ledger._llm_classification.apply_evidence_split` refuses a single-child suggestion. Returns: Per-child amounts, in child order, summing exactly to ``gross``. Raises: ValueError: When no proportions are supplied or ``gross`` is negative. """ifnotproportions:raiseValueError("a split proposal needs at least one child")ifgross<Decimal("0"):raiseValueError("split parent amount must be a non-negative magnitude")amounts=[round_to_cents(gross*proportion)forproportioninproportions[:-1]]amounts.append(gross-sum(amounts,Decimal("0")))returntuple(amounts)