Skip to content

Commit dd3d61c

Browse files
committed
Fix: Strompauschale was applied persistent
1 parent b74d914 commit dd3d61c

6 files changed

Lines changed: 105 additions & 61 deletions

File tree

Deeplex.Saverwalter.BetriebskostenabrechnungService/Abrechnungseinheit.cs

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,50 @@
1313
// You should have received a copy of the GNU Affero General Public License
1414
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1515

16+
using System.Reflection.Metadata;
1617
using Deeplex.Saverwalter.Model;
1718

1819
namespace Deeplex.Saverwalter.BetriebskostenabrechnungService
1920
{
21+
public class BetriebskostenrechnungEntry
22+
{
23+
public Betriebskostenrechnung? Rechnung { get; }
24+
public double Betrag { get; }
25+
public BetriebskostenrechnungEntry(
26+
Betriebskostenrechnung? rechnung,
27+
Zeitraum zeitraum,
28+
List<Note> notes)
29+
{
30+
Rechnung = rechnung;
31+
32+
if (rechnung != null)
33+
{
34+
var abzug = 0.0;
35+
foreach (var hkvo in rechnung.Umlage.HKVOs)
36+
{
37+
var rechnungen = hkvo.Heizkosten.Betriebskostenrechnungen.Where(r
38+
=> r.BetreffendesJahr == zeitraum.Jahr).ToList();
39+
foreach (var r in rechnungen)
40+
{
41+
abzug += r.Betrag * hkvo.Strompauschale;
42+
}
43+
}
44+
45+
Betrag = rechnung.Betrag - abzug;
46+
47+
if (Betrag < 0)
48+
{
49+
notes.Add($"Pauschale der Heizkosten ist mehr als Allgemeinstromrechnung {Betrag:N2}€", Severity.Warning);
50+
}
51+
52+
53+
}
54+
}
55+
}
56+
2057
public class Abrechnungseinheit
2158
{
22-
public Dictionary<Umlage, Betriebskostenrechnung?> Rechnungen { get; } = new();
59+
public Dictionary<Umlage, BetriebskostenrechnungEntry?> Rechnungen { get; } = new();
2360
public double BetragKalt { get; }
2461
public double BetragWarm { get; }
2562
public double GesamtBetragKalt { get; }
@@ -59,10 +96,13 @@ public Abrechnungseinheit(List<Umlage> umlagen, Vertrag vertrag, Zeitraum zeitra
5996

6097
foreach (var umlage in umlagen)
6198
{
62-
Rechnungen[umlage] = umlage.Betriebskostenrechnungen
63-
.SingleOrDefault(rechnung => rechnung.BetreffendesJahr == zeitraum.Jahr);
99+
// TODO: This limits us to one Rechnung per Umlage per Jahr
100+
Rechnungen[umlage] = new BetriebskostenrechnungEntry(
101+
umlage.Betriebskostenrechnungen
102+
.SingleOrDefault(rechnung => rechnung.BetreffendesJahr == zeitraum.Jahr),
103+
zeitraum, notes);
64104

65-
if (Rechnungen[umlage] == null)
105+
if (Rechnungen[umlage]?.Rechnung == null)
66106
{
67107
notes.Add($"Keine Rechnung für {umlage.Typ.Bezeichnung} gefunden.", Severity.Warning);
68108
}
@@ -83,32 +123,6 @@ public Abrechnungseinheit(List<Umlage> umlagen, Vertrag vertrag, Zeitraum zeitra
83123
Heizkostenberechnungen = CalculateHeizkosten(rechnungenWarm, wohnung, VerbrauchAnteile, zeitraum, notes);
84124
BetragWarm = Heizkostenberechnungen.Sum(heizkosten => heizkosten.Betrag);
85125

86-
rechnungenWarm.ForEach(warmeRechnung =>
87-
{
88-
if (warmeRechnung.Umlage.HKVO is HKVO hkvo)
89-
{
90-
var stromRechnung = rechnungenKalt.FirstOrDefault(kalteRechnung =>
91-
kalteRechnung.Umlage.UmlageId == hkvo.Betriebsstrom.UmlageId);
92-
93-
if (stromRechnung == null)
94-
{
95-
notes.Add("Keine Stromrechnung für Heizung gefunden", Severity.Error);
96-
return;
97-
}
98-
99-
var delta = warmeRechnung.Betrag * hkvo.Strompauschale;
100-
// Das wird bereits in der Heizkostenberechnung gemacht und als Pauschalbetrag verbucht.
101-
// Für die Stromrechnung allerdings muss der Teil noch abgezogen werden.
102-
// warmeRechnung.Betrag += delta;
103-
stromRechnung.Betrag -= delta;
104-
105-
if (stromRechnung.Betrag < 0)
106-
{
107-
notes.Add($"Pauschale der Heizkosten ({hkvo.Strompauschale:N2}%) ist mehr als Allgemeinstromrechnung {stromRechnung.Betrag:N2}€", Severity.Warning);
108-
}
109-
}
110-
});
111-
112126
GesamtBetragWarm = rechnungenWarm.Sum(e => e.Betrag);
113127
BetragKalt = GetSum(rechnungenKalt, notes);
114128
GesamtBetragKalt = rechnungenKalt.Sum(rechnung => rechnung.Betrag);
@@ -129,35 +143,53 @@ public double GetAnteil(Umlage umlage)
129143
};
130144
}
131145

132-
private double GetSum(List<Betriebskostenrechnung> rechnungen, List<Note> notes)
146+
private double GetSum(List<BetriebskostenrechnungEntry> rechnungen, List<Note> notes)
133147
{
134148
var PersZeitanteil = PersonenZeitanteile.Sum(z => z.Anteil);
135149

136-
return rechnungen.Sum(rechnung => rechnung.Umlage.Schluessel switch
150+
return rechnungen.Sum(rechnung =>
137151
{
138-
Umlageschluessel.NachNutzeinheit => rechnung.Betrag * NEZeitanteil,
139-
Umlageschluessel.NachWohnflaeche => rechnung.Betrag * WFZeitanteil,
140-
Umlageschluessel.NachNutzflaeche => rechnung.Betrag * NFZeitanteil,
141-
Umlageschluessel.NachMiteigentumsanteil => rechnung.Betrag * MEAZeitanteil,
142-
Umlageschluessel.NachPersonenzahl => rechnung.Betrag * PersZeitanteil,
143-
Umlageschluessel.NachVerbrauch => rechnung.Betrag * GetVerbrauchAnteil(rechnung, notes),
144-
_ => 0
152+
if (rechnung.Rechnung == null)
153+
{
154+
notes.Add($"Keine Rechnung für {rechnung.Rechnung?.Umlage.Typ.Bezeichnung} gefunden.", Severity.Warning);
155+
156+
return 0;
157+
}
158+
159+
return rechnung.Rechnung.Umlage.Schluessel switch
160+
{
161+
Umlageschluessel.NachNutzeinheit => rechnung.Betrag * NEZeitanteil,
162+
Umlageschluessel.NachWohnflaeche => rechnung.Betrag * WFZeitanteil,
163+
Umlageschluessel.NachNutzflaeche => rechnung.Betrag * NFZeitanteil,
164+
Umlageschluessel.NachMiteigentumsanteil => rechnung.Betrag * MEAZeitanteil,
165+
Umlageschluessel.NachPersonenzahl => rechnung.Betrag * PersZeitanteil,
166+
Umlageschluessel.NachVerbrauch => rechnung.Betrag * GetVerbrauchAnteil(rechnung, notes),
167+
_ => 0
168+
};
145169
});
146170
}
147171

148-
private double GetVerbrauchAnteil(Betriebskostenrechnung rechnung, List<Note> notes)
172+
private double GetVerbrauchAnteil(BetriebskostenrechnungEntry rechnung, List<Note> notes)
149173
{
150-
var verbrauchAnteile = VerbrauchAnteile.Where(anteil => anteil.Umlage == rechnung.Umlage).ToList();
174+
var lRechnung = rechnung.Rechnung;
175+
if (lRechnung == null)
176+
{
177+
notes.Add($"Keine Rechnung für {rechnung.Rechnung?.Umlage.Typ.Bezeichnung} gefunden.",
178+
Severity.Error);
179+
return 0;
180+
}
181+
182+
var verbrauchAnteile = VerbrauchAnteile.Where(anteil => anteil.Umlage == lRechnung.Umlage).ToList();
151183
if (verbrauchAnteile.Count == 0)
152184
{
153-
notes.Add($"Keinen Anteil für {rechnung.Umlage.Typ.Bezeichnung} gefunden",
185+
notes.Add($"Keinen Anteil für {lRechnung.Umlage.Typ.Bezeichnung} gefunden",
154186
Severity.Error);
155187

156188
return 0;
157189
}
158190
else if (verbrauchAnteile.Count > 1)
159191
{
160-
notes.Add($"Mehr als einen Anteil für {rechnung.Umlage.Typ.Bezeichnung} gefunden",
192+
notes.Add($"Mehr als einen Anteil für {lRechnung.Umlage.Typ.Bezeichnung} gefunden",
161193
Severity.Error);
162194

163195
return 0;
@@ -167,7 +199,7 @@ private double GetVerbrauchAnteil(Betriebskostenrechnung rechnung, List<Note> no
167199

168200
if (verbrauchAnteil.Anteil.Count > 1)
169201
{
170-
notes.Add($"Verbrauch von Rechnung {rechnung.Umlage.Typ.Bezeichnung} enthält mehr als einen Zählertypen",
202+
notes.Add($"Verbrauch von Rechnung {lRechnung.Umlage.Typ.Bezeichnung} enthält mehr als einen Zählertypen",
171203
Severity.Error);
172204

173205
return 0;
@@ -193,7 +225,7 @@ [.. umlage.Wohnungen.Select(gr => gr.WohnungId).ToList()],
193225
}
194226

195227
private static List<Heizkostenberechnung> CalculateHeizkosten(
196-
List<Betriebskostenrechnung> rechnungen,
228+
List<BetriebskostenrechnungEntry> rechnungen,
197229
Wohnung wohnung,
198230
List<VerbrauchAnteil> verbrauchAnteile,
199231
Zeitraum zeitraum,

Deeplex.Saverwalter.BetriebskostenabrechnungService/Heizkostenberechnung.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,21 @@ public sealed class Heizkostenberechnung
4444
public double Betrag { get; }
4545

4646
public Heizkostenberechnung(
47-
Betriebskostenrechnung rechnung,
47+
BetriebskostenrechnungEntry rechnung,
4848
Wohnung wohnung,
4949
List<VerbrauchAnteil> verbrauchAnteile,
5050
Zeitraum zeitraum,
5151
List<Note> notes)
5252
{
53+
var lRechnung = rechnung.Rechnung;
54+
if (lRechnung == null)
55+
{
56+
notes.Add("Keine Rechnung für Heizkostenabrechnung gefunden.", Severity.Error);
57+
return;
58+
}
59+
5360
GesamtBetrag = rechnung.Betrag;
54-
if (rechnung.Umlage.HKVO is HKVO hkvo)
61+
if (lRechnung.Umlage.HKVO is HKVO hkvo)
5562
{
5663
PauschalBetrag = rechnung.Betrag + rechnung.Betrag * hkvo.Strompauschale;
5764
}
@@ -61,10 +68,10 @@ public Heizkostenberechnung(
6168
}
6269

6370
tw = 60;
64-
Para7 = rechnung.Umlage.HKVO?.HKVO_P7 ?? 0.5; // HeizkostenV §7
65-
Para8 = rechnung.Umlage.HKVO?.HKVO_P8 ?? 0.5; // HeizkostenV §8
71+
Para7 = lRechnung.Umlage.HKVO?.HKVO_P7 ?? 0.5; // HeizkostenV §7
72+
Para8 = lRechnung.Umlage.HKVO?.HKVO_P8 ?? 0.5; // HeizkostenV §8
6673

67-
var warmwasserZaehlerAbrechnungseinheit = rechnung.Umlage.Zaehler.Where(e => e.Typ == Zaehlertyp.Warmwasser).ToList();
74+
var warmwasserZaehlerAbrechnungseinheit = lRechnung.Umlage.Zaehler.Where(e => e.Typ == Zaehlertyp.Warmwasser).ToList();
6875
if (warmwasserZaehlerAbrechnungseinheit.Count == 0)
6976
{
7077
notes.Add("Keine Warmwasserzähler in Abrechnungseinheit gefunden.", Severity.Error);
@@ -76,7 +83,7 @@ public Heizkostenberechnung(
7683
notes.Add("Keine Warmwasserzähler für Wohnung.", Severity.Error);
7784
}
7885

79-
var gasAllgemeinZaehler = rechnung.Umlage.Zaehler.Where(z => z.Wohnung == null && z.Typ == Zaehlertyp.Gas).ToList();
86+
var gasAllgemeinZaehler = lRechnung.Umlage.Zaehler.Where(z => z.Wohnung == null && z.Typ == Zaehlertyp.Gas).ToList();
8087

8188
if (gasAllgemeinZaehler.Count == 0)
8289
{
@@ -85,7 +92,7 @@ public Heizkostenberechnung(
8592
}
8693

8794

88-
var anteile = verbrauchAnteile.Where(anteil => anteil.Umlage == rechnung.Umlage);
95+
var anteile = verbrauchAnteile.Where(anteil => anteil.Umlage == lRechnung.Umlage);
8996
var dieseAnteile = anteile.SelectMany(anteil => anteil.DieseZaehler.Values.SelectMany(value => value));
9097
var alleAnteile = anteile.SelectMany(anteil => anteil.AlleZaehler.Values.SelectMany(value => value));
9198

@@ -116,7 +123,7 @@ public Heizkostenberechnung(
116123
notes.Add("Heizkostenverteilung nach $9(2) ist kleiner als 0%", Severity.Error);
117124
}
118125

119-
GesamtNutzflaeche = rechnung.Umlage.Wohnungen.Sum(w => w.Nutzflaeche);
126+
GesamtNutzflaeche = lRechnung.Umlage.Wohnungen.Sum(w => w.Nutzflaeche);
120127
NFZeitanteil = wohnung.Nutzflaeche / GesamtNutzflaeche * zeitraum.Zeitanteil;
121128

122129
var q = dieseAnteile.Where(w => w.Zaehler.Typ == Zaehlertyp.Gas).Sum(verbrauch => verbrauch.Delta);

Deeplex.Saverwalter.PrintService/TPrint.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -472,9 +472,8 @@ public static void ErmittlungKalteKosten(
472472

473473
void kostenPunkt(Umlage umlage, string zeitraum, int Jahr, double anteil, bool firstLine = true)
474474
{
475-
var betrag = umlage.Betriebskostenrechnungen
476-
.Where(rechnung => rechnung.BetreffendesJahr == abrechnung.Zeitraum.Jahr)
477-
.Sum(b => b.Betrag);
475+
var rechnung = abrechnungseinheit.Rechnungen[umlage];
476+
var betrag = rechnung != null ? rechnung.Betrag : 0;
478477
col1.Add(firstLine ? umlage.Typ.Bezeichnung : "");
479478
col2.Add(abrechnungseinheit.GesamtEinheiten == 1 ? "Direkt" : (firstLine ? umlage.Schluessel.ToDescriptionString() : ""));
480479
col3.Add(zeitraum);

Deeplex.Saverwalter.WebAPI/Controllers/Utils/BetriebskostenabrechnungController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ public class RechnungEntry
9999
public double BetragLetztesJahr { get; }
100100
public string Beschreibung { get; }
101101

102-
public RechnungEntry(KeyValuePair<Umlage, Betriebskostenrechnung?> rechnung, Abrechnungseinheit einheit, int year)
102+
public RechnungEntry(KeyValuePair<Umlage, BetriebskostenrechnungEntry?> rechnung, Abrechnungseinheit einheit, int year)
103103
{
104104
Id = rechnung.Key.UmlageId;
105-
RechnungId = rechnung.Value?.BetriebskostenrechnungId ?? 0;
105+
RechnungId = rechnung.Value?.Rechnung?.BetriebskostenrechnungId ?? 0;
106106
Typ = rechnung.Key.Typ.Bezeichnung;
107107
TypId = rechnung.Key.Typ.UmlagetypId;
108108
var key = rechnung.Key.Schluessel;

Deeplex.Saverwalter.WebAPI/Controllers/Utils/UserController.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using Microsoft.AspNetCore.Authorization;
2525
using Microsoft.AspNetCore.Mvc;
2626
using Microsoft.AspNetCore.WebUtilities;
27+
using MigraDoc.DocumentObjectModel;
2728
using static Deeplex.Saverwalter.WebAPI.Controllers.AccountController;
2829

2930
namespace Deeplex.Saverwalter.WebAPI.Controllers.Utils
@@ -170,7 +171,12 @@ public async Task<ActionResult<List<WalterFile>>> GetFiles()
170171
var result = await FileHandling.RedirectToFileServer(Request, _httpClient, fullPath);
171172
if (result is FileContentResult fileContentResult)
172173
{
173-
var files = FileHandling.ParseS3Stream(Encoding.UTF8.GetString(fileContentResult.FileContents), HttpContext.Request.Path.Value);
174+
var path = HttpContext.Request.Path.Value;
175+
if (path.IsValueNullOrEmpty() || path == null)
176+
{
177+
return new BadRequestResult();
178+
}
179+
var files = FileHandling.ParseS3Stream(Encoding.UTF8.GetString(fileContentResult.FileContents), path);
174180
return Ok(files);
175181
}
176182
else

Deeplex.Saverwalter.WebAPI/Services/DbServices/VertragVersionDbService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ private async Task<VertragVersionEntry> Add(VertragVersionEntry entry)
8989

9090
SetOptionalValues(entity, entry);
9191
Ctx.VertragVersionen.Add(entity);
92-
Ctx.SaveChanges();
92+
await Ctx.SaveChangesAsync();
9393

9494
return new VertragVersionEntry(entity, entry.Permissions);
9595
}
@@ -104,7 +104,7 @@ public override async Task<ActionResult<VertragVersionEntry>> Put(ClaimsPrincipa
104104

105105
SetOptionalValues(entity, entry);
106106
Ctx.VertragVersionen.Update(entity);
107-
Ctx.SaveChanges();
107+
await Ctx.SaveChangesAsync();
108108

109109
return new VertragVersionEntry(entity, entry.Permissions);
110110
});

0 commit comments

Comments
 (0)