예제 #1
0
 def bind_unic_to_position(self):
     unic_repo = Unic_username_repo(self.constr_lora)
     unic_list = unic_repo.get_unic_usernames('WHERE opus_id is NULL')
     pos_repo = Position_repo(self.constr_lora)
     unics_to_update = {}
     for unic_userid in unic_list:
         unic = unic_list[unic_userid]
         positions_related_to_cpr = pos_repo.get_positions(
             "WHERE person_ref = '%s'" % unic.cpr)
         pos_amount = len(positions_related_to_cpr)
         if pos_amount == 1:
             # hvis der kun er en stilling som passer til CPR nummeret på et unic username, bliver der et match.
             # det betyder at der godt kan kobles flere unic brugernavne på en stilling - men dette sker kun når de er på flere institutioner, og bør sorteres fra på anden vis
             unic.opus_id = list(positions_related_to_cpr.keys())[0]
             unics_to_update[unic_userid] = unic
         elif pos_amount > 1:
             # Når der er flere stillinger som kan matche et unic brugernavn, forsøger vi at matche en stilling som passer ud fra institutionens ID.
             # Er der flere end én laver vi et gæt på den stilling med flest timer, er der intet match så opretter vi ingen forbindelse
             los_id_to_match = self.institutions[unic.institution_nr]
             best_guess_for_match_position = None
             for opus_id in positions_related_to_cpr:
                 pos = positions_related_to_cpr[opus_id]
                 if Unic_to_position_service.is_unic_username_and_position_match(
                         self, pos.los_id, los_id_to_match):
                     if best_guess_for_match_position == None:
                         best_guess_for_match_position = pos
                     else:
                         if best_guess_for_match_position.weekly_hours_numerator < pos.weekly_hours_numerator:
                             best_guess_for_match_position = pos
             unic.opus_id = pos.opus_id
             unics_to_update[unic_userid] = unic
         else:
             continue
     unic_repo.update_unic_usernames(unics_to_update)
예제 #2
0
    def link_user_to_position(self):
        '''
        Funktion der kobler positions, hvis data kommer fra fra OPUS løn og personale
        med users, hvis data kommer fra AD.
        Hvis der er en AD bruger med OPUS ID, kan der oprettes forbindelse mellem de to.
        Ligeledes, hvis der har været en forbindelse, som ikke er der længere, skal linket mellem de to fjernes.

        IT har et redskab hvor de kan flytte opus_id på brugere, derfor skal vi også tjekke om opus_id på position og user stemmer over ens.
        '''
        pos_repo = Position_repo(self.constr_lora)
        usr_repo = User_repo(self.constr_lora)
        positions = pos_repo.get_positions()
        users = usr_repo.get_users()
        positions_to_update = {}
        for opus_id in positions:
            position = positions[opus_id]
            if opus_id in users:
                user = users[opus_id]
                if position.uuid_userref == None or position.uuid_userref != user.uuid or position.opus_id != user.opus_id:
                    position.uuid_userref = user.uuid
                    position.updated = True
                    positions_to_update[opus_id] = position
            else:
                if position.uuid_userref != None:
                    # hvis brugeren ikke findes i dbo.users, betyder det at ad_brugeren er slettet fra position, i såfald skal brugere i "slettes køen" med uuid før uuid fjernes.
                    position.ad_user_deleted = True
                    positions_to_update[opus_id] = position

        pos_repo.update_positions(positions_to_update)
