KApp -> App8: GetIKNummern

Abrechnungscode + Tarifkennzeichen werden übergeben
Meldung, falls IK nicht hinterlegt ist
This commit is contained in:
2024-07-19 14:41:49 +02:00
parent 56f829d616
commit f5d85d4c56
10 changed files with 186 additions and 84 deletions

View File

@@ -1,4 +1,5 @@
using BS.Shared.DataContracts;
using BeWo.Data.Entities;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.GkvAbrechnung;
using Dakota.Models;
using System;
@@ -47,34 +48,23 @@ namespace Dakota
throw new DakotaException(error);
}
public static void ValidateOrganisation(OrganisationDC orgadc)
public static void ValidateOrganisation(Organisation orga)
{
string error = null;
if (orgadc == null)
if (orga == null)
error = "Organisation ist null";
if (!ValidateIKNumbers(orgadc))
{
}
//if (!ValidateIKNumber(orgadc.IKDatenannahmestelle))
// error = $"Die Organisation \"{orgadc.Name}\" hat keine gültige IK Nummer für die Datenannahmestelle.";
//else if (!ValidateIKNumber(orgadc.IKKostentrager))
// error = $"Die Organisation \"{orgadc.Name}\" hat keine gültige IK Nummer für die Kostenträger.";
//else if (!ValidateIKNumber(orgadc.IKKrankenkasse))
// error = $"Die Organisation \"{orgadc.Name}\" hat keine gültige IK Nummer für die Krankenkasse.";
if (!ValidateLeistungserbringergruppe(orgadc.Leistungserbringergruppe))
error = $"Die Organisation \"{orgadc.Name}\" hat keine gültige Leistungserbringergruppe: \"{orgadc.Leistungserbringergruppe}\". Erwarten werden 5 Stellen für das Tarifkennzeichen alleine oder 7 Stellen für den Abrechnungscode und für das Tarifkennzeichen zusammen.";
else if (!ValidateLeistungserbringergruppe(orga.Leistungserbringergruppe))
error = $"Die Organisation \"{orga.Name}\" hat keine gültige Leistungserbringergruppe: \"{orga.Leistungserbringergruppe}\". Erwarten werden 5 Stellen für das Tarifkennzeichen alleine oder 7 Stellen für den Abrechnungscode und für das Tarifkennzeichen zusammen.";
else if (!ValidateIKNumber(orga.IKKrankenkasse))
error = $"Die Organisation \"{orga.Name}\" hat kein gültiges IK Kennzeichen: \"{orga.IKKrankenkasse}\".";
if (error != null)
throw new DakotaException(error);
}
private static bool ValidateIKNumbers(OrganisationDC dc)
=> ValidateIKNumbers(dc.IKDatenannahmestelle, dc.IKKostentrager, dc.IKKrankenkasse);
public static bool ValidateIKNumbers(Organisation orga)
=> ValidateIKNumbers(orga.IKDatenannahmestelle, orga.IKKostentrager, orga.IKKrankenkasse);
private static bool ValidateIKNumbers(params string[] iks)
=> iks?.All(ValidateIKNumber) ?? false;

View File

@@ -33,9 +33,17 @@ namespace Dakota.Logic
}
public int GetFileCount() => FileDictionary.Count();
public int GetAllFileEntryCount() => FileDictionary.Sum(x => x.Value.Count);
/// <summary>
///
/// </summary>
/// <param name="ikkrankenkasse"></param>
/// <param name="abrechnungscode"></param>
/// <param name="tarifkennzeichen"></param>
/// <returns>Item1:Datenannahmestelle -
/// Item2:Kostenträger -
/// Item3:Krankenkasse</returns>
public Tuple<string, string, string> Resolve(string ikkrankenkasse, string abrechnungscode, string tarifkennzeichen)
{
foreach (var kv in FileDictionary)

View File

@@ -43,5 +43,42 @@ namespace Dakota.Logic
return sb.ToString();
}
public static string GetAbrechnungscode(string leistungserbringergruppe)
{
var len = leistungserbringergruppe.Length;
if(len == 5)
{
return "69";
}
else if(len == 7)
{
return leistungserbringergruppe.Substring(0, 2);
}
else
{
throw new ArgumentException($"Leistungserbringergruppe \"{leistungserbringergruppe}\" hat ungültige Anzahl Stellen");
}
}
public static string GetTarifkennzeichen(string leistungserbringergruppe)
{
var len = leistungserbringergruppe.Length;
if (len == 5)
{
return leistungserbringergruppe;
}
else if (len == 7)
{
return leistungserbringergruppe.Substring(2);
// return leistungserbringergruppe.Substring(2, 5);
}
else
{
throw new ArgumentException($"Leistungserbringergruppe \"{leistungserbringergruppe}\" hat ungültige Anzahl Stellen");
}
}
}
}

