Implement fin-hub T24-T26: ingest, runway, coupling, RaaS packaging
Add CSV importers, runway calculator, budget alerts, cross-hub coupling emitters, finhub CLI, and raas-mvp-packaging docs with full test coverage.
This commit is contained in:
parent
b6993d4a05
commit
1abbbe85e4
27 changed files with 835 additions and 3 deletions
60
src/fin_hub/services/alerts.py
Normal file
60
src/fin_hub/services/alerts.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
"""Budget and runway alert evaluation."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fin_hub.services.runway import RunwayResult
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BudgetAlert:
|
||||
code: str
|
||||
severity: str
|
||||
summary: str
|
||||
detail: dict
|
||||
|
||||
def as_dict(self) -> dict:
|
||||
return {
|
||||
"code": self.code,
|
||||
"severity": self.severity,
|
||||
"summary": self.summary,
|
||||
"detail": self.detail,
|
||||
}
|
||||
|
||||
|
||||
def evaluate_budget_alerts(
|
||||
*,
|
||||
runway: RunwayResult,
|
||||
allocated: float | None = None,
|
||||
spent: float | None = None,
|
||||
) -> list[BudgetAlert]:
|
||||
alerts: list[BudgetAlert] = []
|
||||
if runway.below_threshold and runway.monthly_burn > 0:
|
||||
alerts.append(
|
||||
BudgetAlert(
|
||||
code="runway_below_threshold",
|
||||
severity="high",
|
||||
summary=(
|
||||
f"Projected runway {runway.months_remaining:.1f} months "
|
||||
f"is below threshold {runway.alert_threshold_months:.1f}"
|
||||
),
|
||||
detail=runway.as_dict(),
|
||||
)
|
||||
)
|
||||
if allocated is not None and spent is not None and allocated > 0:
|
||||
utilisation = spent / allocated
|
||||
if utilisation >= 0.8:
|
||||
alerts.append(
|
||||
BudgetAlert(
|
||||
code="budget_pressure",
|
||||
severity="medium" if utilisation < 1.0 else "high",
|
||||
summary=f"Budget utilisation at {utilisation * 100:.0f}%",
|
||||
detail={
|
||||
"allocated": allocated,
|
||||
"spent": spent,
|
||||
"utilisation": utilisation,
|
||||
},
|
||||
)
|
||||
)
|
||||
return alerts
|
||||
Loading…
Add table
Add a link
Reference in a new issue