class LenderForm(BaseDonorForm): button_label = "Je prête {amount}" payment_modes = [] country_of_birth = LazyTypedChoiceField( required=True, label="Pays de naissance", choices=[("", "Sélectionnez votre pays de naissance")] + list(countries), ) city_of_birth = forms.CharField(label="Ville de naissance", required=True) departement_of_birth = forms.ChoiceField( label="Département de naissance (France uniquement)", choices=(("", "Indiquez votre département de naissance"), ) + departements_choices, required=False, ) amount = forms.IntegerField( max_value=settings.LOAN_MAXIMUM, min_value=settings.LOAN_MINIMUM, required=True, widget=forms.HiddenInput, ) payment_mode = PaymentModeField( label="Comment souhaitez-vous prêter l'argent ?", payment_modes=[]) iban = IBANField( label="Votre IBAN", required=True, allowed_countries=["FR"], help_text= "Le numéro IBAN du compte sur lequel le remboursement du prêt sera effectué.", ) def __init__(self, *args, payment_modes=None, **kwargs): super().__init__(*args, **kwargs) if payment_modes is not None: self.payment_modes = payment_modes self.fields["payment_mode"].payment_modes = self.payment_modes self.fields["gender"].required = True self.fields["date_of_birth"].required = True self.fields["declaration"].label = _( "Je certifie sur l'honneur être une personne physique et que le réglement de mon prêt ne provient pas d'une" " personne morale mais de mon compte en banque personnel.") # retirer le help_text qui indique qu'un reçu fiscal sera émis (ce qui n'est pas le cas pour un prêt) self.fields["declaration"].help_text = None del self.fields["fiscal_resident"] fields = ["amount"] if "email" in self.fields: fields.append("email") fields.extend([ "first_name", "last_name", "gender", "nationality", layout.Field("location_address1", placeholder="Ligne 1"), layout.Field("location_address2", placeholder="Ligne 2"), layout.Row( layout.Div("location_zip", css_class="col-md-4"), layout.Div("location_city", css_class="col-md-8"), ), "location_country", "contact_phone", layout.Field("date_of_birth", placeholder="JJ/MM/AAAA"), "country_of_birth", "city_of_birth", "departement_of_birth", "iban", "payment_mode", "declaration", ]) if "subscribed_lfi" in self.fields: fields.append("subscribed_lfi") if len(self.fields["payment_mode"].payment_modes) <= 1: del self.fields["payment_mode"] fields.remove("payment_mode") self.helper.layout = layout.Layout(*fields) def clean(self): cleaned_data = super().clean() if cleaned_data.get("country_of_birth", "") == "FR" and not cleaned_data.get( "departement_of_birth", ""): self.add_error( "departement_of_birth", forms.ValidationError( "Merci d'indiquer votre département de naissance si vous êtes né⋅e en France", code="departement", ), ) if not "payment_mode" in self.fields: cleaned_data["payment_mode"] = PAYMENT_MODES[self.payment_modes[0]] return cleaned_data class Meta: model = Person fields = ( "first_name", "last_name", "gender", "location_address1", "location_address2", "location_zip", "location_city", "location_country", "contact_phone", "date_of_birth", )
class BillingForm(forms.ModelForm): # these fields are used to make sure there's no problem if user starts paying several events at the same time event = forms.ModelChoiceField(Event.objects.all(), required=True, widget=forms.HiddenInput) submission = forms.ModelChoiceField(PersonFormSubmission.objects.all(), widget=forms.HiddenInput, required=False) payment_mode = PaymentModeField( required=True, payment_modes=["system_pay", "check_events"]) is_guest = forms.BooleanField(required=False, widget=forms.HiddenInput) def __init__(self, *args, event, submission, is_guest, **kwargs): super().__init__(*args, **kwargs) self.fields["submission"].initial = submission self.fields["event"].initial = event self.fields["is_guest"].initial = is_guest if event.payment_parameters.get("payment_modes"): self.fields[ "payment_mode"].payment_modes = event.payment_parameters[ "payment_modes"] # si l'événement est dans moins d'une semaine, on refuse le paiement par chèque if event.start_time - timezone.now() < timezone.timedelta(days=7): self.fields["payment_mode"].payment_modes = [ p for p in self.fields["payment_mode"].payment_modes if p.category != "check" ] for f in [ "first_name", "last_name", "location_address1", "location_zip", "location_city", "location_country", "contact_phone", ]: self.fields[f].required = True self.fields["location_address1"].label = "Adresse" self.fields["location_address2"].label = False fields = ["submission", "event", "is_guest"] fields.extend(["first_name", "last_name"]) fields.extend([ layout.Field("location_address1", placeholder="Ligne 1"), layout.Field("location_address2", placeholder="Ligne 2"), ]) fields.append( Row( layout.Div("location_zip", css_class="col-md-4"), layout.Div("location_city", css_class="col-md-8"), )) fields.append("location_country") fields.append("contact_phone") fields.append("payment_mode") self.helper = FormHelper() self.helper.add_input( layout.Submit( "valider", f"Je paie {floatformat(event.get_price(submission and submission.data)/100, 2)} €", )) self.helper.layout = layout.Layout(*fields) class Meta: model = Person fields = BILLING_FIELDS
class BillingForm(forms.ModelForm): # these fields are used to make sure there's no problem if user starts paying several events at the same time event = forms.ModelChoiceField(Event.objects.all(), required=True, widget=forms.HiddenInput) submission = forms.ModelChoiceField(PersonFormSubmission.objects.all(), widget=forms.HiddenInput, required=False) payment_mode = PaymentModeField( required=True, payment_modes=[PAYMENT_MODES["system_pay"], PAYMENT_MODES["check"]], ) is_guest = forms.BooleanField(required=False, widget=forms.HiddenInput) def __init__(self, *args, event, submission, is_guest, **kwargs): super().__init__(*args, **kwargs) self.fields["submission"].initial = submission self.fields["event"].initial = event self.fields["is_guest"].initial = is_guest for f in [ "first_name", "last_name", "location_address1", "location_zip", "location_city", "location_country", "contact_phone", ]: self.fields[f].required = True self.fields["location_address1"].label = "Adresse" self.fields["location_address2"].label = False fields = ["submission", "event", "is_guest"] fields.extend(["first_name", "last_name"]) fields.extend([ layout.Field("location_address1", placeholder="Ligne 1"), layout.Field("location_address2", placeholder="Ligne 2"), ]) fields.append( Row( layout.Div("location_zip", css_class="col-md-4"), layout.Div("location_city", css_class="col-md-8"), )) fields.append("location_country") fields.append("contact_phone") fields.append("payment_mode") self.helper = FormHelper() self.helper.add_input( layout.Submit( "valider", f"Je paie {floatformat(event.get_price(submission and submission.data)/100, 2)} €", )) self.helper.layout = layout.Layout(*fields) class Meta: model = Person fields = ( "first_name", "last_name", "location_address1", "location_address2", "location_zip", "location_city", "location_country", "contact_phone", )
class NewParticipantForm(BasePersonForm): existing_person = forms.ModelChoiceField( label="Compte existant", queryset=Person.objects.all(), empty_label=_("None"), required=False, ) new_person_email = forms.EmailField(label="Email de la nouvelle personne", required=False) insoumise = forms.BooleanField( required=False, label="La personne souhaite recevoir les emails de la France insoumise", help_text= "Ce champ ne s'applique que s'il s'agit de la création d'une nouvelle personne.", ) payment_mode = PaymentModeField( required=True, payment_modes=["system_pay", "check_events", "money", "tpe"]) def __init__(self, *args, model_admin, event, **kwargs): super().__init__(*args, **kwargs) self.event = event self.fields["existing_person"].widget = AutocompleteSelect( rel=Person._meta.get_field("rsvps"), admin_site=model_admin.admin_site, choices=self.fields["existing_person"].choices, ) if "location_address2" in self.fields: self.fields["location_address2"].required = False self.fieldsets = [ ( "Compte", { "fields": ("existing_person", "new_person_email", "insoumise") }, ), ( "Informations d'inscription", { "fields": list(self.person_form_instance.fields_dict) }, ), ] def clean_existing_person(self): existing_person = self.cleaned_data["existing_person"] if (existing_person is not None and RSVP.objects.filter(event=self.event, person=existing_person).exists()): rsvp = (RSVP.objects.filter( event=self.event, person=existing_person).select_related("payment").get()) try: payment = rsvp.payment if payment is None: raise Payment.DoesNotExist() message = format_html( '{error_text} (<a href="{payment_link_url}">{payment_link_text}</a>)', error_text="Cette personne participe déjà à l'événement", payment_link_url=reverse("admin:payments_payment_change", args=[payment.pk]), payment_link_text="voir son paiement", ) except Payment.DoesNotExist: message = "Cette personne participe déjà à l'événement." raise ValidationError(message, code="already_rsvp") return existing_person def clean(self): if ("existing_person" in self.cleaned_data and self.cleaned_data["existing_person"] is not None): self.data = self.data.dict() for f in self._meta.fields: if f not in self.cleaned_data: self.data[f] = getattr( self.cleaned_data["existing_person"], f) return self.cleaned_data def save(self, commit=True): cleaned_data = self.cleaned_data # si l'existing person existe, c'est elle qui doit être modifiée par le formulaire if cleaned_data["existing_person"] is not None: self.instance = cleaned_data["existing_person"] elif cleaned_data["new_person_email"]: try: self.instance = Person.objects.get_by_natural_key( cleaned_data["new_person_email"]) except Person.DoesNotExist: pass if self.instance._state.adding: self.instance.is_insoumise = self.instance.subscribed = self.cleaned_data[ "insoumise"] # pour sauver l'instance, il faut appeler la méthode ModelForm plutôt que celle # de BasePersonForm parce que cette dernière ne crée jamais d'instance. with transaction.atomic(): self.instance = forms.ModelForm.save(self, commit) self.submission = self.save_submission(self.instance) if cleaned_data["new_person_email"]: self.instance.add_email(cleaned_data["new_person_email"]) return self.instance def free_rsvp(self): rsvp_to_free_event(self.event, self.instance, self.submission) def redirect_to_payment(self): payment = rsvp_to_paid_event_and_create_payment( self.event, self.instance, self.cleaned_data["payment_mode"], self.submission, ) if self.cleaned_data["payment_mode"].can_admin: return HttpResponseRedirect( reverse("admin:payments_payment_change", args=(payment.id, ))) return HttpResponseRedirect(payment.get_payment_url()) class Meta: model = Person fields = BILLING_FIELDS
class LenderForm(SimpleDonorForm): button_label = "Je prête {amount}" country_of_birth = LazyTypedChoiceField( required=True, label="Pays de naissance", choices=[("", "Sélectionnez votre pays de naissance")] + list(countries), ) city_of_birth = forms.CharField(label="Ville de naissance", required=True) departement_of_birth = forms.ChoiceField( label="Département de naissance (France uniquement)", choices=(("", "Indiquez votre département de naissance"), ) + departements_choices, required=False, ) amount = forms.IntegerField( max_value=settings.LOAN_MAXIMUM * 100, min_value=settings.LOAN_MINIMUM * 100, required=True, widget=forms.HiddenInput, ) payment_mode = PaymentModeField( payment_modes=[ PAYMENT_MODES["system_pay_afce_pret"], PAYMENT_MODES["check_afce"], ], label="Comment souhaitez-vous prêter l'argent ?", ) iban = IBANField( label="Votre IBAN", required=True, allowed_countries=["FR"], help_text= "Le numéro IBAN du compte sur lequel le remboursement du prêt sera effectué.", ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["gender"].required = True self.fields["date_of_birth"].required = True self.fields["declaration"].label = _( "Je certifie sur l'honneur être une personne physique et que le réglement de mon prêt ne provient pas d'une" " personne morale mais de mon compte en banque personnel.") # retirer le help_text qui indique qu'un reçu fiscal sera émis (ce qui n'est pas le cas pour un prêt) self.fields["declaration"].help_text = None del self.fields["fiscal_resident"] if (Payment.objects.filter( Q(type=EuropeennesConfig.LOAN_PAYMENT_TYPE) & (Q(status=Payment.STATUS_COMPLETED) | Q(status=Payment.STATUS_WAITING, mode="check_afce")) ).aggregate(amount=Coalesce(Sum("price"), 0))["amount"] > settings.LOAN_MAXIMUM_TOTAL): self.fields["payment_mode"].payment_modes = [ PAYMENT_MODES["system_pay_afce_pret"] ] self.fields["payment_mode"].initial = PAYMENT_MODES[ "system_pay_afce_pret"].id self.fields["payment_mode"].widget = HiddenInput() fields = ["amount"] if "email" in self.fields: fields.append("email") fields.extend([ "first_name", "last_name", "gender", "nationality", layout.Field("location_address1", placeholder="Ligne 1"), layout.Field("location_address2", placeholder="Ligne 2"), layout.Row( layout.Div("location_zip", css_class="col-md-4"), layout.Div("location_city", css_class="col-md-8"), ), "location_country", "contact_phone", layout.Field("date_of_birth", placeholder="JJ/MM/AAAA"), "country_of_birth", "city_of_birth", "departement_of_birth", "iban", "payment_mode", "declaration", ]) if "subscribed" in self.fields: fields.append("subscribed") self.helper.layout = layout.Layout(*fields) def clean(self): cleaned_data = super().clean() if cleaned_data.get("country_of_birth", "") == "FR" and not cleaned_data.get( "departement_of_birth", ""): self.add_error( "departement_of_birth", forms.ValidationError( "Merci d'indiquer votre département de naissance si vous êtes né⋅e en France", code="departement", ), ) return cleaned_data class Meta: model = Person fields = ( "first_name", "last_name", "gender", "location_address1", "location_address2", "location_zip", "location_city", "location_country", "contact_phone", "subscribed", "date_of_birth", )