Merge branch 'master' of ssh://float.ownsoft.de/git/beyondSoft/BeWo

This commit is contained in:
2026-04-28 10:28:15 +02:00
24 changed files with 1788 additions and 846 deletions

View File

@@ -78,6 +78,9 @@
<Compile Include="Models\Auftragsdatei\AuftragssatzPart2.cs" />
<Compile Include="Models\Auftragsdatei\AuftragssatzPart3.cs" />
<Compile Include="Models\Auftragsdatei\AuftragssatzPart4.cs" />
<Compile Include="Models\Blocke\BlockEinsatz.cs" />
<Compile Include="Models\Blocke\BlockEinsatzPosition.cs" />
<Compile Include="Models\Blocke\BlockKlientHKP.cs" />
<Compile Include="Models\DakotaEnums.cs" />
<Compile Include="DakotaExtensions.cs" />
<Compile Include="Models\DakotaFile.cs" />
@@ -143,6 +146,9 @@
<Compile Include="Models\Segmente\KTD\SegmentKTDIDK.cs" />
<Compile Include="Models\Segmente\KTD\SegmentKTDVDT.cs" />
<Compile Include="Models\Segmente\KTD\SegmentKTDVKG.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentEHK.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentELP.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentESK.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentSLLABES.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentSLLADIA.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentSLLAMWS.cs" />
@@ -152,6 +158,7 @@
<Compile Include="Models\Segmente\SLLA\SegmentSLLATXT.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentSLLAZUV.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentSLLAZUZ.cs" />
<Compile Include="Models\Segmente\SLLA\SegmentZHK.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Models\Segmente\Segment.cs" />
<Compile Include="Models\Segmente\SLGA\SegmentSLGAFKT.cs" />

View File

@@ -0,0 +1,47 @@
using Dakota.Models.Infos;
using Dakota.Models.Segmente;
using Dakota.Models.Segmente.SLLA;
using System.Collections.Generic;
namespace Dakota.Models.Blocke
{
/// <summary>
/// ESK + 1-n BlockEinsatzPosition
/// entspricht einem einzelnen Einsatz/Hausbesuch
/// bei Häuslicher Krankenpflege (SLLA: C).
/// </summary>
internal class BlockEinsatz : Block
{
public SegmentSLLAESK SegmentSLLAESK { get; private set; }
public List<BlockEinsatzPosition> Positionen { get; private set; }
public BlockEinsatz()
{
SegmentSLLAESK = new SegmentSLLAESK();
Positionen = new List<BlockEinsatzPosition>();
}
public override List<Segment> GetAllSegments()
{
var res = new List<Segment> { SegmentSLLAESK };
foreach (var pos in Positionen)
res.AddRange(pos.GetSegments());
return res;
}
public override int GetUNHCount() => 0;
public void Apply(InfoAbrechnungsposition info)
{
// ESK: Datum + Uhrzeiten aus der Abrechnungsposition
SegmentSLLAESK.DatumLeistungserbringung.SetValue(info.DatumDerLeistungserbringung);
SegmentSLLAESK.UhrzeitBeginn.SetValue(info.Uhrzeit);
SegmentSLLAESK.UhrzeitEnde.SetValue(info.UhrzeitBis);
SegmentSLLAESK.Dauer.SetValue(info.Dauer > 0 ? info.Dauer.ToString() : null);
var posBlock = new BlockEinsatzPosition();
posBlock.Apply(info);
Positionen.Add(posBlock);
}
}
}

View File

@@ -0,0 +1,64 @@
using Dakota.Models.Infos;
using Dakota.Models.Segmente;
using Dakota.Models.Segmente.SLLA;
using System.Collections.Generic;
namespace Dakota.Models.Blocke
{
/// <summary>
/// EHK + optionale ELP-Segmente + optionales TXT-Segment
/// entspricht einer Abrechnungsposition innerhalb eines Einsatzes
/// bei Häuslicher Krankenpflege (SLLA: C).
/// </summary>
internal class BlockEinsatzPosition : Block
{
public SegmentSLLAEHK SegmentSLLAEHK { get; private set; }
/// <summary>
/// Einzelleistungen innerhalb einer Leistungspauschale (0-n je EHK).
/// Nur füllen, wenn eine Pauschale abgerechnet wird.
/// </summary>
public List<SegmentSLLAELP> SegmenteELP { get; private set; }
public SegmentSLLATXT SegmentSLLATXT { get; private set; }
public decimal AnzahlEinheit => SegmentSLLAEHK.AnzahlMenge.DecimalValue;
public decimal EinzelbetragAbrechnungsposition => SegmentSLLAEHK.EinzelbetragAbrechnungsposition.DecimalValue;
public BlockEinsatzPosition()
{
SegmentSLLAEHK = new SegmentSLLAEHK();
SegmenteELP = new List<SegmentSLLAELP>();
SegmentSLLATXT = new SegmentSLLATXT();
}
public override List<Segment> GetAllSegments()
{
var res = new List<Segment> { SegmentSLLAEHK };
res.AddRange(SegmenteELP);
res.Add(SegmentSLLATXT);
return res;
}
public override int GetUNHCount() => 0;
public void Apply(InfoAbrechnungsposition info)
{
SegmentSLLAEHK.Abrechnungscode.SetValue(info.Abrechnungscode);
SegmentSLLAEHK.Tarifkennzeichen.SetValue(info.Tarifkennzeichen);
SegmentSLLAEHK.ArtLeistung.SetValue(info.GetAbrechnungsposition());
SegmentSLLAEHK.AnzahlMenge.SetValue(info.AnzahlMenge);
SegmentSLLAEHK.EinzelbetragAbrechnungsposition.SetValue(info.EinzelbetragAbrechnungsposition);
SegmentSLLAEHK.GefahreneKilometer.SetValue(info.GefahreneKilometer);
// Beschäftigtennummer: Pflichtfeld Fallback auf Ersatzwert 999999999
var bsnr1 = !string.IsNullOrWhiteSpace(info.Beschäftigtennummer)
? info.Beschäftigtennummer
: "999999999";
SegmentSLLAEHK.Beschäftigtennummer1.SetValue(bsnr1);
SegmentSLLAEHK.Beschäftigtennummer2.SetValue(info.Beschäftigtennummer2);
SegmentSLLATXT.Text.SetValue(info.Text);
}
}
}

View File

@@ -0,0 +1,146 @@
using Dakota.Models.Infos;
using Dakota.Models.Segmente;
using Dakota.Models.Segmente.SLLA;
using System.Collections.Generic;
using System.Linq;
namespace Dakota.Models.Blocke
{
/// <summary>
/// Abrechnungsfall (INV … BES) für Häusliche Krankenpflege (SLLA: C).
/// Segmentfolge gem. TA § 302 Abs. 5.5.3.4:
/// INV, NAD, [IMG], ESK { EHK [ELP] [TXT] }+, ZHK [DIA] SKZ BES
/// </summary>
internal class BlockKlientHKP : Block
{
public SegmentSLLAINV SegmentSLLAINV { get; private set; }
public SegmentSLLANAD SegmentSLLANAD { get; private set; }
public SegmentSLLAIMG SegmentSLLAIMG { get; private set; }
/// <summary>Ein BlockEinsatz pro Einsatz/Hausbesuch (ESK + EHK-Positionen).</summary>
public List<BlockEinsatz> BlockEinsätze { get; private set; }
/// <summary>
/// ZHK Zusatzinfo Verordnung HK.
/// Laut TA 1-n je INV (eine je Verordnung); hier zunächst eine Verordnung pro Fall.
/// </summary>
public SegmentSLLAZHK SegmentSLLAZHK { get; private set; }
public List<BlockDiagnose> BlockDiagnose { get; private set; }
/// <summary>
/// SKZ ist bei C Pflicht (1-n je ZHK, laut TA zwingend zu übermitteln).
/// Liegen mehrere Kostenzusagen vor, ist das Segment zu wiederholen
/// hier wird zunächst eine Kostenzusage je Fall unterstützt.
/// </summary>
public SegmentSLLASKZ SegmentSLLASKZ { get; private set; }
public SegmentSLLABES SegmentSLLABES { get; private set; }
// Summen-Zugriff für NachrichtSLLA / SLGA
public decimal GesamtbetragBrutto => SegmentSLLABES.GesamtbetragBrutto.DecimalValue;
public BlockKlientHKP()
{
SegmentSLLAINV = new SegmentSLLAINV();
SegmentSLLANAD = new SegmentSLLANAD();
SegmentSLLAIMG = new SegmentSLLAIMG();
BlockEinsätze = new List<BlockEinsatz>();
SegmentSLLAZHK = new SegmentSLLAZHK();
BlockDiagnose = new List<BlockDiagnose>();
SegmentSLLASKZ = new SegmentSLLASKZ();
SegmentSLLABES = new SegmentSLLABES();
}
public override List<Segment> GetAllSegments()
{
var res = new List<Segment>();
res.Add(SegmentSLLAINV);
res.Add(SegmentSLLANAD);
// IMG nur wenn befüllt wie in BlockKlient gehandhabt
foreach (var einsatz in BlockEinsätze)
res.AddRange(einsatz.GetSegments());
res.Add(SegmentSLLAZHK);
foreach (var dia in BlockDiagnose)
res.AddRange(dia.GetSegments());
res.Add(SegmentSLLASKZ);
res.Add(SegmentSLLABES);
return res;
}
public override int GetUNHCount() => 0;
public void Apply(InfoAbrechnungsfall info)
{
// INV
SegmentSLLAINV.VersichertenNummer.SetValue(info.VersichtertenNummer);
SegmentSLLAINV.Versichertenstatus.SetValue(info.Versichertenstatus);
SegmentSLLAINV.Beleginformation.SetValue(info.Beleginformation);
SegmentSLLAINV.Belegnummer.SetValue(info.Belegnummer);
// NAD
SegmentSLLANAD.Vorname.SetValue(info.VersichtertenVorname);
SegmentSLLANAD.Nachname.SetValue(info.VersichtertenNachname);
SegmentSLLANAD.Geburtsdatum.SetValue(info.VersichtertenGeburtstag);
SegmentSLLANAD.StraßeNr.SetValue(info.VersichtertenStraßeNr);
SegmentSLLANAD.PLZ.SetValue(info.VersichtertenPLZ);
SegmentSLLANAD.Wohnort.SetValue(info.VersichtertenWohnort);
SegmentSLLANAD.Länderkennzeichen.SetValue(info.VersichtertenLanderkennung);
// ESK + EHK: je Abrechnungsposition ein eigener Einsatz
// (ein InvoiceItem = ein Einsatz; mehrere Positionen am selben Tag
// können durch den Aufrufer in einem BlockEinsatz zusammengefasst werden)
foreach (var posinfo in info.InfosAbrechnungsposition
.OrderBy(x => x.DatumDerLeistungserbringung))
{
var einsatz = new BlockEinsatz();
einsatz.Apply(posinfo);
BlockEinsätze.Add(einsatz);
}
// ZHK
SegmentSLLAZHK.Betriebsstättennummer.SetValue(
string.IsNullOrWhiteSpace(info.Betriebsstättennummer) ? "999999999" : info.Betriebsstättennummer);
SegmentSLLAZHK.LebenslangeArztnummer.SetValue(
string.IsNullOrWhiteSpace(info.LebenslangeArztnummer) ? "999999999" : info.LebenslangeArztnummer);
SegmentSLLAZHK.Verordnungsdatum.SetValue(info.Verordnungsdatum);
SegmentSLLAZHK.Unfallkennzeichen.SetValue(info.Unfallkennzeichen);
SegmentSLLAZHK.KennzeichenBVGSonstiges.SetValue(info.KennzeichenBVGSonstiges);
SegmentSLLAZHK.KennzeichenVerordnungsbesonderheiten.SetValue(info.KennzeichenVerordnungsbesonderheiten);
// DIA
if (info.DakotaInfoDiagnosen?.Any() == true)
{
foreach (var diagnose in info.DakotaInfoDiagnosen)
{
var block = new BlockDiagnose();
block.Apply(diagnose);
BlockDiagnose.Add(block);
}
}
// SKZ
SegmentSLLASKZ.Genehmigungskennzeichen.SetValue(info.Genehmigungskennzeichen);
SegmentSLLASKZ.DatumGenehmigung.SetValue(info.DatumDerGenehmigung);
SegmentSLLASKZ.ArtGenehmigung.SetValue(info.ArtDerGenehmigung);
// BES
CalculateSums();
}
private void CalculateSums()
{
var gesamtbrutto = BlockEinsätze
.SelectMany(e => e.Positionen)
.Sum(p => p.AnzahlEinheit * p.EinzelbetragAbrechnungsposition);
SegmentSLLABES.GesamtbetragBrutto.SetValue(gesamtbrutto);
}
}
}