예제 #3
0
    def handle_updated_persons(self):
        '''
        Funktion som håndterer opdateringer af personer, hvis de har en IT bruger, skal der oprettes en besked om at deres stilling
        skal opdateres, og dermed komme med i køen.
        Det kan f.eks. være hvis man skifter navn, det skal opdateres i de forskellige IT systemer.

        Vi er kun interserede i de positions, der har en IT bruger fordi der ikke er nogen systemer at opdaterer dem i hvis de ikke har.
        Hvis en position er markeret som slettet eller opdateret i forvejen, ryger den allerede i køen, derfor er der ikke behov for at
        behandle disse
        '''
        person_repo = Person_repo(self.constr_lora)
        updated_persons = person_repo.get_persons('WHERE [updated] = 1')
        if len(updated_persons) > 0:
            positions_to_update = {}
            persons_to_update = {}
            position_repo = Position_repo(self.constr_lora)
            # henter udelukkende de nødvendige positions, se funktion beskrivelse
            poss_with_usr = position_repo.get_positions(
                'WHERE [uuid_userref] IS NOT NULL and [updated] = 0 and [deleted] = 0'
            )
            for opus_id in poss_with_usr:
                pos = poss_with_usr[opus_id]
                if pos.person_ref in updated_persons:
                    pos.updated = True
                    positions_to_update[opus_id] = pos
            position_repo.update_positions(positions_to_update)
            for cpr in updated_persons:
                per = updated_persons[cpr]
                per.updated = False
                persons_to_update[cpr] = per
            person_repo.update_persons(persons_to_update)
예제 #4
0
 def __init__(self, constr_lora):
     self.constr_lora = constr_lora
     org_repo = Orgunit_repo(constr_lora)
     pos_repo = Position_repo(constr_lora)
     unic_institution_repo = Unic_institution_repo(constr_lora)
     self.orgunits = org_repo.get_orgunits()
     self.positions = pos_repo.get_positions()
     self.institutions = unic_institution_repo.get_institutions()
예제 #5
0
 def get_poisitions(self, orgs):
     '''
     Funktion som finder de positions, der hører til en af de orgunits som skal synkroniseres med kalenda-greenbyte
     '''
     pos_repo = Position_repo(self.lora_constr)
     poss = pos_repo.get_positions(
         'WHERE [deleted] = 0 and [ad_user_deleted] = 0')
     result = {}
     for opus_id in poss:
         pos = poss[opus_id]
         if pos.los_id in orgs:
             result[opus_id] = pos
     return result
    def create_org_json(self):
        result = Sts_collection_json()
        org_repo = Orgunit_repo(self.lora_constr)
        pos_repo = Position_repo(self.lora_constr)
        per_repo = Person_repo(self.lora_constr)
        usr_repo = User_repo(self.lora_constr)
        orgs = org_repo.get_orgunits()
        poss = pos_repo.get_positions(
            'WHERE [uuid_userref] is not NULL and [deleted] = 0 and [ad_user_deleted] = 0'
        )
        pers = per_repo.get_persons()
        usrs = usr_repo.get_users()

        for los_id in orgs:
            sofd_org = orgs[los_id]
            if sofd_org.uuid is None or len(sofd_org.uuid) < 1:
                continue
            sofd_manager = None
            jsman = None
            # den sidste del er pga de ledere der også er politikere som snyder med deres brugerkonti, det skal der egentligt rydes op i
            if sofd_org.manager_opus_id != None and int(
                    sofd_org.manager_opus_id) in usrs:
                sofd_manager = usrs[int(sofd_org.manager_opus_id)]
                jsman = Manager_json(sofd_manager.uuid, sofd_manager.userid)
            jsorg = Orgunit_json(sofd_org.uuid, sofd_org.longname,
                                 sofd_org.parent_orgunit_uuid, jsman)
            result.add_org(jsorg)

        for opus_id in poss:
            sofd_pos = poss[opus_id]
            sofd_usr = usrs[opus_id]
            if sofd_usr.userid is None or len(sofd_usr.userid) < 1:
                continue
            sofd_per = pers[sofd_pos.person_ref]
            if sofd_pos.los_id not in orgs:
                continue
            sofd_org = orgs[sofd_pos.los_id]
            if sofd_org.uuid is None or len(sofd_org.uuid) < 1:
                continue
            json_pos = Position_json(sofd_pos.position_title, sofd_org.uuid)
            json_usr = User_json(sofd_pos.uuid_userref, sofd_usr.userid,
                                 sofd_per.firstname + ' ' + sofd_per.lastname,
                                 sofd_usr.email)
            json_usr.add_position(json_pos)
            result.add_user(json_usr)
        result = json.dumps(result.reprJSON(),
                            cls=ComplexEncoder,
                            ensure_ascii=False).encode('utf8')
        return result
