Output:
Chunk ID: 654620
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2017
Output:
    fees = _decimal_non_negative(request.fees_original, "fees_original")
    current = _current_equity_quantity(conn, account_id=account_id, instrument_id=instrument_id)
    if quantity > current:
        raise HTTPException(status_code=422, detail="Verkauf würde Bestand negativ machen")
    gross = quantity * price
    net = gross - fees
    if net < 0:
        raise HTTPException(status_code=422, detail="fees exceed gross proceeds")
    currency = request.currency.upper()
    fx_status, fx_rate, _fx_source, fx_warning = _fx_for_explicit_save(conn, currency=currency, trade_date=request.trade_date)
    amount_chf = _chf_amount(_format_decimal(net), Decimal(fx_rate) if fx_rate else None)
    avg = _weighted_average_cost(conn, account_id=account_id, instrument_id=instrument_id)
    warnings = [fx_warning] if fx_warning else []
    if avg is None:
        warnings.append("Einstand unvollständig: realisierter P&L nur eingeschränkt verfügbar.")
    return PreviewResponse(preview_id=_uuid("preview"), asset_class="equity", summary=f"Verkauf {quantity} · Erlös {currency} {_format_decimal(net)}", amount_chf=amount_chf, fx_status=fx_status, warnings=warnings)