View File

@@ -1,4 +1,4 @@
using Dakota.Models.Infos;
using Dakota.Models.Infos;
using Dakota.Models.Nachrichten;
using Dakota.Models.Schlüssels;
using Dakota.Models.Segmente;
@@ -55,6 +55,7 @@ namespace Dakota.Models.Blocke
return list;
}
public override int GetUNHCount()
{
var i = 0;
@@ -74,7 +75,14 @@ namespace Dakota.Models.Blocke
{
BlockKrankenkasse.Add(block);
}
public void Apply(InfoBlockKostentrager info)
/// <param name="info">Infoobjekt für diesen Kostenträger-Block.</param>
/// <param name="isHKP">
/// true = Häusliche Krankenpflege (Sammelgruppenschlüssel C).
/// Wird an BlockKrankenkasse.Apply weitergereicht, damit dort
/// NachrichtSLLA die ESK/EHK-Struktur (BlockKlientHKP) verwendet.
/// </param>
public void Apply(InfoBlockKostentrager info, bool isHKP = false)
{
if (IsSammelrechnung)
{
@@ -91,7 +99,7 @@ namespace Dakota.Models.Blocke
{
var blockkvkarte = new BlockKrankenkasse();
blockkvkarte.Apply(infoblock, IsSammelrechnung);
blockkvkarte.Apply(infoblock, IsSammelrechnung, isHKP);
Add(blockkvkarte);
}
@@ -106,7 +114,7 @@ namespace Dakota.Models.Blocke
private void CalculateSLGA()
{
Dictionary<string, decimal[]> segments = new Dictionary<string, decimal[]>();
var segments = new Dictionary<string, decimal[]>();
foreach (var block in BlockKrankenkasse)
{

View File

@@ -1,4 +1,4 @@
using Dakota.Models.Infos;
using Dakota.Models.Infos;
using Dakota.Models.Nachrichten;
using Dakota.Models.Schlüssels;
using Dakota.Models.Segmente;
@@ -13,24 +13,24 @@ using System.Threading.Tasks;
namespace Dakota.Models.Blocke
{
/// <summary>
/// Wiederhole folgenden Block je IK der Krankenkarte bzw der Verordnung
/// Wiederhole folgenden Block je IK der Krankenkarte bzw. der Verordnung
/// </summary>
internal class BlockKrankenkasse : Block
{
public SegmentUNH SegmentSLGAUNH { get; private set; }
public NachrichtSLGA NachrichtSLGA { get; private set; }
public SegmentUNT SegmentSLGAUNT { get; private set; }
public SegmentUNH SegmentSLLAUNH { get; private set; }
public NachrichtSLLA NachrichtSLLA { get; private set; }
public SegmentUNT SegmentSLLAUNT { get; private set; }
public SegmentUNH SegmentSLGAUNH { get; private set; }
public NachrichtSLGA NachrichtSLGA { get; private set; }
public SegmentUNT SegmentSLGAUNT { get; private set; }
public SegmentUNH SegmentSLLAUNH { get; private set; }
public NachrichtSLLA NachrichtSLLA { get; private set; }
public SegmentUNT SegmentSLLAUNT { get; private set; }
public BlockKrankenkasse()
{
SegmentSLGAUNH = new SegmentUNH();
NachrichtSLGA = new NachrichtSLGA();
NachrichtSLGA = new NachrichtSLGA();
SegmentSLGAUNT = new SegmentUNT(SLGASegmentLength);
SegmentSLLAUNH = new SegmentUNH();
NachrichtSLLA = new NachrichtSLLA();
NachrichtSLLA = new NachrichtSLLA();
SegmentSLLAUNT = new SegmentUNT(SLLASegmentLength);
}
@@ -45,7 +45,7 @@ namespace Dakota.Models.Blocke
public override List<Segment> GetAllSegments()
{
var list = new List<Segment>() { SegmentSLGAUNH };
var list = new List<Segment> { SegmentSLGAUNH };
list.AddRange(NachrichtSLGA.GetSegments());
list.Add(SegmentSLGAUNT);
@@ -61,14 +61,21 @@ namespace Dakota.Models.Blocke
return 2;
}
public void Apply(InfoBlockKrankenkasse blockinfo, bool isSammelrechnung)
/// <param name="blockinfo">Infoobjekt für diesen KV-Karten-Block.</param>
/// <param name="isSammelrechnung">true = Sammelrechnung.</param>
/// <param name="isHKP">
/// true = Häusliche Krankenpflege (Sammelgruppenschlüssel C).
/// Schaltet in NachrichtSLLA auf ESK/EHK-Struktur (BlockKlientHKP) um.
/// </param>
public void Apply(InfoBlockKrankenkasse blockinfo, bool isSammelrechnung, bool isHKP = false)
{
ApplySLGA(blockinfo.DakotaInfoSLGA);
ApplyNachrichtSLGA(blockinfo.DakotaInfoNachrichtSLGA, isSammelrechnung);
ApplySLLA(blockinfo.DakotaInfoSLLA);
ApplyNachrichtSLLA(blockinfo.DakotaInfoNachrichtSLLA);
ApplyNachrichtSLLA(blockinfo.DakotaInfoNachrichtSLLA, isHKP);
CalculateSLGA();
}
private void ApplySLGA(InfoNachricht info)
{
SegmentSLGAUNH.Nachrichtenreferenznummer.SetValue(info.Nachrichtenreferenznummer);
@@ -79,6 +86,7 @@ namespace Dakota.Models.Blocke
SegmentSLGAUNT.Nachrichtenreferenznummer.SetValue(info.Nachrichtenreferenznummer);
}
private void ApplyNachrichtSLGA(InfoNachrichtSLGA info, bool isSammelrechnung)
{
NachrichtSLGA.Apply(info, isSammelrechnung);
@@ -94,40 +102,35 @@ namespace Dakota.Models.Blocke
SegmentSLLAUNT.Nachrichtenreferenznummer.SetValue(info.Nachrichtenreferenznummer);
}
private void ApplyNachrichtSLLA(InfoNachrichtSLLA info)
private void ApplyNachrichtSLLA(InfoNachrichtSLLA info, bool isHKP)
{
NachrichtSLLA.Apply(info);
NachrichtSLLA.Apply(info, isHKP);
}
private void CalculateSLGA()
{
var sumseg = new decimal[3];
var segments = new Dictionary<string, decimal[]>();
Dictionary<string, decimal[]> segments = new Dictionary<string, decimal[]>();
// G/N: ENF-basierte Fälle
foreach (var fall in NachrichtSLLA.BlockKlienten)
{
var versicherten_status = fall.SegmentSLLAINV.Versichertenstatus.GetValue();
var schlüssel_summenstatus = SchlüsselSummenstatus.Parse(versicherten_status);
var status = schlüssel_summenstatus.Value;
AccumulateFall(
fall.SegmentSLLAINV.Versichertenstatus.GetValue(),
fall.GesamtbetragBrutto,
fall.GesamtbetragGesetzlicheZuzahlung + fall.GesamtbetragEigenanteil,
segments, sumseg);
}
if (!segments.ContainsKey(status))
{
segments.Add(status, new decimal[3]);
}
var segment = segments[status];
decimal bruttobetrag = fall.GesamtbetragBrutto;
decimal zuzahlung = fall.GesamtbetragGesetzlicheZuzahlung + fall.GesamtbetragEigenanteil;
decimal rechnungsbetrag = bruttobetrag - zuzahlung;
segment[0] += rechnungsbetrag;
segment[1] += bruttobetrag;
segment[2] += zuzahlung;
sumseg[0] += rechnungsbetrag;
sumseg[1] += bruttobetrag;
sumseg[2] += zuzahlung;
// C: ESK/EHK-basierte Fälle (Häusliche Krankenpflege)
foreach (var fall in NachrichtSLLA.BlockKlientenHKP)
{
AccumulateFall(
fall.SegmentSLLAINV.Versichertenstatus.GetValue(),
fall.GesamtbetragBrutto,
zuzahlung: 0, // HKP hat keine gesetzliche Zuzahlung im BES
segments, sumseg);
}
NachrichtSLGA.SegmentGES00.Status.SetValue(SchlüsselSummenstatus.Gesamtsumme);
@@ -138,7 +141,7 @@ namespace Dakota.Models.Blocke
foreach (var key in segments.Keys.OrderBy(x => x))
{
var segment = new SegmentSLGAGES();
var array = segments[key];
var array = segments[key];
segment.Status.SetValue(key);
segment.Gesamtrechnungsbetrag.SetValue(array[0]);
@@ -148,5 +151,29 @@ namespace Dakota.Models.Blocke
NachrichtSLGA.ListSegmentGES.Add(segment);
}
}
private void AccumulateFall(
string versichertenStatus,
decimal bruttobetrag,
decimal zuzahlung,
Dictionary<string, decimal[]> segments,
decimal[] sumseg)
{
var schlüssel = SchlüsselSummenstatus.Parse(versichertenStatus);
var status = schlüssel.Value;
if (!segments.ContainsKey(status))
segments.Add(status, new decimal[3]);
var seg = segments[status];
var rechnungsbetrag = bruttobetrag - zuzahlung;
seg[0] += rechnungsbetrag;
seg[1] += bruttobetrag;
seg[2] += zuzahlung;
sumseg[0] += rechnungsbetrag;
sumseg[1] += bruttobetrag;
sumseg[2] += zuzahlung;
}
}
}

View File

@@ -1,5 +1,6 @@
using Dakota.Models.Infos;
using Dakota.Models.Infos;
using Dakota.Models.Nachrichten;
using Dakota.Models.Schlüssels;
using Dakota.Models.Segmente;
using System;
using System.Collections.Generic;
@@ -10,13 +11,13 @@ using System.Threading.Tasks;
namespace Dakota.Models.Blocke
{
/// <summary>
/// Nutzdatendatei ohne Logik
/// Nutzdatendatei ohne Logik.
/// </summary>
internal class Nutzdatendatei : Block
{
public DakotaFile Parent { get; set; }
public SegmentUNB SegmentUNB { get; private set; }
public SegmentUNB SegmentUNB { get; private set; }
public List<BlockKostenträger> BlockKostenträger { get; private set; }
public SegmentUNZ SegmentUNZ { get; private set; }
@@ -43,6 +44,7 @@ namespace Dakota.Models.Blocke
return list;
}
public override int GetUNHCount()
{
int i = 0;
@@ -59,8 +61,13 @@ namespace Dakota.Models.Blocke
{
BlockKostenträger.Add(blockkosten);
}
public void Apply(InfoDateiNutzdaten info, bool isSammelrechnung)
{
// isHKP: true fuer Haeusliche Krankenpflege (Sammelgruppenschlüssel C)
var isHKP = info.Leistungsbereich?.Value ==
SchlüsselLeistungserbringerSammelgruppenschlussel.LeistungserbringerVonHäuslicherKrankenpflege.Value;
SegmentUNB.SyntaxKennung.SetValue(info.SyntaxKennung);
SegmentUNB.SyntaxVersionsnummer.SetValue(info.SyntaxVersion);
SegmentUNB.Absenderdatei.SetValue(info.Absenderbezeichnung);
@@ -75,9 +82,7 @@ namespace Dakota.Models.Blocke
foreach (var blockinfo in info.BlockKostentragers)
{
var block = new BlockKostenträger(isSammelrechnung);
block.Apply(blockinfo);
block.Apply(blockinfo, isHKP);
Add(block);
}

View File

@@ -1,9 +1,6 @@
using Dakota.Models.Schlüssels;
using Dakota.Models.Schlüssels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dakota.Models.Infos
{
@@ -18,7 +15,7 @@ namespace Dakota.Models.Infos
public SchlüsselPosArtDerEinrichtung AbrechnungspositionArtDerEinrichtung { get; set; }
public SchlüsselPosBehandlungsart AbrechnungspositionBehandlungsart { get; set; }
public SchlüsselPosVergütungsart AbrechnungspositionVergütungsart { get; set; }
public decimal AnzahlMenge { get; set; }
public decimal EinzelbetragAbrechnungsposition { get; set; }
public DateTime? DatumDerLeistungserbringung { get; set; }
@@ -31,6 +28,19 @@ namespace Dakota.Models.Infos
public string Text { get; set; }
/// <summary>
/// Beschäftigtennummer nach § 293 Abs. 8 Satz 2 SGB V der Person,
/// die die Leistung erbracht hat (Pflichtfeld bei SLLA: C Häusliche Krankenpflege).
/// Bei fehlendem Wert Ersatzwert gemäß Anlage 3, Schlüsseltabelle 8.1.19 verwenden.
/// </summary>
public string Beschäftigtennummer { get; set; }
/// <summary>
/// Optionale Beschäftigtennummer einer zweiten Person (SLLA: C).
/// Wird zum Pflichtfeld, sobald zwei Personen die Leistung erbracht haben.
/// </summary>
public string Beschäftigtennummer2 { get; set; }
internal string GetAbrechnungsposition()
{
return AbrechnungspositionString ?? Abrechnungsposition.Value;

View File

@@ -1,80 +1,86 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Dakota.Models.Blocke;
using Dakota.Models.Infos;
using Dakota.Models.Schlüssels;
using Dakota.Models.Segmente;
using Dakota.Models.Segmente.SLLA;
namespace Dakota.Models.Nachrichten
{
/// <summary>
/// Leistungserbringer
/// </summary>
internal class NachrichtSLLA : Nachricht
{
/// <summary>
/// Das Segment enthält Informationen über den tatsächlichen
/// Leistungserbringer und das IK der Krankenkasse von der
/// Krankenversichertenkarte bzw.der ärztlichen Verordnung bezogen auf die folgenden Abrechnungsfälle.Es kommt je Nachricht nur einmal vor.
/// </summary>
public SegmentSLLAFKT SegmentSLLAFKT { get; private set; }
/// <summary>
/// Das Segment enthält die Rechnungsinformationen, wie Rechnungsnummer und Rechnungsdatum
/// </summary>
public SegmentSLLAREC SegmentSLLAREC { get; private set; }
/// <summary>
/// Abrechnungsfälle (INV - BES)
/// </summary>
public List<BlockKlient> BlockKlienten { get; set; }
/// <summary>
/// Leistungserbringer Abrechnungsdaten (SLLA).
/// Unterstützt G/N (ENF-basiert via BlockKlient) und
/// C Häusliche Krankenpflege (ESK/EHK-basiert via BlockKlientHKP).
/// </summary>
internal class NachrichtSLLA : Nachricht
{
public SegmentSLLAFKT SegmentSLLAFKT { get; private set; }
public SegmentSLLAREC SegmentSLLAREC { get; private set; }
/// <summary>Abrechnungsfälle für G/N (ENF-Struktur).</summary>
public List<BlockKlient> BlockKlienten { get; set; }
/// <summary>Abrechnungsfälle für C Häusliche Krankenpflege (ESK/EHK-Struktur).</summary>
public List<BlockKlientHKP> BlockKlientenHKP { get; set; }
public NachrichtSLLA()
{
SegmentSLLAFKT = new SegmentSLLAFKT();
SegmentSLLAREC = new SegmentSLLAREC();
public NachrichtSLLA()
{
SegmentSLLAFKT = new SegmentSLLAFKT();
SegmentSLLAREC = new SegmentSLLAREC();
BlockKlienten = new List<BlockKlient>();
BlockKlientenHKP = new List<BlockKlientHKP>();
}
BlockKlienten = new List<BlockKlient>();
}
public override List<Segment> GetAllSegments()
{
var list = new List<Segment> { SegmentSLLAFKT, SegmentSLLAREC };
public override List<Segment> GetAllSegments()
{
var list = new List<Segment>() { SegmentSLLAFKT, SegmentSLLAREC };
foreach (var block in BlockKlienten)
list.AddRange(block.GetSegments());
foreach (var block in BlockKlienten)
{
list.AddRange(block.GetSegments());
}
foreach (var block in BlockKlientenHKP)
list.AddRange(block.GetSegments());
return list;
}
return list;
}
public void Add(BlockKlient fall)
{
BlockKlienten.Add(fall);
}
public void Apply(InfoNachrichtSLLA info)
{
SegmentSLLAFKT.Verarbeitungskennzeichen.SetValue(info.Verarbeitungskennzeichen);
SegmentSLLAFKT.IKLeistungserbringers.SetValue(info.IKLeistungserbringer);
SegmentSLLAFKT.IKKostenträgers.SetValue(info.IKKostentrager);
SegmentSLLAFKT.IKKrankenkasse.SetValue(info.IKKrankenkasse);
//SegmentSLLAFKT.IKRechnungsstellers.SetValue(info.IKAbsender);
public void Add(BlockKlient fall) => BlockKlienten.Add(fall);
public void Add(BlockKlientHKP fall) => BlockKlientenHKP.Add(fall);
foreach (var infofall in info.Abrechnungsfalle.OrderBy(x => x.InfosAbrechnungsposition.Min(y => y.DatumDerLeistungserbringung)))
{
var block = new BlockKlient();
/// <summary>
/// Befüllt die Nachricht. Für Häusliche Krankenpflege (Sammelgruppenschlüssel C)
/// isHKP = true übergeben dann wird BlockKlientHKP (ESK/EHK) statt BlockKlient (ENF) verwendet.
/// </summary>
public void Apply(InfoNachrichtSLLA info, bool isHKP = false)
{
SegmentSLLAFKT.Verarbeitungskennzeichen.SetValue(info.Verarbeitungskennzeichen);
SegmentSLLAFKT.IKLeistungserbringers.SetValue(info.IKLeistungserbringer);
SegmentSLLAFKT.IKKostenträgers.SetValue(info.IKKostentrager);
SegmentSLLAFKT.IKKrankenkasse.SetValue(info.IKKrankenkasse);
block.Apply(infofall);
foreach (var infofall in info.Abrechnungsfalle
.OrderBy(x => x.InfosAbrechnungsposition.Min(y => y.DatumDerLeistungserbringung)))
{
if (isHKP)
{
var block = new BlockKlientHKP();
block.Apply(infofall);
Add(block);
}
else
{
var block = new BlockKlient();
block.Apply(infofall);
Add(block);
}
}
Add(block);
}
SegmentSLLAREC.SammelRechnungsnummer.SetValue(info.Rechnungsnummer);
SegmentSLLAREC.EinzelRechnungsnummer.SetValue("0");
SegmentSLLAREC.Rechnungsdatum.SetValue(info.Rechnungsdatum);
SegmentSLLAREC.Rechnungsart.SetValue(info.Rechnungsart);
}
}
SegmentSLLAREC.SammelRechnungsnummer.SetValue(info.Rechnungsnummer);
SegmentSLLAREC.EinzelRechnungsnummer.SetValue("0");
SegmentSLLAREC.Rechnungsdatum.SetValue(info.Rechnungsdatum);
SegmentSLLAREC.Rechnungsart.SetValue(info.Rechnungsart);
}
}
}

View File

@@ -0,0 +1,72 @@
using Dakota.Models.Daten;
using System.Collections.Generic;
namespace Dakota.Models.Segmente.SLLA
{
/// <summary>
/// EHK Einzelfallnachweis Häusliche Krankenpflege (SLLA: C).
/// Das Segment ist je Einsatz/Hausbesuch 1-n mal zu übermitteln.
/// Das letzte EHK kennzeichnet das Einsatzende.
/// </summary>
internal class SegmentSLLAEHK : Segment
{
/// <summary>Datenelementgruppe Abrechnungscode:Tarifkennzeichen.</summary>
public Datenelementgruppe Leistungserbringergruppe { get; private set; }
public Datenelement Abrechnungscode { get; private set; }
public Datenelement Tarifkennzeichen { get; private set; }
/// <summary>Zu vergütende Abrechnungspositionsnummer (Anlage 3, Abschnitt 8.2.4).</summary>
public Datenelement ArtLeistung { get; private set; }
/// <summary>Anzahl der Abrechnungspositionen. Max. ..4,2.</summary>
public DatenelementDecimal AnzahlMenge { get; private set; }
/// <summary>
/// Einzelpreis inkl. MwSt. Als Einzelpreis ist immer der vereinbarte
/// Preis einschließlich Mehrwertsteuer einer Abrechnungsposition zu verstehen.
/// </summary>
public DatenelementDecimal EinzelbetragAbrechnungsposition { get; private set; }
/// <summary>Anzahl der gefahrenen Kilometer (Kann-Feld).</summary>
public DatenelementDecimal GefahreneKilometer { get; private set; }
/// <summary>
/// Beschäftigtennummer nach § 293 Abs. 8 Satz 2 SGB V der Person,
/// die die Leistung erbracht hat. Pflichtfeld bei fehlendem Wert
/// ist ein Ersatzwert gemäß Anlage 3, Schlüsseltabelle 8.1.19 anzugeben.
/// </summary>
public Datenelement Beschäftigtennummer1 { get; private set; }
/// <summary>
/// Beschäftigtennummer der zweiten Person (Kann-Feld; wird zum
/// Muss-Feld, sobald eine zweite Person die Leistung erbracht hat).
/// </summary>
public Datenelement Beschäftigtennummer2 { get; private set; }
public SegmentSLLAEHK() : base(Feldart.Muss)
{
Leistungserbringergruppe = new Datenelementgruppe("Leistungserbringergruppe", 2);
Abrechnungscode = Leistungserbringergruppe.Datenelemente[0] = new Datenelement("Abrechnungscode", 2, Feldart.Muss);
Tarifkennzeichen = Leistungserbringergruppe.Datenelemente[1] = new Datenelement("Tarifkennzeichen", 5, Feldart.Muss);
ArtLeistung = new Datenelement("ArtLeistung", 0, 10, Feldart.Muss);
AnzahlMenge = new DatenelementDecimal("AnzahlMenge", 3, 7, Feldart.Muss);
EinzelbetragAbrechnungsposition = new DatenelementDecimal("EinzelbetragAbrechnungsposition", 3, 13, Feldart.Muss);
GefahreneKilometer = new DatenelementDecimal("GefahreneKilometer", 0, 6, Feldart.Kann);
Beschäftigtennummer1 = new Datenelement("Beschäftigtennummer1", 9, Feldart.Muss);
Beschäftigtennummer2 = new Datenelement("Beschäftigtennummer2", 9, Feldart.Kann);
}
public override string GetHead() => "EHK";
public override List<Dateneinheit> GetBody()
=> new List<Dateneinheit>
{
Leistungserbringergruppe,
ArtLeistung,
AnzahlMenge,
EinzelbetragAbrechnungsposition,
GefahreneKilometer,
Beschäftigtennummer1,
Beschäftigtennummer2
};
}
}

View File

@@ -0,0 +1,33 @@
using Dakota.Models.Daten;
using System.Collections.Generic;
namespace Dakota.Models.Segmente.SLLA
{
/// <summary>
/// ELP Erbrachte unterschiedliche Leistungen je Leistungspauschale (SLLA: C).
/// Das Segment ist je EHK 0-n mal zu übermitteln.
/// Wird eine Leistungspauschale abgerechnet, sind hier die im Rahmen
/// der Leistungspauschale erbrachten Einzelleistungen zwingend anzugeben.
/// </summary>
internal class SegmentSLLAELP : Segment
{
/// <summary>
/// Abrechnungspositionsnummer der erbrachten Einzelleistung
/// (Anlage 3, Abschnitt 8.2.4).
/// </summary>
public Datenelement Abrechnungspositionsnummer { get; private set; }
/// <summary>Anzahl der Abrechnungspositionen. Max. ..4,2.</summary>
public DatenelementDecimal AnzahlMenge { get; private set; }
public SegmentSLLAELP() : base(Feldart.Kann)
{
Abrechnungspositionsnummer = new Datenelement("Abrechnungspositionsnummer", 0, 10, Feldart.Muss);
AnzahlMenge = new DatenelementDecimal("AnzahlMenge", 3, 7, Feldart.Muss);
}
public override string GetHead() => "ELP";
public override List<Dateneinheit> GetBody()
=> new List<Dateneinheit> { Abrechnungspositionsnummer, AnzahlMenge };
}
}

View File

@@ -0,0 +1,37 @@
using Dakota.Models.Daten;
using System.Collections.Generic;
namespace Dakota.Models.Segmente.SLLA
{
/// <summary>
/// ESK Informationen zum Einsatz/Hausbesuch (SLLA: C Häusliche Krankenpflege).
/// Das Segment ist je Abrechnungsfall 1-n mal zu übermitteln.
/// Gilt als Beginn-Segment für einen Einsatz/Hausbesuch.
/// </summary>
internal class SegmentSLLAESK : Segment
{
/// <summary>Tag der Leistungserbringung (JJJJMMTT).</summary>
public DatenelementDateTime DatumLeistungserbringung { get; private set; }
/// <summary>Beginn des Einsatzes (HHMM). Wertebereich HH 0023, MM 0059.</summary>
public DatenelementDateTime UhrzeitBeginn { get; private set; }
/// <summary>Ende des Einsatzes (HHMM). Kann-Feld.</summary>
public DatenelementDateTime UhrzeitEnde { get; private set; }
/// <summary>Zeitangabe in Minuten. Kann-Feld.</summary>
public Datenelement Dauer { get; private set; }
public SegmentSLLAESK() : base(Feldart.Muss)
{
DatumLeistungserbringung = new DatenelementDateTime("DatumLeistungserbringung", 8, "yyyyMMdd", Feldart.Muss);
UhrzeitBeginn = new DatenelementDateTime("UhrzeitBeginn", 4, "HHmm", Feldart.Muss);
UhrzeitEnde = new DatenelementDateTime("UhrzeitEnde", 4, "HHmm", Feldart.Kann);
Dauer = new Datenelement("Dauer", 0, 4, Feldart.Kann);
}
public override string GetHead() => "ESK";
public override List<Dateneinheit> GetBody()
=> new List<Dateneinheit> { DatumLeistungserbringung, UhrzeitBeginn, UhrzeitEnde, Dauer };
}
}

View File

@@ -0,0 +1,59 @@
using Dakota.Models.Daten;
using System.Collections.Generic;
namespace Dakota.Models.Segmente.SLLA
{
/// <summary>
/// ZHK Zusatzinfo Verordnung für Häusliche Krankenpflege (SLLA: C).
/// Das Segment ist für jede Verordnung zu übermitteln.
/// </summary>
internal class SegmentSLLAZHK : Segment
{
/// <summary>
/// Betriebsstättennummer aus der Verordnung (zwingend).
/// Falls nicht vorhanden: 999999999 angeben.
/// </summary>
public Datenelement Betriebsstättennummer { get; private set; }
/// <summary>
/// Lebenslange Arztnummer aus der Verordnung (zwingend).
/// Falls nicht vorhanden: 999999999 angeben.
/// Auffüllen auf 9 Stellen ist unzulässig.
/// </summary>
public Datenelement LebenslangeArztnummer { get; private set; }
/// <summary>Verordnungsdatum (JJJJMMTT).</summary>
public DatenelementDateTime Verordnungsdatum { get; private set; }
/// <summary>Siehe Schlüssel Unfall/Sonstiges Anlage 3 Abschnitt 8.1.2.</summary>
public Datenelement Unfallkennzeichen { get; private set; }
/// <summary>Siehe Schlüssel BVG/SER Anlage 3 Abschnitt 8.1.2.1.</summary>
public Datenelement KennzeichenBVGSonstiges { get; private set; }
/// <summary>Siehe Schlüssel Kennzeichen Verordnungsbesonderheiten Anlage 3 Abschnitt 8.1.11.</summary>
public Datenelement KennzeichenVerordnungsbesonderheiten { get; private set; }
public SegmentSLLAZHK() : base(Feldart.Muss)
{
Betriebsstättennummer = new Datenelement("Betriebsstättennummer", 0, 9, Feldart.Muss);
LebenslangeArztnummer = new Datenelement("LebenslangeArztnummer", 0, 9, Feldart.Muss);
Verordnungsdatum = new DatenelementDateTime("Verordnungsdatum", 8, "yyyyMMdd", Feldart.Muss);
Unfallkennzeichen = new Datenelement("Unfallkennzeichen", 1, Feldart.Kann);
KennzeichenBVGSonstiges = new Datenelement("KennzeichenBVGSonstiges", 1, Feldart.Kann);
KennzeichenVerordnungsbesonderheiten = new Datenelement("KennzeichenVerordnungsbesonderheiten", 1, Feldart.Kann);
}
public override string GetHead() => "ZHK";
public override List<Dateneinheit> GetBody()
=> new List<Dateneinheit>
{
Betriebsstättennummer,
LebenslangeArztnummer,
Verordnungsdatum,
Unfallkennzeichen,
KennzeichenBVGSonstiges,
KennzeichenVerordnungsbesonderheiten
};
}
}

View File

@@ -0,0 +1,51 @@
-- Wie viel Prozent der Stunden wurden bei Leistungskategorie Qualifiziert durch Assistenzkraft erbracht und andersrum
-- 3432911735 (APP4) Caritasverband GünzburgNeuUlm
-- *** Mapping (kundenspezifisch anpassen) ***
-- Leistungskategorie 'Qualifiziert' -> passende Qualifikation: Q1, Q2
-- Leistungskategorie 'Unterstützend' -> passende Qualifikation: Q3, Q4
SELECT
p.LastName AS 'Nachname',
p.Firstname AS 'Vorname',
c2s.ApprovedStartDate AS 'Bewilligt von',
c2s.ApprovedEndDate AS 'Bewilligt bis',
ROUND(SUM(CASE WHEN scat.Name = 'Qualifiziert' AND q12.EmployeeOid IS NOT NULL THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END) / 60, 2) AS 'Qualifiziert durch Q1/Q2',
ROUND(SUM(CASE WHEN scat.Name = 'Qualifiziert' AND q34.EmployeeOid IS NOT NULL THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END) / 60, 2) AS 'Qualifiziert durch Q3/Q4',
ROUND(SUM(CASE WHEN scat.Name = 'Unterstützend' AND q12.EmployeeOid IS NOT NULL THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END) / 60, 2) AS 'Unterstützend durch Q1/Q2',
ROUND(SUM(CASE WHEN scat.Name = 'Unterstützend' AND q34.EmployeeOid IS NOT NULL THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END) / 60, 2) AS 'Unterstützend durch Q3/Q4',
ROUND(SUM(CASE WHEN q12.EmployeeOid IS NULL AND q34.EmployeeOid IS NULL THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END) / 60, 2) AS 'Ohne Qualifikation',
ROUND(SUM(sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount)) / 60, 2) AS 'Gesamt (Std)',
-- Unterqualifiziert: Qualifiziert durch Q3/Q4 in %
ROUND(SUM(CASE WHEN scat.Name = 'Qualifiziert' AND q34.EmployeeOid IS NOT NULL THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END)
/ NULLIF(SUM(CASE WHEN scat.Name = 'Qualifiziert' THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END), 0) * 100, 1) AS '% Unterqualifiziert',
-- Überqualifiziert: Unterstützend durch Q1/Q2 in %
ROUND(SUM(CASE WHEN scat.Name = 'Unterstützend' AND q12.EmployeeOid IS NOT NULL THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END)
/ NULLIF(SUM(CASE WHEN scat.Name = 'Unterstützend' THEN sr.Roundedduration / IF(sr.GroupEmployeeCount IS NULL, 1, sr.GroupEmployeeCount) ELSE 0 END), 0) * 100, 1) AS '% Überqualifiziert'
FROM servicerecord sr
JOIN costbearer2supportconcept c2s ON sr.CostBearer2SupportConceptOid = c2s.Oid
JOIN supportconcept sc ON c2s.SupportConceptOid = sc.Oid
JOIN customer c ON sc.CustomerOid = c.Oid
JOIN person p ON c.PersonOid = p.Oid
JOIN servicedescription sd ON sd.Oid = sr.ServiceDescriptionOid
JOIN servicecategory scat ON scat.Oid = sd.ServiceCategoryOid
-- *** Mapping (kundenspezifisch anpassen) ***
LEFT JOIN (
SELECT DISTINCT v2o.ObjectOid AS EmployeeOid
FROM valuelistentry2object v2o
JOIN valuelistentry vle ON vle.Oid = v2o.ValuelistEntryOid
WHERE v2o.ObjectTid = 2 AND v2o.IsActive = 1 AND vle.Type = 5 AND vle.IsActive = 1 AND vle.Value IN ('Q1', 'Q2') -- Qualifikationen für 'Qualifiziert'
) q12 ON q12.EmployeeOid = sr.EmployeeOid
LEFT JOIN (
SELECT DISTINCT v2o.ObjectOid AS EmployeeOid
FROM valuelistentry2object v2o
JOIN valuelistentry vle ON vle.Oid = v2o.ValuelistEntryOid
WHERE v2o.ObjectTid = 2 AND v2o.IsActive = 1 AND vle.Type = 5 AND vle.IsActive = 1 AND vle.Value IN ('Q3', 'Q4') -- Qualifikationen für 'Unterstützend'
) q34 ON q34.EmployeeOid = sr.EmployeeOid
-- *** Ende Mapping ***
WHERE scat.Billable = 1 AND c2s.ApprovedStartDate <= CURDATE() AND (c2s.ApprovedEndDate >= CURDATE() OR c2s.ApprovedEndDate IS NULL)
-- AND sr.StartDate >= ':Von' AND sr.StartDate < ':Bis'
GROUP BY p.LastName, p.Firstname, c2s.ApprovedStartDate, c2s.ApprovedEndDate
ORDER BY p.LastName;

View File

@@ -0,0 +1,78 @@
-- Query- für Herrn Ferchland - 2385915144 (APP6)
-- Hilfepläne mit aktuellen Bewilligungen (max 3 Bew mit Leistungskategorie u Stunden / Woche + Betreuern)
SELECT
base.Nachname, base.Vorname, base.Kostentraeger, base.`Bewilligt von`, base.`Bewilligt bis`, base.`Bewilligung 1`, base.`Stunden 1`,
-- Betreuer für SCAP 1
(SELECT GROUP_CONCAT(CONCAT(p2.`FirstName`, ' ', p2.`LastName`) ORDER BY scap2e.EmployeeOid SEPARATOR ', ')
FROM supportconceptapprovalperiod2employee scap2e
INNER JOIN `employee` e ON scap2e.`EmployeeOid` = e.`Oid`
INNER JOIN `person` p2 ON e.`PersonOid` = p2.`Oid`
WHERE scap2e.SupportConceptApprovalPeriodOid = base.scap1_oid
) AS 'Betreuer 1',
base.`Bewilligung 2`, base.`Stunden 2`,
-- Betreuer für SCAP 2
(SELECT GROUP_CONCAT(
CONCAT(p2.`FirstName`, ' ', p2.`LastName`)
ORDER BY scap2e.EmployeeOid SEPARATOR ', ')
FROM supportconceptapprovalperiod2employee scap2e
INNER JOIN `employee` e ON scap2e.`EmployeeOid` = e.`Oid`
INNER JOIN `person` p2 ON e.`PersonOid` = p2.`Oid`
WHERE scap2e.SupportConceptApprovalPeriodOid = base.scap2_oid
) AS 'Betreuer 2',
base.`Bewilligung 3`, base.`Stunden 3`,
-- Betreuer für SCAP 3
(SELECT GROUP_CONCAT(
CONCAT(p2.`FirstName`, ' ', p2.`LastName`)
ORDER BY scap2e.EmployeeOid SEPARATOR ', ')
FROM supportconceptapprovalperiod2employee scap2e
INNER JOIN `employee` e ON scap2e.`EmployeeOid` = e.`Oid`
INNER JOIN `person` p2 ON e.`PersonOid` = p2.`Oid`
WHERE scap2e.SupportConceptApprovalPeriodOid = base.scap3_oid
) AS 'Betreuer 3'
FROM (
-- Kernabfrage Bewilligungen ohne Betreuuer
SELECT
p.LastName AS Nachname,
p.FirstName AS Vorname,
o.`Name` AS Kostentraeger,
cb2sc.ApprovedStartDate AS 'Bewilligt von',
cb2sc.ApprovedEndDate AS 'Bewilligt bis',
MAX(CASE WHEN scap.rn = 1 THEN ROUND(scap.ApprovedBEPerInterval, 2) END) AS 'Stunden 1',
MAX(CASE WHEN scap.rn = 1 THEN CONCAT(DATE_FORMAT(scap.Start, '%d.%m.%Y'), ' - ', DATE_FORMAT(scap.EndDate, '%d.%m.%Y'), ' ', cat1.Name) END) AS 'Bewilligung 1',
MAX(CASE WHEN scap.rn = 2 THEN ROUND(scap.ApprovedBEPerInterval, 2) END) AS 'Stunden 2',
MAX(CASE WHEN scap.rn = 2 THEN CONCAT(DATE_FORMAT(scap.Start, '%d.%m.%Y'), ' - ', DATE_FORMAT(scap.EndDate, '%d.%m.%Y'), ' ', cat2.Name) END) AS 'Bewilligung 2',
MAX(CASE WHEN scap.rn = 3 THEN ROUND(scap.ApprovedBEPerInterval, 2) END) AS 'Stunden 3',
MAX(CASE WHEN scap.rn = 3 THEN CONCAT(DATE_FORMAT(scap.Start, '%d.%m.%Y'), ' - ', DATE_FORMAT(scap.EndDate, '%d.%m.%Y'), ' ', cat3.Name) END) AS 'Bewilligung 3',
-- Hilfsspalten: OIDs der 4 SCRAPs für die Betreuer-Subqueries
MAX(CASE WHEN scap.rn = 1 THEN scap.Oid END) AS scap1_oid,
MAX(CASE WHEN scap.rn = 2 THEN scap.Oid END) AS scap2_oid,
MAX(CASE WHEN scap.rn = 3 THEN scap.Oid END) AS scap3_oid
FROM `person` p
INNER JOIN `customer` c ON p.Oid = c.PersonOid
LEFT JOIN team2customer t2c ON c.Oid = t2c.CustomerOid
LEFT JOIN team t ON t2c.TeamOid = t.Oid
INNER JOIN `supportconcept` sc ON c.Oid = sc.CustomerOid
INNER JOIN `costbearer2supportconcept` cb2sc ON sc.Oid = cb2sc.SupportConceptOid
INNER JOIN `costbearer` cb ON cb2sc.`CostBearerOid` = cb.`Oid`
INNER JOIN `organisation` o ON cb.`Oid` = o.`CostBearerOid`
INNER JOIN (
SELECT s1.Oid, s1.CostBearer2SupportConceptOid, s1.ApprovedBEPerInterval,
s1.Start, s1.EndDate, s1.ServiceCategoryOid, s1.Notice,
COUNT(s2.Oid) + 1 AS rn
FROM `supportconceptapprovalperiod` s1
LEFT JOIN `supportconceptapprovalperiod` s2
ON s1.CostBearer2SupportConceptOid = s2.CostBearer2SupportConceptOid
-- AND s1.Start <= CURDATE() AND (s1.EndDate IS NULL OR s1.EndDate >= CURDATE())
AND (s2.Start < s1.Start OR (s2.Start = s1.Start AND s2.Oid < s1.Oid))
-- WHERE s1.Start <= CURDATE() AND (s1.EndDate IS NULL OR s1.EndDate >= CURDATE())
GROUP BY s1.Oid, s1.CostBearer2SupportConceptOid, s1.ApprovedBEPerInterval, s1.Start, s1.EndDate, s1.ServiceCategoryOid, s1.Notice
) scap ON cb2sc.Oid = scap.CostBearer2SupportConceptOid
LEFT JOIN servicecategory cat1 ON scap.ServiceCategoryOid = cat1.Oid AND scap.rn = 1
LEFT JOIN servicecategory cat2 ON scap.ServiceCategoryOid = cat2.Oid AND scap.rn = 2
LEFT JOIN servicecategory cat3 ON scap.ServiceCategoryOid = cat3.Oid AND scap.rn = 3
WHERE c.IsActive = 1 AND sc.IsActive = 1
GROUP BY p.Oid, p.LastName, p.FirstName, p.DateOfBirth, o.`Name`, cb2sc.ApprovedStartDate, cb2sc.ApprovedEndDate
ORDER BY t.Name, p.LastName
) base;

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Report;
@@ -24,7 +25,6 @@ namespace BeWo.Report.DefaultReports.Alt
{
lblNotice.Visible = false;
}
if (pRO.InvoiceItems != null && pRO.InvoiceItems.Count == 1)
{
var ii = pRO.InvoiceItems[0];
@@ -35,7 +35,7 @@ namespace BeWo.Report.DefaultReports.Alt
}
if (!isDefaultSpitzabrechnung)
{
if (pRO.DifferentHourlyRateCount > 0 && pRO.HourlyRateNew.HasValue)
if (pRO.DifferentHourlyRateCount > 0 && pRO.HourlyRateNew.HasValue && !pRO.InvoiceItems.Any(d => d.ItemDescription != null && d.ItemDescription.Contains("Storno")))
{
isDefaultSpitzabrechnung = true;
}
@@ -70,11 +70,19 @@ namespace BeWo.Report.DefaultReports.Alt
{
foreach (var ii in pRO.InvoiceItems)
{
ii.ItemDescription = String.Format("{0:dd.MM.yyyy} bis {1:dd.MM.yyyy}: {2:0.00##} FLS {3}x {4:c}",
if (ii.ItemDescription != null && ii.ItemDescription.Contains("Storno"))
{
ii.ItemDescription = String.Format("Ausbuchung zur vorherigen Rechnung - {0:dd.MM.yyyy} bis {1:dd.MM.yyyy}",
ii.ItemPeriodStart, ii.ItemPeriodEnd);
}
else
{
ii.ItemDescription = String.Format("{0:dd.MM.yyyy} bis {1:dd.MM.yyyy}: {2:0.00##} FLS {3}x {4:c}",
ii.ItemPeriodStart, ii.ItemPeriodEnd,
ii.UnitCount, ii.RateFactor == 0 ? "" : "x " + pRO.RateFactorText2 + " ",
ii.AmountPerUnit);
}
}
}
}
}
}

View File

@@ -223,15 +223,20 @@ namespace BeWo.Report.ReportObjects
{
records = new List<ServiceRecordDC>();
}
// AB, 22.04.2026: Bugfix wenn Betreuung beendet und ein Zeitraum über Ende hinweg gewählt wird
var terminationDate = ro.Costbearer2Supportconcept.SupportConcept.Customer.TerminationDate;
DateTime? effectiveEnd = end;
if (terminationDate.HasValue && (!effectiveEnd.HasValue || terminationDate.Value < effectiveEnd.Value))
{
effectiveEnd = terminationDate.Value;
}
//1.
if (ro.SupportConceptApprovalPeriod != null && ro.SupportConceptApprovalPeriod.ServiceCategory != null)
{
ro.Leistungskategorie = ro.SupportConceptApprovalPeriod.ServiceCategory.Name;
ro.ServiceRecords = records.Where(sr =>
sr.ServiceDescription.Category.ServiceCategoryOid == ro.SupportConceptApprovalPeriod.ServiceCategory.ServiceCategoryOid)
.ToList();
ro.ServiceRecords = records.Where(sr => sr.ServiceDescription.Category.ServiceCategoryOid == ro.SupportConceptApprovalPeriod.ServiceCategory.ServiceCategoryOid).ToList();
}
else
{
@@ -272,7 +277,7 @@ namespace BeWo.Report.ReportObjects
}
else
{
ro.ApprovedHours = calc.GetApprovedHoursTillNow(ro.Costbearer2Supportconcept, end.Value) ?? 0;
ro.ApprovedHours = calc.GetApprovedHoursTillNow(ro.Costbearer2Supportconcept, effectiveEnd.Value) ?? 0;
}
ro.StundenNichtFehlkontakte = calc.GetBillableDurationInMinutes(flsRecords.Where(sr => sr.Start.Value.Date < end.Value.AddDays(1)).ToList()) / 60;
ro.StundenFehlkontakte = calc.GetBillableDurationInMinutes(fkRecords.Where(sr => sr.Start.Value.Date < end.Value.AddDays(1)).ToList()) / 60;
@@ -317,20 +322,20 @@ namespace BeWo.Report.ReportObjects
}
if (ro.SupportConceptApprovalPeriod != null)
{
ro.ApprovedHoursInReportTimeSpan = calc.GetApprovedHoursForPeriod(ro.SupportConceptApprovalPeriod, costRateDcs, start, end) ?? 0;
ro.ApprovedHoursInReportTimeSpan = calc.GetApprovedHoursForPeriod(ro.SupportConceptApprovalPeriod, costRateDcs, start, effectiveEnd) ?? 0;
}
else
{
ro.ApprovedHoursInReportTimeSpan = calc.GetApprovedHoursForPeriod(ro.Costbearer2Supportconcept, start.Value, end.Value);
ro.ApprovedHoursInReportTimeSpan = calc.GetApprovedHoursForPeriod(ro.Costbearer2Supportconcept, start.Value, effectiveEnd.Value);
}
if (splitByServiceCategory && ro.SupportConceptApprovalPeriod != null)
{
ro.ApprovedAmountInReportTimeSpan = (decimal)calc.GetApprovedAmountForPeriod(ro.Costbearer2Supportconcept, start.Value, end.Value, ro.SupportConceptApprovalPeriod.ServiceCategory);
ro.ApprovedAmountInReportTimeSpan = (decimal)calc.GetApprovedAmountForPeriod(ro.Costbearer2Supportconcept, start.Value, effectiveEnd.Value, ro.SupportConceptApprovalPeriod.ServiceCategory);
}
else
{
ro.ApprovedAmountInReportTimeSpan = (decimal)calc.GetApprovedAmountForPeriod(ro.Costbearer2Supportconcept, start.Value, end.Value, null);
ro.ApprovedAmountInReportTimeSpan = (decimal)calc.GetApprovedAmountForPeriod(ro.Costbearer2Supportconcept, start.Value, effectiveEnd.Value, null);
}
ro.AmountInReportTimeSpan = 0;
ro.AmountNichtFehlkontakteInReportTimeSpan = 0;

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using BeWo.Data.Access;
using BeWo.Data.Entities;
@@ -33,11 +34,11 @@ namespace AsSozialeDienstleistungenEV
decimal minutes = 0;
decimal betrag = 0;
decimal stundensatz = 0;
if (pRO.Services != null && pRO.Services.Count > 0)
{
List<ServicesOverviewRO.ServiceDetail> servicesBillable = new List<ServicesOverviewRO.ServiceDetail>();
stundensatz = GetStundensatz(pRO.Services[0], pRO.StartDate);
var mainRecord = pRO.Services.GroupBy(e => e.ServiceCategory).OrderByDescending(g => g.Count()).First().First();
stundensatz = GetStundensatz(mainRecord, pRO.StartDate);
foreach (var sd in pRO.Services)
{
@@ -103,5 +104,6 @@ namespace AsSozialeDienstleistungenEV
// return 0;
//}
}
}

View File

@@ -38,9 +38,29 @@ namespace AutismusLeben.Service
}
DAOFactory.GenericDAO.Insert(i);
inc.IncreaseInvoiceNumber(1, null);
return i;
}
public override SettlementInvoice ErstelleStornoSpitzabrechnung(InvoiceBaseDC ibdc)
{
var i = base.ErstelleStornoSpitzabrechnung(ibdc);
int invoiceCounter = 0;
var inc = PluginLoader.FindClass<InvoiceNumberGenerator>();
i.InvoiceBase.InvoiceNumber = inc.GetNextInvoiceNumber(invoiceCounter, i.InvoiceBase) + " Storno";
if (String.IsNullOrEmpty(i.InvoiceBase.InvoiceTypeText))
{
i.InvoiceBase.InvoiceTypeText = "Storno";
}
else
{
i.InvoiceBase.InvoiceTypeText += " Storno";
}
DAOFactory.GenericDAO.Insert(i);
inc.IncreaseInvoiceNumber(1, null);
return i;
}

View File

@@ -24,6 +24,8 @@ namespace FeidPartnerReports.Invoicing
private decimal BG1Tag = 50m;
private decimal BG2Tag = 30m;
private bool monthly = true;
private HashSet<long> _periodenMitNahtlosemNachfolger = new HashSet<long>();
private HashSet<long> _periodenMitNahtlosemVorgaenger = new HashSet<long>();
public override void SetInvoiceId(ServiceInvoice invoice)
{
@@ -67,11 +69,11 @@ namespace FeidPartnerReports.Invoicing
{
var invoice = new ServiceInvoice();
var newDict = new Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>>();
// Zweites Dict nur für unbewilligte Hilfepläne. Vorher sind unbewilligte und bewilligte im selben Dict gelandet und beide abgerechnet
// Zweites Dict nur für unbewilligte Hilfepl<EFBFBD>ne. Vorher sind unbewilligte und bewilligte im selben Dict gelandet und beide abgerechnet
var unbewilligteDict = new Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>>();
bool unbewilligte = true;
if (supportConcepts2ServiceRecords.Any(sc2sr => sc2sr.Key.IsApproved)) // Für normalen Rechnungslauf
if (supportConcepts2ServiceRecords.Any(sc2sr => sc2sr.Key.IsApproved)) // Für normalen Rechnungslauf
{
unbewilligte = false;
}
@@ -83,7 +85,7 @@ namespace FeidPartnerReports.Invoicing
}
else
{
unbewilligteDict.Add(sc2sr.Key, sc2sr.Value); // Rechnungsvorschau für Unbewilligte Hilfepläne in Berichten
unbewilligteDict.Add(sc2sr.Key, sc2sr.Value); // Rechnungsvorschau für Unbewilligte Hilfepläne in Berichten
}
}
@@ -113,6 +115,59 @@ namespace FeidPartnerReports.Invoicing
return invoice;
}
public override void SetCollectiveBillingServiceInvoicePeriods(ServiceInvoice invoice, DateTimeSpan invoicePeriod,
Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords)
{
BuildNahtlosNachfolgerSet(supportConcepts2ServiceRecords);
base.SetCollectiveBillingServiceInvoicePeriods(invoice, invoicePeriod, supportConcepts2ServiceRecords);
}
private void BuildNahtlosNachfolgerSet(Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> dict)
{
_periodenMitNahtlosemNachfolger.Clear();
_periodenMitNahtlosemVorgaenger.Clear();
// (customerOid, serviceCategoryOid) → alle Bewilligungsperioden dieser Kombination
var lookup = new Dictionary<(long customerOid, long serviceCategoryOid), List<(long scapOid, DateTime start, DateTime end)>>();
foreach (var sc2sr in dict)
{
if (sc2sr.Key.CostBearerRelOids == null || sc2sr.Key.CostBearerRelOids.Count == 0) continue;
var c2s = DAOFactory.GenericDAO.LoadByID<CostBearer2SupportConcept>(sc2sr.Key.CostBearerRelOids[0]);
if (c2s?.ApprovalPeriodList == null || c2s.SupportConcept?.Customer == null) continue;
long customerOid = c2s.SupportConcept.Customer.Oid.Value;
foreach (SupportConceptApprovalPeriod iPeriod in c2s.ApprovalPeriodList)
{
var scapDC = MapperFactory.SupportConceptApprovalPeriodDC_SupportConceptApprovalPeriod.MapToNewDC(iPeriod);
if (!scapDC.SupportConceptApprovalPeriodOid.HasValue) continue;
if (scapDC.ServiceCategory?.ServiceCategoryOid == null) continue;
if (!scapDC.StartDate.HasValue || !scapDC.EndDate.HasValue) continue;
var key = (customerOid, scapDC.ServiceCategory.ServiceCategoryOid.Value);
if (!lookup.ContainsKey(key))
lookup[key] = new List<(long, DateTime, DateTime)>();
lookup[key].Add((scapDC.SupportConceptApprovalPeriodOid.Value, scapDC.StartDate.Value, scapDC.EndDate.Value));
}
}
foreach (var group in lookup.Values)
{
var sorted = group.OrderBy(p => p.start).ToList();
for (int i = 0; i < sorted.Count - 1; i++)
{
if (sorted[i].end.AddDays(1).Date == sorted[i + 1].start.Date)
{
_periodenMitNahtlosemNachfolger.Add(sorted[i].scapOid);
_periodenMitNahtlosemVorgaenger.Add(sorted[i + 1].scapOid);
}
}
}
}
public override void CreateFixedAmounts(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, CostBearer2SupportConcept cb2sc)
{
var calc = PluginLoader.FindClass<BS.Shared.Services.Calculations>(_SpecificID) ?? BS.Shared.Services.Calculations.GetInstance(_SpecificID);
@@ -130,7 +185,7 @@ namespace FeidPartnerReports.Invoicing
{
CreateInvoiceItemsLwv(serviceInvoicePeriod, supportConceptApprovalPeriod, start, end, preis, null);
}
// ...aber es können auch Zeiträume für einzelne Klienten nachträglich abgerechnet werden,
// ...aber es können auch Zeiträume für einzelne Klienten nachträglich abgerechnet werden,
// dann monatliche Rechnungsposition
else
{
@@ -139,7 +194,7 @@ namespace FeidPartnerReports.Invoicing
.GroupBy(e => new DateTime(e.BillingPeriodStart.Value.Year, e.BillingPeriodStart.Value.Month, 1))
.ToDictionary(
g => g.Key,
g => g.OrderBy(e => e.BillingPeriodStart).ToList() // Liste der Einträge in diesem Monat
g => g.OrderBy(e => e.BillingPeriodStart).ToList() // Liste der Einträge in diesem Monat
);
foreach (var kvp in monthlyDict.OrderBy(k => k.Key))
@@ -157,6 +212,30 @@ namespace FeidPartnerReports.Invoicing
private void CreateInvoiceItemsLwv(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, DateTime start, DateTime end, decimal preis, decimal? count)
{
// Nahtloser Vorgänger deckt den Monatsanfang ab: HP1 rechnet den vollen Monat ab,
// dieser Hilfeplan (HP2) erzeugt keinen eigenen Posten für diesen Monat.
var scapOid = supportConceptApprovalPeriod.SupportConceptApprovalPeriodOid;
if (scapOid.HasValue && _periodenMitNahtlosemVorgaenger.Contains(scapOid.Value)
&& supportConceptApprovalPeriod.StartDate.HasValue
&& supportConceptApprovalPeriod.StartDate.Value > start)
{
//Falls kein InvoiceItem mit neuen HP erwünscht ist einfach auskommentieren und stattdessen -> return;
serviceInvoicePeriod.InvoiceItemList.Add(new InvoiceItem
{
ItemPeriodStart = serviceInvoicePeriod.Start,
ItemPeriodEnd = serviceInvoicePeriod.End,
SupportConceptApprovalPeriodOid = supportConceptApprovalPeriod.SupportConceptApprovalPeriodOid,
AccountingInterval = AccountingIntervalType.Monthly,
ItemDescription = supportConceptApprovalPeriod.ServiceCategory.Name,
UnitCount = 0,
AmountPerUnit = 0,
AmountTotal = 0,
GrossAmountTotal = 0,
Notice = "Folgebewilligung"
});
return;
}
if (count == null)
{
count = 1;
@@ -172,16 +251,20 @@ namespace FeidPartnerReports.Invoicing
UnitDescription = String.Format("{0:MM.yyyy}", start),
Notice = "keine Minuten"
};
bool teilmonat = false; // es gibt eigentlich feste Monatsbeträge, nur wenn Bew im Monat endet werden Tage genommen
bool teilmonat = false; // es gibt eigentlich feste Monatsbeträge, nur wenn Bew im Monat endet werden Tage genommen
if (supportConceptApprovalPeriod.StartDate != null && supportConceptApprovalPeriod.StartDate > start)
{
start = supportConceptApprovalPeriod.StartDate.Value;
teilmonat = true;
}
// Kein Teilmonat wenn ein nahtloser Nachfolge-Hilfeplan den Rest des Monats abdeckt
if (supportConceptApprovalPeriod.EndDate != null && supportConceptApprovalPeriod.EndDate < end)
{
end = supportConceptApprovalPeriod.EndDate.Value;
teilmonat = true;
if (!scapOid.HasValue || !_periodenMitNahtlosemNachfolger.Contains(scapOid.Value))
{
end = supportConceptApprovalPeriod.EndDate.Value;
teilmonat = true;
}
}
ii.AccountingInterval = AccountingIntervalType.Monthly;
@@ -217,13 +300,17 @@ namespace FeidPartnerReports.Invoicing
{
iPeriod.Claim = 0;
if (iPeriod.SupportConceptApprovalPeriod.ServiceCategory.Name != "qA" && iPeriod.ApprovedFixedAmount.HasValue && iPeriod.ApprovedFixedAmount.Value != 0)
{
iPeriod.Claim = iPeriod.ApprovedFixedAmount;
}
else
{
foreach (InvoiceItem item in iPeriod.InvoiceItemList)
{
if (item.GrossAmountTotal.HasValue)
{
iPeriod.Claim += item.GrossAmountTotal;
}
}
}
iPeriod.Claim = Math.Round(iPeriod.Claim.Value, 2, MidpointRounding.AwayFromZero);

View File

@@ -72,64 +72,66 @@ namespace InputFamilienhilfe.Invoicing
{
list.Add(i);
}
var listIzl = CreateIZLItems(scap, calc, serviceRecordsInPeriod, invoicePeriod);
list.AddRange(listIzl);
//Bekleidungsergänzung wird erst ab dem ersten VOLLEN Monat des Hilfeplans berechnet
DateTime startMonat2 = new DateTime(scap.StartDate.Value.Year, scap.StartDate.Value.Month, 1).AddMonths(1);
if (scap.StartDate.Value.Day == 1 || invoicePeriod.StartDate >= startMonat2)
// AB, 24.04.2026: neue Betreuungsform wo (vorerst) nur die Tagessätze und nichts anderes abgerechnet wir -> Alias BJW EGH
if (!scap.CostBearer2SupportConcept.SupportConcept.Customer.CustomerAlias.ToLower().Contains("egh"))
{
i = CreateInvoiceItem(scap, invoicePeriod, 1, 48, "Bekleidungsergänzung");
var listIzl = CreateIZLItems(scap, calc, serviceRecordsInPeriod, invoicePeriod);
list.AddRange(listIzl);
//Bekleidungsergänzung wird erst ab dem ersten VOLLEN Monat des Hilfeplans berechnet
DateTime startMonat2 = new DateTime(scap.StartDate.Value.Year, scap.StartDate.Value.Month, 1).AddMonths(1);
if (scap.StartDate.Value.Day == 1 || invoicePeriod.StartDate >= startMonat2)
{
i = CreateInvoiceItem(scap, invoicePeriod, 1, 48, "Bekleidungsergänzung");
if (i != null)
{
list.Add(i);
}
}
i = CreateInvoiceItem(scap, invoicePeriod, 1, 55, "Budget Sonderaufwendungen");
if (i != null)
{
list.Add(i);
}
decimal barbetragPreis = GetBarbetragPreis(scap, invoicePeriod.EndDate);
if (barbetragPreis > 0)
{
i = CreateInvoiceItem(scap, invoicePeriod, 1, barbetragPreis, "Barbetrag");
if (i != null)
{
list.Add(i);
}
}
// AB 24.04.2026, noch ältere Abrechnungslogik, hab die Funktionen mal gelöscht, aber hier lass ich mal für den Fall der Fälle stehe
//i = CreateWohnenPauschale(scap, calc, invoicePeriod);
//if (i != null)
//{
// list.Add(i);
//}
//i = CreateHluPauschale(scap, calc, invoicePeriod);
//if (i != null)
//{
// list.Add(i);
//}
//i = CreateBudget623Pauschale(scap, calc, invoicePeriod);
//if (i != null)
//{
// list.Add(i);
//}
var iilist = CreateSonstigeKosten(scap, calc, serviceRecordsInPeriod, invoicePeriod);
list.AddRange(iilist);
i = CreateLohnAnteil(scap, calc, invoicePeriod);
if (i != null)
{
list.Add(i);
}
}
i = CreateInvoiceItem(scap, invoicePeriod, 1, 55, "Budget Sonderaufwendungen");
if (i != null)
{
list.Add(i);
}
decimal barbetragPreis = GetBarbetragPreis(scap, invoicePeriod.EndDate);
if (barbetragPreis > 0)
{
i = CreateInvoiceItem(scap, invoicePeriod, 1, barbetragPreis, "Barbetrag");
if (i != null)
{
list.Add(i);
}
}
//i = CreateWohnenPauschale(scap, calc, invoicePeriod);
//if (i != null)
//{
// list.Add(i);
//}
//i = CreateHluPauschale(scap, calc, invoicePeriod);
//if (i != null)
//{
// list.Add(i);
//}
//i = CreateBudget623Pauschale(scap, calc, invoicePeriod);
//if (i != null)
//{
// list.Add(i);
//}
var iilist = CreateSonstigeKosten(scap, calc, serviceRecordsInPeriod, invoicePeriod);
list.AddRange(iilist);
i = CreateLohnAnteil(scap, calc, invoicePeriod);
if (i != null)
{
list.Add(i);
}
return CreateSummaryInvoiceItems(list, invoicePeriod, scap, calc);
}
@@ -227,15 +229,9 @@ namespace InputFamilienhilfe.Invoicing
}
unitCount = days;
}
}
}
}
invoiceItem.UnitCount = unitCount;
invoiceItem.AmountPerUnit = amount;
invoiceItem.AmountTotal = invoiceItem.AmountPerUnit * invoiceItem.UnitCount;
@@ -249,107 +245,6 @@ namespace InputFamilienhilfe.Invoicing
return invoiceItem;
}
private InvoiceItem CreateWohnenPauschale(SupportConceptApprovalPeriod scap, Calculations calc, DateTimeSpan invoicePeriod)
{
if (scap.ApprovedFixedAmount.HasValue)
{
var invoiceItem = new InvoiceItem();
if (scap.ApprovedFixedAmountInterval.HasValue &&
scap.ApprovedFixedAmountInterval.Value == SupportConceptApprovalInterval.Monthly)
{
invoiceItem.UnitCount = 1;
}
else
{
DateTime start = invoicePeriod.StartDate;
DateTime end = invoicePeriod.EndDate;
if (scap.StartDate.HasValue && scap.StartDate.Value > start)
{
start = scap.StartDate.Value;
}
if (scap.EndDate.HasValue && scap.EndDate.Value < end)
{
end = scap.EndDate.Value;
}
decimal days = 0;
if (end >= start)
{
days = (decimal)end.Subtract(start).TotalDays + 1;
}
invoiceItem.UnitCount = days;
}
invoiceItem.AmountPerUnit = scap.ApprovedFixedAmount.Value;
invoiceItem.AmountTotal = invoiceItem.AmountPerUnit * invoiceItem.UnitCount;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.ItemPeriodStart = invoicePeriod.StartDate;
invoiceItem.ItemPeriodEnd = invoicePeriod.EndDate;
invoiceItem.AccountingInterval = AccountingIntervalType.FlatRate;
invoiceItem.ItemDescription = "Wohnen / Tag";
invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;
return invoiceItem;
}
return null;
}
private InvoiceItem CreateHluPauschale(SupportConceptApprovalPeriod scap, Calculations calc, DateTimeSpan invoicePeriod)
{
var invoiceItem = new InvoiceItem();
decimal preis = 432;
var cat = DAOFactory.SearchDAO.FindServiceCategoryByName("HLU");
{
if (cat != null)
{
var crpList = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(cat.CostRatePeriods);
var crp = crpList.GetCostRatePeriodForDate(CostRatePeriodType.AmountOfMoney, invoicePeriod.StartDate);
if (crp != null && crp.CostRateValue.HasValue)
{
preis = crp.CostRateValue.Value;
}
}
}
invoiceItem.UnitCount = 1;
invoiceItem.AmountPerUnit = preis;
invoiceItem.AmountTotal = invoiceItem.AmountPerUnit * invoiceItem.UnitCount;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.ItemPeriodStart = invoicePeriod.StartDate;
invoiceItem.ItemPeriodEnd = invoicePeriod.EndDate;
invoiceItem.AccountingInterval = AccountingIntervalType.FlatRate;
invoiceItem.ItemDescription = "HLU / Monat";
invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;
return invoiceItem;
}
private InvoiceItem CreateBudget623Pauschale(SupportConceptApprovalPeriod scap, Calculations calc, DateTimeSpan invoicePeriod)
{
var invoiceItem = new InvoiceItem();
invoiceItem.UnitCount = 1;
invoiceItem.AmountPerUnit = 22;
invoiceItem.AmountTotal = invoiceItem.AmountPerUnit * invoiceItem.UnitCount;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.ItemPeriodStart = invoicePeriod.StartDate;
invoiceItem.ItemPeriodEnd = invoicePeriod.EndDate;
invoiceItem.AccountingInterval = AccountingIntervalType.FlatRate;
invoiceItem.ItemDescription = "Budget nach § 6.2.3";
invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;
return invoiceItem;
}
private InvoiceItem CreateInvoiceItem(SupportConceptApprovalPeriod scap, DateTimeSpan invoicePeriod, decimal unitCount, decimal amountPerUnit, String bezeichnung)
{
var invoiceItem = new InvoiceItem();

View File

@@ -35,9 +35,14 @@ namespace KcmGmbHSozio
this.ReportHeader = new DevExpress.XtraReports.UI.ReportHeaderBand();
this.ruleRateFactorNull = new DevExpress.XtraReports.UI.FormattingRule();
this.topMarginBand1 = new DevExpress.XtraReports.UI.TopMarginBand();
this.xrPictureBox1 = new DevExpress.XtraReports.UI.XRPictureBox();
this.xrLabel1 = new DevExpress.XtraReports.UI.XRLabel();
this.bottomMarginBand1 = new DevExpress.XtraReports.UI.BottomMarginBand();
this.xrLabel12 = new DevExpress.XtraReports.UI.XRLabel();
this.xrLabel13 = new DevExpress.XtraReports.UI.XRLabel();
this.xrLabel11 = new DevExpress.XtraReports.UI.XRLabel();
this.Page1 = new DevExpress.XtraReports.UI.GroupHeaderBand();
this.xrRichText1 = new DevExpress.XtraReports.UI.XRRichText();
this.xrLabel2 = new DevExpress.XtraReports.UI.XRLabel();
this.xrTable2 = new DevExpress.XtraReports.UI.XRTable();
this.xrTableRow4 = new DevExpress.XtraReports.UI.XRTableRow();
this.xrTableCell16 = new DevExpress.XtraReports.UI.XRTableCell();
@@ -88,7 +93,6 @@ namespace KcmGmbHSozio
this.xrTableCell1 = new DevExpress.XtraReports.UI.XRTableCell();
this.xrTableCell5 = new DevExpress.XtraReports.UI.XRTableCell();
this.bindingSource1 = new System.Windows.Forms.BindingSource(this.components);
((System.ComponentModel.ISupportInitialize)(this.xrRichText1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable4)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable6)).BeginInit();
@@ -119,21 +123,94 @@ namespace KcmGmbHSozio
//
// topMarginBand1
//
this.topMarginBand1.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
this.xrPictureBox1,
this.xrLabel1});
this.topMarginBand1.HeightF = 200.625F;
this.topMarginBand1.Name = "topMarginBand1";
//
// xrPictureBox1
//
this.xrPictureBox1.ImageSource = new DevExpress.XtraPrinting.Drawing.ImageSource("img", resources.GetString("xrPictureBox1.ImageSource"));
this.xrPictureBox1.LocationFloat = new DevExpress.Utils.PointFloat(0.1342773F, 132.125F);
this.xrPictureBox1.Name = "xrPictureBox1";
this.xrPictureBox1.SizeF = new System.Drawing.SizeF(249.8656F, 48.27777F);
this.xrPictureBox1.Sizing = DevExpress.XtraPrinting.ImageSizeMode.ZoomImage;
//
// xrLabel1
//
this.xrLabel1.Font = new DevExpress.Drawing.DXFont("Calibri", 10F);
this.xrLabel1.LocationFloat = new DevExpress.Utils.PointFloat(332.9997F, 132.125F);
this.xrLabel1.Multiline = true;
this.xrLabel1.Name = "xrLabel1";
this.xrLabel1.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
this.xrLabel1.SizeF = new System.Drawing.SizeF(317F, 68.49998F);
this.xrLabel1.StylePriority.UseFont = false;
this.xrLabel1.StylePriority.UseTextAlignment = false;
this.xrLabel1.Text = "KCM BeWo GmbH\r\nDilborner Strasse 65\r\n41379 Brüggen\r\n\r\n";
this.xrLabel1.TextAlignment = DevExpress.XtraPrinting.TextAlignment.TopRight;
//
// bottomMarginBand1
//
this.bottomMarginBand1.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
this.xrLabel12,
this.xrLabel13,
this.xrLabel11});
this.bottomMarginBand1.Font = new DevExpress.Drawing.DXFont("Arial", 7F);
this.bottomMarginBand1.HeightF = 97.29169F;
this.bottomMarginBand1.HeightF = 112.5234F;
this.bottomMarginBand1.Name = "bottomMarginBand1";
this.bottomMarginBand1.StylePriority.UseFont = false;
//
// xrLabel12
//
this.xrLabel12.Borders = DevExpress.XtraPrinting.BorderSide.Top;
this.xrLabel12.Font = new DevExpress.Drawing.DXFont("Calibri", 10F);
this.xrLabel12.LocationFloat = new DevExpress.Utils.PointFloat(0F, 0F);
this.xrLabel12.Multiline = true;
this.xrLabel12.Name = "xrLabel12";
this.xrLabel12.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
this.xrLabel12.SizeF = new System.Drawing.SizeF(287.8331F, 79.99996F);
this.xrLabel12.StylePriority.UseBorders = false;
this.xrLabel12.StylePriority.UseFont = false;
this.xrLabel12.StylePriority.UseTextAlignment = false;
this.xrLabel12.Text = "KCM BeWo GmbH\r\nGLS Bank\r\nIBAN: DE76 4306 0967 1221 8357 00\r\nBIC: GENODEM1GLS";
this.xrLabel12.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter;
//
// xrLabel13
//
this.xrLabel13.Borders = DevExpress.XtraPrinting.BorderSide.Top;
this.xrLabel13.Font = new DevExpress.Drawing.DXFont("Calibri", 10F);
this.xrLabel13.LocationFloat = new DevExpress.Utils.PointFloat(287.8329F, 0F);
this.xrLabel13.Multiline = true;
this.xrLabel13.Name = "xrLabel13";
this.xrLabel13.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
this.xrLabel13.SizeF = new System.Drawing.SizeF(144.2209F, 79.99995F);
this.xrLabel13.StylePriority.UseBorders = false;
this.xrLabel13.StylePriority.UseFont = false;
this.xrLabel13.StylePriority.UseTextAlignment = false;
this.xrLabel13.Text = "www.kcm-bewo.de\r\nkontakt@kcm.de\r\n+49 2163 9498915";
this.xrLabel13.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter;
//
// xrLabel11
//
this.xrLabel11.Borders = DevExpress.XtraPrinting.BorderSide.Top;
this.xrLabel11.Font = new DevExpress.Drawing.DXFont("Calibri", 10F);
this.xrLabel11.LocationFloat = new DevExpress.Utils.PointFloat(432.054F, 0F);
this.xrLabel11.Multiline = true;
this.xrLabel11.Name = "xrLabel11";
this.xrLabel11.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
this.xrLabel11.SizeF = new System.Drawing.SizeF(218.6613F, 79.99995F);
this.xrLabel11.StylePriority.UseBorders = false;
this.xrLabel11.StylePriority.UseFont = false;
this.xrLabel11.StylePriority.UseTextAlignment = false;
this.xrLabel11.Text = "Geschäftsführerin Lena Richter\r\nAmtsgericht Krefeld\r\nHRB15069";
this.xrLabel11.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleCenter;
//
// Page1
//
this.Page1.BorderWidth = 2F;
this.Page1.Controls.AddRange(new DevExpress.XtraReports.UI.XRControl[] {
this.xrRichText1,
this.xrLabel2,
this.xrTable2,
this.xrLabel6,
this.xrLabel7,
@@ -145,14 +222,18 @@ namespace KcmGmbHSozio
this.Page1.StylePriority.UseBorderWidth = false;
this.Page1.StylePriority.UseFont = false;
//
// xrRichText1
// xrLabel2
//
this.xrRichText1.Font = new DevExpress.Drawing.DXFont("Calibri", 8.5F);
this.xrRichText1.LocationFloat = new DevExpress.Utils.PointFloat(0F, 0F);
this.xrRichText1.Name = "xrRichText1";
this.xrRichText1.SerializableRtfString = resources.GetString("xrRichText1.SerializableRtfString");
this.xrRichText1.SizeF = new System.Drawing.SizeF(317.0001F, 18F);
this.xrRichText1.StylePriority.UseFont = false;
this.xrLabel2.Font = new DevExpress.Drawing.DXFont("Calibri", 8.5F);
this.xrLabel2.LocationFloat = new DevExpress.Utils.PointFloat(0.134023F, 0F);
this.xrLabel2.Multiline = true;
this.xrLabel2.Name = "xrLabel2";
this.xrLabel2.Padding = new DevExpress.XtraPrinting.PaddingInfo(2, 2, 0, 0, 100F);
this.xrLabel2.SizeF = new System.Drawing.SizeF(316.8658F, 24.99998F);
this.xrLabel2.StylePriority.UseFont = false;
this.xrLabel2.StylePriority.UseTextAlignment = false;
this.xrLabel2.Text = "KCM BeWo GmbH • Dilborner Strasse 65 • 41379 Brüggen\r\n\r\n";
this.xrLabel2.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft;
//
// xrTable2
//
@@ -300,6 +381,7 @@ namespace KcmGmbHSozio
this.xrTableCell7.StylePriority.UseFont = false;
this.xrTableCell7.StylePriority.UsePadding = false;
this.xrTableCell7.StylePriority.UseTextAlignment = false;
this.xrTableCell7.Text = "460586883";
this.xrTableCell7.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleRight;
this.xrTableCell7.Weight = 0.53122488360866615D;
//
@@ -841,14 +923,13 @@ namespace KcmGmbHSozio
this.Font = new DevExpress.Drawing.DXFont("Verdana", 10F);
this.FormattingRuleSheet.AddRange(new DevExpress.XtraReports.UI.FormattingRule[] {
this.ruleRateFactorNull});
this.Margins = new DevExpress.Drawing.DXMargins(100F, 50F, 200.625F, 97.29169F);
this.Margins = new DevExpress.Drawing.DXMargins(100F, 50F, 200.625F, 112.5234F);
this.PageHeight = 1169;
this.PageWidth = 827;
this.PageWidth = 826;
this.PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4;
this.Version = "23.2";
xrWatermark1.Id = "Watermark1";
this.Watermarks.Add(xrWatermark1);
((System.ComponentModel.ISupportInitialize)(this.xrRichText1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable4)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.xrTable6)).EndInit();
@@ -916,6 +997,11 @@ namespace KcmGmbHSozio
private DevExpress.XtraReports.UI.XRTableCell xrTableCell20;
private DevExpress.XtraReports.UI.XRTableCell xrTableCell45;
private DevExpress.XtraReports.UI.XRTableCell xrTableCell47;
private DevExpress.XtraReports.UI.XRRichText xrRichText1;
private DevExpress.XtraReports.UI.XRLabel xrLabel12;
private DevExpress.XtraReports.UI.XRLabel xrLabel13;
private DevExpress.XtraReports.UI.XRLabel xrLabel11;
private DevExpress.XtraReports.UI.XRPictureBox xrPictureBox1;
private DevExpress.XtraReports.UI.XRLabel xrLabel1;
private DevExpress.XtraReports.UI.XRLabel xrLabel2;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff