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

This commit is contained in:
Christian
2025-03-16 20:42:44 +01:00
311 changed files with 49246 additions and 27617 deletions

View File

@@ -745,628 +745,5 @@ namespace BeWo.Service.ServiceImplementations
throw Utils.CreateBeWoFaultException(e);
}
}
#region GKV
public GkvAbrechnungDC GetGkvAbrechnung(long oid)
{
try
{
var gkv = DAOFactory.GenericDAO.GetByID<GkvAbrechnung>(oid);
var dc = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(gkv);
return dc;
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public List<GkvAbrechnungDC> GetFilteredGkvAbrechnungen(GkvAbrechnungViewFilterDC gkvAbrechnungViewFilter)
{
try
{
if (gkvAbrechnungViewFilter == null || !gkvAbrechnungViewFilter.FilterTime)
return GetAllGkvAbrechnungen();
var start = gkvAbrechnungViewFilter.Start;
var end = gkvAbrechnungViewFilter.End;
var filter = gkvAbrechnungViewFilter.FilterForInvoiceDate;
return GetGkvAbrechnungen(() => DAOFactory.SearchDAO.GetGkvAbrechnungen(start, end, filter));
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public List<GkvAbrechnungDC> GetAllGkvAbrechnungen()
{
try
{
return GetGkvAbrechnungen(() => DAOFactory.GenericDAO.GetAllActive<GkvAbrechnung>());
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
private List<GkvAbrechnungDC> GetGkvAbrechnungen(Func<IEnumerable<GkvAbrechnung>> get_entities)
{
var entities = get_entities();
var dcs = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDCs(entities);
var updateables = dcs.Where(x => x.IsWaiting()).ToArray();
if (!updateables.Any())
return dcs;
var isUpToDate = SendApp8GetStatusRequest(updateables);
if (isUpToDate)
return dcs;
entities = get_entities();
dcs = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDCs(entities);
return dcs;
}
public List<CompactGkvAbrechnungDC> GetCompactGkvAbrechnungByTransferDateRange(DateTime? start, DateTime? end)
{
try
{
var entities = DAOFactory.SearchDAO.GetGkvTransferProtokollByDateRange(start, end);
var filter = entities.Where(x => x.SentDakotaSuccess);
var oids = filter.Select(x => x.GkvAbrechnungOid).Distinct();
if (!oids.Any())
return null;
var list = new List<GkvAbrechnung>();
foreach (var oid in oids)
{
var abrechnung = DAOFactory.GenericDAO.LoadByID<GkvAbrechnung>(oid);
list.Add(abrechnung);
}
return MapperFactory.CompactGkvAbrechnungDC_GkvAbrechnung.MapToNewDCs(list);
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public GkvAbrechnungCreateResponseDC CreateNewGkvAbrechnung(GkvAbrechnungCreateRequestDC request)
{
var response = new GkvAbrechnungCreateResponseDC();
try
{
var invoice_bases = DAOFactory.GenericDAO.LoadByIDs<InvoiceBase>(request.SelectedInvoiceBases);
ValidatorExtended.ValidateGkvAbrechnung(request.GkvAbrechnungDC, invoice_bases);
var gkv_abrechnung = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewEntity(request.GkvAbrechnungDC);
if (gkv_abrechnung.AbrechnungsZeitraumEnde.Value.Hour == 0)
{
gkv_abrechnung.AbrechnungsZeitraumEnde = gkv_abrechnung.AbrechnungsZeitraumEnde.Value.Date.AddDays(1).AddMilliseconds(-1);
}
var orga = gkv_abrechnung.Organisation;
gkv_abrechnung.Verfahrensstufe = orga.Verfahrensstufe;
decimal gesamt = 0;
foreach (var invoicebase_oid in request.SelectedInvoiceBases)
{
var service = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(invoicebase_oid);
foreach (var peroid in service.ServiceInvoicePeriodList)
{
foreach (var invoice in peroid.InvoiceItemList)
{
gesamt += invoice.AmountTotal.Value;
}
}
}
gkv_abrechnung.Betrag = gesamt;
gkv_abrechnung.Bezahlt = false;
gkv_abrechnung.ErstelltAm = DateTime.Now;
DAOFactory.GenericDAO.Insert(gkv_abrechnung);
var gkv_abrechnung_dc = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(gkv_abrechnung);
response.Success = true;
response.GkvAbrechnungDC = gkv_abrechnung_dc;
}
catch (GkvException exc)
{
MailUtils.SendGkvModuleErrorMail("CreateNewGkvAbrechnung", exc, Tenant);
if (exc.Title.IsNotNullOrWhiteSpace())
response.TitleMessage = exc.Title;
response.Message = exc.Message;
}
catch (Exception e)
{
MailUtils.SendGkvModuleErrorMail("CreateNewGkvAbrechnung", e, Tenant);
throw Utils.CreateBeWoFaultException(e);
}
return response;
}
public GkvAbrechnungDC UpdateGkvAbrechnung(GkvAbrechnungDC abrechnung)
{
try
{
var entity = DAOFactory.GenericDAO.GetByID<GkvAbrechnung>(abrechnung.GkvAbrechnungOid.Value);
MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MergeWithEntity(abrechnung, entity);
foreach (var invoice in entity.InvoiceBases)
{
invoice.IsPaid = entity.Bezahlt;
}
DAOFactory.GenericDAO.Update(entity);
return MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(entity);
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public void DeleteGkvAbrechnung(GkvAbrechnungDC abrechnung)
{
try
{
ServiceLogic.SetActivationType<GkvAbrechnung>(abrechnung.GkvAbrechnungOid.Value, abrechnung.GkvAbrechnungVersion.Value, ActivationTypeId.Deleted);
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public GkvAbrechnungSendResponseDC SendNewGkvAbrechnung(GkvAbrechnungSendRequestDC req)
{
var response = new GkvAbrechnungSendResponseDC();
var oid = req.GkvAbrechnungOid;
var entity = DAOFactory.GenericDAO.LoadByID<GkvAbrechnung>(oid);
var state = entity.GetState();
if (entity.IsWaiting() || state == GkvState.Paid)
{
response.Message = "Validierung fehlgeschlagen";
return response;
}
var protokoll = CreateGkvTransferProtokoll(entity, out var error);
if (error is object)
{
MailUtils.SendGkvModuleErrorMail("SendNewGkvAbrechnung - CreateGkvTransferProtokoll", error, Tenant);
response.TitleMessage = "Protokoll Erstellung";
response.Message = error;
return response;
}
if (entity.GkvTransferProtokolle is null)
entity.GkvTransferProtokolle = new List<GkvTransferProtokoll>();
entity.GkvTransferProtokolle.Add(protokoll);
// Protokoll braucht Oid
DAOFactory.GenericDAO.Update(entity);
try
{
var app8_response = SendApp8SendNewRequest(protokoll);
var app8_protokoll = app8_response.GkvTransferProtokollDC;
MapperFactory.GkvTransferProtokollDC_GkvTransferprotokoll.MergeWithEntity(app8_protokoll, protokoll);
response.Success = app8_response.Success;
response.Message = app8_response.Message;
}
catch (GkvException de)
{
protokoll.ResultType = GkvTransferResultType.FailSoft;
protokoll.Fehlerdatum = DateTime.Now;
protokoll.Fehlernachricht = de.Message;
protokoll.Fehlertitel = de.Title ?? "Default";
}
catch (Exception e)
{
protokoll.ResultType = GkvTransferResultType.FailFatal;
protokoll.Fehlerdatum = DateTime.Now;
protokoll.Fehlernachricht = e.ToString();
protokoll.Fehlertitel = "Erstellung (kritisch)";
}
DAOFactory.GenericDAO.Update(entity);
response.TransferProtokoll = MapperFactory.GkvTransferProtokollDC_GkvTransferprotokoll.MapToNewDC(protokoll);
response.GkvAbrechnungDC = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(entity);
return response;
}
public GkvAbrechnungGetIKResponseDC SendGetIKRequest(GkvAbrechnungGetIKRequestDC req)
{
try
{
var app8req = new GkvServerGetIKRequestDC
{
IKKrankenkasse = req.IKKrankenkasse,
Leistungserbringergruppe = req.Leistungserbringergruppe,
Abrechnungscode = DakotaUtils.GetAbrechnungscode(req.Leistungserbringergruppe),
Tarifkennzeichen = DakotaUtils.GetTarifkennzeichen(req.Leistungserbringergruppe)
};
var app8res = SendApp8Request<GkvServerGetIKRequestDC, GkvServerGetIKResponseDC>(app8req);
// Erstelle Response
var res = new GkvAbrechnungGetIKResponseDC
{
BezDatenannahmestelle = app8res.BezDatenannahmestelle,
Gefunden = app8res.Gefunden,
IKDatenannahmestelle = app8res.IKDatenannahmestelle,
IKKostentrager = app8res.IKKostentrager,
IKKrankenkasse = app8res.IKKrankenkasse,
Message = app8res.Message,
Success = app8res.Success
};
// Schaue, ob IK Krankenkassen bereits bei einer anderen Organisation hinterlegt ist
if (res.Gefunden)
{
// Holt alle Organisationen
var orgas = DAOFactory.SearchDAO.GetAllOrganisationByIKKrankenkasse(req.IKKrankenkasse);
// Entfernt sich selber
if (req.OrganisationOid is long oid)
{
orgas.RemoveAll(x => x.Oid == oid);
}
if (orgas.Any())
{
res.BereitsEnthalten = true;
res.BereitsEnthaltenBei = orgas.Select(x => x.Name).ToList();
}
}
return res;
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
private GkvTransferProtokoll CreateGkvTransferProtokoll(GkvAbrechnung gkvAbrechnung, out string error)
{
var protokoll = new GkvTransferProtokoll
{
ErstelltAm = DateTime.Now,
GkvAbrechnungOid = gkvAbrechnung.Oid.Value
};
error = null;
try
{
ValidatorExtended.ValidateGkvAbrechnung(gkvAbrechnung, gkvAbrechnung.InvoiceBases);
var manager = new DakotaManager();
var mandatordc = new OperationsServiceImp().GetMandator();
Validator.ValidateMandator(mandatordc);
var gkvAbrechnungDC = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(gkvAbrechnung);
var orgadc = gkvAbrechnungDC.Organisation;
Validator.ValidateOrganisation(orgadc);
var datenannahmestelle = orgadc.IKDatenannahmestelle;
var (datenaustauschreferenz, transfernummer) = GetNextDatenaustauschreferenzTransfernummer(gkvAbrechnung, datenannahmestelle);
var (dat_short, tra_short) = ClearDatenaustauschreferenzTransfernummer(datenaustauschreferenz, transfernummer);
var first_cost = gkvAbrechnung.InvoiceBases.First().CostBearer2SupportConcept.SupportConcept.Customer;
var plugin = PluginLoader.FindClass<AccountingService>();
var addressInfo = plugin.GetAddressInformation(first_cost.Oid);
foreach (var invoicebase in gkvAbrechnung.InvoiceBases)
{
var customer = invoicebase.CostBearer2SupportConcept.SupportConcept.Customer;
var addressInfo2 = plugin.GetAddressInformation(customer.Oid);
if (addressInfo.IKLeistungserbringer != addressInfo2.IKLeistungserbringer)
{
throw new GkvException($"Klient '{first_cost.Person.LastNameFirstName}' ({addressInfo.IKLeistungserbringer}) und '{customer.Person.LastNameFirstName}' ({addressInfo2.IKLeistungserbringer}) verweisen auf unterschiedliche Leistungserbringer.");
}
}
foreach (var invoicebase in gkvAbrechnung.InvoiceBases)
{
var service = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(invoicebase.Oid.Value);
var orga2 = invoicebase.CostBearer2SupportConcept.CostBearer.Organisation;
var customer = invoicebase.CostBearer2SupportConcept.SupportConcept.Customer;
var invoicebase_dc = MapperFactory.InvoiceBaseDC_InvoiceBase.MapToNewDC(invoicebase);
var servicedc = MapperFactory.ServiceInvoiceDC_ServiceInvoice.MapToNewDC(service);
var customerdc = MapperFactory.CustomerDC_Customer.MapToNewDC(customer);
Validator.ValidateCustomer(customerdc);
manager.Add(servicedc, orgadc, customerdc, addressInfo, dat_short, tra_short);
}
manager.Apply();
if (manager.DakotaFileDict.Count != 1 || manager.DakotaFileDict.First().Value.GetKostenträgerCount() != 1)
{
var msg = "Unerwartete Anzahl an Dakota Files berechnet.";
throw new GkvException(msg);
}
var file_from_manager = manager.DakotaFileDict.First().Value;
var nutzdatendatei = file_from_manager.GetNutzdatendatei();
// https://dev.mysql.com/doc/refman/8.3/en/string-type-syntax.html
// A TEXT column with a maximum length of 16,777,215 (224 1) characters.
// The effective maximum length is less if the value contains multibyte characters.
// Each MEDIUMTEXT value is stored using a 3-byte length prefix that indicates the number of bytes in the value.
//
// Type | Maximum length
// -----------+-------------------------------------
// TINYTEXT | 255(2^81) bytes
// TEXT | 65,535(2^161) bytes = 64 KiB
// MEDIUMTEXT | 16,777,215(2^241) bytes = 16 MiB
// LONGTEXT | 4,294,967,295(2^321) bytes = 4 GiB
if (nutzdatendatei.Length > 16777215)
{
var msg = $"nutzdatendatei - Länger als 16777215: {nutzdatendatei.Length}";
throw new GkvException(msg);
}
protokoll.Datenaustauschreferenz = datenaustauschreferenz;
protokoll.Transfernummer = transfernummer;
protokoll.IKDatenannahmestelle = file_from_manager.GetIKDatenannahmestelle();
protokoll.IKKostentrager = file_from_manager.GetIKKostenträger();
protokoll.IKLeistungserbringer = file_from_manager.GetIKLeistungserbringer();
protokoll.IKKrankenkasse = file_from_manager.GetIKVersichertenKarte();
protokoll.Rechnungsnummer = file_from_manager.GetRechnungsnummer();
protokoll.Auftragsdatei = file_from_manager.GetAuftragsdatei();
protokoll.Nutzdatendatei = nutzdatendatei;
protokoll.Transfername = file_from_manager.GetTransferName();
protokoll.Dateigrosse = nutzdatendatei.Length;
protokoll.Dateityp = "Nutzdatendatei";
protokoll.Dateiname = protokoll.Transfername;
protokoll.AbsenderBezeichnung = "ownSoft GmbH";
protokoll.EmpfangerBezeichnung = orgadc.BezDatenannahmestelle;
return protokoll;
}
catch (GkvException de)
{
error = de.ToString();
}
catch (Exception e)
{
error = e.ToString();
}
return null;
}
private Tuple<int, int> GetNextDatenaustauschreferenzTransfernummer(GkvAbrechnung gkvAbrechnung, string datenannahmestelle)
{
var datenaustauschref = DAOFactory.SearchDAO.GetNextDatenaustauschreferenz(datenannahmestelle);
int transfernummer;
var state = gkvAbrechnung.GetState();
if (state == GkvState.NoSend)
{
transfernummer = DAOFactory.SearchDAO.GetNextTransfernummer(datenannahmestelle);
}
else if (state == GkvState.ErrorSoft || state == GkvState.ErrorFatal || state == GkvState.ErrorFolgefehler)
{
transfernummer = gkvAbrechnung.GkvTransferProtokolle.Last().Transfernummer;
}
else
{
throw new ArgumentException($"Versucht Transfernummer zu laden, invalid state: {state}", nameof(state));
}
return new Tuple<int, int>(datenaustauschref, transfernummer);
}
private Tuple<int, int> ClearDatenaustauschreferenzTransfernummer(int datenaustauschreferenz, int transfernummer)
{
int d = datenaustauschreferenz % 99999;
int t = transfernummer % 1000;
if (d == 0)
{
d = 99999;
}
return new Tuple<int, int>(d, t);
}
private GkvServerSendNewResponseDC SendApp8SendNewRequest(GkvTransferProtokoll protokoll)
{
var gkv_transfer_dc = MapperFactory.GkvTransferProtokollDC_GkvTransferprotokoll.MapToNewDC(protokoll);
var request_app8 = new GkvServerSendNewRequestDC
{
Protokoll = gkv_transfer_dc
};
var response_app8 = SendApp8Request<GkvServerSendNewRequestDC, GkvServerSendNewResponseDC>(request_app8);
if (!response_app8.Success)
throw new GkvException(response_app8.Message);
return response_app8;
}
/// <summary>
///
/// </summary>
/// <param name="updateables"></param>
/// <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)
{
var updateables_len = updateables.Count();
var request = new GkvServerGetStatusRequestDC
{
Tenant = MultitenancyOperationContextExt.Current.Tenant,
Oids = new long[updateables_len]
};
for (int id = 0; id < updateables_len; id++)
{
var gkv_abrechnung = updateables[id];
var gkv_transfer = gkv_abrechnung.TransferProtokolle.Last();
request.Oids[id] = gkv_transfer.GkvTransferProtokollOid.Value;
}
GkvServerGetStatusResponseDC response_app8;
try
{
response_app8 = SendApp8Request<GkvServerGetStatusRequestDC, GkvServerGetStatusResponseDC>(request);
}
catch (Exception e)
{
MailUtils.SendGkvModuleErrorMail("GkvServerGetStatusRequest Error", e, Tenant);
return true;
}
if (!response_app8.Success)
throw new GkvException("Success false - " + response_app8.Message);
if (response_app8.Results is null)
throw new GkvException("Result null - " + response_app8.Message);
var results = response_app8.Results.Where(x => x is object);
if (!results.Any())
return true;
HandleGkvServerResults(results);
return false;
}
public void HandleGkvServerResults(IEnumerable<GkvServerResultDC> results)
{
var protokolls = new List<GkvTransferProtokoll>();
foreach (var result in results)
{
var protokoll = DAOFactory.GenericDAO.GetByID<GkvTransferProtokoll>(result.ProtokollOid);
protokoll.ResultType = result.ResultType;
protokoll.Fehlertitel = result.Titel;
protokoll.Fehlerdatum = result.Datum;
protokoll.Fehlernachricht = result.Nachricht;
switch (result.ResultType)
{
case GkvTransferResultType.Success:
protokoll.SentDakotaSuccess = true;
break;
case GkvTransferResultType.FailSoft:
protokoll.SentApp8Success = false;
break;
case GkvTransferResultType.FailFatal:
protokoll.SentApp8Success = false;
break;
case GkvTransferResultType.FailFollowUp:
protokoll.SentApp8Success = false;
break;
}
protokolls.Add(protokoll);
}
if (protokolls.Any())
DAOFactory.GenericDAO.Update(protokolls);
var follows = results.Where(x => x.ResultType == GkvTransferResultType.FailFollowUp);
if (follows.Any())
{
foreach (var follow in follows)
{
var protokoll_oid = follow.ProtokollOid;
var protokoll = DAOFactory.GenericDAO.LoadByID<GkvTransferProtokoll>(protokoll_oid);
var abrechnung_oid = protokoll.GkvAbrechnungOid;
var new_req = new GkvAbrechnungSendRequestDC()
{
GkvAbrechnungOid = abrechnung_oid
};
var res = SendNewGkvAbrechnung(new_req);
if (!res.Success)
throw new GkvException("Success - " + res.Message);
}
}
}
private Res SendApp8Request<Req, Res>(Req request) where Req : GkvServerRequestDC where Res : GkvResponseDC
{
var user = LoggedInUserOperationContextExt.Current?.User ?? SessionFacade.LoggedInUser;
if (user == null)
{
throw new GkvException("User unbekannt", "KundenApp");
}
request.Username = user.LoginName;
request.Password = user.BCryptPassword;
request.Tenant = MultitenancyOperationContextExt.Current.Tenant;
if (request is GkvServerSendNewRequestDC send_new_req)
{
send_new_req.ApplicationUserOid = user.Oid.Value;
}
return GkvSender.SendApp8Request<Req, Res>(request, request.Tenant);
}
#endregion
}
}

View File

@@ -0,0 +1,50 @@
using BeWo.Data.Access;
using BeWo.Service.ServiceContracts;
using BS.Shared.Core;
using BS.Shared.DataContracts.AdminService;
using DevExpress.Pdf.Native.BouncyCastle.Ocsp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceImplementations
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class AdminServiceImp : IAdminService
{
public string Test()
{
return "Test erfolgreich!";
}
public string Echo(string echo)
{
return echo;
}
public object GetGkvAbrechnungSumme(AdminServiceSumReqDC request)
{
if (request == null)
{
throw new ArgumentException("request darf nicht null sein");
}
if(!Utils.TryParseISO8601(request.Start, out var start))
{
throw new ArgumentException("start entspricht nicht ISO8601 Norm.");
}
if (!Utils.TryParseISO8601(request.End, out var end))
{
throw new ArgumentException("end entspricht nicht ISO8601 Norm.");
}
var sum = DAOFactory.ScriptDAO.GetGkvSumByDateRange(start, end);
return sum?.ToString("0.00");
}
}
}

View File

@@ -0,0 +1,669 @@
using BeWo.Data;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.Core;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Plugins;
using BeWo.Service.ServiceContracts;
using BS.Shared;
using BS.Shared.AppSender;
using BS.Shared.Core;
using BS.Shared.DataContracts.GkvAbrechnung;
using BS.Shared.Exceptions;
using BS.Shared.Extensions;
using Dakota;
using Dakota.Logic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using Utils = BeWo.Service.Core.Utils;
namespace BeWo.Service.ServiceImplementations
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class GkvAccountingServiceImp : IGkvAccountingService
{
public string Tenant => MultitenancyOperationContextExt.Current?.Tenant;
public GkvAbrechnungDC GetGkvAbrechnung(long oid)
{
try
{
var gkv = DAOFactory.GenericDAO.GetByID<GkvAbrechnung>(oid);
var dc = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(gkv);
MapperFactory.GkvAbrechnungDC_GkvAbrechnung.ClearRawData(dc);
return dc;
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public List<GkvAbrechnungDC> GetFilteredGkvAbrechnungen(GkvAbrechnungViewFilterDC gkvAbrechnungViewFilter)
{
try
{
if (gkvAbrechnungViewFilter == null || !gkvAbrechnungViewFilter.FilterTime)
return GetAllGkvAbrechnungen();
var start = gkvAbrechnungViewFilter.Start;
var end = gkvAbrechnungViewFilter.End;
var filter = gkvAbrechnungViewFilter.FilterForInvoiceDate;
return GetGkvAbrechnungen(() => DAOFactory.SearchDAO.GetGkvAbrechnungen(start, end, filter));
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public List<GkvAbrechnungDC> GetAllGkvAbrechnungen()
{
try
{
return GetGkvAbrechnungen(() => DAOFactory.GenericDAO.GetAllActive<GkvAbrechnung>());
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
private List<GkvAbrechnungDC> GetGkvAbrechnungen(Func<IEnumerable<GkvAbrechnung>> get_entities)
{
var entities = get_entities();
var dcs = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDCs(entities);
MapperFactory.GkvAbrechnungDC_GkvAbrechnung.ClearRawData(dcs);
var updateables = dcs.Where(x => x.IsWaiting()).ToArray();
if (!updateables.Any())
return dcs;
var isUpToDate = SendApp8GetStatusRequest(updateables);
if (isUpToDate)
return dcs;
entities = get_entities();
dcs = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDCs(entities);
MapperFactory.GkvAbrechnungDC_GkvAbrechnung.ClearRawData(dcs);
return dcs;
}
public string GetProtokollRawDataString(long oid, GkvRawDataType gkvRawData)
{
try
{
if (oid <= 0)
{
throw new ArgumentOutOfRangeException(nameof(oid), $"oid \'{oid}\' nicht positiv");
}
var str = DAOFactory.SearchDAO.GetGkvRawData(oid, gkvRawData);
return str;
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public GkvAbrechnungCreateResponseDC CreateNewGkvAbrechnung(GkvAbrechnungCreateRequestDC request)
{
var response = new GkvAbrechnungCreateResponseDC();
try
{
var invoice_bases = DAOFactory.GenericDAO.LoadByIDs<InvoiceBase>(request.SelectedInvoiceBases);
ValidatorExtended.ValidateGkvAbrechnung(request.GkvAbrechnungDC, invoice_bases);
var gkv_abrechnung = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewEntity(request.GkvAbrechnungDC);
if (gkv_abrechnung.AbrechnungsZeitraumEnde.Value.Hour == 0)
{
gkv_abrechnung.AbrechnungsZeitraumEnde = gkv_abrechnung.AbrechnungsZeitraumEnde.Value.Date.AddDays(1).AddMilliseconds(-1);
}
var orga = gkv_abrechnung.Organisation;
gkv_abrechnung.Verfahrensstufe = orga.Verfahrensstufe;
decimal gesamt = 0;
foreach (var invoicebase_oid in request.SelectedInvoiceBases)
{
var service = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(invoicebase_oid);
foreach (var peroid in service.ServiceInvoicePeriodList)
{
foreach (var invoice in peroid.InvoiceItemList)
{
gesamt += invoice.AmountTotal.Value;
}
}
}
gkv_abrechnung.Betrag = gesamt;
gkv_abrechnung.Bezahlt = false;
gkv_abrechnung.ErstelltAm = DateTime.Now;
DAOFactory.GenericDAO.Insert(gkv_abrechnung);
var gkv_abrechnung_dc = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(gkv_abrechnung);
response.Success = true;
response.GkvAbrechnungDC = gkv_abrechnung_dc;
}
catch (GkvException exc)
{
MailUtils.SendGkvModuleErrorMail("CreateNewGkvAbrechnung", exc, Tenant);
if (exc.Title.IsNotNullOrWhiteSpace())
response.TitleMessage = exc.Title;
response.Message = exc.Message;
}
catch (Exception e)
{
MailUtils.SendGkvModuleErrorMail("CreateNewGkvAbrechnung", e, Tenant);
throw Utils.CreateBeWoFaultException(e);
}
return response;
}
public GkvAbrechnungDC UpdateGkvAbrechnung(GkvAbrechnungDC abrechnung)
{
try
{
var entity = DAOFactory.GenericDAO.GetByID<GkvAbrechnung>(abrechnung.GkvAbrechnungOid.Value);
if(entity.Notice != abrechnung.Notice)
entity.Notice = abrechnung.Notice;
if (entity.UrbelegeGesendet != abrechnung.UrbelegeGesendet)
entity.UrbelegeGesendet = abrechnung.UrbelegeGesendet;
if (entity.Bezahlt != abrechnung.Bezahlt)
{
entity.Bezahlt = abrechnung.Bezahlt;
foreach (var invoice in entity.InvoiceBases)
{
invoice.IsPaid = entity.Bezahlt;
}
}
DAOFactory.GenericDAO.Update(entity);
var dc = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(entity);
MapperFactory.GkvAbrechnungDC_GkvAbrechnung.ClearRawData(dc);
return dc;
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
public void DeleteGkvAbrechnung(GkvAbrechnungDC abrechnung)
{
try
{
ServiceLogic.SetActivationType<GkvAbrechnung>(abrechnung.GkvAbrechnungOid.Value, abrechnung.GkvAbrechnungVersion.Value, ActivationTypeId.Deleted);
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
/// <summary>
/// Erstellt GkvTransferProtokoll
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public GkvAbrechnungSendResponseDC SendNewGkvAbrechnung(GkvAbrechnungSendRequestDC req)
{
var response = new GkvAbrechnungSendResponseDC();
var oid = req.GkvAbrechnungOid;
var entity = DAOFactory.GenericDAO.LoadByID<GkvAbrechnung>(oid);
var state = entity.GetState();
if (entity.IsWaiting() || state == GkvState.Paid)
{
response.Message = "Validierung fehlgeschlagen";
return response;
}
var protokoll = CreateGkvTransferProtokoll(entity, out var error);
if (error is object)
{
MailUtils.SendGkvModuleErrorMail("SendNewGkvAbrechnung - CreateGkvTransferProtokoll", error, Tenant);
response.TitleMessage = "Protokoll Erstellung";
response.Message = error;
return response;
}
if (entity.GkvTransferProtokolle is null)
entity.GkvTransferProtokolle = new List<GkvTransferProtokoll>();
entity.GkvTransferProtokolle.Add(protokoll);
// Protokoll braucht Oid
DAOFactory.GenericDAO.Update(entity);
try
{
var app8_response = SendApp8SendNewRequest(protokoll);
var app8_protokoll = app8_response.GkvTransferProtokollDC;
MapperFactory.GkvTransferProtokollDC_GkvTransferprotokoll.MergeWithEntity(app8_protokoll, protokoll);
response.Success = app8_response.Success;
response.Message = app8_response.Message;
}
catch (GkvException de)
{
protokoll.ResultType = GkvTransferResultType.FailSoft;
protokoll.Fehlerdatum = DateTime.Now;
protokoll.Fehlernachricht = de.Message;
protokoll.Fehlertitel = de.Title ?? "Default";
}
catch (Exception e)
{
protokoll.ResultType = GkvTransferResultType.FailFatal;
protokoll.Fehlerdatum = DateTime.Now;
protokoll.Fehlernachricht = e.ToString();
protokoll.Fehlertitel = "Erstellung (kritisch)";
}
DAOFactory.GenericDAO.Update(entity);
response.TransferProtokoll = MapperFactory.GkvTransferProtokollDC_GkvTransferprotokoll.MapToNewDC(protokoll);
response.GkvAbrechnungDC = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(entity);
MapperFactory.GkvTransferProtokollDC_GkvTransferprotokoll.ClearRawData(response.TransferProtokoll);
MapperFactory.GkvAbrechnungDC_GkvAbrechnung.ClearRawData(response.GkvAbrechnungDC);
return response;
}
public GkvAbrechnungGetIKResponseDC SendGetIKRequest(GkvAbrechnungGetIKRequestDC req)
{
try
{
var app8req = new GkvServerGetIKRequestDC
{
IKKrankenkasse = req.IKKrankenkasse,
Leistungserbringergruppe = req.Leistungserbringergruppe,
Abrechnungscode = DakotaUtils.GetAbrechnungscode(req.Leistungserbringergruppe),
Tarifkennzeichen = DakotaUtils.GetTarifkennzeichen(req.Leistungserbringergruppe)
};
var app8res = SendApp8Request<GkvServerGetIKRequestDC, GkvServerGetIKResponseDC>(app8req);
// Erstelle Response
var res = new GkvAbrechnungGetIKResponseDC
{
BezDatenannahmestelle = app8res.BezDatenannahmestelle,
Gefunden = app8res.Gefunden,
IKDatenannahmestelle = app8res.IKDatenannahmestelle,
IKKostentrager = app8res.IKKostentrager,
IKKrankenkasse = app8res.IKKrankenkasse,
Message = app8res.Message,
Success = app8res.Success
};
// Schaue, ob IK Krankenkassen bereits bei einer anderen Organisation hinterlegt ist
if (res.Gefunden)
{
// Holt alle Organisationen
var orgas = DAOFactory.SearchDAO.GetAllOrganisationByIKKrankenkasse(req.IKKrankenkasse);
// Entfernt sich selber
if (req.OrganisationOid is long oid)
{
orgas.RemoveAll(x => x.Oid == oid);
}
if (orgas.Any())
{
res.BereitsEnthalten = true;
res.BereitsEnthaltenBei = orgas.Select(x => x.Name).ToList();
}
}
return res;
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
private GkvTransferProtokoll CreateGkvTransferProtokoll(GkvAbrechnung gkvAbrechnung, out string error)
{
var protokoll = new GkvTransferProtokoll
{
ErstelltAm = DateTime.Now,
GkvAbrechnungOid = gkvAbrechnung.Oid.Value
};
error = null;
try
{
ValidatorExtended.ValidateGkvAbrechnung(gkvAbrechnung, gkvAbrechnung.InvoiceBases);
var manager = new DakotaManager();
var mandatordc = new OperationsServiceImp().GetMandator();
Validator.ValidateMandator(mandatordc);
var gkvAbrechnungDC = MapperFactory.GkvAbrechnungDC_GkvAbrechnung.MapToNewDC(gkvAbrechnung);
var orgadc = gkvAbrechnungDC.Organisation;
Validator.ValidateOrganisation(orgadc);
var datenannahmestelle = orgadc.IKDatenannahmestelle;
var (datenaustauschreferenz, transfernummer) = GetNextDatenaustauschreferenzTransfernummer(gkvAbrechnung, datenannahmestelle);
var (dat_short, tra_short) = ClearDatenaustauschreferenzTransfernummer(datenaustauschreferenz, transfernummer);
var first_cost = gkvAbrechnung.InvoiceBases.First().CostBearer2SupportConcept.SupportConcept.Customer;
var plugin = PluginLoader.FindClass<AccountingService>();
var addressInfo = plugin.GetAddressInformation(first_cost.Oid);
foreach (var invoicebase in gkvAbrechnung.InvoiceBases)
{
var customer = invoicebase.CostBearer2SupportConcept.SupportConcept.Customer;
var addressInfo2 = plugin.GetAddressInformation(customer.Oid);
if (addressInfo.IKLeistungserbringer != addressInfo2.IKLeistungserbringer)
{
throw new GkvException($"Klient '{first_cost.Person.LastNameFirstName}' ({addressInfo.IKLeistungserbringer}) und '{customer.Person.LastNameFirstName}' ({addressInfo2.IKLeistungserbringer}) verweisen auf unterschiedliche Leistungserbringer.");
}
}
foreach (var invoicebase in gkvAbrechnung.InvoiceBases)
{
var service = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(invoicebase.Oid.Value);
var orga2 = invoicebase.CostBearer2SupportConcept.CostBearer.Organisation;
var customer = invoicebase.CostBearer2SupportConcept.SupportConcept.Customer;
var invoicebase_dc = MapperFactory.InvoiceBaseDC_InvoiceBase.MapToNewDC(invoicebase);
var servicedc = MapperFactory.ServiceInvoiceDC_ServiceInvoice.MapToNewDC(service);
var customerdc = MapperFactory.CustomerDC_Customer.MapToNewDC(customer);
Validator.ValidateCustomer(customerdc);
manager.Add(servicedc, orgadc, customerdc, addressInfo, dat_short, tra_short);
}
manager.Apply();
if (manager.DakotaFileDict.Count != 1 || manager.DakotaFileDict.First().Value.GetKostenträgerCount() != 1)
{
var msg = "Unerwartete Anzahl an Dakota Files berechnet.";
throw new GkvException(msg);
}
var file_from_manager = manager.DakotaFileDict.First().Value;
var nutzdatendatei = file_from_manager.GetNutzdatendatei();
// https://dev.mysql.com/doc/refman/8.3/en/string-type-syntax.html
// A TEXT column with a maximum length of 16,777,215 (224 1) characters.
// The effective maximum length is less if the value contains multibyte characters.
// Each MEDIUMTEXT value is stored using a 3-byte length prefix that indicates the number of bytes in the value.
//
// Type | Maximum length
// -----------+-------------------------------------
// TINYTEXT | 255(2^81) bytes
// TEXT | 65,535(2^161) bytes = 64 KiB
// MEDIUMTEXT | 16,777,215(2^241) bytes = 16 MiB
// LONGTEXT | 4,294,967,295(2^321) bytes = 4 GiB
if (nutzdatendatei.Length > 16777215)
{
var msg = $"nutzdatendatei - Länger als 16777215: {nutzdatendatei.Length}";
throw new GkvException(msg);
}
protokoll.Datenaustauschreferenz = datenaustauschreferenz;
protokoll.Transfernummer = transfernummer;
protokoll.IKDatenannahmestelle = file_from_manager.GetIKDatenannahmestelle();
protokoll.IKKostentrager = file_from_manager.GetIKKostenträger();
protokoll.IKLeistungserbringer = file_from_manager.GetIKLeistungserbringer();
protokoll.IKKrankenkasse = file_from_manager.GetIKVersichertenKarte();
protokoll.Rechnungsnummer = file_from_manager.GetRechnungsnummer();
protokoll.Auftragsdatei = file_from_manager.GetAuftragsdatei();
protokoll.Nutzdatendatei = nutzdatendatei;
protokoll.Transfername = file_from_manager.GetTransferName();
protokoll.Dateigrosse = nutzdatendatei.Length;
protokoll.Dateityp = "Nutzdatendatei";
protokoll.Dateiname = protokoll.Transfername;
protokoll.AbsenderBezeichnung = "ownSoft GmbH";
protokoll.EmpfangerBezeichnung = orgadc.BezDatenannahmestelle;
return protokoll;
}
catch (GkvException de)
{
error = de.ToString();
}
catch (Exception e)
{
error = e.ToString();
}
return null;
}
private Tuple<int, int> GetNextDatenaustauschreferenzTransfernummer(GkvAbrechnung gkvAbrechnung, string datenannahmestelle)
{
var datenaustauschref = DAOFactory.SearchDAO.GetNextDatenaustauschreferenz(datenannahmestelle);
int transfernummer;
var state = gkvAbrechnung.GetState();
if (state == GkvState.NoSend)
{
transfernummer = DAOFactory.SearchDAO.GetNextTransfernummer(datenannahmestelle);
}
else if (state == GkvState.ErrorSoft || state == GkvState.ErrorFatal || state == GkvState.ErrorFolgefehler)
{
transfernummer = gkvAbrechnung.GkvTransferProtokolle.Last().Transfernummer;
}
else
{
throw new ArgumentException($"Versucht Transfernummer zu laden, invalid state: {state}", nameof(state));
}
return new Tuple<int, int>(datenaustauschref, transfernummer);
}
private Tuple<int, int> ClearDatenaustauschreferenzTransfernummer(int datenaustauschreferenz, int transfernummer)
{
int d = datenaustauschreferenz % 99999;
int t = transfernummer % 1000;
if (d == 0)
{
d = 99999;
}
return new Tuple<int, int>(d, t);
}
private GkvServerSendNewResponseDC SendApp8SendNewRequest(GkvTransferProtokoll protokoll)
{
var gkv_transfer_dc = MapperFactory.GkvTransferProtokollDC_GkvTransferprotokoll.MapToNewDC(protokoll);
var request_app8 = new GkvServerSendNewRequestDC
{
Protokoll = gkv_transfer_dc
};
var response_app8 = SendApp8Request<GkvServerSendNewRequestDC, GkvServerSendNewResponseDC>(request_app8);
if (!response_app8.Success)
throw new GkvException(response_app8.Message);
return response_app8;
}
/// <summary>
///
/// </summary>
/// <param name="updateables"></param>
/// <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)
{
var updateables_len = updateables.Count();
var request = new GkvServerGetStatusRequestDC
{
Tenant = MultitenancyOperationContextExt.Current.Tenant,
Oids = new long[updateables_len]
};
for (int id = 0; id < updateables_len; id++)
{
var gkv_abrechnung = updateables[id];
var gkv_transfer = gkv_abrechnung.TransferProtokolle.Last();
request.Oids[id] = gkv_transfer.GkvTransferProtokollOid.Value;
}
GkvServerGetStatusResponseDC response_app8;
try
{
response_app8 = SendApp8Request<GkvServerGetStatusRequestDC, GkvServerGetStatusResponseDC>(request);
}
catch (Exception e)
{
MailUtils.SendGkvModuleErrorMail("GkvServerGetStatusRequest Error", e, Tenant);
return true;
}
if (!response_app8.Success)
throw new GkvException("Success false - " + response_app8.Message);
if (response_app8.Results is null)
throw new GkvException("Result null - " + response_app8.Message);
var results = response_app8.Results.Where(x => x is object);
if (!results.Any())
return true;
HandleGkvServerResults(results);
return false;
}
public void HandleGkvServerResults(IEnumerable<GkvServerResultDC> results)
{
var protokolls = new List<GkvTransferProtokoll>();
foreach (var result in results)
{
var protokoll = DAOFactory.GenericDAO.GetByID<GkvTransferProtokoll>(result.ProtokollOid);
protokoll.ResultType = result.ResultType;
protokoll.Fehlertitel = result.Titel;
protokoll.Fehlerdatum = result.Datum;
protokoll.Fehlernachricht = result.Nachricht;
switch (result.ResultType)
{
case GkvTransferResultType.Success:
protokoll.SentDakotaSuccess = true;
break;
case GkvTransferResultType.FailSoft:
protokoll.SentApp8Success = false;
break;
case GkvTransferResultType.FailFatal:
protokoll.SentApp8Success = false;
break;
case GkvTransferResultType.FailFollowUp:
protokoll.SentApp8Success = false;
break;
}
protokolls.Add(protokoll);
}
if (protokolls.Any())
DAOFactory.GenericDAO.Update(protokolls);
var follows = results.Where(x => x.ResultType == GkvTransferResultType.FailFollowUp);
if (follows.Any())
{
foreach (var follow in follows)
{
var protokoll_oid = follow.ProtokollOid;
var protokoll = DAOFactory.GenericDAO.LoadByID<GkvTransferProtokoll>(protokoll_oid);
var abrechnung_oid = protokoll.GkvAbrechnungOid;
var new_req = new GkvAbrechnungSendRequestDC()
{
GkvAbrechnungOid = abrechnung_oid
};
var res = SendNewGkvAbrechnung(new_req);
if (!res.Success)
throw new GkvException("Success - " + res.Message);
}
}
}
private Res SendApp8Request<Req, Res>(Req request) where Req : GkvServerRequestDC where Res : GkvResponseDC
{
var user = LoggedInUserOperationContextExt.Current?.User ?? SessionFacade.LoggedInUser;
if (user == null)
{
throw new GkvException("User unbekannt", "KundenApp");
}
request.Username = user.LoginName;
request.Password = user.BCryptPassword;
request.Tenant = MultitenancyOperationContextExt.Current.Tenant;
if (request is GkvServerSendNewRequestDC send_new_req)
{
send_new_req.ApplicationUserOid = user.Oid.Value;
}
return GkvSender.SendApp8Request<Req, Res>(request, request.Tenant);
}
}
}