Esempio n. 1
0
def create_new_root_and_it(settings=None) -> None:
    """Setup all necessary classes etc to perform opus-import."""
    logger.warning(
        "'create_new_root_and_it' is deprecated. Use os2mo-init instead.")
    settings = settings or load_settings()
    mox_base = settings.get("mox.base", "http://localhost:8080")
    mora_base = settings.get("mora.base", "http://localhost:5000")

    # Init
    os2mo = ImportHelper(
        create_defaults=True,
        store_integration_data=True,
        mox_base=mox_base,
        mora_base=mora_base,
    )

    # The Organisation class is the main entry point,
    # It exposes the related sub classes such as:
    # Facet, Klasse, Itsystem, OrganisationUnit, Employee
    main_name = settings.get("municipality.name", "Magenta ApS")
    main_uuid = opus_helpers.generate_uuid(main_name)
    os2mo.add_organisation(
        identifier=main_name,
        uuid=str(main_uuid),
        user_key=main_name,
        municipality_code=settings.get("municipality.code", 1234),
    )
    os2mo.new_itsystem(identifier=constants.Opus_it_system,
                       system_name=constants.Opus_it_system)
    os2mo.new_itsystem(identifier=constants.AD_it_system,
                       system_name=constants.AD_it_system)

    # Perfom setup of root unit and it systems.
    os2mo.import_all()
Esempio n. 2
0
def cli(mox_base, mora_base, delete, full_history, opus_id, use_ad, dry_run):
    """Reimport object from opus with given opus-ID to MO
    Optionally deletes the object and all related orgfuncs directly from Lora.
    Defaults to reading latest file only, but supports reading full history
    """
    helper = MoraHelper(hostname=mora_base)
    object_type, obj = find_type(opus_id, full_history)
    if object_type == "bruger":
        cpr = opus_helpers.read_cpr(obj)
        user = helper.read_user(user_cpr=cpr)
        uuid = user["uuid"] if user else None
    else:
        uuid = opus_helpers.generate_uuid(obj["@id"])

    if delete and uuid and not dry_run:
        delete_object_and_orgfuncs(uuid, mox_base, object_type)
    if dry_run:
        click.echo(
            f"Dry-run: {'Delete and reimport' if delete else 'Reimport'} '{object_type}' with {uuid=}"
        )
    else:
        AD = ad_reader.ADParameterReader() if use_ad else None
        import_opus(
            ad_reader=AD,
            import_all=full_history,
            import_last=not full_history,
            opus_id=opus_id,
            rundb_write=False,
        )
Esempio n. 3
0
    def update_unit(self, unit):
        calculated_uuid = opus_helpers.generate_uuid(unit["@id"])
        parent_name = unit["parentOrgUnit"]
        parent_uuid = (opus_helpers.generate_uuid(parent_name)
                       if parent_name else self.helper.read_organisation())
        mo_unit = self.helper.read_ou(calculated_uuid)

        # Default to "Enhed" as unittype
        org_type_title = unit.get("orgTypeTxt", "Enhed")
        org_type_bvn = unit.get("orgType", org_type_title)

        unit_type = self.helper.ensure_class_in_facet("org_unit_type",
                                                      bvn=org_type_bvn,
                                                      title=org_type_title)
        from_date = unit.get("startDate", "01-01-1900")
        unit_user_key = self.settings.get("integrations.opus.unit_user_key",
                                          "@id")
        unit_args = {
            "unit": unit,
            "unit_user_key": unit[unit_user_key],
            "unit_uuid": str(calculated_uuid),
            "unit_type": str(unit_type),
            "parent": str(parent_uuid),
            "from_date": from_date,
        }

        if mo_unit.get("uuid"):  # Edit
            unit_args["from_date"] = self.xml_date.strftime("%Y-%m-%d")
            payload = payloads.edit_org_unit(**unit_args)
            logger.info("Edit unit: {}".format(payload))
            response = self.helper._mo_post("details/edit", payload)
            if response.status_code == 400:
                assert response.text.find("raise to a new registration") > 0
            else:
                response.raise_for_status()
        else:  # Create
            payload = payloads.create_org_unit(**unit_args)
            logger.debug("Create department payload: {}".format(payload))
            response = self.helper._mo_post("ou/create", payload)
            response.raise_for_status()
            logger.info("Created unit {}".format(unit["@id"]))
            logger.debug("Response: {}".format(response.text))

        self._update_unit_addresses(unit)
Esempio n. 4
0
 def _add_klasse(self, klasse_id, klasse, facet, scope='TEXT'):
     if not self.importer.check_if_exists('klasse', klasse_id):
         uuid = opus_helpers.generate_uuid(klasse_id)
         self.importer.add_klasse(identifier=klasse_id,
                                  uuid=uuid,
                                  facet_type_ref=facet,
                                  user_key=klasse_id,
                                  scope=scope,
                                  title=klasse)
     return klasse_id
Esempio n. 5
0
    def _update_unit_addresses(self, unit):
        calculated_uuid = opus_helpers.generate_uuid(unit["@id"])
        unit_addresses = self.helper.read_ou_address(calculated_uuid,
                                                     scope=None,
                                                     return_all=True)

        address_dict = {}
        for address in unit_addresses:
            if address_dict.get(address["type"]) is not None:
                # More than one of this type exist in MO, this is not allowed.
                msg = "Inconsistent addresses for unit: {}"
                logger.error(msg.format(calculated_uuid))
            # if address['value'] not in ('9999999999999', '0000000000'):
            address_dict[address["type"]] = {
                "value": address["value"],
                "uuid": address["uuid"],
            }

        if unit.get("street") and unit.get("zipCode"):
            try:
                address_uuid = dawa_helper.dawa_lookup(unit["street"],
                                                       unit["zipCode"])
            except:
                address_uuid = None
            if address_uuid:
                logger.debug("Found DAR uuid: {}".format(address_uuid))
                unit["dar"] = address_uuid
            else:
                logger.warning("Failed to lookup {}, {}".format(
                    unit["street"], unit["zipCode"]))

        for addr_type, mo_addr_type in UNIT_ADDRESS_CHECKS.items():
            # addr_type is the opus name for the address, mo_addr_type
            # is read from MO
            if unit.get(addr_type) is None:
                continue

            addr_type_uuid = self.helper.ensure_class_in_facet(
                "org_unit_address_type",
                mo_addr_type,
                scope=predefined_scopes.get(mo_addr_type),
            )
            current = address_dict.get(str(addr_type_uuid))
            args = {
                "address_type": {
                    "uuid": str(addr_type_uuid)
                },
                "value": unit[addr_type],
                "validity": {
                    "from": self.xml_date.strftime("%Y-%m-%d"),
                    "to": None
                },
                "unit_uuid": str(calculated_uuid),
            }
            self._perform_address_update(args, current)
Esempio n. 6
0
def find_opus_name() -> str:
    """Generates uuid for opus root.

    Reads the first available opus file and generates the uuid for the first unit in the file.
    Assumes this is the root organisation of opus.
    """
    dumps = opus_helpers.read_available_dumps()

    first_date = min(sorted(dumps.keys()))
    units, _ = opus_helpers.parser(dumps[first_date])
    main_unit = first(units)
    calculated_uuid = opus_helpers.generate_uuid(main_unit["@id"])
    return str(calculated_uuid)
Esempio n. 7
0
 def test_update_unit(self, dawa_helper_mock, xml_date):
     self.assertIsInstance(xml_date, datetime)
     diff = OpusDiffImportTestbase(xml_date, ad_reader=None, employee_mapping="test")
     for unit in self.units:
         diff.update_unit(unit)
         calculated_uuid = opus_helpers.generate_uuid(unit["@id"])
         if unit.get("street"):
             diff.helper._mo_post.assert_called_with(
                 "details/create",
                 {
                     "type": "address",
                     "value": dawa_helper_mock(),
                     "address_type": {
                         "uuid": str(diff.morahelper_mock.ensure_class_in_facet())
                     },
                     "validity": {"from": xml_date.strftime("%Y-%m-%d"), "to": None},
                     "org_unit": {"uuid": str(calculated_uuid)},
                     "visibility": None,
                 },
             )
