remove stock application

This commit is contained in:
thomas girod 2024-09-18 14:49:40 +02:00 committed by imperosol
parent 6f4e93bb76
commit 12bb7e9294
20 changed files with 156 additions and 1467 deletions

View File

@ -70,15 +70,7 @@
<span>
<a class="button" href="{{ url('counter:admin', counter_id=b[0]) }}">{% trans %}Edit{% endtrans %}</a>
<a class="button" href="{{ url('counter:stats', counter_id=b[0]) }}">{% trans %}Stats{% endtrans %}</a>
{% if c.stock %}
<a class="button" href="{{ url('stock:items_list', stock_id=c.stock.id)}}">Stock</a>
{% endif %}
</span>
{% if c.stock %}
<a class="button" href="{{ url('stock:shoppinglist_list', stock_id=c.stock.id)}}">{% trans %}Shopping lists{% endtrans %}</a>
{% else %}
<a class="button" href="{{url('stock:new', counter_id=c.id)}}">{% trans %}Create new stock{% endtrans%}</a>
{% endif %}
</span>
</li>
{% endif %}

View File

@ -33,12 +33,6 @@
<a href="{{ url('counter:admin', counter_id=c.id) }}">{% trans %}Edit{% endtrans %}</a> -
<a href="{{ url('counter:stats', counter_id=c.id) }}">{% trans %}Stats{% endtrans %}</a> -
{% endif %}
{% if c.stock %}
<a href="{{ url('stock:items_list', stock_id=c.stock.id)}}">Stock</a> -
<a href="{{ url('stock:shoppinglist_list', stock_id=c.stock.id)}}">{% trans %}Shopping lists{% endtrans %}</a> -
{% else %}
<a href="{{url('stock:new', counter_id=c.id)}}">{% trans %}Create new stock{% endtrans%}</a> -
{% endif %}
{% if user.is_owner(c) %}
<a href="{{ url('counter:prop_admin', counter_id=c.id) }}">{% trans %}Props{% endtrans %}</a> -
<a href="{{ url('counter:refilling_list', counter_id=c.id) }}">{% trans %}Reloads list{% endtrans %}</a>

View File

