Add product type management views

This commit is contained in:
Skia 2016-07-27 20:05:45 +02:00
parent f230fbc135
commit 80f72df1de
9 changed files with 201 additions and 58 deletions

View File

@ -1,7 +1,7 @@
{% extends "core/base.jinja" %}
{% block content %}
<h2>{% trans %}Create{% endtrans %}</h2>
<h2>{% trans name=form.instance.__class__._meta.verbose_name %}Create {{ name }}{% endtrans %}</h2>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p() }}

View File

@ -14,7 +14,7 @@
{% else %}
<li><a href="{{ url('core:page_rev', page_name=page.get_full_name(), rev=r['id']) }}">{{ r.revision }}</a> -
{{ user_profile_link(r.author) }} -
{{ page.revisions.last().date|localtime|date(DATETIME_FORMAT) }} {{ page.revisions.last().date|localtime|time(DATETIME_FORMAT) }}</a></li>
{{ r.date|localtime|date(DATETIME_FORMAT) }} {{ r.date|localtime|time(DATETIME_FORMAT) }}</a></li>
{% endif %}
{% endfor %}
</ul>

View File

@ -23,7 +23,8 @@
<ul>
{% if user.is_in_group(settings.SITH_GROUPS['counter-admin']['name']) or user.is_in_group(settings.SITH_GROUPS['root']['name']) %}
<li><a href="{{ url('counter:admin_list') }}">{% trans %}General counters management{% endtrans %}</a></li>
<li><a href="{{ url('counter:product_list') }}">{% trans %}General products management{% endtrans %}</a></li>
<li><a href="{{ url('counter:product_list') }}">{% trans %}Products management{% endtrans %}</a></li>
<li><a href="{{ url('counter:producttype_list') }}">{% trans %}Products type management{% endtrans %}</a></li>
{% endif %}
{% for b in settings.SITH_COUNTER_BARS %}
{% if user.is_in_group(b[1]+" admin") %}

View File

