NSW 6.0 / PO Service aktueller Zwischenstand

This commit is contained in:
Daniel Schick 2020-03-05 05:59:33 +00:00
parent 3bb8fcc396
commit 32823a0c07
23 changed files with 562 additions and 126 deletions

View File

@ -0,0 +1,56 @@
<UserControl x:Class="ENI2.Controls.POListControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:util="clr-namespace:ENI2.Util"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:p="clr-namespace:ENI2.Properties"
xmlns:local="clr-namespace:ENI2.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<col:ArrayList x:Key="arrList">
<col:DictionaryEntry Key="None" Value="0" />
<col:DictionaryEntry Key="Maersk BHV" Value="1" />
<col:DictionaryEntry Key="SeaGo BHV" Value="2" />
<col:DictionaryEntry Key="SeaGo WHV" Value="4" />
</col:ArrayList>
</UserControl.Resources>
<GroupBox Name="groupBoxRP" Header="{x:Static p:Resources.textPOLists}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="Calendar week" />
<xctk:DoubleUpDown x:Name="doubleUpDownCalendarWeek" VerticalContentAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Stretch" Margin="2" Value="01" ValueChanged="doubleUpDownCalendarWeek_ValueChanged"/>
<Label Content="Type" />
<ComboBox x:Name="comboBoxFilterType" Margin="2" SelectionChanged="comboBoxFilterType_SelectionChanged" Width="100" />
<Button x:Name="buttonExcelExport" Margin="2" Click="buttonExcelExport_Click" Content="Export Excel" Width="100" />
<Button x:Name="buttonSaveChanges" Margin="2" Click="buttonSaveChanges_Click" Content="Save changes" Width="100" IsEnabled="False" />
</StackPanel>
<local:ENIDataGrid Grid.Row="1" Margin="2,8,2,2" x:Name="dataGridPOCores" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
SelectionMode="Single" AutoGenerateColumns="False" CellEditEnding="dataGridPOCores_CellEditEnding" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="IMO/ENI" Binding="{Binding IMOENIDisplay}" IsReadOnly="True" />
<DataGridTextColumn x:Name="gridColumnPONumber" Header="PO number" Binding="{Binding PONumber, Mode=TwoWay}" IsReadOnly="False" />
<DataGridComboBoxColumn x:Name="gridColumnGroup" Header="Group" IsReadOnly="False" SelectedValueBinding="{Binding Flags, Mode=TwoWay}"
ItemsSource="{StaticResource arrList}" DisplayMemberPath="Key" SelectedValuePath="Value">
</DataGridComboBoxColumn>
<DataGridTextColumn Header="Ship name" Binding="{Binding Shipname}" IsReadOnly="True" />
<DataGridTextColumn Header="ETA" Binding="{Binding ETA_NOA_NOD, StringFormat=\{0:dd.MM.yyyy HH:mm\}, Converter={util:UtcToLocalDateTimeConverter}}" IsReadOnly="True" />
<DataGridTextColumn Header="ETD" Binding="{Binding ETD_NOA_NOD, StringFormat=\{0:dd.MM.yyyy HH:mm\}, Converter={util:UtcToLocalDateTimeConverter}}" IsReadOnly="True" />
<DataGridTextColumn Header="ATA" Binding="{Binding ATA, StringFormat=\{0:dd.MM.yyyy HH:mm\}, Converter={util:UtcToLocalDateTimeConverter}}" IsReadOnly="True" />
<DataGridTextColumn Header="ATD" Binding="{Binding ATD, StringFormat=\{0:dd.MM.yyyy HH:mm\}, Converter={util:UtcToLocalDateTimeConverter}}" IsReadOnly="True" />
<DataGridTextColumn Header="Hafen" Binding="{Binding PortnameDisplay}" IsReadOnly="True" />
<DataGridTextColumn Header="Id" Binding="{Binding DisplayId}" IsReadOnly="True" />
</DataGrid.Columns>
</local:ENIDataGrid>
</Grid>
</GroupBox>
</UserControl>

View File

