diff --git a/ENI2/DetailViewControls/OverViewDetailControl.xaml.cs b/ENI2/DetailViewControls/OverViewDetailControl.xaml.cs index 0b041cdd..b1764f84 100644 --- a/ENI2/DetailViewControls/OverViewDetailControl.xaml.cs +++ b/ENI2/DetailViewControls/OverViewDetailControl.xaml.cs @@ -721,8 +721,8 @@ namespace ENI2.DetailViewControls // get here if user selected some classes // start importer - - // show import result? + + // validate all selected import classes (Finger with "selection") } } diff --git a/ENI2/Import/ExcelBase.cs b/ENI2/Import/ExcelBase.cs new file mode 100644 index 00000000..587350bd --- /dev/null +++ b/ENI2/Import/ExcelBase.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2017-today Informatikbüro Daniel Schick +// Base class excel (writer not yet implemented but eventually..) + +using System; +using System.Collections.Generic; +using Microsoft.Office.Interop.Excel; +using System.Runtime.InteropServices; +using log4net; + +namespace ENI2.Import +{ + internal class ExcelBase : IDisposable + { + + #region Fields + + internal enum CountryMode { NONE, DE, DK }; + + protected CountryMode _countryMode = CountryMode.NONE; + + protected Workbooks _excelWorkbooks; + protected Workbook _portcall; + protected Application _excelApp; + protected Dictionary _nameDict; + protected ILog _log; + + #endregion + + #region Properties + + internal CountryMode Mode { get { return _countryMode; } } + + #endregion + + #region Saving + + internal bool Save(string filePath) + { + bool result = true; + if (this._excelApp == null) return false; + try + { + this._excelApp.SaveWorkspace(filePath); + } + catch (Exception ex) + { + _log.WarnFormat("cannot save workspace: {0}", ex.Message); + result = false; + } + return result; + } + + internal bool SaveCopy(string filePath) + { + bool result = true; + if (this._excelApp == null) return false; + try + { + this._portcall.Saved = true; + this._portcall.SaveCopyAs(filePath); + } + catch (Exception ex) + { + _log.WarnFormat("cannot save copy of workbook: {0}", ex.Message); + result = false; + } + return result; + } + + #endregion + + #region Dispose + + public void Dispose() + { + try + { + if (this._portcall != null) + { + this._portcall.Close(0); + _log.Debug("Close Worksheet"); + Marshal.ReleaseComObject(this._portcall); + } + + if (this._excelWorkbooks != null) + { + this._excelWorkbooks.Close(); + _log.Debug("Close Workbooks"); + Marshal.ReleaseComObject(this._excelWorkbooks); + // this._excelWorkbooks.Close(); + } + if (this._excelApp != null) + { + _log.Debug("Quit Excel"); + this._excelApp.Quit(); + Marshal.ReleaseComObject(this._excelApp); + } + } + catch(Exception ex) + { + _log.ErrorFormat("Exception disposing ExcelReader: {0}", ex.Message); + } + } + + #endregion + + } +} diff --git a/ENI2/Import/ExcelManager.cs b/ENI2/Import/ExcelManager.cs new file mode 100644 index 00000000..a996803d --- /dev/null +++ b/ENI2/Import/ExcelManager.cs @@ -0,0 +1,57 @@ +// Copyright (c) 2017- Informatikbüro Daniel Schick +// Description: Controller class for reading excel sheets (label-based) + +using bsmd.database; +using log4net; +using System; +using System.Collections.Generic; +using System.IO; + +namespace ENI2.Import +{ + public class ExcelManager + { + private readonly ILog _log = LogManager.GetLogger(typeof(ExcelManager)); + + public ExcelManager() + { + Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); + } + + public bool Import(string filePath, MessageCore core, List classes, out string readMessage) + { + bool result = false; + try + { + using (ExcelReader reader = new ExcelReader(filePath)) + { + ImportHeader importHeader = new ImportHeader + { + ImportDate = DateTime.Now + }; + result = ExcelUtil.ProcessSheet(reader, out readMessage, core); // actual import + if (result) + { + importHeader.MessageCoreId = core.Id.Value; + importHeader.Filename = Path.GetFileName(filePath); + ReportingParty thisUser = ReportingParty.CurrentReportingParty; + importHeader.SenderEmail = thisUser.EMail; + importHeader.ReportingPartyId = thisUser.Id; + + DBManager.Instance.Save(importHeader); + // Saving plaintext data (ImportHeader + ImportValues) for each reading + List valueList = importHeader.CreateUpdateList(reader.ImportValues); + // Bulk save recommended here.. + ImportValue.BulkSave(valueList); + } + } + } + catch (Exception ex) + { + readMessage = ex.Message; + _log.Error(ex); + } + return result; + } + } +} diff --git a/ENI2/Import/ExcelReader.cs b/ENI2/Import/ExcelReader.cs new file mode 100644 index 00000000..b6263a2f --- /dev/null +++ b/ENI2/Import/ExcelReader.cs @@ -0,0 +1,576 @@ +// +// Class: ExcelReader +// Current CLR: 4.0.30319.34209 +// System: Microsoft Visual Studio 10.0 +// Author: dani +// Created: 6/15/2015 10:03:40 PM +// +// Copyright (c) 2015 Informatikbüro Daniel Schick. All rights reserved. + +using log4net; +using Microsoft.Office.Interop.Excel; +using System; +using System.Collections.Generic; +using System.Data; + +using System.Globalization; +using System.Linq; +using System.Runtime.InteropServices; +using ENI2.Locode; +using bsmd.database; + +namespace ENI2.Import +{ + internal class ExcelReader : ExcelBase + { + internal enum ReadState { NONE, OK, WARN, FAIL }; + + internal Dictionary ImportValues { get; } = new Dictionary(); + + public ExcelReader(string filePath) + { + _log = LogManager.GetLogger(typeof(ExcelReader)); + + this._excelApp = new Application(); + this._excelApp.DisplayAlerts = false; + this._excelWorkbooks = _excelApp.Workbooks; + + this._portcall = _excelWorkbooks.Open(filePath, 0, true, 5, "", "", false, XlPlatform.xlWindows, "", false, false, 0, false, false, false); + _nameDict = new Dictionary(); + int bookCnt = 0; + foreach(Name name in _portcall.Names) + { + string theValue = name.Value; + // Namensbezug: =SheetZelle. Leere Referenzen überspringen (kommt immer mal wieder vor!) + + string nameKey = name.Name; + + try + { + if (nameKey.Contains("!")) + nameKey = nameKey.Substring(nameKey.IndexOf('!') + 1); + } + catch(Exception) + { + _log.DebugFormat("Strange name in Sheet: {0}", nameKey); + continue; + } + + if ((theValue != "=#REF!#REF!") && (theValue != "=#BEZUG!#BEZUG!")) + { + _nameDict[nameKey] = name; + bookCnt++; + } + } + _log.DebugFormat("{0} named ranges found at Workbook level", bookCnt); + + + foreach(Worksheet ws in _portcall.Worksheets) + { + int wsCnt = 0; + foreach(Name name in ws.Names) + { + string theValue = name.Value; + // Namensbezug: =SheetZelle. Leere Referenzen überspringen (kommt immer mal wieder vor!) + if (!_nameDict.ContainsKey(name.Name)) + { + if ((theValue != "=#REF!#REF!") && (theValue != "=#BEZUG!#BEZUG!")) + { + _nameDict[name.Name] = name; + wsCnt++; + } + } + } + if (wsCnt > 0) + _log.DebugFormat("{0} named ranges found in Worksheet {1}", wsCnt, ws.Name); + } + } + + + internal string ReadText(string lookup) + { + string result = null; + if (_nameDict.ContainsKey(lookup)) + { + try + { + var val = _nameDict[lookup].RefersToRange.Value; + var val2 = _nameDict[lookup].RefersToRange.Value2; + if (val != null) + result = val.ToString().Trim(); + else if (val2 != null) + result = val2.ToString().Trim(); + } + catch (COMException ex) + { + _log.WarnFormat("COMException reading field {0}: {1}", lookup, ex.ErrorCode); + } + } + if (result != null) + { + result = result.Trim(); + this.ImportValues[lookup] = result; + } + + return result; + } + + internal string ReadTextNoWhitespace(string lookup) + { + string val = this.ReadText(lookup); + if (val == null) return val; + return new string(val.Where(c => !Char.IsWhiteSpace(c)).ToArray()); + } + + internal string ReadLoCode(string lookup) + { + string val = this.ReadText(lookup); + if (!val.IsNullOrEmpty()) + { + val = val.ToUpper(); + string portName = LocodeDB.PortNameFromLocode(val); + if(portName.IsNullOrEmpty()) + _log.WarnFormat("unknown Locode {0}", val); + } + return val; + } + + internal int? ReadCargoLACode(string lookup) + { + string val = ReadText(lookup); + if (val.IsNullOrEmpty()) return null; + + if(int.TryParse(val, out int result)) + { + if ((result < 10) || (result > 99)) + _log.WarnFormat("invalid cargo LA code {0}", result); + return result; + } + else + { + _log.ErrorFormat("Cargo LA code parse error for {0}", lookup); + return null; + } + } + + internal byte? ReadGender(string lookup) + { + byte? result = null; + string val = this.ReadText(lookup); + if (val != null) + { + if (val.Equals("m", StringComparison.CurrentCultureIgnoreCase) || val.Equals("male", StringComparison.CurrentCultureIgnoreCase)) { + result = 0; + } + else if (val.Equals("f", StringComparison.CurrentCultureIgnoreCase) || val.Equals("female", StringComparison.CurrentCultureIgnoreCase)) + { + result = 1; + } + else + { + result = 2; + } + } + if(result == null) + { + _log.ErrorFormat("error reading gender on {0}", lookup); + } + return result; + } + + internal byte? ReadIdentityDocumentType(string lookup) + { + byte? result = null; + string val = this.ReadText(lookup); + if (val != null) + { + if (val.Equals("identity_card", StringComparison.CurrentCultureIgnoreCase) || val.Equals("1")) result = 0; + if (val.Equals("passport", StringComparison.CurrentCultureIgnoreCase) || val.Equals("2")) result = 1; + if (val.Equals("muster_book", StringComparison.CurrentCultureIgnoreCase) || val.Equals("3")) result = 2; + if (val.Equals("picture_id", StringComparison.CurrentCultureIgnoreCase) || val.Equals("4")) result = 3; + if (val.Equals("residental_permit", StringComparison.CurrentCultureIgnoreCase) || val.Equals("5")) result = 4; + if (val.Equals("other_legal_identity_document", StringComparison.CurrentCultureIgnoreCase) || val.Equals("6")) result = 5; + if (val.Equals("ic", StringComparison.CurrentCultureIgnoreCase)) result = 0; + } + + if (!result.HasValue) + _log.ErrorFormat("cannot read identity document type {0}", lookup); + + return result; + } + + internal byte? ReadShippingArea(string lookup) + { + string val = this.ReadText(lookup); + byte? result = null; + if (val != null) + { + if ((val.IndexOf("baltic", StringComparison.OrdinalIgnoreCase) >= 0) || (val.Equals("1"))) result = 0; + if ((val.IndexOf("europe", StringComparison.OrdinalIgnoreCase) >= 0) || (val.Equals("2"))) result = 1; + if ((val.IndexOf("overseas", StringComparison.OrdinalIgnoreCase) >= 0) || (val.Equals("3"))) result = 2; + } + + if (!result.HasValue) + _log.ErrorFormat("cannot read shipping area {0}", lookup); + + return result; + } + + internal byte? ReadGeneralDescriptionOfCargo(string lookup) + { + string val = this.ReadText(lookup); + byte? result = null; + if (val != null) + { + if (val.Contains("container", StringComparison.OrdinalIgnoreCase) || val.Equals("1")) result = 0; + if (val.Contains("vehicles", StringComparison.OrdinalIgnoreCase) || val.Equals("2")) result = 1; + if (val.Contains("convent", StringComparison.OrdinalIgnoreCase) || val.Equals("3")) result = 2; + if (val.Contains("dry", StringComparison.OrdinalIgnoreCase) || val.Equals("4")) result = 3; + if (val.Contains("liquid", StringComparison.OrdinalIgnoreCase) || val.Equals("5")) result = 4; + if (val.Contains("empty", StringComparison.OrdinalIgnoreCase) || val.Equals("6")) result = 5; + } + + if (!result.HasValue) + _log.ErrorFormat("cannot read general description of cargo {0}", lookup); + + return result; + } + + internal byte? ReadCargoHandlingType(string lookup) + { + string val = this.ReadText(lookup); + byte? result = null; + + if(val != null) + { + if ((val.IndexOf("load", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("1")) result = 0; + if ((val.IndexOf("discharge", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("2")) result = 1; + if ((val.IndexOf("transit", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("3")) result = 2; + } + + if (!result.HasValue) + _log.ErrorFormat("cannot read cargo handling type {0}", lookup); + + return result; + } + + /// + /// read nationality field an returns 2 Char ISO code (optional lookup) and "confirms" + /// the field + /// + internal string ReadNationality(string lookup) + { + string val = this.ReadText(lookup); + + if (val.Length == 2) + { + string isoCode = LocodeDB.CountryCodeFromName(val); + if (isoCode == null) + _log.ErrorFormat("Wrong ISO code {0}", val); + } + else + { + _log.ErrorFormat("cannot read nationality {0}", lookup); + } + + return val; + } + + internal byte? ReadHullConfiguration(string lookup) + { + string val = this.ReadText(lookup); + byte? result = null; + if (val != null) + { + if (val.IndexOf("sbt", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; + if (val.IndexOf("single", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; + if (val.IndexOf("double", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; + } + + if (!result.HasValue) + _log.ErrorFormat("cannot read hull configuration {0}", lookup); + + return result; + } + + internal byte? ReadPackingGroup(string lookup) + { + string val = this.ReadText(lookup); + byte? result = null; + + if(val!= null) + { + if (val == "I") result = 1; + if (val == "II") result = 2; + if (val == "III") result = 3; + if (val.Equals("NONE", StringComparison.OrdinalIgnoreCase)) result = 0; + } + + if (!result.HasValue) + _log.ErrorFormat("cannot read packing group {0}", lookup); + + return result; + } + + internal string ReadShip2ShipActivityType(string lookup) + { + string val = this.ReadText(lookup); + bool isValid = false; + if(!val.IsNullOrEmpty()) + { + if (int.TryParse(val, out int typeVal)) + { + if ((typeVal >= 1) && (typeVal <= 23)) + isValid = true; + } + } + + if (!isValid) + _log.WarnFormat("cannot read ship2ship activity type {0}", lookup); + + return val; + } + + internal byte? ReadConditionTanks(string lookup) + { + string val = this.ReadText(lookup); + byte? result = null; + if (val != null) + { + if (val.IndexOf("full", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; + if (val.IndexOf("empty", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; + if (val.IndexOf("inerted", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; + } + + if (!result.HasValue) + _log.ErrorFormat("cannot read condition tanks {0}", lookup); + + return result; + } + + internal byte? ReadDelivery(string lookup) + { + string val = this.ReadText(lookup); + byte? result = null; + + if (val != null) + { + if ((val.IndexOf("all", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("1")) result = 0; + if ((val.IndexOf("some", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("2")) result = 1; + if ((val.IndexOf("none", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("3")) result = 2; + } + + if (!result.HasValue) + _log.ErrorFormat("cannot read delivery {0}", lookup); + + return result; + } + + internal DateTime? ReadBirthDate(string lookup) + { + DateTime? result = this.ReadDate(lookup); + if(result.HasValue) + { + if (result.Value > DateTime.Now) + _log.WarnFormat("Birth date implausible for {0} : {1}", lookup, result); + } + return result; + } + + internal DateTime? ReadDate(string lookup, bool noHighlight = false) + { + try + { + DateTime? date = null; + + if (_nameDict.ContainsKey(lookup)) + { + var val = _nameDict[lookup].RefersToRange.Value; + if (val is DateTime) + { + date = val; + } + else if (val is double) + { + try + { + date = DateTime.FromOADate(val); + } + catch (ArgumentException) { /* .. */ } + if(date == null) + { + CultureInfo provider = CultureInfo.InvariantCulture; + string dateString = val.ToString(); + const string format = "yyyyMMdd"; + if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out DateTime tmpDate)) + date = tmpDate; + } + } + + if (date == null) + { + if (DateTime.TryParse(val, out DateTime tmpDate)) + date = tmpDate; + } + + if (date != null) + { + if ((date.Value < new DateTime(1899, 1, 1)) || (date.Value > new DateTime(2030, 1, 1))) + { + date = null; // this can't be right + } + } + } + + return date; + } + catch (Exception) + { + _log.WarnFormat("error parsing datetime for lookup {0}", lookup); + return null; + } + } + + internal DateTime? ReadDateTime(string dateField, string timeField, bool noHighlight = false) + { + DateTime? result = null; + DateTime? etaDate = this.ReadDate(dateField, noHighlight); + DateTime? etaTime = this.ReadTime(timeField, noHighlight); + if (etaDate != null) + { + result = new DateTime(etaDate.Value.Year, etaDate.Value.Month, etaDate.Value.Day); + if (etaTime != null) + { + result = new DateTime(etaDate.Value.Year, etaDate.Value.Month, etaDate.Value.Day, etaTime.Value.Hour, etaTime.Value.Minute, etaTime.Value.Second, DateTimeKind.Local); + result = result.Value.ToUniversalTime(); + } + } + + return result; + } + + internal DateTime? ReadTime(string lookup, bool noHighlight = false) + { + DateTime? result = null; + + try + { + if (_nameDict.ContainsKey(lookup)) + { + var val = _nameDict[lookup].RefersToRange.Value; + if (val is DateTime) + { + result = val; + } + if (val is double) + { + try + { + result = DateTime.FromOADate(val); + } + catch(ArgumentException) { } + + if (result == null) + { + CultureInfo provider = CultureInfo.InvariantCulture; + string dateString = val.ToString(); + if (!dateString.Contains(":")) + { + const string format = "HHmm"; + if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out DateTime tmpDate)) + result = tmpDate; + } + } + + } + if (result == null) + { + if (DateTime.TryParseExact(val, "HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out DateTime date)) + result = date; + } + + if (result == null) + { + if (DateTime.TryParseExact(val, "HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out DateTime date)) + result = date; + } + + if ((result == null) && (val != null)) + { + CultureInfo provider = CultureInfo.InvariantCulture; + string dateString = val.ToString(); + if (!dateString.Contains(":")) + { + const string format = "HHmm"; + if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out DateTime tmpDate)) + result = tmpDate; + } + } + } + } + catch (Exception) + { + _log.WarnFormat("error reading time for lookup {0}", lookup); + } + + return result; + } + + internal double? ReadNumber(string lookup) + { + double? result = null; + try + { + if (_nameDict.ContainsKey(lookup)) + { + var val = _nameDict[lookup].RefersToRange.Value; + if (val is double) result = val; + if (val is string) + { + if (double.TryParse(val, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, + CultureInfo.InvariantCulture, out double tmpDouble)) + result = tmpDouble; + if (result == null) + { + if (double.TryParse(val, out tmpDouble)) // current language style (==GER, mit , statt .) + result = tmpDouble; + } + } + + if ((result == null) && (val != null)) + { + double tmpDouble2 = val[1, 1]; + result = tmpDouble2; + } + } + } + catch (Exception) + { + _log.WarnFormat("error reading number for lookup {0}", lookup); + } + return result; + } + + internal double ReadNumberDefaultZero(string lookup) + { + double? result = this.ReadNumber(lookup); + if(!result.HasValue) + { + result = 0; + } + return result.Value; + } + + internal bool? ReadBoolean(string lookup, bool noHighlight = false) + { + string val = this.ReadText(lookup); + if (val == null) + return null; + + if ((val == "y") || (val == "Y") || val.Equals("yes", StringComparison.OrdinalIgnoreCase) || (val == "1") || (val == "x") || (val == "X")) + return true; + + return false; + } + } +} diff --git a/ENI2/Import/ExcelUtil.cs b/ENI2/Import/ExcelUtil.cs new file mode 100644 index 00000000..a8c1e7ef --- /dev/null +++ b/ENI2/Import/ExcelUtil.cs @@ -0,0 +1,2913 @@ +// +// Class: Util +// Current CLR: 4.0.30319.34209 +// System: Microsoft Visual Studio 10.0 +// Author: dani +// Created: 6/17/2015 7:12:38 AM +// +// Copyright (c) 2015 Informatikbüro Daniel Schick. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using log4net; +using bsmd.database; + +namespace ENI2.Import +{ + public static class ExcelUtil + { + private static readonly ILog _log = LogManager.GetLogger(typeof(ExcelUtil)); + + internal static bool ProcessSheet(ExcelReader reader, out string readMessage, MessageCore messageCore) + { + messageCore = ExcelUtil.LookupMessageCore(reader, out readMessage); + + if (messageCore == null) return false; // cannot work with this sheet or create one + + // load messages if already present + List messages = DBManager.Instance.GetMessagesForCore(messageCore, DBManager.MessageLoad.ALL); + + // start parsing fields + if (messageCore.IsTransit) + { + // scan for transit messages + + ScanAGNT(messages, messageCore, reader); + + ScanNOA_NOD(messages, messageCore, reader); + + ScanSEC(messages, messageCore, reader); + + ScanPOBA(messages, messageCore, reader); + + ScanPOBD(messages, messageCore, reader); + + ScanTIEFA(messages, messageCore, reader); + + ScanBKRA(messages, messageCore, reader); + + ScanSTAT(messages, messageCore, reader); + + ScanMDH(messages, messageCore, reader); + + ScanCREW(messages, messageCore, reader); + + ScanPAS(messages, messageCore, reader); + + // BPOL wieder reingenommen nach RS mit CH (27.9.17) + ScanBPOL(messages, messageCore, reader); + + ScanTOWA(messages, messageCore, reader); + + ScanHAZA(messages, messageCore, reader); + + ScanHAZD(messages, messageCore, reader); + + } + else + { + // scan for visit messages + + ScanAGNT(messages, messageCore, reader); + + ScanNOA_NOD(messages, messageCore, reader); + + ScanATA(messages, messageCore, reader); + + ScanATD(messages, messageCore, reader); + + ScanSEC(messages, messageCore, reader); + + ScanPOBA(messages, messageCore, reader); + + ScanPOBD(messages, messageCore, reader); + + ScanNAME(messages, messageCore, reader); + + ScanTIEFA(messages, messageCore, reader); + + ScanTIEFD(messages, messageCore, reader); + + ScanBKRA(messages, messageCore, reader); + + ScanBKRD(messages, messageCore, reader); + + ScanSTAT(messages, messageCore, reader); + + ScanLADG(messages, messageCore, reader); + + ScanSTO(messages, messageCore, reader); + + ScanINFO(messages, messageCore, reader); + + ScanSERV(messages, messageCore, reader); + + ScanPRE72H(messages, messageCore, reader); + + ScanMDH(messages, messageCore, reader); + + ScanWAS(messages, messageCore, reader); + + ScanCREW(messages, messageCore, reader); + + ScanPAS(messages, messageCore, reader); + + ScanBPOL(messages, messageCore, reader); + + ScanTOWA(messages, messageCore, reader); + + ScanTOWD(messages, messageCore, reader); + + ScanHAZA(messages, messageCore, reader); + + ScanHAZD(messages, messageCore, reader); + + } + + //string sheetVersion = reader.GetCell("Portcall", 2, 1) as string; + //messageCore.SietasSheetVersion = sheetVersion; + + DBManager.Instance.Save(messageCore); + + // save all messages now + + foreach (Message message in messages) + { + message.CreatedBy = "EXCEL"; + if ((message.MessageNotificationClass == Message.NotificationClass.CREWD) || (message.MessageNotificationClass == Message.NotificationClass.CREWD) || + (message.MessageNotificationClass == Message.NotificationClass.STO)) + message.InternalStatus = Message.BSMDStatus.PREPARE; + else + message.InternalStatus = Message.BSMDStatus.EXCEL; + message.UnsentMessageWarningShown = false; + DBManager.Instance.Save(message); + message.SaveElements(); + } + + return true; + } + + #region ATA + + private static void ScanATA(List messages, MessageCore messageCore, ExcelReader reader) + { + Message ataMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.ATA); + if (ataMessage.Elements.Count == 0) + { + ATA newATA = new ATA(); + newATA.MessageHeader = ataMessage; + ataMessage.Elements.Add(newATA); + } + ATA ata = ataMessage.Elements[0] as ATA; + Util.ScanMessage(ata, reader); + + if(!ata.ATAPortOfCall.HasValue) + { + reader.ReadDateTime("ATA.ATADatePortOfCall", "ATA.ATATimePortOfCall"); + } + + if (!ata.ATAPortOfCall.HasValue && ataMessage.IsNew) + messages.Remove(ataMessage); + } + + #endregion + + #region ATD + + private static void ScanATD(List messages, MessageCore messageCore, ExcelReader reader) + { + Message atdMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.ATD); + if (atdMessage.Elements.Count == 0) + { + ATD newATD = new ATD(); + newATD.MessageHeader = atdMessage; + atdMessage.Elements.Add(newATD); + } + ATD atd = atdMessage.Elements[0] as ATD; + Util.ScanMessage(atd, reader); + + if (!atd.ATDPortOfCall.HasValue) + { + reader.ReadDateTime("ATD.ATDDatePortOfCall", "ATD.ATDTimePortOfCall"); + } + + if (!atd.ATDPortOfCall.HasValue && atdMessage.IsNew) + messages.Remove(atdMessage); + } + + #endregion + + #region TIEFA + + private static void ScanTIEFA(List messages, MessageCore messageCore, ExcelReader reader) + { + Message tiefaMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.TIEFA); + if (tiefaMessage.Elements.Count == 0) + { + TIEFA newTIEFA = new TIEFA(); + newTIEFA.MessageHeader = tiefaMessage; + tiefaMessage.Elements.Add(newTIEFA); + } + TIEFA tiefa = tiefaMessage.Elements[0] as TIEFA; + Util.ScanMessage(tiefa, reader); + if (!tiefa.DraughtUponArrival_DMT.HasValue && tiefaMessage.IsNew) + messages.Remove(tiefaMessage); + + reader.Conf.ConfirmNumber("TIEFA.DraughtUponArrival_DMT_DK", tiefa.DraughtUponArrival_DMT, tiefa.DraughtUponArrival_DMT.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL); + + } + + #endregion + + #region TIEFD + + private static void ScanTIEFD(List messages, MessageCore messageCore, ExcelReader reader) + { + Message tiefdMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.TIEFD); + if(tiefdMessage.Elements.Count == 0) + { + TIEFD newTIEFD = new TIEFD(); + newTIEFD.MessageHeader = tiefdMessage; + tiefdMessage.Elements.Add(newTIEFD); + } + TIEFD tiefd = tiefdMessage.Elements[0] as TIEFD; + Util.ScanMessage(tiefd, reader); + if (!tiefd.DraughtUponDeparture_DMT.HasValue && tiefdMessage.IsNew) + messages.Remove(tiefdMessage); + + reader.Conf.ConfirmNumber("TIEFD.DraughtUponDeparture_DMT_DK", tiefd.DraughtUponDeparture_DMT, tiefd.DraughtUponDeparture_DMT.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL); + + } + + #endregion + + #region NAME + + private static void ScanNAME(List messages, MessageCore messageCore, ExcelReader reader) + { + Message nameMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.NAME); + if (nameMessage.Elements.Count == 0) + { + NAME newNAME = new NAME(); + newNAME.MessageHeader = nameMessage; + nameMessage.Elements.Add(newNAME); + } + NAME name = nameMessage.Elements[0] as NAME; + Util.ScanMessage(name, reader); + if (name.NameOfMaster.IsNullOrEmpty() && name.IsNew) + messages.Remove(nameMessage); + } + + #endregion + + #region BPOL + + private static void ScanBPOL(List messages, MessageCore messageCore, ExcelReader reader) + { + // Die Verarbeitung dieser Nachricht aktuell nur für + Message bpolMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.BPOL); + if (bpolMessage.Elements.Count == 0) + { + BPOL newBPOL = new BPOL(); + newBPOL.MessageHeader = bpolMessage; + bpolMessage.Elements.Add(newBPOL); + } + + BPOL bpol = bpolMessage.Elements[0] as BPOL; + Util.ScanMessage(bpol, reader); + + // 19.12.16: Einschleicher-Feld von Klasse POBA übernehmen (anderes ist nicht im Sheet!) + Message pobaMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.POBA); + if(pobaMessage.Elements.Count > 0) + { + POBA poba = pobaMessage.Elements[0] as POBA; + bpol.StowawaysOnBoard = (poba.TotalStowawaysOnBoardUponArrival ?? 0) > 0; + } + + bpol.DeleteElements(); + + // PortOfItinerary + for (int i = 1; i <= 10; i++) + { + string bpolName = string.Format("BPOL.PortOfItineraryName_{0}", i); + string bpolLocode = string.Format("BPOL.PortOfItineraryLoCode_{0}", i); + string bpolETADate = string.Format("BPOL.PortOfItineraryETADate_{0}", i); + string bpolETATime = string.Format("BPOL.PortOfItineraryETATime_{0}", i); + + string bpolNameValue = reader.ReadText(bpolName)?.Trim(); + string bpolLocodeValue = reader.ReadLoCode(bpolLocode); + + if (!bpolNameValue.IsNullOrEmpty() || !bpolLocodeValue.IsNullOrEmpty()) + { + if (!(bpol.GetSublistElementWithIdentifier(i.ToString()) is PortOfItinerary poi)) + { + poi = new PortOfItinerary(); + poi.BPOL = bpol; + poi.Identifier = i.ToString(); + bpol.PortOfItineraries.Add(poi); + } + + poi.PortOfItineraryName = bpolNameValue; + reader.Conf.ConfirmText(bpolName, bpolNameValue, ExcelReader.ReadState.OK); + poi.PortOfItineraryLocode = bpolLocodeValue; + // falls nur Locode angegeben wurde, Portname aus Locode ermitteln + if(poi.PortOfItineraryName.IsNullOrEmpty() && !poi.PortOfItineraryLocode.IsNullOrEmpty() && (poi.PortOfItineraryLocode.Length == 5)) + { + poi.PortOfItineraryName = LocodeDB.PortNameFromLocode(poi.PortOfItineraryLocode); + } + + poi.PortOfItineraryETA = reader.ReadDateTime(bpolETADate, bpolETATime); + } + } + } + + #endregion + + #region POBA + + private static void ScanPOBA(List messages, MessageCore messageCore, ExcelReader reader) + { + Message pobaMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.POBA); + if(pobaMessage.Elements.Count == 0) + { + POBA newPoba = new POBA(); + newPoba.MessageHeader = pobaMessage; + pobaMessage.Elements.Add(newPoba); + } + + POBA poba = pobaMessage.Elements[0] as POBA; + Util.ScanMessage(poba, reader); + if (((poba.TotalPersonsOnBoardUponArrival ?? 0) == 0) && poba.IsNew) + messages.Remove(pobaMessage); + + reader.Conf.ConfirmNumber("POBA.TotalCrewMembersOnBoardUponArrival_DK", poba.TotalCrewMembersOnBoardUponArrival, + (poba.TotalCrewMembersOnBoardUponArrival.HasValue && poba.TotalCrewMembersOnBoardUponArrival > 0) ? + ExcelReader.ReadState.OK : ExcelReader.ReadState.WARN); + + reader.Conf.ConfirmNumber("POBA.TotalPassengersOnBoardUponArrival_DK", poba.TotalPassengersOnBoardUponArrival, + ExcelReader.ReadState.OK); + } + + #endregion + + #region POBD + + private static void ScanPOBD(List messages, MessageCore messageCore, ExcelReader reader) + { + Message pobdMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.POBD); + if(pobdMessage.Elements.Count == 0) + { + POBD newPobd = new POBD(); + newPobd.MessageHeader = pobdMessage; + pobdMessage.Elements.Add(newPobd); + } + + POBD pobd = pobdMessage.Elements[0] as POBD; + Util.ScanMessage(pobd, reader); + if (((pobd.TotalPersonsOnBoardUponDeparture ?? 0) == 0) && pobd.IsNew) + messages.Remove(pobdMessage); + + reader.Conf.ConfirmNumber("POBD.TotalCrewMembersOnBoardUponDeparture_DK", pobd.TotalCrewMembersOnBoardUponDeparture, + (pobd.TotalCrewMembersOnBoardUponDeparture.HasValue && pobd.TotalCrewMembersOnBoardUponDeparture > 0) ? + ExcelReader.ReadState.OK : ExcelReader.ReadState.WARN); + + reader.Conf.ConfirmNumber("POBD.TotalPassengersOnBoardUponDeparture_DK", pobd.TotalPassengersOnBoardUponDeparture, + ExcelReader.ReadState.OK); + + } + + #endregion + + #region HAZA + + private static void ScanHAZA(List messages, MessageCore messageCore, ExcelReader reader) + { + Message hazaMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.HAZA); + if(hazaMessage.Elements.Count == 0) + { + HAZ newHaza = new HAZ(); + newHaza.IsDeparture = false; + newHaza.MessageHeader = hazaMessage; + hazaMessage.Elements.Add(newHaza); + } + HAZ haza = hazaMessage.Elements[0] as HAZ; + // haza.DeleteElements(); + + haza.NoDPGOnBoardOnArrival = !reader.ReadBoolean("HAZA.DGOnBoard"); + haza.DPGManifestOnBoardOnArrival = reader.ReadBoolean("HAZA.DPGManifestOnBoardOnArrival"); + haza.DPGContactFamilyName = reader.ReadText("HAZA.DPGContactFamilyName"); + reader.Conf.ConfirmText("HAZA.DPGContactFamilyName", haza.DPGContactFamilyName, haza.DPGContactFamilyName.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + haza.DPGContactPhone = reader.ReadText("HAZA.DPGContactPhone"); + reader.Conf.ConfirmText("HAZA.DPGContactPhone", haza.DPGContactPhone, haza.DPGContactPhone.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + haza.MOUBaltic = reader.ReadBoolean("HAZA.MOUBaltic"); + string shipClass = reader.ReadText("HAZA.INFShipClass"); + if(shipClass.IsNullOrEmpty()) + { + reader.Conf.ConfirmText("HAZA.INFShipClass", null, ExcelReader.ReadState.FAIL); + } + else + { + if (shipClass.Contains('1')) haza.INFShipClass = 0; + if (shipClass.Contains('2')) haza.INFShipClass = 1; + if (shipClass.Contains('3')) haza.INFShipClass = 2; + // if (shipClass.Equals("none", StringComparison.OrdinalIgnoreCase)) haza.INFShipClass = 0; // "NONE" existiert nicht in der Enumeration!! + reader.Conf.ConfirmText("HAZA.INFShipClass", shipClass, haza.INFShipClass.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.WARN); + } + + // IMDG + #region IMDG + + for (int i = 1; i <= 10; i++) + { + string imdg_unno = string.Format("HAZA.IMDG.UNNumber_{0}", i); + string imdg_properShippingName = string.Format("HAZA.IMDG.ProperShippingName_{0}", i); + string imdg_imoClass = string.Format("HAZA.IMDG.IMOClass_{0}", i); + string imdg_packingGroup = string.Format("HAZA.IMDG.PackingGroup_{0}", i); + string imdg_marinePollutant = string.Format("HAZA.IMDG.MarinePollutant_{0}", i); + string imdg_flashpoint = string.Format("HAZA.IMDG.Flashpoint_CEL_{0}", i); + string imdg_numberOfPackages = string.Format("HAZA.IMDG.NumberOfPackages_{0}", i); + string imdg_packageType = string.Format("HAZA.IMDG.PackageType_{0}", i); + string imdg_limitedQuantities = string.Format("HAZA.IMDG.LimitedQuantities_{0}", i); + string imdg_exceptedQuantities = string.Format("HAZA.IMDG.ExceptedQuantities_{0}", i); + string imdg_netQuantity = string.Format("HAZA.IMDG.NetQuantity_KGM_{0}", i); + string imdg_grossQuantity = string.Format("HAZA.IMDG.GrossQuantity_KGM_{0}", i); + string imdg_number = string.Format("HAZA.IMDG.Number_{0}", i); + string imdg_stowagePosition = string.Format("HAZA.IMDG.StowagePosition_{0}", i); + string imdg_portOfLoading = string.Format("HAZA.IMDG.PortOfLoading_{0}", i); + string imdg_portOfDischarge = string.Format("HAZA.IMDG.PortOfDischarge_{0}", i); + string imdg_containerNumber = string.Format("HAZA.IMDG.ContainerNumber_{0}", i); + + + string unNumber = reader.ReadText(imdg_unno); + if(unNumber.IsNullOrEmpty()) // if unnumber is not set ignore this row + { + reader.Conf.ConfirmText(imdg_unno, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("IMDG-{0}", i); + IMDGPosition imdgPosition = haza.GetIMDGPositionWithIdentifier(posIdent); + if(imdgPosition == null) + { + imdgPosition = new IMDGPosition(); + imdgPosition.HAZ = haza; + imdgPosition.Identifier = posIdent; + haza.IMDGPositions.Add(imdgPosition); + } + + imdgPosition.UNNumber = unNumber; + reader.Conf.ConfirmText(imdg_unno, unNumber, ExcelReader.ReadState.OK); + imdgPosition.ProperShippingName = reader.ReadText(imdg_properShippingName); + reader.Conf.ConfirmText(imdg_properShippingName, imdgPosition.ProperShippingName, imdgPosition.ProperShippingName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.IMOClass = reader.ReadText(imdg_imoClass); + reader.Conf.ConfirmText(imdg_imoClass, imdgPosition.IMOClass, imdgPosition.IMOClass.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.PackingGroup = reader.ReadPackingGroup(imdg_packingGroup); + imdgPosition.MarinePollutant = reader.ReadBoolean(imdg_marinePollutant); + imdgPosition.Flashpoint_CEL = reader.ReadText(imdg_flashpoint); + ExcelReader.ReadState aReadState = ExcelReader.ReadState.NONE; + if (!imdgPosition.Flashpoint_CEL.IsNullOrEmpty()) + { + if (imdgPosition.Flashpoint_CEL == "-") + aReadState = ExcelReader.ReadState.FAIL; + else + aReadState = ExcelReader.ReadState.OK; + } + reader.Conf.ConfirmText(imdg_flashpoint, imdgPosition.Flashpoint_CEL, aReadState); + imdgPosition.NumberOfPackages = (int?)reader.ReadNumber(imdg_numberOfPackages); + imdgPosition.PackageType = reader.ReadText(imdg_packageType); + reader.Conf.ConfirmText(imdg_packageType, imdgPosition.PackageType, imdgPosition.PackageType.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.LimitedQuantities = reader.ReadBoolean(imdg_limitedQuantities); + imdgPosition.ExceptedQuantities = reader.ReadBoolean(imdg_exceptedQuantities); + imdgPosition.NetQuantity_KGM = reader.ReadNumber(imdg_netQuantity); + imdgPosition.GrossQuantity_KGM = reader.ReadNumber(imdg_grossQuantity); + imdgPosition.VehicleLicenseNumber = reader.ReadText(imdg_number); + reader.Conf.ConfirmText(imdg_number, imdgPosition.VehicleLicenseNumber, imdgPosition.VehicleLicenseNumber.IsNullOrEmpty() ? ExcelReader.ReadState.NONE : ExcelReader.ReadState.OK); + imdgPosition.StowagePosition = reader.ReadText(imdg_stowagePosition); + reader.Conf.ConfirmText(imdg_stowagePosition, imdgPosition.StowagePosition, imdgPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.PortOfLoading = reader.ReadText(imdg_portOfLoading); + reader.Conf.ConfirmText(imdg_portOfLoading, imdgPosition.PortOfLoading, imdgPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.PortOfDischarge = reader.ReadText(imdg_portOfDischarge); + reader.Conf.ConfirmText(imdg_portOfDischarge, imdgPosition.PortOfDischarge, imdgPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.ContainerNumber = reader.ReadText(imdg_containerNumber); + reader.Conf.ConfirmText(imdg_containerNumber, imdgPosition.ContainerNumber, imdgPosition.ContainerNumber.IsNullOrEmpty() ? ExcelReader.ReadState.NONE : ExcelReader.ReadState.OK); + } + + #endregion + + #region IBC + // IBC + for (int i = 1; i <= 5; i++) + { + string ibc_productName = string.Format("HAZA.IBC.ProductName_{0}", i); + string ibc_pollutionCategory = string.Format("HAZA.IBC.PollutionCategory_{0}", i); + string ibc_flash = string.Format("HAZA.IBC.FlashpointInformation_{0}", i); + string ibc_quantity = string.Format("HAZA.IBC.Quantity_KGM_{0}", i); + string ibc_stowagePosition = string.Format("HAZA.IBC.StowagePosition_{0}", i); + string ibc_portOfLoading = string.Format("HAZA.IBC.PortOfLoading_{0}", i); + string ibc_portOfDischarge = string.Format("HAZA.IBC.PortOfDischarge_{0}", i); + + string productName = reader.ReadText(ibc_productName); + if(productName.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(ibc_productName, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("IBC-{0}", i); + IBCPosition ibcPosition = haza.GetIBCPositionWithIdentifier(posIdent); + if(ibcPosition == null) + { + ibcPosition = new IBCPosition(); + ibcPosition.Identifier = posIdent; + ibcPosition.HAZ = haza; + haza.IBCPositions.Add(ibcPosition); + } + + ibcPosition.ProductName = productName; + reader.Conf.ConfirmText(ibc_productName, productName, ExcelReader.ReadState.OK); + string pollutionCategory = reader.ReadText(ibc_pollutionCategory); + if(!pollutionCategory.IsNullOrEmpty()) + { + if (pollutionCategory.Equals("X", StringComparison.OrdinalIgnoreCase)) ibcPosition.PollutionCategory = 0; + if (pollutionCategory.Equals("Y", StringComparison.OrdinalIgnoreCase)) ibcPosition.PollutionCategory = 1; + if (pollutionCategory.Equals("Z", StringComparison.OrdinalIgnoreCase)) ibcPosition.PollutionCategory = 2; + if (pollutionCategory.Equals("OS", StringComparison.OrdinalIgnoreCase)) ibcPosition.PollutionCategory = 3; + } + reader.Conf.ConfirmText(ibc_pollutionCategory, pollutionCategory, ibcPosition.PollutionCategory.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL); + + ibcPosition.Flashpoint_CEL = reader.ReadText(ibc_flash); + ExcelReader.ReadState aReadState = ExcelReader.ReadState.NONE; + if (!ibcPosition.Flashpoint_CEL.IsNullOrEmpty()) + { + if (ibcPosition.Flashpoint_CEL == "-") + aReadState = ExcelReader.ReadState.FAIL; + else + { + aReadState = ExcelReader.ReadState.OK; + if (double.TryParse(ibcPosition.Flashpoint_CEL, out double flashval)) + { + if (flashval > 60) ibcPosition.FlashpointInformation = 1; // GT60CEL + else ibcPosition.FlashpointInformation = 2; // LE60CEL + } + } + } + reader.Conf.ConfirmText(ibc_flash, ibcPosition.Flashpoint_CEL, aReadState); + ibcPosition.Quantity_KGM = (int ?) reader.ReadNumber(ibc_quantity); + ibcPosition.StowagePosition = reader.ReadText(ibc_stowagePosition); + reader.Conf.ConfirmText(ibc_stowagePosition, ibcPosition.StowagePosition, ibcPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + ibcPosition.PortOfLoading = reader.ReadText(ibc_portOfLoading); + reader.Conf.ConfirmText(ibc_portOfLoading, ibcPosition.PortOfLoading, ibcPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + ibcPosition.PortOfDischarge = reader.ReadText(ibc_portOfDischarge); + reader.Conf.ConfirmText(ibc_portOfDischarge, ibcPosition.PortOfDischarge, ibcPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + #endregion + + #region IGC + // IGC + for (int i = 1; i <= 5; i++) + { + string igc_productName = string.Format("HAZA.IGC.ProductName_{0}", i); + string igc_quantity = string.Format("HAZA.IGC.Quantity_KGM_{0}", i); + string igc_stowagePosition = string.Format("HAZA.IGC.StowagePosition_{0}", i); + string igc_portOfLoading = string.Format("HAZA.IGC.PortOfLoading_{0}", i); + string igc_portOfDischarge = string.Format("HAZA.IGC.PortOfDischarge_{0}", i); + + string productName = reader.ReadText(igc_productName); + if(productName.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(igc_productName, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("IGC-{0}", i); + IGCPosition igcPosition = haza.GetIGCPositionWithIdentifier(posIdent); + if(igcPosition == null) + { + igcPosition = new IGCPosition(); + igcPosition.Identifier = posIdent; + igcPosition.HAZ = haza; + haza.IGCPositions.Add(igcPosition); + } + + igcPosition.ProductName = productName; + reader.Conf.ConfirmText(igc_productName, productName, ExcelReader.ReadState.OK); + igcPosition.Quantity_KGM = reader.ReadNumber(igc_quantity); + igcPosition.StowagePosition = reader.ReadText(igc_stowagePosition); + reader.Conf.ConfirmText(igc_stowagePosition, igcPosition.StowagePosition, igcPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + igcPosition.PortOfLoading = reader.ReadText(igc_portOfLoading); + reader.Conf.ConfirmText(igc_portOfLoading, igcPosition.PortOfLoading, igcPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + igcPosition.PortOfDischarge = reader.ReadText(igc_portOfDischarge); + reader.Conf.ConfirmText(igc_portOfDischarge, igcPosition.PortOfDischarge, igcPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + #endregion + + #region IMSBC + // IMSBC + for (int i = 1; i <= 5; i++) + { + string imsbc_bcsn = string.Format("HAZA.IMSBC.BulkCargoShippingName_{0}", i); + string imsbc_mhb = string.Format("HAZA.IMSBC.MHB_{0}", i); + string imsbc_quantity = string.Format("HAZA.IMSBC.Quantity_KGM_{0}", i); + string imsbc_stowagePosition = string.Format("HAZA.IMSBC.StowagePosition_{0}", i); + string imsbc_portOfLoading = string.Format("HAZA.IMSBC.PortOfLoading_{0}", i); + string imsbc_portOfDischarge = string.Format("HAZA.IMSBC.PortOfDischarge_{0}", i); + + string bcsn = reader.ReadText(imsbc_bcsn); + if(bcsn.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(imsbc_bcsn, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("IMSBC-{0}", i); + IMSBCPosition imsbcPosition = haza.GetIMSBCPositionWithIdentifier(posIdent); + if(imsbcPosition == null) + { + imsbcPosition = new IMSBCPosition(); + imsbcPosition.Identifier = posIdent; + imsbcPosition.HAZ = haza; + haza.IMSBCPositions.Add(imsbcPosition); + } + + imsbcPosition.BulkCargoShippingName = bcsn; + reader.Conf.ConfirmText(imsbc_bcsn, bcsn, ExcelReader.ReadState.OK); + imsbcPosition.MHB = reader.ReadBoolean(imsbc_mhb); + imsbcPosition.Quantity_KGM = reader.ReadNumber(imsbc_quantity); + imsbcPosition.StowagePosition = reader.ReadText(imsbc_stowagePosition); + reader.Conf.ConfirmText(imsbc_stowagePosition, imsbcPosition.StowagePosition, imsbcPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imsbcPosition.PortOfLoading = reader.ReadText(imsbc_portOfLoading); + reader.Conf.ConfirmText(imsbc_portOfLoading, imsbcPosition.PortOfLoading, imsbcPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imsbcPosition.PortOfDischarge = reader.ReadText(imsbc_portOfDischarge); + reader.Conf.ConfirmText(imsbc_portOfDischarge, imsbcPosition.PortOfDischarge, imsbcPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + #endregion + + #region MARPOL + // MARPOL + for (int i = 1; i <= 5; i++) + { + string marpol_name = string.Format("HAZA.MARPOL.Name_{0}", i); + string marpol_flash = string.Format("HAZA.MARPOL.Flashpoint_CEL_{0}", i); + string marpol_quantity = string.Format("HAZA.MARPOL.Quantity_KGM_{0}", i); + string marpol_stowagePosition = string.Format("HAZA.MARPOL.StowagePosition_{0}", i); + string marpol_portOfLoading = string.Format("HAZA.MARPOL.PortOfLoading_{0}", i); + string marpol_portOfDischarge = string.Format("HAZA.MARPOL.PortOfDischarge_{0}", i); + + string name = reader.ReadText(marpol_name); + if(name.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(marpol_name, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("MARPOL-{0}", i); + MARPOL_Annex_I_Position marpolPosition = haza.GetMARPOLPositionWithIdentifier(posIdent); + if(marpolPosition == null) + { + marpolPosition = new MARPOL_Annex_I_Position(); + marpolPosition.Identifier = posIdent; + marpolPosition.HAZ = haza; + haza.MARPOLPositions.Add(marpolPosition); + } + + marpolPosition.Name = name; + reader.Conf.ConfirmText(marpol_name, name, ExcelReader.ReadState.OK); + marpolPosition.Flashpoint_CEL = reader.ReadText(marpol_flash); + ExcelReader.ReadState aReadState = ExcelReader.ReadState.NONE; + if (!marpolPosition.Flashpoint_CEL.IsNullOrEmpty()) + { + if (marpolPosition.Flashpoint_CEL == "-") + aReadState = ExcelReader.ReadState.FAIL; + else + aReadState = ExcelReader.ReadState.OK; + } + reader.Conf.ConfirmText(marpol_flash, marpolPosition.Flashpoint_CEL, aReadState); + + // Früher bei NULL: NF // Ableitung Flashpoint-Info: Christin, 22.3.2017 + // jetzt bei leerer Flashpoint_CEL: Flashpointinformation NULL: Basti, 13.7.2020 + if (marpolPosition.Flashpoint_CEL.IsNullOrEmpty()) { marpolPosition.FlashpointInformation = null; } + else + { + if (double.TryParse(marpolPosition.Flashpoint_CEL, out double flashval)) + { + if (flashval > 60) marpolPosition.FlashpointInformation = 1; // GT60CEL + else marpolPosition.FlashpointInformation = 2; // LE60CEL + } + } + + marpolPosition.Quantity_KGM = reader.ReadNumber(marpol_quantity); + marpolPosition.StowagePosition = reader.ReadText(marpol_stowagePosition); + reader.Conf.ConfirmText(marpol_stowagePosition, marpolPosition.StowagePosition, marpolPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + marpolPosition.PortOfLoading = reader.ReadText(marpol_portOfLoading); + reader.Conf.ConfirmText(marpol_portOfLoading, marpolPosition.PortOfLoading, marpolPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + marpolPosition.PortOfDischarge = reader.ReadText(marpol_portOfDischarge); + reader.Conf.ConfirmText(marpol_portOfDischarge, marpolPosition.PortOfDischarge, marpolPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + #endregion + + + if(haza.HasPositions) // Christin 22.3.17: Felder bei Positionen immer fest ausfüllen + { + haza.NoDPGOnBoardOnArrival = false; + // haza.DPGManifestOnBoardOnArrival = true; + } + + + } + + #endregion + + #region HAZD + + private static void ScanHAZD(List messages, MessageCore messageCore, ExcelReader reader) + { + Message hazdMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.HAZD); + if (hazdMessage.Elements.Count == 0) + { + HAZ newHazd = new HAZ(); + newHazd.IsDeparture = true; + newHazd.MessageHeader = hazdMessage; + hazdMessage.Elements.Add(newHazd); + } + HAZ hazd = hazdMessage.Elements[0] as HAZ; + // hazd.DeleteElements(); + + hazd.NoDPGOnBoardOnArrival = !reader.ReadBoolean("HAZD.DGOnBoard"); + hazd.DPGManifestOnBoardOnArrival = reader.ReadBoolean("HAZD.DPGManifestOnBoardOnDeparture"); + hazd.DPGContactFamilyName = reader.ReadText("HAZD.DPGContactFamilyName"); + reader.Conf.ConfirmText("HAZD.DPGContactFamilyName", hazd.DPGContactFamilyName, hazd.DPGContactFamilyName.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + hazd.DPGContactPhone = reader.ReadText("HAZD.DPGContactPhone"); + reader.Conf.ConfirmText("HAZD.DPGContactPhone", hazd.DPGContactPhone, hazd.DPGContactPhone.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + hazd.MOUBaltic = reader.ReadBoolean("HAZD.MOUBaltic"); + string shipClass = reader.ReadText("HAZD.INFShipClass"); + if (shipClass.IsNullOrEmpty()) + { + reader.Conf.ConfirmText("HAZD.INFShipClass", null, ExcelReader.ReadState.FAIL); + } + else + { + if (shipClass.Contains('1')) hazd.INFShipClass = 0; + if (shipClass.Contains('2')) hazd.INFShipClass = 1; + if (shipClass.Contains('3')) hazd.INFShipClass = 2; + // if (shipClass.Equals("none", StringComparison.OrdinalIgnoreCase)) hazd.INFShipClass = 0; + reader.Conf.ConfirmText("HAZD.INFShipClass", shipClass, hazd.INFShipClass.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.WARN); + } + + // IMDG + #region IMDG + + for (int i = 1; i <= 10; i++) + { + string imdg_unno = string.Format("HAZD.IMDG.UNNumber_{0}", i); + string imdg_properShippingName = string.Format("HAZD.IMDG.ProperShippingName_{0}", i); + string imdg_imoClass = string.Format("HAZD.IMDG.IMOClass_{0}", i); + string imdg_packingGroup = string.Format("HAZD.IMDG.PackingGroup_{0}", i); + string imdg_marinePollutant = string.Format("HAZD.IMDG.MarinePollutant_{0}", i); + string imdg_flashpoint = string.Format("HAZD.IMDG.Flashpoint_CEL_{0}", i); + string imdg_numberOfPackages = string.Format("HAZD.IMDG.NumberOfPackages_{0}", i); + string imdg_packageType = string.Format("HAZD.IMDG.PackageType_{0}", i); + string imdg_limitedQuantities = string.Format("HAZD.IMDG.LimitedQuantities_{0}", i); + string imdg_exceptedQuantities = string.Format("HAZD.IMDG.ExceptedQuantities_{0}", i); + string imdg_netQuantity = string.Format("HAZD.IMDG.NetQuantity_KGM_{0}", i); + string imdg_grossQuantity = string.Format("HAZD.IMDG.GrossQuantity_KGM_{0}", i); + string imdg_number = string.Format("HAZD.IMDG.Number_{0}", i); + string imdg_stowagePosition = string.Format("HAZD.IMDG.StowagePosition_{0}", i); + string imdg_portOfLoading = string.Format("HAZD.IMDG.PortOfLoading_{0}", i); + string imdg_portOfDischarge = string.Format("HAZD.IMDG.PortOfDischarge_{0}", i); + string imdg_containerNumber = string.Format("HAZD.IMDG.ContainerNumber_{0}", i); + + string unNumber = reader.ReadText(imdg_unno); + if (unNumber.IsNullOrEmpty()) // if unnumber is not set ignore this row + { + reader.Conf.ConfirmText(imdg_unno, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("IMDG-{0}", i); + IMDGPosition imdgPosition = hazd.GetIMDGPositionWithIdentifier(posIdent); + if (imdgPosition == null) + { + imdgPosition = new IMDGPosition(); + imdgPosition.HAZ = hazd; + imdgPosition.Identifier = posIdent; + hazd.IMDGPositions.Add(imdgPosition); + } + + imdgPosition.UNNumber = unNumber; + reader.Conf.ConfirmText(imdg_unno, unNumber, ExcelReader.ReadState.OK); + imdgPosition.ProperShippingName = reader.ReadText(imdg_properShippingName); + reader.Conf.ConfirmText(imdg_properShippingName, imdgPosition.ProperShippingName, imdgPosition.ProperShippingName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.IMOClass = reader.ReadText(imdg_imoClass); + reader.Conf.ConfirmText(imdg_imoClass, imdgPosition.IMOClass, imdgPosition.IMOClass.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.PackingGroup = reader.ReadPackingGroup(imdg_packingGroup); + imdgPosition.MarinePollutant = reader.ReadBoolean(imdg_marinePollutant); + imdgPosition.Flashpoint_CEL = reader.ReadText(imdg_flashpoint); + ExcelReader.ReadState aReadState = ExcelReader.ReadState.NONE; + if (!imdgPosition.Flashpoint_CEL.IsNullOrEmpty()) + { + if (imdgPosition.Flashpoint_CEL == "-") + aReadState = ExcelReader.ReadState.FAIL; + else + aReadState = ExcelReader.ReadState.OK; + } + reader.Conf.ConfirmText(imdg_flashpoint, imdgPosition.Flashpoint_CEL, aReadState); + imdgPosition.NumberOfPackages = (int?)reader.ReadNumber(imdg_numberOfPackages); + imdgPosition.PackageType = reader.ReadText(imdg_packageType); + reader.Conf.ConfirmText(imdg_packageType, imdgPosition.PackageType, imdgPosition.PackageType.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.LimitedQuantities = reader.ReadBoolean(imdg_limitedQuantities); + imdgPosition.ExceptedQuantities = reader.ReadBoolean(imdg_exceptedQuantities); + imdgPosition.NetQuantity_KGM = reader.ReadNumber(imdg_netQuantity); + imdgPosition.GrossQuantity_KGM = reader.ReadNumber(imdg_grossQuantity); + imdgPosition.VehicleLicenseNumber = reader.ReadText(imdg_number); + reader.Conf.ConfirmText(imdg_number, imdgPosition.VehicleLicenseNumber, imdgPosition.VehicleLicenseNumber.IsNullOrEmpty() ? ExcelReader.ReadState.NONE : ExcelReader.ReadState.OK); + imdgPosition.StowagePosition = reader.ReadText(imdg_stowagePosition); + reader.Conf.ConfirmText(imdg_stowagePosition, imdgPosition.StowagePosition, imdgPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.PortOfLoading = reader.ReadText(imdg_portOfLoading); + reader.Conf.ConfirmText(imdg_portOfLoading, imdgPosition.PortOfLoading, imdgPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.PortOfDischarge = reader.ReadText(imdg_portOfDischarge); + reader.Conf.ConfirmText(imdg_portOfDischarge, imdgPosition.PortOfDischarge, imdgPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imdgPosition.ContainerNumber = reader.ReadText(imdg_containerNumber); + reader.Conf.ConfirmText(imdg_containerNumber, imdgPosition.ContainerNumber, imdgPosition.ContainerNumber.IsNullOrEmpty() ? ExcelReader.ReadState.NONE : ExcelReader.ReadState.OK); + } + + #endregion + + #region IBC + // IBC + for (int i = 1; i <= 5; i++) + { + string ibc_productName = string.Format("HAZD.IBC.ProductName_{0}", i); + string ibc_pollutionCategory = string.Format("HAZD.IBC.PollutionCategory_{0}", i); + string ibc_flash = string.Format("HAZD.IBC.Flashpoint_CEL_{0}", i); + string ibc_quantity = string.Format("HAZD.IBC.Quantity_KGM_{0}", i); + string ibc_stowagePosition = string.Format("HAZD.IBC.StowagePosition_{0}", i); + string ibc_portOfLoading = string.Format("HAZD.IBC.PortOfLoading_{0}", i); + string ibc_portOfDischarge = string.Format("HAZD.IBC.PortOfDischarge_{0}", i); + + string productName = reader.ReadText(ibc_productName); + if (productName.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(ibc_productName, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("IBC-{0}", i); + IBCPosition ibcPosition = hazd.GetIBCPositionWithIdentifier(posIdent); + if (ibcPosition == null) + { + ibcPosition = new IBCPosition(); + ibcPosition.Identifier = posIdent; + ibcPosition.HAZ = hazd; + hazd.IBCPositions.Add(ibcPosition); + } + + ibcPosition.ProductName = productName; + reader.Conf.ConfirmText(ibc_productName, productName, ExcelReader.ReadState.OK); + string pollutionCategory = reader.ReadText(ibc_pollutionCategory); + if (!pollutionCategory.IsNullOrEmpty()) + { + if (pollutionCategory.Equals("X", StringComparison.OrdinalIgnoreCase)) ibcPosition.PollutionCategory = 0; + if (pollutionCategory.Equals("Y", StringComparison.OrdinalIgnoreCase)) ibcPosition.PollutionCategory = 1; + if (pollutionCategory.Equals("Z", StringComparison.OrdinalIgnoreCase)) ibcPosition.PollutionCategory = 2; + if (pollutionCategory.Equals("OS", StringComparison.OrdinalIgnoreCase)) ibcPosition.PollutionCategory = 3; + } + reader.Conf.ConfirmText(ibc_pollutionCategory, pollutionCategory, ibcPosition.PollutionCategory.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL); + + ibcPosition.Flashpoint_CEL = reader.ReadText(ibc_flash); + ExcelReader.ReadState aReadState = ExcelReader.ReadState.NONE; + if (!ibcPosition.Flashpoint_CEL.IsNullOrEmpty()) + { + if (ibcPosition.Flashpoint_CEL == "-") + { + aReadState = ExcelReader.ReadState.FAIL; + } + else + { + aReadState = ExcelReader.ReadState.OK; + if (double.TryParse(ibcPosition.Flashpoint_CEL, out double flashval)) + { + if (flashval > 60) ibcPosition.FlashpointInformation = 1; // GT60CEL + else ibcPosition.FlashpointInformation = 2; // LE60CEL + } + } + } + reader.Conf.ConfirmText(ibc_flash, ibcPosition.Flashpoint_CEL, aReadState); + ibcPosition.Quantity_KGM = (int?)reader.ReadNumber(ibc_quantity); + ibcPosition.StowagePosition = reader.ReadText(ibc_stowagePosition); + reader.Conf.ConfirmText(ibc_stowagePosition, ibcPosition.StowagePosition, ibcPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + ibcPosition.PortOfLoading = reader.ReadText(ibc_portOfLoading); + reader.Conf.ConfirmText(ibc_portOfLoading, ibcPosition.PortOfLoading, ibcPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + ibcPosition.PortOfDischarge = reader.ReadText(ibc_portOfDischarge); + reader.Conf.ConfirmText(ibc_portOfDischarge, ibcPosition.PortOfDischarge, ibcPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + #endregion + + #region IGC + // IGC + for (int i = 1; i <= 5; i++) + { + string igc_productName = string.Format("HAZD.IGC.ProductName_{0}", i); + string igc_quantity = string.Format("HAZD.IGC.Quantity_KGM_{0}", i); + string igc_stowagePosition = string.Format("HAZD.IGC.StowagePosition_{0}", i); + string igc_portOfLoading = string.Format("HAZD.IGC.PortOfLoading_{0}", i); + string igc_portOfDischarge = string.Format("HAZD.IGC.PortOfDischarge_{0}", i); + + string productName = reader.ReadText(igc_productName); + if (productName.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(igc_productName, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("IGC-{0}", i); + IGCPosition igcPosition = hazd.GetIGCPositionWithIdentifier(posIdent); + if (igcPosition == null) + { + igcPosition = new IGCPosition(); + igcPosition.Identifier = posIdent; + igcPosition.HAZ = hazd; + hazd.IGCPositions.Add(igcPosition); + } + + igcPosition.ProductName = productName; + reader.Conf.ConfirmText(igc_productName, productName, ExcelReader.ReadState.OK); + igcPosition.Quantity_KGM = reader.ReadNumber(igc_quantity); + igcPosition.StowagePosition = reader.ReadText(igc_stowagePosition); + reader.Conf.ConfirmText(igc_stowagePosition, igcPosition.StowagePosition, igcPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + igcPosition.PortOfLoading = reader.ReadText(igc_portOfLoading); + reader.Conf.ConfirmText(igc_portOfLoading, igcPosition.PortOfLoading, igcPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + igcPosition.PortOfDischarge = reader.ReadText(igc_portOfDischarge); + reader.Conf.ConfirmText(igc_portOfDischarge, igcPosition.PortOfDischarge, igcPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + #endregion + + #region IMSBC + // IMSBC + for (int i = 1; i <= 5; i++) + { + string imsbc_bcsn = string.Format("HAZD.IMSBC.BulkCargoShippingName_{0}", i); + string imsbc_mhb = string.Format("HAZD.IMSBC.MHB_{0}", i); + string imsbc_quantity = string.Format("HAZD.IMSBC.Quantity_KGM_{0}", i); + string imsbc_stowagePosition = string.Format("HAZD.IMSBC.StowagePosition_{0}", i); + string imsbc_portOfLoading = string.Format("HAZD.IMSBC.PortOfLoading_{0}", i); + string imsbc_portOfDischarge = string.Format("HAZD.IMSBC.PortOfDischarge_{0}", i); + + string bcsn = reader.ReadText(imsbc_bcsn); + if (bcsn.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(imsbc_bcsn, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("IMSBC-{0}", i); + IMSBCPosition imsbcPosition = hazd.GetIMSBCPositionWithIdentifier(posIdent); + if (imsbcPosition == null) + { + imsbcPosition = new IMSBCPosition(); + imsbcPosition.Identifier = posIdent; + imsbcPosition.HAZ = hazd; + hazd.IMSBCPositions.Add(imsbcPosition); + } + + imsbcPosition.BulkCargoShippingName = bcsn; + reader.Conf.ConfirmText(imsbc_bcsn, bcsn, ExcelReader.ReadState.OK); + imsbcPosition.MHB = reader.ReadBoolean(imsbc_mhb); + imsbcPosition.Quantity_KGM = reader.ReadNumber(imsbc_quantity); + imsbcPosition.StowagePosition = reader.ReadText(imsbc_stowagePosition); + reader.Conf.ConfirmText(imsbc_stowagePosition, imsbcPosition.StowagePosition, imsbcPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imsbcPosition.PortOfLoading = reader.ReadText(imsbc_portOfLoading); + reader.Conf.ConfirmText(imsbc_portOfLoading, imsbcPosition.PortOfLoading, imsbcPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + imsbcPosition.PortOfDischarge = reader.ReadText(imsbc_portOfDischarge); + reader.Conf.ConfirmText(imsbc_portOfDischarge, imsbcPosition.PortOfDischarge, imsbcPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + #endregion + + #region MARPOL + // MARPOL + for (int i = 1; i <= 5; i++) + { + string marpol_name = string.Format("HAZD.MARPOL.Name_{0}", i); + string marpol_flash = string.Format("HAZD.MARPOL.Flashpoint_CEL_{0}", i); + string marpol_quantity = string.Format("HAZD.MARPOL.Quantity_KGM_{0}", i); + string marpol_stowagePosition = string.Format("HAZD.MARPOL.StowagePosition_{0}", i); + string marpol_portOfLoading = string.Format("HAZD.MARPOL.PortOfLoading_{0}", i); + string marpol_portOfDischarge = string.Format("HAZD.MARPOL.PortOfDischarge_{0}", i); + + string name = reader.ReadText(marpol_name); + if (name.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(marpol_name, null, ExcelReader.ReadState.WARN); + continue; + } + + string posIdent = string.Format("MARPOL-{0}", i); + MARPOL_Annex_I_Position marpolPosition = hazd.GetMARPOLPositionWithIdentifier(posIdent); + if (marpolPosition == null) + { + marpolPosition = new MARPOL_Annex_I_Position(); + marpolPosition.Identifier = posIdent; + marpolPosition.HAZ = hazd; + hazd.MARPOLPositions.Add(marpolPosition); + } + + marpolPosition.Name = name; + reader.Conf.ConfirmText(marpol_name, name, ExcelReader.ReadState.OK); + marpolPosition.Flashpoint_CEL = reader.ReadText(marpol_flash); + ExcelReader.ReadState aReadState = ExcelReader.ReadState.NONE; + if (!marpolPosition.Flashpoint_CEL.IsNullOrEmpty()) + { + if (marpolPosition.Flashpoint_CEL == "-") + aReadState = ExcelReader.ReadState.FAIL; + else + aReadState = ExcelReader.ReadState.OK; + } + reader.Conf.ConfirmText(marpol_flash, marpolPosition.Flashpoint_CEL, aReadState); + + if (marpolPosition.Flashpoint_CEL.IsNullOrEmpty()) { marpolPosition.FlashpointInformation = 0; } // NF // Ableitung Flashpoint-Info: Christin, 22.3.2017 + else + { + if (double.TryParse(marpolPosition.Flashpoint_CEL, out double flashval)) + { + if (flashval > 60) marpolPosition.FlashpointInformation = 1; // GT60CEL + else marpolPosition.FlashpointInformation = 2; // LE60CEL + } + } + + marpolPosition.Quantity_KGM = reader.ReadNumber(marpol_quantity); + marpolPosition.StowagePosition = reader.ReadText(marpol_stowagePosition); + reader.Conf.ConfirmText(marpol_stowagePosition, marpolPosition.StowagePosition, marpolPosition.StowagePosition.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + marpolPosition.PortOfLoading = reader.ReadText(marpol_portOfLoading); + reader.Conf.ConfirmText(marpol_portOfLoading, marpolPosition.PortOfLoading, marpolPosition.PortOfLoading.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + marpolPosition.PortOfDischarge = reader.ReadText(marpol_portOfDischarge); + reader.Conf.ConfirmText(marpol_portOfDischarge, marpolPosition.PortOfDischarge, marpolPosition.PortOfDischarge.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + #endregion + + + + if (hazd.HasPositions) // Christin 22.3.17: Felder bei Positionen immer fest ausfüllen + { + hazd.NoDPGOnBoardOnArrival = false; + // hazd.DPGManifestOnBoardOnArrival = true; + } + + + + } + + #endregion + + #region INFO + + private static void ScanINFO(List messages, MessageCore messageCore, ExcelReader reader) + { + Message infoMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.INFO); + if(infoMessage.Elements.Count == 0) + { + INFO newINFO = new INFO(); + newINFO.MessageHeader = infoMessage; + infoMessage.Elements.Add(newINFO); + } + INFO info = infoMessage.Elements[0] as INFO; + Util.ScanMessage(info, reader); + + info.ShippingArea = reader.ReadShippingArea("INFO.ShippingArea"); // enum read func + + bool? fumigatedBulkCargo = reader.ReadBoolean("INFO.FumigatedBulkCargo"); + info.FumigatedBulkCargo = (byte) ((fumigatedBulkCargo ?? false) ? 1 : 0); + // wird nicht wieder entfernt + } + + #endregion + + #region STAT + + private static void ScanSTAT(List messages, MessageCore messageCore, ExcelReader reader) + { + Message statMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.STAT); + if(statMessage.Elements.Count == 0) + { + STAT newSTAT = new STAT(); + newSTAT.MessageHeader = statMessage; + statMessage.Elements.Add(newSTAT); + } + STAT stat = statMessage.Elements[0] as STAT; + Util.ScanMessage(stat, reader); + + stat.PortOfRegistry = reader.ReadLoCode("STAT.PortOfRegistry"); + stat.Flag = reader.ReadNationality("STAT.Flag"); + + stat.MMSINumber = reader.ReadTextNoWhitespace("STAT.MMSINumber"); + reader.Conf.ConfirmText("STAT.MMSINumber", stat.MMSINumber, (stat.MMSINumber.IsNullOrEmpty() || (stat.MMSINumber.Length != 9)) ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + stat.CallSign = reader.ReadTextNoWhitespace("STAT.CallSign"); + reader.Conf.ConfirmText("STAT.CallSign", stat.CallSign, stat.CallSign.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + stat.ISMCompanyId = reader.ReadTextNoWhitespace("STAT.ISMCompanyId"); + + reader.Conf.ConfirmText("STAT.ISMCompanyId", stat.ISMCompanyId, (stat.ISMCompanyId.IsNullOrEmpty() || (stat.ISMCompanyId.Length != 7)) ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + if (!stat.ISMCompanyId.IsNullOrEmpty() && stat.ISMCompanyId.Length < 7) + { + while (stat.ISMCompanyId.Length < 7) + stat.ISMCompanyId = "0" + stat.ISMCompanyId; + } + + string transportMode = reader.ReadText("STAT.TransportMode"); + if(transportMode != null) + { + if (transportMode.Contains("maritime", StringComparison.OrdinalIgnoreCase)) stat.TransportMode = "1"; + if (transportMode.Equals("1")) stat.TransportMode = transportMode; + + if (transportMode.Contains("inland", StringComparison.OrdinalIgnoreCase)) stat.TransportMode = "8"; + if (transportMode.Equals("8")) stat.TransportMode = transportMode; + } + reader.Conf.ConfirmText("STAT.TransportMode", transportMode, stat.TransportMode.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + + if (!stat.ShipType.IsNullOrEmpty() && stat.ShipType.Length > 3) + reader.Conf.ConfirmText("STAT.ShipType", stat.ShipType, ExcelReader.ReadState.WARN); + + // Vessel Email as HerbergEmail sichern + messageCore.HerbergEmailContactReportingVessel = reader.ReadText("ShipMail"); + reader.Conf.ConfirmText("ShipMail", messageCore.HerbergEmailContactReportingVessel, messageCore.HerbergEmailContactReportingVessel.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + // wird nicht wieder entfernt (core ist auch da!) + + } + + #endregion + + #region NOA_NOD + + private static void ScanNOA_NOD(List messages, MessageCore messageCore, ExcelReader reader) + { + Message noa_nodMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.NOA_NOD); + if (noa_nodMessage.Elements.Count == 0) + { + NOA_NOD newNoa_nod = new NOA_NOD(); + newNoa_nod.MessageHeader = noa_nodMessage; + noa_nodMessage.Elements.Add(newNoa_nod); + } + + NOA_NOD noa_nod = noa_nodMessage.Elements[0] as NOA_NOD; + + DateTime? eta = reader.ReadDateTime("NOA_NOD.ETADateToPortOfCall", "NOA_NOD.ETATimeToPortOfCall"); + + if (messageCore.IsTransit) + { + if (eta.HasValue) + noa_nod.ETAToKielCanal = eta; + //else + // noa_nod.ETAToKielCanal = messageCore.ETAKielCanal; + } + else + { + if (eta.HasValue) + noa_nod.ETAToPortOfCall = eta; + //else + // noa_nod.ETAToPortOfCall = messageCore.ETA; + + // Zeit muss zurückkonvertiert werden, da toUniversalTime() kodiert + if(noa_nod.ETAToPortOfCall.HasValue) + reader.Conf.ConfirmDate("NOA_NOD.ETAToPortOfCall", noa_nod.ETAToPortOfCall.Value.ToLocalTime(), ExcelReader.ReadState.OK); + + for (int i = 1; i <= noa_nod.NumberOfExcelRows; i++) + { + string callPurposeDescriptionKey = string.Format("NOA_NOD.CallPuposeDescription_{0}", i); + string callPurposeCodeKey = string.Format("NOA_NOD.CallPurposeCode_{0}", i); + string callPurposeDescription = reader.ReadText(callPurposeDescriptionKey); + string callPurposeCode = reader.ReadText(callPurposeCodeKey); + + if (!callPurposeCode.IsNullOrEmpty()) + { + + if (!(noa_nod.GetSublistElementWithIdentifier(i.ToString()) is CallPurpose callPurpose)) + { + callPurpose = new CallPurpose(); + callPurpose.NOA_NOD = noa_nod; + callPurpose.Identifier = i.ToString(); + noa_nod.CallPurposes.Add(callPurpose); + } + + callPurpose.CallPurposeCode = ((int?)reader.ReadNumber(callPurposeCodeKey)) ?? 0; + callPurpose.CallPurposeDescription = callPurposeDescription; + ExcelReader.ReadState aReadState = ExcelReader.ReadState.OK; + if (callPurposeDescription.IsNullOrEmpty()) aReadState = ExcelReader.ReadState.WARN; + else if (callPurposeDescription.Length > 90) aReadState = ExcelReader.ReadState.FAIL; + reader.Conf.ConfirmText(callPurposeDescriptionKey, callPurposeDescription, aReadState); + if (i == 1) + reader.Conf.ConfirmText("NOA_NOD.CallPuposeDescription_1_DK", callPurposeDescription, callPurposeDescription.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + } + } + } + + string lastPort = reader.ReadText("NOA_NOD.LastPort")?.Trim().ToUpper(); + + if (lastPort != null) + { + if (LocodeDB.PortNameFromLocode(lastPort) != null) + { + noa_nod.LastPort = lastPort; + } + else + { + List lastPorts = LocodeDB.AllLocodesForCityName(lastPort); + if (lastPorts.Count == 1) + noa_nod.LastPort = lastPorts[0]; + else + _log.WarnFormat("{0} results in {1} possible LOCODES", lastPort, lastPorts.Count); + } + } + + reader.Conf.ConfirmText("NOA_NOD.LastPort", lastPort, noa_nod.LastPort.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + + string nextPort = reader.ReadText("NOA_NOD.NextPort")?.Trim().ToUpper(); + bool isValidSSNPort = false; + if (!nextPort.IsNullOrEmpty()) + { + if (nextPort.Length > 5) + nextPort = nextPort.Substring(0, 5); //trunc + else + isValidSSNPort = !LocodeDB.SSNPortNameFromLocode(nextPort).IsNullOrEmpty(); + } + + if(string.IsNullOrEmpty(nextPort)) + reader.Conf.ConfirmText("NOA_NOD.NextPort", nextPort, ExcelReader.ReadState.WARN); + else + reader.Conf.ConfirmText("NOA_NOD.NextPort", nextPort, isValidSSNPort ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL); + + noa_nod.NextPort = nextPort; + + if(messageCore.IsTransit) + { + noa_nod.ETDFromKielCanal = reader.ReadDateTime("NOA_NOD.ETDDateFromPortOfCall", "NOA_NOD.ETDTimeFromPortOfCall"); + if(noa_nod.ETDFromKielCanal.HasValue) + reader.Conf.ConfirmDate("NOA_NOD.ETDFromPortOfCall", noa_nod.ETDFromKielCanal.Value.ToLocalTime(), ExcelReader.ReadState.OK); + else + reader.Conf.ConfirmDate("NOA_NOD.ETDFromPortOfCall", null, ExcelReader.ReadState.FAIL); + } else + { + noa_nod.ETDFromPortOfCall = reader.ReadDateTime("NOA_NOD.ETDDateFromPortOfCall", "NOA_NOD.ETDTimeFromPortOfCall"); + if(noa_nod.ETDFromPortOfCall.HasValue) + reader.Conf.ConfirmDate("NOA_NOD.ETDFromPortOfCall", noa_nod.ETDFromPortOfCall.Value.ToLocalTime(), ExcelReader.ReadState.OK); + else + reader.Conf.ConfirmDate("NOA_NOD.ETDFromPortOfCall", null, ExcelReader.ReadState.FAIL); + } + + noa_nod.ETDFromLastPort = reader.ReadDateTime("NOA_NOD.ETDDateFromLastPort", "NOA_NOD.ETDTimeFromLastPort"); + noa_nod.ETAToNextPort = reader.ReadDateTime("NOA_NOD.ETADateToNextPort", "NOA_NOD.ETATimeToNextPort"); + // DK + noa_nod.IsAnchored = reader.ReadBoolean("NOA_NOD.IsAnchored", reader.Mode == ExcelReader.CountryMode.DE); + + } + + #endregion + + #region AGNT + + private static void ScanAGNT(List messages, MessageCore messageCore, ExcelReader reader) + { + Message agntMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.AGNT); + if(agntMessage.Elements.Count == 0) + { + AGNT newAgnt = new AGNT(); + newAgnt.MessageHeader = agntMessage; + agntMessage.Elements.Add(newAgnt); + } + AGNT agnt = agntMessage.Elements[0] as AGNT; + Util.ScanMessage(agnt, reader); + + if (agnt.AgentLastName.IsNullOrEmpty()) agnt.AgentLastName = "-"; + + // wird nicht mehr entfernt, egal welche Felder gelesen werden + } + + #endregion + + #region WAS + + private static void ScanWAS(List messages, MessageCore messageCore, ExcelReader reader) + { + Message wasMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.WAS); + if (wasMessage.Elements.Count == 0) + { + WAS newWAS = new WAS(); + newWAS.MessageHeader = wasMessage; + wasMessage.Elements.Add(newWAS); + } + WAS was = wasMessage.Elements[0] as WAS; + was.DeleteElements(); + + Util.ScanMessage(was, reader); + + was.WasteDisposalDelivery = reader.ReadDelivery("WAS.WasteDisposalDelivery"); + was.LastWasteDisposalPort = reader.ReadLoCode("WAS.LastWasteDisposalPort"); + + string wastedispServProvName = reader.ReadText("WAS.WasteDisposalServiceProviderName"); + if (wastedispServProvName != null) + { + if (was.WasteDisposalServiceProvider.Count == 0) + { + WasteDisposalServiceProvider wdsp = new WasteDisposalServiceProvider(); + wdsp.Identifier = "1"; + wdsp.WAS = was; + was.WasteDisposalServiceProvider.Add(wdsp); + } + ((WasteDisposalServiceProvider) was.WasteDisposalServiceProvider[0]).WasteDisposalServiceProviderName = wastedispServProvName; + ((WasteDisposalServiceProvider) was.WasteDisposalServiceProvider[0]).WasteDisposalDelivery = was.WasteDisposalDelivery; + } + + ExcelReader.ReadState readState = ExcelReader.ReadState.WARN; + if (!wastedispServProvName.IsNullOrEmpty()) { + if (wastedispServProvName.Length > 90) readState = ExcelReader.ReadState.FAIL; + else readState = ExcelReader.ReadState.OK; + } + + reader.Conf.ConfirmText("WAS.WasteDisposalServiceProviderName", wastedispServProvName, readState); + + // Waste 1 - 15 + for (int i = 1; i <= was.NumberOfExcelRows; i++) + { + string wastetype = string.Format("WAS.WasteType_{0}", i); + string wasteCode = string.Format("WAS.WasteCode_{0}", i); + string wasteDescription = string.Format("WAS.WasteDescription_{0}", i); + string wasteAmount = string.Format("WAS.WasteDisposalAmount_MTQ_{0}", i); + string wasteCapacity = string.Format("WAS.WasteCapacity_MTQ_{0}", i); + string wasteRetained = string.Format("WAS.WasteAmountRetained_MTQ_{0}", i); + string wastePort = string.Format("WAS.WasteDisposalPort_{0}", i); + string amountGen = string.Format("WAS.WasteAmountGeneratedTillNextPort_MTQ_{0}", i); + string wasteDis = string.Format("WAS.WasteDisposedAtLastPort_MTQ_{0}", i); + + if (!(was.GetSublistElementWithIdentifier(i.ToString()) is Waste waste)) + { + waste = new Waste(); + waste.Identifier = i.ToString(); + waste.WAS = was; + was.Waste.Add(waste); + } + + waste.WasteType = (int?) reader.ReadNumber(wasteCode); + + if (waste.WasteType.HasValue && (waste.WasteType == 2313)) + waste.WasteType = 2600; + + if (reader.Mode == ExcelReader.CountryMode.DE) + { + reader.Conf.ConfirmText(wastetype, waste.WasteTypeDisplay, ExcelReader.ReadState.OK); + reader.Conf.ConfirmNumber(wasteCode, waste.WasteType, ExcelReader.ReadState.OK); + } + else if (reader.Mode == ExcelReader.CountryMode.DK) + { + reader.Conf.ConfirmText(wastetype, WAS.DKWasteTypes[i - 1], ExcelReader.ReadState.OK); + reader.Conf.ConfirmNumber(wasteCode, WAS.DKWasteCodes[i - 1], ExcelReader.ReadState.OK); + } + + // Waste description Spezialfälle für DK + waste.WasteDescription = reader.ReadText(wasteDescription); + if (waste.WasteDescription.IsNullOrEmpty()) + { + if (reader.Mode == ExcelReader.CountryMode.DE) + { + waste.WasteDescription = "-"; + } + else if (reader.Mode == ExcelReader.CountryMode.DK) + { + waste.WasteDescription = "-"; + if (i == 6) waste.WasteDescription = "Domestic waste"; + if (i == 9) waste.WasteDescription = "Operational waste"; + } + } + else + { + if (reader.Mode == ExcelReader.CountryMode.DK) + { + if (i == 6) + waste.WasteDescription = string.Format("Domestic waste - {0}", waste.WasteDescription); + if (i == 9) + waste.WasteDescription = string.Format("Operational waste - {0}", waste.WasteDescription); + } + } + + // RM am 24.1.18, ich hoffe das stimmt so wie sie meint.. + if((reader.Mode == ExcelReader.CountryMode.DK) && (i==9)) + { + _log.DebugFormat("DK: Changing Waste code {0} to 2300 for line {1}", waste.WasteType, i); + waste.WasteType = 2300; + } + + reader.Conf.ConfirmText(wasteDescription, waste.WasteDescription, waste.WasteDescription.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + waste.WasteDisposalAmount_MTQ = reader.ReadNumberDefaultZero(wasteAmount); + waste.WasteCapacity_MTQ = reader.ReadNumberDefaultZero(wasteCapacity); + waste.WasteAmountRetained_MTQ = reader.ReadNumberDefaultZero(wasteRetained); + + waste.WasteDisposalPort = reader.ReadLoCode(wastePort); + bool isLocode; + ExcelReader.ReadState rs; + if (waste.WasteDisposalPort.IsNullOrEmpty()) + { + waste.WasteDisposalPort = "ZZUKN"; + rs = ExcelReader.ReadState.WARN; + } + else + { + isLocode = (LocodeDB.PortNameFromLocode(waste.WasteDisposalPort) != null); + rs = isLocode ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL; + } + reader.Conf.ConfirmText(wastePort, waste.WasteDisposalPort, rs); + + waste.WasteAmountGeneratedTillNextPort_MTQ = reader.ReadNumberDefaultZero(amountGen); + waste.WasteDisposedAtLastPort_MTQ = reader.ReadNumberDefaultZero(wasteDis); + + /* + if ((reader.Mode == ExcelReader.CountryMode.DE) && + ((i == 6) || (i == 8) || (i == 9))) + { + waste.WasteDescription = "-"; + waste.WasteDisposalAmount_MTQ = 0; + waste.WasteCapacity_MTQ = 0; + waste.WasteAmountRetained_MTQ = 0; + waste.WasteDisposalPort = "ZZUKN"; + waste.WasteAmountGeneratedTillNextPort_MTQ = 0; + } + */ + + if(i==15) // falls letzte Zeile leer, entfernen: Christin 22.3.17 + { + if ((waste.WasteDescription.IsNullOrEmpty() || waste.WasteDescription == "-") && + ((waste.WasteDisposalAmount_MTQ ?? 0) == 0) && + (((waste.WasteType ?? 0) == 1300) || !waste.WasteType.HasValue)) + was.Waste.Remove(waste); + + // 24.3.: - Für Waste-Type 15: Wenn in dieser Zeile andere Werte enthalten, als die nachfolgenden, ist die ganze Zeile rot zu markieren. + bool highlightRow15 = waste.WasteType != null; + highlightRow15 &= (waste.WasteDisposalAmount_MTQ > 0); + highlightRow15 &= (waste.WasteCapacity_MTQ > 0); + highlightRow15 &= (waste.WasteAmountRetained_MTQ > 0); + highlightRow15 &= (waste.WasteDisposalPort != "ZZUKN"); + highlightRow15 &= (waste.WasteAmountGeneratedTillNextPort_MTQ > 0); + highlightRow15 &= (waste.WasteDisposedAtLastPort_MTQ > 0); + + if(highlightRow15) + { + reader.Conf.HighlightCellWithState(wastetype, ExcelReader.ReadState.FAIL); + reader.Conf.HighlightCellWithState(wasteCode, ExcelReader.ReadState.FAIL); + reader.Conf.HighlightCellWithState(wasteDescription, ExcelReader.ReadState.FAIL); + reader.Conf.HighlightCellWithState(wasteAmount, ExcelReader.ReadState.FAIL); + reader.Conf.HighlightCellWithState(wasteCapacity, ExcelReader.ReadState.FAIL); + reader.Conf.HighlightCellWithState(wasteRetained, ExcelReader.ReadState.FAIL); + reader.Conf.HighlightCellWithState(wastePort, ExcelReader.ReadState.FAIL); + reader.Conf.HighlightCellWithState(amountGen, ExcelReader.ReadState.FAIL); + reader.Conf.HighlightCellWithState(wasteDis, ExcelReader.ReadState.FAIL); + } + } + + if (!waste.WasteType.HasValue) + { + was.Waste.Remove(waste); + } + } + + was.AddMissingWaste(); + + } + #endregion + + #region MDH + + private static void ScanMDH(List messages, MessageCore messageCore, ExcelReader reader) + { + Message mdhMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.MDH); + if(mdhMessage.Elements.Count == 0) + { + MDH newMDH = new MDH(); + newMDH.MessageHeader = mdhMessage; + mdhMessage.Elements.Add(newMDH); + } + MDH mdh = mdhMessage.Elements[0] as MDH; + mdh.DeleteElements(); + Util.ScanMessage(mdh, reader); + + // lt. Mail von Christin am 28.9.2016 + mdh.MDHSimplification = false; + mdh.PortOfCallWhereCompleteMDHNotified = ""; + + + string kuerzelErsteZelle = reader.ReadText("MDH.PortOfCallLast30DaysLocode_1"); + + try + { + + #region PoC last 30 days + + // lt. Mail von Christin am 11.10.2016 + // "SEC" Mode, die Werte aus last10PortFacilitesCalled (SEC) werden übernommen + // das funktioniert, da SEC vor MDH gelesen wird + if (!kuerzelErsteZelle.IsNullOrEmpty() && kuerzelErsteZelle.Equals("sec", StringComparison.OrdinalIgnoreCase)) + { + Message secMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.SEC); + if (secMessage.Elements.Count == 0) return; + SEC sec = secMessage.Elements[0] as SEC; + int i = 1; + foreach (LastTenPortFacilitiesCalled ltpfc in sec.LastTenPortFacilitesCalled) + { + if (!(mdh.GetSublistElementWithIdentifier((i + 1).ToString()) is PortOfCallLast30Days poc30d)) + { + poc30d = new PortOfCallLast30Days(); + poc30d.Identifier = (i + 1).ToString(); + poc30d.MDH = mdh; + mdh.PortOfCallLast30Days.Add(poc30d); + } + + poc30d.PortOfCallLast30DaysCrewMembersJoined = false; + poc30d.PortOfCallLast30DaysLocode = ltpfc.PortFacilityPortLoCode; + poc30d.PortOfCallLast30DaysDateOfDeparture = ltpfc.PortFacilityDateOfDeparture; + i++; + } + } + else // "normal mode", aus den Zellen lesen + { + + // POC last 30 days + for (int i = 0; i < mdh.NumberOfExcelRows; i++) + { + string portName = string.Format("MDH.PortOfCallLast30DaysPort_{0}", i + 1); + string portCountry = string.Format("MDH.PortOfCallLast30DaysCountry_{0}", i + 1); + string locode = string.Format("MDH.PortOfCallLast30DaysLocode_{0}", i + 1); + string crewJoined = string.Format("MDH.PortOfCallLast30DaysCrewMembersJoined_{0}", i + 1); + string crewName = string.Format("MDH.PortOfCallLast30DaysCrewJoinedShipName_{0}", i + 1); + string depDate = string.Format("MDH.PortOfCallLast30DaysDateOfDeparture_{0}", i + 1); + + if (!(mdh.GetSublistElementWithIdentifier((i + 1).ToString()) is PortOfCallLast30Days poc30d)) + { + poc30d = new PortOfCallLast30Days(); + poc30d.Identifier = (i + 1).ToString(); + poc30d.MDH = mdh; + mdh.PortOfCallLast30Days.Add(poc30d); + } + + string pName = reader.ReadText(portName); + string pCountry = reader.ReadText(portCountry); + reader.Conf.ConfirmText(portName, pName, ExcelReader.ReadState.NONE); + reader.Conf.ConfirmText(portCountry, pCountry, ExcelReader.ReadState.NONE); + + poc30d.PortOfCallLast30DaysDateOfDeparture = reader.ReadDate(depDate); + poc30d.PortOfCallLast30DaysLocode = reader.ReadLoCode(locode); + + // Verbesserungsvorschlag Jul/21: CrewMembersJoined Häkchen abhängig von den Namen in der Spalte + bool? PortOfCallLast30DaysCrewMembersJoinedFlag = reader.ReadBoolean(crewJoined); + + string crewNameString = reader.ReadText(crewName); + if (!crewNameString.IsNullOrEmpty()) + poc30d.PortOfCallLast30DaysCrewMembersJoined = true; + else + poc30d.PortOfCallLast30DaysCrewMembersJoined = false; + + if (poc30d.PortOfCallLast30DaysCrewMembersJoined ?? false) + { + // try different separators + string[] crew = crewNameString.Split(';'); + if (crew.Length == 1) + crew = crewNameString.Split(','); + ExcelReader.ReadState readState = ExcelReader.ReadState.OK; + for (int j = 0; j < crew.Length; j++) + { + if (!(poc30d.GetSublistElementWithIdentifier((j + 1).ToString()) is PortOfCallLast30DaysCrewJoinedShip poc30dCrew)) + { + poc30dCrew = new PortOfCallLast30DaysCrewJoinedShip(); + poc30dCrew.Identifier = (j + 1).ToString(); + poc30dCrew.PortOfCallLast30Days = poc30d; + poc30d.CrewJoinedShip.Add(poc30dCrew); + } + + poc30dCrew.PortOfCallLast30DaysCrewJoinedShipName = crew[j]; + if (crew[j].Length > 90) + readState = ExcelReader.ReadState.FAIL; + } + reader.Conf.ConfirmText(crewName, crewNameString, readState); + } + + // falls Häkchen gesetzt aber Namensfeld leer: Fehler markieren + if((PortOfCallLast30DaysCrewMembersJoinedFlag ?? false) && crewNameString.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(crewName, null, ExcelReader.ReadState.FAIL); + } + + // Leer/def. Zeilen entfernen + if (!poc30d.PortOfCallLast30DaysDateOfDeparture.HasValue && (poc30d.PortOfCallLast30DaysLocode == null)) + mdh.PortOfCallLast30Days.Remove(poc30d); + } + } + + #endregion + + #region SanitaryMeasures + + if (mdh.SanitaryMeasuresApplied ?? false) + { + for (int i = 1; i <= 3; i++) + { + string smType = string.Format("MDH.SanitaryMeasuresType_{0}", i); + string smLocation = string.Format("MDH.SanitaryMeasuresLocation_{0}", i); + string smDate = string.Format("MDH.SanitaryMeasuresDate_{0}", i); + + SanitaryMeasuresDetail smd = mdh.GetSanitaryMeasuresDetailWithIdentifier(i.ToString()); + if(smd == null) + { + smd = new SanitaryMeasuresDetail(); + smd.Identifier = i.ToString(); + mdh.SanitaryMeasuresDetails.Add(smd); + smd.MDH = mdh; + } + + smd.SanitaryMeasuresType = reader.ReadText(smType); + ExcelReader.ReadState readState = ExcelReader.ReadState.OK; + if (smd.SanitaryMeasuresType.IsNullOrEmpty() || smd.SanitaryMeasuresType.Length > 90) + readState = ExcelReader.ReadState.FAIL; + reader.Conf.ConfirmText(smType, smd.SanitaryMeasuresType, readState); + + smd.SanitaryMeasuresLocation = reader.ReadText(smLocation); + readState = ExcelReader.ReadState.OK; + if (smd.SanitaryMeasuresLocation.IsNullOrEmpty() || smd.SanitaryMeasuresLocation.Length > 90) + readState = ExcelReader.ReadState.FAIL; + reader.Conf.ConfirmText(smLocation, smd.SanitaryMeasuresLocation, smd.SanitaryMeasuresLocation.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + smd.SanitaryMeasuresDate = reader.ReadDate(smDate); + // dont save completely empty structs + if (!smd.SanitaryMeasuresDate.HasValue && smd.SanitaryMeasuresLocation.IsNullOrEmpty() && smd.SanitaryMeasuresType.IsNullOrEmpty()) + mdh.SanitaryMeasuresDetails.Remove(smd); + } + } + + #endregion + + #region InfectedArea + + if (mdh.InfectedAreaVisited ?? false) + { + for (int i = 1; i <= 3; i++) + { + string iaPort = string.Format("MDH.InfectedAreaPort_{0}", i); + string iaDate = string.Format("MDH.InfectedAreaDate_{0}", i); + InfectedArea ia = mdh.GetInfectedAreaWithIdentifier(i.ToString()); + if (ia == null) + { + ia = new InfectedArea(); + ia.Identifier = i.ToString(); + mdh.InfectedAreas.Add(ia); + ia.MDH = mdh; + } + ia.InfectedAreaPort = reader.ReadText(iaPort); + ExcelReader.ReadState readState = ExcelReader.ReadState.OK; + if (ia.InfectedAreaPort.IsNullOrEmpty() || ia.InfectedAreaPort.Length > 90) + readState = ExcelReader.ReadState.FAIL; + reader.Conf.ConfirmText(iaPort, ia.InfectedAreaPort, readState); + ia.InfectedAreaDate = reader.ReadDate(iaDate); + // dont save completely empty structs + if (!ia.InfectedAreaDate.HasValue && ia.InfectedAreaPort.IsNullOrEmpty()) + mdh.InfectedAreas.Remove(ia); + } + } + + #endregion + + #region StowawaysJoiningLocation + + if(mdh.StowawaysDetected ?? false) + { + for (int i = 1; i <= 3; i++) + { + string sjlLookup = string.Format("MDH.StowawaysJoiningLocation_{0}", i); + StowawaysJoiningLocation sjl = mdh.GetStowawaysJoiningLocationWithIdentifier(i.ToString()); + if (sjl == null) + { + sjl = new StowawaysJoiningLocation(); + sjl.Identifier = i.ToString(); + sjl.MDH = mdh; + mdh.StowawaysJoiningLocations.Add(sjl); + } + + sjl.StowawayJoiningLocation = reader.ReadText(sjlLookup); + if (sjl.StowawayJoiningLocation.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(sjlLookup, null, ExcelReader.ReadState.WARN); + mdh.StowawaysJoiningLocations.Remove(sjl); + } + else + { + ExcelReader.ReadState readState = ExcelReader.ReadState.OK; + if (sjl.StowawayJoiningLocation.Length > 90) + readState = ExcelReader.ReadState.FAIL; + + reader.Conf.ConfirmText(sjlLookup, sjl.StowawayJoiningLocation, readState); + } + } + } + + #endregion + + } + catch(Exception ex) + { + _log.ErrorFormat("Crash during reading of MDH message: {0}", ex); + } + + // wird nicht wieder entfernt falls keine Daten vorliegen + } + + #endregion + + #region SEC + + private static void ScanSEC(List messages, MessageCore messageCore, ExcelReader reader) + { + Message secMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.SEC); + if (secMessage.Elements.Count == 0) + { + SEC newSEC = new SEC(); + newSEC.MessageHeader = secMessage; + secMessage.Elements.Add(newSEC); + } + SEC sec = secMessage.Elements[0] as SEC; + Util.ScanMessage(sec, reader); + + reader.ReadBoolean("SEC.AreMatterToReport"); // das berücksichtigen wir derzeit nicht in der DB (implizit) + + string isscType = reader.ReadText("SEC.ISSCType"); + if(isscType != null) + { + if (isscType.Equals("full", StringComparison.OrdinalIgnoreCase) || isscType.Equals("1")) + sec.ISSCType = 0; + if (isscType.Equals("interim", StringComparison.OrdinalIgnoreCase) || isscType.Equals("2")) + sec.ISSCType = 1; + } + + string shipsecLevel = reader.ReadText("SEC.CurrentShipSecurityLevel"); + if (shipsecLevel.IsNullOrEmpty()) + { + reader.Conf.ConfirmText("SEC.CurrentShipSecurityLevel", null, ExcelReader.ReadState.FAIL); + } + else + { + if (shipsecLevel.Contains('1')) sec.CurrentShipSecurityLevel = 1; + if (shipsecLevel.Contains('2')) sec.CurrentShipSecurityLevel = 2; + if (shipsecLevel.Contains('3')) sec.CurrentShipSecurityLevel = 3; + reader.Conf.ConfirmText("SEC.CurrentShipSecurityLevel", shipsecLevel, sec.CurrentShipSecurityLevel.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.WARN); + } + + reader.Conf.ConfirmText("SEC.ISSCType", isscType, sec.ISSCType.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL); + + string isscIssuerType = reader.ReadText("SEC.ISSCIssuerType"); + if(isscIssuerType != null) + { + if (isscIssuerType.Equals("rso", StringComparison.OrdinalIgnoreCase) || isscIssuerType.Equals("2")) + sec.ISSCIssuerType = 1; + if (isscIssuerType.Contains("admin", StringComparison.OrdinalIgnoreCase) || isscIssuerType.Equals("1")) + sec.ISSCIssuerType = 0; + } + + reader.Conf.ConfirmText("SEC.ISSCIssuerType", isscIssuerType, sec.ISSCIssuerType.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL); + sec.GeneralDescriptionOfCargo = reader.ReadGeneralDescriptionOfCargo("SEC.GeneralDescriptionOfCargo"); + + bool? secKielArrival = reader.ReadBoolean("SEC.KielCanalPassagePlanned_Arrival"); + bool? secKielDeparture = reader.ReadBoolean("SEC.KielCanalPassagePlanned_Departure"); + + // Leichter Umbau ("Verbesserung") der Logik Jul 21: Wenn ETA Werte drin stehen und das Flag nicht gesetzt ist + // wird es gesetzt sonst nicht gesetzt + sec.KielCanalPassagePlanned = (secKielArrival ?? false) || (secKielDeparture ?? false); + // if (sec.KielCanalPassagePlanned ?? false) + // { + sec.KielCanalPassagePlannedIncomming = reader.ReadDateTime("SEC.ETADateKielCanalPassagePlannedIncomming", "SEC.ETATimeKielCanalPassagePlannedIncomming", !(secKielArrival ?? false)); + sec.KielCanalPassagePlannedOutgoing = reader.ReadDateTime("SEC.ETADateKielCanalPassagePlannedOutgoing", "SEC.ETATimeKielCanalPassagePlannedOutgoing", !(secKielDeparture ?? false)); + // } + + if ((!sec.KielCanalPassagePlanned ?? false) && sec.KielCanalPassagePlannedIncomming.HasValue) sec.KielCanalPassagePlanned = true; + if ((!sec.KielCanalPassagePlanned ?? false) && sec.KielCanalPassagePlannedOutgoing.HasValue) sec.KielCanalPassagePlanned = true; + + if (!sec.KielCanalPassagePlannedIncomming.HasValue && !sec.KielCanalPassagePlannedOutgoing.HasValue) + sec.KielCanalPassagePlanned = false; + + + + + // Last10PortFacilitesCalled + for (int i = 1; i <= 10; i++) + { + string portName = string.Format("SEC.PortFacilityPortName_{0}", i); + string portCountry = string.Format("SEC.PortFacilityPortCountry_{0}", i); + string portLocode = string.Format("SEC.PortFacilityPortLoCode_{0}", i); + string portDateOfArrival = string.Format("SEC.PortFacilityDateOfArrival_{0}", i); + string portDateOfDeparture = string.Format("SEC.PortFacilityDateOfDeparture_{0}", i); + string portShipSecLevel = string.Format("SEC.PortFacilityShipSecurityLevel_{0}", i); + string portGISISCode = string.Format("SEC.PortFacilityGISISCode_{0}", i); + string portSecMatters = string.Format("SEC.PortFacilitySecurityMattersToReport_{0}", i); + + if (!(sec.GetPortFacilityWithIdentifier(i.ToString()) is LastTenPortFacilitiesCalled l10fc)) + { + l10fc = new LastTenPortFacilitiesCalled(); + l10fc.Identifier = i.ToString(); + l10fc.SEC = sec; + sec.LastTenPortFacilitesCalled.Add(l10fc); + } + + l10fc.PortFacilityPortName = reader.ReadText(portName); + reader.Conf.ConfirmText(portName, l10fc.PortFacilityPortName, ExcelReader.ReadState.OK); + l10fc.PortFacilityPortCountry = reader.ReadText(portCountry); + reader.Conf.ConfirmText(portCountry, l10fc.PortFacilityPortCountry, ExcelReader.ReadState.OK); + l10fc.PortFacilityPortLoCode = reader.ReadLoCode(portLocode); + l10fc.PortFacilityDateOfArrival = reader.ReadDate(portDateOfArrival); + l10fc.PortFacilityDateOfDeparture = reader.ReadDate(portDateOfDeparture); + + string sLevel = reader.ReadText(portShipSecLevel); + if(sLevel.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(portShipSecLevel, null, ExcelReader.ReadState.FAIL); + } + else + { + if (sLevel.Contains('1')) l10fc.PortFacilityShipSecurityLevel = 1; + if (sLevel.Contains('2')) l10fc.PortFacilityShipSecurityLevel = 2; + if (sLevel.Contains('3')) l10fc.PortFacilityShipSecurityLevel = 3; + reader.Conf.ConfirmText(portShipSecLevel, sLevel, l10fc.PortFacilityShipSecurityLevel.HasValue ? ExcelReader.ReadState.OK : ExcelReader.ReadState.WARN); + } + + l10fc.PortFacilityGISISCode = reader.ReadTextNoWhitespace(portGISISCode); + + if (l10fc.PortFacilityGISISCode.IsNullOrEmpty() || l10fc.PortFacilityGISISCode == "0") + l10fc.PortFacilityGISISCode = "0000"; + if(l10fc.PortFacilityGISISCode?.Length < 4) + { + while (l10fc.PortFacilityGISISCode.Length < 4) l10fc.PortFacilityGISISCode = "0" + l10fc.PortFacilityGISISCode; + } + if (l10fc.PortFacilityGISISCode.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(portGISISCode, l10fc.PortFacilityGISISCode, ExcelReader.ReadState.FAIL); + } + else + { + reader.Conf.ConfirmText(portGISISCode, l10fc.PortFacilityGISISCode, l10fc.PortFacilityGISISCode.IsDigitsOnly() ? ExcelReader.ReadState.OK : ExcelReader.ReadState.WARN); + } + + l10fc.PortFacilitySecurityMattersToReport = reader.ReadText(portSecMatters); + reader.Conf.ConfirmText(portSecMatters, l10fc.PortFacilitySecurityMattersToReport, l10fc.PortFacilitySecurityMattersToReport.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL :ExcelReader.ReadState.OK); + + // keinen "leeren" Hafen anlegen, wenn der Eintrag leer war (trifft anscheinend bei Neubauten zu, siehe E-Mail Christin vom 20./22.6.17 + if (l10fc.PortFacilityPortName.IsNullOrEmpty() && l10fc.PortFacilityPortLoCode.IsNullOrEmpty() && l10fc.PortFacilityPortCountry.IsNullOrEmpty()) + sec.LastTenPortFacilitesCalled.Remove(l10fc); + + } + + // Ship2ShipActivities + for (int i = 1; i <= 10; i++) + { + string s2sName = string.Format("SEC.ShipToShipActivityLocationName_{0}", i); + string s2sLocode = string.Format("SEC.ShipToShipActivityLocationLoCode_{0}", i); + string s2sLatitude = string.Format("SEC.ShipToShipActivityLocationCoordinatesLatitude_{0}", i); + string s2sLongitude = string.Format("SEC.ShipToShipActivityLocationCoordinatesLongitude_{0}", i); + string s2sFromDate = string.Format("SEC.ShipToShipActivityDateFrom_{0}", i); + string s2sToDate = string.Format("SEC.ShipToShipActivityDateTo_{0}", i); + string s2sSec = string.Format("SEC.ShipToShipActivitySecurityMattersToReport_{0}", i); + string s2sActivityString = string.Format("SEC.ShipToShipActivityType_{0}", i); + + + if (!(sec.GetShipToShipWithIdentifier(i.ToString()) is ShipToShipActivitiesDuringLastTenPortFacilitiesCalled s2sActivity)) + { + s2sActivity = new ShipToShipActivitiesDuringLastTenPortFacilitiesCalled(); + s2sActivity.Identifier = i.ToString(); + s2sActivity.SEC = sec; + sec.ShipToShipActivitiesDuringLastTenPortFacilitiesCalled.Add(s2sActivity); + } + + s2sActivity.ShipToShipActivityLocationName = reader.ReadText(s2sName); + if (s2sActivity.ShipToShipActivityLocationName.IsNullOrEmpty()) + { + sec.ShipToShipActivitiesDuringLastTenPortFacilitiesCalled.Remove(s2sActivity); + continue; + } + reader.Conf.ConfirmText(s2sName, s2sActivity.ShipToShipActivityLocationName, ExcelReader.ReadState.OK); + + s2sActivity.ShipToShipActivityLocationLoCode = reader.ReadLoCode(s2sLocode); + s2sActivity.ShipToShipActivityLocationCoordinatesLatitude = (int?)reader.ReadNumber(s2sLatitude); + // keine "0" (d.h. fehlerhafte Koordinaten) ins ANSW übergeben falls im Sheet nichts ist aber der Reader das aus irgendeinem Grund liest + if (s2sActivity.ShipToShipActivityLocationCoordinatesLatitude.HasValue && s2sActivity.ShipToShipActivityLocationCoordinatesLatitude.Value == 0) + s2sActivity.ShipToShipActivityLocationCoordinatesLatitude = null; + s2sActivity.ShipToShipActivityLocationCoordinatesLongitude = (int?)reader.ReadNumber(s2sLongitude); + if (s2sActivity.ShipToShipActivityLocationCoordinatesLongitude.HasValue && s2sActivity.ShipToShipActivityLocationCoordinatesLongitude.Value == 0) + s2sActivity.ShipToShipActivityLocationCoordinatesLongitude = null; + s2sActivity.ShipToShipActivityDateFrom = reader.ReadDate(s2sFromDate); + s2sActivity.ShipToShipActivityDateTo = reader.ReadDate(s2sToDate); + s2sActivity.ShipToShipActivityTypeCode = (int?) reader.ReadNumber(s2sActivityString); + reader.ReadShip2ShipActivityType(s2sActivityString); // 24.8.21 nicht Code dem Klartext zuordnen, nur das Feld kolorieren + s2sActivity.ShipToShipActivitySecurityMattersToReport = reader.ReadText(s2sSec); + reader.Conf.ConfirmText(s2sSec, s2sActivity.ShipToShipActivitySecurityMattersToReport, s2sActivity.ShipToShipActivitySecurityMattersToReport.IsNullOrEmpty() ? ExcelReader.ReadState.NONE : ExcelReader.ReadState.OK); + } + + } + + #endregion + + #region BKRA + + private static void ScanBKRA(List messages, MessageCore messageCore, ExcelReader reader) + { + Message bkraMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.BKRA); + bkraMessage.DeleteElements(); + for (int i = 1; i <= bkraMessage.NumberOfExcelRows; i++) + { + string lnQuantity = string.Format("BKRA.BunkerFuelQuantity_TNE_{0}", i); + string lnType = string.Format("BKRA.BunkerFuelType_{0}", i); + + if (!(bkraMessage.GetSublistElementWithIdentifier((i).ToString()) is BRKA bkra)) + { + bkra = new BRKA(); + bkra.Identifier = (i).ToString(); + bkra.MessageHeader = bkraMessage; + bkraMessage.Elements.Add(bkra); + } + + bkra.BunkerFuelQuantity_TNE = reader.ReadNumber(lnQuantity); + bkra.BunkerFuelType = reader.ReadText(lnType); + reader.Conf.ConfirmText(lnType, bkra.BunkerFuelType, ExcelReader.ReadState.OK); + + // "OK" Quantity falls Type nicht angegeben + if (bkra.BunkerFuelType.IsNullOrEmpty() && !bkra.BunkerFuelQuantity_TNE.HasValue) + reader.Conf.ConfirmNumber(lnQuantity, null, ExcelReader.ReadState.OK); + // "WARN" Quantity falls Menge aber kein Type + if(bkra.BunkerFuelQuantity_TNE.HasValue && bkra.BunkerFuelType.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(lnType, null, ExcelReader.ReadState.FAIL); + reader.Conf.ConfirmNumber(lnQuantity, bkra.BunkerFuelQuantity_TNE, ExcelReader.ReadState.WARN); + } + + // dont save empty element + if(bkra.IsNew && !bkra.BunkerFuelQuantity_TNE.HasValue && bkra.BunkerFuelType.IsNullOrEmpty()) + bkraMessage.Elements.Remove(bkra); + } + } + + #endregion + + #region BKRD + + private static void ScanBKRD(List messages, MessageCore messageCore, ExcelReader reader) + { + Message bkrdMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.BKRD); + bkrdMessage.DeleteElements(); + for (int i = 1; i <= bkrdMessage.NumberOfExcelRows; i++) + { + string lnQuantity = string.Format("BKRD.BunkerFuelQuantity_TNE_{0}", i); + string lnType = string.Format("BKRD.BunkerFuelType_{0}", i); + if (!(bkrdMessage.GetSublistElementWithIdentifier((i).ToString()) is BRKD bkrd)) + { + bkrd = new BRKD(); + bkrd.Identifier = (i).ToString(); + bkrd.MessageHeader = bkrdMessage; + bkrdMessage.Elements.Add(bkrd); + } + + bkrd.BunkerFuelQuantity_TNE = reader.ReadNumber(lnQuantity); + bkrd.BunkerFuelType = reader.ReadText(lnType); + reader.Conf.ConfirmText(lnType, bkrd.BunkerFuelType, ExcelReader.ReadState.OK); + + // "OK" Quantity falls Type nicht angegeben + if (bkrd.BunkerFuelType.IsNullOrEmpty() && !bkrd.BunkerFuelQuantity_TNE.HasValue) + reader.Conf.ConfirmNumber(lnQuantity, null, ExcelReader.ReadState.OK); + // "WARN" Quantity falls Menge aber kein Type + if (bkrd.BunkerFuelQuantity_TNE.HasValue && bkrd.BunkerFuelType.IsNullOrEmpty()) + { + reader.Conf.ConfirmText(lnType, null, ExcelReader.ReadState.FAIL); + reader.Conf.ConfirmNumber(lnQuantity, bkrd.BunkerFuelQuantity_TNE, ExcelReader.ReadState.WARN); + } + + // dont save empty element + if (bkrd.IsNew && !bkrd.BunkerFuelQuantity_TNE.HasValue && bkrd.BunkerFuelType.IsNullOrEmpty()) + bkrdMessage.Elements.Remove(bkrd); + } + } + + #endregion + + #region TOWA + + private static void ScanTOWA(List messages, MessageCore messageCore, ExcelReader reader) + { + Message towaMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.TOWA); + + // 24.4.21: TOWA beim Excel import + bool hasTOWAMarker = false; + for (int i = 1; i <= towaMessage.NumberOfExcelRows; i++) + { + string tName = string.Format("TOWA.TowageOnArrivalName_{0}", i); + string towageName = reader.ReadText(tName); + if (!towageName.IsNullOrEmpty()) + { + hasTOWAMarker = true; + break; + } + } + if (!hasTOWAMarker) return; // no TOWA info on sheet + + towaMessage.DeleteElements(); + for (int i = 1; i <= towaMessage.NumberOfExcelRows; i++) + { + string tName = string.Format("TOWA.TowageOnArrivalName_{0}", i); + string tFlag = string.Format("TOWA.TowageOnArrivalFlag_{0}", i); + string tPoC = string.Format("TOWA.TowageOnArrivalPurposeOfCall_{0}", i); + string tDraft = string.Format("TOWA.TowageOnArrivalDraught_DMT_{0}", i); + string tGT = string.Format("TOWA.TowageOnArrivalGrossTonnage_{0}", i); + string tLen = string.Format("TOWA.TowageOnArrivalLengthOverall_MTR_{0}", i); + string tBeam = string.Format("TOWA.TowageOnArrivalBeam_MTR_{0}", i); + string tOp = string.Format("TOWA.TowageOnArrivalOperatorCompanyName_{0}", i); + + string towageName = reader.ReadText(tName); + if (towageName.IsNullOrEmpty()) continue; + + if (!(towaMessage.GetSublistElementWithIdentifier((i).ToString()) is TOWA towa)) + { + towa = new TOWA(); + towa.Identifier = (i).ToString(); + towa.MessageHeader = towaMessage; + towaMessage.Elements.Add(towa); + } + + towa.TowageOnArrivalName = towageName; + reader.Conf.ConfirmText(tName, towageName, ExcelReader.ReadState.OK); + towa.TowageOnArrivalFlag = reader.ReadText(tFlag); + reader.Conf.ConfirmText(tFlag, towa.TowageOnArrivalFlag, towa.TowageOnArrivalFlag.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + towa.TowageOnArrivalPurposeOfCall = reader.ReadText(tPoC); + reader.Conf.ConfirmText(tPoC, towa.TowageOnArrivalPurposeOfCall, towa.TowageOnArrivalPurposeOfCall.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + towa.TowageOnArrivalDraught_DMT = reader.ReadNumber(tDraft); + towa.TowageOnArrivalGrossTonnage = (int?) reader.ReadNumber(tGT); + towa.TowageOnArrivalLengthOverall_MTR = reader.ReadNumber(tLen); + towa.TowageOnArrivalBeam_MTR = reader.ReadNumber(tBeam); + towa.TowageOnArrivalOperatorCompanyName = reader.ReadText(tOp); + reader.Conf.ConfirmText(tOp, towa.TowageOnArrivalOperatorCompanyName, towa.TowageOnArrivalOperatorCompanyName.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + } + } + + #endregion + + #region TOWD + + private static void ScanTOWD(List messages, MessageCore messageCore, ExcelReader reader) + { + Message towdMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.TOWD); + + // 24.4.21: TOWD beim Excel import + bool hasTOWDMarker = false; + for (int i = 1; i <= towdMessage.NumberOfExcelRows; i++) + { + string tName = string.Format("TOWD.TowageOnDepartureName_{0}", i); + string towageName = reader.ReadText(tName); + if (!towageName.IsNullOrEmpty()) + { + hasTOWDMarker = true; + break; + } + } + if (!hasTOWDMarker) return; // no TOWD info on sheet + + towdMessage.DeleteElements(); + + for (int i = 1; i <= towdMessage.NumberOfExcelRows; i++) + { + string tName = string.Format("TOWD.TowageOnDepartureName_{0}", i); + string tFlag = string.Format("TOWD.TowageOnDepartureFlag_{0}", i); + string tDraft = string.Format("TOWD.TowageOnDepartureDraught_DMT_{0}", i); + string tLen = string.Format("TOWD.TowageOnDepartureLengthOverall_MTR_{0}", i); + string tBeam = string.Format("TOWD.TowageOnDepartureBeam_MTR_{0}", i); + string tOp = string.Format("TOWD.TowageOnDepartureOperatorCompanyName_{0}", i); + + string towageName = reader.ReadText(tName); + if (towageName.IsNullOrEmpty()) continue; + + if (!(towdMessage.GetSublistElementWithIdentifier((i).ToString()) is TOWD towd)) + { + towd = new TOWD(); + towd.Identifier = (i).ToString(); + towd.MessageHeader = towdMessage; + towdMessage.Elements.Add(towd); + } + + towd.TowageOnDepartureName = towageName; + reader.Conf.ConfirmText(tName, towageName, ExcelReader.ReadState.OK); + towd.TowageOnDepartureFlag = reader.ReadText(tFlag); + reader.Conf.ConfirmText(tFlag, towd.TowageOnDepartureFlag, towd.TowageOnDepartureFlag.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + towd.TowageOnDepartureDraught_DMT = reader.ReadNumber(tDraft); + towd.TowageOnDepartureLengthOverall_MTR = reader.ReadNumber(tLen); + towd.TowageOnDepartureBeam_MTR = reader.ReadNumber(tBeam); + towd.TowageOnDepartureOperatorCompanyName = reader.ReadText(tOp); + reader.Conf.ConfirmText(tOp, towd.TowageOnDepartureOperatorCompanyName, towd.TowageOnDepartureOperatorCompanyName.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + + } + } + + #endregion + + #region PRE72H + + private static void ScanPRE72H(List messages, MessageCore messageCore, ExcelReader reader) + { + Message pre72hMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.PRE72H); + if (pre72hMessage.Elements.Count == 0) + { + PRE72H newPRE72H = new PRE72H(); + newPRE72H.MessageHeader = pre72hMessage; + pre72hMessage.Elements.Add(newPRE72H); + } + PRE72H pre72h = pre72hMessage.Elements[0] as PRE72H; + Util.ScanMessage(pre72h, reader); + // diese Nachricht bleibt auch wenn sie leer ist + pre72h.ConditionCargoBallastTanks = reader.ReadConditionTanks("PRE72H.ConditionCargoBallastTanks"); + pre72h.TankerHullConfiguration = reader.ReadHullConfiguration("PRE72H.TankerHullConfiguration"); + pre72h.PlannedWorks = reader.ReadText("PRE72H.PlannedWorks"); + reader.Conf.ConfirmText("PRE72H.PlannedWorks", pre72h.PlannedWorks, pre72h.PlannedWorks.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + + #endregion + + #region SERV + + private static void ScanSERV(List messages, MessageCore messageCore, ExcelReader reader) + { + Message servMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.SERV); + if(servMessage.Elements.Count == 0) + { + SERV newSERV = new SERV(); + newSERV.MessageHeader = servMessage; + newSERV.Identifier = "1"; + servMessage.Elements.Add(newSERV); + } + SERV serv = servMessage.Elements[0] as SERV; + Util.ScanMessage(serv, reader); + if (serv.ServiceBeneficiary.IsNullOrEmpty() && serv.ServiceInvoiceRecipient.IsNullOrEmpty()) + servMessage.Elements.Remove(serv); + if (serv.ServiceBeneficiary.IsNullOrEmpty()) reader.Conf.ConfirmText("SERV.ServiceBeneficiary", null, ExcelReader.ReadState.FAIL); + if (serv.ServiceInvoiceRecipient.IsNullOrEmpty()) reader.Conf.ConfirmText("SERV.ServiceInvoiceRecipient", null, ExcelReader.ReadState.FAIL); + + + } + + #endregion + + #region STO + + private static void ScanSTO(List messages, MessageCore messageCore, ExcelReader reader) + { + Message stoMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.STO); + stoMessage.DeleteElements(); + + for(int i=0;i messages, MessageCore messageCore, ExcelReader reader) + { + Message ladgMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.LADG); + ladgMessage.DeleteElements(); + + for (int i = 0; i < ladgMessage.NumberOfExcelRows; i++) + { + string lnCHT = string.Format("LADG.CargoHandlingType_{0}", i + 1); + string lnType = string.Format("LADG.CargoType_{0}", i + 1); + string lnCNOI = string.Format("LADG.CargoNumberOfItems_{0}", i + 1); + string lnCGQ = string.Format("LADG.CargoGrossQuantity_TNE_{0}", i + 1); + string lnLoad = string.Format("LADG.CargoPortOfLoading_{0}", i + 1); + string lnDis = string.Format("LADG.CargoPortOfDischarge_{0}", i + 1); + string lnLACode = string.Format("LADG.CargoLACode_{0}", i + 1); + string lnZusatz = string.Format("LADG.CargoTypeZusatz_{0}", i + 1); + + if (!(ladgMessage.GetSublistElementWithIdentifier((i + 1).ToString()) is LADG ladg)) + { + ladg = new LADG(); + ladg.Identifier = (i + 1).ToString(); + ladg.MessageHeader = ladgMessage; + ladgMessage.Elements.Add(ladg); + } + + ladg.CargoHandlingType = reader.ReadCargoHandlingType(lnCHT); + + // Transit-Ladung für DE nicht übernehmen! + if ((reader.Mode == ExcelReader.CountryMode.DE) && ((ladg.CargoHandlingType ?? 0) == 2)) + { + ladgMessage.Elements.Remove(ladg); + continue; + } + + ladg.CargoCodeNST = reader.ReadText(lnType); + // Cargo Type Freitext in DK + + if(reader.Mode == ExcelReader.CountryMode.DK) + { + reader.Conf.ConfirmText(lnType, ladg.CargoCodeNST, ladg.CargoCodeNST.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + } + if (reader.Mode == ExcelReader.CountryMode.DE) + { + if (ladg.CargoCodeNST?.Length == 1) + ladg.CargoCodeNST = "0" + ladg.CargoCodeNST; + + if ((ladg.CargoCodeNST != null) && (ladg.CargoCodeNST.Length != 2)) + { + ladg.CargoCodeNST = null; // stupid validation + reader.Conf.ConfirmText(lnType, null, ExcelReader.ReadState.WARN); + } + else + { + if(Int32.TryParse(ladg.CargoCodeNST, out int ccnst)) + { + if ((ccnst > 0) && (ccnst < 21)) + { + reader.Conf.ConfirmText(lnType, ladg.CargoCodeNST, ExcelReader.ReadState.OK); + } + else + { + reader.Conf.ConfirmText(lnType, null, ExcelReader.ReadState.WARN); + ladg.CargoCodeNST = null; + } + } + else + { + ladg.CargoCodeNST = null; + reader.Conf.ConfirmText(lnType, null, ExcelReader.ReadState.FAIL); + } + } + } + + ladg.CargoLACode = reader.ReadCargoLACode(lnLACode); + + ladg.CargoCodeNST_3 = reader.ReadText(lnZusatz); + if (!ladg.CargoCodeNST_3.IsNullOrEmpty()) + { + if (ladg.CargoCodeNST_3.Length == 1) + { + reader.Conf.ConfirmText(lnZusatz, ladg.CargoCodeNST_3, ExcelReader.ReadState.OK); + } + else + { + if(ladg.CargoCodeNST_3.Length > 8) + { + ladg.CargoCodeNST_3 = ladg.CargoCodeNST_3.Substring(0, 8); + reader.Conf.ConfirmText(lnZusatz, ladg.CargoCodeNST_3, ExcelReader.ReadState.FAIL); + } else + { + reader.Conf.ConfirmText(lnZusatz, ladg.CargoCodeNST_3, ExcelReader.ReadState.WARN); + } + } + } + + ladg.CargoNumberOfItems = (int?) reader.ReadNumber(lnCNOI); + ladg.CargoGrossQuantity_TNE = reader.ReadNumber(lnCGQ); + ladg.PortOfLoading = reader.ReadLoCode(lnLoad); + ladg.PortOfDischarge = reader.ReadLoCode(lnDis); + + // dont save empty element + if (ladg.IsNew && !ladg.CargoHandlingType.HasValue) + ladgMessage.Elements.Remove(ladg); + } + } + + #endregion + + #region CREW + + private static void ScanCREW(List messages, MessageCore messageCore, ExcelReader reader) + { + Message crewMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.CREW); + crewMessage.DeleteElements(); + + for (int i = 0; i < crewMessage.NumberOfExcelRows; i++) + { + string crewLastName = string.Format("CREW.CrewMemberLastName_{0}", i + 1); + string crewFirstName = string.Format("CREW.CrewMemberFirstName_{0}", i + 1); + string crewGender = string.Format("CREW.CrewMemberGender_{0}", i + 1); + string crewNationality = string.Format("CREW.CrewMemberNationality_{0}", i + 1); + string crewDuty = string.Format("CREW.CrewMemberDuty_{0}", i + 1); + string crewPlaceOfBirth = string.Format("CREW.CrewMemberPlaceOfBirth_{0}", i + 1); + string crewDateOfBirth = string.Format("CREW.CrewMemberDateOfBirth_{0}", i + 1); + string crewIdentDocType = string.Format("CREW.CrewMemberIdentityDocumentType_{0}", i + 1); + string crewIdentDocId = string.Format("CREW.CrewMemberIdentityDocumentId_{0}", i + 1); + string crewVisaNo = string.Format("CREW.CrewMemberVisaNumber_{0}", i + 1); + + string lastName = reader.ReadText(crewLastName); + string firstName = reader.ReadText(crewFirstName); + + if (!lastName.IsNullOrEmpty() || !firstName.IsNullOrEmpty()) + { + if (!(crewMessage.GetSublistElementWithIdentifier((i + 1).ToString()) is CREW crew)) + { + crew = new CREW(); + crew.Identifier = (i + 1).ToString(); + crew.MessageHeader = crewMessage; + crewMessage.Elements.Add(crew); + } + + crew.CrewMemberLastName = lastName; + reader.Conf.ConfirmText(crewLastName, lastName, crew.CrewMemberLastName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + crew.CrewMemberFirstName = firstName; + reader.Conf.ConfirmText(crewFirstName, crew.CrewMemberFirstName, crew.CrewMemberFirstName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + crew.CrewMemberGender = reader.ReadGender(crewGender); + crew.CrewMemberDuty = reader.ReadText(crewDuty); + reader.Conf.ConfirmText(crewDuty, crew.CrewMemberDuty, crew.CrewMemberDuty.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + crew.CrewMemberNationality = reader.ReadNationality(crewNationality); + crew.CrewMemberPlaceOfBirth = reader.ReadText(crewPlaceOfBirth); + reader.Conf.ConfirmText(crewPlaceOfBirth, crew.CrewMemberPlaceOfBirth, crew.CrewMemberPlaceOfBirth.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + crew.CrewMemberDateOfBirth = reader.ReadBirthDate(crewDateOfBirth); + + crew.CrewMemberIdentityDocumentType = reader.ReadIdentityDocumentType(crewIdentDocType); + crew.CrewMemberIdentityDocumentId = reader.ReadText(crewIdentDocId); + reader.Conf.ConfirmText(crewIdentDocId, crew.CrewMemberIdentityDocumentId, crew.CrewMemberIdentityDocumentId.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + crew.CrewMemberVisaNumber = reader.ReadText(crewVisaNo); + reader.Conf.ConfirmText(crewVisaNo, crew.CrewMemberVisaNumber, crew.CrewMemberVisaNumber.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + + } + } + + // CREW DEPARTURE + crewMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.CREWD); + for (int i = 0; i < crewMessage.NumberOfExcelRows; i++) + { + string crewLastName = string.Format("CREWD.CrewMemberLastName_{0}", i + 1); + string crewFirstName = string.Format("CREWD.CrewMemberFirstName_{0}", i + 1); + string crewGender = string.Format("CREWD.CrewMemberGender_{0}", i + 1); + string crewNationality = string.Format("CREWD.CrewMemberNationality_{0}", i + 1); + string crewDuty = string.Format("CREWD.CrewMemberDuty_{0}", i + 1); + string crewPlaceOfBirth = string.Format("CREWD.CrewMemberPlaceOfBirth_{0}", i + 1); + string crewDateOfBirth = string.Format("CREWD.CrewMemberDateOfBirth_{0}", i + 1); + string crewIdentDocType = string.Format("CREWD.CrewMemberIdentityDocumentType_{0}", i + 1); + string crewIdentDocId = string.Format("CREWD.CrewMemberIdentityDocumentId_{0}", i + 1); + string crewVisaNo = string.Format("CREWD.CrewMemberVisaNumber_{0}", i + 1); + + string lastName = reader.ReadText(crewLastName); + if (!lastName.IsNullOrEmpty()) + { + if (!(crewMessage.GetSublistElementWithIdentifier((i + 1).ToString()) is CREWD crew)) + { + crew = new CREWD(); + crew.Identifier = (i + 1).ToString(); + crew.MessageHeader = crewMessage; + crewMessage.Elements.Add(crew); + } + + crew.IsDeparture = true; + crew.CrewMemberLastName = lastName; + reader.Conf.ConfirmText(crewLastName, lastName, lastName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + crew.CrewMemberFirstName = reader.ReadText(crewFirstName); + reader.Conf.ConfirmText(crewFirstName, crew.CrewMemberFirstName, crew.CrewMemberFirstName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + crew.CrewMemberGender = reader.ReadGender(crewGender); + crew.CrewMemberDuty = reader.ReadText(crewDuty); + reader.Conf.ConfirmText(crewDuty, crew.CrewMemberDuty, crew.CrewMemberDuty.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + crew.CrewMemberNationality = reader.ReadNationality(crewNationality); + crew.CrewMemberPlaceOfBirth = reader.ReadText(crewPlaceOfBirth); + reader.Conf.ConfirmText(crewPlaceOfBirth, crew.CrewMemberPlaceOfBirth, crew.CrewMemberPlaceOfBirth.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + crew.CrewMemberDateOfBirth = reader.ReadBirthDate(crewDateOfBirth); + + crew.CrewMemberIdentityDocumentType = reader.ReadIdentityDocumentType(crewIdentDocType); + crew.CrewMemberIdentityDocumentId = reader.ReadText(crewIdentDocId); + reader.Conf.ConfirmText(crewIdentDocId, crew.CrewMemberIdentityDocumentId, crew.CrewMemberIdentityDocumentId.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + crew.CrewMemberVisaNumber = reader.ReadText(crewVisaNo); + reader.Conf.ConfirmText(crewVisaNo, crew.CrewMemberVisaNumber, crew.CrewMemberVisaNumber.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + + } + } + } + + #endregion + + #region PAS + + private static void ScanPAS(List messages, MessageCore messageCore, ExcelReader reader) + { + Message pasMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.PAS); + pasMessage.DeleteElements(); + + for (int i = 0; i < pasMessage.NumberOfExcelRows; i++) + { + string pasLastName = string.Format("PAS.PassengerLastName_{0}", i + 1); + string pasFirstName = string.Format("PAS.PassengerFirstName_{0}", i + 1); + string pasGender = string.Format("PAS.PassengerGender_{0}", i + 1); + string pasNationality = string.Format("PAS.PassengerNationality_{0}", i + 1); + string pasEmbarkation = string.Format("PAS.PassengerPortOfEmbarkation_{0}", i + 1); + string pasDebarkation = string.Format("PAS.PassengerPortOfDisembarkation_{0}", i + 1); + string pasTransit = string.Format("PAS.PassengerInTransit_{0}", i + 1); + string pasPlaceOfBirth = string.Format("PAS.PassengerPlaceOfBirth_{0}", i + 1); + string pasDateOfBirth = string.Format("PAS.PassengerDateOfBirth_{0}", i + 1); + string pasIdentDocType = string.Format("PAS.PassengerIdentityDocumentType_{0}", i + 1); + string pasIdentDocId = string.Format("PAS.PassengerIdentityDocumentId_{0}", i + 1); + string pasVisaNo = string.Format("PAS.PassengerVisaNumber_{0}", i + 1); + + string lastName = reader.ReadText(pasLastName); + string firstName = reader.ReadText(pasFirstName); + + if (!lastName.IsNullOrEmpty() || !firstName.IsNullOrEmpty()) + { + if (!(pasMessage.GetSublistElementWithIdentifier((i + 1).ToString()) is PAS pas)) + { + pas = new PAS(); + pas.Identifier = (i + 1).ToString(); + pas.MessageHeader = pasMessage; + pasMessage.Elements.Add(pas); + } + + pas.PassengerLastName = lastName; + reader.Conf.ConfirmText(pasLastName, lastName, lastName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerFirstName = firstName; + reader.Conf.ConfirmText(pasFirstName, pas.PassengerFirstName, pas.PassengerFirstName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerGender = reader.ReadGender(pasGender); + pas.PassengerNationality = reader.ReadNationality(pasNationality); + // TODO: Nicht klar ob hier LOCODEs kommen oder nicht + pas.PassengerPortOfEmbarkation = reader.ReadLoCode(pasEmbarkation); + reader.Conf.ConfirmText(pasEmbarkation, pas.PassengerPortOfEmbarkation, pas.PassengerPortOfEmbarkation.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerPortOfDisembarkation = reader.ReadLoCode(pasDebarkation); + reader.Conf.ConfirmText(pasDebarkation, pas.PassengerPortOfDisembarkation, pas.PassengerPortOfDisembarkation.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerInTransit = reader.ReadBoolean(pasTransit); + pas.PassengerPlaceOfBirth = reader.ReadText(pasPlaceOfBirth); + reader.Conf.ConfirmText(pasPlaceOfBirth, pas.PassengerPlaceOfBirth, pas.PassengerPlaceOfBirth.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL: ExcelReader.ReadState.OK); + pas.PassengerDateOfBirth = reader.ReadBirthDate(pasDateOfBirth); + pas.PassengerIdentityDocumentType = reader.ReadIdentityDocumentType(pasIdentDocType); + pas.PassengerIdentityDocumentId = reader.ReadText(pasIdentDocId); + reader.Conf.ConfirmText(pasIdentDocId, pas.PassengerIdentityDocumentId, pas.PassengerIdentityDocumentId.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerVisaNumber = reader.ReadText(pasVisaNo); + reader.Conf.ConfirmText(pasVisaNo, pas.PassengerVisaNumber, pas.PassengerVisaNumber.IsNullOrEmpty() ? ExcelReader.ReadState.WARN :ExcelReader.ReadState.OK); + } + } + + // PASSENGER DEPARTURE + pasMessage = Util.GetMessageWithType(messages, messageCore, Message.NotificationClass.PASD); + for (int i = 0; i < pasMessage.NumberOfExcelRows; i++) + { + string pasLastName = string.Format("PASD.PassengerLastName_{0}", i + 1); + string pasFirstName = string.Format("PASD.PassengerFirstName_{0}", i + 1); + string pasGender = string.Format("PASD.PassengerGender_{0}", i + 1); + string pasNationality = string.Format("PASD.PassengerNationality_{0}", i + 1); + string pasEmbarkation = string.Format("PASD.PassengerPortOfEmbarkation_{0}", i + 1); + string pasDebarkation = string.Format("PASD.PassengerPortOfDisembarkation_{0}", i + 1); + string pasTransit = string.Format("PASD.PassengerInTransit_{0}", i + 1); + string pasPlaceOfBirth = string.Format("PASD.PassengerPlaceOfBirth_{0}", i + 1); + string pasDateOfBirth = string.Format("PASD.PassengerDateOfBirth_{0}", i + 1); + string pasIdentDocType = string.Format("PASD.PassengerIdentityDocumentType_{0}", i + 1); + string pasIdentDocId = string.Format("PASD.PassengerIdentityDocumentId_{0}", i + 1); + string pasVisaNo = string.Format("PASD.PassengerVisaNumber_{0}", i + 1); + + string lastName = reader.ReadText(pasLastName); + if (!lastName.IsNullOrEmpty()) + { + if (!(pasMessage.GetSublistElementWithIdentifier((i + 1).ToString()) is PASD pas)) + { + pas = new PASD(); + pas.Identifier = (i + 1).ToString(); + pas.MessageHeader = pasMessage; + pasMessage.Elements.Add(pas); + } + + pas.IsDeparture = true; + + pas.PassengerLastName = lastName; + reader.Conf.ConfirmText(pasLastName, lastName, ExcelReader.ReadState.OK); + pas.PassengerFirstName = reader.ReadText(pasFirstName); + reader.Conf.ConfirmText(pasFirstName, pas.PassengerFirstName, pas.PassengerFirstName.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerGender = reader.ReadGender(pasGender); + pas.PassengerNationality = reader.ReadNationality(pasNationality); + // TODO: Nicht klar ob hier LOCODEs kommen oder nicht + pas.PassengerPortOfEmbarkation = reader.ReadTextNoWhitespace(pasEmbarkation); + reader.Conf.ConfirmText(pasEmbarkation, pas.PassengerPortOfEmbarkation, pas.PassengerPortOfEmbarkation.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerPortOfDisembarkation = reader.ReadTextNoWhitespace(pasDebarkation); + reader.Conf.ConfirmText(pasDebarkation, pas.PassengerPortOfDisembarkation, pas.PassengerPortOfDisembarkation.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerInTransit = reader.ReadBoolean(pasTransit); + pas.PassengerPlaceOfBirth = reader.ReadText(pasPlaceOfBirth); + reader.Conf.ConfirmText(pasPlaceOfBirth, pas.PassengerPlaceOfBirth, pas.PassengerPlaceOfBirth.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerDateOfBirth = reader.ReadBirthDate(pasDateOfBirth); + pas.PassengerIdentityDocumentType = reader.ReadIdentityDocumentType(pasIdentDocType); + pas.PassengerIdentityDocumentId = reader.ReadText(pasIdentDocId); + reader.Conf.ConfirmText(pasIdentDocId, pas.PassengerIdentityDocumentId, pas.PassengerIdentityDocumentId.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + pas.PassengerVisaNumber = reader.ReadText(pasVisaNo); + reader.Conf.ConfirmText(pasVisaNo, pas.PassengerVisaNumber, pas.PassengerVisaNumber.IsNullOrEmpty() ? ExcelReader.ReadState.WARN : ExcelReader.ReadState.OK); + } + } + + } + + #endregion + + #region ScanMessage (generic) + + private static void ScanMessage(DatabaseEntity dbEntity, ExcelReader reader) + { + Type objType = dbEntity.GetType(); + List props = new List(); + + // add lookup properties to scan list + props.AddRange(objType.GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(LookupNameAttribute)))); + + foreach (PropertyInfo property in props) + { + object propValue = property.GetValue(dbEntity, null); + string value = (propValue == null) ? string.Empty : propValue.ToString(); + LookupNameAttribute lookupNameAttribute = Attribute.GetCustomAttribute(property, typeof(LookupNameAttribute)) as LookupNameAttribute; + + if (property.PropertyType == typeof(DateTime?)) + { + DateTime? sheetValue = reader.ReadDate(lookupNameAttribute.LookupName); + if (sheetValue != null) + { + property.SetValue(dbEntity, sheetValue); + reader.Conf.ConfirmDate(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.OK); + } + else + { + reader.Conf.ConfirmDate(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.WARN); + } + + } + else if (property.PropertyType == typeof(double?)) + { + double? sheetValue = reader.ReadNumber(lookupNameAttribute.LookupName); + if (sheetValue != null) + { + property.SetValue(dbEntity, sheetValue); + reader.Conf.ConfirmNumber(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.OK); + } + else + { + reader.Conf.ConfirmNumber(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.WARN); + } + } + else if (property.PropertyType == typeof(string)) + { + string sheetValue = reader.ReadText(lookupNameAttribute.LookupName); + if (sheetValue != null) + { + + property.SetValue(dbEntity, sheetValue); + ExcelReader.ReadState readState = ExcelReader.ReadState.OK; + // Wenn der Zellentext länger ist als 90 Zeichen und maximal 99/100 Zeichen lang ist soll die Zelle rot gefärbt werden + if (Attribute.IsDefined(property, typeof(MaxLengthAttribute))) + { + MaxLengthAttribute mla = Attribute.GetCustomAttribute(property, typeof(MaxLengthAttribute)) as MaxLengthAttribute; + if ((sheetValue.Length >= 90) && ((mla.MaxLength == 99) || (mla.MaxLength == 100))) + { + readState = ExcelReader.ReadState.FAIL; + } + } + + reader.Conf.ConfirmText(lookupNameAttribute.LookupName, sheetValue, readState); + } + else + { + reader.Conf.ConfirmText(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.WARN); + } + } + else if (property.PropertyType == typeof(int?)) + { + double? sheetValue = reader.ReadNumber(lookupNameAttribute.LookupName); + if (sheetValue.HasValue) + { + property.SetValue(dbEntity, (int)sheetValue.Value); + reader.Conf.ConfirmNumber(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.OK); + } + else + { + reader.Conf.ConfirmNumber(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.WARN); + } + } + else if (property.PropertyType == typeof(byte?)) + { + double? sheetValue = reader.ReadNumber(lookupNameAttribute.LookupName); + if (sheetValue.HasValue) + { + property.SetValue(dbEntity, (byte)sheetValue.Value); + reader.Conf.ConfirmNumber(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.OK); + } + else + { + reader.Conf.ConfirmNumber(lookupNameAttribute.LookupName, sheetValue, ExcelReader.ReadState.WARN); + } + + } + else if (property.PropertyType == typeof(Boolean?)) + { + bool? sheetValue = reader.ReadBoolean(lookupNameAttribute.LookupName); + string boolStringValue = reader.ReadText(lookupNameAttribute.LookupName); + if (sheetValue.HasValue) { + property.SetValue(dbEntity, sheetValue); + reader.Conf.ConfirmText(lookupNameAttribute.LookupName, sheetValue.Value ? "Y" : "N", + ExcelReader.ReadState.OK); + } + else + { + reader.Conf.ConfirmText(lookupNameAttribute.LookupName, boolStringValue, ExcelReader.ReadState.WARN); + } + } + else + { + _log.DebugFormat("unhandled property type: {0}", property.PropertyType); + } + + } + + } + + #endregion + + #region LookupMessageCore + + /// + /// Check with cell values if this message core is already in our DB + /// + private static MessageCore LookupMessageCore(ExcelReader reader, out string message) + { + // lookup using field values + MessageCore result = null; + DateTime? eta = null; + string poc; + string imo = null; + message = string.Empty; + bool isTransit = false; + + // first check with visit/transit ID + string visitTransitId = reader.ReadTextNoWhitespace("ID"); + + if (visitTransitId != null) + { + if (bsmd.database.Util.IsVisitId(visitTransitId)) + { + result = DBManager.Instance.GetMessageCoreByVisitId(visitTransitId); + } + else if (bsmd.database.Util.IsTransitId(visitTransitId)) + { + result = DBManager.Instance.GetMessageCoreByTransitId(visitTransitId); + } + } + else + { + message = "Visit / Transit Id missing!"; + return null; + } + + if (result != null) + { + // setup returning confirmation sheets according to PoC + if (result.PoC.Substring(0, 2) == "DK") + reader.SetConfirmation(Properties.Settings.Default.ConfirmationDK); + else + reader.SetConfirmation(Properties.Settings.Default.ConfirmationDE); + + // copy poc/imo/eta to return sheet + poc = reader.ReadText("Visit.PortOfCall"); + reader.Conf.ConfirmText("Visit.PortOfCall", poc, ExcelReader.ReadState.OK); + reader.Conf.ConfirmText("Visit.PortOfCall_DK", poc, ExcelReader.ReadState.OK); + imo = reader.ReadText("Visit.IMONumber"); + reader.Conf.ConfirmText("Visit.IMONumber", imo, ExcelReader.ReadState.OK); + eta = reader.ReadDateTime("NOA_NOD.ETADateToPortOfCall", "NOA_NOD.ETATimeToPortOfCall"); + result.HerbergReportType = reader.ReadText("ReferenceNumber"); + reader.Conf.ConfirmText("ReferenceNumber", result.HerbergReportType, result.HerbergReportType.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + } + else + { + // lookup poc, imo, eta + poc = reader.ReadText("Visit.PortOfCall"); + + if (poc != null) + { + + // Prüfen auf Transit + if (poc.IndexOf("CANAL", StringComparison.OrdinalIgnoreCase) >= 0 || poc.Equals("ZZNOK", StringComparison.OrdinalIgnoreCase)) + { + reader.SetConfirmation(Properties.Settings.Default.ConfirmationDE); + poc = "ZZNOK"; + isTransit = true; + } + else + { + // Im Sheet könnte der Name statt des LOCODES stehen! + if (!RuleEngine.IsGermanLocode(poc)) + { + string aGermanPortName = poc; + + if(poc.Contains(',')) // irgendwas wie "Hamburg, Germany" + { + aGermanPortName = poc.Split(',')[0]; + } + + if (RuleEngine.IsGermanLocode(aGermanPortName)) + { + poc = aGermanPortName; + } + else + { + // somehow lookup LOCODE from the port's name! + poc = LocodeDB.LocodeGERFromCity(aGermanPortName); + } + + // okay, könnte DK Locode etc sein.. + if(poc == null) + { + if(aGermanPortName?.Length == 5) // possible locode? + { + if (LocodeDB.PortNameFromLocode(aGermanPortName) != null) + poc = aGermanPortName; + } + } + + if(poc == null) + { + List locodes = LocodeDB.AllLocodesForCityName(aGermanPortName); + if (locodes.Count > 0) + poc = locodes[0]; + } + + } + + if (poc != null) + { + poc = poc.ToUpper(); + + // setup returning confirmation sheets according to PoC + if (poc.Substring(0, 2) == "DK") + reader.SetConfirmation(Properties.Settings.Default.ConfirmationDK); + else + reader.SetConfirmation(Properties.Settings.Default.ConfirmationDE); + } + else + { + message = "invalid PoC"; + return null; + } + } + + imo = reader.ReadText("Visit.IMONumber"); + reader.Conf.ConfirmText("Visit.IMONumber", imo, imo.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + if ((imo.Length > 0) && !bsmd.database.Util.IsIMOValid(imo)) + reader.Conf.ConfirmText("Visit.IMONumber", imo, ExcelReader.ReadState.WARN); + + // ETA + if (poc != null) + eta = reader.ReadDateTime("NOA_NOD.ETADateToPortOfCall", "NOA_NOD.ETATimeToPortOfCall"); + + if ((imo != null) && (eta.HasValue) && (poc != null)) + { + result = DBManager.Instance.GetMessageCoreByShipInfos(imo, eta.Value, poc); + if(result != null) + { + _log.InfoFormat("Core [{3}] found for IMO {0}, ETA {1}, Poc {2}", imo, eta, poc, result.Id); + result.HerbergReportType = reader.ReadText("ReferenceNumber"); + reader.Conf.ConfirmText("ReferenceNumber", result.HerbergReportType, result.HerbergReportType.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + // Spezialfall: Wenn ein Core gefunden wird, dieser jedoch eine andere Visit/Transit Id hat als die Anmeldung ist das eine Neuanlage! + // Eingebaut 17.11.17 + if(!visitTransitId.IsNullOrEmpty() && !result.DisplayId.IsNullOrEmpty() && + (visitTransitId != result.DisplayId)) + { + _log.WarnFormat("Different visit ID ({0} (Sheet) {1} (Core) for the same decl. treating as NEW!", visitTransitId, result.DisplayId); + result = null; + } + + } + } + + reader.Conf.ConfirmText("Visit.PortOfCall", poc, ExcelReader.ReadState.OK); + reader.Conf.ConfirmText("Visit.PortOfCall_DK", poc, ExcelReader.ReadState.OK); + } + + else + { + message = string.Format("Port of call missing or not found for IMO {0}", imo); + return null; + } + } + + bool isValidId = bsmd.database.Util.IsVisitId(visitTransitId) ||bsmd.database.Util.IsTransitId(visitTransitId); + reader.Conf.ConfirmText("ID", visitTransitId, isValidId ? ExcelReader.ReadState.OK : ExcelReader.ReadState.FAIL); + + if (result == null) + { + if (imo == null) + { + message = "IMO number missing or not found"; + return null; + } + + if(poc == null) + { + message = string.Format("Port of call missing or not found for IMO {0}", imo); + return null; + } + + if(eta == null) + { + message = string.Format("ETA missing or not found for IMO {0}", imo); + return null; + } + + // neuen MessageCore erzeugen + result = new MessageCore(); + + result.Incoming = true; + result.HerbergFormGuid = Guid.Empty; + result.IMO = imo; + result.IsTransit = isTransit; + result.ReportStatus = MessageCore.ReportStatusEnum.NONE; // Bestätigungs-Sheet reicht als Report, keine separate Generierung + result.BSMDStatusInternal = MessageCore.BSMDStatus.PREPARE; + result.PoC = poc; + result.Portname = LocodeDB.PortNameFromLocode(poc); + + result.HerbergEmailContactReportingVessel = reader.ReadText("ShipMail"); + result.HerbergReportType = reader.ReadText("ReferenceNumber"); + reader.Conf.ConfirmText("ReferenceNumber", result.HerbergReportType, result.HerbergReportType.IsNullOrEmpty() ? ExcelReader.ReadState.FAIL : ExcelReader.ReadState.OK); + + if (result.IsTransit) + result.ETAKielCanal = eta; + else + result.ETA = eta; + + if (result.IMO.Length > 7) + { + _log.WarnFormat("IMO {0} is longer than 7 chars, truncating!", result.IMO); + result.IMO = result.IMO.Substring(0, 7); + } + + if((result.IMO.Length == 7) && !bsmd.database.Util.IsIMOValid(result.IMO)) + { + _log.WarnFormat("IMO {0} possibly invalid (checksum number violation)", result.IMO); + } + + if(visitTransitId != null) + { + if (bsmd.database.Util.IsTransitId(visitTransitId)) + result.TransitId = visitTransitId; + else + result.VisitId = visitTransitId; + } + + DBManager.Instance.Save(result); + // Meldeklassen erzeugen um doppelte Generierung über ENI-2 zu vermeiden + bsmd.database.Util.CreateMessagesForCore(result, new List(), null); + + } + + return result; + } + + #endregion + + #region GetMessageWithType + + private static Message GetMessageWithType(List messages, MessageCore core, Message.NotificationClass type) + { + foreach(Message message in messages) + if (message.MessageNotificationClass == type) return message; + + Message newMessage = DBManager.Instance.GetMessage(core, type); + if (newMessage == null) + { + newMessage = new Message(); + newMessage.MessageNotificationClass = type; + messages.Add(newMessage); + newMessage.MessageCore = core; + newMessage.MessageCoreId = core.Id; + } + return newMessage; + } + + #endregion + + } +} diff --git a/bsmd.ExcelReadService/LocodeDB.cs b/bsmd.ExcelReadService/LocodeDB.cs index 25a1d30b..43b23ed8 100644 --- a/bsmd.ExcelReadService/LocodeDB.cs +++ b/bsmd.ExcelReadService/LocodeDB.cs @@ -14,7 +14,7 @@ using System.Data.SQLite; using bsmd.database; using log4net; -namespace bsmd.ExcelReadService +namespace ENI2.Locode { /// /// Locodes suchen (zu Orten), die DB ist aus einem github Projekt: