diff --git a/core/templates/core/user_account.jinja b/core/templates/core/user_account.jinja index 50a4d8ab..ca5093f5 100644 --- a/core/templates/core/user_account.jinja +++ b/core/templates/core/user_account.jinja @@ -14,48 +14,56 @@ {% trans %}Date{% endtrans %} + {% trans %}Counter{% endtrans %} {% trans %}Barman{% endtrans %} {% trans %}Amount{% endtrans %} + {% trans %}Payment method{% endtrans %} - {% for i in customer.refillings.all() %} + {% for i in customer.refillings.order_by('-date').all() %} {{ i.date|localtime|date(DATETIME_FORMAT) }} - {{ i.date|localtime|time(DATETIME_FORMAT) }} + {{ i.counter }} {{ i.operator.get_display_name() }} {{ i.amount }} € + {{ i.get_payment_method_display() }} {% endfor %} {% endif %} {% if customer.buyings.exists() %} -

{% trans %}Buyings{% endtrans %}

+

{% trans %}Account buyings{% endtrans %}

+ + - {% for i in customer.buyings.all() %} + {% for i in customer.buyings.order_by('-date').all() %} - + + + {% endfor %}
{% trans %}Date{% endtrans %}{% trans %}Counter{% endtrans %} {% trans %}Barman{% endtrans %} {% trans %}Label{% endtrans %} {% trans %}Quantity{% endtrans %} {% trans %}Total{% endtrans %}{% trans %}Payment method{% endtrans %}
{{ i.date|localtime|date(DATETIME_FORMAT) }} - {{ i.date|localtime|time(DATETIME_FORMAT) }}{{ i.seller }}{{ i.counter }}{{ i.seller.get_display_name() }} {{ i.label }} {{ i.quantity }} {{ i.quantity * i.unit_price }} €{{ i.get_payment_method_display() }}
{% endif %} {% if customer.user.invoices.exists() %} -

{% trans %}Invoices{% endtrans %}

+

{% trans %}Eboutic invoices{% endtrans %}

