- Engine: Add ppa_revenue_cr, mcp_revenue_cr, tariff, units to PnLRow - Engine: Split PPA vs MCP revenue in P&L computation - Web: Collapsible rows for PPA/MCP Revenue and Opex - Web: Highlighted rows (Total Revenue, EBITDA, EBIT, PBT, PAT) - Web: Units above Tariff in breakdown, bg-blue-50 highlight - Fix sticky column z-index for horizontal scroll - CLAUDE.md: Add project documentation Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
41 lines
1.2 KiB
Python
41 lines
1.2 KiB
Python
"""PPA revenue and commercial settlement computation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from remodel_engine.schemas.financial import CommercialConfig
|
|
|
|
|
|
def compute_annual_generation_mwh(
|
|
solar_ac_mwh_by_year: list[float],
|
|
wind_ac_mwh_by_year: list[float],
|
|
) -> list[float]:
|
|
"""Sum solar and wind generation for each year."""
|
|
n = max(len(solar_ac_mwh_by_year), len(wind_ac_mwh_by_year))
|
|
result: list[float] = []
|
|
for y in range(n):
|
|
s = solar_ac_mwh_by_year[y] if y < len(solar_ac_mwh_by_year) else 0.0
|
|
w = wind_ac_mwh_by_year[y] if y < len(wind_ac_mwh_by_year) else 0.0
|
|
result.append(s + w)
|
|
return result
|
|
|
|
|
|
def compute_receivables(
|
|
revenue_by_year: list[float],
|
|
config: CommercialConfig,
|
|
) -> list[float]:
|
|
"""Receivables = revenue * receivable_days / 365."""
|
|
return [
|
|
round(rev * config.receivable_days / 365.0, 4)
|
|
for rev in revenue_by_year
|
|
]
|
|
|
|
|
|
def compute_payables(
|
|
opex_by_year: list[float],
|
|
config: CommercialConfig,
|
|
) -> list[float]:
|
|
"""Payables = opex * payable_days / 365."""
|
|
return [
|
|
round(opex * config.payable_days / 365.0, 4)
|
|
for opex in opex_by_year
|
|
]
|