3.8.7: weitere Korrekturen, PDF

This commit is contained in:
Daniel Schick 2017-11-19 08:46:16 +00:00
parent 5c2892e1eb
commit d61886daef
35 changed files with 841 additions and 352 deletions

View File

@ -26,12 +26,12 @@
<value>1000</value>
</setting>
<setting name="LockingServerAddress" serializeAs="String">
<value>http://192.168.2.4/LockingService/LockingService.svc</value>
<!--value>http://heupferd/bsmd.LockingService/LockingService.svc</value-->
<!--value>http://192.168.2.4/LockingService/LockingService.svc</value-->
<value>http://heupferd/bsmd.LockingService/LockingService.svc</value>
</setting>
<setting name="ConnectionString" serializeAs="String">
<value>Data Source=192.168.2.12;Initial Catalog=nsw;Uid=dfuser;Pwd=dfpasswd;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False</value>
<!--value>Data Source=(localdb)\Projects;Initial Catalog=nsw;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False</value-->
<!--value>Data Source=192.168.2.12;Initial Catalog=nsw;Uid=dfuser;Pwd=dfpasswd;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False</value-->
<value>Data Source=(localdb)\Projects;Initial Catalog=nsw;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False</value>
</setting>
</ENI2.Properties.Settings>
</applicationSettings>

View File

@ -124,7 +124,11 @@ namespace ENI2
{
_typeMessageDict[message.MessageNotificationClass] = message;
}
}
public virtual void SetEnabled(bool enabled)
{
this.IsEnabled = enabled;
}
#endregion

View File

@ -84,10 +84,7 @@ namespace ENI2
this._listBoxList.Add(new MessageGroup() { MessageGroupName = Properties.Resources.textTowage, MessageGroupControlType = typeof(TowageDetailControl), ImagePath = "Resources/ship2.png" });
this.listBoxMessages.ItemsSource = this._listBoxList;
// Locking ergänzt. Ich habe den Eindruck, dass die DataReader Fehler beim BSMD daran liegen, dass das hier länger dauert als
// man eine neue Anmeldung anklickt -> paralleles Laden -> Autsch
this.listBoxMessages.ItemsSource = this._listBoxList;
_messages = DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).GetMessagesForCore(_core, DBManager.MessageLoad.ALL);
@ -144,9 +141,10 @@ namespace ENI2
detailControl.RequestDisable += DetailControl_RequestDisable;
detailControl.Initialize();
detailControl.IsEnabled = !this.LockedByOtherUser;
bool isEnabled = !this.LockedByOtherUser;
detailControl.SetEnabled(isEnabled);
if (!detailControl.IsEnabled && (detailControl is OverViewDetailControl) && !(_core.Cancelled ?? false))
if (!isEnabled && (detailControl is OverViewDetailControl) && !(_core.Cancelled ?? false))
((OverViewDetailControl)detailControl).ShowLockedBy(this.LockedBy);
controlCache.Add(mg.MessageGroupName, detailControl);
@ -272,6 +270,14 @@ namespace ENI2
{
this.SaveMessage(message);
}
DetailBaseControl currentControl = this.detailView.Children[0] as DetailBaseControl;
if (currentControl is OverViewDetailControl)
{
// ggf. hat sich die Ticketnr geändert..
DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(currentControl.Core);
}
this.buttonSaveAll.Visibility = Visibility.Hidden;
this.buttonSave.Visibility = Visibility.Hidden;
}
@ -379,7 +385,10 @@ namespace ENI2
}
// "neue" regelbasierte Validierung: Hier werden die einzelnen Regeln geprüft.
bsmd.database.ValidationRule.PrepareNameLookupDict(this.Core, this._messages);
List<bsmd.database.ValidationRule> validationRules = DBManager.Instance.GetValidationRules();
foreach (bsmd.database.ValidationRule validationRule in validationRules) {
if (!validationRule.IsActive ?? false) continue;
// Regel auspacken

View File

@ -41,6 +41,8 @@ namespace ENI2.DetailViewControls
this.RegisterCheckboxChange(this.checkBoxStowaways, Message.NotificationClass.BPOL);
}
public override void Initialize()
{
base.Initialize();
@ -120,7 +122,18 @@ namespace ENI2.DetailViewControls
#endregion
}
}
#region SetEnabled
public override void SetEnabled(bool enabled)
{
this.groupBoxBorderPolice.IsEnabled = enabled;
this.groupBoxCrewList.IsEnabled = enabled;
this.groupBoxPassengerList.IsEnabled = enabled;
}
#endregion
#region port of itinerary grid

View File

@ -184,6 +184,23 @@ namespace ENI2.DetailViewControls
this._initialized = true;
}
#region SetEnabled
public override void SetEnabled(bool enabled)
{
this.dataGridIBCItems.IsEnabled = enabled;
this.checkBoxDangerousGoodsOnBoard.IsEnabled = enabled;
this.checkBoxDGManifestOnBoard.IsEnabled = enabled;
this.checkBoxMoUBaltic.IsEnabled = enabled;
this.dataGridIBCItems.IsEnabled = enabled;
this.dataGridIMDGItems.IsEnabled = enabled;
this.dataGridIGCItems.IsEnabled = enabled;
this.dataGridIMSBCItems.IsEnabled = enabled;
this.dataGridMARPOLItems.IsEnabled = enabled;
}
#endregion
#region Copy event handler
private void copyMARPOL(object sender, RoutedEventArgs e)

View File