@ -126,45 +126,23 @@ class StudentCardDeleteView(DeleteView, CanEditMixin):
class CounterTabsMixin(TabedViewMixin):
def get_tabs_title(self):
if hasattr(self.object, "stock_owner"):
return self.object.stock_owner.counter
else:
return self.object
return self.object
def get_list_of_tabs(self):
tab_list = []
tab_list.append(
tab_list = [
{
"url": reverse_lazy(
"counter:details",
kwargs={
"counter_id": (
self.object.stock_owner.counter.id
if hasattr(self.object, "stock_owner")
else self.object.id
)
},
"counter:details", kwargs={"counter_id": self.object.id}
),
"slug": "counter",
"name": _("Counter"),
}
)
if (
self.object.stock_owner.counter.type
if hasattr(self.object, "stock_owner")
else self.object.type == "BAR"
):
]
if self.object.type == "BAR":
tab_list.append(
{
"url": reverse_lazy(
"counter:cash_summary",
kwargs={
"counter_id": (
self.object.stock_owner.counter.id
if hasattr(self.object, "stock_owner")
else self.object.id
)
},
"counter:cash_summary", kwargs={"counter_id": self.object.id}
),
"slug": "cash_summary",
"name": _("Cash summary"),
@ -173,38 +151,12 @@ class CounterTabsMixin(TabedViewMixin):
tab_list.append(
{
"url": reverse_lazy(
"counter:last_ops",
kwargs={
"counter_id": (
self.object.stock_owner.counter.id
if hasattr(self.object, "stock_owner")
else self.object.id
)
},
"counter:last_ops", kwargs={"counter_id": self.object.id}
),
"slug": "last_ops",
"name": _("Last operations"),
}
)
try:
tab_list.append(
{
"url": reverse_lazy(
"stock:take_items",
kwargs={
"stock_id": (
self.object.stock.id
if hasattr(self.object, "stock")
else self.object.stock_owner.id
)
},
),
"slug": "take_items_from_stock",
"name": _("Take items from stock"),
}
)
except:
pass # The counter just have no stock
return tab_list
@ -721,7 +673,6 @@ def counter_logout(request: HttpRequest, counter_id: int) -> HttpResponseRedirec
class CounterAdminTabsMixin(TabedViewMixin):
tabs_title = _("Counter administration")
list_of_tabs = [
{"url": reverse_lazy("stock:list"), "slug": "stocks", "name": _("Stocks")},
{
"url": reverse_lazy("counter:admin_list"),
"slug": "counters",

View File

@ -58,27 +58,25 @@ sith/
│ └── ...
├── sith/ (19)
│ └── ...
├── stock/ (20)
├── subscription/ (20)
│ └── ...
├── subscription/ (21)
├── trombi/ (21)
│ └── ...
├── trombi/ (22)
├── antispam/ (22)
│ └── ...
├── antispam/ (23)
│ └── ...
├── staticfiles/ (24)
├── staticfiles/ (23)
│ └── ...
├── .coveragerc (25)
├── .envrc (26)
├── .coveragerc (24)
├── .envrc (25)
├── .gitattributes
├── .gitignore
├── .mailmap
├── .env.exemple
├── manage.py (27)
├── mkdocs.yml (28)
├── manage.py (26)
├── mkdocs.yml (27)
├── poetry.lock
├── pyproject.toml (29)
├── pyproject.toml (28)
└── README.md
```
</div>
@ -113,22 +111,21 @@ sith/
peuvent également laisser leurs avis.
17. Fonctionnalités utiles aux utilisateurs root.
18. Le SAS, où l'on trouve toutes les photos de l'AE.
19. Application principale du projet, contenant sa configuration.
20. Gestion des stocks des comptoirs.
21. Gestion des cotisations des utilisateurs du site.
22. Outil pour faciliter la fabrication des trombinoscopes de promo.
23. Fonctionnalités pour gérer le spam.
24. Gestion des statics du site. Override le système de statics de Django.
19. Application principale du projet, contenant sa configuration.
20. Gestion des cotisations des utilisateurs du site.
21. Outil pour faciliter la fabrication des trombinoscopes de promo.
22. Fonctionnalités pour gérer le spam.
23. Gestion des statics du site. Override le système de statics de Django.
Ajoute l'intégration du scss et de webpack
de manière transparente pour l'utilisateur.
25. Fichier de configuration de coverage.
26. Fichier de configuration de direnv.
27. Fichier généré automatiquement par Django. C'est lui
de manière transparente pour l'utilisateur.
24. Fichier de configuration de coverage.
25. Fichier de configuration de direnv.
26. Fichier généré automatiquement par Django. C'est lui
qui permet d'appeler des commandes de gestion du projet
avec la syntaxe `python ./manage.py <nom de la commande>`
28. Le fichier de configuration de la documentation,
avec ses plugins et sa table des matières.
29. Le fichier où sont déclarés les dépendances et la configuration
27. Le fichier de configuration de la documentation,
avec ses plugins et sa table des matières.
28. Le fichier où sont déclarés les dépendances et la configuration
de certaines d'entre elles.

View File

@ -20,8 +20,7 @@ msgstr ""
#: accounting/models.py:203 club/models.py:55 com/models.py:274
#: com/models.py:293 counter/models.py:220 counter/models.py:253
#: counter/models.py:388 forum/models.py:59 launderette/models.py:29
#: launderette/models.py:84 launderette/models.py:122 stock/models.py:36
#: stock/models.py:57 stock/models.py:97 stock/models.py:125
#: launderette/models.py:84 launderette/models.py:122
msgid "name"
msgstr "nom"
@ -131,12 +130,12 @@ msgstr "classeur"
#: core/models.py:1505 core/models.py:1534 core/models.py:1558
#: counter/models.py:621 counter/models.py:725 counter/models.py:937
#: eboutic/models.py:57 eboutic/models.py:189 forum/models.py:311
#: forum/models.py:412 stock/models.py:96
#: forum/models.py:412
msgid "date"
msgstr "date"
#: accounting/models.py:274 counter/models.py:222 counter/models.py:938
#: pedagogy/models.py:207 stock/models.py:99
#: pedagogy/models.py:207
msgid "comment"
msgstr "commentaire"
@ -220,7 +219,6 @@ msgid "Company"
msgstr "Entreprise"
#: accounting/models.py:324 core/models.py:312 sith/settings.py:411
#: stock/templates/stock/shopping_list_items.jinja:37
msgid "Other"
msgstr "Autre"
@ -317,7 +315,7 @@ msgstr "Liste des types comptable"
#: accounting/templates/accounting/label_list.jinja:10
#: accounting/templates/accounting/operation_edit.jinja:10
#: accounting/templates/accounting/simplifiedaccountingtype_list.jinja:10
#: core/templates/core/user_tools.jinja:96
#: core/templates/core/user_tools.jinja:88
msgid "Accounting"
msgstr "Comptabilité"
@ -336,7 +334,7 @@ msgstr "Il n'y a pas de types comptable dans ce site web."
#: accounting/templates/accounting/bank_account_details.jinja:4
#: accounting/templates/accounting/bank_account_details.jinja:14
#: core/templates/core/user_tools.jinja:109
#: core/templates/core/user_tools.jinja:101
msgid "Bank account: "
msgstr "Compte en banque : "
@ -381,10 +379,7 @@ msgstr "Compte en banque : "
#: pedagogy/templates/pedagogy/guide.jinja:110
#: pedagogy/templates/pedagogy/uv_detail.jinja:189
#: sas/templates/sas/album.jinja:32 sas/templates/sas/moderation.jinja:18
#: sas/templates/sas/picture.jinja:50
#: stock/templates/stock/stock_shopping_list.jinja:43
#: stock/templates/stock/stock_shopping_list.jinja:69
#: trombi/templates/trombi/detail.jinja:35
#: sas/templates/sas/picture.jinja:50 trombi/templates/trombi/detail.jinja:35
#: trombi/templates/trombi/edit_profile.jinja:35
msgid "Delete"
msgstr "Supprimer"
@ -428,7 +423,7 @@ msgstr "Nouveau compte club"
#: counter/templates/counter/cash_summary_list.jinja:53
#: counter/templates/counter/counter_list.jinja:17
#: counter/templates/counter/counter_list.jinja:33
#: counter/templates/counter/counter_list.jinja:55
#: counter/templates/counter/counter_list.jinja:49
#: election/templates/election/election_detail.jinja:184
#: forum/templates/forum/macros.jinja:20 forum/templates/forum/macros.jinja:62
#: launderette/templates/launderette/launderette_list.jinja:16
@ -489,9 +484,6 @@ msgstr "Vous ne pouvez pas créer de journal tant qu'il y en a un d'ouvert"
#: accounting/templates/accounting/club_account_details.jinja:31
#: launderette/templates/launderette/launderette_admin.jinja:43
#: stock/templates/stock/shopping_list_items.jinja:20
#: stock/templates/stock/stock_shopping_list.jinja:26
#: stock/templates/stock/stock_shopping_list.jinja:55
msgid "Name"
msgstr "Nom"
@ -570,7 +562,7 @@ msgstr "Voir"
#: accounting/templates/accounting/co_list.jinja:4
#: accounting/templates/accounting/journal_details.jinja:19
#: core/templates/core/user_tools.jinja:103
#: core/templates/core/user_tools.jinja:95
msgid "Company list"
msgstr "Liste des entreprises"
@ -625,8 +617,6 @@ msgstr "No"
#: counter/templates/counter/last_ops.jinja:45
#: counter/templates/counter/refilling_list.jinja:16
#: rootplace/templates/rootplace/logs.jinja:12 sas/views.py:310
#: stock/templates/stock/stock_shopping_list.jinja:25
#: stock/templates/stock/stock_shopping_list.jinja:54
#: trombi/templates/trombi/user_profile.jinja:40
msgid "Date"
msgstr "Date"
@ -656,12 +646,11 @@ msgid "Nature"
msgstr "Nature"
#: accounting/templates/accounting/journal_details.jinja:40
#: stock/templates/stock/stock_shopping_list.jinja:50
msgid "Done"
msgstr "Effectuées"
#: accounting/templates/accounting/journal_details.jinja:41
#: counter/templates/counter/cash_summary_list.jinja:37 counter/views.py:989
#: counter/templates/counter/cash_summary_list.jinja:37 counter/views.py:940
#: pedagogy/templates/pedagogy/moderation.jinja:13
#: pedagogy/templates/pedagogy/uv_detail.jinja:142
#: trombi/templates/trombi/comment.jinja:4
@ -978,15 +967,15 @@ msgstr "Date de fin"
#: club/forms.py:160 club/templates/club/club_sellings.jinja:49
#: core/templates/core/user_account_detail.jinja:17
#: core/templates/core/user_account_detail.jinja:56
#: counter/templates/counter/cash_summary_list.jinja:33 counter/views.py:149
#: counter/templates/counter/cash_summary_list.jinja:33 counter/views.py:138
msgid "Counter"
msgstr "Comptoir"
#: club/forms.py:167 counter/views.py:733
#: club/forms.py:167 counter/views.py:684
msgid "Products"
msgstr "Produits"
#: club/forms.py:172 counter/views.py:738
#: club/forms.py:172 counter/views.py:689
msgid "Archived products"
msgstr "Produits archivés"
@ -1267,7 +1256,7 @@ msgid "Payment method"
msgstr "Méthode de paiement"
#: club/templates/club/club_tools.jinja:4
#: core/templates/core/user_tools.jinja:157
#: core/templates/core/user_tools.jinja:149
msgid "Club tools"
msgstr "Outils club"
@ -1294,7 +1283,7 @@ msgstr "Nouveau Trombi"
#: club/templates/club/club_tools.jinja:14
#: com/templates/com/poster_list.jinja:17
#: core/templates/core/poster_list.jinja:17
#: core/templates/core/user_tools.jinja:145
#: core/templates/core/user_tools.jinja:137
msgid "Posters"
msgstr "Affiches"
@ -1406,8 +1395,8 @@ msgid "Posters list"
msgstr "Liste d'affiches"
#: club/views.py:171 counter/templates/counter/counter_list.jinja:21
#: counter/templates/counter/counter_list.jinja:43
#: counter/templates/counter/counter_list.jinja:59
#: counter/templates/counter/counter_list.jinja:37
#: counter/templates/counter/counter_list.jinja:53
msgid "Props"
msgstr "Propriétés"
@ -1454,8 +1443,7 @@ msgid "content"
msgstr "contenu"
#: com/models.py:71 core/models.py:1503 launderette/models.py:92
#: launderette/models.py:130 launderette/models.py:181 stock/models.py:74
#: stock/models.py:129
#: launderette/models.py:130 launderette/models.py:181
msgid "type"
msgstr "type"
@ -1517,7 +1505,7 @@ msgid "Begin date should be before end date"
msgstr "La date de début doit être avant celle de fin"
#: com/templates/com/mailing_admin.jinja:4 com/views.py:127
#: core/templates/core/user_tools.jinja:144
#: core/templates/core/user_tools.jinja:136
msgid "Mailing lists administration"
msgstr "Administration des mailing listes"
@ -1565,7 +1553,7 @@ msgstr "Nouvelles"
#: com/templates/com/news_admin_list.jinja:11
#: com/templates/com/news_edit.jinja:8 com/templates/com/news_edit.jinja:31
#: core/templates/core/user_tools.jinja:139
#: core/templates/core/user_tools.jinja:131
msgid "Create news"
msgstr "Créer nouvelle"
@ -1817,7 +1805,7 @@ msgid "Screen - edit"
msgstr "Écran - modifier"
#: com/templates/com/screen_list.jinja:4 com/templates/com/screen_list.jinja:11
#: core/templates/core/user_tools.jinja:146
#: core/templates/core/user_tools.jinja:138
msgid "Screens"
msgstr "Écrans"
@ -1831,7 +1819,7 @@ msgid "Slideshow"
msgstr "Diaporama"
#: com/templates/com/weekmail.jinja:5 com/templates/com/weekmail.jinja:9
#: com/views.py:104 core/templates/core/user_tools.jinja:137
#: com/views.py:104 core/templates/core/user_tools.jinja:129
msgid "Weekmail"
msgstr "Weekmail"
@ -1877,7 +1865,6 @@ msgstr "Supprimer du Weekmail"
#: core/templates/core/user_account_detail.jinja:116 launderette/views.py:217
#: pedagogy/templates/pedagogy/uv_detail.jinja:16
#: pedagogy/templates/pedagogy/uv_detail.jinja:25
#: stock/templates/stock/shopping_list_items.jinja:9
#: trombi/templates/trombi/comment_moderation.jinja:10
#: trombi/templates/trombi/export.jinja:9
msgid "Back"
@ -1941,7 +1928,7 @@ msgstr "Date de début"
msgid "Communication administration"
msgstr "Administration de la communication"
#: com/views.py:110 core/templates/core/user_tools.jinja:138
#: com/views.py:110 core/templates/core/user_tools.jinja:130
msgid "Weekmail destinations"
msgstr "Destinataires du Weekmail"
@ -2466,7 +2453,7 @@ msgstr "Les clubs de L'AE"
msgid "Others UTBM's Associations"
msgstr "Les autres associations de l'UTBM"
#: core/templates/core/base.jinja:218 core/templates/core/user_tools.jinja:180
#: core/templates/core/base.jinja:218 core/templates/core/user_tools.jinja:172
msgid "Elections"
msgstr "Élections"
@ -2517,7 +2504,7 @@ msgstr "Laverie"
msgid "Files"
msgstr "Fichiers"
#: core/templates/core/base.jinja:231 core/templates/core/user_tools.jinja:171
#: core/templates/core/base.jinja:231 core/templates/core/user_tools.jinja:163
msgid "Pedagogy"
msgstr "Pédagogie"
@ -3052,7 +3039,7 @@ msgid "Eboutic invoices"
msgstr "Facture eboutic"
#: core/templates/core/user_account.jinja:54
#: core/templates/core/user_tools.jinja:58 counter/views.py:758
#: core/templates/core/user_tools.jinja:58 counter/views.py:709
msgid "Etickets"
msgstr "Etickets"
@ -3388,7 +3375,7 @@ msgid "Subscription stats"
msgstr "Statistiques de cotisation"
#: core/templates/core/user_tools.jinja:48 counter/forms.py:164
#: counter/views.py:728
#: counter/views.py:679
msgid "Counters"
msgstr "Comptoirs"
@ -3405,102 +3392,90 @@ msgid "Product types management"
msgstr "Gestion des types de produit"
#: core/templates/core/user_tools.jinja:56
#: counter/templates/counter/cash_summary_list.jinja:23 counter/views.py:748
#: counter/templates/counter/cash_summary_list.jinja:23 counter/views.py:699
msgid "Cash register summaries"
msgstr "Relevés de caisse"
#: core/templates/core/user_tools.jinja:57
#: counter/templates/counter/invoices_call.jinja:4 counter/views.py:753
#: counter/templates/counter/invoices_call.jinja:4 counter/views.py:704
msgid "Invoices call"
msgstr "Appels à facture"
#: core/templates/core/user_tools.jinja:72 core/views/user.py:272
#: counter/templates/counter/counter_list.jinja:18
#: counter/templates/counter/counter_list.jinja:34
#: counter/templates/counter/counter_list.jinja:56
#: counter/templates/counter/counter_list.jinja:50
msgid "Stats"
msgstr "Stats"
#: core/templates/core/user_tools.jinja:78
#: counter/templates/counter/counter_list.jinja:38
#: stock/templates/stock/stock_item_list.jinja:11
#: stock/templates/stock/stock_list.jinja:16
msgid "Shopping lists"
msgstr "Liste de courses"
#: core/templates/core/user_tools.jinja:80
#: counter/templates/counter/counter_list.jinja:40
msgid "Create new stock"
msgstr "Créer nouveau stock"
#: core/templates/core/user_tools.jinja:101
#: core/templates/core/user_tools.jinja:93
msgid "Refound Account"
msgstr "Rembourser un compte"
#: core/templates/core/user_tools.jinja:102
#: core/templates/core/user_tools.jinja:94
msgid "General accounting"
msgstr "Comptabilité générale"
#: core/templates/core/user_tools.jinja:117
#: core/templates/core/user_tools.jinja:109
msgid "Club account: "
msgstr "Compte club : "
#: core/templates/core/user_tools.jinja:133
#: core/templates/core/user_tools.jinja:125
msgid "Communication"
msgstr "Communication"
#: core/templates/core/user_tools.jinja:136
#: core/templates/core/user_tools.jinja:128
msgid "Create weekmail article"
msgstr "Rédiger un nouvel article dans le Weekmail"
#: core/templates/core/user_tools.jinja:140
#: core/templates/core/user_tools.jinja:132
msgid "Moderate news"
msgstr "Modérer les nouvelles"
#: core/templates/core/user_tools.jinja:141
#: core/templates/core/user_tools.jinja:133
msgid "Edit alert message"
msgstr "Éditer le message d'alerte"
#: core/templates/core/user_tools.jinja:142
#: core/templates/core/user_tools.jinja:134
msgid "Edit information message"
msgstr "Éditer le message d'informations"
#: core/templates/core/user_tools.jinja:143
#: core/templates/core/user_tools.jinja:135
msgid "Moderate files"
msgstr "Modérer les fichiers"
#: core/templates/core/user_tools.jinja:149
#: core/templates/core/user_tools.jinja:141
msgid "Moderate pictures"
msgstr "Modérer les photos"
#: core/templates/core/user_tools.jinja:173
#: core/templates/core/user_tools.jinja:165
#: pedagogy/templates/pedagogy/guide.jinja:21
msgid "Create UV"
msgstr "Créer UV"
#: core/templates/core/user_tools.jinja:174
#: core/templates/core/user_tools.jinja:166
#: pedagogy/templates/pedagogy/guide.jinja:24
#: trombi/templates/trombi/detail.jinja:10
msgid "Moderate comments"
msgstr "Modérer les commentaires"
#: core/templates/core/user_tools.jinja:182
#: core/templates/core/user_tools.jinja:174
msgid "See available elections"
msgstr "Voir les élections disponibles"
#: core/templates/core/user_tools.jinja:183
#: core/templates/core/user_tools.jinja:175
msgid "See archived elections"
msgstr "Voir les élections archivées"
#: core/templates/core/user_tools.jinja:185
#: core/templates/core/user_tools.jinja:177
msgid "Create a new election"
msgstr "Créer une nouvelle élection"
#: core/templates/core/user_tools.jinja:191
#: core/templates/core/user_tools.jinja:183
msgid "Other tools"
msgstr "Autres outils"
#: core/templates/core/user_tools.jinja:193
#: core/templates/core/user_tools.jinja:185
msgid "Trombi tools"
msgstr "Outils Trombi"
@ -3634,7 +3609,7 @@ msgid "Galaxy"
msgstr "Galaxie"
#: counter/apps.py:30 counter/models.py:414 counter/models.py:898
#: counter/models.py:934 launderette/models.py:32 stock/models.py:39
#: counter/models.py:934 launderette/models.py:32
msgid "counter"
msgstr "comptoir"
@ -3674,7 +3649,7 @@ msgstr "client"
msgid "customers"
msgstr "clients"
#: counter/models.py:74 counter/views.py:309
#: counter/models.py:74 counter/views.py:261
msgid "Not enough money"
msgstr "Solde insuffisant"
@ -3944,7 +3919,7 @@ msgstr "Liste des relevés de caisse"
msgid "Theoric sums"
msgstr "Sommes théoriques"
#: counter/templates/counter/cash_summary_list.jinja:36 counter/views.py:990
#: counter/templates/counter/cash_summary_list.jinja:36 counter/views.py:941
msgid "Emptied"
msgstr "Coffre vidé"
@ -4012,7 +3987,7 @@ msgid "New counter"
msgstr "Nouveau comptoir"
#: counter/templates/counter/counter_list.jinja:22
#: counter/templates/counter/counter_list.jinja:44
#: counter/templates/counter/counter_list.jinja:38
#: counter/templates/counter/refilling_list.jinja:5
msgid "Reloads list"
msgstr "Liste de rechargements"
@ -4021,11 +3996,11 @@ msgstr "Liste de rechargements"
msgid "Bars"
msgstr "Bars"
#: counter/templates/counter/counter_list.jinja:49
#: counter/templates/counter/counter_list.jinja:43
msgid "Offices"
msgstr "Bureaux"
#: counter/templates/counter/counter_list.jinja:65
#: counter/templates/counter/counter_list.jinja:59
msgid "There is no counters in this website."
msgstr "Il n'y a pas de comptoirs dans ce site web."
@ -4170,105 +4145,97 @@ msgstr "Temps"
msgid "Top 100 barman %(counter_name)s (all semesters)"
msgstr "Top 100 barman %(counter_name)s (tous les semestres)"
#: counter/views.py:170
#: counter/views.py:148
msgid "Cash summary"
msgstr "Relevé de caisse"
#: counter/views.py:186
#: counter/views.py:157
msgid "Last operations"
msgstr "Dernières opérations"
#: counter/views.py:203
msgid "Take items from stock"
msgstr "Prendre des éléments du stock"
#: counter/views.py:252
#: counter/views.py:204
msgid "Bad credentials"
msgstr "Mauvais identifiants"
#: counter/views.py:254
#: counter/views.py:206
msgid "User is not barman"
msgstr "L'utilisateur n'est pas barman."
#: counter/views.py:259
#: counter/views.py:211
msgid "Bad location, someone is already logged in somewhere else"
msgstr "Mauvais comptoir, quelqu'un est déjà connecté ailleurs"
#: counter/views.py:300
#: counter/views.py:252
msgid "Too young for that product"
msgstr "Trop jeune pour ce produit"
#: counter/views.py:303
#: counter/views.py:255
msgid "Not allowed for that product"
msgstr "Non autorisé pour ce produit"
#: counter/views.py:306
#: counter/views.py:258
msgid "No date of birth provided"
msgstr "Pas de date de naissance renseignée"
#: counter/views.py:595
#: counter/views.py:547
msgid "You have not enough money to buy all the basket"
msgstr "Vous n'avez pas assez d'argent pour acheter le panier"
#: counter/views.py:722
#: counter/views.py:674
msgid "Counter administration"
msgstr "Administration des comptoirs"
#: counter/views.py:724
msgid "Stocks"
msgstr "Stocks"
#: counter/views.py:743
#: counter/views.py:694
msgid "Product types"
msgstr "Types de produit"
#: counter/views.py:947
#: counter/views.py:898
msgid "10 cents"
msgstr "10 centimes"
#: counter/views.py:948
#: counter/views.py:899
msgid "20 cents"
msgstr "20 centimes"
#: counter/views.py:949
#: counter/views.py:900
msgid "50 cents"
msgstr "50 centimes"
#: counter/views.py:950
#: counter/views.py:901
msgid "1 euro"
msgstr "1 €"
#: counter/views.py:951
#: counter/views.py:902
msgid "2 euros"
msgstr "2 €"
#: counter/views.py:952
#: counter/views.py:903
msgid "5 euros"
msgstr "5 €"
#: counter/views.py:953
#: counter/views.py:904
msgid "10 euros"
msgstr "10 €"
#: counter/views.py:954
#: counter/views.py:905
msgid "20 euros"
msgstr "20 €"
#: counter/views.py:955
#: counter/views.py:906
msgid "50 euros"
msgstr "50 €"
#: counter/views.py:957
#: counter/views.py:908
msgid "100 euros"
msgstr "100 €"
#: counter/views.py:960 counter/views.py:966 counter/views.py:972
#: counter/views.py:978 counter/views.py:984
#: counter/views.py:911 counter/views.py:917 counter/views.py:923
#: counter/views.py:929 counter/views.py:935
msgid "Check amount"
msgstr "Montant du chèque"
#: counter/views.py:963 counter/views.py:969 counter/views.py:975
#: counter/views.py:981 counter/views.py:987
#: counter/views.py:914 counter/views.py:920 counter/views.py:926
#: counter/views.py:932 counter/views.py:938
msgid "Check quantity"
msgstr "Nombre de chèque"
@ -5175,7 +5142,6 @@ msgid "Leave comment"
msgstr "Laisser un commentaire"
#: pedagogy/templates/pedagogy/uv_detail.jinja:150
#: stock/templates/stock/shopping_list_items.jinja:42 stock/views.py:244
#: trombi/templates/trombi/export.jinja:70
msgid "Comments"
msgstr "Commentaires"
@ -5712,200 +5678,6 @@ msgstr "Weekmail envoyé avec succès"
msgid "AE tee-shirt"
msgstr "Tee-shirt AE"
#: stock/models.py:59
msgid "unit quantity"
msgstr "quantité unitaire"
#: stock/models.py:59
msgid "number of element in one box"
msgstr "nombre d'éléments par boîte"
#: stock/models.py:62
msgid "effective quantity"
msgstr "quantité effective"
#: stock/models.py:62
msgid "number of box"
msgstr "nombre de boîtes"
#: stock/models.py:65
msgid "minimal quantity"
msgstr "quantité minimale"
#: stock/models.py:68
msgid ""
"if the effective quantity is less than the minimal, item is added to the "
"shopping list"
msgstr ""
"si la quantité effective est en dessous du minima, l'item est ajouté àla "
"liste de courses"
#: stock/models.py:98
msgid "todo"
msgstr "à faire"
#: stock/models.py:119
msgid "shopping lists"
msgstr "listes de courses"
#: stock/models.py:135
msgid "quantity to buy"
msgstr "quantité à acheter"
#: stock/models.py:137
msgid "quantity to buy during the next shopping session"
msgstr "quantité à acheter pendant les prochaines courses"
#: stock/models.py:140
msgid "quantity bought"
msgstr "quantité achetée"
#: stock/models.py:142
msgid "quantity bought during the last shopping session"
msgstr "quantité achetée pendant les dernières courses"
#: stock/templates/stock/shopping_list_items.jinja:4
#, python-format
msgid "%(shoppinglist)s's items"
msgstr "éléments de %(shoppinglist)s"
#: stock/templates/stock/shopping_list_items.jinja:21
msgid "Quantity asked"
msgstr "Quantité demandée"
#: stock/templates/stock/shopping_list_items.jinja:22
msgid "Quantity bought"
msgstr "Quantité achetée"
#: stock/templates/stock/shopping_list_quantity.jinja:4
#: stock/templates/stock/shopping_list_quantity.jinja:8
#, python-format
msgid "%(s)s's quantity to buy"
msgstr "quantité à acheter de %(s)s"
#: stock/templates/stock/shopping_list_quantity.jinja:13
#: stock/templates/stock/stock_shopping_list.jinja:9
msgid "Create shopping list"
msgstr "Créer une liste de courses"
#: stock/templates/stock/stock_item_list.jinja:10
msgid "New item"
msgstr "Nouvel élément"
#: stock/templates/stock/stock_item_list.jinja:19
#: stock/templates/stock/stock_item_list.jinja:26
msgid "left"
msgstr "restant"
#: stock/templates/stock/stock_item_list.jinja:23
msgid "Others"
msgstr "Autres"
#: stock/templates/stock/stock_item_list.jinja:30
msgid "There is no items in this stock."
msgstr "Il n'y a pas d'élements dans ce stock."
#: stock/templates/stock/stock_list.jinja:4
#: stock/templates/stock/stock_list.jinja:9
msgid "Stock list"
msgstr "Liste des stocks"
#: stock/templates/stock/stock_list.jinja:22
msgid "There is no stocks in this website."
msgstr "Il n'y a pas de stocks sur ce site web."
#: stock/templates/stock/stock_shopping_list.jinja:11
#, python-format
msgid "Shopping lists history for %(s)s"
msgstr "Historique des listes de course pour %(s)s"
#: stock/templates/stock/stock_shopping_list.jinja:14
msgid "Information :"
msgstr "Information : "
#: stock/templates/stock/stock_shopping_list.jinja:16
msgid ""
"Use the \"update stock\" action when you get back from shopping to add the "
"effective quantity bought for each shopping list item."
msgstr ""
"Utilisez la fonction \"mettre à jour le stock\" quand vous revenez de "
"courses pour ajouter la quantité effectivement achetée pour chaque élément "
"de la liste"
#: stock/templates/stock/stock_shopping_list.jinja:18
msgid ""
"For example, 3 Cheeseburger (boxes) are aksing in the list, but there were "
"only 2 so, 2 have to be added in the stock quantity."
msgstr ""
"Par exemple, 3 Cheeseburger (boîtes) sont demandés dans la liste, mais il "
"n'y en avait que 2, donc il faut mettre 2 dans la quantité en stock."
#: stock/templates/stock/stock_shopping_list.jinja:21
msgid "To do"
msgstr "À faire"
#: stock/templates/stock/stock_shopping_list.jinja:27
#: stock/templates/stock/stock_shopping_list.jinja:56
msgid "Number of items"
msgstr "Nombre d'éléments"
#: stock/templates/stock/stock_shopping_list.jinja:37
msgid "Update stock"
msgstr "Mettre à jour le stock"
#: stock/templates/stock/stock_shopping_list.jinja:40
msgid "Mark as done"
msgstr "Marquer comme fait"
#: stock/templates/stock/stock_shopping_list.jinja:66
msgid "Mark as to do"
msgstr "Marquer comme à faire"
#: stock/templates/stock/stock_take_items.jinja:5
#: stock/templates/stock/stock_take_items.jinja:9
#, python-format
msgid "Take items from %(s)s"
msgstr "Prendre des éléments de %(s)s"
#: stock/templates/stock/stock_take_items.jinja:14
msgid "Take items"
msgstr "Prendre les éléments"
#: stock/templates/stock/update_after_shopping.jinja:4
#: stock/templates/stock/update_after_shopping.jinja:8
#, python-format
msgid "Update %(s)s's quantity after shopping"
msgstr "Mettre à jour les quantités de %(s)s après les courses"
#: stock/templates/stock/update_after_shopping.jinja:13
msgid "Update stock quantities"
msgstr "Mettre à jour les quantités en stock"
#: stock/views.py:223
msgid "Shopping list name"
msgstr "Nom de la liste de courses"
#: stock/views.py:233
msgid " left"
msgstr " restant"
#: stock/views.py:239
msgid ""
"Add here, items to buy that are not reference as a stock item (example : "
"sponge, knife, mugs ...)"
msgstr ""
"Ajouter ici les éléments non référencé comme élément de stock (example : "
"éponge, couteau, mugs ...)"
#: stock/views.py:411
msgid " asked"
msgstr " demandé"
#: stock/views.py:489
#, python-format
msgid "%(effective_quantity)s left"
msgstr "%(effective_quantity)s restant"
#: subscription/models.py:34
msgid "Bad subscription type"
msgstr "Mauvais type de cotisation"

View File

@ -135,9 +135,6 @@ nav:
- reference/staticfiles/storage.md
- reference/staticfiles/finders.md
- reference/staticfiles/processors.md
- stock:
- reference/stock/models.md
- reference/stock/views.md
- subscription:
- reference/subscription/models.md
- reference/subscription/views.md

View File

@ -41,7 +41,6 @@ urlpatterns = [
path("com/", include(("com.urls", "com"), namespace="com")),
path("club/", include(("club.urls", "club"), namespace="club")),
path("counter/", include(("counter.urls", "counter"), namespace="counter")),
path("stock/", include(("stock.urls", "stock"), namespace="stock")),
path(
"accounting/",
include(("accounting.urls", "accounting"), namespace="accounting"),

View File

@ -1,33 +0,0 @@
#
# Copyright 2016,2017
# - Guillaume "Lo-J" Renaud <renaudg779@gmail.com>
# - Skia <skia@libskia.so>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
from django.contrib import admin
from stock.models import ShoppingList, ShoppingListItem, Stock, StockItem
# Register your models here.
admin.site.register(Stock)
admin.site.register(StockItem)
admin.site.register(ShoppingList)
admin.site.register(ShoppingListItem)

View File

@ -0,0 +1,51 @@
# Generated by Django 4.2.16 on 2024-09-18 11:33
from django.db import migrations
# This migration is here only to delete all the models
# of the stock application and will be removed in a subsequent release
class Migration(migrations.Migration):
dependencies = [
("stock", "0001_initial"),
]
operations = [
migrations.RemoveField(
model_name="shoppinglistitem",
name="shopping_lists",
),
migrations.RemoveField(
model_name="shoppinglistitem",
name="stockitem_owner",
),
migrations.RemoveField(
model_name="shoppinglistitem",
name="type",
),
migrations.RemoveField(
model_name="stock",
name="counter",
),
migrations.RemoveField(
model_name="stockitem",
name="stock_owner",
),
migrations.RemoveField(
model_name="stockitem",
name="type",
),
migrations.DeleteModel(
name="ShoppingList",
),
migrations.DeleteModel(
name="ShoppingListItem",
),
migrations.DeleteModel(
name="Stock",
),
migrations.DeleteModel(
name="StockItem",
),
]

View File

@ -1,152 +0,0 @@
#
# Copyright 2016,2017
# - Guillaume "Lo-J" Renaud <renaudg779@gmail.com>
# - Skia <skia@libskia.so>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
from django.conf import settings
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from counter.models import Counter, ProductType
class Stock(models.Model):
"""The Stock class, this one is used to know how many products are left for a specific counter."""
name = models.CharField(_("name"), max_length=64)
counter = models.OneToOneField(
Counter,
verbose_name=_("counter"),
related_name="stock",
on_delete=models.CASCADE,
)
def __str__(self):
return "%s (%s)" % (self.name, self.counter)
def get_absolute_url(self):
return reverse("stock:list")
def can_be_viewed_by(self, user):
return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)
class StockItem(models.Model):
"""The StockItem class, element of the stock."""
name = models.CharField(_("name"), max_length=64)
unit_quantity = models.IntegerField(
_("unit quantity"), default=0, help_text=_("number of element in one box")
)
effective_quantity = models.IntegerField(
_("effective quantity"), default=0, help_text=_("number of box")
)
minimal_quantity = models.IntegerField(
_("minimal quantity"),
default=1,
help_text=_(
"if the effective quantity is less than the minimal, item is added to the shopping list"
),
)
type = models.ForeignKey(
ProductType,
related_name="stock_items",
verbose_name=_("type"),
null=True,
blank=True,
on_delete=models.SET_NULL,
)
stock_owner = models.ForeignKey(
Stock, related_name="items", on_delete=models.CASCADE
)
def __str__(self):
return "%s" % (self.name)
def get_absolute_url(self):
return reverse("stock:items_list", kwargs={"stock_id": self.stock_owner.id})
def can_be_viewed_by(self, user):
return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)
class ShoppingList(models.Model):
"""The ShoppingList class, used to make an history of the shopping lists."""
date = models.DateTimeField(_("date"))
name = models.CharField(_("name"), max_length=64)
todo = models.BooleanField(_("todo"))
comment = models.TextField(_("comment"), null=True, blank=True)
stock_owner = models.ForeignKey(
Stock, null=True, related_name="shopping_lists", on_delete=models.CASCADE
)
def __str__(self):
return "%s (%s)" % (self.name, self.date)
def get_absolute_url(self):
return reverse("stock:shoppinglist_list")
def can_be_viewed_by(self, user):
return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)
class ShoppingListItem(models.Model):
"""An Item on a shopping list."""
shopping_lists = models.ManyToManyField(
ShoppingList,
verbose_name=_("shopping lists"),
related_name="shopping_items_to_buy",
)
stockitem_owner = models.ForeignKey(
StockItem, related_name="shopping_item", null=True, on_delete=models.CASCADE
)
name = models.CharField(_("name"), max_length=64)
type = models.ForeignKey(
ProductType,
related_name="shoppinglist_items",
verbose_name=_("type"),
null=True,
blank=True,
on_delete=models.SET_NULL,
)
tobuy_quantity = models.IntegerField(
_("quantity to buy"),
default=6,
help_text=_("quantity to buy during the next shopping session"),
)
bought_quantity = models.IntegerField(
_("quantity bought"),
default=0,
help_text=_("quantity bought during the last shopping session"),
)
def __str__(self):
return f"{self.name} - {self.shopping_lists.first()}"
def get_absolute_url(self):
return reverse("stock:shoppinglist_list")
def can_be_viewed_by(self, user):
return user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)

View File

@ -1,51 +0,0 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}{{ shoppinglist }}'s items{% endtrans %}
{% endblock %}
{% block content %}
{% if current_tab == "stocks" %}
<a href="{{ url('stock:shoppinglist_list', stock_id=shoppinglist.stock_owner.id)}}">{% trans %}Back{% endtrans %}</a>
{% endif %}
<h3>{{ shoppinglist.name }}</h3>
{% for t in ProductType.objects.order_by('name').all() %}
{% if shoppinglist.shopping_items_to_buy.filter(type=t) %}
<h4>{{ t }}</h4>
<br>
<table>
<thead>
<tr>
<td>{% trans %}Name{% endtrans %}</td>
<td>{% trans %}Quantity asked{% endtrans %}</td>
<td>{% trans %}Quantity bought{% endtrans %}</td>
</tr>
</thead>
<tbody>
{% for i in shoppinglist.shopping_items_to_buy.filter(type=t).order_by('name').all() %}
<tr>
<td>{{ i.name }}</td>
<td>{{ i.tobuy_quantity }}</td>
<td>{{ i.bought_quantity }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endfor %}
<h4>{% trans %}Other{% endtrans %}</h4>
<br>
<table>
<thead>
<tr>
<td>{% trans %}Comments{% endtrans %}</td>
</tr>
</thead>
<tbody>
<tr>
<td>{{ shoppinglist.comment }}</td>
</tr>
</tbody>
</table>
{% endblock %}

View File

@ -1,16 +0,0 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans s = stock %}{{ s }}'s quantity to buy{% endtrans %}
{% endblock %}
{% block content %}
<h3>{% trans s = stock %}{{ s }}'s quantity to buy{% endtrans %}</h3>
<div>
<form method="post" action="" class="inline" style="display:inline">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Create shopping list{% endtrans %}" /></p>
</form>
</div>
{% endblock %}

View File

@ -1,32 +0,0 @@
{% extends "core/base.jinja" %}
{% from 'core/macros.jinja' import user_profile_link %}
{% block title %}
{{ stock }}
{% endblock %}
{% block content %}
{% if current_tab == "stocks" %}
<p><a href="{{ url('stock:new_item', stock_id=stock.id)}}">{% trans %}New item{% endtrans %}</a></p>
<h5><a href="{{ url('stock:shoppinglist_list', stock_id=stock.id)}}">{% trans %}Shopping lists{% endtrans %}</a></h5>
{% endif %}
{% if stock %}
<h3>{{ stock }}</h3>
{% for t in ProductType.objects.order_by('name') %}
<h4>{{ t }}</h4>
<ul>
{% for i in stock.items.filter(type=t).order_by('name') %}
<li><a href="{{ url('stock:edit_item', item_id=i.id)}}">{{ i }} ({{ i.effective_quantity }} {% trans %}left{% endtrans %})</a></li>
{% endfor %}
</ul>
{% endfor %}
<h4>{% trans %}Others{% endtrans %}</h4>
<ul>
{% for i in stock.items.filter(type=None).order_by('name') %}
<li><a href="{{ url('stock:edit_item', item_id=i.id)}}">{{ i }} ({{ i.effective_quantity }} {% trans %}left{% endtrans %})</a></li>
{% endfor %}
</ul>
{% else %}
{% trans %}There is no items in this stock.{% endtrans %}
{% endif %}
{% endblock %}

View File

@ -1,24 +0,0 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Stock list{% endtrans %}
{% endblock %}
{% block content %}
{% if stock_list %}
<h3>{% trans %}Stock list{% endtrans %}</h3>
<ul>
{% for s in stock_list.order_by('name') %}
<li>
{% if user.can_edit(s) %}
<a href="{{ url('stock:items_list', stock_id=s.id) }}">{{ s }}</a>
- <a href="{{ url('stock:edit', stock_id=s.id) }}">Edit</a>
- <a href="{{ url('stock:shoppinglist_list', stock_id=s.id)}}">{% trans %}Shopping lists{% endtrans %}</a>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
{% trans %}There is no stocks in this website.{% endtrans %}
{% endif %}
{% endblock %}

View File

@ -1,75 +0,0 @@
{% extends "core/base.jinja" %}
{% block title %}
Shopping list for {{ stock }}
{% endblock %}
{% block content %}
{% if current_tab == "stocks" %}
<a href="{{ url('stock:shoppinglist_create', stock_id=stock.id)}}">{% trans %}Create shopping list{% endtrans %}</a>
{% endif %}
<h3>{% trans s=stock %}Shopping lists history for {{ s }}{% endtrans %}</h3>
<p>
{% trans %}Information :{% endtrans %}
<br>
{% trans %}Use the "update stock" action when you get back from shopping to add the effective quantity bought for each shopping list item.{% endtrans %}
<br>
{% trans %}For example, 3 Cheeseburger (boxes) are aksing in the list, but there were only 2 so, 2 have to be added in the stock quantity.{% endtrans %}
</p>
<h4>{% trans %}To do{% endtrans %}</h4>
<table>
<thead>
<tr>
<td>{% trans %}Date{% endtrans %}</td>
<td>{% trans %}Name{% endtrans %}</td>
<td>{% trans %}Number of items{% endtrans %}</td>
</tr>
</thead>
<tbody>
{% for s in stock.shopping_lists.filter(todo=True).filter(stock_owner=stock).order_by('-date').all() %}
<tr>
<td>{{ s.date|localtime|date("Y-m-d H:i") }}</td>
<td><a href="{{ url('stock:shoppinglist_items', stock_id=stock.id, shoppinglist_id=s.id)}}">{{ s.name }}</a></td>
<td>{{ s.shopping_items_to_buy.count() }}</td>
<td>
<a href="{{ url('stock:update_after_shopping', stock_id=stock.id, shoppinglist_id=s.id)}}">{% trans %}Update stock{% endtrans %}</a>
</td>
<td>
<a href="{{ url('stock:shoppinglist_set_done', stock_id=stock.id, shoppinglist_id=s.id)}}">{% trans %}Mark as done{% endtrans %}</a>
</td>
<td>
<a href="{{ url('stock:shoppinglist_delete', stock_id=stock.id, shoppinglist_id=s.id)}}">{% trans %}Delete{% endtrans %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<h4>{% trans %}Done{% endtrans %}</h4>
<table>
<thead>
<tr>
<td>{% trans %}Date{% endtrans %}</td>
<td>{% trans %}Name{% endtrans %}</td>
<td>{% trans %}Number of items{% endtrans %}</td>
</tr>
</thead>
<tbody>
{% for s in stock.shopping_lists.filter(todo=False).filter(stock_owner=stock).order_by('-date').all() %}
<tr>
<td>{{ s.date|localtime|date("Y-m-d H:i") }}</td>
<td><a href="{{ url('stock:shoppinglist_items', stock_id=stock.id, shoppinglist_id=s.id)}}">{{ s.name }}</a></td>
<td>{{ s.shopping_items_to_buy.count() }}</td>
<td>
<a href="{{ url('stock:shoppinglist_set_todo', stock_id=stock.id, shoppinglist_id=s.id)}}">{% trans %}Mark as to do{% endtrans %}</a>
</td>
<td>
<a href="{{ url('stock:shoppinglist_delete', stock_id=stock.id, shoppinglist_id=s.id)}}">{% trans %}Delete{% endtrans %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -1,17 +0,0 @@
{% extends "core/base.jinja" %}
{% from 'core/macros.jinja' import user_profile_link %}
{% block title %}
{% trans s = stock %}Take items from {{ s }}{% endtrans %}
{% endblock %}
{% block content %}
<h3>{% trans s = stock %}Take items from {{ s }}{% endtrans %}</h3>
<div>
<form method="post" action="" class="inline" style="display:inline">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Take items{% endtrans %}" /></p>
</form>
</div>
{% endblock %}

View File

@ -1,16 +0,0 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans s = shoppinglist %}Update {{ s }}'s quantity after shopping{% endtrans %}
{% endblock %}
{% block content %}
<h3>{% trans s = shoppinglist %}Update {{ s }}'s quantity after shopping{% endtrans %}</h3>
<div>
<form method="post" action="" class="inline" style="display:inline">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Update stock quantities{% endtrans %}" /></p>
</form>
</div>
{% endblock %}

View File

@ -1,25 +0,0 @@
#
# Copyright 2016,2017
# - Guillaume "Lo-J" Renaud <renaudg779@gmail.com>
# - Skia <skia@libskia.so>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
# Create your tests here.

View File

@ -1,87 +0,0 @@
#
# Copyright 2016,2017
# - Guillaume "Lo-J" Renaud <renaudg779@gmail.com>
# - Skia <skia@libskia.so>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
from django.urls import path
from stock.views import *
urlpatterns = [
# Stock re_paths
path("new/counter/<int:counter_id>/", StockCreateView.as_view(), name="new"),
path("edit/<int:stock_id>/", StockEditView.as_view(), name="edit"),
path("list/", StockListView.as_view(), name="list"),
# StockItem re_paths
path("<int:stock_id>/", StockItemList.as_view(), name="items_list"),
path(
"<int:stock_id>/stock_item/new_item/",
StockItemCreateView.as_view(),
name="new_item",
),
path(
"stock_item/<int:item_id>/edit/",
StockItemEditView.as_view(),
name="edit_item",
),
path(
"<int:stock_id>/stock_item/take_items/",
StockTakeItemsBaseFormView.as_view(),
name="take_items",
),
# ShoppingList re_paths
path(
"<int:stock_id>/shopping_list/list/",
StockShoppingListView.as_view(),
name="shoppinglist_list",
),
path(
"<int:stock_id>/shopping_list/create/",
StockItemQuantityBaseFormView.as_view(),
name="shoppinglist_create",
),
path(
"<int:stock_id>/shopping_list/<int:shoppinglist_id>/items/",
StockShoppingListItemListView.as_view(),
name="shoppinglist_items",
),
path(
"<int:stock_id>/shopping_list/<int:shoppinglist_id>/delete/",
StockShoppingListDeleteView.as_view(),
name="shoppinglist_delete",
),
path(
"<int:stock_id>/shopping_list/<int:shoppinglist_id>/set_done/",
StockShopppingListSetDone.as_view(),
name="shoppinglist_set_done",
),
path(
"<int:stock_id>/shopping_list/<int:shoppinglist_id>/set_todo/",
StockShopppingListSetTodo.as_view(),
name="shoppinglist_set_todo",
),
path(
"<int:stock_id>/shopping_list/<int:shoppinglist_id>/update_stock/",
StockUpdateAfterShopppingBaseFormView.as_view(),
name="update_after_shopping",
),
]

View File

@ -1,536 +0,0 @@
#
# Copyright 2016,2017
# - Guillaume "Lo-J" Renaud <renaudg779@gmail.com>
# - Skia <skia@libskia.so>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
from collections import OrderedDict
from django import forms
from django.db import transaction
from django.forms.models import modelform_factory
from django.http import HttpResponseRedirect
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView, ListView
from django.views.generic.edit import BaseFormView, CreateView, DeleteView, UpdateView
from core.views import CanCreateMixin, CanEditMixin, CanEditPropMixin, CanViewMixin
from counter.models import ProductType
from counter.views import CounterAdminTabsMixin, CounterTabsMixin
from stock.models import ShoppingList, ShoppingListItem, Stock, StockItem
class StockItemList(CounterAdminTabsMixin, CanCreateMixin, ListView):
"""The stockitems list view for the counter owner."""
model = Stock
template_name = "stock/stock_item_list.jinja"
pk_url_kwarg = "stock_id"
current_tab = "stocks"
def get_context_data(self):
ret = super().get_context_data()
if "stock_id" in self.kwargs.keys():
ret["stock"] = Stock.objects.filter(id=self.kwargs["stock_id"]).first()
return ret
class StockListView(CounterAdminTabsMixin, CanViewMixin, ListView):
"""A list view for the admins."""
model = Stock
template_name = "stock/stock_list.jinja"
current_tab = "stocks"
class StockEditForm(forms.ModelForm):
"""A form to change stock's characteristics."""
class Meta:
model = Stock
fields = ["name", "counter"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def save(self, *args, **kwargs):
return super().save(*args, **kwargs)
class StockEditView(CounterAdminTabsMixin, CanEditPropMixin, UpdateView):
"""An edit view for the stock."""
model = Stock
form_class = modelform_factory(Stock, fields=["name", "counter"])
pk_url_kwarg = "stock_id"
template_name = "core/edit.jinja"
current_tab = "stocks"
class StockItemEditView(CounterAdminTabsMixin, CanEditPropMixin, UpdateView):
"""An edit view for a stock item."""
model = StockItem
form_class = modelform_factory(
StockItem,
fields=[
"name",
"unit_quantity",
"effective_quantity",
"minimal_quantity",
"type",
"stock_owner",
],
)
pk_url_kwarg = "item_id"
template_name = "core/edit.jinja"
current_tab = "stocks"
class StockCreateView(CounterAdminTabsMixin, CanCreateMixin, CreateView):
"""A create view for a new Stock."""
model = Stock
form_class = modelform_factory(Stock, fields=["name", "counter"])
template_name = "core/create.jinja"
pk_url_kwarg = "counter_id"
current_tab = "stocks"
success_url = reverse_lazy("stock:list")
def get_initial(self):
ret = super().get_initial()
if "counter_id" in self.kwargs.keys():
ret["counter"] = self.kwargs["counter_id"]
return ret
class StockItemCreateView(CounterAdminTabsMixin, CanCreateMixin, CreateView):
"""A create view for a new StockItem."""
model = StockItem
form_class = modelform_factory(
StockItem,
fields=[
"name",
"unit_quantity",
"effective_quantity",
"minimal_quantity",
"type",
"stock_owner",
],
)
template_name = "core/create.jinja"
pk_url_kwarg = "stock_id"
current_tab = "stocks"
def get_initial(self):
ret = super().get_initial()
if "stock_id" in self.kwargs.keys():
ret["stock_owner"] = self.kwargs["stock_id"]
return ret
def get_success_url(self):
return reverse_lazy(
"stock:items_list", kwargs={"stock_id": self.object.stock_owner.id}
)
class StockShoppingListView(CounterAdminTabsMixin, CanViewMixin, ListView):
"""A list view for the people to know the item to buy."""
model = Stock
template_name = "stock/stock_shopping_list.jinja"
pk_url_kwarg = "stock_id"
current_tab = "stocks"
def get_context_data(self):
ret = super().get_context_data()
if "stock_id" in self.kwargs.keys():
ret["stock"] = Stock.objects.filter(id=self.kwargs["stock_id"]).first()
return ret
class StockItemQuantityForm(forms.BaseForm):
def clean(self):
with transaction.atomic():
self.stock = Stock.objects.filter(id=self.stock_id).first()
shopping_list = ShoppingList(
name="Courses " + self.stock.counter.name,
date=timezone.now(),
todo=True,
)
shopping_list.save()
shopping_list.stock_owner = self.stock
shopping_list.save()
for k, t in self.cleaned_data.items():
if k == "name":
shopping_list.name = t
shopping_list.save()
elif k == "comment":
shopping_list.comment = t
shopping_list.save()
else:
if t > 0:
item_id = int(k[5:])
item = StockItem.objects.filter(id=item_id).first()
shoppinglist_item = ShoppingListItem(
stockitem_owner=item,
name=item.name,
type=item.type,
tobuy_quantity=t,
)
shoppinglist_item.save()
shoppinglist_item.shopping_lists.add(shopping_list)
shoppinglist_item.save()
return self.cleaned_data
class StockItemQuantityBaseFormView(
CounterAdminTabsMixin, CanEditMixin, DetailView, BaseFormView
):
"""docstring for StockItemOutList."""
model = StockItem
template_name = "stock/shopping_list_quantity.jinja"
pk_url_kwarg = "stock_id"
current_tab = "stocks"
def get_form_class(self):
fields = OrderedDict()
kwargs = {}
fields["name"] = forms.CharField(
max_length=30, required=True, label=_("Shopping list name")
)
for t in ProductType.objects.order_by("name").all():
for i in self.stock.items.filter(type=t).order_by("name").all():
if i.effective_quantity <= i.minimal_quantity:
field_name = "item-%s" % (str(i.id))
fields[field_name] = forms.IntegerField(
required=True,
label=str(i),
initial=0,
help_text=_(str(i.effective_quantity) + " left"),
)
fields["comment"] = forms.CharField(
widget=forms.Textarea(
attrs={
"placeholder": _(
"Add here, items to buy that are not reference as a stock item (example : sponge, knife, mugs ...)"
)
}
),
required=False,
label=_("Comments"),
)
kwargs["stock_id"] = self.stock.id
kwargs["base_fields"] = fields
return type("StockItemQuantityForm", (StockItemQuantityForm,), kwargs)
def get(self, request, *args, **kwargs):
"""Simple get view."""
self.stock = Stock.objects.filter(id=self.kwargs["stock_id"]).first()
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
"""Handle the many possibilities of the post request."""
self.object = self.get_object()
self.stock = Stock.objects.filter(id=self.kwargs["stock_id"]).first()
return super().post(request, *args, **kwargs)
def form_valid(self, form):
return super().form_valid(form)
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
if "form" not in kwargs.keys():
kwargs["form"] = self.get_form()
kwargs["stock"] = self.stock
return kwargs
def get_success_url(self):
return reverse_lazy(
"stock:shoppinglist_list", args=self.args, kwargs=self.kwargs
)
class StockShoppingListItemListView(CounterAdminTabsMixin, CanViewMixin, ListView):
"""docstring for StockShoppingListItemListView."""
model = ShoppingList
template_name = "stock/shopping_list_items.jinja"
pk_url_kwarg = "shoppinglist_id"
current_tab = "stocks"
def get_context_data(self):
ret = super().get_context_data()
if "shoppinglist_id" in self.kwargs.keys():
ret["shoppinglist"] = ShoppingList.objects.filter(
id=self.kwargs["shoppinglist_id"]
).first()
return ret
class StockShoppingListDeleteView(CounterAdminTabsMixin, CanEditMixin, DeleteView):
"""Delete a ShoppingList (for the resonsible account)."""
model = ShoppingList
pk_url_kwarg = "shoppinglist_id"
template_name = "core/delete_confirm.jinja"
current_tab = "stocks"
def get_success_url(self):
return reverse_lazy(
"stock:shoppinglist_list", kwargs={"stock_id": self.object.stock_owner.id}
)
class StockShopppingListSetDone(CanEditMixin, DetailView):
"""Set a ShoppingList as done."""
model = ShoppingList
pk_url_kwarg = "shoppinglist_id"
def get(self, request, *args, **kwargs):
self.object = self.get_object()
self.object.todo = False
self.object.save()
return HttpResponseRedirect(
reverse(
"stock:shoppinglist_list",
args=self.args,
kwargs={"stock_id": self.object.stock_owner.id},
)
)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return HttpResponseRedirect(
reverse(
"stock:shoppinglist_list",
args=self.args,
kwargs={"stock_id": self.object.stock_owner.id},
)
)
class StockShopppingListSetTodo(CanEditMixin, DetailView):
"""Set a ShoppingList as done."""
model = ShoppingList
pk_url_kwarg = "shoppinglist_id"
def get(self, request, *args, **kwargs):
self.object = self.get_object()
self.object.todo = True
self.object.save()
return HttpResponseRedirect(
reverse(
"stock:shoppinglist_list",
args=self.args,
kwargs={"stock_id": self.object.stock_owner.id},
)
)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return HttpResponseRedirect(
reverse(
"stock:shoppinglist_list",
args=self.args,
kwargs={"stock_id": self.object.stock_owner.id},
)
)
class StockUpdateAfterShopppingForm(forms.BaseForm):
def clean(self):
with transaction.atomic():
self.shoppinglist = ShoppingList.objects.filter(
id=self.shoppinglist_id
).first()
for k, t in self.cleaned_data.items():
shoppinglist_item_id = int(k[5:])
if int(t) > 0:
shoppinglist_item = ShoppingListItem.objects.filter(
id=shoppinglist_item_id
).first()
shoppinglist_item.bought_quantity = int(t)
shoppinglist_item.save()
shoppinglist_item.stockitem_owner.effective_quantity += int(t)
shoppinglist_item.stockitem_owner.save()
self.shoppinglist.todo = False
self.shoppinglist.save()
return self.cleaned_data
class StockUpdateAfterShopppingBaseFormView(
CounterAdminTabsMixin, CanEditMixin, DetailView, BaseFormView
):
"""docstring for StockUpdateAfterShopppingBaseFormView."""
model = ShoppingList
template_name = "stock/update_after_shopping.jinja"
pk_url_kwarg = "shoppinglist_id"
current_tab = "stocks"
def get_form_class(self):
fields = OrderedDict()
kwargs = {}
for t in ProductType.objects.order_by("name").all():
for i in (
self.shoppinglist.shopping_items_to_buy.filter(type=t)
.order_by("name")
.all()
):
field_name = "item-%s" % (str(i.id))
fields[field_name] = forms.CharField(
max_length=30,
required=True,
label=str(i),
help_text=_(str(i.tobuy_quantity) + " asked"),
)
kwargs["shoppinglist_id"] = self.shoppinglist.id
kwargs["base_fields"] = fields
return type(
"StockUpdateAfterShopppingForm", (StockUpdateAfterShopppingForm,), kwargs
)
def get(self, request, *args, **kwargs):
self.shoppinglist = ShoppingList.objects.filter(
id=self.kwargs["shoppinglist_id"]
).first()
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
"""Handle the many possibilities of the post request."""
self.object = self.get_object()
self.shoppinglist = ShoppingList.objects.filter(
id=self.kwargs["shoppinglist_id"]
).first()
return super().post(request, *args, **kwargs)
def form_valid(self, form):
"""We handle here the redirection."""
return super().form_valid(form)
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
if "form" not in kwargs:
kwargs["form"] = self.get_form()
kwargs["shoppinglist"] = self.shoppinglist
kwargs["stock"] = self.shoppinglist.stock_owner
return kwargs
def get_success_url(self):
self.kwargs.pop("shoppinglist_id", None)
return reverse_lazy(
"stock:shoppinglist_list", args=self.args, kwargs=self.kwargs
)
class StockTakeItemsForm(forms.BaseForm):
"""docstring for StockTakeItemsFormView."""
def clean(self):
with transaction.atomic():
for k, t in self.cleaned_data.items():
item_id = int(k[5:])
if t > 0:
item = StockItem.objects.filter(id=item_id).first()
item.effective_quantity -= t
item.save()
return self.cleaned_data
class StockTakeItemsBaseFormView(
CounterTabsMixin, CanEditMixin, DetailView, BaseFormView
):
"""docstring for StockTakeItemsBaseFormView."""
model = StockItem
template_name = "stock/stock_take_items.jinja"
pk_url_kwarg = "stock_id"
current_tab = "take_items_from_stock"
def get_form_class(self):
fields = OrderedDict()
kwargs = {}
for t in ProductType.objects.order_by("name").all():
for i in self.stock.items.filter(type=t).order_by("name").all():
field_name = "item-%s" % (str(i.id))
fields[field_name] = forms.IntegerField(
required=False,
label=str(i),
initial=0,
min_value=0,
max_value=i.effective_quantity,
help_text=_(
"%(effective_quantity)s left"
% {"effective_quantity": str(i.effective_quantity)}
),
)
kwargs[field_name] = i.effective_quantity
kwargs["stock_id"] = self.stock.id
kwargs["counter_id"] = self.stock.counter.id
kwargs["base_fields"] = fields
return type("StockTakeItemsForm", (StockTakeItemsForm,), kwargs)
def get(self, request, *args, **kwargs):
self.stock = Stock.objects.filter(id=self.kwargs["stock_id"]).first()
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
"""Handle the many possibilities of the post request."""
self.object = self.get_object()
self.stock = Stock.objects.filter(id=self.kwargs["stock_id"]).first()
if self.stock.counter.type == "BAR" and not (
"counter_token" in self.request.session.keys()
and self.request.session["counter_token"] == self.stock.counter.token
): # Also check the token to avoid the bar to be stolen
return HttpResponseRedirect(
reverse_lazy(
"counter:details",
args=self.args,
kwargs={"counter_id": self.stock.counter.id},
)
+ "?bad_location"
)
return super().post(request, *args, **kwargs)
def form_valid(self, form):
return super().form_valid(form)
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
if "form" not in kwargs.keys():
kwargs["form"] = self.get_form()
kwargs["stock"] = self.stock
kwargs["counter"] = self.stock.counter
return kwargs
def get_success_url(self):
stock = Stock.objects.filter(id=self.kwargs["stock_id"]).first()
self.kwargs["counter_id"] = stock.counter.id
self.kwargs.pop("stock_id", None)
return reverse_lazy("counter:details", args=self.args, kwargs=self.kwargs)