예제 #7
0
    def update_user_queue(self):
        '''
        Funktion der bygger vores user queue
        '''
        # sørger for at alle person opdateringer er gået igennem før funktionen kører
        User_queue_service.handle_updated_persons(self)
        position_repo = Position_repo(self.constr_lora)
        updated_positions = position_repo.get_positions(
            'where [updated] = 1 or [deleted] = 1 or [ad_user_deleted] = 1')

        if len(updated_positions) > 0:
            positions_to_update = {}
            queue_items_to_insert = {}
            queue_repo = Queue_users_repo(self.constr_lora)
            i = 0
            for opus_id in updated_positions:
                pos = updated_positions[opus_id]
                # deleted vejer tungere end updated, derfor bliver positions, som både er opdaterede og slettede - slettet
                if pos.deleted == True or pos.ad_user_deleted == True:
                    if pos.uuid_userref != None:
                        # hvis der er et uuid, er der en user og så skal STS org opdateres (False)
                        queue_item = Queue_user(i, pos.uuid_userref, opus_id,
                                                'Deleted', False)
                        i += 1
                        queue_items_to_insert[i] = queue_item
                        # nu kan UUID fjernes fra position
                        pos.uuid_userref = None
                        pos.ad_user_deleted = False
                        positions_to_update[opus_id] = pos
                    else:
                        # Hvis der ikke er et uuid, er der ikke en user og så behøves STS ikke at blive opdateret (True) true er lidt snyd, men altså
                        queue_item = Queue_user(i, 'none', opus_id, 'Deleted',
                                                True)
                        i += 1
                        queue_items_to_insert[i] = queue_item
                elif pos.updated == True and pos.deleted == False and pos.ad_user_deleted == False:
                    pos.updated = False
                    if pos.uuid_userref != None:
                        queue_item = Queue_user(i, pos.uuid_userref, opus_id,
                                                'Updated', False)
                        i += 1
                        queue_items_to_insert[i] = queue_item
                    positions_to_update[opus_id] = pos
            queue_repo.insert_user_queue(queue_items_to_insert)
            position_repo.update_positions(positions_to_update)
예제 #8
0
 def remove_deleted_managers_from_orgunits(self):
     '''
     funktion som fjerner ledere, der ikke længere er ansat i organisationen
     '''
     org_repo = Orgunit_repo(self.constr_lora)
     pos_repo = Position_repo(self.constr_lora)
     orgs = org_repo.get_orgunits('WHERE [manager_opus_id] IS NOT NULL')
     managers = pos_repo.get_positions(
         'WHERE [is_manager] = 1 and [deleted] = 0')
     orgs_to_update = {}
     for los_id in orgs:
         org = orgs[los_id]
         if org.manager_opus_id in managers:
             continue
         else:
             org.manager_opus_id = None
             org.updated = True
             orgs_to_update[los_id] = org
     org_repo.update_orgunits(orgs_to_update)
예제 #9
0
    def clean_user_queue(self):
        '''
            Funktion der ryder op i [pyt].[positions] og [queue].[users_queue] tabellerne, efter synkroniseringerne ud til forskellige systemer er håndteret.

        '''
        queue_repo = Queue_users_repo(self.constr_lora)
        users_and_positions_that_are_handled = queue_repo.get_completed_user_queues(
        )
        pos_repo = Position_repo(self.constr_lora)
        deleted_positions = pos_repo.get_positions('WHERE [Deleted] = 1')
        for key in users_and_positions_that_are_handled:
            pu = users_and_positions_that_are_handled[key]
            # Tjekker om alle synkroniseringer, der skal gennemføres er kørt
            if pu.all_syncs_completed():
                # hvis en bruger er slettet og denne er synkroniseret, kan den nu fjernes fra SOFD'en
                if pu.change_type == 'Deleted':
                    if pu.opus_id in deleted_positions:
                        pos_repo.delete_position(pu.opus_id)
                # sletter item fra køen
                queue_repo.delete_person(pu.system_id)