@ -0,0 +1,156 @@
// Copyright (c) 2017 schick Informatik
// Description: PO Nummer Übersicht. Ergänzung Nummern. Excel Export
//
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using bsmd.database;
namespace ENI2.Controls
{
/// <summary>
/// Interaction logic for POListControl.xaml
/// </summary>
public partial class POListControl : UserControl
{
#region Fields
private readonly string[] _comboBoxEntries =
{
"All",
"Maersk BHV",
"SeaGo BHV",
"SeaGo WHV"
};
private List<MessageCore> searchResult = new List<MessageCore>();
private readonly List<MessageCore> filteredResult = new List<MessageCore>();
#endregion
#region Construction
public POListControl()
{
InitializeComponent();
Loaded += POList_Loaded;
}
#endregion
#region control event handler
private void POList_Loaded(object sender, RoutedEventArgs e)
{
this.comboBoxFilterType.ItemsSource = this._comboBoxEntries;
this.doubleUpDownCalendarWeek.Value = bsmd.database.Util.GetIso8601WeekOfYear(DateTime.Now);
this.dataGridPOCores.ItemsSource = this.filteredResult;
}
private void buttonExcelExport_Click(object sender, RoutedEventArgs e)
{
}
private void buttonSaveChanges_Click(object sender, RoutedEventArgs e)
{
foreach(MessageCore messageCore in this.filteredResult)
{
if (messageCore.IsDirty)
{
DBManager.Instance.Save(messageCore);
messageCore.IsDirty = false;
}
}
this.buttonSaveChanges.IsEnabled = false;
}
private void doubleUpDownCalendarWeek_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if (!this.IsLoaded) return;
this.comboBoxFilterType.SelectedIndex = -1;
this.PerformSearch();
}
private void comboBoxFilterType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.dataGridPOCores.ItemsSource = null;
if (this.comboBoxFilterType.SelectedIndex == -1) return;
this.filteredResult.Clear();
foreach (MessageCore core in this.searchResult)
{
switch (this.comboBoxFilterType.SelectedIndex)
{
case 0: this.filteredResult.Add(core); break;
case 1: if (core.IsFlagSet(MessageCore.CoreFlags.MAERSK_BHV)) this.filteredResult.Add(core); break;
case 2: if (core.IsFlagSet(MessageCore.CoreFlags.SEAGO_BHV)) this.filteredResult.Add(core); break;
case 3: if (core.IsFlagSet(MessageCore.CoreFlags.SEAGO_WHV)) this.filteredResult.Add(core); break;
}
}
this.dataGridPOCores.ItemsSource = this.filteredResult;
}
private void dataGridPOCores_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
if (e.Column == gridColumnPONumber)
{
// validate for "true" number
var el = e.EditingElement as TextBox;
if (!el.Text.IsDigitsOnly())
{
el.Text = string.Empty;
e.Cancel = true;
}
else
{
buttonSaveChanges.IsEnabled = true;
MessageCore editedCore = this.filteredResult[e.Row.GetIndex()];
editedCore.IsDirty = true;
}
}
}
}
#endregion
#region private methods
private void PerformSearch()
{
this.filteredResult.Clear();
if (!this.doubleUpDownCalendarWeek.Value.HasValue) return;
Dictionary<MessageCore.SearchFilterType, string> filterDict = new Dictionary<MessageCore.SearchFilterType, string>();
DateTime start = bsmd.database.Util.FirstDateOfWeekISO8601(DateTime.Now.Year, (int)this.doubleUpDownCalendarWeek.Value);
DateTime end = start.Add(new TimeSpan(6, 23, 59, 59));
uint from = start.ToUniversalTime().ToUnixTimeStamp();
uint to = end.ToUniversalTime().ToUnixTimeStamp();
filterDict.Add(MessageCore.SearchFilterType.FILTER_ETA, string.Format("{0}:{1}", from.ToString() ?? "", to.ToString() ?? ""));
Util.UIHelper.SetBusyState();
// suche auslösen
this.searchResult = DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).GetMessageCoresWithFilters(filterDict);
// alle anderen Häfen weg
this.searchResult.RemoveAll(item => (!item.PoC.Equals("DEBRV") && !item.PoC.Equals("DEWHV")));
this.dataGridPOCores.SelectedItem = null;
this.filteredResult.AddRange(searchResult);
}
#endregion
}
}

View File

@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p="clr-namespace:ENI2.Properties"
xmlns:p="clr-namespace:ENI2.Properties"
xmlns:util="clr-namespace:ENI2.Util"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:local="clr-namespace:ENI2.Controls"

View File

@ -34,8 +34,8 @@
<MinimumRequiredVersion>5.4.0.0</MinimumRequiredVersion>
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>publish.html</WebPage>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>6.0.2.%2a</ApplicationVersion>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>6.0.5.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted>
@ -167,6 +167,9 @@
<Compile Include="Controls\LocodeControl.xaml.cs">
<DependentUpon>LocodeControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\POListControl.xaml.cs">
<DependentUpon>POListControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\ReportingPartyControl.xaml.cs">
<DependentUpon>ReportingPartyControl.xaml</DependentUpon>
</Compile>
@ -362,6 +365,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\POListControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\ReportingPartyControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -76,7 +76,7 @@
<RadioButton Grid.Column="3" x:Name="buttonNotifications" Content="{x:Static p:Resources.textNotifications}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto" Click="radioButton_Click" Background="Transparent" Margin="2,5,0,0" IsChecked="True" />
<RadioButton Grid.Column="4" x:Name="buttonStatus" Content="{x:Static p:Resources.textServerStatus}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto" Click="radioButton_Click" Background="Transparent" Margin="2,5,0,0" />
<RadioButton Grid.Column="5" x:Name="buttonUserAdmin" Content="{x:Static p:Resources.textUserAdministration}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto" Click="radioButton_Click" Background="Transparent" Visibility="Hidden" Margin="2,5,0,0"/>
<RadioButton Grid.Column="6" x:Name="buttonEditRules" Content="{x:Static p:Resources.textEditRules}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto" Click="radioButton_Click" Background="Transparent" Visibility="Hidden" Margin="2,5,0,0" />
<RadioButton Grid.Column="6" x:Name="buttonPOListe" Content="{x:Static p:Resources.textPOLists}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto" Click="radioButton_Click" Background="Transparent" Visibility="Hidden" Margin="2,5,0,0" />
<Button Grid.Column="7" x:Name="buttonAbout" Content="?" HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" Margin="2" Padding="5,0,5,0" Click="buttonAbout_Click"/>
</Grid>

View File

