Make ProductType an OrderedModel

This commit is contained in:
imperosol 2024-12-15 18:55:09 +01:00
parent 6c8a6008d5
commit 483670e798
8 changed files with 167 additions and 100 deletions

View File

@ -129,7 +129,7 @@ class PermanencyAdmin(SearchModelAdmin):
@admin.register(ProductType) @admin.register(ProductType)
class ProductTypeAdmin(admin.ModelAdmin): class ProductTypeAdmin(admin.ModelAdmin):
list_display = ("name", "priority") list_display = ("name", "order")
@admin.register(CashRegisterSummary) @admin.register(CashRegisterSummary)

View File

@ -71,7 +71,7 @@ class ProductController(ControllerBase):
def search_products(self, filters: Query[ProductFilterSchema]): def search_products(self, filters: Query[ProductFilterSchema]):
return filters.filter( return filters.filter(
Product.objects.order_by( Product.objects.order_by(
F("product_type__priority").desc(nulls_last=True), F("product_type__order").asc(nulls_last=True),
"product_type", "product_type",
"name", "name",
).values() ).values()
@ -95,7 +95,7 @@ class ProductController(ControllerBase):
.prefetch_related("buying_groups") .prefetch_related("buying_groups")
.select_related("product_type") .select_related("product_type")
.order_by( .order_by(
F("product_type__priority").desc(nulls_last=True), F("product_type__order").asc(nulls_last=True),
"product_type", "product_type",
"name", "name",
) )

View File

@ -0,0 +1,62 @@
# Generated by Django 4.2.17 on 2024-12-15 17:53
from django.db import migrations, models
from django.db.migrations.state import StateApps
def move_priority_to_order(apps: StateApps, schema_editor):
"""Migrate the previous homemade `priority` to `OrderedModel.order`.
`priority` was a system were click managers set themselves the priority
of a ProductType.
The higher the priority, the higher it was to be displayed in the eboutic.
Multiple product types could share the same priority, in which
case they were ordered by alphabetic order.
The new field is unique per object, and works in the other way :
the nearer from 0, the higher it should appear.
"""
ProductType = apps.get_model("counter", "ProductType")
product_types = list(ProductType.objects.order_by("-priority", "name"))
for order, product_type in enumerate(product_types):
product_type.order = order
ProductType.objects.bulk_update(product_types, ["order"])
class Migration(migrations.Migration):
dependencies = [("counter", "0027_alter_refilling_payment_method")]
operations = [
migrations.AlterField(
model_name="producttype",
name="comment",
field=models.TextField(
default="",
help_text="A text that will be shown on the eboutic.",
verbose_name="comment",
),
),
migrations.AlterField(
model_name="producttype",
name="description",
field=models.TextField(default="", verbose_name="description"),
),
migrations.AlterModelOptions(
name="producttype",
options={"ordering": ["order"], "verbose_name": "product type"},
),
migrations.AddField(
model_name="producttype",
name="order",
field=models.PositiveIntegerField(
db_index=True, default=0, editable=False, verbose_name="order"
),
preserve_default=False,
),
migrations.RunPython(
move_priority_to_order,
reverse_code=migrations.RunPython.noop,
elidable=True,
),
migrations.RemoveField(model_name="producttype", name="priority"),
]

View File

@ -35,6 +35,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 ordered_model.models import OrderedModel
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
from accounting.models import CurrencyField from accounting.models import CurrencyField
@ -289,26 +290,26 @@ class AccountDump(models.Model):
) )
class ProductType(models.Model): class ProductType(OrderedModel):
"""A product type. """A product type.
Useful only for categorizing. Useful only for categorizing.
""" """
name = models.CharField(_("name"), max_length=30) name = models.CharField(_("name"), max_length=30)
description = models.TextField(_("description"), null=True, blank=True) description = models.TextField(_("description"), default="")
comment = models.TextField(_("comment"), null=True, blank=True) comment = models.TextField(
_("comment"),
default="",
help_text=_("A text that will be shown on the eboutic."),
)
icon = ResizedImageField( icon = ResizedImageField(
height=70, force_format="WEBP", upload_to="products", null=True, blank=True height=70, force_format="WEBP", upload_to="products", null=True, blank=True
) )
# priority holds no real backend logic but helps to handle the order in which
# the items are to be shown to the user
priority = models.PositiveIntegerField(default=0)
class Meta: class Meta:
verbose_name = _("product type") verbose_name = _("product type")
ordering = ["-priority", "name"] ordering = ["order"]
def __str__(self): def __str__(self):
return self.name return self.name