예제 #10
0
    def set_nearest_manager(self):
        '''
        funktion som sætter nærmeste leder på medarbejderne gennem rekursion hvor der ledes op i org hierakiet
        indtil der findes en organisation som har en leder.
        Det her skal køres efter de to andre manager scripts er kørt, fordi det tager udgangspunkt i organsiations
        tabellen og de ledere, som er påtrykt organisations enheder
        '''
        org_repo = Orgunit_repo(self.constr_lora)
        pos_repo = Position_repo(self.constr_lora)
        orgs = org_repo.get_orgunits()
        positions = pos_repo.get_positions('WHERE [deleted] = 0')
        positions_to_update = {}

        for pkey in positions:
            position = positions[pkey]
            # fordi managers ikke skal have sig selv som leder skal vi lige finde det rigtige los_id,
            # hvis du er leder, starter vi på niveauet over dig.
            # dette skal stoppe ved borgmesteren
            los_id_for_recursion = position.los_id

            # hvis der er fucket op i løn, tjekker vi lige at der faktisk er en orgunit
            if los_id_for_recursion not in orgs:
                continue

            if position.is_manager == True:
                org_actual = orgs[los_id_for_recursion]
                if org_actual.niveau > 2:
                    los_id_for_recursion = org_actual.parent_orgunit_los_id

            manager_id = Manager_setup_service.get_manager(
                self, los_id_for_recursion, orgs)
            manager_uuid = positions[manager_id].uuid_userref
            if position.manager_opus_id != manager_id or position.manager_uuid_userref != manager_uuid:
                position.manager_opus_id = manager_id
                position.manager_uuid_userref = manager_uuid
                position.updated = True
                positions_to_update[pkey] = position
            else:
                continue
        pos_repo.update_positions(positions_to_update)
예제 #11
0
 def set_orgunit_manager(self):
     '''
     funktion som tilføjer ledere til orgunits, mange orgunits vil ikke have en leder
     '''
     org_repo = Orgunit_repo(self.constr_lora)
     pos_repo = Position_repo(self.constr_lora)
     orgs = org_repo.get_orgunits()
     managers = pos_repo.get_positions(
         'WHERE [is_manager] = 1 and [deleted] = 0')
     orgs_to_update = {}
     for opus_id in managers:
         manager = managers[opus_id]
         if manager.los_id not in orgs:
             continue
         org = orgs[manager.los_id]
         if org.manager_opus_id == manager.opus_id:
             continue
         else:
             org.manager_opus_id = manager.opus_id
             org.updated = True
             orgs_to_update[org.los_id] = org
     org_repo.update_orgunits(orgs_to_update)
예제 #12
0
    def update_positions(self):
        '''
        Funktion der indsætter nye positions fra OPUS, 
        opdaterer positions hvor der er forandringer og sletter 
        positions som ikke længere er en del af vores lønsystem
        '''
        pos_repo = Position_repo(self.constr_lora)
        sofd_positions = pos_repo.get_positions('WHERE [deleted] = 0')
        opus_positions = self.get_positions()
        positions_to_insert = {}
        positions_to_update = {}

        # key er opus_id (medarbejdernummer)
        for key in opus_positions:
            opus_pos = opus_positions[key]
            # hvis stillingen findes, tjekkes den for forandringer
            if key in sofd_positions:
                sofd_pos = sofd_positions[key]
                if opus_pos.los_id == sofd_pos.los_id and opus_pos.person_ref == sofd_pos.person_ref and opus_pos.position_title == sofd_pos.position_title \
                        and opus_pos.position_id == sofd_pos.position_id and opus_pos.position_title_short == sofd_pos.position_title_short and \
                        opus_pos.position_paygrade_text == sofd_pos.position_paygrade_text and opus_pos.is_manager == sofd_pos.is_manager and \
                        opus_pos.payment_method == sofd_pos.payment_method and opus_pos.payment_method_text == sofd_pos.payment_method_text and \
                        opus_pos.weekly_hours_numerator == sofd_pos.weekly_hours_numerator and opus_pos.weekly_hours_denominator == sofd_pos.weekly_hours_denominator \
                        and opus_pos.invoice_recipient == sofd_pos.invoice_recipient and opus_pos.pos_pnr == sofd_pos.pos_pnr and opus_pos.dsuser == sofd_pos.dsuser \
                        and opus_pos.start_date == sofd_pos.start_date and opus_pos.leave_date == sofd_pos.leave_date:
                    # Når der ikke er forandringer, springer vi videre til næste position
                    continue
                else:
                    opus_pos.updated = True
                    positions_to_update[key] = opus_pos
            # ellers indsættes en ny
            else:
                positions_to_insert[key] = opus_pos

        for key in sofd_positions:
            # hvis en nøgle (opus_id) er i SOFD men ikke i OPUS udtræk er det fordi stillingen er nedlagt
            if key not in opus_positions:
                pos = sofd_positions[key]
                pos.deleted = True
                positions_to_update[key] = pos

        pos_repo.insert_positions(positions_to_insert)
        pos_repo.update_positions(positions_to_update)
예제 #13
0
    def sync_users(self):
        '''
        funktion, der synkroniserer alle de users, som er i køen. der kigges på sts_org feltet fordi det er her vi registerer om et queue item er sendt
        til sykronisering eller ej.
        '''
        queue_repo = Queue_users_repo(self.constr_lora)
        queue = queue_repo.get_user_queues("WHERE sts_org = 0")
        if (len(queue) > 0):
            synced_queue_items = {}
            usr_repo = User_repo(self.constr_lora)
            per_repo = Person_repo(self.constr_lora)
            pos_repo = Position_repo(self.constr_lora)
            orgs = self.org_repo.get_orgunits()
            usrs = usr_repo.get_users()
            pers = per_repo.get_persons()
            poses = pos_repo.get_positions()
            for system_id in queue:
                queue_item = queue[system_id]
                if queue_item.change_type == 'Updated':
                    '''
                    Når en medarbejder forlader organisationen, bliver der typisk oprettet et "updated" event i opus, dagen før der oprettes et "deleted" event.
                    Hvis synkroniseirngen af en eller anden årsag går galt. Eller begge events kommer samme dag (kmd levere kun data 5 dage om ugen, så det kan poole)
                    vil denne "updated" stoppe synkroniseringen fordi stillingen slås op i pyt.positions når der skal opdateres. Her vil stillinge dog ikke længere være,
                    fordi den også er deleted - og et deleted event fjerne stillingen når eventet er føjet til køen.

                    Følgene IF sætning fikser det problem.
                    '''
                    if queue_item.opus_id not in poses or queue_item.opus_id not in usrs:
                        queue_item.change_type = 'Deleted'
                        synced_queue_items[system_id] = queue_item
                        continue
                    pos = poses[queue_item.opus_id]
                    if pos.person_ref not in pers:
                        queue_item.change_type = 'Deleted'
                        synced_queue_items[system_id] = queue_item
                        continue
                    usr = usrs[queue_item.opus_id]
                    per = pers[pos.person_ref]
                    org = orgs[pos.los_id]
                    person_json = Person_json(
                        per.get_firstname_including_displayname() + ' ' +
                        per.get_lastname_including_displayname(), per.cpr)
                    position_json = Position_json(org.uuid, org.longname)
                    usr_json = User_json(pos.uuid_userref, usr.userid,
                                         usr.email, org.longname,
                                         queue_item.opus_id, usr.phone)
                    usr_json.add_person(person_json)
                    usr_json.add_position(position_json)
                    json_to_submit = json.dumps(
                        usr_json.reprJSON(),
                        cls=ComplexEncoder,
                        ensure_ascii=False).encode('utf8')
                    result = Os2sync_sync_service.post_json(
                        self, self.user_api_url, json_to_submit)
                    if result == 200:
                        queue_item.sts_org = True
                        synced_queue_items[system_id] = queue_item
                    # det følgende opdaterer status i DB per enhed, i stedet for at tage dem i et ruf. Kan bruges når der er MANGE i kø
                    #if result == 200:
                    #    queue_item.sts_org = True
                    #    queue_repo.update_queue_user(queue_item)

                elif queue_item.change_type == 'Deleted':
                    #print('deleted')
                    end_point_url_delete = self.user_api_url + '/' + queue_item.uuid
                    result = Os2sync_sync_service.delete_action(
                        self, end_point_url_delete)
                    if result == 200:
                        queue_item.sts_org = True
                        synced_queue_items[system_id] = queue_item
                    # det følgende opdaterer status i DB per enhed, i stedet for at tage dem i et ruf. Kan bruges når der er MANGE i kø
                    #if result == 200:
                    #    queue_item.sts_org = True
                    #    queue_repo.update_queue_user(queue_item)
            queue_repo.update_queue_users(synced_queue_items)
