ALmost done with Halbjahres Bilanz

This commit is contained in:
2026-02-12 15:58:29 +01:00
parent 567b9edc2d
commit 5424d25822
27 changed files with 3056 additions and 271 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,24 @@
# Generated by Django 5.1.5 on 2026-02-09 07:01
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sheets', '0012_tableconfig_rowcalculation'),
]
operations = [
migrations.CreateModel(
name='MonthlySummary',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('gesamtbestand_neu_lhe', models.DecimalField(blank=True, decimal_places=6, max_digits=18, null=True)),
('gasbestand_lhe', models.DecimalField(blank=True, decimal_places=6, max_digits=18, null=True)),
('verbraucherverlust_lhe', models.DecimalField(blank=True, decimal_places=6, max_digits=18, null=True)),
('sheet', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='summary', to='sheets.monthlysheet')),
],
),
]

View File

@@ -212,4 +212,42 @@ class SecondTableEntry(models.Model):
date_joined = models.DateField(auto_now_add=True)
def __str__(self):
return f"{self.client.name} - {self.date}"
return f"{self.client.name} - {self.date}"
class MonthlySummary(models.Model):
"""
Stores per-month summary values that we need in other months
or in the half-year overview.
"""
sheet = models.OneToOneField(
MonthlySheet,
on_delete=models.CASCADE,
related_name='summary',
)
# K44: Gesamtbestand neu (Lit. LHe) from Bottom Table 2
gesamtbestand_neu_lhe = models.DecimalField(
max_digits=18,
decimal_places=6,
null=True,
blank=True,
)
# Gasbestand (Lit. LHe) from Bottom Table 1
gasbestand_lhe = models.DecimalField(
max_digits=18,
decimal_places=6,
null=True,
blank=True,
)
# Verbraucherverluste (Lit. L-He) from overall summary
verbraucherverlust_lhe = models.DecimalField(
max_digits=18,
decimal_places=6,
null=True,
blank=True,
)
def __str__(self):
return f"Summary {self.sheet.year}-{self.sheet.month:02d}"

View File

@@ -4,6 +4,38 @@
<div class="container">
<!-- Title -->
<h1 class="page-title">Helium Output Yearly Summary</h1>
<form method="post" action="{% url 'set_halfyear_interval' %}" class="interval-form">
{% csrf_token %}
<h3>Global 6-Month Interval</h3>
<label>Year:</label>
<select name="year">
{% for y in available_years %}
<option value="{{ y }}" {% if y == interval_year %}selected{% endif %}>
{{ y }}
</option>
{% endfor %}
</select>
<label>Start Month:</label>
<select name="start_month">
<option value="1" {% if interval_start_month == 1 %}selected{% endif %}>01</option>
<option value="2" {% if interval_start_month == 2 %}selected{% endif %}>02</option>
<option value="3" {% if interval_start_month == 3 %}selected{% endif %}>03</option>
<option value="4" {% if interval_start_month == 4 %}selected{% endif %}>04</option>
<option value="5" {% if interval_start_month == 5 %}selected{% endif %}>05</option>
<option value="6" {% if interval_start_month == 6 %}selected{% endif %}>06</option>
<option value="7" {% if interval_start_month == 7 %}selected{% endif %}>07</option>
<option value="8" {% if interval_start_month == 8 %}selected{% endif %}>08</option>
<option value="9" {% if interval_start_month == 9 %}selected{% endif %}>09</option>
<option value="10" {% if interval_start_month == 10 %}selected{% endif %}>10</option>
<option value="11" {% if interval_start_month == 11 %}selected{% endif %}>11</option>
<option value="12" {% if interval_start_month == 12 %}selected{% endif %}>12</option>
</select>
<button type="submit">Apply Interval</button>
</form>
<!-- Year Filter -->
<div class="year-filter">
@@ -16,6 +48,8 @@
{% endfor %}
</select>
</div>
<!-- Annual Summary Table -->
<table class="summary-table">
@@ -48,6 +82,7 @@
<a href="/admin/" class="nav-button admin-button">Go to Admin Panel</a>
<a href="{% url 'betriebskosten_list' %}" class="nav-button">Betriebskosten</a>
<a href="{% url 'monthly_sheet' year=2024 month=1 %}">Monthly Sheets</a>
<a href="{% url 'halfyear_balance' %}">Halbjahres Bilanz</a>
</div>
</div>
@@ -136,5 +171,22 @@
.admin-button:hover {
background-color: #5a6268;
}
.interval-filter {
margin: 10px 0 25px 0;
text-align: left;
}
.interval-filter h3 {
margin-bottom: 8px;
}
.interval-filter label {
margin-right: 6px;
}
.interval-filter select {
margin-right: 12px;
padding: 4px 6px;
}
.interval-filter button {
padding: 6px 12px;
}
</style>
{% endblock %}

View File

@@ -0,0 +1,301 @@
{% extends "base.html" %}
{% block content %}
<div class="spreadsheet-container">
<style>
.spreadsheet-container {
padding: 20px;
}
.sheet-navigation {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 10px;
background-color: #f8f9fa;
border-radius: 5px;
}
.sheet-navigation h2 {
margin: 0;
font-size: 20px;
font-weight: bold;
}
.sheet-navigation a,
.sheet-navigation span {
text-decoration: none;
color: #007bff;
font-weight: bold;
}
.sheet-navigation .disabled-link {
color: #aaa;
cursor: default;
}
.indent {
padding-left: 18px;
font-weight: bold;
text-align: center;
width: 60px;
}
.top-tables {
display: flex;
gap: 20px;
align-items: flex-start;
}
.table-container {
flex: 1;
background-color: #ffffff;
border-radius: 5px;
padding: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.table-container h3 {
margin-top: 0;
margin-bottom: 10px;
font-size: 16px;
}
.sheet-table,
.spreadsheet-table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
.sheet-table th,
.sheet-table td,
.spreadsheet-table th,
.spreadsheet-table td {
border: 1px solid #dee2e6;
padding: 4px 6px;
}
.sheet-table th,
.spreadsheet-table th {
background-color: #f2f2f2;
font-weight: bold;
text-align: center;
}
.row-label {
background-color: #f9f9f9;
font-weight: bold;
white-space: nowrap;
}
.number-cell {
text-align: right;
white-space: nowrap;
}
.sheet-table tbody tr:nth-child(even),
.spreadsheet-table tbody tr:nth-child(even) {
background-color: #fcfcfc;
}
.sheet-table tbody tr:hover,
.spreadsheet-table tbody tr:hover {
background-color: #f1f3f5;
}
.summary-row {
font-weight: bold;
background-color: #e8f4f8;
}
</style>
<div class="sheet-navigation">
<a href="{% url 'clients_list' %}">&larr; Helium Output Übersicht</a>
<h2>
{% with first=window.0 last=window|last %}
Halbjahres-Bilanz ({{ first.1 }}/{{ first.0 }} {{ last.1 }}/{{ last.0 }})
{% endwith %}
</h2>
{% with first=window.0 %}
<a href="{% url 'monthly_sheet' first.0 first.1 %}">Monatsblätter</a>
{% endwith %}
</div>
<div class="top-tables">
<!-- LEFT TABLE (Top Left AG Vogel / AG Halfm / IKP) -->
<div class="table-container">
<h3>Top Left Halbjahresbilanz</h3>
<table class="sheet-table spreadsheet-table">
<thead>
<tr>
<th>Bezeichnung</th>
{% for c in clients_left %}
<th>{{ c }}</th>
{% endfor %}
<th>&Sigma;</th>
</tr>
</thead>
<tbody>
{% for row in rows_left %}
<tr>
<td>{{ row.label }}</td>
{% for v in row.values %}
<td class="number-cell">
{% if row.is_percent and v is not None %}
{{ v|floatformat:4 }}
{% elif v is not None %}
{{ v|floatformat:2 }}
{% endif %}
</td>
{% endfor %}
<td class="number-cell">
{% if row.is_percent and row.total %}
{{ row.total|floatformat:4 }}
{% elif row.total is not None %}
{{ row.total|floatformat:2 }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- RIGHT TABLE (Top Right Dr. Fohrer / AG Buntk. / etc.) -->
<div class="table-container">
<h3>Top Right Halbjahresbilanz</h3>
<table class="sheet-table spreadsheet-table">
<thead>
<tr>
<th>Bezeichnung</th>
{% for c in clients_right %}
<th>{{ c }}</th>
{% endfor %}
<th>&Sigma;</th>
</tr>
</thead>
<tbody>
{% for row in rows_right %}
<tr>
<td>{{ row.label }}</td>
{% for v in row.values %}
<td class="number-cell">
{% if row.is_text_row %}
{{ v }}
{% elif row.is_percent and v is not None %}
{{ v|floatformat:4 }}
{% elif v is not None %}
{{ v|floatformat:2 }}
{% endif %}
</td>
{% endfor %}
<td class="number-cell">
{% if row.is_text_row %}
{{ row.total }}
{% elif row.is_percent and row.total %}
{{ row.total|floatformat:4 }}
{% elif row.total is not None %}
{{ row.total|floatformat:2 }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="table-container">
<h3>Summe</h3>
<table class="sheet-table spreadsheet-table">
<thead>
<tr>
<th>Bezeichnung</th>
<th>Σ</th>
<th>Licht-wiese</th>
<th>Chemie</th>
<th>MaWi</th>
<th>M3</th>
</tr>
</thead>
<tbody>
{% for r in rows_sum %}
<tr>
<td>{{ r.label }}</td>
<td class="sum-col">
{% if r.is_percent %}
{{ r.total|floatformat:2 }}%
{% else %}
{{ r.total|floatformat:2 }}
{% endif %}
</td>
<td class="sum-col">
{% if r.is_percent %}
{{ r.lichtwiese|floatformat:2 }}%
{% else %}
{{ r.lichtwiese|floatformat:2 }}
{% endif %}
</td>
<td class="sum-col">
{% if r.is_percent %}
{{ r.chemie|floatformat:2 }}%
{% else %}
{{ r.chemie|floatformat:2 }}
{% endif %}
</td>
<td class="sum-col">
{% if r.is_percent %}
{{ r.mawi|floatformat:2 }}%
{% else %}
{{ r.mawi|floatformat:2 }}
{% endif %}
</td>
<td class="sum-col">
{% if r.is_percent %}
{{ r.m3|floatformat:2 }}%
{% else %}
{{ r.m3|floatformat:2 }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="table-container" style="margin-top: 20px;">
<h3>Bottom Table 1 Bilanz (read-only)</h3>
<table class="sheet-table spreadsheet-table">
<thead>
<tr>
<th>Gasspeicher</th>
<th>Volumen</th>
<th>bar</th>
<th>korrigiert</th>
<th>Nm³</th>
<th>Lit. LHe</th>
</tr>
</thead>
<tbody>
{% for r in bottom1_rows %}
<tr class="{% if r.is_total %}summary-row{% endif %}">
<td class="row-label {% if r.indent %}indent{% endif %}">{{ r.label }}</td>
<td class="number-cell">{{ r.volume|floatformat:1 }}</td>
<td class="number-cell">{{ r.bar|floatformat:0 }}</td>
<td class="number-cell">{{ r.korr|floatformat:1 }}</td>
<td class="number-cell">{{ r.nm3|floatformat:0 }}</td>
<td class="number-cell">{{ r.lhe|floatformat:0 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div> {# closes .spreadsheet-container #}
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@@ -291,42 +291,16 @@
<!-- 6-Month overview card (OUTSIDE any <a>) -->
<div class="overview-card">
<div class="overview-title">Helium Input 6 Month Overview</div>
<form method="get" class="overview-header">
<div>
<label for="overview-year">Year</label><br>
<select name="overview_year" id="overview-year">
{% for y in available_years %}
<option value="{{ y }}"
{% if overview and overview.year == y %}selected{% endif %}>
{{ y }}
</option>
{% endfor %}
</select>
</div>
<div>
<label for="overview-start-month">Start month</label><br>
<select name="overview_start_month" id="overview-start-month">
{% for m, label in month_choices %}
<option value="{{ m }}"
{% if overview and overview.start_month == m %}selected{% endif %}>
{{ m }} - {{ label }}
</option>
{% endfor %}
</select>
</div>
<div>
<button type="submit">Show overview</button>
</div>
</form>
<div class="overview-title">Helium Input 6 Month Overview</div>
{% if overview %}
<div class="overview-subtitle">
Period:
<strong>{{ overview.start_month }}{{ overview.end_month }} / {{ overview.year }}</strong>
<strong>
{{ overview.start_month }}/{{ overview.start_year }}
{{ overview.end_month }}/{{ overview.end_year }}
</strong>
(selected on the main page)
</div>
<table class="overview-table">
@@ -361,11 +335,8 @@
</tr>
</tbody>
</table>
{% else %}
<div class="overview-subtitle">
No data yet choose a year and start month and click “Show overview”.
</div>
{% endif %}
</div>

View File

@@ -1,6 +1,6 @@
from django.urls import path
from .views import DebugTopRightView
from .views import SaveCellsView
from .views import SaveCellsView , SaveMonthSummaryView, halfyear_settings,MonthlySheetView, monthly_sheet_root,set_halfyear_interval
from . import views
urlpatterns = [
@@ -17,9 +17,15 @@ urlpatterns = [
path('quick-debug/', views.QuickDebugView.as_view(), name='quick_debug'),
path('test-formula/', views.TestFormulaView.as_view(), name='test_formula'),
path('simple-debug/', views.SimpleDebugView.as_view(), name='simple_debug'),
path('sheet/', monthly_sheet_root, name='monthly_sheet_root'),
path('set-halfyear-interval/', set_halfyear_interval, name='set_halfyear_interval'),
path('halfyear-bilanz/', views.halfyear_balance_view, name='halfyear_balance'),
path('sheet/<int:year>/<int:month>/', MonthlySheetView.as_view(), name='monthly_sheet'),
path('settings/halfyear/', halfyear_settings, name='halfyear_settings'),
path('sheet/<int:year>/<int:month>/', views.MonthlySheetView.as_view(), name='monthly_sheet'),
path('summary/<int:year>/<int:start_month>/', views.SummarySheetView.as_view(), name='summary_sheet'),
path("save-cells/", SaveCellsView.as_view(), name="save_cells"),
path("save-cells/", SaveCellsView.as_view(), name="save_cells"), path("save-cells/", SaveCellsView.as_view(), name="save_cells"),path('save-month-summary/', SaveMonthSummaryView.as_view(), name='save_month_summary'),
path('save-month-summary/', SaveMonthSummaryView.as_view(), name='save_month_summary'),
path('calculate/', views.CalculateView.as_view(), name='calculate'),
path('debug-calculation/', views.DebugCalculationView.as_view(), name='debug_calculation'),
path('debug-top-right/', DebugTopRightView.as_view(), name='debug_top_right'),

File diff suppressed because it is too large Load Diff