@@ -65,7 +73,7 @@ - {% for i in customer.user.invoices.all() %} + {% for i in customer.user.invoices.order_by('-date').all() %}
{{ i.date|localtime|date(DATETIME_FORMAT) }} - {{ i.date|localtime|time(DATETIME_FORMAT) }} diff --git a/counter/migrations/0009_auto_20160818_1709.py b/counter/migrations/0009_auto_20160818_1709.py new file mode 100644 index 00000000..f6c9ccbf --- /dev/null +++ b/counter/migrations/0009_auto_20160818_1709.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('counter', '0008_auto_20160818_0231'), + ] + + operations = [ + migrations.AlterField( + model_name='refilling', + name='payment_method', + field=models.CharField(verbose_name='payment method', default='CASH', choices=[('CHECK', 'Check'), ('CASH', 'Cash'), ('EBOUTIC', 'Eboutic')], max_length=255), + ), + ] diff --git a/counter/migrations/0010_auto_20160818_1716.py b/counter/migrations/0010_auto_20160818_1716.py new file mode 100644 index 00000000..cb92c366 --- /dev/null +++ b/counter/migrations/0010_auto_20160818_1716.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('counter', '0009_auto_20160818_1709'), + ] + + operations = [ + migrations.AlterField( + model_name='refilling', + name='payment_method', + field=models.CharField(default='CASH', max_length=255, verbose_name='payment method', choices=[('CHECK', 'Check'), ('CASH', 'Cash'), ('CARD', 'Credit card')]), + ), + ] diff --git a/counter/migrations/0011_auto_20160818_1722.py b/counter/migrations/0011_auto_20160818_1722.py new file mode 100644 index 00000000..391f475d --- /dev/null +++ b/counter/migrations/0011_auto_20160818_1722.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +from django.conf import settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('counter', '0010_auto_20160818_1716'), + ] + + operations = [ + migrations.AlterField( + model_name='selling', + name='club', + field=models.ForeignKey(related_name='sellings', null=True, on_delete=django.db.models.deletion.SET_NULL, to='club.Club'), + ), + migrations.AlterField( + model_name='selling', + name='counter', + field=models.ForeignKey(related_name='sellings', null=True, on_delete=django.db.models.deletion.SET_NULL, to='counter.Counter'), + ), + migrations.AlterField( + model_name='selling', + name='customer', + field=models.ForeignKey(related_name='buyings', null=True, on_delete=django.db.models.deletion.SET_NULL, to='counter.Customer'), + ), + migrations.AlterField( + model_name='selling', + name='product', + field=models.ForeignKey(related_name='sellings', null=True, on_delete=django.db.models.deletion.SET_NULL, blank=True, to='counter.Product'), + ), + migrations.AlterField( + model_name='selling', + name='seller', + field=models.ForeignKey(related_name='sellings_as_operator', null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/counter/migrations/0012_selling_payment_method.py b/counter/migrations/0012_selling_payment_method.py new file mode 100644 index 00000000..6f56d94e --- /dev/null +++ b/counter/migrations/0012_selling_payment_method.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('counter', '0011_auto_20160818_1722'), + ] + + operations = [ + migrations.AddField( + model_name='selling', + name='payment_method', + field=models.CharField(default='SITH_ACCOUNT', max_length=255, verbose_name='payment method', choices=[('SITH_ACCOUNT', 'Compte AE'), ('CARD', 'Credit card')]), + ), + ] diff --git a/counter/migrations/0013_auto_20160818_1736.py b/counter/migrations/0013_auto_20160818_1736.py new file mode 100644 index 00000000..d509ec9d --- /dev/null +++ b/counter/migrations/0013_auto_20160818_1736.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('counter', '0012_selling_payment_method'), + ] + + operations = [ + migrations.AlterField( + model_name='selling', + name='payment_method', + field=models.CharField(max_length=255, default='SITH_ACCOUNT', verbose_name='payment method', choices=[('SITH_ACCOUNT', 'Sith account'), ('CARD', 'Credit card')]), + ), + ] diff --git a/counter/models.py b/counter/models.py index 7a76c1e3..066f6bbc 100644 --- a/counter/models.py +++ b/counter/models.py @@ -5,7 +5,8 @@ from django.conf import settings from django.core.urlresolvers import reverse from django.forms import ValidationError -from datetime import timedelta +from datetime import timedelta, datetime +from pytz import timezone import random import string @@ -206,7 +207,7 @@ class Refilling(models.Model): amount = CurrencyField(_('amount')) operator = models.ForeignKey(User, related_name="refillings_as_operator", blank=False) customer = models.ForeignKey(Customer, related_name="refillings", blank=False) - date = models.DateTimeField(_('date'), auto_now=True) + date = models.DateTimeField(_('date')) payment_method = models.CharField(_('payment method'), max_length=255, choices=settings.SITH_COUNTER_PAYMENT_METHOD, default='CASH') bank = models.CharField(_('bank'), max_length=255, @@ -223,6 +224,8 @@ class Refilling(models.Model): # return reverse('counter:details', kwargs={'counter_id': self.id}) def save(self, *args, **kwargs): + if not self.date: + self.date = datetime.now().replace(tzinfo=timezone(settings.TIME_ZONE)) self.full_clean() if not self.is_validated: self.customer.amount += self.amount @@ -235,14 +238,16 @@ class Selling(models.Model): Handle the sellings """ label = models.CharField(_("label"), max_length=64) - product = models.ForeignKey(Product, related_name="sellings", null=True, blank=True) - counter = models.ForeignKey(Counter, related_name="sellings", blank=False) - club = models.ForeignKey(Club, related_name="sellings", blank=False) + product = models.ForeignKey(Product, related_name="sellings", null=True, blank=True, on_delete=models.SET_NULL) + counter = models.ForeignKey(Counter, related_name="sellings", null=True, blank=False, on_delete=models.SET_NULL) + club = models.ForeignKey(Club, related_name="sellings", null=True, blank=False, on_delete=models.SET_NULL) unit_price = CurrencyField(_('unit price')) quantity = models.IntegerField(_('quantity')) - seller = models.ForeignKey(User, related_name="sellings_as_operator", blank=False) - customer = models.ForeignKey(Customer, related_name="buyings", blank=False) - date = models.DateTimeField(_('date'), auto_now=True) + seller = models.ForeignKey(User, related_name="sellings_as_operator", null=True, blank=False, on_delete=models.SET_NULL) + customer = models.ForeignKey(Customer, related_name="buyings", null=True, blank=False, on_delete=models.SET_NULL) + date = models.DateTimeField(_('date')) + payment_method = models.CharField(_('payment method'), max_length=255, + choices=[('SITH_ACCOUNT', _('Sith account')), ('CARD', _('Credit card'))], default='SITH_ACCOUNT') is_validated = models.BooleanField(_('is validated'), default=False) class Meta: @@ -253,6 +258,8 @@ class Selling(models.Model): self.quantity*self.unit_price, self.customer.user.get_display_name()) def save(self, *args, **kwargs): + if not self.date: + self.date = datetime.now().replace(tzinfo=timezone(settings.TIME_ZONE)) self.full_clean() if not self.is_validated: self.customer.amount -= self.quantity * self.unit_price diff --git a/counter/views.py b/counter/views.py index 361e4833..f6298df0 100644 --- a/counter/views.py +++ b/counter/views.py @@ -44,7 +44,8 @@ class GetUserForm(forms.Form): elif cleaned_data['id'] is not None: cus = Customer.objects.filter(user=cleaned_data['id']).first() sub = get_subscriber(cus.user) if cus is not None else None - if cus is None or sub is None or (date.today() - sub.subscriptions.last().subscription_end) > timedelta(days=90): + if (cus is None or sub is None or not sub.subscriptions.last() or + (date.today() - sub.subscriptions.last().subscription_end) > timedelta(days=90)): raise forms.ValidationError(_("User not found")) cleaned_data['user_id'] = cus.user.id cleaned_data['user'] = cus.user diff --git a/eboutic/migrations/0002_auto_20160818_1635.py b/eboutic/migrations/0002_auto_20160818_1635.py new file mode 100644 index 00000000..f1a52223 --- /dev/null +++ b/eboutic/migrations/0002_auto_20160818_1635.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('eboutic', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='basketitem', + name='type', + ), + migrations.RemoveField( + model_name='invoiceitem', + name='type', + ), + migrations.AddField( + model_name='basketitem', + name='type_id', + field=models.IntegerField(default=1, verbose_name='product type id'), + preserve_default=False, + ), + migrations.AddField( + model_name='invoiceitem', + name='type_id', + field=models.IntegerField(default=1, verbose_name='product type id'), + preserve_default=False, + ), + ] diff --git a/eboutic/migrations/0003_auto_20160818_1738.py b/eboutic/migrations/0003_auto_20160818_1738.py new file mode 100644 index 00000000..0b72703a --- /dev/null +++ b/eboutic/migrations/0003_auto_20160818_1738.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('eboutic', '0002_auto_20160818_1635'), + ] + + operations = [ + migrations.AlterField( + model_name='invoice', + name='payment_method', + field=models.CharField(verbose_name='payment method', max_length=20, choices=[('CARD', 'Credit card'), ('SITH_ACCOUNT', 'Sith account')]), + ), + ] diff --git a/eboutic/migrations/0004_remove_invoice_payment_method.py b/eboutic/migrations/0004_remove_invoice_payment_method.py new file mode 100644 index 00000000..27241c1e --- /dev/null +++ b/eboutic/migrations/0004_remove_invoice_payment_method.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('eboutic', '0003_auto_20160818_1738'), + ] + + operations = [ + migrations.RemoveField( + model_name='invoice', + name='payment_method', + ), + ] diff --git a/eboutic/models.py b/eboutic/models.py index 58ee1063..2f4bc61b 100644 --- a/eboutic/models.py +++ b/eboutic/models.py @@ -1,8 +1,9 @@ from django.db import models, DataError from django.utils.translation import ugettext_lazy as _ +from django.conf import settings from accounting.models import CurrencyField -from counter.models import Counter, Product, Customer +from counter.models import Counter, Product, Customer, Selling, Refilling from core.models import User class Basket(models.Model): @@ -15,7 +16,7 @@ class Basket(models.Model): def add_product(self, p, q = 1): item = self.items.filter(product_id=p.id).first() if item is None: - BasketItem(basket=self, product_id=p.id, product_name=p.name, type=p.product_type.name, + BasketItem(basket=self, product_id=p.id, product_name=p.name, type_id=p.product_type.id, quantity=q, product_unit_price=p.selling_price).save() else: item.quantity += q @@ -44,10 +45,11 @@ class Invoice(models.Model): """ user = models.ForeignKey(User, related_name='invoices', verbose_name=_('user'), blank=False) date = models.DateTimeField(_('date'), auto_now=True) - payment_method = models.CharField(choices=[('CREDIT_CARD', _('Credit card')), ('SITH_ACCOUNT', _('Sith account'))], - max_length=20, verbose_name=_('payment method')) validated = models.BooleanField(_("validated"), default=False) + def __str__(self): + return "%s - %s - %s" % (self.user, self.get_total(), self.date) + def get_total(self): total = 0 for i in self.items.all(): @@ -59,23 +61,44 @@ class Invoice(models.Model): raise DataError(_("Invoice already validated")) from counter.models import Customer if not Customer.objects.filter(user=self.user).exists(): - number = Customer.objects.last().account_id[:-1] + number = Customer.objects.count() + 1 Customer(user=self.user, account_id=Customer.generate_account_id(number), amount=0).save() - if self.payment_method == "SITH_ACCOUNT": - self.user.customer.amount -= self.get_total() - self.user.customer.save() - else: - for i in self.items.filter(type="REFILLING").all(): - self.user.customer.amount += i.product_unit_price * i.quantity - self.user.customer.save() - + eboutic = Counter.objects.filter(type="EBOUTIC").first() + for i in self.items.all(): + if i.type_id == settings.SITH_COUNTER_PRODUCTTYPE_REFILLING: + new = Refilling( + counter=eboutic, + customer=self.user.customer, + operator=self.user, + amount=i.product_unit_price * i.quantity, + payment_method="CARD", + bank="OTHER", + date=self.date, + ) + new.save() + else: + product = Product.objects.filter(id=i.product_id).first() + new = Selling( + label=i.product_name, + counter=eboutic, + club=product.club, + product=product, + seller=self.user, + customer=self.user.customer, + unit_price=i.product_unit_price, + quantity=i.quantity, + payment_method="CARD", + is_validated=True, + date=self.date, + ) + new.save() self.validated = True self.save() class AbstractBaseItem(models.Model): product_id = models.IntegerField(_('product id')) product_name = models.CharField(_('product name'), max_length=255) - type = models.CharField(_('product type'), max_length=255) + type_id = models.IntegerField(_('product type id')) product_unit_price = CurrencyField(_('unit price')) quantity = models.IntegerField(_('quantity')) diff --git a/eboutic/templates/eboutic/eboutic_main.jinja b/eboutic/templates/eboutic/eboutic_main.jinja index 68d4f7e8..cce2caf3 100644 --- a/eboutic/templates/eboutic/eboutic_main.jinja +++ b/eboutic/templates/eboutic/eboutic_main.jinja @@ -1,5 +1,9 @@ {% extends "core/base.jinja" %} +{% block title %} +{% trans %}Eboutic{% endtrans %} +{% endblock %} + {% macro add_product(id, content) %}
{% csrf_token %} @@ -34,11 +38,14 @@
-

{% trans %}Products: {% endtrans %} - {% for p in eboutic.products.all() %} - {{ add_product(p.id, p.name) }} + {% for t in categories %} + {% if eboutic.products.filter(product_type=t).exists() %} +

{{ t }}
+ {% for p in eboutic.products.filter(product_type=t).all() %} + {{ add_product(p.id, p.name) }} + {% endfor %} + {% endif %} {% endfor %} -

{% endblock %} diff --git a/eboutic/templates/eboutic/eboutic_makecommand.jinja b/eboutic/templates/eboutic/eboutic_makecommand.jinja index 33e93a6c..f60986ce 100644 --- a/eboutic/templates/eboutic/eboutic_makecommand.jinja +++ b/eboutic/templates/eboutic/eboutic_makecommand.jinja @@ -1,5 +1,9 @@ {% extends "core/base.jinja" %} +{% block title %} +{% trans %}Basket state{% endtrans %} +{% endblock %} + {% block content %}

{% trans %}Eboutic{% endtrans %}

@@ -30,7 +34,7 @@ {% endfor %} - {% if basket.items.filter(type="REFILLING").exists() %} + {% if basket.items.filter(type_id=settings.SITH_COUNTER_PRODUCTTYPE_REFILLING).exists() %}

{% trans %}AE account payment disabled because your basket contains refilling items.{% endtrans %}

{% else %}
diff --git a/eboutic/views.py b/eboutic/views.py index 18f5eaae..f698b9b0 100644 --- a/eboutic/views.py +++ b/eboutic/views.py @@ -14,10 +14,9 @@ from django.db import transaction, DataError from django.utils.translation import ugettext as _ from django.conf import settings -from counter.models import Product, Customer, Counter +from counter.models import Product, Customer, Counter, ProductType, Selling from eboutic.models import Basket, Invoice, BasketItem, InvoiceItem -# Create your views here. class EbouticMain(TemplateView): template_name = 'eboutic/eboutic_main.jinja' @@ -72,6 +71,7 @@ class EbouticMain(TemplateView): kwargs = super(EbouticMain, self).get_context_data(**kwargs) kwargs['basket'] = self.basket kwargs['eboutic'] = Counter.objects.filter(type="EBOUTIC").first() + kwargs['categories'] = ProductType.objects.all() return kwargs class EbouticCommand(TemplateView): @@ -125,7 +125,7 @@ class EbouticPayWithSith(TemplateView): if 'basket_id' not in request.session.keys() or not request.user.is_authenticated(): return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs)) b = Basket.objects.filter(id=request.session['basket_id']).first() - if b is None or b.items.filter(type="REFILLING").exists(): + if b is None or b.items.filter(type_id=settings.SITH_COUNTER_PRODUCTTYPE_REFILLING).exists(): return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs)) c = Customer.objects.filter(user__id=b.user.id).first() if c is None: @@ -134,14 +134,20 @@ class EbouticPayWithSith(TemplateView): if c.amount < b.get_total(): raise DataError(_("You do not have enough money to buy the basket")) else: - i = Invoice() - i.user = b.user - i.payment_method = "SITH_ACCOUNT" - i.save() + eboutic = Counter.objects.filter(type="EBOUTIC").first() for it in b.items.all(): - InvoiceItem(invoice=i, product_id=it.product_id, product_name=it.product_name, type=it.type, - product_unit_price=it.product_unit_price, quantity=it.quantity).save() - i.validate() + product = Product.objects.filter(id=it.product_id).first() + Selling( + label=it.product_name, + counter=eboutic, + club=product.club, + product=product, + seller=c.user, + customer=c, + unit_price=it.product_unit_price, + quantity=it.quantity, + payment_method="SITH_ACCOUNT", + ).save() b.delete() kwargs['not_enough'] = False request.session.pop('basket_id', None) @@ -172,10 +178,10 @@ class EtransactionAutoAnswer(View): return HttpResponse("Basket does not exists", status=400) i = Invoice() i.user = b.user - i.payment_method = "CREDIT_CARD" + i.payment_method = "CARD" i.save() for it in b.items.all(): - InvoiceItem(invoice=i, product_id=it.product_id, product_name=it.product_name, type=it.type, + InvoiceItem(invoice=i, product_id=it.product_id, product_name=it.product_name, type_id=it.type_id, product_unit_price=it.product_unit_price, quantity=it.quantity).save() i.validate() b.delete() diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo index 78b0da2a..4600b1d2 100644 Binary files a/locale/fr/LC_MESSAGES/django.mo and b/locale/fr/LC_MESSAGES/django.mo differ diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 114dfca7..464a1138 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-08-15 21:41+0200\n" +"POT-Creation-Date: 2016-08-18 17:40+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -40,12 +40,12 @@ msgstr "numero de compte" msgid "%(club_account)s on %(bank_account)s" msgstr "%(club_account)s sur %(bank_account)s" -#: accounting/models.py:109 club/models.py:147 counter/models.py:268 +#: accounting/models.py:109 club/models.py:147 counter/models.py:271 #: launderette/models.py:122 msgid "start date" msgstr "date de début" -#: accounting/models.py:110 club/models.py:148 counter/models.py:269 +#: accounting/models.py:110 club/models.py:148 counter/models.py:272 msgid "end date" msgstr "date de fin" @@ -67,8 +67,8 @@ msgid "number" msgstr "numéro" #: accounting/models.py:154 core/models.py:404 core/models.py:680 -#: counter/models.py:209 counter/models.py:244 eboutic/models.py:13 -#: eboutic/models.py:46 +#: counter/models.py:209 counter/models.py:245 eboutic/models.py:14 +#: eboutic/models.py:47 msgid "date" msgstr "date" @@ -80,8 +80,8 @@ msgstr "intitulé" msgid "remark" msgstr "remarque" -#: accounting/models.py:157 counter/models.py:210 eboutic/models.py:48 -#: subscription/models.py:34 +#: accounting/models.py:157 counter/models.py:210 counter/models.py:247 +#: eboutic/models.py:49 subscription/models.py:34 msgid "payment method" msgstr "méthode de paiement" @@ -89,7 +89,7 @@ msgstr "méthode de paiement" msgid "cheque number" msgstr "numéro de chèque" -#: accounting/models.py:159 eboutic/models.py:92 +#: accounting/models.py:159 eboutic/models.py:119 msgid "invoice" msgstr "facture" @@ -268,8 +268,8 @@ msgstr "Fin" #: accounting/templates/accounting/club_account_details.jinja:20 #: accounting/templates/accounting/journal_details.jinja:23 -#: core/templates/core/user_account.jinja:18 -#: core/templates/core/user_account.jinja:64 +#: core/templates/core/user_account.jinja:19 +#: core/templates/core/user_account.jinja:72 msgid "Amount" msgstr "Montant" @@ -324,13 +324,13 @@ msgstr "No" #: accounting/templates/accounting/journal_details.jinja:21 #: core/templates/core/user_account.jinja:16 -#: core/templates/core/user_account.jinja:37 -#: core/templates/core/user_account.jinja:62 +#: core/templates/core/user_account.jinja:41 +#: core/templates/core/user_account.jinja:70 msgid "Date" msgstr "Date" #: accounting/templates/accounting/journal_details.jinja:22 -#: core/templates/core/user_account.jinja:39 +#: core/templates/core/user_account.jinja:44 msgid "Label" msgstr "Intitulé" @@ -394,7 +394,7 @@ msgstr "Vous ne pouvez pas faire de boucles dans les clubs" msgid "A club with that unix_name already exists" msgstr "Un club avec ce nom UNIX existe déjà." -#: club/models.py:145 eboutic/models.py:12 eboutic/models.py:45 +#: club/models.py:145 eboutic/models.py:13 eboutic/models.py:46 #: launderette/models.py:89 launderette/models.py:126 msgid "user" msgstr "nom d'utilisateur" @@ -447,7 +447,6 @@ msgstr "Éditer le club" #: core/templates/core/create.jinja:12 core/templates/core/edit.jinja:12 #: core/templates/core/file_edit.jinja:8 core/templates/core/page_prop.jinja:8 #: core/templates/core/pagerev_edit.jinja:24 -#: counter/templates/counter/counter_edit.jinja:8 #: subscription/templates/subscription/subscription.jinja:22 msgid "Save" msgstr "Sauver" @@ -1234,31 +1233,43 @@ msgid "Refillings" msgstr "Rechargements" #: core/templates/core/user_account.jinja:17 -#: core/templates/core/user_account.jinja:38 +#: core/templates/core/user_account.jinja:42 +#: counter/templates/counter/counter_click.jinja:24 +msgid "Counter" +msgstr "Comptoir" + +#: core/templates/core/user_account.jinja:18 +#: core/templates/core/user_account.jinja:43 msgid "Barman" msgstr "Barman" -#: core/templates/core/user_account.jinja:33 -msgid "Buyings" -msgstr "Achats" +#: core/templates/core/user_account.jinja:20 +#: core/templates/core/user_account.jinja:47 +#: core/templates/core/user_account.jinja:73 +msgid "Payment method" +msgstr "Méthode de paiement" -#: core/templates/core/user_account.jinja:40 +#: core/templates/core/user_account.jinja:37 +msgid "Account buyings" +msgstr "Achat sur compte utilisateur" + +#: core/templates/core/user_account.jinja:45 msgid "Quantity" msgstr "Quantité" -#: core/templates/core/user_account.jinja:41 +#: core/templates/core/user_account.jinja:46 msgid "Total" msgstr "Total" -#: core/templates/core/user_account.jinja:58 -msgid "Invoices" -msgstr "Factures" +#: core/templates/core/user_account.jinja:66 +msgid "Eboutic invoices" +msgstr "Facture eboutic" -#: core/templates/core/user_account.jinja:63 +#: core/templates/core/user_account.jinja:71 msgid "Items" msgstr "Articles" -#: core/templates/core/user_account.jinja:85 +#: core/templates/core/user_account.jinja:95 msgid "User has no account" msgstr "L'utilisateur n'a pas de compte" @@ -1459,7 +1470,7 @@ msgstr "clients" msgid "Not enough money" msgstr "Solde insuffisant" -#: counter/models.py:57 eboutic/models.py:78 +#: counter/models.py:57 msgid "product type" msgstr "type du produit" @@ -1491,8 +1502,9 @@ msgstr "Bar" msgid "Office" msgstr "Bureau" -#: counter/models.py:110 eboutic/templates/eboutic/eboutic_main.jinja:20 -#: eboutic/templates/eboutic/eboutic_makecommand.jinja:4 +#: counter/models.py:110 eboutic/templates/eboutic/eboutic_main.jinja:4 +#: eboutic/templates/eboutic/eboutic_main.jinja:24 +#: eboutic/templates/eboutic/eboutic_makecommand.jinja:8 #: eboutic/templates/eboutic/eboutic_payment_result.jinja:4 #: sith/settings.py:279 sith/settings_sample.py:265 msgid "Eboutic" @@ -1510,7 +1522,7 @@ msgstr "comptoir" msgid "bank" msgstr "banque" -#: counter/models.py:214 counter/models.py:245 +#: counter/models.py:214 counter/models.py:246 msgid "is validated" msgstr "est validé" @@ -1518,26 +1530,32 @@ msgstr "est validé" msgid "refilling" msgstr "rechargement" -#: counter/models.py:240 eboutic/models.py:79 +#: counter/models.py:241 eboutic/models.py:106 msgid "unit price" msgstr "prix unitaire" -#: counter/models.py:241 eboutic/models.py:80 +#: counter/models.py:242 eboutic/models.py:107 msgid "quantity" msgstr "quantité" -#: counter/models.py:248 +#: counter/models.py:248 eboutic/models.py:48 +msgid "Sith account" +msgstr "Compte utilisateur" + +#: counter/models.py:248 eboutic/models.py:48 sith/settings.py:272 +#: sith/settings.py:277 sith/settings.py:298 sith/settings_sample.py:258 +#: sith/settings_sample.py:263 sith/settings_sample.py:284 +msgid "Credit card" +msgstr "Carte banquaire" + +#: counter/models.py:251 msgid "selling" msgstr "vente" -#: counter/models.py:272 +#: counter/models.py:275 msgid "permanency" msgstr "permanence" -#: counter/templates/counter/counter_click.jinja:24 -msgid "Counter" -msgstr "Comptoir" - #: counter/templates/counter/counter_click.jinja:26 msgid "Club: " msgstr "Club : " @@ -1563,14 +1581,14 @@ msgid "Selling" msgstr "Vente" #: counter/templates/counter/counter_click.jinja:54 -#: eboutic/templates/eboutic/eboutic_main.jinja:23 -#: eboutic/templates/eboutic/eboutic_makecommand.jinja:7 +#: eboutic/templates/eboutic/eboutic_main.jinja:27 +#: eboutic/templates/eboutic/eboutic_makecommand.jinja:11 msgid "Basket: " msgstr "Panier : " #: counter/templates/counter/counter_click.jinja:62 #: counter/templates/counter/counter_main.jinja:24 -#: eboutic/templates/eboutic/eboutic_main.jinja:30 +#: eboutic/templates/eboutic/eboutic_main.jinja:34 msgid "Total: " msgstr "Total : " @@ -1579,14 +1597,10 @@ msgid "Finish" msgstr "Terminer" #: counter/templates/counter/counter_click.jinja:73 -#: eboutic/templates/eboutic/eboutic_main.jinja:37 +#: eboutic/templates/eboutic/eboutic_main.jinja:41 msgid "Products: " msgstr "Produits : " -#: counter/templates/counter/counter_edit.jinja:4 -msgid "Edit counter" -msgstr "Éditer le comptoir" - #: counter/templates/counter/counter_list.jinja:4 #: counter/templates/counter/counter_list.jinja:10 msgid "Counter admin list" @@ -1664,67 +1678,66 @@ msgstr "Nouveau type de produit" msgid "There is no product types in this website." msgstr "Il n'y a pas de types de produit dans ce site web." -#: counter/views.py:48 +#: counter/views.py:49 msgid "User not found" msgstr "Utilisateur non trouvé" -#: counter/views.py:211 +#: counter/views.py:212 msgid "END" msgstr "FIN" -#: counter/views.py:213 +#: counter/views.py:214 msgid "CAN" msgstr "ANN" -#: counter/views.py:243 +#: counter/views.py:244 msgid "You have not enough money to buy all the basket" msgstr "Vous n'avez pas assez d'argent pour acheter le panier" -#: eboutic/models.py:47 sith/settings.py:272 sith/settings.py:277 -#: sith/settings_sample.py:258 sith/settings_sample.py:263 -msgid "Credit card" -msgstr "Carte banquaire" - -#: eboutic/models.py:47 -msgid "Sith account" -msgstr "Compte utilisateur" - -#: eboutic/models.py:49 +#: eboutic/models.py:50 msgid "validated" msgstr "validé" -#: eboutic/models.py:59 +#: eboutic/models.py:60 msgid "Invoice already validated" msgstr "Facture déjà validée" -#: eboutic/models.py:76 +#: eboutic/models.py:103 msgid "product id" msgstr "ID du produit" -#: eboutic/models.py:77 +#: eboutic/models.py:104 msgid "product name" msgstr "nom du produit" -#: eboutic/models.py:89 +#: eboutic/models.py:105 +msgid "product type id" +msgstr "id du type du produit" + +#: eboutic/models.py:116 msgid "basket" msgstr "panier" -#: eboutic/templates/eboutic/eboutic_main.jinja:33 +#: eboutic/templates/eboutic/eboutic_main.jinja:37 msgid "Proceed to command" msgstr "Procéder à la commande" -#: eboutic/templates/eboutic/eboutic_makecommand.jinja:31 +#: eboutic/templates/eboutic/eboutic_makecommand.jinja:4 +msgid "Basket state" +msgstr "État du panier" + +#: eboutic/templates/eboutic/eboutic_makecommand.jinja:35 msgid "Pay with credit card" msgstr "Payer avec une carte banquaire" -#: eboutic/templates/eboutic/eboutic_makecommand.jinja:34 +#: eboutic/templates/eboutic/eboutic_makecommand.jinja:38 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." -#: eboutic/templates/eboutic/eboutic_makecommand.jinja:39 +#: eboutic/templates/eboutic/eboutic_makecommand.jinja:43 msgid "Pay with Sith account" msgstr "Payer avec un compte AE" @@ -1829,12 +1842,12 @@ msgid "Washing and drying" msgstr "Lavage et séchage" #: launderette/templates/launderette/launderette_book.jinja:26 -#: sith/settings.py:398 sith/settings_sample.py:384 +#: sith/settings.py:408 sith/settings_sample.py:394 msgid "Washing" msgstr "Lavage" #: launderette/templates/launderette/launderette_book.jinja:30 -#: sith/settings.py:398 sith/settings_sample.py:384 +#: sith/settings.py:408 sith/settings_sample.py:394 msgid "Drying" msgstr "Séchage" @@ -1917,80 +1930,80 @@ msgstr "Sevenans" msgid "Montbéliard" msgstr "Montbéliard" -#: sith/settings.py:311 sith/settings_sample.py:297 +#: sith/settings.py:321 sith/settings_sample.py:307 msgid "One semester" msgstr "Un semestre" -#: sith/settings.py:316 sith/settings_sample.py:302 +#: sith/settings.py:326 sith/settings_sample.py:312 msgid "Two semesters" msgstr "Deux semestres" -#: sith/settings.py:321 sith/settings_sample.py:307 +#: sith/settings.py:331 sith/settings_sample.py:317 msgid "Common core cursus" msgstr "Cursus tronc commun" -#: sith/settings.py:326 sith/settings.py:331 sith/settings_sample.py:312 -#: sith/settings_sample.py:317 +#: sith/settings.py:336 sith/settings.py:341 sith/settings_sample.py:322 +#: sith/settings_sample.py:327 msgid "Branch cursus" msgstr "Cursus branche" -#: sith/settings.py:336 sith/settings_sample.py:322 +#: sith/settings.py:346 sith/settings_sample.py:332 msgid "Honorary member" msgstr "Membre honoraire" -#: sith/settings.py:341 sith/settings_sample.py:327 +#: sith/settings.py:351 sith/settings_sample.py:337 msgid "Assidu member" msgstr "Membre d'Assidu" -#: sith/settings.py:346 sith/settings_sample.py:332 +#: sith/settings.py:356 sith/settings_sample.py:342 msgid "Amicale/DOCEO member" msgstr "Membre de l'Amicale/DOCEO" -#: sith/settings.py:351 sith/settings_sample.py:337 +#: sith/settings.py:361 sith/settings_sample.py:347 msgid "UT network member" msgstr "Cotisant du réseau UT" -#: sith/settings.py:356 sith/settings_sample.py:342 +#: sith/settings.py:366 sith/settings_sample.py:352 msgid "CROUS member" msgstr "Membres du CROUS" -#: sith/settings.py:361 sith/settings_sample.py:347 +#: sith/settings.py:371 sith/settings_sample.py:357 msgid "Sbarro/ESTA member" msgstr "Membre de Sbarro ou de l'ESTA" -#: sith/settings.py:369 sith/settings_sample.py:355 +#: sith/settings.py:379 sith/settings_sample.py:365 msgid "President" msgstr "Président" -#: sith/settings.py:370 sith/settings_sample.py:356 +#: sith/settings.py:380 sith/settings_sample.py:366 msgid "Vice-President" msgstr "Vice-Président" -#: sith/settings.py:371 sith/settings_sample.py:357 +#: sith/settings.py:381 sith/settings_sample.py:367 msgid "Treasurer" msgstr "Trésorier" -#: sith/settings.py:372 sith/settings_sample.py:358 +#: sith/settings.py:382 sith/settings_sample.py:368 msgid "Communication supervisor" msgstr "Responsable com" -#: sith/settings.py:373 sith/settings_sample.py:359 +#: sith/settings.py:383 sith/settings_sample.py:369 msgid "Secretary" msgstr "Secrétaire" -#: sith/settings.py:374 sith/settings_sample.py:360 +#: sith/settings.py:384 sith/settings_sample.py:370 msgid "IT supervisor" msgstr "Responsable info" -#: sith/settings.py:375 sith/settings_sample.py:361 +#: sith/settings.py:385 sith/settings_sample.py:371 msgid "Board member" msgstr "Membre du bureau" -#: sith/settings.py:376 sith/settings_sample.py:362 +#: sith/settings.py:386 sith/settings_sample.py:372 msgid "Active member" msgstr "Membre actif" -#: sith/settings.py:377 sith/settings_sample.py:363 +#: sith/settings.py:387 sith/settings_sample.py:373 msgid "Curious" msgstr "Curieux" @@ -2035,5 +2048,3 @@ 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 "User Profile" -#~ msgstr "Profil de l'utilisateur" diff --git a/migrate.py b/migrate.py index fb51f37d..76b61843 100644 --- a/migrate.py +++ b/migrate.py @@ -20,6 +20,7 @@ from core.models import User, SithFile from club.models import Club, Membership from counter.models import Customer, Counter, Selling, Refilling, Product, ProductType from subscription.models import Subscription, Subscriber +from eboutic.models import Invoice, InvoiceItem db = MySQLdb.connect( host="ae-db", @@ -142,7 +143,6 @@ def migrate_users(): except Exception as e: print("FAIL for user %s: %s" % (u['id_utilisateur'], repr(e))) c.close() - reset_index('core') def migrate_profile_pict(): PROFILE_ROOT = "/data/matmatronch/" @@ -357,8 +357,8 @@ def migrate_refillings(): SELECT * FROM cpt_rechargements """) - Refilling.objects.all().delete() - print("Refillings deleted") + Refilling.objects.filter(payment_method="SITH_ACCOUNT").delete() + print("Sith account refillings deleted") for c in Customer.objects.all(): c.amount = 0 c.save() @@ -386,11 +386,8 @@ def migrate_refillings(): operator=op or root_cust.user, amount=r['montant_rech']/100, bank=BANK[r['banque_rech']], + date=r['date_rech'].replace(tzinfo=timezone('Europe/Paris')), ) - for f in new._meta.local_fields: - if f.name == "date": - f.auto_now = False - new.date = r['date_rech'].replace(tzinfo=timezone('Europe/Paris')) new.save() except Exception as e: print("FAIL to migrate refilling %s for %s: %s" % (r['id_rechargement'], r['id_utilisateur'], repr(e))) @@ -434,9 +431,9 @@ def migrate_products(): name=to_unicode(r['nom_prod']), description=to_unicode(r['description_prod']), code=to_unicode(r['cbarre_prod']), - purchase_price=r['prix_achat_prod'], - selling_price=r['prix_vente_prod'], - special_selling_price=r['prix_vente_barman_prod'], + purchase_price=r['prix_achat_prod']/100, + selling_price=r['prix_vente_prod']/100, + special_selling_price=r['prix_vente_barman_prod']/100, club=club, ) new.save() @@ -444,6 +441,62 @@ def migrate_products(): print("FAIL to migrate product %s: %s" % (r['nom_prod'], repr(e))) cur.close() +def migrate_products_to_counter(): + cur = db.cursor(MySQLdb.cursors.SSDictCursor) + cur.execute(""" + SELECT * + FROM cpt_mise_en_vente + """) + for r in cur: + try: + product = Product.objects.filter(id=r['id_produit']).first() + counter = Counter.objects.filter(id=r['id_comptoir']).first() + counter.products.add(product) + counter.save() + except Exception as e: + print("FAIL to set product %s in counter %s: %s" % (product, counter, repr(e))) + cur.close() + +def migrate_invoices(): + cur = db.cursor(MySQLdb.cursors.SSDictCursor) + cur.execute(""" + SELECT * + FROM cpt_vendu ven + LEFT JOIN cpt_debitfacture fac + ON ven.id_facture = fac.id_facture + WHERE fac.mode_paiement = 'SG' + """) + Invoice.objects.all().delete() + print("Invoices deleted") + Refilling.objects.filter(payment_method="CARD").delete() + print("Card refillings deleted") + Selling.objects.filter(payment_method="CARD").delete() + print("Card sellings deleted") + root = User.objects.filter(id=0).first() + for r in cur: + try: + product = Product.objects.filter(id=r['id_produit']).first() + user = User.objects.filter(id=r['id_utilisateur_client']).first() + i = Invoice.objects.filter(id=r['id_facture']).first() or Invoice(id=r['id_facture']) + i.user = user or root + for f in i._meta.local_fields: + if f.name == "date": + f.auto_now = False + i.date = r['date_facture'].replace(tzinfo=timezone('Europe/Paris')) + i.save() + InvoiceItem(invoice=i, product_id=product.id, product_name=product.name, type_id=product.product_type.id, + product_unit_price=r['prix_unit']/100, quantity=r['quantite']).save() + except ValidationError as e: + print(repr(e) + " for %s (%s)" % (customer, customer.user.id)) + except Exception as e: + print("FAIL to migrate invoice %s: %s" % (r['id_facture'], repr(e))) + cur.close() + for i in Invoice.objects.all(): + for f in i._meta.local_fields: + if f.name == "date": + f.auto_now = False + i.validate() + def migrate_sellings(): cur = db.cursor(MySQLdb.cursors.SSDictCursor) cur.execute(""" @@ -453,8 +506,8 @@ def migrate_sellings(): ON ven.id_facture = fac.id_facture WHERE fac.mode_paiement = 'AE' """) - Selling.objects.all().delete() - print("Selling deleted") + Selling.objects.filter(payment_method="SITH_ACCOUNT").delete() + print("Sith account selling deleted") for r in cur: try: product = Product.objects.filter(id=r['id_produit']).first() @@ -471,11 +524,9 @@ def migrate_sellings(): customer=customer, unit_price=r['prix_unit']/100, quantity=r['quantite'], + payment_method="SITH_ACCOUNT", + date=r['date_facture'].replace(tzinfo=timezone('Europe/Paris')), ) - for f in new._meta.local_fields: - if f.name == "date": - f.auto_now = False - new.date = r['date_facture'].replace(tzinfo=timezone('Europe/Paris')) new.save() except ValidationError as e: print(repr(e) + " for %s (%s)" % (customer, customer.user.id)) @@ -483,6 +534,7 @@ def migrate_sellings(): print("FAIL to migrate selling %s: %s" % (r['id_facture'], repr(e))) cur.close() + def main(): # migrate_users() # migrate_profile_pict() @@ -491,10 +543,13 @@ def main(): # migrate_subscriptions() # update_customer_account() # migrate_counters() + # migrate_typeproducts() + # migrate_products() + # migrate_products_to_counter() + migrate_invoices() migrate_refillings() - migrate_typeproducts() - migrate_products() migrate_sellings() + reset_index('core', 'counter') if __name__ == "__main__": main() diff --git a/sith/settings_sample.py b/sith/settings_sample.py index 4262d26e..d7c53edb 100644 --- a/sith/settings_sample.py +++ b/sith/settings_sample.py @@ -281,6 +281,7 @@ SITH_COUNTER_BARS = [ SITH_COUNTER_PAYMENT_METHOD = [ ('CHECK', _('Check')), ('CASH', _('Cash')), + ('CARD', _('Credit card')), ] SITH_COUNTER_BANK = [ @@ -296,6 +297,9 @@ SITH_COUNTER_BANK = [ ('LA-POSTE', 'La Poste'), ] +# Defines which product type is the refilling type, and thus increases the account amount +SITH_COUNTER_PRODUCTTYPE_REFILLING = 11 + # Subscription durations are in semestres # Be careful, modifying this parameter will need a migration to be applied SITH_SUBSCRIPTIONS = {