Kopf-Sammelabrechnung
This commit is contained in:
@@ -0,0 +1,311 @@
|
||||
|
||||
|
||||
|
||||
' Requires NuGet:
|
||||
' - Confluent.Kafka
|
||||
' - Newtonsoft.Json
|
||||
' Target framework: .NET Framework 4.8 oder .NET 6/8 (passt beides)
|
||||
|
||||
Imports System.Threading
|
||||
Imports System.Threading.Tasks
|
||||
Imports Confluent.Kafka
|
||||
Imports Newtonsoft.Json
|
||||
|
||||
Namespace Verag.Udm
|
||||
|
||||
''' <summary>
|
||||
''' UDM-Record inkl. Beispielbefüllung und Kafka-Producer.
|
||||
''' Datenschema gemäß bereitgestellter JSON-Struktur. :contentReference[oaicite:1]{index=1}
|
||||
''' </summary>
|
||||
Public Class cATEZ_Greenpulse_KafkaDecs
|
||||
|
||||
'========================
|
||||
'== Kafka: Konfiguration (Klassenebene)
|
||||
'========================
|
||||
Public Shared BootstrapServers As String = "192.168.85.250:8888" 'http://192.168.85.250:8888
|
||||
Public Shared TopicName As String = "greenpulse.declarationdata.v1"
|
||||
' Falls SASL/TLS benötigt:
|
||||
Public Shared UseSasl As Boolean = False
|
||||
Public Shared SaslUsername As String = ""
|
||||
Public Shared SaslPassword As String = ""
|
||||
Public Shared SecurityProtocolSetting As SecurityProtocol = SecurityProtocol.Plaintext
|
||||
Public Shared SaslMechanismSetting As SaslMechanism = SaslMechanism.Plain
|
||||
|
||||
'========================
|
||||
'== Datenobjekte lt. UDM-Schema
|
||||
'========================
|
||||
|
||||
<JsonProperty("declaration")>
|
||||
Public Property Declaration As DeclarationNode
|
||||
|
||||
<JsonProperty("parties")>
|
||||
Public Property Parties As PartiesNode
|
||||
|
||||
<JsonProperty("commercial")>
|
||||
Public Property Commercial As CommercialNode
|
||||
|
||||
<JsonProperty("exporterDetails")>
|
||||
Public Property ExporterDetails As ExporterDetailsNode
|
||||
|
||||
<JsonProperty("importerDetails")>
|
||||
Public Property ImporterDetails As ImporterDetailsNode
|
||||
|
||||
'--- declaration ---
|
||||
Public Class DeclarationNode
|
||||
<JsonProperty("declarationsourceId")>
|
||||
Public Property DeclarationSourceId As String
|
||||
|
||||
<JsonProperty("declarationNo")>
|
||||
Public Property DeclarationNo As String
|
||||
|
||||
<JsonProperty("declarationDate")>
|
||||
Public Property DeclarationDate As String
|
||||
|
||||
<JsonProperty("requestedProcedure")>
|
||||
Public Property RequestedProcedure As String
|
||||
|
||||
<JsonProperty("previousProcedure")>
|
||||
Public Property PreviousProcedure As String
|
||||
|
||||
<JsonProperty("goods")>
|
||||
Public Property Goods As List(Of GoodItem)
|
||||
End Class
|
||||
|
||||
Public Class GoodItem
|
||||
<JsonProperty("commodityCode")>
|
||||
Public Property CommodityCode As String
|
||||
|
||||
<JsonProperty("originCountryCode")>
|
||||
Public Property OriginCountryCode As String
|
||||
|
||||
<JsonProperty("netMass")>
|
||||
Public Property NetMass As String
|
||||
|
||||
<JsonProperty("typeOfMeasurementUnit")>
|
||||
Public Property TypeOfMeasurementUnit As String
|
||||
|
||||
<JsonProperty("specialProcedures")>
|
||||
Public Property SpecialProcedures As SpecialProceduresNode
|
||||
End Class
|
||||
|
||||
Public Class SpecialProceduresNode
|
||||
<JsonProperty("memberStateAutharization")>
|
||||
Public Property MemberStateAutharization As String
|
||||
|
||||
<JsonProperty("dischargeBillWaiver")>
|
||||
Public Property DischargeBillWaiver As String
|
||||
|
||||
<JsonProperty("authorisation")>
|
||||
Public Property Authorisation As String
|
||||
|
||||
<JsonProperty("startTime")>
|
||||
Public Property StartTime As String
|
||||
|
||||
<JsonProperty("endTime")>
|
||||
Public Property EndTime As String
|
||||
|
||||
<JsonProperty("deadline")>
|
||||
Public Property Deadline As String
|
||||
End Class
|
||||
|
||||
'--- parties ---
|
||||
Public Class PartiesNode
|
||||
<JsonProperty("importerIdentificationNumber")>
|
||||
Public Property ImporterIdentificationNumber As String
|
||||
|
||||
<JsonProperty("exporterIdentificationNumber")>
|
||||
Public Property ExporterIdentificationNumber As String
|
||||
|
||||
<JsonProperty("reportingDeclarantEORINumber")>
|
||||
Public Property ReportingDeclarantEORINumber As String
|
||||
|
||||
<JsonProperty("typeOfRepresentation")>
|
||||
Public Property TypeOfRepresentation As String
|
||||
End Class
|
||||
|
||||
'--- commercial ---
|
||||
Public Class CommercialNode
|
||||
<JsonProperty("invoiceNumbers")>
|
||||
Public Property InvoiceNumbers As String
|
||||
|
||||
<JsonProperty("invoiceDate")>
|
||||
Public Property InvoiceDate As String
|
||||
End Class
|
||||
|
||||
'--- exporterDetails ---
|
||||
Public Class ExporterDetailsNode
|
||||
<JsonProperty("exporterTitle")>
|
||||
Public Property ExporterTitle As String
|
||||
|
||||
<JsonProperty("exporterEmail")>
|
||||
Public Property ExporterEmail As String
|
||||
|
||||
<JsonProperty("exporterPhone")>
|
||||
Public Property ExporterPhone As String
|
||||
End Class
|
||||
|
||||
'--- importerDetails ---
|
||||
Public Class ImporterDetailsNode
|
||||
<JsonProperty("importerTitle")>
|
||||
Public Property ImporterTitle As String
|
||||
|
||||
<JsonProperty("importerEmail")>
|
||||
Public Property ImporterEmail As String
|
||||
|
||||
<JsonProperty("importerPhone")>
|
||||
Public Property ImporterPhone As String
|
||||
|
||||
<JsonProperty("importerCountryCodeOrMemberState")>
|
||||
Public Property ImporterCountryCodeOrMemberState As String
|
||||
|
||||
<JsonProperty("importerSubdivision")>
|
||||
Public Property ImporterSubdivision As String
|
||||
|
||||
<JsonProperty("importerCity")>
|
||||
Public Property ImporterCity As String
|
||||
|
||||
<JsonProperty("importerStreet")>
|
||||
Public Property ImporterStreet As String
|
||||
|
||||
<JsonProperty("importerStreetAdditional")>
|
||||
Public Property ImporterStreetAdditional As String
|
||||
|
||||
<JsonProperty("importerAddressNumber")>
|
||||
Public Property ImporterAddressNumber As String
|
||||
|
||||
<JsonProperty("importerPostCode")>
|
||||
Public Property ImporterPostCode As String
|
||||
|
||||
<JsonProperty("importerPoBox")>
|
||||
Public Property ImporterPoBox As String
|
||||
|
||||
<JsonProperty("importerCoordinateLongitudeX")>
|
||||
Public Property ImporterCoordinateLongitudeX As String
|
||||
|
||||
<JsonProperty("importerCoordinateLatitudeY")>
|
||||
Public Property ImporterCoordinateLatitudeY As String
|
||||
End Class
|
||||
|
||||
'========================
|
||||
'== Serialisierung
|
||||
'========================
|
||||
Public Function ToJson(Optional pretty As Boolean = True) As String
|
||||
Dim format = If(pretty, Formatting.Indented, Formatting.None)
|
||||
Return JsonConvert.SerializeObject(Me, format)
|
||||
End Function
|
||||
|
||||
'========================
|
||||
'== Beispielbefüllung
|
||||
'========================
|
||||
Public Shared Function BuildDemo() As cATEZ_Greenpulse_KafkaDecs
|
||||
Return New cATEZ_Greenpulse_KafkaDecs() With {
|
||||
.Declaration = New DeclarationNode() With {
|
||||
.DeclarationSourceId = "xx123",
|
||||
.DeclarationNo = "24AT000000INL0JD01",
|
||||
.DeclarationDate = "2024-11-22",
|
||||
.RequestedProcedure = "40",
|
||||
.PreviousProcedure = "00",
|
||||
.Goods = New List(Of GoodItem) From {
|
||||
New GoodItem() With {
|
||||
.CommodityCode = "72072710",
|
||||
.OriginCountryCode = "TR",
|
||||
.NetMass = "150",
|
||||
.TypeOfMeasurementUnit = "Tonnes",
|
||||
.SpecialProcedures = New SpecialProceduresNode() With {
|
||||
.MemberStateAutharization = "AT",
|
||||
.DischargeBillWaiver = "01",
|
||||
.Authorisation = "Name of authorisation",
|
||||
.StartTime = "2024-10-22",
|
||||
.EndTime = "2024-11-22",
|
||||
.Deadline = "2024-12-22"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
.Parties = New PartiesNode() With {
|
||||
.ImporterIdentificationNumber = "ATEOS1000000001",
|
||||
.ExporterIdentificationNumber = "FR123456789000",
|
||||
.ReportingDeclarantEORINumber = "ATEOS1000000002",
|
||||
.TypeOfRepresentation = "01"
|
||||
},
|
||||
.Commercial = New CommercialNode() With {
|
||||
.InvoiceNumbers = "123456789",
|
||||
.InvoiceDate = "2024-11-22"
|
||||
},
|
||||
.ExporterDetails = New ExporterDetailsNode() With {
|
||||
.ExporterTitle = "",
|
||||
.ExporterEmail = "",
|
||||
.ExporterPhone = ""
|
||||
},
|
||||
.ImporterDetails = New ImporterDetailsNode() With {
|
||||
.ImporterTitle = "Importer name",
|
||||
.ImporterEmail = "info@test.com",
|
||||
.ImporterPhone = "123456789",
|
||||
.ImporterCountryCodeOrMemberState = "DE",
|
||||
.ImporterSubdivision = "Sub-division",
|
||||
.ImporterCity = "City name",
|
||||
.ImporterStreet = "Street Name",
|
||||
.ImporterStreetAdditional = "Street additonal name",
|
||||
.ImporterAddressNumber = "10",
|
||||
.ImporterPostCode = "DCL-123",
|
||||
.ImporterPoBox = "PO DCL-123",
|
||||
.ImporterCoordinateLongitudeX = "41.0091982",
|
||||
.ImporterCoordinateLatitudeY = "28.9662187"
|
||||
}
|
||||
}
|
||||
End Function
|
||||
|
||||
'========================
|
||||
'== Unique-Key-Ermittlung (leer gelassen – später definieren)
|
||||
'========================
|
||||
Public Shared Function GetUniqueKey(ByVal record As cATEZ_Greenpulse_KafkaDecs) As String
|
||||
' TODO: Hier Logik zur Schlüsselbildung implementieren (z.B. declarationsourceId + declarationNo)
|
||||
Return ""
|
||||
End Function
|
||||
|
||||
'========================
|
||||
'== Kafka: Insert/Update (per Message-Key)
|
||||
'========================
|
||||
Public Shared Async Function InsertOrUpdateToKafkaAsync(ByVal record As cATEZ_Greenpulse_KafkaDecs,
|
||||
Optional ct As CancellationToken = Nothing) As Task(Of DeliveryResult(Of String, String))
|
||||
|
||||
Dim cfg As New ProducerConfig() With {
|
||||
.BootstrapServers = BootstrapServers,
|
||||
.Acks = Acks.All,
|
||||
.EnableIdempotence = True,
|
||||
.MessageTimeoutMs = 30000
|
||||
}
|
||||
|
||||
If UseSasl Then
|
||||
cfg.SecurityProtocol = SecurityProtocolSetting
|
||||
cfg.SaslMechanism = SaslMechanismSetting
|
||||
cfg.SaslUsername = SaslUsername
|
||||
cfg.SaslPassword = SaslPassword
|
||||
' Optional: cfg.SslCaLocation = "path\to\ca.pem"
|
||||
End If
|
||||
|
||||
Dim key As String = GetUniqueKey(record) ' bleibt leer bis du definierst
|
||||
Dim payload As String = record.ToJson(False)
|
||||
|
||||
Using producer As IProducer(Of String, String) = New ProducerBuilder(Of String, String)(cfg).Build()
|
||||
Dim msg As New Message(Of String, String) With {
|
||||
.key = key,
|
||||
.Value = payload
|
||||
}
|
||||
Dim result = Await producer.ProduceAsync(TopicName, msg, ct)
|
||||
' Flush ist bei Await ProduceAsync nicht zwingend nötig, hier dennoch zur Sicherheit:
|
||||
producer.Flush(TimeSpan.FromSeconds(5))
|
||||
Return result
|
||||
End Using
|
||||
End Function
|
||||
|
||||
'========================
|
||||
'== Sync-Wrapper (falls bevorzugt)
|
||||
'========================
|
||||
Public Shared Function InsertOrUpdateToKafka(ByVal record As cATEZ_Greenpulse_KafkaDecs) As DeliveryResult(Of String, String)
|
||||
Return InsertOrUpdateToKafkaAsync(record).GetAwaiter().GetResult()
|
||||
End Function
|
||||
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
Reference in New Issue
Block a user