from typing import List import structlog from vbv_lernwelt.core.models import Organisation, User from vbv_lernwelt.course.consts import ( COURSE_UK, COURSE_UK_FR, COURSE_UK_IT, VV_COURSE_IDS, ) from vbv_lernwelt.course.models import Course, CourseSessionUser from vbv_lernwelt.learning_mentor.models import ( AgentParticipantRelation, AgentParticipantRoleType, ) logger = structlog.get_logger(__name__) UK_COURSES = [COURSE_UK, COURSE_UK_FR, COURSE_UK_IT] def users_by_org( org: Organisation, is_uk: bool, courses: List[Course], excluded_course_sessions: List[int] = None, ) -> set[CourseSessionUser]: if not excluded_course_sessions: excluded_course_sessions = [] return set( CourseSessionUser.objects.filter(user__organisation=org) .filter(course_session__course__configuration__is_uk=is_uk) .filter(role=CourseSessionUser.Role.MEMBER.value) .filter(course_session__course_id__in=courses) .exclude(course_session_id__in=excluded_course_sessions) ) def uk_cs_users_by_org(org: Organisation) -> set[CourseSessionUser]: return users_by_org( org, is_uk=True, courses=UK_COURSES, # ignore "Demo" course sessions excluded_course_sessions=[4, 5, 6], ) def vv_cs_users_by_org(org: Organisation) -> set[CourseSessionUser]: return users_by_org(org, False, VV_COURSE_IDS) def create_or_sync_berufsbildner( berufsbildner: User, organisation: Organisation ) -> bool: org_members = uk_cs_users_by_org(organisation) return create_or_sync_learning_mentor(berufsbildner, org_members, organisation) def create_or_sync_ausbildungsverantwortlicher( ausbildungsverantwortlicher: User, organisation: Organisation ) -> bool: org_members = vv_cs_users_by_org(organisation) return create_or_sync_learning_mentor( ausbildungsverantwortlicher, org_members, organisation ) def create_or_sync_learning_mentor( agent: User, org_members: set[CourseSessionUser], organisation: Organisation ) -> bool: logger.info( "Creating or syncing berufsbildner/ausbildungsverantwortlicher", berufsbildner=agent, org=organisation.name_de, ) # Check if it is a valid organisation # ids < 4 are "andere Broker/Krankenversicherer" if organisation and organisation.organisation_id < 4: logger.error("Invalid organisation", org=organisation) return False # Get existing connections (full relation objects) existing_relations = set(agent.agentparticipantrelation_set.all()) # Add new relations that are not in existing relations existing_members = {relation.participant for relation in existing_relations} for csu in org_members: if csu not in existing_members: AgentParticipantRelation.objects.get_or_create( agent=agent, participant=csu, role=AgentParticipantRoleType.BERUFSBILDNER.value, ) # Remove old relations that are not in the new relations for relation in existing_relations: if relation.participant not in org_members: relation.delete() return True def delete_berufsbildner_relation(berufsbildner: User, organisation: Organisation): org_members = uk_cs_users_by_org(organisation) delete_org_supervisor_relation(berufsbildner, org_members) def delete_ausbildungsverantwortlicher_relation( ausbildungsverantwortlicher: User, organisation: Organisation ): org_members = vv_cs_users_by_org(organisation) delete_org_supervisor_relation(ausbildungsverantwortlicher, org_members) def delete_org_supervisor_relation( agent: User, org_members: set[CourseSessionUser], ): # As the key berufsbildner is used in several courses, we use org_members to select the ones from the correct # course sessions relations_to_delete = agent.agentparticipantrelation_set.filter( participant__in=org_members ) # Bulk delete the identified relations deleted_count, _ = relations_to_delete.delete() # Log the result logger.info( "Deleted ausbildungsverantwortlicher relations", agent=agent, deleted_count=deleted_count, )