Improve counter app and migrate products/producttypes/refillings/sellings

This commit is contained in:
Skia 2016-08-18 03:04:50 +02:00
parent d4f87e7581
commit 84364d9018
14 changed files with 337 additions and 50 deletions

View File

@ -22,7 +22,7 @@
{% for i in customer.refillings.all() %}
<tr>
<td>{{ i.date|localtime|date(DATETIME_FORMAT) }} - {{ i.date|localtime|time(DATETIME_FORMAT) }}</td>
<td>{{ i.operator }}</td>
<td><a href="{{ i.operator.get_absolute_url() }}">{{ i.operator.get_display_name() }}</a></td>
<td>{{ i.amount }} €</td>
</tr>
{% endfor %}

View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('counter', '0003_auto_20160814_1634'),
]
operations = [
migrations.AlterField(
model_name='counter',
name='type',
field=models.CharField(choices=[('BAR', 'Bar'), ('OFFICE', 'Office'), ('EBOUTIC', 'Eboutic')], verbose_name='counter type', max_length=255),
),
migrations.AlterField(
model_name='refilling',
name='bank',
field=models.CharField(default='OTHER', choices=[('OTHER', 'Autre'), ('SOCIETE-GENERALE', 'Société générale'), ('BANQUE-POPULAIRE', 'Banque populaire'), ('BNP', 'BNP'), ('CAISSE-EPARGNE', "Caisse d'épargne"), ('CIC', 'CIC'), ('CREDIT-AGRICOLE', 'Crédit Agricole'), ('CREDIT-MUTUEL', 'Credit Mutuel'), ('CREDIT-LYONNAIS', 'Credit Lyonnais'), ('LA-POSTE', 'La Poste')], verbose_name='bank', max_length=255),
),
migrations.AlterField(
model_name='refilling',
name='payment_method',
field=models.CharField(default='CASH', choices=[('CHECK', 'Check'), ('CASH', 'Cash')], verbose_name='payment method', max_length=255),
),
]

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('counter', '0004_auto_20160817_1655'),
]
operations = [
migrations.AlterField(
model_name='product',
name='code',
field=models.CharField(verbose_name='code', max_length=10, blank=True),
),
migrations.AlterField(
model_name='product',
name='name',
field=models.CharField(verbose_name='name', max_length=64),
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('counter', '0005_auto_20160817_2251'),
]
operations = [
migrations.AlterField(
model_name='product',
name='code',
field=models.CharField(blank=True, max_length=16, verbose_name='code'),
),
]

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('club', '0004_auto_20160813_1551'),
('counter', '0006_auto_20160817_2253'),
]
operations = [
migrations.AddField(
model_name='selling',
name='club',
field=models.ForeignKey(default=1, related_name='sellings', to='club.Club'),
preserve_default=False,
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('counter', '0007_selling_club'),
]
operations = [
migrations.AlterField(
model_name='selling',
name='label',
field=models.CharField(max_length=64, verbose_name='label'),
),
]

View File

@ -74,10 +74,10 @@ class Product(models.Model):
"""
This describes a product, with all its related informations
"""
name = models.CharField(_('name'), max_length=30)
name = models.CharField(_('name'), max_length=64)
description = models.TextField(_('description'), blank=True)
product_type = models.ForeignKey(ProductType, related_name='products', null=True, blank=True)
code = models.CharField(_('code'), max_length=10)
code = models.CharField(_('code'), max_length=16, blank=True)
purchase_price = CurrencyField(_('purchase price'))
selling_price = CurrencyField(_('selling price'))
special_selling_price = CurrencyField(_('special selling price'))
@ -105,7 +105,7 @@ class Counter(models.Model):
name = models.CharField(_('name'), max_length=30)
club = models.ForeignKey(Club, related_name="counters")
products = models.ManyToManyField(Product, related_name="counters", blank=True)
type = models.CharField(_('subscription type'),
type = models.CharField(_('counter type'),
max_length=255,
choices=[('BAR',_('Bar')), ('OFFICE',_('Office')), ('EBOUTIC',_('Eboutic'))])
sellers = models.ManyToManyField(Subscriber, verbose_name=_('sellers'), related_name='counters', blank=True)
@ -208,9 +208,9 @@ class Refilling(models.Model):
customer = models.ForeignKey(Customer, related_name="refillings", blank=False)
date = models.DateTimeField(_('date'), auto_now=True)
payment_method = models.CharField(_('payment method'), max_length=255,
choices=settings.SITH_COUNTER_PAYMENT_METHOD, default='cash')
choices=settings.SITH_COUNTER_PAYMENT_METHOD, default='CASH')
bank = models.CharField(_('bank'), max_length=255,
choices=settings.SITH_COUNTER_BANK, default='other')
choices=settings.SITH_COUNTER_BANK, default='OTHER')
is_validated = models.BooleanField(_('is validated'), default=False)
class Meta:
@ -234,9 +234,10 @@ class Selling(models.Model):
"""
Handle the sellings
"""
label = models.CharField(_("label"), max_length=30)
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)
unit_price = CurrencyField(_('unit price'))
quantity = models.IntegerField(_('quantity'))
seller = models.ForeignKey(User, related_name="sellings_as_operator", blank=False)

