461 lines
10 KiB
C#
461 lines
10 KiB
C#
using BS.Shared;
|
|
using BS.Shared.AppSender;
|
|
using BS.Shared.Core;
|
|
using BS.Shared.DataContracts;
|
|
using BS.Shared.DataContracts.GkvAbrechnung;
|
|
using BS.Shared.Exceptions;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Configuration;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace DakotaSender
|
|
{
|
|
class Program
|
|
{
|
|
static readonly string TEST_TENANT = "5000000000";
|
|
static readonly string TEST_TENANT_2 = "7375324044";
|
|
|
|
static bool time_in_line = false;
|
|
static bool is_dakota_running = false;
|
|
|
|
static Dictionary<string, Dictionary<long, GkvClientResultRequestDC>> ten2user2req;
|
|
|
|
static void Main(string[] args)
|
|
{
|
|
FileStream filestream = new FileStream(Config.LogPath, FileMode.Append);
|
|
var streamwriter = new StreamWriter(filestream);
|
|
streamwriter.AutoFlush = true;
|
|
|
|
Console.SetOut(streamwriter);
|
|
Console.SetError(streamwriter);
|
|
|
|
try
|
|
{
|
|
PrintTitle();
|
|
|
|
HandleQueueFiles();
|
|
|
|
HandleResults();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
HandleException(e, null);
|
|
|
|
if (is_dakota_running)
|
|
{
|
|
PrintSeperator();
|
|
PrintLine($"Verarbeitung im Silent Modus fehlgeschlagen. dakota30.exe läuft (bereits).");
|
|
PrintLine("Ignoriere Verarbeitung aktuell. Versuche im nächsten Programm Aufruf erneut.");
|
|
}
|
|
|
|
PrintSeperator();
|
|
}
|
|
|
|
PrintEnd();
|
|
}
|
|
|
|
internal static void PrintTitle()
|
|
{
|
|
PrintLine();
|
|
PrintSeperator();
|
|
PrintLine("Dakota Sender Modul");
|
|
PrintSeperator();
|
|
}
|
|
internal static void PrintSeperator() => PrintLine("-------------------");
|
|
internal static void PrintEnd()
|
|
{
|
|
PrintLine("Ende");
|
|
PrintSeperator();
|
|
}
|
|
internal static void PrintLine() => PrintWithTime("\n", false);
|
|
internal static void PrintLine(string line)
|
|
{
|
|
PrintWithTime(line + "\n", !time_in_line);
|
|
|
|
time_in_line = false;
|
|
}
|
|
internal static void Print(string line)
|
|
{
|
|
PrintWithTime(line, !time_in_line);
|
|
|
|
time_in_line = true;
|
|
}
|
|
internal 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);
|
|
}
|
|
internal static void PrintFileInfo(DakotaSystemFile file)
|
|
{
|
|
Print($"Verarbeite Datei: {file.SourceNutzdatendatei.Name}");
|
|
PrintLine($"(T:{file.Tenant}, U:{file.ApplicationUserOid}, P:{file.ProtokollOid}, D:{file.Datenannahmestelle})");
|
|
}
|
|
internal static void HandleException(Exception e, string tenant)
|
|
{
|
|
MailUtils.SendGkvModuleErrorMail("GkvSender Exception", e, tenant);
|
|
|
|
PrintLine(e.ToString());
|
|
}
|
|
|
|
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
|
|
{
|
|
throw new Exception($"Statuscode {code} wird nicht akzeptiert. {message}");
|
|
}
|
|
|
|
PrintSeperator();
|
|
}
|
|
|
|
static Dictionary<string, Dictionary<string, List<DakotaSystemFile>>> ScanQueueFolder()
|
|
{
|
|
var queue = Config.QueueFolder;
|
|
|
|
var files = queue.GetFiles("*.auf", SearchOption.TopDirectoryOnly)
|
|
.OrderBy(x => x.FullName);
|
|
|
|
var ten2dat2files = new Dictionary<string, Dictionary<string, List<DakotaSystemFile>>>();
|
|
foreach (var auft in files)
|
|
{
|
|
var file = ScanQueueFile(auft);
|
|
|
|
if (file is null)
|
|
continue;
|
|
|
|
var tenant = file.Tenant;
|
|
var datenannahmestelle = file.Datenannahmestelle;
|
|
|
|
if (!ten2dat2files.ContainsKey(tenant))
|
|
ten2dat2files.Add(tenant, new Dictionary<string, List<DakotaSystemFile>>());
|
|
|
|
var dat2files = ten2dat2files[tenant];
|
|
|
|
if (!dat2files.ContainsKey(datenannahmestelle))
|
|
dat2files.Add(datenannahmestelle, new List<DakotaSystemFile>());
|
|
|
|
ten2dat2files[tenant][datenannahmestelle].Add(file);
|
|
}
|
|
|
|
if (ten2dat2files.Any())
|
|
return ten2dat2files;
|
|
|
|
PrintLine("Keine gültigen Dakota Dateien in Queue gefunden.");
|
|
return null;
|
|
}
|
|
static DakotaSystemFile ScanQueueFile(FileInfo auft)
|
|
{
|
|
string tenant = null;
|
|
|
|
try
|
|
{
|
|
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");
|
|
return null;
|
|
}
|
|
|
|
PrintLine($"- {auft.FullName}");
|
|
|
|
var split = nutz.Name.Split('_');
|
|
tenant = split[0];
|
|
var app_oid = long.Parse(split[1]);
|
|
var p_oid = long.Parse(split[2]);
|
|
var datenannahmestelle = split[3];
|
|
var transfername = split[4];
|
|
|
|
// Muss nachher nur entfernt werden, um andere zu testen
|
|
// Ggf Tool einbauen?
|
|
if (tenant != TEST_TENANT && tenant != TEST_TENANT_2)
|
|
{
|
|
PrintLine($"{auft.FullName} wird ignoriert. Tenant {tenant} nicht gültig.");
|
|
return null;
|
|
}
|
|
|
|
var file = new DakotaSystemFile()
|
|
{
|
|
SourceAuftragsdatei = auft,
|
|
SourceNutzdatendatei = nutz,
|
|
Tenant = tenant,
|
|
ProtokollOid = p_oid,
|
|
ApplicationUserOid = app_oid,
|
|
Datenannahmestelle = datenannahmestelle,
|
|
Transfername = transfername,
|
|
};
|
|
|
|
return file;
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
HandleException(e, tenant);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static void HandleQueueFiles()
|
|
{
|
|
PrintLine("Scanne Dakota Dateien:");
|
|
|
|
var ten2dat2files = ScanQueueFolder();
|
|
|
|
PrintSeperator();
|
|
|
|
if (ten2dat2files is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CheckDakotaStatus();
|
|
|
|
ten2user2req = new Dictionary<string, Dictionary<long, GkvClientResultRequestDC>>();
|
|
|
|
PrintLine("Bearbeite Queue");
|
|
PrintSeperator();
|
|
|
|
foreach (var kv in ten2dat2files)
|
|
{
|
|
var ten = kv.Key;
|
|
var dat2files = kv.Value;
|
|
|
|
foreach (var kv2 in dat2files)
|
|
{
|
|
var dat = kv2.Key;
|
|
var files = kv2.Value;
|
|
|
|
PrintLine($"Bearbeite Datenannahmestelle \'{dat}\' für Tenant \'{ten}\':");
|
|
|
|
HandleQueueFiles(files);
|
|
|
|
PrintSeperator();
|
|
|
|
CheckDakotaStatus();
|
|
}
|
|
}
|
|
|
|
PrintLine("Bearbeitung Queue beendet");
|
|
PrintSeperator();
|
|
}
|
|
static void HandleQueueFiles(List<DakotaSystemFile> files)
|
|
{
|
|
bool error = false;
|
|
|
|
foreach (var file in files)
|
|
{
|
|
if (!error)
|
|
{
|
|
var msg = HandleQueueFile(file, out bool success);
|
|
|
|
if (success)
|
|
{
|
|
PrintLine(msg);
|
|
|
|
Add2Results(file, GkvTransferResultType.Success);
|
|
|
|
FileController.CopyFileToCopy(file);
|
|
|
|
FileController.CopyFileToSuccesss(file);
|
|
}
|
|
else
|
|
{
|
|
error = true;
|
|
|
|
PrintLine("Fehler gefunden. " + msg);
|
|
|
|
Add2Results(file, GkvTransferResultType.FailSoft, msg, "DS:Fehler");
|
|
|
|
FileController.CopyFileToCopy(file);
|
|
|
|
FileController.CopyFileToFailed(file);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PrintLine($"Folgefehler: {file.SourceNutzdatendatei.Name}");
|
|
|
|
Add2Results(file, GkvTransferResultType.FailFollowUp, "Wird neu erstellt und übertragen.", "DS:Folgefehler");
|
|
}
|
|
|
|
FileController.DeleteQueueFile(file);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="file"></param>
|
|
/// <param name="success"></param>
|
|
/// <returns></returns>
|
|
static string HandleQueueFile(DakotaSystemFile file, out bool success)
|
|
{
|
|
success = false;
|
|
|
|
PrintFileInfo(file);
|
|
|
|
if (!Config.IsDatenannahmestelleValid(file.Datenannahmestelle))
|
|
return $"Datenannahmestelle {file.Datenannahmestelle} unbekannt.";
|
|
|
|
FileController.CopyFileToDestination(file);
|
|
|
|
Print("Sende via Dakota. ");
|
|
|
|
var rc = ExecuteDakota("-x");
|
|
|
|
Returncodes.EvaluateSendCode(rc, out is_dakota_running, out success, out string message);
|
|
|
|
if (!success)
|
|
{
|
|
FileController.DeleteDakotaFile(file);
|
|
}
|
|
|
|
if (is_dakota_running)
|
|
{
|
|
throw new Exception();
|
|
}
|
|
|
|
return message;
|
|
}
|
|
static void Add2Results(DakotaSystemFile file, GkvTransferResultType type, string nachricht = null, string title = null)
|
|
{
|
|
var tenant = file.Tenant;
|
|
var user = file.ApplicationUserOid;
|
|
|
|
if (!ten2user2req.ContainsKey(tenant))
|
|
ten2user2req.Add(tenant, new Dictionary<long, GkvClientResultRequestDC>());
|
|
|
|
var user2req = ten2user2req[tenant];
|
|
|
|
if (!user2req.ContainsKey(user))
|
|
user2req.Add(user, new GkvClientResultRequestDC()
|
|
{
|
|
UserOid = file.ApplicationUserOid,
|
|
Tenant = file.Tenant,
|
|
GkvSecretKey = Config.GkvSecretKey
|
|
});
|
|
|
|
var req = user2req[user];
|
|
|
|
if (req.ResultDCs is null)
|
|
req.ResultDCs = new List<GkvServerResultDC>();
|
|
|
|
var item = new GkvServerResultDC();
|
|
|
|
item.Datum = DateTime.Now;
|
|
item.Nachricht = nachricht;
|
|
item.ProtokollOid = file.ProtokollOid;
|
|
item.ResultType = type;
|
|
item.Titel = title;
|
|
|
|
req.ResultDCs.Add(item);
|
|
}
|
|
|
|
static void HandleResults()
|
|
{
|
|
PrintLine("Sende Ergebnisse:");
|
|
PrintSeperator();
|
|
|
|
if (ten2user2req is null || !ten2user2req.Any())
|
|
return;
|
|
|
|
var task = HandleResultsAsync();
|
|
|
|
task.Wait();
|
|
|
|
if (task.IsFaulted)
|
|
throw task.Exception;
|
|
}
|
|
static async Task HandleResultsAsync()
|
|
{
|
|
var tasks = new List<Task>();
|
|
foreach (var tenant in ten2user2req.Keys)
|
|
{
|
|
foreach (var user in ten2user2req[tenant].Keys)
|
|
{
|
|
var req = ten2user2req[tenant][user];
|
|
|
|
var task = HandleResult(req, tenant, user);
|
|
|
|
tasks.Add(task);
|
|
}
|
|
}
|
|
|
|
await Task.WhenAll(tasks);
|
|
}
|
|
static async Task HandleResult(GkvClientResultRequestDC req, string tenant, long user)
|
|
{
|
|
var res = new GkvResponseDC(false, "empty");
|
|
|
|
try
|
|
{
|
|
PrintLine($"Sende Ergebnis an: Tenant: {req.Tenant}, User; {req.UserOid}");
|
|
|
|
res = await GkvSender.SendKundenAppClientRequestAsync<GkvClientResultRequestDC, GkvResponseDC>(req, tenant, user);
|
|
|
|
if (res.Success)
|
|
PrintLine("Erfolgreich!");
|
|
else
|
|
PrintLine("Fehler: " + res.Message);
|
|
}
|
|
catch (GkvException e)
|
|
{
|
|
HandleException(e, tenant);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
HandleException(e, tenant);
|
|
}
|
|
|
|
PrintSeperator();
|
|
|
|
if (res.Success)
|
|
return;
|
|
|
|
foreach (var result in req.ResultDCs)
|
|
{
|
|
FileController.SaveAsXmlFileInResultFolder(result, tenant, user);
|
|
}
|
|
|
|
PrintSeperator();
|
|
}
|
|
|
|
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). ");
|
|
}
|
|
}
|
|
}
|
|
}
|