Merge branch 'release/eni_7.9'

This commit is contained in:
Daniel Schick 2023-03-02 13:41:34 +01:00
commit c3aeb12c36
50 changed files with 2034 additions and 558 deletions

View File

@ -62,6 +62,9 @@ namespace ENI2
base.OnStartup(e); base.OnStartup(e);
// set connectnion string to async loader
DBManagerAsync.ConnectionString = ENI2.Properties.Settings.Default.ConnectionString;
// initialize static / localized lookups from sqlite database // initialize static / localized lookups from sqlite database
string langKey = CultureInfo.CurrentCulture.TwoLetterISOLanguageName; string langKey = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;

View File

@ -0,0 +1,14 @@
<UserControl x:Class="ENI2.Controls.BusyControl"
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:p="clr-namespace:ENI2.Properties"
xmlns:util="clr-namespace:ENI2.Util"
xmlns:local="clr-namespace:ENI2.Controls"
mc:Ignorable="d"
d:DesignHeight="28" d:DesignWidth="28">
<Grid>
<Image Source="../Resources/bullet_ball_grey.png" x:Name="imageBall" />
</Grid>
</UserControl>

View File

@ -0,0 +1,44 @@
// Copyright (c) 2023- schick Informatik
//
// Description: Idea to have a simple control that shows if the application is busy or not using a simple icon
// that will be set according to a state
//
using ENI2.Util;
using System.Windows.Controls;
namespace ENI2.Controls
{
/// <summary>
/// Interaction logic for BusyControl.xaml
/// </summary>
public partial class BusyControl : UserControl
{
UIHelper.BusyStateEnum _busyState = UIHelper.BusyStateEnum.NEUTRAL;
public BusyControl()
{
InitializeComponent();
}
public UIHelper.BusyStateEnum BusyState
{
set
{
_busyState = value;
//Dispatcher.Invoke(() =>
//{
switch (_busyState)
{
case UIHelper.BusyStateEnum.NEUTRAL: imageBall.Source = Properties.Resources.bullet_ball_grey.CreateBitmapSource(); break;
case UIHelper.BusyStateEnum.BUSY: imageBall.Source = Properties.Resources.bullet_ball_yellow.CreateBitmapSource(); break;
case UIHelper.BusyStateEnum.FAIL: imageBall.Source = Properties.Resources.bullet_ball_red.CreateBitmapSource(); break;
case UIHelper.BusyStateEnum.SUCCESS: imageBall.Source = Properties.Resources.bullet_ball_green.CreateBitmapSource(); break;
}
//});
}
get => _busyState;
}
}
}

View File

@ -0,0 +1,115 @@
<UserControl x:Class="ENI2.Controls.MaerskListControl"
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"
xmlns:db="clr-namespace:bsmd.database;assembly=bsmd.database"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="900">
<UserControl.Resources>
<col:ArrayList x:Key="arrList">
<col:DictionaryEntry Key="None" Value="0" />
<col:DictionaryEntry Key="Maersk BRV/WHV" 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>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<Label Content="From" Grid.Column="0" />
<DatePicker x:Name="dateTimePickerFrom" Margin="2" Grid.Column="1" SelectedDateChanged="dateTimePickerFrom_SelectedDateChanged"/>
<Label Content="To" Grid.Column="2" />
<DatePicker x:Name="dateTimePickerTo" Margin="2" Grid.Column="3" SelectedDateChanged="dateTimePickerFrom_SelectedDateChanged"/>
<Button x:Name="buttonLoad" Grid.Column="4" Content="Load" Margin="2" Click="buttonLoad_Click" />
<!--Button x:Name="buttonSave" Grid.Column="5" Content="Save" Margin="2" Click="buttonSave_Click" /-->
<Button x:Name="buttonRequestIds" Grid.Column="6" Content="Request marked Ids" Margin="2" Click="buttonRequestIds_Click" />
<Button x:Name="buttonRequestPlus3" Grid.Column="7" Content="Request +4" Margin="2" Click="buttonRequestIds_Click" />
<Button x:Name="buttonImport" Grid.Column="9" Margin="2" Content="Import" Click="buttonImport_Click" />
<Button x:Name="buttonExport" Grid.Column="10" Margin="2" Content="Export" Click="buttonExport_Click" />
<local:BusyControl x:Name="busyControl" Grid.Column="5" />
</Grid>
<local:ENIDataGrid Grid.Row="1" Margin="2,8,2,2" x:Name="dataGridPOCores" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
SelectionMode="Extended" AutoGenerateColumns="False" CellEditEnding="dataGridPOCores_CellEditEnding" CanUserAddRows="False"
MouseDoubleClick="dataGridPOCores_MouseDoubleClick">
<local:ENIDataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="{x:Static db:MaerskData+MDStatus.ID}">
<Setter Property="Background" Value="LightGreen"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="{x:Static db:MaerskData+MDStatus.NO_ID}">
<Setter Property="Background" Value="LightPink"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="{x:Static db:MaerskData+MDStatus.UPDATED}">
<Setter Property="Background" Value="LightYellow"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="{x:Static db:MaerskData+MDStatus.NO_ETA}">
<Setter Property="Background" Value="LightCoral"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="{x:Static db:MaerskData+MDStatus.REQUESTING_ID}">
<Setter Property="Background" Value="Yellow"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="{x:Static db:MaerskData+MDStatus.ID_ASSIGNED}">
<Setter Property="Background" Value="GreenYellow"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="{x:Static db:MaerskData+MDStatus.NO_ID_AND_DUE}">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</local:ENIDataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Status" Binding="{Binding Status}" IsReadOnly="True" />
<DataGridTextColumn Header="ETA" Binding="{Binding ColA}" IsReadOnly="True" />
<DataGridTextColumn Header="ETD" Binding="{Binding ColB}" IsReadOnly="True" />
<DataGridTextColumn Header="Rotation name" Binding="{Binding ColC}" IsReadOnly="True" />
<DataGridTextColumn Header="Vessel code" Binding="{Binding ColD}" IsReadOnly="True" />
<DataGridTextColumn Header="Vessel name" Binding="{Binding ColE}" IsReadOnly="True" />
<DataGridTextColumn Header="IMO" Binding="{Binding ColF}" IsReadOnly="True" />
<DataGridTextColumn Header="Arr voy" Binding="{Binding ColG}" IsReadOnly="True" />
<DataGridTextColumn Header="Dep voy" Binding="{Binding ColH}" IsReadOnly="True" />
<DataGridTextColumn Header="Terminal name" Binding="{Binding ColI}" IsReadOnly="True" />
<DataGridTextColumn Header="Operator code" Binding="{Binding ColJ}" IsReadOnly="True" />
<DataGridTextColumn Header="Pro arr" Binding="{Binding ColK}" IsReadOnly="True" />
<DataGridTextColumn Header="Pro dep" Binding="{Binding ColL}" IsReadOnly="True" />
<DataGridTextColumn Header="Id" Binding="{Binding ColM}" IsReadOnly="True" />
<DataGridTextColumn Header="Remark" Binding="{Binding Remark, Mode=TwoWay}" x:Name="gridColumnRemark" />
<!--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="ETA" Binding="{Binding ETA_NOA_NOD, StringFormat=\{0:dd.MM.yyyy HH:mm\}, Converter={util:UtcToLocalDateTimeConverter}}" IsReadOnly="True" /-->
<!--DataGridTextColumn x:Name="gridColumnATA" Header="ATA" Binding="{Binding POATA, StringFormat=\{0:dd.MM.yyyy\}, Mode=TwoWay, Converter={util:UtcToLocalDateTimeConverter}}" IsReadOnly="False" /-->
<!--DataGridTextColumn Header="ATD" Binding="{Binding ATD, StringFormat=\{0:dd.MM.yyyy HH:mm\}, Converter={util:UtcToLocalDateTimeConverter}}" IsReadOnly="True" /-->
</DataGrid.Columns>
</local:ENIDataGrid>
</Grid>
</GroupBox>
</UserControl>

View File

