Commit da9e7246 authored by Marco Schmiedel's avatar Marco Schmiedel

fix

parent 92796ceb
{
"fileId": "12a942d7-6f13-4c57-9f5c-1c6fd3baaf21",
"originalPath": "work/manager/OpenAiManager.py",
"currentPath": "work/manager/OpenAiManager.py",
"hash": "a5d54b395c9edf435ee5ec0a2f3637058b54bab058827175487268f4dc07304a",
"docContent": "<p><br></p>",
"checkedStatus": "done",
"comments": [],
"lastCheckedTimestamp": 1745314592645,
"lastFileModificationTimestamp": 1745314218432.6475
}
{
"fileId": "1e5daa93-a29c-4db7-98ac-3457b779f0d1",
"originalPath": "work/manager/S3Manager.py",
"currentPath": "work/manager/S3Manager.py",
"hash": "3626bb3b00d9142ba6d471dfdd2d7a0f54d72afca4b908843c9cf6d483d66754",
"docContent": "<p><br></p>",
"checkedStatus": "done",
"comments": [],
"lastCheckedTimestamp": 1745314595210,
"lastFileModificationTimestamp": 1745314341957.45
}
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
"fileId": "22983490-9c01-4bd1-8649-dfe87c659225", "fileId": "22983490-9c01-4bd1-8649-dfe87c659225",
"originalPath": "work/config/MauiConfig.py", "originalPath": "work/config/MauiConfig.py",
"currentPath": "work/config/MauiConfig.py", "currentPath": "work/config/MauiConfig.py",
"hash": "7749ff881e9fac6aaeffe5274aa9566b2b5692a1ec4e7f47e20b79671a0788a3", "hash": "6e627f3800fd413c6dbde92ad2e274d5e3047af0f906de4d75fc826cc129631e",
"docContent": "<p>In this configuration, you’ll find the credentials required to log in to Freenet-Maui.</p>", "docContent": "<p>In this configuration, you’ll find the credentials required to log in to Freenet-Maui.</p>",
"checkedStatus": "done", "checkedStatus": "todo",
"comments": [ "comments": [
{ {
"commentId": "3bc16f5e-4032-44a8-9012-4b632849ba50", "commentId": "3bc16f5e-4032-44a8-9012-4b632849ba50",
...@@ -12,6 +12,6 @@ ...@@ -12,6 +12,6 @@
"timestamp": 1744614418809 "timestamp": 1744614418809
} }
], ],
"lastCheckedTimestamp": 1744614348029, "lastCheckedTimestamp": 1745314578450,
"lastFileModificationTimestamp": 1744614095522.7373 "lastFileModificationTimestamp": 1745313945182.1555
} }
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
"fileId": "24784b38-54dc-4000-9d2a-f59082ebbc1c", "fileId": "24784b38-54dc-4000-9d2a-f59082ebbc1c",
"originalPath": "work/models/base_base.py", "originalPath": "work/models/base_base.py",
"currentPath": "work/models/base_base.py", "currentPath": "work/models/base_base.py",
"hash": "19b6bd8fd24ccac708053a39f013632721ed03ec35663efd7d7ec222cf0be934", "hash": "a13647e2879a37dfcb76bf95c143fc42b0da2eac67a471884afd5c314dc46f8f",
"docContent": "<p><br></p>", "docContent": "<p><br></p>",
"checkedStatus": "done", "checkedStatus": "done",
"comments": [], "comments": [],
"lastCheckedTimestamp": 1744805211278, "lastCheckedTimestamp": 1745314601207,
"lastFileModificationTimestamp": 1744787773143.9746, "lastFileModificationTimestamp": 1745313922231.5488,
"flaggedForCopy": false "flaggedForCopy": false
} }
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
"fileId": "38b9eebe-955e-4052-a0f6-29c69b1242b3", "fileId": "38b9eebe-955e-4052-a0f6-29c69b1242b3",
"originalPath": "work/config/MysqlConfig.py", "originalPath": "work/config/MysqlConfig.py",
"currentPath": "work/config/MysqlConfig.py", "currentPath": "work/config/MysqlConfig.py",
"hash": "f9c624640584ecc2400d5053b7b366a6b2305ecdf836221aa95e3e169254af79", "hash": "8eeae892f7c5f5aa1e894ca9ff7b8c66ea2891bc37c0167c404cd6e0cb95f858",
"docContent": "<p><br></p>", "docContent": "<p><br></p>",
"checkedStatus": "done", "checkedStatus": "todo",
"comments": [ "comments": [
{ {
"commentId": "56c5adba-20f4-4524-a894-41f81ab7ca55", "commentId": "56c5adba-20f4-4524-a894-41f81ab7ca55",
...@@ -12,6 +12,6 @@ ...@@ -12,6 +12,6 @@
"timestamp": 1744622354948 "timestamp": 1744622354948
} }
], ],
"lastCheckedTimestamp": 1744624735475, "lastCheckedTimestamp": 1745314583521,
"lastFileModificationTimestamp": 1744624729595.99 "lastFileModificationTimestamp": 1745313973064.8933
} }
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
"fileId": "543b791f-9a45-4b53-906e-c49f79ac95d7", "fileId": "543b791f-9a45-4b53-906e-c49f79ac95d7",
"originalPath": "work/notebooks/ImportCsvToDatabase.ipynb", "originalPath": "work/notebooks/ImportCsvToDatabase.ipynb",
"currentPath": "work/notebooks/ImportCsvToDatabase.ipynb", "currentPath": "work/notebooks/ImportCsvToDatabase.ipynb",
"hash": "6cdb9455f0658ca804b4beb6201bdfa4ae721451c9fa7c99e0bebe9f5a0dbf09", "hash": "c6e6e4c70653fbfc4d43ae89e4f05fc1a8d2804eb2f515ad52c41637bd5b0e14",
"docContent": "<p><br></p>", "docContent": "<p><br></p>",
"checkedStatus": "done", "checkedStatus": "changed",
"comments": [], "comments": [],
"lastCheckedTimestamp": 1744806594117, "lastCheckedTimestamp": 1744806594117,
"lastFileModificationTimestamp": 1744806589225.9287 "lastFileModificationTimestamp": 1745313435812.8953
} }
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
"fileId": "766dc461-001e-4901-8faf-263820ad96cd", "fileId": "766dc461-001e-4901-8faf-263820ad96cd",
"originalPath": "work/manager/MysqlManager.py", "originalPath": "work/manager/MysqlManager.py",
"currentPath": "work/manager/MysqlManager.py", "currentPath": "work/manager/MysqlManager.py",
"hash": "c016d5cb9c9b391d19e41323196715c0e57b5838846232d2bdf761f53293e1b4", "hash": "0506c7ebbfff68bce628902018e66ba50936a52e08aa595cadc8d5324c48d46f",
"docContent": "<p><br></p>", "docContent": "<p><br></p>",
"checkedStatus": "done", "checkedStatus": "done",
"comments": [], "comments": [],
"lastCheckedTimestamp": 1744624751868, "lastCheckedTimestamp": 1745314589383,
"lastFileModificationTimestamp": 1744624748400.9556, "lastFileModificationTimestamp": 1745314105678.9277,
"flaggedForCopy": false "flaggedForCopy": false
} }
{
"fileId": "7a3a246b-fc0e-4c80-b748-96b941efab5c",
"originalPath": "work/config/AWSConfig.py",
"currentPath": "work/config/AWSConfig.py",
"hash": "5a6654cb1cd77f8d531fcc1541d31261ea02c4e8cb126f2cc43a217c9c6920aa",
"docContent": "<p><br></p>",
"checkedStatus": "todo",
"comments": [],
"lastCheckedTimestamp": 1745314580866,
"lastFileModificationTimestamp": 1745311719614.9841
}
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
"fileId": "d470fd53-8f95-47d0-a63b-5851586c0eda", "fileId": "d470fd53-8f95-47d0-a63b-5851586c0eda",
"originalPath": "work/manager/SeleniumManager.py", "originalPath": "work/manager/SeleniumManager.py",
"currentPath": "work/manager/SeleniumManager.py", "currentPath": "work/manager/SeleniumManager.py",
"hash": "be7dde51af30a8ea1f80ea3090f39d2e9a84168cf7d3e15086c16bdbbfde2c26", "hash": "f29307970d124e55c7066e71ddf682f55e043d4f925195bdf320ff9da1311e27",
"docContent": "<p><br></p>", "docContent": "<p><br></p>",
"checkedStatus": "done", "checkedStatus": "done",
"comments": [], "comments": [],
"lastCheckedTimestamp": 1744620379152, "lastCheckedTimestamp": 1745314597597,
"lastFileModificationTimestamp": 1744547804595.8647 "lastFileModificationTimestamp": 1745314531223.019
} }
{
"fileId": "f645f6dc-6831-4020-a6ae-8b5a572eed54",
"originalPath": "work/config/OpenAiConfig.py",
"currentPath": "work/config/OpenAiConfig.py",
"hash": "3da3805934b36b3ab8c21e10d8babe3cc8b6c9acb7b2b1446f782612b76cf2c4",
"docContent": "<p><br></p>",
"checkedStatus": "todo",
"comments": [],
"lastCheckedTimestamp": 1745314586062,
"lastFileModificationTimestamp": 1745313976355.6653
}
AWS_ACCESS_KEY_ID = "AKIATXO2FKVK3BSS3DMT"
AWS_SECRET_ACCESS_KEY = "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"
REGION = "eu-central-1"
BUCKET_NAME = "freenetflyer"
# This variable stores the username for accessing Maui.
MAUI_USERNAME = "28009594-198" MAUI_USERNAME = "28009594-198"
# This variable stores the password for accessing Maui.
MAUI_PASSWORD = "8v#5YeeQyh" MAUI_PASSWORD = "8v#5YeeQyh"
# This variable stores the authentication code (2FA code) for accessing Maui.
MAUI_AUTHCODE = "2D3JJNG3WWGSWRDI5KRW2MZKL3NJEZXJ" MAUI_AUTHCODE = "2D3JJNG3WWGSWRDI5KRW2MZKL3NJEZXJ"
# The MySQL host address.
MYSQL_HOST = "itmax-backoffice-prod-aurora-r3dbcluster-1e8hysitdwijk.cluster-crb5tahpiszg.eu-central-1.rds.amazonaws.com" MYSQL_HOST = "itmax-backoffice-prod-aurora-r3dbcluster-1e8hysitdwijk.cluster-crb5tahpiszg.eu-central-1.rds.amazonaws.com"
# The MySQL username for the connection.
MYSQL_USER = "labor-itmaxmaster" MYSQL_USER = "labor-itmaxmaster"
# The MySQL password for the connection.
MYSQL_PASSWORD = "floz09sx3dTyx144gy" MYSQL_PASSWORD = "floz09sx3dTyx144gy"
# The MySQL database name.
MYSQL_DATABASE = "itmax_tarifs" MYSQL_DATABASE = "itmax_tarifs"
# The MySQL port number.
MYSQL_PORT = 3306 MYSQL_PORT = 3306
# If set to True, the MysqlManager will establish an SSH tunnel when connecting to MySQL.
USE_SSH_TUNNEL = True USE_SSH_TUNNEL = True
# The SSH host address (the remote SSH server to tunnel through).
SSH_HOST = "jumphost.bugsmasher.online" SSH_HOST = "jumphost.bugsmasher.online"
# The SSH port number (default is usually 22).
SSH_PORT = 22 SSH_PORT = 22
# The SSH username for the tunnel.
SSH_USERNAME = "root" SSH_USERNAME = "root"
# The SSH password for the tunnel.
SSH_PASSWORD = "7dHz2xO8ct1143T" SSH_PASSWORD = "7dHz2xO8ct1143T"
\ No newline at end of file
secret = "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"
...@@ -4,15 +4,14 @@ from sqlalchemy.orm import sessionmaker ...@@ -4,15 +4,14 @@ from sqlalchemy.orm import sessionmaker
import config.MysqlConfig as DatabaseConfig import config.MysqlConfig as DatabaseConfig
from sshtunnel import SSHTunnelForwarder from sshtunnel import SSHTunnelForwarder
# We create a new class called MysqlManager. # In dieser Klasse wird die Verwaltung einer MySQL-Verbindung umgesetzt.
class MysqlManager: class MysqlManager:
# The following constructor initializes the MySQL connection. # In diesem Konstruktor werden die Verbindungskonfigurationen aus dem Config-Modul geladen und der SSH-Tunnel bei Bedarf gestartet.
def __init__(self): def __init__(self):
# Instead of reading a configuration file, we import the Python configuration. # In dieser Variablen werden die Konfigurationsdaten für den Datenbankzugriff gesammelt.
# We construct the configuration dictionary using values from the DatabaseConfig module. self.dbConfig = {
self.config = {
"host": DatabaseConfig.MYSQL_HOST, "host": DatabaseConfig.MYSQL_HOST,
"user": DatabaseConfig.MYSQL_USER, "user": DatabaseConfig.MYSQL_USER,
"password": DatabaseConfig.MYSQL_PASSWORD, "password": DatabaseConfig.MYSQL_PASSWORD,
...@@ -20,45 +19,46 @@ class MysqlManager: ...@@ -20,45 +19,46 @@ class MysqlManager:
"port": DatabaseConfig.MYSQL_PORT "port": DatabaseConfig.MYSQL_PORT
} }
# Check if an SSH tunnel should be used. # In dieser Abzweigung wird geprüft, ob ein SSH-Tunnel verwendet werden soll.
if getattr(DatabaseConfig, "USE_SSH_TUNNEL", False): if getattr(DatabaseConfig, "USE_SSH_TUNNEL", False):
# Initialize the SSH tunnel using SSHTunnelForwarder. # In dieser Variablen wird ein SSH-Tunnel erstellt, der den Datenverkehr zu einem lokalen Port umleitet.
self.tunnel = SSHTunnelForwarder( self.sshTunnel = SSHTunnelForwarder(
(DatabaseConfig.SSH_HOST, DatabaseConfig.SSH_PORT), (DatabaseConfig.SSH_HOST, DatabaseConfig.SSH_PORT),
ssh_username=DatabaseConfig.SSH_USERNAME, ssh_username=DatabaseConfig.SSH_USERNAME,
ssh_password=DatabaseConfig.SSH_PASSWORD, ssh_password=DatabaseConfig.SSH_PASSWORD,
remote_bind_address=(self.config["host"], self.config["port"]) remote_bind_address=(self.dbConfig["host"], self.dbConfig["port"])
) )
# Start the SSH tunnel.
self.tunnel.start()
# Set the host to localhost and port to the tunnel's local bind port. # Hier wird der SSH-Tunnel gestartet, damit die Weiterleitung aktiv wird.
host = "127.0.0.1" self.sshTunnel.start()
port = self.tunnel.local_bind_port
# In diesen Variablen werden Host und Port auf die lokalen Tunnel-Daten gesetzt.
dbHost = "127.0.0.1"
dbPort = self.sshTunnel.local_bind_port
else: else:
# No SSH tunnel is used. # In dieser Abzweigung wird kein SSH-Tunnel verwendet.
self.tunnel = None self.sshTunnel = None
host = self.config["host"] dbHost = self.dbConfig["host"]
port = self.config["port"] dbPort = self.dbConfig["port"]
# Construct the MySQL engine using the connection details. # In dieser Variablen wird das SQLAlchemy-Engine-Objekt mit den Verbindungsdaten erzeugt.
engine = create_engine( dbEngine = create_engine(
f"mysql+pymysql://{self.config['user']}:{self.config['password']}@{host}:{port}/{self.config['database']}", f"mysql+pymysql://{self.dbConfig['user']}:{self.dbConfig['password']}@{dbHost}:{dbPort}/{self.dbConfig['database']}",
echo=False echo=False
) )
# Start the database session. # In dieser Variablen wird eine neue SessionFactory erzeugt und eine Session erstellt.
self.session = sessionmaker(bind=engine)() self.dbSession = sessionmaker(bind=dbEngine)()
# "getSession" provides the database connection to other modules. # In dieser Methode wird eine Session-Instanz zurückgegeben, um Datenbankaktionen durchzuführen.
def getSession(self): def getSession(self):
return self.session return self.dbSession
# The following method closes the database connection and stops the SSH tunnel if active. # In dieser Methode wird die bestehende Session geschlossen und der SSH-Tunnel (falls vorhanden) gestoppt.
def close(self): def close(self):
self.session.close() self.dbSession.close()
if self.tunnel: if self.sshTunnel:
self.tunnel.stop() self.sshTunnel.stop()
import sys; sys.path.append("..")
import requests
import json
import re
import time
import config.OpenAiConfig as Config
# In dieser Klasse wird die Kommunikation mit der OpenAI-API verwaltet.
class OpenAiManager:
# In diesem Konstruktor werden die Konfiguration und der API-Key geladen und grundlegende Parameter für die Anfragen gesetzt.
def __init__(self):
# In dieser Variablen wird die Konfiguration abgelegt, wobei der Key aus dem externen Config-Modul stammt.
self.config = {
"secret": Config.secret
}
# In dieser Variablen wird der API-Key aus dem Konfigurationsdictionary entnommen.
self.apiKey = self.config["secret"]
# In dieser Variablen wird die URL für Chat-Completions hinterlegt.
self.openAiUrl = "https://api.openai.com/v1/chat/completions"
# In dieser Variablen werden die Header für die HTTP-Anfragen an die OpenAI-API definiert.
self.requestHeaders = {
"Authorization": f"Bearer {self.apiKey}",
"Content-Type": "application/json"
}
# In dieser Methode wird ein Prompt an die OpenAI-API geschickt, um eine Chat-Antwort zu erhalten.
def chat(self, prompt, model="o1-mini"):
# In dieser Variablen wird das JSON-Objekt für die Anfrage an die OpenAI-API aufgebaut.
requestData = {
"model": model,
"messages": [{"role": "user", "content": prompt}]
}
# In diesem Schritt wird ein POST-Request an die definierte Chat-Completion-URL gesendet.
response = requests.post(self.openAiUrl, headers=self.requestHeaders, json=requestData)
# In dieser Variablen wird die Antwort als Python-Objekt interpretiert.
responseData = response.json()
# In dieser Abzweigung wird geprüft, ob in der Antwort mindestens ein Eintrag unter 'choices' existiert.
if "choices" in responseData:
# Hier wird der Inhalt der ersten Choice zurückgegeben, wenn vorhanden.
return responseData["choices"][0]["message"]["content"]
# In dieser Abzweigung wird None zurückgegeben, falls kein verwertbarer Inhalt existiert.
else:
return None
import sys; sys.path.append("..")
import config.AWSConfig as Config
import boto3
import json
import re
# In dieser Klasse werden die Interaktionen mit AWS S3 verwaltet, wie zum Beispiel das Hochladen von Dateien.
class S3Manager:
# In diesem Konstruktor wird ein S3-Client erzeugt und der Bucketname aus den Konfigurationswerten hinterlegt.
def __init__(self):
self.s3Client = boto3.client(
's3',
aws_access_key_id=Config.AWS_ACCESS_KEY_ID,
aws_secret_access_key=Config.AWS_SECRET_ACCESS_KEY,
region_name=Config.REGION
)
self.bucketName = Config.BUCKET_NAME
# In dieser Methode wird eine Datei in den konfigurierten S3-Bucket hochgeladen, wobei standardmäßig eine ACL für public-read gesetzt wird.
def uploadFile(self, filePath, s3Key, acl="public-read"):
# In diesem try-Block wird versucht, die Datei auf S3 hochzuladen und anschließend der öffentliche Link zurückgegeben.
try:
self.s3Client.upload_file(filePath, self.bucketName, s3Key, ExtraArgs={'ACL': acl})
return self.getPublicUrl(s3Key)
# In dieser Abzweigung wird eine Exception abgefangen, falls das Hochladen fehlschlägt, und None zurückgegeben.
except Exception as e:
print(f"Fehler beim Hochladen der Datei: {e}")
return None
# In dieser Methode wird der öffentliche URL-Link generiert, anhand des Bucketnamens und des S3-Schlüssels.
def getPublicUrl(self, s3Key):
return f"https://{self.bucketName}.s3.amazonaws.com/{s3Key}"
This diff is collapsed.
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, JSON
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from models._system import Base from models._system import Base
from models.basegroup_bgro import BasegroupBgro from models.basegroup_bgro import BasegroupBgro
...@@ -7,13 +7,16 @@ from models.option_opti import OptionOpti ...@@ -7,13 +7,16 @@ from models.option_opti import OptionOpti
class BaseBase(Base): class BaseBase(Base):
__tablename__ = 'base_base' __tablename__ = 'base_base'
id_base = Column(Integer, primary_key=True, autoincrement=True) id_base = Column(Integer, primary_key=True, autoincrement=True)
basegroup_base = Column(Integer, ForeignKey('basegroup_bgro.id_bgro')) basegroup_base = Column(Integer, ForeignKey("basegroup_bgro.id_bgro"))
provider_base = Column(String(255), nullable=False) provider_base = Column(String(255), nullable=False)
providercode_base = Column(String(255)) providercode_base= Column(String(255))
name_base = Column(String(255), nullable=False) name_base = Column(String(255), nullable=False)
alias_base = Column(String(255)) alias_base = Column(String(255))
network_base = Column(Integer, nullable=False) network_base = Column(Integer, nullable=False)
type_base = Column(Integer, nullable=False) type_base = Column(Integer, nullable=False)
flyerurl_base = Column(String(255))
piburl_base = Column(String(255))
details_base = Column(JSON) # enthält das von GPT extrahierte Tarif‑JSON
created_base = Column(DateTime, nullable=False) created_base = Column(DateTime, nullable=False)
updated_base = Column(DateTime, nullable=False) updated_base = Column(DateTime, nullable=False)
basegroup = relationship("BasegroupBgro", back_populates="bases") basegroup = relationship("BasegroupBgro", back_populates="bases")
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
**Aufgabe:**
Du bist eine hochpräzise API zur Extraktion spezifischer Mobilfunktarif-Merkmale aus Dokumentenpaaren. Deine Eingabe besteht immer aus zwei PDF-Dateien: einem **Produktdetailblatt/Flyer** und einem **Produktinformationsblatt (PIB)**, die gemeinsam *einen* spezifischen Tarif beschreiben.
Deine Aufgabe ist es, beide Dokumente sorgfältig und vergleichend zu analysieren, um die unten definierten **relevanten Tarifbestandteile** mit höchstmöglicher Genauigkeit zu extrahieren. Das Ergebnis **muss ausschließlich** ein einzelnes JSON-Objekt sein, das exakt die vorgegebenen Schlüsselnamen und das flache Key-Value-Format verwendet. Ignoriere irrelevante Informationen wie Anbieteradressen, AGB-Verweise oder allgemeine Marketingtexte.
**Extraktionsanweisungen und Felddefinitionen:**
1. **`tariff_name` (String):** Extrahiere den vollständigen, exakten Namen des Tarifs.
2. **`marketing_start_date` (String oder null):** Extrahiere das Vermarktungsdatum (aus PIB). Formatiere als `JJJJ-MM-TT` oder `null`.
3. **`network_operator` (String oder null):** Identifiziere den Netzbetreiber (z.B. "Telekom", "Vodafone", "O2").
4. **`network_technology` (String oder null):** Identifiziere die primär beworbene/höchste Netztechnologie (z.B. "5G", "LTE").
5. **`is_data_only_tariff` (Boolean):** Ermittle präzise, ob es ein reiner Datentarif ist (`true`/`false`). Ein Kriterium ist, wenn Telefonie nicht als Flat inkludiert ist oder explizit als "nicht möglich" gilt. Achte darauf, Tarife mit "Data" im Namen, die dennoch Telefonie/SMS-Flats haben könnten, nicht fälschlicherweise als reine Datentarife zu klassifizieren. Prüfe die Inklusivleistungen und Preise sorgfältig.
6. **`inclusive_internet_flat` (Boolean oder null):** Prüfe auf explizite Nennung einer Internet-Flat (`true`/`false`).
7. **`inclusive_telephony_flat` (Boolean oder null):** Prüfe auf explizite Nennung einer Telefonie-Flat oder Preis pro Minute von 0,00 € (`true`/`false`). Bei `is_data_only_tariff: true` setze auf `false`.
8. **`telephony_price_per_minute_eur_brutto` (Number oder null):** Wenn `inclusive_telephony_flat: false` und Telefonie möglich ist, extrahiere den Brutto-Preis pro Minute. Sonst `0.0` (bei Flat) oder `null` (wenn nicht möglich/gefunden).
9. **`telephony_price_per_minute_eur_netto` (Number oder null):** Wenn `telephony_price_per_minute_eur_brutto` ein Wert größer als 0 ist, berechne den Nettopreis (Bruttopreis / 1.19). Sonst `0.0` (bei Flat) oder `null`. Runde auf 4 Nachkommastellen.
10. **`inclusive_sms_flat` (Boolean oder null):** Prüfe auf explizite Nennung einer SMS-Flat oder Preis pro SMS von 0,00 € (`true`/`false`).
11. **`sms_price_per_unit_eur_brutto` (Number oder null):** Wenn `inclusive_sms_flat: false`, extrahiere den Brutto-Preis pro SMS. Sonst `0.0` (bei Flat) oder `null` (wenn nicht gefunden).
12. **`sms_price_per_unit_eur_netto` (Number oder null):** Wenn `sms_price_per_unit_eur_brutto` ein Wert größer als 0 ist, berechne den Nettopreis (Bruttopreis / 1.19). Sonst `0.0` (bei Flat) oder `null`. Runde auf 4 Nachkommastellen.
13. **`inclusive_volte_wlan_call` (Boolean oder null):** Prüfe auf explizite Nennung von VoLTE/WLAN-Call. Setze `true`, wenn erwähnt und `is_data_only_tariff: false`. Sonst `false`.
14. **`data_volume_gb` (Number oder null):** Extrahiere das Datenvolumen in GB.
15. **`data_download_max_mbps` (Number oder null):** Extrahiere max. Download in Mbit/s.
16. **`data_upload_max_mbps` (Number oder null):** Extrahiere max. Upload in Mbit/s.
17. **`data_download_throttled_kbps` (Number oder null):** Extrahiere Drossel-Download in kbit/s.
18. **`data_upload_throttled_kbps` (Number oder null):** Extrahiere Drossel-Upload in kbit/s.
19. **`data_billing_increment_kb` (Number oder null):** Extrahiere Datentaktung in KB.
20. **`telephony_billing_increment_seconds` (String oder null):** Extrahiere Telefontaktung (z.B. "60/60"). Setze `null` bei Datentarifen.
21. **`pricing_connection_fee_eur_brutto` (Number oder null):** Extrahiere den einmaligen Anschlusspreis (Brutto).
22. **`pricing_connection_fee_eur_netto` (Number oder null):** Berechne den Netto-Anschlusspreis (Bruttopreis / 1.19), falls Brutto vorhanden. Runde auf 4 Nachkommastellen.
23. **`pricing_monthly_initial_eur_brutto` (Number oder null):** Extrahiere den monatlichen Bruttopreis (initiale Periode).
24. **`pricing_monthly_initial_eur_netto` (Number oder null):** Extrahiere den monatlichen Nettopreis (initiale Periode), falls explizit genannt (oft in Klammern). Falls nicht genannt, berechne ihn (Bruttopreis / 1.19). Runde auf 4 Nachkommastellen.
25. **`pricing_monthly_after_period_eur_brutto` (Number oder null):** Extrahiere den monatlichen Bruttopreis nach der initialen Periode.
26. **`pricing_monthly_after_period_eur_netto` (Number oder null):** Berechne den monatlichen Nettopreis nach der initialen Periode (Bruttopreis / 1.19). Runde auf 4 Nachkommastellen.
27. **`contract_min_duration_months` (Number oder null):** Extrahiere die Mindestlaufzeit in Monaten.
28. **`contract_cancellation_notice_period_months` (Number oder null):** Extrahiere die Kündigungsfrist als Zahl der Monate (z.B. `1` aus "1 Monat").
**Wichtige Hinweise:**
* Verwende `null` für Werte, die nicht zuverlässig extrahiert werden können.
* Stelle sicher, dass numerische Werte als Zahlen (Number) im JSON erscheinen.
* Runde berechnete Nettopreise auf 4 Nachkommastellen.
* Die Ausgabe darf **nur das JSON-Objekt** enthalten, ohne jeglichen erläuternden Text davor oder danach.
**Gewünschtes JSON-Ausgabeformat (zur Referenz):**
{
"tariff_name": "...",
"marketing_start_date": "...",
"network_operator": "...",
"network_technology": "...",
"is_data_only_tariff": ...,
"inclusive_internet_flat": ...,
"inclusive_telephony_flat": ...,
"telephony_price_per_minute_eur_brutto": ...,
"telephony_price_per_minute_eur_netto": ...,
"inclusive_sms_flat": ...,
"sms_price_per_unit_eur_brutto": ...,
"sms_price_per_unit_eur_netto": ...,
"inclusive_volte_wlan_call": ...,
"data_volume_gb": ...,
"data_download_max_mbps": ...,
"data_upload_max_mbps": ...,
"data_download_throttled_kbps": ...,
"data_upload_throttled_kbps": ...,
"data_billing_increment_kb": ...,
"telephony_billing_increment_seconds": "...",
"pricing_connection_fee_eur_brutto": ...,
"pricing_connection_fee_eur_netto": ...,
"pricing_monthly_initial_eur_brutto": ...,
"pricing_monthly_initial_eur_netto": ...,
"pricing_monthly_after_period_eur_brutto": ...,
"pricing_monthly_after_period_eur_netto": ...,
"contract_min_duration_months": ...,
"contract_cancellation_notice_period_months": ...
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment