ALmost done with Halbjahres Bilanz
This commit is contained in:
BIN
db.sqlite3
BIN
db.sqlite3
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.
BIN
sheets/__pycache__/signals.cpython-313.pyc
Normal file
BIN
sheets/__pycache__/signals.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
24
sheets/migrations/0013_monthlysummary.py
Normal file
24
sheets/migrations/0013_monthlysummary.py
Normal 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')),
|
||||
],
|
||||
),
|
||||
]
|
||||
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.
@@ -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}"
|
||||
@@ -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
sheets/templates/halfyear_balance.html
Normal file
301
sheets/templates/halfyear_balance.html
Normal 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' %}">← 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>Σ</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>Σ</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
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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'),
|
||||
|
||||
1806
sheets/views.py
1806
sheets/views.py
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user