Skip to content
Snippets Groups Projects
Commit b7ba3c62 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Merge branch '40-allow-selecting-plan-version-and-default-to-newest-version' into 'master'

Resolve "Allow selecting plan version and default to newest version"

Closes #40

See merge request !117
parents 74fb0271 e9406719
No related branches found
No related tags found
1 merge request!117Resolve "Allow selecting plan version and default to newest version"
Pipeline #65986 failed
......@@ -9,6 +9,16 @@ and this project adheres to `Semantic Versioning`_.
Unreleased
----------
Added
~~~~~
* Plan version can be explicitly selected (defaulting to newest)
Fixed
~~~~~
* Import now only imports one plan version
`2.1`_ - 2022-01-13
-------------------
......
......@@ -32,7 +32,7 @@ Licence
Copyright © 2018, 2019, 2020, 2021 Jonathan Weth <dev@jonathanweth.de>
Copyright © 2018, 2019 Frank Poetzsch-Heffter <p-h@katharineum.de>
Copyright © 2019, 2020, 2021 Dominik George <dominik.george@teckids.org>
Copyright © 2019, 2020, 2021, 2022 Dominik George <dominik.george@teckids.org>
Copyright © 2019, 2020 Tom Teichler <tom.teichler@teckids.org>
Copyright © 2019 Julian Leucker <leuckeju@katharineum.de>
Copyright © 2019 mirabilos <thorsten.glaser@teckids.org>
......
......@@ -12,7 +12,7 @@ class UntisConfig(AppConfig):
copyright_info = (
([2018, 2019, 2020, 2021], "Jonathan Weth", "dev@jonathanweth.de"),
([2018, 2019], "Frank Poetzsch-Heffter", "p-h@katharineum.de"),
([2019, 2020, 2021], "Dominik George", "dominik.george@teckids.org"),
([2019, 2020, 2021, 2022], "Dominik George", "dominik.george@teckids.org"),
([2019, 2020], "Tom Teichler", "tom.teichler@teckids.org"),
([2019], "Julian Leucker", "leuckeju@katharineum.de"),
([2019], "mirabilos", "thorsten.glaser@teckids.org"),
......
......@@ -27,15 +27,15 @@ class ImportCommand:
return None
@classmethod
def run(cls, background: bool = False):
def run(cls, background: bool = False, version: Optional[int] = None):
"""Run the import command (foreground/background)."""
if background:
from .tasks import TASKS
task = TASKS[cls.task_name]
task.delay()
task.delay(version=version)
else:
_untis_import_mysql(cls.get_terms())
_untis_import_mysql(cls.get_terms(), version=version)
class CurrentImportCommand(ImportCommand):
......
......@@ -13,8 +13,13 @@ class Command(BaseCommand):
action="store_true",
help="Run import job in background using Celery",
)
parser.add_argument(
"--plan-version",
help="Select explicit Untis plan version",
)
def handle(self, *args, **options):
command = COMMANDS_BY_NAME[options["command"]]
background = options["background"]
command.run(background=background)
version = options.get("plan_version", None)
command.run(background=background, version=version)
......@@ -6,8 +6,8 @@ TASKS = {}
for import_command in ImportCommand.__subclasses__():
@app.task(name=import_command.task_name, bind=True)
def _task(self):
def _task(self, *args, **kwargs):
import_command = COMMANDS_BY_TASK_NAME[self.name]
import_command.run()
import_command.run(*args, **kwargs)
TASKS[import_command.task_name] = _task
......@@ -2,7 +2,7 @@ import logging
from datetime import date
from typing import Dict, Optional
from django.db.models import QuerySet
from django.db.models import Max, OuterRef, QuerySet, Subquery
from django.utils import timezone
from tqdm import tqdm
......@@ -49,12 +49,31 @@ logger = logging.getLogger(__name__)
def import_terms(
qs: Optional[QuerySet] = None,
version: Optional[int] = None,
) -> Dict[int, chronos_models.ValidityRange]:
"""Import terms and school years as validity ranges and school terms."""
ranges_ref = {}
if not isinstance(qs, QuerySet):
qs = run_using(mysql_models.Terms.objects).all()
qs = run_using(mysql_models.Terms.objects)
if version is None:
# Select newest version per term / validity range
sub_qs = (
run_using(mysql_models.Terms.objects)
.filter(
school_id=OuterRef("school_id"),
schoolyear_id=OuterRef("schoolyear_id"),
term_id=OuterRef("term_id"),
)
.values("school_id", "schoolyear_id", "term_id")
.annotate(max_version=Max("version_id"))
.values("max_version")
)
qs = qs.filter(version_id=Subquery(sub_qs))
else:
# Select passed version
qs = qs.filter(version_id=version)
school_terms = {}
for term in tqdm(qs, desc="Import terms (as validity ranges)", **TQDM_DEFAULTS):
......
......@@ -25,9 +25,9 @@ from .importers.lessons import import_lessons
from .importers.substitutions import import_substitutions
def untis_import_mysql(terms: Optional[QuerySet] = None):
def untis_import_mysql(terms: Optional[QuerySet] = None, version: Optional[int] = None):
# School terms and validity ranges
validity_ref = import_terms(terms)
validity_ref = import_terms(terms, version=version)
for validity_range in tqdm(
validity_ref.values(), desc="Import data for terms", **TQDM_DEFAULTS
......
......@@ -14,7 +14,7 @@ Supported Untis features
------------------------
Not all features of Untis are supported in AlekSIS. The following
information form Untis can be imported into AlekSIS:
information from Untis can be imported into AlekSIS:
* Terms
* Holidays
......@@ -26,6 +26,9 @@ information form Untis can be imported into AlekSIS:
* Substitutions, extra lessons, cancellations
* Events
The Untis integration supports the versioning features of Untis. By default,
the most recent version of each object is imported.
Currently, the following features are known not to be supported:
* Students, student groups, student choices
......
......@@ -92,7 +92,9 @@ is also already imported when it becomes reelvant.
In general, all tasks will do nothing if there is no matching Untis term.
To use these tasks, you have to add them as periodic tasks.
To use these tasks, you have to add them as periodic tasks. By default, they will
import the most recent plan version from Untis. To select a specific version (i.e.
to import an older snapshot), you can pass the ``version`` argument in the tasks.
How existing data is matched
----------------------------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment