This commit is contained in:
2026-04-13 13:41:28 +02:00
parent e1da4fa041
commit cfbb5c2fa2
7 changed files with 465 additions and 403 deletions
+175 -62
View File
@@ -13,8 +13,37 @@ from django.db.models import Sum
from django.db.models.functions import Coalesce
from django.db.models import DecimalField, Value
HALFYEAR_CLIENTS = ["AG Vogel", "AG Halfm", "IKP"]
TR_RUECKF_FLUESSIG_ROW = 2 # confirmed by your March value 172.840560
TR_RUECKF_FLUESSIG_ROW = 2
TR_BESTAND_KANNEN_ROW = 5
GASBESTAND_ROW_INDEX = 9
GASBESTAND_COL_NM3 = 3
# In top_left / top_right, "Bestand in Kannen-1 (Lit. L-He)" is row_index 5
BESTAND_KANNEN_ROW_INDEX = 5
HALFYEAR_RIGHT_CLIENTS = [
"Dr. Fohrer",
"AG Buntk.",
"AG Alff",
"AG Gutfl.",
"M3 Thiele",
"M3 Buntkowsky",
"M3 Gutfleisch",
"Merck"
]
BOTTOM1_COL_VOLUME = 0
BOTTOM1_COL_BAR = 1
BOTTOM1_COL_KORR = 2
BOTTOM1_COL_NM3 = 3
BOTTOM1_COL_LHE = 4
BOTTOM2_ROW_ANLAGE = 0
BOTTOM2_COL_G39 = 0 # "Gefäss 2,5" (cell id shows column_index=0)
BOTTOM2_COL_I39 = 1 # "Gefäss 1,0" (cell id shows column_index=1)
BOTTOM2_ROW_INPUTS = {
"g39": (0, 0), # row_index=0, column_index=0 (your G39)
"i39": (0, 1), # row_index=0, column_index=1 (your I39)
}
FACTOR_NM3_TO_LHE = Decimal("0.75")
RIGHT_CLIENT_INDEX = {name: idx for idx, name in enumerate(HALFYEAR_RIGHT_CLIENTS)}
def get_top_right_value(sheet, client_name: str, row_index: int) -> Decimal:
"""
Read a numeric value from the top_right table of a MonthlySheet for
@@ -128,34 +157,7 @@ def pick_sheet_by_gasbestand(window, sheets_by_ym, prev_sheet):
return sheet
return prev_sheet
# NEW: clients for the top-right half-year table
GASBESTAND_ROW_INDEX = 9 # <-- adjust if your bottom_1 has a different row index
GASBESTAND_COL_NM3 = 3 # <-- adjust to the column index for Nm³ in bottom_1
# In top_left / top_right, "Bestand in Kannen-1 (Lit. L-He)" is row_index 5
BESTAND_KANNEN_ROW_INDEX = 5
HALFYEAR_RIGHT_CLIENTS = [
"Dr. Fohrer",
"AG Buntk.",
"AG Alff",
"AG Gutfl.",
"M3 Thiele",
"M3 Buntkowsky",
"M3 Gutfleisch",
]
BOTTOM1_COL_VOLUME = 0
BOTTOM1_COL_BAR = 1
BOTTOM1_COL_KORR = 2
BOTTOM1_COL_NM3 = 3
BOTTOM1_COL_LHE = 4
BOTTOM2_ROW_ANLAGE = 0
BOTTOM2_COL_G39 = 0 # "Gefäss 2,5" (cell id shows column_index=0)
BOTTOM2_COL_I39 = 1 # "Gefäss 1,0" (cell id shows column_index=1)
BOTTOM2_ROW_INPUTS = {
"g39": (0, 0), # row_index=0, column_index=0 (your G39)
"i39": (0, 1), # row_index=0, column_index=1 (your I39)
}
FACTOR_NM3_TO_LHE = Decimal("0.75")
RIGHT_CLIENT_INDEX = {name: idx for idx, name in enumerate(HALFYEAR_RIGHT_CLIENTS)}
def build_halfyear_window(interval_year: int, start_month: int):
"""
@@ -171,7 +173,53 @@ def build_halfyear_window(interval_year: int, start_month: int):
return window
# Import ONLY models + pure helpers here
from sheets.models import MonthlySheet, Cell, Client, SecondTableEntry, BetriebskostenSummary
def sum_right_row_without_duplicates(label: str, clients_right: list[str], values: list):
"""
For specific rows, clients are logically merged, so we must only count one copy.
"""
# rows where the PAIRS are merged:
# - Bestand in Kannen-1
# - Summe Bestand
# - Best. in Kannen Vormonat
merged_pair_labels = {
"Bestand in Kannen-1 (Lit. L-He)",
"Summe Bestand (Lit. L-He)",
"Best. in Kannen Vormonat (Lit. L-He)",
"Verbraucherverluste (Liter L-He)",
# ✅ Sammel is also duplicated for the merged PAIRS (Fohrer+Buntk, Alff+Gutfl)
"Sammelrückführungen (Lit. L-He)",
"Sammelrückführung (Lit. L-He)", # safety (singular)
}
merged_m3_labels = {
# ✅ Sammel is duplicated for the merged M3 triple
"Sammelrückführungen (Lit. L-He)",
"Sammelrückführung (Lit. L-He)", # safety (singular)
}
skip_indices = set()
# skip second column of each merged PAIR
if label in merged_pair_labels:
for right_name in ("AG Buntk.", "AG Gutfl."):
if right_name in clients_right:
skip_indices.add(clients_right.index(right_name))
# skip 2nd+3rd of the merged TRIPLE
if label in merged_m3_labels:
for name in ("M3 Buntkowsky", "M3 Gutfleisch"):
if name in clients_right:
skip_indices.add(clients_right.index(name))
total = Decimal("0")
for i, v in enumerate(values):
if i in skip_indices:
continue
if v in (None, ""):
continue
total += Decimal(str(v).replace(",", "."))
return total
def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[str, Any]:
"""
Returns a context dict with the SAME keys your current halfyear_balance.html expects.
@@ -227,8 +275,8 @@ def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[st
# ----------------------------
chosen_sheet_bottom1 = pick_sheet_by_gasbestand(window, sheets_by_ym, prev_sheet)
# IMPORTANT: define which bottom_1 row_index corresponds to Excel rows 27..35
# If your bottom_1 starts at Excel row 27 => row_index 0 == Excel 27
# define which bottom_1 row_index corresponds to Excel rows 27..35
# If bottom_1 starts at Excel row 27 => row_index 0 == Excel 27
# then row_index = excel_row - 27
BOTTOM1_EXCEL_START_ROW = 27
@@ -671,6 +719,20 @@ def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[st
right_data["M3 Gutfleisch"]['sammel'] = group3_total
def safe_div(a: Decimal, b: Decimal) -> Decimal:
return (a / b) if b != 0 else Decimal("0")
# Merck: Sammelrückführung = total helium input (ExcelEntry.lhe_ges) over the 6-month window
merck_sammel_total = Decimal("0")
for (y, m) in window:
qs = ExcelEntry.objects.filter(
client__name="Merck",
date__year=y,
date__month=m,
).aggregate(
total=Coalesce(Sum("lhe_ges"), Value(0, output_field=DecimalField()))
)
merck_sammel_total += Decimal(str(qs["total"]))
right_data["Merck"]["sammel"] = merck_sammel_total
# --- Rückführung flüssig (Lit. L-He) for Halbjahres-Bilanz top-right ---
# Uses your exact formulas.
@@ -741,6 +803,9 @@ def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[st
right_data["M3 Thiele"]["bestand_kannen"] = pick_bestand_top_right("M3 Thiele")
right_data["M3 Buntkowsky"]["bestand_kannen"] = pick_bestand_top_right("M3 Buntkowsky")
right_data["M3 Gutfleisch"]["bestand_kannen"] = pick_bestand_top_right("M3 Gutfleisch")
# Merck should stay empty in Bestand in Kannen-1
right_data["Merck"]["bestand_kannen"] = None
right_data["Merck"]["best_kannen_vormonat"] = None
# Summe Bestand = same as previous row
for cname in RIGHT_CLIENTS:
@@ -807,9 +872,23 @@ def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[st
b11 = right_data[cname]['summe_bestand']
# Excel: P13+P12-P11 etc.
right_data[cname]['rueckf_soll'] = b13 + b12 - b11
# Merck: only selected rows should have values in Top Right Halbjahresbilanz
right_data["Merck"]["stand_prev_share"] = None
right_data["Merck"]["rueckf_fluessig"] = None
right_data["Merck"]["sonder"] = None
right_data["Merck"]["bestand_kannen"] = None
right_data["Merck"]["summe_bestand"] = None
right_data["Merck"]["best_kannen_vormonat"] = None
right_data["Merck"]["rueckf_soll"] = None
right_data["Merck"]["verluste"] = None
right_data["Merck"]["fuellungen_warm"] = None
right_data["Merck"]["kaltgas_rueckgabe"] = None
# --- Verluste (Soll-Rückf.) (Lit. L-He) = B14 - B6 - B7 ---
for cname in RIGHT_CLIENTS:
if cname == "Merck":
right_data[cname]['verluste'] = None
continue
b14 = right_data[cname]['rueckf_soll']
b6 = right_data[cname]['rueckf_fluessig']
b7 = right_data[cname]['sonder']
@@ -829,17 +908,22 @@ def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[st
b13 = right_data[cname]['bezug']
right_data[cname]['kaltgas_rueckgabe'] = b13 * factor
# --- Verbraucherverluste (Liter L-He) = Verluste - Kaltgas Rückgabe ---
# --- Verbraucherverluste (Liter L-He) ---
for cname in RIGHT_CLIENTS:
b15 = right_data[cname]['verluste']
b17 = right_data[cname]['kaltgas_rueckgabe']
right_data[cname]['verbraucherverluste'] = b15 - b17
if cname == "Merck":
bezug = right_data[cname].get("bezug") or Decimal("0")
sammel = right_data[cname].get("sammel") or Decimal("0")
right_data[cname]["verbraucherverluste"] = bezug - sammel
else:
b15 = right_data[cname]['verluste']
b17 = right_data[cname]['kaltgas_rueckgabe']
right_data[cname]['verbraucherverluste'] = b15 - b17
# --- % = Verbraucherverluste / Bezug ---
for cname in RIGHT_CLIENTS:
bezug = right_data[cname]['bezug']
verb = right_data[cname]['verbraucherverluste']
if bezug != 0:
bezug = right_data[cname].get('bezug') or Decimal("0")
verb = right_data[cname].get('verbraucherverluste')
if bezug != 0 and verb is not None:
right_data[cname]['percent'] = verb / bezug
else:
right_data[cname]['percent'] = None
@@ -910,50 +994,78 @@ def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[st
def safe_pct(verb, bez):
return (verb / bez) if bez != 0 else None
def sum_right_key(label_for_merge: str, clients: list[str], key: str) -> Decimal:
vals = [right_data[c].get(key) for c in clients]
return sum_right_row_without_duplicates(label_for_merge, clients, vals)
rows_sum = []
def d(x):
return x if isinstance(x, Decimal) else Decimal("0")
for label, key in SUM_TABLE_ROWS:
for row_index, (label, key) in enumerate(SUM_TABLE_ROWS):
if key == "factor_row":
lichtwiese = chemie = mawi = m3 = total = Decimal("0.06")
elif key == "percent":
# Right totals
rw_bez = sum(d(right_data[c].get("bezug")) for c in RIGHT_ALL)
rw_verb = sum(d(right_data[c].get("verbraucherverluste")) for c in RIGHT_ALL)
# We want % = Verbraucherverluste / Bezug (for each group)
# LEFT totals (no merge on left)
left_bez = sum(d(client_data_left[c].get("bezug")) for c in LEFT_ALL)
left_verb = sum(d(client_data_left[c].get("verbraucherverluste")) for c in LEFT_ALL)
# RIGHT totals (must skip merged duplicates!)
rw_bez = sum(d(right_data[c].get("bezug")) for c in RIGHT_ALL)
rw_verb = sum_right_key("Verbraucherverluste (Liter L-He)", RIGHT_ALL, "verbraucherverluste")
lichtwiese = safe_pct(rw_verb, rw_bez)
# Chemie
ch_bez = sum(d(right_data[c].get("bezug")) for c in RIGHT_GROUPS["chemie"])
ch_verb = sum(d(right_data[c].get("verbraucherverluste")) for c in RIGHT_GROUPS["chemie"])
# Chemie group (Fohrer+Buntk)
ch_clients = RIGHT_GROUPS["chemie"]
ch_bez = sum_right_key("Bezug (Liter L-He)", ch_clients, "bezug")
ch_verb = sum_right_key("Verbraucherverluste (Liter L-He)", ch_clients, "verbraucherverluste")
chemie = safe_pct(ch_verb, ch_bez)
# MaWi
mw_bez = sum(d(right_data[c].get("bezug")) for c in RIGHT_GROUPS["mawi"])
mw_verb = sum(d(right_data[c].get("verbraucherverluste")) for c in RIGHT_GROUPS["mawi"])
# MaWi group (Alff+Gutfl)
mw_clients = RIGHT_GROUPS["mawi"]
mw_bez = sum_right_key("Bezug (Liter L-He)", mw_clients, "bezug")
mw_verb = sum_right_key("Verbraucherverluste (Liter L-He)", mw_clients, "verbraucherverluste")
mawi = safe_pct(mw_verb, mw_bez)
# M3
m3_bez = sum(d(right_data[c].get("bezug")) for c in RIGHT_GROUPS["m3"])
m3_verb = sum(d(right_data[c].get("verbraucherverluste")) for c in RIGHT_GROUPS["m3"])
# M3 group (triple)
m3_clients = RIGHT_GROUPS["m3"]
m3_bez = sum_right_key("Bezug (Liter L-He)", m3_clients, "bezug")
m3_verb = sum_right_key("Verbraucherverluste (Liter L-He)", m3_clients, "verbraucherverluste")
m3 = safe_pct(m3_verb, m3_bez)
# Σ column = (left verb + right verb) / (left bez + right bez)
left_bez = sum(d(client_data_left[c].get("bezug")) for c in LEFT_ALL)
left_verb = sum(d(client_data_left[c].get("verbraucherverluste")) for c in LEFT_ALL)
# Overall Σ (%)
total = safe_pct(left_verb + rw_verb, left_bez + rw_bez)
else:
# normal rows = sums
lichtwiese = sum(d(right_data[c].get(key)) for c in RIGHT_ALL)
chemie = sum(d(right_data[c].get(key)) for c in RIGHT_GROUPS["chemie"])
mawi = sum(d(right_data[c].get(key)) for c in RIGHT_GROUPS["mawi"])
m3 = sum(d(right_data[c].get(key)) for c in RIGHT_GROUPS["m3"])
# normal rows = sums (BUT skip duplicates for merged logical cells)
rw_values = [right_data[c].get(key) for c in RIGHT_ALL]
lichtwiese = sum_right_row_without_duplicates(label, RIGHT_ALL, rw_values)
ch_clients = RIGHT_GROUPS["chemie"]
ch_values = [right_data[c].get(key) for c in ch_clients]
chemie = sum_right_row_without_duplicates(label, ch_clients, ch_values)
mw_clients = RIGHT_GROUPS["mawi"]
mw_values = [right_data[c].get(key) for c in mw_clients]
mawi = sum_right_row_without_duplicates(label, mw_clients, mw_values)
m3_clients = RIGHT_GROUPS["m3"]
m3_values = [right_data[c].get(key) for c in m3_clients]
m3 = sum_right_row_without_duplicates(label, m3_clients, m3_values)
left_total = sum(d(client_data_left[c].get(key)) for c in LEFT_ALL)
total = left_total + lichtwiese
# Merck should count ONLY in the overall total, not in Lichtwiese
merck_val = d(right_data["Merck"].get(key))
total = left_total + lichtwiese + merck_val
# ✅ THIS MUST BE OUTSIDE THE IF/ELIF/ELSE
rows_sum.append({
"row_index": row_index,
"label": label,
@@ -964,6 +1076,7 @@ def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[st
"m3": m3,
"is_percent": (key == "percent"),
})
def find_sum_row(rows, label_startswith: str):
for r in rows:
if str(r.get("label", "")).strip().startswith(label_startswith):
@@ -999,8 +1112,8 @@ def compute_halfyear_context(interval_year: int, interval_start: int) -> Dict[st
bottom2["k44"] = k44
bottom2["j44"] = j44
def d(x):
return x if isinstance(x, Decimal) else Decimal("0")
def d_or_none(x):
return x if isinstance(x, Decimal) else None
# ---- Bottom2: J38/K38 depend on rows_sum (overall summary), so do it HERE ----
k38 = Decimal("0")
+2 -2
View File
@@ -3,10 +3,10 @@
{% block content %}
<div class="container">
<!-- Title -->
<h1 class="page-title">Helium Output Yearly Summary</h1>
<h1 class="page-title">Heliumabgabe - Halbjahresübersicht</h1>
<form method="post" action="{% url 'set_halfyear_interval' %}" class="interval-form">
{% csrf_token %}
<h3>Global 6-Month Interval</h3>
<h3>Allgemeines 6-Monats-Intervall</h3>
<label>Year:</label>
<select name="year">
+45 -42
View File
@@ -222,52 +222,55 @@
</tr>
</thead>
<tbody>
{% for r in rows_sum %}
<tr data-row-index="{{ r.row_index }}">
<tr>
<td>{{ r.label }}</td>
<td class="sum-col sum-cell">
{% if r.is_percent %}
{{ r.total|floatformat:2 }}%
{% else %}
{{ r.total|floatformat:2 }}
{% endif %}
</td>
<tbody>
{% for r in rows_sum %}
<tr data-row-index="{{ r.row_index }}">
<td>{{ r.label }}</td>
<td class="sum-col">
{% if r.is_percent %}
{{ r.lichtwiese|floatformat:2 }}%
{% else %}
{{ r.lichtwiese|floatformat:2 }}
{% endif %}
</td>
<td class="sum-col sum-cell">
{% if r.is_percent %}
{{ r.total|floatformat:2 }}%
{% else %}
{{ r.total|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.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>
<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;">
+52 -15
View File
@@ -28,6 +28,7 @@
</div>
<!-- Top Tables Container -->
<div class="top-section"></div>
<div class="top-tables">
<!-- Left Table (18 rows × clients) -->
<div class="table-container top-left-table">
@@ -114,7 +115,9 @@
<td class="sum-cell">
{{ row.sum|default_if_none:"" }}
{% if row.sum is not None %}
{{ row.sum|floatformat:2 }}
{% endif %}
</td>
</tr>
{% endwith %}
@@ -219,7 +222,11 @@
{% endfor %}
<td class="sum-cell">
{{ row.sum|default_if_none:"" }}
<td class="sum-cell">
{% if row.sum is not None %}
{{ row.sum|floatformat:2 }}
{% endif %}
</td>
</td>
</tr>
{% endwith %}
@@ -242,13 +249,18 @@
<tr data-row-index="{{ row.row_index }}">
<td class="row-label">{{ row.label }}</td>
<td class="sum-cell overall-sum-cell">
{{ row.sum|default_if_none:"" }}
<td class="sum-cell">
{% if row.sum is not None %}
{{ row.sum|floatformat:2 }}
{% endif %}
</td>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Bottom Tables -->
<div class="bottom-tables">
<div class="table-container bottom-table-1">
@@ -320,7 +332,9 @@
data-row="{{ forloop.parentloop.counter0 }}"
data-col="{{ forloop.counter0 }}"
contenteditable="true">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% else %}
<td class="readonly-cell"
@@ -328,7 +342,9 @@
data-table="bottom_1"
data-row="{{ forloop.parentloop.counter0 }}"
data-col="{{ forloop.counter0 }}">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% endif %}
@@ -339,7 +355,9 @@
data-table="bottom_1"
data-row="{{ forloop.parentloop.counter0 }}"
data-col="{{ forloop.counter0 }}">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% endif %}
{% endif %}
@@ -379,7 +397,9 @@
data-col="0"
data-client-id="{{ cell.client.id|default:'' }}"
contenteditable="true">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% endwith %}
<td>Gefäss 1,0</td>
@@ -392,7 +412,9 @@
data-col="1"
data-client-id="{{ cell.client.id|default:'' }}"
contenteditable="true">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% endwith %}
<td id="bt2-j39" class="readonly-cell"></td>
@@ -454,7 +476,9 @@
<td id="bt3-j46"
class="readonly-cell calculated-cell"
data-cell-id="{{ cell.id|default:'' }}">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% endwith %}
@@ -490,7 +514,9 @@
data-col="1"
data-cell-id="{{ cell.id|default:'' }}"
contenteditable="true">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% endwith %}
@@ -503,7 +529,9 @@
data-col="2"
data-cell-id="{{ cell.id|default:'' }}"
contenteditable="true">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% endwith %}
@@ -546,7 +574,9 @@
data-col="2"
data-client-id="{{ cell.client.id|default:'' }}"
contenteditable="true">
{{ cell.value|default:"" }}
{% if cell.value is not None %}
{{ cell.value|floatformat:2 }}
{% endif %}
</td>
{% endwith %}
@@ -800,6 +830,12 @@ $(document).ready(function() {
const v = parseFloat(t);
return isNaN(v) ? null : v;
}
function formatNumber(value) {
if (value === null || value === undefined || value === '') return '';
const num = parseFloat(String(value).replace(',', '.'));
if (isNaN(num)) return value;
return num.toFixed(2);
}
// Recalculate Sum cell (last column) for a given row
function recalcRowSum($row) {
@@ -837,7 +873,7 @@ $(document).ready(function() {
});
if (hasValue) {
$row.find('.sum-cell').text(total);
$row.find('.sum-cell').text(total.toFixed(2));
} else {
$row.find('.sum-cell').text('');
}
@@ -1243,8 +1279,9 @@ $(document).ready(function() {
const targetCell = $('[data-cell-id="' + cellData.id + '"]');
if (!targetCell.length) return;
targetCell.text(cellData.value || '');
targetCell.data('original-value', cellData.value || '');
const formattedValue = formatNumber(cellData.value);
targetCell.text(formattedValue);
targetCell.data('original-value', formattedValue);
if (cellData.is_calculated) {
targetCell.addClass('calculated-cell');
+4 -5
View File
@@ -1,5 +1,5 @@
from django.urls import path
from .views import DebugTopRightView
from .views import SaveCellsView , SaveMonthSummaryView, halfyear_settings,MonthlySheetView, monthly_sheet_root,set_halfyear_interval,AbrechnungView, SaveAbrechnungCellsView
from . import views
from .views import RechnungView
@@ -19,9 +19,9 @@ urlpatterns = [
path("abrechnung/autosave/", SaveAbrechnungCellsView.as_view(), name="abrechnung_autosave"),
path("abrechnung/save/", SaveAbrechnungCellsView.as_view(), name="save_abrechnung"),
path('check-sheets/', views.CheckSheetView.as_view(), name='check_sheets'),
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("rechnung/", RechnungView.as_view(), name="rechnung"),
path('sheet/', monthly_sheet_root, name='monthly_sheet_root'),
path('set-halfyear-interval/', set_halfyear_interval, name='set_halfyear_interval'),
@@ -33,6 +33,5 @@ urlpatterns = [
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'),
]
+187 -277
View File
@@ -59,6 +59,12 @@ CLIENT_GROUPS = {
'M3 Gutfleisch',
],
},
'merck': {
'label': 'Merck',
'names': [
'Merck',
],
},
}
# Add this CALCULATION_CONFIG at the top of views.py
@@ -275,12 +281,12 @@ def build_halfyear_window(interval_year: int, start_month: int):
# Halbjahres-Bilanz helpers
# ---------------------------------------------------------------------------
# You can adjust these indices if needed.
# Assuming:
# - bottom_1.table has row "Gasbestand" at some fixed row index,
# and columns: ... Nm³, Lit. LHe
GASBESTAND_ROW_INDEX = 9 # <-- adjust if your bottom_1 has a different row index
GASBESTAND_COL_NM3 = 3 # <-- adjust to the column index for Nm³ in bottom_1
GASBESTAND_ROW_INDEX = 9
GASBESTAND_COL_NM3 = 3
# In top_left / top_right, "Bestand in Kannen-1 (Lit. L-He)" is row_index 5
BESTAND_KANNEN_ROW_INDEX = 5
@@ -382,6 +388,7 @@ HALFYEAR_RIGHT_CLIENTS = [
"M3 Thiele",
"M3 Buntkowsky",
"M3 Gutfleisch",
"Merck",
]
BOTTOM1_COL_VOLUME = 0
BOTTOM1_COL_BAR = 1
@@ -461,6 +468,7 @@ def get_group_clients(group_key):
group = CLIENT_GROUPS.get(group_key)
if not group:
return Client.objects.none()
return Client.objects.filter(name__in=group['names'])
def calculate_summation(sheet, table_type, row_index, sum_column_index):
@@ -575,6 +583,7 @@ class MonthlySheetView(TemplateView):
"M3 Thiele", # Column index 4 (P)
"M3 Buntkowsky", # Column index 5 (Q)
"M3 Gutfleisch", # Column index 6 (R)
"Merck",
]
# For each client in top-right table
@@ -735,6 +744,7 @@ class MonthlySheetView(TemplateView):
"M3 Thiele",
"M3 Buntkowsky",
"M3 Gutfleisch",
"Merck",
]
current_summary = MonthlySummary.objects.filter(sheet=sheet).first()
@@ -765,6 +775,10 @@ class MonthlySheetView(TemplateView):
("Dr. Fohrer", "AG Buntk."),
("AG Alff", "AG Gutfl."),
]
MERGED_TRIPLES = [
("M3 Thiele", "M3 Buntkowsky", "M3 Gutfleisch"),
]
rows = []
# Determine row count
@@ -813,13 +827,29 @@ class MonthlySheetView(TemplateView):
has_value = False
merged_second_indices = set()
if table_type == 'top_right' and row_idx in MERGED_ROWS:
# Handle pairs
for left_name, right_name in MERGED_PAIRS:
try:
right_idx = client_names.index(right_name)
merged_second_indices.add(right_idx)
except ValueError:
# client not in this table; just ignore
pass
# Handle M3 triple group
MERGED_TRIPLES = [
("M3 Thiele", "M3 Buntkowsky", "M3 Gutfleisch"),
]
for a, b, c in MERGED_TRIPLES:
try:
b_idx = client_names.index(b)
c_idx = client_names.index(c)
merged_second_indices.add(b_idx)
merged_second_indices.add(c_idx)
except ValueError:
pass
for col_idx, cell in enumerate(display_cells):
@@ -1250,100 +1280,8 @@ def get_factor_value(table_type, row_index):
# Save Cells View
# views.py - Updated SaveCellsView
# views.py - Update SaveCellsView class
def debug_cell_values(self, sheet, client_id):
"""Debug method to check cell values"""
from .models import Cell
cells = Cell.objects.filter(
sheet=sheet,
table_type='top_left',
client_id=client_id
).order_by('row_index')
debug_info = {}
for cell in cells:
debug_info[f"row_{cell.row_index}"] = {
'value': str(cell.value) if cell.value else 'None',
'ui_row': cell.row_index + 1,
'excel_ref': f"B{cell.row_index + 3}"
}
return debug_info
class DebugCalculationView(View):
"""Debug view to test calculations directly"""
def get(self, request):
sheet_id = request.GET.get('sheet_id', 1)
client_name = request.GET.get('client', 'AG Vogel')
try:
sheet = MonthlySheet.objects.get(id=sheet_id)
client = Client.objects.get(name=client_name)
# Get SaveCellsView instance
save_view = SaveCellsView()
# Create a dummy cell to trigger calculations
dummy_cell = Cell.objects.filter(
sheet=sheet,
table_type='top_left',
client=client,
row_index=0 # B3
).first()
if not dummy_cell:
return JsonResponse({'error': 'No cells found for this client'})
# Trigger calculation
updated = save_view.calculate_top_left_dependents(sheet, dummy_cell)
# Get updated cell values
cells = Cell.objects.filter(
sheet=sheet,
table_type='top_left',
client=client
).order_by('row_index')
cell_data = []
for cell in cells:
cell_data.append({
'row_index': cell.row_index,
'ui_row': cell.row_index + 1,
'excel_ref': f"B{cell.row_index + 3}",
'value': str(cell.value) if cell.value else 'None',
'description': self.get_row_description(cell.row_index)
})
return JsonResponse({
'sheet': f"{sheet.year}-{sheet.month:02d}",
'client': client.name,
'cells': cell_data,
'updated_count': len(updated),
'calculation': 'B5 = IF(B3>0; B3-B4; 0)'
})
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
def get_row_description(self, row_index):
"""Get description for row index"""
descriptions = {
0: "B3: Stand der Gaszähler (Nm³)",
1: "B4: Stand der Gaszähler (Vormonat) (Nm³)",
2: "B5: Gasrückführung (Nm³)",
3: "B6: Rückführung flüssig (Lit. L-He)",
4: "B7: Sonderrückführungen (Lit. L-He)",
5: "B8: Bestand in Kannen-1 (Lit. L-He)",
6: "B9: Summe Bestand (Lit. L-He)",
7: "B10: Best. in Kannen Vormonat (Lit. L-He)",
8: "B11: Bezug (Liter L-He)",
9: "B12: Rückführ. Soll (Lit. L-He)",
10: "B13: Verluste (Soll-Rückf.) (Lit. L-He)",
11: "B14: Füllungen warm (Lit. L-He)",
12: "B15: Kaltgas Rückgabe (Lit. L-He) Faktor",
13: "B16: Faktor",
14: "B17: Verbraucherverluste (Liter L-He)",
15: "B18: %"
}
return descriptions.get(row_index, f"Row {row_index}")
def recalculate_stand_der_gaszahler(self, sheet):
"""Recalculate Stand der Gaszähler for all client pairs"""
from decimal import Decimal
@@ -1443,82 +1381,7 @@ def recalculate_stand_der_gaszahler(self, sheet):
ag_gutfl_row0.save()
except Exception as e:
print(f"Error recalculating Stand der Gaszähler for AG Alff/AG Gutfl.: {e}")
# In your SaveCellsView class in views.py
class DebugTopRightView(View):
"""Debug view to check top_right calculations"""
def get(self, request):
sheet_id = request.GET.get('sheet_id', 1)
client_name = request.GET.get('client', 'Dr. Fohrer')
try:
sheet = MonthlySheet.objects.get(id=sheet_id)
client = Client.objects.get(name=client_name)
# Get all cells for this client in top_right
cells = Cell.objects.filter(
sheet=sheet,
table_type='top_right',
client=client
).order_by('row_index')
cell_data = []
descriptions = {
0: "Stand der Gaszähler (Vormonat)",
1: "Gasrückführung (Nm³)",
2: "Rückführung flüssig",
3: "Sonderrückführungen",
4: "Sammelrückführungen",
5: "Bestand in Kannen-1",
6: "Summe Bestand",
7: "Best. in Kannen Vormonat",
8: "Same as row 9 from prev sheet",
9: "Bezug",
10: "Rückführ. Soll",
11: "Verluste",
12: "Füllungen warm",
13: "Kaltgas Rückgabe",
14: "Faktor 0.06",
15: "Verbraucherverluste",
16: "%"
}
for cell in cells:
cell_data.append({
'row_index': cell.row_index,
'ui_row': cell.row_index + 1,
'description': descriptions.get(cell.row_index, f"Row {cell.row_index}"),
'value': str(cell.value) if cell.value else 'Empty',
'cell_id': cell.id
})
# Test calculation
row3_cell = cells.filter(row_index=3).first()
row5_cell = cells.filter(row_index=5).first()
row6_cell = cells.filter(row_index=6).first()
calculation_info = {
'row3_value': str(row3_cell.value) if row3_cell and row3_cell.value else '0',
'row5_value': str(row5_cell.value) if row5_cell and row5_cell.value else '0',
'row6_value': str(row6_cell.value) if row6_cell and row6_cell.value else '0',
'expected_sum': '0'
}
if row3_cell and row5_cell and row6_cell:
row3_val = Decimal(str(row3_cell.value)) if row3_cell.value else Decimal('0')
row5_val = Decimal(str(row5_cell.value)) if row5_cell.value else Decimal('0')
expected = row3_val + row5_val
calculation_info['expected_sum'] = str(expected)
calculation_info['is_correct'] = row6_cell.value == expected
return JsonResponse({
'sheet': f"{sheet.year}-{sheet.month}",
'client': client.name,
'cells': cell_data,
'calculation': calculation_info
})
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
ABRECHNUNG_COL_CLIENTS = {
# first 3 columns
"pkm_vogel": ["AG Vogel"],
@@ -1582,7 +1445,12 @@ class AbrechnungView(TemplateView):
("rechnungsbetrag", "Rechnungsbetrag", "EUR"),
("eff_lhe_preis", "eff. L-He-Preis", "EUR/L"),
]
SUMMARY_ROWS = {
"bezogen_menge",
"kaltg_warmfuell",
"he_verbrauch",
"lhe_verluste",
}
# Editable rows = your yellow rows
EDITABLE_ROW_KEYS = {"ghe_bezug", "betrag", "gutschriften"}
@@ -1706,9 +1574,12 @@ class AbrechnungView(TemplateView):
def sum_all_cols(values_dict):
return sum(v for k, v in values_dict.items() if k != "gesamt_summe")
bezogen["gesamt_summe"] = sum_all_cols(bezogen)
warmfills["gesamt_summe"] = sum_all_cols(warmfills)
bezogen["gesamt_summe"] = (
d(bezogen.get("chemie")) + d(bezogen.get("mawi")) + d(bezogen.get("physik"))
)
warmfills["gesamt_summe"] = (
d(warmfills.get("chemie")) + d(warmfills.get("mawi")) + d(warmfills.get("physik"))
)
# ---- Row: Bezogen. Menge ----
for col_key in bezogen:
computed[("bezogen_menge", col_key)] = bezogen[col_key]
@@ -1765,12 +1636,30 @@ class AbrechnungView(TemplateView):
for col_key in he_verbrauch:
if col_key in first3:
row1_vals[col_key] = instandhaltung * safe_div(he_verbrauch[col_key], physik_hv) / Decimal("3")
elif col_key in next3:
row1_vals[col_key] = instandhaltung / Decimal("9")
elif col_key in next2:
row1_vals[col_key] = instandhaltung / Decimal("6")
# ✅ NEW: summary columns
elif col_key in ("chemie", "mawi"):
row1_vals[col_key] = instandhaltung / Decimal("3")
elif col_key == "physik":
row1_vals[col_key] = (
d(row1_vals.get("pkm_vogel")) +
d(row1_vals.get("iap_halfmann")) +
d(row1_vals.get("ikp"))
)
elif col_key == "gesamt_summe":
row1_vals[col_key] = sum(row1_vals.get(k, Decimal("0")) for k in first3)
# keep whatever you want here; example: chemie+mawi+physik
row1_vals[col_key] = (
d(row1_vals.get("chemie")) + d(row1_vals.get("mawi")) + d(row1_vals.get("physik"))
)
else:
row1_vals[col_key] = Decimal("0")
@@ -1820,23 +1709,21 @@ class AbrechnungView(TemplateView):
elif col_key == "chemie":
v = (
d(verbrauch_right.get("Dr. Fohrer")) +
d(verbrauch_right.get("AG Buntk.")) +
d(verbrauch_right.get("M3 Buntkowsky")) +
d(verbrauch_right.get("M3 Thiele"))
d(verbrauch_right.get("AG Buntk."))
)
elif col_key == "mawi":
# MaWi = MaWi Gutfl + MaWi Alff (Abrechnung columns)
v = (
d(verbrauch_right.get("AG Alff")) +
d(verbrauch_right.get("AG Gutfl.")) +
d(verbrauch_right.get("M3 Gutfleisch"))
d(lhe_verluste.get("AG Gutfl")) +
d(lhe_verluste.get("mawi_alff"))
)
elif col_key == "physik":
v = (
d(verbrauch_left.get("AG Vogel")) +
d(verbrauch_left.get("AG Halfm")) +
d(verbrauch_left.get("IKP"))
v = (
d(verbrauch_right.get("M3 Thiele")) +
d(verbrauch_right.get("M3 Buntkowsky")) +
d(verbrauch_right.get("M3 Gutfleisch"))
)
elif col_key == "gesamt_summe":
@@ -1851,14 +1738,41 @@ class AbrechnungView(TemplateView):
# --- Gesamt-summe ---
lhe_verluste["gesamt_summe"] = sum(v for k, v in lhe_verluste.items())
lhe_verluste["gesamt_summe"] = (
d(lhe_verluste.get("chemie")) + d(lhe_verluste.get("mawi")) + d(lhe_verluste.get("physik"))
)
computed[("lhe_verluste", "gesamt_summe")] = lhe_verluste["gesamt_summe"]
# ---- Row: 3 Umlage Heliumkosten = heliumkosten * (LHe-Verluste col / LHe-Verluste gesamt_summe) ----
for col_key in lhe_verluste:
computed[("umlage_heliumkosten_3", col_key)] = heliumkosten * safe_div(lhe_verluste[col_key], lhe_verluste["gesamt_summe"])
FIRST8 = [
"pkm_vogel",
"iap_halfmann",
"ikp",
"orgchem_thiele",
"phychem_m3_buntkow",
"orgchem_fohrer",
"mawi_m3_gutfl",
"mawi_alff",
]
den = sum(d(lhe_verluste.get(k)) for k in FIRST8) # denominator = sum of first 8 LHeVerluste
# 1) compute first 8 columns
for k in FIRST8:
computed[("umlage_heliumkosten_3", k)] = heliumkosten * safe_div(d(lhe_verluste.get(k)), den)
# 2) compute the 3 summary columns from those first 8 (so they stay consistent)
# 2) compute the 3 summary columns directly from their LHeVerluste shares (Excel logic)
computed[("umlage_heliumkosten_3", "chemie")] = heliumkosten * safe_div(d(lhe_verluste.get("chemie")), den)
computed[("umlage_heliumkosten_3", "mawi")] = heliumkosten * safe_div(d(lhe_verluste.get("mawi")), den)
computed[("umlage_heliumkosten_3", "physik")] = heliumkosten * safe_div(d(lhe_verluste.get("physik")), den)
# 3) last column = sum of first 8 columns (your requirement)
computed[("umlage_heliumkosten_3", "gesamt_summe")] = sum(
d(computed.get(("umlage_heliumkosten_3", k))) for k in FIRST8
)
# ---- Row: 4-Kosten He-Gas-Bezug = Umlage Heliumkosten * Bezugskosten-GasHe ----
for col_key, _label in self.COLUMNS:
ghe = d(value_map.get(("ghe_bezug", col_key)))
@@ -1901,7 +1815,17 @@ class AbrechnungView(TemplateView):
elif col_key in ("chemie", "mawi", "physik"):
v = safe_div(he_verbrauch[col_key], sum3) * umlage_personal_total
elif col_key == "gesamt_summe":
v = sum(d(computed.get(("umlage_personal_5", k))) for k in he_verbrauch if k != "gesamt_summe")
# sum of the FIRST 8 columns only (exclude chemie/mawi/physik/gesamt_summe)
v = (
d(computed.get(("umlage_personal_5", "pkm_vogel"))) +
d(computed.get(("umlage_personal_5", "iap_halfmann"))) +
d(computed.get(("umlage_personal_5", "ikp"))) +
d(computed.get(("umlage_personal_5", "orgchem_thiele"))) +
d(computed.get(("umlage_personal_5", "phychem_m3_buntkow"))) +
d(computed.get(("umlage_personal_5", "orgchem_fohrer"))) +
d(computed.get(("umlage_personal_5", "mawi_m3_gutfl"))) +
d(computed.get(("umlage_personal_5", "mawi_alff")))
)
else:
v = Decimal("0")
computed[("umlage_personal_5", col_key)] = v
@@ -1932,6 +1856,19 @@ class AbrechnungView(TemplateView):
else:
sonstiges_text[col_key] = "Nachzahlung"
# overwrite display values for non-editable computed rows
FIRST4 = {"bezogen_menge", "kaltg_warmfuell", "anzahl_15", "he_verbrauch"}
FIRST8 = ["pkm_vogel", "iap_halfmann", "ikp", "orgchem_thiele",
"phychem_m3_buntkow", "orgchem_fohrer", "mawi_m3_gutfl", "mawi_alff"]
for rk, _label, _unit in self.ROWS:
if rk in FIRST4:
computed[(rk, "gesamt_summe")] = (
d(computed.get((rk, "chemie"))) +
d(computed.get((rk, "mawi"))) +
d(computed.get((rk, "physik")))
)
else:
computed[(rk, "gesamt_summe")] = sum(d(computed.get((rk, ck))) for ck in FIRST8)
non_editable_formula_rows = {
"bezogen_menge",
"kaltg_warmfuell",
@@ -1981,19 +1918,31 @@ class AbrechnungView(TemplateView):
# -------------------------------
GROUP_IJKL = ["orgchem_thiele", "phychem_m3_buntkow", "orgchem_fohrer", "mawi_m3_gutfl", "mawi_alff"]
GROUP_NOP = GROUP_IJKL + ["chemie", "mawi", "physik"]
GROUP_NOP = ["chemie", "mawi", "physik"]
GROUP_STADT = ["pkm_vogel", "iap_halfmann", "ikp"]
def nop_cols_for_row(row_key: str):
# For gutschriften, NOP should sum the 5 IJKL client columns
if row_key == "gutschriften":
return GROUP_IJKL
# otherwise NOP is the 3 summary columns (Chemie/MaWi/Physik)
return GROUP_NOP
def val(row_key, col_key):
"""Get the final numeric value for a cell (computed if available, else stored)."""
v = value_map.get((row_key, col_key))
return d(v)
"""Get the final numeric value for a cell (prefer computed, fallback to stored)."""
if (row_key, col_key) in computed:
return d(computed.get((row_key, col_key)))
return d(value_map.get((row_key, col_key)))
def sum_group(row_key, cols):
return sum(val(row_key, ck) for ck in cols)
right_rows = []
def nop_cols_for_row(row_key: str):
# For gutschriften, NOP should sum the 5 IJKL client columns
if row_key == "gutschriften":
return GROUP_IJKL
# otherwise NOP is the 3 summary columns
return GROUP_NOP
# These are your normal rows (same order as UI)
# We will create one summary row per Abrechnung row_key.
for row_key, label, unit in self.ROWS:
@@ -2011,14 +1960,27 @@ class AbrechnungView(TemplateView):
continue
ijkl = sum_group(row_key, GROUP_IJKL)
nop = sum_group(row_key, GROUP_NOP)
if row_key == "umlage_heliumkosten_3":
nop = (
val(row_key, "chemie") +
val(row_key, "mawi") +
val(row_key, "physik")
)
else:
nop = sum_group(row_key, nop_cols_for_row(row_key))
stadt = sum_group(row_key, GROUP_STADT)
check = nop + stadt
# Special rule: Rechnungsbetrag row gets +Betrag +Gutschriften (for NOP only)
if row_key == "rechnungsbetrag":
nop_extra = sum_group("betrag", GROUP_NOP) + sum_group("gutschriften", GROUP_NOP)
nop = nop + nop_extra
# Rechnungsbetrag (NOP) = (Chemie+MaWi+Physik Rechnungsbetrag)
# + (Chemie+MaWi+Physik Betrag)
# + (IJKL Gutschriften) <-- because you want gutschriften NOP from IJKL
nop = (
sum_group("rechnungsbetrag", GROUP_NOP)
+ sum_group("betrag", GROUP_NOP)
+ sum_group("gutschriften", GROUP_IJKL)
)
check = nop + stadt
right_rows.append({
@@ -2180,7 +2142,7 @@ class RechnungView(TemplateView):
bs = BetriebskostenSummary.objects.first()
instandhaltung = d(bs.instandhaltung) if bs else Decimal("0")
personalkosten = d(bs.personalkosten) if bs else Decimal("0")
personalkosten = d(bs.umlage_personal) if bs else Decimal("0")
preis_eur_pro_l = (instandhaltung / interval_total_output_lhe) if interval_total_output_lhe != 0 else Decimal("0")
@@ -2537,6 +2499,7 @@ class SaveCellsView(View):
"M3 Thiele", # P
"M3 Buntkowsky", # Q
"M3 Gutfleisch", # R
"Merck"
]
# Define merged pairs
@@ -2553,6 +2516,7 @@ class SaveCellsView(View):
"fohrer_buntk": ["Dr. Fohrer", "AG Buntk."],
"alff_gutfl": ["AG Alff", "AG Gutfl."],
"m3": ["M3 Thiele", "M3 Buntkowsky", "M3 Gutfleisch"],
"merck": ["Merck"],
}
year = sheet.year
@@ -2797,6 +2761,26 @@ class SaveCellsView(View):
else:
prozent = Decimal('0')
set_val(m3_client, 15, prozent, is_calculated=True)
# 9. Simple client(s): only Bezug, Sammelrückführungen, Verbraucherverluste = Sammel - Bezug
SIMPLE_RIGHT_CLIENTS = ["Merck"] # use the exact database name here
for client_name in SIMPLE_RIGHT_CLIENTS:
# Bezug (row 8)
bezug = get_val(client_name, 8)
# Sammelrückführungen (row 4)
sammel = get_val(client_name, 4)
# Verbraucherverluste (row 14) = Sammelrückführungen - Bezug
verbrauch = bezug - sammel
set_val(client_name, 14, verbrauch, is_calculated=True)
# % (row 15) = Verbraucherverluste / Bezug
if bezug != 0:
prozent = verbrauch / bezug
else:
prozent = Decimal("0")
set_val(client_name, 15, prozent, is_calculated=True)
return updated_cells
@@ -4360,41 +4344,7 @@ class CheckSheetView(View):
})
class QuickDebugView(View):
def get(self, request):
# Get ALL sheets
sheets = MonthlySheet.objects.all().order_by('year', 'month')
result = {
'sheets': []
}
for sheet in sheets:
sheet_info = {
'id': sheet.id,
'display': f"{sheet.year}-{sheet.month:02d}",
'url': f"/sheet/{sheet.year}/{sheet.month}/", # CHANGED THIS LINE
'sheet_url_pattern': 'sheet/{year}/{month}/', # Add this for clarity
}
# Count cells with data for first client in top_left table
first_client = Client.objects.first()
if first_client:
test_cells = sheet.cells.filter(
client=first_client,
table_type='top_left',
row_index__in=[8, 9, 10] # Rows 9, 10, 11
).order_by('row_index')
cell_values = {}
for cell in test_cells:
cell_values[f"row_{cell.row_index}"] = str(cell.value) if cell.value else "Empty"
sheet_info['test_cells'] = cell_values
else:
sheet_info['test_cells'] = "No clients"
result['sheets'].append(sheet_info)
return JsonResponse(result)
class TestFormulaView(View):
@@ -4417,46 +4367,6 @@ class TestFormulaView(View):
})
class SimpleDebugView(View):
"""Simplest debug view to check if things are working"""
def get(self, request):
sheet_id = request.GET.get('sheet_id', 1)
try:
sheet = MonthlySheet.objects.get(id=sheet_id)
# Get first client
client = Client.objects.first()
if not client:
return JsonResponse({'error': 'No clients found'})
# Check a few cells
cells = Cell.objects.filter(
sheet=sheet,
client=client,
table_type='top_left',
row_index__in=[8, 9, 10]
).order_by('row_index')
cell_data = []
for cell in cells:
cell_data.append({
'row_index': cell.row_index,
'ui_row': cell.row_index + 1,
'value': str(cell.value) if cell.value is not None else 'Empty',
'cell_id': cell.id
})
return JsonResponse({
'sheet': f"{sheet.year}-{sheet.month}",
'sheet_id': sheet.id,
'client': client.name,
'cells': cell_data,
'note': 'Row 8 = UI Row 9, Row 9 = UI Row 10, Row 10 = UI Row 11'
})
except MonthlySheet.DoesNotExist:
return JsonResponse({'error': f'Sheet with id {sheet_id} not found'})
def halfyear_settings(request):
"""