# /// script # requires-python = ">=3.12" # /// """Trace net income, OCI, comprehensive income, AOCI, and ending equity. Run the downloaded file directly with uv: uv run granite-harbor-income-oci-equity-bridge.py Try another OCI gain or reclassification adjustment: uv run granite-harbor-income-oci-equity-bridge.py \ --oci-gain 1800 --reclassification-adjustment -600 Amounts are USD thousands. Positive values increase income or equity; negative values reduce them. The accounting classifications and net-of-tax amounts are stipulated. This lab verifies the bridge after those judgments. """ from __future__ import annotations import argparse from dataclasses import dataclass @dataclass(frozen=True) class ReportingInputs: """Named inputs for one controlled reporting period.""" continuing_revenues: float = 120_000.0 continuing_expenses: float = 100_000.0 discontinued_operation: float = -3_000.0 oci_gain: float = 1_400.0 reclassification_adjustment: float = -400.0 opening_contributed_capital: float = 30_000.0 opening_retained_earnings: float = 28_000.0 opening_aoci: float = 2_000.0 owner_distributions: float = 4_000.0 ending_assets: float = 120_000.0 ending_liabilities: float = 46_000.0 @dataclass(frozen=True) class ReportingBridge: """Recomputed performance and equity outputs.""" income_from_continuing_operations: float net_income: float other_comprehensive_income: float comprehensive_income: float ending_retained_earnings: float ending_aoci: float ending_equity: float balance_sheet_equity: float def calculate_bridge(inputs: ReportingInputs) -> ReportingBridge: """Apply the visible statement and equity relationships.""" income_from_continuing_operations = inputs.continuing_revenues - inputs.continuing_expenses net_income = income_from_continuing_operations + inputs.discontinued_operation other_comprehensive_income = inputs.oci_gain + inputs.reclassification_adjustment comprehensive_income = net_income + other_comprehensive_income ending_retained_earnings = ( inputs.opening_retained_earnings + net_income - inputs.owner_distributions ) ending_aoci = inputs.opening_aoci + other_comprehensive_income ending_equity = inputs.opening_contributed_capital + ending_retained_earnings + ending_aoci balance_sheet_equity = inputs.ending_assets - inputs.ending_liabilities return ReportingBridge( income_from_continuing_operations=income_from_continuing_operations, net_income=net_income, other_comprehensive_income=other_comprehensive_income, comprehensive_income=comprehensive_income, ending_retained_earnings=ending_retained_earnings, ending_aoci=ending_aoci, ending_equity=ending_equity, balance_sheet_equity=balance_sheet_equity, ) def verify_bridge(inputs: ReportingInputs, bridge: ReportingBridge) -> None: """Fail if a cross-statement relationship is broken.""" opening_equity = ( inputs.opening_contributed_capital + inputs.opening_retained_earnings + inputs.opening_aoci ) expected_ending_equity = ( opening_equity + bridge.comprehensive_income - inputs.owner_distributions ) if abs(bridge.ending_equity - expected_ending_equity) > 1e-9: raise AssertionError("the component equity rollforward does not reconcile") if abs(bridge.ending_equity - bridge.balance_sheet_equity) > 1e-9: raise AssertionError("ending equity does not tie to assets minus liabilities") if ( inputs.oci_gain == 1_400 and inputs.reclassification_adjustment == -400 and bridge.comprehensive_income != 18_000 ): raise AssertionError("the published comprehensive-income seed must be 18,000") def money(amount: float) -> str: """Format USD-thousand amounts with commas and accounting parentheses.""" absolute = f"{abs(amount):,.0f}" return f"({absolute})" if amount < 0 else absolute def show_bridge(inputs: ReportingInputs, bridge: ReportingBridge) -> None: """Print the same sequence a learner sees in the workbook.""" rows = [ ("Income from continuing operations", bridge.income_from_continuing_operations), ("Discontinued operation, net of tax", inputs.discontinued_operation), ("Net income", bridge.net_income), ("OCI gain, net of tax", inputs.oci_gain), ("Reclassification adjustment, net of tax", inputs.reclassification_adjustment), ("Other comprehensive income", bridge.other_comprehensive_income), ("Comprehensive income", bridge.comprehensive_income), ] print("Granite Harbor performance bridge — USD thousands") print("-" * 66) for label, amount in rows: print(f"{label:<50}{money(amount):>16}") print("\nEquity rollforward — USD thousands") print("-" * 66) print(f"{'Ending Retained Earnings':<50}{money(bridge.ending_retained_earnings):>16}") print(f"{'Ending AOCI':<50}{money(bridge.ending_aoci):>16}") print(f"{'Ending total equity':<50}{money(bridge.ending_equity):>16}") print(f"{'Assets minus liabilities':<50}{money(bridge.balance_sheet_equity):>16}") print( "\nBoundary: this script verifies arithmetic articulation. It does not " "decide discontinued-operation status, OCI eligibility, tax, or disclosure." ) def arguments() -> argparse.Namespace: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--oci-gain", type=float, default=1_400.0) parser.add_argument("--reclassification-adjustment", type=float, default=-400.0) return parser.parse_args() def main() -> int: args = arguments() # The command-line variant isolates the OCI change. With liabilities and all # other activities held constant, the same change must reach ending assets # for the supplied balance sheet to remain articulated. variant_oci = args.oci_gain + args.reclassification_adjustment inputs = ReportingInputs( oci_gain=args.oci_gain, reclassification_adjustment=args.reclassification_adjustment, ending_assets=120_000.0 + (variant_oci - 1_000.0), ) bridge = calculate_bridge(inputs) verify_bridge(inputs, bridge) show_bridge(inputs, bridge) return 0 if __name__ == "__main__": raise SystemExit(main())