@ -0,0 +1,613 @@
// Copyright (c) 2017 / 2023 schick Informatik
// Description: Request dbh ids for Maersk data lists
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
using bsmd.database;
using ExcelDataReader;
using System.Collections.ObjectModel;
using ENI2.Excel;
using ENI2.Locode;
using ENI2.Util;
using System.Diagnostics;
using System.Linq;
namespace ENI2.Controls
{
/// <summary>
/// Interaction logic for MaerskListControl.xaml
/// </summary>
public partial class MaerskListControl : UserControl
{
#region Fields
private readonly ObservableCollection<MaerskData> maerskDataList = new ObservableCollection<MaerskData>();
private const uint MAX_EMPTY_ROWS_ON_IMPORT = 3; // import breaks if more than this count of empty rows have been read
private readonly DatabaseEntityWatchdog _dbWatchDog;
#endregion
#region Construction
public MaerskListControl()
{
InitializeComponent();
Loaded += POList_Loaded;
this.dateTimePickerFrom.SelectedDate = DateTime.Today.AddDays(-14);
this.dateTimePickerTo.SelectedDate = DateTime.Today.AddDays(14);
this._dbWatchDog = new DatabaseEntityWatchdog();
this._dbWatchDog.DatabaseEntityChanged += _dbWatchDog_DatabaseEntityChanged;
this._dbWatchDog.VisitTransitIdUpdated += _dbWatchDog_VisitTransitIdUpdated;
}
#endregion
#region Events
public delegate void DateChanged(DateTime date);
public event DateChanged FromDateChanged;
public event DateChanged ToDateChanged;
#endregion
#region DB Watchdog
private async void _dbWatchDog_VisitTransitIdUpdated(DatabaseEntity entity)
{
if (entity is MessageCore core)
{
foreach (MaerskData md in this.maerskDataList)
{
if ((md.MessageCore != null) && (md.MessageCore.Id == core.Id))
{
md.MessageCore = core;
md.Status = MaerskData.MDStatus.ID;
md.ColM = core.VisitId;
await DBManagerAsync.Save(md);
_dbWatchDog.UnRegister(core);
this.Dispatcher.Invoke(() =>
{
this.dataGridPOCores.Items.Refresh();
if(_dbWatchDog.Idle)
busyControl.BusyState = Util.UIHelper.BusyStateEnum.NEUTRAL;
});
}
}
}
}
private void _dbWatchDog_DatabaseEntityChanged(DatabaseEntity entity)
{
if (entity is MessageCore core)
System.Diagnostics.Trace.WriteLine($"Core state changed to {core.BSMDStatusInternal}");
}
#endregion
#region Properties
/// <summary>
/// Locode of the port that is concerned by this import list. Is to be set in the surrounding container:
/// </summary>
public string PortLocode { get; set; }
/// <summary>
/// synchronize selection props
/// </summary>
public DateTime? FromDate {
get { return this.dateTimePickerFrom.SelectedDate; }
set { this.dateTimePickerFrom.SelectedDate = value; }
}
/// <summary>
/// synchronize selection props
/// </summary>
public DateTime? ToDate
{
get { return this.dateTimePickerTo.SelectedDate; }
set { this.dateTimePickerTo.SelectedDate = value; }
}
#endregion
#region events
public event MessageCore.MessageCoreSelectedHandler MessageCoreSelected;
#endregion
#region control event handler
private void POList_Loaded(object sender, RoutedEventArgs e)
{
dataGridPOCores.ItemsSource = maerskDataList;
}
private async void dataGridPOCores_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
if (e.Column == gridColumnRemark)
{
MaerskData maerskData = this.maerskDataList[e.Row.GetIndex()];
var el = e.EditingElement as System.Windows.Controls.TextBox;
if (el.Text.Length > 100)
{
el.Text = el.Text.Trim().Substring(0, 100);
}
maerskData.Remark = el.Text;
if (maerskData.MessageCore != null)
await DBManagerAsync.Save(maerskData);
}
/*
if(e.Column == gridColumnGroup)
{
var el = e.EditingElement as ComboBox;
DictionaryEntry selectedItem = (DictionaryEntry) el.SelectedItem;
MessageCore.CoreFlags coreFlag = (MessageCore.CoreFlags) Enum.Parse(typeof(MessageCore.CoreFlags), selectedItem.Value.ToString());
MessageCore editedCore = this.filteredResult[e.Row.GetIndex()];
// clear all first
editedCore.SetFlag(false, MessageCore.CoreFlags.MAERSK_BHV);
editedCore.SetFlag(false, MessageCore.CoreFlags.SEAGO_BHV);
editedCore.SetFlag(false, MessageCore.CoreFlags.SEAGO_WHV);
editedCore.SetFlag(false, MessageCore.CoreFlags.HOEGH);
if (coreFlag != MessageCore.CoreFlags.NONE)
{
editedCore.SetFlag(true, coreFlag);
}
// buttonSaveChanges.IsEnabled = true;
editedCore.IsDirty = true;
}
if(e.Column == gridColumnATA)
{
var el = e.EditingElement as System.Windows.Controls.TextBox;
if(DateTime.TryParse(el.Text, out DateTime localATA))
{
MessageCore editedCore = this.filteredResult[e.Row.GetIndex()];
editedCore.ATA = DateTime.SpecifyKind(localATA, DateTimeKind.Local).ToUniversalTime();
// buttonSaveChanges.IsEnabled = true;
editedCore.IsDirty = true;
}
else
{
el.Text = string.Empty;
e.Cancel = true;
}
}
*/
}
}
#endregion
#region private methods
/// <summary>
/// "Status" of a Maersk Data element is a momentary evaluation that is relevant for display purposes only
/// It is not saved
/// </summary>
private void UpdateStatus(MaerskData md)
{
// here we set the following: NO_ID, NO_ID_AND_DUE, ID, NO_ETA and DONE
// the other status are set during active processing
if(md.ETA.HasValue)
{
if((md.ETA.Value - DateTime.Now).TotalSeconds > 0) // future
{
if(!md.ColM.IsNullOrEmpty() || ((md.MessageCore != null) && (!md.MessageCore.VisitId.IsNullOrEmpty())))
{
md.Status = MaerskData.MDStatus.ID;
}
else
{
if(md.ETA.Value.IsNextXDays(4))
{
md.Status = MaerskData.MDStatus.NO_ID_AND_DUE;
}
else
{
md.Status = MaerskData.MDStatus.NO_ID;
}
}
}
else // past
{
md.Status = MaerskData.MDStatus.DONE;
}
}
else
{
// no ETA means done
md.Status = MaerskData.MDStatus.NO_ETA;
}
}
private async void PerformSearch()
{
busyControl.BusyState = Util.UIHelper.BusyStateEnum.BUSY;
Dictionary<MessageCore.SearchFilterType, string> filterDict = new Dictionary<MessageCore.SearchFilterType, string>();
// Die Suche findet in dem eingestellten Intervall statt
uint from = this.dateTimePickerFrom.SelectedDate.Value.ToUniversalTime().ToUnixTimeStamp();
DateTime toDate = this.dateTimePickerTo.SelectedDate.Value.ToUniversalTime().Add(new TimeSpan(23, 59, 59));
uint to = toDate.ToUnixTimeStamp();
filterDict.Add(MessageCore.SearchFilterType.FILTER_ETA, string.Format("{0}:{1}", from.ToString() ?? "", to.ToString() ?? ""));
// eingeschränkt auf flags
filterDict.Add(MessageCore.SearchFilterType.FILTER_FLAG_EQ, "0");
// suche auslösen
List<MessageCore> searchResult = DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).GetMessageCoresWithFilters(filterDict);
// alle anderen Häfen weg
searchResult.RemoveAll(item => (item.PoC == null) || (!item.PoC.Equals(PortLocode)));
// alles entfernen was keine Maersk Xtra-Data hat (=noch nicht schon einmal importiert wurde)
foreach(MessageCore core in searchResult)
{
MaerskData md = await DBManagerAsync.LoadMaerskDataForCoreAsync(core.Id.Value);
if(md != null)
{
md.MessageCore = core;
md.MessageCoreId = core.Id.Value;
this.UpdateStatus(md);
if(!maerskDataList.Contains(md)) // DatabaseEntity implements IEquatable
this.maerskDataList.Add(md);
}
}
this.TimeFilterItemSource();
// this.SortItemSource();
this.dataGridPOCores.SelectedItem = null;
busyControl.BusyState = Util.UIHelper.BusyStateEnum.NEUTRAL;
}
private string ReadFieldAsString(IExcelDataReader reader, int fieldNum)
{
if (fieldNum >= reader.FieldCount) return null;
if (reader.GetFieldType(fieldNum) == typeof(string))
return reader.GetString(fieldNum).Clean();
if (reader.GetFieldType(fieldNum) == typeof(DateTime))
return reader.GetDateTime(fieldNum).ToString();
if (reader.GetFieldType(fieldNum) == typeof(int))
return reader.GetInt32(fieldNum).ToString();
if (reader.GetFieldType(fieldNum) == typeof(double))
return ((int) reader.GetDouble(fieldNum)).ToString();
Type theType = reader.GetFieldType(fieldNum);
return null;
}
private void TimeFilterItemSource()
{
List<MaerskData> removeList = new List<MaerskData>();
foreach (MaerskData md in this.maerskDataList)
{
if (md.ETA.HasValue)
{
if (this.dateTimePickerFrom.SelectedDate.HasValue && (md.ETA.Value < this.dateTimePickerFrom.SelectedDate.Value))
removeList.Add(md);
if (this.dateTimePickerTo.SelectedDate.HasValue) {
DateTime toDate = this.dateTimePickerTo.SelectedDate.Value.ToUniversalTime().Add(new TimeSpan(23, 59, 59));
if(md.ETA.Value > toDate)
removeList.Add(md);
}
}
}
foreach (MaerskData md in removeList)
this.maerskDataList.Remove(md);
}
private void SortItemSource()
{
ObservableCollection<MaerskData> temp;
temp = new ObservableCollection<MaerskData>(this.maerskDataList.OrderBy(p => p.ColA));
this.maerskDataList.Clear();
foreach (MaerskData md in temp)
this.maerskDataList.Add(md);
}
#endregion
#region button event handler
private void buttonLoad_Click(object sender, RoutedEventArgs e)
{
Util.UIHelper.SetBusyState();
this.PerformSearch();
}
private async void buttonImport_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog
{
Filter = "Excel Files|*.xls;*.xlsx"
};
if (ofd.ShowDialog() ?? false)
{
FileStream stream;
try
{
stream = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
using (IExcelDataReader reader = ExcelReaderFactory.CreateReader(stream))
{
List<MaerskData> importData = new List<MaerskData>();
uint emptyRowCnt = 0;
bool isFirstRow = true;
try
{
while (reader.Read())
{
if (isFirstRow)
{
isFirstRow = false; // this must be a header row, skip
continue;
}
if (reader.FieldCount < 13)
{
throw new InvalidDataException("Sheet must have 13 columns of data");
}
MaerskData md = new MaerskData();
if (!reader.IsDBNull(0))
{
if (reader.GetFieldType(0) == typeof(DateTime))
{
md.ETA = reader.GetDateTime(0);
md.ColA = md.ETA.ToString();
}
else
{
md.ColA = reader.GetString(0);
if (DateTime.TryParse(md.ColA, out DateTime aDateTime))
md.ETA = aDateTime;
}
}
if (!reader.IsDBNull(1)) md.ColB = ReadFieldAsString(reader, 1);
if (!reader.IsDBNull(2)) md.ColC = ReadFieldAsString(reader, 2);
if (!reader.IsDBNull(3)) md.ColD = ReadFieldAsString(reader, 3);
if (!reader.IsDBNull(4)) md.ColE = ReadFieldAsString(reader, 4);
if (!reader.IsDBNull(5)) md.ColF = ReadFieldAsString(reader, 5);
if (!reader.IsDBNull(6)) md.ColG = ReadFieldAsString(reader, 6);
if (!reader.IsDBNull(7)) md.ColH = ReadFieldAsString(reader, 7);
if (!reader.IsDBNull(8)) md.ColI = ReadFieldAsString(reader, 8);
if (md.ColI != null)
{
if ((md.ColI.Contains("bremerhaven", StringComparison.OrdinalIgnoreCase) && this.PortLocode.Equals("DEWVN")) ||
(md.ColI.Contains("eurogate", StringComparison.OrdinalIgnoreCase) && this.PortLocode.Equals("DEBRV")))
throw new InvalidOperationException($"{md.ColI} found in import to {PortLocode}, this is probably an error. Aborting import");
}
if (!reader.IsDBNull(9)) md.ColJ = ReadFieldAsString(reader, 9);
if (md.ColJ == null) continue;
if (!(md.ColJ.Equals("msk", StringComparison.OrdinalIgnoreCase) || md.ColJ.Equals("sgl", StringComparison.OrdinalIgnoreCase))) continue; // skip operator we are not interested in
if (!reader.IsDBNull(10)) md.ColK = ReadFieldAsString(reader, 10);
if (!reader.IsDBNull(11)) md.ColL = ReadFieldAsString(reader, 11);
if (!reader.IsDBNull(12)) md.ColM = ReadFieldAsString(reader, 12);
if (!reader.IsDBNull(13)) md.Remark = ReadFieldAsString(reader, 13);
if (!md.ColF.IsNullOrEmpty()) // only add this if IMO is set
importData.Add(md);
else
emptyRowCnt++;
if (emptyRowCnt > MAX_EMPTY_ROWS_ON_IMPORT) break;
if (isFirstRow) isFirstRow = false;
}
}
catch (Exception ex)
{
MessageBox.Show("Error reading Excel: " + ex.Message, Properties.Resources.textCaptionError, MessageBoxButton.OK, MessageBoxImage.Error);
}
if (importData.Count > 0)
{
busyControl.BusyState = Util.UIHelper.BusyStateEnum.BUSY;
foreach (MaerskData md in importData)
{
if (this.maerskDataList.Contains(md))
{
// update record with imported record
MaerskData foundData = this.maerskDataList.First((m) => (m.ColF != null) ? m.ColF.Equals(md.ColF) : (md.ColF == null) &&
(m.ColG != null) ? m.ColG.Equals(md.ColG) : (md.ColG == null) &&
(m.ColH != null) ? m.ColH.Equals(md.ColH) : (md.ColH == null));
if(foundData.ETA.HasValue && ((foundData.ETA.Value - DateTime.Now).TotalSeconds > 0) && foundData.Update(md))
foundData.Status = MaerskData.MDStatus.UPDATED;
}
else
{
if (!md.ColM.IsNullOrEmpty())
{
md.MessageCore = await DBManagerAsync.LoadCoreByVisitIdAsync(md.ColM);
}
this.UpdateStatus(md);
maerskDataList.Add(md);
}
}
this.TimeFilterItemSource();
// this.SortItemSource();
busyControl.BusyState = Util.UIHelper.BusyStateEnum.NEUTRAL;
}
this.dataGridPOCores.Items.Refresh();
}
stream.Close();
}
}
private void buttonExport_Click(object sender, RoutedEventArgs e)
{
// Export of the current collection
string predefFilename = string.Format("{0}_{1}.xlsx", this.PortLocode, DateTime.Today.ToString("yyyyMMdd"));
SaveFileDialog sfd = new SaveFileDialog()
{
Filter = "Excel Files|*.xlsx;*.xls",
FileName = predefFilename
};
if(sfd.ShowDialog() ?? false)
{
Util.UIHelper.SetBusyState();
ExcelManager em = new ExcelManager();
try
{
List<MaerskData> exportList = new List<MaerskData>(this.maerskDataList);
em.ExportMaersk(exportList, sfd.FileName);
Process.Start(sfd.FileName);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Export failed", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
/*
private async void buttonSave_Click(object sender, RoutedEventArgs e)
{
busyControl.BusyState = Util.UIHelper.BusyStateEnum.BUSY;
// save the current list to DB (only if the entries have matching cores!)
foreach(MaerskData md in this.maerskDataList)
{
if(md.MessageCore != null)
{
await DBManagerAsync.Save(md);
}
}
busyControl.BusyState = Util.UIHelper.BusyStateEnum.NEUTRAL;
}
*/
private async void buttonRequestIds_Click(object sender, RoutedEventArgs e)
{
// find all entries from now until 4 days into the future and track parallel requests
List<MaerskData> requestList = new List<MaerskData>();
if (sender == this.buttonRequestIds)
{
foreach (MaerskData md in this.dataGridPOCores.SelectedItems)
{
if (md.MessageCore?.VisitId.IsNullOrEmpty() == false) continue; // already requested
if (md.ColM?.IsNullOrEmpty() == false) continue; // already something there
requestList.Add(md);
}
}
if(sender == this.buttonRequestPlus3)
{
foreach(MaerskData md in this.maerskDataList)
{
if(((md.MessageCore == null) && md.ColM.IsNullOrEmpty()) ||
((md.MessageCore != null) && md.MessageCore.VisitId.IsNullOrEmpty()))
{
if (md.ETA.HasValue && md.ETA.Value.IsNextXDays(4))
requestList.Add(md);
}
}
}
if(requestList.Count == 0)
{
MessageBox.Show("No valid rows selected", "Warning", MessageBoxButton.OK, MessageBoxImage.Exclamation);
}
else
{
busyControl.BusyState = Util.UIHelper.BusyStateEnum.BUSY;
foreach (MaerskData md in requestList)
{
md.Status = MaerskData.MDStatus.REQUESTING_ID;
// create MessageCore and message classes
md.MessageCore = new MessageCore();
md.MessageCore.InitialHIS = Message.NSWProvider.DBH_MAERSK;
md.MessageCore.IMO = md.ColF;
md.MessageCore.ETA = md.ETA;
md.MessageCore.IsTransit = false;
md.MessageCore.PoC = this.PortLocode;
md.MessageCore.Portname = LocodeDB.PortNameFromLocode(md.MessageCore.PoC);
md.MessageCore.BSMDStatusInternal = MessageCore.BSMDStatus.TOSEND;
md.MessageCore.Incoming = true;
md.MessageCore.DefaultReportingPartyId = App.UserId.Value;
await DBManagerAsync.Save(md.MessageCore);
md.MessageCoreId = md.MessageCore.Id.Value;
await DBManagerAsync.Save(md);
// Meldeklassen für neuen Anlauf erzeugen
// TODO: pre-set certain fields taken from Maersk data
await bsmd.database.Util.CreateMessagesForCoreAsync(md.MessageCore, null);
// watchdog registrieren
this._dbWatchDog.Register(md.MessageCore);
}
}
this.dataGridPOCores.Items.Refresh();
}
#endregion
#region grid event handler
private void dataGridPOCores_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (sender != null)
{
DataGrid grid = sender as DataGrid;
if (grid?.SelectedItems?.Count == 1)
{
MaerskData md = grid.SelectedItem as MaerskData;
if(md.MessageCore != null) {
Util.UIHelper.SetBusyState();
this.MessageCoreSelected?.Invoke(md.MessageCore);
}
}
}
}
#endregion
#region DateTime picker event handler
private void dateTimePickerFrom_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
{
if (sender == dateTimePickerFrom)
this.FromDateChanged?.Invoke(dateTimePickerFrom.SelectedDate.Value);
if (sender == dateTimePickerTo)
this.ToDateChanged?.Invoke(dateTimePickerTo.SelectedDate.Value);
}
#endregion
}
}

View File

@ -0,0 +1,24 @@
<UserControl x:Class="ENI2.Controls.MaerskOverviewControl"
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:local="clr-namespace:ENI2.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Maersk lists" />
<TabControl x:Name="tabControlMaersk" Grid.Row="1">
<TabItem Name="tabItemBRV" Header="DEBRV">
<local:MaerskListControl x:Name="brvListControl" />
</TabItem>
<TabItem Name="tabItemWVN" Header="DEWVN">
<local:MaerskListControl x:Name="wvnListControl" />
</TabItem>
</TabControl>
</Grid>
</UserControl>

