def __init__(self, *args, **kwargs): self.component = kwargs.pop('component') self.learning_unit_year = kwargs.pop('learning_unit_year') self.entities = kwargs.pop('entities', []) self.is_faculty_manager = kwargs.pop('is_faculty_manager', False) self.title = self.component.acronym self.title_help = _(self.component.type) + ' ' if self.component.type else '' self.title_help += self.component.acronym super().__init__(*args, **kwargs) help_volume_global = "{} = {} * {}".format(_('volume total global'), _('Volume total annual'), _('Planned classes')) # Append dynamic fields entities_to_add = [entity for entity in REQUIREMENT_ENTITIES if entity in self.entities] for i, key in enumerate(entities_to_add): entity = self.entities[key] self.fields["volume_" + key.lower()] = VolumeField( label=entity.acronym, help_text=entity.title, widget=StepHalfIntegerWidget(), ) if i != len(entities_to_add) - 1: self.fields["add" + key.lower()] = EmptyField(label='+') if self.is_faculty_manager \ and self.learning_unit_year.is_full() \ and self.learning_unit_year.learning_container_year.container_type \ in LEARNING_CONTAINER_YEAR_TYPES_CANT_UPDATE_BY_FACULTY: self._disable_central_manager_fields()
def __init__(self, *args, **kwargs): self.component = kwargs.pop('component') self.learning_unit_year = kwargs.pop('learning_unit_year') self.entities = kwargs.pop('entities', []) self.is_faculty_manager = kwargs.pop('is_faculty_manager', False) self.title = _(self.component.get_type_display( )) + ' ' if self.component.type else self.component.acronym self.title_help = _(self.component.get_type_display() ) + ' ' if self.component.type else '' self.title_help += self.component.acronym super().__init__(*args, **kwargs) help_volume_global = "{} = {} * {}".format(_('volume total global'), _('Volume total annual'), _('Planned classes')) # Append dynamic fields entities_to_add = [ entity for entity in REQUIREMENT_ENTITIES if entity in self.entities ] size_entities_to_add = len(entities_to_add) if size_entities_to_add > 1: self.fields["opening_brackets_entities_field"] = EmptyField( label='[') for i, key in enumerate(entities_to_add): entity = self.entities[key] if entity: self.fields["volume_" + key.lower()] = VolumeField( label=entity.acronym, help_text=entity.title, widget=DecimalFormatInput(render_value=True), required=False) if i != len(entities_to_add) - 1: self.fields["add" + key.lower()] = EmptyField(label='+') if size_entities_to_add > 1: self.fields["closing_brackets_entities_field"] = EmptyField( label=']') if self.is_faculty_manager \ and self.learning_unit_year.is_full() \ and self.learning_unit_year.learning_container_year.container_type \ in LEARNING_CONTAINER_YEAR_TYPES_CANT_UPDATE_BY_FACULTY: self._disable_central_manager_fields()
def __init__(self, *args, **kwargs): self.component = kwargs.pop('component') self.learning_unit_year = kwargs.pop('learning_unit_year') self.entities = kwargs.pop('entities', []) self.is_faculty_manager = kwargs.pop('is_faculty_manager', False) self.title = _(self.component.get_type_display( )) + ' ' if self.component.type else self.component.acronym self.title_help = _(self.component.get_type_display() ) + ' ' if self.component.type else '' self.title_help += self.component.acronym super().__init__(*args, **kwargs) # Append dynamic fields entities_to_add = [ entity for entity in REQUIREMENT_ENTITIES if entity in self.entities ] size_entities_to_add = len(entities_to_add) if size_entities_to_add > 1: self.fields["opening_brackets_entities_field"] = EmptyField( label='[') for i, key in enumerate(entities_to_add): entity = self.entities[key] if entity: self.fields["volume_" + key.lower()] = VolumeField( label=entity.acronym, help_text=entity.title, widget=DecimalFormatInput(render_value=True), required=False) if i != len(entities_to_add) - 1: self.fields["add" + key.lower()] = EmptyField(label='+') if size_entities_to_add > 1: self.fields["closing_brackets_entities_field"] = EmptyField( label=']') if self.is_faculty_manager \ and self.learning_unit_year.is_full() \ and self.learning_unit_year.learning_container_year.container_type \ in LCY_TYPES_WITH_FIXED_ACRONYM: self._disable_central_manager_fields()
class MailReminderRow(forms.Form): responsible = EmptyField(label='') learning_unit_years = EmptyField(label='') check = forms.BooleanField(required=False, label='') person_id = forms.IntegerField(widget=forms.HiddenInput(), required=False) def __init__(self, *args, **kwargs): self.person = kwargs.pop('person', None) self.learning_unit_years = kwargs.pop('learning_unit_years', []) super().__init__(*args, **kwargs) self.initial['check'] = True self.initial['responsible'] = self.person if self.person: self.initial['person_id'] = self.person.id self.fields["responsible"].label = "{} {}".format( self.person.last_name, self.person.first_name) acronym_list = _get_acronyms_concatenation(self.learning_unit_years) self.initial['learning_unit_years'] = acronym_list self.fields["learning_unit_years"].label = acronym_list self.fields["responsible"].widget.attrs['class'] = 'no_label'
def __init__(self, *args, **kwargs): self.component = kwargs.pop('component') self.learning_unit_year = kwargs.pop('learning_unit_year') self.entities = kwargs.pop('entities') self.is_faculty_manager = kwargs.pop('is_faculty_manager', False) self.title = self.component.acronym self.title_help = _( self.component.type) + ' ' if self.component.type else '' self.title_help += self.component.acronym super().__init__(*args, **kwargs) # Append dynamic fields for key in ENTITY_TYPES_VOLUME: self._add_entity_fields(key) self.fields['equal_field_3'] = EmptyField(label='=') self.fields['volume_total_requirement_entities'] = VolumeField( label=_('vol_charge'), help_text=_('total_volume_charge')) if self.is_faculty_manager and self.learning_unit_year.is_full(): self._disable_central_manager_fields()
class VolumeEditionForm(forms.Form): requirement_entity_key = 'volume_' + entity_types.REQUIREMENT_ENTITY.lower( ) additional_requirement_entity_1_key = 'volume_' + entity_types.ADDITIONAL_REQUIREMENT_ENTITY_1.lower( ) additional_requirement_entity_2_key = 'volume_' + entity_types.ADDITIONAL_REQUIREMENT_ENTITY_2.lower( ) opening_brackets_field = EmptyField(label='[') opening_parenthesis_field = EmptyField(label='(') volume_q1 = VolumeField( label=_('Q1'), help_text=_('Volume Q1'), widget=DecimalFormatInput(render_value=True), required=False, ) add_field = EmptyField(label='+') volume_q2 = VolumeField( label=_('Q2'), help_text=_('Volume Q2'), widget=DecimalFormatInput(render_value=True), required=False, ) closing_parenthesis_field = EmptyField(label=')') equal_field_1 = EmptyField(label='=') volume_total = VolumeField( label=_('Vol. annual'), help_text= _('The annual volume must be equal to the sum of the volumes Q1 and Q2' ), widget=DecimalFormatInput(render_value=True), required=False, ) help_volume_total = "{} = {} + {}".format(_('Volume total annual'), _('Volume Q1'), _('Volume Q2')) closing_brackets_field = EmptyField(label=']') mult_field = EmptyField(label='*') planned_classes = forms.IntegerField(label=_('Planned classes'), help_text=_('Planned classes'), min_value=0, widget=forms.TextInput(), required=False) equal_field_2 = EmptyField(label='=') _post_errors = [] _parent_data = {} _faculty_manager_fields = ['volume_q1', 'volume_q2'] def __init__(self, *args, **kwargs): self.component = kwargs.pop('component') self.learning_unit_year = kwargs.pop('learning_unit_year') self.entities = kwargs.pop('entities', []) self.is_faculty_manager = kwargs.pop('is_faculty_manager', False) self.title = _(self.component.get_type_display( )) + ' ' if self.component.type else self.component.acronym self.title_help = _(self.component.get_type_display() ) + ' ' if self.component.type else '' self.title_help += self.component.acronym super().__init__(*args, **kwargs) help_volume_global = "{} = {} * {}".format(_('volume total global'), _('Volume total annual'), _('Planned classes')) # Append dynamic fields entities_to_add = [ entity for entity in REQUIREMENT_ENTITIES if entity in self.entities ] size_entities_to_add = len(entities_to_add) if size_entities_to_add > 1: self.fields["opening_brackets_entities_field"] = EmptyField( label='[') for i, key in enumerate(entities_to_add): entity = self.entities[key] if entity: self.fields["volume_" + key.lower()] = VolumeField( label=entity.acronym, help_text=entity.title, widget=DecimalFormatInput(render_value=True), required=False) if i != len(entities_to_add) - 1: self.fields["add" + key.lower()] = EmptyField(label='+') if size_entities_to_add > 1: self.fields["closing_brackets_entities_field"] = EmptyField( label=']') if self.is_faculty_manager \ and self.learning_unit_year.is_full() \ and self.learning_unit_year.learning_container_year.container_type \ in LEARNING_CONTAINER_YEAR_TYPES_CANT_UPDATE_BY_FACULTY: self._disable_central_manager_fields() def _disable_central_manager_fields(self): for key, field in self.fields.items(): if key not in self._faculty_manager_fields: field.disabled = True def clean(self): """ Prevent faculty users to a volume to 0 if there was a value other than 0. Also, prevent the faculty user from putting a volume if its value was 0. """ cleaned_data = super().clean() input_names = { 'volume_q1': 'volume_q1', 'volume_q2': 'volume_q2', 'volume_total': 'volume_total', 'planned_classes': 'planned_classes', 'volume_requirement_entity': 'volume_requirement_entity', 'volume_additional_requirement_entity_1': 'volume_additional_requirement_entity_1', 'volume_additional_requirement_entity_2': 'volume_additional_requirement_entity_2', } strategy = { True: CompleteVolumeEditionFacultyStrategy, False: VolumeEditionNoFacultyStrategy, } strategy[self.is_faculty_manager](self, input_names).is_valid() return cleaned_data def get_entity_fields(self): entity_keys = [ self.requirement_entity_key, self.additional_requirement_entity_1_key, self.additional_requirement_entity_2_key ] return [self.fields[key] for key in entity_keys if key in self.fields] def save(self, postponement): if not self.changed_data: return None conflict_report = {} if postponement: conflict_report = edition.get_postponement_conflict_report( self.learning_unit_year) luy_to_update_list = conflict_report['luy_without_conflict'] else: luy_to_update_list = [self.learning_unit_year] with transaction.atomic(): for component in self._find_learning_components_year( luy_to_update_list): self._save(component) # Show conflict error if exists check_postponement_conflict_report_errors(conflict_report) def _save(self, component): component.hourly_volume_total_annual = self.cleaned_data[ 'volume_total'] component.hourly_volume_partial_q1 = self.cleaned_data['volume_q1'] component.hourly_volume_partial_q2 = self.cleaned_data['volume_q2'] component.planned_classes = self.cleaned_data['planned_classes'] self._set_requirement_entities(component) return component.save() def _set_requirement_entities(self, component): updated_repartition_volumes = {} for entity_container_type in component.repartition_volumes.keys(): repartition_volume = self.cleaned_data.get( 'volume_' + entity_container_type.lower()) updated_repartition_volumes[ entity_container_type] = repartition_volume component.set_repartition_volumes(updated_repartition_volumes) def _find_learning_components_year(self, luy_to_update_list): return [ lcy for lcy in LearningComponentYear.objects.filter( learning_unit_year__in=luy_to_update_list) if lcy.type == self.component.type ]
class SimplifiedVolumeForm(forms.ModelForm): _learning_unit_year = None add_field = EmptyField(label="+") equal_field = EmptyField(label='=') def __init__(self, component_type, index, *args, is_faculty_manager=False, proposal=False, **kwargs): component_type = component_type self.is_faculty_manager = is_faculty_manager self.index = index self.proposal = proposal super().__init__(*args, **kwargs) self.label = component_type[1] self.instance.type = component_type[0] self.instance.acronym = DEFAULT_ACRONYM_COMPONENT[self.instance.type] class Meta: model = LearningComponentYear fields = ('hourly_volume_total_annual', 'hourly_volume_partial_q1', 'hourly_volume_partial_q2', 'planned_classes', 'repartition_volume_requirement_entity', 'repartition_volume_additional_entity_1', 'repartition_volume_additional_entity_2') widgets = { 'hourly_volume_total_annual': DecimalFormatInput(attrs={ 'title': _("The annual volume must be equal to the sum of the volumes Q1 and Q2" ) }, render_value=True), 'hourly_volume_partial_q1': DecimalFormatInput(attrs={ 'title': _("Volume Q1"), 'style': STYLE_MIN_WIDTH_VOLUME }, render_value=True), 'hourly_volume_partial_q2': DecimalFormatInput(attrs={ 'title': _("Volume Q2"), 'style': STYLE_MIN_WIDTH_VOLUME }, render_value=True), 'planned_classes': forms.TextInput(attrs={'title': _("Planned classes")}), 'repartition_volume_requirement_entity': DecimalFormatInput(attrs={'style': STYLE_MIN_WIDTH_VOLUME}, render_value=True), 'repartition_volume_additional_entity_1': DecimalFormatInput(attrs={'style': STYLE_MIN_WIDTH_VOLUME}, render_value=True), 'repartition_volume_additional_entity_2': DecimalFormatInput(attrs={'style': STYLE_MIN_WIDTH_VOLUME}, render_value=True), } def clean(self): """ Prevent faculty users to a volume to 0 if there was a value other than 0. Also, prevent the faculty user from putting a volume if its value was 0. """ cleaned_data = super().clean() input_names = { 'volume_q1': 'hourly_volume_partial_q1', 'volume_q2': 'hourly_volume_partial_q2', 'volume_total': 'hourly_volume_total_annual', 'planned_classes': 'planned_classes', 'volume_requirement_entity': 'repartition_volume_requirement_entity', 'volume_additional_requirement_entity_1': 'repartition_volume_additional_entity_1', 'volume_additional_requirement_entity_2': 'repartition_volume_additional_entity_2', } strategy = { True: { False: SimpleVolumeEditionFacultyStrategy, True: VolumeEditionNoFacultyStrategy }, False: { False: VolumeEditionNoFacultyStrategy, True: VolumeEditionNoFacultyStrategy }, } strategy[self.is_faculty_manager][self.proposal]( self, input_names).is_valid() return cleaned_data def save(self, commit=True): if self.need_to_create_untyped_component(): self.instance.acronym = DEFAULT_ACRONYM_COMPONENT[None] self.instance.type = None # In case of untyped component, we just need to create only 1 component (not more) if self.index != 0: return None self.instance.learning_unit_year = self._learning_unit_year self._assert_repartition_volumes_consistency() return super().save(commit) def _assert_repartition_volumes_consistency(self): """In case EntityContainer link is not set, need to reset repartition volumes to None.""" container_year = self._learning_unit_year.learning_container_year existing_entity_container_types = { link_type for link_type, entity_id in container_year.get_map_entity_by_type().items() if entity_id } for entity_container_type in LearningComponentYear.repartition_volume_attrs_by_entity_container_type( ).keys(): if entity_container_type not in existing_entity_container_types: self.instance.set_repartition_volume(entity_container_type, None) def need_to_create_untyped_component(self): container_type = self._learning_unit_year.learning_container_year.container_type return container_type not in CONTAINER_TYPE_WITH_DEFAULT_COMPONENT
class VolumeEditionForm(forms.Form): requirement_entity_key = 'volume_' + entity_types.REQUIREMENT_ENTITY.lower( ) additional_requirement_entity_1_key = 'volume_' + entity_types.ADDITIONAL_REQUIREMENT_ENTITY_1.lower( ) additional_requirement_entity_2_key = 'volume_' + entity_types.ADDITIONAL_REQUIREMENT_ENTITY_2.lower( ) volume_total = VolumeField(label=_('total_volume_voltot'), help_text=_('total_volume')) equal_field_1 = EmptyField(label='=') volume_q1 = VolumeField(label=_('partial_volume_1Q'), help_text=_('partial_volume_1')) add_field = EmptyField(label='+') volume_q2 = VolumeField(label=_('partial_volume_2Q'), help_text=_('partial_volume_2')) mult_field = EmptyField(label='*') planned_classes = forms.IntegerField(label=_('planned_classes_pc'), help_text=_('planned_classes'), min_value=0) equal_field_2 = EmptyField(label='=') _post_errors = [] _parent_data = {} _faculty_manager_fields = ['volume_q1', 'volume_q2'] def __init__(self, *args, **kwargs): self.component = kwargs.pop('component') self.learning_unit_year = kwargs.pop('learning_unit_year') self.entities = kwargs.pop('entities') self.is_faculty_manager = kwargs.pop('is_faculty_manager', False) self.title = self.component.acronym self.title_help = _( self.component.type) + ' ' if self.component.type else '' self.title_help += self.component.acronym super().__init__(*args, **kwargs) # Append dynamic fields for key in ENTITY_TYPES_VOLUME: self._add_entity_fields(key) self.fields['equal_field_3'] = EmptyField(label='=') self.fields['volume_total_requirement_entities'] = VolumeField( label=_('vol_charge'), help_text=_('total_volume_charge')) if self.is_faculty_manager and self.learning_unit_year.is_full(): self._disable_central_manager_fields() def _disable_central_manager_fields(self): for key, field in self.fields.items(): if key not in self._faculty_manager_fields: field.disabled = True def _add_entity_fields(self, key): if key in self.entities: entity = self.entities[key] self.fields["volume_" + key.lower()] = VolumeField( label=entity.acronym, help_text=entity.title) def clean(self): cleaned_data = super().clean().copy() self._check_tot_annual_equal_to_q1_q2(cleaned_data) self._check_tot_req_entities_equal_to_tot_annual_mult_cp(cleaned_data) self._check_tot_req_entities_equal_to_vol_req_entity(cleaned_data) def _check_tot_annual_equal_to_q1_q2(self, cleaned_data): total_annual = cleaned_data.get('volume_total', 0) q1 = cleaned_data.get('volume_q1', 0) q2 = cleaned_data.get('volume_q2', 0) if total_annual != (q1 + q2): self.add_error("volume_total", _('vol_tot_not_equal_to_q1_q2')) def _check_tot_req_entities_equal_to_vol_req_entity(self, cleaned_data): requirement_entity = cleaned_data.get(self.requirement_entity_key, 0) # Optional fields additional_requirement_entity_1 = cleaned_data.get( self.additional_requirement_entity_1_key, 0) additional_requirement_entity_2 = cleaned_data.get( self.additional_requirement_entity_2_key, 0) total = requirement_entity + additional_requirement_entity_1 + additional_requirement_entity_2 if cleaned_data.get('volume_total_requirement_entities') != total: error_msg = ' + '.join([ self.entities.get(t).acronym for t in ENTITY_TYPES_VOLUME if self.entities.get(t) ]) error_msg += ' = {}'.format(_('vol_charge')) self.add_error("volume_total_requirement_entities", error_msg) def _check_tot_req_entities_equal_to_tot_annual_mult_cp( self, cleaned_data): total_annual = cleaned_data.get('volume_total', 0) cp = cleaned_data.get('planned_classes', 0) total_requirement_entities = cleaned_data.get( 'volume_total_requirement_entities', 0) if total_requirement_entities != (total_annual * cp): self.add_error( 'volume_total_requirement_entities', _('vol_tot_req_entities_not_equal_to_vol_tot_mult_cp')) def validate_parent_partim_component(self, parent_data): self._parent_data = parent_data self._compare_parent_partim('volume_total', 'vol_tot_full_must_be_greater_than_partim', lower_or_equal=True) self._compare_parent_partim( 'volume_q1', 'vol_q1_full_must_be_greater_or_equal_to_partim') self._compare_parent_partim( 'volume_q2', 'vol_q2_full_must_be_greater_or_equal_to_partim') self._compare_parent_partim( 'planned_classes', 'planned_classes_full_must_be_greater_or_equal_to_partim') self._compare_parent_partim( self.requirement_entity_key, 'entity_requirement_full_must_be_greater_or_equal_to_partim') self._compare_additional_entities( self.additional_requirement_entity_1_key) self._compare_additional_entities( self.additional_requirement_entity_2_key) return self.errors def _compare_additional_entities(self, key): # Verify if we have additional_requirement entity if key in self._parent_data and key in self.cleaned_data: self._compare_parent_partim( key, 'entity_requirement_full_must_be_greater_or_equal_to_partim') def _compare_parent_partim(self, key, msg, lower_or_equal=False): partim_data = self.cleaned_data or self.initial condition = self._compare(self._parent_data[key], partim_data[key], lower_or_equal) if condition: self.add_error(key, _(msg)) @staticmethod def _compare(value_parent, value_partim, lower_or_equal): if value_parent == 0 and value_partim == 0: condition = False elif lower_or_equal: condition = value_parent <= value_partim else: condition = value_parent < value_partim return condition def save(self, postponement): if not self.changed_data: return None conflict_report = {} if postponement: conflict_report = edition.get_postponement_conflict_report( self.learning_unit_year) luy_to_update_list = conflict_report['luy_without_conflict'] else: luy_to_update_list = [self.learning_unit_year] with transaction.atomic(): for component in self._find_learning_components_year( luy_to_update_list): self._save(component) # Show conflict error if exists check_postponement_conflict_report_errors(conflict_report) def _save(self, component): component.hourly_volume_partial = self.cleaned_data['volume_q1'] component.planned_classes = self.cleaned_data['planned_classes'] component.save() self._save_requirement_entities(component.entity_components_year) def _save_requirement_entities(self, entity_components_year): for ecy in entity_components_year: link_type = ecy.entity_container_year.type repartition_volume = self.cleaned_data.get('volume_' + link_type.lower()) if repartition_volume is None: continue ecy.repartition_volume = repartition_volume ecy.save() def _find_learning_components_year(self, luy_to_update_list): prefetch = Prefetch('learning_component_year__entitycomponentyear_set', queryset=EntityComponentYear.objects.all(), to_attr='entity_components_year') return [ luc.learning_component_year for luc in LearningUnitComponent.objects.filter( learning_unit_year__in=luy_to_update_list).prefetch_related( prefetch) if luc.learning_component_year.type == self.component.type ]
class VolumeEditionForm(forms.Form): requirement_entity_key = 'volume_' + entity_types.REQUIREMENT_ENTITY.lower() additional_requirement_entity_1_key = 'volume_' + entity_types.ADDITIONAL_REQUIREMENT_ENTITY_1.lower() additional_requirement_entity_2_key = 'volume_' + entity_types.ADDITIONAL_REQUIREMENT_ENTITY_2.lower() opening_parenthesis_field = EmptyField(label='(') volume_q1 = VolumeField( label=_('Q1'), help_text=_('Volume Q1'), widget=StepHalfIntegerWidget(), required=False, ) add_field = EmptyField(label='+') volume_q2 = VolumeField( label=_('Q2'), help_text=_('Volume Q2'), widget=StepHalfIntegerWidget(), required=False, ) equal_field_1 = EmptyField(label='=') volume_total = VolumeField( label=_('Vol. annual'), help_text=_('The annual volume must be equal to the sum of the volumes Q1 and Q2'), widget=StepHalfIntegerWidget(), required=False, ) help_volume_total = "{} = {} + {}".format(_('Volume total annual'), _('Volume Q1'), _('Volume Q2')) closing_parenthesis_field = EmptyField(label=')') mult_field = EmptyField(label='*') planned_classes = forms.IntegerField(label=_('P.C.'), help_text=_('Planned classes'), min_value=0) equal_field_2 = EmptyField(label='=') _post_errors = [] _parent_data = {} _faculty_manager_fields = ['volume_q1', 'volume_q2'] def __init__(self, *args, **kwargs): self.component = kwargs.pop('component') self.learning_unit_year = kwargs.pop('learning_unit_year') self.entities = kwargs.pop('entities', []) self.is_faculty_manager = kwargs.pop('is_faculty_manager', False) self.title = self.component.acronym self.title_help = _(self.component.type) + ' ' if self.component.type else '' self.title_help += self.component.acronym super().__init__(*args, **kwargs) help_volume_global = "{} = {} * {}".format(_('volume total global'), _('Volume total annual'), _('Planned classes')) # Append dynamic fields entities_to_add = [entity for entity in REQUIREMENT_ENTITIES if entity in self.entities] for i, key in enumerate(entities_to_add): entity = self.entities[key] self.fields["volume_" + key.lower()] = VolumeField( label=entity.acronym, help_text=entity.title, widget=StepHalfIntegerWidget(), ) if i != len(entities_to_add) - 1: self.fields["add" + key.lower()] = EmptyField(label='+') if self.is_faculty_manager \ and self.learning_unit_year.is_full() \ and self.learning_unit_year.learning_container_year.container_type \ in LEARNING_CONTAINER_YEAR_TYPES_CANT_UPDATE_BY_FACULTY: self._disable_central_manager_fields() def _disable_central_manager_fields(self): for key, field in self.fields.items(): if key not in self._faculty_manager_fields: field.disabled = True def clean(self): """ Prevent faculty users to a volume to 0 if there was a value other than 0. Also, prevent the faculty user from putting a volume if its value was 0. """ cleaned_data = super().clean() volume_q1 = self.cleaned_data.get("volume_q1") or 0 volume_q2 = self.cleaned_data.get("volume_q2") or 0 volume_total = self.cleaned_data.get("volume_total") or 0 if (self.cleaned_data.get("volume_q1") is not None or self.cleaned_data.get( "volume_q2") is not None) and volume_total != volume_q1 + volume_q2: self.add_error("volume_total", _('The annual volume must be equal to the sum of the volumes Q1 and Q2')) self.add_error("volume_q1", "") self.add_error("volume_q2", "") if self.is_faculty_manager: if 0 in [self.initial.get("volume_q1"), self.initial.get("volume_q2")]: if 0 not in [self.cleaned_data.get("volume_q1"), self.cleaned_data.get("volume_q2")]: self.add_error("volume_q1", _("One of the partial volumes must have a value to 0.")) self.add_error("volume_q2", _("One of the partial volumes must have a value to 0.")) else: if volume_q1 == 0: self.add_error("volume_q1", _("The volume can not be set to 0.")) if volume_q2 == 0: self.add_error("volume_q2", _("The volume can not be set to 0.")) return cleaned_data def get_entity_fields(self): entity_keys = [self.requirement_entity_key, self.additional_requirement_entity_1_key, self.additional_requirement_entity_2_key] return [self.fields[key] for key in entity_keys if key in self.fields] def save(self, postponement): if not self.changed_data: return None conflict_report = {} if postponement: conflict_report = edition.get_postponement_conflict_report(self.learning_unit_year) luy_to_update_list = conflict_report['luy_without_conflict'] else: luy_to_update_list = [self.learning_unit_year] with transaction.atomic(): for component in self._find_learning_components_year(luy_to_update_list): self._save(component) # Show conflict error if exists check_postponement_conflict_report_errors(conflict_report) def _save(self, component): component.hourly_volume_total_annual = self.cleaned_data['volume_total'] component.hourly_volume_partial_q1 = self.cleaned_data['volume_q1'] component.hourly_volume_partial_q2 = self.cleaned_data['volume_q2'] component.planned_classes = self.cleaned_data['planned_classes'] component.save() self._save_requirement_entities(component.entity_components_year) def _save_requirement_entities(self, entity_components_year): for ecy in entity_components_year: link_type = ecy.entity_container_year.type repartition_volume = self.cleaned_data.get('volume_' + link_type.lower()) if repartition_volume is None: continue ecy.repartition_volume = repartition_volume ecy.save() def _find_learning_components_year(self, luy_to_update_list): prefetch = Prefetch( 'learning_component_year__entitycomponentyear_set', queryset=EntityComponentYear.objects.all(), to_attr='entity_components_year' ) return [ luc.learning_component_year for luc in LearningUnitComponent.objects.filter( learning_unit_year__in=luy_to_update_list).prefetch_related(prefetch) if luc.learning_component_year.type == self.component.type ]
class SimplifiedVolumeForm(forms.ModelForm): _learning_unit_year = None _entity_containers = [] add_field = EmptyField(label="+") equal_field = EmptyField(label='=') def __init__(self, component_type, index, *args, is_faculty_manager=False, **kwargs): component_type = component_type self.is_faculty_manager = is_faculty_manager self.index = index super().__init__(*args, **kwargs) self.label = component_type[1] self.instance.type = component_type[0] self.instance.acronym = DEFAULT_ACRONYM_COMPONENT[self.instance.type] class Meta: model = LearningComponentYear fields = ( 'hourly_volume_total_annual', 'hourly_volume_partial_q1', 'hourly_volume_partial_q2' ) widgets = { 'hourly_volume_total_annual': StepHalfIntegerWidget, 'hourly_volume_partial_q1': StepHalfIntegerWidget, 'hourly_volume_partial_q2': StepHalfIntegerWidget, } def clean(self): """ Prevent faculty users to a volume to 0 if there was a value other than 0. Also, prevent the faculty user from putting a volume if its value was 0. # FIXME Refactor this method with the clean of VolumeEditionForm """ cleaned_data = super().clean() if self.is_faculty_manager: if 0 in [self.instance.hourly_volume_partial_q1, self.instance.hourly_volume_partial_q2]: if 0 not in [self.cleaned_data.get("hourly_volume_partial_q1"), self.cleaned_data.get("hourly_volume_partial_q2")]: self.add_error("hourly_volume_partial_q1", _("One of the partial volumes must have a value to 0.")) self.add_error("hourly_volume_partial_q2", _("One of the partial volumes must have a value to 0.")) else: if self.cleaned_data.get("hourly_volume_partial_q1") == 0: self.add_error("hourly_volume_partial_q1", _("The volume can not be set to 0.")) if self.cleaned_data.get("hourly_volume_partial_q2") == 0: self.add_error("hourly_volume_partial_q2", _("The volume can not be set to 0.")) volume_q1 = self.cleaned_data.get("hourly_volume_partial_q1") or 0 volume_q2 = self.cleaned_data.get("hourly_volume_partial_q2") or 0 volume_total = self.cleaned_data.get("hourly_volume_total_annual") or 0 if (self.cleaned_data.get("hourly_volume_partial_q1") is not None or self.cleaned_data.get( "hourly_volume_partial_q2") is not None) and volume_total != volume_q1 + volume_q2: self.add_error("hourly_volume_total_annual", _('The annual volume must be equal to the sum of the volumes Q1 and Q2')) self.add_error("hourly_volume_partial_q1", "") self.add_error("hourly_volume_partial_q2", "") return cleaned_data def save(self, commit=True): if self.need_to_create_untyped_component(): self.instance.acronym = DEFAULT_ACRONYM_COMPONENT[None] self.instance.type = None # In case of untyped component, we just need to create only 1 component (not more) if self.index != 0: return None return self._create_structure_components(commit) def need_to_create_untyped_component(self): container_type = self._learning_unit_year.learning_container_year.container_type return container_type not in CONTAINER_TYPE_WITH_DEFAULT_COMPONENT def _create_structure_components(self, commit): self.instance.learning_container_year = self._learning_unit_year.learning_container_year if self.instance.hourly_volume_total_annual is None or self.instance.hourly_volume_total_annual == 0: self.instance.planned_classes = 0 else: self.instance.planned_classes = 1 instance = super().save(commit) LearningUnitComponent.objects.update_or_create( learning_unit_year=self._learning_unit_year, learning_component_year=instance ) requirement_entity_containers = self._get_requirement_entity_container() for requirement_entity_container in requirement_entity_containers: learning_unit_components = LearningUnitComponent.objects.filter( learning_unit_year__learning_container_year=self._learning_unit_year.learning_container_year ) self._create_entity_component_years(learning_unit_components, requirement_entity_container) return instance @staticmethod def _create_entity_component_years(learning_unit_components, requirement_entity_container): for learning_unit_component in learning_unit_components: EntityComponentYear.objects.update_or_create( entity_container_year=requirement_entity_container, learning_component_year=learning_unit_component.learning_component_year ) def _get_requirement_entity_container(self): requirement_entity_containers = [] for entity_container_year in self._entity_containers: if entity_container_year and entity_container_year.type != entity_types.ALLOCATION_ENTITY: requirement_entity_containers.append(entity_container_year) return requirement_entity_containers
class VolumeEditionForm(forms.Form): requirement_entity_key = 'volume_' + entity_types.REQUIREMENT_ENTITY.lower( ) additional_requirement_entity_1_key = 'volume_' + entity_types.ADDITIONAL_REQUIREMENT_ENTITY_1.lower( ) additional_requirement_entity_2_key = 'volume_' + entity_types.ADDITIONAL_REQUIREMENT_ENTITY_2.lower( ) opening_parenthesis_field = EmptyField(label='(') volume_q1 = VolumeField( label=_('partial_volume_1Q'), help_text=_('partial_volume_1'), widget=forms.NumberInput(attrs={'step': STEP_HALF_INTEGER}), ) add_field = EmptyField(label='+') volume_q2 = VolumeField( label=_('partial_volume_2Q'), help_text=_('partial_volume_2'), widget=forms.NumberInput(attrs={'step': STEP_HALF_INTEGER}), ) equal_field_1 = EmptyField(label='=') volume_total = VolumeField( label=_('Vol. annual'), help_text= _('The annual volume must be equal to the sum of the volumes Q1 and Q2' ), widget=forms.NumberInput(attrs={'step': STEP_HALF_INTEGER}), ) help_volume_total = "{} = {} + {}".format(_('Volume total annual'), _('partial_volume_1'), _('partial_volume_2')) closing_parenthesis_field = EmptyField(label=')') mult_field = EmptyField(label='*') planned_classes = forms.IntegerField(label=_('planned_classes_pc'), help_text=_('planned_classes'), min_value=0) equal_field_2 = EmptyField(label='=') _post_errors = [] _parent_data = {} _faculty_manager_fields = ['volume_q1', 'volume_q2'] def __init__(self, *args, **kwargs): self.component = kwargs.pop('component') self.learning_unit_year = kwargs.pop('learning_unit_year') self.entities = kwargs.pop('entities') self.is_faculty_manager = kwargs.pop('is_faculty_manager', False) self.title = self.component.acronym self.title_help = _( self.component.type) + ' ' if self.component.type else '' self.title_help += self.component.acronym super().__init__(*args, **kwargs) help_volume_global = "{} = {} * {}".format(_('volume_global'), _('Volume total annual'), _('planned_classes')) # Append dynamic fields entities_to_add = [ entity for entity in ENTITY_TYPES_VOLUME if entity in self.entities ] for i, key in enumerate(entities_to_add): entity = self.entities[key] self.fields["volume_" + key.lower()] = VolumeField( label=entity.acronym, help_text=entity.title, widget=forms.NumberInput(attrs={'step': STEP_HALF_INTEGER}), ) if i != len(entities_to_add) - 1: self.fields["add" + key.lower()] = EmptyField(label='+') if self.is_faculty_manager \ and self.learning_unit_year.is_full() \ and self.learning_unit_year.learning_container_year.container_type \ in LEARNING_CONTAINER_YEAR_TYPES_CANT_UPDATE_BY_FACULTY: self._disable_central_manager_fields() def _disable_central_manager_fields(self): for key, field in self.fields.items(): if key not in self._faculty_manager_fields: field.disabled = True def get_entity_fields(self): entity_keys = [ self.requirement_entity_key, self.additional_requirement_entity_1_key, self.additional_requirement_entity_2_key ] return [self.fields[key] for key in entity_keys if key in self.fields] def save(self, postponement): if not self.changed_data: return None conflict_report = {} if postponement: conflict_report = edition.get_postponement_conflict_report( self.learning_unit_year) luy_to_update_list = conflict_report['luy_without_conflict'] else: luy_to_update_list = [self.learning_unit_year] with transaction.atomic(): for component in self._find_learning_components_year( luy_to_update_list): self._save(component) # Show conflict error if exists check_postponement_conflict_report_errors(conflict_report) def _save(self, component): component.hourly_volume_total_annual = self.cleaned_data[ 'volume_total'] component.hourly_volume_partial_q1 = self.cleaned_data['volume_q1'] component.hourly_volume_partial_q2 = self.cleaned_data['volume_q2'] component.planned_classes = self.cleaned_data['planned_classes'] component.save() self._save_requirement_entities(component.entity_components_year) def _save_requirement_entities(self, entity_components_year): for ecy in entity_components_year: link_type = ecy.entity_container_year.type repartition_volume = self.cleaned_data.get('volume_' + link_type.lower()) if repartition_volume is None: continue ecy.repartition_volume = repartition_volume ecy.save() def _find_learning_components_year(self, luy_to_update_list): prefetch = Prefetch('learning_component_year__entitycomponentyear_set', queryset=EntityComponentYear.objects.all(), to_attr='entity_components_year') return [ luc.learning_component_year for luc in LearningUnitComponent.objects.filter( learning_unit_year__in=luy_to_update_list).prefetch_related( prefetch) if luc.learning_component_year.type == self.component.type ]
class SimplifiedVolumeForm(forms.ModelForm): _learning_unit_year = None _entity_containers = [] add_field = EmptyField(label="+") equal_field = EmptyField(label='=') def __init__(self, *args, **kwargs): self.component_type = kwargs.pop('component_type') super().__init__(*args, **kwargs) self.instance.type = self.component_type self.instance.acronym = DEFAULT_ACRONYM_COMPONENT[self.component_type] class Meta: model = LearningComponentYear fields = ('planned_classes', 'hourly_volume_total_annual', 'hourly_volume_partial_q1', 'hourly_volume_partial_q2') widgets = { 'hourly_volume_total_annual': forms.NumberInput(attrs={'step': STEP_HALF_INTEGER}), 'hourly_volume_partial_q1': forms.NumberInput(attrs={'step': STEP_HALF_INTEGER}), 'hourly_volume_partial_q2': forms.NumberInput(attrs={'step': STEP_HALF_INTEGER}), 'volume_declared_vacant': forms.NumberInput(attrs={'step': STEP_HALF_INTEGER}), } def save(self, commit=True): if self.need_to_create_untyped_component(): self.instance.acronym = DEFAULT_ACRONYM_COMPONENT[None] self.instance.type = None # In case of untyped component, we just need to create only 1 component (not more) if not self.is_first_form_in_formset(): return None return self._create_structure_components(commit) def need_to_create_untyped_component(self): container_type = self._learning_unit_year.learning_container_year.container_type return container_type not in CONTAINER_TYPE_WITH_DEFAULT_COMPONENT def is_first_form_in_formset(self): return self.prefix == "form-0" def _create_structure_components(self, commit): self.instance.learning_container_year = self._learning_unit_year.learning_container_year if self.instance.hourly_volume_total_annual is None or self.instance.hourly_volume_total_annual == 0: self.instance.planned_classes = 0 else: self.instance.planned_classes = 1 instance = super().save(commit) LearningUnitComponent.objects.get_or_create( learning_unit_year=self._learning_unit_year, learning_component_year=instance) requirement_entity_containers = self._get_requirement_entity_container( ) for requirement_entity_container in requirement_entity_containers: if not self.instance.hourly_volume_total_annual and self.initial: self._get_initial_volume_data() learning_unit_components = LearningUnitComponent.objects.filter( learning_unit_year__learning_container_year=self. _learning_unit_year.learning_container_year) self._create_entity_component_years(learning_unit_components, requirement_entity_container) return instance def _create_entity_component_years(self, learning_unit_components, requirement_entity_container): for learning_unit_component in learning_unit_components: EntityComponentYear.objects.get_or_create( entity_container_year=requirement_entity_container, learning_component_year=learning_unit_component. learning_component_year) def _get_initial_volume_data(self): self.instance.hourly_volume_total_annual = self.initial.get( 'hourly_volume_total_annual') self.instance.hourly_volume_partial_q1 = self.initial.get( 'hourly_volume_partial_q1') self.instance.hourly_volume_partial_q2 = self.initial.get( 'hourly_volume_partial_q2') self.instance.save() def _get_requirement_entity_container(self): requirement_entity_containers = [] for entity_container_year in self._entity_containers: if entity_container_year and entity_container_year.type != entity_types.ALLOCATION_ENTITY: requirement_entity_containers.append(entity_container_year) return requirement_entity_containers