Esempio n. 8
0
    def create_engagement(self, mo_user_uuid, opus_employee):
        job_function, eng_type = self._job_and_engagement_type(opus_employee)
        unit_uuid = opus_helpers.generate_uuid(opus_employee["orgUnit"])

        engagement_unit = self.helper.read_ou(unit_uuid)
        if "error" in engagement_unit:
            msg = "The wanted unit does not exit: {}"
            logger.error(msg.format(opus_employee["orgUnit"]))
            raise UnknownOpusUnit

        validity = self.validity(opus_employee, edit=False)
        payload = payloads.create_engagement(
            employee=opus_employee,
            user_uuid=mo_user_uuid,
            unit_uuid=unit_uuid,
            job_function=job_function,
            engagement_type=eng_type,
            primary=self.updater.primary_types["non_primary"],
            validity=validity,
        )
        logger.debug("Create engagement payload: {}".format(payload))
        response = self.helper._mo_post("details/create", payload)
        assert response.status_code == 201
Esempio n. 9
0
    def update_roller(self, employee):
        cpr = employee["cpr"]["#text"]
        mo_user = self.helper.read_user(user_cpr=cpr)
        logger.info("Check {} for updates in Roller".format(mo_user["uuid"]))
        if isinstance(employee["function"], dict):
            opus_roles = [employee["function"]]
        else:
            opus_roles = employee["function"]
        mo_roles = self.helper._mo_lookup(mo_user["uuid"], "e/{}/details/role")
        for opus_role in opus_roles:
            opus_end_datetime = datetime.strptime(opus_role["@endDate"],
                                                  "%Y-%m-%d")
            if opus_role["@endDate"] == "9999-12-31":
                opus_role["@endDate"] = None

            found = False
            for mo_role in mo_roles:
                if "roleText" in opus_role:
                    combined_role = "{} - {}".format(opus_role["artText"],
                                                     opus_role["roleText"])
                else:
                    combined_role = opus_role["artText"]

                if (mo_role["person"]["uuid"] == mo_user["uuid"]
                        and combined_role == mo_role["role_type"]["name"]):
                    found = True
                    if mo_role["validity"]["to"] is None:
                        mo_end_datetime = datetime.strptime(
                            "9999-12-31", "%Y-%m-%d")
                    else:
                        mo_end_datetime = datetime.strptime(
                            mo_role["validity"]["to"], "%Y-%m-%d")

                    # We only compare end dates, it is assumed start-date is not
                    # changed.
                    if mo_end_datetime == opus_end_datetime:
                        logger.info("No edit")
                    elif opus_end_datetime > mo_end_datetime:
                        logger.info("Extend role")
                        validity = {
                            "from": opus_role["@startDate"],
                            "to": opus_role["@endDate"],
                        }
                        payload = payloads.edit_role(validity, mo_role["uuid"])
                        logger.debug("Edit role, payload: {}".format(payload))
                        response = self.helper._mo_post(
                            "details/edit", payload)
                        self._assert(response)
                    else:  # opus_end_datetime < mo_end_datetime:
                        logger.info("Terminate role")
                        self.terminate_detail(
                            mo_role["uuid"],
                            detail_type="role",
                            end_date=opus_end_datetime,
                        )
            if not found:
                logger.info("Create new role: {}".format(opus_role))
                # TODO: We will fail a if  new role-type surfaces
                role_name = opus_role["artText"]
                role_type = self.helper.ensure_class_in_facet(
                    "role_type", role_name)
                payload = payloads.create_role(
                    employee=employee,
                    user_uuid=mo_user["uuid"],
                    unit_uuid=str(
                        opus_helpers.generate_uuid(employee["orgUnit"])),
                    role_type=str(role_type),
                    validity={
                        "from": opus_role["@startDate"],
                        "to": opus_role["@endDate"],
                    },
                )
                logger.debug("New role, payload: {}".format(payload))
                response = self.helper._mo_post("details/create", payload)
                assert response.status_code == 201
