update
This commit is contained in:
124
sheets/models.py
124
sheets/models.py
@@ -73,47 +73,45 @@ class CellReference(models.Model):
|
||||
class Meta:
|
||||
unique_together = ['source_cell', 'target_cell']
|
||||
|
||||
from decimal import Decimal
|
||||
from django.db import models
|
||||
|
||||
class Betriebskosten(models.Model):
|
||||
KOSTENTYP_CHOICES = [
|
||||
('sach', 'Sachkosten'),
|
||||
('ln2', 'LN2'),
|
||||
('sach', 'Sach'),
|
||||
('helium', 'Helium'),
|
||||
('inv', 'Inventar'),
|
||||
]
|
||||
|
||||
buchungsdatum = models.DateField('Buchungsdatum')
|
||||
rechnungsnummer = models.CharField('Rechnungsnummer', max_length=50)
|
||||
gegenstand = models.CharField("Gegenstand", max_length=200)
|
||||
buchungsdatum = models.DateField('Zahlungsdatum')
|
||||
rechnungsnummer = models.CharField('Firma', max_length=50)
|
||||
kostentyp = models.CharField('Kostentyp', max_length=10, choices=KOSTENTYP_CHOICES)
|
||||
gas_volume = models.DecimalField('Gasvolumen (Liter)', max_digits=10, decimal_places=2, null=True, blank=True)
|
||||
|
||||
# IMPORTANT: now this field stores m³ (not liters)
|
||||
gas_volume = models.DecimalField('Gasvolumen (m³)', max_digits=10, decimal_places=2, null=True, blank=True)
|
||||
|
||||
betrag = models.DecimalField('Betrag (€)', max_digits=10, decimal_places=2)
|
||||
beschreibung = models.TextField('Beschreibung', blank=True)
|
||||
|
||||
|
||||
@property
|
||||
def price_per_liter(self):
|
||||
def gas_volume_liter(self):
|
||||
# Liter = m³ / 0.75
|
||||
if self.kostentyp == 'helium' and self.gas_volume:
|
||||
return self.gas_volume / Decimal("0.75")
|
||||
return None
|
||||
|
||||
@property
|
||||
def price_per_m3(self):
|
||||
if self.kostentyp == 'helium' and self.gas_volume:
|
||||
return self.betrag / self.gas_volume
|
||||
return None
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.buchungsdatum} - {self.get_kostentyp_display()} - {self.betrag}€"
|
||||
class RowCalculation(models.Model):
|
||||
"""Define calculations for specific rows"""
|
||||
table_type = models.CharField(max_length=20, choices=[
|
||||
('top_left', 'Top Left Table'),
|
||||
('top_right', 'Top Right Table'),
|
||||
('bottom_1', 'Bottom Table 1'),
|
||||
('bottom_2', 'Bottom Table 2'),
|
||||
('bottom_3', 'Bottom Table 3'),
|
||||
])
|
||||
row_index = models.IntegerField() # Which row has the formula
|
||||
formula = models.TextField() # e.g., "row_10 + row_9"
|
||||
description = models.CharField(max_length=200, blank=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ['table_type', 'row_index']
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.table_type}[{self.row_index}]: {self.formula}"
|
||||
|
||||
@property
|
||||
def price_per_liter(self):
|
||||
# Preis(Liter) = betrag / liter
|
||||
liters = self.gas_volume_liter
|
||||
if self.kostentyp == 'helium' and liters:
|
||||
return self.betrag / liters
|
||||
return None
|
||||
|
||||
# Or simpler: Just store row calculations in a JSONField
|
||||
class TableConfig(models.Model):
|
||||
@@ -201,6 +199,8 @@ class SecondTableEntry(models.Model):
|
||||
date = models.DateField(default=timezone.now)
|
||||
is_warm = models.BooleanField(default=False)
|
||||
lhe_delivery = models.CharField(max_length=100, blank=True, null=True)
|
||||
vor = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
|
||||
nach = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
|
||||
lhe_output = models.DecimalField(
|
||||
max_digits=10,
|
||||
decimal_places=2,
|
||||
@@ -210,7 +210,8 @@ class SecondTableEntry(models.Model):
|
||||
)
|
||||
notes = models.TextField(blank=True, null=True)
|
||||
date_joined = models.DateField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["date", "id"]
|
||||
def __str__(self):
|
||||
return f"{self.client.name} - {self.date}"
|
||||
|
||||
@@ -250,4 +251,63 @@ class MonthlySummary(models.Model):
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"Summary {self.sheet.year}-{self.sheet.month:02d}"
|
||||
return f"Summary {self.sheet.year}-{self.sheet.month:02d}"
|
||||
|
||||
|
||||
class BetriebskostenSummary(models.Model):
|
||||
personalkosten = models.DecimalField(max_digits=12, decimal_places=2, default=0)
|
||||
|
||||
instandhaltung = models.DecimalField(max_digits=12, decimal_places=2, default=0)
|
||||
heliumkosten = models.DecimalField(max_digits=12, decimal_places=2, default=0)
|
||||
bezugskosten_gashe = models.DecimalField(max_digits=12, decimal_places=4, default=0)
|
||||
umlage_personal = models.DecimalField(max_digits=12, decimal_places=2, default=0)
|
||||
|
||||
def recalculate(self):
|
||||
from django.db.models import Sum
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.db.models import DecimalField, Value
|
||||
from .models import Betriebskosten
|
||||
|
||||
items = Betriebskosten.objects.all()
|
||||
|
||||
sach_sum = items.filter(kostentyp='sach').aggregate(
|
||||
total=Coalesce(Sum('betrag'), Value(0, output_field=DecimalField()))
|
||||
)['total'] or Decimal('0')
|
||||
|
||||
helium_sum = items.filter(kostentyp='helium').aggregate(
|
||||
total=Coalesce(Sum('betrag'), Value(0, output_field=DecimalField()))
|
||||
)['total'] or Decimal('0')
|
||||
|
||||
helium_m3_sum = items.filter(kostentyp='helium').aggregate(
|
||||
total=Coalesce(Sum('gas_volume'), Value(0, output_field=DecimalField()))
|
||||
)['total'] or Decimal('0')
|
||||
|
||||
bezug = (helium_sum / helium_m3_sum) if helium_m3_sum not in (None, 0, Decimal('0')) else Decimal('0')
|
||||
|
||||
self.instandhaltung = sach_sum
|
||||
self.heliumkosten = helium_sum
|
||||
self.bezugskosten_gashe = bezug
|
||||
self.umlage_personal = self.personalkosten / 2
|
||||
self.save()
|
||||
|
||||
# models.py
|
||||
from django.db import models
|
||||
|
||||
class AbrechnungCell(models.Model):
|
||||
"""
|
||||
Storage for the 'Abrechnung' page where columns are custom (not 1:1 with Client).
|
||||
Values are saved by: (interval_year, interval_start_month, row_key, col_key).
|
||||
"""
|
||||
interval_year = models.IntegerField()
|
||||
interval_start_month = models.IntegerField() # first month of the 6-month window
|
||||
|
||||
row_key = models.CharField(max_length=60)
|
||||
col_key = models.CharField(max_length=60)
|
||||
|
||||
value = models.DecimalField(max_digits=18, decimal_places=6, null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("interval_year", "interval_start_month", "row_key", "col_key")
|
||||
|
||||
def __str__(self):
|
||||
return f"Abrechnung {self.interval_year}/{self.interval_start_month} {self.row_key}:{self.col_key}={self.value}"
|
||||
|
||||
Reference in New Issue
Block a user