@ -123,7 +123,24 @@ namespace ENI2.DetailViewControls
#endregion
}
}
#region SetEnabled
public override void SetEnabled(bool enabled)
{
this.mdhGroupBox.IsEnabled = enabled;
this.dataGridPortOfCallLast30Days.IsEnabled = enabled;
this.buttonImportFromSEC.IsEnabled = enabled;
this.checkBoxHasShipVisited.IsEnabled = enabled;
this.dataGridInfectedAreas.IsEnabled = enabled;
this.checkBoxSanitaryMeasuresApplied.IsEnabled = enabled;
this.dataGridSanitaryMeasures.IsEnabled = enabled;
}
#endregion
#region Enable Controls based on Checkbox (fixed)
private void CheckBoxSanitaryControlExemption_Checked(object sender, RoutedEventArgs e)
{
@ -192,6 +209,8 @@ namespace ENI2.DetailViewControls
this.dataGridSanitaryMeasures.IsReadOnly = !(this.checkBoxSanitaryMeasuresApplied.IsChecked ?? false);
}
#endregion
private void MaritimeHealthDeclarationDetailControl_Loaded(object sender, RoutedEventArgs e)
{

View File

@ -76,7 +76,7 @@
<Label Name="labelCreated" Grid.Column="4" Grid.Row="4" Margin="2, 0, 0, 0" />
<TextBox Name="textBoxTicketNo" Grid.Column="1" Grid.Row="4" Grid.ColumnSpan="2" Text="{Binding TicketNo, Mode=TwoWay}" Margin="2" VerticalContentAlignment="Center"/>
<StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="6" Visibility="Hidden" Name="stackPanelLock">
<StackPanel Orientation="Horizontal" Grid.Column="3" Grid.Row="7" Visibility="Hidden" Name="stackPanelLock">
<Image Source="../Resources/lock.png" Margin="0,0,5,0" Height="24" />
<TextBlock Name="textBlockLockUserName" VerticalAlignment="Center" />
</StackPanel>

View File

@ -28,6 +28,7 @@ namespace ENI2.DetailViewControls
private Message _noanodMessage;
private Timer _checkStatusTimer;
private DateTime _startStatusCheck;
private object _collectionLock = new object();
public OverViewDetailControl()
{
@ -88,7 +89,52 @@ namespace ENI2.DetailViewControls
if (this.Core.Cancelled ?? false) this.ShowCancelledLabel();
#region Meldeklassen einrichten und Icons / Gruppen / Index zuordnen
#region Context-Menu Meldeklassen
// wenn man das mal aufwendig "schön" machen will (die Items enabled abh. vom Zustand der Meldeklasse) sollte man
// Command Bindings verwenden. Hier ist das erklärt: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/commanding-overview#code-snippet-2
this.dataGridMessages.ContextMenu = new ContextMenu();
MenuItem sendItem = new MenuItem();
sendItem.Header = Properties.Resources.textSendToNSW;
sendItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/mail_forward.png")) };
//sendItem.Command =
sendItem.Click += new RoutedEventHandler(this.contextSendMessage);
this.dataGridMessages.ContextMenu.Items.Add(sendItem);
MenuItem resetItem = new MenuItem();
resetItem.Header = Properties.Resources.textReset;
resetItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/mail_delete.png")) };
resetItem.Click += new RoutedEventHandler(this.contextResetMessage);
this.dataGridMessages.ContextMenu.Items.Add(resetItem);
MenuItem systemErrorItem = new MenuItem();
systemErrorItem.Header = Properties.Resources.textSystemErrors;
systemErrorItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/hand_red_card.png")) };
systemErrorItem.Click += new RoutedEventHandler(this.buttonSystemErrors_Click);
this.dataGridMessages.ContextMenu.Items.Add(systemErrorItem);
MenuItem errorItem = new MenuItem();
errorItem.Header = Properties.Resources.textErrors;
errorItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/error.png")) };
errorItem.Click += new RoutedEventHandler(this.buttonErrors_Click);
this.dataGridMessages.ContextMenu.Items.Add(errorItem);
MenuItem vioItem = new MenuItem();
vioItem.Header = Properties.Resources.textViolations;
vioItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/sign_warning.png")) };
vioItem.Click += new RoutedEventHandler(this.buttonWarnings_Click);
this.dataGridMessages.ContextMenu.Items.Add(vioItem);
MenuItem pdfItem = new MenuItem();
pdfItem.Header = Properties.Resources.textCreatePDF;
pdfItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/document_pdf.png")) };
pdfItem.Click += new RoutedEventHandler(this.buttonCreatePDF_Click);
this.dataGridMessages.ContextMenu.Items.Add(pdfItem);
#endregion
#region lokale Meldeklassen
foreach (Message aMessage in this.Messages)
{
@ -100,7 +146,100 @@ namespace ENI2.DetailViewControls
this._atdMessage = aMessage;
if (aMessage.MessageNotificationClass == Message.NotificationClass.NOA_NOD)
this._noanodMessage = aMessage;
}
#endregion
#region init ATA
// ganz hakelig ich weiß dafür kapiert das gleich jeder
if (this._ataMessage == null)
{
this._ataMessage = this.Core.CreateMessage(Message.NotificationClass.ATA);
this.Messages.Add(this._ataMessage);
this._ataMessage.ENINotificationIconString = "../Resources/arrow_down_right_red.png";
this._ataMessage.ENINotificationDetailGroup = Properties.Resources.textArrivalNotification;
this._ataMessage.ENINotificationDetailIndex = 4;
}
ATA ata = null;
if (this._ataMessage.Elements.Count > 0)
ata = this._ataMessage.Elements[0] as ATA;
if (ata == null)
{
ata = new ATA();
ata.MessageCore = this.Core;
ata.MessageHeader = this._ataMessage;
_ataMessage.Elements.Add(ata);
}
this.dateTimePickerATA.DataContext = ata;
this.ControlMessages.Add(this._ataMessage);
#endregion
#region init ATD
if (this._atdMessage == null)
{
this._atdMessage = this.Core.CreateMessage(Message.NotificationClass.ATD);
this.Messages.Add(this._atdMessage);
this._atdMessage.ENINotificationIconString = "../Resources/arrow_up_right_green.png";
this._atdMessage.ENINotificationDetailGroup = Properties.Resources.textDepartureNotification;
this._atdMessage.ENINotificationDetailIndex = 10;
}
ATD atd = null;
if (this._atdMessage.Elements.Count > 0)
atd = this._atdMessage.Elements[0] as ATD;
if (atd == null)
{
atd = new ATD();
atd.MessageCore = this.Core;
atd.MessageHeader = this._atdMessage;
_atdMessage.Elements.Add(atd);
}
this.dateTimePickerATD.DataContext = atd;
this.ControlMessages.Add(this._atdMessage);
#endregion
#region init NOA_NOD
if (this._noanodMessage == null)
{
this._noanodMessage = this.Core.CreateMessage(Message.NotificationClass.NOA_NOD);
this.Messages.Add(this._noanodMessage);
_noanodMessage.ENINotificationIconString = "../Resources/eye_blue.png";
_noanodMessage.ENINotificationDetailGroup = Properties.Resources.textPortCall;
_noanodMessage.ENINotificationDetailIndex = 1;
}
NOA_NOD noa_nod = null;
if (this._noanodMessage.Elements.Count > 0)
noa_nod = this._noanodMessage.Elements[0] as NOA_NOD;
if (noa_nod == null)
{
noa_nod = new NOA_NOD();
noa_nod.MessageCore = this.Core;
noa_nod.MessageHeader = this._noanodMessage;
_noanodMessage.Elements.Add(noa_nod);
}
this.dateTimePickerETD.DataContext = noa_nod;
this.dateTimePickerETA.DataContext = noa_nod;
this.ControlMessages.Add(this._noanodMessage);
#endregion
#region Meldeklassen einrichten und Icons / Gruppen / Index zuordnen
foreach (Message aMessage in this.Messages)
{
switch (aMessage.MessageNotificationClass)
{
case Message.NotificationClass.VISIT:
@ -196,7 +335,8 @@ namespace ENI2.DetailViewControls
#endregion
// Meldeklassen nach ihrem Vorkommen in den Detailansichten sortieren (SH, 12.5.17)
#region Meldeklassen nach ihrem Vorkommen in den Detailansichten sortieren (SH, 12.5.17)
this.Messages.Sort((a, b) =>
{
if (a.ENINotificationDetailIndex == b.ENINotificationDetailIndex)
@ -208,140 +348,12 @@ namespace ENI2.DetailViewControls
{
// kann das eigentlich passieren??!
}
#region Context-Menu Meldeklassen
// wenn man das mal aufwendig "schön" machen will (die Items enabled abh. vom Zustand der Meldeklasse) sollte man
// Command Bindings verwenden. Hier ist das erklärt: https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/commanding-overview#code-snippet-2
this.dataGridMessages.ContextMenu = new ContextMenu();
MenuItem sendItem = new MenuItem();
sendItem.Header = Properties.Resources.textSendToNSW;
sendItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/mail_forward.png")) };
//sendItem.Command =
sendItem.Click += new RoutedEventHandler(this.contextSendMessage);
this.dataGridMessages.ContextMenu.Items.Add(sendItem);
MenuItem resetItem = new MenuItem();
resetItem.Header = Properties.Resources.textReset;
resetItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/mail_delete.png")) };
resetItem.Click += new RoutedEventHandler(this.contextResetMessage);
this.dataGridMessages.ContextMenu.Items.Add(resetItem);
MenuItem systemErrorItem = new MenuItem();
systemErrorItem.Header = Properties.Resources.textSystemErrors;
systemErrorItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/hand_red_card.png")) };
systemErrorItem.Click += new RoutedEventHandler(this.buttonSystemErrors_Click);
this.dataGridMessages.ContextMenu.Items.Add(systemErrorItem);
MenuItem errorItem = new MenuItem();
errorItem.Header = Properties.Resources.textErrors;
errorItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/error.png")) };
errorItem.Click += new RoutedEventHandler(this.buttonErrors_Click);
this.dataGridMessages.ContextMenu.Items.Add(errorItem);
MenuItem vioItem = new MenuItem();
vioItem.Header = Properties.Resources.textViolations;
vioItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/sign_warning.png")) };
vioItem.Click += new RoutedEventHandler(this.buttonWarnings_Click);
this.dataGridMessages.ContextMenu.Items.Add(vioItem);
MenuItem pdfItem = new MenuItem();
pdfItem.Header = Properties.Resources.textCreatePDF;
pdfItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/document_pdf.png")) };
pdfItem.Click += new RoutedEventHandler(this.buttonCreatePDF_Click);
this.dataGridMessages.ContextMenu.Items.Add(pdfItem);
#endregion
#region init ATA
// ganz hakelig ich weiß dafür kapiert das gleich jeder
if (this._ataMessage == null)
{
this._ataMessage = this.Core.CreateMessage(Message.NotificationClass.ATA);
this.Messages.Add(this._ataMessage);
this._ataMessage.ENINotificationIconString = "../Resources/arrow_down_right_red.png";
this._ataMessage.ENINotificationDetailGroup = Properties.Resources.textArrivalNotification;
this._ataMessage.ENINotificationDetailIndex = 4;
}
ATA ata = null;
if (this._ataMessage.Elements.Count > 0)
ata = this._ataMessage.Elements[0] as ATA;
if (ata == null)
{
ata = new ATA();
ata.MessageCore = this.Core;
ata.MessageHeader = this._ataMessage;
_ataMessage.Elements.Add(ata);
}
this.dateTimePickerATA.DataContext = ata;
this.ControlMessages.Add(this._ataMessage);
#endregion
#region init ATD
if (this._atdMessage == null)
{
this._atdMessage = this.Core.CreateMessage(Message.NotificationClass.ATD);
this.Messages.Add(this._atdMessage);
this._atdMessage.ENINotificationIconString = "../Resources/arrow_up_right_green.png";
this._atdMessage.ENINotificationDetailGroup = Properties.Resources.textDepartureNotification;
this._atdMessage.ENINotificationDetailIndex = 10;
}
ATD atd = null;
if (this._atdMessage.Elements.Count > 0)
atd = this._atdMessage.Elements[0] as ATD;
if (atd == null)
{
atd = new ATD();
atd.MessageCore = this.Core;
atd.MessageHeader = this._atdMessage;
_atdMessage.Elements.Add(atd);
}
this.dateTimePickerATD.DataContext = atd;
this.ControlMessages.Add(this._atdMessage);
#endregion
#region init NOA_NOD
if (this._noanodMessage == null)
{
this._noanodMessage = this.Core.CreateMessage(Message.NotificationClass.NOA_NOD);
this.Messages.Add(this._noanodMessage);
_noanodMessage.ENINotificationIconString = "../Resources/eye_blue.png";
_noanodMessage.ENINotificationDetailGroup = Properties.Resources.textPortCall;
_noanodMessage.ENINotificationDetailIndex = 1;
}
NOA_NOD noa_nod = null;
if (this._noanodMessage.Elements.Count > 0)
noa_nod = this._noanodMessage.Elements[0] as NOA_NOD;
if (noa_nod == null)
{
noa_nod = new NOA_NOD();
noa_nod.MessageCore = this.Core;
noa_nod.MessageHeader = this._noanodMessage;
_noanodMessage.Elements.Add(noa_nod);
}
this.dateTimePickerETD.DataContext = noa_nod;
this.dateTimePickerETA.DataContext = noa_nod;
this.ControlMessages.Add(this._noanodMessage);
#endregion
BindingOperations.EnableCollectionSynchronization(this.Messages, _collectionLock);
this.dataGridMessages.ItemsSource = this.Messages;
base.Initialize(); // wenn Meldeklassen erst bei der Init. erzeugt werden, fehlen die Handler, die hier erneut festgelegt werden
this._initialized = true;
}
@ -623,12 +635,15 @@ namespace ENI2.DetailViewControls
private void buttonCreatePDF_Click(object sender, RoutedEventArgs e)
{
for(int i = 0; i < this.dataGridMessages.SelectedItems.Count; i++)
{
Message selectedMessage = this.dataGridMessages.SelectedItems[i] as Message;
selectedMessage.InternalStatus = Message.BSMDStatus.REPORT;
selectedMessage.ReportingPartyId = App.UserId; // wichtig damit der Richtige(!) die Mail mit dem PDF bekommt
DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(selectedMessage);
}
if (this.dataGridMessages.SelectedItems.Count > 0)
{
Message selectedMessage = this.dataGridMessages.SelectedItems[0] as Message;
selectedMessage.InternalStatus = Message.BSMDStatus.REPORT;
selectedMessage.ReportingPartyId = App.UserId; // wichtig damit der richtige die Mail mit dem PDF bekommt
DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(selectedMessage);
this.Core.ReportStatus = MessageCore.ReportStatusEnum.SINGLE;
DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(this.Core);
this.dataGridMessages.Items.Refresh();

View File

@ -95,7 +95,18 @@ namespace ENI2.DetailViewControls
#endregion
}
}
#region SetEnabled
public override void SetEnabled(bool enabled)
{
this.secGroupBox.IsEnabled = enabled;
this.dataGridLast10PortFacilities.IsEnabled = enabled;
this.dataGridShip2ShipActivities.IsEnabled = enabled;
}
#endregion
#region data grid ship 2 ship activities

View File

@ -58,49 +58,9 @@ namespace ENI2.DetailViewControls
private void buttonAddMissingEntries_Click(object sender, RoutedEventArgs e)
{
// Convenience Methode, die fehlende Waste Einträge ergänzt (interessant bei "manuellen" Anmeldungen)
foreach (int wasteCode in WAS.DKWasteCodes)
{
Waste foundWaste = null;
foreach (Waste waste in this._was.Waste)
{
if (waste.WasteType.HasValue && waste.WasteType.Value == wasteCode)
{
foundWaste = waste;
break;
}
}
if (foundWaste == null)
{
Waste newWaste = new Waste();
newWaste.Identifier = DatabaseEntity.GetNewIdentifier(this._was.Waste);
newWaste.WAS = _was;
newWaste.WasteAmountGeneratedTillNextPort_MTQ = 0;
newWaste.WasteAmountRetained_MTQ = 0;
newWaste.WasteCapacity_MTQ = 0;
newWaste.WasteDescription = (wasteCode == 1300) ? "-" : "";
newWaste.WasteDisposalAmount_MTQ = 0;
newWaste.WasteDisposalPort = "ZZUKN";
newWaste.WasteDisposedAtLastPort_MTQ = 0;
newWaste.WasteType = wasteCode;
this._was.Waste.Add(newWaste);
}
else
{
if (!foundWaste.WasteAmountGeneratedTillNextPort_MTQ.HasValue) foundWaste.WasteAmountGeneratedTillNextPort_MTQ = 0;
if (!foundWaste.WasteAmountRetained_MTQ.HasValue) foundWaste.WasteAmountRetained_MTQ = 0;
if (!foundWaste.WasteCapacity_MTQ.HasValue) foundWaste.WasteCapacity_MTQ = 0;
if ((wasteCode == 1300) && foundWaste.WasteDescription.IsNullOrEmpty()) foundWaste.WasteDescription = "-";
if (!foundWaste.WasteDisposalAmount_MTQ.HasValue) foundWaste.WasteDisposalAmount_MTQ = 0;
if (foundWaste.WasteDisposalPort.IsNullOrEmpty()) foundWaste.WasteDisposalPort = "ZZUKN";
if (!foundWaste.WasteDisposedAtLastPort_MTQ.HasValue) foundWaste.WasteDisposedAtLastPort_MTQ = 0;
}
}
this._was.AddMissingWaste();
this.SublistElementChanged(Message.NotificationClass.WAS);
this.dataGridWaste.Items.Refresh();
}
public override void Initialize()

View File

@ -35,8 +35,8 @@
<MinimumRequiredVersion>3.5.1.0</MinimumRequiredVersion>
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>publish.html</WebPage>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>3.8.5.%2a</ApplicationVersion>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>3.8.6.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted>

View File

@ -52,6 +52,7 @@ namespace ENI2.EditControls
this.decimalUpDownMaxActivity.Value = this.IMDG.Class7MaxActivity_BQL;
this.decimalUpDownNetExplosiveMass.Value = this.IMDG.NetExplosiveMass_KGM;
this.decimalUpDownNetQuantity.Value = this.IMDG.NetQuantity_KGM;
this.doubleUpDownCargoVolume.Value = this.IMDG.Volume_MTQ;
this.integerUpDownCategory.Value = this.IMDG.Class7Category;
this.integerUpDownNumberOfPackages.Value = this.IMDG.NumberOfPackages;
@ -105,6 +106,7 @@ namespace ENI2.EditControls
this.IMDG.Class7MaxActivity_BQL = this.decimalUpDownMaxActivity.Value;
this.IMDG.NetExplosiveMass_KGM = this.decimalUpDownNetExplosiveMass.Value;
this.IMDG.NetQuantity_KGM = this.decimalUpDownNetQuantity.Value;
this.IMDG.Volume_MTQ = this.doubleUpDownCargoVolume.Value;
this.IMDG.Class7Category = this.integerUpDownCategory.Value;
this.IMDG.NumberOfPackages = this.integerUpDownNumberOfPackages.Value;

View File

@ -11,10 +11,14 @@
Title="{x:Static p:Resources.textViolations}" Height="300" Width="600" Background="AliceBlue">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition Height="*" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<enictrl:ENIDataGrid Grid.Row="0" Grid.Column="0" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
SelectionMode="Single" AutoGenerateColumns="False" Margin="0,5,0,0" x:Name="dataGridViolations">
SelectionMode="Single" AutoGenerateColumns="False" Margin="5,5,5,0" x:Name="dataGridViolations">
<DataGrid.Columns>
<DataGridTextColumn Header="{x:Static p:Resources.textCode}" Binding="{Binding ViolationCode}" IsReadOnly="True" Width="0.3*" />
<DataGridTextColumn Header="{x:Static p:Resources.textDescription}" Binding="{Binding ViolationText}" IsReadOnly="True" Width="0.7*" />

View File

@ -28,21 +28,16 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
/-->
<Grid Background="{TemplateBinding Background}" Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<!-- This ContentPresenter automatically binds to the Content of the Window -->
<ContentPresenter Grid.Row="0"/>
<DockPanel Background="{TemplateBinding Background}" Margin="2">
<!-- TODO das hier lokalisieren! -->
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="5" HorizontalAlignment="Right">
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Margin="5" HorizontalAlignment="Right">
<Button Width="80" Content="Add" Name="buttonAdd" Margin="0,0,10,0" Visibility="Hidden" />
<Button Width="80" Content="OK" IsDefault="True" IsCancel="False" Name="buttonOK" Margin="0,0,10,0" />
<Button Width="80" Content="Cancel" IsCancel="True" IsDefault="False" Name="buttonCancel" />
</StackPanel>
</Grid>
<!-- This ContentPresenter automatically binds to the Content of the Window -->
<ContentPresenter />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>

Binary file not shown.

View File

@ -1283,11 +1283,10 @@ namespace bsmd.ExcelReadService
was.Waste.Add(waste);
}
waste.WasteType = (int?) reader.ReadNumber(wasteCode);
waste.WasteType = (int?) reader.ReadNumber(wasteCode);
if (waste.WasteType.HasValue && (waste.WasteType == 2313))
waste.WasteType = 2600;
waste.WasteType = 2600;
if (reader.Mode == ExcelReader.CountryMode.DE)
{
@ -1392,31 +1391,13 @@ namespace bsmd.ExcelReadService
}
}
}
/*
try
{
// Übergangsphase: Für "DE" werden nur 9 Positionen verwendet
// EMail Christin mit angehängtem Excel Sheet vom 30.1.2017
if (reader.Mode == ExcelReader.CountryMode.DE)
if (!waste.WasteType.HasValue)
{
Waste nrSeven = was.GetSublistElementWithIdentifier("7") as Waste;
Waste nrEleven = was.GetSublistElementWithIdentifier("11") as Waste;
nrSeven.WasteDescription = nrEleven.WasteDescription;
nrSeven.WasteDisposalAmount_MTQ = nrEleven.WasteDisposalAmount_MTQ;
nrSeven.WasteCapacity_MTQ = nrEleven.WasteCapacity_MTQ;
nrSeven.WasteAmountRetained_MTQ = nrEleven.WasteAmountRetained_MTQ;
nrSeven.WasteDisposalPort = nrEleven.WasteDisposalPort;
nrSeven.WasteAmountGeneratedTillNextPort_MTQ = nrEleven.WasteAmountGeneratedTillNextPort_MTQ;
// was.Waste.RemoveRange(9, 6); // 9-15 entfernen
was.Waste.Remove(waste);
}
}
catch(Exception ex)
{
_log.ErrorFormat("Error Waste Workaround DE: {0}", ex.Message);
}
*/
was.AddMissingWaste();
}
#endregion
@ -2667,9 +2648,18 @@ namespace bsmd.ExcelReadService
if(result != null)
{
_log.InfoFormat("Core [{3}] found for IMO {0}, ETA {1}, Poc {2}", imo, eta, poc, result.Id);
result.HerbergReportType = reader.ReadText("ReferenceNumber");
reader.Conf.ConfirmText("ReferenceNumber", result.HerbergReportType, result.HerbergReportType.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK);
// Spezialfall: Wenn ein Core gefunden wird, dieser jedoch eine andere Visit/Transit Id hat als die Anmeldung ist das eine Neuanlage!
// Eingebaut 17.11.17
if(!visitTransitId.IsNullOrEmpty() && !result.DisplayId.IsNullOrEmpty() &&
(visitTransitId != result.DisplayId))
{
_log.WarnFormat("Different visit ID ({0} (Sheet) {1} (Core) for the same decl. treating as NEW!", visitTransitId, result.DisplayId);
result = null;
}
}
}

