diff --git a/SDL/My Project/Resources.Designer.vb b/SDL/My Project/Resources.Designer.vb index 47ca005d..9e3c7974 100644 --- a/SDL/My Project/Resources.Designer.vb +++ b/SDL/My Project/Resources.Designer.vb @@ -2631,6 +2631,16 @@ Namespace My.Resources End Get End Property + ''' + ''' Sucht eine lokalisierte Ressource vom Typ System.Byte[]. + ''' + Friend ReadOnly Property VERAG_CBAM_Report_Template() As Byte() + Get + Dim obj As Object = ResourceManager.GetObject("VERAG_CBAM_Report_Template", resourceCulture) + Return CType(obj,Byte()) + End Get + End Property + ''' ''' Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. ''' diff --git a/SDL/My Project/Resources.resx b/SDL/My Project/Resources.resx index 69d73ef2..4593efdf 100644 --- a/SDL/My Project/Resources.resx +++ b/SDL/My Project/Resources.resx @@ -973,4 +973,7 @@ ..\Resources\ambar_boarder_new.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\VERAG_CBAM_Report_Template.xlsx;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/SDL/Resources/VERAG_CBAM_Report_Template.xlsx b/SDL/Resources/VERAG_CBAM_Report_Template.xlsx new file mode 100644 index 00000000..dd6f3fa1 Binary files /dev/null and b/SDL/Resources/VERAG_CBAM_Report_Template.xlsx differ diff --git a/SDL/SDL.vbproj b/SDL/SDL.vbproj index aacb56cb..6caa65ef 100644 --- a/SDL/SDL.vbproj +++ b/SDL/SDL.vbproj @@ -4987,6 +4987,7 @@ + Always diff --git a/SDL/kunden/usrCntlCBAM.vb b/SDL/kunden/usrCntlCBAM.vb index 7c1524fe..38d64056 100644 --- a/SDL/kunden/usrCntlCBAM.vb +++ b/SDL/kunden/usrCntlCBAM.vb @@ -2249,7 +2249,8 @@ Public Class usrCntlCBAM doVERAG_SUM(LIST, EORI(0)) - doVERAG_DETAIL(LIST, EORI(0)) + doVERAG_DETAIL_OLD(LIST, EORI(0)) + 'doVERAG_DETAIL(LIST, EORI(0)) If cbxVERAG_GPXLS.Checked Then doVERAG_GREENPULSE_XLS(LIST, EORI(0)) @@ -2410,7 +2411,342 @@ Public Class usrCntlCBAM End Try End Sub - Sub doVERAG_DETAIL(LIST As List(Of VERAG_PROG_ALLGEMEIN.cVERAG_CustomsDeclarations), EORI As String) + Public Sub doVERAG_DETAIL(LIST As List(Of VERAG_PROG_ALLGEMEIN.cVERAG_CustomsDeclarations), EORI As String) + + btnCBAM_DS_VERAG_Detail.Enabled = False + btnCBAM_DS_VERAG_Detail.Tag = "" + + Try + + ' ========================================================= + ' Daten holen + ' ========================================================= + Dim details = + From za In LIST + From it In za.Items + Let importer = za.Parties. + FirstOrDefault(Function(p) cVERAG_CustomsDeclarations.IMPORTER_ROLES.Contains(p.zaParty_Role)) + Let exporter = za.Parties. + FirstOrDefault(Function(p) cVERAG_CustomsDeclarations.EXPORTER_ROLES.Contains(p.zaParty_Role)) + Let declarant = za.Parties. + FirstOrDefault(Function(p) cVERAG_CustomsDeclarations.DECLARANT_ROLES.Contains(p.zaParty_Role)) + Let cbamDeclarantTmp = za.Parties. + FirstOrDefault(Function(p) p.zaParty_Role = "CBAM") + Let cbamDeclarant = If(cbamDeclarantTmp, declarant) + Let invoice = + it.Documents.FirstOrDefault(Function(d) d.zaDoc_Code = "N380" OrElse d.zaDoc_Code = "N325") + Let anmeldedatum = If(za.za_ReleaseDate, za.za_DeclarationDate) + Order By anmeldedatum + Select New With { + .MRN = If(za.za_MRN, ""), + .SendungsId = za.za_SendungsId, + .PositionsNummer = it.zaItem_PosNo, + .Anmeldedatum = anmeldedatum, + .BezugsNr = If(za.za_LRN, ""), + .VertretungsVerhaeltnis = If(za.za_RepresentationCode, ""), + .Tarifnummer = If(LeftStr(it.zaItem_HSCode, 8), ""), + .Eigenmasse = it.zaItem_NetMass, + .Rohmasse = it.zaItem_GrossMass, + .Ursprungsland = If(it.zaItem_OriginCountry, ""), + .VersendungsLand = If(za.za_CountryDispatch, ""), + .BestimmungsLand = If(za.za_CountryDestination, ""), + .Rechnungspreis = If(it.zaItem_InvoiceValueEUR, it.zaItem_StatisticalValueEUR), + .Rechnungswaehrung = If(it.zaItem_InvoiceCurrency, ""), + .EmpfaengerEORI = If(importer IsNot Nothing, If(importer.zaParty_EORI, ""), ""), + .Empfaenger = If(importer IsNot Nothing, If(importer.zaParty_Name, ""), ""), + .AbsenderEORI = If(exporter IsNot Nothing, If(exporter.zaParty_EORI, ""), ""), + .Absender = If(exporter IsNot Nothing, If(exporter.zaParty_Name, ""), ""), + .DeclarantEORI = If(declarant IsNot Nothing, If(declarant.zaParty_EORI, ""), ""), + .DeclarantName = If(declarant IsNot Nothing, If(declarant.zaParty_Name, ""), ""), + .CBAMDeclarantEORI = If(cbamDeclarant IsNot Nothing, If(cbamDeclarant.zaParty_EORI, ""), ""), + .CBAMDeclarantName = If(cbamDeclarant IsNot Nothing, If(cbamDeclarant.zaParty_Name, ""), ""), + .Rechnungsnummer = If(invoice IsNot Nothing, If(invoice.zaDoc_Reference, ""), ""), + .Rechnungsdatum = If(invoice IsNot Nothing, ParseDateSafe(invoice.zaDoc_Date), Nothing), + .RequestedProcedure = If(za.za_MainProcedure, ""), + .PreviousProcedure = If(it.zaItem_PrevProcedure, ""), + .MeasurementUnit = If(it.zaItem_SuppUnitCode, "") + } + + ' ========================================================= + ' DataTable exakt nach Excel-Template + ' ========================================================= + Dim dt As New DataTable + + dt.Columns.Add("MRN") + dt.Columns.Add("position_no") + dt.Columns.Add("declaration_date") + dt.Columns.Add("reference_no") + dt.Columns.Add("customer_reference") + dt.Columns.Add("representation_type") + dt.Columns.Add("tariff_code") + dt.Columns.Add("net_mass_kg") + dt.Columns.Add("gross_mass_kg") + dt.Columns.Add("origin_country") + dt.Columns.Add("dispatch_country") + dt.Columns.Add("destination_country") + dt.Columns.Add("invoice_number") + dt.Columns.Add("invoice_date") + dt.Columns.Add("invoice_amount") + dt.Columns.Add("invoice_currency") + dt.Columns.Add("sender_eori") + dt.Columns.Add("sender_name") + dt.Columns.Add("sender_address") + dt.Columns.Add("sender_country") + dt.Columns.Add("recipient_eori") + dt.Columns.Add("recipient_name") + dt.Columns.Add("recipient_address") + dt.Columns.Add("recipient_country") + dt.Columns.Add("importer_eori") + dt.Columns.Add("importer_name") + dt.Columns.Add("importer_address") + dt.Columns.Add("importer_country") + dt.Columns.Add("importer_email") + dt.Columns.Add("importer_phone") + dt.Columns.Add("declarant_eori") + dt.Columns.Add("declarant_name") + dt.Columns.Add("declarant_address") + dt.Columns.Add("declarant_country") + dt.Columns.Add("requested_procedure") + dt.Columns.Add("previous_procedure") + dt.Columns.Add("measurement_unit") + dt.Columns.Add("member_state_authorisation") + dt.Columns.Add("discharge_bill_waiver") + dt.Columns.Add("authorisation") + dt.Columns.Add("inward_processing_start") + dt.Columns.Add("inward_processing_end") + dt.Columns.Add("inward_processing_deadline") + dt.Columns.Add("Benchmark (Default)") + dt.Columns.Add("Emission (Default)") + dt.Columns.Add("Factor") + dt.Columns.Add("Estimated Cost") + + ' ========================================================= + ' Befüllen + ' ========================================================= + For Each r In details + + Dim KdAtrNr As String = "" + + If cbxKdAtrNr.Checked AndAlso r.SendungsId IsNot Nothing Then + Dim Snd = New VERAG_PROG_ALLGEMEIN.cSendungen(r.SendungsId) + If Snd IsNot Nothing Then + KdAtrNr = Snd.getKdAtrNr("AUFTRAGGEBER") + If KdAtrNr = "" Then + KdAtrNr = Snd.getKdAtrNr("EMPFAENGER") + End If + End If + + If EORI = "DE4991397" AndAlso KdAtrNr.Contains("/") Then + KdAtrNr = KdAtrNr.Split("/"c)(0) + End If + End If + + Dim benchmark As Object = Nothing + Dim emission As Object = Nothing + Dim faktor As Object = Nothing + Dim weight = r.Eigenmasse + Dim year = If(txtBis._value <> "", CDate(txtBis._value).Year, Now.Year) + Dim cost As String = "0" + + If cbxKosten.Checked Then + Dim benchmarkObj As Object = Nothing + Dim emissionObj As Object = Nothing + Dim faktorObj As Object = Nothing + Dim costObj As String = "0" + + ' Dim weight = 0D + If IsNumeric(r.Eigenmasse) Then weight = CDbl(r.Eigenmasse) + + 'Dim year = If(txtBis._value <> "", CDate(txtBis._value).Year, Now.Year) + + If IsNumeric(txtVERA_ZertPreis._value) Then + cATEZ_Greenpulse_CBAM_CostCalculation.calcCBAM_ByCertificatePrice( + cn_code:=Convert.ToString(r.Tarifnummer), + weight:=weight / 1000, + country_code:=Convert.ToString(r.Ursprungsland), + certificate_price:=CDbl(txtVERA_ZertPreis._value), + year:=year, + costObj, + emissionObj, + benchmarkObj, + faktorObj + ) + Else + cATEZ_Greenpulse_CBAM_CostCalculation.calcCBAM( + cn_code:=Convert.ToString(r.Tarifnummer), + weight:=weight / 1000, + country_code:=Convert.ToString(r.Ursprungsland), + Nothing, + year:=year, + Nothing, + costObj, + emissionObj, + benchmarkObj, + faktorObj + ) + End If + + benchmark = If(benchmarkObj Is Nothing, "", Convert.ToString(benchmarkObj)) + emission = If(emissionObj Is Nothing, "", Convert.ToString(emissionObj)) + faktor = If(faktorObj Is Nothing, "", Convert.ToString(faktorObj)) + + If IsNumeric(costObj) Then + If CDbl(costObj) >= 0 Then + cost = Convert.ToString(costObj) + Else + cost = "" + End If + Else + cost = "" + End If + End If + + Dim row = dt.NewRow() + + row("MRN") = If(r.MRN, "") + row("position_no") = r.PositionsNummer + row("declaration_date") = If(r.Anmeldedatum Is Nothing, "", CDate(r.Anmeldedatum).ToString("yyyy-MM-dd")) + row("reference_no") = If(r.BezugsNr, "") + row("customer_reference") = If(KdAtrNr, "") + row("representation_type") = If(r.VertretungsVerhaeltnis, "") + row("tariff_code") = If(r.Tarifnummer, "") + row("net_mass_kg") = If(r.Eigenmasse Is Nothing, "", Convert.ToString(r.Eigenmasse)) + row("gross_mass_kg") = If(r.Rohmasse Is Nothing, "", Convert.ToString(r.Rohmasse)) + row("origin_country") = If(r.Ursprungsland, "") + row("dispatch_country") = If(r.VersendungsLand, "") + row("destination_country") = If(r.BestimmungsLand, "") + + row("invoice_number") = If(r.Rechnungsnummer, "") + row("invoice_date") = If(r.Rechnungsdatum Is Nothing, "", CDate(r.Rechnungsdatum).ToString("yyyy-MM-dd")) + row("invoice_amount") = If(r.Rechnungspreis Is Nothing, "", Convert.ToString(r.Rechnungspreis)) + row("invoice_currency") = If(r.Rechnungswaehrung, "") + + row("sender_eori") = If(r.AbsenderEORI, "") + row("sender_name") = If(r.Absender, "") + row("sender_address") = "" + row("sender_country") = "" + + row("recipient_eori") = If(r.EmpfaengerEORI, "") + row("recipient_name") = If(r.Empfaenger, "") + row("recipient_address") = "" + row("recipient_country") = "" + + row("importer_eori") = If(r.EmpfaengerEORI, "") + row("importer_name") = If(r.Empfaenger, "") + row("importer_address") = "" + row("importer_country") = "" + row("importer_email") = "" + row("importer_phone") = "" + + row("declarant_eori") = If(r.DeclarantEORI, "") + row("declarant_name") = If(r.DeclarantName, "") + row("declarant_address") = "" + row("declarant_country") = "" + + row("requested_procedure") = If(r.RequestedProcedure, "") + row("previous_procedure") = If(r.PreviousProcedure, "") + row("measurement_unit") = If(r.MeasurementUnit, "") + row("member_state_authorisation") = "" + row("discharge_bill_waiver") = "" + row("authorisation") = "" + row("inward_processing_start") = "" + row("inward_processing_end") = "" + row("inward_processing_deadline") = "" + + row("Benchmark (Default)") = benchmark + row("Emission (Default)") = emission + row("Factor") = faktor + row("Estimated Cost") = cost + + dt.Rows.Add(row) + + Next + + ' ========================================================= + ' Datei vorbereiten + ' ========================================================= + Dim Path_DETAIL As String = "" + Dim sPath As String = Environment.GetFolderPath(Environment.SpecialFolder.Personal) & "\VERAG\CBAM_REPORT_DETAIL\" + + If Not My.Computer.FileSystem.DirectoryExists(sPath) Then + My.Computer.FileSystem.CreateDirectory(sPath) + End If + + Path_DETAIL = sPath & EORI & "_CBAM_Detail_" & txtVon._value & "-" & txtBis._value & ".xlsx" + While System.IO.File.Exists(Path_DETAIL) + Path_DETAIL = sPath & EORI & "_CBAM_Detail_" & txtVon._value & "-" & txtBis._value & "_" & Now.ToString("ddMMyyyyHHmmss") & ".xlsx" + End While + + My.Computer.FileSystem.WriteAllBytes(Path_DETAIL, My.Resources.VERAG_CBAM_Report_Template, False) + + ' ========================================================= + ' Excel schreiben + ' ========================================================= + Dim wb = New ClosedXML.Excel.XLWorkbook(Path_DETAIL) + Dim ws = wb.Worksheet("CBAM_Report") + + ' Header + ws.Cell("A3").Value = txtVon._value + ws.Cell("C3").Value = txtBis._value + + ' CBAM Declarant + ws.Cell("A6").Value = "VERAG" + ws.Cell("B6").Value = "" + ws.Cell("C6").Value = "" + ws.Cell("D6").Value = "" + ws.Cell("E6").Value = "" + ws.Cell("F6").Value = EORI + + ' Declarant + ws.Cell("A8").Value = "VERAG" + ws.Cell("B8").Value = "" + ws.Cell("C8").Value = "" + ws.Cell("D8").Value = "" + ws.Cell("E8").Value = "" + ws.Cell("F8").Value = EORI + + ' Importer (Default) - aus Parameter / erster Datensatz + Dim firstImporterName As String = "" + If dt.Rows.Count > 0 Then + firstImporterName = Convert.ToString(dt.Rows(0)("importer_name")) + End If + + ws.Cell("A10").Value = firstImporterName + ws.Cell("B10").Value = "" + ws.Cell("C10").Value = "" + ws.Cell("D10").Value = "" + ws.Cell("E10").Value = "" + ws.Cell("F10").Value = EORI + + ' Alte Detaildatenbereich-Inhalte leeren + Dim startRow As Integer = 14 + 'For r As Integer = startRow To Math.max(ws.LastRowUsed().RowNumber(), startRow + 5000) + ' For c As Integer = 1 To 47 + ' ws.Cell(r, c).Clear(XLCellClearOptions.Contents) + ' Next + 'Next + + ' Detaildaten schreiben + For i As Integer = 0 To dt.Rows.Count - 1 + For j As Integer = 0 To dt.Columns.Count - 1 + ws.Cell(startRow + i, j + 1).Value = If(dt.Rows(i)(j), "") + Next + Next + + wb.SaveAs(Path_DETAIL) + + If dt.Rows.Count > 0 Then + btnCBAM_DS_VERAG_Detail.Tag = Path_DETAIL + btnCBAM_DS_VERAG_Detail.Enabled = True + btnCBAM_DS_VERAG_Copy.Enabled = True + End If + + Catch ex As Exception + VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR(ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name) + End Try + + End Sub + Sub doVERAG_DETAIL_OLD(LIST As List(Of VERAG_PROG_ALLGEMEIN.cVERAG_CustomsDeclarations), EORI As String) btnCBAM_DS_VERAG_Detail.Enabled = False btnCBAM_DS_VERAG_Detail.Tag = "" diff --git a/VERAG_PROG_ALLGEMEIN/VERAG_PROG_ALLGEMEIN.vbproj b/VERAG_PROG_ALLGEMEIN/VERAG_PROG_ALLGEMEIN.vbproj index 7145d084..18e1309a 100644 --- a/VERAG_PROG_ALLGEMEIN/VERAG_PROG_ALLGEMEIN.vbproj +++ b/VERAG_PROG_ALLGEMEIN/VERAG_PROG_ALLGEMEIN.vbproj @@ -762,7 +762,8 @@ True Reference.svcmap - + + True True diff --git a/VERAG_PROG_ALLGEMEIN/VERAG_Zollanmeldung/cVERAG_Zollanmeldung.vb b/VERAG_PROG_ALLGEMEIN/VERAG_Zollanmeldung/cVERAG_CustomsDeclarations.vb similarity index 100% rename from VERAG_PROG_ALLGEMEIN/VERAG_Zollanmeldung/cVERAG_Zollanmeldung.vb rename to VERAG_PROG_ALLGEMEIN/VERAG_Zollanmeldung/cVERAG_CustomsDeclarations.vb diff --git a/VERAG_PROG_ALLGEMEIN/VERAG_Zollanmeldung/cVERAG_CustomsDeclarations_Convert.vb b/VERAG_PROG_ALLGEMEIN/VERAG_Zollanmeldung/cVERAG_CustomsDeclarations_Convert.vb new file mode 100644 index 00000000..dc33680f --- /dev/null +++ b/VERAG_PROG_ALLGEMEIN/VERAG_Zollanmeldung/cVERAG_CustomsDeclarations_Convert.vb @@ -0,0 +1,615 @@ +Imports ClosedXML.Excel +Imports System.Globalization +Imports System.IO +Imports System.Linq + +Public Class cVERAG_CustomsDeclarations_Convert + + Public Const EXPECTED_TEMPLATE_VERSION As String = "CBAM-2026-V1.0" + + Public Shared Function LOAD_FROM_CBAM_DETAIL_EXCEL(filePath As String, + Optional ByRef errors As List(Of String) = Nothing, + Optional stopOnFirstInvalidRow As Boolean = False) As List(Of cVERAG_CustomsDeclarations) + + Dim result As New List(Of cVERAG_CustomsDeclarations) + + Try + If errors Is Nothing Then errors = New List(Of String) + + If String.IsNullOrWhiteSpace(filePath) Then + errors.Add("Es wurde kein Dateipfad übergeben.") + Return result + End If + + If Not File.Exists(filePath) Then + errors.Add("Datei nicht gefunden: " & filePath) + Return result + End If + + Using wb As New XLWorkbook(filePath) + + Dim ws As IXLWorksheet = Nothing + + If wb.Worksheets.Any(Function(x) x.Name.Trim().ToUpper() = "CBAM_REPORT") Then + ws = wb.Worksheet("CBAM_Report") + Else + ws = wb.Worksheet(1) + End If + + If ws Is Nothing Then + errors.Add("Kein Worksheet gefunden.") + Return result + End If + + ' ========================================================= + ' Template-Version prüfen + ' ========================================================= + Dim versionInFile As String = TrimSafe(ws.Cell("F3").GetString()) + + If Not String.Equals(versionInFile, EXPECTED_TEMPLATE_VERSION, StringComparison.OrdinalIgnoreCase) Then + errors.Add("Ungültige Template-Version in F3. Erwartet: '" & EXPECTED_TEMPLATE_VERSION & "', gefunden: '" & versionInFile & "'") + Return result + End If + + Dim headerRow As Integer = 13 + Dim dataStartRow As Integer = 14 + + Dim lastRow = If(ws.LastRowUsed() Is Nothing, 0, ws.LastRowUsed().RowNumber()) + Dim lastCol = If(ws.LastColumnUsed() Is Nothing, 0, ws.LastColumnUsed().ColumnNumber()) + + If lastRow < dataStartRow OrElse lastCol = 0 Then + errors.Add("Keine Positionsdaten gefunden.") + Return result + End If + + ' ========================================================= + ' Header-Mapping aufbauen + ' ========================================================= + Dim colMap As New Dictionary(Of String, Integer)(StringComparer.OrdinalIgnoreCase) + + For c As Integer = 1 To lastCol + Dim h = TrimSafe(ws.Cell(headerRow, c).GetString()) + If h <> "" AndAlso Not colMap.ContainsKey(h) Then + colMap.Add(h, c) + End If + Next + + ' ========================================================= + ' Pflichtspalten im Excel prüfen + ' ========================================================= + Dim requiredHeaders = New String() {"MRN", "declaration_date", "tariff_code"} + + For Each req In requiredHeaders + If Not colMap.ContainsKey(req) Then + errors.Add("Pflichtspalte im Excel nicht gefunden: " & req) + End If + Next + + If errors.Any(Function(x) x.StartsWith("Pflichtspalte im Excel nicht gefunden:")) Then + Return result + End If + + ' ========================================================= + ' Bereits vorhandene / ungültige MRN verwalten + ' ========================================================= + Dim skippedExistingMrns As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase) + Dim invalidMrns As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase) + Dim dict As New Dictionary(Of String, cVERAG_CustomsDeclarations)(StringComparer.OrdinalIgnoreCase) + Dim artificialCounter As Integer = 0 + + For r As Integer = dataStartRow To lastRow + + Dim mrn As String = GetCellString(ws, r, colMap, "MRN") + Dim referenceNo As String = GetCellString(ws, r, colMap, "reference_no") + Dim tariffCode As String = GetCellString(ws, r, colMap, "tariff_code") + Dim itemNoTxt As String = GetCellString(ws, r, colMap, "position_no") + + ' Komplette Leerzeile überspringen + If mrn = "" AndAlso referenceNo = "" AndAlso tariffCode = "" AndAlso itemNoTxt = "" Then + Continue For + End If + + ' ===================================================== + ' Zeilenvalidierung + ' ===================================================== + Dim validationMessage As String = "" + If Not ValidateImportRow(ws, r, colMap, validationMessage) Then + errors.Add(validationMessage) + + If mrn <> "" Then + invalidMrns.Add(mrn) + End If + + If stopOnFirstInvalidRow Then + Return result + End If + + Continue For + End If + + ' Wenn MRN bereits als ungültig markiert wurde -> überspringen + If mrn <> "" AndAlso invalidMrns.Contains(mrn) Then + Continue For + End If + + ' ===================================================== + ' MRN bereits in DB? + ' Dann komplette Anmeldung überspringen + ' ===================================================== + If mrn <> "" Then + If skippedExistingMrns.Contains(mrn) Then + Continue For + End If + + If MRN_EXISTS_IN_DB(mrn) Then + skippedExistingMrns.Add(mrn) + errors.Add("MRN bereits vorhanden - Import übersprungen: " & mrn & " (Zeile " & r & ")") + Continue For + End If + End If + + ' ===================================================== + ' Gruppenschlüssel + ' ===================================================== + Dim grpKey As String = "" + If mrn <> "" Then + grpKey = "MRN|" & mrn + ElseIf referenceNo <> "" Then + grpKey = "REF|" & referenceNo + Else + artificialCounter += 1 + grpKey = "AUTO|" & artificialCounter.ToString() + End If + + Dim za As cVERAG_CustomsDeclarations = Nothing + + If Not dict.ContainsKey(grpKey) Then + + za = New cVERAG_CustomsDeclarations() + + za.za_MRN = mrn + za.za_LRN = referenceNo + za.za_ReferenceCustomer = GetCellString(ws, r, colMap, "customer_reference") + za.za_RepresentationCode = GetCellString(ws, r, colMap, "representation_type") + za.za_DeclarationDate = GetCellDateNullable(ws, r, colMap, "declaration_date") + za.za_ReleaseDate = GetCellDateNullable(ws, r, colMap, "declaration_date") + + za.za_CountryDispatch = GetCellString(ws, r, colMap, "dispatch_country") + za.za_CountryDestination = GetCellString(ws, r, colMap, "destination_country") + za.za_CountryImport = GetCellString(ws, r, colMap, "destination_country") + + za.za_MainProcedure = GetCellString(ws, r, colMap, "requested_procedure") + za.za_InvoiceCurrency = GetCellString(ws, r, colMap, "invoice_currency") + za.za_InvoiceAmount = GetCellDecimalNullable(ws, r, colMap, "invoice_amount") + za.za_IsFinalDeclaration = True + za.za_REGIME = "IMPORT" + + za.za_System = "CBAM_EXCEL_IMPORT" + za.za_CustomsSystem = "" + za.za_CustomsSystemCountry = "" + za.za_IsExternalSystem = True + za.za_Firma = "" + za.za_Niederlassung = "" + za.za_AdditionalProcedure = "" + za.za_WarehouseCode = "" + za.za_Incoterms = "" + za.za_IncotermsPlace = "" + za.za_TotGrossMass = Nothing + + AddOrMergeParty(za.Parties, CreateParty( + role:="EXPORTER", + eori:=GetCellString(ws, r, colMap, "sender_eori"), + name:=GetCellString(ws, r, colMap, "sender_name"), + street:=GetCellString(ws, r, colMap, "sender_address"), + postalCode:="", + city:="", + country:=GetCellString(ws, r, colMap, "sender_country"), + email:="", + phone:="" + )) + + AddOrMergeParty(za.Parties, CreateParty( + role:="CONSIGNEE", + eori:=GetCellString(ws, r, colMap, "recipient_eori"), + name:=GetCellString(ws, r, colMap, "recipient_name"), + street:=GetCellString(ws, r, colMap, "recipient_address"), + postalCode:="", + city:="", + country:=GetCellString(ws, r, colMap, "recipient_country"), + email:="", + phone:="" + )) + + AddOrMergeParty(za.Parties, CreateParty( + role:="IMPORTER", + eori:=GetCellString(ws, r, colMap, "importer_eori"), + name:=GetCellString(ws, r, colMap, "importer_name"), + street:=GetCellString(ws, r, colMap, "importer_address"), + postalCode:="", + city:="", + country:=GetCellString(ws, r, colMap, "importer_country"), + email:=GetCellString(ws, r, colMap, "importer_email"), + phone:=GetCellString(ws, r, colMap, "importer_phone") + )) + + AddOrMergeParty(za.Parties, CreateParty( + role:="DECLARANT", + eori:=GetCellString(ws, r, colMap, "declarant_eori"), + name:=GetCellString(ws, r, colMap, "declarant_name"), + street:=GetCellString(ws, r, colMap, "declarant_address"), + postalCode:="", + city:="", + country:=GetCellString(ws, r, colMap, "declarant_country"), + email:="", + phone:="" + )) + + Dim invNo = GetCellString(ws, r, colMap, "invoice_number") + Dim invDate = GetCellString(ws, r, colMap, "invoice_date") + + If invNo <> "" OrElse invDate <> "" Then + za.Documents.Add(New cVERAG_CustomsDeclarations_Document With { + .zaDoc_Code = "N380", + .zaDoc_Reference = invNo, + .zaDoc_Date = invDate, + .zaDoc_Description = "Invoice" + }) + End If + + dict.Add(grpKey, za) + + Else + za = dict(grpKey) + + AddOrMergeParty(za.Parties, CreateParty( + role:="EXPORTER", + eori:=GetCellString(ws, r, colMap, "sender_eori"), + name:=GetCellString(ws, r, colMap, "sender_name"), + street:=GetCellString(ws, r, colMap, "sender_address"), + postalCode:="", + city:="", + country:=GetCellString(ws, r, colMap, "sender_country"), + email:="", + phone:="" + )) + + AddOrMergeParty(za.Parties, CreateParty( + role:="CONSIGNEE", + eori:=GetCellString(ws, r, colMap, "recipient_eori"), + name:=GetCellString(ws, r, colMap, "recipient_name"), + street:=GetCellString(ws, r, colMap, "recipient_address"), + postalCode:="", + city:="", + country:=GetCellString(ws, r, colMap, "recipient_country"), + email:="", + phone:="" + )) + + AddOrMergeParty(za.Parties, CreateParty( + role:="IMPORTER", + eori:=GetCellString(ws, r, colMap, "importer_eori"), + name:=GetCellString(ws, r, colMap, "importer_name"), + street:=GetCellString(ws, r, colMap, "importer_address"), + postalCode:="", + city:="", + country:=GetCellString(ws, r, colMap, "importer_country"), + email:=GetCellString(ws, r, colMap, "importer_email"), + phone:=GetCellString(ws, r, colMap, "importer_phone") + )) + + AddOrMergeParty(za.Parties, CreateParty( + role:="DECLARANT", + eori:=GetCellString(ws, r, colMap, "declarant_eori"), + name:=GetCellString(ws, r, colMap, "declarant_name"), + street:=GetCellString(ws, r, colMap, "declarant_address"), + postalCode:="", + city:="", + country:=GetCellString(ws, r, colMap, "declarant_country"), + email:="", + phone:="" + )) + End If + + Dim it As New cVERAG_CustomsDeclarations_Item() + + it.zaItem_PosNo = GetCellInt(ws, r, colMap, "position_no", za.Items.Count + 1) + it.zaItem_HSCode = GetCellString(ws, r, colMap, "tariff_code") + it.zaItem_OriginCountry = GetCellString(ws, r, colMap, "origin_country") + it.zaItem_GrossMass = GetCellDecimalNullable(ws, r, colMap, "gross_mass_kg") + it.zaItem_NetMass = GetCellDecimalNullable(ws, r, colMap, "net_mass_kg") + it.zaItem_SuppUnitCode = GetCellString(ws, r, colMap, "measurement_unit") + it.zaItem_PrevProcedure = GetCellString(ws, r, colMap, "previous_procedure") + it.zaItem_MainProcedure = GetCellString(ws, r, colMap, "requested_procedure") + it.zaItem_InvoiceValueEUR = GetCellDecimalNullable(ws, r, colMap, "invoice_amount") + it.zaItem_InvoiceCurrency = GetCellString(ws, r, colMap, "invoice_currency") + it.zaItem_StatisticalValueEUR = GetCellDecimalNullable(ws, r, colMap, "invoice_amount") + + Dim remarks As String = "" + Dim bench = GetCellString(ws, r, colMap, "Benchmark (Default)") + Dim emi = GetCellString(ws, r, colMap, "Emission (Default)") + Dim fac = GetCellString(ws, r, colMap, "Factor") + Dim est = GetCellString(ws, r, colMap, "Estimated Cost") + + If bench <> "" OrElse emi <> "" OrElse fac <> "" OrElse est <> "" Then + remarks = + "CBAM Import | " & + "Benchmark=" & bench & "; " & + "Emission=" & emi & "; " & + "Factor=" & fac & "; " & + "EstimatedCost=" & est + End If + + it.zaItem_Remarks = remarks + + Dim itemInvNo = GetCellString(ws, r, colMap, "invoice_number") + Dim itemInvDate = GetCellString(ws, r, colMap, "invoice_date") + + If itemInvNo <> "" OrElse itemInvDate <> "" Then + it.Documents.Add(New cVERAG_CustomsDeclarations_Document With { + .zaDoc_Code = "N380", + .zaDoc_Reference = itemInvNo, + .zaDoc_Date = itemInvDate, + .zaDoc_Description = "Invoice" + }) + End If + + za.Items.Add(it) + + Next + + For Each za In dict.Values + If za.Items IsNot Nothing AndAlso za.Items.Count > 0 Then + za.za_TotGrossMass = za.Items.Sum(Function(x) If(x.zaItem_GrossMass, 0D)) + + If Not za.za_InvoiceAmount.HasValue Then + Dim invSum = za.Items.Sum(Function(x) If(x.zaItem_InvoiceValueEUR, 0D)) + If invSum <> 0D Then + za.za_InvoiceAmount = invSum + End If + End If + + result.Add(za) + End If + Next + + End Using + + Catch ex As Exception + VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR(ex.Message, ex.StackTrace, Reflection.MethodInfo.GetCurrentMethod.Name) + End Try + + Return result + + End Function + + Private Shared Function ValidateImportRow(ws As IXLWorksheet, + row As Integer, + colMap As Dictionary(Of String, Integer), + ByRef validationMessage As String) As Boolean + + validationMessage = "" + + Dim mrn As String = GetCellString(ws, row, colMap, "MRN") + Dim tariffCode As String = GetCellString(ws, row, colMap, "tariff_code") + Dim declarationDate As Date? = GetCellDateNullable(ws, row, colMap, "declaration_date") + + Dim missing As New List(Of String) + + If mrn = "" Then missing.Add("MRN") + If Not declarationDate.HasValue Then missing.Add("declaration_date") + If tariffCode = "" Then missing.Add("tariff_code") + + If missing.Count > 0 Then + validationMessage = "Zeile " & row & " ungültig. Pflichtfeld(er) fehlen oder sind ungültig: " & String.Join(", ", missing) + Return False + End If + + Return True + + End Function + + Private Shared Function MRN_EXISTS_IN_DB(mrn As String) As Boolean + + Try + mrn = TrimSafe(mrn) + If mrn = "" Then Return False + + Dim za = cVERAG_CustomsDeclarations.loadByMRN(mrn, False) + Return za IsNot Nothing AndAlso za.hasEntry + + Catch ex As Exception + VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR(ex.Message, ex.StackTrace, Reflection.MethodInfo.GetCurrentMethod.Name) + End Try + + Return False + + End Function + + Private Shared Function CreateParty(role As String, + eori As String, + name As String, + street As String, + postalCode As String, + city As String, + country As String, + email As String, + phone As String) As cVERAG_CustomsDeclarations_Parties + + If TrimSafe(eori) = "" AndAlso + TrimSafe(name) = "" AndAlso + TrimSafe(street) = "" AndAlso + TrimSafe(country) = "" AndAlso + TrimSafe(email) = "" AndAlso + TrimSafe(phone) = "" Then + Return Nothing + End If + + Return New cVERAG_CustomsDeclarations_Parties With { + .zaParty_Role = role, + .zaParty_EORI = TrimSafe(eori), + .zaParty_Name = TrimSafe(name), + .zaParty_Street = TrimSafe(street), + .zaParty_PostalCode = TrimSafe(postalCode), + .zaParty_City = TrimSafe(city), + .zaParty_Country = TrimSafe(country), + .zaParty_Email = TrimSafe(email), + .zaParty_Phone = TrimSafe(phone) + } + + End Function + + Private Shared Sub AddOrMergeParty(list As List(Of cVERAG_CustomsDeclarations_Parties), + p As cVERAG_CustomsDeclarations_Parties) + + If p Is Nothing Then Exit Sub + If list Is Nothing Then Exit Sub + + Dim existing = list.FirstOrDefault(Function(x) + Return String.Equals(TrimSafe(x.zaParty_Role), TrimSafe(p.zaParty_Role), StringComparison.OrdinalIgnoreCase) AndAlso + String.Equals(TrimSafe(x.zaParty_EORI), TrimSafe(p.zaParty_EORI), StringComparison.OrdinalIgnoreCase) AndAlso + String.Equals(TrimSafe(x.zaParty_Name), TrimSafe(p.zaParty_Name), StringComparison.OrdinalIgnoreCase) + End Function) + + If existing Is Nothing Then + list.Add(p) + Else + If TrimSafe(existing.zaParty_Street) = "" Then existing.zaParty_Street = p.zaParty_Street + If TrimSafe(existing.zaParty_PostalCode) = "" Then existing.zaParty_PostalCode = p.zaParty_PostalCode + If TrimSafe(existing.zaParty_City) = "" Then existing.zaParty_City = p.zaParty_City + If TrimSafe(existing.zaParty_Country) = "" Then existing.zaParty_Country = p.zaParty_Country + If TrimSafe(existing.zaParty_Email) = "" Then existing.zaParty_Email = p.zaParty_Email + If TrimSafe(existing.zaParty_Phone) = "" Then existing.zaParty_Phone = p.zaParty_Phone + End If + + End Sub + + Private Shared Function GetCellString(ws As IXLWorksheet, + row As Integer, + colMap As Dictionary(Of String, Integer), + header As String) As String + + Try + If ws Is Nothing OrElse colMap Is Nothing Then Return "" + If Not colMap.ContainsKey(header) Then Return "" + Return TrimSafe(ws.Cell(row, colMap(header)).GetString()) + Catch + Return "" + End Try + + End Function + + Private Shared Function GetCellDecimalNullable(ws As IXLWorksheet, + row As Integer, + colMap As Dictionary(Of String, Integer), + header As String) As Decimal? + + Try + If ws Is Nothing OrElse colMap Is Nothing Then Return Nothing + If Not colMap.ContainsKey(header) Then Return Nothing + + Dim cell = ws.Cell(row, colMap(header)) + If cell Is Nothing OrElse cell.IsEmpty() Then Return Nothing + + If cell.DataType = XLDataType.Number Then + Return Convert.ToDecimal(cell.GetDouble()) + End If + + Dim txt = TrimSafe(cell.GetString()) + If txt = "" Then Return Nothing + + Dim d As Decimal + txt = txt.Replace(" ", "") + + If Decimal.TryParse(txt, NumberStyles.Any, CultureInfo.InvariantCulture, d) Then Return d + If Decimal.TryParse(txt, NumberStyles.Any, CultureInfo.GetCultureInfo("de-AT"), d) Then Return d + If Decimal.TryParse(txt, NumberStyles.Any, CultureInfo.GetCultureInfo("de-DE"), d) Then Return d + + Catch + End Try + + Return Nothing + + End Function + + Private Shared Function GetCellDateNullable(ws As IXLWorksheet, + row As Integer, + colMap As Dictionary(Of String, Integer), + header As String) As Date? + + Try + If ws Is Nothing OrElse colMap Is Nothing Then Return Nothing + If Not colMap.ContainsKey(header) Then Return Nothing + + Dim cell = ws.Cell(row, colMap(header)) + If cell Is Nothing OrElse cell.IsEmpty() Then Return Nothing + + If cell.DataType = XLDataType.DateTime Then + Return cell.GetDateTime() + End If + + If cell.DataType = XLDataType.Number Then + Return DateTime.FromOADate(cell.GetDouble()) + End If + + Dim txt = TrimSafe(cell.GetString()) + If txt = "" Then Return Nothing + + Dim dt As DateTime + If DateTime.TryParse(txt, CultureInfo.InvariantCulture, DateTimeStyles.None, dt) Then Return dt + If DateTime.TryParse(txt, CultureInfo.GetCultureInfo("de-AT"), DateTimeStyles.None, dt) Then Return dt + If DateTime.TryParse(txt, CultureInfo.GetCultureInfo("de-DE"), DateTimeStyles.None, dt) Then Return dt + + Catch + End Try + + Return Nothing + + End Function + + Private Shared Function GetCellInt(ws As IXLWorksheet, + row As Integer, + colMap As Dictionary(Of String, Integer), + header As String, + Optional defaultValue As Integer = 0) As Integer + + Try + If ws Is Nothing OrElse colMap Is Nothing Then Return defaultValue + If Not colMap.ContainsKey(header) Then Return defaultValue + + Dim cell = ws.Cell(row, colMap(header)) + If cell Is Nothing OrElse cell.IsEmpty() Then Return defaultValue + + If cell.DataType = XLDataType.Number Then + Return Convert.ToInt32(Math.Truncate(cell.GetDouble())) + End If + + Dim txt = TrimSafe(cell.GetString()) + If txt = "" Then Return defaultValue + + Dim i As Integer + If Integer.TryParse(txt, i) Then Return i + + Dim d As Decimal + If Decimal.TryParse(txt, NumberStyles.Any, CultureInfo.InvariantCulture, d) Then + Return Convert.ToInt32(Math.Truncate(d)) + End If + If Decimal.TryParse(txt, NumberStyles.Any, CultureInfo.GetCultureInfo("de-AT"), d) Then + Return Convert.ToInt32(Math.Truncate(d)) + End If + If Decimal.TryParse(txt, NumberStyles.Any, CultureInfo.GetCultureInfo("de-DE"), d) Then + Return Convert.ToInt32(Math.Truncate(d)) + End If + + Catch + End Try + + Return defaultValue + + End Function + + Private Shared Function TrimSafe(value As Object) As String + If value Is Nothing Then Return "" + Return Convert.ToString(value).Trim() + End Function + +End Class \ No newline at end of file