Add history window controls and expand taxonomy pack support

- add 3Y/5Y/10Y financial history filtering and reorganize normalization details UI
- add new fiscal taxonomy surface/income bridge/KPI packs and update Rust taxonomy loading
- auto-detect Homebrew SQLite for native `sqlite-vec` in local dev/e2e with docs and env guidance
This commit is contained in:
2026-03-18 23:40:28 -04:00
parent f8426c4dde
commit 17de3dd72d
102 changed files with 14978 additions and 1316 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1762,4 +1762,130 @@ mod tests {
Some(-15.0)
);
}
#[test]
fn maps_software_balance_overrides() {
let mut rows = empty_map();
rows.get_mut("balance").unwrap().extend([
row(
"software-costs",
"us-gaap:CapitalizedSoftwareCosts",
"balance",
55.0,
),
row(
"software-defrev",
"us-gaap:DeferredRevenueSoftware",
"balance",
21.0,
),
]);
let model = build_compact_surface_model(
&[period("p1")],
&rows,
"us-gaap",
FiscalPack::Software,
vec![],
)
.expect("compact model should build");
let balance_rows = model.surface_rows.get("balance").unwrap();
let software_costs = balance_rows
.iter()
.find(|row| row.key == "capitalized_software_costs")
.unwrap();
let deferred_revenue = balance_rows
.iter()
.find(|row| row.key == "deferred_revenue")
.unwrap();
assert_eq!(
software_costs.values.get("p1").copied().flatten(),
Some(55.0)
);
assert_eq!(
deferred_revenue.values.get("p1").copied().flatten(),
Some(21.0)
);
}
#[test]
fn maps_broadcaster_programming_library_balance_row() {
let mut rows = empty_map();
rows.get_mut("balance").unwrap().push(row(
"broadcast-library",
"us-gaap:ProgrammingLibrary",
"balance",
88.0,
));
let model = build_compact_surface_model(
&[period("p1")],
&rows,
"us-gaap",
FiscalPack::EntertainmentBroadcasters,
vec![],
)
.expect("compact model should build");
let programming_library = model
.surface_rows
.get("balance")
.unwrap()
.iter()
.find(|row| row.key == "programming_library")
.unwrap();
assert_eq!(
programming_library.values.get("p1").copied().flatten(),
Some(88.0)
);
}
#[test]
fn maps_defined_benefit_plan_balance_rows() {
let mut rows = empty_map();
rows.get_mut("balance").unwrap().extend([
row(
"plan-assets",
"us-gaap:FairValueOfPlanAssets",
"balance",
140.0,
),
row(
"pbo",
"us-gaap:ProjectedBenefitObligation",
"balance",
125.0,
),
]);
let model = build_compact_surface_model(
&[period("p1")],
&rows,
"us-gaap",
FiscalPack::PlanDefinedBenefit,
vec![],
)
.expect("compact model should build");
let plan_assets = model
.surface_rows
.get("balance")
.unwrap()
.iter()
.find(|row| row.key == "plan_assets")
.unwrap();
let obligations = model
.surface_rows
.get("balance")
.unwrap()
.iter()
.find(|row| row.key == "benefit_obligations")
.unwrap();
assert_eq!(plan_assets.values.get("p1").copied().flatten(), Some(140.0));
assert_eq!(obligations.values.get("p1").copied().flatten(), Some(125.0));
}
}

View File

