#131 EGON export

* finishes egon compatible (tested) data export
* moves egon export into celery process
* adds export of data in case of intervention recording
* adds _RABBITMQ_ settings for intervention/settings.py
* adds new dependency for requirements.txt
This commit is contained in:
mpeltriaux 2022-03-21 12:14:55 +01:00
parent 17c954e844
commit 7689e0b80d
5 changed files with 120 additions and 23 deletions

View File

@ -13,6 +13,7 @@ from django.db.models.fields.files import FieldFile
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from intervention.tasks import celery_export_to_egon
from user.models import User from user.models import User
from django.db import models, transaction from django.db import models, transaction
from django.db.models import QuerySet from django.db.models import QuerySet
@ -131,9 +132,20 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
self.add_log_entry_to_compensations(log_entry) self.add_log_entry_to_compensations(log_entry)
return log_entry return log_entry
def send_data_to_egon(self):
""" Performs the export to rabbitmq of this intervention's data
FOLLOWING BACKWARDS COMPATIBILITY LOGIC
Returns:
"""
celery_export_to_egon.delay(self.id)
def set_recorded(self, user: User) -> UserActionLogEntry: def set_recorded(self, user: User) -> UserActionLogEntry:
log_entry = super().set_recorded(user) log_entry = super().set_recorded(user)
self.add_log_entry_to_compensations(log_entry) self.add_log_entry_to_compensations(log_entry)
self.send_data_to_egon()
return log_entry return log_entry
def add_log_entry_to_compensations(self, log_entry: UserActionLogEntry): def add_log_entry_to_compensations(self, log_entry: UserActionLogEntry):

View File

@ -7,3 +7,10 @@ Created on: 30.11.20
""" """
INTERVENTION_IDENTIFIER_LENGTH = 6 INTERVENTION_IDENTIFIER_LENGTH = 6
INTERVENTION_IDENTIFIER_TEMPLATE = "EIV-{}" INTERVENTION_IDENTIFIER_TEMPLATE = "EIV-{}"
# EGON connection settings via rabbitmq
# NEEDED FOR BACKWARDS COMPATIBILITY
EGON_RABBITMQ_HOST = "CHANGE_ME"
EGON_RABBITMQ_PORT = "CHANGE_ME"
EGON_RABBITMQ_USER = "CHANGE_ME"
EGON_RABBITMQ_PW = "CHANGE_ME"

18
intervention/tasks.py Normal file
View File

