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
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+24
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')),
],
),
]
+39 -1
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}"
+52
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 %}
+301
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
+7 -36
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>
+8 -2
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'),
+1719 -87
View File
File diff suppressed because it is too large Load Diff