View File

@ -1,13 +0,0 @@
{% extends "core/base.jinja" %}
{% block content %}
<h2>{% trans %}Edit counter{% endtrans %}</h2>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
{% endblock %}

View File

@ -242,7 +242,7 @@ class CounterClick(DetailView):
if uprice * infos['qty'] > self.customer.amount:
raise DataError(_("You have not enough money to buy all the basket"))
request.session['last_basket'].append("%d x %s" % (infos['qty'], p.name))
s = Selling(label=p.name, product=p, counter=self.object, unit_price=uprice,
s = Selling(label=p.name, product=p, club=p.club, counter=self.object, unit_price=uprice,
quantity=infos['qty'], seller=self.operator, customer=self.customer)
s.save()
request.session['last_customer'] = self.customer.user.get_display_name()
@ -336,7 +336,7 @@ class CounterEditView(CanEditPropMixin, UpdateView):
'products':CheckboxSelectMultiple,
'sellers':CheckboxSelectMultiple})
pk_url_kwarg = "counter_id"
template_name = 'counter/counter_edit.jinja'
template_name = 'core/edit.jinja'
class CounterCreateView(CanEditMixin, CreateView):
"""
@ -345,7 +345,7 @@ class CounterCreateView(CanEditMixin, CreateView):
model = Counter
form_class = modelform_factory(Counter, fields=['name', 'club', 'type', 'products'],
widgets={'products':CheckboxSelectMultiple})
template_name = 'counter/counter_edit.jinja'
template_name = 'core/create.jinja'
class CounterDeleteView(CanEditMixin, DeleteView):
"""

View File

