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)
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
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))
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