Esempio n. 1
0
        def get_manager(org_unit_uuid, mh: MoraHelper):

            present = mh._mo_lookup(org_unit_uuid,
                                    "ou/{}/details/manager?validity=present")
            future = mh._mo_lookup(org_unit_uuid,
                                   "ou/{}/details/manager?validity=future")
            managers = present + future

            if not managers:
                return None
            if len(managers) > 1:
                logger.warning("More than one manager exists for {}".format(
                    org_unit_uuid))
            manager = managers[0]

            person = manager.get("person")
            if not person:
                return None

            ad_guid, sam_account_name = get_employee_from_map(
                person["uuid"], mapping_file_path)
            # Only import users who are in AD
            if not ad_guid or not sam_account_name:
                return {}

            return {"uuid": person["uuid"], "userId": sam_account_name}
Esempio n. 2
0
        def get_employee_positions(employee_uuid, mh: MoraHelper):
            present = mh._mo_lookup(
                employee_uuid, "e/{}/details/engagement?validity=present")
            future = mh._mo_lookup(employee_uuid,
                                   "e/{}/details/engagement?validity=future")
            engagements = present + future

            converted_positions = []
            for engagement in engagements:
                converted_positions.append({
                    "name":
                    engagement["job_function"]["name"],
                    "orgUnitUuid":
                    engagement["org_unit"]["uuid"],
                })
            return converted_positions
Esempio n. 3
0
def fixup_single_user(
    mora_base: AnyHttpUrl,
    person_uuid: UUID,
    engagement_uuid: UUID,
    dry_run: bool = False,
) -> Tuple[Dict[str, Any], Any]:
    """Fixup the end-date of a single engagement for a single user."""
    helper = MoraHelper(hostname=mora_base, use_cache=False)
    # Fetch all present engagements for the user
    engagements: Iterator[Dict[str, Any]] = helper._mo_lookup(
        person_uuid,
        "e/{}/details/engagement",
        validity="present",
        only_primary=False,
        use_cache=False,
        calculate_primary=False,
    )
    # Find the engagement we are looking for in the list
    engagements = filter(
        lambda engagement: engagement["uuid"] == str(engagement_uuid),
        engagements)
    engagement: Dict[str, Any] = one(engagements)

    # Construct data-part of our payload using current data.
    uuid_keys = [
        "engagement_type",
        "job_function",
        "org_unit",
        "person",
        "primary",
    ]
    direct_keys = ["extension_" + str(i) for i in range(1, 11)] + [
        "fraction",
        "is_primary",
        "user_key",
        "uuid",
    ]
    data: Dict[str, Any] = {}
    data.update({key: {"uuid": engagement[key]["uuid"]} for key in uuid_keys})
    data.update({key: engagement[key] for key in direct_keys})
    data.update(
        {"validity": {
            "from": engagement["validity"]["from"],
            "to": None,
        }})

    # Construct entire payload
    payload: Dict[str, Any] = {
        "type": "engagement",
        "uuid": str(engagement_uuid),
        "data": data,
        "person": {
            "uuid": str(person_uuid, )
        },
    }
    if dry_run:
        return payload, AttrDict({"status_code": 200, "text": "Dry-run"})
    response = helper._mo_post("details/edit", payload)
    return payload, response
Esempio n. 4
0
        def get_employee_email(employee_uuid, mh: MoraHelper):
            present = mh._mo_lookup(employee_uuid,
                                    "e/{}/details/address?validity=present")
            future = mh._mo_lookup(employee_uuid,
                                   "e/{}/details/address?validity=future")
            addresses = present + future

            emails = list(
                filter(
                    lambda address: address["address_type"]["scope"] ==
                    "EMAIL",
                    addresses,
                ))

            if emails:
                if len(emails) > 1:
                    logger.warning(
                        "More than one email exists for user {}".format(
                            employee_uuid))
                return emails[0]["value"]
            return None
