Add the merge user function

This commit is contained in:
Skia 2016-09-21 14:09:16 +02:00
parent f1e54439e1
commit 9e4e9597d1
15 changed files with 249 additions and 99 deletions

View File

@ -6,7 +6,6 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div id="user_profile_container"> <div id="user_profile_container">
<div id="user_profile"> <div id="user_profile">
<div id="right_column"> <div id="right_column">

View File

@ -12,6 +12,7 @@
<ul> <ul>
{% if user.is_root %} {% if user.is_root %}
<li><a href="{{ url('core:group_list') }}">{% trans %}Groups{% endtrans %}</a></li> <li><a href="{{ url('core:group_list') }}">{% trans %}Groups{% endtrans %}</a></li>
<li><a href="{{ url('rootplace:merge') }}">{% trans %}Merge users{% endtrans %}</a></li>
{% endif %} {% endif %}
{% if user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_root %} {% if user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_root %}
<li><a href="{{ url('subscription:subscription') }}">{% trans %}Subscriptions{% endtrans %}</a></li> <li><a href="{{ url('subscription:subscription') }}">{% trans %}Subscriptions{% endtrans %}</a></li>

View File

@ -44,6 +44,14 @@ class Customer(models.Model):
raise ValidationError(_("Not enough money")) raise ValidationError(_("Not enough money"))
super(Customer, self).save(*args, **kwargs) super(Customer, self).save(*args, **kwargs)
def recompute_amount(self):
self.amount = 0
for r in self.refillings.all():
self.amount += r.amount
for s in self.buyings.filter(payment_method="SITH_ACCOUNT"):
self.amount -= s.quantity * s.unit_price
self.save()
class ProductType(models.Model): class ProductType(models.Model):
""" """
This describes a product type This describes a product type

Binary file not shown.

View File

