def test_get_option_list_case_ignore_finality_list_choice(self): """ This test ensure that the tree will be pruned when a child if type of finality list choice and option isn't considered as part of tree """ option_1 = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=MiniTrainingType.OPTION.name) GroupElementYearFactory(parent=self.root, child_branch=option_1) for finality_type in [ GroupType.FINALITY_120_LIST_CHOICE.name, GroupType.FINALITY_180_LIST_CHOICE.name ]: finality_group = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=finality_type) GroupElementYearFactory(parent=self.root, child_branch=finality_group) GroupElementYearFactory( parent=finality_group, child_branch=EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=MiniTrainingType.OPTION.name)) node = EducationGroupHierarchy(self.root) self.assertListEqual(node.get_option_list(), [option_1])
def test_node_to_list_flat(self): node = EducationGroupHierarchy(self.parent) list_children = node.to_list(flat=True) self.assertCountEqual(list_children, [ self.group_element_year_1, self.group_element_year_1_1, self.group_element_year_2, self.group_element_year_2_1 ])
def test_get_option_list_case_result_found(self): option_1 = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=MiniTrainingType.OPTION.name) GroupElementYearFactory(parent=self.root, child_branch=option_1) node = EducationGroupHierarchy(self.root) self.assertListEqual(node.get_option_list(), [option_1])
def test_node_to_list_with_pruning_function(self): """ This test ensure that if the parameter pruning function is specified we only get the tree without node which has been pruned """ node = EducationGroupHierarchy(self.parent) list_children = node.to_list( flat=True, pruning_function=lambda child: child.group_element_year.pk == self. group_element_year_2.pk) self.assertCountEqual(list_children, [self.group_element_year_2])
def test_get_finality_list_case_result_found(self): finality_list = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=GroupType.FINALITY_120_LIST_CHOICE) finality_1 = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=TrainingType.MASTER_MS_120.name) GroupElementYearFactory(parent=self.root, child_branch=finality_list) GroupElementYearFactory(parent=finality_list, child_branch=finality_1) node = EducationGroupHierarchy(self.root) self.assertListEqual(node.get_finality_list(), [finality_1])
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) root = self.get_root() self.hierarchy = EducationGroupHierarchy(root, tab_to_show=self.request.GET.get("tab_to_show")) # TODO remove parent in context context['person'] = self.get_person() context['root'] = root context['root_id'] = root.pk context['parent'] = root context['tree'] = json.dumps(self.hierarchy.to_json()) context['group_to_parent'] = self.request.GET.get("group_to_parent") or '0' context['show_prerequisites'] = self.show_prerequisites(root) context['selected_element_clipboard'] = self.get_selected_element_for_clipboard() return context
def test_tree_luy_is_prerequisite(self): # self.learning_unit_year_1 is prerequisite PrerequisiteItemFactory( learning_unit=self.learning_unit_year_1.learning_unit, prerequisite=PrerequisiteFactory(education_group_year=self.parent)) node = EducationGroupHierarchy(self.parent) json = node.to_json() self.assertEqual( json['children'][1]['children'][0]['a_attr']['title'], "{}\n{}".format(self.learning_unit_year_1.complete_title, _("The learning unit is a prerequisite"))) self.assertEqual(json['children'][1]['children'][0]['icon'], 'fa fa-arrow-right')
class LearningUnitGenericDetailView(PermissionRequiredMixin, DetailView, CatalogGenericDetailView): model = LearningUnitYear context_object_name = "learning_unit_year" pk_url_kwarg = 'learning_unit_year_id' permission_required = 'base.can_access_education_group' raise_exception = True def get_person(self): return get_object_or_404(Person, user=self.request.user) def get_root(self): return get_object_or_404(EducationGroupYear, pk=self.kwargs.get("root_id")) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) root = self.get_root() self.hierarchy = EducationGroupHierarchy(root, tab_to_show=self.request.GET.get("tab_to_show")) # TODO remove parent in context context['person'] = self.get_person() context['root'] = root context['root_id'] = root.pk context['parent'] = root context['tree'] = json.dumps(self.hierarchy.to_json()) context['group_to_parent'] = self.request.GET.get("group_to_parent") or '0' context['show_prerequisites'] = self.show_prerequisites(root) context['selected_element_clipboard'] = self.get_selected_element_for_clipboard() return context def show_prerequisites(self, education_group_year): return education_group_year.education_group_type.name not in NO_PREREQUISITES
def test_contains_luy_borrowed(self): acronym = 'LTEST0022' acronym2 = 'LTEST0023' GroupElementYearFactory( parent=self.group_element_year_2.child_branch, child_branch=None, child_leaf=LearningUnitYearFactory( acronym=acronym, academic_year=self.academic_year, learning_container_year__requirement_entity=self.BARC.entity)) GroupElementYearFactory( parent=self.group_element_year_2.child_branch, child_branch=None, child_leaf=LearningUnitYearFactory( acronym=acronym2, academic_year=self.academic_year, learning_container_year__requirement_entity=self.BARC.entity, learning_container_year__allocation_entity=self.MATH.entity)) node = json.dumps(EducationGroupHierarchy(self.parent).to_json()) str_expected_borrowed = '|E| {}'.format(acronym) str_expected_borrowed2 = '|E|S| {}'.format(acronym2) str_expected_not_borrowed = '|E| LTEST0021' self.assertTrue(str_expected_borrowed in node) self.assertTrue(str_expected_borrowed2 in node) self.assertTrue(str_expected_not_borrowed not in node)
def test_get_verbose_children(self): result = EducationGroupHierarchy(self.education_group_year_1).to_list() context_waiting = [ self.group_element_year_1, [self.group_element_year_2], self.group_element_year_3, [self.group_element_year_4] ] self.assertEqual(result, context_waiting) credits = self.group_element_year_1.relative_credits or self.group_element_year_1.child_branch.credits or 0 verbose_branch = "{} ({} {})".format( self.group_element_year_1.child.title, credits, _("credits")) self.assertEqual(self.group_element_year_1.verbose, verbose_branch) components = LearningComponentYear.objects.filter( learning_unit_year=self.group_element_year_2.child_leaf).annotate( total=Case(When(hourly_volume_total_annual=None, then=0), default=F('hourly_volume_total_annual'))).values( 'type', 'total') verbose_leaf = "{} {} [{}] ({} {})".format( self.group_element_year_2.child_leaf.acronym, self.group_element_year_2.child_leaf.complete_title, volume_total_verbose(components), self.group_element_year_2.relative_credits or self.group_element_year_2.child_leaf.credits or 0, _("credits"), ) self.assertEqual(self.group_element_year_2.verbose, verbose_leaf)
def test_get_finality_list_case_multiple_result_found_on_different_children( self): list_finality = [] for _ in range(5): group_child = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=GroupType.SUB_GROUP.name) GroupElementYearFactory(parent=self.root, child_branch=group_child) finality = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=TrainingType.MASTER_MS_120.name) list_finality.append(finality) GroupElementYearFactory(parent=group_child, child_branch=finality) node = EducationGroupHierarchy(self.root) self.assertCountEqual(node.get_finality_list(), list_finality)
def test_get_option_list_case_multiple_result_found_on_different_children( self): list_option = [] for _ in range(5): group_child = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=GroupType.SUB_GROUP.name) GroupElementYearFactory(parent=self.root, child_branch=group_child) option = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=MiniTrainingType.OPTION.name) list_option.append(option) GroupElementYearFactory(parent=group_child, child_branch=option) node = EducationGroupHierarchy(self.root) self.assertCountEqual(node.get_option_list(), list_option)
def test_build_tree_reference(self): """ This tree contains a reference link. """ self.group_element_year_1.link_type = LinkTypes.REFERENCE.name self.group_element_year_1.save() node = EducationGroupHierarchy(self.parent) self.assertEqual(node.children[0]._get_icon(), static('img/reference.jpg')) list_children = node.to_list() self.assertEqual(list_children, [ self.group_element_year_1_1, self.group_element_year_2, [self.group_element_year_2_1] ])
def test_build_pdf_tree_with_mandatory(self): tree = EducationGroupHierarchy(self.education_group_year_1).to_list() out = Template( "{% load education_group_pdf %}" "{{ tree|pdf_tree_list }}" ).render(Context({ 'tree': tree })) self.assertEqual(out, _build_correct_tree_list(tree))
def test_get_group_tree(self): response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_200_OK) serializer = EducationGroupTreeSerializer( EducationGroupHierarchy(self.common_core), context={ 'request': RequestFactory().get(self.url), }) self.assertEqual(response.data, serializer.data)
def __init__(self, egy: EducationGroupYear): self.egy = egy self.hierarchy = EducationGroupHierarchy(root=self.egy) self.learning_unit_years_parent = {} for grp in self.hierarchy.included_group_element_years: if not grp.child_leaf: continue self.learning_unit_years_parent.setdefault(grp.child_leaf.id, grp)
def test_tree_to_json(self): node = EducationGroupHierarchy(self.parent) json = node.to_json() self.assertEqual(json['text'], self.parent.verbose) self.assertEqual( json['a_attr']['href'], reverse('education_group_read', args=[self.parent.pk, self.parent.pk]) + "?group_to_parent=0") self.assertEqual( json['children'][1]['children'][0]['a_attr']['href'], reverse('learning_unit_utilization', args=[ self.parent.pk, self.group_element_year_2_1.child_leaf.pk ]) + "?group_to_parent={}".format(self.group_element_year_2_1.pk))
def test_contains_luy_borrowed_without_entity(self): acronym = 'LTEST0022' GroupElementYearFactory( parent=self.group_element_year_2.child_branch, child_branch=None, child_leaf=LearningUnitYearFactory(acronym=acronym)) node = json.dumps(EducationGroupHierarchy(self.parent).to_json()) str_expected_not_borrowed = '|E| LTEST0022' self.assertTrue(acronym in node) self.assertTrue(str_expected_not_borrowed not in node)
def pdf_content(request, root_id, education_group_year_id, language): education_group_year = get_object_or_404(EducationGroupYear, pk=education_group_year_id) tree_object = EducationGroupHierarchy(root=education_group_year, pdf_content=True) context = { 'root': education_group_year, 'tree': tree_object.to_list(), 'language': language, 'created': datetime.datetime.now(), 'max_block': tree_object.max_block, 'main_part_col_length': get_main_part_col_length(tree_object.max_block), } with translation.override(language): return render_pdf( request, context=context, filename=education_group_year.acronym, template='pdf_content.html', )
def test_get_option_list_case_reference_link(self): """ This test ensure that the tree will not be pruned when the link of child is reference """ reference_group_child = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=GroupType.SUB_GROUP.name) GroupElementYearFactory( parent=self.root, child_branch=reference_group_child, link_type=LinkTypes.REFERENCE.name, ) option_1 = EducationGroupYearFactory( academic_year=self.academic_year, education_group_type__name=MiniTrainingType.OPTION.name) GroupElementYearFactory(parent=reference_group_child, child_branch=option_1) node = EducationGroupHierarchy(self.root) self.assertListEqual(node.get_option_list(), [option_1])
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # This objects are mandatory for all education group views context['person'] = self.person # FIXME same param context['root'] = self.root context['root_id'] = self.root.pk context['parent'] = self.root context['parent_training'] = self.object.parent_by_training() context["show_identification"] = self.show_identification() context["show_diploma"] = self.show_diploma() context["show_general_information"] = self.show_general_information() context["show_skills_and_achievements"] = self.show_skills_and_achievements() context["show_administrative"] = self.show_administrative() context["show_content"] = self.show_content() context["show_utilization"] = self.show_utilization() context["show_admission_conditions"] = self.show_admission_conditions() if self.with_tree: # FIXME: resolve dependency in other way from program_management.business.group_element_years.group_element_year_tree import EducationGroupHierarchy education_group_hierarchy_tree = EducationGroupHierarchy(self.root, tab_to_show=self.request.GET.get('tab_to_show')) context['tree'] = json.dumps(education_group_hierarchy_tree.to_json()) context['group_to_parent'] = self.request.GET.get("group_to_parent") or '0' context['can_change_education_group'] = perms.is_eligible_to_change_education_group( person=self.person, education_group=context['object'], ) context['can_change_coorganization'] = perms.is_eligible_to_change_coorganization( person=self.person, education_group=context['object'], ) context['enums'] = mdl.enums.education_group_categories context['current_academic_year'] = self.starting_academic_year context['selected_element_clipboard'] = self.get_selected_element_for_clipboard() context['form_xls_custom'] = CustomXlsForm() return context
def get_object(self): queryset = self.filter_queryset(self.get_queryset()) filter_kwargs = { lookup_field: self.kwargs[lookup_url_kwarg] for lookup_field, lookup_url_kwarg in zip(self.lookup_fields, self.lookup_url_kwargs) } education_group_year = get_object_or_404(queryset, **filter_kwargs) self.check_object_permissions(self.request, education_group_year) return EducationGroupHierarchy(education_group_year)
def test_contains_luy_borrowed_when_child_higher_entity_type_than_parent( self): acronym = 'LTEST0022' GroupElementYearFactory( parent=self.group_element_year_2.child_branch, child_branch=None, child_leaf=LearningUnitYearFactory( acronym=acronym, learning_container_year__requirement_entity=self.root.entity)) node = json.dumps(EducationGroupHierarchy(self.parent).to_json()) str_expected_borrowed = '|E| {}'.format(acronym) self.assertTrue(str_expected_borrowed not in node)
def test_contains_luy_borrowed_from_non_academic_entities(self): acronym = 'LTEST0022' GroupElementYearFactory( parent=self.parent_ILV, child_branch=None, child_leaf=LearningUnitYearFactory( acronym=acronym, academic_year=self.academic_year, learning_container_year__requirement_entity=self.BARC.entity)) node = json.dumps(EducationGroupHierarchy(self.parent_ILV).to_json()) str_expected_borrowed = '|E| {}'.format(acronym) self.assertTrue(str_expected_borrowed in node)
def test_tree_get_url(self): test_cases = [ { 'name': 'with tab', 'node': EducationGroupHierarchy(self.parent, tab_to_show='show_identification'), 'correct_url': reverse('education_group_read', args=[self.parent.pk, self.parent.pk]) + "?group_to_parent=0&tab_to_show=show_identification" }, { 'name': 'without tab', 'node': EducationGroupHierarchy(self.parent), 'correct_url': reverse('education_group_read', args=[self.parent.pk, self.parent.pk]) + "?group_to_parent=0" }, { 'name': 'with wrong tab', 'node': EducationGroupHierarchy(self.parent, tab_to_show='not_existing'), 'correct_url': reverse('education_group_read', args=[self.parent.pk, self.parent.pk]) + "?group_to_parent=0" }, ] for case in test_cases: with self.subTest(type=case['name']): self.assertEqual(case['correct_url'], case['node'].get_url())
def test_tree_to_json_a_attr(self): """In this test, we ensure that a attr contains some url for tree contextual menu""" node = EducationGroupHierarchy(self.parent) json = node.to_json() child = self.group_element_year_1.child_branch expected_modify_url = reverse( 'group_element_year_update', args=[self.parent.pk, child.pk, self.group_element_year_1.pk]) self.assertEqual(json['children'][0]['a_attr']['modify_url'], expected_modify_url) expected_attach_url = reverse('education_group_attach', args=[self.parent.pk, child.pk]) self.assertEqual(json['children'][0]['a_attr']['attach_url'], expected_attach_url) expected_detach_url = reverse( 'group_element_year_delete', args=[self.parent.pk, child.pk, self.group_element_year_1.pk]) self.assertEqual(json['children'][0]['a_attr']['detach_url'], expected_detach_url)
def test_contains_egy_borrowed_from_non_academic_entities(self): acronym = 'LTEST0022' group = GroupElementYearFactory(parent=self.parent_ILV, child_branch=EducationGroupYearFactory( acronym=acronym, academic_year=self.academic_year, management_entity=self.BARC.entity, ), child_leaf=None) node = json.dumps(EducationGroupHierarchy(self.parent_ILV).to_json()) str_expected_borrowed = '|E| {}'.format(group.child_branch.verbose) self.assertTrue(str_expected_borrowed in node)
def test_build_pdf_tree_with_optional(self): self.group_element_year_1.is_mandatory = False self.group_element_year_1.save() self.group_element_year_2.is_mandatory = False self.group_element_year_2.save() tree = EducationGroupHierarchy(self.education_group_year_1).to_list() out = Template( "{% load education_group_pdf %}" "{{ tree|pdf_tree_list }}" ).render(Context({ 'tree': tree })) self.assertEqual(out, _build_correct_tree_list(tree))
def test_contains_egy_borrowed_without_entity(self): acronym = 'LTEST0022' group = GroupElementYearFactory( parent=self.group_element_year_2.child_branch, child_branch=EducationGroupYearFactory( acronym=acronym, academic_year=self.academic_year, management_entity=None), child_leaf=None) node = json.dumps(EducationGroupHierarchy(self.parent).to_json()) str_expected_not_borrowed = '|E| {}'.format(group.child_branch.verbose) self.assertTrue(group.child_branch.verbose in node) self.assertTrue(str_expected_not_borrowed not in node)
def _check_detach_options_rules(self): """ In context of 2M when we detach an option [or group which contains option], we must ensure that these options are not present in MA/MD/MS """ options_to_detach = self._options_to_detach() for master_2m in self.get_parents_program_master(): master_2m_tree = EducationGroupHierarchy(root=master_2m) counter_options = Counter(master_2m_tree.get_option_list()) counter_options.subtract(options_to_detach) options_to_check = [opt for opt, count in counter_options.items() if count == 0] if not options_to_check: continue finality_list = [elem.child for elem in master_2m_tree.to_list(flat=True) if isinstance(elem.child, EducationGroupYear) and elem.child.education_group_type.name in TrainingType.finality_types()] for finality in finality_list: mandatory_options = EducationGroupHierarchy(root=finality).get_option_list() missing_options = set(options_to_check) & set(mandatory_options) if missing_options: self.errors.append( ValidationError( ngettext( "Option \"%(acronym)s\" cannot be detach because it is contained in" " %(finality_acronym)s program.", "Options \"%(acronym)s\" cannot be detach because they are contained in" " %(finality_acronym)s program.", len(missing_options) ) % { "acronym": ', '.join(option.acronym for option in missing_options), "finality_acronym": finality.acronym }) )