View File

@ -17,6 +17,10 @@ using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;
// keine "echten" Dependencies, nur durch File Link notwendig (Code sharing)
using ENI2;
using bsmd.ExcelReadService;
using bsmd.database;
namespace bsmd.ReportGenerator
@ -63,10 +67,10 @@ namespace bsmd.ReportGenerator
BSMDDocument.DefineSingleStyle(document);
BSMDDocument.DefineSingleHeader(document, coverInfos, rp);
BSMDDocument.DefineContentSectionInitial(document);
DatabaseEntity.ReportReplacer += DatabaseEntity_ReportReplacer;
return document;
}
}
/// <summary>
/// create the final output document
@ -236,6 +240,7 @@ namespace bsmd.ReportGenerator
static List<KeyValuePair<string, string>> ReplaceLabels(List<KeyValuePair<string, string>> messageText)
{
if (messageText == null) return null;
List<KeyValuePair<string, string>> result = new List<KeyValuePair<string, string>>();
foreach(KeyValuePair<string, string> field in messageText)
{
@ -473,7 +478,7 @@ namespace bsmd.ReportGenerator
#endregion
if (messageParagraph.MessageText != null) // komplette Nachricht (z.B. STAT)
BSMDDocument.AddActualTableParagraph(document, BSMDDocument.ReplaceLabels(messageParagraph.MessageText), false);
BSMDDocument.AddActualTableParagraph(document, messageParagraph, false);
#region SEC
@ -501,7 +506,7 @@ namespace bsmd.ReportGenerator
{
foreach (IMessageParagraph childParagraph in messageParagraph.ChildParagraphs)
{
BSMDDocument.AddActualTableParagraph(document, BSMDDocument.ReplaceLabels(childParagraph.MessageText), true);
BSMDDocument.AddActualTableParagraph(document, childParagraph, true);
}
}
@ -981,8 +986,18 @@ namespace bsmd.ReportGenerator
#endregion
private static void AddActualTableParagraph(Document document, List<KeyValuePair<string, string>> messageText, bool isSubTable)
{
private static void AddActualTableParagraph(Document document, IMessageParagraph paragraph, bool isSubTable)
{
if(isSubTable)
{
if(!paragraph.Title.IsNullOrEmpty())
document.LastSection.AddParagraph(BSMDDocument.ReplaceTitle(paragraph.Title), "Heading3");
if(!paragraph.Subtitle.IsNullOrEmpty())
document.LastSection.AddParagraph(BSMDDocument.ReplaceTitle(paragraph.Subtitle), "Heading4");
}
List<KeyValuePair<string, string>> messageText = BSMDDocument.ReplaceLabels(paragraph.MessageText);
Table table = document.LastSection.AddTable();
table.Borders.Color = Colors.LightGray;
@ -1001,7 +1016,11 @@ namespace bsmd.ReportGenerator
Row row = table.AddRow();
Cell cell = row.Cells[0];
cell.AddParagraph(elem.Key);
row.Cells[1].AddParagraph(elem.Value);
string val = elem.Value;
// funktioniert leider nicht, müsste das auf PDFsharp umstellen (http://www.pdfsharp.net/wiki/Unicode-sample.ashx)
if (val == "True") val = "Yes"; // @"\u2611"; // unicode ballot box with check
if (val == "False") val = "No"; // @"\u2610"; // unicode ballot box
row.Cells[1].AddParagraph(val);
}
if (isSubTable)
@ -1011,6 +1030,55 @@ namespace bsmd.ReportGenerator
document.LastSection.AddParagraph();
if (isSubTable)
{
if (paragraph.ChildParagraphs != null)
{
foreach (IMessageParagraph childParagraph in paragraph.ChildParagraphs)
AddActualTableParagraph(document, childParagraph, true);
}
}
}
#endregion
#region Spezialbehandlung Ersetzen einzelner Felder durch Klartexte
/// <summary>
/// Auf besonderen Wunsch einer einzelnen Dame :D
/// </summary>
/// <param name="propertyName">Name des Felds (ohne Klassenname)</param>
/// <param name="value">Aktueller Wert / Wert aus der DB</param>
/// <returns>ggf. ersetzter Wert</returns>
private static string DatabaseEntity_ReportReplacer(string propertyName, string value)
{
if (propertyName.IsNullOrEmpty()) return value;
if (value.IsNullOrEmpty()) return value;
string result = value;
switch(propertyName)
{
case "PackageType":
if (LocalizedLookup.getPackageTypes().ContainsKey(value))
result = string.Format("{0} - {1}", value, LocalizedLookup.getPackageTypes()[value]);
break;
case "PortOfLoading":
case "PortOfDischarge":
case "PoC":
{
string portName = LocodeDB.PortNameFromLocode(value);
if (!portName.IsNullOrEmpty())
{
result = string.Format("{0} - {1}", value, portName);
}
}
break;
default:
break;
}
return result;
}
#endregion

View File

@ -250,6 +250,8 @@ namespace bsmd.ReportGenerator
reportingPartyId = aMessage.ReportingPartyId.Value;
}
}
if (sb.Length > 0) sb.Remove(sb.Length - 1, 1);
string classes = sb.ToString();
if (!classes.IsNullOrEmpty())
{
@ -260,8 +262,8 @@ namespace bsmd.ReportGenerator
Dictionary<string, string> coverInfos = new Dictionary<string, string>();
coverInfos.Add("Ship", DBManager.Instance.GetShipNameFromCore(reportCore));
coverInfos.Add("ETA", reportCore.ETADisplay.ToString());
coverInfos.Add("Port of call", reportCore.PoC);
coverInfos.Add("ETA", reportCore.ETA_NOA_NOD.ToString());
coverInfos.Add("Port of call", reportCore.Portname);
coverInfos.Add("Visit-ID", reportCore.DisplayId);
coverInfos.Add("Class", classes);
@ -278,7 +280,7 @@ namespace bsmd.ReportGenerator
// prepare and send E-Mail with generated attachment
// Schiffsname_ID_Meldeklassen.pdf
string shipName = DBManager.Instance.GetShipNameFromCore(reportCore);
shipName = shipName.Replace(' ', '_');
shipName = shipName.Replace(' ', '_');
string fullPath = string.Format("{0}\\{1}_{2}_{3}.pdf", Properties.Settings.Default.OutputDirectory, shipName, reportCore.DisplayId, classes);
BSMDDocument.RenderDocument(migraDocument, fullPath);

View File

@ -79,6 +79,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\ENI-2\ENI2\ENI2\LocalizedLookup.cs">
<Link>LocalizedLookup.cs</Link>
</Compile>
<Compile Include="..\bsmd.database\Properties\AssemblyProductInfo.cs">
<Link>Properties\AssemblyProductInfo.cs</Link>
</Compile>
@ -88,6 +91,9 @@
<Compile Include="..\bsmd.database\Properties\AssemblyProjectKeyInfo.cs">
<Link>Properties\AssemblyProjectKeyInfo.cs</Link>
</Compile>
<Compile Include="..\bsmd.ExcelReadService\LocodeDB.cs">
<Link>LocodeDB.cs</Link>
</Compile>
<Compile Include="ANSWMessageComparer.cs" />
<Compile Include="BSMDDocument.cs" />
<Compile Include="CrewPasHelper.cs" />
@ -113,6 +119,10 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\misc\db.sqlite">
<Link>db.sqlite</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\misc\report.db">
<Link>report.db</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

View File

@ -155,7 +155,11 @@ namespace bsmd.database
List<MessageCore> result = new List<MessageCore>();
foreach (MessageCore core in cores)
{
this.LoadCustomer(core);
this.LoadETA_ETD(core);
this.LoadSTATShipName(core);
result.Add(core);
}
@ -1106,14 +1110,14 @@ namespace bsmd.database
}
reader.Close();
if (!core.ETA_NOA_NOD.HasValue && !core.IsTransit)
if (!core.ETA_NOA_NOD.HasValue && !core.IsTransit && core.ETA.HasValue)
{
// die Zeit aus MessageCore ist nur ein Datum. Daher verwendet er 00:00 als lokale Zeit, was z.B. nach 01:00 MET zur Anzeige konvertiert wird.
// Das darf in diesem Fall nicht sein, der Wert müsste also gefakt lokal gesetzt werden.. ouch hack
core.ETA_NOA_NOD = DateTime.SpecifyKind(core.ETA.Value, DateTimeKind.Local).ToUniversalTime();
}
if (!core.ETA_NOA_NOD.HasValue && core.IsTransit)
if (!core.ETA_NOA_NOD.HasValue && core.IsTransit && core.ETAKielCanal.HasValue)
{
core.ETA_NOA_NOD = DateTime.SpecifyKind(core.ETAKielCanal.Value, DateTimeKind.Local).ToUniversalTime();
}