@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-19 20:31+0200\n" "POT-Creation-Date: 2016-09-21 12:42+0200\n"
"PO-Revision-Date: 2016-07-18\n" "PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia <skia@libskia.so>\n" "Last-Translator: Skia <skia@libskia.so>\n"
"Language-Team: AE info <ae.info@utbm.fr>\n" "Language-Team: AE info <ae.info@utbm.fr>\n"
@ -17,8 +17,8 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: accounting/models.py:36 accounting/models.py:55 accounting/models.py:82 #: accounting/models.py:36 accounting/models.py:55 accounting/models.py:82
#: accounting/models.py:132 club/models.py:19 counter/models.py:52 #: accounting/models.py:132 club/models.py:19 counter/models.py:60
#: counter/models.py:77 counter/models.py:112 launderette/models.py:15 #: counter/models.py:85 counter/models.py:120 launderette/models.py:15
#: launderette/models.py:60 launderette/models.py:85 #: launderette/models.py:60 launderette/models.py:85
msgid "name" msgid "name"
msgstr "nom" msgstr "nom"
@ -64,7 +64,7 @@ msgid "account number"
msgstr "numero de compte" msgstr "numero de compte"
#: accounting/models.py:58 accounting/models.py:83 club/models.py:145 #: accounting/models.py:58 accounting/models.py:83 club/models.py:145
#: counter/models.py:86 counter/models.py:113 #: counter/models.py:94 counter/models.py:121
msgid "club" msgid "club"
msgstr "club" msgstr "club"
@ -85,12 +85,12 @@ msgstr "Compte club"
msgid "%(club_account)s on %(bank_account)s" msgid "%(club_account)s on %(bank_account)s"
msgstr "%(club_account)s sur %(bank_account)s" msgstr "%(club_account)s sur %(bank_account)s"
#: accounting/models.py:130 club/models.py:146 counter/models.py:322 #: accounting/models.py:130 club/models.py:146 counter/models.py:330
#: launderette/models.py:122 #: launderette/models.py:122
msgid "start date" msgid "start date"
msgstr "date de début" msgstr "date de début"
#: accounting/models.py:131 club/models.py:147 counter/models.py:323 #: accounting/models.py:131 club/models.py:147 counter/models.py:331
msgid "end date" msgid "end date"
msgstr "date de fin" msgstr "date de fin"
@ -103,7 +103,7 @@ msgid "club account"
msgstr "compte club" msgstr "compte club"
#: accounting/models.py:135 accounting/models.py:178 counter/models.py:25 #: accounting/models.py:135 accounting/models.py:178 counter/models.py:25
#: counter/models.py:210 #: counter/models.py:218
msgid "amount" msgid "amount"
msgstr "montant" msgstr "montant"
@ -124,16 +124,16 @@ msgid "journal"
msgstr "classeur" msgstr "classeur"
#: accounting/models.py:179 core/models.py:461 core/models.py:739 #: accounting/models.py:179 core/models.py:461 core/models.py:739
#: counter/models.py:213 counter/models.py:256 counter/models.py:339 #: counter/models.py:221 counter/models.py:264 counter/models.py:347
#: eboutic/models.py:15 eboutic/models.py:48 #: eboutic/models.py:15 eboutic/models.py:48
msgid "date" msgid "date"
msgstr "date" msgstr "date"
#: accounting/models.py:180 counter/models.py:340 #: accounting/models.py:180 counter/models.py:348
msgid "comment" msgid "comment"
msgstr "commentaire" msgstr "commentaire"
#: accounting/models.py:181 counter/models.py:214 counter/models.py:257 #: accounting/models.py:181 counter/models.py:222 counter/models.py:265
#: subscription/models.py:57 #: subscription/models.py:57
msgid "payment method" msgid "payment method"
msgstr "méthode de paiement" msgstr "méthode de paiement"
@ -182,7 +182,7 @@ msgstr "Compte"
msgid "Company" msgid "Company"
msgstr "Entreprise" msgstr "Entreprise"
#: accounting/models.py:190 sith/settings.py:278 #: accounting/models.py:190 sith/settings.py:279
msgid "Other" msgid "Other"
msgstr "Autre" msgstr "Autre"
@ -224,7 +224,7 @@ msgstr ""
"Vous devez fournir soit un type comptable simplifié ou un type comptable " "Vous devez fournir soit un type comptable simplifié ou un type comptable "
"standard" "standard"
#: accounting/models.py:277 counter/models.py:81 #: accounting/models.py:277 counter/models.py:89
msgid "code" msgid "code"
msgstr "code" msgstr "code"
@ -232,7 +232,7 @@ msgstr "code"
msgid "An accounting type code contains only numbers" msgid "An accounting type code contains only numbers"
msgstr "Un code comptable ne contient que des numéros" msgstr "Un code comptable ne contient que des numéros"
#: accounting/models.py:282 accounting/models.py:308 counter/models.py:248 #: accounting/models.py:282 accounting/models.py:308 counter/models.py:256
msgid "label" msgid "label"
msgstr "intitulé" msgstr "intitulé"
@ -272,7 +272,7 @@ msgstr "Liste des types comptable"
#: accounting/templates/accounting/journal_details.jinja:9 #: accounting/templates/accounting/journal_details.jinja:9
#: accounting/templates/accounting/operation_edit.jinja:9 #: accounting/templates/accounting/operation_edit.jinja:9
#: accounting/templates/accounting/simplifiedaccountingtype_list.jinja:9 #: accounting/templates/accounting/simplifiedaccountingtype_list.jinja:9
#: core/templates/core/user_tools.jinja:40 #: core/templates/core/user_tools.jinja:41
msgid "Accounting" msgid "Accounting"
msgstr "Comptabilité" msgstr "Comptabilité"
@ -291,7 +291,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:4
#: accounting/templates/accounting/bank_account_details.jinja:13 #: accounting/templates/accounting/bank_account_details.jinja:13
#: core/templates/core/user_tools.jinja:47 #: core/templates/core/user_tools.jinja:48
msgid "Bank account: " msgid "Bank account: "
msgstr "Compte en banque : " msgstr "Compte en banque : "
@ -494,7 +494,7 @@ msgstr "Éditer l'opération"
#: core/templates/core/create.jinja:12 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/file_edit.jinja:8 core/templates/core/page_prop.jinja:8
#: core/templates/core/pagerev_edit.jinja:24 #: core/templates/core/pagerev_edit.jinja:24
#: core/templates/core/user_godfathers.jinja:25 #: core/templates/core/user_godfathers.jinja:27
#: counter/templates/counter/cash_register_summary.jinja:22 #: counter/templates/counter/cash_register_summary.jinja:22
#: subscription/templates/subscription/subscription.jinja:23 #: subscription/templates/subscription/subscription.jinja:23
msgid "Save" msgid "Save"
@ -545,7 +545,7 @@ msgstr "Vous ne pouvez pas faire de boucles dans les clubs"
msgid "A club with that unix_name already exists" msgid "A club with that unix_name already exists"
msgstr "Un club avec ce nom UNIX existe déjà." msgstr "Un club avec ce nom UNIX existe déjà."
#: club/models.py:144 counter/models.py:320 counter/models.py:337 #: club/models.py:144 counter/models.py:328 counter/models.py:345
#: eboutic/models.py:14 eboutic/models.py:47 launderette/models.py:89 #: eboutic/models.py:14 eboutic/models.py:47 launderette/models.py:89
#: launderette/models.py:126 #: launderette/models.py:126
msgid "user" msgid "user"
@ -555,8 +555,8 @@ msgstr "nom d'utilisateur"
msgid "role" msgid "role"
msgstr "rôle" msgstr "rôle"
#: club/models.py:150 core/models.py:32 counter/models.py:53 #: club/models.py:150 core/models.py:32 counter/models.py:61
#: counter/models.py:78 #: counter/models.py:86
msgid "description" msgid "description"
msgstr "description" msgstr "description"
@ -693,7 +693,7 @@ msgid "Payment method"
msgstr "Méthode de paiement" msgstr "Méthode de paiement"
#: club/templates/club/club_tools.jinja:4 #: club/templates/club/club_tools.jinja:4
#: core/templates/core/user_tools.jinja:59 #: core/templates/core/user_tools.jinja:60
msgid "Club tools" msgid "Club tools"
msgstr "Outils club" msgstr "Outils club"
@ -1632,16 +1632,16 @@ msgstr "Filière : "
msgid "Subscribed until %(subscription_end)s" msgid "Subscribed until %(subscription_end)s"
msgstr "Cotisant jusqu'au %(subscription_end)s" msgstr "Cotisant jusqu'au %(subscription_end)s"
#: core/templates/core/user_detail.jinja:60 #: core/templates/core/user_detail.jinja:61
#: core/templates/core/user_edit.jinja:39 #: core/templates/core/user_edit.jinja:39
msgid "Account number: " msgid "Account number: "
msgstr "Numero de compte : " msgstr "Numero de compte : "
#: core/templates/core/user_detail.jinja:66 #: core/templates/core/user_detail.jinja:68
msgid "Not subscribed" msgid "Not subscribed"
msgstr "Non cotisant" msgstr "Non cotisant"
#: core/templates/core/user_detail.jinja:68 #: core/templates/core/user_detail.jinja:70
#: subscription/templates/subscription/subscription.jinja:4 #: subscription/templates/subscription/subscription.jinja:4
#: subscription/templates/subscription/subscription.jinja:8 #: subscription/templates/subscription/subscription.jinja:8
msgid "New subscription" msgid "New subscription"
@ -1692,6 +1692,7 @@ msgid "Change user password"
msgstr "Changer le mot de passe" msgstr "Changer le mot de passe"
#: core/templates/core/user_godfathers.jinja:5 #: core/templates/core/user_godfathers.jinja:5
#, python-format
msgid "%(user_name)s's godfathers" msgid "%(user_name)s's godfathers"
msgstr "Parrains de %(user_name)s" msgstr "Parrains de %(user_name)s"
@ -1699,7 +1700,7 @@ msgstr "Parrains de %(user_name)s"
msgid "Godfathers" msgid "Godfathers"
msgstr "Parrains" msgstr "Parrains"
#: core/templates/core/user_godfathers.jinja:15 #: core/templates/core/user_godfathers.jinja:16
msgid "Godchildren" msgid "Godchildren"
msgstr "Fillots" msgstr "Fillots"
@ -1772,11 +1773,18 @@ msgstr "Gestion des types de produit"
msgid "Cash register summaries" msgid "Cash register summaries"
msgstr "Relevés de caisse" msgstr "Relevés de caisse"
#: core/templates/core/user_tools.jinja:43 #: core/templates/core/user_tools.jinja:35 core/views/user.py:145
#: counter/templates/counter/counter_list.jinja:18
#: counter/templates/counter/counter_list.jinja:33
#: counter/templates/counter/counter_list.jinja:48
msgid "Stats"
msgstr "Stats"
#: core/templates/core/user_tools.jinja:44
msgid "General accounting" msgid "General accounting"
msgstr "Comptabilité générale" msgstr "Comptabilité générale"
#: core/templates/core/user_tools.jinja:52 #: core/templates/core/user_tools.jinja:53
msgid "Club account: " msgid "Club account: "
msgstr "Compte club : " msgstr "Compte club : "
@ -1838,12 +1846,6 @@ msgstr "Fillot"
msgid "Select user" msgid "Select user"
msgstr "Choisir un utilisateur" msgstr "Choisir un utilisateur"
#: core/views/user.py:145 counter/templates/counter/counter_list.jinja:18
#: counter/templates/counter/counter_list.jinja:33
#: counter/templates/counter/counter_list.jinja:48
msgid "Stats"
msgstr "Stats"
#: core/views/user.py:272 #: core/views/user.py:272
msgid "User already has a profile picture" msgid "User already has a profile picture"
msgstr "L'utilisateur a déjà une photo de profil" msgstr "L'utilisateur a déjà une photo de profil"
@ -1864,146 +1866,146 @@ msgstr "clients"
msgid "Not enough money" msgid "Not enough money"
msgstr "Solde insuffisant" msgstr "Solde insuffisant"
#: counter/models.py:57 counter/models.py:79 #: counter/models.py:65 counter/models.py:87
msgid "product type" msgid "product type"
msgstr "type du produit" msgstr "type du produit"
#: counter/models.py:82 #: counter/models.py:90
msgid "purchase price" msgid "purchase price"
msgstr "prix d'achat" msgstr "prix d'achat"
#: counter/models.py:83 #: counter/models.py:91
msgid "selling price" msgid "selling price"
msgstr "prix de vente" msgstr "prix de vente"
#: counter/models.py:84 #: counter/models.py:92
msgid "special selling price" msgid "special selling price"
msgstr "prix de vente spécial" msgstr "prix de vente spécial"
#: counter/models.py:85 #: counter/models.py:93
msgid "icon" msgid "icon"
msgstr "icône" msgstr "icône"
#: counter/models.py:87 #: counter/models.py:95
msgid "limit age" msgid "limit age"
msgstr "âge limite" msgstr "âge limite"
#: counter/models.py:88 #: counter/models.py:96
msgid "tray price" msgid "tray price"
msgstr "prix plateau" msgstr "prix plateau"
#: counter/models.py:89 #: counter/models.py:97
msgid "parent product" msgid "parent product"
msgstr "produit parent" msgstr "produit parent"
#: counter/models.py:91 #: counter/models.py:99
msgid "buying groups" msgid "buying groups"
msgstr "groupe d'achat" msgstr "groupe d'achat"
#: counter/models.py:92 #: counter/models.py:100
msgid "archived" msgid "archived"
msgstr "archivé" msgstr "archivé"
#: counter/models.py:95 #: counter/models.py:103
msgid "product" msgid "product"
msgstr "produit" msgstr "produit"
#: counter/models.py:114 #: counter/models.py:122
msgid "products" msgid "products"
msgstr "produits" msgstr "produits"
#: counter/models.py:115 #: counter/models.py:123
msgid "counter type" msgid "counter type"
msgstr "type de comptoir" msgstr "type de comptoir"
#: counter/models.py:117 #: counter/models.py:125
msgid "Bar" msgid "Bar"
msgstr "Bar" msgstr "Bar"
#: counter/models.py:117 #: counter/models.py:125
msgid "Office" msgid "Office"
msgstr "Bureau" msgstr "Bureau"
#: counter/models.py:117 counter/templates/counter/counter_list.jinja:11 #: counter/models.py:125 counter/templates/counter/counter_list.jinja:11
#: eboutic/templates/eboutic/eboutic_main.jinja:4 #: eboutic/templates/eboutic/eboutic_main.jinja:4
#: eboutic/templates/eboutic/eboutic_main.jinja:24 #: eboutic/templates/eboutic/eboutic_main.jinja:24
#: eboutic/templates/eboutic/eboutic_makecommand.jinja:8 #: eboutic/templates/eboutic/eboutic_makecommand.jinja:8
#: eboutic/templates/eboutic/eboutic_payment_result.jinja:4 #: eboutic/templates/eboutic/eboutic_payment_result.jinja:4
#: sith/settings.py:277 sith/settings.py:285 #: sith/settings.py:278 sith/settings.py:286
msgid "Eboutic" msgid "Eboutic"
msgstr "Eboutic" msgstr "Eboutic"
#: counter/models.py:118 #: counter/models.py:126
msgid "sellers" msgid "sellers"
msgstr "vendeurs" msgstr "vendeurs"
#: counter/models.py:123 counter/models.py:321 counter/models.py:338 #: counter/models.py:131 counter/models.py:329 counter/models.py:346
#: launderette/models.py:16 #: launderette/models.py:16
msgid "counter" msgid "counter"
msgstr "comptoir" msgstr "comptoir"
#: counter/models.py:216 #: counter/models.py:224
msgid "bank" msgid "bank"
msgstr "banque" msgstr "banque"
#: counter/models.py:218 counter/models.py:259 #: counter/models.py:226 counter/models.py:267
msgid "is validated" msgid "is validated"
msgstr "est validé" msgstr "est validé"
#: counter/models.py:221 #: counter/models.py:229
msgid "refilling" msgid "refilling"
msgstr "rechargement" msgstr "rechargement"
#: counter/models.py:252 eboutic/models.py:103 #: counter/models.py:260 eboutic/models.py:103
msgid "unit price" msgid "unit price"
msgstr "prix unitaire" msgstr "prix unitaire"
#: counter/models.py:253 counter/models.py:371 eboutic/models.py:104 #: counter/models.py:261 counter/models.py:379 eboutic/models.py:104
msgid "quantity" msgid "quantity"
msgstr "quantité" msgstr "quantité"
#: counter/models.py:258 #: counter/models.py:266
msgid "Sith account" msgid "Sith account"
msgstr "Compte utilisateur" msgstr "Compte utilisateur"
#: counter/models.py:258 sith/settings.py:270 sith/settings.py:275 #: counter/models.py:266 sith/settings.py:271 sith/settings.py:276
#: sith/settings.py:297 #: sith/settings.py:298
msgid "Credit card" msgid "Credit card"
msgstr "Carte bancaire" msgstr "Carte bancaire"
#: counter/models.py:262 #: counter/models.py:270
msgid "selling" msgid "selling"
msgstr "vente" msgstr "vente"
#: counter/models.py:324 #: counter/models.py:332
msgid "last activity date" msgid "last activity date"
msgstr "dernière activité" msgstr "dernière activité"
#: counter/models.py:327 #: counter/models.py:335
msgid "permanency" msgid "permanency"
msgstr "permanence" msgstr "permanence"
#: counter/models.py:341 #: counter/models.py:349
msgid "emptied" msgid "emptied"
msgstr "coffre vidée" msgstr "coffre vidée"
#: counter/models.py:344 #: counter/models.py:352
msgid "cash register summary" msgid "cash register summary"
msgstr "relevé de caisse" msgstr "relevé de caisse"
#: counter/models.py:369 #: counter/models.py:377
msgid "cash summary" msgid "cash summary"
msgstr "relevé" msgstr "relevé"
#: counter/models.py:370 #: counter/models.py:378
msgid "value" msgid "value"
msgstr "valeur" msgstr "valeur"
#: counter/models.py:372 #: counter/models.py:380
msgid "check" msgid "check"
msgstr "chèque" msgstr "chèque"
#: counter/models.py:375 #: counter/models.py:383
msgid "cash register summary item" msgid "cash register summary item"
msgstr "élément de relevé de caisse" msgstr "élément de relevé de caisse"
@ -2416,12 +2418,12 @@ msgid "Washing and drying"
msgstr "Lavage et séchage" msgstr "Lavage et séchage"
#: launderette/templates/launderette/launderette_book.jinja:27 #: launderette/templates/launderette/launderette_book.jinja:27
#: sith/settings.py:411 #: sith/settings.py:412
msgid "Washing" msgid "Washing"
msgstr "Lavage" msgstr "Lavage"
#: launderette/templates/launderette/launderette_book.jinja:31 #: launderette/templates/launderette/launderette_book.jinja:31
#: sith/settings.py:411 #: sith/settings.py:412
msgid "Drying" msgid "Drying"
msgstr "Séchage" msgstr "Séchage"
@ -2472,115 +2474,135 @@ msgstr "L'utilisateur n'a pas réservé de créneau"
msgid "Token not found" msgid "Token not found"
msgstr "Jeton non trouvé" msgstr "Jeton non trouvé"
#: sith/settings.py:164 #: rootplace/templates/rootplace/merge.jinja:4
msgid "Merge users"
msgstr "Fusionner deux utilisateurs"
#: rootplace/templates/rootplace/merge.jinja:8
msgid "Merge two users"
msgstr "Fusionner deux utilisateurs"
#: rootplace/templates/rootplace/merge.jinja:12
msgid "Merge"
msgstr "Fusion"
#: rootplace/views.py:63
msgid "User that will be kept"
msgstr "Utilisateur qui sera conservé"
#: rootplace/views.py:64
msgid "User that will be deleted"
msgstr "Utilisateur qui sera supprimé"
#: sith/settings.py:165
msgid "English" msgid "English"
msgstr "Anglais" msgstr "Anglais"
#: sith/settings.py:165 #: sith/settings.py:166
msgid "French" msgid "French"
msgstr "Français" msgstr "Français"
#: sith/settings.py:267 sith/settings.py:274 sith/settings.py:295 #: sith/settings.py:268 sith/settings.py:275 sith/settings.py:296
msgid "Check" msgid "Check"
msgstr "Chèque" msgstr "Chèque"
#: sith/settings.py:268 sith/settings.py:276 sith/settings.py:296 #: sith/settings.py:269 sith/settings.py:277 sith/settings.py:297
msgid "Cash" msgid "Cash"
msgstr "Espèces" msgstr "Espèces"
#: sith/settings.py:269 #: sith/settings.py:270
msgid "Transfert" msgid "Transfert"
msgstr "Virement" msgstr "Virement"
#: sith/settings.py:282 #: sith/settings.py:283
msgid "Belfort" msgid "Belfort"
msgstr "Belfort" msgstr "Belfort"
#: sith/settings.py:283 #: sith/settings.py:284
msgid "Sevenans" msgid "Sevenans"
msgstr "Sevenans" msgstr "Sevenans"
#: sith/settings.py:284 #: sith/settings.py:285
msgid "Montbéliard" msgid "Montbéliard"
msgstr "Montbéliard" msgstr "Montbéliard"
#: sith/settings.py:324 #: sith/settings.py:325
msgid "One semester" msgid "One semester"
msgstr "Un semestre, 15 €" msgstr "Un semestre, 15 €"
#: sith/settings.py:329 #: sith/settings.py:330
msgid "Two semesters" msgid "Two semesters"
msgstr "Deux semestres, 28 €" msgstr "Deux semestres, 28 €"
#: sith/settings.py:334 #: sith/settings.py:335
msgid "Common core cursus" msgid "Common core cursus"
msgstr "Cursus tronc commun, 45 €" msgstr "Cursus tronc commun, 45 €"
#: sith/settings.py:339 #: sith/settings.py:340
msgid "Branch cursus" msgid "Branch cursus"
msgstr "Cursus branche, 45 €" msgstr "Cursus branche, 45 €"
#: sith/settings.py:344 #: sith/settings.py:345
msgid "Alternating cursus" msgid "Alternating cursus"
msgstr "Cursus alternant, 30 €" msgstr "Cursus alternant, 30 €"
#: sith/settings.py:349 #: sith/settings.py:350
msgid "Honorary member" msgid "Honorary member"
msgstr "Membre honoraire, 0 €" msgstr "Membre honoraire, 0 €"
#: sith/settings.py:354 #: sith/settings.py:355
msgid "Assidu member" msgid "Assidu member"
msgstr "Membre d'Assidu, 0 €" msgstr "Membre d'Assidu, 0 €"
#: sith/settings.py:359 #: sith/settings.py:360
msgid "Amicale/DOCEO member" msgid "Amicale/DOCEO member"
msgstr "Membre de l'Amicale/DOCEO, 0 €" msgstr "Membre de l'Amicale/DOCEO, 0 €"
#: sith/settings.py:364 #: sith/settings.py:365
msgid "UT network member" msgid "UT network member"
msgstr "Cotisant du réseau UT, 0 €" msgstr "Cotisant du réseau UT, 0 €"
#: sith/settings.py:369 #: sith/settings.py:370
msgid "CROUS member" msgid "CROUS member"
msgstr "Membres du CROUS, 0 €" msgstr "Membres du CROUS, 0 €"
#: sith/settings.py:374 #: sith/settings.py:375
msgid "Sbarro/ESTA member" msgid "Sbarro/ESTA member"
msgstr "Membre de Sbarro ou de l'ESTA, 15 €" msgstr "Membre de Sbarro ou de l'ESTA, 15 €"
#: sith/settings.py:382 #: sith/settings.py:383
msgid "President" msgid "President"
msgstr "Président" msgstr "Président"
#: sith/settings.py:383 #: sith/settings.py:384
msgid "Vice-President" msgid "Vice-President"
msgstr "Vice-Président" msgstr "Vice-Président"
#: sith/settings.py:384 #: sith/settings.py:385
msgid "Treasurer" msgid "Treasurer"
msgstr "Trésorier" msgstr "Trésorier"
#: sith/settings.py:385 #: sith/settings.py:386
msgid "Communication supervisor" msgid "Communication supervisor"
msgstr "Responsable com" msgstr "Responsable com"
#: sith/settings.py:386 #: sith/settings.py:387
msgid "Secretary" msgid "Secretary"
msgstr "Secrétaire" msgstr "Secrétaire"
#: sith/settings.py:387 #: sith/settings.py:388
msgid "IT supervisor" msgid "IT supervisor"
msgstr "Responsable info" msgstr "Responsable info"
#: sith/settings.py:388 #: sith/settings.py:389
msgid "Board member" msgid "Board member"
msgstr "Membre du bureau" msgstr "Membre du bureau"
#: sith/settings.py:389 #: sith/settings.py:390
msgid "Active member" msgid "Active member"
msgstr "Membre actif" msgstr "Membre actif"
#: sith/settings.py:390 #: sith/settings.py:391
msgid "Curious" msgid "Curious"
msgstr "Curieux" msgstr "Curieux"