View File

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Windows.Controls;
namespace ENI2.Controls
{
/// <summary>
/// Interaction logic for MaerskOverviewControl.xaml
/// </summary>
public partial class MaerskOverviewControl : UserControl
{
public MaerskOverviewControl()
{
InitializeComponent();
this.brvListControl.PortLocode = "DEBRV";
this.wvnListControl.PortLocode = "DEWVN";
this.brvListControl.FromDateChanged += BrvListControl_FromDateChanged;
this.brvListControl.ToDateChanged += BrvListControl_ToDateChanged;
this.wvnListControl.FromDateChanged += WvnListControl_FromDateChanged;
this.wvnListControl.ToDateChanged += WvnListControl_ToDateChanged;
}
private void WvnListControl_ToDateChanged(System.DateTime date)
{
this.brvListControl.ToDate = date;
}
private void WvnListControl_FromDateChanged(System.DateTime date)
{
this.brvListControl.FromDate = date;
}
private void BrvListControl_ToDateChanged(System.DateTime date)
{
this.wvnListControl.ToDate = date;
}
private void BrvListControl_FromDateChanged(System.DateTime date)
{
this.wvnListControl.FromDate = date;
}
public List<MaerskListControl> ListControls
{
get
{
return new List<MaerskListControl>() { this.brvListControl, this.wvnListControl };
}
}
}
}

View File

@ -1,56 +0,0 @@
<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 BRV/WHV" 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 x:Name="gridColumnATA" Header="ATA" Binding="{Binding POATA, StringFormat=\{0:dd.MM.yyyy\}, Mode=TwoWay, Converter={util:UtcToLocalDateTimeConverter}}" IsReadOnly="False" />
<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

@ -1,278 +0,0 @@
// Copyright (c) 2017 schick Informatik
// Description: PO Nummer Übersicht. Ergänzung Nummern. Excel Export
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
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 BRV/WHV",
"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)
{
if (this.filteredResult.Count == 0) return;
OpenFileDialog ofd = new OpenFileDialog
{
Filter = "Excel Files|*.xls;*.xlsx"
};
if (ofd.ShowDialog() ?? false)
{
try
{
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.DisplayAlerts = false;
Workbook workBook = excelApp.Workbooks.Open(ofd.FileName);
Worksheet workSheet = workBook.Worksheets[1];
int rowIndex = 3;
foreach(MessageCore core in this.filteredResult)
{
workSheet.Cells[rowIndex, 7].Value = core.Shipname;
workSheet.Cells[rowIndex, 10].Value = core.PoC.Substring(2);
if(core.POATA.HasValue)
workSheet.Cells[rowIndex, 11].Value = core.POATA.Value.ToShortDateString();
workSheet.Cells[rowIndex, 13].Value = core.PONumber;
rowIndex++;
}
workBook.Save();
workBook.Close();
Marshal.ReleaseComObject(workBook);
excelApp.Quit();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
}
}
private void buttonSaveChanges_Click(object sender, RoutedEventArgs e)
{
foreach(MessageCore messageCore in this.filteredResult)
{
if (messageCore.IsDirty)
{
DBManager.Instance.Save(messageCore);
messageCore.IsDirty = false;
// load ATA for this Core
/* DAS ATA WIRD JETZT NICHT MEHR IN DIE MELDEKLASSE GESPEICHERT
Message ataMessage = DBManager.Instance.GetMessage(messageCore, Message.NotificationClass.ATA);
if(ataMessage?.Elements.Count == 1)
{
if(messageCore.ATA != ((ATA)ataMessage.Elements[0]).ATAPortOfCall)
{
((ATA)ataMessage.Elements[0]).ATAPortOfCall = messageCore.ATA;
DBManager.Instance.Save(ataMessage.Elements[0]);
}
}
*/
}
}
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;
case 4: if (core.IsFlagSet(MessageCore.CoreFlags.HOEGH)) 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 System.Windows.Controls.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;
}
}
if(e.Column == gridColumnGroup)
{
var el = e.EditingElement as ComboBox;
DictionaryEntry selectedItem = (DictionaryEntry) el.SelectedItem;
MessageCore.CoreFlags coreFlag = (MessageCore.CoreFlags) Enum.Parse(typeof(MessageCore.CoreFlags), selectedItem.Value.ToString());
MessageCore editedCore = this.filteredResult[e.Row.GetIndex()];
// clear all first
editedCore.SetFlag(false, MessageCore.CoreFlags.MAERSK_BHV);
editedCore.SetFlag(false, MessageCore.CoreFlags.SEAGO_BHV);
editedCore.SetFlag(false, MessageCore.CoreFlags.SEAGO_WHV);
editedCore.SetFlag(false, MessageCore.CoreFlags.HOEGH);
if (coreFlag != MessageCore.CoreFlags.NONE)
{
editedCore.SetFlag(true, coreFlag);
}
buttonSaveChanges.IsEnabled = true;
editedCore.IsDirty = true;
}
if(e.Column == gridColumnATA)
{
var el = e.EditingElement as System.Windows.Controls.TextBox;
if(DateTime.TryParse(el.Text, out DateTime localATA))
{
MessageCore editedCore = this.filteredResult[e.Row.GetIndex()];
editedCore.ATA = DateTime.SpecifyKind(localATA, DateTimeKind.Local).ToUniversalTime();
buttonSaveChanges.IsEnabled = true;
editedCore.IsDirty = true;
}
else
{
el.Text = string.Empty;
e.Cancel = true;
}
}
}
}
#endregion
#region private methods
private void PerformSearch()
{
this.dataGridPOCores.ItemsSource = null;
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));
// Die Suche findet in einem erweiterten Intervall statt, da später wenn möglich nach ATA gefiltert wird
uint from = start.Subtract(new TimeSpan(10, 0, 0, 0)).ToUniversalTime().ToUnixTimeStamp();
uint to = end.Add(new TimeSpan(5, 0, 0, 0)).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 == null) || (!item.PoC.Equals("DEBRV") && !item.PoC.Equals("DEWHV") && !item.PoC.Equals("DEWVN")));
// rückwärts iterieren um nach ETA und ATA zu filtern
if (this.searchResult.Count > 0)
{
for (int i = this.searchResult.Count - 1; i >= 0; i--)
{
MessageCore messageCore = this.searchResult[i];
if (messageCore.ATA.HasValue)
{
if ((messageCore.ATA.Value < start) || (messageCore.ATA.Value > end))
{
this.searchResult.RemoveAt(i);
}
else
{
if(!messageCore.POATA.HasValue)
{
messageCore.POATA = messageCore.ATA;
messageCore.IsDirty = true;
this.buttonSaveChanges.IsEnabled = true;
}
}
}
else
{
if ((messageCore.ETA.Value < start) || (messageCore.ETA.Value > end)) this.searchResult.RemoveAt(i);
}
}
}
searchResult.Sort((x, y) => DateTime.Compare(x.ATA ?? DateTime.MaxValue, y.ATA ?? DateTime.MaxValue));
this.dataGridPOCores.SelectedItem = null;
this.filteredResult.AddRange(searchResult);
this.dataGridPOCores.ItemsSource = this.filteredResult;
}
#endregion
}
}

View File

@ -787,7 +787,6 @@ namespace ENI2.DetailViewControls
if (sfd.ShowDialog() ?? false) if (sfd.ShowDialog() ?? false)
{ {
Util.UIHelper.SetBusyState(); Util.UIHelper.SetBusyState();
ExcelManager em = new ExcelManager(); ExcelManager em = new ExcelManager();
try try

View File

@ -36,8 +36,8 @@
<MinimumRequiredVersion>5.4.0.0</MinimumRequiredVersion> <MinimumRequiredVersion>5.4.0.0</MinimumRequiredVersion>
<CreateWebPageOnPublish>true</CreateWebPageOnPublish> <CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>publish.html</WebPage> <WebPage>publish.html</WebPage>
<ApplicationRevision>2</ApplicationRevision> <ApplicationRevision>11</ApplicationRevision>
<ApplicationVersion>7.8.1.%2a</ApplicationVersion> <ApplicationVersion>7.9.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut> <CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted> <PublishWizardCompleted>true</PublishWizardCompleted>
@ -218,6 +218,9 @@
<Compile Include="..\bsmd.ExcelReadService\LocodeDB.cs"> <Compile Include="..\bsmd.ExcelReadService\LocodeDB.cs">
<Link>Locode\LocodeDB.cs</Link> <Link>Locode\LocodeDB.cs</Link>
</Compile> </Compile>
<Compile Include="Controls\BusyControl.xaml.cs">
<DependentUpon>BusyControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\ClosableTabItem.cs" /> <Compile Include="Controls\ClosableTabItem.cs" />
<Compile Include="Controls\ConditionGroupControl.xaml.cs"> <Compile Include="Controls\ConditionGroupControl.xaml.cs">
<DependentUpon>ConditionGroupControl.xaml</DependentUpon> <DependentUpon>ConditionGroupControl.xaml</DependentUpon>
@ -228,6 +231,9 @@
<Compile Include="Controls\LocodeControl.xaml.cs"> <Compile Include="Controls\LocodeControl.xaml.cs">
<DependentUpon>LocodeControl.xaml</DependentUpon> <DependentUpon>LocodeControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\MaerskOverviewControl.xaml.cs">
<DependentUpon>MaerskOverviewControl.xaml</DependentUpon>
</Compile>
<Compile Include="EditControls\CompareExcelDialog.xaml.cs"> <Compile Include="EditControls\CompareExcelDialog.xaml.cs">
<DependentUpon>CompareExcelDialog.xaml</DependentUpon> <DependentUpon>CompareExcelDialog.xaml</DependentUpon>
</Compile> </Compile>
@ -248,9 +254,10 @@
<Compile Include="Excel\ExcelComparer.cs" /> <Compile Include="Excel\ExcelComparer.cs" />
<Compile Include="Excel\ExcelManager.cs" /> <Compile Include="Excel\ExcelManager.cs" />
<Compile Include="Excel\ExcelReader.cs" /> <Compile Include="Excel\ExcelReader.cs" />
<Compile Include="Excel\ExcelSimpleWriter.cs" />
<Compile Include="Excel\ExcelUtil.cs" /> <Compile Include="Excel\ExcelUtil.cs" />
<Compile Include="Controls\POListControl.xaml.cs"> <Compile Include="Controls\MaerskListControl.xaml.cs">
<DependentUpon>POListControl.xaml</DependentUpon> <DependentUpon>MaerskListControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\ReportingPartyControl.xaml.cs"> <Compile Include="Controls\ReportingPartyControl.xaml.cs">
<DependentUpon>ReportingPartyControl.xaml</DependentUpon> <DependentUpon>ReportingPartyControl.xaml</DependentUpon>
@ -450,6 +457,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\BusyControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\ConditionGroupControl.xaml"> <Page Include="Controls\ConditionGroupControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -458,7 +469,11 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\POListControl.xaml"> <Page Include="Controls\MaerskOverviewControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\MaerskListControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
@ -838,6 +853,11 @@
<Resource Include="Resources\logo_eni.png" /> <Resource Include="Resources\logo_eni.png" />
<Resource Include="Resources\import1.png" /> <Resource Include="Resources\import1.png" />
<Resource Include="Resources\import2.png" /> <Resource Include="Resources\import2.png" />
<Resource Include="Resources\about.png" />
<Resource Include="Resources\document_into.png" />
<Resource Include="Resources\document_plain_new.png" />
<Resource Include="Resources\exit.png" />
<Resource Include="Resources\document_exchange.png" />
<Content Include="x64\SQLite.Interop.dll"> <Content Include="x64\SQLite.Interop.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>

View File

@ -31,7 +31,7 @@ namespace ENI2.EditControls
#region Drag&Drop event handler #region Drag&Drop event handler
private async void imageSource_Drop(object sender, DragEventArgs e) private void imageSource_Drop(object sender, DragEventArgs e)
{ {
string[] files = (string[]) e.Data.GetData(DataFormats.FileDrop); string[] files = (string[]) e.Data.GetData(DataFormats.FileDrop);
if (files != null) if (files != null)

View File

@ -97,6 +97,15 @@ namespace ENI2.EditControls
private void LocodePoC_PropertyChanged(object sender, PropertyChangedEventArgs e) private void LocodePoC_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
this.CheckComplete(); this.CheckComplete();
string locode = this.locodePoC.LocodeValue;
if ((locode != null) && (locode.Equals("DEBRV") || locode.Equals("DEBRE")))
{
this.comboBoxInitialHIS.SelectedValue = Message.NSWProvider.DBH;
}
else
{
this.comboBoxInitialHIS.SelectedValue = Message.NSWProvider.DUDR;
}
} }
private void doubleUpDownIMO_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<object> e) private void doubleUpDownIMO_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<object> e)

View File

@ -11,7 +11,7 @@ Copyright (c) 2017 schick Informatik
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:p="clr-namespace:ENI2.Properties" xmlns:p="clr-namespace:ENI2.Properties"
mc:Ignorable="d" mc:Ignorable="d"
Title="{x:Static p:Resources.textLadg}" Height="246" Width="900" WindowStyle="SingleBorderWindow" Background="AliceBlue"> Title="{x:Static p:Resources.textLadg}" Height="300" Width="900" WindowStyle="SingleBorderWindow" Background="AliceBlue">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="28" /> <RowDefinition Height="28" />

View File

@ -37,6 +37,9 @@ namespace ENI2.EditControls
this.comboBoxInitialHIS.ItemsSource = comboDataSource; this.comboBoxInitialHIS.ItemsSource = comboDataSource;
this.comboBoxInitialHIS.SelectedIndex = 0; this.comboBoxInitialHIS.SelectedIndex = 0;
} }
public bool ValidId { get; set; } public bool ValidId { get; set; }
@ -54,6 +57,14 @@ namespace ENI2.EditControls
private void textBoxVisitTransitId_TextChanged(object sender, TextChangedEventArgs e) private void textBoxVisitTransitId_TextChanged(object sender, TextChangedEventArgs e)
{ {
this.CheckComplete(); this.CheckComplete();
if(textBoxVisitTransitId.Text.StartsWith("DEBRE") || textBoxVisitTransitId.Text.StartsWith("DEBRV"))
{
this.comboBoxInitialHIS.SelectedValue = Message.NSWProvider.DBH;
}
else
{
this.comboBoxInitialHIS.SelectedValue = Message.NSWProvider.DUDR;
}
} }
private void CheckComplete() private void CheckComplete()

View File

