diff --git a/DakotaSender/App.config b/DakotaSender/App.config index 5d6f70fc4..ed14047d0 100644 --- a/DakotaSender/App.config +++ b/DakotaSender/App.config @@ -6,6 +6,7 @@ + diff --git a/DakotaSender/DakotaSender.csproj b/DakotaSender/DakotaSender.csproj index 768167ec3..829fcd19d 100644 --- a/DakotaSender/DakotaSender.csproj +++ b/DakotaSender/DakotaSender.csproj @@ -45,8 +45,10 @@ + + diff --git a/DakotaSender/DakotaSystemFile.cs b/DakotaSender/DakotaSystemFile.cs index ce82a33f5..2d0621553 100644 --- a/DakotaSender/DakotaSystemFile.cs +++ b/DakotaSender/DakotaSystemFile.cs @@ -12,12 +12,10 @@ namespace DakotaSender public string Tenant { get; set; } public long ProtokollOid { get; set; } public string Datenannahmestelle { get; set; } - public string Transfernummer { get; set; } + public string Transfername { get; set; } + public string TransfernameAuf => Transfername + ".auf"; public FileInfo SourceAuftragsdatei { get; set; } public FileInfo SourceNutzdatendatei { get; set; } - - public FileInfo DestinationAuftragsdatei { get; set; } - public FileInfo DestinationNutzdatendatei { get; set; } } } diff --git a/DakotaSender/FehlerXml.cs b/DakotaSender/FehlerXml.cs new file mode 100644 index 000000000..11a5b0699 --- /dev/null +++ b/DakotaSender/FehlerXml.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +using System.Xml.Serialization; + +namespace DakotaSender +{ + [Serializable()] + [XmlRoot("Fehler")] + public class FehlerXml + { + [XmlAttribute("Oid")] + public long Oid { get; set; } + + [XmlElement("Titel")] + public string Titel { get; set; } + + [XmlElement("Datum")] + public DateTime? Datum { get; set; } + + [XmlElement("Nachricht")] + public string Nachricht { get; set; } + + [XmlElement("Level")] + public int Level { get; set; } + } +} diff --git a/DakotaSender/Program.cs b/DakotaSender/Program.cs index 27e48fb20..f362a86ca 100644 --- a/DakotaSender/Program.cs +++ b/DakotaSender/Program.cs @@ -12,6 +12,8 @@ namespace DakotaSender { class Program { + const int RC_DAKOTA_ALREADY_LOADED = 18; + static readonly string TEST_TENANT = "7375324044"; static int[] AcceptStatusCodes = new int[] { 0 }; @@ -46,7 +48,7 @@ namespace DakotaSender static void PrintTitle() { - PrintLine(); + PrintWithTime("\n", false); PrintLine("-------------------"); PrintLine("Dakota Sender Modul"); PrintLine("-------------------"); @@ -114,31 +116,9 @@ namespace DakotaSender foreach (var file in files) { - var protokoll_oid = file.ProtokollOid; + TryProcessFile(file); - PrintLine($"Verarbeite Datei: {file.SourceNutzdatendatei.Name}"); - PrintLine($"- Tenant: {file.Tenant}"); - PrintLine($"- Protokoll Oid: {protokoll_oid}"); - PrintLine($"- Datenannahmestelle: {file.Datenannahmestelle}"); - - CopyFile(file); - - Print("Sende via Dakota. "); - - var code = ExecuteDakota("-x"); - - if (AcceptSendCodes.Contains(code)) - { - PrintLine($"Ok."); - - DeleteSourceFile(file); - } - else - { - PrintLine($"Verarbeitung fehlgeschlagen. Statuscode {code} wird nicht akzeptiert."); - - DeleteDestinationFile(file); - } + CheckDakotaStatus(); } } @@ -166,7 +146,7 @@ namespace DakotaSender var tenant = split[0]; var p_oid = long.Parse(split[1]); var datenannahmestelle = split[2]; - var transfernummer = split[3]; + var transfername = split[3]; if (tenant != TEST_TENANT && tenant != "demo") { @@ -178,11 +158,6 @@ namespace DakotaSender tenant = TEST_TENANT; } - var destination = GetDakotaFolderDatenannahmestelle(datenannahmestelle).FullName; - var dest_file = Path.Combine(destination, transfernummer); - var dest_auft = new FileInfo(dest_file + ".auf"); - var dest_nutz = new FileInfo(dest_file); - var file = new DakotaSystemFile() { SourceAuftragsdatei = auft, @@ -190,9 +165,7 @@ namespace DakotaSender Tenant = tenant, ProtokollOid = p_oid, Datenannahmestelle = datenannahmestelle, - Transfernummer = transfernummer, - DestinationAuftragsdatei = dest_auft, - DestinationNutzdatendatei = dest_nutz + Transfername = transfername, }; if (!toCheck.ContainsKey(tenant)) @@ -203,39 +176,142 @@ namespace DakotaSender return toCheck.Any() ? toCheck : null; } - - static void CopyFile(DakotaSystemFile file) + static void TryProcessFile(DakotaSystemFile file) { - var sour_auftrags = file.SourceAuftragsdatei.FullName; - var dest_auftrags = file.DestinationAuftragsdatei.FullName; - var sour_nutz = file.SourceNutzdatendatei.FullName; - var dest_nutz = file.DestinationNutzdatendatei.FullName; + bool copied = false; + try + { + var protokoll_oid = file.ProtokollOid; - Print($"Kopiere \"{sour_auftrags}\" nach \"{dest_auftrags}\". "); + PrintLine($"Verarbeite Datei: {file.SourceNutzdatendatei.Name}"); + PrintLine($"- Tenant: {file.Tenant}"); + PrintLine($"- Protokoll Oid: {protokoll_oid}"); + PrintLine($"- Datenannahmestelle: {file.Datenannahmestelle}"); - File.Copy(sour_auftrags, dest_auftrags); + copied = true; + CopyFileToDestination(file); - PrintLine("Ok."); + Print("Sende via Dakota. "); - Print($"Kopiere \"{sour_nutz}\" nach \"{dest_nutz}\". "); + var code = ExecuteDakota("-x"); - File.Copy(sour_nutz, dest_nutz); + if (AcceptSendCodes.Contains(code)) + { + PrintLine($"Ok."); + + DeleteQueueFile(file); + } + else + { + 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); + } + else + { + var error = $"Verarbeitung fehlgeschlagen. Statuscode {code} wird nicht akzeptiert."; + + PrintLine(error); + + MoveQueueToFailed(file); + + DeleteDakotaFile(file); + + CreateResultXmlFile(file, error); + } + } + } + catch (Exception e) + { + PrintLine($"Verarbeitung fehlgeschlagen. Exception: {e}"); + + if (copied) + DeleteDakotaFile(file); + } + } + + static void CreateResultXmlFile(DakotaSystemFile file, string error) + { + Print("Speichere Fehler als Xml. "); + + var fehler = new FehlerXml(); + + fehler.Datum = DateTime.Now; + fehler.Titel = "Dakota Fehler"; + fehler.Nachricht = error; + fehler.Level = 1; + fehler.Oid = file.ProtokollOid; + + var folder = GetResultFolderTenant(file.Tenant).FullName; + var path = Path.Combine(folder, $"P{file.ProtokollOid}.xml"); + + Print($"Path: {path}"); + + XmlFileConverter.Save(fehler, path); PrintLine("Ok."); } - static void DeleteSourceFile(DakotaSystemFile file) + + static void MoveQueueToFailed(DakotaSystemFile file) { - PrintLine($"Lösche {file.SourceAuftragsdatei.FullName}."); - File.Delete(file.SourceAuftragsdatei.FullName); - PrintLine($"Lösche {file.SourceNutzdatendatei.FullName}."); - File.Delete(file.SourceNutzdatendatei.FullName); + CopyFileToFailed(file); + + DeleteQueueFile(file); } - static void DeleteDestinationFile(DakotaSystemFile file) + + static void CopyFileToFailed(DakotaSystemFile file) { - PrintLine($"Lösche {file.DestinationAuftragsdatei.FullName}."); - File.Delete(file.DestinationAuftragsdatei.FullName); - PrintLine($"Lösche {file.DestinationNutzdatendatei.FullName}."); - File.Delete(file.DestinationNutzdatendatei.FullName); + var failed_folder = GetFailedFolder(); + + CopyFileTo(file.SourceAuftragsdatei, failed_folder.FullName); + CopyFileTo(file.SourceNutzdatendatei, failed_folder.FullName); + } + static void CopyFileToDestination(DakotaSystemFile file) + { + var folder = GetDakotaFolderDatenannahmestelle(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 = GetDakotaFolderDatenannahmestelle(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) @@ -274,7 +350,16 @@ namespace DakotaSender return folder; } + static DirectoryInfo GetResultFolderTenant(string tenant) + { + var dirinfo = new DirectoryInfo(Path.Combine(GetResultFolder().FullName, tenant)); + if (!dirinfo.Exists) + dirinfo.Create(); + + return dirinfo; + } + static string GetLogPath() => ConfigurationManager.AppSettings.Get("LogPath") ?? @"C:\GkvAbrechnung\Sender\log.txt"; static int GetProcessWaitForExitMs() @@ -287,5 +372,7 @@ namespace DakotaSender => 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\"); } } diff --git a/DakotaSender/XmlFileConverter.cs b/DakotaSender/XmlFileConverter.cs new file mode 100644 index 000000000..a55ea026b --- /dev/null +++ b/DakotaSender/XmlFileConverter.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; + +namespace DakotaSender +{ + public static class XmlFileConverter + { + /// + /// Saves to an xml file + /// + /// File path of the new xml file + public static void Save(T obj, string FileName) where T : class + { + using (var writer = new System.IO.StreamWriter(FileName)) + { + var serializer = new XmlSerializer(obj.GetType()); + serializer.Serialize(writer, obj); + writer.Flush(); + } + } + + /// + /// Load an object from an xml file + /// + /// Xml file name + /// The object created from the xml file + public static T Load(string FileName) where T : class + { + using (var stream = System.IO.File.OpenRead(FileName)) + { + var serializer = new XmlSerializer(typeof(T)); + return serializer.Deserialize(stream) as T; + } + } + } +}