@ -35,7 +35,7 @@ namespace ENI2
#region Fields
private ReportingPartyControl rpControl;
private RuleControl ruleControl;
private POListControl poControl;
private ServerStatusControl statusControl;
private readonly SucheControl sucheControl;
@ -266,15 +266,13 @@ namespace ENI2
}
this.rootContainer.Children.Add(this.rpControl);
}
else if(sender == this.buttonEditRules)
else if(sender == this.buttonPOListe)
{
if (this.ruleControl == null)
if (this.poControl == null)
{
this.ruleControl = new RuleControl();
this.ruleControl.UserEntity = this.userEntity;
this.ruleControl.ValidationRules = DBManager.Instance.GetValidationRules();
this.poControl = new POListControl();
}
this.rootContainer.Children.Add(ruleControl);
this.rootContainer.Children.Add(poControl);
}
else if(sender == this.buttonStatus)
{
@ -547,8 +545,7 @@ namespace ENI2
return;
}
ReportingParty.LogonResult logonResult = ReportingParty.Login(this.textUsername.Text, this.textPassword.Password, out this.userEntity);
switch(logonResult)
switch(ReportingParty.Login(this.textUsername.Text, this.textPassword.Password, out this.userEntity))
{
case ReportingParty.LogonResult.OK:
@ -559,8 +556,8 @@ namespace ENI2
if (this.userEntity.IsAdmin)
{
this.buttonUserAdmin.Visibility = Visibility.Visible;
this.sucheControl.AdminMode = true;
// this.buttonEditRules.Visibility = Visibility.Visible; // wird aktuell doch nicht so umgesetzt
this.buttonPOListe.Visibility = Visibility.Visible;
this.sucheControl.AdminMode = true;
}
break;
case ReportingParty.LogonResult.FAILED:

View File

@ -3449,6 +3449,15 @@ namespace ENI2.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to PO numbers.
/// </summary>
public static string textPOLists {
get {
return ResourceManager.GetString("textPOLists", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pollution category.
/// </summary>

View File

@ -1711,4 +1711,7 @@
<data name="textIMOHazardClass" xml:space="preserve">
<value>IMO hazard class (Group)</value>
</data>
<data name="textPOLists" xml:space="preserve">
<value>PO numbers</value>
</data>
</root>

Binary file not shown.

View File

@ -9,7 +9,8 @@
<xs:element name="DPGManifestOnBoardOnArrival" type="yorn-type" minOccurs="0"/>
<xs:element name="INFShipClass" type="infclass-type" minOccurs="0"/>
<xs:element name="MOUBaltic" type="y-type" minOccurs="0"/>
<xs:element name="DPGOnArrival" type="dglist"/>
<!-- neu in NSW V6.0 DPGOnArrival vereinfachung zu DPG -->
<xs:element name="DPG" type="dglist"/>
</xs:sequence>
</xs:choice>
</xs:complexType>
@ -21,7 +22,8 @@
<xs:element name="DPGManifestOnBoardOnDeparture" type="yorn-type" minOccurs="0"/>
<xs:element name="INFShipClass" type="infclass-type" minOccurs="0"/>
<xs:element name="MOUBaltic" type="y-type" minOccurs="0"/>
<xs:element name="DPGOnDeparture" type="dglist"/>
<!-- neu in NSW V6.0 DPGOnDeparture vereinfachung zu DPG -->
<xs:element name="DPG" type="dglist"/>
</xs:sequence>
</xs:choice>
</xs:complexType>

View File

@ -3355,8 +3355,8 @@ public partial class hazd {
private ItemsChoiceType2[] itemsElementNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DPG", typeof(dglist), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("DPGManifestOnBoardOnDeparture", typeof(yorntype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("DPGOnDeparture", typeof(dglist), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("INFShipClass", typeof(infclasstype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("MOUBaltic", typeof(ytype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("NoDPGOnBoardOnDeparture", typeof(ytype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
@ -4695,10 +4695,10 @@ public enum infclasstype {
public enum ItemsChoiceType2 {
/// <remarks/>
DPGManifestOnBoardOnDeparture,
DPG,
/// <remarks/>
DPGOnDeparture,
DPGManifestOnBoardOnDeparture,
/// <remarks/>
INFShipClass,
@ -4722,8 +4722,8 @@ public partial class haza {
private ItemsChoiceType1[] itemsElementNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DPG", typeof(dglist), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("DPGManifestOnBoardOnArrival", typeof(yorntype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("DPGOnArrival", typeof(dglist), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("INFShipClass", typeof(infclasstype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("MOUBaltic", typeof(ytype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("NoDPGOnBoardOnArrival", typeof(ytype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
@ -4757,10 +4757,10 @@ public partial class haza {
public enum ItemsChoiceType1 {
/// <remarks/>
DPGManifestOnBoardOnArrival,
DPG,
/// <remarks/>
DPGOnArrival,
DPGManifestOnBoardOnArrival,
/// <remarks/>
INFShipClass,

View File

@ -0,0 +1,16 @@
-- neues Feld PO Nummer im Core
PRINT N'Altering [dbo].[MessageCore]...';
GO
ALTER TABLE [dbo].[MessageCore] ADD [PONumber] NVARCHAR (16) NULL;
GO
PRINT N'Altering [dbo].[MessageCore]...';
GO
ALTER TABLE [dbo].[MessageCore]
ADD [Flags] INT DEFAULT 0 NULL;
GO

View File

@ -3,15 +3,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Globalization;
using System.ServiceProcess;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Timers;
using bsmd.email;
using bsmd.database;
@ -78,11 +74,12 @@ namespace bsmd.POService
this._timer_Elapsed(null, null);
}
internal static bool ParsePO(string inputValue)
internal static bool ParsePO(string inputValue, ref string poNumber, ref string port,
ref string shipname, ref string something, ref string dateString)
{
bool result = false;
// Betreffzeile parsen. Ein Beispiel:
// WuselString parsen. Ein Beispiel:
// "WG: PO:8204730095 DEWVNTM-ADELINA D-005E-310120";
// Hier kann man designen: https://regex101.com/
const string poPattern = @"PO:(\d+) ([A-Z]+)-(.*?)-(.*?)-(\d{6})";
@ -90,11 +87,11 @@ namespace bsmd.POService
Match aMatch = poRegex.Match(inputValue);
if (aMatch.Success)
{
string poNummer = aMatch.Groups[1].Captures[0].Value;
string hafen = aMatch.Groups[2].Captures[0].Value;
string name = aMatch.Groups[3].Captures[0].Value;
string irgendwas = aMatch.Groups[4].Captures[0].Value;
string datumString = aMatch.Groups[5].Captures[0].Value;
poNumber = aMatch.Groups[1].Captures[0].Value;
port = aMatch.Groups[2].Captures[0].Value;
shipname = aMatch.Groups[3].Captures[0].Value;
something = aMatch.Groups[4].Captures[0].Value;
dateString = aMatch.Groups[5].Captures[0].Value;
result = true;
}
@ -103,6 +100,8 @@ namespace bsmd.POService
#endregion
#region timer loop handler
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
@ -124,20 +123,10 @@ namespace bsmd.POService
{
// check and download next e-Mail, saving attachment
while (bsmdPopClient.ReceiveSingleMailText(out messageId, out mailSender, out mailSubject, out body))
{
{
string receiptText = "";
bool readResult = false;
string readMessage = "";
string receiptText = "";
MessageCore messageCore = null;
if (attachmentLocalPath == null)
{
receiptText = "incoming E-Mail did not contain an Excel attachment!";
_log.WarnFormat(receiptText);
}
else
{
// only a valid sender gets a reply
bool isValidSender = false;
foreach (string aValidSender in Properties.Settings.Default.ValidSender)
@ -149,34 +138,94 @@ namespace bsmd.POService
}
}
if (!isValidSender)
if (!isValidSender)
{
receiptText = string.Format("ignored e - mail from illegal sender: {0}", mailSender);
_log.Warn(receiptText);
}
else
{
try
{
receiptText = string.Format("ignored e - mail from illegal sender: {0}", mailSender);
_log.Warn(receiptText);
}
else
{
try
string poNumber = null;
string port = null;
string dateString = null;
string shipname = null;
string something = null;
// Mail nach dem PO Nummerntext durchsuchen
// Der Nummerstring ist vielleicht im Betreff, im Body oder im Dateinamen des
// PDF Attachments. In den PDF's selbst habe ich den (kompletten) String aktuell nicht gefunden.
if (!ParsePO(mailSubject, ref poNumber, ref port, ref shipname, ref something, ref dateString))
{
if(!ParsePO(mailSubject))
if (!ParsePO(body, ref poNumber, ref port, ref shipname, ref something, ref dateString))
{
string attachmentFileName = bsmdPopClient.GetNameOfFirstMailEmailPDFAttachment(messageId);
if (attachmentFileName != null)
ParsePO(attachmentFileName, ref poNumber, ref port, ref shipname, ref something, ref dateString);
}
// aus (ungefährem) Datum, Name und Hafen den MessageCore suchen
// PO-Nummer und Schiffs/Anlaufklassifizierung eintragen
}
catch (Exception someException)
if (poNumber != null)
{
receiptText = string.Format("Error processing po mail: {0}", someException.Message);
_log.Error(receiptText);
// aus (ungefährem) Datum, Name und Hafen den MessageCore suchen
uint? from = null, to = null;
if (DateTime.TryParseExact(dateString, "ddMMyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime etaDate))
{
// Alle Anmeldungen des betreffenden Tages laden
Dictionary<MessageCore.SearchFilterType, string> filterDict = new Dictionary<MessageCore.SearchFilterType, string>();
from = etaDate.ToUniversalTime().ToUnixTimeStamp();
to = etaDate.ToUniversalTime().Add(new TimeSpan(23, 59, 59)).ToUnixTimeStamp();
filterDict.Add(MessageCore.SearchFilterType.FILTER_ETA, string.Format("{0}:{1}", from?.ToString() ?? "", to?.ToString() ?? ""));
List<MessageCore> anmeldungen = DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).GetMessageCoresWithFilters(filterDict, 100);
List<MessageCore> possibleMatches = new List<MessageCore>();
// nach Hafen und Schiffsnamen ausfiltern
if (port.Length > 5) port = port.Substring(0, 5);
foreach (MessageCore foundCore in anmeldungen)
{
if (foundCore.PoC.Equals(port) && foundCore.Shipname.Equals(shipname, StringComparison.OrdinalIgnoreCase))
possibleMatches.Add(foundCore);
}
if (possibleMatches.Count == 0)
{
// nix gefunden
receiptText = string.Format("no match found for PO number {0} ship {1} date {2} port {3}",
poNumber, shipname, etaDate, port);
_log.Warn(receiptText);
}
else if (possibleMatches.Count > 1)
{
// nicht eindeutig
receiptText = string.Format("{0} matches found for PO number {1} ship {2} date {3} port {4}",
possibleMatches.Count, poNumber, shipname, etaDate, port);
_log.Warn(receiptText);
}
else
{
// PO-Nummer und Schiffs/Anlaufklassifizierung eintragen
possibleMatches[0].PONumber = poNumber;
DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).Save(possibleMatches[0]);
_log.InfoFormat("MessageCore {0} updated with po number {1}", possibleMatches[0].Id, poNumber);
}
}
else
{
_log.WarnFormat("Error parsing date component of PO string: {0}", dateString);
}
}
else
{
_log.Warn("incoming e-mail did not contain a po number");
}
}
catch (Exception someException)
{
receiptText = string.Format("Error processing po mail: {0}", someException.Message);
_log.Error(receiptText);
}
}
if (receiptText.Length > 0)
@ -185,29 +234,14 @@ namespace bsmd.POService
BSMDMail.SendSystemInfo(receiptSubject, receiptText, mailSender);
}
// remove e-Mail
_log.InfoFormat("deleting mail with messageId {0}", messageId);
_log.InfoFormat("mail delete {0}", bsmdPopClient.DeleteMessageByMessageId(messageId) ? "successful" : "failed");
}
}
}
#region Phase II - Excel Sheets auf Anforderung erzeugen
List<MessageCore> excelMessageCoreList = DBManager.Instance.GetMessageCoresForExcelCreate();
if (excelMessageCoreList.Count > 0)
_log.InfoFormat("{0} excel sheets to create from database", excelMessageCoreList.Count);
foreach (MessageCore excelCore in excelMessageCoreList)
{
// load messages
List<Message> messages = DBManager.Instance.GetMessagesForCore(excelCore, DBManager.MessageLoad.ALL);
// template
}
#endregion
}
DBManager.Instance.Disconnect();
}
@ -223,5 +257,7 @@ namespace bsmd.POService
}
#endregion
}
}

View File

@ -1,12 +1,8 @@
// Copyright (c) 2020-present schick Informatik
// Description:
// Description: Tool main entry point
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace bsmd.POService
{
@ -25,7 +21,16 @@ namespace bsmd.POService
{
new POService()
};
ServiceBase.Run(ServicesToRun);
if (Debugger.IsAttached)
{
((POService)ServicesToRun[0]).DoOnce();
}
else
{
ServiceBase.Run(ServicesToRun);
}
}
}
}

View File

@ -84,6 +84,15 @@ namespace bsmd.database
FILTER_TICKETNO
}
[Flags]
public enum CoreFlags
{
NONE = 0,
MAERSK_BHV = 1,
SEAGO_BHV = 2,
SEAGO_WHV = 4
}
#endregion
#region Properties
@ -294,6 +303,23 @@ namespace bsmd.database
/// </summary>
public bool? ExcelImportComplete { get; set; }
/// <summary>
/// Diese Nummer wird bei Schiffen von Maersk/SeaGo für die Identifikation bei der Fakturierung benutzt. Das Feld ist funktional
/// für den NSW Betrieb so nicht erforderlich. (nur Ausgabe / POService)
/// </summary>
public string PONumber { get; set; }
/// <summary>
/// generic multipurpose flag field
/// </summary>
public int Flags { get; set; }
#region Flag properties not backed by field
#endregion
#region Felder um NSW Statusinformationen zu speichern (abgefragte Daten!)
public bool? Cancelled { get; set; }
@ -371,6 +397,8 @@ namespace bsmd.database
scmd.Parameters.AddWithNullableValue("@P35", this.StatusCheckErrorMessage);
scmd.Parameters.AddWithNullableValue("@P36", this.QueryNSWStatus);
scmd.Parameters.AddWithNullableValue("@P37", this.ExcelImportComplete);
scmd.Parameters.AddWithNullableValue("@P38", this.PONumber);
scmd.Parameters.AddWithValue("@P39", this.Flags);
if (this.IsNew)
{
@ -381,9 +409,9 @@ namespace bsmd.database
"HerbergFormTemplateGuid, HerbergReportType, HerbergEmailcontactReportingVessel, HerbergEmail24HrsContact, " +
"ETAKielCanal, HerbergRevDate, ReportStatus, SietasSheetVersion, Incoming, DefaultReportingPartyId, CreateExcel, " +
"EditedBy, TicketNo, Cancelled, VisitIdOrTransitIdCancellable, BlockedNotificationClasses, FreeNotificationClasses, " +
"OwnNotificationClasses, StatusCheckErrorCode, StatusCheckErrorMessage, QueryNSWStatus, ExcelImportComplete) VALUES " +
"OwnNotificationClasses, StatusCheckErrorCode, StatusCheckErrorMessage, QueryNSWStatus, ExcelImportComplete, PONumber, Flags) VALUES " +
"(@ID, @P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8, @P9, @P10, @P11, @P12, @P13, @P14, @P15, @P16, @P17, " +
"@P18, @P19, @P20, @P21, @P22, @P23, @P24, @P25, @P26, @P27, @P28, @P29, @P30, @P31, @P32, @P33, @P34, @P35, @P36, @P37)",
"@P18, @P19, @P20, @P21, @P22, @P23, @P24, @P25, @P26, @P27, @P28, @P29, @P30, @P31, @P32, @P33, @P34, @P35, @P36, @P37, @P38, @P39)",
this.Tablename);
scmd.CommandText = query;
}
@ -398,7 +426,7 @@ namespace bsmd.database
"SietasSheetVersion = @P23, Incoming = @P24, DefaultReportingPartyId = @P25, CreateExcel = @P26, EditedBy = @P27, " +
"TicketNo = @P28, Cancelled = @P29, VisitIdOrTransitIdCancellable = @P30, BlockedNotificationClasses = @P31, " +
"FreeNotificationClasses = @P32, OwnNotificationClasses = @P33, StatusCheckErrorCode = @P34, StatusCheckErrorMessage = @P35, " +
"QueryNSWStatus = @P36, ExcelImportComplete = @P37 WHERE Id = @ID", this.Tablename);
"QueryNSWStatus = @P36, ExcelImportComplete = @P37, PONumber = @P38, Flags = @P39 WHERE Id = @ID", this.Tablename);
scmd.CommandText = query;
}
}
@ -418,7 +446,7 @@ namespace bsmd.database
"[{0}].[DefaultReportingPartyId], [{0}].[Created], [{0}].[Changed], [{0}].[CreateExcel], [{0}].[EditedBy], [{0}].[TicketNo], " +
"[{0}].[Cancelled], [{0}].[VisitIdOrTransitIdCancellable], [{0}].[BlockedNotificationClasses], [{0}].[FreeNotificationClasses], " +
"[{0}].[OwnNotificationClasses], [{0}].[StatusCheckErrorCode], [{0}].[StatusCheckErrorMessage], [{0}].[QueryNSWStatus], " +
"[{0}].[ExcelImportComplete]",
"[{0}].[ExcelImportComplete], [{0}].[PONumber], [{0}].Flags ",
this.Tablename);
if(filter == Message.LoadFilter.SEARCH_CORE_FILTERS)
@ -616,7 +644,6 @@ namespace bsmd.database
}
}
public override List<DatabaseEntity> LoadList(IDataReader reader)
{
List<DatabaseEntity> result = new List<DatabaseEntity>();
@ -663,6 +690,8 @@ namespace bsmd.database
if (!reader.IsDBNull(37)) core.StatusCheckErrorMessage = reader.GetString(37);
if (!reader.IsDBNull(38)) core.QueryNSWStatus = reader.GetBoolean(38);
if (!reader.IsDBNull(39)) core.ExcelImportComplete = reader.GetBoolean(39);
if (!reader.IsDBNull(40)) core.PONumber = reader.GetString(40);
if (!reader.IsDBNull(41)) core.Flags = reader.GetInt32(41);
result.Add(core);
}
@ -701,6 +730,17 @@ namespace bsmd.database
return false;
}
public bool IsFlagSet(CoreFlags flag)
{
return (this.Flags & (int)flag) != 0;
}
public void SetFlag(bool value, CoreFlags flag)
{
if (value) this.Flags |= (int)flag;
else this.Flags &= (int)~flag;
}
#endregion
#region display override
@ -710,7 +750,7 @@ namespace bsmd.database
return string.Format("{0} - {1}", this.IMO, this.ETA);
}
#endregion
#endregion
#region IComparable implementation