def confirm_equity_sell(conn: Connection, request: EquitySellConfirmRequest) -> ConfirmResponse:
    if not request.confirm:
        raise HTTPException(status_code=400, detail="Explicit confirm required")
    preview = preview_equity_sell(conn, request)
    account_id, instrument_id = _position_ids(request.position_id)
    quantity = _decimal(request.quantity, "quantity")
    price = _decimal(request.price_original, "price_original")
    fees = _decimal_non_negative(request.fees_original, "fees_original")
    gross = quantity * price
    net = gross - fees
    fx_status, fx_rate, fx_source, _ = _fx_for_explicit_save(conn, currency=request.currency, trade_date=request.trade_date)
    gross_chf = _chf_amount(_format_decimal(gross), Decimal(fx_rate) if fx_rate else None)
    fee_chf = _chf_amount(_format_decimal(fees), Decimal(fx_rate) if fx_rate else None)
    net_chf = _chf_amount(_format_decimal(net), Decimal(fx_rate) if fx_rate else None)
    tx_id = _uuid("tx")
    ts = _now()
    conn.execute("""
        INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, quantity, price_original, gross_amount_original, fee_original, net_amount_original, currency_original, fx_rate_to_chf, fx_source, fx_status, gross_amount_chf, fee_chf, net_amount_chf, source_type, is_confirmed, quality_status, notes, created_at)
        VALUES (?, 'sell', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'vue_equity_sale', 1, ?, ?, ?)
    """, (tx_id, account_id, instrument_id, request.trade_date, _format_decimal(-quantity), _format_decimal(price), _format_decimal(gross), _format_decimal(fees), _format_decimal(net), request.currency.upper(), fx_rate, fx_source, fx_status, gross_chf, fee_chf, net_chf, "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
    if _cash_account_exists(conn, request.cash_account_id):
        conn.execute("INSERT INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (_uuid("cash"), request.cash_account_id, request.trade_date, request.currency.upper(), _format_decimal(net), fx_rate, net_chf, f"vue_equity_sale:{tx_id}", "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
    audit_id = _audit(conn, action="equity_sell_confirm", entity_type="position", entity_id=request.position_id, payload={**request.model_dump(), "net_amount_original": _format_decimal(net), "gross_amount_original": _format_decimal(gross)}, note=request.note, quality_status="ok" if fx_status != "missing" else "missing_fx")
    conn.commit()
    return ConfirmResponse(status="confirmed", entity_id=tx_id, audit_id=audit_id, message="Verkauf bestätigt · Audit geschrieben")

def preview_equity_dividend(conn: Connection, request: EquityDividendPreviewRequest) -> PreviewResponse:
    _position_ids(request.position_id)
    gross = _decimal(request.gross_amount, "gross_amount")
    taxes = _decimal_non_negative(request.swiss_tax, "swiss_tax") + _decimal_non_negative(request.foreign_tax, "foreign_tax") + _decimal_non_negative(request.other_deductions, "other_deductions")
    net = gross - taxes
    if net < 0:
        {where}
        ORDER BY account_id, instrument_id, trade_date, created_at, transaction_id
        """,
        params,
    ).fetchall()
    for row in rows:
        key = (row["account_id"], row["instrument_id"])
        pos = result.positions.setdefault(key, Position(row["account_id"], row["instrument_id"]))
        lot = lots.setdefault(key, WeightedAverageLot())
        t = row["transaction_type"]
        qty = _d(row["quantity"])
        gross = _d(row["gross_amount_original"])
        fee = _d(row["fee_original"])
        tax = _d(row["tax_original"])
        fx = _d(row["fx_rate_to_chf"], "1") if row["fx_rate_to_chf"] is not None else None
        if fx is None or row["fx_status"] == "missing":
            add_warning(pos, "missing_fx", "Historic FX is missing; precise CHF total return cannot be calculated.")
        if t in {"initial_position_snapshot", "buy"}:
            if qty > 0:
                cost_original = gross + fee
                cost_chf = (gross + fee) * fx if fx is not None else Decimal("0")
                lot.buy(qty, cost_original, cost_chf)
                pos.fees_chf += fee * fx if fx is not None else Decimal("0")
                pos.taxes_chf += tax * fx if fx is not None else Decimal("0")
        elif t in {"partial_sell", "full_sell"}:
            if qty > 0:
                proceeds_chf = (gross - fee - tax) * fx if fx is not None else Decimal("0")
                lot.sell(qty, proceeds_chf)
                pos.fees_chf += fee * fx if fx is not None else Decimal("0")
                pos.taxes_chf += tax * fx if fx is not None else Decimal("0")
        elif t in {"dividend", "etf_distribution"}:
            income_original = _d(row["net_amount_original"]) if row["net_amount_original"] is not None else gross - fee - tax
            if fx is not None:
                pos.income_chf += income_original * fx
                pos.fees_chf += fee * fx
                pos.taxes_chf += tax * fx
        if t == "initial_position_snapshot":
            add_warning(pos, "snapshot_only", "Initial snapshot lacks full transaction history; performance is incomplete.")
            if gross == 0 or fx is None:
                add_warning(pos, "cost_basis_uncertain", "Cost basis is uncertain for this initial snapshot.")
    for key, lot in lots.items():
        pos = result.positions[key]
        meta = _instrument_metadata(conn, pos.instrument_id)
        pos.hedge_status = str(meta.get("hedge_status") or "unknown")
        pos.instrument_status = str(meta.get("instrument_status") or "unknown")
        pos.valuation_policy = str(meta.get("valuation_policy") or "live_price")
        pos.corporate_action_status = str(meta.get("corporate_action_status") or "not_checked")
        if pos.hedge_status == "unknown":
            add_warning(pos, "hedge_status_unknown", "Currency hedge status is unknown; FX attribution is incomplete.")
        if pos.instrument_status in {"delisted", "suspended", "merged", "inactive"} and pos.valuation_policy in {"live_price", "exclude_from_auto_price_update"}:
            add_warning(pos, "delisted_or_suspended", "Instrument status excludes or limits automatic valuation.")
        if pos.corporate_action_status in {"suspected", "confirmed"} or meta.get("split_or_corporate_action_review_required"):
            add_warning(pos, "corporate_action_suspected", "Corporate action review is required before high-confidence valuation.")
        pos.quantity = lot.quantity.normalize()
        pos.cost_basis_original = _money(lot.cost_basis_original) or Decimal("0")
        pos.cost_basis_chf = _money(lot.cost_basis_chf) or Decimal("0")


sed -n '600,685p' src/jarvis_finance/imports/postfinance_documents.py


Output:
Chunk ID: df98f6
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 934
Output:
            positions.append(
                PFSnapshotPosition(
                    _hash("snapshot-row", len(positions) + 1, normalize_label(label))[:32],
                    label,
                    normalize_label(label),
                    section,
                    quantity,
                    average,
                    provider_total,
                    price,
                    currency,
                    value,
                    weight,
                )
            )
            continue
        if stripped.startswith("Gesamt CHF") and not in_positions:
            values = [
                _number(value, required=True)
                for value in re.findall(r"[+\-−]?[0-9][0-9'’.,]*", stripped)
            ]
            if len(values) >= 3:
                cash_total, securities_total, total = values[0], values[1], values[2]
            continue
        if stripped.startswith("Zwischensumme Aktien in CHF"):
            values = [
                _number(value, required=True)
                for value in re.findall(r"[+\-−]?[0-9][0-9'’.,]*", stripped)
            ]
            if len(values) >= 3:
                stock_total = values[2]
            continue
        if stripped.startswith("Zwischensumme ETFs in CHF"):
            values = [
                _number(value, required=True)
                for value in re.findall(r"[+\-−]?[0-9][0-9'’.,]*", stripped)
            ]
            if len(values) >= 3:
                etf_total = values[2]
            continue
        m = re.search(r"Offene Aufträge\s+([0-9]+)", stripped)
        if m:
            open_orders = int(m.group(1))
        m = re.search(r"Wert der Wertschriften\s+([0-9][0-9'’.,]*(?: [0-9]{3})*)", stripped)
        if m:
            securities_total = _number(m.group(1), required=True)
        m = re.search(r"Barguthaben\s+([0-9][0-9'’.,]*(?: [0-9]{3})*)", stripped)
        if m:
            cash_total = _number(m.group(1), required=True)
        m = re.search(r"Totalwert\s+([0-9][0-9'’.,]*(?: [0-9]{3})*)", stripped)
        if m and total is None:
            total = _number(m.group(1), required=True)
        m = re.search(r"Zwischensumme Aktien in CHF\s+([0-9][0-9'’.,]*(?: [0-9]{3})*)", stripped)
        if m:
            stock_total = _number(m.group(1), required=True)
        m = re.search(r"Zwischensumme ETFs in CHF\s+([0-9][0-9'’.,]*(?: [0-9]{3})*)", stripped)
        if m:
            etf_total = _number(m.group(1), required=True)
    if len(positions) != 22 or len(cash) != 2:
        raise ValueError(
            "PostFinance account overview does not contain the expected complete snapshot"
        )
    if None in (cash_total, securities_total, total, stock_total, etf_total, open_orders):
        raise ValueError("PostFinance account overview lacks required totals")
    assert (
        cash_total is not None
        and securities_total is not None
        and total is not None
        and stock_total is not None
        and etf_total is not None
        and open_orders is not None
    )
    if abs(sum((p.market_value_chf for p in positions), Decimal("0")) - securities_total) > Decimal(
        "0.05"
    ):
        raise ValueError("PostFinance position sum does not reconcile")
    if abs(securities_total + cash_total - total) > Decimal("0.05"):
        raise ValueError("PostFinance account total does not reconcile")
    if abs(stock_total + etf_total - securities_total) > Decimal("0.05"):
        raise ValueError("PostFinance asset-class totals do not reconcile")
    cash = _reconcile_cash_components(cash, cash_total)
    return PFSnapshot(
        sha256(raw).hexdigest(),
        page_count,
        valuation_at,
        tuple(positions),


Output:
Chunk ID: 9e1a3a
Wall time: 30.0005 seconds
Process running with session ID 38576
Original token count: 7
Output:
...........................


Output:
Chunk ID: 23f4a9
Wall time: 30.0011 seconds
Process running with session ID 38576
Original token count: 0
Output:


Output:
Chunk ID: 3a3f6a
Wall time: 30.0014 seconds
Process running with session ID 38576
Original token count: 0
Output:


nl -ba src/jarvis_finance/services/portfolio_aggregation.py | sed -n '135,260p'; nl -ba src/jarvis_finance/services/cash_service.py | sed -n '180,280p'; nl -ba src/jarvis_finance/dashboard/data.py | sed -n '580,635p'


Output:
Chunk ID: ba7e60
Wall time: 0.0001 seconds
Process exited with code 0
Original token count: 3467
Output:
   135	            account_id=account_id,
   136	            currency=str(row["currency"]),
   137	            amount_original=_decimal(row["amount_original"]),
   138	            source_fx_rate_to_chf=_decimal(row["fx_rate_to_chf"]),
   139	            amount_chf=value,
   140	            snapshot_date=valuation_at[:10],
   141	            valuation_at=valuation_at,
   142	        )
   143	        for row, value in zip(rows, allocated, strict=True)
   144	    ]
   145
   146
   147	def latest_official_postfinance_positions(
   148	    conn: Connection,
   149	    *,
   150	    as_of: str | None = None,
   151	    data_cutoff: str | None = None,
   152	) -> dict[tuple[str, str], OfficialPositionOverride]:
   153	    roles = postfinance_account_roles(conn)
   154	    account_id = roles.get("etrading_depot")
   155	    if not account_id:
   156	        return {}
   157	    conditions: list[str] = []
   158	    params: list[str] = []
   159	    if as_of:
   160	        conditions.append("date(snapshot_at)<=date(?)")
   161	        params.append(as_of)
   162	    if data_cutoff:
   163	        conditions.append("datetime(created_at)<=datetime(?)")
   164	        params.append(data_cutoff)
   165	    where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
   166	    snapshot = conn.execute(
   167	        f"""SELECT snapshot_id,snapshot_at,stocks_chf,etfs_chf
   168	            FROM postfinance_snapshots {where}
   169	            ORDER BY snapshot_at DESC,datetime(created_at) DESC LIMIT 1""",
   170	        params,
   171	    ).fetchone()
   172	    if not snapshot:
   173	        return {}
   174	    rows = conn.execute(
   175	        """SELECT instrument_id,asset_class,quantity,price_original,price_currency,value_chf
   176	           FROM postfinance_snapshot_positions
   177	           WHERE snapshot_id=? ORDER BY asset_class,instrument_id""",
   178	        (snapshot["snapshot_id"],),
   179	    ).fetchall()
   180	    targets = {
   181	        "stock": _money(_decimal(snapshot["stocks_chf"])),
   182	        "etf": _money(_decimal(snapshot["etfs_chf"])),
   183	    }
   184	    allocated_by_instrument: dict[str, Decimal] = {}
   185	    for asset_class, target in targets.items():
   186	        members = [row for row in rows if str(row["asset_class"]).lower() == asset_class]
   187	        allocated = _allocate_pro_rata(
   188	            [_decimal(row["value_chf"]) for row in members], target
   189	        )
   190	        allocated_by_instrument.update(
   191	            {
   192	                str(row["instrument_id"]): value
   193	                for row, value in zip(members, allocated, strict=True)
   194	            }
   195	        )
   196	    valuation_at = str(snapshot["snapshot_at"])
   197	    return {
   198	        (account_id, str(row["instrument_id"])): OfficialPositionOverride(
   199	            account_id=account_id,
   200	            instrument_id=str(row["instrument_id"]),
   201	            asset_class=str(row["asset_class"]).lower(),
   202	            quantity=_decimal(row["quantity"]),
   203	            market_price_original=_decimal(row["price_original"]),
   204	            price_currency=str(row["price_currency"]),
   205	            market_value_chf=allocated_by_instrument[str(row["instrument_id"])],
   206	            snapshot_date=valuation_at[:10],
   207	            valuation_at=valuation_at,
   208	        )
   209	        for row in rows
   210	    }
   211
   212
   213	def post_snapshot_postfinance_quantity_deltas(
   214	    conn: Connection,
   215	    positions: dict[tuple[str, str], OfficialPositionOverride],
   216	    *,
   217	    as_of: str | None = None,
   218	) -> dict[str, Decimal]:
   219	    """Replay confirmed buys/sells after the official snapshot baseline."""
   220
   221	    if not positions:
   222	        return {}
   223	    roles = postfinance_account_roles(conn)
   224	    account_ids = [
   225	        account_id
   226	        for role in ("etrading_depot", "etrading_cash")
   227	        if (account_id := roles.get(role))
   228	    ]
   229	    if not account_ids:
   230	        return {}
   231	    snapshot_date = min(item.snapshot_date for item in positions.values())
   232	    effective_as_of = as_of or "9999-12-31"
   233	    placeholders = ",".join("?" for _ in account_ids)
   234	    rows = conn.execute(
   235	        f"""SELECT instrument_id,lower(transaction_type) transaction_type,quantity
   236	            FROM transactions
   237	            WHERE account_id IN ({placeholders})
   238	              AND instrument_id IS NOT NULL
   239	              AND COALESCE(is_confirmed,0)=1
   240	              AND COALESCE(is_voided,0)=0
   241	              AND lower(transaction_type) IN ('buy','sell','partial_sell','full_sell')
   242	              AND trade_date>? AND trade_date<=?""",
   243	        (*account_ids, snapshot_date, effective_as_of),
   244	    ).fetchall()
   245	    deltas: dict[str, Decimal] = {}
   246	    for row in rows:
   247	        instrument_id = str(row["instrument_id"])
   248	        quantity = abs(_decimal(row["quantity"]))
   249	        if str(row["transaction_type"]) in {"sell", "partial_sell", "full_sell"}:
   250	            quantity = -quantity
   251	        deltas[instrument_id] = deltas.get(instrument_id, Decimal("0")) + quantity
   252	    return deltas
   253
   254
   255	def latest_audited_market_values(
   256	    conn: Connection,
   257	) -> dict[tuple[str, str], AuditedMarketValue]:
   258	    """Return the latest immutable market-analysis values without writing on GET."""
   259
   260	    row = conn.execute(
   180	    row = conn.execute("SELECT MAX(trade_date) AS last_date FROM transactions WHERE account_id=? AND source_type LIKE '%csv%'", (account_id,)).fetchone()
   181	    return row["last_date"] if row else None
   182
   183
   184	def _post_snapshot_cash_deltas(
   185	    conn: Connection,
   186	    account_id: str,
   187	    snapshot_date: str,
   188	) -> dict[str, tuple[Decimal, Decimal | None]]:
   189	    rows = conn.execute(
   190	        """SELECT * FROM transactions
   191	           WHERE account_id=? AND trade_date>?
   192	             AND COALESCE(is_confirmed,0)=1 AND COALESCE(is_voided,0)=0
   193	           ORDER BY trade_date,created_at,transaction_id""",
   194	        (account_id, snapshot_date),
   195	    ).fetchall()
   196	    deltas: dict[str, tuple[Decimal, Decimal | None]] = {}
   197	    for row in rows:
   198	        original, amount_chf = _signed_cash_delta(row)
   199	        if original == 0 and amount_chf in {None, Decimal("0")}:
   200	            continue
   201	        currency = str(row["currency_original"])
   202	        previous_original, previous_chf = deltas.get(
   203	            currency,
   204	            (Decimal("0"), Decimal("0")),
   205	        )
   206	        deltas[currency] = (
   207	            previous_original + original,
   208	            None
   209	            if previous_chf is None or amount_chf is None
   210	            else previous_chf + amount_chf,
   211	        )
   212	    return deltas
   213
   214
   215	def list_cash_positions(conn: Connection) -> list[CashPosition]:
   216	    ledger = calculate_cash_balances(conn, persist_alerts=False)
   217	    rows = conn.execute(
   218	        """
   219	        SELECT a.account_id, a.account_name, a.account_type, a.currency, COALESCE(a.balance_mode,'manual') AS balance_mode, p.name AS platform
   220	        FROM accounts a JOIN platforms p ON p.platform_id=a.platform_id
   221	        WHERE a.is_active=1
   222	          AND (
   223	              a.account_type='cash'
   224	              OR a.account_id IN (
   225	                  SELECT account_id FROM postfinance_account_roles
   226	                  WHERE role='etrading_cash'
   227	              )
   228	          )
   229	        ORDER BY p.name, a.account_name
   230	        """
   231	    ).fetchall()
   232	    positions: list[CashPosition] = []
   233	    official_components = latest_official_postfinance_cash(conn)
   234	    official_by_account: dict[str, list] = {}
   235	    for component in official_components:
   236	        official_by_account.setdefault(component.account_id, []).append(component)
   237	    for row in rows:
   238	        account_id = row["account_id"]
   239	        if account_id in official_by_account:
   240	            components = {
   241	                component.currency: component
   242	                for component in official_by_account[account_id]
   243	            }
   244	            snapshot_date = next(iter(components.values())).snapshot_date
   245	            deltas = _post_snapshot_cash_deltas(conn, account_id, snapshot_date)
   246	            for currency in sorted(set(components) | set(deltas)):
   247	                component = components.get(currency)
   248	                delta_original, delta_chf = deltas.get(
   249	                    currency,
   250	                    (Decimal("0"), Decimal("0")),
   251	                )
   252	                amount_original = (
   253	                    component.amount_original if component else Decimal("0")
   254	                ) + delta_original
   255	                baseline_chf = component.amount_chf if component else Decimal("0")
   256	                amount_chf = (
   257	                    baseline_chf + delta_chf if delta_chf is not None else baseline_chf
   258	                )
   259	                status = (
   260	                    "Abgleich offen"
   261	                    if delta_chf is None
   262	                    else "Offiziell abgeglichen + Bewegungen"
   263	                    if delta_original or delta_chf
   264	                    else "Offiziell abgeglichen"
   265	                )
   266	                positions.append(
   267	                    CashPosition(
   268	                        id=f"{account_id}:{currency}",
   269	                        account_id=account_id,
   270	                        platform=row["platform"],
   271	                        account_label=row["account_name"],
   272	                        account_type=row["account_type"],
   273	                        currency=currency,
   274	                        balance_mode="official_components",
   275	                        amount=decimal_text(amount_original, 2),
   276	                        amount_chf=decimal_text(amount_chf, 2),
   277	                        calculated_balance_chf=decimal_text(amount_chf, 2),
   278	                        manual_balance_chf=None,
   279	                        csv_anchor_balance_chf=None,
   280	                        used_value_chf=decimal_text(amount_chf, 2),
   580	            SELECT a.account_name, p.name AS platform, i.name, i.ticker, i.isin, i.asset_class, i.currency,
   581	                   i.hedge_status, i.instrument_status, i.valuation_policy, i.corporate_action_status,
   582	                   mp.close AS latest_price, mp.currency AS latest_price_currency, mp.price_date AS latest_price_date,
   583	                   mp.provider AS latest_price_provider
   584	            FROM accounts a JOIN platforms p ON p.platform_id=a.platform_id
   585	            JOIN instruments i ON i.instrument_id=?
   586	            LEFT JOIN market_prices mp ON mp.market_price_id = (
   587	                SELECT market_price_id FROM market_prices
   588	                WHERE instrument_id=i.instrument_id AND quality_status IN ('fresh','ok')
   589	                ORDER BY price_date DESC, created_at DESC LIMIT 1
   590	            )
   591	            WHERE a.account_id=?
   592	            """,
   593	            (instrument_id, account_id),
   594	        ).fetchone()
   595	        override = official.get((account_id, instrument_id))
   596	        effective_quantity = (
   597	            override.quantity + post_snapshot_deltas.get(instrument_id, Decimal("0"))
   598	            if override
   599	            else pos.quantity
   600	        )
   601	        if override and effective_quantity <= 0:
   602	            continue
   603	        market_value = audited.get((account_id, instrument_id))
   604	        use_market_run = bool(
   605	            market_value
   606	            and (not override or market_value.as_of > override.snapshot_date)
   607	        )
   608	        if override and not use_market_run:
   609	            quantity = effective_quantity
   610	            market_price = override.market_price_original
   611	            market_value_chf = (
   612	                override.market_value_chf * effective_quantity / override.quantity
   613	                if override.quantity
   614	                else Decimal("0")
   615	            )
   616	            price_currency = override.price_currency
   617	            price_date = override.valuation_at
   618	            price_provider = "PostFinance official snapshot"
   619	            valuation_source = "postfinance_official_import"
   620	        elif use_market_run and market_value:
   621	            quantity = effective_quantity
   622	            market_price = market_value.close
   623	            market_value_chf = (
   624	                market_value.value_chf * effective_quantity / market_value.quantity
   625	                if market_value.quantity
   626	                else market_value.value_chf
   627	            )
   628	            price_currency = market_value.currency
   629	            price_date = market_value.as_of
   630	            price_provider = market_value.provider
   631	            valuation_source = "audited_market_run"
   632	        else:
   633	            quantity = pos.quantity
   634	            market_price = pos.market_price_original
   635	            market_value_chf = pos.market_value_chf


sed -n '700,825p' src/jarvis_finance/services/postfinance_service.py


Output:
Chunk ID: c52bc3
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1660
Output:
                    to_consume -= consumed
        for instrument_id, instrument_lots in lots.items():
            for lot in instrument_lots:
                event = lot["event"]
                conn.execute(
                    """INSERT INTO postfinance_cost_basis_lots(lot_id,event_id,instrument_id,acquired_on,quantity_acquired,quantity_remaining,unit_cost_original,fees_original,currency,method,provenance_document_hash,created_at) VALUES(?,?,?,?,?,?,?,?,?,'documented_trade_fifo',?,?)""",
                    (
                        _id("pflot"),
                        f"pfevent_{event.event_fingerprint[:24]}",
                        instrument_id,
                        event.occurred_on,
                        _text(event.quantity),
                        _text(lot["remaining"]),
                        _text(event.price_original),
                        _text(event.fee_original) or "0",
                        event.currency,
                        event.document_hash,
                        now,
                    ),
                )
        for position in snapshot.positions:
            instrument_id = position_map[position.row_reference]
            matched_lots = lots.get(instrument_id, [])
            quantity = sum((lot["remaining"] for lot in matched_lots), Decimal("0"))
            complete = (
                bool(matched_lots)
                and quantity == position.quantity
                and len({lot["event"].currency for lot in matched_lots}) == 1
            )
            calculated = (
                sum(
                    (
                        lot["remaining"] * (lot["event"].price_original or 0)
                        + (lot["event"].fee_original + lot["event"].tax_original)
                        * (lot["remaining"] / lot["event"].quantity)
                        for lot in matched_lots
                        if lot["event"].quantity
                    ),
                    Decimal("0"),
                )
                if complete
                else None
            )
            status = "complete" if complete else "partial" if matched_lots else "unavailable"
            conn.execute(
                """INSERT INTO postfinance_snapshot_positions(snapshot_position_id,snapshot_id,source_row_reference,instrument_id,asset_class,quantity,provider_average_cost_original,provider_cost_total_original,price_original,price_currency,value_chf,weight_pct,computed_cost_basis_original,computed_cost_basis_status,provenance_json,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
                (
                    _id("pfposition"),
                    snapshot_id,
                    position.row_reference,
                    instrument_id,
                    position.asset_class,
                    _text(position.quantity),
                    _text(position.provider_average_cost_original),
                    _text(position.provider_cost_total_original),
                    _text(position.market_price_original),
                    position.price_currency,
                    _money(position.market_value_chf),
                    _text(position.weight_pct),
                    _text(calculated),
                    status,
                    json.dumps(
                        {
                            "provider": "official_account_overview",
                            "calculated": "documented_trade_fifo",
                            "estimated": False,
                        },
                        sort_keys=True,
                    ),
                    now,
                ),
            )
            conn.execute(
                """INSERT INTO positions_snapshot(position_snapshot_id,snapshot_date,account_id,platform_id,instrument_id,quantity,average_cost_original,cost_basis_original,market_price_original,market_value_original,market_fx_rate_to_chf,market_value_chf,portfolio_weight_pct,category,data_quality_status,source_type,source_reference,created_at) SELECT ?,?,?,a.platform_id,?,?,?,?,?,?,?,?,?,?,?,?,?,? FROM accounts a WHERE a.account_id=?""",
                (
                    _id("position"),
                    snapshot.valuation_at[:10],
                    accounts["etrading_depot"],
                    instrument_id,
                    _text(position.quantity),
                    _text(position.provider_average_cost_original),
                    _text(position.provider_cost_total_original),
                    _text(position.market_price_original),
                    _text(position.quantity * position.market_price_original),
                    None,
                    _money(position.market_value_chf),
                    _text(position.weight_pct),
                    position.asset_class,
                    "verified",
                    "postfinance_official_import",
                    snapshot_id,
                    now,
                    accounts["etrading_depot"],
                ),
            )
        for cash in snapshot.cash:
            conn.execute(
                "INSERT INTO postfinance_snapshot_cash(snapshot_cash_id,snapshot_id,currency,amount_original,fx_rate_to_chf,value_chf,created_at) VALUES(?,?,?,?,?,?,?)",
                (
                    _id("pfcash"),
                    snapshot_id,
                    cash.currency,
                    _text(cash.amount_original),
                    _text(cash.fx_rate_to_chf),
                    _money(cash.source_value_chf),
                    now,
                ),
            )
            conn.execute(
                "INSERT INTO cash_balances(cash_balance_id,account_id,balance_date,currency,amount_original,fx_rate_to_chf,amount_chf,source_type,quality_status,notes,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?)",
                (
                    _id("cash"),
                    accounts["etrading_cash"],
                    snapshot.valuation_at[:10],
                    cash.currency,
                    _text(cash.amount_original),
                    _text(cash.fx_rate_to_chf),
                    _money(cash.source_value_chf),
                    "postfinance_official_import",
                    "verified",
                    "Official PostFinance account overview",
                    now,
                ),
            )
        conn.execute(
            "INSERT INTO account_value_snapshots(snapshot_id,account_id,valuation_date,total_value_chf,currency,source_type,quality_status,notes,created_at,valuation_at,source_reference,is_active) VALUES(?,?,?,?,'CHF','postfinance_official_import','ok','Official PostFinance account overview',?,?,?,1)",


sed -n '620,720p' src/jarvis_finance/services/postfinance_service.py


Output:
Chunk ID: 633233
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1226
Output:
                now,
            ),
        )
        for event in bundle.events:
            instrument_id = event_instruments[event.event_fingerprint]
            event_id = f"pfevent_{event.event_fingerprint[:24]}"
            account_id = accounts[event.account_role]
            conn.execute(
                """INSERT INTO postfinance_ledger_events(event_id,event_fingerprint,document_hash,semantic_reference_hash,event_type,account_role,account_id,occurred_on,settlement_on,direction,instrument_id,quantity,price_original,gross_original,fee_original,tax_original,net_original,currency,fx_rate_to_chf,internal_transfer_group,quality_status,reason_codes_json,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
                (
                    event_id,
                    event.event_fingerprint,
                    event.document_hash,
                    _hash(event.semantic_reference),
                    event.event_type,
                    event.account_role,
                    account_id,
                    event.occurred_on,
                    event.settlement_on,
                    event.direction or "neutral",
                    instrument_id,
                    _text(event.quantity),
                    _text(event.price_original),
                    _text(event.gross_original),
                    _text(event.fee_original) or "0",
                    _text(event.tax_original) or "0",
                    _text(event.net_original),
                    event.currency,
                    _text(event.fx_rate_to_chf),
                    event.internal_transfer_group,
                    event.quality_status,
                    json.dumps(event.reason_codes),
                    now,
                ),
            )
            for kind, amount in (
                ("gross", event.gross_original),
                ("fee", event.fee_original),
                ("tax", event.tax_original),
                ("net", event.net_original),
            ):
                if amount is not None and event.currency:
                    conn.execute(
                        "INSERT INTO postfinance_event_components(component_id,event_id,component_type,amount_original,currency,provenance_document_hash,created_at) VALUES(?,?,?,?,?,?,?)",
                        (
                            _id("pfcomponent"),
                            event_id,
                            kind,
                            _text(amount),
                            event.currency,
                            event.document_hash,
                            now,
                        ),
                    )
            _canonical_transaction(conn, event_id, event, account_id, instrument_id, now)
        lots: dict[str, list[dict[str, Any]]] = defaultdict(list)
        for event in sorted(
            bundle.events,
            key=lambda item: (
                item.occurred_on,
                0 if item.event_type == "buy" else 1,
                item.event_fingerprint,
            ),
        ):
            instrument_id = event_instruments[event.event_fingerprint]
            if (
                event.event_type == "buy"
                and instrument_id
                and event.quantity
                and event.price_original
                and event.currency
            ):
                lots[instrument_id].append({"event": event, "remaining": event.quantity})
            elif event.event_type == "sell" and instrument_id and event.quantity:
                to_consume = event.quantity
                for lot in lots[instrument_id]:
                    if to_consume <= 0:
                        break
                    consumed = min(lot["remaining"], to_consume)
                    lot["remaining"] -= consumed
                    to_consume -= consumed
        for instrument_id, instrument_lots in lots.items():
            for lot in instrument_lots:
                event = lot["event"]
                conn.execute(
                    """INSERT INTO postfinance_cost_basis_lots(lot_id,event_id,instrument_id,acquired_on,quantity_acquired,quantity_remaining,unit_cost_original,fees_original,currency,method,provenance_document_hash,created_at) VALUES(?,?,?,?,?,?,?,?,?,'documented_trade_fifo',?,?)""",
                    (
                        _id("pflot"),
                        f"pfevent_{event.event_fingerprint[:24]}",
                        instrument_id,
                        event.occurred_on,
                        _text(event.quantity),
                        _text(lot["remaining"]),
                        _text(event.price_original),
                        _text(event.fee_original) or "0",
                        event.currency,
                        event.document_hash,
                        now,
                    ),
                )
        for position in snapshot.positions:


grep -n "def _canonical_transaction" -A80 src/jarvis_finance/services/postfinance_service.py


Output:
Chunk ID: cee605
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 746
Output:
413:def _canonical_transaction(
414-    conn: Connection,
415-    event_id: str,
416-    event: PFEvent,
417-    account_id: str,
418-    instrument_id: str | None,
419-    now: str,
420-) -> None:
421-    if event.event_type in {"split", "corporate_action"}:
422-        return
423-    tx_type = {
424-        "buy": "buy",
425-        "sell": "sell",
426-        "dividend": "dividend",
427-        "interest": "interest",
428-        "fee": "fee",
429-        "internal_transfer": "transfer",
430-        "fx": "fx",
431-    }[event.event_type]
432-    activity = (
433-        "internal_transfer"
434-        if event.event_type == "internal_transfer"
435-        else "external_cashflow"
436-        if event.event_type in {"dividend", "interest", "fee"}
437-        else "trade"
438-    )
439-    columns = (
440-        "transaction_id,transaction_type,account_id,instrument_id,trade_date,settlement_date,quantity,"
441-        "price_original,gross_amount_original,fee_original,tax_original,net_amount_original,currency_original,"
442-        "fx_rate_to_chf,fx_source,fx_status,gross_amount_chf,fee_chf,tax_chf,net_amount_chf,source_type,source_id,"
443-        "external_transaction_id,row_hash,is_confirmed,quality_status,notes,created_at,updated_at,is_voided,"
444-        "activity_kind,booking_date,base_currency,internal_transfer_group_id,source_reference"
445-    )
446-    values = (
447-        event_id,
448-        tx_type,
449-        account_id,
450-        instrument_id,
451-        event.occurred_on,
452-        event.settlement_on,
453-        _text(event.quantity),
454-        _text(event.price_original),
455-        _text(event.gross_original),
456-        _text(event.fee_original) or "0",
457-        _text(event.tax_original) or "0",
458-        _text(event.net_original),
459-        event.currency,
460-        _text(event.fx_rate_to_chf),
461-        None,
462-        "unavailable",
463-        None,
464-        None,
465-        None,
466-        None,
467-        "postfinance_official_import",
468-        event_id,
469-        event.event_fingerprint,
470-        event.event_fingerprint,
471-        1,
472-        event.quality_status,
473-        "Verified PostFinance document event",
474-        now,
475-        None,
476-        0,
477-        activity,
478-        event.settlement_on or event.occurred_on,
479-        "CHF",
480-        event.internal_transfer_group,
481-        _hash(event.semantic_reference),
482-    )
483-    conn.execute(
484-        f"INSERT INTO transactions({columns}) VALUES({','.join('?' for _ in values)})", values
485-    )
486-
487-
488-def confirm_postfinance_import(conn: Connection, request: dict[str, Any]) -> dict[str, Any]:
489-    if request.get("confirm") is not True:
490-        raise ValueError("Explicit PostFinance import confirmation is required")
491-    preview = preview_postfinance_import(conn, request)
492-    if (
493-        request.get("preview_id") != preview["preview_id"]


grep -n "def confirm_equity_buy" -A50 src/jarvis_finance/services/manual_entry_service.py


Output:
Chunk ID: 0bb076
Wall time: 0.0000 seconds
Process exited with code 1
Original token count: 0
Output:


grep -R "cash_account_id" -n src/jarvis_finance/services src/jarvis_finance/api | head -60


Output:
Chunk ID: e0fa18
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 429
Output:
grep: src/jarvis_finance/services/__pycache__/manual_entry_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/api/schemas/__pycache__/positions.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/api/schemas/__pycache__/positions.cpython-312.pyc: binary file matches
src/jarvis_finance/services/manual_entry_service.py:918:    if _cash_account_exists(conn, request.cash_account_id):
src/jarvis_finance/services/manual_entry_service.py:919:        conn.execute("INSERT INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (_uuid("cash"), request.cash_account_id, request.trade_date, request.currency.upper(), _format_decimal(net), fx_rate, net_chf, f"vue_equity_sale:{tx_id}", "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
src/jarvis_finance/services/manual_entry_service.py:932:    if not _cash_account_exists(conn, request.cash_account_id):
src/jarvis_finance/services/manual_entry_service.py:957:    conn.execute("INSERT INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'vue_equity_dividend', ?, ?, ?)", (_uuid("cash"), request.cash_account_id, request.payment_date, request.currency.upper(), _format_decimal(net), fx_rate, net_chf, "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
src/jarvis_finance/api/schemas/positions.py:340:    cash_account_id: str | None = None
src/jarvis_finance/api/schemas/positions.py:356:    cash_account_id: str


sed -n '930,965p' src/jarvis_finance/services/manual_entry_service.py


Output:
Chunk ID: 011658
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 897
Output:
    if net < 0:
        raise HTTPException(status_code=422, detail="deductions exceed gross dividend")
    if not _cash_account_exists(conn, request.cash_account_id):
        raise HTTPException(status_code=404, detail="Cash account not found")
    fx_status, fx_rate, _fx_source, fx_warning = _fx_for_explicit_save(conn, currency=request.currency, trade_date=request.payment_date)
    warnings = [fx_warning] if fx_warning else []
    return PreviewResponse(preview_id=_uuid("preview"), asset_class="income", summary=f"Dividende netto {request.currency.upper()} {_format_decimal(net)}", amount_chf=_chf_amount(_format_decimal(net), Decimal(fx_rate) if fx_rate else None), fx_status=fx_status, warnings=warnings)

def confirm_equity_dividend(conn: Connection, request: EquityDividendConfirmRequest) -> ConfirmResponse:
    if not request.confirm:
        raise HTTPException(status_code=400, detail="Explicit confirm required")
    preview = preview_equity_dividend(conn, request)
    account_id, instrument_id = _position_ids(request.position_id)
    gross = _decimal(request.gross_amount, "gross_amount")
    taxes = _decimal_non_negative(request.swiss_tax, "swiss_tax") + _decimal_non_negative(request.foreign_tax, "foreign_tax") + _decimal_non_negative(request.other_deductions, "other_deductions")
    net = gross - taxes
    fx_status, fx_rate, fx_source, _ = _fx_for_explicit_save(conn, currency=request.currency, trade_date=request.payment_date)
    gross_chf = _chf_amount(_format_decimal(gross), Decimal(fx_rate) if fx_rate else None)
    tax_chf = _chf_amount(_format_decimal(taxes), Decimal(fx_rate) if fx_rate else None)
    net_chf = _chf_amount(_format_decimal(net), Decimal(fx_rate) if fx_rate else None)
    tx_id = _uuid("tx")
    ts = _now()
    conn.execute("""
        INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, gross_amount_original, tax_original, net_amount_original, currency_original, fx_rate_to_chf, fx_source, fx_status, gross_amount_chf, tax_chf, net_amount_chf, source_type, is_confirmed, quality_status, notes, created_at)
        VALUES (?, 'dividend', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'vue_equity_dividend', 1, ?, ?, ?)
    """, (tx_id, account_id, instrument_id, request.payment_date, _format_decimal(gross), _format_decimal(taxes), _format_decimal(net), request.currency.upper(), fx_rate, fx_source, fx_status, gross_chf, tax_chf, net_chf, "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
    conn.execute("INSERT INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'vue_equity_dividend', ?, ?, ?)", (_uuid("cash"), request.cash_account_id, request.payment_date, request.currency.upper(), _format_decimal(net), fx_rate, net_chf, "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
    audit_id = _audit(conn, action="equity_dividend_confirm", entity_type="position", entity_id=request.position_id, payload={**request.model_dump(), "net_amount_original": _format_decimal(net), "tax_original": _format_decimal(taxes)}, note=request.note, quality_status="ok" if fx_status != "missing" else "missing_fx")
    conn.commit()
    return ConfirmResponse(status="confirmed", entity_id=tx_id, audit_id=audit_id, message="Dividende bestätigt · Audit geschrieben")

def cleanup_review_artifacts_preview(conn: Connection) -> CleanupPreviewResponse:
    plan = identify_review_test_equity_artifacts(conn)
    warnings = []


sed -n '1460,1515p' src/jarvis_finance/services/portfolio_data.py && grep -n "account_map" -n src/jarvis_finance/services/portfolio_data.py | head -20


Output:
Chunk ID: 03a525
Wall time: 0.0001 seconds
Process exited with code 0
Original token count: 1363
Output:
    if base_currency.upper() != "CHF":
        raise ValueError("Reconciliation v1 unterstützt als Basiswährung ausschliesslich CHF")
    absolute = _decimal(absolute_tolerance, "Absolute Toleranz", non_negative=True)
    relative = _decimal(relative_tolerance, "Relative Toleranz", non_negative=True)
    if limit < 1 or limit > 500 or offset < 0:
        raise ValueError("Pagination ist ungültig")
    accounts = _validate_scope(conn, "account" if account_id else "portfolio", account_id)
    account_map = {row["account_id"]: row for row in accounts}
    if not account_map:
        empty_coverage = {key: {"covered": 0, "total": 0, "ratio": None} for key in ("accounts", "instruments", "activities", "opening_valuations", "closing_valuations", "prices", "fx", "cost_basis", "reconciliation")}
        return {"as_of": as_of, "data_cutoff": cutoff, "base_currency": "CHF", "status": "unavailable", "reason_codes": ["missing_account_valuation"], "tolerance": {"version": TOLERANCE_VERSION, "absolute": str(absolute), "relative": str(relative)}, "coverage": empty_coverage, "differences": [], "account_totals": [], "input_fingerprint": _hash([as_of, cutoff, []]), "sources": [], "limit": limit, "offset": offset, "total": 0}
    placeholders = ",".join("?" for _ in account_map)
    transaction_rows = conn.execute(
        f"""SELECT * FROM transactions WHERE account_id IN ({placeholders}) AND trade_date<=?
            AND datetime(created_at)<=datetime(?)
            AND COALESCE(is_voided,0)=0 AND COALESCE(is_confirmed,1)=1
            ORDER BY trade_date, created_at, transaction_id""", (*account_map, as_of, cutoff)
    ).fetchall()
    quantities: dict[tuple[str, str], Decimal] = {}
    activity_supported = 0
    cost_basis_keys: set[tuple[str, str]] = set()
    for row in transaction_rows:
        kind = str(row["activity_kind"] or row["transaction_type"] or "").lower()
        if kind in SUPPORTED_ACTIVITIES:
            activity_supported += 1
        if not row["instrument_id"] or row["quantity"] in (None, ""):
            continue
        key = (str(row["account_id"]), str(row["instrument_id"]))
        try:
            quantity = _stored_decimal(row["quantity"], "Menge", non_negative=True)
        except ValueError:
            continue
        if kind in {"buy", "initial_position_snapshot"}:
            quantities[key] = quantities.get(key, Decimal("0")) + quantity
            if row["gross_amount_original"] not in (None, ""):
                cost_basis_keys.add(key)
        elif kind in {"partial_sell", "full_sell", "sell"}:
            quantities[key] = quantities.get(key, Decimal("0")) - quantity
    reported_rows = conn.execute(
        f"""WITH ranked AS (
              SELECT p.*, ROW_NUMBER() OVER(PARTITION BY account_id,instrument_id ORDER BY snapshot_date DESC,created_at DESC,position_snapshot_id DESC) rn
              FROM positions_snapshot p WHERE account_id IN ({placeholders}) AND snapshot_date<=?
                AND datetime(created_at)<=datetime(?)
            ) SELECT * FROM ranked WHERE rn=1""", (*account_map, as_of, cutoff)
    ).fetchall()
    reported = {(str(row["account_id"]), str(row["instrument_id"])): row for row in reported_rows}
    keys = sorted(set(quantities) | set(reported))
    differences: list[dict[str, Any]] = []
    price_covered = fx_covered = recon_covered = 0
    account_position_values: dict[str, Decimal] = {key: Decimal("0") for key in account_map}
    account_position_dates: dict[str, set[str]] = {key: set() for key in account_map}
    for account, instrument in keys:
        ledger_qty = quantities.get((account, instrument))
        source = reported.get((account, instrument))
        source_qty = _stored_decimal(source["quantity"], "Gemeldete Menge") if source and source["quantity"] not in (None, "") else None
        reasons: list[str] = []
217:    account_map = {row["account_id"]: row for row in accounts}
218:    placeholders = ",".join("?" for _ in account_map)
223:        (*account_map, period_from, period_to, cutoff),
278:            fingerprint, account_id, _safe_ref("account", account_id), _safe_label(account_map[account_id]["account_name"]),
291:    account_map = {row["account_id"]: row for row in accounts}
292:    placeholders = ",".join("?" for _ in account_map)
297:        (*account_map, period_from, period_to, cutoff),
340:            fingerprint, account_id, _safe_ref("account", account_id), _safe_label(account_map[account_id]["account_name"]),
353:    account_map = {row["account_id"]: row for row in accounts}
354:    placeholders = ",".join("?" for _ in account_map)
360:        (*account_map, period_from, period_to, cutoff),
389:            fingerprint, account_id, _safe_ref("account", account_id), _safe_label(account_map[account_id]["account_name"]),
1467:    account_map = {row["account_id"]: row for row in accounts}
1468:    if not account_map:
1471:    placeholders = ",".join("?" for _ in account_map)
1476:            ORDER BY trade_date, created_at, transaction_id""", (*account_map, as_of, cutoff)
1503:            ) SELECT * FROM ranked WHERE rn=1""", (*account_map, as_of, cutoff)
1509:    account_position_values: dict[str, Decimal] = {key: Decimal("0") for key in account_map}
1510:    account_position_dates: dict[str, set[str]] = {key: set() for key in account_map}
1592:            "account_ref": _safe_ref("account", account), "account_label": _safe_label(account_map[account]["account_name"]),


grep -n "def _validate_scope" -A80 src/jarvis_finance/services/portfolio_data.py


Output:
Chunk ID: a7c20b
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1002
Output:
131:def _validate_scope(conn: Connection, scope_kind: str, account_id: str | None) -> list[dict[str, str]]:
132-    if scope_kind not in {"portfolio", "account"}:
133-        raise ValueError("Scope muss portfolio oder account sein")
134-    if scope_kind == "account" and not account_id:
135-        raise ValueError("Für den Account-Scope ist ein Konto erforderlich")
136-    params: tuple[object, ...] = ()
137-    where = "WHERE is_active=1 AND performance_included=1"
138-    if account_id:
139-        where += " AND account_id=?"
140-        params = (account_id,)
141-    rows = conn.execute(f"SELECT account_id, account_name, account_type, currency FROM accounts {where} ORDER BY account_id", params).fetchall()
142-    if scope_kind == "account" and not rows:
143-        raise ValueError("Portfolio-Konto wurde nicht gefunden")
144-    return [dict(row) for row in rows]
145-
146-
147-def _validate_request(conn: Connection, request: dict[str, Any]) -> tuple[list[dict[str, str]], str, str, str]:
148-    source_key = str(request.get("source_key") or "")
149-    if source_key not in SOURCE_KEYS:
150-        raise ValueError("Datenquelle ist nicht vorhanden oder nicht für Ingestion freigegeben")
151-    period_from = str(request.get("period_from") or "")
152-    period_to = str(request.get("period_to") or "")
153-    start, end = _date(period_from, "Von"), _date(period_to, "Bis")
154-    if start > end:
155-        raise ValueError("Zeitraum: 'von' darf nicht nach 'bis' liegen")
156-    cutoff = str(request.get("data_cutoff") or _now().isoformat())
157-    cutoff = _instant(cutoff, "Data-Cutoff").isoformat()
158-    scope_kind = str(request.get("scope_kind") or "portfolio")
159-    account_id = str(request.get("account_id") or "") or None
160-    accounts = _validate_scope(conn, scope_kind, account_id)
161-    return accounts, period_from, period_to, cutoff
162-
163-
164-def _record_ref(source_key: str, raw_id: str) -> str:
165-    return _safe_ref("record", f"{source_key}:{raw_id}")
166-
167-
168-def _existing_lineage(conn: Connection, lineage_hash: str) -> tuple[str, str] | None:
169-    row = conn.execute(
170-        """SELECT target_type, target_id FROM portfolio_ingestion_items
171-           WHERE lineage_hash=? AND disposition IN ('new','versioned','unchanged') AND target_id IS NOT NULL
172-           ORDER BY created_at DESC LIMIT 1""",
173-        (lineage_hash,),
174-    ).fetchone()
175-    return (str(row["target_type"]), str(row["target_id"])) if row else None
176-
177-
178-def _valuation_snapshot_id(source_key: str, lineage_hash: str, version: int) -> str:
179-    return "valuation-" + _hash([source_key, lineage_hash, version])[:24]
180-
181-
182-def _valuation_disposition(
183-    conn: Connection,
184-    *,
185-    source_key: str,
186-    account_id: str,
187-    valuation_at: str,
188-    lineage_hash: str,
189-    planned_versions: dict[tuple[str, str], tuple[int, str | None]],
190-) -> tuple[str, str | None, int, str | None]:
191-    existing = _existing_lineage(conn, lineage_hash)
192-    if existing:
193-        return "unchanged", existing[1], 0, None
194-    key = (account_id, valuation_at[:10])
195-    planned = planned_versions.get(key)
196-    if planned is None:
197-        row = conn.execute(
198-            """SELECT snapshot_id,snapshot_version FROM portfolio_valuation_snapshots
199-               WHERE scope_kind='account' AND scope_id=? AND substr(valuation_at,1,10)=?
200-               ORDER BY snapshot_version DESC,captured_at DESC LIMIT 1""",
201-            key,
202-        ).fetchone()
203-        version = int(row["snapshot_version"]) + 1 if row else 1
204-        supersedes = str(row["snapshot_id"]) if row else None
205-    else:
206-        version, supersedes = planned
207-    snapshot_id = _valuation_snapshot_id(source_key, lineage_hash, version)
208-    planned_versions[key] = (version + 1, snapshot_id)
209-    return ("versioned" if supersedes else "new"), None, version, supersedes
210-
211-


Output:
Chunk ID: 640652
Wall time: 30.0015 seconds
Process running with session ID 38576
Original token count: 0
Output:


[P2] Include cash balance postings after official snapshot

When the PostFinance cash account has an official snapshot, later Vue equity actions record the cash leg in `cash_balances` using `cash_account_id` while the corresponding transaction remains on the depot account (see `confirm_equity_sell`/`confirm_equity_dividend`). This new replay only reads `transactions` for the trading-cash account, so post-snapshot sale proceeds or dividends booked through the existing flows are omitted from `get_cash_summary` and the cash overview remains stuck at the official snapshot value.

The patch misses cash movements recorded through existing manual equity workflows after an official PostFinance snapshot, causing incorrect cash totals for that supported scenario.