View File

@ -24,6 +24,13 @@ namespace bsmd.database
protected string tablename;
private Guid instance_id = Guid.NewGuid(); // Comparison id in case entity has not been saved
#region delegate / events
// Ein etwas hakeliger Mechanismus, damit ein abhängiges Projekt (ReportGenerator) die Werte ersetzen kann ohne dass die ganze Logik
// hier in die Basisklasse muss
public delegate string ReplaceValFunc(string propertyName, string value);
public static event ReplaceValFunc ReportReplacer;
#endregion
#region enum ValidationBlock
public enum ValidationBlock
@ -290,23 +297,40 @@ namespace bsmd.database
foreach (PropertyInfo property in props)
{
bool isDouble = (property.PropertyType == typeof(Nullable<double>));
object propValue = property.GetValue(this, null);
string value = (propValue == null) ? string.Empty : (isDouble ? ((double) propValue).ToString("N2") : propValue.ToString());
string displayName = property.Name;
if(Attribute.IsDefined(property, typeof(ReportDisplayNameAttribute))) {
ReportDisplayNameAttribute reportDisplayNameAttribute = Attribute.GetCustomAttribute(property, typeof(ReportDisplayNameAttribute))
as ReportDisplayNameAttribute;
displayName = reportDisplayNameAttribute.DisplayName;
}
result.Add(new KeyValuePair<string, string>(displayName, value));
}
result.Add(new KeyValuePair<string, string>(displayName, this.GetDisplayValue(property)));
}
return result;
}
}
public virtual string GetDisplayValue(PropertyInfo property)
{
bool isDouble = (property.PropertyType == typeof(Nullable<double>));
object propValue = property.GetValue(this, null);
if (propValue == null) return "";
string value = propValue.ToString();
if(isDouble)
{
value = ((double)propValue).ToString("N2");
}
else
{
if(ReportReplacer != null)
{
value = ReportReplacer(property.Name, value);
}
}
return value;
}
public virtual List<IMessageParagraph> ChildParagraphs { get { return null; } }
#endregion