예제 #14
0
    def build_people_and_positions_from_opusxml(self):
        '''
        OPUS XML filen fra KMD indeholder to tags employee og orgunit.
        Denne funktion splitter "employee" tagget op i to dictionaries,
        som indeholder henholdsvis Person og Position objekter, der bliver
        kædet sammen med CPR.
        Der er også en reference til den orgunit som en position tilhører.

        I Person dictionary er CPR nøgle.
        I Position dictionary er OPUS ID (medarbejdernr) nøgle.
        Begge er unikke og ændre sig ikke.

        OBS: Et CPR nr kan i teorien godt ændre sig, hvis en person f.eks.
        skifter køn, men OPUS kan ikke håndtere den slags forandringer, derfor
        er det heller ikke et problem i dette script. Hvis OPUS engang bliver 
        woke, skal scriptet her rettes til.
        '''
        pos_repo = Position_repo(self.constr_lora)
        disabled_orgs = pos_repo.get_disabled_orgunits()
        for emp in self.root.findall('employee'):
            if emp.get('action') == None:
                cpr = emp.find('cpr').text
                opus_id = emp.get('id')
                los_id = int(emp.find('orgUnit').text)
                if los_id in disabled_orgs:
                    # vi har nogle orgunits som indeholder ikke-medarbejdere, dem ønsker vi ikke i SOFD'en og de bliver sorteret fra her.
                    continue

                userId = None
                if emp.find('userId') != None:
                    userId = emp.find('userId').text

                # sætter en start dato fra de forskellige datapunkter vi har at gøre godt med. Det er lidt rodet fordi det er en manuel indtastning fra løn
                # Entry date er aldrig none, men tom når der ikke er en dato
                startdate = None
                if emp.find('entryDate').text != None:
                    startdate = emp.find('entryDate').text
                elif emp.find('initialEntry') != None:
                    startdate = emp.find('initialEntry').text
                elif emp.find('entryIntoGroup') != None:
                    startdate = emp.find('entryIntoGroup').text

                if startdate == None:
                    # Hvis der ikke er en start dato for en stilling, er den oprettet forkert i løn og kan ikke meldes til vores andre systemer, derfor ignorer vi den.
                    print(opus_id)
                    continue
                else:
                    startdate = datetime.strptime(startdate, '%Y-%m-%d').date()

                leavedate = None
                if emp.find('leaveDate') != None:
                    leavedate = emp.find('leaveDate').text

                per = Person(cpr,
                             emp.find('firstName').text,
                             emp.find('lastName').text,
                             emp.find('address').text,
                             emp.find('postalCode').text,
                             emp.find('city').text,
                             emp.find('country').text,
                             True)

                pos = Position(opus_id,
                               None,
                               los_id,
                               cpr,
                               emp.find('cpr').get('suppId'),
                               emp.find('position').text,
                               emp.find('positionId').text,
                               emp.find('positionShort').text,
                               emp.find('payGradeText').text,
                               emp.find('isManager').text,
                               emp.find('workContract').text,
                               emp.find('workContractText').text,
                               emp.find('numerator').text,
                               emp.find('denominator').text,
                               emp.find('invoiceRecipient').text,
                               emp.find('productionNumber').text,
                               userId,
                               startdate,
                               leavedate,
                               None,
                               None,
                               True,
                               False,
                               False)

                self.persons[cpr] = per
                self.positions[int(opus_id)] = pos
            elif emp.get('action') == 'leave':
                # OPUS filen indeholder alle stillinger der har eksisteret, vi sorterer de nedlagte fra her.
                continue