Esempio n. 10
0
    def update_manager_status(self, employee_mo_uuid, employee):
        url = "e/{}/details/manager?at=" + self.validity(employee,
                                                         edit=True)["from"]
        manager_functions = self.helper._mo_lookup(employee_mo_uuid, url)
        logger.debug(
            "Manager functions to update: {}".format(manager_functions))
        if manager_functions:
            logger.debug(
                "Manager functions to update: {}".format(manager_functions))

        if employee["isManager"] == "false":
            if manager_functions:
                logger.info("Terminate manager function")
                self.terminate_detail(manager_functions[0]["uuid"],
                                      detail_type="manager")
            else:
                logger.debug("Correctly not a manager")

        if employee["isManager"] == "true":
            manager_level = "{}.{}".format(employee["superiorLevel"],
                                           employee["subordinateLevel"])
            manager_level_uuid = self.helper.ensure_class_in_facet(
                "manager_level", manager_level)
            manager_type = employee["position"]
            manager_type_uuid = self.helper.ensure_class_in_facet(
                "manager_type", manager_type)
            responsibility_uuid = self.helper.ensure_class_in_facet(
                "responsibility", "Lederansvar")

            args = {
                "unit": str(opus_helpers.generate_uuid(employee["orgUnit"])),
                "person": employee_mo_uuid,
                "manager_type": str(manager_type_uuid),
                "level": str(manager_level_uuid),
                "responsibility": str(responsibility_uuid),
                "validity": self.validity(employee, edit=True),
            }
            if manager_functions:
                logger.info(
                    "Attempt manager update of {}:".format(employee_mo_uuid))
                # Currently Opus supports only a single manager object pr employee
                assert len(manager_functions) == 1

                mf = manager_functions[0]

                payload = payloads.edit_manager(
                    object_uuid=manager_functions[0]["uuid"], **args)

                something_new = not (
                    mf["org_unit"]["uuid"] == args["unit"]
                    and mf["person"]["uuid"] == args["person"]
                    and mf["manager_type"]["uuid"] == args["manager_type"]
                    and mf["manager_level"]["uuid"] == args["level"] and
                    mf["responsibility"][0]["uuid"] == args["responsibility"])

                if something_new:
                    logger.debug("Something is changed, execute payload")
                else:
                    mo_end_datetime = self._to_datetime(mf["validity"]["to"])
                    opus_end_datetime = self._to_datetime(
                        args["validity"]["to"])
                    logger.info("MO end datetime: {}".format(mo_end_datetime))
                    logger.info(
                        "OPUS end datetime: {}".format(opus_end_datetime))

                    if mo_end_datetime == opus_end_datetime:
                        logger.info("No edit of manager object")
                        payload = None
                    elif opus_end_datetime > mo_end_datetime:
                        logger.info("Extend validity, send payload to MO")
                    else:  # opus_end_datetime < mo_end_datetime:
                        logger.info("Terminate mangement role")
                        payload = None
                        self.terminate_detail(
                            mf["uuid"],
                            detail_type="manager",
                            end_date=opus_end_datetime,
                        )

                logger.debug("Update manager payload: {}".format(payload))
                if payload is not None:
                    response = self.helper._mo_post("details/edit", payload)
                    self._assert(response)
            else:  # No existing manager functions
                logger.info("Turn this person into a manager")
                # Validity is set to edit=True since the validiy should
                # calculated as an edit to the engagement
                payload = payloads.create_manager(user_key=employee["@id"],
                                                  **args)
                logger.debug("Create manager payload: {}".format(payload))
                response = self.helper._mo_post("details/create", payload)
                assert response.status_code == 201