View File

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

View File

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

View File

@ -31,14 +31,14 @@ namespace bsmd.database
public string ServiceName { get; set; }
[ShowReport]
[Validation(ValidationCode.NOT_NULL_MAX_LEN, 99)]
[Validation(ValidationCode.NOT_NULL_MAX_LEN, 255)]
[LookupName("SERV.ServiceBeneficiary")]
[MaxLength(255)]
[ENI2Validation]
public string ServiceBeneficiary { get; set; }
[ShowReport]
[Validation(ValidationCode.NOT_NULL_MAX_LEN, 99)]
[Validation(ValidationCode.NOT_NULL_MAX_LEN, 255)]
[LookupName("SERV.ServiceInvoiceRecipient")]
[MaxLength(255)]
[ENI2Validation]

View File

@ -12,6 +12,7 @@ using System.Data.SqlClient;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using log4net;
using System.Globalization;
namespace bsmd.database
{
@ -280,5 +281,59 @@ namespace bsmd.database
#endregion
#region Date calculations
// This presumes that weeks start with Monday.
// Week 1 is the 1st week of the year with a Thursday in it.
public static int GetIso8601WeekOfYear(DateTime time)
{
// Seriously cheat. If its Monday, Tuesday or Wednesday, then it'll
// be the same week# as whatever Thursday, Friday or Saturday are,
// and we always get those right
DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
time = time.AddDays(3);
}
// Return the week of our adjusted day
return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
public static DateTime StartOfWeek(this DateTime dt)
{
int diff = (7 + (dt.DayOfWeek - DayOfWeek.Monday)) % 7;
return dt.AddDays(-1 * diff).Date;
}
public static DateTime FirstDateOfWeekISO8601(int year, int weekOfYear)
{
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;
// Use first Thursday in January to get first week of the year as
// it will never be in Week 52/53
DateTime firstThursday = jan1.AddDays(daysOffset);
var cal = CultureInfo.CurrentCulture.Calendar;
int firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
var weekNum = weekOfYear;
// As we're adding days to a date in Week 1,
// we need to subtract 1 in order to get the right date for week #1
if (firstWeek == 1)
{
weekNum--;
}
// Using the first Thursday as starting week ensures that we are starting in the right year
// then we add number of weeks multiplied with days
var result = firstThursday.AddDays(weekNum * 7);
// Subtract 3 days from Thursday to get Monday, which is the first weekday in ISO8601
return result.AddDays(-3);
}
#endregion
}
}

