- Added monitoring metrics for project creation success and error handling in `ProjectRepository`. - Implemented similar monitoring for scenario creation in `ScenarioRepository`. - Refactored `run_monte_carlo` function in `simulation.py` to include timing and success/error metrics. - Introduced new CSS styles for headers, alerts, and navigation buttons in `main.css` and `projects.css`. - Created a new JavaScript file for navigation logic to handle chevron buttons. - Updated HTML templates to include new navigation buttons and improved styling for buttons. - Added tests for reporting service and routes to ensure proper functionality and access control. - Removed unused imports and optimized existing test files for better clarity and performance.
150 lines
4.9 KiB
HTML
150 lines
4.9 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Scenario Distribution | CalMiner{% endblock %}
|
|
|
|
{% block content %}
|
|
{% include "partials/reports_header.html" %}
|
|
|
|
<section class="report-overview">
|
|
<div class="report-grid">
|
|
<article class="report-card">
|
|
<h2>Scenario Details</h2>
|
|
<dl class="definition-list">
|
|
<div>
|
|
<dt>Name</dt>
|
|
<dd>{{ scenario.name }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Project ID</dt>
|
|
<dd>{{ scenario.project_id }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Status</dt>
|
|
<dd>{{ scenario.status | title }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Currency</dt>
|
|
<dd>{{ scenario.currency or "—" }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Discount Rate</dt>
|
|
<dd>{{ metrics.discount_rate | percentage_display }}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Updated</dt>
|
|
<dd>{{ scenario.updated_at | format_datetime }}</dd>
|
|
</div>
|
|
</dl>
|
|
</article>
|
|
|
|
<article class="report-card">
|
|
<h2>Financial Totals</h2>
|
|
<ul class="metric-list">
|
|
<li>
|
|
<span>Inflows</span>
|
|
<strong>{{ summary.inflows | currency_display(scenario.currency) }}</strong>
|
|
</li>
|
|
<li>
|
|
<span>Outflows</span>
|
|
<strong>{{ summary.outflows | currency_display(scenario.currency) }}</strong>
|
|
</li>
|
|
<li>
|
|
<span>Net Cash Flow</span>
|
|
<strong>{{ summary.net | currency_display(scenario.currency) }}</strong>
|
|
</li>
|
|
</ul>
|
|
{% if summary.by_category %}
|
|
<h3>By Category</h3>
|
|
<ul class="metric-list compact">
|
|
{% for label, value in summary.by_category.items() %}
|
|
<li>
|
|
<span>{{ label | replace("_", " ") | title }}</span>
|
|
<strong>{{ value | currency_display(scenario.currency) }}</strong>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
</article>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="report-section">
|
|
<header class="section-header">
|
|
<h2>Deterministic Metrics</h2>
|
|
<p class="section-subtitle">Key financial indicators calculated from deterministic cash flows.</p>
|
|
</header>
|
|
<table class="metrics-table">
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row">NPV</th>
|
|
<td>{{ metrics.npv | currency_display(scenario.currency) }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">IRR</th>
|
|
<td>{{ metrics.irr | percentage_display }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row">Payback Period</th>
|
|
<td>{{ metrics.payback_period | period_display }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
{% if metrics.notes %}
|
|
<ul class="note-list">
|
|
{% for note in metrics.notes %}
|
|
<li>{{ note }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
</section>
|
|
|
|
<section class="report-section">
|
|
<header class="section-header">
|
|
<h2>Monte Carlo Distribution</h2>
|
|
<p class="section-subtitle">Simulation-driven distributions contextualize stochastic variability.</p>
|
|
</header>
|
|
{% if monte_carlo and monte_carlo.available %}
|
|
<div class="simulation-summary">
|
|
<p>Iterations: {{ monte_carlo.iterations }} · Percentiles: {{ percentiles | join(", ") }}</p>
|
|
<table class="metrics-table">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">Metric</th>
|
|
<th scope="col">Mean</th>
|
|
<th scope="col">P5</th>
|
|
<th scope="col">Median</th>
|
|
<th scope="col">P95</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for metric, summary in monte_carlo.metrics.items() %}
|
|
<tr>
|
|
<th scope="row">{{ metric | replace("_", " ") | title }}</th>
|
|
<td>{{ summary.mean | format_metric(metric, scenario.currency) }}</td>
|
|
<td>{{ summary.percentiles['5'] | format_metric(metric, scenario.currency) }}</td>
|
|
<td>{{ summary.percentiles['50'] | format_metric(metric, scenario.currency) }}</td>
|
|
<td>{{ summary.percentiles['95'] | format_metric(metric, scenario.currency) }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% if monte_carlo.notes %}
|
|
<ul class="note-list">
|
|
{% for note in monte_carlo.notes %}
|
|
<li>{{ note }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
</div>
|
|
{% else %}
|
|
<p class="muted">Monte Carlo output is unavailable for this scenario.</p>
|
|
{% if monte_carlo and monte_carlo.notes %}
|
|
<ul class="note-list">
|
|
{% for note in monte_carlo.notes %}
|
|
<li>{{ note }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
{% endif %}
|
|
</section>
|
|
{% endblock %}
|