From 3c96d1aac4baa24dfdff894d3255e7d637b4610c Mon Sep 17 00:00:00 2001 From: Rene Evertz Date: Tue, 29 Oct 2024 15:23:30 +0100 Subject: [PATCH] Zwischenstand... - DakotaSender gibt detailiertere Fehlermeldung aus -> Ohne PDFs nachschauen - DakotaSender gruppiert Files nach Tenant und dann nach Datenannahmestelle. -> Konsistenz nur zwischen Tenant und Datenannahmestelle erforderlich. - DakotaSender sammelt Ergebnisse. Todo: - DakotaSender nach Bearbeitung Feedback an jeweilige AppServer - GkvAbrechnungServer wertet Feedback aus und startet ggf neuen Sendeprozess --- BeWo/ViewModel/GkvAbrechnungVM.cs | 4 +- DakotaSender/Config.cs | 65 ++ DakotaSender/DakotaSender.csproj | 8 + DakotaSender/DakotaSystemFile.cs | 1 + DakotaSender/Program.cs | 718 +++++++++--------- DakotaSender/Returncodes.cs | 111 +++ Host/GkvAbrechnungClient.aspx.cs | 6 +- Host/GkvAbrechnungServer.aspx.cs | 71 +- .../AccountingServiceImp.cs | 20 +- Shared/AppSender/GkvSender.cs | 2 +- Shared/BeWoEntityEnums.cs | 6 +- Shared/DataContracts/AppRequestDC.cs | 2 +- .../GkvAbrechnung/GkvClientResultRequestDC.cs | 8 +- .../GkvServerSendNewRequestDC.cs | 9 +- Shared/Extensions/GkvAbrechnungExtensions.cs | 4 +- 15 files changed, 614 insertions(+), 421 deletions(-) create mode 100644 DakotaSender/Config.cs create mode 100644 DakotaSender/Returncodes.cs diff --git a/BeWo/ViewModel/GkvAbrechnungVM.cs b/BeWo/ViewModel/GkvAbrechnungVM.cs index 66a54ff18..f12423e1b 100644 --- a/BeWo/ViewModel/GkvAbrechnungVM.cs +++ b/BeWo/ViewModel/GkvAbrechnungVM.cs @@ -446,11 +446,11 @@ namespace BeWo.ViewModel var protokoll = cb.TransferProtokoll; - if (protokoll.ResultType == GkvTransferResultType.Soft) + if (protokoll.ResultType == GkvTransferResultType.FailSoft) { MessageBox.Show(Application.Current.MainWindow, protokoll.Fehlernachricht, protokoll.Fehlertitel); } - else if (protokoll.ResultType == GkvTransferResultType.Fatal) + else if (protokoll.ResultType == GkvTransferResultType.FailFatal) { BeWoApp.ShowError(protokoll.Fehlertitel + ": " + protokoll.Fehlernachricht, null, false, false); } diff --git a/DakotaSender/Config.cs b/DakotaSender/Config.cs new file mode 100644 index 000000000..5ffea00a1 --- /dev/null +++ b/DakotaSender/Config.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DakotaSender +{ + internal static class Config + { + public static string GkvSecretKey { get; set; } = ConfigurationManager.AppSettings.Get("GkvSecretKey"); + + public static string LogPath { get; } + = ConfigurationManager.AppSettings.Get("LogPath") ?? @"C:\GkvAbrechnung\Sender\log.txt"; + public static int ProcessWaitForExitMs { get; } + = int.Parse(ConfigurationManager.AppSettings.Get("ProcessWaitForExitMs") ?? "10000"); + public static FileInfo DakotaExe { get; } + = new FileInfo(ConfigurationManager.AppSettings.Get("DakotaExePath") ?? @"C:\Program Files (x86)\ITSG\dakotale\dakota30.exe"); + public static DirectoryInfo DakotaFolder { get; } + = new DirectoryInfo(ConfigurationManager.AppSettings.Get("DakotaFolder") ?? @"C:\dakotale\"); + public static DirectoryInfo QueueFolder { get; } + = new DirectoryInfo(ConfigurationManager.AppSettings.Get("GkvAbrechnungQueueFolderPath") ?? @"C:\GkvAbrechnung\Queue\"); + public static DirectoryInfo ResultFolder { get; } + = new DirectoryInfo(ConfigurationManager.AppSettings.Get("GkvAbrechnungResultFolderPath") ?? @"C:\GkvAbrechnung\Results\"); + public static DirectoryInfo FailedFolder { get; } + = new DirectoryInfo(ConfigurationManager.AppSettings.Get("GkvAbrechnungFailedFolderPath") ?? @"C:\GkvAbrechnung\Failed\"); + + public static bool IsDatenannahmestelleValid(string datenannahmestelle) + { + try + { + _ = LoadDatenannahmestelleFolder(datenannahmestelle); + } + catch (Exception) + { + return false; + } + + return true; + } + public static DirectoryInfo LoadDatenannahmestelleFolder(string datenannahmestelle) + { + var folder = new DirectoryInfo(Path.Combine(Config.DakotaFolder.FullName, "TP5Daten", datenannahmestelle)); + + if (!folder.Exists) + folder = new DirectoryInfo(Path.Combine(Config.DakotaFolder.FullName, "TP5Daten", datenannahmestelle.Substring(0, datenannahmestelle.Length - 1))); + + if (!folder.Exists) + throw new Exception($"Datenannahmestelle {datenannahmestelle} konnte nicht gefunden werden."); + + return folder; + } + public static DirectoryInfo GetResultTenantFolder(string tenant) + { + var dirinfo = new DirectoryInfo(Path.Combine(Config.ResultFolder.FullName, tenant)); + + if (!dirinfo.Exists) + dirinfo.Create(); + + return dirinfo; + } + } +} diff --git a/DakotaSender/DakotaSender.csproj b/DakotaSender/DakotaSender.csproj index f35dcf96f..9fedb922f 100644 --- a/DakotaSender/DakotaSender.csproj +++ b/DakotaSender/DakotaSender.csproj @@ -44,6 +44,8 @@ + + @@ -53,5 +55,11 @@ + + + {2f50b83d-a3f0-4ec4-979a-3f9b7e3d8ed4} + Shared + + \ No newline at end of file diff --git a/DakotaSender/DakotaSystemFile.cs b/DakotaSender/DakotaSystemFile.cs index 2d0621553..b24cea9ef 100644 --- a/DakotaSender/DakotaSystemFile.cs +++ b/DakotaSender/DakotaSystemFile.cs @@ -11,6 +11,7 @@ namespace DakotaSender { public string Tenant { get; set; } public long ProtokollOid { get; set; } + public long ApplicationUserOid { get; set; } public string Datenannahmestelle { get; set; } public string Transfername { get; set; } public string TransfernameAuf => Transfername + ".auf"; diff --git a/DakotaSender/Program.cs b/DakotaSender/Program.cs index a98a0825a..cf5f8b2c0 100644 --- a/DakotaSender/Program.cs +++ b/DakotaSender/Program.cs @@ -1,4 +1,6 @@ -using System; +using BS.Shared; +using BS.Shared.DataContracts.GkvAbrechnung; +using System; using System.Collections.Generic; using System.Configuration; using System.Diagnostics; @@ -10,406 +12,408 @@ using System.Threading.Tasks; namespace DakotaSender { - class Program - { - const int RC_DAKOTA_ALREADY_LOADED = 18; + class Program + { + static readonly string TEST_TENANT = "7375324044"; - static readonly string TEST_TENANT = "7375324044"; + static bool time_in_line = false; + static bool is_dakota_running = false; - static int[] AcceptStatusCodes = new int[] { 0 }; - static int[] AcceptSendCodes = new int[] { 0 }; + static Dictionary> handleRequests; - static bool time_in_line = false; + static void Main(string[] args) + { + FileStream filestream = new FileStream(Config.LogPath, FileMode.Append); + var streamwriter = new StreamWriter(filestream); + streamwriter.AutoFlush = true; - static void Main(string[] args) - { - FileStream filestream = new FileStream(GetLogPath(), FileMode.Append); - var streamwriter = new StreamWriter(filestream); - streamwriter.AutoFlush = true; + Console.SetOut(streamwriter); + Console.SetError(streamwriter); - Console.SetOut(streamwriter); - Console.SetError(streamwriter); - - try - { - PrintTitle(); - - CheckDakotaStatus(); - - ProcessFiles(); - } - catch (Exception e) - { - PrintLine(e.ToString()); - } - - PrintEnd(); - } - - static void PrintTitle() - { - PrintWithTime("\n", false); - PrintLine("-------------------"); - PrintLine("Dakota Sender Modul"); - PrintLine("-------------------"); - } - static void PrintEnd() - { - PrintLine("Ende"); - PrintLine("-------------------"); - } - - static void PrintLine() => PrintLine(null); - static void PrintLine(string line) - { - PrintWithTime(line + "\n", !time_in_line); - - time_in_line = false; - } - static void Print(string line) - { - PrintWithTime(line, !time_in_line); - - time_in_line = true; - } - static void PrintWithTime(string line, bool showTime) - { - if (showTime) - Console.Write($"[{DateTime.Now:dd.MM.yy HH:mm:ss.fff}] {line}"); - else - Console.Write(line); - } - static void PrintFileInfo(DakotaSystemFile file) - { - PrintLine($"Verarbeite Datei: {file.SourceNutzdatendatei.Name}"); - PrintLine($"- Tenant: {file.Tenant}"); - PrintLine($"- Protokoll Oid: {file.ProtokollOid}"); - PrintLine($"- Datenannahmestelle: {file.Datenannahmestelle}"); - } - - static void CheckDakotaStatus() - { - PrintLine("Überprüfe Dakota Status"); - - var code = ExecuteDakota("-s"); - - if (AcceptStatusCodes.Contains(code)) - { - PrintLine("Ok"); - } - else - { - throw new Exception($"Statuscode {code} wird nicht akzeptiert"); - } - } - static void ProcessFiles() - { - PrintLine("Scanne Dakota Dateien"); - - var toCheck = ScanQueueFolder(); - - if (toCheck is null) - { - PrintLine("Keine Dakota Dateien gefunden."); - return; - } - - var testCheck = toCheck.TryGetValue(TEST_TENANT, out var files); - - if (!testCheck) - { - PrintLine($"Keine Dakota Dateien für {TEST_TENANT} gefunden."); - return; - } - - foreach (var file in files) - { - TryProcessFile(file); - - CheckDakotaStatus(); - } - } - - static Dictionary> ScanQueueFolder() - { - var queue = GetQueueFolder(); - - var files = queue.GetFiles("*.auf", SearchOption.TopDirectoryOnly); - - var toCheck = new Dictionary>(); - foreach (var auft in files) - { - var nutz_fullname = auft.FullName.Substring(0, auft.FullName.Length - 4); - var nutz = new FileInfo(nutz_fullname); - - if (!nutz.Exists) - { - PrintLine($"{auft.FullName} wird ignoriert. {nutz.FullName} nicht vorhanden"); - continue; - } - - PrintLine($"{auft.FullName} gefunden."); - - var split = nutz.Name.Split('_'); - var tenant = split[0]; - var p_oid = long.Parse(split[1]); - var datenannahmestelle = split[2]; - var transfername = split[3]; - - // Muss nachher nur entfernt werden, um andere zu testen - if (tenant != TEST_TENANT && tenant != "demo") - { - PrintLine($"{auft.FullName} wird ignoriert. Tenant {tenant} nicht gültig."); - continue; - } - else - { - tenant = TEST_TENANT; - } - - var file = new DakotaSystemFile() - { - SourceAuftragsdatei = auft, - SourceNutzdatendatei = nutz, - Tenant = tenant, - ProtokollOid = p_oid, - Datenannahmestelle = datenannahmestelle, - Transfername = transfername, - }; - - if (!toCheck.ContainsKey(tenant)) - toCheck.Add(tenant, new List()); - - toCheck[tenant].Add(file); - } - - return toCheck.Any() ? toCheck : null; - } - - static void TryProcessFile(DakotaSystemFile file) - { - string error; - bool copied = false; - try - { - error = ProcessFile(file, out copied); - } - catch (Exception e) - { - error = e.ToString(); - } - - if (error == string.Empty) + try { - // Dakota läuft bereits. - // Nächster Run + PrintTitle(); + + CheckDakotaStatus(); + + HandleQueueFiles(); } - else if (error is string) - { - PrintLine(error); - MoveQueueToFailed(file); + catch (Exception e) + { + PrintLine(e.ToString()); - if (copied) - DeleteDakotaFile(file); + if (is_dakota_running) + { + PrintLine($"Verarbeitung im Silent Modus fehlgeschlagen. dakota30.exe läuft (bereits)."); + PrintLine("Ignoriere Verarbeitung aktuell. Versuche im nächsten Programm Aufruf erneut."); + } + } - CreateResultFehlerXmlFile(file, error); - } + PrintEnd(); + } + + static void PrintTitle() + { + PrintWithTime("\n", false); + PrintLine("-------------------"); + PrintLine("Dakota Sender Modul"); + PrintLine("-------------------"); + } + static void PrintEnd() + { + PrintLine("Ende"); + PrintLine("-------------------"); + } + + static void PrintLine() => PrintLine(null); + static void PrintLine(string line) + { + PrintWithTime(line + "\n", !time_in_line); + + time_in_line = false; + } + static void Print(string line) + { + PrintWithTime(line, !time_in_line); + + time_in_line = true; + } + static void PrintWithTime(string line, bool showTime) + { + if (showTime) + Console.Write($"[{DateTime.Now:dd.MM.yy HH:mm:ss.fff}] {line}"); + else + Console.Write(line); + } + static void PrintFileInfo(DakotaSystemFile file) + { + PrintLine($"Verarbeite Datei: {file.SourceNutzdatendatei.Name}"); + PrintLine($"- Tenant: {file.Tenant}"); + PrintLine($"- Protokoll Oid: {file.ProtokollOid}"); + PrintLine($"- Datenannahmestelle: {file.Datenannahmestelle}"); + } + + static void CheckDakotaStatus() + { + PrintLine("Überprüfe Dakota Status"); + + var code = ExecuteDakota("-s"); + + Returncodes.EvaluateStatusCode(code, out is_dakota_running, out bool accept, out string message); + + if (accept) + { + PrintLine(message); + } else { - CreateResultSuccessXmlFile(file); + throw new Exception($"Statuscode {code} wird nicht akzeptiert. {message}"); } - } - static string ProcessFile(DakotaSystemFile file, out bool copied) - { - copied = false; - - PrintFileInfo(file); - - if (!IsDakotaFolderDatenannahmestelleValid(file.Datenannahmestelle)) - return "Datenannahmestelle unbekannt."; - - CopyFileToDestination(file); - copied = true; - - Print("Sende via Dakota. "); - - var code = ExecuteDakota("-x"); - - if (code == RC_DAKOTA_ALREADY_LOADED) - { - PrintLine($"Verarbeitung fehlgeschlagen. Dakota läuft bereits."); - - PrintLine("Ignoriere Verarbeitung aktuell. Versuche im nächsten Programm Aufruf erneut."); - - DeleteDakotaFile(file); - - return string.Empty; - } - - if (!AcceptSendCodes.Contains(code)) - return $"Verarbeitung fehlgeschlagen. Statuscode {code} wird nicht akzeptiert."; - - PrintLine($"Ok."); - DeleteQueueFile(file); - return null; - } - - static void CreateResultSuccessXmlFile(DakotaSystemFile file) - => CreateResultXmlFile(file, "Dakota Erfolg", "", 0); - static void CreateResultFehlerXmlFile(DakotaSystemFile file, string error) - => CreateResultXmlFile(file, "Dakota Fehler", error, 1); - static void CreateResultXmlFile(DakotaSystemFile file, string title, string nachricht, int fehler_level) + } + static Dictionary>> ScanQueueFolder() { - Print($"Speichere {title} als Xml. "); + var queue = Config.QueueFolder; - var result = new ResultXml(); + var files = queue.GetFiles("*.auf", SearchOption.TopDirectoryOnly) + .OrderBy(x => x.FullName); - result.Datum = DateTime.Now; - result.Titel = title; - result.Nachricht = nachricht; - result.Level = fehler_level; - result.Oid = file.ProtokollOid; + var ten2dat2files = new Dictionary>>(); + foreach (var auft in files) + { + var nutz_fullname = auft.FullName.Substring(0, auft.FullName.Length - 4); + var nutz = new FileInfo(nutz_fullname); - var folder = GetResultFolderTenant(file.Tenant).FullName; - var path = Path.Combine(folder, $"P{file.ProtokollOid}.xml"); + if (!nutz.Exists) + { + PrintLine($"{auft.FullName} wird ignoriert. {nutz.FullName} nicht vorhanden"); + continue; + } - Print($"Path: {path}. "); + PrintLine($"{auft.FullName} gefunden."); - XmlFileConverter.Save(result, path); + var split = nutz.Name.Split('_'); + var tenant = split[0]; + var p_oid = long.Parse(split[1]); + var app_oid = long.Parse(split[2]); + var datenannahmestelle = split[3]; + var transfername = split[4]; - PrintLine("Ok."); - } + // Muss nachher nur entfernt werden, um andere zu testen + // Ggf Tool einbauen? + if (tenant != TEST_TENANT && tenant != "demo") + { + PrintLine($"{auft.FullName} wird ignoriert. Tenant {tenant} nicht gültig."); + continue; + } + else + { + tenant = TEST_TENANT; + } - static void MoveQueueToFailed(DakotaSystemFile file) - { - CopyFileToFailed(file); + var file = new DakotaSystemFile() + { + SourceAuftragsdatei = auft, + SourceNutzdatendatei = nutz, + Tenant = tenant, + ProtokollOid = p_oid, + ApplicationUserOid = app_oid, + Datenannahmestelle = datenannahmestelle, + Transfername = transfername, + }; - DeleteQueueFile(file); - } + if (!ten2dat2files.ContainsKey(tenant)) + ten2dat2files.Add(tenant, new Dictionary>()); - static void CopyFileToFailed(DakotaSystemFile file) - { - var failed_folder = GetFailedFolder(); + var dat2files = ten2dat2files[tenant]; - CopyFileTo(file.SourceAuftragsdatei, failed_folder.FullName); - CopyFileTo(file.SourceNutzdatendatei, failed_folder.FullName); - } - static void CopyFileToDestination(DakotaSystemFile file) - { - var folder = GetDakotaFolderDatenannahmestelle(file.Datenannahmestelle); + if (!dat2files.ContainsKey(datenannahmestelle)) + dat2files.Add(datenannahmestelle, new List()); - CopyFileTo(file.SourceAuftragsdatei, folder.FullName, file.TransfernameAuf); - CopyFileTo(file.SourceNutzdatendatei, folder.FullName, file.Transfername); - } - static void CopyFileTo(FileSystemInfo file, string destination_folder, string file_name = null) - { - if (file_name is null) - file_name = file.Name; + ten2dat2files[tenant][datenannahmestelle].Add(file); + } - CopyFile(file.FullName, Path.Combine(destination_folder, file_name)); - } - static void CopyFile(string source, string destination) - { - Print($"Kopiere \"{source}\" nach \"{destination}\". "); + if (ten2dat2files.Any()) + return ten2dat2files; - File.Copy(source, destination); + PrintLine("Keine Dakota Dateien in Queue gefunden."); + return null; + } - PrintLine("Ok."); - } + static void HandleQueueFiles() + { + PrintLine("Scanne Dakota Dateien"); - static void DeleteQueueFile(DakotaSystemFile file) - { - DeleteFile(file.SourceAuftragsdatei.FullName); - DeleteFile(file.SourceNutzdatendatei.FullName); - } - static void DeleteDakotaFile(DakotaSystemFile file) - { - var folder = GetDakotaFolderDatenannahmestelle(file.Datenannahmestelle).FullName; + var ten2dat2files = ScanQueueFolder(); - DeleteFile(Path.Combine(folder, file.TransfernameAuf)); - DeleteFile(Path.Combine(folder, file.Transfername)); - } - static void DeleteFile(string file) - { - Print($"Lösche {file}. "); + if (ten2dat2files is null) + return; - File.Delete(file); + handleRequests = new Dictionary>(); - PrintLine("Ok."); - } + PrintLine(); + foreach (var kv in ten2dat2files) + { + var ten = kv.Key; + var dat2files = kv.Value; - static int ExecuteDakota(string arg) - { - var fileinfo = GetDakotaExe(); + foreach (var kv2 in dat2files) + { + var dat = kv2.Key; + var files = kv2.Value; - PrintLine($"{fileinfo.Name} {arg} wird ausgeführt"); + PrintLine($"Bearbeite Datenannahmestelle {dat} für Tenant {ten}."); - var process = Process.Start(GetDakotaExe().FullName, arg); + HandleQueueFiles(ten, dat, files); + } + } + } - var success = process.WaitForExit(GetProcessWaitForExitMs()); + static void HandleQueueFiles(string tenant, string datenstelle, List files) + { + List successful = new List(); + DakotaSystemFile error = null; + List followUpError = new List(); - if (success) - { - var exitcode = process.ExitCode; + foreach (var file in files) + { + if (error is object) + { + PrintLine($"Folgefehler: {file.SourceNutzdatendatei.Name}"); - PrintLine($"Returncode {exitcode}"); + followUpError.Add(file); + continue; + } - return exitcode; - } - else - { - throw new Exception("Timeout"); - } - } + var msg = HandleQueueFile(file, out bool success); - static bool IsDakotaFolderDatenannahmestelleValid(string datenannahmestelle) - { - try - { - _ = GetDakotaFolderDatenannahmestelle(datenannahmestelle); + if (success) + { + successful.Add(file); - return true; - } - catch (Exception e) - { - return false; - } - } - static DirectoryInfo GetDakotaFolderDatenannahmestelle(string datenannahmestelle) - { - var folder = new DirectoryInfo(Path.Combine(GetDakotaFolder().FullName, "TP5Daten", datenannahmestelle)); + PrintLine(msg); + } + else + { + error = file; - if (!folder.Exists) - folder = new DirectoryInfo(Path.Combine(GetDakotaFolder().FullName, "TP5Daten", datenannahmestelle.Substring(0, datenannahmestelle.Length - 1))); + PrintLine("Fehler gefunden. " + msg); - if (!folder.Exists) - throw new Exception($"Datenannahmestelle {datenannahmestelle} konnte nicht gefunden werden."); + CopyFileToFailed(file); + } - return folder; - } - static DirectoryInfo GetResultFolderTenant(string tenant) - { - var dirinfo = new DirectoryInfo(Path.Combine(GetResultFolder().FullName, tenant)); + DeleteQueueFile(file); + } - if (!dirinfo.Exists) - dirinfo.Create(); + if (successful is object && !successful.Any()) + successful = null; - return dirinfo; - } + if (followUpError is object && !followUpError.Any()) + followUpError = null; - static string GetLogPath() - => ConfigurationManager.AppSettings.Get("LogPath") ?? @"C:\GkvAbrechnung\Sender\log.txt"; - static int GetProcessWaitForExitMs() - => int.Parse(ConfigurationManager.AppSettings.Get("ProcessWaitForExitMs") ?? "10000"); - static FileInfo GetDakotaExe() - => new FileInfo(ConfigurationManager.AppSettings.Get("DakotaExePath") ?? @"C:\Program Files (x86)\ITSG\dakotale\dakota30.exe"); - static DirectoryInfo GetDakotaFolder() - => new DirectoryInfo(ConfigurationManager.AppSettings.Get("DakotaFolder") ?? @"C:\dakotale\"); - static DirectoryInfo GetQueueFolder() - => new DirectoryInfo(ConfigurationManager.AppSettings.Get("GkvAbrechnungQueueFolderPath") ?? @"C:\GkvAbrechnung\Queue\"); - static DirectoryInfo GetResultFolder() - => new DirectoryInfo(ConfigurationManager.AppSettings.Get("GkvAbrechnungResultFolderPath") ?? @"C:\GkvAbrechnung\Results\"); - static DirectoryInfo GetFailedFolder() - => new DirectoryInfo(ConfigurationManager.AppSettings.Get("GkvAbrechnungFailedFolderPath") ?? @"C:\GkvAbrechnung\Failed\"); - } + var application_user_oids = GetApplicationUserOids(successful, error, followUpError); + + if (!handleRequests.ContainsKey(tenant)) + handleRequests.Add(tenant, new Dictionary()); + + var p_successful = successful?.Select(x => x.ProtokollOid).ToList(); + var p_error = error?.ApplicationUserOid; + var p_followup = followUpError?.Select(x => x.ProtokollOid).ToList(); + + handleRequests[tenant].Add(datenstelle, new GkvClientResultRequestDC() + { + Application_User_Oids = application_user_oids, + GkvSecretKey = Config.GkvSecretKey, + Tenant = tenant, + Protokoll_Success_Oid = p_successful, + Protokoll_Fehler_Oid = p_error, + Protokoll_Folgefehler_Oid = p_followup + }); + } + + /// + /// Bearbeitet eine File. Wenn dakota.exe während der Bearbeitung gestartet wird, wird das Dakota Verzeichnis gesäubert und die weitere Bearbeitung durch throw Exception unterbrochen. + /// + /// + /// + /// + static string HandleQueueFile(DakotaSystemFile file, out bool success) + { + success = false; + + PrintFileInfo(file); + + if (!Config.IsDatenannahmestelleValid(file.Datenannahmestelle)) + return $"Datenannahmestelle {file.Datenannahmestelle} unbekannt."; + + CopyFileToDestination(file); + + Print("Sende via Dakota. "); + + var rc = ExecuteDakota("-x"); + + Returncodes.EvaluateSendCode(rc, out is_dakota_running, out success, out string message); + + if (is_dakota_running) + { + DeleteDakotaFile(file); + + throw new Exception(); + } + + return message; + } + + static List GetApplicationUserOids(List successful, DakotaSystemFile error, List followUpError) + { + var res = new List(); + + if (successful is object) + successful.ForEach(x => res.Add(x.ApplicationUserOid)); + + if (error is object ) + res.Add(error.ApplicationUserOid); + + if (followUpError is object) + followUpError.ForEach(x => res.Add(x.ApplicationUserOid)); + + return res; + } + + static void CopyFileToFailed(DakotaSystemFile file) + { + var failed_folder = Config.FailedFolder; + + CopyFileTo(file.SourceAuftragsdatei, failed_folder.FullName); + CopyFileTo(file.SourceNutzdatendatei, failed_folder.FullName); + } + static void CopyFileToDestination(DakotaSystemFile file) + { + var folder = Config.LoadDatenannahmestelleFolder(file.Datenannahmestelle); + + CopyFileTo(file.SourceAuftragsdatei, folder.FullName, file.TransfernameAuf); + CopyFileTo(file.SourceNutzdatendatei, folder.FullName, file.Transfername); + } + static void CopyFileTo(FileSystemInfo file, string destination_folder, string file_name = null) + { + if (file_name is null) + file_name = file.Name; + + CopyFile(file.FullName, Path.Combine(destination_folder, file_name)); + } + static void CopyFile(string source, string destination) + { + Print($"Kopiere \"{source}\" nach \"{destination}\". "); + + File.Copy(source, destination); + + PrintLine("Ok."); + } + + static void DeleteQueueFile(DakotaSystemFile file) + { + DeleteFile(file.SourceAuftragsdatei.FullName); + DeleteFile(file.SourceNutzdatendatei.FullName); + } + static void DeleteDakotaFile(DakotaSystemFile file) + { + var folder = Config.LoadDatenannahmestelleFolder(file.Datenannahmestelle).FullName; + + DeleteFile(Path.Combine(folder, file.TransfernameAuf)); + DeleteFile(Path.Combine(folder, file.Transfername)); + } + static void DeleteFile(string file) + { + Print($"Lösche {file}. "); + + File.Delete(file); + + PrintLine("Ok."); + } + + static int ExecuteDakota(string arg) + { + var fileinfo = Config.DakotaExe; + + PrintLine($"{fileinfo.Name} {arg} wird ausgeführt"); + + var process = Process.Start(Config.DakotaExe.FullName, arg); + + var success = process.WaitForExit(Config.ProcessWaitForExitMs); + + if (success) + { + return process.ExitCode; + } + else + { + throw new Exception($"dakota30.exe - Timeout exceeded ({Config.ProcessWaitForExitMs} ms). "); + } + } + + // static void CreateResultSuccessXmlFile(DakotaSystemFile file) + // => CreateResultXmlFile(file, "Dakota Erfolg", "", GkvTransferResultType.Success); + // static void CreateResultFehlerXmlFile(DakotaSystemFile file, string error) + // => CreateResultXmlFile(file, "Dakota Fehler", error, GkvTransferResultType.FailSoft); + // static void CreateResultXmlFile(DakotaSystemFile file, string title, string nachricht, GkvTransferResultType result_type) + //{ + // Print($"Speichere {title} als Xml. "); + + // var result = new ResultXml(); + + // result.Datum = DateTime.Now; + // result.Titel = title; + // result.Nachricht = nachricht; + // result.Level = (int)result_type; + // result.Oid = file.ProtokollOid; + + // var folder = Config.GetResultTenantFolder(file.Tenant).FullName; + // var path = Path.Combine(folder, $"P{file.ProtokollOid}.xml"); + + // Print($"Path: {path}. "); + + // XmlFileConverter.Save(result, path); + + // PrintLine("Ok."); + // } + } } diff --git a/DakotaSender/Returncodes.cs b/DakotaSender/Returncodes.cs new file mode 100644 index 000000000..3963c3a3c --- /dev/null +++ b/DakotaSender/Returncodes.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DakotaSender +{ + internal static class Returncodes + { + const int RC_DAKOTA_ALREADY_LOADED = 18; + + static readonly int[] AcceptStatusCodes = new int[] { 0 }; + static readonly int[] AcceptSendCodes = new int[] { 0 }; + + static readonly Dictionary StatusReturncodeToMeaning = new Dictionary() + { + {0, "dakota ist betriebsbereit. "}, + {6, "dakota konnte die Verbindung aufbauen. Stammdatenserver ist online und die Anfrage an den Stammdatenserver zu einem Fehler führt z.b \'die Lizenz ist ungültig!\' "}, + {10, "dakota ist registriert, aber noch nicht betriebsbereit. "}, + {30, "dakota ist nicht registriert. "}, + {40, "Die Verbindung zum Stammdatenserver war nicht möglich. "}, + {41, "Die Verbindung zum Stammdatenserver war wiederholt nicht möglich. "}, + {50, "Der Stammdatenserver wurde seit mehr als 10, Tagen nicht erreicht und daher wurde die Lizenz gesperrt. "}, + {100, "Es ist seit x-Tagen kein Stammdatenupdate durchgeführt worden. dakota wurde ohne Fehler beendet. "}, + {90, "Es liegt ein fertiges Zertifikat vor und es wurde erfolgreich ein Nachfolgezertifikat beantragt. "}, + {91, "Es liegt ein fertiges Zertifikat vor und es wurde erfolgreich ein Nachfolgezertifikat beantragt. Das aktive Zertifikat läuft in der angegebenen Frist ab. "}, + {101, "Es ist seit x-Tagen kein Stammdatenupdate durchgeführt worden und das Zertifikat läuft in der angegebenen Frist ab. dakota wurde ohne Fehler beendet. "}, + {200, "Es ist seit x-Tagen keine Schlüsselsicherung durchgeführt worden. dakota wurde ohne Fehler beendet. "}, + {201, "Es ist seit x-Tagen keine Schlüsselsicherung durchgeführt worden und das Zertifikat läuft in der angegebenen Frist ab. dakota wurde ohne Fehler beendet. "}, + {300, "Es ist seit x-Tagen kein Stammdatenupdate und keine Schlüsselsicherung durchgeführt worden. dakota wurde ohne Fehler beendet. "}, + {301, "Es ist seit x-Tagen kein Stammdatenupdate und keine Schlüsselsicherung durchgeführt worden und das Zertifikat läuft in der angegebenen Frist ab. dakota wurde ohne Fehler beende " }, + }; + + static readonly Dictionary SendReturncodeToMeaning = new Dictionary() + { + {0, "Alle Dateien wurden verarbeitet. " }, + {1, "Alle Dateien wurden verarbeitet und das Zertifikat läuft in der angegebenen Frist ab. "}, + {2, "Es sind keine Daten zur Verarbeitung vorhanden. "}, + {3, "Es sind keine Daten zur Verarbeitung vorhanden und das Zertifikat läuft in der angegebenen Frist ab. "}, + {4, "Eine oder mehrere Dateien konnten nicht verarbeitet werden. "}, + {5, "Eine oder mehrere Dateien konnten nicht verarbeitet werden und das Zertifikat läuft in der angegebenen Frist ab. "}, + }; + + static readonly Dictionary ExecuteModusReturnCodes2Meaning = new Dictionary() + { + {0, "Alle Dateien verarbeitet, bzw. Schlüssel erfolgreich eingelesen, bzw. alle Dateien erfolgreich entschlüsselt, ohne Fehler beendet. "}, + {1, "Alle Dateien verarbeitet, Zertifikat läuft in der angegebenen Frist ab, ohne Fehler beendet. "}, + {2, "Keine Daten zur Verarbeitung bzw. keine Daten zur Entschlüsselung vorhanden, ohne Fehler beendet. "}, + {3, "Keine Daten zur Verarbeitung vorhanden, ohne Fehler beendet, Zertifikat läuft in der angegebenen Frist ab. "}, + {4, "Eine oder mehrere Dateien konnten nicht verarbeitet bzw. entschlüsselt werden, siehe Protokoll, ohne Fehler beendet. "}, + {5, "Eine oder mehrere Dateien konnten nicht verarbeitet werden, Zertifikat läuft in der angegebenen Frist ab, ohne Fehler beendet. "}, + {6, "Aktion vom Anwender abgebrochen (Achtung: Im Kurzprotokoll-Modus normal). "}, + {7, "Aktion vom Anwender abgebrochen, Zertifikat läuft in der angegebenen Frist ab. "}, + {9, "Antrag am Trust Center gestellt, noch nicht schlüsselfertig (tritt nur bei Statusabfrage –s auf, alle anderen Parameter RC10). "}, + {10, "dakota noch nicht schlüsselfertig konfiguriert, Programmabbruch. "}, + {14, "Falscher Programmaufruf, Programmabbruch. "}, + {16, "Interner Fehler, Programmabbruch. "}, + {18, "Programm ist bereits geladen. "}, + {30, "Die Lizenz ist nicht registriert (ab dakota.ag 6.2). "}, + {40, "Verbindung zum Stammdatenupdateserver war nicht möglich (ab dakota.ag 6.2). "}, + {41, "Verbindung zum Stammdatenupdateserver war wiederholt nicht möglich (ab dakota.ag 6.2). "}, + {50, "Der Stammdatenserver wurde seit mehr als 10 Tagen nicht erreicht und daher wurde die Lizenz gesperrt (ab dakota.ag 6.1). "}, + {90, "Es liegt ein fertiges Zertifikat vor und es wurde erfolgreich ein Nachfolgezertifikat beantragt. "}, + {91, "Es liegt ein fertiges Zertifikat vor und es wurde erfolgreich ein Nachfolgezertifikat beantragt, aktives Zertifikat läuft in der angegebenen Frist ab. "}, + {100, "Es ist seit x-Tagen kein Stammdatenupdate durchgeführt worden, ohne Fehler beendet (nur bei Parameter –s). "}, + {101, "Es ist seit x-Tagen kein Stammdatenupdate durchgeführt worden und Ihr Zertifikat läuft in der angegebenen Frist ab, ohne Fehler beendet (nur bei Parameter –s). "}, + {200, "Es ist seit x-Tagen keine Schlüsselsicherung durchgeführt worden, ohne Fehler beendet (nur bei Parameter –s). "}, + }; + + /// + /// Werten den Return Code beim Statusabfrage aus. + /// + /// + /// + /// + /// + public static void EvaluateStatusCode(int rc, out bool isDakotaRunning, out bool accept, out string message) + { + isDakotaRunning = rc == RC_DAKOTA_ALREADY_LOADED; + accept = AcceptStatusCodes.Contains(rc); + + if (ExecuteModusReturnCodes2Meaning.TryGetValue(rc, out string msg)) + message = msg; + else if (StatusReturncodeToMeaning.TryGetValue(rc, out string msg2)) + message = "special: " + msg2; + else + message = "Unknown returncode"; + } + + /// + /// Werten den Return Code beim Senden aus. + /// + /// + /// + /// + /// + public static void EvaluateSendCode(int rc, out bool isDakotaRunning, out bool accept, out string message) + { + isDakotaRunning = rc == RC_DAKOTA_ALREADY_LOADED; + accept = AcceptSendCodes.Contains(rc); + + if (ExecuteModusReturnCodes2Meaning.TryGetValue(rc, out string msg)) + message = msg; + else if (SendReturncodeToMeaning.TryGetValue(rc, out string msg2)) + message = "special: " + msg2; + else + message = "Unknown returncode"; + } + } +} diff --git a/Host/GkvAbrechnungClient.aspx.cs b/Host/GkvAbrechnungClient.aspx.cs index c23994c0e..52869d35b 100644 --- a/Host/GkvAbrechnungClient.aspx.cs +++ b/Host/GkvAbrechnungClient.aspx.cs @@ -31,7 +31,7 @@ namespace Host { try { - //https://app8.bewoplaner.de/Host/GkvAbrechungServer?tenant=12345 + //https://app5.bewoplaner.de/Host/GkvAbrechungServer?tenant=12345 var str = new StreamReader(Request.InputStream).ReadToEnd(); @@ -68,7 +68,7 @@ namespace Host try { - var fehler_protokoll = DAOFactory.GenericDAO.GetByID(req.Protokoll_Fehler_Oid); + // var fehler_protokoll = DAOFactory.GenericDAO.GetByID(req.Protokoll_Fehler_Oid); response.Success = true; } @@ -85,7 +85,6 @@ namespace Host } #region Senden - private void SendInvalidInputResponse() => SendErrorResponse(INVALID_INPUT); private void SendErrorResponse(string message) { @@ -102,7 +101,6 @@ namespace Host Response.End(); } - #endregion } } \ No newline at end of file diff --git a/Host/GkvAbrechnungServer.aspx.cs b/Host/GkvAbrechnungServer.aspx.cs index a2fb7bd6c..6a95acb3b 100644 --- a/Host/GkvAbrechnungServer.aspx.cs +++ b/Host/GkvAbrechnungServer.aspx.cs @@ -21,6 +21,7 @@ namespace Host public partial class GkvAbrechnungServer : Page { public const int PROCESS_WAITFOREXIT_MS = 10 * 1000; + public const int WAIT_BEFORE_ERROR_MS = 5 * 1000; private readonly string LOGINSERVER_URL = "{0}/Login.aspx"; private readonly string INVALID_INPUT = "Ungültige Eingabe"; @@ -29,8 +30,6 @@ namespace Host private string QueueFolderPath { get; set; } = ConfigurationManager.AppSettings.Get("GkvAbrechnungQueueFolderPath"); private string KostentragerdateiFolderPath { get; set; } = ConfigurationManager.AppSettings.Get("GkvKostentragerdateiFolderPath"); - public GkvRequestDC GkvRequest { get; set; } - protected void Page_Load(object sender, EventArgs e) { try @@ -39,15 +38,15 @@ namespace Host var str = new StreamReader(Request.InputStream).ReadToEnd(); - GkvRequest = GkvSender.DeserializeRequest(str, SendInvalidInputResponse); + var req = GkvSender.DeserializeRequest(str, SendInvalidInputResponse); - if (!CheckValues(GkvRequest)) + if (!CheckValues(req)) SendErrorResponse("Check Fehlgeschlagen"); - if (!TryLogin(GkvRequest)) + if (!TryLogin(req)) SendErrorResponse("Login Fehlgeschlagen"); - switch (GkvRequest.Type) + switch (req.Type) { case RequestType.GkvServerSendNew: SendNew(GkvSender.DeserializeRequest(str, SendInvalidInputResponse)); @@ -58,7 +57,7 @@ namespace Host return; case RequestType.GkvServerGetStatus: - GetStatus(JsonConvert.DeserializeObject(str)); + GetStatus(GkvSender.DeserializeRequest(str, SendInvalidInputResponse)); return; default: @@ -139,40 +138,38 @@ namespace Host private void SendNew(GkvServerSendNewRequestDC req) { // Response - var response = new GkvServerSendNewResponseDC(); + var res = new GkvServerSendNewResponseDC(); - var protokoll = req.GkvTransferProtokoll; + res.GkvTransferProtokollDC = req.Protokoll; try { - var finalpath = SaveFileInFileSystem(req); + var finalpath = SaveFileInQueue(req); - req.GkvTransferProtokoll.SentApp8Success = true; + req.Protokoll.SentApp8Success = true; - response.Success = true; + res.Success = true; } catch (GkvException e) { - protokoll.ResultType = GkvTransferResultType.Soft; - protokoll.Fehlerdatum = DateTime.Now; - protokoll.Fehlertitel = "App8"; - protokoll.Fehlernachricht = e.Message; + req.Protokoll.ResultType = GkvTransferResultType.FailSoft; + req.Protokoll.Fehlerdatum = DateTime.Now; + req.Protokoll.Fehlertitel = "App8 - Gkv"; + req.Protokoll.Fehlernachricht = e.Message; - response.Message = e.Message; + res.Message = e.Message; } catch (Exception e) { - protokoll.ResultType = GkvTransferResultType.Soft; - protokoll.Fehlerdatum = DateTime.Now; - protokoll.Fehlertitel = "App8"; - protokoll.Fehlernachricht = e.Message; + req.Protokoll.ResultType = GkvTransferResultType.FailSoft; + req.Protokoll.Fehlerdatum = DateTime.Now; + req.Protokoll.Fehlertitel = "App8"; + req.Protokoll.Fehlernachricht = e.Message; - response.Message = e.Message; + res.Message = e.Message; } - response.GkvTransferProtokollDC = protokoll; - - SendResponse(response); + SendResponse(res); } private void GetIK(GkvServerGetIKRequestDC req) { @@ -206,7 +203,7 @@ namespace Host try { // Load XML Info - var results = GetResultFile(GkvRequest.Tenant); + var results = GetResultFile(req.Tenant); if (results is object) for (int i = 0; i < tuple_count; i++) @@ -219,7 +216,7 @@ namespace Host } } - ClearResultFolder(GkvRequest.Tenant, req.Oids); + ClearResultFolder(req.Tenant, req.Oids); response.Success = true; } @@ -237,25 +234,19 @@ namespace Host return; } - private string SaveFileInFileSystem(GkvServerSendNewRequestDC req) - => SaveFileInFileSystem(req.GkvTransferProtokoll.GkvTransferProtokollOid.Value, GkvRequest.Tenant, req.GkvTransferProtokoll.IKDatenannahmestelle, req.GkvTransferProtokoll.Transfername, - req.GkvTransferProtokoll.Nutzdatendatei, req.GkvTransferProtokoll.Auftragsdatei); - private string SaveFileInFileSystem(long protokoll_oid, string tenant, string datenannahmestelle, string transfername, string nutzdaten, string auftragsdatei) + private string SaveFileInQueue(GkvServerSendNewRequestDC req) { string root_path = QueueFolderPath; - string file_path = $@"{tenant}_{protokoll_oid}_{datenannahmestelle}_{transfername}"; + string file_path = string.Format("{0}_{1}_{2}_{3}_{4}", + req.Tenant, req.ApplicationUserOid, req.Protokoll_Oid, req.Datenannahmestelle, req.Transfername); Directory.CreateDirectory(root_path); var finalpath = root_path + file_path; - return SaveFileInFileSystem(finalpath, nutzdaten, auftragsdatei); - } - private string SaveFileInFileSystem(string finalpath, string nutzdaten, string auftragsdatei) - { - File.WriteAllText(finalpath, nutzdaten); + File.WriteAllText(finalpath, req.Nutzdatendatei); - var auftragsdatei2 = Encoding.GetEncoding("ISO-8859-1").GetBytes(auftragsdatei); + var auftragsdatei2 = Encoding.GetEncoding("ISO-8859-1").GetBytes(req.Auftragsdatei); File.WriteAllBytes(finalpath + ".auf", auftragsdatei2); @@ -320,14 +311,12 @@ namespace Host } } - private void Sleep() => Thread.Sleep(5000); - private void SendInvalidInputResponse() => SendErrorResponse(INVALID_INPUT); private void SendErrorResponse(string message) { var response = new GkvResponseDC(false, message); - Sleep(); + Thread.Sleep(WAIT_BEFORE_ERROR_MS); SendResponse(GkvSender.SerializeResponse(response)); } diff --git a/Service/ServiceImplementations/AccountingServiceImp.cs b/Service/ServiceImplementations/AccountingServiceImp.cs index 8cf61bfc5..3bd14b76a 100644 --- a/Service/ServiceImplementations/AccountingServiceImp.cs +++ b/Service/ServiceImplementations/AccountingServiceImp.cs @@ -911,10 +911,11 @@ namespace BeWo.Service.ServiceImplementations return response; } - var protokoll = new GkvTransferProtokoll(); - - protokoll.ErstelltAm = DateTime.Now; - protokoll.GkvAbrechnungOid = entity.Oid.Value; + var protokoll = new GkvTransferProtokoll + { + ErstelltAm = DateTime.Now, + GkvAbrechnungOid = entity.Oid.Value + }; try { @@ -938,14 +939,14 @@ namespace BeWo.Service.ServiceImplementations } catch (GkvException de) { - protokoll.ResultType = GkvTransferResultType.Soft; + protokoll.ResultType = GkvTransferResultType.FailSoft; protokoll.Fehlerdatum = DateTime.Now; protokoll.Fehlernachricht = de.Message; protokoll.Fehlertitel = de.Title ?? "Default"; } catch (Exception e) { - protokoll.ResultType = GkvTransferResultType.Fatal; + protokoll.ResultType = GkvTransferResultType.FailFatal; protokoll.Fehlerdatum = DateTime.Now; protokoll.Fehlernachricht = e.ToString(); protokoll.Fehlertitel = "Erstellung (kritisch)"; @@ -1120,7 +1121,7 @@ namespace BeWo.Service.ServiceImplementations var request_app8 = new GkvServerSendNewRequestDC { - GkvTransferProtokoll = gkv_transfer_dc + Protokoll = gkv_transfer_dc }; var response_app8 = SendApp8Request(request_app8); @@ -1207,6 +1208,11 @@ namespace BeWo.Service.ServiceImplementations 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(request, request.Tenant); } diff --git a/Shared/AppSender/GkvSender.cs b/Shared/AppSender/GkvSender.cs index f8da5d9bd..66c605fb6 100644 --- a/Shared/AppSender/GkvSender.cs +++ b/Shared/AppSender/GkvSender.cs @@ -59,7 +59,7 @@ namespace BS.Shared.AppSender return app8_response; } - public static Res SendKundenAppClientRequest(Req request, string tenant) where Req : GkvRequestDC where Res : GkvResponseDC + public static Res SendKundenAppClientRequest(Req request, string tenant) where Req : AppRequestDC where Res : AppResponseDC { string server = AppRequestSender.GetServerFromTenant(tenant); diff --git a/Shared/BeWoEntityEnums.cs b/Shared/BeWoEntityEnums.cs index 8ee3e283f..17c1ff76c 100644 --- a/Shared/BeWoEntityEnums.cs +++ b/Shared/BeWoEntityEnums.cs @@ -1272,9 +1272,9 @@ namespace BS.Shared public enum GkvTransferResultType { Success = 0, // Kein Fehler - Soft = 1, // Kann erneut senden - Fatal = 2, // Kann nicht erneut senden - Folgefehler = 3, // Muss neu berechnet werden + FailSoft = 1, // Kann erneut senden + FailFatal = 2, // Kann nicht erneut senden + FailFollowUp = 3, // Muss neu berechnet werden } public enum GkvState diff --git a/Shared/DataContracts/AppRequestDC.cs b/Shared/DataContracts/AppRequestDC.cs index 823e84c31..2b3508d1e 100644 --- a/Shared/DataContracts/AppRequestDC.cs +++ b/Shared/DataContracts/AppRequestDC.cs @@ -24,6 +24,6 @@ namespace BS.Shared.DataContracts } [DataMember] public string Tenant { get; set; } - [DataMember] public RequestType Type { get; set; } + [DataMember] public RequestType Type { get; private set; } } } diff --git a/Shared/DataContracts/GkvAbrechnung/GkvClientResultRequestDC.cs b/Shared/DataContracts/GkvAbrechnung/GkvClientResultRequestDC.cs index af6a16feb..3374103ac 100644 --- a/Shared/DataContracts/GkvAbrechnung/GkvClientResultRequestDC.cs +++ b/Shared/DataContracts/GkvAbrechnung/GkvClientResultRequestDC.cs @@ -7,13 +7,17 @@ using System.Threading.Tasks; namespace BS.Shared.DataContracts.GkvAbrechnung { - public class GkvClientResultRequestDC : GkvRequestDC + public class GkvClientResultRequestDC : AppRequestDC { public GkvClientResultRequestDC() : base(RequestType.GkvClientResult) { } [DataMember] public string GkvSecretKey { get; set; } - [DataMember] public long Protokoll_Fehler_Oid { get; set; } + + [DataMember] public IList Application_User_Oids { get; set; } + + [DataMember] public IList Protokoll_Success_Oid { get; set; } + [DataMember] public long? Protokoll_Fehler_Oid { get; set; } [DataMember] public IList Protokoll_Folgefehler_Oid { get; set; } } } diff --git a/Shared/DataContracts/GkvAbrechnung/GkvServerSendNewRequestDC.cs b/Shared/DataContracts/GkvAbrechnung/GkvServerSendNewRequestDC.cs index e254db972..d76e88bde 100644 --- a/Shared/DataContracts/GkvAbrechnung/GkvServerSendNewRequestDC.cs +++ b/Shared/DataContracts/GkvAbrechnung/GkvServerSendNewRequestDC.cs @@ -15,6 +15,13 @@ namespace BS.Shared.DataContracts.GkvAbrechnung public GkvServerSendNewRequestDC(string tenant, string username, string password) : base(RequestType.GkvServerSendNew, tenant, username, password) { } - [DataMember] public GkvTransferProtokollDC GkvTransferProtokoll { get; set; } + [DataMember] public long ApplicationUserOid { get; set; } + [DataMember] public GkvTransferProtokollDC Protokoll { get; set; } + + public long Protokoll_Oid => Protokoll.GkvTransferProtokollOid.Value; + public string Datenannahmestelle => Protokoll.IKDatenannahmestelle; + public string Transfername => Protokoll.Transfername; + public string Nutzdatendatei => Protokoll.Nutzdatendatei; + public string Auftragsdatei => Protokoll.Auftragsdatei; } } diff --git a/Shared/Extensions/GkvAbrechnungExtensions.cs b/Shared/Extensions/GkvAbrechnungExtensions.cs index a03c5032f..4b094a7c6 100644 --- a/Shared/Extensions/GkvAbrechnungExtensions.cs +++ b/Shared/Extensions/GkvAbrechnungExtensions.cs @@ -18,10 +18,10 @@ namespace BS.Shared.Extensions if (gkvAbrechnung.LastTransferProtokoll is null) return GkvState.NoSend; - if (gkvAbrechnung.LastTransferProtokoll.ResultType == GkvTransferResultType.Soft) + if (gkvAbrechnung.LastTransferProtokoll.ResultType == GkvTransferResultType.FailSoft) return GkvState.Error; - if (gkvAbrechnung.LastTransferProtokoll.ResultType == GkvTransferResultType.Fatal) + if (gkvAbrechnung.LastTransferProtokoll.ResultType == GkvTransferResultType.FailFatal) return GkvState.ErrorFatal; if (gkvAbrechnung.LastTransferProtokoll.ResultType is null)