示例#1
0
def _build_legend_sheet():
    content = []
    colored_cells = defaultdict(list)
    idx = 1
    for name in ProposalType.get_names():
        content.append([ProposalType.get_value(name)])
        colored_cells[PROPOSAL_LINE_STYLES.get(name)].append(idx)
        idx += 1
    return {LEGEND_WB_STYLE: colored_cells, LEGEND_WB_CONTENT: content}
示例#2
0
class ProposalLearningUnitFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = "base.ProposalLearningUnit"
        django_get_or_create = ('learning_unit_year',)

    external_id = factory.fuzzy.FuzzyText(length=10, chars=string.digits)
    changed = factory.fuzzy.FuzzyNaiveDateTime(datetime.datetime(2016, 1, 1), datetime.datetime(2017, 3, 1))
    learning_unit_year = factory.SubFactory(LearningUnitYearFakerFactory)
    type = factory.Iterator(ProposalType.choices(), getter=operator.itemgetter(0))
    state = factory.Iterator(ProposalState.choices(), getter=operator.itemgetter(0))
    initial_data = {}
    entity = factory.SubFactory(EntityFactory)
    folder_id = factory.fuzzy.FuzzyInteger(100)
    author = factory.SubFactory(PersonFactory)
示例#3
0
    def test_access_edit_learning_unit_proposal_as_faculty_manager(self):
        generated_container = GenerateContainer(start_year=self.academic_yr_1,
                                                end_year=self.academic_yr_1)
        generated_container_first_year = generated_container.generated_container_years[
            0]
        an_requirement_entity = generated_container_first_year.requirement_entity_container_year

        luy = generated_container_first_year.learning_unit_year_full
        faculty_managers = [
            create_person_with_permission_and_group(FACULTY_MANAGER_GROUP),
            create_person_with_permission_and_group(UE_FACULTY_MANAGER_GROUP)
        ]

        a_proposal = ProposalLearningUnitFactory(
            state=proposal_state.ProposalState.CENTRAL.name,
            type=proposal_type.ProposalType.SUPPRESSION.name,
            learning_unit_year=luy)

        generate_modification_transformation_proposal_calendars([
            self.academic_yr, self.academic_yr_1, self.academic_yr_2,
            self.academic_yr_6
        ])

        for manager in faculty_managers:
            a_proposal.state = proposal_state.ProposalState.CENTRAL.name
            a_proposal.save()
            PersonEntityFactory(entity=an_requirement_entity, person=manager)

            self.assertFalse(perms.is_eligible_to_edit_proposal(None, manager))
            self.assertFalse(
                perms.is_eligible_to_edit_proposal(a_proposal, manager))

            a_proposal.state = proposal_state.ProposalState.FACULTY.name
            a_proposal.save()
            self.assertTrue(
                perms.is_eligible_to_edit_proposal(a_proposal, manager))

            for tag in ProposalType.choices():
                a_proposal.type = tag[0]
                a_proposal.save()
                if a_proposal.type != ProposalType.MODIFICATION:
                    self.assertTrue(
                        perms.is_eligible_to_edit_proposal(
                            a_proposal, manager))
                else:
                    self.assertFalse(
                        perms.is_eligible_to_edit_proposal(
                            a_proposal, manager))
示例#4
0
class LearningUnitProposalForm(LearningUnitSearchForm):

    entity_folder_id = forms.ChoiceField(label=_('Folder entity'),
                                         required=False)

    folder_id = forms.IntegerField(
        min_value=0,
        required=False,
        label=_('Folder num.'),
    )

    proposal_type = forms.ChoiceField(label=_('Proposal type'),
                                      choices=_get_sorted_choices(
                                          ProposalType.choices()),
                                      required=False)

    proposal_state = forms.ChoiceField(label=_('Proposal status'),
                                       choices=_get_sorted_choices(
                                           ProposalState.choices()),
                                       required=False)

    def __init__(self, data, person, *args, **kwargs):
        super().__init__(data, *args, **kwargs)
        self._get_entity_folder_id_linked_ordered_by_acronym(person)

    def _get_entity_folder_id_linked_ordered_by_acronym(self, person):
        entities = Entity.objects.filter(
            proposallearningunit__isnull=False).distinct()
        entities_sorted_by_acronym = sorted(
            list(entities.filter(id__in=person.linked_entities)),
            key=lambda t: t.most_recent_acronym)
        self.fields['entity_folder_id'].choices = [LearningUnitSearchForm.ALL_LABEL] + \
                                                  [(ent.pk, ent.most_recent_acronym)
                                                   for ent in entities_sorted_by_acronym]

    def get_proposal_learning_units(self):
        learning_units = self.get_queryset().filter(
            proposallearningunit__isnull=False)

        learning_units = mdl.proposal_learning_unit.filter_proposal_fields(
            learning_units, **self.cleaned_data)

        for learning_unit in learning_units:
            append_latest_entities(learning_unit, False)

        return learning_units
