Highlighting erster Ansatz, immer weitere Korrekturen rund um HIS-Nord Versand
212 lines
12 KiB
C#
212 lines
12 KiB
C#
// Copyright (c) 2015-2017 schick Informatik
|
|
// Description: Bearbeitung von Antworten (dateibasiert..)
|
|
|
|
using bsmd.database;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using log4net;
|
|
using System.Xml.Linq;
|
|
|
|
namespace bsmd.hisnord
|
|
{
|
|
public class Response
|
|
{
|
|
|
|
private static ILog _log = LogManager.GetLogger(typeof(Response));
|
|
|
|
|
|
public static void ReadAnswers()
|
|
{
|
|
foreach (string answerFile in Directory.GetFiles(Properties.Settings.Default.AnswerDir))
|
|
{
|
|
bool isOK = true;
|
|
|
|
// Informationen aus dem Dateinamen
|
|
// Meldetyp_Referenz_ID_Timestamp.xml
|
|
string bareFileName = Path.GetFileNameWithoutExtension(answerFile);
|
|
string[] fileNameElems = bareFileName.Split('_');
|
|
|
|
if (fileNameElems.Length < 4)
|
|
{
|
|
_log.WarnFormat("ANSWER file {0}.xml has an invalid file name", bareFileName);
|
|
isOK = false;
|
|
}
|
|
else
|
|
{
|
|
int prozessStatus;
|
|
if (!Int32.TryParse(fileNameElems[fileNameElems.Length - 1], out prozessStatus))
|
|
{
|
|
_log.WarnFormat("ANSWER file {0}.xml has no process status at the end (2..6)", bareFileName);
|
|
isOK = false;
|
|
}
|
|
else
|
|
{
|
|
long timestampMilliSecs;
|
|
if (!Int64.TryParse(fileNameElems[fileNameElems.Length - 2], out timestampMilliSecs))
|
|
{
|
|
_log.WarnFormat("ANSWER file {0}.xml has no readable timestamp", bareFileName);
|
|
isOK = false;
|
|
}
|
|
else
|
|
{
|
|
string refId = fileNameElems[fileNameElems.Length - 3];
|
|
string meldeTyp = fileNameElems[fileNameElems.Length - 4];
|
|
if (fileNameElems.Length == 5)
|
|
meldeTyp = string.Format("{0}_{1}", fileNameElems[fileNameElems.Length - 5], meldeTyp);
|
|
|
|
// TODO: klären was man hier liest: reguläre Antwort oder Schnittstellenfehler
|
|
// XML Linq statt Serialisierung
|
|
try
|
|
{
|
|
XElement xml = XElement.Load(answerFile);
|
|
|
|
// declare Namespaces
|
|
XNamespace ns1 = "http://api.national-single-window.de/visitIdRequest";
|
|
XNamespace ns6 = "http://api.national-single-window.de/receipt";
|
|
//XNamespace ns15 = "http://api.national-single-window.de/statusForClientRequestId";
|
|
XNamespace soap = "http://schemas.xmlsoap.org/soap/envelope/";
|
|
XNamespace ns15 = "http://api.national-single-window.de/visitIdResponse";
|
|
|
|
if (xml.Name == "SystemError")
|
|
{
|
|
// Fehlernachricht
|
|
SystemError systemError = SystemError.createFromXml(xml);
|
|
if (systemError != null)
|
|
{
|
|
MessageCore aCore = DBManager.Instance.GetMessageCoreById(systemError.MessageCoreId);
|
|
if (aCore != null)
|
|
{
|
|
_log.InfoFormat("SystemError received for Core [{0}], IMO {1} ETA {2}: {3}", aCore.Id, aCore.IMO, aCore.ETADisplay, systemError.ErrorMessage);
|
|
}
|
|
else
|
|
{
|
|
_log.WarnFormat("SystemError received for unknown core {0}: {1}", systemError.MessageCoreId, systemError.ErrorMessage);
|
|
}
|
|
// trotzdem immer speichern
|
|
DBManager.Instance.Save(systemError);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// NSW Rückmeldung
|
|
NSWResponse nswResponse = new NSWResponse(xml);
|
|
|
|
// Rückmeldung auswerten
|
|
|
|
if (nswResponse.MessageCoreId.HasValue)
|
|
{
|
|
MessageCore core = DBManager.Instance.GetMessageCoreById(nswResponse.MessageCoreId.Value);
|
|
if (core != null)
|
|
{
|
|
List<Message> messages = DBManager.Instance.GetMessagesForCore(core, DBManager.MessageLoad.ALL);
|
|
|
|
if(nswResponse.NotificationClass == Message.NotificationClass.VISIT)
|
|
{
|
|
if ((nswResponse.Status == "ACCEPTED") && !nswResponse.VisitId.IsNullOrEmpty())
|
|
core.VisitId = nswResponse.VisitId;
|
|
}
|
|
|
|
if(nswResponse.NotificationClass == Message.NotificationClass.TRANSIT)
|
|
{
|
|
if ((nswResponse.Status == "ACCEPTED") && !nswResponse.TransitId.IsNullOrEmpty())
|
|
core.TransitId = nswResponse.TransitId;
|
|
}
|
|
|
|
core.BSMDStatusInternal = MessageCore.BSMDStatus.RESPONDED;
|
|
DBManager.Instance.Save(core);
|
|
|
|
// now find the message that was meant..
|
|
foreach (Message aMessage in messages)
|
|
{
|
|
if (aMessage.MessageNotificationClass == nswResponse.NotificationClass)
|
|
{
|
|
|
|
if (nswResponse.Status != null)
|
|
{
|
|
bool isAccepted = (nswResponse.Status == "ACCEPTED");
|
|
if(isAccepted)
|
|
{
|
|
aMessage.Status = Message.MessageStatus.ACCEPTED;
|
|
aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED;
|
|
if (nswResponse.Violations.Count > 0)
|
|
{
|
|
aMessage.InternalStatus = Message.BSMDStatus.VIOLATION;
|
|
aMessage.StatusInfo = "Violations reported";
|
|
}
|
|
aMessage.ReceivedAt = nswResponse.ReceiveAt;
|
|
}
|
|
else
|
|
{
|
|
aMessage.Status = Message.MessageStatus.REJECTED;
|
|
aMessage.InternalStatus = Message.BSMDStatus.ERROR;
|
|
aMessage.StatusInfo = "Errors reported";
|
|
}
|
|
|
|
DBManager.Instance.Save(aMessage);
|
|
}
|
|
|
|
#region Error / Violation handling
|
|
|
|
foreach (MessageError existingError in aMessage.ErrorList)
|
|
DBManager.Instance.Delete(existingError);
|
|
|
|
foreach (MessageViolation existingViolation in aMessage.ViolationList)
|
|
DBManager.Instance.Delete(existingViolation);
|
|
|
|
foreach (MessageError messageError in nswResponse.Errors)
|
|
{
|
|
messageError.MessageHeaderId = aMessage.Id.Value;
|
|
messageError.MessageHeader = aMessage;
|
|
DBManager.Instance.Save(messageError);
|
|
}
|
|
|
|
foreach (MessageViolation messageViolation in nswResponse.Violations)
|
|
{
|
|
messageViolation.MessageHeaderId = aMessage.Id.Value;
|
|
messageViolation.MessageHeader = aMessage;
|
|
DBManager.Instance.Save(messageViolation);
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_log.ErrorFormat("cannot find core for id {0}", nswResponse.MessageCoreId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_log.ErrorFormat("received response without suitable conveyance code, request id {0}", nswResponse.ClientRequestId);
|
|
isOK = false;
|
|
}
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
_log.WarnFormat("Exception deserializing ANSWER file: {0}", ex.ToString());
|
|
isOK = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(isOK)
|
|
{
|
|
// archive file
|
|
File.Move(answerFile, Path.Combine(Properties.Settings.Default.AnswerArchiveDir, Path.GetFileName(answerFile)));
|
|
}
|
|
else
|
|
{
|
|
// save in separate folder (to look at it later?)
|
|
File.Move(answerFile, Path.Combine(Properties.Settings.Default.AnswerCorruptDir, Path.GetFileName(answerFile)));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|