View File

@ -9,6 +9,7 @@
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Reflection;
namespace bsmd.database
{
@ -26,8 +27,7 @@ namespace bsmd.database
{ }
#region Properties
[ShowReport]
[Validation(ValidationCode.NOT_NULL)]
[ENI2Validation]
public bool? NoDPGOnBoardOnArrival { get; set; }
@ -43,33 +43,30 @@ namespace bsmd.database
[ShowReport]
[ENI2Validation]
public bool? MOUBaltic { get; set; }
[ShowReport]
[ENI2Validation]
public bool? DPGClassificationIMDG { get; set; }
[ShowReport]
[ENI2Validation]
public bool? DPGClassificationIGC { get; set; }
[ShowReport]
[ENI2Validation]
public bool? DPGClassificationIBC { get; set; }
[ShowReport]
[ENI2Validation]
public bool? DPGClassificationIMSBC { get; set; }
[ShowReport]
[ENI2Validation]
public bool? DPGClassificationMARPOL_ANNEX_I { get; set; }
// DK
[ENI2Validation]
[MaxLength(128)]
public string DPGContactFamilyName { get; set; }
// DK
[ENI2Validation]
[MaxLength(64)]
public string DPGContactPhone { get; set; }
public List<DatabaseEntity> IMDGPositions { get { return this.imdgPositions; } }
@ -83,7 +80,6 @@ namespace bsmd.database
public List<DatabaseEntity> MARPOLPositions { get { return this.marpolPositions; } }
// selektor HAZA / HAZD
[ShowReport]
[ENI2Validation]
public bool IsDeparture {
get { return this._isDeparture; }
@ -93,7 +89,6 @@ namespace bsmd.database
/// <summary>
/// No NSW field! Set to determine whether HAZ info should be reported to the NSW
/// </summary>
[ShowReport]
[ENI2Validation]
public string TransmissionType { get; set; }
@ -341,6 +336,14 @@ namespace bsmd.database
#region IMessageParagraph implementation
public override string Title
{
get
{
return this.IsDeparture ? "HAZD" : "HAZA";
}
}
public override string Subtitle
{
get
@ -353,20 +356,61 @@ namespace bsmd.database
{
get
{
List<IMessageParagraph> result = new List<IMessageParagraph>();
foreach (IMessageParagraph imp in this.IMDGPositions)
result.Add(imp);
foreach (IMessageParagraph imp in this.IBCPositions)
result.Add(imp);
foreach (IMessageParagraph imp in this.IGCPositions)
result.Add(imp);
foreach (IMessageParagraph imp in this.IMSBCPositions)
result.Add(imp);
foreach (IMessageParagraph imp in this.MARPOLPositions)
result.Add(imp);
return result;
List<IMessageParagraph> allChildParagraphs = new List<IMessageParagraph>();
if(this.IMDGPositions.Count > 0)
{
MessageParagraph containerParagraph = new MessageParagraph();
containerParagraph.Title = "IMDGPositions";
List<IMessageParagraph> sublist = new List<IMessageParagraph>();
foreach (IMessageParagraph imp in this.IMDGPositions)
containerParagraph.ChildParagraphs.Add(imp);
allChildParagraphs.Add(containerParagraph);
}
if(this.IBCPositions.Count > 0)
{
MessageParagraph containerParagraph = new MessageParagraph();
containerParagraph.Title = "IBCPositions";
List<IMessageParagraph> sublist = new List<IMessageParagraph>();
foreach (IMessageParagraph imp in this.IBCPositions)
containerParagraph.ChildParagraphs.Add(imp);
allChildParagraphs.Add(containerParagraph);
}
if(this.IGCPositions.Count > 0)
{
MessageParagraph containerParagraph = new MessageParagraph();
containerParagraph.Title = "IGCPositions";
List<IMessageParagraph> sublist = new List<IMessageParagraph>();
foreach (IMessageParagraph imp in this.IGCPositions)
containerParagraph.ChildParagraphs.Add(imp);
allChildParagraphs.Add(containerParagraph);
}
if(this.IMSBCPositions.Count > 0)
{
MessageParagraph containerParagraph = new MessageParagraph();
containerParagraph.Title = "IMSBCPositions";
List<IMessageParagraph> sublist = new List<IMessageParagraph>();
foreach (IMessageParagraph imp in this.IMSBCPositions)
containerParagraph.ChildParagraphs.Add(imp);
allChildParagraphs.Add(containerParagraph);
}
if(this.MARPOLPositions.Count > 0)
{
MessageParagraph containerParagraph = new MessageParagraph();
containerParagraph.Title = "MARPOLPositions";
List<IMessageParagraph> sublist = new List<IMessageParagraph>();
foreach (IMessageParagraph imp in this.MARPOLPositions)
containerParagraph.ChildParagraphs.Add(imp);
allChildParagraphs.Add(containerParagraph);
}
return allChildParagraphs;
}
}
}
#endregion

View File

@ -11,7 +11,7 @@ using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
namespace bsmd.database
{
@ -62,12 +62,13 @@ namespace bsmd.database
[ENI2Validation]
public string ProductName { get; set; }
[ShowReport]
[Validation(ValidationCode.NOT_NULL)]
[ENI2Validation]
public byte? PollutionCategory { get; set; }
[ShowReport]
[ReportDisplayName("PollutionCategory")]
public string PollutionCategoryDisplay
{
get
@ -77,11 +78,12 @@ namespace bsmd.database
return "";
}
}
[ShowReport]
[ENI2Validation]
public byte? Hazards { get; set; }
[ShowReport]
[ReportDisplayName("Hazards")]
public string HazardsDisplay
{
get
@ -91,12 +93,13 @@ namespace bsmd.database
return "";
}
}
[ShowReport]
[Validation(ValidationCode.NOT_NULL)]
[ENI2Validation]
public byte? FlashpointInformation { get; set; }
[ShowReport]
[ReportDisplayName("FlashpointInformation")]
public string FlashpointInformationDisplay
{
get
@ -148,7 +151,7 @@ namespace bsmd.database
public string SublistCollectionKey { get { return "ibc"; } }
#endregion
#endregion
#region DatabaseEntity implementation

View File

@ -50,8 +50,7 @@ namespace bsmd.database
[MaxLength(10)]
[ENI2Validation]
public string IMOClass { get; set; }
[ShowReport]
[MaxLength(10)]
[ENI2Validation]
public string CompatibilityGroup { get; set; }
@ -157,14 +156,17 @@ namespace bsmd.database
[ENI2Validation]
public string StowagePosition { get; set; }
[ShowReport]
[MaxLength(5)]
[ENI2Validation]
public string Bay { get; set; }
[ShowReport]
[MaxLength(5)]
[ENI2Validation]
public string Row { get; set; }
[ShowReport]
[MaxLength(5)]
[ENI2Validation]
public string Tier { get; set; }

View File

@ -1,4 +1,7 @@
using System;
// Copyright (c) 2015-2017 schick Informatik
// Description: Abstraktion für Report / Druckerzeugung..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -23,4 +26,46 @@ namespace bsmd.database
List<IMessageParagraph> ChildParagraphs { get; }
}
/// <summary>
/// Dummy Container class implementation for sublist display purposes
/// </summary>
public class MessageParagraph : IMessageParagraph
{
private List<IMessageParagraph> childParagraphs = new List<IMessageParagraph>();
private List<KeyValuePair<string, string>> messageText = new List<KeyValuePair<string, string>>();
public List<IMessageParagraph> ChildParagraphs
{
get
{
return childParagraphs;
}
}
public List<KeyValuePair<string, string>> MessageText
{
get
{
return messageText;
}
}
public bool ShowChildrenAsTable
{
get; set;
}
public string Subtitle
{
get; set;
}
public string Title
{
get; set;
}
}
}

