Dakota: GKV-Abrechnung für Häusliche Krankenpflege unterstützen

This commit is contained in:
2026-04-27 09:24:15 +02:00
parent cb462e0dd9
commit e3c2a6a315
13 changed files with 634 additions and 113 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
};
}
}