View File

@@ -54,5 +54,19 @@ namespace DakotaUnitTest
Assert.IsTrue(test.Item3 == "105328415");
}
[TestMethod]
public void ValidateAOKRheinlandHamburgSoz()
{
var test = Reader.Resolve("104212505", "69", "00000");
Assert.IsNotNull(test);
Assert.IsTrue(test.Item1 == "104212516");
Assert.IsTrue(test.Item2 == "104212505");
Assert.IsTrue(test.Item3 == "104212505");
}
}
}

View File

@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BS.Shared;
using BS.Shared.Extensions;
@@ -31,5 +31,10 @@ namespace BeWo.Data.Entities
(x) => x.Fehlerdatum,
(x) => x.Fehlerlevel,
(x) => x.ErstelltAm.Value);
public virtual Organisation GetOrganisation()
{
return InvoiceBases.First().CostBearer2SupportConcept.CostBearer.Organisation;
}
}
}

View File

@@ -32,6 +32,7 @@ using System.Xml;
using System.Xml.Linq;
using System.Diagnostics;
using System.Xml.Serialization;
using Dakota.Logic;
namespace Host
{
@@ -44,6 +45,7 @@ namespace Host
private string ResultFolderPath { get; set; } = ConfigurationManager.AppSettings.Get("GkvAbrechnungResultFolderPath");
private string QueueFolderPath { get; set; } = ConfigurationManager.AppSettings.Get("GkvAbrechnungQueueFolderPath");
private string KostentragerdateiFolderPath { get; set; } = ConfigurationManager.AppSettings.Get("GkvKostentragerdateiFolderPath");
public GkvApp8Request GkvRequest { get; set; }
@@ -253,14 +255,21 @@ namespace Host
}
private void GetIK(GkvApp8GetIKRequest req)
{
var input = req.KrankenkassenIK;
var ktd_reader = new DakotaKTDReader(KostentragerdateiFolderPath);
var resolved = ktd_reader.Resolve(req.IKKrankenkasse, req.Abrechnungscode, req.Tarifkennzeichen);
var response = new GkvApp8GetIKResponse();
response.Success = true;
response.IKVersichertenKarte = input;
response.IKDatenannahmestelle = "111222333";
response.IKKostenträger = "333444555";
response.Gefunden = resolved is object;
if (response.Gefunden)
{
response.IKDatenannahmestelle = resolved.Item1;
response.IKKostentrager = resolved.Item2;
response.IKKrankenkasse = resolved.Item3;
}
SendResponse(response);
}

View File

@@ -17,7 +17,7 @@ namespace BeWo.Service.DCEntityMapper
{
}
var orga = pEntity.InvoiceBases.First().CostBearer2SupportConcept.CostBearer.Organisation;
var orga = pEntity.GetOrganisation();
pDataContract.GkvAbrechnungOid = pEntity.Oid;
pDataContract.GkvAbrechnungVersion = pEntity.Version;

View File