View File

@ -529,7 +529,8 @@ namespace bsmd.dbh
rootCREW.CrewMember[i].CrewMemberNationality = crew.CrewMemberNationality;
rootCREW.CrewMember[i].CrewMemberPlaceOfBirth = crew.CrewMemberPlaceOfBirth;
rootCREW.CrewMember[i].CrewMemberVisaNumber = crew.CrewMemberVisaNumber;
rootCREW.CrewMember[i].CrewMemberIdentityDocumentIssuingState = crew.CrewMemberIdentityDocumentIssuingState;
if(crew.CrewMemberIdentityDocumentIssuingState.Trim().Length == 2)
rootCREW.CrewMember[i].CrewMemberIdentityDocumentIssuingState = crew.CrewMemberIdentityDocumentIssuingState;
rootCREW.CrewMember[i].CrewMemberIdentityDocumentExpiryDateSpecified = crew.CrewMemberIdentityDocumentExpiryDate.HasValue;
if (crew.CrewMemberIdentityDocumentExpiryDate.HasValue)
rootCREW.CrewMember[i].CrewMemberIdentityDocumentExpiryDate = crew.CrewMemberIdentityDocumentExpiryDate.Value;
@ -565,7 +566,8 @@ namespace bsmd.dbh
rootPAS.Passenger[i].PassengerPortOfEmbarkation = pas.PassengerPortOfEmbarkation;
rootPAS.Passenger[i].PassengerPortOfDisembarkation = pas.PassengerPortOfDisembarkation;
rootPAS.Passenger[i].PassengerInTransit = pas.PassengerInTransit ?? false ? RootSECValidISSCOnBoard.Y : RootSECValidISSCOnBoard.N;
rootPAS.Passenger[i].PassengerIdentityDocumentIssuingState = pas.PassengerIdentityDocumentIssuingState;
if(pas.PassengerIdentityDocumentIssuingState.Trim().Length == 2)
rootPAS.Passenger[i].PassengerIdentityDocumentIssuingState = pas.PassengerIdentityDocumentIssuingState;
rootPAS.Passenger[i].PassengerIdentityDocumentExpiryDateSpecified = pas.PassengerIdentityDocumentExpiryDate.HasValue;
if (pas.PassengerIdentityDocumentExpiryDate.HasValue)
rootPAS.Passenger[i].PassengerIdentityDocumentExpiryDate = pas.PassengerIdentityDocumentExpiryDate.Value;

