dipex 5.2.0__tar.gz → 5.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dipex-5.2.0 → dipex-5.3.0}/PKG-INFO +1 -1
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/config.py +3 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/date_utils.py +2 -1
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/fix_departments.py +64 -80
- dipex-5.3.0/integrations/SD_Lon/sdlon/log.py +65 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/main.py +2 -2
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_changed_at.py +148 -148
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_common.py +2 -2
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_importer.py +5 -23
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/skip.py +2 -3
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sync_job_id.py +3 -18
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_config.py +1 -0
- dipex-5.3.0/integrations/SD_Lon/tests/test_log.py +12 -0
- {dipex-5.2.0 → dipex-5.3.0}/pyproject.toml +1 -1
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/gql_lora_cache_async.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/lc_for_jobs_db.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/lora_cache.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/lora_gql_equivalence_tester.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/main.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/old_lora_cache.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/sql_export.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/sql_table_defs.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/sql_url.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/sql_export/trigger.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/exporters/utils/priority_by_class.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/employees.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/engagement.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/exceptions.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/graphql.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/it_systems.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/models.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/scripts/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/scripts/fix_monthly_hourly_divide.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/scripts/fix_status8.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/scripts/generate_org_unit_level_uuid.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_changed_at_redo.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_cli.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_fixup.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_log_analyzer.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_payloads.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/sd_to_pydantic.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/test_mo_against_sd.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdlon/test_sd_connectivity.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdtool/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdtool/config.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/sdtool/main.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/fixtures.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/org_manipulations.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/sdtool/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/sdtool/test_app.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/sdtool/test_config.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/sdtool/utils.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_date_utils.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_employee.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_engagement.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_fix_departments.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_graphql.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_it_systems.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_main.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_sd_changed_at.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_sd_common.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_sd_importer.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_sd_log_analyzer.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_sd_to_pydantic.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_skip.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/SD_Lon/tests/test_sync_job_id.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/config.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/dar_helper.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/initial.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/initial_classes.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/los_files.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/los_import.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/los_leder.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/los_org.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/los_pers.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/los_stam.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/payloads.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/conftest.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/helpers.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/strategies.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_config.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_initial.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_los_files.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_los_import.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_los_leder.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_los_org.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_los_pers.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_los_stam.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_payloads.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/tests/test_util.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/util.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/aarhus/uuids.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_common.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_exceptions.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_fix_enddate.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_jinja_filters.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_life_cycle.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_logger.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_reader.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_sync.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_template_engine.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_templates.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/ad_writer.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/import_ad_group_into_mo.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/mo_to_ad_sync.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/payloads.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/read_ad_conf_settings.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/sync_mo_uuid_to_ad.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/test_connectivity.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/mocks.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/name_simulator.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_ad_common.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_ad_fix_enddate.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_ad_jinja_filters.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_ad_life_cycle.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_ad_logger.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_ad_reader.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_ad_sync.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_ad_writer.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_dot_mapping.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_first_included.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_import_ad_group_into_mo.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_location_element.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_mo_data_source.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_mo_to_ad_sync.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_morestsource.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_read_ad_conf_settings.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_recursive_dict_update.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_sync_mo_uuid_to_ad.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_usernames.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/tests/test_utils.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/user_names.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/username_rules/method_2.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/ad_integration/utils.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/calculate_primary/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/calculate_primary/calculate_primary.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/calculate_primary/common.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/calculate_primary/default.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/calculate_primary/opus.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/calculate_primary/sd.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/calculate_primary/tests/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/calculate_primary/tests/test_primary.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/cpr_mapper.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/dawa_helper.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/kle/__init__.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/kle/kle_import.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/kle/kle_import_export.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/kle/kle_xlsx.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/kle/payloads.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/clear_and_import_opus.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/opus_diff_import.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/opus_exceptions.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/opus_file_reader.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/opus_helpers.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/opus_reimport_one.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/org_tree_print/main.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/payloads.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/tests/test_opus_diff_import.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/tests/test_opus_file_reader.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/opus/tests/test_opus_helpers.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/rundb/db_overview.py +0 -0
- {dipex-5.2.0 → dipex-5.3.0}/integrations/rundb/tests/test_db_overview.py +0 -0
|
@@ -24,6 +24,7 @@ from pydantic import UUID4
|
|
|
24
24
|
from ra_utils.load_settings import load_settings
|
|
25
25
|
from ra_utils.job_settings import JobSettings
|
|
26
26
|
|
|
27
|
+
from .log import LogLevel
|
|
27
28
|
from .models import JobFunction
|
|
28
29
|
|
|
29
30
|
|
|
@@ -63,6 +64,8 @@ class CommonSettings(BaseSettings): # type: ignore
|
|
|
63
64
|
"/opt/dipex/os2mo-data-import-and-export/settings/cpr_uuid_map.csv"
|
|
64
65
|
)
|
|
65
66
|
|
|
67
|
+
log_level: LogLevel = LogLevel.DEBUG
|
|
68
|
+
|
|
66
69
|
job_settings: JobSettings = JobSettings()
|
|
67
70
|
|
|
68
71
|
|
|
@@ -14,6 +14,7 @@ from typing import Tuple
|
|
|
14
14
|
from more_itertools import pairwise
|
|
15
15
|
from more_itertools import tabulate
|
|
16
16
|
|
|
17
|
+
from .log import get_logger
|
|
17
18
|
from .sd_common import EmploymentStatus
|
|
18
19
|
|
|
19
20
|
# TODO: move constants elsewhere
|
|
@@ -24,7 +25,7 @@ MO_INFINITY = None
|
|
|
24
25
|
SD_INFINITY: str = "9999-12-31"
|
|
25
26
|
DATE_REGEX_STR = "[0-9]{4}-(0[1-9]|1[0-2])-([0-2][0-9]|3[0-1])"
|
|
26
27
|
|
|
27
|
-
logger =
|
|
28
|
+
logger = get_logger()
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def date_to_datetime(d: date) -> datetime:
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import json
|
|
3
|
-
import logging
|
|
4
|
-
import sys
|
|
5
3
|
from typing import Any
|
|
6
4
|
from typing import Optional
|
|
7
5
|
from typing import List
|
|
@@ -22,28 +20,13 @@ from . import sd_payloads
|
|
|
22
20
|
from .config import ChangedAtSettings
|
|
23
21
|
from .config import get_changed_at_settings
|
|
24
22
|
from .exceptions import NoCurrentValdityException
|
|
23
|
+
from .log import get_logger
|
|
24
|
+
from .log import setup_logging
|
|
25
25
|
from .sd_common import mora_assert
|
|
26
26
|
from .sd_common import sd_lookup
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
logger = logging.getLogger("fixDepartments")
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def setup_logging():
|
|
35
|
-
detail_logging = ("sdCommon", "fixDepartments")
|
|
36
|
-
for name in logging.root.manager.loggerDict:
|
|
37
|
-
if name in detail_logging:
|
|
38
|
-
logging.getLogger(name).setLevel(LOG_LEVEL)
|
|
39
|
-
else:
|
|
40
|
-
logging.getLogger(name).setLevel(logging.ERROR)
|
|
41
|
-
|
|
42
|
-
logging.basicConfig(
|
|
43
|
-
format="%(levelname)s %(asctime)s %(name)s %(message)s",
|
|
44
|
-
level=LOG_LEVEL,
|
|
45
|
-
stream=sys.stdout,
|
|
46
|
-
)
|
|
29
|
+
logger = get_logger()
|
|
47
30
|
|
|
48
31
|
|
|
49
32
|
class FixDepartments:
|
|
@@ -61,12 +44,10 @@ class FixDepartments:
|
|
|
61
44
|
try:
|
|
62
45
|
self.org_uuid = self.helper.read_organisation()
|
|
63
46
|
except requests.exceptions.RequestException as e:
|
|
64
|
-
logger.error(e)
|
|
65
|
-
print(e)
|
|
47
|
+
logger.error("Problem getting the MO organization", err=e)
|
|
66
48
|
exit()
|
|
67
49
|
except json.decoder.JSONDecodeError as e:
|
|
68
|
-
logger.error(e)
|
|
69
|
-
print(e)
|
|
50
|
+
logger.error("Problem decoding response JSON", err=e)
|
|
70
51
|
exit()
|
|
71
52
|
|
|
72
53
|
logger.info("Read org_unit types")
|
|
@@ -115,7 +96,7 @@ class FixDepartments:
|
|
|
115
96
|
parent_uuid: The parent UUID of the department in SD
|
|
116
97
|
"""
|
|
117
98
|
logger.info(
|
|
118
|
-
|
|
99
|
+
"Create department", sd_dep_uuid=department["DepartmentUUIDIdentifier"]
|
|
119
100
|
)
|
|
120
101
|
|
|
121
102
|
effective_parent_uuid = (
|
|
@@ -126,21 +107,18 @@ class FixDepartments:
|
|
|
126
107
|
if unit_level["user_key"] == department["DepartmentLevelIdentifier"]:
|
|
127
108
|
unit_level_uuid = unit_level["uuid"]
|
|
128
109
|
|
|
129
|
-
logger.debug("SD department
|
|
110
|
+
logger.debug("SD department", department=department)
|
|
130
111
|
payload = sd_payloads.create_single_org_unit(
|
|
131
112
|
department=department,
|
|
132
113
|
unit_type=self.unit_type["uuid"],
|
|
133
114
|
unit_level=unit_level_uuid,
|
|
134
115
|
parent=effective_parent_uuid,
|
|
135
116
|
)
|
|
136
|
-
logger.debug("Create
|
|
137
|
-
if self.dry_run:
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
response.raise_for_status()
|
|
142
|
-
logger.info("Created unit {}".format(department["DepartmentIdentifier"]))
|
|
143
|
-
logger.debug("Create response status: {}".format(response.status_code))
|
|
117
|
+
logger.debug("Create MO department (ou/create)", payload=payload)
|
|
118
|
+
if not self.dry_run:
|
|
119
|
+
response = self.helper._mo_post("ou/create", payload)
|
|
120
|
+
response.raise_for_status()
|
|
121
|
+
logger.info("Created unit")
|
|
144
122
|
|
|
145
123
|
def _create_org_unit_if_missing_in_mo(
|
|
146
124
|
self, department: OrderedDict, parent_uuid: Optional[str]
|
|
@@ -191,14 +169,15 @@ class FixDepartments:
|
|
|
191
169
|
if unit_level["user_key"] == department_level_identifier:
|
|
192
170
|
unit_level_uuid = unit_level["uuid"]
|
|
193
171
|
if unit_level_uuid is None:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
172
|
+
logger.exception(
|
|
173
|
+
"Unknown department level!!",
|
|
174
|
+
department_level_identifier=department_level_identifier,
|
|
175
|
+
)
|
|
176
|
+
raise Exception("Unknown department level!!")
|
|
197
177
|
|
|
198
178
|
parent = parent_uuid if parent_uuid is not None else self.org_uuid
|
|
199
179
|
|
|
200
|
-
|
|
201
|
-
logger.info(msg.format(from_date, parent))
|
|
180
|
+
logger.info("Unit parent at from_date", from_date=from_date, parent_uuid=parent)
|
|
202
181
|
|
|
203
182
|
payload = sd_payloads.edit_org_unit(
|
|
204
183
|
user_key=shortname,
|
|
@@ -210,16 +189,14 @@ class FixDepartments:
|
|
|
210
189
|
from_date=from_date,
|
|
211
190
|
to_date=to_date,
|
|
212
191
|
)
|
|
213
|
-
logger.debug("Edit payload to fix unit
|
|
214
|
-
if self.dry_run:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
else:
|
|
222
|
-
response.raise_for_status()
|
|
192
|
+
logger.debug("Edit payload to fix unit (details/edit)", payload=payload)
|
|
193
|
+
if not self.dry_run:
|
|
194
|
+
response = self.helper._mo_post("details/edit", payload)
|
|
195
|
+
logger.debug("Edit response status: {}".format(response.status_code))
|
|
196
|
+
if response.status_code == 400:
|
|
197
|
+
assert response.text.find("raise to a new registration") > 0
|
|
198
|
+
else:
|
|
199
|
+
response.raise_for_status()
|
|
223
200
|
|
|
224
201
|
def fix_department(self, unit_uuid: str, validity_date: datetime.date) -> None:
|
|
225
202
|
"""
|
|
@@ -228,8 +205,7 @@ class FixDepartments:
|
|
|
228
205
|
:param validity_date: The validity date to read the department info from SD.
|
|
229
206
|
"""
|
|
230
207
|
|
|
231
|
-
|
|
232
|
-
logger.info(msg.format(unit_uuid, validity_date))
|
|
208
|
+
logger.info("Fix department", unit_uuid=unit_uuid, validity_date=validity_date)
|
|
233
209
|
validity = {
|
|
234
210
|
"from_date": validity_date.strftime("%d.%m.%Y"),
|
|
235
211
|
"to_date": datetime_to_sd_date(parse_datetime(SD_INFINITY)),
|
|
@@ -318,8 +294,11 @@ class FixDepartments:
|
|
|
318
294
|
relevant_engagement = mo_eng
|
|
319
295
|
|
|
320
296
|
if relevant_engagement is None:
|
|
321
|
-
|
|
322
|
-
|
|
297
|
+
logger.info(
|
|
298
|
+
"Fruitlessly searched for employment_id in MO engagements",
|
|
299
|
+
employment_id=job_id,
|
|
300
|
+
mo_engagements=mo_engagements,
|
|
301
|
+
)
|
|
323
302
|
return relevant_engagement
|
|
324
303
|
|
|
325
304
|
def _read_department_engagements(self, unit_uuid, validity_date):
|
|
@@ -341,8 +320,9 @@ class FixDepartments:
|
|
|
341
320
|
}
|
|
342
321
|
department = self.get_department(sd_validity, uuid=unit_uuid)[0]
|
|
343
322
|
if not department["DepartmentLevelIdentifier"] in too_deep:
|
|
344
|
-
|
|
345
|
-
|
|
323
|
+
logger.info(
|
|
324
|
+
"Enhed regnes ikke som et SD afdelingsniveau", unit_uuid=unit_uuid
|
|
325
|
+
)
|
|
346
326
|
return {}
|
|
347
327
|
|
|
348
328
|
params = {
|
|
@@ -359,7 +339,7 @@ class FixDepartments:
|
|
|
359
339
|
time_deltas = [0, 90, 365]
|
|
360
340
|
|
|
361
341
|
all_people = {}
|
|
362
|
-
logger.debug("Perform GetEmployments,
|
|
342
|
+
logger.debug("Perform GetEmployments", time_deltas=time_deltas)
|
|
363
343
|
for time_delta in time_deltas:
|
|
364
344
|
effective_date = validity_date + datetime.timedelta(days=time_delta)
|
|
365
345
|
params["EffectiveDate"] = (effective_date.strftime("%d.%m.%Y"),)
|
|
@@ -375,7 +355,7 @@ class FixDepartments:
|
|
|
375
355
|
cpr = person["PersonCivilRegistrationIdentifier"]
|
|
376
356
|
if cpr not in all_people:
|
|
377
357
|
all_people[cpr] = person
|
|
378
|
-
logger.debug("Department engagements
|
|
358
|
+
logger.debug("Department engagements", all_people=all_people.keys())
|
|
379
359
|
return all_people
|
|
380
360
|
|
|
381
361
|
def fix_NY_logic(self, unit_uuid, validity_date):
|
|
@@ -397,9 +377,9 @@ class FixDepartments:
|
|
|
397
377
|
mo_unit = self.helper.read_ou(unit_uuid)
|
|
398
378
|
while mo_unit["org_unit_level"]["user_key"] in too_deep:
|
|
399
379
|
mo_unit = mo_unit["parent"]
|
|
400
|
-
logger.debug("Parent unit
|
|
380
|
+
logger.debug("Parent unit", parent_uuid=mo_unit["uuid"])
|
|
401
381
|
destination_unit = mo_unit["uuid"]
|
|
402
|
-
logger.debug("Destination found
|
|
382
|
+
logger.debug("Destination found", destination_unit=destination_unit)
|
|
403
383
|
|
|
404
384
|
all_people = self._read_department_engagements(unit_uuid, validity_date)
|
|
405
385
|
|
|
@@ -414,9 +394,7 @@ class FixDepartments:
|
|
|
414
394
|
|
|
415
395
|
for employment in person["Employment"]:
|
|
416
396
|
job_id = employment["EmploymentIdentifier"]
|
|
417
|
-
|
|
418
|
-
print(msg.format(job_id))
|
|
419
|
-
logger.info(msg.format(job_id))
|
|
397
|
+
logger.info("Checking job-id", employment_id=job_id)
|
|
420
398
|
sd_uuid = employment["EmploymentDepartment"]["DepartmentUUIDIdentifier"]
|
|
421
399
|
if not sd_uuid == unit_uuid:
|
|
422
400
|
# This employment is not from the current department,
|
|
@@ -426,8 +404,9 @@ class FixDepartments:
|
|
|
426
404
|
|
|
427
405
|
mo_person = self.helper.read_user(user_cpr=cpr, org_uuid=self.org_uuid)
|
|
428
406
|
if mo_person is None:
|
|
429
|
-
|
|
430
|
-
|
|
407
|
+
logger.warning(
|
|
408
|
+
"MO person is None for employment_id", employment_id=job_id
|
|
409
|
+
)
|
|
431
410
|
continue
|
|
432
411
|
|
|
433
412
|
mo_engagements = self.helper.read_user_engagement(
|
|
@@ -438,8 +417,11 @@ class FixDepartments:
|
|
|
438
417
|
# future rows.
|
|
439
418
|
mo_engagement = self._find_engagement(mo_engagements, job_id)
|
|
440
419
|
if mo_engagement is None:
|
|
441
|
-
|
|
442
|
-
|
|
420
|
+
logger.warning(
|
|
421
|
+
"MO engagement is None",
|
|
422
|
+
employment_id=job_id,
|
|
423
|
+
mo_person_uuid=mo_person["uuid"],
|
|
424
|
+
)
|
|
443
425
|
continue
|
|
444
426
|
for eng in mo_engagements:
|
|
445
427
|
if not eng["uuid"] == mo_engagement["uuid"]:
|
|
@@ -460,12 +442,12 @@ class FixDepartments:
|
|
|
460
442
|
"validity": eng["validity"],
|
|
461
443
|
}
|
|
462
444
|
payload = sd_payloads.engagement(data, mo_engagement)
|
|
463
|
-
logger.debug(
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
445
|
+
logger.debug(
|
|
446
|
+
"Move engagement payload (details/edit)", payload=payload
|
|
447
|
+
)
|
|
448
|
+
if not self.dry_run:
|
|
449
|
+
response = self.helper._mo_post("details/edit", payload)
|
|
450
|
+
mora_assert(response)
|
|
469
451
|
|
|
470
452
|
def get_parent(self, unit_uuid, validity_date) -> Optional[str]:
|
|
471
453
|
"""
|
|
@@ -489,8 +471,11 @@ class FixDepartments:
|
|
|
489
471
|
"GetDepartmentParent20190701", settings=self.settings, params=params
|
|
490
472
|
)
|
|
491
473
|
if "DepartmentParent" not in parent_response:
|
|
492
|
-
|
|
493
|
-
|
|
474
|
+
logger.error(
|
|
475
|
+
"No parent found at this date",
|
|
476
|
+
unit_uuid=unit_uuid,
|
|
477
|
+
validity_date=validity_date,
|
|
478
|
+
)
|
|
494
479
|
raise NoCurrentValdityException()
|
|
495
480
|
parent = parent_response["DepartmentParent"]["DepartmentUUIDIdentifier"]
|
|
496
481
|
if parent == self.institution_uuid:
|
|
@@ -528,8 +513,7 @@ class FixDepartments:
|
|
|
528
513
|
uuid = department["DepartmentUUIDIdentifier"]
|
|
529
514
|
department_branch.append((shortname, uuid))
|
|
530
515
|
current_uuid = self.get_parent(current_uuid, validity_date=validity_date)
|
|
531
|
-
|
|
532
|
-
logger.debug(msg.format(shortname, uuid, level))
|
|
516
|
+
logger.debug("Department", shortname=shortname, uuid=uuid, level=level)
|
|
533
517
|
return department_branch
|
|
534
518
|
|
|
535
519
|
def sd_uuid_from_short_code(self, validity_date, shortname):
|
|
@@ -543,17 +527,17 @@ class FixDepartments:
|
|
|
543
527
|
|
|
544
528
|
def unit_fixer(ou_uuid: UUID):
|
|
545
529
|
"""Sync SD department information to MO."""
|
|
546
|
-
setup_logging()
|
|
547
|
-
|
|
548
530
|
settings = get_changed_at_settings()
|
|
531
|
+
setup_logging(settings.log_level)
|
|
532
|
+
|
|
549
533
|
unit_fixer = FixDepartments(settings)
|
|
550
534
|
|
|
551
535
|
today = datetime.datetime.today().date()
|
|
552
536
|
|
|
553
|
-
logger.info(
|
|
537
|
+
logger.info("Calling fix_departments", ou_uuid=ou_uuid)
|
|
554
538
|
unit_fixer.fix_department(str(ou_uuid), today)
|
|
555
539
|
|
|
556
|
-
logger.info(
|
|
540
|
+
logger.info("Calling fix_NY_logic", ou_uuid=ou_uuid)
|
|
557
541
|
unit_fixer.fix_NY_logic(str(ou_uuid), today)
|
|
558
542
|
|
|
559
543
|
logger.info("unit_fixer done!")
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import logging.config
|
|
2
|
+
import re
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from uuid import uuid4
|
|
5
|
+
|
|
6
|
+
import structlog
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
CPR_REGEX = re.compile("[0-9]{10}")
|
|
10
|
+
|
|
11
|
+
# Unique log context for this application
|
|
12
|
+
APP_LOG_CONTEXT = uuid4()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class LogLevel(str, Enum):
|
|
16
|
+
DEBUG = "DEBUG"
|
|
17
|
+
INFO = "INFO"
|
|
18
|
+
WARNING = "WARNING"
|
|
19
|
+
ERROR = "ERROR"
|
|
20
|
+
CRITICAL = "CRITICAL"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def anonymize_cpr(cpr: str) -> str:
|
|
24
|
+
assert CPR_REGEX.match(cpr)
|
|
25
|
+
return cpr[:6] + "xxxx"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def log_filter(logger, method_name, event_dict):
|
|
29
|
+
# Only log from our application log context
|
|
30
|
+
if event_dict.get("log_context") == APP_LOG_CONTEXT:
|
|
31
|
+
return event_dict
|
|
32
|
+
raise structlog.DropEvent
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_logger():
|
|
36
|
+
"""
|
|
37
|
+
Use this function to get a logger instead of using structlog.get_logger() directly
|
|
38
|
+
"""
|
|
39
|
+
return structlog.get_logger().bind(log_context=APP_LOG_CONTEXT)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def setup_logging(log_level: LogLevel) -> None:
|
|
43
|
+
log_level_value = logging.getLevelName(log_level.value)
|
|
44
|
+
|
|
45
|
+
# Disable logging from imported modules that use Pythons stdlib logging
|
|
46
|
+
logging.config.dictConfig(
|
|
47
|
+
{
|
|
48
|
+
"version": 1,
|
|
49
|
+
"disable_existing_loggers": True, # This line does not really seem to work
|
|
50
|
+
"root": {"level": logging.CRITICAL + 1},
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
structlog.configure(
|
|
55
|
+
processors=[
|
|
56
|
+
log_filter,
|
|
57
|
+
structlog.contextvars.merge_contextvars,
|
|
58
|
+
structlog.processors.add_log_level,
|
|
59
|
+
structlog.processors.StackInfoRenderer(),
|
|
60
|
+
structlog.dev.set_exc_info,
|
|
61
|
+
structlog.processors.TimeStamper(),
|
|
62
|
+
structlog.dev.ConsoleRenderer(),
|
|
63
|
+
],
|
|
64
|
+
wrapper_class=structlog.make_filtering_bound_logger(log_level_value),
|
|
65
|
+
)
|
|
@@ -6,7 +6,6 @@ from contextlib import contextmanager
|
|
|
6
6
|
from functools import partial
|
|
7
7
|
from uuid import UUID
|
|
8
8
|
|
|
9
|
-
import structlog
|
|
10
9
|
from fastapi import FastAPI
|
|
11
10
|
from fastapi import Request
|
|
12
11
|
from fastapi import Response
|
|
@@ -18,10 +17,11 @@ from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR
|
|
|
18
17
|
|
|
19
18
|
from .config import get_changed_at_settings
|
|
20
19
|
from .fix_departments import FixDepartments
|
|
20
|
+
from .log import get_logger
|
|
21
21
|
from .sd_changed_at import changed_at
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
logger =
|
|
24
|
+
logger = get_logger()
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class State(enum.Enum):
|