This commit is contained in:
2025-12-23 11:09:44 +01:00
parent 31f391b4f9
commit 33621096c1
3 changed files with 270 additions and 172 deletions

View File

@@ -1,15 +1,7 @@
' ============================================================================
' GreenPulse CBAM Carbon Cost API
' Single-file VB.NET implementation using Chilkat
' --------------------------------------------------------------------------
' Contains:
' - cATEZ_Greenpulse_CBAM_CostCalculation (main API class)
' - Request / Response DTO classes
' - Error handling & JSON parsing
'
' Requirements:
' - Chilkat.Http
' - Chilkat.JsonObject
' Adapted to latest Postman Collection (country_code, benchmark_value)
' ============================================================================
Imports Chilkat
@@ -21,45 +13,66 @@ Imports System.Globalization
Public Class cATEZ_Greenpulse_CBAM_CostCalculation
Private ReadOnly _baseUrl As String = "https://test-greenpulse-api.singlewindow.io/api/v1-0/public"
' Private ReadOnly _baseUrl As String = "https://greenpulse-api.singlewindow.io/api/v1-0/public"
'Private ReadOnly _baseUrl As String = "https://greenpulse-api.singlewindow.io/api/v1-0/public"
Private ReadOnly _http As Http
Public Sub New()
'_baseUrl = baseUrl.TrimEnd("/"c)
_http = New Http()
_http.SetRequestHeader("Content-Type", "application/json")
End Sub
' ------------------------------------------------------------------------
' GET /carbon-cost/cn-codes
' Returns raw JSON (ideal for dropdowns / caching)
' ------------------------------------------------------------------------
Public Function GetCnCodesRaw() As String
Dim url As String = _baseUrl & "/carbon-cost/cn-codes"
Public Function GetCnCodes() As cCBAM_CnCode_Response
Dim url As String = _baseUrl & "/carbon-cost/cn-codes"
Dim resp As HttpResponse = _http.QuickGetObj(url)
If resp Is Nothing Then
Throw New Exception(_http.LastErrorText)
End If
Return resp.BodyStr
Dim json As New JsonObject()
json.Load(resp.BodyStr)
Dim result As New cCBAM_CnCode_Response With {
.success = json.BoolOf("success")
}
If result.success Then
result.data = New List(Of cCBAM_CnCode)
Dim arr = json.ArrayOf("data")
For i As Integer = 0 To arr.Size - 1
Dim o = arr.ObjectAt(i)
result.data.Add(New cCBAM_CnCode With {
.cn_code = o.StringOf("cn_code"),
.cn_description = o.StringOf("cn_description")
})
Next
Else
Dim e = json.ObjectOf("error")
result.error = New cCBAM_Error With {
.code = e.StringOf("code"),
.message = e.StringOf("message"),
.statusCode = e.IntOf("statusCode")
}
End If
Return result
End Function
' ------------------------------------------------------------------------
' POST /carbon-cost/calculate
' ------------------------------------------------------------------------
Public Function CalculateCost(req As cCBAM_CostCalculation_Request) As cCBAM_CostCalculation_Response
Public Function CalculateCost(req As cCBAM_CostCalculation_Request) _
As cCBAM_CostCalculation_Response
VERAG_PROG_ALLGEMEIN.cChilkat_Helper.UnlockCilkat()
Dim url As String = _baseUrl & "/carbon-cost/calculate"
Dim resp As HttpResponse = _http.PostJson2(
url,
"application/json",
req.ToJson()
)
Dim resp As HttpResponse = _http.PostJson2(url, "application/json", req.ToJson())
If resp Is Nothing Then
Throw New Exception(_http.LastErrorText)
@@ -77,8 +90,9 @@ Public Class cATEZ_Greenpulse_CBAM_CostCalculation
Dim json As New JsonObject()
json.Load(jsonStr)
Dim result As New cCBAM_CostCalculation_Response()
result.success = json.BoolOf("success")
Dim result As New cCBAM_CostCalculation_Response With {
.success = json.BoolOf("success")
}
If result.success Then
Dim d = json.ObjectOf("data")
@@ -114,109 +128,140 @@ Public Class cATEZ_Greenpulse_CBAM_CostCalculation
End Function
' ------------------------------------------------------------------------
' Robust numeric parsing across Chilkat versions:
' Many Chilkat builds don't expose DoubleOf/NumberOf in the .NET wrapper.
' Any JSON value (incl. numbers) can be read via StringOf and converted.
' Robust Decimal Parsing (Chilkat-safe)
' ------------------------------------------------------------------------
Private Shared Function GetDec(obj As JsonObject, name As String) As Decimal
Dim s As String = obj.StringOf(name)
If String.IsNullOrWhiteSpace(s) Then Return 0D
' Ensure dot decimal separator
s = s.Trim().Replace(",", ".")
s = s.Replace(",", ".")
Dim v As Decimal
If Decimal.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, v) Then
Return v
End If
' Fallback: try current culture (last resort)
If Decimal.TryParse(s, NumberStyles.Any, CultureInfo.CurrentCulture, v) Then
Return v
End If
If Decimal.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, v) Then Return v
Return 0D
End Function
Shared Function calcCBAM(cn_code, weight, Optional see_total = "", Optional year = "", Optional country = "") As String
' ------------------------------------------------------------------------
' Convenience Wrapper für einfache CBAM-Kalkulation
' ------------------------------------------------------------------------
Public Shared Function calcCBAM(
cn_code As String,
weight As Object,
country_code As String,
Optional see_total As Object = Nothing,
Optional year As Object = Nothing,
Optional benchmark_value As Object = Nothing
) As String
If cn_code = "" Or Not IsNumeric(cn_code) Then
Return "Fehler: ungültiger CN-Code"
End If
If weight = "" Or Not IsNumeric(weight) Then
Return "Fehler: ungültiges Gewicht"
End If
If see_total <> "" AndAlso Not IsNumeric(see_total) Then
Return "Fehler: ungültige echten Emissionen"
End If
If year <> "" AndAlso Not IsNumeric(year) Then
If Not IsNumeric(year) Then Return "Fehler: ungültiges Phase-in Jahr"
If year.length <> 4 Then Return "Fehler: ungültiges Phase-in Jahr"
End If
If country <> "" AndAlso country.length > 2 Then
' Derzeit nicht unterstützt
Return "Fehler: Land wird derzeit nicht unterstützt"
End If
' ------------------------------------------------------------
' 1) API initialisieren
' Validierung (grundlegend, API macht Rest)
' ------------------------------------------------------------
If String.IsNullOrWhiteSpace(cn_code) OrElse cn_code.Length <> 8 OrElse Not IsNumeric(cn_code) Then
Return "Fehler: ungültiger CN-Code (muss 8-stellig numerisch sein)"
End If
If weight Is Nothing OrElse Not IsNumeric(weight) OrElse CDbl(weight) <= 0 Then
Return "Fehler: ungültiges Gewicht (muss > 0 sein)"
End If
If String.IsNullOrWhiteSpace(country_code) OrElse country_code.Length <> 2 Then
Return "Fehler: country_code muss ein ISO-2 Code sein (z.B. TR)"
End If
If see_total <> "" And (see_total IsNot Nothing AndAlso Not IsNumeric(see_total)) Then
Return "Fehler: ungültige echte Emissionen (see_total)"
End If
If year IsNot Nothing Then
If Not IsNumeric(year) OrElse CInt(year) < 2020 OrElse CInt(year) > 2100 Then
Return "Fehler: ungültiges Jahr"
End If
End If
If benchmark_value <> "" And (benchmark_value IsNot Nothing AndAlso Not IsNumeric(benchmark_value)) Then
Return "Fehler: ungültiger Benchmark-Wert"
End If
' ------------------------------------------------------------
' API initialisieren
' ------------------------------------------------------------
Dim api As New cATEZ_Greenpulse_CBAM_CostCalculation()
' ------------------------------------------------------------
' 2) Request aufbauen
' Request aufbauen
' ------------------------------------------------------------
Dim req As New cCBAM_CostCalculation_Request With {
.cn_code = cn_code,
.weight = CDbl(weight), ' Tonnen
.see_total = If(see_total = "", Nothing, see_total), ' optionale echte Emissionen
.year = If(year = "", Nothing, CInt(year)) ' Phase-in Jahr
}
.cn_code = cn_code,
.country_code = country_code.ToUpperInvariant(),
.weight = CDec(weight)
}
If If(see_total, "") <> "" Then
req.see_total = CDec(see_total)
Else
req.see_total = Nothing
End If
If year IsNot Nothing Then
req.year = CInt(year)
End If
If If(benchmark_value, "") <> "" Then
req.benchmark_value = CDec(benchmark_value)
Else
req.benchmark_value = Nothing
End If
' ------------------------------------------------------------
' 3) Request ausführen
' Request ausführen
' ------------------------------------------------------------
Dim resp As cCBAM_CostCalculation_Response = api.CalculateCost(req)
Dim resp As cCBAM_CostCalculation_Response
Try
resp = api.CalculateCost(req)
Catch ex As Exception
Return "Technischer Fehler bei API-Aufruf: " & ex.Message
End Try
Dim erg = ""
' ------------------------------------------------------------
' 4) Ergebnis auswerten
' Ergebnis aufbereiten
' ------------------------------------------------------------
Dim erg As String = ""
If resp.success Then
erg &= "CBAM Kostenberechnung erfolgreich" & vbNewLine
erg &= "--------------------------------" & vbNewLine
erg &= $"Kosten: {CDbl(resp.data.cost).ToString("N2")} {resp.data.currency}" & vbNewLine
erg &= $"CBAM Emission: {resp.data.cbam_emission}" & vbNewLine
erg &= $"Benchmark: {resp.data.benchmark}" & vbNewLine
erg &= $"Phase-Faktor: {resp.data.phase_factor}" & vbNewLine
erg &= $"CO2 Preis: {resp.data.carbon_price}" & vbNewLine
erg &= "CBAM Kostenberechnung erfolgreich" & vbCrLf
erg &= "--------------------------------" & vbCrLf
erg &= $"CN-Code: {cn_code}" & vbCrLf
erg &= $"Ursprungsland: {req.country_code}" & vbCrLf
erg &= $"Gewicht: {req.weight:N2} t" & vbCrLf
erg &= vbCrLf
erg &= "" & vbNewLine
erg &= "Details:" & vbNewLine
erg &= $" Adjusted Benchmark: {resp.data.calculation_details.adjusted_benchmark}" & vbNewLine
erg &= $" Emission Difference: {resp.data.calculation_details.emission_difference}" & vbNewLine
erg &= $" Gewicht: {CDbl(resp.data.calculation_details.weight).ToString("N2")} t" & vbNewLine
erg &= $"Kosten: {resp.data.cost:N2} {resp.data.currency}" & vbCrLf
erg &= $"CBAM Emission: {resp.data.cbam_emission:N5}" & vbCrLf
erg &= $"Benchmark: {resp.data.benchmark:N5}" & vbCrLf
erg &= $"Phase-Faktor: {resp.data.phase_factor:P2}" & vbCrLf
erg &= $"CO₂ Preis: {resp.data.carbon_price:N2} EUR/t" & vbCrLf
erg &= vbCrLf
erg &= "Details:" & vbCrLf
erg &= $" Adjusted Benchmark: {resp.data.calculation_details.adjusted_benchmark:N5}" & vbCrLf
erg &= $" Emission Difference: {resp.data.calculation_details.emission_difference:N5}" & vbCrLf
erg &= $" Gewicht (berechnet): {resp.data.calculation_details.weight:N2} t" & vbCrLf
Else
erg &= "CBAM Kostenberechnung FEHLER" & vbNewLine
erg &= "--------------------------------" & vbNewLine
erg &= $"Code: {resp.error.code}" & vbNewLine
erg &= $"Message: {resp.error.message}" & vbNewLine
erg &= $"HTTP Status: {resp.error.statusCode}" & vbNewLine
erg &= "CBAM Kostenberechnung FEHLER" & vbCrLf
erg &= "--------------------------------" & vbCrLf
erg &= $"Code: {resp.error.code}" & vbCrLf
erg &= $"Message: {resp.error.message}" & vbCrLf
erg &= $"HTTP Status: {resp.error.statusCode}" & vbCrLf
End If
' Console.ReadKey()
Return erg
End Function
End Class
' ============================================================================
@@ -225,17 +270,20 @@ End Class
Public Class cCBAM_CostCalculation_Request
Public Property cn_code As String
Public Property country_code As String
Public Property weight As Decimal
Public Property see_total As Nullable(Of Decimal)
Public Property year As Nullable(Of Integer)
Public Property benchmark_value As Nullable(Of Decimal)
Public Function ToJson() As String
Dim json As New JsonObject()
json.UpdateString("cn_code", cn_code)
json.UpdateString("country_code", country_code)
json.UpdateNumber("weight", weight.ToString(CultureInfo.InvariantCulture))
If see_total.HasValue Then
If see_total IsNot Nothing AndAlso see_total.HasValue Then
json.UpdateNumber("see_total", see_total.Value.ToString(CultureInfo.InvariantCulture))
End If
@@ -243,13 +291,17 @@ Public Class cCBAM_CostCalculation_Request
json.UpdateInt("year", year.Value)
End If
If benchmark_value IsNot Nothing AndAlso benchmark_value.HasValue Then
json.UpdateNumber("benchmark_value", benchmark_value.Value.ToString(CultureInfo.InvariantCulture))
End If
Return json.Emit()
End Function
End Class
' ============================================================================
' RESPONSE ROOT
' RESPONSE OBJECTS
' ============================================================================
Public Class cCBAM_CostCalculation_Response
Public Property success As Boolean
@@ -257,9 +309,6 @@ Public Class cCBAM_CostCalculation_Response
Public Property [error] As cCBAM_Error
End Class
' ============================================================================
' RESPONSE DATA
' ============================================================================
Public Class cCBAM_CostCalculation_Data
Public Property cost As Decimal
Public Property cbam_emission As Decimal
@@ -270,9 +319,6 @@ Public Class cCBAM_CostCalculation_Data
Public Property calculation_details As cCBAM_CostCalculation_Details
End Class
' ============================================================================
' RESPONSE DETAILS
' ============================================================================
Public Class cCBAM_CostCalculation_Details
Public Property cbam_emission As Decimal
Public Property benchmark As Decimal
@@ -282,6 +328,20 @@ Public Class cCBAM_CostCalculation_Details
Public Property carbon_price As Decimal
End Class
' ============================================================================
' CN CODE RESPONSE
' ============================================================================
Public Class cCBAM_CnCode_Response
Public Property success As Boolean
Public Property data As List(Of cCBAM_CnCode)
Public Property [error] As cCBAM_Error
End Class
Public Class cCBAM_CnCode
Public Property cn_code As String
Public Property cn_description As String
End Class
' ============================================================================
' ERROR OBJECT
' ============================================================================