@ -291,7 +291,7 @@ class ClickTokenForm(forms.BaseForm):
t.borrow_date = datetime.now().replace(tzinfo=pytz.UTC)
t.save()
price = settings.SITH_LAUNDERETTE_PRICES[t.type]
s = Selling(label="Jeton "+t.get_type_display()+""+t.name, product=None, counter=counter, unit_price=price,
s = Selling(label="Jeton "+t.get_type_display()+""+t.name, club=counter.club, product=None, counter=counter, unit_price=price,
quantity=1, seller=operator, customer=customer)
s.save()
total += price

Binary file not shown.

View File

@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-08-14 16:36+0200\n"
"POT-Creation-Date: 2016-08-15 21:41+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"
@ -444,11 +444,11 @@ msgstr "Éditer le club"
#: club/templates/club/club_edit.jinja:8
#: club/templates/club/club_edit_prop.jinja:8
#: core/templates/core/create.jinja:8 core/templates/core/edit.jinja:12
#: 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:12
#: subscription/templates/subscription/subscription.jinja:22
msgid "Save"
msgstr "Sauver"
@ -929,11 +929,11 @@ msgstr "Clubs"
msgid "Services"
msgstr "Services"
#: core/templates/core/base.jinja:55
#: core/templates/core/base.jinja:56
msgid "Site made by good people"
msgstr "Site réalisé par des gens bons"
#: core/templates/core/create.jinja:4
#: core/templates/core/create.jinja:4 core/templates/core/create.jinja.py:8
#, python-format
msgid "Create %(name)s"
msgstr "Créer %(name)s"
@ -1274,10 +1274,12 @@ msgstr "Profil de %(user_name)s"
#: core/templates/core/user_detail.jinja:12
#: core/templates/core/user_edit.jinja:15
#: core/templates/core/user_mini.jinja:4
msgid "Profile"
msgstr "Profil"
#: core/templates/core/user_detail.jinja:21
#: core/templates/core/user_mini.jinja:12
msgid "Born: "
msgstr "Né le : "
@ -1286,6 +1288,7 @@ msgid "Option: "
msgstr "Filière : "
#: core/templates/core/user_detail.jinja:32
#: core/templates/core/user_mini.jinja:16
msgid "Promo: "
msgstr "Promo : "
@ -1476,9 +1479,9 @@ msgstr "prix de vente spécial"
msgid "product"
msgstr "produit"
#: counter/models.py:108 subscription/models.py:29
msgid "subscription type"
msgstr "type d'inscription"
#: counter/models.py:108
msgid "counter type"
msgstr "type de comptoir"
#: counter/models.py:110
msgid "Bar"
@ -1999,6 +2002,10 @@ msgstr "Mauvais type de cotisation"
msgid "Bad payment method"
msgstr "Mauvais type de paiement"
#: subscription/models.py:29
msgid "subscription type"
msgstr "type d'inscription"
#: subscription/models.py:32
msgid "subscription start"
msgstr "début de la cotisation"

View File

@ -3,6 +3,7 @@ import os
import django
import random
from io import StringIO
from pytz import timezone
os.environ["DJANGO_SETTINGS_MODULE"] = "sith.settings"
os.environ['DJANGO_COLORS'] = 'nocolor'
@ -12,11 +13,12 @@ from django.db import IntegrityError
from django.conf import settings
from django.core.management import call_command
from django.db import connection
from django.forms import ValidationError
from core.models import User, SithFile
from club.models import Club, Membership
from counter.models import Customer
from counter.models import Customer, Counter, Selling, Refilling, Product, ProductType
from subscription.models import Subscription, Subscriber
db = MySQLdb.connect(
@ -85,7 +87,7 @@ def migrate_users():
email = "no_email_%s@git.an" % random.randrange(4000, 40000)
return email
c = db.cursor(MySQLdb.cursors.DictCursor)
c = db.cursor(MySQLdb.cursors.SSDictCursor)
c.execute("""
SELECT *
FROM utilisateurs utl
@ -97,7 +99,7 @@ def migrate_users():
ON uxtra.id_utilisateur = utl.id_utilisateur
LEFT JOIN loc_ville ville
ON utl.id_ville = ville.id_ville
-- WHERE utl.id_utilisateur = 9248
-- WHERE utl.id_utilisateur = 9360
""")
User.objects.filter(id__gt=0).delete()
print("Users deleted")
@ -178,7 +180,7 @@ def migrate_profile_pict():
print(repr(e))
def migrate_clubs():
cur = db.cursor(MySQLdb.cursors.DictCursor)
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM asso asso
@ -213,7 +215,7 @@ def migrate_clubs():
cur.close()
def migrate_club_memberships():
cur = db.cursor(MySQLdb.cursors.DictCursor)
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM asso_membre
@ -268,7 +270,7 @@ def migrate_subscriptions():
5: "EBOUTIC",
0: "OTHER",
}
cur = db.cursor(MySQLdb.cursors.DictCursor)
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM ae_cotisations
@ -297,7 +299,7 @@ def migrate_subscriptions():
cur.close()
def update_customer_account():
cur = db.cursor(MySQLdb.cursors.DictCursor)
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM ae_carte carte
@ -314,13 +316,185 @@ def update_customer_account():
print("FAIL to update customer account for %s: %s" % (r['id_cotisation'], repr(e)))
cur.close()
def migrate_counters():
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM cpt_comptoir
""")
Counter.objects.all().delete()
for r in cur.fetchall():
try:
club = Club.objects.filter(id=r['id_assocpt']).first()
new = Counter(
id=r['id_comptoir'],
name=to_unicode(r['nom_cpt']),
club=club,
type="OFFICE",
)
new.save()
except Exception as e:
print("FAIL to migrate counter %s: %s" % (r['id_comptoir'], repr(e)))
cur.close()
def migrate_refillings():
BANK = {
0: "OTHER",
1: "SOCIETE-GENERALE",
2: "BANQUE-POPULAIRE",
3: "BNP",
4: "CAISSE-EPARGNE",
5: "CIC",
6: "CREDIT-AGRICOLE",
7: "CREDIT-MUTUEL",
8: "CREDIT-LYONNAIS",
9: "LA-POSTE",
100: "OTHER",
None: "OTHER",
}
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM cpt_rechargements
""")
Refilling.objects.all().delete()
print("Refillings deleted")
for c in Customer.objects.all():
c.amount = 0
c.save()
print("Customer amount reset")
fail = 100
root_cust = Customer.objects.filter(user__id=0).first()
mde = Counter.objects.filter(id=1).first()
for r in cur.fetchall():
try:
cust = Customer.objects.filter(user__id=r['id_utilisateur']).first()
user = User.objects.filter(id=r['id_utilisateur']).first()
if not cust:
if not user:
cust = root_cust
else:
cust = Customer(user=user, amount=0, account_id=Customer.generate_account_id(fail))
cust.save()
fail += 1
op = User.objects.filter(id=r['id_utilisateur_operateur']).first()
counter = Counter.objects.filter(id=r['id_comptoir']).first()
new = Refilling(
id=r['id_rechargement'],
counter=counter or mde,
customer=cust,
operator=op or root_cust.user,
amount=r['montant_rech']/100,
bank=BANK[r['banque_rech']],
)
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)))
cur.close()
def migrate_typeproducts():
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM cpt_type_produit
""")
ProductType.objects.all().delete()
print("Product types deleted")
for r in cur.fetchall():
try:
new = ProductType(
id=r['id_typeprod'],
name=to_unicode(r['nom_typeprod']),
description=to_unicode(r['description_typeprod']),
)
new.save()
except Exception as e:
print("FAIL to migrate product type %s: %s" % (r['nom_typeprod'], repr(e)))
cur.close()
def migrate_products():
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM cpt_produits
""")
Product.objects.all().delete()
print("Product deleted")
for r in cur.fetchall():
try:
type = ProductType.objects.filter(id=r['id_typeprod']).first()
club = Club.objects.filter(id=r['id_assocpt']).first()
new = Product(
id=r['id_produit'],
product_type=type,
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'],
club=club,
)
new.save()
except Exception as e:
print("FAIL to migrate product %s: %s" % (r['nom_prod'], repr(e)))
cur.close()
def migrate_sellings():
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 = 'AE'
""")
Selling.objects.all().delete()
print("Selling deleted")
for r in cur:
try:
product = Product.objects.filter(id=r['id_produit']).first()
club = Club.objects.filter(id=r['id_assocpt']).first()
counter = Counter.objects.filter(id=r['id_comptoir']).first()
op = User.objects.filter(id=r['id_utilisateur']).first()
customer = Customer.objects.filter(user__id=r['id_utilisateur_client']).first()
new = Selling(
label=product.name,
counter=counter,
club=club,
product=product,
seller=op,
customer=customer,
unit_price=r['prix_unit']/100,
quantity=r['quantite'],
)
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))
except Exception as e:
print("FAIL to migrate selling %s: %s" % (r['id_facture'], repr(e)))
cur.close()
def main():
migrate_users()
migrate_profile_pict()
migrate_clubs()
migrate_club_memberships()
migrate_subscriptions()
update_customer_account()
# migrate_users()
# migrate_profile_pict()
# migrate_clubs()
# migrate_club_memberships()
# migrate_subscriptions()
# update_customer_account()
# migrate_counters()
migrate_refillings()
migrate_typeproducts()
migrate_products()
migrate_sellings()
if __name__ == "__main__":
main()

View File

@ -273,9 +273,9 @@ SITH_SUBSCRIPTION_LOCATIONS = [
]
SITH_COUNTER_BARS = [
(1, "Foyer"),
(2, "MDE"),
(3, "La Gommette"),
(1, "MDE"),
(2, "Foyer"),
(35, "La Gommette"),
]
SITH_COUNTER_PAYMENT_METHOD = [
@ -285,9 +285,15 @@ SITH_COUNTER_PAYMENT_METHOD = [
SITH_COUNTER_BANK = [
('OTHER', 'Autre'),
('LA-POSTE', 'La Poste'),
('CREDIT-AGRICOLE', 'Credit Agricole'),
('SOCIETE-GENERALE', 'Société générale'),
('BANQUE-POPULAIRE', 'Banque populaire'),
('BNP', 'BNP'),
('CAISSE-EPARGNE', 'Caisse d\'épargne'),
('CIC', 'CIC'),
('CREDIT-AGRICOLE', 'Crédit Agricole'),
('CREDIT-MUTUEL', 'Credit Mutuel'),
('CREDIT-LYONNAIS', 'Credit Lyonnais'),
('LA-POSTE', 'La Poste'),
]
# Subscription durations are in semestres