示例#5
0
class ProposalLearningUnit(models.Model):
    external_id = models.CharField(max_length=100,
                                   blank=True,
                                   null=True,
                                   db_index=True)
    changed = models.DateTimeField(null=True, auto_now=True)
    author = models.ForeignKey('Person', null=True, on_delete=models.PROTECT)
    date = models.DateTimeField(auto_now=True)
    learning_unit_year = models.OneToOneField('LearningUnitYear',
                                              on_delete=models.CASCADE)
    type = models.CharField(max_length=50,
                            choices=ProposalType.choices(),
                            verbose_name=_("Type"),
                            default=ProposalType.MODIFICATION.name)

    state = models.CharField(max_length=50,
                             choices=ProposalState.choices(),
                             verbose_name=_("State"),
                             default=ProposalState.FACULTY.name)

    initial_data = JSONField(default={}, encoder=DjangoJSONEncoder)
    entity = models.ForeignKey('Entity', on_delete=models.CASCADE)
    folder_id = models.PositiveIntegerField(
        validators=[MaxValueValidator(9999999)])

    class Meta:
        permissions = (
            # TODO: Remove this permissions : already exists with can_change_proposal_learning_unit
            ("can_edit_learning_unit_proposal",
             "Can edit learning unit proposal"), )

    def __str__(self):
        return "{} - {}".format(self.folder_id, self.learning_unit_year)

    @property
    def folder(self):
        last_entity = entity_version.get_last_version(self.entity)
        return "{}{}".format(last_entity.acronym if last_entity else '',
                             str(self.folder_id))