View File

@ -109,7 +109,7 @@ class ProductTypeCreateView(CounterAdminTabsMixin, CounterAdminMixin, CreateView
"""A create view for the admins.""" """A create view for the admins."""
model = ProductType model = ProductType
fields = ["name", "description", "comment", "icon", "priority"] fields = ["name", "description", "comment", "icon"]
template_name = "core/create.jinja" template_name = "core/create.jinja"
current_tab = "products" current_tab = "products"
@ -119,7 +119,7 @@ class ProductTypeEditView(CounterAdminTabsMixin, CounterAdminMixin, UpdateView):
model = ProductType model = ProductType
template_name = "core/edit.jinja" template_name = "core/edit.jinja"
fields = ["name", "description", "comment", "icon", "priority"] fields = ["name", "description", "comment", "icon"]
pk_url_kwarg = "type_id" pk_url_kwarg = "type_id"
current_tab = "products" current_tab = "products"
@ -129,7 +129,7 @@ class ProductListView(CounterAdminTabsMixin, CounterAdminMixin, ListView):
queryset = Product.objects.values("id", "name", "code", "product_type__name") queryset = Product.objects.values("id", "name", "code", "product_type__name")
template_name = "counter/product_list.jinja" template_name = "counter/product_list.jinja"
ordering = [ ordering = [
F("product_type__priority").desc(nulls_last=True), F("product_type__order").asc(nulls_last=True),
"product_type", "product_type",
"name", "name",
] ]

View File

@ -36,7 +36,7 @@ def get_eboutic_products(user: User) -> list[Product]:
.products.filter(product_type__isnull=False) .products.filter(product_type__isnull=False)
.filter(archived=False) .filter(archived=False)
.filter(limit_age__lte=user.age) .filter(limit_age__lte=user.age)
.annotate(priority=F("product_type__priority")) .annotate(order=F("product_type__order"))
.annotate(category=F("product_type__name")) .annotate(category=F("product_type__name"))
.annotate(category_comment=F("product_type__comment")) .annotate(category_comment=F("product_type__comment"))
.prefetch_related("buying_groups") # <-- used in `Product.can_be_sold_to` .prefetch_related("buying_groups") # <-- used in `Product.can_be_sold_to`

View File

@ -88,7 +88,7 @@
</div> </div>
{% endif %} {% endif %}
{% for priority_groups in products|groupby('priority')|reverse %} {% for priority_groups in products|groupby('order') %}
{% for category, items in priority_groups.list|groupby('category') %} {% for category, items in priority_groups.list|groupby('category') %}
{% if items|count > 0 %} {% if items|count > 0 %}
<section> <section>

View File

@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-17 10:53+0100\n" "POT-Creation-Date: 2024-12-17 13:09+0100\n"
"PO-Revision-Date: 2016-07-18\n" "PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n" "Last-Translator: Maréchal <thomas.girod@utbm.fr\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:101 accounting/models.py:132 #: accounting/models.py:62 accounting/models.py:101 accounting/models.py:132
#: accounting/models.py:190 club/models.py:55 com/models.py:274 #: accounting/models.py:190 club/models.py:55 com/models.py:274
#: com/models.py:293 counter/models.py:298 counter/models.py:329 #: com/models.py:293 counter/models.py:299 counter/models.py:330
#: counter/models.py:480 forum/models.py:60 launderette/models.py:29 #: counter/models.py:481 forum/models.py:60 launderette/models.py:29
#: launderette/models.py:80 launderette/models.py:116 #: launderette/models.py:80 launderette/models.py:116
msgid "name" msgid "name"
msgstr "nom" msgstr "nom"
@ -65,8 +65,8 @@ msgid "account number"
msgstr "numéro de compte" msgstr "numéro de compte"
#: accounting/models.py:107 accounting/models.py:136 club/models.py:345 #: accounting/models.py:107 accounting/models.py:136 club/models.py:345
#: com/models.py:74 com/models.py:259 com/models.py:299 counter/models.py:358 #: com/models.py:74 com/models.py:259 com/models.py:299 counter/models.py:359
#: counter/models.py:482 trombi/models.py:209 #: counter/models.py:483 trombi/models.py:209
msgid "club" msgid "club"
msgstr "club" msgstr "club"
@ -87,12 +87,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:188 club/models.py:351 counter/models.py:965 #: accounting/models.py:188 club/models.py:351 counter/models.py:966
#: election/models.py:16 launderette/models.py:165 #: election/models.py:16 launderette/models.py:165
msgid "start date" msgid "start date"
msgstr "date de début" msgstr "date de début"
#: accounting/models.py:189 club/models.py:352 counter/models.py:966 #: accounting/models.py:189 club/models.py:352 counter/models.py:967
#: election/models.py:17 #: election/models.py:17
msgid "end date" msgid "end date"
msgstr "date de fin" msgstr "date de fin"
@ -105,8 +105,8 @@ msgstr "est fermé"
msgid "club account" msgid "club account"
msgstr "compte club" msgstr "compte club"
#: accounting/models.py:199 accounting/models.py:255 counter/models.py:92 #: accounting/models.py:199 accounting/models.py:255 counter/models.py:93
#: counter/models.py:683 #: counter/models.py:684
msgid "amount" msgid "amount"
msgstr "montant" msgstr "montant"
@ -128,18 +128,18 @@ msgstr "classeur"
#: accounting/models.py:256 core/models.py:956 core/models.py:1467 #: accounting/models.py:256 core/models.py:956 core/models.py:1467
#: core/models.py:1512 core/models.py:1541 core/models.py:1565 #: core/models.py:1512 core/models.py:1541 core/models.py:1565
#: counter/models.py:693 counter/models.py:797 counter/models.py:1001 #: counter/models.py:694 counter/models.py:798 counter/models.py:1002
#: eboutic/models.py:57 eboutic/models.py:193 forum/models.py:312 #: eboutic/models.py:57 eboutic/models.py:193 forum/models.py:312
#: forum/models.py:413 #: forum/models.py:413
msgid "date" msgid "date"
msgstr "date" msgstr "date"
#: accounting/models.py:257 counter/models.py:300 counter/models.py:1002 #: accounting/models.py:257 counter/models.py:302 counter/models.py:1003
#: pedagogy/models.py:208 #: pedagogy/models.py:208
msgid "comment" msgid "comment"
msgstr "commentaire" msgstr "commentaire"
#: accounting/models.py:259 counter/models.py:695 counter/models.py:799 #: accounting/models.py:259 counter/models.py:696 counter/models.py:800
#: 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,7 +166,7 @@ msgstr "type comptable"
#: accounting/models.py:294 accounting/models.py:429 accounting/models.py:460 #: accounting/models.py:294 accounting/models.py:429 accounting/models.py:460
#: accounting/models.py:492 core/models.py:1540 core/models.py:1566 #: accounting/models.py:492 core/models.py:1540 core/models.py:1566
#: counter/models.py:763 #: counter/models.py:764
msgid "label" msgid "label"
msgstr "étiquette" msgstr "étiquette"
@ -264,7 +264,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:421 counter/models.py:339 pedagogy/models.py:41 #: accounting/models.py:421 counter/models.py:340 pedagogy/models.py:41
msgid "code" msgid "code"
msgstr "code" msgstr "code"
@ -1041,7 +1041,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:337 counter/models.py:956 counter/models.py:992 #: club/models.py:337 counter/models.py:957 counter/models.py:993
#: eboutic/models.py:53 eboutic/models.py:189 election/models.py:183 #: eboutic/models.py:53 eboutic/models.py:189 election/models.py:183
#: launderette/models.py:130 launderette/models.py:184 sas/models.py:273 #: launderette/models.py:130 launderette/models.py:184 sas/models.py:273
#: trombi/models.py:205 #: trombi/models.py:205
@ -1053,8 +1053,8 @@ msgstr "nom d'utilisateur"
msgid "role" msgid "role"
msgstr "rôle" msgstr "rôle"
#: club/models.py:359 core/models.py:90 counter/models.py:299 #: club/models.py:359 core/models.py:90 counter/models.py:300
#: counter/models.py:330 election/models.py:13 election/models.py:115 #: counter/models.py:331 election/models.py:13 election/models.py:115
#: election/models.py:188 forum/models.py:61 forum/models.py:245 #: election/models.py:188 forum/models.py:61 forum/models.py:245
msgid "description" msgid "description"
msgstr "description" msgstr "description"
@ -2501,7 +2501,7 @@ msgstr "Forum"
msgid "Gallery" msgid "Gallery"
msgstr "Photos" msgstr "Photos"
#: core/templates/core/base/navbar.jinja:22 counter/models.py:490 #: core/templates/core/base/navbar.jinja:22 counter/models.py:491
#: 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
@ -3607,13 +3607,13 @@ msgstr "Chèque"
msgid "Cash" msgid "Cash"
msgstr "Espèces" msgstr "Espèces"
#: counter/apps.py:30 counter/models.py:801 sith/settings.py:415 #: counter/apps.py:30 counter/models.py:802 sith/settings.py:415
#: sith/settings.py:420 #: sith/settings.py:420
msgid "Credit card" msgid "Credit card"
msgstr "Carte bancaire" msgstr "Carte bancaire"
#: counter/apps.py:36 counter/models.py:506 counter/models.py:962 #: counter/apps.py:36 counter/models.py:507 counter/models.py:963
#: counter/models.py:998 launderette/models.py:32 #: counter/models.py:999 launderette/models.py:32
msgid "counter" msgid "counter"
msgstr "comptoir" msgstr "comptoir"
@ -3637,180 +3637,184 @@ msgstr "Vidange de votre compte AE"
msgid "Ecocup regularization" msgid "Ecocup regularization"
msgstr "Régularization des ecocups" msgstr "Régularization des ecocups"
#: counter/models.py:91 #: counter/models.py:92
msgid "account id" msgid "account id"
msgstr "numéro de compte" msgstr "numéro de compte"
#: counter/models.py:93 #: counter/models.py:94
msgid "recorded product" msgid "recorded product"
msgstr "produits consignés" msgstr "produits consignés"
#: counter/models.py:98 #: counter/models.py:99
msgid "customer" msgid "customer"
msgstr "client" msgstr "client"
#: counter/models.py:99 #: counter/models.py:100
msgid "customers" msgid "customers"
msgstr "clients" msgstr "clients"
#: counter/models.py:111 counter/views/click.py:68 #: counter/models.py:112 counter/views/click.py:68
msgid "Not enough money" msgid "Not enough money"
msgstr "Solde insuffisant" msgstr "Solde insuffisant"
#: counter/models.py:197 #: counter/models.py:198
msgid "First name" msgid "First name"
msgstr "Prénom" msgstr "Prénom"
#: counter/models.py:198 #: counter/models.py:199
msgid "Last name" msgid "Last name"
msgstr "Nom de famille" msgstr "Nom de famille"
#: counter/models.py:199 #: counter/models.py:200
msgid "Address 1" msgid "Address 1"
msgstr "Adresse 1" msgstr "Adresse 1"
#: counter/models.py:200 #: counter/models.py:201
msgid "Address 2" msgid "Address 2"
msgstr "Adresse 2" msgstr "Adresse 2"
#: counter/models.py:201 #: counter/models.py:202
msgid "Zip code" msgid "Zip code"
msgstr "Code postal" msgstr "Code postal"
#: counter/models.py:202 #: counter/models.py:203
msgid "City" msgid "City"
msgstr "Ville" msgstr "Ville"
#: counter/models.py:203 #: counter/models.py:204
msgid "Country" msgid "Country"
msgstr "Pays" msgstr "Pays"
#: counter/models.py:211 #: counter/models.py:212
msgid "Phone number" msgid "Phone number"
msgstr "Numéro de téléphone" msgstr "Numéro de téléphone"
#: counter/models.py:253 #: counter/models.py:254
msgid "When the mail warning that the account was about to be dumped was sent." msgid "When the mail warning that the account was about to be dumped was sent."
msgstr "Quand le mail d'avertissement de la vidange du compte a été envoyé." msgstr "Quand le mail d'avertissement de la vidange du compte a été envoyé."
#: counter/models.py:258 #: counter/models.py:259
msgid "Set this to True if the warning mail received an error" msgid "Set this to True if the warning mail received an error"
msgstr "Mettre à True si le mail a reçu une erreur" msgstr "Mettre à True si le mail a reçu une erreur"
#: counter/models.py:265 #: counter/models.py:266
msgid "The operation that emptied the account." msgid "The operation that emptied the account."
msgstr "L'opération qui a vidé le compte." msgstr "L'opération qui a vidé le compte."
#: counter/models.py:310 counter/models.py:334 #: counter/models.py:304
msgid "A text that will be shown on the eboutic."
msgstr "Un texte qui sera affiché sur l'eboutic."
#: counter/models.py:311 counter/models.py:335
msgid "product type" msgid "product type"
msgstr "type du produit" msgstr "type du produit"
#: counter/models.py:341 #: counter/models.py:342
msgid "purchase price" msgid "purchase price"
msgstr "prix d'achat" msgstr "prix d'achat"
#: counter/models.py:342 #: counter/models.py:343
msgid "Initial cost of purchasing the product" msgid "Initial cost of purchasing the product"
msgstr "Coût initial d'achat du produit" msgstr "Coût initial d'achat du produit"
#: counter/models.py:344 #: counter/models.py:345
msgid "selling price" msgid "selling price"
msgstr "prix de vente" msgstr "prix de vente"
#: counter/models.py:346 #: counter/models.py:347
msgid "special selling price" msgid "special selling price"
msgstr "prix de vente spécial" msgstr "prix de vente spécial"
#: counter/models.py:347 #: counter/models.py:348
msgid "Price for barmen during their permanence" msgid "Price for barmen during their permanence"
msgstr "Prix pour les barmen durant leur permanence" msgstr "Prix pour les barmen durant leur permanence"
#: counter/models.py:355 #: counter/models.py:356
msgid "icon" msgid "icon"
msgstr "icône" msgstr "icône"
#: counter/models.py:360 #: counter/models.py:361
msgid "limit age" msgid "limit age"
msgstr "âge limite" msgstr "âge limite"
#: counter/models.py:361 #: counter/models.py:362
msgid "tray price" msgid "tray price"
msgstr "prix plateau" msgstr "prix plateau"
#: counter/models.py:363 #: counter/models.py:364
msgid "buying groups" msgid "buying groups"
msgstr "groupe d'achat" msgstr "groupe d'achat"
#: counter/models.py:365 election/models.py:50 #: counter/models.py:366 election/models.py:50
msgid "archived" msgid "archived"
msgstr "archivé" msgstr "archivé"
#: counter/models.py:368 counter/models.py:1096 #: counter/models.py:369 counter/models.py:1097
msgid "product" msgid "product"
msgstr "produit" msgstr "produit"
#: counter/models.py:485 #: counter/models.py:486
msgid "products" msgid "products"
msgstr "produits" msgstr "produits"
#: counter/models.py:488 #: counter/models.py:489
msgid "counter type" msgid "counter type"
msgstr "type de comptoir" msgstr "type de comptoir"
#: counter/models.py:490 #: counter/models.py:491
msgid "Bar" msgid "Bar"
msgstr "Bar" msgstr "Bar"
#: counter/models.py:490 #: counter/models.py:491
msgid "Office" msgid "Office"
msgstr "Bureau" msgstr "Bureau"
#: counter/models.py:493 #: counter/models.py:494
msgid "sellers" msgid "sellers"
msgstr "vendeurs" msgstr "vendeurs"
#: counter/models.py:501 launderette/models.py:178 #: counter/models.py:502 launderette/models.py:178
msgid "token" msgid "token"
msgstr "jeton" msgstr "jeton"
#: counter/models.py:701 #: counter/models.py:702
msgid "bank" msgid "bank"
msgstr "banque" msgstr "banque"
#: counter/models.py:703 counter/models.py:804 #: counter/models.py:704 counter/models.py:805
msgid "is validated" msgid "is validated"
msgstr "est validé" msgstr "est validé"
#: counter/models.py:708 #: counter/models.py:709
msgid "refilling" msgid "refilling"
msgstr "rechargement" msgstr "rechargement"
#: counter/models.py:781 eboutic/models.py:249 #: counter/models.py:782 eboutic/models.py:249
msgid "unit price" msgid "unit price"
msgstr "prix unitaire" msgstr "prix unitaire"
#: counter/models.py:782 counter/models.py:1076 eboutic/models.py:250 #: counter/models.py:783 counter/models.py:1077 eboutic/models.py:250
msgid "quantity" msgid "quantity"
msgstr "quantité" msgstr "quantité"
#: counter/models.py:801 #: counter/models.py:802
msgid "Sith account" msgid "Sith account"
msgstr "Compte utilisateur" msgstr "Compte utilisateur"
#: counter/models.py:809 #: counter/models.py:810
msgid "selling" msgid "selling"
msgstr "vente" msgstr "vente"
#: counter/models.py:913 #: counter/models.py:914
msgid "Unknown event" msgid "Unknown event"
msgstr "Événement inconnu" msgstr "Événement inconnu"
#: counter/models.py:914 #: counter/models.py:915
#, 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:916 counter/models.py:929 #: counter/models.py:917 counter/models.py:930
#, 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"
@ -3822,67 +3826,67 @@ 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:967 #: counter/models.py:968
msgid "last activity date" msgid "last activity date"
msgstr "dernière activité" msgstr "dernière activité"
#: counter/models.py:970 #: counter/models.py:971
msgid "permanency" msgid "permanency"
msgstr "permanence" msgstr "permanence"
#: counter/models.py:1003 #: counter/models.py:1004
msgid "emptied" msgid "emptied"
msgstr "coffre vidée" msgstr "coffre vidée"
#: counter/models.py:1006 #: counter/models.py:1007
msgid "cash register summary" msgid "cash register summary"
msgstr "relevé de caisse" msgstr "relevé de caisse"
#: counter/models.py:1072 #: counter/models.py:1073
msgid "cash summary" msgid "cash summary"
msgstr "relevé" msgstr "relevé"
#: counter/models.py:1075 #: counter/models.py:1076
msgid "value" msgid "value"
msgstr "valeur" msgstr "valeur"
#: counter/models.py:1078 #: counter/models.py:1079
msgid "check" msgid "check"
msgstr "chèque" msgstr "chèque"
#: counter/models.py:1080 #: counter/models.py:1081
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:1084 #: counter/models.py:1085
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:1100 #: counter/models.py:1101
msgid "banner" msgid "banner"
msgstr "bannière" msgstr "bannière"
#: counter/models.py:1102 #: counter/models.py:1103
msgid "event date" msgid "event date"
msgstr "date de l'événement" msgstr "date de l'événement"
#: counter/models.py:1104 #: counter/models.py:1105
msgid "event title" msgid "event title"
msgstr "titre de l'événement" msgstr "titre de l'événement"
#: counter/models.py:1106 #: counter/models.py:1107
msgid "secret" msgid "secret"
msgstr "secret" msgstr "secret"
#: counter/models.py:1145 #: counter/models.py:1146
msgid "uid" msgid "uid"
msgstr "uid" msgstr "uid"
#: counter/models.py:1150 counter/models.py:1155 #: counter/models.py:1151 counter/models.py:1156
msgid "student card" msgid "student card"
msgstr "carte étudiante" msgstr "carte étudiante"
#: counter/models.py:1156 #: counter/models.py:1157
msgid "student cards" msgid "student cards"
msgstr "cartes étudiantes" msgstr "cartes étudiantes"
@ -4194,15 +4198,15 @@ msgid "There is no products in this website."
msgstr "Il n'y a pas de produits dans ce site web." msgstr "Il n'y a pas de produits dans ce site web."
#: counter/templates/counter/producttype_list.jinja:4 #: counter/templates/counter/producttype_list.jinja:4
#: counter/templates/counter/producttype_list.jinja:10 #: counter/templates/counter/producttype_list.jinja:26
msgid "Product type list" msgid "Product type list"
msgstr "Liste des types de produit" msgstr "Liste des types de produit"
#: counter/templates/counter/producttype_list.jinja:8 #: counter/templates/counter/producttype_list.jinja:16
msgid "New product type" msgid "New product type"
msgstr "Nouveau type de produit" msgstr "Nouveau type de produit"
#: counter/templates/counter/producttype_list.jinja:17 #: counter/templates/counter/producttype_list.jinja:42
msgid "There is no product types in this website." msgid "There is no product types in this website."
msgstr "Il n'y a pas de types de produit dans ce site web." msgstr "Il n'y a pas de types de produit dans ce site web."