def admin_summary(spending_request): shown_fields = [ "id", "title", "status", "group", "event", "category", "category_precisions", "explanation", "amount", "spending_date", "provider", "iban", ] values = {f: getattr(spending_request, f) for f in shown_fields} values["group"] = format_html( '<a href="{group_link}">{group_name}</a> ({group_balance})<br><a href="mailto:{group_email}">{group_email}</a><br>{group_phone}', group_name=spending_request.group.name, group_email=spending_request.group.contact_email, group_phone=spending_request.group.contact_phone, group_link=front_url("view_group", args=(spending_request.group_id, )), group_balance=display_price(get_balance(spending_request.group)), ) values["amount"] = display_price(spending_request.amount) return [{ "label": SpendingRequest._meta.get_field(f).verbose_name, "value": values[f] } for f in shown_fields]
class AllocationSubscriptionForm(AllocationMixin, SimpleDonationForm): amount = AskAmountField( label="Montant du don mensuel", max_value=settings.MONTHLY_DONATION_MAXIMUM, min_value=settings.MONTHLY_DONATION_MINIMUM, required=True, error_messages={ "invalid": _("Indiquez le montant de votre don mensuel."), "min_value": format_lazy( _("Les dons mensuels de moins de {min} ne sont pas acceptés."), min=display_price(settings.MONTHLY_DONATION_MINIMUM), ), "max_value": format_lazy( _("Les dons mensuels de plus de {max} ne sont pas acceptés."), max=display_price(settings.MONTHLY_DONATION_MAXIMUM), ), }, by_month=True, show_tax_credit=True, ) previous_subscription = forms.ModelChoiceField( queryset=Subscription.objects.filter(status=Subscription.STATUS_ACTIVE), required=False, widget=forms.HiddenInput, ) def __init__(self, *args, user, **kwargs): super().__init__(*args, user=user, **kwargs) self.fields["amount"].amount_choices = [ 100 * 100, 50 * 100, 20 * 100, 10 * 100, 5 * 100, ] if user: self.fields["previous_subscription"].queryset = self.fields[ "previous_subscription" ].queryset.filter(person=user.person) self.helper.layout.fields.append("previous_subscription") def get_button_label(self): if self.get_initial_for_field( self.fields["previous_subscription"], "previous_subscription" ): return "Modifier ce don mensuel" return "Mettre en place le don mensuel"
def group_formatter(group): return format_html( '<a href="{group_link}">{group_name}</a> ({group_balance})<br><a href="mailto:{group_email}">{group_email}</a><br>{group_phone}', group_name=group.name, group_email=group.contact_email, group_phone=group.contact_phone, group_link=front_url("view_group", args=(group.id, )), group_balance=display_price(get_balance(group)), )
def allocation(self, object, show_add_button=False): value = display_price(object.allocation) if object.allocation else "-" if show_add_button: value = format_html( '{value} (<a href="{link}">Changer</a>)', value=value, link=reverse("admin:donations_operation_add") + "?group=" + str(object.pk), ) return value
def handle(self, event, category_field, **kwargs): writer = csv.writer(sys.stdout) writer.writerow([ "numero", "canceled", "full_name", "uuid", "contact_email", "gender", "category", "price", "status", ]) for i, rsvp in enumerate(event.rsvps.order_by("created")): writer.writerow([ "R" + str(rsvp.pk), "O" if rsvp.status == RSVP.STATUS_CANCELED else "", f"{rsvp.form_submission.data.get('first_name')} {rsvp.form_submission.data.get('last_name')}", str(rsvp.person.id), rsvp.person.email, rsvp.person.gender or "", rsvp.form_submission.data[category_field], display_price(event.get_price(rsvp.form_submission.data)), "completed" if rsvp.status == RSVP.STATUS_CONFIRMED else "on-hold", ]) for j, guest in enumerate(rsvp.identified_guests.order_by("id")): writer.writerow([ "G" + str(rsvp.pk) + "g" + str(guest.pk), "O" if guest.status == RSVP.STATUS_CANCELED else "", f"{guest.submission.data['first_name']} {guest.submission.data['last_name']}", str(rsvp.person.id), rsvp.person.email, guest.submission.data.get("gender", ""), guest.submission.data[category_field], display_price(event.get_price(guest.submission.data)), "completed" if guest.status == RSVP.STATUS_CONFIRMED else "on-hold", ])
def generate_html_contract(contract_information, baselevel=1): gender = contract_information["gender"] signed = "signature_datetime" in contract_information signature_image_path = ( Path(__file__) .parent.joinpath("static", "europeennes", "signature_manon_aubry.png") .absolute() .as_uri() ) contract_markdown = get_template("europeennes/loans/contract.md").render( context={ "lender_date_of_birth": "22/12/1989", "lender_place_of_birth": "Fréjus (Var)", "name": f'{contract_information["first_name"]} {contract_information["last_name"]}', "address": "personal address", "date_of_birth": contract_information["date_of_birth"], "place_of_birth": display_place_of_birth(contract_information), "full_address": display_full_address(contract_information), "amount_letters": num2words(contract_information["amount"] / 100, lang="fr") + " euros", "amount_figure": display_price(contract_information["amount"]), "signature_date": contract_information.get( "signature_datetime", "XX/XX/XXXX" ), "e": SUBSTITUTIONS["final_e"][gender], "preteur": SUBSTITUTIONS["lender"][gender], "le": SUBSTITUTIONS["article"][gender], "Le": SUBSTITUTIONS["article"][gender].capitalize(), "du": SUBSTITUTIONS["determinant"][gender], "il": SUBSTITUTIONS["pronoun"][gender], "mode_paiement": SUBSTITUTIONS["payment"][ contract_information["payment_mode"] ], "signature": f"Accepté en ligne le {contract_information['acceptance_datetime']}" if signed else "", "signature_emprunteuse": mark_safe( f'<img title="Signature de Manon Aubry" src="{signature_image_path}">' ) if signed else "", } ) return mark_safe( markdown( contract_markdown, extensions=["extra", TocExtension(baselevel=baselevel)] ) )
class LoanForm(SimpleDonationForm): button_label = "Je prête !" amount = AskAmountField( label="Montant du prêt", max_value=settings.LOAN_MAXIMUM, min_value=settings.LOAN_MINIMUM, required=True, error_messages={ "invalid": _("Indiquez le montant à prêter."), "min_value": format_lazy( _("Les prêts de moins de {min} ne sont pas acceptés."), min=display_price(settings.LOAN_MINIMUM), ), "max_value": format_lazy( _("Les prêts de plus de {max} ne peuvent être faits par carte bleue." ), max=display_price(settings.LOAN_MAXIMUM), ), }, amount_choices=[ 10000 * 100, 5000 * 100, 2000 * 100, 1000 * 100, 400 * 100 ], show_tax_credit=False, ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_class = "donation-form" self.helper.add_input(layout.Submit("valider", self.button_label)) self.helper.layout = Layout()
class SimpleDonationForm(forms.Form): button_label = "Je donne !" amount = AskAmountField( label="Montant du don", max_value=settings.DONATION_MAXIMUM, min_value=settings.DONATION_MINIMUM, required=True, error_messages={ "invalid": _("Indiquez le montant à donner."), "min_value": format_lazy( _("Il n'est pas possible de donner moins que {min}."), min=display_price(settings.DONATION_MINIMUM), ), "max_value": format_lazy( _("Les dons de plus de {max} ne peuvent être faits par carte bleue." ), max=display_price(settings.DONATION_MAXIMUM), ), }, ) def get_button_label(self): return self.button_label def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_class = "donation-form" self.helper.add_input(layout.Submit("valider", self.get_button_label())) self.helper.layout = Layout("amount")
def form_valid(self, form): with reversion.create_revision(): montant = display_price(form.cleaned_data["montant"], price_in_cents=False) message = f"Ajout d'un réglement d'une valeur de {montant}" reversion.set_user(self.request.user) reversion.set_comment(message) LogEntry.objects.log_action( user_id=self.request.user.pk, content_type_id=get_content_type_for_model(self.depense).pk, object_id=self.depense.pk, object_repr=str(self.depense), action_flag=CHANGE, change_message=message, ) return super().form_valid(form)
def default_contract_context_generator( contract_information: Mapping[str, object]) -> Dict[str, str]: gender = contract_information["gender"] signed = "signature_datetime" in contract_information payment_mode = PAYMENT_MODES[contract_information["payment_mode"]] # noinspection PyTypeChecker return { "nom_preteur": f'{contract_information["first_name"]} {contract_information["last_name"]}', "date_naissance": contract_information["date_of_birth"], "lieu_naissance": display_place_of_birth(contract_information), "adresse_preteur": display_full_address(contract_information), "amount_letters": num2words(contract_information["amount"] / 100, lang="fr") + " euros", "amount_figure": display_price(contract_information["amount"]), "signature_date": contract_information.get("signature_datetime", "XX/XX/XXXX"), "e": SUBSTITUTIONS["final_e"][gender], "preteur": SUBSTITUTIONS["preteur"][gender], "le": SUBSTITUTIONS["article"][gender], "Le": SUBSTITUTIONS["article"][gender].capitalize(), "du": SUBSTITUTIONS["determinant"][gender], "il": SUBSTITUTIONS["pronom"][gender], "mode_paiement": SUBSTITUTIONS["payment"][payment_mode.category], "signature": f"Accepté en ligne le {contract_information['acceptance_datetime']}" if signed else "", "signe": signed, }
def get_price_display(self): return display_price(self.price)
def montant(self, obj): total = getattr(obj, "montant") return display_price(total, price_in_cents=False) if total else "-"
def montant_(self, obj): if obj: return display_price(obj.montant, price_in_cents=False) return "-"
def show_amount(self, obj): return display_price(obj.amount)
def handle(self, event, category_field, **kwargs): writer = csv.writer(sys.stdout) writer.writerow([ "numero", "canceled", "full_name", "uuid", "contact_email", "gender", "category", "price", "status", "entry", ]) rsvps = event.rsvps.filter( form_submission__isnull=False).select_related( "person", "form_submission") guests = IdentifiedGuest.objects.filter( rsvp__event_id=event.id, ).select_related("rsvp__person", "submission") # Pour éviter emails = PersonEmail.objects.raw( """ WITH emails AS ( SELECT pe.id, pe.person_id, pe.address, row_number() OVER (PARTITION BY pe.person_id ORDER BY pe.person_id, _order) AS num FROM people_personemail pe JOIN people_person p ON p.id = pe.person_id JOIN events_rsvp r on p.id = r.person_id WHERE r.event_id = %s AND NOT pe.bounced ) SELECT id, person_id, address FROM emails WHERE num = 1; """, [event.id], ) emails = {e.person_id: e.address for e in emails} for rsvp in rsvps: writer.writerow([ "R" + str(rsvp.pk), "O" if rsvp.status == RSVP.STATUS_CANCELED else "", f"{rsvp.form_submission.data.get('first_name')} {rsvp.form_submission.data.get('last_name')}", str(rsvp.person_id), emails.get(rsvp.person_id, None) or rsvp.person.email, rsvp.person.gender or "", rsvp.form_submission.data.get(category_field, ""), display_price(event.get_price(rsvp.form_submission.data)), "completed" if rsvp.status == RSVP.STATUS_CONFIRMED else "on-hold", rsvp.created.isoformat() if rsvp.form_submission.data.get( "admin", False) else None, ]) for guest in guests: writer.writerow([ "G" + str(guest.rsvp_id) + "g" + str(guest.pk), "O" if guest.status == RSVP.STATUS_CANCELED else "", f"{guest.submission.data['first_name']} {guest.submission.data['last_name']}", str(guest.rsvp.person_id), emails.get(guest.rsvp.person_id, None) or guest.rsvp.person.email, guest.submission.data.get("gender", ""), guest.submission.data.get(category_field, ""), display_price(event.get_price(guest.submission.data)), "completed" if guest.status == RSVP.STATUS_CONFIRMED else "on-hold", None, ])
def summary(spending_request): """Renvoie un résumé de la demande de dépense pour l'affichage sur la page de gestion :param spending_request: la demande de dépense à résumer :return: un itérateur vers les différents champs constituant le résumé """ other_display_fields = [ "category_precisions", "explanation", "spending_date", "provider", "iban", "payer_name", ] yield { "label": "Identifiant de la demande", "value": str(spending_request.pk)[:6] } yield { "label": get_spending_request_field_label("title"), "value": spending_request.title, } status = spending_request.get_status_display() if spending_request.status == SpendingRequest.STATUS_DRAFT and can_be_sent( spending_request): status = _( "Dès que votre brouillon est complet, vous pouvez le confirmer pour validation par l'équipe de suivi." ) if spending_request.status in SpendingRequest.STATUS_NEED_ACTION: status = format_html("<strong>{}</strong>", status) yield { "label": get_spending_request_field_label("status"), "value": status } balance = get_balance(spending_request.group) amount_text = display_price(spending_request.amount) if spending_request.amount > balance: amount_text = format_html( "{}<br><strong style=\"color: #BB1111;\">L'allocation de votre groupe est pour l'instant insuffisante, votre" " demande ne pourra pas être validée</strong>", amount_text, ) yield { "label": get_spending_request_field_label("amount"), "value": amount_text } yield { "label": get_spending_request_field_label("event"), "value": format_html( '<a href="{link}">{name}</a>', link=reverse("view_event", kwargs={"pk": spending_request.event.id}), name=spending_request.event.name, ) if spending_request.event else _("Aucun"), } yield { "label": get_spending_request_field_label("category"), "value": spending_request.get_category_display(), } for f in other_display_fields: yield { "label": get_spending_request_field_label(f), "value": getattr(spending_request, f), }