@ -39,6 +39,9 @@ class ProductType(models.Model):
description = models.TextField(_('description'), null=True, blank=True)
icon = models.ImageField(upload_to='products', null=True, blank=True)
class Meta:
verbose_name = _('product type')
def is_owned_by(self, user):
"""
Method to see if that object can be edited by the given user
@ -50,6 +53,9 @@ class ProductType(models.Model):
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('counter:producttype_list')
class Product(models.Model):
"""
This describes a product, with all its related informations
@ -64,6 +70,9 @@ class Product(models.Model):
icon = models.ImageField(upload_to='products', null=True, blank=True)
club = models.ForeignKey(Club, related_name="products")
class Meta:
verbose_name = _('product')
def is_owned_by(self, user):
"""
Method to see if that object can be edited by the given user
@ -89,6 +98,9 @@ class Counter(models.Model):
view_groups = models.ManyToManyField(Group, related_name="viewable_counters", blank=True)
barmen_session = {}
class Meta:
verbose_name = _('counter')
def __getattribute__(self, name):
if name == "owner_group":
return Group.objects.filter(name=self.club.unix_name+settings.SITH_BOARD_SUFFIX).first()
@ -173,6 +185,9 @@ class Refilling(models.Model):
bank = models.CharField(_('bank'), max_length=255,
choices=settings.SITH_COUNTER_BANK, default='other')
class Meta:
verbose_name = _("refilling")
def __str__(self):
return "Refilling: %.2f for %s" % (self.amount, self.customer.user.get_display_name())
@ -197,6 +212,9 @@ class Selling(models.Model):
customer = models.ForeignKey(Customer, related_name="buyings", blank=False)
date = models.DateTimeField(_('date'), auto_now=True)
class Meta:
verbose_name = _("selling")
def __str__(self):
return "Selling: %d x %s (%f) for %s" % (self.quantity, self.product.name,
self.quantity*self.unit_price, self.customer.user.get_display_name())
@ -219,14 +237,11 @@ class Permanency(models.Model):
start = models.DateTimeField(_('start date'))
end = models.DateTimeField(_('end date'))
class Meta:
verbose_name = _("permanency")
def __str__(self):
return "%s in %s from %s to %s" % (self.user, self.counter,
self.start.strftime("%Y-%m-%d %H:%M:%S"), self.end.strftime("%Y-%m-%d %H:%M:%S"))
# TODO:
# une classe Vente
# foreign key vers comptoir, vendeur, client, produit, mais stocker le prix du produit, pour gerer les maj de prix
# une classe Rechargement
# foreign key vers comptoir, vendeur, client, plus montant

View File

@ -0,0 +1,24 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Product type list{% endtrans %}
{% endblock %}
{% block content %}
<p><a href="{{ url('counter:new_producttype') }}">{% trans %}New product type{% endtrans %}</a></p>
{% if producttype_list %}
<h3>{% trans %}Product type list{% endtrans %}</h3>
<ul>
{% for t in producttype_list %}
<li><a href="{{ url('counter:producttype_edit', type_id=t.id) }}">{{ t }}</a></li>
{% endfor %}
</ul>
{% else %}
{% trans %}There is no product types in this website.{% endtrans %}
{% endif %}
{% endblock %}

View File

@ -14,6 +14,9 @@ urlpatterns = [
url(r'^admin/product/list$', ProductListView.as_view(), name='product_list'),
url(r'^admin/product/create$', ProductCreateView.as_view(), name='new_product'),
url(r'^admin/product/(?P<product_id>[0-9]+)$', ProductEditView.as_view(), name='product_edit'),
url(r'^admin/producttype/list$', ProductTypeListView.as_view(), name='producttype_list'),
url(r'^admin/producttype/create$', ProductTypeCreateView.as_view(), name='new_producttype'),
url(r'^admin/producttype/(?P<type_id>[0-9]+)$', ProductTypeEditView.as_view(), name='producttype_edit'),
]

View File

@ -16,7 +16,7 @@ import re
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin
from subscription.models import Subscriber
from counter.models import Counter, Customer, Product, Selling, Refilling
from counter.models import Counter, Customer, Product, Selling, Refilling, ProductType
class GetUserForm(forms.Form):
"""
@ -42,7 +42,7 @@ class GetUserForm(forms.Form):
elif cleaned_data['id'] is not None:
user = Customer.objects.filter(user=cleaned_data['id']).first()
if user is None:
raise forms.ValidationError("User not found")
raise forms.ValidationError(_("User not found"))
cleaned_data['user_id'] = user.user.id
return cleaned_data
@ -69,7 +69,6 @@ class CounterMain(DetailView, ProcessFormView, FormMixin):
if self.request.method == 'POST':
self.object = self.get_object()
kwargs = super(CounterMain, self).get_context_data(**kwargs)
# TODO: make some checks on the counter type, in order not to make the AuthenticationForm if there is no need to
kwargs['login_form'] = AuthenticationForm()
kwargs['login_form'].fields['username'].widget.attrs['autofocus'] = True
kwargs['form'] = self.get_form()
@ -353,6 +352,30 @@ class CounterDeleteView(CanEditMixin, DeleteView):
# Product management
class ProductTypeListView(ListView):
"""
A list view for the admins
"""
model = ProductType
template_name = 'counter/producttype_list.jinja'
class ProductTypeCreateView(CreateView):
"""
A create view for the admins
"""
model = ProductType
fields = ['name', 'description', 'icon']
template_name = 'core/create.jinja'
class ProductTypeEditView(UpdateView):
"""
An edit view for the admins
"""
model = ProductType
template_name = 'core/edit.jinja'
fields = ['name', 'description', 'icon']
pk_url_kwarg = "type_id"
class ProductListView(ListView):
"""
A list view for the admins
@ -365,15 +388,17 @@ class ProductCreateView(CreateView):
A create view for the admins
"""
model = Product
template_name = 'core/edit.jinja'
fields = ['name', 'description', 'product_type', 'code', 'purchase_price',
'selling_price', 'special_selling_price', 'icon', 'club']
template_name = 'core/create.jinja'
class ProductEditView(UpdateView):
"""
An edit view for the admins
"""
model = Product
form_class = modelform_factory(Product, fields=['name', 'description', 'product_type', 'code', 'purchase_price',
'selling_price', 'special_selling_price', 'icon', 'club'])
fields = ['name', 'description', 'product_type', 'code', 'purchase_price',
'selling_price', 'special_selling_price', 'icon', 'club']
pk_url_kwarg = "product_id"
template_name = 'core/edit.jinja'
# TODO: add management of the 'counters' ForeignKey
@ -391,8 +416,8 @@ class UserAccountView(DetailView):
def dispatch(self, request, *arg, **kwargs):
res = super(UserAccountView, self).dispatch(request, *arg, **kwargs)
if (self.object.user == request.user
or request.user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name'])
or request.user.is_in_group(settings.SITH_GROUPS['root']['name'])):
or request.user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name'])
or request.user.is_in_group(settings.SITH_GROUPS['root']['name'])):
return res
raise PermissionDenied