Esempio n. 11
0
    def update_engagement(self, engagement, employee):
        """
        Update a MO engagement according to opus employee object.
        It often happens that the change that provoked lastChanged to
        be updated is not a MO field, and thus we check for relevant
        differences before shipping the payload to MO.
        :param engagement: Relevant MO engagement object.
        :param employee: Relevent Opus employee object.
        :return: True if update happended, False if not.
        """
        job_function, eng_type = self._job_and_engagement_type(employee)
        unit_uuid = opus_helpers.generate_uuid(employee["orgUnit"])

        validity = self.validity(employee, edit=True)
        data = {
            "engagement_type": {
                "uuid": eng_type
            },
            "job_function": {
                "uuid": job_function
            },
            "org_unit": {
                "uuid": str(unit_uuid)
            },
            "validity": validity,
        }

        engagement_unit = self.helper.read_ou(unit_uuid)
        if "error" in engagement_unit:
            msg = "The wanted unit does not exit: {}"
            logger.error(msg.format(unit_uuid))
            raise UnknownOpusUnit

        if engagement["validity"]["to"] is None:
            old_valid_to = datetime.strptime("9999-12-31", "%Y-%m-%d")
        else:
            old_valid_to = datetime.strptime(engagement["validity"]["to"],
                                             "%Y-%m-%d")
        if validity["to"] is None:
            new_valid_to = datetime.strptime("9999-12-31", "%Y-%m-%d")
        else:
            new_valid_to = datetime.strptime(validity["to"], "%Y-%m-%d")

        something_new = not (
            (engagement["engagement_type"]["uuid"] == eng_type) and
            (engagement["job_function"]["uuid"] == job_function) and
            (engagement["org_unit"]["uuid"] == str(unit_uuid)) and
            (old_valid_to == new_valid_to))

        logger.info("Something new? {}".format(something_new))
        if something_new:
            payload = payloads.edit_engagement(data, engagement["uuid"])
            logger.debug("Update engagement payload: {}".format(payload))
            response = self.helper._mo_post("details/edit", payload)
            self._assert(response)

        if new_valid_to < old_valid_to:
            self.terminate_detail(engagement["uuid"],
                                  detail_type="engagement",
                                  end_date=new_valid_to)
        return something_new
Esempio n. 12
0
    def _import_org_unit(self, unit):
        try:
            org_type = unit['orgType']
            self._add_klasse(org_type, unit['orgTypeTxt'], 'org_unit_type')
        except KeyError:
            org_type = 'Enhed'
            self._add_klasse(org_type, 'Enhed', 'org_unit_type')

        identifier = unit['@id']
        uuid = opus_helpers.generate_uuid(identifier)
        logger.debug('Generated uuid for {}: {}'.format(unit['@id'], uuid))

        user_key = unit['shortName']

        if unit['startDate'] == '1900-01-01':
            date_from = '1930-01-01'
        else:
            date_from = unit['startDate']

        if unit['endDate'] == '9999-12-31':
            date_to = None
        else:
            date_to = unit['endDate']

        name = unit['longName']

        parent_org = unit.get("parentOrgUnit")
        if parent_org == self.organisation_id and not self.import_first:
            parent_org = None

        self.importer.add_organisation_unit(identifier=identifier,
                                            name=name,
                                            uuid=str(uuid),
                                            user_key=user_key,
                                            parent_ref=parent_org,
                                            type_ref=org_type,
                                            date_from=date_from,
                                            date_to=date_to)

        if 'seNr' in unit:
            self.importer.add_address_type(organisation_unit=identifier,
                                           value=unit['seNr'],
                                           type_ref='SE',
                                           date_from=date_from,
                                           date_to=date_to)

        if 'cvrNr' in unit:
            self.importer.add_address_type(organisation_unit=identifier,
                                           value=unit['cvrNr'],
                                           type_ref='CVR',
                                           date_from=date_from,
                                           date_to=date_to)

        if 'eanNr' in unit and (not unit['eanNr'] == '9999999999999'):
            self.importer.add_address_type(organisation_unit=identifier,
                                           value=unit['eanNr'],
                                           type_ref='EAN',
                                           date_from=date_from,
                                           date_to=date_to)

        if 'pNr' in unit and (not unit['pNr'] == '0000000000'):
            self.importer.add_address_type(organisation_unit=identifier,
                                           value=unit['pNr'],
                                           type_ref='Pnummer',
                                           date_from=date_from,
                                           date_to=date_to)

        if unit['phoneNumber']:
            self.importer.add_address_type(organisation_unit=identifier,
                                           value=unit['phoneNumber'],
                                           type_ref='PhoneUnit',
                                           date_from=date_from,
                                           date_to=date_to)

        address_string = unit['street']
        zip_code = unit['zipCode']
        if address_string and zip_code:
            address_uuid = dawa_helper.dawa_lookup(address_string, zip_code)
            if address_uuid:
                self.importer.add_address_type(organisation_unit=identifier,
                                               value=address_uuid,
                                               type_ref='AddressPostUnit',
                                               date_from=date_from,
                                               date_to=date_to)
Esempio n. 13
0
 def test_generate_uuid(self, value):
     uuid1 = opus_helpers.generate_uuid(value)
     uuid2 = opus_helpers.generate_uuid(value)
     self.assertEqual(uuid1, uuid2)