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}
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
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
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
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)
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)
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'])