View File

@ -19,10 +19,17 @@ namespace bsmd.email
{
public class BSMDPopClient : IDisposable
{
#region Fields
private readonly Pop3Client pop3Client;
private readonly ILog _log = LogManager.GetLogger(typeof(BSMDPopClient));
private int currentMail = 1;
#endregion
#region Construction / Destruction
public BSMDPopClient()
{
try
@ -42,6 +49,20 @@ namespace bsmd.email
}
}
public void Dispose()
{
if (this.pop3Client != null)
{
if (this.pop3Client.Connected)
this.pop3Client.Disconnect();
this.pop3Client.Dispose();
}
}
#endregion
#region Hack
/// <summary>
/// Diese Funktion validiert *jedes* Zertifikat und ist eigentlich scheiße. Das geht nur so im abgeschlossenen BSMD Netz!
/// </summary>
@ -50,8 +71,16 @@ namespace bsmd.email
return true;
}
#endregion
#region Properties
public bool IsConnected { get; } = false;
#endregion
#region E-Mail receive helper / convenience funcs
public bool ReceiveSingleMailText(out string messageId, out string sender, out string subject, out string body)
{
messageId = null;
@ -83,7 +112,7 @@ namespace bsmd.email
{
return false;
}
}
}
public bool ReceiveSingleMail(out string attachmentLocalFile, out string messageId, out string sender, out string subject)
{
@ -133,6 +162,35 @@ namespace bsmd.email
}
}
public string GetNameOfFirstMailEmailPDFAttachment(string messageId)
{
if (IsConnected)
{
int messageCount = this.pop3Client.GetMessageCount();
// Run through each of these messages and download the headers
for (int messageIndex = messageCount; messageIndex > 0; messageIndex--)
{
// If the Message ID of the current message is the same as the parameter given, delete that message
if (this.pop3Client.GetMessageHeaders(messageIndex).MessageId.Equals(messageId))
{
// gefunden, Nachricht laden
Message mailMessage = this.pop3Client.GetMessage(messageIndex);
foreach (MessagePart part in mailMessage.FindAllAttachments())
{
if (part.FileName.EndsWith(".pdf", StringComparison.InvariantCultureIgnoreCase))
return part.FileName;
}
}
}
}
return null;
}
#endregion
#region delete designated email
/// <summary>
/// deletes message referenced by messageId
/// </summary>
@ -160,15 +218,7 @@ namespace bsmd.email
return false;
}
public void Dispose()
{
if (this.pop3Client != null)
{
if(this.pop3Client.Connected)
this.pop3Client.Disconnect();
this.pop3Client.Dispose();
}
}
#endregion
}
}