@@ -566,7 +566,7 @@ namespace BeWo.Service.ServiceImplementations
{
var dc = invoices.Where(i => i.InvoiceBaseOid == entity.Oid).FirstOrDefault();
if (dc.IsPaid != entity.IsPaid ||
dc.IsExported != entity.IsExported ||
dc.IsReviewed != entity.IsReviewed ||
@@ -718,7 +718,6 @@ namespace BeWo.Service.ServiceImplementations
throw Utils.CreateBeWoFaultException(e);
}
}
public List<GkvAbrechnungDC> GetFilteredGkvAbrechnungen(GkvAbrechnungViewFilterDC gkvAbrechnungViewFilter)
{
try
@@ -739,7 +738,6 @@ namespace BeWo.Service.ServiceImplementations
throw Utils.CreateBeWoFaultException(e);
}
}
public List<GkvAbrechnungDC> GetAllGkvAbrechnungen()
{
try
@@ -755,7 +753,7 @@ namespace BeWo.Service.ServiceImplementations
if (!updateables.Any())
return dcs;
var isUpToDate = SendApp8GetStatusRequest(updateables, user.LoginName, user.BCryptPassword);
var isUpToDate = SendApp8GetStatusRequest(updateables);
if (isUpToDate)
return dcs;
@@ -829,7 +827,6 @@ namespace BeWo.Service.ServiceImplementations
return response;
}
public GkvAbrechnungDC UpdateGkvAbrechnung(GkvAbrechnungDC abrechnung)
{
try
@@ -847,7 +844,6 @@ namespace BeWo.Service.ServiceImplementations
throw Utils.CreateBeWoFaultException(e);
}
}
public void DeleteGkvAbrechnung(GkvAbrechnungDC abrechnung)
{
try
@@ -866,16 +862,18 @@ namespace BeWo.Service.ServiceImplementations
response.Successful = false;
var user = LoggedInUserOperationContextExt.Current?.User ?? SessionFacade.LoggedInUser;
if (user == null)
var oid = req.GkvAbrechnungOid;
var entity = DAOFactory.GenericDAO.LoadByID<GkvAbrechnung>(oid);
var state = GkvAbrechnung.GetState(entity);
if (state == GkvState.Waiting || state == GkvState.OldAndNoFeedback || state == GkvState.Paid)
{
response.Message = "User unbekannt";
response.Message = "Validierung fehlgeschlagen";
return response;
}
var oid = req.GkvAbrechnungOid;
var entity = DAOFactory.GenericDAO.LoadByID<GkvAbrechnung>(oid);
var protokoll = new GkvTransferProtokoll();
protokoll.ErstelltAm = DateTime.Now;
@@ -883,22 +881,17 @@ namespace BeWo.Service.ServiceImplementations
try
{
var validation_success = CreateGkvTransferProtokoll(entity, protokoll);
if(!validation_success)
{
response.Message = "Validierung fehlgeschlagen";
return response;
}
CreateGkvTransferProtokoll(oid, entity, protokoll);
if (entity.GkvTransferProtokolle is null)
entity.GkvTransferProtokolle = new List<GkvTransferProtokoll>();
entity.GkvTransferProtokolle.Add(protokoll);
// Protokoll braucht Oid
DAOFactory.GenericDAO.Update(entity);
var app8_response = SendApp8SendNewRequest(protokoll, user.LoginName, user.BCryptPassword);
var app8_response = SendApp8SendNewRequest(protokoll);
var app8_protokoll = app8_response.GkvTransferProtokollDC;
@@ -928,8 +921,7 @@ namespace BeWo.Service.ServiceImplementations
return response;
}
private bool CreateGkvTransferProtokoll(GkvAbrechnung gkvAbrechnung, GkvTransferProtokoll protokoll)
private void CreateGkvTransferProtokoll(long oid, GkvAbrechnung gkvAbrechnung, GkvTransferProtokoll protokoll)
{
try
{
@@ -938,19 +930,38 @@ namespace BeWo.Service.ServiceImplementations
DakotaValidator.ValidateMandator(mandatordc);
var orga = gkvAbrechnung.GetOrganisation();
DakotaValidator.ValidateOrganisation(orga);
if (!DakotaValidator.ValidateIKNumbers(orga))
{
var res = SendApp8GetIKRequest(orga);
if (!res.Success)
throw new DakotaException(res.Message, "Interner Fehler");
if (!res.Gefunden)
throw new DakotaException($"Für die Organisation \"{orga.Name}\" mit dem IK \"{orga.IKKrankenkasse}\" konnte keine Datenannahmestelle gefunden werden. " +
$"Bitte informieren Sie sich bei der Krankenkasse, ob zum elektronischen Datenaustausch " +
$"eine seperate Anmeldung benötigt wird.");
orga.IKDatenannahmestelle = res.IKDatenannahmestelle;
orga.IKKostentrager = res.IKKostentrager;
// orgadc.IKKrankenkasse = res.IKKrankenkasse;
if (!DakotaValidator.ValidateIKNumbers(orga))
throw new DakotaException($"Für die Organisation \"{orga.Name}\" konnten die hinterlegten IKs nicht verifiziert werden: \"{orga.IKDatenannahmestelle}\", \"{orga.IKKostentrager}\", \"{orga.IKKrankenkasse}\"", "Interner Fehler");
DAOFactory.GenericDAO.Update(orga);
gkvAbrechnung = DAOFactory.GenericDAO.LoadByID<GkvAbrechnung>(oid);
}
var gkvAbrechnungDC = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(gkvAbrechnung);
var orgadc = gkvAbrechnungDC.Organisation;
DakotaValidator.ValidateOrganisation(orgadc);
var state = GkvAbrechnung.GetState(gkvAbrechnung);
if (state == GkvState.Waiting || state == GkvState.OldAndNoFeedback || state == GkvState.Paid)
{
return false;
}
var datenannahmestelle = gkvAbrechnungDC.Organisation.IKDatenannahmestelle;
var datenannahmestelle = orgadc.IKDatenannahmestelle;
var (datenaustauschreferenz, transfernummer) = GetNextDatenaustauschreferenzTransfernummer(gkvAbrechnung, datenannahmestelle);
var (dat_short, tra_short) = ClearDatenaustauschreferenzTransfernummer(datenaustauschreferenz, transfernummer);
@@ -1010,8 +1021,6 @@ namespace BeWo.Service.ServiceImplementations
protokoll.AbsenderBezeichnung = "TestAbsBez";
protokoll.EmpfangerBezeichnung = "TestEmpBez";
return true;
}
catch (DakotaException de)
{
@@ -1048,7 +1057,6 @@ namespace BeWo.Service.ServiceImplementations
return new Tuple<int, int>(datenaustauschref, transfernummer);
}
private Tuple<int, int> ClearDatenaustauschreferenzTransfernummer(int datenaustauschreferenz, int transfernummer)
{
int d = datenaustauschreferenz % 99999;
@@ -1062,7 +1070,7 @@ namespace BeWo.Service.ServiceImplementations
return new Tuple<int, int>(d, t);
}
private GkvApp8SendNewResponse SendApp8SendNewRequest(GkvTransferProtokoll protokoll, string loginName, string hashed_password)
private GkvApp8SendNewResponse SendApp8SendNewRequest(GkvTransferProtokoll protokoll)
{
var gkv_transfer_dc = MapperFactory.GkvTransferProtokollDC_GkvTransferprotokoll.MapToNewDC(protokoll);
@@ -1075,20 +1083,14 @@ namespace BeWo.Service.ServiceImplementations
var request_app8 = new GkvApp8SendNewRequest
{
SendDirect = true,
GkvTransferProtokoll = gkv_transfer_dc,
Username = loginName,
Password = hashed_password,
Tenant = MultitenancyOperationContextExt.Current.Tenant,
DebugMode = "fozc4897b6ztvf978AFCRRG244fvFV2532fvf324AF"
GkvTransferProtokoll = gkv_transfer_dc
};
#if DEBUG
request_app8.SendDirect = false;
#endif
var response_app8_str = SendApp8Request(url, request_app8);
var response_app8 = JsonConvert.DeserializeObject<GkvApp8SendNewResponse>(response_app8_str);
var response_app8 = SendApp8Request<GkvApp8SendNewRequest, GkvApp8SendNewResponse>(url, request_app8);
if (!response_app8.Success)
throw new DakotaException(response_app8.Message);
@@ -1102,7 +1104,7 @@ namespace BeWo.Service.ServiceImplementations
/// <param name="loginName"></param>
/// <param name="hashed_password"></param>
/// <returns>Returns true, if the states are all up to date. False otherwise.</returns>
private bool SendApp8GetStatusRequest(GkvAbrechnungDC[] updateables, string loginName, string hashed_password)
private bool SendApp8GetStatusRequest(GkvAbrechnungDC[] updateables)
{
var updateables_len = updateables.Count();
@@ -1110,8 +1112,6 @@ namespace BeWo.Service.ServiceImplementations
var request = new GkvApp8GetStatusRequest
{
Username = loginName,
Password = hashed_password,
Tenant = MultitenancyOperationContextExt.Current.Tenant,
Oids = new long[updateables_len],
DebugMode = "fozc4897b6ztvf978AFCRRG244fvFV2532fvf324AF",
@@ -1128,18 +1128,16 @@ namespace BeWo.Service.ServiceImplementations
GkvApp8GetStatusResponse response_app8;
try
{
var response_app8_str = SendApp8Request(url, JsonConvert.SerializeObject(request));
response_app8 = JsonConvert.DeserializeObject<GkvApp8GetStatusResponse>(response_app8_str);
response_app8 = SendApp8Request<GkvApp8GetStatusRequest, GkvApp8GetStatusResponse>(url, request);
}
catch(Exception e)
catch (Exception e)
{
return true;
}
if (!response_app8.Success)
throw new DakotaException(response_app8.Message);
bool allAreUpToDate = true;
for (int id = 0; id < updateables_len; id++)
{
@@ -1166,7 +1164,39 @@ namespace BeWo.Service.ServiceImplementations
return allAreUpToDate;
}
private string SendApp8Request(string url, object request) => SendApp8Request(url, JsonConvert.SerializeObject(request));
private GkvApp8GetIKResponse SendApp8GetIKRequest(Organisation orga)
{
var gruppe = orga.Leistungserbringergruppe;
var abr = DakotaUtils.GetAbrechnungscode(gruppe);
var tarif = DakotaUtils.GetTarifkennzeichen(gruppe);
var url = "https://app8.bewoplaner.de/service/GkvAbrechnungView.aspx";
var request = new GkvApp8GetIKRequest
{
Abrechnungscode = abr,
IKKrankenkasse = orga.IKKrankenkasse,
Tarifkennzeichen = tarif
};
return SendApp8Request<GkvApp8GetIKRequest, GkvApp8GetIKResponse>(url, request);
}
private T2 SendApp8Request<T, T2>(string url, T request) where T : GkvApp8Request where T2 : GkvApp8Response
{
var user = LoggedInUserOperationContextExt.Current?.User ?? SessionFacade.LoggedInUser;
if (user == null)
{
throw new DakotaException("User unbekannt", "KApp");
}
request.Username = user.LoginName;
request.Password = user.BCryptPassword;
request.DebugMode = "fozc4897b6ztvf978AFCRRG244fvFV2532fvf324AF";
request.Tenant = MultitenancyOperationContextExt.Current.Tenant;
return JsonConvert.DeserializeObject<T2>(SendApp8Request(url, JsonConvert.SerializeObject(request)));
}
private string SendApp8Request(string url, string dataString)
{
string response_app8_str;
@@ -1182,7 +1212,7 @@ namespace BeWo.Service.ServiceImplementations
response_app8_str = client.UploadString(url, "POST", dataString);
}
}
catch(Exception e)
catch (Exception e)
{
throw new DakotaException(e.Message, "App8");
}

View File

@@ -10,7 +10,13 @@ namespace BS.Shared.DataContracts.GkvAbrechnung
public class GkvApp8GetIKRequest : GkvApp8Request
{
[DataMember]
public string KrankenkassenIK { get; set; }
public string IKKrankenkasse { get; set; }
[DataMember]
public string Abrechnungscode { get; set; }
[DataMember]
public string Tarifkennzeichen { get; set; }
public GkvApp8GetIKRequest()
{

View File

@@ -10,10 +10,13 @@ namespace BS.Shared.DataContracts.GkvAbrechnung
public class GkvApp8GetIKResponse : GkvApp8Response
{
[DataMember]
public string IKVersichertenKarte { get; set; }
public bool Gefunden { get; set; }
[DataMember]
public string IKKostenträger { get; set; }
public string IKKrankenkasse { get; set; }
[DataMember]
public string IKKostentrager { get; set; }
[DataMember]
public string IKDatenannahmestelle { get; set; }