@ -78,7 +78,7 @@ namespace ENI2.EditControls
private void doubleUpDownIMO_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e) private void doubleUpDownIMO_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{ {
bool hasValue = (doubleUpDownIMO.Value.HasValue && doubleUpDownIMO.Value > 0); bool hasValue = doubleUpDownIMO.Value.HasValue && doubleUpDownIMO.Value > 0;
doubleUpDownENI.IsReadOnly = hasValue; doubleUpDownENI.IsReadOnly = hasValue;
this.CheckComplete(); this.CheckComplete();
@ -88,7 +88,7 @@ namespace ENI2.EditControls
private void doubleUpDownENI_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e) private void doubleUpDownENI_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{ {
bool hasValue = (doubleUpDownENI.Value.HasValue && doubleUpDownENI.Value > 0); bool hasValue = doubleUpDownENI.Value.HasValue && doubleUpDownENI.Value > 0;
doubleUpDownIMO.IsReadOnly = hasValue; doubleUpDownIMO.IsReadOnly = hasValue;
this.CheckComplete(); this.CheckComplete();
} }
@ -96,6 +96,15 @@ namespace ENI2.EditControls
private void LocodePoC_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) private void LocodePoC_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{ {
this.CheckComplete(); this.CheckComplete();
string locode = this.locodePoC.LocodeValue;
if((locode != null) && (locode.Equals("DEBRV") || locode.Equals("DEBRE")))
{
this.comboBoxInitialHIS.SelectedValue = Message.NSWProvider.DBH;
}
else
{
this.comboBoxInitialHIS.SelectedValue = Message.NSWProvider.DUDR;
}
} }
private void datePickerETA_SelectedDateChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) private void datePickerETA_SelectedDateChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
@ -128,7 +137,7 @@ namespace ENI2.EditControls
isComplete &= validLocode; isComplete &= validLocode;
isComplete &= (comboBoxInitialHIS.SelectedValue != null); isComplete &= comboBoxInitialHIS.SelectedValue != null;
this.EnableOK(isComplete); this.EnableOK(isComplete);
} }

View File

@ -80,11 +80,16 @@ namespace ENI2.Excel
resultMessage = ""; resultMessage = "";
// Create ExcelWriter // Create ExcelWriter
using (ExcelWriter ew = new ExcelWriter(fileName, isRefSheet)) using (ExcelWriter ew = new ExcelWriter(isRefSheet))
{ {
ew.WriteData(messages, core, out resultMessage, isRefSheet); ew.WriteData(messages, core, out resultMessage, isRefSheet);
ew.Save(fileName); ew.Save(fileName);
} }
} }
internal void ExportMaersk(List<MaerskData> exportList, string fileName)
{
ExcelSimpleWriter.WriteMaerskList(fileName, exportList);
}
} }
} }

View File