View File

@ -31,12 +31,13 @@ namespace bsmd.database
[MaxLength(255)]
[ENI2Validation]
public string Name { get; set; }
[ShowReport]
[Validation(ValidationCode.NOT_NULL)]
[ENI2Validation]
public byte? FlashpointInformation { get; set; }
[ShowReport]
[ReportDisplayName("FlashpointInformation")]
public string FlashpointInformationDisplay
{
get

View File

@ -2,6 +2,6 @@
[assembly: AssemblyCompany("schick Informatik")]
[assembly: AssemblyProduct("BSMD NSW interface")]
[assembly: AssemblyInformationalVersion("3.8.5")]
[assembly: AssemblyInformationalVersion("3.8.7")]
[assembly: AssemblyCopyright("Copyright © 2014-2017 schick Informatik")]
[assembly: AssemblyTrademark("")]

View File

@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("3.8.5.*")]
[assembly: AssemblyVersion("3.8.7.*")]

View File

@ -56,13 +56,7 @@ namespace bsmd.database
{
bool? result = null;
message = "";
bool conditionResult = false;
// Aus der List an Messages muss (irgendwie :-) ein Dictionary aufgebaut werden, mit dem man aus den Namen der Fieldnames auf
// den Wert bzw. die Liste an Werten (bei Listenklassen) kommt. Das ValidationField "weiß" schon ob es eine Listenklasse ist.
// das hier muss noch früher rein damit es nicht für jede Regel erneut erzeugt wird
ValidationRule.PrepareNameLookupDict(core, messages);
bool conditionResult = false;
try
{
@ -184,6 +178,7 @@ namespace bsmd.database
#endregion
#region field evaluation
private bool Evaluate(MessageCore core, List<Message> messages, out ValidationField failedField)
{
@ -194,31 +189,46 @@ namespace bsmd.database
{
// den Wert aus der Nachrichtenklasse lesen
ValidationField aValField = ValidationRule.ValidationFieldDict[this.FieldName];
// object value = aValField.PropertyInfo.GetValue()
if(aValField.IsInListType)
{
List<object> vals = ValidationRule.GetValueListFromData(aValField);
// TODO: Wie melden wir hier "Listenposition 1+3 ok, aber 2 falsch" zurück?
}
else
{
object val = ValidationRule.GetValueFromData(aValField);
switch (this.ConditionOperator)
{
case ConditionOperatorEnum.EQUAL:
result = val.ToString().Equals(this.Value);
break;
case ConditionOperatorEnum.NOT_EQUAL:
result = !val.ToString().Equals(this.Value);
break;
case ConditionOperatorEnum.LESS:
//result = val.ToString() < this.Value;
break;
case ConditionOperatorEnum.GREATER:
break;
case ConditionOperatorEnum.NULL:
result = (val == null);
break;
case ConditionOperatorEnum.NOT_NULL:
result = (val != null);
break;
}
}
// check type and evaluate with operator (local prop)
switch (this.ConditionOperator)
{
case ConditionOperatorEnum.EQUAL:
break;
case ConditionOperatorEnum.NOT_EQUAL:
break;
case ConditionOperatorEnum.LESS:
break;
case ConditionOperatorEnum.GREATER:
break;
case ConditionOperatorEnum.NULL:
break;
case ConditionOperatorEnum.NOT_NULL:
break;
}
// if failed set failedField to aValField
@ -229,6 +239,7 @@ namespace bsmd.database
return result;
}
#endregion
#region hier ist das alte audius Zeugs
@ -481,6 +492,7 @@ namespace bsmd.database
}
public string PropertyName { get; set; }
public string NotificationClassText { get; set; }
public Message.NotificationClass? NotificationClass { get; set; }
@ -489,6 +501,11 @@ namespace bsmd.database
public PropertyInfo PropertyInfo { get { return _info; } }
/// <summary>
/// Hilfsfeld um bei Gefahrgutpositionen HAZA/HAZD auseinanderzuhalten
/// </summary>
public string ExtraInfo { get; set; }
public string FullName
{
get { return this.ToString(); }

View File

@ -7,14 +7,18 @@ using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using log4net;
namespace bsmd.database
{
public class ValidationRule : DatabaseEntity
{
private static ILog _log = LogManager.GetLogger("ValidationRule");
private static List<ValidationField> _validationFields = null;
private static Dictionary<string, ValidationField> _validationFieldDict = null;
private static Dictionary<string, object> _lookupDict = null;
private static Dictionary<ValidationField, object> _lookupDict = new Dictionary<ValidationField, object>();
private static Dictionary<ValidationField, List<object>> _lookupListDict = new Dictionary<ValidationField, List<object>>();
public ValidationRule()
{
@ -60,19 +64,28 @@ namespace bsmd.database
_validationFields.AddRange(GetFieldsForClass(typeof(BRKA), true, Message.NotificationClass.BKRA));
_validationFields.AddRange(GetFieldsForClass(typeof(BRKD), true, Message.NotificationClass.BKRD));
_validationFields.AddRange(GetFieldsForClass(typeof(BPOL), false, Message.NotificationClass.BPOL));
_validationFields.AddRange(GetFieldsForClass(typeof(CallPurpose), false, null));
_validationFields.AddRange(GetFieldsForClass(typeof(CallPurpose), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(CREW), true, Message.NotificationClass.CREW));
_validationFields.AddRange(GetFieldsForClass(typeof(Customer), false, null));
_validationFields.AddRange(GetFieldsForClass(typeof(HAZ), false, Message.NotificationClass.HAZA));
_validationFields.AddRange(GetFieldsForClass(typeof(IBCPosition), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(IGCPosition), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(IMDGPosition), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(IMSBCPosition), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(IBCPosition), true, null, "HAZA"));
_validationFields.AddRange(GetFieldsForClass(typeof(IGCPosition), true, null, "HAZA"));
_validationFields.AddRange(GetFieldsForClass(typeof(IMDGPosition), true, null, "HAZA"));
_validationFields.AddRange(GetFieldsForClass(typeof(IMSBCPosition), true, null, "HAZA"));
_validationFields.AddRange(GetFieldsForClass(typeof(MARPOL_Annex_I_Position), true, null, "HAZA"));
_validationFields.AddRange(GetFieldsForClass(typeof(HAZ), false, Message.NotificationClass.HAZD));
_validationFields.AddRange(GetFieldsForClass(typeof(IBCPosition), true, null, "HAZD"));
_validationFields.AddRange(GetFieldsForClass(typeof(IGCPosition), true, null, "HAZD"));
_validationFields.AddRange(GetFieldsForClass(typeof(IMDGPosition), true, null, "HAZD"));
_validationFields.AddRange(GetFieldsForClass(typeof(IMSBCPosition), true, null, "HAZD"));
_validationFields.AddRange(GetFieldsForClass(typeof(MARPOL_Annex_I_Position), true, null, "HAZD"));
_validationFields.AddRange(GetFieldsForClass(typeof(InfectedArea), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(INFO), false, Message.NotificationClass.INFO));
_validationFields.AddRange(GetFieldsForClass(typeof(LADG), true, Message.NotificationClass.LADG));
_validationFields.AddRange(GetFieldsForClass(typeof(LastTenPortFacilitiesCalled), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(MARPOL_Annex_I_Position), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(LastTenPortFacilitiesCalled), true, null));
_validationFields.AddRange(GetFieldsForClass(typeof(MDH), false, Message.NotificationClass.MDH));
_validationFields.AddRange(GetFieldsForClass(typeof(NAME), false, Message.NotificationClass.NAME));
_validationFields.AddRange(GetFieldsForClass(typeof(NOA_NOD), false, Message.NotificationClass.NOA_NOD));
@ -121,7 +134,11 @@ namespace bsmd.database
public static Dictionary<string, ValidationField> ValidationFieldDict { get { return _validationFieldDict; } }
private static List<ValidationField> GetFieldsForClass(Type objType, bool isList, Message.NotificationClass? notificationClass)
#endregion
#region private static
private static List<ValidationField> GetFieldsForClass(Type objType, bool isList, Message.NotificationClass? notificationClass, string extraInfo = null)
{
List<ValidationField> result = new List<ValidationField>();
@ -135,44 +152,208 @@ namespace bsmd.database
vField.PropertyName = property.Name;
vField.IsInListType = isList;
vField.NotificationClass = notificationClass;
vField.ExtraInfo = extraInfo;
result.Add(vField);
}
return result;
}
/// <summary>
/// Hilfsmethode, die eine Liste von object der untergeordneten Listenklasse zurückliefert. Da es hier verschiedene Ebene/Namen etc. gibt
/// wird das einfach über den NotificationClassText aufgelöst, der beim Erzeugen der ValidationFields angelegt wird (aus dem Klassennamen)
/// Da nicht klar ist in welcher Meldeklasse das Objekt steckt ist das hier der Einfachheit halber fest verdrahtet
/// </summary>
private static List<object> GetListForSublistField(ValidationField field, Dictionary<Message.NotificationClass, Message> messageDict)
{
List<object> result = null;
switch(field.NotificationClassText)
{
case "CallPurpose":
{
NOA_NOD nn = messageDict[Message.NotificationClass.NOA_NOD].Elements[0] as NOA_NOD;
result = nn.CallPurposes.Cast<object>().ToList();
break;
}
case "IBCPosition":
{
HAZ haz = (field.ExtraInfo == "HAZA") ? (messageDict[Message.NotificationClass.HAZA].Elements[0] as HAZ) : (messageDict[Message.NotificationClass.HAZD].Elements[0] as HAZ);
result = haz.IBCPositions.Cast<object>().ToList();
break;
}
case "IGCPosition":
{
HAZ haz = (field.ExtraInfo == "HAZA") ? (messageDict[Message.NotificationClass.HAZA].Elements[0] as HAZ) : (messageDict[Message.NotificationClass.HAZD].Elements[0] as HAZ);
result = haz.IGCPositions.Cast<object>().ToList();
break;
}
case "IMDGPosition":
{
HAZ haz = (field.ExtraInfo == "HAZA") ? (messageDict[Message.NotificationClass.HAZA].Elements[0] as HAZ) : (messageDict[Message.NotificationClass.HAZD].Elements[0] as HAZ);
result = haz.IMDGPositions.Cast<object>().ToList();
break;
}
case "IMSBCPosition":
{
HAZ haz = (field.ExtraInfo == "HAZA") ? (messageDict[Message.NotificationClass.HAZA].Elements[0] as HAZ) : (messageDict[Message.NotificationClass.HAZD].Elements[0] as HAZ);
result = haz.IMSBCPositions.Cast<object>().ToList();
break;
}
case "MARPOL_Annex_I_Position":
{
HAZ haz = (field.ExtraInfo == "HAZA") ? (messageDict[Message.NotificationClass.HAZA].Elements[0] as HAZ) : (messageDict[Message.NotificationClass.HAZD].Elements[0] as HAZ);
result = haz.MARPOLPositions.Cast<object>().ToList();
break;
}
case "InfectedArea":
{
MDH mdh = messageDict[Message.NotificationClass.MDH].Elements[0] as MDH;
result = mdh.InfectedAreas.Cast<object>().ToList();
break;
}
case "SanitaryMeasuresDetail":
{
MDH mdh = messageDict[Message.NotificationClass.MDH].Elements[0] as MDH;
result = mdh.SanitaryMeasuresDetails.Cast<object>().ToList();
break;
}
case "PortOfCallLast30Days":
{
MDH mdh = messageDict[Message.NotificationClass.MDH].Elements[0] as MDH;
result = mdh.PortOfCallLast30Days.Cast<object>().ToList();
break;
}
case "StowawaysJoiningLocation":
{
MDH mdh = messageDict[Message.NotificationClass.MDH].Elements[0] as MDH;
result = mdh.StowawaysJoiningLocations.Cast<object>().ToList();
break;
}
case "LastTenPortFacilitiesCalled":
{
SEC sec = messageDict[Message.NotificationClass.SEC].Elements[0] as SEC;
result = sec.LastTenPortFacilitesCalled.Cast<object>().ToList();
break;
}
case "ShipToShipActivitiesDuringLastTenPortFacilitiesCalled":
{
SEC sec = messageDict[Message.NotificationClass.SEC].Elements[0] as SEC;
result = sec.ShipToShipActivitiesDuringLastTenPortFacilitiesCalled.Cast<object>().ToList();
break;
}
case "Waste":
{
WAS was = messageDict[Message.NotificationClass.WAS].Elements[0] as WAS;
result = was.Waste.Cast<object>().ToList();
break;
}
case "WasteDisposalServiceProvider":
{
WAS was = messageDict[Message.NotificationClass.WAS].Elements[0] as WAS;
result = was.WasteDisposalServiceProvider.Cast<object>().ToList();
break;
}
case "PortOfItinerary":
{
BPOL bpol = messageDict[Message.NotificationClass.BPOL].Elements[0] as BPOL;
result = bpol.PortOfItineraries.Cast<object>().ToList();
break;
}
default:
_log.WarnFormat("unknown list class {0}", field.NotificationClassText);
break;
}
return result;
}
#endregion
#region public static methods
public static object GetValueFromData(ValidationField field, Dictionary<string,Message> dataDict)
{
// hier könnte auch ein List<object> rauskommen bzw. ein Dict<Identifier,object> mit Werten..
public static object GetValueFromData(ValidationField field)
{
if (_lookupDict.ContainsKey(field))
return field.PropertyInfo.GetValue(_lookupDict[field]);
return null;
}
public static List<object> GetValueListFromData(ValidationField field)
{
List<object> result = new List<object>();
if(_lookupListDict.ContainsKey(field))
{
foreach (object o in _lookupListDict[field])
result.Add(field.PropertyInfo.GetValue(o));
}
return result;
}
public static void PrepareNameLookupDict(MessageCore core, List<Message> messages)
{
if(_lookupDict == null) _lookupDict = new Dictionary<string, object>();
_lookupDict.Clear();
foreach(Message message in messages)
_lookupListDict.Clear();
Dictionary<Message.NotificationClass, Message> messageLookup = new Dictionary<Message.NotificationClass, Message>();
foreach (Message message in messages)
{
messageLookup.Add(message.MessageNotificationClass, message);
}
try
{
// Das kann nicht richtig funktionieren da ich hier eigentlich AGNT und nicht Message mappen will :-(
_lookupDict[message.MessageNotificationClassDisplay] = message;
Type t = message.GetType();
foreach(Type intfType in t.GetInterfaces())
foreach (ValidationField field in _validationFields)
{
if(intfType == typeof(ISublistContainer))
System.Diagnostics.Trace.WriteLine("ISublistContainer: " + message.MessageNotificationClassDisplay);
}
if (!field.IsInListType)
{
if (field.NotificationClass.HasValue)
{
_lookupDict.Add(field, messageLookup[field.NotificationClass.Value].Elements[0]);
}
else
{
// "fixed" type wie Core / Customer usw.
switch(field.NotificationClassText)
{
case "Customer":
_lookupDict.Add(field, core.Customer);
break;
case "MessageCore":
_lookupDict.Add(field, core);
break;
case "ReportingParty":
_lookupDict.Add(field, DBManager.Instance.GetReportingPartyDict()[core.DefaultReportingPartyId.Value]);
break;
default:
_log.WarnFormat("Unknown class type {0}", field.NotificationClassText);
break;
}
}
}
else
{
if (field.NotificationClass.HasValue)
{
// Feld gehört zu einer Liste auf "Top-Level" Ebene
_lookupListDict.Add(field, messageLookup[field.NotificationClass.Value].Elements.Cast<object>().ToList());
}
else
{
// Feld gehört zu einer untergeordneten Liste
// Trickster: Komplizierte Logik vermeiden und den Namen statisch hinterlegen?
_lookupListDict.Add(field, GetListForSublistField(field, messageLookup));
}
}
}
}
catch(Exception ex)
{
_log.ErrorFormat("Error preparing lookup dict: {0}", ex.Message);
}
}

View File

@ -344,6 +344,52 @@ namespace bsmd.database
return result;
}
/// <summary>
/// Convenience Methode, die fehlende Waste Einträge ergänzt. Verbesserte Version, aus ENI-2 herüberkopiert, damit es auch im
/// Excel_Reader nutzbar wird
/// </summary>
public void AddMissingWaste()
{
foreach (int wasteCode in WAS.DKWasteCodes)
{
Waste foundWaste = null;
foreach (Waste waste in this.Waste)
{
if (waste.WasteType.HasValue && waste.WasteType.Value == wasteCode)
{
foundWaste = waste;
break;
}
}
if (foundWaste == null)
{
Waste newWaste = new Waste();
newWaste.Identifier = DatabaseEntity.GetNewIdentifier(this.Waste);
newWaste.WAS = this;
newWaste.WasteAmountGeneratedTillNextPort_MTQ = 0;
newWaste.WasteAmountRetained_MTQ = 0;
newWaste.WasteCapacity_MTQ = 0;
newWaste.WasteDescription = (wasteCode == 1300) ? "-" : "";
newWaste.WasteDisposalAmount_MTQ = 0;
newWaste.WasteDisposalPort = "ZZUKN";
newWaste.WasteDisposedAtLastPort_MTQ = 0;
newWaste.WasteType = wasteCode;
this.Waste.Add(newWaste);
}
else
{
if (!foundWaste.WasteAmountGeneratedTillNextPort_MTQ.HasValue) foundWaste.WasteAmountGeneratedTillNextPort_MTQ = 0;
if (!foundWaste.WasteAmountRetained_MTQ.HasValue) foundWaste.WasteAmountRetained_MTQ = 0;
if (!foundWaste.WasteCapacity_MTQ.HasValue) foundWaste.WasteCapacity_MTQ = 0;
if ((wasteCode == 1300) && foundWaste.WasteDescription.IsNullOrEmpty()) foundWaste.WasteDescription = "-";
if (!foundWaste.WasteDisposalAmount_MTQ.HasValue) foundWaste.WasteDisposalAmount_MTQ = 0;
if (foundWaste.WasteDisposalPort.IsNullOrEmpty()) foundWaste.WasteDisposalPort = "ZZUKN";
if (!foundWaste.WasteDisposedAtLastPort_MTQ.HasValue) foundWaste.WasteDisposedAtLastPort_MTQ = 0;
}
}
}
#endregion
}

View File

@ -94,14 +94,17 @@ namespace bsmd.dbh
aMessage.SendSuccess = true;
DBManager.Instance.Save(aMessage.MessageCore);
break;
case dbh.response.RootType.RESET:
if ((ReportingClassesResetted != null) && (ReportingClassesResetted.Count > 0) &&
(int) ReportingClassesResetted[0] .ReportingClass[0] == (int)aMessage.MessageNotificationClass)
{
aMessage.Reset = true;
aMessage.SendSuccess = false; // zurücksetzen des "grünen Punkts" im ENI-2
aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED;
}
case dbh.response.RootType.RESET:
// Die Liste ist auch bei erfolgtem RESET offenbar immer NULL...
//if ((ReportingClassesResetted != null) && (ReportingClassesResetted.Count > 0))
// das Mapping stimmt bei uns natürlich so nicht, aber da die Nachrichten einzeln gehen sollte es trotzdem funktionieren
// (int) ReportingClassesResetted[0].ReportingClass[0] == (int)aMessage.MessageNotificationClass)
//{
//_log.InfoFormat("RESET response received for {0}", ReportingClassesResetted[0].ReportingClass[0]);
aMessage.Reset = true;
aMessage.SendSuccess = false; // zurücksetzen des "grünen Punkts" im ENI-2
aMessage.InternalStatus = Message.BSMDStatus.CONFIRMED;
//}
break;
case dbh.response.RootType.DATA:
if((ReportingClassesFull != null) && (ReportingClassesFull.Count > 0) &&

Binary file not shown.

BIN
nsw/Störfälle.xlsx Normal file

Binary file not shown.