View File

@ -604,7 +604,7 @@ namespace bsmd.hisnord
SetHAZPositions(hn_dgList, haz);
hn_haza_items.Add(hn_dgList);
hn_haza_itemsChoiceType1.Add(ItemsChoiceType1.DPGOnArrival);
hn_haza_itemsChoiceType1.Add(ItemsChoiceType1.DPG);
hn_haza.Items = hn_haza_items.ToArray();
hn_haza.ItemsElementName = hn_haza_itemsChoiceType1.ToArray();
@ -666,7 +666,7 @@ namespace bsmd.hisnord
SetHAZPositions(hn_dgList, haz);
hn_hazd_items.Add(hn_dgList);
hn_hazd_itemsChoiceType2.Add(ItemsChoiceType2.DPGOnDeparture);
hn_hazd_itemsChoiceType2.Add(ItemsChoiceType2.DPG);
hn_hazd.Items = hn_hazd_items.ToArray();
hn_hazd.ItemsElementName = hn_hazd_itemsChoiceType2.ToArray();
@ -1356,7 +1356,8 @@ namespace bsmd.hisnord
hn_pas.Passenger[i].PassengerIdentityDocumentExpiryDateSpecified = pas.PassengerIdentityDocumentExpiryDate.HasValue;
if (pas.PassengerIdentityDocumentExpiryDate.HasValue)
hn_pas.Passenger[i].PassengerIdentityDocumentExpiryDate = pas.PassengerIdentityDocumentExpiryDate.Value;
hn_pas.Passenger[i].PassengerIdentityDocumentIssuingState = pas.PassengerIdentityDocumentIssuingState;
if(pas.PassengerIdentityDocumentIssuingState.Trim().Length == 2)
hn_pas.Passenger[i].PassengerIdentityDocumentIssuingState = pas.PassengerIdentityDocumentIssuingState;
}
items1ChoiceType.Add(Items1ChoiceType.PAS);
@ -1396,14 +1397,15 @@ namespace bsmd.hisnord
hn_crew.CrewMember[i].CrewMemberIdentityDocumentId = crew.CrewMemberIdentityDocumentId;
if (crew.CrewMemberIdentityDocumentType.HasValue)
hn_crew.CrewMember[i].CrewMemberIdentityDocumentType = (documenttype)crew.CrewMemberIdentityDocumentType.Value;
hn_crew.CrewMember[i].CrewMemberLastName = crew.CrewMemberLastName;
hn_crew.CrewMember[i].CrewMemberLastName = crew.CrewMemberLastName;
hn_crew.CrewMember[i].CrewMemberNationality = crew.CrewMemberNationality;
hn_crew.CrewMember[i].CrewMemberPlaceOfBirth = crew.CrewMemberPlaceOfBirth;
hn_crew.CrewMember[i].CrewMemberVisaNumber = crew.CrewMemberVisaNumber.IsNullOrEmpty() ? "-" : crew.CrewMemberVisaNumber;
hn_crew.CrewMember[i].CrewmemberIdentityDocumentExpiryDateSpecified = crew.CrewMemberIdentityDocumentExpiryDate.HasValue;
if (crew.CrewMemberIdentityDocumentExpiryDate.HasValue)
hn_crew.CrewMember[i].CrewmemberIdentityDocumentExpiryDate = crew.CrewMemberIdentityDocumentExpiryDate.Value;
hn_crew.CrewMember[i].CrewMemberIdentityDocumentIssuingState = crew.CrewMemberIdentityDocumentIssuingState;
if(crew.CrewMemberIdentityDocumentIssuingState.Trim().Length == 2)
hn_crew.CrewMember[i].CrewMemberIdentityDocumentIssuingState = crew.CrewMemberIdentityDocumentIssuingState;
}
items1ChoiceType.Add(Items1ChoiceType.CREW);

