diff --git a/ENI2/Controls/MaerskListControl.xaml.cs b/ENI2/Controls/MaerskListControl.xaml.cs
index bf334d66..1cb21559 100644
--- a/ENI2/Controls/MaerskListControl.xaml.cs
+++ b/ENI2/Controls/MaerskListControl.xaml.cs
@@ -444,8 +444,8 @@ namespace ENI2.Controls
else
{
imosAreOkay = false;
- }
- }
+ }
+ }
else
{
imosAreOkay = false;
@@ -459,7 +459,7 @@ namespace ENI2.Controls
importData.Add(md);
- if (isFirstRow) isFirstRow = false;
+ if (isFirstRow) isFirstRow = false;
}
}
catch (Exception ex)
@@ -469,7 +469,7 @@ namespace ENI2.Controls
if (imosAreOkay && importData.Count > 0)
{
- busyControl.BusyState = Util.UIHelper.BusyStateEnum.BUSY;
+ busyControl.BusyState = Util.UIHelper.BusyStateEnum.BUSY;
foreach (MaerskData md in importData)
{
@@ -480,15 +480,37 @@ namespace ENI2.Controls
(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;
+ if ((foundData.MessageCore == null) || !(foundData.MessageCore.Cancelled ?? false))
+ {
+ 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);
+ if (md.MessageCore != null)
+ {
+ MaerskData existingMD = await DBManagerAsync.LoadMaerskDataForCoreAsync(md.MessageCore.Id.Value);
+ if(existingMD == null)
+ {
+ // we have a core but no MarskData for this import -> save it
+ md.MessageCoreId = (Guid) md.MessageCore.Id;
+ _ = DBManagerAsync.SaveAsync(md);
+ }
+ else
+ {
+ existingMD.Update(md);
+ _ = DBManagerAsync.SaveAsync(existingMD);
+ this.UpdateStatus(existingMD);
+ maerskDataList.Add(existingMD);
+ continue; // add existing instead of new one
+ }
+ }
}
+
this.UpdateStatus(md);
maerskDataList.Add(md);
}
@@ -498,7 +520,7 @@ namespace ENI2.Controls
busyControl.BusyState = Util.UIHelper.BusyStateEnum.NEUTRAL;
this.dataGridPOCores.Items.Refresh();
- }
+ }
}
stream.Close();
@@ -531,26 +553,6 @@ namespace ENI2.Controls
}
}
- /*
-
- 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
diff --git a/ENI2/DetailViewControls/OverViewDetailControl.xaml b/ENI2/DetailViewControls/OverViewDetailControl.xaml
index bb384509..8a06b9d0 100644
--- a/ENI2/DetailViewControls/OverViewDetailControl.xaml
+++ b/ENI2/DetailViewControls/OverViewDetailControl.xaml
@@ -8,6 +8,7 @@
xmlns:enictrl="clr-namespace:ENI2.Controls"
xmlns:p="clr-namespace:ENI2.Properties"
xmlns:util="clr-namespace:ENI2.Util"
+ xmlns:data="clr-namespace:bsmd.database;assembly=bsmd.database"
xmlns:local="clr-namespace:ENI2.DetailViewControls"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="800">
@@ -147,6 +148,13 @@
+
+
+
+
+
+
+
@@ -160,10 +168,7 @@
-
-
+
diff --git a/ENI2/ENI2.csproj b/ENI2/ENI2.csproj
index efd719f2..4af2fcb4 100644
--- a/ENI2/ENI2.csproj
+++ b/ENI2/ENI2.csproj
@@ -36,8 +36,8 @@
5.4.0.0
true
publish.html
- 8
- 7.10.0.%2a
+ 6
+ 7.11.0.%2a
false
true
true
@@ -436,6 +436,7 @@
+
diff --git a/ENI2/EditControls/EditIMSBCDialog.xaml b/ENI2/EditControls/EditIMSBCDialog.xaml
index e40e216c..0964c8f9 100644
--- a/ENI2/EditControls/EditIMSBCDialog.xaml
+++ b/ENI2/EditControls/EditIMSBCDialog.xaml
@@ -46,7 +46,7 @@
-
+
diff --git a/ENI2/Excel/ExcelSimpleWriter.cs b/ENI2/Excel/ExcelSimpleWriter.cs
index 0082c94e..4f73552d 100644
--- a/ENI2/Excel/ExcelSimpleWriter.cs
+++ b/ENI2/Excel/ExcelSimpleWriter.cs
@@ -15,6 +15,8 @@ namespace ENI2.Excel
{
public static void WriteMaerskList(string filename, List data)
{
+ data.Sort();
+
Application excelApp = new Application();
excelApp.DisplayAlerts = false;
excelApp.Visible = false;
@@ -57,7 +59,7 @@ namespace ENI2.Excel
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;
+ ws.Cells[i + 2, 14] = md.Remark;
if((md.MessageCore != null) && (md.MessageCore.Cancelled ?? false))
{
diff --git a/ENI2/Properties/Resources.Designer.cs b/ENI2/Properties/Resources.Designer.cs
index a47afa95..934f8aa0 100644
--- a/ENI2/Properties/Resources.Designer.cs
+++ b/ENI2/Properties/Resources.Designer.cs
@@ -1613,6 +1613,15 @@ namespace ENI2.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to Copy IMO to clipboard.
+ ///
+ public static string textCopyIMO {
+ get {
+ return ResourceManager.GetString("textCopyIMO", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Copy to {0}.
///
diff --git a/ENI2/Properties/Resources.resx b/ENI2/Properties/Resources.resx
index f959d19d..27e88020 100644
--- a/ENI2/Properties/Resources.resx
+++ b/ENI2/Properties/Resources.resx
@@ -1876,4 +1876,7 @@
..\Resources\exit.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ Copy IMO to clipboard
+
\ No newline at end of file
diff --git a/ENI2/SucheControl.xaml.cs b/ENI2/SucheControl.xaml.cs
index d3df5625..fae3ecfb 100644
--- a/ENI2/SucheControl.xaml.cs
+++ b/ENI2/SucheControl.xaml.cs
@@ -51,6 +51,11 @@ namespace ENI2
addItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/documents.png")) };
addItem.Click += this.copyID;
this.dataGrid.ContextMenu.Items.Add(addItem);
+ MenuItem copyIMOItem = new MenuItem();
+ copyIMOItem.Header = Properties.Resources.textCopyIMO;
+ copyIMOItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/document_into.png")) };
+ copyIMOItem.Click += this.copyIMO;
+ this.dataGrid.ContextMenu.Items.Add(copyIMOItem);
cancelItem = new MenuItem();
cancelItem.Header = Properties.Resources.textUndoCancel;
cancelItem.Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/Resources/delete.png")) };
@@ -297,6 +302,14 @@ namespace ENI2
}
}
+ private void copyIMO(object sender, RoutedEventArgs e)
+ {
+ if (dataGrid.SelectedItem is MessageCore selectedCore)
+ {
+ Clipboard.SetText(selectedCore.IMO);
+ }
+ }
+
#endregion
private void logoImage_MouseUp(object sender, MouseButtonEventArgs e)
diff --git a/ENI2/Util/CutoffConverter.cs b/ENI2/Util/CutoffConverter.cs
new file mode 100644
index 00000000..b19c5570
--- /dev/null
+++ b/ENI2/Util/CutoffConverter.cs
@@ -0,0 +1,49 @@
+// Copyright (c) 2023- schick Informatik
+// Description: Simple converter to check if a numeric value is greater than a specific value. This can
+// be used by datatriggers in XAML
+//
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Markup;
+
+namespace ENI2.Util
+{
+ public class CutoffConverter : MarkupExtension, IValueConverter
+ {
+
+ #region MarkupExtension implementation
+
+ private static CutoffConverter _converter = null;
+ public override object ProvideValue(IServiceProvider serviceProvider)
+ {
+ if (_converter == null)
+ {
+ _converter = new CutoffConverter();
+ }
+ return _converter;
+ }
+
+ #endregion
+
+ #region IValueConverter implementation
+
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is ICollection collection)
+ return collection.Count > Cutoff;
+ return ((int)value) > Cutoff;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+
+ public int Cutoff { get; set; }
+ }
+}
diff --git a/bsmd.ExcelReadService/LocodeDB.cs b/bsmd.ExcelReadService/LocodeDB.cs
index cf6ac2e6..67439ca4 100644
--- a/bsmd.ExcelReadService/LocodeDB.cs
+++ b/bsmd.ExcelReadService/LocodeDB.cs
@@ -45,7 +45,7 @@ namespace ENI2.Locode
public static string LocodeFromCity(string city, string country)
{
string result = null;
- string query = string.Format("SELECT city_code FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE countries.code = '{0}' AND locodes.port='t' AND (locodes.name like '{1}' OR locodes.name_wo_diacritics like '{1}')",
+ string query = string.Format("SELECT city_code FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE countries.code = '{0}' AND locodes.port=1 AND (locodes.name like '{1}' OR locodes.name_wo_diacritics like '{1}')",
country, city);
SQLiteCommand cmd = new SQLiteCommand(query, _con);
IDataReader reader = cmd.ExecuteReader();
@@ -73,7 +73,7 @@ namespace ENI2.Locode
if ((countryCode != null) && (lcLookup != null))
results.Add(lcLookup);
}
- string query = string.Format("SELECT city_code, countries.code FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE locodes.port='t' AND (locodes.name like '{0}' OR locodes.name_wo_diacritics like '{0}')", city);
+ string query = string.Format("SELECT city_code, countries.code FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE locodes.port=1 AND (locodes.name like '{0}' OR locodes.name_wo_diacritics like '{0}')", city);
SQLiteCommand cmd = new SQLiteCommand(query, _con);
IDataReader reader = cmd.ExecuteReader();
while (reader.Read())
@@ -103,7 +103,7 @@ namespace ENI2.Locode
}
}
- string query = "SELECT locodes.name_wo_diacritics, city_code, countries.code FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE locodes.port='t' AND (locodes.name like $PAR OR locodes.name_wo_diacritics like $PAR)";
+ string query = "SELECT locodes.name_wo_diacritics, city_code, countries.code FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE locodes.port=1 AND (locodes.name like $PAR OR locodes.name_wo_diacritics like $PAR)";
if(!onlyPorts)
query = "SELECT locodes.name_wo_diacritics, city_code, countries.code FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE (locodes.name like $PAR OR locodes.name_wo_diacritics like $PAR)";
@@ -190,7 +190,7 @@ namespace ENI2.Locode
try
{
string locodeUpper = locode.ToUpper();
- string query = string.Format("SELECT locodes.name_wo_diacritics FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE locodes.port='t' AND locodes.city_code = '{0}' AND countries.code = '{1}'",
+ string query = string.Format("SELECT locodes.name_wo_diacritics FROM locodes JOIN countries ON locodes.country_id = countries.ID WHERE locodes.port=1 AND locodes.city_code = '{0}' AND countries.code = '{1}'",
locodeUpper.Substring(2), locodeUpper.Substring(0, 2));
SQLiteCommand cmd = new SQLiteCommand(query, _con);
IDataReader reader = cmd.ExecuteReader();
diff --git a/bsmd.Tool.sln b/bsmd.Tool.sln
index 39a1ec6c..5da0a53c 100644
--- a/bsmd.Tool.sln
+++ b/bsmd.Tool.sln
@@ -1,22 +1,51 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.33328.57
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bsmd.Tool", "bsmd.Tool\bsmd.Tool.csproj", "{5F5E65EE-9351-4F30-817A-9C6C6D6835AE}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bsmd.database", "bsmd.database\bsmd.database.csproj", "{19945AF2-379B-46A5-B27A-303B5EC1D557}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug 64|Any CPU = Debug 64|Any CPU
+ Debug 64|x64 = Debug 64|x64
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Debug 64|Any CPU.ActiveCfg = Debug|Any CPU
+ {5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Debug 64|Any CPU.Build.0 = Debug|Any CPU
+ {5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Debug 64|x64.ActiveCfg = Debug|Any CPU
+ {5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Debug 64|x64.Build.0 = Debug|Any CPU
{5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Debug|x64.Build.0 = Debug|Any CPU
{5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Release|x64.ActiveCfg = Release|Any CPU
+ {5F5E65EE-9351-4F30-817A-9C6C6D6835AE}.Release|x64.Build.0 = Release|Any CPU
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Debug 64|Any CPU.ActiveCfg = Debug 64|Any CPU
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Debug 64|Any CPU.Build.0 = Debug 64|Any CPU
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Debug 64|x64.ActiveCfg = Debug 64|x64
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Debug 64|x64.Build.0 = Debug 64|x64
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Debug|x64.ActiveCfg = Debug|x64
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Debug|x64.Build.0 = Debug|x64
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Release|Any CPU.Build.0 = Release|Any CPU
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Release|x64.ActiveCfg = Release|x64
+ {19945AF2-379B-46A5-B27A-303B5EC1D557}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {6B3F5B6D-3615-4A93-A6A7-46BD448CEED6}
+ EndGlobalSection
EndGlobal
diff --git a/bsmd.Tool/App.config b/bsmd.Tool/App.config
index b9f6a508..ec50e784 100644
--- a/bsmd.Tool/App.config
+++ b/bsmd.Tool/App.config
@@ -1,30 +1,30 @@
-
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
@@ -33,4 +33,4 @@
-
\ No newline at end of file
+
diff --git a/bsmd.Tool/CheckRules.cs b/bsmd.Tool/CheckRules.cs
index bd071dd5..3dcc51dc 100644
--- a/bsmd.Tool/CheckRules.cs
+++ b/bsmd.Tool/CheckRules.cs
@@ -14,9 +14,9 @@ using log4net;
namespace bsmd.Tool
{
- public class CheckRules
+ public static class CheckRules
{
- private static ILog log = LogManager.GetLogger("CheckRules");
+ private static readonly ILog log = LogManager.GetLogger("CheckRules");
public static void Check(Guid messageCoreId)
{
if(DBManager.Instance.Connect(Properties.Settings.Default.ConnectionString))
@@ -28,16 +28,15 @@ namespace bsmd.Tool
List messages = DBManager.Instance.GetMessagesForCore(core, DBManager.MessageLoad.ALL);
RuleEngine ruleEngine = new RuleEngine();
- foreach(Message message in messages) {
-
+ foreach(Message message in messages)
+ {
// clear old results
DBManager.Instance.DeleteMessageErrors(message);
DBManager.Instance.DeleteMessageViolations(message);
// perform validation
ruleEngine.Validate(message);
-
- }
+ }
}
else
{
diff --git a/bsmd.Tool/CleanupFiles.cs b/bsmd.Tool/CleanupFiles.cs
index ffa7ddc7..ed91c0f7 100644
--- a/bsmd.Tool/CleanupFiles.cs
+++ b/bsmd.Tool/CleanupFiles.cs
@@ -7,9 +7,8 @@ using System.IO;
namespace bsmd.Tool
{
- class CleanupFiles
+ internal static class CleanupFiles
{
-
///
/// Alle XML Dateien in einem Dateipfad(rootPath) (recursive) löschen, die älter als (staleDays) Tage sind
///
@@ -35,6 +34,5 @@ namespace bsmd.Tool
Cleanup(directory, staleDays, recursive);
}
}
-
}
}
diff --git a/bsmd.Tool/LocodeSQliteImport.cs b/bsmd.Tool/LocodeSQliteImport.cs
new file mode 100644
index 00000000..9abc9ed9
--- /dev/null
+++ b/bsmd.Tool/LocodeSQliteImport.cs
@@ -0,0 +1,210 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Data;
+using System.Data.SQLite;
+using log4net;
+
+namespace bsmd.Tool
+{
+ public static class LocodeSQliteImport
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(LocodeSQliteImport));
+
+ ///
+ /// Importer / Updater für CSV files, die im SVN unter \bsmd\nsw\Archiv abgelegt wurde
+ /// (offizielle UNLOCODEs)..
+ ///
+ ///
+ ///
+ public static void Import(string sqliteDBPath, string csvFilePath)
+ {
+ if (!File.Exists(sqliteDBPath)) throw new ArgumentException($"file {sqliteDBPath} does not exits");
+ if (!File.Exists(csvFilePath)) throw new ArgumentException($"file {csvFilePath} does not exist");
+ List currentLocodes = new List();
+
+ using (var connection = new SQLiteConnection($"Data Source={sqliteDBPath}"))
+ {
+ connection.Open();
+
+ // preload countries
+ Dictionary countryDict = new Dictionary();
+
+ SQLiteCommand countryCmd = new SQLiteCommand(connection);
+ countryCmd.CommandText = "SELECT id, code FROM countries";
+ SQLiteDataReader reader = countryCmd.ExecuteReader();
+ while (reader.Read())
+ {
+ countryDict[reader.GetString(1)] = reader.GetInt32(0);
+ }
+
+ SQLiteCommand lookupCmd = new SQLiteCommand(connection);
+ lookupCmd.CommandText = "SELECT locodes.id FROM locodes INNER JOIN countries ON locodes.country_id = countries.id WHERE countries.code = @CCODE AND locodes.city_code = @LCODE";
+ SQLiteParameter ccode = new SQLiteParameter("@CCODE", DbType.String);
+ lookupCmd.Parameters.Add(ccode);
+ SQLiteParameter lcode = new SQLiteParameter("@LCODE", DbType.String);
+ lookupCmd.Parameters.Add(lcode);
+
+ SQLiteCommand insertCmd = new SQLiteCommand(connection);
+ insertCmd.CommandText = "INSERT INTO locodes (country_id, city_code, name, name_wo_diacritics, sub_div, port, rail_terminal, road_terminal, airport, postal_exchange_office, inland_clearance_depot, fixed_transport_functions, border_crossing_function, status, date, iata, coordinates, remarks) VALUES " +
+ "(@P1, @P2, @P3, @P4, @P5, @P6, @P7, @P8, @P9, @P10, @P11, @P12, @P13, @P14, @P15, @P16, @P17, @P18)";
+
+
+ SQLiteCommand updateCmd = new SQLiteCommand(connection);
+ updateCmd.CommandText = "UPDATE locodes SET name = @P3, name_wo_diacritics = @P4, sub_div = @P5, port = @P6, rail_terminal = @P7, road_terminal = @P8, airport = @P9, postal_exchange_office = @P10, " +
+ "inland_clearance_depot = @P11, fixed_transport_functions = @P12, border_crossing_function = @P13, status = @P14, date = @P15, iata = @P16, coordinates = @P17, remarks = @P18 WHERE id = @ID";
+
+ SQLiteParameter p1 = new SQLiteParameter("@P1", DbType.Int32);
+ SQLiteParameter p2 = new SQLiteParameter("@P2", DbType.String);
+ SQLiteParameter p3 = new SQLiteParameter("@P3", DbType.String);
+ SQLiteParameter p4 = new SQLiteParameter("@P4", DbType.String);
+ SQLiteParameter p5 = new SQLiteParameter("@P5", DbType.String);
+ SQLiteParameter p6 = new SQLiteParameter("@P6", DbType.Boolean);
+ SQLiteParameter p7 = new SQLiteParameter("@P7", DbType.Boolean);
+ SQLiteParameter p8 = new SQLiteParameter("@P8", DbType.Boolean);
+ SQLiteParameter p9 = new SQLiteParameter("@P9", DbType.Boolean);
+ SQLiteParameter p10 = new SQLiteParameter("@P10", DbType.Boolean);
+ SQLiteParameter p11 = new SQLiteParameter("@P11", DbType.Boolean);
+ SQLiteParameter p12 = new SQLiteParameter("@P12", DbType.Boolean);
+ SQLiteParameter p13 = new SQLiteParameter("@P13", DbType.Boolean);
+ SQLiteParameter p14 = new SQLiteParameter("@P14", DbType.String);
+ SQLiteParameter p15 = new SQLiteParameter("@P15", DbType.String);
+ SQLiteParameter p16 = new SQLiteParameter("@P16", DbType.String);
+ SQLiteParameter p17 = new SQLiteParameter("@P17", DbType.String);
+ SQLiteParameter p18 = new SQLiteParameter("@P18", DbType.String);
+
+ SQLiteParameter idParam = new SQLiteParameter("@ID", DbType.Int32);
+
+ insertCmd.Parameters.AddRange(new[] { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18 });
+ updateCmd.Parameters.AddRange(new[] { p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, idParam });
+
+ string[] csvLines = File.ReadAllLines(csvFilePath);
+ int updateCnt = 0, insertCnt = 0;
+
+ for (int i = 0; i < csvLines.Length; i++)
+ {
+ string line = csvLines[i];
+ string[] elems = line.Split(',');
+ if (elems.Length < 12) continue;
+ string country = elems[1].Trim().Replace("\"", "");
+ if (country.Length < 2) continue;
+ string code = elems[2].Trim().Replace("\"", "");
+ if (code.Length < 3) continue;
+
+ currentLocodes.Add(country + code);
+
+ ccode.Value = country;
+ lcode.Value = code;
+
+ // Eingabeformat: https://service.unece.org/trade/locode/Service/LocodeColumn.htm
+
+ object lookupResult = lookupCmd.ExecuteScalar();
+ if ((lookupResult != null) && (lookupResult != DBNull.Value))
+ {
+ int lid = Convert.ToInt32(lookupResult);
+
+ p3.Value = elems[3].Trim().Replace("\"", "");
+ p4.Value = elems[4].Trim().Replace("\"", "");
+ p5.Value = elems[5].Trim().Replace("\"", "");
+ SetBoolParamsFromFunctionString(elems[6].Trim().Replace("\"", ""), p6, p7, p8, p9, p10, p11, p12, p13);
+ p14.Value = elems[7].Trim().Replace("\"", "");
+ p15.Value = elems[8].Trim().Replace("\"", "");
+ p16.Value = elems[9].Trim().Replace("\"", "");
+ p17.Value = elems[10].Trim().Replace("\"", "");
+ p18.Value = elems[11].Trim().Replace("\"", "");
+
+ idParam.Value = lid;
+ if (updateCmd.ExecuteNonQuery() == 0)
+ {
+ _log.WarnFormat("Update of {0} affected no rows.", lid);
+ }
+ // UPDATE entry
+ updateCnt++;
+ }
+ else
+ {
+ if(!countryDict.ContainsKey(country))
+ {
+ _log.WarnFormat("Country {0} not in dictionary!", country);
+ continue;
+ }
+ p1.Value = countryDict[country];
+ p2.Value = code;
+ p3.Value = elems[3].Trim().Replace("\"", "");
+ p4.Value = elems[4].Trim().Replace("\"", "");
+ p5.Value = elems[5].Trim().Replace("\"", "");
+ SetBoolParamsFromFunctionString(elems[6].Trim().Replace("\"", ""), p6, p7, p8, p9, p10, p11, p12, p13);
+ p14.Value = elems[7].Trim().Replace("\"", "");
+ p15.Value = elems[8].Trim().Replace("\"", "");
+ p16.Value = elems[9].Trim().Replace("\"", "");
+ p17.Value = elems[10].Trim().Replace("\"", "");
+ p18.Value = elems[11].Trim().Replace("\"", "");
+
+ if (insertCmd.ExecuteNonQuery() == 0)
+ {
+ _log.Warn("Insert of {0} affected no rows.");
+ }
+ // CREATE new entry
+ insertCnt++;
+ }
+
+
+ Console.Write($"\r({i}/{csvLines.Length})");
+ }
+
+ Console.Write("\n");
+ Console.WriteLine($"{insertCnt} new entries, {updateCnt} updated");
+
+ // jetzt durch alle Ids in der DB laufen und mit dem Import vergleichen
+ List deleteIds = new List();
+ SQLiteCommand cmd = new SQLiteCommand(connection);
+ cmd.CommandText = "SELECT countries.code, locodes.id, locodes.city_code FROM countries INNER JOIN locodes on locodes.country_id = countries.id";
+ SQLiteDataReader reader2 = cmd.ExecuteReader();
+ while (reader2.Read())
+ {
+ if (reader2.IsDBNull(2))
+ {
+ deleteIds.Add(reader2.GetInt32(1));
+ }
+ else
+ {
+ string locode = reader2.GetString(0) + reader2.GetString(2);
+ if (locode.Equals("ZZUKN")) continue;
+ if (locode.Equals("ZZNOK")) continue;
+ if (!currentLocodes.Contains(locode))
+ deleteIds.Add(reader2.GetInt32(1));
+ }
+ }
+
+ Console.WriteLine($"deleting {deleteIds.Count} obsolete entries");
+
+ SQLiteCommand delCmd = new SQLiteCommand(connection);
+ delCmd.CommandText = "DELETE FROM locodes where id = @DELID";
+ // diejenigen löschen, die nicht mehr in der Quell CSV Datei auftauchen
+ foreach (int deleteId in deleteIds)
+ {
+ delCmd.Parameters.AddWithValue("@DELID", deleteId);
+ if (delCmd.ExecuteNonQuery() != 1)
+ _log.WarnFormat("{0} affected no rows", deleteId);
+ }
+ }
+ }
+
+ private static void SetBoolParamsFromFunctionString(string func, SQLiteParameter p6, SQLiteParameter p7, SQLiteParameter p8,
+ SQLiteParameter p9, SQLiteParameter p10, SQLiteParameter p11, SQLiteParameter p12, SQLiteParameter p13)
+ {
+ if (func.Length < 8) return;
+ p6.Value = (func[0] == '1');
+ p7.Value = (func[1] == '2');
+ p8.Value = (func[2] == '3');
+ p9.Value = (func[3] == '4');
+ p10.Value = (func[4] == '5');
+ p11.Value = (func[5] == '6');
+ p12.Value = (func[6] == '7');
+ p13.Value = (func[7] == 'B');
+ }
+ }
+}
diff --git a/bsmd.Tool/Options.cs b/bsmd.Tool/Options.cs
index ca93d56e..026e703c 100644
--- a/bsmd.Tool/Options.cs
+++ b/bsmd.Tool/Options.cs
@@ -7,10 +7,7 @@
//
// Copyright (c) 2015 Informatikbüro Daniel Schick. All rights reserved.
-using System;
-using System.Collections.Generic;
using CommandLine;
-using CommandLine.Text;
namespace bsmd.Tool
{
@@ -19,30 +16,28 @@ namespace bsmd.Tool
[Option('c', "core", Required=false, HelpText="MessageCoreId to process")]
public string MessageCoreId { get; set; }
- [Option('v',"verbose", DefaultValue=true, HelpText="print messages to console")]
+ [Option('v',"verbose", Default=true, HelpText="print messages to console")]
public bool Verbose { get; set; }
- [Option('r', "checkrules", MutuallyExclusiveSet = "command", HelpText = "Use rule engine on message core")]
+ [Option('r', "checkrules", HelpText = "Use rule engine on message core")]
public bool CheckRules { get; set; }
- [Option('s', "staledays", DefaultValue = 30, HelpText ="Delete files older than X days")]
+ [Option("locodes", HelpText = "use this flag if you want to import locodes")]
+ public bool ImportLocodes { get; set; }
+
+ [Option('s', "staledays", Default = 30, HelpText ="Delete files older than X days")]
public int StaleDays { get; set; }
[Option('p', "path", HelpText ="Path to cleanup root folder")]
public string CleanupFolderRoot { get; set; }
- [Option('x', "recursive", DefaultValue = false, HelpText ="Cleanup subdirectories recursively")]
+ [Option('x', "recursive", Default = false, HelpText ="Cleanup subdirectories recursively")]
public bool CleanupRecursive { get; set; }
- [ParserState]
- public IParserState LastParserState { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- return HelpText.AutoBuild(this, (HelpText current) => HelpText.DefaultParsingErrorsHandler(this, current));
- }
-
+ [Option("csv", HelpText = "PATH to import LOCODE csv")]
+ public string LocodeCSV { get; set; }
+ [Option("db", HelpText = "PATH to locode db (SQLITE)")]
+ public string LocodeDB { get; set; }
}
}
diff --git a/bsmd.Tool/Program.cs b/bsmd.Tool/Program.cs
index f6357b9a..54909cb8 100644
--- a/bsmd.Tool/Program.cs
+++ b/bsmd.Tool/Program.cs
@@ -1,28 +1,25 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using CommandLine;
using log4net;
+using System;
namespace bsmd.Tool
{
- class Program
+ public static class Program
{
- private static ILog log = LogManager.GetLogger("Tool");
+ private static readonly ILog log = LogManager.GetLogger("Tool");
- static int Main(string[] args)
+ public static int Main(string[] args)
{
+ int result = 0;
log4net.Config.XmlConfigurator.Configure();
Options options = new Options();
- if (CommandLine.Parser.Default.ParseArguments(args, options))
+ try
{
- try
+ Parser.Default.ParseArguments(args).WithParsed(o =>
{
- if (options.CheckRules)
+ if (o.CheckRules)
{
- Guid coreId;
- if (Guid.TryParse(options.MessageCoreId, out coreId))
+ if (Guid.TryParse(options.MessageCoreId, out Guid coreId))
{
CheckRules.Check(coreId);
}
@@ -32,27 +29,27 @@ namespace bsmd.Tool
log.FatalFormat("CheckRules: cannot parse message core id");
}
}
- else if((options.CleanupFolderRoot != null) && (options.CleanupFolderRoot.Length > 0))
+ if (!string.IsNullOrEmpty(o.CleanupFolderRoot))
{
CleanupFiles.Cleanup(options.CleanupFolderRoot, options.StaleDays, options.CleanupRecursive);
}
- else
+ if(o.ImportLocodes)
{
-
+ if(!string.IsNullOrEmpty(o.LocodeCSV) && !string.IsNullOrEmpty(o.LocodeDB))
+ {
+ LocodeSQliteImport.Import(o.LocodeDB, o.LocodeCSV);
+ }
}
- return 0;
- }
- catch (Exception ex)
- {
- log.ErrorFormat("an exception occurred: {0}", ex.Message);
- return 1;
- }
+
+ });
}
- else
+ catch (Exception ex)
{
- Console.WriteLine(options.GetUsage());
- return 1;
+ log.Fatal(ex.ToString());
+ result = 1;
}
+ Console.Read();
+ return result;
}
}
}
diff --git a/bsmd.Tool/Properties/Settings.Designer.cs b/bsmd.Tool/Properties/Settings.Designer.cs
index 9607f28a..4d40f00d 100644
--- a/bsmd.Tool/Properties/Settings.Designer.cs
+++ b/bsmd.Tool/Properties/Settings.Designer.cs
@@ -12,7 +12,7 @@ namespace bsmd.Tool.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
diff --git a/bsmd.Tool/bsmd.Tool.csproj b/bsmd.Tool/bsmd.Tool.csproj
index 8b66e734..92d23e99 100644
--- a/bsmd.Tool/bsmd.Tool.csproj
+++ b/bsmd.Tool/bsmd.Tool.csproj
@@ -9,8 +9,11 @@
Properties
bsmd.Tool
bsmd.Tool
- v4.5
+ v4.8
512
+
+
+
AnyCPU
@@ -38,15 +41,23 @@
..\bsmdKey.snk
-
- ..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll
+
+ ..\bsmd.database\bin\Debug\bsmd.database.dll
-
- ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll
- True
+
+ ..\packages\CommandLineParser.2.9.1\lib\net461\CommandLine.dll
+
+
+ ..\packages\log4net.2.0.15\lib\net45\log4net.dll
+
+
+ ..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.117.0\lib\net46\System.Data.SQLite.dll
+
+
+
@@ -65,6 +76,7 @@
+
@@ -83,13 +95,14 @@
Settings.Designer.cs
-
-
- {19945af2-379b-46a5-b27a-303b5ec1d557}
- bsmd.database
-
-
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+