Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ verify_ssl = true
name = "pypi"

[packages]
django = "~=5.0.11"
django = "~=5.0.13"
django-ninja = "~=1.1"
psycopg2-binary = "~=2.9.5"
django-environ = "~=0.11"
Expand Down
392 changes: 200 additions & 192 deletions Pipfile.lock

Large diffs are not rendered by default.

25 changes: 7 additions & 18 deletions app/bod/management/commands/bod_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,7 @@ def import_providers(self) -> None:
processed = set()

for organization in BodContactOrganisation.objects.all():
if organization.attribution is not None and len(
organization.attribution.split('.')
) != 2:
if not organization.attribution or len(organization.attribution.split('.')) != 2:
# Skip entries that are not a provider.
# BodContactOrganisation (table 'contactorganisation') contains providers and
# attributions. Providers are of the format "ch.<short_name>" and only include a
Expand All @@ -99,7 +97,7 @@ def import_providers(self) -> None:
is_new_model = True
provider = Provider.objects.create(
_legacy_id=legacy_id,
provider_id=organization.attribution, # type:ignore[misc]
provider_id=organization.attribution,
acronym_de="undefined",
acronym_fr="undefined",
acronym_en="undefined",
Expand Down Expand Up @@ -171,8 +169,8 @@ def import_attribution(self) -> None:
processed.add(legacy_id)

# Get related provider
provider: Provider | None
if organization.attribution is not None:
provider = None
if organization.attribution:
provider_of_attribution = ".".join(organization.attribution.split(".", 2)[:2])
provider = Provider.objects.filter(provider_id=provider_of_attribution).first()
if not provider:
Expand Down Expand Up @@ -256,7 +254,7 @@ def import_datasets(self) -> None:
"""

processed = set()
for bod_dataset in BodDataset.objects.all():
for bod_dataset in BodDataset.objects.filter(staging='prod').all():
# Keep track of processed BOD datasets for orphan removal
legacy_id = bod_dataset.id
processed.add(legacy_id)
Expand All @@ -273,24 +271,15 @@ def import_datasets(self) -> None:
)
continue

# Get related provider
provider = Provider.objects.filter(id=attribution.provider_id).first()
if not provider:
# Skip as no matching provider
self.print(
f"skipping dataset '{bod_dataset.id_dataset}' as no matching provider was found"
)
continue

# Get or create dataset
is_new_model = False
dataset = Dataset.objects.filter(
provider=provider, attribution=attribution, _legacy_id=legacy_id
provider=attribution.provider, attribution=attribution, _legacy_id=legacy_id
).first()
if not dataset:
is_new_model = True
dataset = Dataset.objects.create(
provider=provider,
provider=attribution.provider,
attribution=attribution,
_legacy_id=legacy_id,
dataset_id='undefined'
Expand Down
3 changes: 2 additions & 1 deletion app/bod/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0.9 on 2024-10-03 13:55
# Generated by Django 5.0.12 on 2025-03-11 11:57

from django.conf import settings
from django.db import migrations
Expand Down Expand Up @@ -39,6 +39,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(primary_key=True, serialize=False, unique=True)),
('id_dataset', models.TextField()),
('fk_contactorganisation_id', models.IntegerField(blank=True, null=True)),
('staging', models.TextField(blank=True, null=True)),
],
options={
'db_table': 'dataset',
Expand Down
1 change: 1 addition & 0 deletions app/bod/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class BodDataset(models.Model):
id = models.AutoField(unique=True, primary_key=True)
id_dataset = models.TextField()
fk_contactorganisation_id = models.IntegerField(blank=True, null=True)
staging = models.TextField(blank=True, null=True)

class Meta:
managed = settings.TESTING
Expand Down
90 changes: 66 additions & 24 deletions app/tests/bod/test_bod_sync_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def fixture_bod_dataset(bod_contact_organisation):
yield BodDataset.objects.create(
id=170,
id_dataset="ch.bafu.auen-vegetationskarten",
fk_contactorganisation_id=bod_contact_organisation.pk_contactorganisation_id
fk_contactorganisation_id=bod_contact_organisation.pk_contactorganisation_id,
staging="prod"
)


Expand Down Expand Up @@ -131,17 +132,22 @@ def test_command_imports_providers(bod_dataset):
assert provider.acronym_rm == "UFAM"


def test_command_imports_attributions(bod_contact_organisation, bod_dataset):
out = StringIO()
call_command(
"bod_sync", providers=False, attributions=True, datasets=False, verbosity=2, stdout=out
)
assert "skipping attribution 'ch.bafu' as no matching provider was found" in out.getvalue()
assert 'nothing to be done, already in sync' in out.getvalue()
assert Provider.objects.count() == 0
assert Attribution.objects.count() == 0
assert Dataset.objects.count() == 0
def test_command_skips_invalid_providers(bod_contact_organisation, bod_dataset):
for attribution in ("somethingelse", "", None):
bod_contact_organisation.attribution = attribution
bod_contact_organisation.save()

out = StringIO()
call_command(
"bod_sync", providers=True, attributions=False, datasets=False, verbosity=2, stdout=out
)
assert "nothing to be done" in out.getvalue()
assert Provider.objects.count() == 0
assert Attribution.objects.count() == 0
assert Dataset.objects.count() == 0


def test_command_imports_attributions(bod_contact_organisation, bod_dataset):
provider = Provider.objects.create(
provider_id="ch.bafu",
name_de="XXX",
Expand All @@ -152,6 +158,8 @@ def test_command_imports_attributions(bod_contact_organisation, bod_dataset):
acronym_en="XXX",
_legacy_id=bod_contact_organisation.pk_contactorganisation_id
)

out = StringIO()
call_command(
"bod_sync", providers=False, attributions=True, datasets=False, verbosity=2, stdout=out
)
Expand All @@ -175,20 +183,24 @@ def test_command_imports_attributions(bod_contact_organisation, bod_dataset):
assert attribution.description_rm == "UFAM"


def test_command_imports_datasets(bod_contact_organisation, bod_dataset):
out = StringIO()
call_command(
"bod_sync", providers=False, attributions=False, datasets=True, verbosity=2, stdout=out
)
assert (
"skipping dataset 'ch.bafu.auen-vegetationskarten' " +
"as no matching attribution was found"
) in out.getvalue()
assert 'nothing to be done, already in sync' in out.getvalue()
assert Provider.objects.count() == 0
assert Attribution.objects.count() == 0
assert Dataset.objects.count() == 0
def test_command_skips_invalid_attributions(bod_contact_organisation, bod_dataset):
for attribution in (bod_contact_organisation.attribution, "", None):
bod_contact_organisation.attribution = attribution
bod_contact_organisation.save()

out = StringIO()
call_command(
"bod_sync", providers=False, attributions=True, datasets=False, verbosity=2, stdout=out
)
assert (f"skipping attribution '{attribution}' as no matching provider was found"
) in out.getvalue()
assert 'nothing to be done, already in sync' in out.getvalue()
assert Provider.objects.count() == 0
assert Attribution.objects.count() == 0
assert Dataset.objects.count() == 0


def test_command_imports_datasets(bod_contact_organisation, bod_dataset):
provider = Provider.objects.create(
provider_id="ch.bafu",
name_de="XXX",
Expand All @@ -210,6 +222,8 @@ def test_command_imports_datasets(bod_contact_organisation, bod_dataset):
provider=provider,
_legacy_id=bod_contact_organisation.pk_contactorganisation_id
)

out = StringIO()
call_command(
"bod_sync", providers=False, attributions=False, datasets=True, verbosity=2, stdout=out
)
Expand All @@ -224,6 +238,34 @@ def test_command_imports_datasets(bod_contact_organisation, bod_dataset):
assert dataset.dataset_id == "ch.bafu.auen-vegetationskarten"


def test_command_skips_invalid_datasets(bod_dataset):
out = StringIO()
call_command(
"bod_sync", providers=False, attributions=False, datasets=True, verbosity=2, stdout=out
)
assert (
"skipping dataset 'ch.bafu.auen-vegetationskarten' " +
"as no matching attribution was found"
) in out.getvalue()
assert 'nothing to be done, already in sync' in out.getvalue()
assert Provider.objects.count() == 0
assert Attribution.objects.count() == 0
assert Dataset.objects.count() == 0


def test_command_skips_non_prod_datasets(bod_dataset):
bod_dataset.staging = 'test'

out = StringIO()
call_command(
"bod_sync", providers=False, attributions=False, datasets=True, verbosity=2, stdout=out
)
assert 'nothing to be done, already in sync' in out.getvalue()
assert Provider.objects.count() == 0
assert Attribution.objects.count() == 0
assert Dataset.objects.count() == 0


def test_command_updates(bod_contact_organisation, bod_dataset):
# Add objects that will be updated
provider = Provider.objects.create(
Expand Down
Loading