@ -0,0 +1,18 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 21.03.22
"""
from celery import shared_task
from intervention.utils.egon_export import EgonExporter
@shared_task
def celery_export_to_egon(intervention_id: str):
from intervention.models import Intervention
intervention = Intervention.objects.get(id=intervention_id)
egon_exporter = EgonExporter(intervention)
egon_exporter.export_to_rabbitmq()

View File

@ -6,12 +6,14 @@ Created on: 07.03.22
""" """
import base64 import base64
import json
import pika
import xmltodict import xmltodict
from django.db.models import Sum from django.db.models import Sum
from django.utils import formats
from intervention.models import Intervention from intervention.settings import EGON_RABBITMQ_HOST, EGON_RABBITMQ_USER, EGON_RABBITMQ_PW, EGON_RABBITMQ_PORT
from konova.sub_settings.django_settings import DEFAULT_DATE_FORMAT
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
@ -26,12 +28,36 @@ class EgonExporter:
intervention = None intervention = None
gml_builder = None gml_builder = None
def __init__(self, intervention: Intervention): def __init__(self, intervention):
self.intervention = intervention self.intervention = intervention
self.gml_builder = EgonGmlBuilder(intervention) self.gml_builder = EgonGmlBuilder(intervention)
def export_to_rabbitmq(self): def export_to_rabbitmq(self):
raise NotImplementedError("ToDo!") """ Sends the exporter gml to message broker rabbitmq to be fetched by EGON application from there
Returns:
"""
msg = {
"nachricht": self.gml_builder.gml,
}
msg = json.dumps(msg)
print(msg)
credentials = pika.PlainCredentials(EGON_RABBITMQ_USER, EGON_RABBITMQ_PW)
params = pika.ConnectionParameters(
EGON_RABBITMQ_HOST,
EGON_RABBITMQ_PORT,
"/",
credentials
)
conn = pika.BlockingConnection(params)
channel = conn.channel()
channel.basic_publish(
exchange="",
routing_key="KSP_EGON",
body=msg.encode("utf-8"),
)
conn.close()
class EgonGmlBuilder: class EgonGmlBuilder:
@ -41,7 +67,7 @@ class EgonGmlBuilder:
intervention = None intervention = None
gml = None gml = None
def __init__(self, intervention: Intervention): def __init__(self, intervention):
self.intervention = intervention self.intervention = intervention
self.gml = self.build_gml() self.gml = self.build_gml()
@ -66,11 +92,13 @@ class EgonGmlBuilder:
)["summed"] )["summed"]
return all_payments return all_payments
def _gen_kompensationsArt(self): def _gen_kompensationsArt(self) -> (str, int):
comp_type = "Ersatzzahlung" comp_type = "Ersatzzahlung"
comp_type_code = 774898901
if self.intervention.compensations.exists(): if self.intervention.compensations.exists():
comp_type += " und Kompensation" comp_type += " und Kompensation"
return comp_type comp_type_code = 771655351
return comp_type, comp_type_code
def _gen_geometry_list(self): def _gen_geometry_list(self):
geom = self.intervention.geometry.geom geom = self.intervention.geometry.geom
@ -80,7 +108,7 @@ class EgonGmlBuilder:
"gml:Polygon": { "gml:Polygon": {
"gml:exterior": { "gml:exterior": {
"gml:LinearRing": { "gml:LinearRing": {
"gml:posList": " ".join([f"{str(coord[0])},{str(coord[1])}" for coord in coords[0]]) "gml:posList": " ".join([f"{str(coord[0])} {str(coord[1])}" for coord in coords[0]])
} }
} }
} }
@ -95,9 +123,15 @@ class EgonGmlBuilder:
"oneo:datumAbgleich": None, "oneo:datumAbgleich": None,
"oneo:ortsangabe": { "oneo:ortsangabe": {
"oneo:Ortsangaben": { "oneo:Ortsangaben": {
"oneo:kreisSchluessel": parcel.district.krs, "oneo:kreisSchluessel": {
"oneo:gemeindeSchluessel": parcel.district.gmnd, "xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/588/{parcel.district.krs}",
"oneo:verbandsgemeindeSchluessel": parcel.gmrkng, },
"oneo:gemeindeSchluessel": {
"xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/910/{parcel.district.gmnd}",
},
"oneo:verbandsgemeindeSchluessel": {
"xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/589/{parcel.gmrkng}",
},
"oneo:flurstuecksKennzeichen": self._gen_flurstuecksKennzeichen(parcel), "oneo:flurstuecksKennzeichen": self._gen_flurstuecksKennzeichen(parcel),
} }
}, },
@ -110,7 +144,7 @@ class EgonGmlBuilder:
docs_list = [ docs_list = [
{ {
"oneo:Foto": { "oneo:Foto": {
"oneo:aufnahmezeitpunkt": formats.localize(doc.date_of_creation), "oneo:aufnahmezeitpunkt": doc.date_of_creation.strftime(DEFAULT_DATE_FORMAT),
"oneo:bemerkung": doc.comment, "oneo:bemerkung": doc.comment,
"oneo:fotoverweis": base64.b64encode(doc.file.read()).decode("utf-8"), "oneo:fotoverweis": base64.b64encode(doc.file.read()).decode("utf-8"),
"oneo:dateiname": doc.title, "oneo:dateiname": doc.title,
@ -121,23 +155,48 @@ class EgonGmlBuilder:
return docs_list return docs_list
def build_gml(self): def build_gml(self):
comp_type, comp_type_code = self._gen_kompensationsArt()
xml_dict = { xml_dict = {
"wfs:FeatureCollection": { "wfs:FeatureCollection": {
"@xmlns:wfs": "http://www.opengis.net/wfs",
"@xmlns:xlink": "http://www.w3.org/1999/xlink",
"@xmlns:oneo": "http://www.osiris-projekt.rlp.de/oneo",
"@xmlns:gmlexr": "http://www.opengis.net/gml/3.3/exr",
"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"@xmlns:gml": "http://www.opengis.net/gml/3.2",
"oneo:Eingriffsverfahren": { "oneo:Eingriffsverfahren": {
"@gml:id": self.intervention.identifier, "@gml:id": self.intervention.identifier,
"oneo:azEintragungsstelle": self.intervention.responsible.conservation_file_number, "oneo:azEintragungsstelle": self.intervention.responsible.conservation_file_number,
"oneo:azZulassungsstelle": self.intervention.responsible.registration_file_number, "oneo:azZulassungsstelle": self.intervention.responsible.registration_file_number,
"oneo:bemerkungZulassungsstelle": None, "oneo:bemerkungZulassungsstelle": None,
"oneo:eintragungsstelle": self.intervention.responsible.conservation_office.long_name, "oneo:eintragungsstelle": {
"oneo:zulassungsstelle": self.intervention.responsible.registration_office.long_name, "@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/907/{self.intervention.responsible.conservation_office.atom_id}",
"#text": self.intervention.responsible.conservation_office.long_name
},
"oneo:zulassungsstelle": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{self.intervention.responsible.registration_office.atom_id}",
"#text": self.intervention.responsible.registration_office.long_name
},
"oneo:ersatzzahlung": self._sum_all_payments(), "oneo:ersatzzahlung": self._sum_all_payments(),
"oneo:kompensationsart": self._gen_kompensationsArt(), "oneo:kompensationsart": {
"oneo:verfahrensrecht": self.intervention.legal.laws.first().short_name, "@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/88140/{comp_type_code}",
"oneo:verfahrenstyp": self.intervention.legal.process_type.long_name, "#text": comp_type
},
"oneo:verfahrensrecht": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1048/{self.intervention.legal.laws.first().atom_id}",
"#text": self.intervention.legal.laws.first().short_name
},
"oneo:verfahrenstyp": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/44382/{self.intervention.legal.process_type.atom_id}",
"#text": self.intervention.legal.process_type.long_name,
},
"oneo:eingreifer": { "oneo:eingreifer": {
"oneo:Eingreifer": { "oneo:Eingreifer": {
"oneo:art": self.intervention.responsible.handler.type.long_name, "oneo:art": {
"oneo:bemerkung": self.intervention.responsible.handler.type.long_name, "@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{self.intervention.responsible.handler.type.atom_id}",
"#text": self.intervention.responsible.handler.type.long_name,
},
"oneo:bemerkung": self.intervention.responsible.handler.detail,
} }
}, },
"oneo:erfasser": { "oneo:erfasser": {
@ -148,9 +207,9 @@ class EgonGmlBuilder:
}, },
"oneo:zulassung": { "oneo:zulassung": {
"oneo:Zulassungstermin": { "oneo:Zulassungstermin": {
"oneo:bauBeginn": formats.localize(self.intervention.payments.first().due_on), "oneo:bauBeginn": self.intervention.payments.first().due_on.strftime(DEFAULT_DATE_FORMAT),
"oneo:erlass": formats.localize(self.intervention.legal.registration_date), "oneo:erlass": self.intervention.legal.registration_date.strftime(DEFAULT_DATE_FORMAT),
"oneo:rechtsKraft": formats.localize(self.intervention.legal.binding_date), "oneo:rechtsKraft": self.intervention.legal.binding_date.strftime(DEFAULT_DATE_FORMAT),
} }
}, },
"oneo:geometrie": { "oneo:geometrie": {

View File

@ -28,6 +28,7 @@ kombu==5.2.3
openpyxl==3.0.9 openpyxl==3.0.9
OWSLib==0.25.0 OWSLib==0.25.0
packaging==21.3 packaging==21.3
pika==1.2.0
prompt-toolkit==3.0.24 prompt-toolkit==3.0.24
psycopg2-binary==2.9.1 psycopg2-binary==2.9.1
pyparsing==3.0.6 pyparsing==3.0.6