336 lines
14 KiB
C#
336 lines
14 KiB
C#
// Copyright (c) 2015-2017 schick Informatik
|
|
// Service entry point
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.ServiceProcess;
|
|
using System.Timers;
|
|
|
|
using log4net;
|
|
using MigraDoc.DocumentObjectModel;
|
|
|
|
using bsmd.database;
|
|
using bsmd.email;
|
|
using System.Text;
|
|
|
|
namespace bsmd.ReportGenerator
|
|
{
|
|
public partial class ReportService : ServiceBase
|
|
{
|
|
|
|
private Timer _timer;
|
|
private readonly object _timerlock = new object();
|
|
private bool processRunning = false;
|
|
private readonly ILog _log = LogManager.GetLogger(typeof(ReportService));
|
|
|
|
public ReportService()
|
|
{
|
|
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
|
|
InitializeComponent();
|
|
}
|
|
|
|
#region windows service overrides
|
|
|
|
protected override void OnStart(string[] args)
|
|
{
|
|
this.EventLog.Source = this.ServiceName;
|
|
this.EventLog.Log = "Application";
|
|
this.Init(args);
|
|
this.EventLog.WriteEntry("Report Service started.", EventLogEntryType.Information);
|
|
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
|
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
|
|
string version = fvi.FileVersion;
|
|
_log.InfoFormat("Report Service started. v.{0}", version);
|
|
this.DoOnce();
|
|
}
|
|
|
|
protected override void OnStop()
|
|
{
|
|
_log.Info("Report Service stopping.");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region timer functions
|
|
|
|
private void Init(string[] args)
|
|
{
|
|
this._timer = new Timer();
|
|
this._timer.Interval = Properties.Settings.Default.SleepSeconds * 1000;
|
|
this._timer.Elapsed += _timer_Elapsed;
|
|
this._timer.Enabled = true;
|
|
}
|
|
|
|
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
|
|
{
|
|
lock (this._timerlock)
|
|
{
|
|
if (this.processRunning) return;
|
|
else this.processRunning = true;
|
|
}
|
|
|
|
if (DBManager.Instance.Connect(Properties.Settings.Default.ConnectionString))
|
|
{
|
|
|
|
try
|
|
{
|
|
// load all messages with report flag set
|
|
List<MessageCore> reportCores = DBManager.Instance.GetMessageCoresByReportStatus(MessageCore.ReportStatusEnum.COMPLETE);
|
|
reportCores.AddRange(DBManager.Instance.GetMessageCoresByReportStatus(MessageCore.ReportStatusEnum.HE_REPORTTYPE));
|
|
reportCores.AddRange(DBManager.Instance.GetMessageCoresByReportStatus(MessageCore.ReportStatusEnum.HE_REVISION));
|
|
// create report documents for each of the messages
|
|
foreach (MessageCore reportCore in reportCores)
|
|
{
|
|
this.CreateReport(reportCore);
|
|
}
|
|
|
|
// new ENI-2 Mode
|
|
reportCores = DBManager.Instance.GetMessageCoresByReportStatus(MessageCore.ReportStatusEnum.SINGLE);
|
|
foreach(MessageCore reportCore in reportCores)
|
|
{
|
|
this.CreateSingleReport(reportCore);
|
|
}
|
|
|
|
|
|
DBManager.Instance.Disconnect();
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_log.ErrorFormat("Exception occurred: {0}", ex.ToString());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.EventLog.WriteEntry("ReportService DB connection failed", EventLogEntryType.Error);
|
|
}
|
|
|
|
lock (this._timerlock)
|
|
{
|
|
this.processRunning = false;
|
|
}
|
|
}
|
|
|
|
internal void DoOnce()
|
|
{
|
|
this._timer_Elapsed(null, null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region create and send "old" EU-NOAD report
|
|
|
|
private void CreateReport(MessageCore reportCore)
|
|
{
|
|
List<Message> messages = DBManager.Instance.GetMessagesForCore(reportCore, DBManager.MessageLoad.ALL);
|
|
messages.Sort(new ANSWMessageComparer());
|
|
Dictionary<string, string> coverInfos = new Dictionary<string, string>();
|
|
bool isReportUpdate = reportCore.ReportStatus != MessageCore.ReportStatusEnum.COMPLETE;
|
|
|
|
coverInfos.Add("Type", reportCore.HerbergReportType);
|
|
coverInfos.Add("Ship", DBManager.Instance.GetShipNameFromCore(reportCore));
|
|
coverInfos.Add("E-Mail Ship", reportCore.HerbergEmailContactReportingVessel);
|
|
coverInfos.Add("IMO", reportCore.IMO);
|
|
DateTime eta = reportCore.ETA ?? (reportCore.ETAKielCanal ?? new DateTime(0));
|
|
coverInfos.Add("ETA", eta.ToShortDateString());
|
|
coverInfos.Add("Port", reportCore.Portname);
|
|
coverInfos.Add("", "");
|
|
if (reportCore.Customer != null)
|
|
{
|
|
coverInfos.Add("Name", reportCore.Customer.Name);
|
|
coverInfos.Add("Contact first name", reportCore.Customer.ContactFirstName);
|
|
coverInfos.Add("Contact last name", reportCore.Customer.ContactLastName);
|
|
coverInfos.Add("Customer number", reportCore.Customer.CustomerNumber);
|
|
coverInfos.Add("Street", reportCore.Customer.StreetAndNumber);
|
|
coverInfos.Add("Postal code", reportCore.Customer.PostalCode);
|
|
coverInfos.Add("City", reportCore.Customer.City);
|
|
coverInfos.Add("Country", reportCore.Customer.Country);
|
|
coverInfos.Add("Phone", reportCore.Customer.Phone);
|
|
coverInfos.Add("E-Mail", reportCore.Customer.Email);
|
|
}
|
|
|
|
// create document and print header area (with message core data)
|
|
Document migraDocument = BSMDDocument.CreateDocument(
|
|
string.Format("NSW Eingangsdatenübersicht für IMO {0}, ETA {1}", reportCore.IMO, reportCore.ETA),
|
|
"NSW Meldung",
|
|
Properties.Settings.Default.ReportAuthor,
|
|
coverInfos,
|
|
isReportUpdate);
|
|
|
|
// print messages in subsequent tables
|
|
foreach (Message message in messages)
|
|
{
|
|
BSMDDocument.AddNSWMessageParagraph(migraDocument, message);
|
|
}
|
|
|
|
// prepare and send E-Mail with generated attachment
|
|
string fullPath = string.Format("{0}\\{1}.pdf", Properties.Settings.Default.OutputDirectory,
|
|
reportCore.Id);
|
|
BSMDDocument.RenderDocument(migraDocument, fullPath);
|
|
_log.InfoFormat("Document created for MessageCoreId {0}, IMO {1}", reportCore.Id, reportCore.IMO);
|
|
string subject = string.Format("NEW EU-NOAD message IMO {0}", reportCore.IMO);
|
|
if(isReportUpdate)
|
|
subject = string.Format("UPDATE EU-NOAD message IMO {0}", reportCore.IMO);
|
|
List<string> attachments = new List<string>();
|
|
attachments.Add(fullPath);
|
|
|
|
#region 10.7.15: Check PAS/CREW messages to create extra csv files and add them as well
|
|
|
|
Message pas = messages.Find(x => x.MessageNotificationClass == Message.NotificationClass.PAS);
|
|
string passengerCSV = null;
|
|
if ((pas != null) && (pas.Elements.Count > 0))
|
|
{
|
|
passengerCSV = CrewPasHelper.CreateCSV(pas);
|
|
attachments.Add(passengerCSV);
|
|
}
|
|
|
|
Message crew = messages.Find(x => x.MessageNotificationClass == Message.NotificationClass.CREW);
|
|
string crewCSV = null;
|
|
if ((crew != null) && (crew.Elements.Count > 0))
|
|
{
|
|
crewCSV = CrewPasHelper.CreateCSV(crew);
|
|
attachments.Add(crewCSV);
|
|
}
|
|
|
|
#endregion
|
|
|
|
BSMDMail.SendNSWReportWithAttachments(subject, attachments, null);
|
|
// reset report status
|
|
reportCore.ReportStatus = MessageCore.ReportStatusEnum.NONE;
|
|
DBManager.Instance.Save(reportCore);
|
|
|
|
if (passengerCSV != null)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(passengerCSV);
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
_log.WarnFormat("Exception trying to delete passenger csv:{0}", ex.Message);
|
|
}
|
|
}
|
|
if (crewCSV != null)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(crewCSV);
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
_log.WarnFormat("Exception trying to delete crew csv:{0}", ex.Message);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region create (and send) "single" report (a report per message class)
|
|
|
|
internal void CreateSingleReport(MessageCore reportCore)
|
|
{
|
|
List<Message> messages = DBManager.Instance.GetMessagesForCore(reportCore, DBManager.MessageLoad.ALL);
|
|
List<Message> reportMessages = new List<Message>();
|
|
messages.Sort(new ANSWMessageComparer());
|
|
StringBuilder sb = new StringBuilder();
|
|
Guid reportingPartyId = Guid.Empty;
|
|
|
|
foreach (Message aMessage in messages)
|
|
{
|
|
if (aMessage.InternalStatus == Message.BSMDStatus.REPORT)
|
|
{
|
|
if (
|
|
(aMessage.MessageNotificationClass != Message.NotificationClass.VISIT) &&
|
|
(aMessage.MessageNotificationClass != Message.NotificationClass.TRANSIT) &&
|
|
(aMessage.Elements.Count > 0)
|
|
)
|
|
reportMessages.Add(aMessage);
|
|
aMessage.InternalStatus = aMessage.LastStatus ?? Message.BSMDStatus.PREPARE;
|
|
DBManager.Instance.Save(aMessage);
|
|
sb.Append(aMessage.MessageNotificationClassDisplay);
|
|
sb.Append("_");
|
|
if (aMessage.ReportingPartyId.HasValue)
|
|
reportingPartyId = aMessage.ReportingPartyId.Value;
|
|
}
|
|
}
|
|
|
|
if (sb.Length > 0) sb.Remove(sb.Length - 1, 1);
|
|
string classes = sb.ToString();
|
|
if (!classes.IsNullOrEmpty())
|
|
{
|
|
ReportingParty rp;
|
|
if (DBManager.Instance.GetReportingPartyDict().ContainsKey(reportingPartyId))
|
|
{
|
|
rp = DBManager.Instance.GetReportingPartyDict()[reportingPartyId];
|
|
|
|
Dictionary<string, string> coverInfos = new Dictionary<string, string>();
|
|
coverInfos.Add("Ship", DBManager.Instance.GetShipNameFromCore(reportCore));
|
|
coverInfos.Add("ETA", reportCore.ETA_NOA_NOD.HasValue ? reportCore.ETA_NOA_NOD.Value.ToLocalTime().ToString() : "");
|
|
coverInfos.Add("Port of call", reportCore.Portname);
|
|
coverInfos.Add("Visit-ID", reportCore.DisplayId);
|
|
coverInfos.Add("Class", classes);
|
|
|
|
string subject = string.Format("PDF report IMO {0} class(es) {1}", reportCore.IMO, classes);
|
|
|
|
Document migraDocument = BSMDDocument.CreateSingleClassDocument(reportCore, reportMessages, coverInfos, classes, rp);
|
|
|
|
// print messages to document
|
|
foreach (Message message in reportMessages)
|
|
{
|
|
BSMDDocument.AddNSWMessageParagraph(migraDocument, message);
|
|
}
|
|
|
|
// prepare and send E-Mail with generated attachment
|
|
// Schiffsname_ID_Meldeklassen.pdf
|
|
string shipName = DBManager.Instance.GetShipNameFromCore(reportCore);
|
|
if (shipName.IsNullOrEmpty()) shipName = "UNKNOWN";
|
|
// INSANITY CHECK!!!
|
|
string invalid = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
|
|
foreach (char c in invalid)
|
|
shipName = shipName.Replace(c.ToString(), "");
|
|
|
|
shipName = shipName.Replace(' ', '_');
|
|
string fullPath = string.Format("{0}\\{1}_{2}_{3}.pdf", Properties.Settings.Default.OutputDirectory, shipName, reportCore.DisplayId, classes);
|
|
|
|
BSMDDocument.RenderDocument(migraDocument, fullPath);
|
|
_log.InfoFormat("Document created for MessageCoreId {0}, IMO {1}", reportCore.Id, reportCore.IMO);
|
|
List<string> attachments = new List<string>();
|
|
attachments.Add(fullPath);
|
|
|
|
BSMDMail.SendNSWReportWithAttachments(subject, attachments, rp.UserEMail);
|
|
|
|
// remove
|
|
if (Properties.Settings.Default.DeleteFileAfterSend)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(fullPath);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_log.ErrorFormat("Cannot delete {0}: {1}", fullPath, ex.Message);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_log.WarnFormat("Default reporting party not set on core {0}", reportCore.Id);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_log.WarnFormat("Core {0} set for report, but no message classes!", reportCore.Id);
|
|
}
|
|
|
|
// reset report status
|
|
reportCore.ReportStatus = MessageCore.ReportStatusEnum.NONE;
|
|
DBManager.Instance.Save(reportCore);
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|