示例#6
0
class ProposalLearningUnitFilter(FilterSet):
    academic_year = filters.ModelChoiceFilter(
        queryset=AcademicYear.objects.all(),
        required=False,
        label=_('Ac yr.'),
        empty_label=pgettext_lazy("plural", "All"),
    )
    acronym = filters.CharFilter(
        field_name="acronym",
        lookup_expr="iregex",
        max_length=40,
        required=False,
        label=_('Code'),
    )
    requirement_entity = filters.CharFilter(
        method='filter_entity',
        max_length=20,
        label=_('Req. Entity'),
    )
    with_entity_subordinated = filters.BooleanFilter(
        method=lambda queryset, *args, **kwargs: queryset,
        label=_('Include subordinate entities'),
        widget=forms.CheckboxInput,
        initial='True')
    tutor = filters.CharFilter(
        method="filter_tutor",
        max_length=40,
        label=_('Tutor'),
    )
    entity_folder = filters.ChoiceFilter(
        field_name="proposallearningunit__entity_id",
        label=_('Folder entity'),
        required=False,
        empty_label=pgettext_lazy("plural", "All"),
    )
    folder = filters.NumberFilter(field_name="proposallearningunit__folder_id",
                                  min_value=0,
                                  required=False,
                                  label=_('Folder num.'),
                                  widget=forms.TextInput())
    proposal_type = filters.ChoiceFilter(
        field_name="proposallearningunit__type",
        label=_('Proposal type'),
        choices=_get_sorted_choices(ProposalType.choices()),
        required=False,
        empty_label=pgettext_lazy("plural", "All"),
    )
    proposal_state = filters.ChoiceFilter(
        field_name="proposallearningunit__state",
        label=_('Proposal status'),
        choices=_get_sorted_choices(ProposalState.choices()),
        required=False,
        empty_label=pgettext_lazy("plural", "All"),
    )
    search_type = filters.CharFilter(
        field_name="acronym",
        method=lambda request, *args, **kwargs: request,
        widget=forms.HiddenInput,
        required=False,
        initial=SearchTypes.PROPOSAL_SEARCH.value)

    order_by_field = 'ordering'
    ordering = ProposalLearningUnitOrderingFilter(
        fields=(
            ('academic_year__year', 'academic_year'),
            ('acronym', 'acronym'),
            ('full_title', 'title'),
            ('learning_container_year__container_type', 'type'),
            ('entity_requirement', 'requirement_entity'),
            ('proposallearningunit__type', 'proposal_type'),
            ('proposallearningunit__state', 'proposal_state'),
            ('proposallearningunit__folder_id',
             'folder'),  # Overrided by ProposalLearningUnitOrderingFilter
        ),
        widget=forms.HiddenInput)

    class Meta:
        model = LearningUnitYear
        fields = [
            "academic_year",
            "acronym",
            "subtype",
            "requirement_entity",
        ]

    def __init__(self, *args, person=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.person = person
        self.queryset = self.get_queryset
        self._get_entity_folder_id_linked_ordered_by_acronym(self.person)

        # Academic year default value = n+1 for proposals search -> use event having n+1 as first open academic year
        event_perm = event_perms.EventPermCreationOrEndDateProposalFacultyManager(
        )
        self.form.fields[
            "academic_year"].initial = event_perm.get_academic_years().first()

    def _get_entity_folder_id_linked_ordered_by_acronym(self, person):
        most_recent_acronym = EntityVersion.objects.filter(entity__id=OuterRef(
            'id'), ).order_by("-start_date").values('acronym')[:1]

        entities = Entity.objects.filter(
            proposallearningunit__isnull=False).annotate(
                entity_acronym=Subquery(
                    most_recent_acronym)).distinct().order_by("entity_acronym")

        self.form.fields['entity_folder'].choices = [
            (ent.pk, ent.entity_acronym) for ent in entities
        ]

    def filter_entity(self, queryset, name, value):
        with_subordinated = self.form.cleaned_data['with_entity_subordinated']
        lookup_expression = "__".join(["learning_container_year", name, "in"])
        if value:
            entity_ids = get_entities_ids(value, with_subordinated)
            queryset = queryset.filter(**{lookup_expression: entity_ids})
        return queryset

    def filter_tutor(self, queryset, name, value):
        for tutor_name in value.split():
            filter_by_first_name = Q(
                learningcomponentyear__attributionchargenew__attribution__tutor__person__first_name__iregex
                =tutor_name)
            filter_by_last_name = Q(
                learningcomponentyear__attributionchargenew__attribution__tutor__person__last_name__iregex
                =tutor_name)
            queryset = queryset.filter(filter_by_first_name
                                       | filter_by_last_name).distinct()
        return queryset

    @property
    def get_queryset(self):
        # Need this close so as to return empty query by default when form is unbound
        if not self.data:
            return LearningUnitYear.objects.none()

        entity_folder = EntityVersion.objects.filter(
            entity=OuterRef('proposallearningunit__entity'), ).current(
                OuterRef('academic_year__start_date')).values('acronym')[:1]

        has_proposal = ProposalLearningUnit.objects.filter(
            learning_unit_year=OuterRef('pk'), )

        queryset = LearningUnitYear.objects_with_container.filter(
            proposallearningunit__isnull=False).select_related(
                'academic_year',
                'learning_container_year__academic_year',
                'language',
                'externallearningunityear',
                'campus',
                'proposallearningunit',
                'campus__organization',
            ).prefetch_related("learningcomponentyear_set", ).annotate(
                has_proposal=Exists(has_proposal),
                entity_folder=Subquery(entity_folder),
            )

        queryset = LearningUnitYearQuerySet.annotate_full_title_class_method(
            queryset)
        queryset = LearningUnitYearQuerySet.annotate_entities_allocation_and_requirement_acronym(
            queryset)

        return queryset