"""Credit-fund loan schedule: the eNAV 'HLD-LOANS' sheet must fold into holdings and NAV. Regression for the SATS Credit Fund case where the Portal showed $3.6M of securities while the fund held a $46.3M loan — because the loan lives on a separate schedule, not the HLD Holdings Report. See import_router._parse_loans. """ import io from datetime import date, datetime import openpyxl from ten31portal.routers.import_router import _parse_schedule_xlsx def _enav_with_loan() -> bytes: """Minimal eNAV: an HLD securities sheet plus an HLD-LOANS loan schedule.""" wb = openpyxl.Workbook() hld = wb.active hld.title = "HLD" hld["A1"] = datetime(2025, 12, 31) hld.append([None]) hld.append(["SECURITY NAME", "QUANTITY", "COST BASIS - BOOK", "MARKET VALUE (BOOK)"]) hld.append(["BTC", 18.74, 1_734_584.37, 1_639_942.63]) hld.append(["Fold Holdings, Inc. - Warrant 03/26/25", 3_702_360, 0, 0]) hld.append(["TOTAL - LONG", None, 1_734_584.37, 3_597_442.63]) loans = wb.create_sheet("HLD-LOANS") loans.append(["SATS CREDIT FUND LP"]) loans.append([None]) # Header + one loan row + a total row the parser must skip. loans.append([ "COUNTERPART", "SECURITY NAME", "ISSUER NAME", "TRADE DATE", "PRINCIPAL BALANCE", "TOTAL COST", "VALUE", "VALUE PLUS ACCRUED INTEREST REC / (PAY)", ]) loans.append([ "Fold Holdings, Inc.", "Fold Holdings, Inc. (Floating Rate)", "Fold Holdings, Inc.", datetime(2025, 3, 26), 46_279_500, 46_279_500, 46_279_500, 46_494_185.46, ]) loans.append(["TOTAL - LOAN", None, None, None, 46_279_500, 46_279_500, 46_279_500, 46_494_185.46]) out = io.BytesIO() wb.save(out) return out.getvalue() def test_loan_schedule_folds_into_holdings_and_nav(): name, as_of, holdings, positions, errors = _parse_schedule_xlsx(_enav_with_loan()) assert errors == [] assert as_of == date(2025, 12, 31) # The loan groups under its issuer, which the warrant already created: no duplicate holding. assert [h["company_name"] for h in holdings].count("Fold Holdings, Inc.") == 1 loan = next(p for p in positions if p["security_name"] == "Fold Holdings, Inc. (Floating Rate)") assert loan["company_name"] == "Fold Holdings, Inc." assert loan["value_cents"] == 46_494_185_46 # principal + accrued interest, in cents assert loan["cost_cents"] == 46_279_500_00 assert loan["investment_date"] == "2025-03-26" assert loan["shares"] is None # NAV is the sum of every position value: securities ($3.6M) + the loan ($46.5M). nav = sum(p["value_cents"] or 0 for p in positions) assert nav == 1_639_942_63 + 0 + 46_494_185_46 def test_no_loan_sheet_is_a_noop(): """A workbook with no HLD-LOANS sheet parses the securities exactly as before.""" wb = openpyxl.Workbook() hld = wb.active hld.title = "HLD" hld["A1"] = datetime(2025, 12, 31) hld.append([None]) hld.append(["SECURITY NAME", "QUANTITY", "COST BASIS - BOOK", "MARKET VALUE (BOOK)"]) hld.append(["Acme - Series A", 10, 100.0, 900.0]) out = io.BytesIO() wb.save(out) _, _, holdings, positions, errors = _parse_schedule_xlsx(out.getvalue()) assert errors == [] assert len(positions) == 1 assert positions[0]["value_cents"] == 900_00