0
rootplace/__init__.py Normal file
View File

3
rootplace/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

3
rootplace/models.py Normal file
View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,14 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Merge users{% endtrans %}
{% endblock %}
{% block content %}
<h3>{% trans %}Merge two users{% endtrans %}</h3>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p() }}
<p><input type="submit" value="{% trans %}Merge{% endtrans %}" /></p>
</form>
{% endblock %}

3
rootplace/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

10
rootplace/urls.py Normal file
View File

@ -0,0 +1,10 @@
from django.conf.urls import url, include
from rootplace.views import *
urlpatterns = [
url(r'^merge$', MergeUsersView.as_view(), name='merge'),
]

85
rootplace/views.py Normal file
View File

@ -0,0 +1,85 @@
from django.shortcuts import render
from django.utils.translation import ugettext as _
from django.views.generic.edit import FormView
from django.core.urlresolvers import reverse
from django import forms
from django.core.exceptions import PermissionDenied
from ajax_select.fields import AutoCompleteSelectField
from core.models import User
from subscription.models import Subscriber
from counter.models import Customer
def merge_users(u1, u2):
u1.nick_name = u1.nick_name or u2.nick_name
u1.date_of_birth = u1.date_of_birth or u2.date_of_birth
u1.home = u1.home or u2.home
u1.sex = u1.sex or u2.sex
u1.tshirt_size = u1.tshirt_size or u2.tshirt_size
u1.role = u1.role or u2.role
u1.department = u1.department or u2.department
u1.dpt_option = u1.dpt_option or u2.dpt_option
u1.semester = u1.semester or u2.semester
u1.quote = u1.quote or u2.quote
u1.school = u1.school or u2.school
u1.promo = u1.promo or u2.promo
u1.forum_signature = u1.forum_signature or u2.forum_signature
u1.second_email = u1.second_email or u2.second_email
u1.phone = u1.phone or u2.phone
u1.parent_phone = u1.parent_phone or u2.parent_phone
u1.address = u1.address or u2.address
u1.parent_address = u1.parent_address or u2.parent_address
u1.save()
for u in u2.godfathers.all():
u1.godfathers.add(u)
u1.save()
for i in u2.invoices.all():
for f in i._meta.local_fields: # I have sadly not found anything better :/
if f.name == "date":
f.auto_now = False
u1.invoices.add(i)
u1.save()
s1 = Subscriber.objects.filter(id=u1.id).first()
s2 = Subscriber.objects.filter(id=u2.id).first()
for s in s2.subscriptions.all():
s1.subscriptions.add(s)
s1.save()
c1 = Customer.objects.filter(user__id=u1.id).first()
c2 = Customer.objects.filter(user__id=u2.id).first()
if c1 and c2:
for r in c2.refillings.all():
c1.refillings.add(r)
c1.save()
for s in c2.buyings.all():
c1.buyings.add(s)
c1.save()
elif c2 and not c1:
c2.user = u1
c1 = c2
c1.save()
c1.recompute_amount()
u2.delete()
return u1
class MergeForm(forms.Form):
user1 = AutoCompleteSelectField('users', label=_("User that will be kept"), help_text=None, required=True)
user2 = AutoCompleteSelectField('users', label=_("User that will be deleted"), help_text=None, required=True)
class MergeUsersView(FormView):
template_name = "rootplace/merge.jinja"
form_class = MergeForm
def dispatch(self, request, *arg, **kwargs):
res = super(MergeUsersView, self).dispatch(request, *arg, **kwargs)
if request.user.is_root:
return res
raise PermissionDenied
def form_valid(self, form):
self.final_user = merge_users(form.cleaned_data['user1'], form.cleaned_data['user2'])
return super(MergeUsersView, self).form_valid(form)
def get_success_url(self):
return reverse('core:user_profile', kwargs={'user_id': self.final_user.id})

View File

@ -54,6 +54,7 @@ INSTALLED_APPS = (
'eboutic', 'eboutic',
'launderette', 'launderette',
'api', 'api',
'rootplace',
) )
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (

View File

@ -29,6 +29,7 @@ handler404 = "core.views.not_found"
urlpatterns = [ urlpatterns = [
url(r'^', include('core.urls', namespace="core", app_name="core")), url(r'^', include('core.urls', namespace="core", app_name="core")),
url(r'^rootplace/', include('rootplace.urls', namespace="rootplace", app_name="rootplace")),
url(r'^subscription/', include('subscription.urls', namespace="subscription", app_name="subscription")), url(r'^subscription/', include('subscription.urls', namespace="subscription", app_name="subscription")),
url(r'^club/', include('club.urls', namespace="club", app_name="club")), url(r'^club/', include('club.urls', namespace="club", app_name="club")),
url(r'^counter/', include('counter.urls', namespace="counter", app_name="counter")), url(r'^counter/', include('counter.urls', namespace="counter", app_name="counter")),