diff --git a/Stundensheet.xlsx b/Stundensheet.xlsx
index 65328b84..5b4c842b 100644
Binary files a/Stundensheet.xlsx and b/Stundensheet.xlsx differ
diff --git a/nsw/Source/bsmd.ReportGenerator/App.config b/nsw/Source/bsmd.ReportGenerator/App.config
index 96b98d8b..d40bb9be 100644
--- a/nsw/Source/bsmd.ReportGenerator/App.config
+++ b/nsw/Source/bsmd.ReportGenerator/App.config
@@ -45,6 +45,9 @@
+
+ False
+
\ No newline at end of file
diff --git a/nsw/Source/bsmd.ReportGenerator/BSMDDocument.cs b/nsw/Source/bsmd.ReportGenerator/BSMDDocument.cs
index 02c8f3d0..27626c0e 100644
--- a/nsw/Source/bsmd.ReportGenerator/BSMDDocument.cs
+++ b/nsw/Source/bsmd.ReportGenerator/BSMDDocument.cs
@@ -51,6 +51,23 @@ namespace bsmd.ReportGenerator
return document;
}
+ internal static Document CreateSingleClassDocument(MessageCore reportCore, List reportMessages,
+ Dictionary coverInfos, string classes, ReportingParty rp)
+ {
+
+ Document document = new Document();
+ document.Info.Title = string.Format("{0} for {1}", classes, reportCore.DisplayId);
+ document.Info.Subject = "Reporting class info";
+ document.Info.Author = Properties.Settings.Default.ReportAuthor;
+
+ BSMDDocument.DefineSingleStyle(document);
+ BSMDDocument.DefineSingleHeader(document, coverInfos, rp);
+ BSMDDocument.DefineContentSectionInitial(document);
+
+
+ return document;
+ }
+
///
/// create the final output document
///
@@ -130,9 +147,43 @@ namespace bsmd.ReportGenerator
style.ParagraphFormat.Font.Color = Colors.Blue;
}
+ static void DefineSingleStyle(Document doc)
+ {
+ Style style = doc.Styles["Normal"];
+ style.Font.Name = "Verdana";
+
+ Style tableStyle = doc.Styles.AddStyle("Table", "Normal");
+ tableStyle.Font.Name = "Verdana";
+ tableStyle.Font.Size = 9;
+
+ // usw
+ Style tableHeaderStyle = doc.Styles.AddStyle("TableHeader", "Normal");
+ //tableHeaderStyle.Font.Name = "Verdana";
+ tableHeaderStyle.Font.Size = 10;
+ tableHeaderStyle.Font.Bold = true;
+
+ Style tableValueStyle = doc.Styles.AddStyle("TableValue", "Normal");
+ tableValueStyle.Font.Size = 9;
+ tableValueStyle.Font.Bold = true;
+
+ style = doc.Styles["Heading2"];
+ style.Font.Size = 12;
+ style.Font.Bold = true;
+ style.ParagraphFormat.SpaceBefore = 6;
+ style.ParagraphFormat.SpaceAfter = 6;
+
+ style = doc.Styles["Heading3"];
+ style.Font.Size = 10;
+ style.Font.Bold = true;
+ style.Font.Italic = true;
+ style.ParagraphFormat.SpaceBefore = 6;
+ style.ParagraphFormat.SpaceAfter = 3;
+
+ }
+
#endregion
- #region Cover
+ #region Cover (alt, EU-NOAD)
///
/// Defines the cover page.
@@ -177,13 +228,110 @@ namespace bsmd.ReportGenerator
row.Cells[0].AddParagraph(key);
row.Cells[1].AddParagraph(coverInfos[key] ?? string.Empty);
}
-
}
#endregion
+ #region "Neuer" EUREPORT Header Block für Einzelnachrichten
+
+ internal static void DefineSingleHeader(Document document, Dictionary coverInfos, ReportingParty rp)
+ {
+ Section section = document.AddSection();
+ section.PageSetup.StartingNumber = 1;
+
+ Table table = document.LastSection.AddTable();
+ table.Style = "Table";
+ table.Borders.Color = Colors.LightGray;
+ table.Borders.Width = 0.25;
+
+ // Define Colums
+ Column col = table.AddColumn(80); // die Bildspalte
+ col.Format.Alignment = ParagraphAlignment.Center;
+
+ col = table.AddColumn(70);
+ col = table.AddColumn(140);
+ col = table.AddColumn(60);
+ col = table.AddColumn(140);
+
+ Row row = table.AddRow();
+ Image logoImage = row.Cells[0].AddImage(Properties.Settings.Default.LogoPath);
+ logoImage.Width = 80;
+ row.Cells[0].MergeDown = 6;
+
+ Paragraph paragraph = row.Cells[1].AddParagraph("Visit Details");
+ row.Cells[1].MergeRight = 3;
+ row.Cells[1].Shading.Color = Colors.LightGray;
+ paragraph.Style = "TableHeader";
+
+ row = table.AddRow();
+ row.Cells[1].AddParagraph("Visit-ID");
+ paragraph = row.Cells[2].AddParagraph(coverInfos["Visit-ID"]);
+ paragraph.Style = "TableValue";
+ row.Cells[3].AddParagraph("Name");
+ paragraph = row.Cells[4].AddParagraph(coverInfos["Ship"]);
+ paragraph.Style = "TableValue";
+
+ row = table.AddRow();
+ row.Cells[1].AddParagraph("Port of call");
+ paragraph = row.Cells[2].AddParagraph(coverInfos["Port of call"]);
+ paragraph.Style = "TableValue";
+ row.Cells[3].AddParagraph("ETA");
+ paragraph = row.Cells[4].AddParagraph(coverInfos["ETA"]);
+ paragraph.Style = "TableValue";
+
+ row = table.AddRow();
+ row.Shading.Color = Colors.LightGray;
+ paragraph = row.Cells[1].AddParagraph("Reporting Party");
+ row.Cells[1].MergeRight = 3;
+ paragraph.Style = "TableHeader";
+
+ row = table.AddRow();
+ row.Cells[1].AddParagraph("Organization");
+ paragraph = row.Cells[2].AddParagraph(rp.Name);
+ paragraph.Style = "TableValue";
+ row.Cells[2].MergeRight = 2;
+
+ row = table.AddRow();
+ row.Cells[1].AddParagraph("Last name");
+ paragraph = row.Cells[2].AddParagraph(rp.LastName);
+ paragraph.Style = "TableValue";
+
+ row.Cells[3].AddParagraph("City");
+ paragraph = row.Cells[4].AddParagraph(rp.City);
+ paragraph.Style = "TableValue";
+
+ row = table.AddRow();
+ row.Cells[1].AddParagraph("Phone");
+ paragraph = row.Cells[2].AddParagraph(rp.Phone);
+ paragraph.Style = "TableValue";
+
+ row.Cells[3].AddParagraph("Email");
+ paragraph = row.Cells[4].AddParagraph(rp.EMail);
+ paragraph.Style = "TableValue";
+
+ }
+
+ #endregion
+
#region setup, header and footers
+ public static void DefineContentSectionInitial(Document document)
+ {
+ Section section = document.LastSection;
+ section.PageSetup.OddAndEvenPagesHeaderFooter = false;
+ section.PageSetup.Orientation = Orientation.Portrait;
+ HeaderFooter header = section.Headers.Primary;
+ header.AddParagraph(string.Format("EUREPORT - created {0}", DateTime.Now.ToString()));
+
+ Paragraph paragraph = new Paragraph();
+ paragraph.AddTab();
+ paragraph.AddPageField();
+ paragraph.AddText(" / ");
+ paragraph.AddNumPagesField();
+ section.Footers.Primary.Add(paragraph);
+
+ }
+
///
/// Defines page setup, headers, and footers.
///
@@ -211,7 +359,7 @@ namespace bsmd.ReportGenerator
// Add clone of paragraph to footer for odd pages. Cloning is necessary because an object must
// not belong to more than one other object. If you forget cloning an exception is thrown.
section.Footers.EvenPage.Add(paragraph.Clone());
- }
+ }
#endregion
@@ -301,7 +449,7 @@ namespace bsmd.ReportGenerator
BSMDDocument.AddActualTableParagraph(document, childParagraph.MessageText, true);
}
}
- }
+ }
#region CREW
private static void CreateCrewTable(Document document, Message message)
@@ -778,16 +926,16 @@ namespace bsmd.ReportGenerator
private static void AddActualTableParagraph(Document document, List> messageText, bool isSubTable)
{
Table table = document.LastSection.AddTable();
-
+ table.Borders.Color = Colors.LightGray;
// table.LeftPadding = new Unit(0.5, UnitType.Centimeter);
- Column leadColumn = table.AddColumn(Unit.FromCentimeter(8));
+ Column leadColumn = table.AddColumn(200);
leadColumn.Format.Alignment = ParagraphAlignment.Left;
- Column mainColumn = table.AddColumn(Unit.FromCentimeter(8));
+ Column mainColumn = table.AddColumn(290);
mainColumn.Format.Alignment = ParagraphAlignment.Left;
for (int i = 0; i < messageText.Count; i++)
diff --git a/nsw/Source/bsmd.ReportGenerator/Properties/Settings.Designer.cs b/nsw/Source/bsmd.ReportGenerator/Properties/Settings.Designer.cs
index 52fd5d2d..abf8e5aa 100644
--- a/nsw/Source/bsmd.ReportGenerator/Properties/Settings.Designer.cs
+++ b/nsw/Source/bsmd.ReportGenerator/Properties/Settings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.34209
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace bsmd.ReportGenerator.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -114,5 +114,14 @@ namespace bsmd.ReportGenerator.Properties {
return ((string)(this["LogoPath"]));
}
}
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool DeleteFileAfterSend {
+ get {
+ return ((bool)(this["DeleteFileAfterSend"]));
+ }
+ }
}
}
diff --git a/nsw/Source/bsmd.ReportGenerator/Properties/Settings.settings b/nsw/Source/bsmd.ReportGenerator/Properties/Settings.settings
index a7368bb1..da3a5781 100644
--- a/nsw/Source/bsmd.ReportGenerator/Properties/Settings.settings
+++ b/nsw/Source/bsmd.ReportGenerator/Properties/Settings.settings
@@ -35,5 +35,8 @@
+
+ False
+
\ No newline at end of file
diff --git a/nsw/Source/bsmd.ReportGenerator/ReportService.cs b/nsw/Source/bsmd.ReportGenerator/ReportService.cs
index cdec4ba3..d79126c8 100644
--- a/nsw/Source/bsmd.ReportGenerator/ReportService.cs
+++ b/nsw/Source/bsmd.ReportGenerator/ReportService.cs
@@ -1,4 +1,7 @@
-using System;
+// Copyright (c) 2015-2017 schick Informatik
+// Service entry point
+
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -10,6 +13,7 @@ using MigraDoc.DocumentObjectModel;
using bsmd.database;
using bsmd.email;
+using System.Text;
namespace bsmd.ReportGenerator
{
@@ -27,6 +31,8 @@ namespace bsmd.ReportGenerator
InitializeComponent();
}
+ #region windows service overrides
+
protected override void OnStart(string[] args)
{
this.EventLog.Source = this.ServiceName;
@@ -40,6 +46,15 @@ namespace bsmd.ReportGenerator
this.DoOnce();
}
+ protected override void OnStop()
+ {
+ _log.Info("Report Service stopping.");
+ }
+
+ #endregion
+
+ #region timer functions
+
private void Init(string[] args)
{
this._timer = new Timer();
@@ -96,19 +111,16 @@ namespace bsmd.ReportGenerator
{
this.processRunning = false;
}
- }
-
- protected override void OnStop()
- {
- _log.Info("Report Service stopping.");
- }
+ }
internal void DoOnce()
{
this._timer_Elapsed(null, null);
}
- #region create and send report
+ #endregion
+
+ #region create and send "old" EU-NOAD report
private void CreateReport(MessageCore reportCore)
{
@@ -118,7 +130,7 @@ namespace bsmd.ReportGenerator
bool isReportUpdate = reportCore.ReportStatus != MessageCore.ReportStatusEnum.COMPLETE;
coverInfos.Add("Type", reportCore.HerbergReportType);
- coverInfos.Add("Ship", DBManager.Instance.GetShipNameFromCore(reportCore));
+ 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));
@@ -213,19 +225,93 @@ namespace bsmd.ReportGenerator
}
}
+ #region create (and send) "single" report (a report per message class)
+
internal void CreateSingleReport(MessageCore reportCore)
{
List messages = DBManager.Instance.GetMessagesForCore(reportCore, DBManager.MessageLoad.ALL);
+ List reportMessages = new List();
messages.Sort(new ANSWMessageComparer());
- Dictionary coverInfos = new Dictionary();
+ StringBuilder sb = new StringBuilder();
+ Guid reportingPartyId = Guid.Empty;
- string subject = string.Format("NEW EU-NOAD message IMO {0}", reportCore.IMO);
+ foreach (Message aMessage in messages)
+ {
+ if (aMessage.InternalStatus == Message.BSMDStatus.REPORT)
+ {
+ reportMessages.Add(aMessage);
+ aMessage.InternalStatus = Message.BSMDStatus.PREPARE;
+ DBManager.Instance.Save(aMessage);
+ sb.Append(aMessage.MessageNotificationClassDisplay);
+ sb.Append(" ");
+ if (aMessage.ReportingPartyId.HasValue)
+ reportingPartyId = aMessage.ReportingPartyId.Value;
+ }
+ }
+ string classes = sb.ToString();
+ if (!classes.IsNullOrEmpty())
+ {
+ ReportingParty rp = null;
+ if (DBManager.Instance.GetReportingPartyDict().ContainsKey(reportingPartyId))
+ {
+ rp = DBManager.Instance.GetReportingPartyDict()[reportingPartyId];
+
+ Dictionary coverInfos = new Dictionary();
+ coverInfos.Add("Ship", DBManager.Instance.GetShipNameFromCore(reportCore));
+ coverInfos.Add("ETA", reportCore.ETADisplay.ToString());
+ coverInfos.Add("Port of call", reportCore.PoC);
+ 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
+ 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);
+ List attachments = new List();
+ attachments.Add(fullPath);
+
+ BSMDMail.SendNSWReportWithAttachments(subject, attachments, rp.EMail);
+
+ // 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
#endregion
diff --git a/nsw/Source/bsmd.ReportGenerator/bsmd.ReportGenerator.csproj b/nsw/Source/bsmd.ReportGenerator/bsmd.ReportGenerator.csproj
index 35e5c4b5..a98526c6 100644
--- a/nsw/Source/bsmd.ReportGenerator/bsmd.ReportGenerator.csproj
+++ b/nsw/Source/bsmd.ReportGenerator/bsmd.ReportGenerator.csproj
@@ -108,6 +108,7 @@
+
SettingsSingleFileGenerator
@@ -132,6 +133,9 @@
bsmd.email
+
+
+
\ No newline at end of file
diff --git a/nsw/Source/bsmd.ReportGenerator/readme.txt b/nsw/Source/bsmd.ReportGenerator/readme.txt
new file mode 100644
index 00000000..32f75e98
--- /dev/null
+++ b/nsw/Source/bsmd.ReportGenerator/readme.txt
@@ -0,0 +1,17 @@
+Es gibt zwei unterschiedliche Verfahren:
+
+1) MigraDoc Document (MigraDoc.*.dll)
+Das erfolgt im HTML Style bei dem man einfach Paragrafen an ein Dokument anfügt und der
+Flow wird dann vom Renderer berechnet. Es gehen auch absolute Positionen aber keine
+grafischen Elemente außer Bildern und Tabellen
+
+2) PdfDocument (PdfSharp.*.dll)
+Das ist der "Drawing" Style, hier können auch MigraDoc Dokumente eingebettet werden wenn
+man beides machen will. Es geht aber über eine graph. Context (XGraphics) und absolute
+Koordinaten. Man kann damit z.B. auch mehrere MigraDoc's in kleine Rectangles "reinrendern".
+
+Auf dieser Seite wird das sehr gut an einem Beispiel gegenübergestellt:
+http://www.pdfsharp.net/wiki/MixMigraDocAndPdfSharp-sample.ashx
+
+Koordinatensystem ist "Points" (72pt = 1 inch), es gibt Umrechnungsfunktionen für cm etc.
+In Points hat eine DIN-A4 Seite dann die Ausdehnung von 595 x 842.
diff --git a/nsw/Source/bsmd.dbh.ResponseService/packages.config b/nsw/Source/bsmd.dbh.ResponseService/packages.config
new file mode 100644
index 00000000..9a0551c5
--- /dev/null
+++ b/nsw/Source/bsmd.dbh.ResponseService/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/nsw/Source/bsmd.dbh/Response.cs b/nsw/Source/bsmd.dbh/Response.cs
index e86c36ec..584a7270 100644
--- a/nsw/Source/bsmd.dbh/Response.cs
+++ b/nsw/Source/bsmd.dbh/Response.cs
@@ -71,11 +71,13 @@ namespace bsmd.dbh
// neue VISIT - ID
aMessage.MessageCore.VisitId = VisitId;
aMessage.MessageCore.BSMDStatusInternal = MessageCore.BSMDStatus.PREPARE;
+ aMessage.SendSuccess = true;
DBManager.Instance.Save(aMessage.MessageCore);
break;
case dbh.response.RootType.TRANSIT:
aMessage.MessageCore.TransitId = TransitId;
aMessage.MessageCore.BSMDStatusInternal = MessageCore.BSMDStatus.PREPARE;
+ aMessage.SendSuccess = true;
DBManager.Instance.Save(aMessage.MessageCore);
break;
case dbh.response.RootType.CANCEL:
@@ -99,6 +101,7 @@ namespace bsmd.dbh
(int) ReportingClassesFull[0].ReportingClass[0] == (int)aMessage.MessageNotificationClass)
{
// this was successful, save status to MessageHeader
+ aMessage.SendSuccess = true;
aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED;
aMessage.Status = Message.MessageStatus.ACCEPTED;
}
@@ -125,7 +128,7 @@ namespace bsmd.dbh
error.MessageHeaderId = aMessage.Id.Value;
aMessage.InternalStatus = Message.BSMDStatus.ERROR;
DBManager.Instance.Save(error);
-
+ aMessage.SendSuccess = false;
break;
case dbh.response.RootMessageType.VIOLATION:
diff --git a/nsw/Source/bsmd.hisnord/transmitter.cs b/nsw/Source/bsmd.hisnord/transmitter.cs
index 7f352c45..89181858 100644
--- a/nsw/Source/bsmd.hisnord/transmitter.cs
+++ b/nsw/Source/bsmd.hisnord/transmitter.cs
@@ -45,7 +45,23 @@ namespace bsmd.hisnord
{
_log.WarnFormat("Transmitter process not exited within {0} minute", Properties.Settings.Default.BatchTimeoutMins);
// kill Kill KILLLL!!!
- process.Kill();
+ try
+ {
+ process.Kill();
+ process.WaitForExit(500);
+ if (process.HasExited)
+ {
+ _log.Info("Transmitter killed, process exited");
+ }
+ else
+ {
+ _log.Warn("Killing Transmitter failed, this thing hangs and we're in trouble now");
+ }
+ }
+ catch (Exception e)
+ {
+ _log.WarnFormat("Killing Transmitter failed: {0}", e.Message);
+ }
}
string errorString = process.StandardError.ReadToEnd();
if(!errorString.IsNullOrEmpty())