diff --git a/datenmanagement/models/constants_vars.py b/datenmanagement/models/constants_vars.py
index af64ae3..8cea0ee 100644
--- a/datenmanagement/models/constants_vars.py
+++ b/datenmanagement/models/constants_vars.py
@@ -78,6 +78,9 @@
linien_linie_message = 'Die Linie muss mit einer ' \
'Ziffer oder einem Großbuchstaben beginnen, der bzw. ' \
'dem optional weitere Ziffern und/oder Großbuchstaben folgen können.'
+mobilfunkantennen_stob_regex = r'^[0-9]{6,8}$'
+mobilfunkantennen_stob_message = 'Die Standortbescheinigungsnummer ' \
+ 'muss aus sechs bis acht Ziffern bestehen.'
parkscheinautomaten_bewohnerparkgebiet_regex = r'^[A-Z][0-9]$'
parkscheinautomaten_bewohnerparkgebiet_message = 'Das Bewohnerparkgebiet' \
' muss aus genau einem ' \
diff --git a/datenmanagement/models/models_simple.py b/datenmanagement/models/models_simple.py
index f3d24e2..a1b514c 100644
--- a/datenmanagement/models/models_simple.py
+++ b/datenmanagement/models/models_simple.py
@@ -25,7 +25,8 @@
hydranten_bezeichnung_regex, hydranten_bezeichnung_message, \
ingenieurbauwerke_nummer_asb_regex, ingenieurbauwerke_nummer_asb_message, \
ingenieurbauwerke_baujahr_regex, ingenieurbauwerke_baujahr_message, \
- kleinklaeranlagen_zulassung_regex, kleinklaeranlagen_zulassung_message, poller_nummer_regex, \
+ kleinklaeranlagen_zulassung_regex, kleinklaeranlagen_zulassung_message, \
+ mobilfunkantennen_stob_regex, mobilfunkantennen_stob_message, poller_nummer_regex, \
poller_nummer_message, trinkwassernotbrunnen_nummer_regex, trinkwassernotbrunnen_nummer_message
from .fields import ChoiceArrayField, NullTextField, PositiveSmallIntegerMinField, \
PositiveSmallIntegerRangeField, point_field, line_field, multiline_field, polygon_field, \
@@ -4040,6 +4041,138 @@ def __str__(self):
(', Adresse: ' + str(self.adresse) if self.adresse else '') + ']'
+class Mobilfunkantennen(SimpleModel):
+ """
+ Mobilfunkantennen
+ """
+
+ adresse = ForeignKey(
+ to=Adressen,
+ verbose_name='Adresse',
+ on_delete=SET_NULL,
+ db_column='adresse',
+ to_field='uuid',
+ related_name='%(app_label)s_%(class)s_adressen',
+ blank=True,
+ null=True
+ )
+ stob = CharField(
+ verbose_name='Standortbescheinigungsnummer',
+ max_length=255,
+ validators=[
+ RegexValidator(
+ regex=mobilfunkantennen_stob_regex,
+ message=mobilfunkantennen_stob_message
+ )
+ ]
+ )
+ erteilungsdatum = DateField(
+ verbose_name='Erteilungsdatum',
+ default=date.today
+ )
+ techniken = ArrayField(
+ CharField(
+ verbose_name='Techniken',
+ max_length=255,
+ blank=True,
+ null=True,
+ validators=standard_validators
+ ),
+ verbose_name='Techniken',
+ blank=True,
+ null=True
+ )
+ betreiber = ArrayField(
+ CharField(
+ verbose_name='Betreiber',
+ max_length=255,
+ blank=True,
+ null=True,
+ validators=standard_validators
+ ),
+ verbose_name='Betreiber',
+ blank=True,
+ null=True
+ )
+ montagehoehe = CharField(
+ verbose_name='Montagehöhe',
+ max_length=255,
+ blank=True,
+ null=True,
+ validators=standard_validators
+ )
+ anzahl_gsm = PositiveSmallIntegerMinField(
+ verbose_name='Anzahl GSM-Einheiten',
+ min_value=1,
+ blank=True,
+ null=True
+ )
+ anzahl_umts = PositiveSmallIntegerMinField(
+ verbose_name='Anzahl UMTS-Einheiten',
+ min_value=1,
+ blank=True,
+ null=True
+ )
+ anzahl_lte = PositiveSmallIntegerMinField(
+ verbose_name='Anzahl LTE-Einheiten',
+ min_value=1,
+ blank=True,
+ null=True
+ )
+ anzahl_sonstige = PositiveSmallIntegerMinField(
+ verbose_name='Anzahl sonstige Einheiten',
+ min_value=1,
+ blank=True,
+ null=True
+ )
+ geometrie = point_field
+
+ class Meta(SimpleModel.Meta):
+ db_table = 'fachdaten_adressbezug\".\"mobilfunkantennen_hro'
+ verbose_name = 'Mobilfunkantenne'
+ verbose_name_plural = 'Mobilfunkantennen'
+
+ class BasemodelMeta(SimpleModel.BasemodelMeta):
+ description = 'Mobilfunkantennen in der Hanse- und Universitätsstadt Rostock'
+ as_overlay = True
+ address_type = 'Adresse'
+ address_mandatory = False
+ geometry_type = 'Point'
+ list_fields = {
+ 'aktiv': 'aktiv?',
+ 'adresse': 'Adresse',
+ 'stob': 'Standortbescheinigungsnummer',
+ 'erteilungsdatum': 'Erteilungsdatum',
+ 'techniken': 'Techniken',
+ 'betreiber': 'Betreiber',
+ 'montagehoehe': 'Montagehöhe',
+ 'anzahl_gsm': 'Anzahl GSM-Einheiten',
+ 'anzahl_umts': 'Anzahl UMTS-Einheiten',
+ 'anzahl_lte': 'Anzahl LTE-Einheiten',
+ 'anzahl_sonstige': 'Anzahl sonstige Einheiten'
+ }
+ list_fields_with_date = ['erteilungsdatum']
+ list_fields_with_foreign_key = {
+ 'adresse': 'adresse'
+ }
+ map_feature_tooltip_fields = ['stob']
+ map_filter_fields = {
+ 'aktiv': 'aktiv?',
+ 'stob': 'Standortbescheinigungsnummer',
+ 'erteilungsdatum': 'Erteilungsdatum',
+ 'techniken': 'Techniken',
+ 'betreiber': 'Betreiber',
+ 'montagehoehe': 'Montagehöhe',
+ 'anzahl_gsm': 'Anzahl GSM-Einheiten',
+ 'anzahl_umts': 'Anzahl UMTS-Einheiten',
+ 'anzahl_lte': 'Anzahl LTE-Einheiten',
+ 'anzahl_sonstige': 'Anzahl sonstige Einheiten'
+ }
+
+ def __str__(self):
+ return self.stob
+
+
class Mobilpunkte(SimpleModel):
"""
Mobilpunkte
diff --git a/datenmanagement/sql/schema.sql b/datenmanagement/sql/schema.sql
index 4de9f3c..867524a 100644
--- a/datenmanagement/sql/schema.sql
+++ b/datenmanagement/sql/schema.sql
@@ -115,7 +115,7 @@ CREATE FUNCTION fachdaten.foto() RETURNS trigger
AS $$
BEGIN
IF NEW.foto = '' THEN
- NEW.foto := NULL;
+ NEW.foto := NULL;
END IF;
RETURN NEW;
END;
@@ -3430,6 +3430,32 @@ CREATE TABLE fachdaten_adressbezug.meldedienst_punkthaft_hro (
);
+--
+-- Name: mobilfunkantennen_hro; Type: TABLE; Schema: fachdaten_adressbezug; Owner: -
+--
+
+CREATE TABLE fachdaten_adressbezug.mobilfunkantennen_hro (
+ uuid uuid DEFAULT public.uuid_generate_v4() NOT NULL,
+ aktualisiert date DEFAULT (now())::date NOT NULL,
+ erstellt date DEFAULT (now())::date NOT NULL,
+ id_fachsystem character varying(255),
+ id_zielsystem character varying(255),
+ aktiv boolean DEFAULT true NOT NULL,
+ deaktiviert date,
+ adresse uuid,
+ stob character varying(8) NOT NULL,
+ erteilungsdatum date NOT NULL,
+ techniken character varying(255)[],
+ betreiber character varying(255)[],
+ montagehoehe character varying(255),
+ anzahl_gsm smallint,
+ anzahl_umts smallint,
+ anzahl_lte smallint,
+ anzahl_sonstige smallint,
+ geometrie public.geometry(Point,25833) NOT NULL
+);
+
+
--
-- Name: parkmoeglichkeiten_hro; Type: TABLE; Schema: fachdaten_adressbezug; Owner: -
--
@@ -6269,6 +6295,22 @@ ALTER TABLE ONLY fachdaten_adressbezug.meldedienst_punkthaft_hro
ADD CONSTRAINT meldedienst_punkthaft_hro_pk PRIMARY KEY (uuid);
+--
+-- Name: mobilfunkantennen_hro mobilfunkantennen_hro_pk; Type: CONSTRAINT; Schema: fachdaten_adressbezug; Owner: -
+--
+
+ALTER TABLE ONLY fachdaten_adressbezug.mobilfunkantennen_hro
+ ADD CONSTRAINT mobilfunkantennen_hro_pk PRIMARY KEY (uuid);
+
+
+--
+-- Name: mobilfunkantennen_hro mobilfunkantennen_hro_stob_unique; Type: CONSTRAINT; Schema: fachdaten_adressbezug; Owner: -
+--
+
+ALTER TABLE ONLY fachdaten_adressbezug.mobilfunkantennen_hro
+ ADD CONSTRAINT mobilfunkantennen_hro_stob_unique UNIQUE (stob);
+
+
--
-- Name: parkmoeglichkeiten_hro parkmoeglichkeiten_hro_pk; Type: CONSTRAINT; Schema: fachdaten_adressbezug; Owner: -
--
diff --git a/datenmanagement/tests/test_models_simple.py b/datenmanagement/tests/test_models_simple.py
index bd7b9d1..9a8ee2e 100644
--- a/datenmanagement/tests/test_models_simple.py
+++ b/datenmanagement/tests/test_models_simple.py
@@ -18,10 +18,10 @@
Hydranten, Ingenieurbauwerke, Kadaverfunde, Kehrbezirke, Kindertagespflegeeinrichtungen, \
Kinder_Jugendbetreuung, Kleinklaeranlagen, Kunst_im_oeffentlichen_Raum, \
Ladestationen_Elektrofahrzeuge, Materialien_Denksteine, Meldedienst_flaechenhaft, \
- Meldedienst_punkthaft, Mobilpunkte, Parkmoeglichkeiten, Pflegeeinrichtungen, Poller, Quartiere, \
- Reinigungsreviere, Reisebusparkplaetze_Terminals, Rettungswachen, Schiffsliegeplaetze, \
- Schlagwoerter_Bildungstraeger, Schlagwoerter_Vereine, Schutzzaeune_Tierseuchen, Sportarten, \
- Sportanlagen, Sporthallen, Stadtteil_Begegnungszentren, \
+ Meldedienst_punkthaft, Mobilfunkantennen, Mobilpunkte, Parkmoeglichkeiten, Pflegeeinrichtungen, \
+ Poller, Quartiere, Reinigungsreviere, Reisebusparkplaetze_Terminals, Rettungswachen, \
+ Schiffsliegeplaetze, Schlagwoerter_Bildungstraeger, Schlagwoerter_Vereine, \
+ Schutzzaeune_Tierseuchen, Sportarten, Sportanlagen, Sporthallen, Stadtteil_Begegnungszentren, \
Standortqualitaeten_Geschaeftslagen_Sanierungsgebiet, \
Standortqualitaeten_Wohnlagen_Sanierungsgebiet, Status_Baudenkmale_Denkmalbereiche, \
Status_Poller, Strassen, Thalasso_Kurwege, Tierseuchen, Toiletten, Trinkwassernotbrunnen, \
@@ -7978,6 +7978,246 @@ def test_view_geometry_lat_lng(self):
)
+class MobilfunkantennenTest(DefaultSimpleModelTestCase):
+ """
+ Mobilfunkantennen
+ """
+
+ model = Mobilfunkantennen
+ create_test_object_in_classmethod = False
+ create_test_subset_in_classmethod = False
+
+ @classmethod
+ def setUpTestData(cls):
+ super().setUpTestData()
+ adresse = Adressen.objects.create(
+ adresse='Adresse'
+ )
+ cls.attributes_values_db_initial = {
+ 'adresse': adresse,
+ 'stob': '1234567',
+ 'erteilungsdatum': VALID_DATE,
+ 'geometrie': VALID_POINT_DB
+ }
+ cls.attributes_values_db_updated = {
+ 'stob': '2345678'
+ }
+ cls.attributes_values_view_initial = {
+ 'aktiv': True,
+ 'adresse': str(adresse.pk),
+ 'stob': '7654321',
+ 'erteilungsdatum': VALID_DATE,
+ 'geometrie': VALID_POINT_VIEW
+ }
+ cls.attributes_values_view_updated = {
+ 'aktiv': True,
+ 'adresse': str(adresse.pk),
+ 'stob': '8765432',
+ 'erteilungsdatum': VALID_DATE,
+ 'geometrie': VALID_POINT_VIEW
+ }
+ cls.attributes_values_view_invalid = {
+ 'montagehoehe': INVALID_STRING
+ }
+ cls.test_object = cls.model.objects.create(**cls.attributes_values_db_initial)
+ cls.test_subset = create_test_subset(cls.model, cls.test_object)
+
+ def setUp(self):
+ self.init()
+
+ def test_is_simplemodel(self):
+ self.generic_is_simplemodel_test()
+
+ def test_create(self):
+ self.generic_create_test(self.model, self.attributes_values_db_initial)
+
+ def test_update(self):
+ self.generic_update_test(self.model, self.attributes_values_db_updated)
+
+ def test_delete(self):
+ self.generic_delete_test(self.model)
+
+ def test_view_start(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_start',
+ {},
+ 200,
+ 'text/html; charset=utf-8',
+ START_VIEW_STRING
+ )
+
+ def test_view_list(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_list',
+ {},
+ 200,
+ 'text/html; charset=utf-8',
+ LIST_VIEW_STRING
+ )
+
+ def test_view_list_subset(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_list_subset',
+ {'subset_id': self.test_subset.pk},
+ 200,
+ 'text/html; charset=utf-8',
+ LIST_VIEW_STRING
+ )
+
+ def test_view_data(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_data',
+ DATA_VIEW_PARAMS,
+ 200,
+ 'application/json',
+ str(self.test_object.pk)
+ )
+
+ def test_view_data_subset(self):
+ data_subset_view_params = DATA_VIEW_PARAMS.copy()
+ data_subset_view_params['subset_id'] = self.test_subset.pk
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_data_subset',
+ data_subset_view_params,
+ 200,
+ 'application/json',
+ str(self.test_object.pk)
+ )
+
+ def test_view_map(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_map',
+ {},
+ 200,
+ 'text/html; charset=utf-8',
+ MAP_VIEW_STRING
+ )
+
+ def test_view_map_subset(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_map_subset',
+ {'subset_id': self.test_subset.pk},
+ 200,
+ 'text/html; charset=utf-8',
+ MAP_VIEW_STRING
+ )
+
+ def test_view_mapdata(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_mapdata',
+ {},
+ 200,
+ 'application/json',
+ str(self.test_object.pk)
+ )
+
+ def test_view_mapdata_subset(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_mapdata_subset',
+ {'subset_id': self.test_subset.pk},
+ 200,
+ 'application/json',
+ str(self.test_object.pk)
+ )
+
+ def test_view_add_success(self):
+ self.generic_add_update_view_test(
+ False,
+ self.model,
+ self.attributes_values_view_initial,
+ 302,
+ 'text/html; charset=utf-8',
+ 1
+ )
+
+ def test_view_add_error(self):
+ self.generic_add_update_view_test(
+ False,
+ self.model,
+ self.attributes_values_view_invalid,
+ 200,
+ 'text/html; charset=utf-8',
+ 0
+ )
+
+ def test_view_change_success(self):
+ self.generic_add_update_view_test(
+ True,
+ self.model,
+ self.attributes_values_view_updated,
+ 302,
+ 'text/html; charset=utf-8',
+ 1
+ )
+
+ def test_view_change_error(self):
+ self.generic_add_update_view_test(
+ True,
+ self.model,
+ self.attributes_values_view_invalid,
+ 200,
+ 'text/html; charset=utf-8',
+ 0
+ )
+
+ def test_view_delete(self):
+ self.generic_delete_view_test(
+ False,
+ self.model,
+ self.attributes_values_db_initial,
+ 302,
+ 'text/html; charset=utf-8'
+ )
+
+ def test_view_deleteimmediately(self):
+ self.generic_delete_view_test(
+ True,
+ self.model,
+ self.attributes_values_db_initial,
+ 204,
+ 'text/html; charset=utf-8'
+ )
+
+ def test_view_geometry(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_geometry',
+ {},
+ 200,
+ 'application/json',
+ str(self.test_object.pk)
+ )
+
+ def test_view_geometry_pk(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_geometry',
+ {'pk': str(self.test_object.pk)},
+ 200,
+ 'application/json',
+ str(self.test_object.pk)
+ )
+
+ def test_view_geometry_lat_lng(self):
+ self.generic_view_test(
+ self.model,
+ self.model.__name__ + '_geometry',
+ GEOMETRY_VIEW_PARAMS,
+ 200,
+ 'application/json',
+ str(self.test_object.pk)
+ )
+
+
class MobilpunkteTest(DefaultSimpleModelTestCase):
"""
Mobilpunkte