@@ -440,4 +440,58 @@ mod tests {
let core_bridge = load_income_bridge(FiscalPack::Core).expect("core bridge should load");
assert_eq!(core_bridge.pack, "core");
}
#[test]
fn loads_all_non_core_pack_assets() {
let packs = [
FiscalPack::BankLender,
FiscalPack::Insurance,
FiscalPack::ReitRealEstate,
FiscalPack::BrokerAssetManager,
FiscalPack::Agriculture,
FiscalPack::ContractorsConstruction,
FiscalPack::ContractorsFederalGovernment,
FiscalPack::DevelopmentStage,
FiscalPack::EntertainmentBroadcasters,
FiscalPack::EntertainmentCableTelevision,
FiscalPack::EntertainmentCasinos,
FiscalPack::EntertainmentFilms,
FiscalPack::EntertainmentMusic,
FiscalPack::ExtractiveMining,
FiscalPack::MortgageBanking,
FiscalPack::TitlePlant,
FiscalPack::Franchisors,
FiscalPack::NotForProfit,
FiscalPack::PlanDefinedBenefit,
FiscalPack::PlanDefinedContribution,
FiscalPack::PlanHealthWelfare,
FiscalPack::RealEstateGeneral,
FiscalPack::RealEstateCommonInterest,
FiscalPack::RealEstateRetailLand,
FiscalPack::RealEstateTimeSharing,
FiscalPack::Software,
FiscalPack::Steamship,
];
for pack in packs {
let surface_pack = load_surface_pack(pack)
.unwrap_or_else(|error| panic!("surface pack {} failed: {error}", pack.as_str()));
assert_eq!(surface_pack.pack, pack.as_str());
assert!(
!surface_pack.surfaces.is_empty(),
"{} should define surfaces",
pack.as_str()
);
let bridge = load_income_bridge(pack)
.unwrap_or_else(|error| panic!("income bridge {} failed: {error}", pack.as_str()));
assert_eq!(bridge.pack, pack.as_str());
assert!(bridge.rows.contains_key("revenue"));
assert!(bridge.rows.contains_key("net_income"));
let kpi_pack = load_kpi_pack(pack)
.unwrap_or_else(|error| panic!("kpi pack {} failed: {error}", pack.as_str()));
assert_eq!(kpi_pack.pack, pack.as_str());
}
}
}

View File

@@ -1800,6 +1800,113 @@ mod tests {
assert_eq!(revenue.resolution_method.as_deref(), Some("direct"));
}
#[test]
fn derives_software_gross_profit_from_revenue_minus_cost_of_software_revenue() {
let rows = empty_rows();
let mut model = empty_model();
model.surface_rows.get_mut("income").unwrap().extend([
surface_row("revenue", 150.0),
surface_row("cost_of_software_revenue", 45.0),
]);
apply_universal_income_rows(
&[period("p1")],
&rows,
&[],
"us-gaap",
FiscalPack::Software,
&mut model,
)
.expect("software universal income rows should build");
let gross_profit = model
.surface_rows
.get("income")
.unwrap()
.iter()
.find(|row| row.key == "gross_profit")
.unwrap();
assert_eq!(
gross_profit.values.get("p1").copied().flatten(),
Some(105.0)
);
assert_eq!(
gross_profit.resolution_method.as_deref(),
Some("formula_derived")
);
}
#[test]
fn derives_development_stage_sga_from_general_and_administrative() {
let rows = empty_rows();
let mut model = empty_model();
model
.surface_rows
.get_mut("income")
.unwrap()
.push(surface_row("general_and_administrative", 22.0));
apply_universal_income_rows(
&[period("p1")],
&rows,
&[],
"us-gaap",
FiscalPack::DevelopmentStage,
&mut model,
)
.expect("development stage universal income rows should build");
let sga = model
.surface_rows
.get("income")
.unwrap()
.iter()
.find(|row| row.key == "selling_general_and_administrative")
.unwrap();
assert_eq!(sga.values.get("p1").copied().flatten(), Some(22.0));
assert_eq!(sga.resolution_method.as_deref(), Some("formula_derived"));
}
#[test]
fn emits_not_meaningful_not_for_profit_net_income_row() {
let rows = empty_rows();
let mut model = empty_model();
model.surface_rows.get_mut("income").unwrap().extend([
surface_row("contribution_revenue", 120.0),
surface_row("administrative_expense", 40.0),
surface_row("change_in_net_assets", 80.0),
]);
apply_universal_income_rows(
&[period("p1")],
&rows,
&[],
"us-gaap",
FiscalPack::NotForProfit,
&mut model,
)
.expect("not-for-profit universal income rows should build");
let net_income = model
.surface_rows
.get("income")
.unwrap()
.iter()
.find(|row| row.key == "net_income")
.unwrap();
assert_eq!(net_income.values.get("p1").copied().flatten(), None);
assert_eq!(
net_income.resolution_method.as_deref(),
Some("not_meaningful")
);
assert!(net_income
.warning_codes
.contains(&"net_income_not_meaningful_not_for_profit".to_string()));
}
#[test]
fn derives_income_tax_expense_from_pretax_income_minus_net_income() {
let mut rows = empty_rows();