View File

@ -3355,8 +3355,8 @@ public partial class hazd {
private ItemsChoiceType2[] itemsElementNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DPG", typeof(dglist), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("DPGManifestOnBoardOnDeparture", typeof(yorntype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("DPGOnDeparture", typeof(dglist), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("INFShipClass", typeof(infclasstype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("MOUBaltic", typeof(ytype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("NoDPGOnBoardOnDeparture", typeof(ytype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
@ -4695,10 +4695,10 @@ public enum infclasstype {
public enum ItemsChoiceType2 {
/// <remarks/>
DPGManifestOnBoardOnDeparture,
DPG,
/// <remarks/>
DPGOnDeparture,
DPGManifestOnBoardOnDeparture,
/// <remarks/>
INFShipClass,
@ -4722,8 +4722,8 @@ public partial class haza {
private ItemsChoiceType1[] itemsElementNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DPG", typeof(dglist), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("DPGManifestOnBoardOnArrival", typeof(yorntype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("DPGOnArrival", typeof(dglist), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("INFShipClass", typeof(infclasstype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("MOUBaltic", typeof(ytype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlElementAttribute("NoDPGOnBoardOnArrival", typeof(ytype), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
@ -4757,10 +4757,10 @@ public partial class haza {
public enum ItemsChoiceType1 {
/// <remarks/>
DPGManifestOnBoardOnArrival,
DPG,
/// <remarks/>
DPGOnArrival,
DPGManifestOnBoardOnArrival,
/// <remarks/>
INFShipClass,