Esempio n. 5
0
        def get_kle(org_unit_uuid: str,
                    mh: MoraHelper) -> Tuple[List[str], List[str]]:
            present = mh._mo_lookup(org_unit_uuid,
                                    "ou/{}/details/kle?validity=present")
            future = mh._mo_lookup(org_unit_uuid,
                                   "ou/{}/details/kle?validity=future")
            kles = present + future

            def get_kle_tuples(
                kles: List[dict], ) -> Generator[Tuple[str, str], None, None]:
                for kle in kles:
                    number = kle["kle_number"]["user_key"]
                    for aspect in kle["kle_aspect"]:
                        yield number, aspect["scope"]

            kle_tuples = get_kle_tuples(kles)
            buckets = bucket(kle_tuples, key=itemgetter(1))

            interest = map(itemgetter(0), buckets["INDSIGT"])
            performing = map(itemgetter(0), buckets["UDFOERENDE"])

            return list(interest), list(performing)
Esempio n. 6
0
    def _find_manager(self, org_unit_uuid, mora_helper: MoraHelper):
        url = "ou/{}/details/manager"
        managers = mora_helper._mo_lookup(org_unit_uuid, url)
        responsibility_class = self.settings[
            "exporters.viborg.primary_manager_responsibility"]

        for manager in managers:
            if responsibility_class in map(lambda x: x.get("uuid"),
                                           manager["responsibility"]):
                return manager

        parent = mora_helper.read_ou(org_unit_uuid).get("parent")
        if not parent:
            return {}
        return self._find_manager(parent["uuid"], mora_helper)
Esempio n. 7
0
class QueryTests(unittest.TestCase):
    @classmethod
    def setUpClass(self):
        self.morah = MoraHelper()
        org = self.morah.read_organisation()
        # This assumes a single top-unit. Tests will fail if we have more.
        roots = self.morah.read_top_units(org)
        self.nodes = self.morah.read_ou_tree(roots[0]['uuid'])
        self.counts = self.morah._mo_lookup(org, 'o/{}/')

        cq.export_orgs(self.morah, self.nodes, 'all_employees.csv')
        cq.export_orgs(self.morah,
                       self.nodes,
                       'all_orgs.csv',
                       include_employees=False)
        cq.export_managers(self.morah, self.nodes, 'all_managers.csv')
        cq.export_adm_org(self.morah, self.nodes, 'adm_org.csv')

    @classmethod
    def tearDownClass(self):
        os.remove('all_employees.csv')
        os.remove('all_orgs.csv')
        os.remove('all_managers.csv')
        os.remove('adm_org.csv')

    def _load_csv(self, filename):
        rows = []
        detector = UniversalDetector()
        with open(filename, 'rb') as csvfile:
            for row in csvfile:
                detector.feed(row)
                if detector.done:
                    break
        detector.close()
        encoding = detector.result['encoding']
        with open(filename, encoding=encoding) as csvfile:
            reader = csv.DictReader(csvfile, delimiter=';')
            for row in reader:
                rows.append(row)
        return rows

    def test_node_levels(self):
        """ Test that the tree is not flat """
        height = self.nodes['root'].height
        self.assertTrue(height > 2)

    def test_user_names(self):
        """ Test that we did not mistakingly write the same username for
        multiple users. This could for example happen if we mistankingly
        exports the same use for every employee in an ou. We allow a
        small difference (15%) since it actally happens that an employee
        is listed more than once."""
        rows = self._load_csv('all_employees.csv')
        usernames = []
        for row in rows:
            if row['Brugernavn'] not in usernames:
                usernames.append(row['Brugernavn'])
        self.assertTrue(len(usernames) > len(rows) * 0.85)

    def test_adm_orgs(self):
        """ Test that we have exported all OUs exactly once """
        rows = self._load_csv('adm_org.csv')
        self.assertEqual(len(rows), len(self.nodes))

    def test_all_employees(self):
        """ Test that we have exported all employees exactly once """
        rows = self._load_csv('all_employees.csv')
        self.assertEqual(len(rows), self.counts['engagement_count'])

    def test_consistency(self):
        rows = self._load_csv('all_orgs.csv')
        self.assertEqual(len(rows), len(self.nodes))

    def test_all_managers(self):
        rows = self._load_csv('all_managers.csv')
        self.assertEqual(len(rows), self.counts['manager_count'])