mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-22 14:13:21 +00:00
Merge pull request #842 from ae-utbm/3dsv2-again
Add the new 3DSv2 fields
This commit is contained in:
commit
8ec3074488
@ -306,6 +306,12 @@ a:not(.button) {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
|
|
||||||
|
&.alert-yellow {
|
||||||
|
background-color: rgb(255, 255, 240);
|
||||||
|
color: rgb(99, 87, 6);
|
||||||
|
border: rgb(192, 180, 16) 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
&.alert-green {
|
&.alert-green {
|
||||||
background-color: rgb(245, 255, 245);
|
background-color: rgb(245, 255, 245);
|
||||||
color: rgb(3, 84, 63);
|
color: rgb(3, 84, 63);
|
||||||
|
@ -46,6 +46,7 @@ class CustomerAdmin(SearchModelAdmin):
|
|||||||
@admin.register(BillingInfo)
|
@admin.register(BillingInfo)
|
||||||
class BillingInfoAdmin(admin.ModelAdmin):
|
class BillingInfoAdmin(admin.ModelAdmin):
|
||||||
list_display = ("first_name", "last_name", "address_1", "city", "country")
|
list_display = ("first_name", "last_name", "address_1", "city", "country")
|
||||||
|
autocomplete_fields = ("customer",)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Counter)
|
@admin.register(Counter)
|
||||||
|
@ -2,6 +2,7 @@ from ajax_select import make_ajax_field
|
|||||||
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
|
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from phonenumber_field.widgets import RegionalPhoneNumberWidget
|
||||||
|
|
||||||
from core.views.forms import NFCTextInput, SelectDate, SelectDateTime
|
from core.views.forms import NFCTextInput, SelectDate, SelectDateTime
|
||||||
from counter.models import (
|
from counter.models import (
|
||||||
@ -26,7 +27,11 @@ class BillingInfoForm(forms.ModelForm):
|
|||||||
"zip_code",
|
"zip_code",
|
||||||
"city",
|
"city",
|
||||||
"country",
|
"country",
|
||||||
|
"phone_number",
|
||||||
]
|
]
|
||||||
|
widgets = {
|
||||||
|
"phone_number": RegionalPhoneNumberWidget,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class StudentCardForm(forms.ModelForm):
|
class StudentCardForm(forms.ModelForm):
|
||||||
|
20
counter/migrations/0023_billinginfo_phone_number.py
Normal file
20
counter/migrations/0023_billinginfo_phone_number.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 4.2.16 on 2024-09-26 10:28
|
||||||
|
|
||||||
|
import phonenumber_field.modelfields
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("counter", "0022_alter_product_icon"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="billinginfo",
|
||||||
|
name="phone_number",
|
||||||
|
field=phonenumber_field.modelfields.PhoneNumberField(
|
||||||
|
max_length=128, null=True, region=None, verbose_name="Phone number"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -34,6 +34,7 @@ from django.utils import timezone
|
|||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django_countries.fields import CountryField
|
from django_countries.fields import CountryField
|
||||||
|
from phonenumber_field.modelfields import PhoneNumberField
|
||||||
|
|
||||||
from accounting.models import CurrencyField
|
from accounting.models import CurrencyField
|
||||||
from club.models import Club
|
from club.models import Club
|
||||||
@ -176,6 +177,14 @@ class BillingInfo(models.Model):
|
|||||||
city = models.CharField(_("City"), max_length=50)
|
city = models.CharField(_("City"), max_length=50)
|
||||||
country = CountryField(blank_label=_("Country"))
|
country = CountryField(blank_label=_("Country"))
|
||||||
|
|
||||||
|
# This table was created during the A22 semester.
|
||||||
|
# However, later on, CA asked for the phone number to be added to the billing info.
|
||||||
|
# As the table was already created, this new field had to be nullable,
|
||||||
|
# even tough it is required by the bank and shouldn't be null.
|
||||||
|
# If one day there is no null phone number remaining,
|
||||||
|
# please make the field non-nullable.
|
||||||
|
phone_number = PhoneNumberField(_("Phone number"), null=True, blank=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.first_name} {self.last_name}"
|
return f"{self.first_name} {self.last_name}"
|
||||||
|
|
||||||
@ -192,6 +201,8 @@ class BillingInfo(models.Model):
|
|||||||
"ZipCode": self.zip_code,
|
"ZipCode": self.zip_code,
|
||||||
"City": self.city,
|
"City": self.city,
|
||||||
"CountryCode": self.country.numeric, # ISO-3166-1 numeric code
|
"CountryCode": self.country.numeric, # ISO-3166-1 numeric code
|
||||||
|
"MobilePhone": self.phone_number.as_national.replace(" ", ""),
|
||||||
|
"CountryCodeMobilePhone": f"+{self.phone_number.country_code}",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.address_2:
|
if self.address_2:
|
||||||
|
@ -315,6 +315,7 @@ class TestBillingInfo:
|
|||||||
"zip_code": "34301",
|
"zip_code": "34301",
|
||||||
"city": "Sète",
|
"city": "Sète",
|
||||||
"country": "FR",
|
"country": "FR",
|
||||||
|
"phone_number": "0612345678",
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_edit_infos(self, client: Client, payload: dict):
|
def test_edit_infos(self, client: Client, payload: dict):
|
||||||
@ -356,7 +357,7 @@ class TestBillingInfo:
|
|||||||
for key, val in payload.items():
|
for key, val in payload.items():
|
||||||
assert getattr(infos, key) == val
|
assert getattr(infos, key) == val
|
||||||
|
|
||||||
def test_invalid_data(self, client: Client, payload):
|
def test_invalid_data(self, client: Client, payload: dict[str, str]):
|
||||||
user = subscriber_user.make()
|
user = subscriber_user.make()
|
||||||
client.force_login(user)
|
client.force_login(user)
|
||||||
# address_1, zip_code and country are missing
|
# address_1, zip_code and country are missing
|
||||||
@ -391,6 +392,60 @@ class TestBillingInfo:
|
|||||||
)
|
)
|
||||||
assert response.status_code == expected_code
|
assert response.status_code == expected_code
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"phone_number",
|
||||||
|
["+33612345678", "0612345678", "06 12 34 56 78", "06-12-34-56-78"],
|
||||||
|
)
|
||||||
|
def test_phone_number_format(
|
||||||
|
self, client: Client, payload: dict, phone_number: str
|
||||||
|
):
|
||||||
|
"""Test that various formats of phone numbers are accepted."""
|
||||||
|
user = subscriber_user.make()
|
||||||
|
client.force_login(user)
|
||||||
|
payload["phone_number"] = phone_number
|
||||||
|
response = client.put(
|
||||||
|
reverse("api:put_billing_info", args=[user.id]),
|
||||||
|
json.dumps(payload),
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
infos = BillingInfo.objects.get(customer__user=user)
|
||||||
|
assert infos.phone_number == "0612345678"
|
||||||
|
assert infos.phone_number.country_code == 33
|
||||||
|
|
||||||
|
def test_foreign_phone_number(self, client: Client, payload: dict):
|
||||||
|
"""Test that a foreign phone number is accepted."""
|
||||||
|
user = subscriber_user.make()
|
||||||
|
client.force_login(user)
|
||||||
|
payload["phone_number"] = "+49612345678"
|
||||||
|
response = client.put(
|
||||||
|
reverse("api:put_billing_info", args=[user.id]),
|
||||||
|
json.dumps(payload),
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
infos = BillingInfo.objects.get(customer__user=user)
|
||||||
|
assert infos.phone_number.as_national == "06123 45678"
|
||||||
|
assert infos.phone_number.country_code == 49
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"phone_number", ["061234567a", "06 12 34 56", "061234567879", "azertyuiop"]
|
||||||
|
)
|
||||||
|
def test_invalid_phone_number(
|
||||||
|
self, client: Client, payload: dict, phone_number: str
|
||||||
|
):
|
||||||
|
"""Test that invalid phone numbers are rejected."""
|
||||||
|
user = subscriber_user.make()
|
||||||
|
client.force_login(user)
|
||||||
|
payload["phone_number"] = phone_number
|
||||||
|
response = client.put(
|
||||||
|
reverse("api:put_billing_info", args=[user.id]),
|
||||||
|
json.dumps(payload),
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
assert response.status_code == 422
|
||||||
|
assert not BillingInfo.objects.filter(customer__user=user).exists()
|
||||||
|
|
||||||
|
|
||||||
class TestBarmanConnection(TestCase):
|
class TestBarmanConnection(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
from typing import Annotated
|
||||||
|
|
||||||
from ninja import ModelSchema, Schema
|
from ninja import ModelSchema, Schema
|
||||||
from pydantic import Field, NonNegativeInt, PositiveInt, TypeAdapter
|
from pydantic import Field, NonNegativeInt, PositiveInt, TypeAdapter
|
||||||
|
|
||||||
|
# from phonenumber_field.phonenumber import PhoneNumber
|
||||||
|
from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
|
||||||
|
|
||||||
from counter.models import BillingInfo
|
from counter.models import BillingInfo
|
||||||
|
|
||||||
|
|
||||||
@ -31,3 +36,8 @@ class BillingInfoSchema(ModelSchema):
|
|||||||
"country",
|
"country",
|
||||||
]
|
]
|
||||||
fields_optional = ["customer"]
|
fields_optional = ["customer"]
|
||||||
|
|
||||||
|
# for reasons described in the model, BillingInfo.phone_number
|
||||||
|
# in nullable, but null values shouldn't be actually allowed,
|
||||||
|
# so we force the field to be required
|
||||||
|
phone_number: Annotated[PhoneNumber, PhoneNumberValidator(default_region="FR")]
|
||||||
|
@ -42,7 +42,16 @@ document.addEventListener("alpine:init", () => {
|
|||||||
this.req_state = res.ok
|
this.req_state = res.ok
|
||||||
? BillingInfoReqState.SUCCESS
|
? BillingInfoReqState.SUCCESS
|
||||||
: BillingInfoReqState.FAILURE;
|
: BillingInfoReqState.FAILURE;
|
||||||
if (res.ok) {
|
if (res.status === 422) {
|
||||||
|
const errors = (await res.json())["detail"].map((err) => err["loc"]).flat();
|
||||||
|
Array.from(form.querySelectorAll("input"))
|
||||||
|
.filter((elem) => errors.includes(elem.name))
|
||||||
|
.forEach((elem) => {
|
||||||
|
elem.setCustomValidity(gettext("Incorrect value"));
|
||||||
|
elem.reportValidity();
|
||||||
|
elem.oninput = () => elem.setCustomValidity("");
|
||||||
|
});
|
||||||
|
} else if (res.ok) {
|
||||||
Alpine.store("billing_inputs").fill();
|
Alpine.store("billing_inputs").fill();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -98,13 +98,20 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
{% if must_fill_billing_infos %}
|
{% if billing_infos_state == BillingInfoState.EMPTY %}
|
||||||
<p>
|
<div class="alert alert-yellow">
|
||||||
<i>
|
|
||||||
{% trans %}You must fill your billing infos if you want to pay with your credit
|
{% trans %}You must fill your billing infos if you want to pay with your credit
|
||||||
card{% endtrans %}
|
card{% endtrans %}
|
||||||
</i>
|
</div>
|
||||||
</p>
|
{% elif billing_infos_state == BillingInfoState.MISSING_PHONE_NUMBER %}
|
||||||
|
<div class="alert alert-yellow">
|
||||||
|
{% trans %}
|
||||||
|
The Crédit Agricole changed its policy related to the billing
|
||||||
|
information that must be provided in order to pay with a credit card.
|
||||||
|
If you want to pay with your credit card, you must add a phone number
|
||||||
|
to the data you already provided.
|
||||||
|
{% endtrans %}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form method="post" action="{{ settings.SITH_EBOUTIC_ET_URL }}" name="bank-pay-form">
|
<form method="post" action="{{ settings.SITH_EBOUTIC_ET_URL }}" name="bank-pay-form">
|
||||||
<template x-data x-for="[key, value] in Object.entries($store.billing_inputs.data)">
|
<template x-data x-for="[key, value] in Object.entries($store.billing_inputs.data)">
|
||||||
@ -113,7 +120,7 @@
|
|||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
id="bank-submit-button"
|
id="bank-submit-button"
|
||||||
{% if must_fill_billing_infos %}disabled="disabled"{% endif %}
|
{% if billing_infos_state != BillingInfoState.VALID %}disabled="disabled"{% endif %}
|
||||||
value="{% trans %}Pay with credit card{% endtrans %}"
|
value="{% trans %}Pay with credit card{% endtrans %}"
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
import sentry_sdk
|
import sentry_sdk
|
||||||
from cryptography.exceptions import InvalidSignature
|
from cryptography.exceptions import InvalidSignature
|
||||||
@ -82,6 +83,12 @@ def payment_result(request, result: str) -> HttpResponse:
|
|||||||
return render(request, "eboutic/eboutic_payment_result.jinja", context)
|
return render(request, "eboutic/eboutic_payment_result.jinja", context)
|
||||||
|
|
||||||
|
|
||||||
|
class BillingInfoState(Enum):
|
||||||
|
VALID = 1
|
||||||
|
EMPTY = 2
|
||||||
|
MISSING_PHONE_NUMBER = 3
|
||||||
|
|
||||||
|
|
||||||
class EbouticCommand(LoginRequiredMixin, TemplateView):
|
class EbouticCommand(LoginRequiredMixin, TemplateView):
|
||||||
template_name = "eboutic/eboutic_makecommand.jinja"
|
template_name = "eboutic/eboutic_makecommand.jinja"
|
||||||
basket: Basket
|
basket: Basket
|
||||||
@ -130,9 +137,16 @@ class EbouticCommand(LoginRequiredMixin, TemplateView):
|
|||||||
default_billing_info = customer.billing_infos
|
default_billing_info = customer.billing_infos
|
||||||
else:
|
else:
|
||||||
kwargs["customer_amount"] = None
|
kwargs["customer_amount"] = None
|
||||||
kwargs["must_fill_billing_infos"] = default_billing_info is None
|
# make the enum available in the template
|
||||||
if not kwargs["must_fill_billing_infos"]:
|
kwargs["BillingInfoState"] = BillingInfoState
|
||||||
# the user has already filled its billing_infos, thus we can
|
if default_billing_info is None:
|
||||||
|
kwargs["billing_infos_state"] = BillingInfoState.EMPTY
|
||||||
|
elif default_billing_info.phone_number is None:
|
||||||
|
kwargs["billing_infos_state"] = BillingInfoState.MISSING_PHONE_NUMBER
|
||||||
|
else:
|
||||||
|
kwargs["billing_infos_state"] = BillingInfoState.VALID
|
||||||
|
if kwargs["billing_infos_state"] == BillingInfoState.VALID:
|
||||||
|
# the user has already filled all of its billing_infos, thus we can
|
||||||
# get it without expecting an error
|
# get it without expecting an error
|
||||||
kwargs["billing_infos"] = dict(self.basket.get_e_transaction_data())
|
kwargs["billing_infos"] = dict(self.basket.get_e_transaction_data())
|
||||||
kwargs["basket"] = self.basket
|
kwargs["basket"] = self.basket
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-09-17 12:21+0200\n"
|
"POT-Creation-Date: 2024-09-26 17:51+0200\n"
|
||||||
"PO-Revision-Date: 2016-07-18\n"
|
"PO-Revision-Date: 2016-07-18\n"
|
||||||
"Last-Translator: Skia <skia@libskia.so>\n"
|
"Last-Translator: Skia <skia@libskia.so>\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@ -18,8 +18,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: accounting/models.py:62 accounting/models.py:103 accounting/models.py:136
|
#: accounting/models.py:62 accounting/models.py:103 accounting/models.py:136
|
||||||
#: accounting/models.py:203 club/models.py:54 com/models.py:274
|
#: accounting/models.py:203 club/models.py:54 com/models.py:274
|
||||||
#: com/models.py:293 counter/models.py:209 counter/models.py:242
|
#: com/models.py:293 counter/models.py:213 counter/models.py:246
|
||||||
#: counter/models.py:377 forum/models.py:59 launderette/models.py:29
|
#: counter/models.py:381 forum/models.py:59 launderette/models.py:29
|
||||||
#: launderette/models.py:84 launderette/models.py:122 stock/models.py:36
|
#: launderette/models.py:84 launderette/models.py:122 stock/models.py:36
|
||||||
#: stock/models.py:57 stock/models.py:97 stock/models.py:125
|
#: stock/models.py:57 stock/models.py:97 stock/models.py:125
|
||||||
msgid "name"
|
msgid "name"
|
||||||
@ -66,8 +66,8 @@ msgid "account number"
|
|||||||
msgstr "numéro de compte"
|
msgstr "numéro de compte"
|
||||||
|
|
||||||
#: accounting/models.py:109 accounting/models.py:140 club/models.py:344
|
#: accounting/models.py:109 accounting/models.py:140 club/models.py:344
|
||||||
#: com/models.py:74 com/models.py:259 com/models.py:299 counter/models.py:265
|
#: com/models.py:74 com/models.py:259 com/models.py:299 counter/models.py:269
|
||||||
#: counter/models.py:379 trombi/models.py:210
|
#: counter/models.py:383 trombi/models.py:210
|
||||||
msgid "club"
|
msgid "club"
|
||||||
msgstr "club"
|
msgstr "club"
|
||||||
|
|
||||||
@ -88,12 +88,12 @@ msgstr "Compte club"
|
|||||||
msgid "%(club_account)s on %(bank_account)s"
|
msgid "%(club_account)s on %(bank_account)s"
|
||||||
msgstr "%(club_account)s sur %(bank_account)s"
|
msgstr "%(club_account)s sur %(bank_account)s"
|
||||||
|
|
||||||
#: accounting/models.py:201 club/models.py:350 counter/models.py:860
|
#: accounting/models.py:201 club/models.py:350 counter/models.py:864
|
||||||
#: election/models.py:16 launderette/models.py:179
|
#: election/models.py:16 launderette/models.py:179
|
||||||
msgid "start date"
|
msgid "start date"
|
||||||
msgstr "date de début"
|
msgstr "date de début"
|
||||||
|
|
||||||
#: accounting/models.py:202 club/models.py:351 counter/models.py:861
|
#: accounting/models.py:202 club/models.py:351 counter/models.py:865
|
||||||
#: election/models.py:17
|
#: election/models.py:17
|
||||||
msgid "end date"
|
msgid "end date"
|
||||||
msgstr "date de fin"
|
msgstr "date de fin"
|
||||||
@ -106,8 +106,8 @@ msgstr "est fermé"
|
|||||||
msgid "club account"
|
msgid "club account"
|
||||||
msgstr "compte club"
|
msgstr "compte club"
|
||||||
|
|
||||||
#: accounting/models.py:212 accounting/models.py:272 counter/models.py:56
|
#: accounting/models.py:212 accounting/models.py:272 counter/models.py:57
|
||||||
#: counter/models.py:583
|
#: counter/models.py:587
|
||||||
msgid "amount"
|
msgid "amount"
|
||||||
msgstr "montant"
|
msgstr "montant"
|
||||||
|
|
||||||
@ -127,20 +127,20 @@ msgstr "numéro"
|
|||||||
msgid "journal"
|
msgid "journal"
|
||||||
msgstr "classeur"
|
msgstr "classeur"
|
||||||
|
|
||||||
#: accounting/models.py:273 core/models.py:940 core/models.py:1442
|
#: accounting/models.py:273 core/models.py:940 core/models.py:1460
|
||||||
#: core/models.py:1487 core/models.py:1516 core/models.py:1540
|
#: core/models.py:1505 core/models.py:1534 core/models.py:1558
|
||||||
#: counter/models.py:593 counter/models.py:686 counter/models.py:896
|
#: counter/models.py:597 counter/models.py:690 counter/models.py:900
|
||||||
#: eboutic/models.py:57 eboutic/models.py:173 forum/models.py:311
|
#: eboutic/models.py:57 eboutic/models.py:173 forum/models.py:311
|
||||||
#: forum/models.py:412 stock/models.py:96
|
#: forum/models.py:412 stock/models.py:96
|
||||||
msgid "date"
|
msgid "date"
|
||||||
msgstr "date"
|
msgstr "date"
|
||||||
|
|
||||||
#: accounting/models.py:274 counter/models.py:211 counter/models.py:897
|
#: accounting/models.py:274 counter/models.py:215 counter/models.py:901
|
||||||
#: pedagogy/models.py:207 stock/models.py:99
|
#: pedagogy/models.py:207 stock/models.py:99
|
||||||
msgid "comment"
|
msgid "comment"
|
||||||
msgstr "commentaire"
|
msgstr "commentaire"
|
||||||
|
|
||||||
#: accounting/models.py:276 counter/models.py:595 counter/models.py:688
|
#: accounting/models.py:276 counter/models.py:599 counter/models.py:692
|
||||||
#: subscription/models.py:56
|
#: subscription/models.py:56
|
||||||
msgid "payment method"
|
msgid "payment method"
|
||||||
msgstr "méthode de paiement"
|
msgstr "méthode de paiement"
|
||||||
@ -166,8 +166,8 @@ msgid "accounting type"
|
|||||||
msgstr "type comptable"
|
msgstr "type comptable"
|
||||||
|
|
||||||
#: accounting/models.py:311 accounting/models.py:450 accounting/models.py:483
|
#: accounting/models.py:311 accounting/models.py:450 accounting/models.py:483
|
||||||
#: accounting/models.py:515 core/models.py:1515 core/models.py:1541
|
#: accounting/models.py:515 core/models.py:1533 core/models.py:1559
|
||||||
#: counter/models.py:652
|
#: counter/models.py:656
|
||||||
msgid "label"
|
msgid "label"
|
||||||
msgstr "étiquette"
|
msgstr "étiquette"
|
||||||
|
|
||||||
@ -266,7 +266,7 @@ msgstr ""
|
|||||||
"Vous devez fournir soit un type comptable simplifié ou un type comptable "
|
"Vous devez fournir soit un type comptable simplifié ou un type comptable "
|
||||||
"standard"
|
"standard"
|
||||||
|
|
||||||
#: accounting/models.py:442 counter/models.py:252 pedagogy/models.py:41
|
#: accounting/models.py:442 counter/models.py:256 pedagogy/models.py:41
|
||||||
msgid "code"
|
msgid "code"
|
||||||
msgstr "code"
|
msgstr "code"
|
||||||
|
|
||||||
@ -370,7 +370,7 @@ msgstr "Compte en banque : "
|
|||||||
#: core/templates/core/user_account_detail.jinja:66
|
#: core/templates/core/user_account_detail.jinja:66
|
||||||
#: core/templates/core/user_clubs.jinja:34
|
#: core/templates/core/user_clubs.jinja:34
|
||||||
#: core/templates/core/user_clubs.jinja:63
|
#: core/templates/core/user_clubs.jinja:63
|
||||||
#: core/templates/core/user_edit.jinja:57
|
#: core/templates/core/user_edit.jinja:62
|
||||||
#: core/templates/core/user_preferences.jinja:48
|
#: core/templates/core/user_preferences.jinja:48
|
||||||
#: counter/templates/counter/last_ops.jinja:35
|
#: counter/templates/counter/last_ops.jinja:35
|
||||||
#: counter/templates/counter/last_ops.jinja:65
|
#: counter/templates/counter/last_ops.jinja:65
|
||||||
@ -968,11 +968,11 @@ msgstr "Une action est requise"
|
|||||||
msgid "You must specify at least an user or an email address"
|
msgid "You must specify at least an user or an email address"
|
||||||
msgstr "vous devez spécifier au moins un utilisateur ou une adresse email"
|
msgstr "vous devez spécifier au moins un utilisateur ou une adresse email"
|
||||||
|
|
||||||
#: club/forms.py:153 counter/forms.py:186
|
#: club/forms.py:153 counter/forms.py:187
|
||||||
msgid "Begin date"
|
msgid "Begin date"
|
||||||
msgstr "Date de début"
|
msgstr "Date de début"
|
||||||
|
|
||||||
#: club/forms.py:156 com/views.py:82 com/views.py:201 counter/forms.py:189
|
#: club/forms.py:156 com/views.py:82 com/views.py:201 counter/forms.py:190
|
||||||
#: election/views.py:167 subscription/views.py:38
|
#: election/views.py:167 subscription/views.py:38
|
||||||
msgid "End date"
|
msgid "End date"
|
||||||
msgstr "Date de fin"
|
msgstr "Date de fin"
|
||||||
@ -1058,7 +1058,7 @@ msgstr "Vous ne pouvez pas faire de boucles dans les clubs"
|
|||||||
msgid "A club with that unix_name already exists"
|
msgid "A club with that unix_name already exists"
|
||||||
msgstr "Un club avec ce nom UNIX existe déjà."
|
msgstr "Un club avec ce nom UNIX existe déjà."
|
||||||
|
|
||||||
#: club/models.py:336 counter/models.py:851 counter/models.py:887
|
#: club/models.py:336 counter/models.py:855 counter/models.py:891
|
||||||
#: eboutic/models.py:53 eboutic/models.py:169 election/models.py:183
|
#: eboutic/models.py:53 eboutic/models.py:169 election/models.py:183
|
||||||
#: launderette/models.py:136 launderette/models.py:198 sas/models.py:270
|
#: launderette/models.py:136 launderette/models.py:198 sas/models.py:270
|
||||||
#: trombi/models.py:206
|
#: trombi/models.py:206
|
||||||
@ -1070,8 +1070,8 @@ msgstr "nom d'utilisateur"
|
|||||||
msgid "role"
|
msgid "role"
|
||||||
msgstr "rôle"
|
msgstr "rôle"
|
||||||
|
|
||||||
#: club/models.py:358 core/models.py:89 counter/models.py:210
|
#: club/models.py:358 core/models.py:89 counter/models.py:214
|
||||||
#: counter/models.py:243 election/models.py:13 election/models.py:115
|
#: counter/models.py:247 election/models.py:13 election/models.py:115
|
||||||
#: election/models.py:188 forum/models.py:60 forum/models.py:244
|
#: election/models.py:188 forum/models.py:60 forum/models.py:244
|
||||||
msgid "description"
|
msgid "description"
|
||||||
msgstr "description"
|
msgstr "description"
|
||||||
@ -1440,7 +1440,7 @@ msgstr "résumé"
|
|||||||
msgid "content"
|
msgid "content"
|
||||||
msgstr "contenu"
|
msgstr "contenu"
|
||||||
|
|
||||||
#: com/models.py:71 core/models.py:1485 launderette/models.py:92
|
#: com/models.py:71 core/models.py:1503 launderette/models.py:92
|
||||||
#: launderette/models.py:130 launderette/models.py:181 stock/models.py:74
|
#: launderette/models.py:130 launderette/models.py:181 stock/models.py:74
|
||||||
#: stock/models.py:129
|
#: stock/models.py:129
|
||||||
msgid "type"
|
msgid "type"
|
||||||
@ -2217,7 +2217,7 @@ msgstr "Un utilisateur de ce nom d'utilisateur existe déjà"
|
|||||||
#: core/templates/core/user_detail.jinja:110
|
#: core/templates/core/user_detail.jinja:110
|
||||||
#: core/templates/core/user_detail.jinja:112
|
#: core/templates/core/user_detail.jinja:112
|
||||||
#: core/templates/core/user_detail.jinja:113
|
#: core/templates/core/user_detail.jinja:113
|
||||||
#: core/templates/core/user_edit.jinja:16
|
#: core/templates/core/user_edit.jinja:21
|
||||||
#: election/templates/election/election_detail.jinja:132
|
#: election/templates/election/election_detail.jinja:132
|
||||||
#: election/templates/election/election_detail.jinja:134
|
#: election/templates/election/election_detail.jinja:134
|
||||||
#: forum/templates/forum/macros.jinja:104
|
#: forum/templates/forum/macros.jinja:104
|
||||||
@ -2250,7 +2250,7 @@ msgstr "avoir une notification pour chaque rechargement"
|
|||||||
msgid "file name"
|
msgid "file name"
|
||||||
msgstr "nom du fichier"
|
msgstr "nom du fichier"
|
||||||
|
|
||||||
#: core/models.py:899 core/models.py:1234
|
#: core/models.py:899 core/models.py:1252
|
||||||
msgid "parent"
|
msgid "parent"
|
||||||
msgstr "parent"
|
msgstr "parent"
|
||||||
|
|
||||||
@ -2266,11 +2266,11 @@ msgstr "miniature"
|
|||||||
msgid "owner"
|
msgid "owner"
|
||||||
msgstr "propriétaire"
|
msgstr "propriétaire"
|
||||||
|
|
||||||
#: core/models.py:932 core/models.py:1251 core/views/files.py:223
|
#: core/models.py:932 core/models.py:1269 core/views/files.py:223
|
||||||
msgid "edit group"
|
msgid "edit group"
|
||||||
msgstr "groupe d'édition"
|
msgstr "groupe d'édition"
|
||||||
|
|
||||||
#: core/models.py:935 core/models.py:1254 core/views/files.py:226
|
#: core/models.py:935 core/models.py:1272 core/views/files.py:226
|
||||||
msgid "view group"
|
msgid "view group"
|
||||||
msgstr "groupe de vue"
|
msgstr "groupe de vue"
|
||||||
|
|
||||||
@ -2316,11 +2316,11 @@ msgstr "Un fichier de ce nom existe déjà"
|
|||||||
msgid "You must provide a file"
|
msgid "You must provide a file"
|
||||||
msgstr "Vous devez fournir un fichier"
|
msgstr "Vous devez fournir un fichier"
|
||||||
|
|
||||||
#: core/models.py:1217
|
#: core/models.py:1235
|
||||||
msgid "page unix name"
|
msgid "page unix name"
|
||||||
msgstr "nom unix de la page"
|
msgstr "nom unix de la page"
|
||||||
|
|
||||||
#: core/models.py:1223
|
#: core/models.py:1241
|
||||||
msgid ""
|
msgid ""
|
||||||
"Enter a valid page name. This value may contain only unaccented letters, "
|
"Enter a valid page name. This value may contain only unaccented letters, "
|
||||||
"numbers and ./+/-/_ characters."
|
"numbers and ./+/-/_ characters."
|
||||||
@ -2328,55 +2328,55 @@ msgstr ""
|
|||||||
"Entrez un nom de page correct. Uniquement des lettres non accentuées, "
|
"Entrez un nom de page correct. Uniquement des lettres non accentuées, "
|
||||||
"numéros, et ./+/-/_"
|
"numéros, et ./+/-/_"
|
||||||
|
|
||||||
#: core/models.py:1241
|
#: core/models.py:1259
|
||||||
msgid "page name"
|
msgid "page name"
|
||||||
msgstr "nom de la page"
|
msgstr "nom de la page"
|
||||||
|
|
||||||
#: core/models.py:1246
|
#: core/models.py:1264
|
||||||
msgid "owner group"
|
msgid "owner group"
|
||||||
msgstr "groupe propriétaire"
|
msgstr "groupe propriétaire"
|
||||||
|
|
||||||
#: core/models.py:1259
|
#: core/models.py:1277
|
||||||
msgid "lock user"
|
msgid "lock user"
|
||||||
msgstr "utilisateur bloquant"
|
msgstr "utilisateur bloquant"
|
||||||
|
|
||||||
#: core/models.py:1266
|
#: core/models.py:1284
|
||||||
msgid "lock_timeout"
|
msgid "lock_timeout"
|
||||||
msgstr "décompte du déblocage"
|
msgstr "décompte du déblocage"
|
||||||
|
|
||||||
#: core/models.py:1316
|
#: core/models.py:1334
|
||||||
msgid "Duplicate page"
|
msgid "Duplicate page"
|
||||||
msgstr "Une page de ce nom existe déjà"
|
msgstr "Une page de ce nom existe déjà"
|
||||||
|
|
||||||
#: core/models.py:1319
|
#: core/models.py:1337
|
||||||
msgid "Loop in page tree"
|
msgid "Loop in page tree"
|
||||||
msgstr "Boucle dans l'arborescence des pages"
|
msgstr "Boucle dans l'arborescence des pages"
|
||||||
|
|
||||||
#: core/models.py:1439
|
#: core/models.py:1457
|
||||||
msgid "revision"
|
msgid "revision"
|
||||||
msgstr "révision"
|
msgstr "révision"
|
||||||
|
|
||||||
#: core/models.py:1440
|
#: core/models.py:1458
|
||||||
msgid "page title"
|
msgid "page title"
|
||||||
msgstr "titre de la page"
|
msgstr "titre de la page"
|
||||||
|
|
||||||
#: core/models.py:1441
|
#: core/models.py:1459
|
||||||
msgid "page content"
|
msgid "page content"
|
||||||
msgstr "contenu de la page"
|
msgstr "contenu de la page"
|
||||||
|
|
||||||
#: core/models.py:1482
|
#: core/models.py:1500
|
||||||
msgid "url"
|
msgid "url"
|
||||||
msgstr "url"
|
msgstr "url"
|
||||||
|
|
||||||
#: core/models.py:1483
|
#: core/models.py:1501
|
||||||
msgid "param"
|
msgid "param"
|
||||||
msgstr "param"
|
msgstr "param"
|
||||||
|
|
||||||
#: core/models.py:1488
|
#: core/models.py:1506
|
||||||
msgid "viewed"
|
msgid "viewed"
|
||||||
msgstr "vue"
|
msgstr "vue"
|
||||||
|
|
||||||
#: core/models.py:1546
|
#: core/models.py:1564
|
||||||
msgid "operation type"
|
msgid "operation type"
|
||||||
msgstr "type d'opération"
|
msgstr "type d'opération"
|
||||||
|
|
||||||
@ -2474,7 +2474,7 @@ msgstr "Forum"
|
|||||||
msgid "Gallery"
|
msgid "Gallery"
|
||||||
msgstr "Photos"
|
msgstr "Photos"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:225 counter/models.py:387
|
#: core/templates/core/base.jinja:225 counter/models.py:391
|
||||||
#: counter/templates/counter/counter_list.jinja:11
|
#: counter/templates/counter/counter_list.jinja:11
|
||||||
#: eboutic/templates/eboutic/eboutic_main.jinja:4
|
#: eboutic/templates/eboutic/eboutic_main.jinja:4
|
||||||
#: eboutic/templates/eboutic/eboutic_main.jinja:22
|
#: eboutic/templates/eboutic/eboutic_main.jinja:22
|
||||||
@ -2693,7 +2693,7 @@ msgid "Edit group"
|
|||||||
msgstr "Éditer le groupe"
|
msgstr "Éditer le groupe"
|
||||||
|
|
||||||
#: core/templates/core/group_edit.jinja:9
|
#: core/templates/core/group_edit.jinja:9
|
||||||
#: core/templates/core/user_edit.jinja:268
|
#: core/templates/core/user_edit.jinja:170
|
||||||
#: core/templates/core/user_group.jinja:13
|
#: core/templates/core/user_group.jinja:13
|
||||||
#: pedagogy/templates/pedagogy/uv_edit.jinja:36
|
#: pedagogy/templates/pedagogy/uv_edit.jinja:36
|
||||||
msgid "Update"
|
msgid "Update"
|
||||||
@ -3184,39 +3184,35 @@ msgstr "Aucun cadeau donné pour l'instant"
|
|||||||
msgid "Edit user"
|
msgid "Edit user"
|
||||||
msgstr "Éditer l'utilisateur"
|
msgstr "Éditer l'utilisateur"
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:36
|
#: core/templates/core/user_edit.jinja:41
|
||||||
msgid "Enable camera"
|
msgid "Enable camera"
|
||||||
msgstr "Activer la caméra"
|
msgstr "Activer la caméra"
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:44
|
#: core/templates/core/user_edit.jinja:49
|
||||||
msgid "Take a picture"
|
msgid "Take a picture"
|
||||||
msgstr "Prendre une photo"
|
msgstr "Prendre une photo"
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:64
|
#: core/templates/core/user_edit.jinja:69
|
||||||
msgid "To edit your profile picture, ask a member of the AE"
|
msgid "To edit your profile picture, ask a member of the AE"
|
||||||
msgstr "Pour changer votre photo de profil, demandez à un membre de l'AE"
|
msgstr "Pour changer votre photo de profil, demandez à un membre de l'AE"
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:173
|
#: core/templates/core/user_edit.jinja:98
|
||||||
msgid "captured"
|
|
||||||
msgstr "capturé"
|
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:196
|
|
||||||
msgid "Edit user profile"
|
msgid "Edit user profile"
|
||||||
msgstr "Éditer le profil de l'utilisateur"
|
msgstr "Éditer le profil de l'utilisateur"
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:258
|
#: core/templates/core/user_edit.jinja:160
|
||||||
msgid "Change my password"
|
msgid "Change my password"
|
||||||
msgstr "Changer mon mot de passe"
|
msgstr "Changer mon mot de passe"
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:263
|
#: core/templates/core/user_edit.jinja:165
|
||||||
msgid "Change user password"
|
msgid "Change user password"
|
||||||
msgstr "Changer le mot de passe"
|
msgstr "Changer le mot de passe"
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:273
|
#: core/templates/core/user_edit.jinja:175
|
||||||
msgid "Username:"
|
msgid "Username:"
|
||||||
msgstr "Nom d'utilisateur : "
|
msgstr "Nom d'utilisateur : "
|
||||||
|
|
||||||
#: core/templates/core/user_edit.jinja:276
|
#: core/templates/core/user_edit.jinja:178
|
||||||
msgid "Account number:"
|
msgid "Account number:"
|
||||||
msgstr "Numéro de compte : "
|
msgstr "Numéro de compte : "
|
||||||
|
|
||||||
@ -3350,7 +3346,7 @@ msgstr "Achats"
|
|||||||
msgid "Product top 10"
|
msgid "Product top 10"
|
||||||
msgstr "Top 10 produits"
|
msgstr "Top 10 produits"
|
||||||
|
|
||||||
#: core/templates/core/user_stats.jinja:43 counter/forms.py:200
|
#: core/templates/core/user_stats.jinja:43 counter/forms.py:201
|
||||||
msgid "Product"
|
msgid "Product"
|
||||||
msgstr "Produit"
|
msgstr "Produit"
|
||||||
|
|
||||||
@ -3395,7 +3391,7 @@ msgstr "Cotisations"
|
|||||||
msgid "Subscription stats"
|
msgid "Subscription stats"
|
||||||
msgstr "Statistiques de cotisation"
|
msgstr "Statistiques de cotisation"
|
||||||
|
|
||||||
#: core/templates/core/user_tools.jinja:48 counter/forms.py:159
|
#: core/templates/core/user_tools.jinja:48 counter/forms.py:160
|
||||||
#: counter/views.py:728
|
#: counter/views.py:728
|
||||||
msgid "Counters"
|
msgid "Counters"
|
||||||
msgstr "Comptoirs"
|
msgstr "Comptoirs"
|
||||||
@ -3654,7 +3650,7 @@ msgstr "Parrain / Marraine"
|
|||||||
msgid "Godchild"
|
msgid "Godchild"
|
||||||
msgstr "Fillot / Fillote"
|
msgstr "Fillot / Fillote"
|
||||||
|
|
||||||
#: core/views/forms.py:338 counter/forms.py:67 trombi/views.py:149
|
#: core/views/forms.py:338 counter/forms.py:68 trombi/views.py:149
|
||||||
msgid "Select user"
|
msgid "Select user"
|
||||||
msgstr "Choisir un utilisateur"
|
msgstr "Choisir un utilisateur"
|
||||||
|
|
||||||
@ -3713,24 +3709,24 @@ msgstr "Photos"
|
|||||||
msgid "Galaxy"
|
msgid "Galaxy"
|
||||||
msgstr "Galaxie"
|
msgstr "Galaxie"
|
||||||
|
|
||||||
#: counter/apps.py:30 counter/models.py:403 counter/models.py:857
|
#: counter/apps.py:30 counter/models.py:407 counter/models.py:861
|
||||||
#: counter/models.py:893 launderette/models.py:32 stock/models.py:39
|
#: counter/models.py:897 launderette/models.py:32 stock/models.py:39
|
||||||
msgid "counter"
|
msgid "counter"
|
||||||
msgstr "comptoir"
|
msgstr "comptoir"
|
||||||
|
|
||||||
#: counter/forms.py:48
|
#: counter/forms.py:49
|
||||||
msgid "This UID is invalid"
|
msgid "This UID is invalid"
|
||||||
msgstr "Cet UID est invalide"
|
msgstr "Cet UID est invalide"
|
||||||
|
|
||||||
#: counter/forms.py:89
|
#: counter/forms.py:90
|
||||||
msgid "User not found"
|
msgid "User not found"
|
||||||
msgstr "Utilisateur non trouvé"
|
msgstr "Utilisateur non trouvé"
|
||||||
|
|
||||||
#: counter/forms.py:145
|
#: counter/forms.py:146
|
||||||
msgid "Parent product"
|
msgid "Parent product"
|
||||||
msgstr "Produit parent"
|
msgstr "Produit parent"
|
||||||
|
|
||||||
#: counter/forms.py:151
|
#: counter/forms.py:152
|
||||||
msgid "Buying groups"
|
msgid "Buying groups"
|
||||||
msgstr "Groupes d'achat"
|
msgstr "Groupes d'achat"
|
||||||
|
|
||||||
@ -3738,165 +3734,169 @@ msgstr "Groupes d'achat"
|
|||||||
msgid "Ecocup regularization"
|
msgid "Ecocup regularization"
|
||||||
msgstr "Régularization des ecocups"
|
msgstr "Régularization des ecocups"
|
||||||
|
|
||||||
#: counter/models.py:55
|
#: counter/models.py:56
|
||||||
msgid "account id"
|
msgid "account id"
|
||||||
msgstr "numéro de compte"
|
msgstr "numéro de compte"
|
||||||
|
|
||||||
#: counter/models.py:57
|
#: counter/models.py:58
|
||||||
msgid "recorded product"
|
msgid "recorded product"
|
||||||
msgstr "produits consignés"
|
msgstr "produits consignés"
|
||||||
|
|
||||||
#: counter/models.py:60
|
#: counter/models.py:61
|
||||||
msgid "customer"
|
msgid "customer"
|
||||||
msgstr "client"
|
msgstr "client"
|
||||||
|
|
||||||
#: counter/models.py:61
|
#: counter/models.py:62
|
||||||
msgid "customers"
|
msgid "customers"
|
||||||
msgstr "clients"
|
msgstr "clients"
|
||||||
|
|
||||||
#: counter/models.py:73 counter/views.py:309
|
#: counter/models.py:74 counter/views.py:309
|
||||||
msgid "Not enough money"
|
msgid "Not enough money"
|
||||||
msgstr "Solde insuffisant"
|
msgstr "Solde insuffisant"
|
||||||
|
|
||||||
#: counter/models.py:171
|
#: counter/models.py:172
|
||||||
msgid "First name"
|
msgid "First name"
|
||||||
msgstr "Prénom"
|
msgstr "Prénom"
|
||||||
|
|
||||||
#: counter/models.py:172
|
#: counter/models.py:173
|
||||||
msgid "Last name"
|
msgid "Last name"
|
||||||
msgstr "Nom de famille"
|
msgstr "Nom de famille"
|
||||||
|
|
||||||
#: counter/models.py:173
|
#: counter/models.py:174
|
||||||
msgid "Address 1"
|
msgid "Address 1"
|
||||||
msgstr "Adresse 1"
|
msgstr "Adresse 1"
|
||||||
|
|
||||||
#: counter/models.py:174
|
#: counter/models.py:175
|
||||||
msgid "Address 2"
|
msgid "Address 2"
|
||||||
msgstr "Adresse 2"
|
msgstr "Adresse 2"
|
||||||
|
|
||||||
#: counter/models.py:175
|
#: counter/models.py:176
|
||||||
msgid "Zip code"
|
msgid "Zip code"
|
||||||
msgstr "Code postal"
|
msgstr "Code postal"
|
||||||
|
|
||||||
#: counter/models.py:176
|
#: counter/models.py:177
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr "Ville"
|
msgstr "Ville"
|
||||||
|
|
||||||
#: counter/models.py:177
|
#: counter/models.py:178
|
||||||
msgid "Country"
|
msgid "Country"
|
||||||
msgstr "Pays"
|
msgstr "Pays"
|
||||||
|
|
||||||
#: counter/models.py:221 counter/models.py:247
|
#: counter/models.py:179
|
||||||
|
msgid "Phone number"
|
||||||
|
msgstr "Numéro de téléphone"
|
||||||
|
|
||||||
|
#: counter/models.py:225 counter/models.py:251
|
||||||
msgid "product type"
|
msgid "product type"
|
||||||
msgstr "type du produit"
|
msgstr "type du produit"
|
||||||
|
|
||||||
#: counter/models.py:253
|
#: counter/models.py:257
|
||||||
msgid "purchase price"
|
msgid "purchase price"
|
||||||
msgstr "prix d'achat"
|
msgstr "prix d'achat"
|
||||||
|
|
||||||
#: counter/models.py:254
|
#: counter/models.py:258
|
||||||
msgid "selling price"
|
msgid "selling price"
|
||||||
msgstr "prix de vente"
|
msgstr "prix de vente"
|
||||||
|
|
||||||
#: counter/models.py:255
|
#: counter/models.py:259
|
||||||
msgid "special selling price"
|
msgid "special selling price"
|
||||||
msgstr "prix de vente spécial"
|
msgstr "prix de vente spécial"
|
||||||
|
|
||||||
#: counter/models.py:262
|
#: counter/models.py:266
|
||||||
msgid "icon"
|
msgid "icon"
|
||||||
msgstr "icône"
|
msgstr "icône"
|
||||||
|
|
||||||
#: counter/models.py:267
|
#: counter/models.py:271
|
||||||
msgid "limit age"
|
msgid "limit age"
|
||||||
msgstr "âge limite"
|
msgstr "âge limite"
|
||||||
|
|
||||||
#: counter/models.py:268
|
#: counter/models.py:272
|
||||||
msgid "tray price"
|
msgid "tray price"
|
||||||
msgstr "prix plateau"
|
msgstr "prix plateau"
|
||||||
|
|
||||||
#: counter/models.py:272
|
#: counter/models.py:276
|
||||||
msgid "parent product"
|
msgid "parent product"
|
||||||
msgstr "produit parent"
|
msgstr "produit parent"
|
||||||
|
|
||||||
#: counter/models.py:278
|
#: counter/models.py:282
|
||||||
msgid "buying groups"
|
msgid "buying groups"
|
||||||
msgstr "groupe d'achat"
|
msgstr "groupe d'achat"
|
||||||
|
|
||||||
#: counter/models.py:280 election/models.py:50
|
#: counter/models.py:284 election/models.py:50
|
||||||
msgid "archived"
|
msgid "archived"
|
||||||
msgstr "archivé"
|
msgstr "archivé"
|
||||||
|
|
||||||
#: counter/models.py:283 counter/models.py:993
|
#: counter/models.py:287 counter/models.py:997
|
||||||
msgid "product"
|
msgid "product"
|
||||||
msgstr "produit"
|
msgstr "produit"
|
||||||
|
|
||||||
#: counter/models.py:382
|
#: counter/models.py:386
|
||||||
msgid "products"
|
msgid "products"
|
||||||
msgstr "produits"
|
msgstr "produits"
|
||||||
|
|
||||||
#: counter/models.py:385
|
#: counter/models.py:389
|
||||||
msgid "counter type"
|
msgid "counter type"
|
||||||
msgstr "type de comptoir"
|
msgstr "type de comptoir"
|
||||||
|
|
||||||
#: counter/models.py:387
|
#: counter/models.py:391
|
||||||
msgid "Bar"
|
msgid "Bar"
|
||||||
msgstr "Bar"
|
msgstr "Bar"
|
||||||
|
|
||||||
#: counter/models.py:387
|
#: counter/models.py:391
|
||||||
msgid "Office"
|
msgid "Office"
|
||||||
msgstr "Bureau"
|
msgstr "Bureau"
|
||||||
|
|
||||||
#: counter/models.py:390
|
#: counter/models.py:394
|
||||||
msgid "sellers"
|
msgid "sellers"
|
||||||
msgstr "vendeurs"
|
msgstr "vendeurs"
|
||||||
|
|
||||||
#: counter/models.py:398 launderette/models.py:192
|
#: counter/models.py:402 launderette/models.py:192
|
||||||
msgid "token"
|
msgid "token"
|
||||||
msgstr "jeton"
|
msgstr "jeton"
|
||||||
|
|
||||||
#: counter/models.py:601
|
#: counter/models.py:605
|
||||||
msgid "bank"
|
msgid "bank"
|
||||||
msgstr "banque"
|
msgstr "banque"
|
||||||
|
|
||||||
#: counter/models.py:603 counter/models.py:693
|
#: counter/models.py:607 counter/models.py:697
|
||||||
msgid "is validated"
|
msgid "is validated"
|
||||||
msgstr "est validé"
|
msgstr "est validé"
|
||||||
|
|
||||||
#: counter/models.py:606
|
#: counter/models.py:610
|
||||||
msgid "refilling"
|
msgid "refilling"
|
||||||
msgstr "rechargement"
|
msgstr "rechargement"
|
||||||
|
|
||||||
#: counter/models.py:670 eboutic/models.py:227
|
#: counter/models.py:674 eboutic/models.py:227
|
||||||
msgid "unit price"
|
msgid "unit price"
|
||||||
msgstr "prix unitaire"
|
msgstr "prix unitaire"
|
||||||
|
|
||||||
#: counter/models.py:671 counter/models.py:973 eboutic/models.py:228
|
#: counter/models.py:675 counter/models.py:977 eboutic/models.py:228
|
||||||
msgid "quantity"
|
msgid "quantity"
|
||||||
msgstr "quantité"
|
msgstr "quantité"
|
||||||
|
|
||||||
#: counter/models.py:690
|
#: counter/models.py:694
|
||||||
msgid "Sith account"
|
msgid "Sith account"
|
||||||
msgstr "Compte utilisateur"
|
msgstr "Compte utilisateur"
|
||||||
|
|
||||||
#: counter/models.py:690 sith/settings.py:405 sith/settings.py:410
|
#: counter/models.py:694 sith/settings.py:405 sith/settings.py:410
|
||||||
#: sith/settings.py:430
|
#: sith/settings.py:430
|
||||||
msgid "Credit card"
|
msgid "Credit card"
|
||||||
msgstr "Carte bancaire"
|
msgstr "Carte bancaire"
|
||||||
|
|
||||||
#: counter/models.py:696
|
#: counter/models.py:700
|
||||||
msgid "selling"
|
msgid "selling"
|
||||||
msgstr "vente"
|
msgstr "vente"
|
||||||
|
|
||||||
#: counter/models.py:800
|
#: counter/models.py:804
|
||||||
msgid "Unknown event"
|
msgid "Unknown event"
|
||||||
msgstr "Événement inconnu"
|
msgstr "Événement inconnu"
|
||||||
|
|
||||||
#: counter/models.py:801
|
#: counter/models.py:805
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Eticket bought for the event %(event)s"
|
msgid "Eticket bought for the event %(event)s"
|
||||||
msgstr "Eticket acheté pour l'événement %(event)s"
|
msgstr "Eticket acheté pour l'événement %(event)s"
|
||||||
|
|
||||||
#: counter/models.py:803 counter/models.py:826
|
#: counter/models.py:807 counter/models.py:830
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"You bought an eticket for the event %(event)s.\n"
|
"You bought an eticket for the event %(event)s.\n"
|
||||||
@ -3908,63 +3908,63 @@ msgstr ""
|
|||||||
"Vous pouvez également retrouver tous vos e-tickets sur votre page de compte "
|
"Vous pouvez également retrouver tous vos e-tickets sur votre page de compte "
|
||||||
"%(url)s."
|
"%(url)s."
|
||||||
|
|
||||||
#: counter/models.py:862
|
#: counter/models.py:866
|
||||||
msgid "last activity date"
|
msgid "last activity date"
|
||||||
msgstr "dernière activité"
|
msgstr "dernière activité"
|
||||||
|
|
||||||
#: counter/models.py:865
|
#: counter/models.py:869
|
||||||
msgid "permanency"
|
msgid "permanency"
|
||||||
msgstr "permanence"
|
msgstr "permanence"
|
||||||
|
|
||||||
#: counter/models.py:898
|
#: counter/models.py:902
|
||||||
msgid "emptied"
|
msgid "emptied"
|
||||||
msgstr "coffre vidée"
|
msgstr "coffre vidée"
|
||||||
|
|
||||||
#: counter/models.py:901
|
#: counter/models.py:905
|
||||||
msgid "cash register summary"
|
msgid "cash register summary"
|
||||||
msgstr "relevé de caisse"
|
msgstr "relevé de caisse"
|
||||||
|
|
||||||
#: counter/models.py:969
|
#: counter/models.py:973
|
||||||
msgid "cash summary"
|
msgid "cash summary"
|
||||||
msgstr "relevé"
|
msgstr "relevé"
|
||||||
|
|
||||||
#: counter/models.py:972
|
#: counter/models.py:976
|
||||||
msgid "value"
|
msgid "value"
|
||||||
msgstr "valeur"
|
msgstr "valeur"
|
||||||
|
|
||||||
#: counter/models.py:975
|
#: counter/models.py:979
|
||||||
msgid "check"
|
msgid "check"
|
||||||
msgstr "chèque"
|
msgstr "chèque"
|
||||||
|
|
||||||
#: counter/models.py:977
|
#: counter/models.py:981
|
||||||
msgid "True if this is a bank check, else False"
|
msgid "True if this is a bank check, else False"
|
||||||
msgstr "Vrai si c'est un chèque, sinon Faux."
|
msgstr "Vrai si c'est un chèque, sinon Faux."
|
||||||
|
|
||||||
#: counter/models.py:981
|
#: counter/models.py:985
|
||||||
msgid "cash register summary item"
|
msgid "cash register summary item"
|
||||||
msgstr "élément de relevé de caisse"
|
msgstr "élément de relevé de caisse"
|
||||||
|
|
||||||
#: counter/models.py:997
|
#: counter/models.py:1001
|
||||||
msgid "banner"
|
msgid "banner"
|
||||||
msgstr "bannière"
|
msgstr "bannière"
|
||||||
|
|
||||||
#: counter/models.py:999
|
#: counter/models.py:1003
|
||||||
msgid "event date"
|
msgid "event date"
|
||||||
msgstr "date de l'événement"
|
msgstr "date de l'événement"
|
||||||
|
|
||||||
#: counter/models.py:1001
|
#: counter/models.py:1005
|
||||||
msgid "event title"
|
msgid "event title"
|
||||||
msgstr "titre de l'événement"
|
msgstr "titre de l'événement"
|
||||||
|
|
||||||
#: counter/models.py:1003
|
#: counter/models.py:1007
|
||||||
msgid "secret"
|
msgid "secret"
|
||||||
msgstr "secret"
|
msgstr "secret"
|
||||||
|
|
||||||
#: counter/models.py:1042
|
#: counter/models.py:1046
|
||||||
msgid "uid"
|
msgid "uid"
|
||||||
msgstr "uid"
|
msgstr "uid"
|
||||||
|
|
||||||
#: counter/models.py:1047
|
#: counter/models.py:1051
|
||||||
msgid "student cards"
|
msgid "student cards"
|
||||||
msgstr "cartes étudiante"
|
msgstr "cartes étudiante"
|
||||||
|
|
||||||
@ -4439,7 +4439,7 @@ msgstr "Solde restant : "
|
|||||||
msgid "Billing information"
|
msgid "Billing information"
|
||||||
msgstr "Informations de facturation"
|
msgstr "Informations de facturation"
|
||||||
|
|
||||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:104
|
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:103
|
||||||
msgid ""
|
msgid ""
|
||||||
"You must fill your billing infos if you want to pay with your credit\n"
|
"You must fill your billing infos if you want to pay with your credit\n"
|
||||||
" card"
|
" card"
|
||||||
@ -4447,32 +4447,50 @@ msgstr ""
|
|||||||
"Vous devez renseigner vos coordonnées de facturation si vous voulez payer "
|
"Vous devez renseigner vos coordonnées de facturation si vous voulez payer "
|
||||||
"par carte bancaire"
|
"par carte bancaire"
|
||||||
|
|
||||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:117
|
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:108
|
||||||
|
msgid ""
|
||||||
|
"\n"
|
||||||
|
" The Crédit Agricole changed its policy related to the "
|
||||||
|
"billing\n"
|
||||||
|
" information that must be provided in order to pay with a "
|
||||||
|
"credit card.\n"
|
||||||
|
" If you want to pay with your credit card, you must add a "
|
||||||
|
"phone number\n"
|
||||||
|
" to the data you already provided.\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
"Le Crédit Agricole a changé sa politique relative aux informations à "
|
||||||
|
"fournir pour effectuer un paiement par carte bancaire. De ce fait, si vous "
|
||||||
|
"souhaitez payer par carte, vous devez rajouter un numéro de téléphone aux "
|
||||||
|
"données que vous aviez déjà fourni."
|
||||||
|
|
||||||
|
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:124
|
||||||
msgid "Pay with credit card"
|
msgid "Pay with credit card"
|
||||||
msgstr "Payer avec une carte bancaire"
|
msgstr "Payer avec une carte bancaire"
|
||||||
|
|
||||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:122
|
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:129
|
||||||
msgid ""
|
msgid ""
|
||||||
"AE account payment disabled because your basket contains refilling items."
|
"AE account payment disabled because your basket contains refilling items."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Paiement par compte AE désactivé parce que votre panier contient des bons de "
|
"Paiement par compte AE désactivé parce que votre panier contient des bons de "
|
||||||
"rechargement."
|
"rechargement."
|
||||||
|
|
||||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:124
|
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:131
|
||||||
msgid ""
|
msgid ""
|
||||||
"AE account payment disabled because you do not have enough money remaining."
|
"AE account payment disabled because you do not have enough money remaining."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Paiement par compte AE désactivé parce que votre solde est insuffisant."
|
"Paiement par compte AE désactivé parce que votre solde est insuffisant."
|
||||||
|
|
||||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:129
|
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:136
|
||||||
msgid "Pay with Sith account"
|
msgid "Pay with Sith account"
|
||||||
msgstr "Payer avec un compte AE"
|
msgstr "Payer avec un compte AE"
|
||||||
|
|
||||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:140
|
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:147
|
||||||
msgid "Billing info registration success"
|
msgid "Billing info registration success"
|
||||||
msgstr "Informations de facturation enregistrées"
|
msgstr "Informations de facturation enregistrées"
|
||||||
|
|
||||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:141
|
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:148
|
||||||
msgid "Billing info registration failure"
|
msgid "Billing info registration failure"
|
||||||
msgstr "Echec de l'enregistrement des informations de facturation."
|
msgstr "Echec de l'enregistrement des informations de facturation."
|
||||||
|
|
||||||
@ -6325,3 +6343,6 @@ msgstr "Vous ne pouvez plus écrire de commentaires, la date est passée."
|
|||||||
#, python-format
|
#, python-format
|
||||||
msgid "Maximum characters: %(max_length)s"
|
msgid "Maximum characters: %(max_length)s"
|
||||||
msgstr "Nombre de caractères max: %(max_length)s"
|
msgstr "Nombre de caractères max: %(max_length)s"
|
||||||
|
|
||||||
|
#~ msgid "captured"
|
||||||
|
#~ msgstr "capturé"
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-09-03 15:22+0200\n"
|
"POT-Creation-Date: 2024-09-27 22:32+0200\n"
|
||||||
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
||||||
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@ -16,9 +16,24 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
#: core/static/user/js/family_graph.js:230
|
|
||||||
|
#: core/static/user/js/family_graph.js:233
|
||||||
msgid "family_tree.%(extension)s"
|
msgid "family_tree.%(extension)s"
|
||||||
msgstr "arbre_genealogique.%(extension)s"
|
msgstr "arbre_genealogique.%(extension)s"
|
||||||
#: sas/static/sas/js/picture.js:52
|
|
||||||
|
#: core/static/user/js/user_edit.js:93
|
||||||
|
#, javascript-format
|
||||||
|
msgid "captured.%s"
|
||||||
|
msgstr "capture.%s"
|
||||||
|
|
||||||
|
#: eboutic/static/eboutic/js/makecommand.js:50
|
||||||
|
msgid "Incorrect value"
|
||||||
|
msgstr "Valeur incorrecte"
|
||||||
|
|
||||||
|
#: sas/static/sas/js/viewer.js:196
|
||||||
|
msgid "Couldn't moderate picture"
|
||||||
|
msgstr "Echec de la suppression de la photo"
|
||||||
|
|
||||||
|
#: sas/static/sas/js/viewer.js:209
|
||||||
msgid "Couldn't delete picture"
|
msgid "Couldn't delete picture"
|
||||||
msgstr "Echec de la suppression de la photo"
|
msgstr "Echec de la suppression de la photo"
|
||||||
|
29
poetry.lock
generated
29
poetry.lock
generated
@ -1813,6 +1813,33 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic-extra-types"
|
||||||
|
version = "2.9.0"
|
||||||
|
description = "Extra Pydantic types."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = []
|
||||||
|
develop = false
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
pydantic = ">=2.5.2"
|
||||||
|
typing-extensions = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["pendulum (>=3.0.0,<4.0.0)", "phonenumbers (>=8,<9)", "pycountry (>=23)", "python-ulid (>=1,<2)", "python-ulid (>=1,<3)", "pytz (>=2024.1)", "semver (>=3.0.2)", "semver (>=3.0.2,<3.1.0)", "tzdata (>=2024.1)"]
|
||||||
|
pendulum = ["pendulum (>=3.0.0,<4.0.0)"]
|
||||||
|
phonenumbers = ["phonenumbers (>=8,<9)"]
|
||||||
|
pycountry = ["pycountry (>=23)"]
|
||||||
|
python-ulid = ["python-ulid (>=1,<2)", "python-ulid (>=1,<3)"]
|
||||||
|
semver = ["semver (>=3.0.2)"]
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "git"
|
||||||
|
url = "https://github.com/pydantic/pydantic-extra-types.git"
|
||||||
|
reference = "HEAD"
|
||||||
|
resolved_reference = "58db4b096d7c90566d3d48d51b4665c01a591df6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pygments"
|
name = "pygments"
|
||||||
version = "2.18.0"
|
version = "2.18.0"
|
||||||
@ -2626,4 +2653,4 @@ filelock = ">=3.4"
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.12"
|
||||||
content-hash = "b6202203d272cecdb607ea8ebc1ba12dd8369e4f387f65692c4a9681915e6f48"
|
content-hash = "c9c49497cc576b24c96ea914b74ef5c3a0c2981c488a599752f05aabb575f8d8"
|
||||||
|
@ -45,6 +45,10 @@ dict2xml = "^1.7.3"
|
|||||||
Sphinx = "^5" # Needed for building xapian
|
Sphinx = "^5" # Needed for building xapian
|
||||||
tomli = "^2.0.1"
|
tomli = "^2.0.1"
|
||||||
django-honeypot = "^1.2.1"
|
django-honeypot = "^1.2.1"
|
||||||
|
# When I introduced pydantic-extra-types, I needed *right now*
|
||||||
|
# the PhoneNumberValidator class which was on the master branch but not released yet.
|
||||||
|
# Once it's released, switch this to a regular version.
|
||||||
|
pydantic-extra-types = { git = "https://github.com/pydantic/pydantic-extra-types.git", rev = "58db4b0" }
|
||||||
|
|
||||||
[tool.poetry.group.prod.dependencies]
|
[tool.poetry.group.prod.dependencies]
|
||||||
# deps used in prod, but unnecessary for development
|
# deps used in prod, but unnecessary for development
|
||||||
|
Loading…
Reference in New Issue
Block a user