@ -289,6 +289,15 @@ namespace ENI2.Excel
if (val.IndexOf("sbt", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; if (val.IndexOf("sbt", StringComparison.OrdinalIgnoreCase) >= 0) result = 1;
if (val.IndexOf("single", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; if (val.IndexOf("single", StringComparison.OrdinalIgnoreCase) >= 0) result = 0;
if (val.IndexOf("double", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; if (val.IndexOf("double", StringComparison.OrdinalIgnoreCase) >= 0) result = 2;
if (!result.HasValue)
{
if (int.TryParse(val, out int parsed))
{
if ((parsed < 4) && (parsed > 0))
result = (byte)(parsed - 1);
}
}
} }
if (!result.HasValue) if (!result.HasValue)
@ -347,6 +356,15 @@ namespace ENI2.Excel
if (val.IndexOf("full", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; if (val.IndexOf("full", StringComparison.OrdinalIgnoreCase) >= 0) result = 0;
if (val.IndexOf("empty", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; if (val.IndexOf("empty", StringComparison.OrdinalIgnoreCase) >= 0) result = 1;
if (val.IndexOf("inerted", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; if (val.IndexOf("inerted", StringComparison.OrdinalIgnoreCase) >= 0) result = 2;
if (!result.HasValue)
{
if (int.TryParse(val, out int parsed))
{
if ((parsed < 4) && (parsed > 0))
result = (byte)(parsed - 1);
}
}
} }
if (!result.HasValue) if (!result.HasValue)
@ -535,12 +553,12 @@ namespace ENI2.Excel
} }
} }
if (val is string) if (val is string @string)
{ {
if (((string)val).EndsWith("lt", StringComparison.OrdinalIgnoreCase)) if (@string.EndsWith("lt", StringComparison.OrdinalIgnoreCase))
val = ((string)val).Substring(0, ((string)val).Length - 2).Trim(); val = @string.Substring(0, @string.Length - 2).Trim();
else else
val = ((string)val).Trim(); val = @string.Trim();
} }
if (result == null) if (result == null)

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using bsmd.database;
namespace ENI2.Excel
{
static class ExcelSimpleWriter
{
public static void WriteMaerskList(string filename, List<MaerskData> data)
{
Application excelApp = new Application();
excelApp.DisplayAlerts = false;
excelApp.Visible = false;
Workbook wb = excelApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
Worksheet ws = wb.Worksheets[1];
// Überschriften erste Zeile
ws.Cells[1, 1] = "ETA";
ws.Cells[1, 2] = "ETD";
ws.Cells[1, 3] = "Rotation name";
ws.Cells[1, 4] = "Vessel code";
ws.Cells[1, 5] = "Vessel name";
ws.Cells[1, 6] = "IMO";
ws.Cells[1, 7] = "Arr voy";
ws.Cells[1, 8] = "Dep voy";
ws.Cells[1, 9] = "Terminal name";
ws.Cells[1, 10] = "Operator code";
ws.Cells[1, 11] = "Pro arr";
ws.Cells[1, 12] = "Pro dep";
ws.Cells[1, 13] = "ID";
ws.Cells[1, 14] = "Remark";
for (int i = 0; i < data.Count; i++)
{
MaerskData md = data[i];
ws.Cells[i + 2, 1].NumberFormat = "TT/hh:mm";
ws.Cells[i + 2, 1] = md.ColA;
ws.Cells[i + 2, 2].NumberFormat = "TT/hh:mm";
ws.Cells[i + 2, 2] = md.ColB;
ws.Cells[i + 2, 3] = md.ColC;
ws.Cells[i + 2, 4] = md.ColD;
ws.Cells[i + 2, 5] = md.ColE;
ws.Cells[i + 2, 6] = md.ColF;
ws.Cells[i + 2, 7] = md.ColG;
ws.Cells[i + 2, 8] = md.ColH;
ws.Cells[i + 2, 9] = md.ColI;
ws.Cells[i + 2, 10] = md.ColJ;
ws.Cells[i + 2, 11] = md.ColK;
ws.Cells[i + 2, 12] = md.ColL;
ws.Cells[i + 2, 13] = md.ColM ;
// ws.Cells[i + 2, 14] = md.Remark;
}
wb.SaveAs(filename, XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
wb.Saved = true;
wb.Close(0);
Marshal.ReleaseComObject(ws);
Marshal.ReleaseComObject(wb);
excelApp.Quit();
Marshal.ReleaseComObject(excelApp);
}
}
}

View File

@ -18,11 +18,9 @@ namespace ENI2.Excel
internal class ExcelWriter : ExcelBase internal class ExcelWriter : ExcelBase
{ {
#region Construction #region Construction
public ExcelWriter(string filePath, bool isRefSheet) public ExcelWriter(bool isRefSheet)
{ {
string filename = @"Excel\EU-NoAD-Data-Collecting-Tool-5_0.xlsx"; string filename = @"Excel\EU-NoAD-Data-Collecting-Tool-5_0.xlsx";
if (isRefSheet) filename = @"Excel\Reference_Sheet_DE.xlsx"; if (isRefSheet) filename = @"Excel\Reference_Sheet_DE.xlsx";
@ -194,6 +192,11 @@ namespace ENI2.Excel
} }
public void WriteMaerskList(List<MaerskData> maerskList)
{
}
#endregion #endregion
#region private excel field writing #region private excel field writing

View File

@ -59,38 +59,48 @@
</Grid> </Grid>
</xctk:BusyIndicator.BusyContent> </xctk:BusyIndicator.BusyContent>
<DockPanel Name="mainPanel"> <DockPanel Name="mainPanel">
<Grid DockPanel.Dock="Top" Height="80" Background="#FFE8F6FF"> <Menu DockPanel.Dock="Top" Background="#FFE8F6FF">
<Grid.ColumnDefinitions> <Menu.ItemsPanel>
<ColumnDefinition Width="auto" /> <ItemsPanelTemplate>
<ColumnDefinition Width="*" /> <DockPanel HorizontalAlignment="Stretch"/>
</Grid.ColumnDefinitions> </ItemsPanelTemplate>
<Image Grid.Column="0" x:Name="logoImage" HorizontalAlignment="Left" Height="75" Width="75" Source="Resources/EUREPORT.png" Stretch="Fill" MouseUp="logoImage_MouseUp" Margin="2"/> </Menu.ItemsPanel>
<Grid Grid.Column="1"> <MenuItem Header="_File">
<Grid.ColumnDefinitions> <MenuItem Header="_Create new Id" Click="buttonNewTransitIdClick">
<ColumnDefinition Width="auto"/> <MenuItem.Icon>
<ColumnDefinition Width="auto"/> <Image Source="Resources/document_plain_new.png" />
<ColumnDefinition Width="auto"/> </MenuItem.Icon>
<ColumnDefinition Width="auto"/> </MenuItem>
<ColumnDefinition Width="auto"/> <MenuItem Header="_New with Id" Click="buttonNewWithIdClick">
<ColumnDefinition Width="auto"/> <MenuItem.Icon>
<ColumnDefinition Width="*"/> <Image Source="Resources/document_into.png" />
</Grid.ColumnDefinitions> </MenuItem.Icon>
<Grid.RowDefinitions> </MenuItem>
<RowDefinition Height="28"/> <MenuItem Header="Compare _Excel sheets" Click="buttonCompareSheets_Click">
<RowDefinition Height="28"/> <MenuItem.Icon>
</Grid.RowDefinitions> <Image Source="Resources/document_exchange.png" />
<Button Grid.Column="0" x:Name="buttonNewId" Content="{x:Static p:Resources.textNewVisitTransitId}" HorizontalAlignment="Left" VerticalAlignment="Top" Click="buttonNewTransitIdClick" Background="Transparent" Margin="2,2,0,0" Grid.RowSpan="2"/> </MenuItem.Icon>
<Button Grid.Column="1" x:Name="buttonNewWithId" Content="{x:Static p:Resources.textNewWithId}" HorizontalAlignment="Left" VerticalAlignment="Top" Click="buttonNewWithIdClick" Background="Transparent" Margin="2,2,0,0" Grid.RowSpan="2"/> </MenuItem>
<RadioButton Grid.Column="2" 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" Grid.RowSpan="2" /> <Separator />
<RadioButton Grid.Column="3" 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" Grid.RowSpan="2" /> <MenuItem Header="Exit" Click="MenuItem_Click">
<RadioButton Grid.Column="4" 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" Grid.RowSpan="2"/> <MenuItem.Icon>
<RadioButton Grid.Column="5" 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" Grid.RowSpan="2" /> <Image Source="Resources/exit.png" />
<Button Grid.Column="6" x:Name="buttonCompareSheets" Content="{x:Static p:Resources.textCompareExcel}" HorizontalAlignment="Left" VerticalAlignment="Top" Click="buttonCompareSheets_Click" Background="Transparent" Margin="2,2,0,0" /> </MenuItem.Icon>
<Button Grid.Column="7" x:Name="buttonAbout" Content="?" HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" Margin="0,2,2,0" Padding="5,0,5,0" Click="buttonAbout_Click" Grid.RowSpan="2"/> </MenuItem>
<Label Grid.Column="0" Grid.Row="1" x:Name="labelStatusId" Grid.ColumnSpan="3" Margin="2,2,0,0" HorizontalAlignment="Left"/> </MenuItem>
</Grid> <MenuItem x:Name="menuItemNotifications" Header="{x:Static p:Resources.textNotifications}" Click="radioButton_Click" Background="LightBlue"/>
</Grid> <MenuItem x:Name="menuItemStatus" Header="{x:Static p:Resources.textServerStatus}" Click="radioButton_Click" />
<MenuItem x:Name="menuItemUserAdministration" Header="{x:Static p:Resources.textUserAdministration}" Click="radioButton_Click" Visibility="Hidden"/>
<MenuItem x:Name="menuItemMaersk" Header="{x:Static p:Resources.textPOLists}" Click="radioButton_Click" Visibility="Hidden" />
<MenuItem x:Name="labelStatusId" />
<MenuItem Header="Help" HorizontalAlignment="Right">
<MenuItem Header="About" Click="buttonAbout_Click">
<MenuItem.Icon>
<Image Source="Resources/about.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
<Grid DockPanel.Dock="Bottom" Height="22" Background="#FFE8F6FF"> <Grid DockPanel.Dock="Bottom" Height="22" Background="#FFE8F6FF">
<StatusBar> <StatusBar>
<StatusBar.ItemsPanel> <StatusBar.ItemsPanel>

View File

@ -1,28 +1,27 @@
// Copyright (c) 2017 schick Informatik // Copyright (c) 2017-present schick Informatik
// Description: The main application window // Description: The main application window
// //
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics; using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Threading; using System.Threading;
using System.Timers; using System.Text;
using log4net;
using bsmd.database; using bsmd.database;
using System.Windows.Controls;
using ENI2.Controls; using ENI2.Controls;
using ENI2.EditControls; using ENI2.EditControls;
using ENI2.Util; using ENI2.Util;
using log4net;
using System.ComponentModel;
using ENI2.Locode; using ENI2.Locode;
using System.Text;
namespace ENI2 namespace ENI2
{ {
@ -35,12 +34,11 @@ namespace ENI2
#region Fields #region Fields
private ReportingPartyControl rpControl; private ReportingPartyControl rpControl;
private POListControl poControl; private MaerskOverviewControl moControl;
private ServerStatusControl statusControl; private ServerStatusControl statusControl;
private readonly SucheControl sucheControl; private readonly SucheControl sucheControl;
private CompareExcelDialog compareExcelDialog; private CompareExcelDialog compareExcelDialog;
private bool efMode = false;
private bool dbConnected; private bool dbConnected;
private readonly ScaleTransform _transform = new ScaleTransform(1.0, 1.0); private readonly ScaleTransform _transform = new ScaleTransform(1.0, 1.0);
private readonly Dictionary<Guid, ClosableTabItem> openTabs = new Dictionary<Guid, ClosableTabItem>(); private readonly Dictionary<Guid, ClosableTabItem> openTabs = new Dictionary<Guid, ClosableTabItem>();
@ -51,6 +49,8 @@ namespace ENI2
private readonly DatabaseEntityWatchdog _dbWatchDog; private readonly DatabaseEntityWatchdog _dbWatchDog;
private readonly Dictionary<Guid, ShowIdDialog> showIdDict = new Dictionary<Guid, ShowIdDialog>(); private readonly Dictionary<Guid, ShowIdDialog> showIdDict = new Dictionary<Guid, ShowIdDialog>();
private MenuItem _selectedMenuItem; // simulate radio button logic
#endregion #endregion
#region Construction #region Construction
@ -71,6 +71,7 @@ namespace ENI2
App.SplashScreen.ShowMessage("done"); App.SplashScreen.ShowMessage("done");
Thread.Sleep(500); Thread.Sleep(500);
App.SplashScreen.LoadComplete(); App.SplashScreen.LoadComplete();
_selectedMenuItem = menuItemNotifications;
} }
#endregion #endregion
@ -81,6 +82,12 @@ namespace ENI2
{ {
if(aMessageCore != null) if(aMessageCore != null)
{ {
Dispatcher.BeginInvoke((Action)(() =>
{
this.radioButton_Click(this.menuItemNotifications, null);
}));
if (!openTabs.ContainsKey(aMessageCore.Id.Value)) if (!openTabs.ContainsKey(aMessageCore.Id.Value))
{ {
ClosableTabItem searchResultItem = new ClosableTabItem(); ClosableTabItem searchResultItem = new ClosableTabItem();
@ -247,12 +254,6 @@ namespace ENI2
#region Window control click event handler #region Window control click event handler
private void logoImage_MouseUp(object sender, MouseButtonEventArgs e)
{
if(efMode) Process.Start("http://www.eintracht-frankfurt.de/home.html");
else Process.Start("http://www.eureport.de/");
}
private void buttonAbout_Click(object sender, RoutedEventArgs e) private void buttonAbout_Click(object sender, RoutedEventArgs e)
{ {
AboutDialog ad = new AboutDialog(); AboutDialog ad = new AboutDialog();
@ -261,15 +262,21 @@ namespace ENI2
private void radioButton_Click(object sender, RoutedEventArgs e) private void radioButton_Click(object sender, RoutedEventArgs e)
{ {
this.rootContainer.Children.Clear(); if (sender == _selectedMenuItem) return; // same selected
bool newButtonsVisible = false;
if(sender == this.buttonNotifications) this.rootContainer.Children.Clear();
MenuItem mi = sender as MenuItem;
_selectedMenuItem.Background = mi.Background;
_selectedMenuItem = mi;
_selectedMenuItem.Background = Brushes.LightBlue;
if(sender == this.menuItemNotifications)
{ {
this.rootContainer.Children.Add(this.mainFrame); this.rootContainer.Children.Add(this.mainFrame);
newButtonsVisible = true;
} }
else if(sender == this.buttonUserAdmin) else if(sender == this.menuItemUserAdministration)
{ {
if (this.rpControl == null) if (this.rpControl == null)
{ {
@ -279,15 +286,17 @@ namespace ENI2
} }
this.rootContainer.Children.Add(this.rpControl); this.rootContainer.Children.Add(this.rpControl);
} }
else if(sender == this.buttonPOListe) else if(sender == this.menuItemMaersk)
{ {
if (this.poControl == null) if (this.moControl == null)
{ {
this.poControl = new POListControl(); this.moControl = new MaerskOverviewControl();
foreach (MaerskListControl mlc in this.moControl.ListControls)
mlc.MessageCoreSelected += this.AnmeldungenControl_MessageCoreSelected;
} }
this.rootContainer.Children.Add(poControl); this.rootContainer.Children.Add(moControl);
} }
else if(sender == this.buttonStatus) else if(sender == this.menuItemStatus)
{ {
if(this.statusControl == null) if(this.statusControl == null)
{ {
@ -295,9 +304,6 @@ namespace ENI2
} }
this.rootContainer.Children.Add(this.statusControl); this.rootContainer.Children.Add(this.statusControl);
} }
this.buttonNewId.Visibility = newButtonsVisible ? Visibility.Visible : Visibility.Hidden;
this.buttonNewWithId.Visibility = newButtonsVisible ? Visibility.Visible : Visibility.Hidden;
} }
private void buttonCompareSheets_Click(object sender, RoutedEventArgs ev) private void buttonCompareSheets_Click(object sender, RoutedEventArgs ev)
@ -328,11 +334,6 @@ namespace ENI2
labelGeneralStatus.Text = dbConnected ? "DB Connected" : "DB Connect failed"; labelGeneralStatus.Text = dbConnected ? "DB Connected" : "DB Connect failed";
labelVersion.Text = "V. " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; labelVersion.Text = "V. " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
labelUsername.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name; labelUsername.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
if (Keyboard.IsKeyDown(Key.LeftShift))
{
efMode = true;
logoImage.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/ef_logo.png"));
}
Microsoft.Win32.SystemEvents.SessionEnded += SystemEvents_SessionEnded; Microsoft.Win32.SystemEvents.SessionEnded += SystemEvents_SessionEnded;
} }
@ -609,6 +610,11 @@ namespace ENI2
} }
} }
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
#endregion #endregion
#region mouse wheel / zooming events #region mouse wheel / zooming events
@ -657,8 +663,8 @@ namespace ENI2
ReportingParty.CurrentReportingParty = this.userEntity; ReportingParty.CurrentReportingParty = this.userEntity;
if (this.userEntity.IsAdmin) if (this.userEntity.IsAdmin)
{ {
this.buttonUserAdmin.Visibility = Visibility.Visible; this.menuItemUserAdministration.Visibility = Visibility.Visible;
this.buttonPOListe.Visibility = Visibility.Visible; this.menuItemMaersk.Visibility = Visibility.Visible;
this.sucheControl.AdminMode = true; this.sucheControl.AdminMode = true;
} }
break; break;
@ -708,11 +714,11 @@ namespace ENI2
{ {
if(this.showIdDict.Count == 0) if(this.showIdDict.Count == 0)
{ {
this.labelStatusId.Content = ""; this.labelStatusId.Header = "";
} }
else else
{ {
this.labelStatusId.Content = string.Format("waiting for {0} id(s)..", this.showIdDict.Count); this.labelStatusId.Header = string.Format("waiting for {0} id(s)..", this.showIdDict.Count);
} }
} }

View File

@ -70,6 +70,16 @@ namespace ENI2.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
public static System.Drawing.Bitmap about {
get {
object obj = ResourceManager.GetObject("about", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -290,6 +300,26 @@ namespace ENI2.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
public static System.Drawing.Bitmap document_exchange {
get {
object obj = ResourceManager.GetObject("document_exchange", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
public static System.Drawing.Bitmap document_into {
get {
object obj = ResourceManager.GetObject("document_into", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -310,6 +340,16 @@ namespace ENI2.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
public static System.Drawing.Bitmap document_plain_new {
get {
object obj = ResourceManager.GetObject("document_plain_new", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -380,6 +420,16 @@ namespace ENI2.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
public static System.Drawing.Bitmap exit {
get {
object obj = ResourceManager.GetObject("exit", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>
@ -3733,7 +3783,7 @@ namespace ENI2.Properties {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to PO numbers. /// Looks up a localized string similar to Maersk.
/// </summary> /// </summary>
public static string textPOLists { public static string textPOLists {
get { get {

View File

@ -1709,7 +1709,7 @@
<value>IMO hazard class (Group)</value> <value>IMO hazard class (Group)</value>
</data> </data>
<data name="textPOLists" xml:space="preserve"> <data name="textPOLists" xml:space="preserve">
<value>PO numbers</value> <value>Maersk</value>
</data> </data>
<data name="textMaerskSeago" xml:space="preserve"> <data name="textMaerskSeago" xml:space="preserve">
<value>Maersk / SeaGo</value> <value>Maersk / SeaGo</value>
@ -1861,4 +1861,19 @@
<data name="textSpecialCaseBREBRV" xml:space="preserve"> <data name="textSpecialCaseBREBRV" xml:space="preserve">
<value>At least one of NOA_NOD, AGNT, INFO, SEC, TIEFA hasn't been sent for DEBRE/DEBRV: ({0}) Close anyway?</value> <value>At least one of NOA_NOD, AGNT, INFO, SEC, TIEFA hasn't been sent for DEBRE/DEBRV: ({0}) Close anyway?</value>
</data> </data>
<data name="about" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\about.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="document_exchange" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\document_exchange.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="document_into" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\document_into.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="document_plain_new" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\document_plain_new.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="exit" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\exit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

BIN
ENI2/Resources/about.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
ENI2/Resources/exit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -17,7 +17,8 @@
<Grid Grid.Row="0"> <Grid Grid.Row="0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="75" />
<ColumnDefinition Width="75" />
<ColumnDefinition Width="2*" /> <ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" />
<ColumnDefinition Width="2*" /> <ColumnDefinition Width="2*" />
@ -30,19 +31,19 @@
<RowDefinition Height="30" /> <RowDefinition Height="30" />
<RowDefinition Height="30" /> <RowDefinition Height="30" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Image Grid.Column="0" Grid.RowSpan="3" x:Name="logoImage" HorizontalAlignment="Left" Height="75" Width="75" Source="Resources/EUREPORT.png" Stretch="Fill" MouseUp="logoImage_MouseUp" Margin="2"/>
<Label HorizontalContentAlignment="Right" Grid.Column="1" Grid.Row="0" Content="Id" Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="1" Grid.Row="1" Content="IMO / ENI No." Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="1" Grid.Row="2" Content="Shipname" Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="3" Grid.Row="0" Content="Port of call" Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="3" Grid.Row="1" Content="ETA" Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="3" Grid.Row="2" Content="Ticket-No." Margin="0,0,10,0"/>
<TextBox Grid.Column="2" Grid.Row="0" Name="textBoxId" VerticalContentAlignment="Center" Margin="2"/>
<TextBox Grid.Column="2" Grid.Row="1" Name="textBoxIMO" VerticalContentAlignment="Center" Margin="2" MaxLength="8"/>
<TextBox Grid.Column="2" Grid.Row="2" Name="textBoxName" VerticalContentAlignment="Center" Margin="2"/>
<TextBox Grid.Column="4" Grid.Row="0" Name="textBoxHafen" VerticalContentAlignment="Center" Margin="2"/>
<Label HorizontalContentAlignment="Right" Grid.Column="0" Grid.Row="0" Content="Id" Margin="0,0,10,0"/> <Grid Grid.Column="4" Grid.Row="1" Height="Auto" Margin="2">
<Label HorizontalContentAlignment="Right" Grid.Column="0" Grid.Row="1" Content="IMO / ENI No." Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="0" Grid.Row="2" Content="Shipname" Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="2" Grid.Row="0" Content="Port of call" Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="2" Grid.Row="1" Content="ETA" Margin="0,0,10,0"/>
<Label HorizontalContentAlignment="Right" Grid.Column="2" Grid.Row="2" Content="Ticket-No." Margin="0,0,10,0"/>
<TextBox Grid.Column="1" Grid.Row="0" Name="textBoxId" VerticalContentAlignment="Center" Margin="2"/>
<TextBox Grid.Column="1" Grid.Row="1" Name="textBoxIMO" VerticalContentAlignment="Center" Margin="2" MaxLength="8"/>
<TextBox Grid.Column="1" Grid.Row="2" Name="textBoxName" VerticalContentAlignment="Center" Margin="2"/>
<TextBox Grid.Column="3" Grid.Row="0" Name="textBoxHafen" VerticalContentAlignment="Center" Margin="2"/>
<Grid Grid.Column="3" Grid.Row="1" Height="Auto" Margin="2">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" /> <ColumnDefinition Width="3*" />
@ -54,9 +55,9 @@
<Label Grid.Column="2" Grid.Row="0" Content="To:" HorizontalAlignment="Left" /> <Label Grid.Column="2" Grid.Row="0" Content="To:" HorizontalAlignment="Left" />
<DatePicker Grid.Column="3" Grid.Row="0" Name="dateTimePickerETATo" VerticalContentAlignment="Center" SelectedDateChanged="etaValueChanged" ContextMenu="{DynamicResource ClearContextMenu}"/> <DatePicker Grid.Column="3" Grid.Row="0" Name="dateTimePickerETATo" VerticalContentAlignment="Center" SelectedDateChanged="etaValueChanged" ContextMenu="{DynamicResource ClearContextMenu}"/>
</Grid> </Grid>
<TextBox Grid.Column="3" Grid.Row="2" Name="textBoxTicketNr" VerticalContentAlignment="Center" Margin="2"/> <TextBox Grid.Column="4" Grid.Row="2" Name="textBoxTicketNr" VerticalContentAlignment="Center" Margin="2"/>
<Button Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="1" Content="Search" Name="buttonSuche" Click="buttonSuche_Click" Margin="2" FontSize="14"/> <Button Grid.Column="2" Grid.Row="3" Grid.ColumnSpan="1" Content="Search" Name="buttonSuche" Click="buttonSuche_Click" Margin="2" FontSize="14"/>
<Grid Grid.Column="3" Grid.Row="3"> <Grid Grid.Column="4" Grid.Row="3">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" />

View File

@ -13,6 +13,7 @@ using bsmd.database;
using System.Windows.Data; using System.Windows.Data;
using log4net; using log4net;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Diagnostics;
namespace ENI2 namespace ENI2
{ {
@ -24,6 +25,7 @@ namespace ENI2
#region Fields #region Fields
private bool efMode = false;
private List<MessageCore> anmeldungen = new List<MessageCore>(); private List<MessageCore> anmeldungen = new List<MessageCore>();
private readonly object searchLock = new object(); private readonly object searchLock = new object();
private readonly ILog _log = LogManager.GetLogger("SucheControl"); private readonly ILog _log = LogManager.GetLogger("SucheControl");
@ -55,6 +57,12 @@ namespace ENI2
cancelItem.Click += CancelItem_Click; cancelItem.Click += CancelItem_Click;
cancelItem.Visibility = Visibility.Collapsed; cancelItem.Visibility = Visibility.Collapsed;
this.dataGrid.ContextMenu.Items.Add(cancelItem); this.dataGrid.ContextMenu.Items.Add(cancelItem);
if (Keyboard.IsKeyDown(Key.LeftShift))
{
efMode = true;
logoImage.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/ef_logo.png"));
}
} }
@ -291,5 +299,10 @@ namespace ENI2
#endregion #endregion
private void logoImage_MouseUp(object sender, MouseButtonEventArgs e)
{
if (efMode) Process.Start("http://www.eintracht-frankfurt.de/home.html");
else Process.Start("http://www.eureport.de/");
}
} }
} }

View File

@ -31,6 +31,8 @@ namespace ENI2.Util
this.bgTimer.Interval = Properties.Settings.Default.changeTimerTimeout; this.bgTimer.Interval = Properties.Settings.Default.changeTimerTimeout;
} }
public bool Idle => _watchedEntities.Count == 0;
private void BgTimer_Elapsed(object sender, ElapsedEventArgs e) private void BgTimer_Elapsed(object sender, ElapsedEventArgs e)
{ {
lock (this._entityLock) lock (this._entityLock)

View File

@ -5,10 +5,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading; using System.Windows.Threading;
using bsmd.database; using bsmd.database;
@ -21,6 +23,15 @@ namespace ENI2.Util
private static bool isBusy; private static bool isBusy;
private static readonly Random r = new Random(); private static readonly Random r = new Random();
public enum BusyStateEnum
{
NEUTRAL,
BUSY,
FAIL,
SUCCESS
}
public static void SetBusyState() public static void SetBusyState()
{ {
SetBusyState(true); SetBusyState(true);
@ -28,6 +39,7 @@ namespace ENI2.Util
private static void SetBusyState(bool busy) private static void SetBusyState(bool busy)
{ {
if(busy != isBusy) if(busy != isBusy)
{ {
isBusy = busy; isBusy = busy;
@ -36,7 +48,7 @@ namespace ENI2.Util
if(isBusy) if(isBusy)
{ {
new DispatcherTimer(TimeSpan.FromSeconds(0), DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick, Application.Current.Dispatcher); _ = new DispatcherTimer(TimeSpan.FromSeconds(0), DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick, Application.Current.Dispatcher);
} }
} }
@ -59,6 +71,38 @@ namespace ENI2.Util
return Color.FromRgb((byte) r.Next(150, 255), (byte) r.Next(150, 255), (byte) r.Next(150, 255)); return Color.FromRgb((byte) r.Next(150, 255), (byte) r.Next(150, 255), (byte) r.Next(150, 255));
} }
public static BitmapSource CreateBitmapSource(this System.Drawing.Bitmap bitmap)
{
if (bitmap == null)
throw new ArgumentNullException("bitmap");
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);
System.Drawing.Imaging.BitmapData bitmapData = bitmap.LockBits(rect,
System.Drawing.Imaging.ImageLockMode.ReadWrite,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
try
{
var size = rect.Width * rect.Height * 4;
return BitmapSource.Create(
bitmap.Width,
bitmap.Height,
bitmap.HorizontalResolution,
bitmap.VerticalResolution,
PixelFormats.Bgra32,
null,
bitmapData.Scan0,
size,
bitmapData.Stride);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
}
public static void SetMessageIcons(List<Message> messages) public static void SetMessageIcons(List<Message> messages)
{ {
foreach (Message aMessage in messages) foreach (Message aMessage in messages)
@ -159,6 +203,5 @@ namespace ENI2.Util
} }
} }
} }
} }
} }

View File

@ -0,0 +1,30 @@
CREATE TABLE [dbo].[XtraData]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[ParentId] UNIQUEIDENTIFIER NULL,
[ReferenceId] UNIQUEIDENTIFIER NOT NULL,
[Field1] NVARCHAR(100) NULL,
[Field2] NVARCHAR(100) NULL,
[Field3] NVARCHAR(100) NULL,
[Field4] NVARCHAR(100) NULL,
[Field5] NVARCHAR(100) NULL,
[Field6] NVARCHAR(100) NULL,
[Field7] NVARCHAR(100) NULL,
[Field8] NVARCHAR(100) NULL,
[Field9] NVARCHAR(100) NULL,
[Field10] NVARCHAR(100) NULL,
[Field11] NVARCHAR(100) NULL,
[Field12] NVARCHAR(100) NULL,
[Field13] NVARCHAR(100) NULL,
[Field14] NVARCHAR(100) NULL,
[Field15] NVARCHAR(100) NULL,
[Field16] NVARCHAR(100) NULL,
[Field17] NVARCHAR(100) NULL,
[Field18] NVARCHAR(100) NULL,
[Field19] NVARCHAR(100) NULL,
[Field20] NVARCHAR(100) NULL
)
GO
CREATE INDEX [IX_XtraData_RefId] ON [dbo].[XtraData] ([ReferenceId])

View File

@ -176,7 +176,7 @@ namespace SendNSWMessageService
if(message.HIS == Message.NSWProvider.UNDEFINED) if(message.HIS == Message.NSWProvider.UNDEFINED)
message.HIS = core.InitialHIS; message.HIS = core.InitialHIS;
_log.InfoFormat("Sending {0} message to {1}", message.MessageNotificationClass.ToString(), message.HIS.ToString()); _log.InfoFormat("Sending {0} message {1} to {2}", message.MessageNotificationClass.ToString(), message.Id, message.HIS.ToString());
// switch über passendes HIS / Schnittstelle // switch über passendes HIS / Schnittstelle
switch (message.HIS) switch (message.HIS)
@ -270,9 +270,11 @@ namespace SendNSWMessageService
} }
// external processing for HIS-Nord // external processing for HIS-Nord
bsmd.hisnord.transmitter.CallTransmitter(); if (bsmd.hisnord.transmitter.Transmit())
{
bsmd.hisnord.Request.ReadResponseFiles(); bsmd.hisnord.Request.ReadResponseFiles();
bsmd.hisnord.Response.ReadAnswers(); bsmd.hisnord.Response.ReadAnswers();
}
// external processing for dbh // external processing for dbh
bsmd.dbh.MessageController.SendAndReceive(); bsmd.dbh.MessageController.SendAndReceive();

View File

@ -15,6 +15,8 @@ using System.Diagnostics;
using Newtonsoft.Json; using Newtonsoft.Json;
using log4net; using log4net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
namespace bsmd.database namespace bsmd.database
{ {
@ -99,6 +101,22 @@ namespace bsmd.database
} }
} }
public async Task<bool> ConnectAsync(string dbConnectionString)
{
try
{
_con = new SqlConnection(dbConnectionString);
await _con.OpenAsync();
this.ConnectionString = dbConnectionString;
return true;
}
catch(Exception ex)
{
_log.ErrorFormat("DBManager cannot connect:{0}", ex.Message);
return false;
}
}
public void Disconnect() public void Disconnect()
{ {
if (this._con?.State == ConnectionState.Open) if (this._con?.State == ConnectionState.Open)

View File

@ -0,0 +1,177 @@
// Copyright (c) 2020-present schick Informatik
// Description: The new and mighty DB manager that uses async methods and
// connection pooling.. will try it out in Maersk/PO numbers and expand over the whole
// app later
using log4net;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace bsmd.database
{
public static class DBManagerAsync
{
#region Fields
private static readonly ILog _log = LogManager.GetLogger(typeof(DBManagerAsync));
#endregion
#region Properties
public static string ConnectionString { get; set; }
#endregion
#region public methods
public static async Task<int> Save(DatabaseEntity entity)
{
SqlCommand cmd = new SqlCommand();
entity.PrepareSave(cmd);
return await PerformNonQueryAsync(cmd);
}
#region convenience loading functions
public static async Task<List<MessageCore>> LoadMaerskCoresByIntervalAsync(Dictionary<MessageCore.SearchFilterType, string> filterDict, bool loadXtraData = false)
{
SqlCommand cmd = new SqlCommand();
MessageCore aMessageCore = new MessageCore();
aMessageCore.PrepareLoadCommand(cmd, Message.LoadFilter.SEARCH_CORE_FILTERS, filterDict);
SqlDataReader reader = await PerformCommandAsync(cmd);
return await aMessageCore.LoadListAsync(reader);
}
public static async Task<MessageCore> LoadCoreByVisitIdAsync(string visitId)
{
SqlCommand cmd = new SqlCommand();
MessageCore aMessageCore = new MessageCore();
aMessageCore.PrepareLoadCommand(cmd, Message.LoadFilter.BY_VISITID, visitId);
SqlDataReader reader = await PerformCommandAsync(cmd);
List<MessageCore> resultList = await aMessageCore.LoadListAsync(reader);
MessageCore result = null;
if(resultList.Count > 0)
{
if(resultList.Count > 1)
_log.WarnFormat("more than one core found for VISIT-ID {0}", visitId);
result = resultList[0];
}
return result;
}
public static async Task<MaerskData> LoadMaerskDataForCoreAsync(Guid messageCoreId)
{
SqlCommand cmd = new SqlCommand();
MaerskData md = new MaerskData();
md.PrepareLoadCommand(cmd, Message.LoadFilter.BY_CORE, messageCoreId);
SqlDataReader reader = await PerformCommandAsync(cmd);
List<MaerskData> resultList = await md.LoadListAsync(reader);
MaerskData result = null;
if(resultList.Count > 0)
{
if(resultList.Count > 1)
_log.WarnFormat("more than one xtra data found for core id {0}", messageCoreId);
result = resultList[0];
}
return result;
}
#endregion
#endregion
#region async DB access methods
internal static async Task<SqlDataReader> PerformCommandAsync(SqlCommand cmd)
{
SqlDataReader reader = null;
try
{
SqlConnection connection = new SqlConnection(ConnectionString);
await connection.OpenAsync();
cmd.Connection = connection;
reader = await cmd.ExecuteReaderAsync();
}
catch (SqlException ex)
{
Trace.WriteLine("SQL Exception:" + ex.Message);
_log.Error("Error performing command", ex);
_log.DebugFormat("Query: {0}", cmd.CommandText);
_log.Debug("Parameters:");
for (int i = 0; i < cmd.Parameters.Count; i++)
{
_log.DebugFormat("{0}:{1}", cmd.Parameters[i].ParameterName, cmd.Parameters[i].Value);
}
}
return reader;
}
internal static async Task<int> PerformNonQueryAsync(SqlCommand cmd)
{
int result = -1;
// await _asyncSemaphore.WaitAsync();
try
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
await connection.OpenAsync();
cmd.Connection = connection;
result = await cmd.ExecuteNonQueryAsync();
}
}
catch (SqlException ex)
{
Trace.WriteLine("SQL Exception:" + ex.Message);
_log.Error("Error performing command", ex);
_log.DebugFormat("Query: {0}", cmd.CommandText);
_log.Debug("Parameters:");
for (int i = 0; i < cmd.Parameters.Count; i++)
{
_log.DebugFormat("{0}:{1}", cmd.Parameters[i].ParameterName, cmd.Parameters[i].Value);
}
}
return result;
}
internal static async Task<int?> PerformReadIntQueryAsync(SqlCommand cmd)
{
int? result = null;
try
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
cmd.Connection = connection;
object r = await cmd.ExecuteScalarAsync();
if (r == null) { result = null; }
else if (r == DBNull.Value) { result = null; }
else { result = (int)r; }
}
}
catch (SqlException ex)
{
_log.Error("Error performing command", ex);
_log.DebugFormat("Query: {0}", cmd.CommandText);
_log.Debug("Parameters:");
for (int i = 0; i < cmd.Parameters.Count; i++)
{
_log.DebugFormat("{0}:{1}", cmd.Parameters[i].ParameterName, cmd.Parameters[i].Value);
}
}
return result;
}
#endregion
}
}

View File

@ -121,7 +121,18 @@ namespace bsmd.database
public static bool IsTimeEmpty(this DateTime datetime) public static bool IsTimeEmpty(this DateTime datetime)
{ {
return ((datetime.Hour == 0) && (datetime.Minute == 0) && (datetime.Second == 0)); return (datetime.Hour == 0) && (datetime.Minute == 0) && (datetime.Second == 0);
}
/// <summary>
/// Returns true if the date is between now and numDays in the future (or past, if numDays is negative)
/// (regarding full days, ignoring time component
/// </summary>
public static bool IsNextXDays(this DateTime datetime, int numDays)
{
double diff = (datetime.Date - DateTime.Now.Date).TotalDays;
if (numDays >= 0) return diff <= numDays && diff >= 0;
else return diff < numDays && diff < 0;
} }
public static double? TryParseDouble(string text) public static double? TryParseDouble(string text)

View File

@ -606,6 +606,11 @@ namespace bsmd.database
(this.PlaceOfIssue.IsNullOrEmpty() || !this.DateOfIssue.HasValue)) (this.PlaceOfIssue.IsNullOrEmpty() || !this.DateOfIssue.HasValue))
violations.Add(RuleEngine.CreateViolation(ValidationCode.V765, "Cert. Place or Date of issue missing", null, this.Title, null, this.Tablename)); violations.Add(RuleEngine.CreateViolation(ValidationCode.V765, "Cert. Place or Date of issue missing", null, this.Title, null, this.Tablename));
if( (!this.ValidSanitaryControlExemptionOrCertificateOnBoard.HasValue || (this.ValidSanitaryControlExemptionOrCertificateOnBoard.Value == false)) &&
((!this.PlaceOfIssue.IsNullOrEmpty()) || this.DateOfIssue.HasValue))
violations.Add(RuleEngine.CreateViolation(ValidationCode.IMPLAUSIBLE, "Check sanitary control exemption or certificate", null, this.Title, null, this.Tablename));
if ((this.InfectedAreaVisited ?? false) && this.InfectedAreas.IsNullOrEmpty()) if ((this.InfectedAreaVisited ?? false) && this.InfectedAreas.IsNullOrEmpty())
violations.Add(RuleEngine.CreateViolation(ValidationCode.V766, "Infected area date or port missing", null, this.Title, null, this.Tablename)); violations.Add(RuleEngine.CreateViolation(ValidationCode.V766, "Infected area date or port missing", null, this.Title, null, this.Tablename));

283
bsmd.database/MaerskData.cs Normal file
View File

@ -0,0 +1,283 @@
// Copyright (c) 2020-present schick Informatik
// Description:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bsmd.database
{
/// <summary>
/// Extra balcony: Data stored in Maersk Excel sheets must be stored to be exported
/// at a later date. In order to do that (and to be a little more flexible in the future)
/// we use a generic storage class called "XtraData" that hopefully might be useful in another
/// future scenario as well
/// </summary>
public class MaerskData : DatabaseEntity, IEquatable<MaerskData>, IComparable<MaerskData>
{
#region Construction
public MaerskData()
{
this.tablename = "[dbo].[XtraData]";
}
#endregion
#region Enums
public enum MDStatus
{
[Description("No id and is in the future")]
NO_ID,
[Description("Updated")]
UPDATED,
[Description("Requesting id")]
REQUESTING_ID,
[Description("Id assigned")]
ID_ASSIGNED,
[Description("upcoming without an id")]
NO_ID_AND_DUE,
[Description("Has id and is in the future")]
ID,
[Description("In the past, id or not")]
DONE,
[Description("no ETA found on data record")]
NO_ETA
}
#endregion
#region Properties
/// <summary>
/// reference id as set in the database
/// </summary>
public Guid MessageCoreId { get; set; }
/// <summary>
/// Core instance reference once matched / set
/// </summary>
public MessageCore Core { get; set; }
public MDStatus Status { get; set; }
public DateTime? ETA { get; set; }
public string ColA { get; set; }
public string ColB { get; set; }
/// <summary>
/// Shipping area?
/// </summary>
public string ColC { get; set; }
public string ColD { get; set; }
/// <summary>
/// Vessel name
/// </summary>
public string ColE { get; set; }
/// <summary>
/// IMO
/// </summary>
public string ColF { get; set; }
/// <summary>
/// Voyage-No incoming
/// </summary>
public string ColG { get; set; }
/// <summary>
/// Voyage-No outgoing
/// </summary>
public string ColH { get; set; }
/// <summary>
/// Terminal
/// </summary>
public string ColI { get; set; }
/// <summary>
/// Operator
/// </summary>
public string ColJ { get; set; }
/// <summary>
/// ETA
/// </summary>
public string ColK { get; set; }
/// <summary>
/// ETD
/// </summary>
public string ColL { get; set; }
/// <summary>
/// Visit-Id
/// </summary>
public string ColM { get; set; }
[MaxLength(100)]
public string Remark { get; set; }
#endregion
#region abstract DatabaseEntity method implementation
public override List<DatabaseEntity> LoadList(IDataReader reader)
{
List<DatabaseEntity> result = new List<DatabaseEntity>();
if (reader != null)
{
while (reader.Read())
{
result.Add(ReadRowFromReader(reader));
}
reader.Close();
}
return result;
}
public async Task<List<MaerskData>> LoadListAsync(SqlDataReader reader)
{
List<MaerskData> result = new List<MaerskData>();
if (reader != null)
{
while (await reader.ReadAsync())
{
result.Add(ReadRowFromReader(reader));
}
reader.Close();
}
return result;
}
private MaerskData ReadRowFromReader(IDataReader reader)
{
MaerskData md = null;
if (reader != null)
{
md = new MaerskData();
md.id = reader.GetGuid(0);
if (!reader.IsDBNull(1)) md.MessageCoreId = reader.GetGuid(1);
if (!reader.IsDBNull(2)) md.ColA = reader.GetString(2);
if (!reader.IsDBNull(3)) md.ColB = reader.GetString(3);
if (!reader.IsDBNull(4)) md.ColC = reader.GetString(4);
if (!reader.IsDBNull(5)) md.ColD = reader.GetString(5);
if (!reader.IsDBNull(6)) md.ColE = reader.GetString(6);
if (!reader.IsDBNull(7)) md.ColF = reader.GetString(7);
if (!reader.IsDBNull(8)) md.ColG = reader.GetString(8);
if (!reader.IsDBNull(9)) md.ColH = reader.GetString(9);
if (!reader.IsDBNull(10)) md.ColI = reader.GetString(10);
if (!reader.IsDBNull(11)) md.ColJ = reader.GetString(11);
if (!reader.IsDBNull(12)) md.ColK = reader.GetString(12);
if (!reader.IsDBNull(13)) md.ColL = reader.GetString(13);
if (!reader.IsDBNull(14)) md.ColM = reader.GetString(14);
if (!reader.IsDBNull(15)) md.Remark = reader.GetString(15);
// try parsing the column to datetime
if (DateTime.TryParse(md.ColA, out DateTime eta))
md.ETA = eta;
}
return md;
}
public override void PrepareLoadCommand(IDbCommand cmd, Message.LoadFilter filter, params object[] criteria)
{
string query = string.Format("SELECT Id, ReferenceId, Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11, Field12 , Field13, Field14 FROM {0} ", this.Tablename);
switch (filter)
{
case Message.LoadFilter.BY_ID:
query += " WHERE Id = @ID";
((SqlCommand)cmd).Parameters.AddWithValue("@ID", criteria[0]);
break;
case Message.LoadFilter.BY_CORE:
query += " WHERE ReferenceId = @ID";
((SqlCommand)cmd).Parameters.AddWithValue("@ID", criteria[0]);
break;
default:
break;
}
cmd.CommandText = query;
}
public override void PrepareSave(IDbCommand cmd)
{
SqlCommand scmd = cmd as SqlCommand;
scmd.Parameters.AddWithNullableValue("@REF", this.MessageCoreId);
scmd.Parameters.AddWithNullableValue("@COLA", this.ColA);
scmd.Parameters.AddWithNullableValue("@COLB", this.ColB);
scmd.Parameters.AddWithNullableValue("@COLC", this.ColC);
scmd.Parameters.AddWithNullableValue("@COLD", this.ColD);
scmd.Parameters.AddWithNullableValue("@COLE", this.ColE);
scmd.Parameters.AddWithNullableValue("@COLF", this.ColF);
scmd.Parameters.AddWithNullableValue("@COLG", this.ColG);
scmd.Parameters.AddWithNullableValue("@COLH", this.ColH);
scmd.Parameters.AddWithNullableValue("@COLI", this.ColI);
scmd.Parameters.AddWithNullableValue("@COLJ", this.ColJ);
scmd.Parameters.AddWithNullableValue("@COLK", this.ColK);
scmd.Parameters.AddWithNullableValue("@COLL", this.ColL);
scmd.Parameters.AddWithNullableValue("@COLM", this.ColM);
scmd.Parameters.AddWithNullableValue("@REMARK", this.Remark);
if (this.IsNew)
{
this.CreateId();
scmd.Parameters.AddWithValue("@ID", this.Id);
scmd.CommandText = string.Format("INSERT INTO {0} (Id, ReferenceId, Field1, Field2, Field3, Field4, Field5, Field6, Field7, Field8, Field9, Field10, Field11, Field12, Field13, Field14) " +
"VALUES (@ID, @REF, @COLA, @COLB, @COLC, @COLD, @COLE, @COLF, @COLG, @COLH, @COLI, @COLJ, @COLK, @COLL, @COLM, @REMARK)", this.Tablename);
}
else
{
scmd.Parameters.AddWithValue("@ID", this.Id);
scmd.CommandText = string.Format("UPDATE {0} SET Field1 = @COLA, Field2 = @COLB, Field3 = @COLC, Field4 = @COLD, Field5 = @COLE, Field6 = @COLF, Field7 = @COLG, Field8 = @COLH, " +
"Field9 = @COLI, Field10 = @COLJ, Field11 = @COLK, Field12 = @COLL, Field13 = @COLM, Field14 = @Remark WHERE Id = @ID", this.Tablename);
}
}
/// <summary>
/// Equality means if IMO and Voyage no. In/Out are the same
/// </summary>
public bool Equals(MaerskData other)
{
if (other == null) return false;
if (this.ColG == null) return (other.ColG == null);
if (this.ColH == null) return (other.ColH == null);
if (this.ColF == null) return (other.ColF == null);
return this.ColF.Equals(other.ColF) && this.ColG.Equals(other.ColG) && this.ColH.Equals(other.ColH);
}
/// <summary>
/// Sort-Order is by ETA
/// </summary>
public int CompareTo(MaerskData other)
{
if (this.ColA == null) return 0;
if (other == null) return 0;
return this.ColA.CompareTo(other.ColA);
}
public bool Update(MaerskData md)
{
bool result = false;
if (!md.ColA.IsNullOrEmpty() && !md.ColA.Equals(ColA)) { ColA = md.ColA; result = true; }
if (!md.ColB.IsNullOrEmpty() && !md.ColB.Equals(ColB)) { ColB = md.ColB; result = true; }
if (!md.ColC.IsNullOrEmpty() && !md.ColC.Equals(ColC)) { ColC = md.ColC; result = true; }
if (!md.ColD.IsNullOrEmpty() && !md.ColD.Equals(ColD)) { ColD = md.ColD; result = true; }
if (!md.ColE.IsNullOrEmpty() && !md.ColE.Equals(ColE)) { ColE = md.ColE; result = true; }
if (!md.ColI.IsNullOrEmpty() && !md.ColI.Equals(ColI)) { ColI = md.ColI; result = true; }
if (!md.ColJ.IsNullOrEmpty() && !md.ColJ.Equals(ColJ)) { ColJ = md.ColJ; result = true; }
if (!md.ColK.IsNullOrEmpty() && !md.ColK.Equals(ColK)) { ColK = md.ColK; result = true; }
if (!md.ColL.IsNullOrEmpty() && !md.ColL.Equals(ColL)) { ColL = md.ColL; result = true; }
if (!md.ColM.IsNullOrEmpty() && !md.ColM.Equals(ColM)) { ColM = md.ColM; result = true; }
return result;
}
#endregion
}
}

View File

@ -7,6 +7,7 @@ using System.Data.SqlClient;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using log4net; using log4net;
using System.Threading.Tasks;
namespace bsmd.database namespace bsmd.database
{ {
@ -85,7 +86,9 @@ namespace bsmd.database
FILTER_ETA, FILTER_ETA,
FILTER_TICKETNO, FILTER_TICKETNO,
FILTER_LATESTIDS, FILTER_LATESTIDS,
FILTER_CREATEDBY FILTER_CREATEDBY,
FILTER_FLAG_EQ,
FILTER_FLAG_NEQ
} }
[Flags] [Flags]
@ -463,7 +466,7 @@ namespace bsmd.database
} }
} }
public override void PrepareLoadCommand(System.Data.IDbCommand cmd, Message.LoadFilter filter, params object[] criteria) public override void PrepareLoadCommand(IDbCommand cmd, Message.LoadFilter filter, params object[] criteria)
{ {
StringBuilder sb = new StringBuilder("SELECT "); StringBuilder sb = new StringBuilder("SELECT ");
if (this.ResultLimit > 0) if (this.ResultLimit > 0)
@ -619,8 +622,8 @@ namespace bsmd.database
case SearchFilterType.FILTER_ETA: case SearchFilterType.FILTER_ETA:
uint? from = null, to = null; uint? from = null, to = null;
string[] elems = searchDict[key].Split(':'); string[] elems = searchDict[key].Split(':');
if (!elems[0].IsNullOrEmpty()) from = UInt32.Parse(elems[0]); if (!elems[0].IsNullOrEmpty()) from = uint.Parse(elems[0]);
if (!elems[1].IsNullOrEmpty()) to = UInt32.Parse(elems[1]); if (!elems[1].IsNullOrEmpty()) to = uint.Parse(elems[1]);
// SQL Logik für die Zeitfilterung: Wenn es bereits eine Tabelle NOA_NOD mit einem Eintrag für ETAToPortOfCall / ETAToKielCanal gibt // SQL Logik für die Zeitfilterung: Wenn es bereits eine Tabelle NOA_NOD mit einem Eintrag für ETAToPortOfCall / ETAToKielCanal gibt
// soll dieser Wert als Vergleich herangezogen werden, sonst ETA / ETAKielCanal aus MessageCore // soll dieser Wert als Vergleich herangezogen werden, sonst ETA / ETAKielCanal aus MessageCore
@ -692,6 +695,20 @@ namespace bsmd.database
((SqlCommand)cmd).Parameters.AddWithValue("@DRPID", searchDict[key]); ((SqlCommand)cmd).Parameters.AddWithValue("@DRPID", searchDict[key]);
break; break;
} }
case SearchFilterType.FILTER_FLAG_EQ:
{
sb.Append(" MessageCore.Flags = @FLAG ");
int.TryParse(searchDict[key], out int flag);
((SqlCommand)cmd).Parameters.AddWithValue("@FLAG", flag);
break;
}
case SearchFilterType.FILTER_FLAG_NEQ:
{
sb.Append(" MessageCore.Flags <> @FLAG ");
int.TryParse(searchDict[key], out int flag);
((SqlCommand)cmd).Parameters.AddWithValue("@FLAG", flag);
break;
}
} }
if (!moreThanOne) moreThanOne = true; if (!moreThanOne) moreThanOne = true;
} }
@ -708,6 +725,26 @@ namespace bsmd.database
{ {
List<DatabaseEntity> result = new List<DatabaseEntity>(); List<DatabaseEntity> result = new List<DatabaseEntity>();
while(reader.Read()) while(reader.Read())
{
result.Add(ReadRowFromReader(reader));
}
reader.Close();
return result;
}
public async Task<List<MessageCore>> LoadListAsync(SqlDataReader reader)
{
List<MessageCore> result = new List<MessageCore>();
while (await reader.ReadAsync())
{
result.Add(ReadRowFromReader(reader));
}
reader.Close();
return result;
}
private MessageCore ReadRowFromReader(IDataReader reader)
{ {
MessageCore core = new MessageCore(); MessageCore core = new MessageCore();
core.id = reader.GetGuid(0); core.id = reader.GetGuid(0);
@ -723,8 +760,8 @@ namespace bsmd.database
if (!reader.IsDBNull(10)) core.next = reader.GetGuid(10); if (!reader.IsDBNull(10)) core.next = reader.GetGuid(10);
core.IsTransit = reader.GetBoolean(11); core.IsTransit = reader.GetBoolean(11);
if (!reader.IsDBNull(12)) core.wetris_zz_56_datensatz_id = reader.GetInt32(12); if (!reader.IsDBNull(12)) core.wetris_zz_56_datensatz_id = reader.GetInt32(12);
core.BSMDStatusInternal = (BSMDStatus) Enum.ToObject(typeof(BSMDStatus), reader.GetByte(13)); core.BSMDStatusInternal = (BSMDStatus)Enum.ToObject(typeof(BSMDStatus), reader.GetByte(13));
core.InitialHIS = (Message.NSWProvider) Enum.ToObject(typeof(Message.NSWProvider), reader.GetByte(14)); core.InitialHIS = (Message.NSWProvider)Enum.ToObject(typeof(Message.NSWProvider), reader.GetByte(14));
if (!reader.IsDBNull(15)) core.HerbergFormGuid = reader.GetGuid(15); if (!reader.IsDBNull(15)) core.HerbergFormGuid = reader.GetGuid(15);
if (!reader.IsDBNull(16)) core.HerbergFormTemplateGuid = reader.GetGuid(16); if (!reader.IsDBNull(16)) core.HerbergFormTemplateGuid = reader.GetGuid(16);
if (!reader.IsDBNull(17)) core.HerbergReportType = reader.GetString(17); if (!reader.IsDBNull(17)) core.HerbergReportType = reader.GetString(17);
@ -732,7 +769,7 @@ namespace bsmd.database
if (!reader.IsDBNull(19)) core.HerbergEmail24HrsContact = reader.GetString(19); if (!reader.IsDBNull(19)) core.HerbergEmail24HrsContact = reader.GetString(19);
if (!reader.IsDBNull(20)) core.ETAKielCanal = reader.GetDateTime(20); if (!reader.IsDBNull(20)) core.ETAKielCanal = reader.GetDateTime(20);
if (!reader.IsDBNull(21)) core.HerbergRevDate = reader.GetDateTime(21); if (!reader.IsDBNull(21)) core.HerbergRevDate = reader.GetDateTime(21);
if (!reader.IsDBNull(22)) core.ReportStatus = (ReportStatusEnum) Enum.ToObject(typeof(ReportStatusEnum), reader.GetByte(22)); if (!reader.IsDBNull(22)) core.ReportStatus = (ReportStatusEnum)Enum.ToObject(typeof(ReportStatusEnum), reader.GetByte(22));
if (!reader.IsDBNull(23)) core.SietasSheetVersion = reader.GetString(23); if (!reader.IsDBNull(23)) core.SietasSheetVersion = reader.GetString(23);
if (!reader.IsDBNull(24)) core.Incoming = reader.GetBoolean(24); if (!reader.IsDBNull(24)) core.Incoming = reader.GetBoolean(24);
if (!reader.IsDBNull(25)) core.DefaultReportingPartyId = reader.GetGuid(25); if (!reader.IsDBNull(25)) core.DefaultReportingPartyId = reader.GetGuid(25);
@ -754,10 +791,7 @@ namespace bsmd.database
if (!reader.IsDBNull(41)) core.Flags = reader.GetInt32(41); if (!reader.IsDBNull(41)) core.Flags = reader.GetInt32(41);
if (!reader.IsDBNull(42)) core.POATA = reader.GetDateTime(42); if (!reader.IsDBNull(42)) core.POATA = reader.GetDateTime(42);
result.Add(core); return core;
}
reader.Close();
return result;
} }
#endregion #endregion

View File

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

View File

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

View File

@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using log4net; using log4net;
using System.Globalization; using System.Globalization;
using System.Threading.Tasks;
namespace bsmd.database namespace bsmd.database
{ {
@ -213,6 +214,99 @@ namespace bsmd.database
return result; return result;
} }
/// <summary>
/// Hilfsfunktion für "manuelle" Anlage eines Schiffsanlaufs. Die Objekte sind bereits gespeichert.
/// Es werden nur noch nicht vorhandene Meldeklassen erzeugt (Async version)
/// </summary>
public static async Task<List<Message>> CreateMessagesForCoreAsync(MessageCore core, List<Message> existingMessages, ReportingParty user = null)
{
List<Message> result = new List<Message>();
Dictionary<Message.NotificationClass, Message> messageDict = new Dictionary<Message.NotificationClass, Message>();
if (!existingMessages.IsNullOrEmpty())
{
foreach (Message aMessage in existingMessages)
{
if (messageDict.ContainsKey(aMessage.MessageNotificationClass))
{
_log.WarnFormat("Core {0} [{1}] has more than one message class for {2}", core.Id, core.DisplayId, aMessage.MessageNotificationClassDisplay);
}
messageDict[aMessage.MessageNotificationClass] = aMessage;
}
}
bool isDE, isDK;
if (core?.PoC != null)
{
isDE = core.PoC.Equals("ZZNOK") || core.PoC.StartsWith("DE");
isDK = core.PoC.StartsWith("DK");
foreach (Message.NotificationClass notificationClass in Enum.GetValues(typeof(Message.NotificationClass)))
{
if (isDE)
{
if (notificationClass == Message.NotificationClass.STO) continue;
}
if (isDK)
{
// gibt es hier etwas, das nicht gebraucht wird? (siehe Mail von Christin, 29.5.17
if ((notificationClass == Message.NotificationClass.MDH) ||
(notificationClass == Message.NotificationClass.BKRA) ||
(notificationClass == Message.NotificationClass.BKRD) ||
(notificationClass == Message.NotificationClass.TOWA) ||
(notificationClass == Message.NotificationClass.TOWD)) continue;
}
if (core.IsTransit && (notificationClass == Message.NotificationClass.VISIT)) continue;
if (!core.IsTransit && (notificationClass == Message.NotificationClass.TRANSIT)) continue;
Message message;
if (!messageDict.ContainsKey(notificationClass))
{
message = new Message();
if (user != null)
message.CreatedBy = string.Format("ENI-2: {0}", user.Logon);
message.MessageCore = core;
message.MessageCoreId = core.Id;
message.MessageNotificationClass = notificationClass;
await DBManagerAsync.Save(message);
result.Add(message);
}
else
{
message = messageDict[notificationClass];
}
// abgesehen von "Listen" für die Nachrichtenklassen auch untergeordnete Elemente erzeugen, falls nicht vorhanden!
DatabaseEntity classElement;
if (!Message.IsListClass(notificationClass) && (message.Elements.Count == 0))
{
classElement = DBManager.CreateMessage(notificationClass);
// CH: 6.10.17: Für die manuelle Eingabe (wird leider nicht ganz auszuschließen sein) wäre es hilfreich, wenn alle Checkboxen nicht leer sind, sondern False beinhalten.
if (notificationClass == Message.NotificationClass.MDH)
{
((MDH)classElement).SetBoolsToFalse();
}
if (notificationClass == Message.NotificationClass.BPOL)
{
// Vorbelegung, Spezialwunsch aus BRV 5.2.18
((BPOL)classElement).CruiseShip = false;
((BPOL)classElement).StowawaysOnBoard = false;
}
if (classElement != null) // null für Visit/Transit
{
classElement.MessageHeader = message;
await DBManagerAsync.Save(classElement);
message.Elements.Add(classElement);
}
}
}
}
return result;
}
public static int? GetNumericIdentifier(ISublistElement element) public static int? GetNumericIdentifier(ISublistElement element)
{ {
if (element != null) if (element != null)

View File

@ -111,6 +111,7 @@
<Compile Include="AGNT_Template.cs" /> <Compile Include="AGNT_Template.cs" />
<Compile Include="CallPurpose.cs" /> <Compile Include="CallPurpose.cs" />
<Compile Include="Customer.cs" /> <Compile Include="Customer.cs" />
<Compile Include="DBManagerAsync.cs" />
<Compile Include="Extensions.cs" /> <Compile Include="Extensions.cs" />
<Compile Include="HAZ.cs" /> <Compile Include="HAZ.cs" />
<Compile Include="HAZPosTemplate.cs" /> <Compile Include="HAZPosTemplate.cs" />
@ -126,6 +127,7 @@
<Compile Include="ISublistContainer.cs" /> <Compile Include="ISublistContainer.cs" />
<Compile Include="LastTenPortFacilitiesCalled.cs" /> <Compile Include="LastTenPortFacilitiesCalled.cs" />
<Compile Include="LookupNameAttribute.cs" /> <Compile Include="LookupNameAttribute.cs" />
<Compile Include="MaerskData.cs" />
<Compile Include="MARPOL_Annex_I_Position.cs" /> <Compile Include="MARPOL_Annex_I_Position.cs" />
<Compile Include="MessageHistory.cs" /> <Compile Include="MessageHistory.cs" />
<Compile Include="NoTypeConverterJsonConverter.cs" /> <Compile Include="NoTypeConverterJsonConverter.cs" />

View File

@ -248,8 +248,8 @@ namespace bsmd.hisnord
DBManager.Instance.Save(messageError); DBManager.Instance.Save(messageError);
} }
_log.InfoFormat("Saving Message {0} Status {1} InternalStatus {2}", _log.InfoFormat("{0} message {1} returned: Status {2} InternalStatus {3}",
aMessage.Id, aMessage.Status, aMessage.InternalStatus); aMessage.MessageNotificationClassDisplay, aMessage.Id, aMessage.Status, aMessage.InternalStatus);
DBManager.Instance.Save(aMessage); DBManager.Instance.Save(aMessage);
@ -260,7 +260,7 @@ namespace bsmd.hisnord
if (aMessage.InternalStatus == Message.BSMDStatus.SENT) if (aMessage.InternalStatus == Message.BSMDStatus.SENT)
{ {
aMessageStillInSENTstate = true; aMessageStillInSENTstate = true;
_log.InfoFormat("message {0} {1} still in SENT state", aMessage.Id, aMessage.MessageNotificationClassDisplay); _log.DebugFormat("message {0} {1} still in SENT state", aMessage.Id, aMessage.MessageNotificationClassDisplay);
} }
} }

View File

@ -10,6 +10,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Threading.Tasks;
using System.Xml.Serialization; using System.Xml.Serialization;
using bsmd.database; using bsmd.database;
using log4net; using log4net;
@ -19,16 +20,16 @@ namespace bsmd.hisnord
public class transmitter public class transmitter
{ {
private static readonly ILog _log = LogManager.GetLogger(typeof(transmitter)); private static readonly ILog _log = LogManager.GetLogger(typeof(transmitter));
private static int? processId; // Achtung, das müsste getrennt behandelt werden Test <-> Livesystem! private static int? processId;
public static void CallTransmitter() public static bool Transmit()
{ {
string rootDir = Properties.Settings.Default.TransmitterRoot; string rootDir = Properties.Settings.Default.TransmitterRoot;
if(processId.HasValue) if(processId.HasValue)
{ {
_log.InfoFormat("Transmitter process {0} still running, aborting call", processId); _log.InfoFormat("Transmitter process {0} still running, aborting call", processId);
return; return false;
} }
ProcessStartInfo startInfo = new ProcessStartInfo(Path.Combine(rootDir, Properties.Settings.Default.Transmitter)); ProcessStartInfo startInfo = new ProcessStartInfo(Path.Combine(rootDir, Properties.Settings.Default.Transmitter));
@ -43,7 +44,6 @@ namespace bsmd.hisnord
using (Process transmitterProcess = new Process()) using (Process transmitterProcess = new Process())
{ {
transmitterProcess.Exited += TransmitterProcess_Exited; transmitterProcess.Exited += TransmitterProcess_Exited;
transmitterProcess.ErrorDataReceived += TransmitterProcess_ErrorDataReceived; transmitterProcess.ErrorDataReceived += TransmitterProcess_ErrorDataReceived;
@ -60,28 +60,31 @@ namespace bsmd.hisnord
// _log.DebugFormat("started {0}", transmitterProcess.ProcessName); // _log.DebugFormat("started {0}", transmitterProcess.ProcessName);
int timeout = Properties.Settings.Default.BatchTimeoutMins * 1000 * 60; // convert to ms int timeout = Properties.Settings.Default.BatchTimeoutMins * 1000 * 60; // convert to ms
_log.InfoFormat($"starting transmitter, process ID: {processId}, timeout {timeout} ms.");
if (!transmitterProcess.WaitForExit((timeout == 0) ? int.MaxValue : timeout)) if (!transmitterProcess.WaitForExit((timeout == 0) ? int.MaxValue : timeout))
{ {
_log.WarnFormat("Transmitter process not exited within {0} minute", Properties.Settings.Default.BatchTimeoutMins); _log.Warn($"Transmitter {processId} not exited within {timeout} ms");
// dauert zu lang, beende Prozess..
try try
{ {
transmitterProcess.Kill(); transmitterProcess.Kill();
_log.Info("Transmitter killed"); _log.Warn($"Transmitter {processId} killed");
processId = null; processId = null;
} }
catch (Exception e) catch (Exception e)
{ {
_log.WarnFormat("Killing Transmitter failed: {0}", e.Message); _log.Warn($"Killing Transmitter {processId} failed: {e.Message}");
} }
} }
} }
return true;
} }
private static void TransmitterProcess_OutputDataReceived(object sender, DataReceivedEventArgs e) private static void TransmitterProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{ {
if(!e.Data.IsNullOrEmpty()) if(!e.Data.IsNullOrEmpty())
_log.Debug(e.Data); _log.Info(e.Data);
} }
private static void TransmitterProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e) private static void TransmitterProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
@ -92,7 +95,7 @@ namespace bsmd.hisnord
private static void TransmitterProcess_Exited(object sender, EventArgs e) private static void TransmitterProcess_Exited(object sender, EventArgs e)
{ {
_log.Debug("Transmitter process exited"); _log.Info("Transmitter process exited");
processId = null; processId = null;
} }
@ -105,8 +108,6 @@ namespace bsmd.hisnord
return result.ReadResult(resultFullPath); return result.ReadResult(resultFullPath);
} }
/// <summary> /// <summary>
/// class to read transmitter result xml files /// class to read transmitter result xml files
/// </summary> /// </summary>

Binary file not shown.