Binary file not shown.

View File

@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-07-27 00:05+0200\n"
"POT-Creation-Date: 2016-07-27 19:57+0200\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia <skia@libskia.so>\n"
"Language-Team: AE info <ae.info@utbm.fr>\n"
@ -17,8 +17,8 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: accounting/models.py:32 accounting/models.py:55 accounting/models.py:94
#: club/models.py:18 counter/models.py:38 counter/models.py:57
#: counter/models.py:79
#: club/models.py:18 counter/models.py:38 counter/models.py:63
#: counter/models.py:91
msgid "name"
msgstr "nom"
@ -30,11 +30,11 @@ msgstr "IBAN"
msgid "account number"
msgstr "numero de compte"
#: accounting/models.py:92 club/models.py:109 counter/models.py:216
#: accounting/models.py:92 club/models.py:109 counter/models.py:237
msgid "start date"
msgstr "date de début"
#: accounting/models.py:93 club/models.py:110 counter/models.py:217
#: accounting/models.py:93 club/models.py:110 counter/models.py:238
msgid "end date"
msgstr "date de fin"
@ -43,7 +43,7 @@ msgid "is closed"
msgstr "est fermé"
#: accounting/models.py:97 accounting/models.py:136 counter/models.py:21
#: counter/models.py:164
#: counter/models.py:179
msgid "amount"
msgstr "montant"
@ -55,8 +55,8 @@ msgstr "montant effectif"
msgid "number"
msgstr "numéro"
#: accounting/models.py:137 core/models.py:462 counter/models.py:167
#: counter/models.py:195 eboutic/models.py:13 eboutic/models.py:46
#: accounting/models.py:137 core/models.py:463 counter/models.py:182
#: counter/models.py:213 eboutic/models.py:13 eboutic/models.py:46
msgid "date"
msgstr "date"
@ -68,7 +68,7 @@ msgstr "intitulé"
msgid "remark"
msgstr "remarque"
#: accounting/models.py:140 counter/models.py:168 eboutic/models.py:48
#: accounting/models.py:140 counter/models.py:183 eboutic/models.py:48
#: subscription/models.py:34
msgid "payment method"
msgstr "méthode de paiement"
@ -90,7 +90,7 @@ msgstr ""
"La date ne peut pas être avant la date de début du journal, qui est\n"
"%(start_date)s."
#: accounting/models.py:197 counter/models.py:60
#: accounting/models.py:197 counter/models.py:66
msgid "code"
msgstr "code"
@ -114,12 +114,12 @@ msgstr "Il n'y a pas de types comptable dans ce site web."
#: accounting/templates/accounting/bank_account_details.jinja:5
#: accounting/templates/accounting/club_account_details.jinja:5
#: accounting/templates/accounting/journal_details.jinja:5
#: core/templates/core/user_tools.jinja:36
#: core/templates/core/user_tools.jinja:38
msgid "Accounting"
msgstr "Comptabilité"
#: accounting/templates/accounting/bank_account_details.jinja:8
#: core/templates/core/user_tools.jinja:43
#: core/templates/core/user_tools.jinja:45
msgid "Bank account: "
msgstr "Compte en banque : "
@ -146,7 +146,7 @@ msgstr "Nouveau compte club"
#: accounting/templates/accounting/journal_details.jinja:51
#: club/templates/club/club_detail.jinja:7 core/templates/core/page.jinja:31
#: core/templates/core/user_base.jinja:8
#: core/templates/core/user_tools.jinja:30
#: core/templates/core/user_tools.jinja:32
#: counter/templates/counter/counter_list.jinja:15
#: counter/templates/counter/counter_list.jinja:18
msgid "Edit"
@ -323,7 +323,7 @@ msgid "role"
msgstr "rôle"
#: club/models.py:113 core/models.py:27 counter/models.py:39
#: counter/models.py:58
#: counter/models.py:64
msgid "description"
msgstr "description"
@ -396,7 +396,7 @@ msgid "Add"
msgstr "Ajouter"
#: club/templates/club/club_tools.jinja:4
#: core/templates/core/user_tools.jinja:54
#: core/templates/core/user_tools.jinja:56
msgid "Club tools"
msgstr "Outils club"
@ -507,10 +507,14 @@ msgid "Loop in page tree"
msgstr "Boucle dans l'arborescence des pages"
#: core/models.py:460
msgid "revision"
msgstr "révision"
#: core/models.py:461
msgid "page title"
msgstr "titre de la page"
#: core/models.py:461
#: core/models.py:462
msgid "page content"
msgstr "contenu de la page"
@ -563,13 +567,17 @@ msgstr "Pages"
msgid "Clubs"
msgstr "Clubs"
#: core/templates/core/base.jinja:45
#: core/templates/core/base.jinja:33
msgid "Services"
msgstr "Services"
#: core/templates/core/base.jinja:46
msgid "Site made by good people"
msgstr "Site réalisé par des gens biens"
#: core/templates/core/create.jinja:4
msgid "Create"
msgstr "Créer"
msgid "Create %(name)s"
msgstr "Créer %(name)s"
#: core/templates/core/delete_confirm.jinja:4
msgid "Delete confirmation"
@ -676,15 +684,19 @@ msgstr ""
"Ceci n'est peut-être pas la dernière version de la page. Vous consultez la "
"version %(rev_id)s."
#: core/templates/core/page_hist.jinja:4
#: core/templates/core/page_hist.jinja:6
msgid "Page history"
msgstr "Historique de la page"
#: core/templates/core/page_hist.jinja:5
#: core/templates/core/page_hist.jinja:7
#, python-format
msgid "You're seeing the history of page \"%(page_name)s\""
msgstr "Vous consultez l'historique de la page \"%(page_name)s\""
#: core/templates/core/page_hist.jinja:11
msgid "last"
msgstr "actuel"
#: core/templates/core/page_list.jinja:16
msgid "There is no page in this website."
msgstr "Il n'y a pas de page sur ce site web."
@ -874,11 +886,19 @@ msgstr "Comptoirs"
msgid "General counters management"
msgstr "Gestion générale des comptoirs"
#: core/templates/core/user_tools.jinja:39
#: core/templates/core/user_tools.jinja:26
msgid "Products management"
msgstr "Gestion des produits"
#: core/templates/core/user_tools.jinja:27
msgid "Products type management"
msgstr "Gestion des types de produit"
#: core/templates/core/user_tools.jinja:41
msgid "General accounting"
msgstr "Comptabilité générale"
#: core/templates/core/user_tools.jinja:47
#: core/templates/core/user_tools.jinja:49
msgid "Club account: "
msgstr "Compte club : "
@ -894,48 +914,72 @@ msgstr "client"
msgid "customers"
msgstr "clients"
#: counter/models.py:61
#: counter/models.py:43 eboutic/models.py:77
msgid "product type"
msgstr "type du produit"
#: counter/models.py:67
msgid "purchase price"
msgstr "prix d'achat"
#: counter/models.py:62
#: counter/models.py:68
msgid "selling price"
msgstr "prix de vente"
#: counter/models.py:63
#: counter/models.py:69
msgid "special selling price"
msgstr "prix de vente spécial"
#: counter/models.py:82 subscription/models.py:29
#: counter/models.py:74
msgid "product"
msgstr "produit"
#: counter/models.py:94 subscription/models.py:29
msgid "subscription type"
msgstr "type d'inscription"
#: counter/models.py:84
#: counter/models.py:96
msgid "Bar"
msgstr "Bar"
#: counter/models.py:84
#: counter/models.py:96
msgid "Office"
msgstr "Bureau"
#: counter/models.py:84 eboutic/templates/eboutic/eboutic_main.jinja:20
#: counter/models.py:96 eboutic/templates/eboutic/eboutic_main.jinja:20
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:4
#: eboutic/templates/eboutic/eboutic_payment_result.jinja:4
msgid "Eboutic"
msgstr "Eboutic"
#: counter/models.py:170
#: counter/models.py:102
msgid "counter"
msgstr "comptoir"
#: counter/models.py:185
msgid "bank"
msgstr "banque"
#: counter/models.py:191 eboutic/models.py:78
#: counter/models.py:189
msgid "refilling"
msgstr "rechargement"
#: counter/models.py:209 eboutic/models.py:78
msgid "unit price"
msgstr "prix unitaire"
#: counter/models.py:192 eboutic/models.py:79
#: counter/models.py:210 eboutic/models.py:79
msgid "quantity"
msgstr "quantité"
#: counter/models.py:216
msgid "selling"
msgstr "vente"
#: counter/models.py:241
msgid "permanency"
msgstr "permanence"
#: counter/templates/counter/counter_click.jinja:20
msgid "Counter"
msgstr "Comptoir"
@ -1040,6 +1084,32 @@ msgstr "Merci de vous identifier"
msgid "Barman: "
msgstr "Barman : "
#: counter/templates/counter/product_list.jinja:4
#: counter/templates/counter/product_list.jinja:10
msgid "Product list"
msgstr "Liste des produits"
#: counter/templates/counter/product_list.jinja:8
msgid "New product"
msgstr "Nouveau produit"
#: counter/templates/counter/product_list.jinja:17
msgid "There is no products in this website."
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:10
msgid "Product type list"
msgstr "Liste des types de produit"
#: counter/templates/counter/producttype_list.jinja:8
msgid "New product type"
msgstr "Nouveau type de produit"
#: counter/templates/counter/producttype_list.jinja:17
msgid "There is no product types in this website."
msgstr "Il n'y a pas de types de produit dans ce site web."
#: counter/templates/counter/user_account.jinja:4
#, python-format
msgid "%(user_name)s's account"
@ -1082,15 +1152,19 @@ msgstr "Factures"
msgid "Items"
msgstr "Articles"
#: counter/views.py:208
#: counter/views.py:45
msgid "User not found"
msgstr "Utilisateur non trouvé"
#: counter/views.py:207
msgid "END"
msgstr "FIN"
#: counter/views.py:210
#: counter/views.py:209
msgid "CAN"
msgstr "ANN"
#: counter/views.py:240
#: counter/views.py:239
msgid "You have not enough money to buy all the basket"
msgstr "Vous n'avez pas assez d'argent pour acheter le panier"
@ -1118,10 +1192,6 @@ msgstr "ID du produit"
msgid "product name"
msgstr "nom du produit"
#: eboutic/models.py:77
msgid "product type"
msgstr "type du produit"
#: eboutic/models.py:88
msgid "basket"
msgstr "panier"
@ -1141,7 +1211,9 @@ msgstr "Payer avec une carte banquaire"
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:34
msgid ""
"AE account payment disabled because your basket contains refilling items."
msgstr "Paiement par compte AE désactivé parce que votre panier contient des bons de rechargement."
msgstr ""
"Paiement par compte AE désactivé parce que votre panier contient des bons de "
"rechargement."
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:39
msgid "Pay with Sith account"
@ -1268,6 +1340,9 @@ msgid "You must either choose an existing user or create a new one properly"
msgstr ""
"Vous devez soit choisir un utilisateur existant, ou en créer un proprement."
#~ msgid "Create"
#~ msgstr "Créer"
#~ msgid "%(c)s counter"
#~ msgstr "Comptoir %(c)s"