From 500f7e6155d86683f91cbb434a4cead3ae12815b Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Thu, 28 Jan 2021 12:00:41 +0100 Subject: [PATCH 1/4] =?UTF-8?q?On=20rajoute=20les=20champs=20=C2=AB=20?= =?UTF-8?q?=C3=A9tudes=20pass=C3=A9es=20=C2=BB=20et=20=C2=AB=20exp=C3=A9ri?= =?UTF-8?q?ences=20=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locale/en/LC_MESSAGES/django.mo | Bin 5497 -> 5494 bytes locale/en/LC_MESSAGES/django.po | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo index f0263c19147e6293107be57ae79ac53bc21f4ad2..7748db499b821b2a348076f176e525924bf42aad 100644 GIT binary patch delta 859 zcmYMy&r4KM7{>8ebaedHIH@Ef=7>e$pxj2090V1G2r3XnNQIn5Q4j{sbtBSUxri1D zg3BOWD3mCSNNofW7cL?Q6rqLw10gDiwMf6uc*0rC=e+0K_q^{p_x@=*Yg#SH4|?*< z=5CmknAvW`tPBsa0Drsq1f#?kSdP&Ovzu6tRhUG!u!mTTgKm8ktBEsMi0|<>&boM| z!h&4kbtXz#*u+Nsj!8Vm7~Y|}>~aoaf_MVe_$O5U7Z-nZ@s{%k-eUb1>R_j+gPuo& ztHcn;2{REzZ5TtH=q}b^8>)dP7{XVmn;1hqH-*akfb?whZhjGqh}Tg!uz@PPjmrNS zFwh2vs11%#C;5v?D6G6nC`ZLHR09oIi}#$psH=UBYTzB}`59CL^Qc$z5p@GgZar9L zpm(^2>TCxmaSxT)&!RSZhAKRYD)bW7@HFaXW>L?7cJo>12I@dNs0MbCt?dA5B(PHk zd{=gkDir36QK1NG!)nx3)u9R|P_L>Tb&@V;pYsvwAWu+?vDElw8 zAMUyDHG2=@UPr36J>exiujFw$<2MhCr^hmH(*E1=RD9q?#*bf5#5;W^y8Zu8%+*A` N<+rwY*}cd@=n~F$UnKwl delta 862 zcmXZa!Alfj7{~Faa%7QyIX{p!J7x^ z(4IVso)SzHilvhf(ZNF$!FK78|3E}8h!lQ*>$`{j%royi@AEwGOg(v++-f=#-a2Jg zxoFm6X0@2vdECb){O#fcY$HA$H@kodY{y=Q1cCr2wHCP=r=uumE zk{D&2C^r(Q4SP@%-N0@fK{aq6Blr|`63B*| zy~FpY&h~Htf1nbxENY_(RN*|T&=XX{OQ@5npq}4!_un~pQ3LIv8mJ*#+b^V%(CS?9 zec2JJP%B@I3bms)>_#1xhbri!UezdSl8p0?a~w6u161B47tbQ!dgC|2f4XtC^FLCH zW>P_aFz5wAdU&ueHIPcRjOR+_{%kQfUz*L83&pgTEzEg$pHCI1^D|}dX1Oru&$wu8 WdcNd8u5`t!k-#7F2X?;2)*{Eb=U+tt diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 79b583e..e611f31 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -7,16 +7,16 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-23 22:53+0100\n" -"PO-Revision-Date: 2021-02-23 22:53+0100\n" -"Last-Translator: Tom Hubrecht \n" +"POT-Creation-Date: 2021-02-06 12:02+0000\n" +"PO-Revision-Date: 2021-10-08 09:36+0200\n" +"Last-Translator: Test Translator \n" "Language-Team: \n" "Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.4.1\n" +"X-Generator: Poedit 3.0\n" #: fiches/forms.py:20 msgid "Nom/Surnom" From 54e6877998d6d28fd3dfd2d24301ea1bd2a97da9 Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Mon, 1 Feb 2021 11:46:37 +0100 Subject: [PATCH 2/4] =?UTF-8?q?Utilitaire=20pour=20transf=C3=A9rer=20les?= =?UTF-8?q?=20anciennes=20fiches?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fiches/management/commands/get_photos.py | 2 +- transfert.py | 147 +++++++++++++++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 transfert.py diff --git a/fiches/management/commands/get_photos.py b/fiches/management/commands/get_photos.py index cb9c30f..cc10bd4 100644 --- a/fiches/management/commands/get_photos.py +++ b/fiches/management/commands/get_photos.py @@ -13,7 +13,7 @@ from ._ldap import AnnuaireLDAP class Command(BaseCommand): - help = "Si possible, import les photos des conscrit·e·s dans l'annuaire." + help = "Si possible, importe les photos des conscrit·e·s dans l'annuaire." def add_arguments(self, parser): group = parser.add_mutually_exclusive_group() diff --git a/transfert.py b/transfert.py new file mode 100644 index 0000000..4da0416 --- /dev/null +++ b/transfert.py @@ -0,0 +1,147 @@ +import json +import os +import sys + +from datetime import datetime + +import django +from django.contrib.auth import get_user_model + +# Configuration +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "annuaire.settings") +django.setup() + +User = get_user_model() + +from fiches.management.commands._ldap import ClipperLDAP +from fiches.models import Address, Department, Mail, Phone, Profile + +# Utilitaires +def parse_date(s): + try: + return datetime.strptime(s, "%d/%m/%Y").date() + except ValueError: + return "" + + +def get_text_field(data): + text = "" + if data["interets"]: + text += "Mes intérêts :\n" + data["interets"] + "\n\n" + if data["pages_web"]: + text += "Mes pages web :\n" + data["pages_web"] + "\n\n" + if data["commentaires"]: + text += data["commentaires"] + "\n\n" + return text + + +def get_address(data): + content = data["lignes"] + "\n" + if data["code_postal"] and data["ville"]: + content += data["code_postal"] + ", " + data["ville"] + elif data["code_postal"] or data["ville"]: + content += data["code_postal"] + data["ville"] + if data["pays"]: + content += ", " + data["pays"] + return content + + +def parse_list(s): + return [p for p in s.split(",").split("\n").split(";") if p] + + +def create_phones(s, profile, numeros, name="Téléphone"): + for p in parse_list(s): + numeros.append(Phone(profile=profile, name=name, content=p)) + + +def create_mails(s, profile, mails, name="E-mail"): + for m in parse_list(s): + mails.append(Mail(profile=profile, name=name, content=m)) + +# On récupère la liste des élèves à créer +ldap = ClipperLDAP() +clipper_list = ldap.get_clipper_list(stdout=sys.stdout) + +# On vire les élèves déjà existants +existing_users = set(User.objects.values_list("username", flat=True)) +clippers = [clipper for clipper in clipper_list if clipper.uid not in existing_users] + +# On récupère la liste des départements +depts = { + dept: Department.objects.get_or_create(name=dept)[0].id + for dept in ldap.verbose_depts.values() +} + +users_to_create = [] +users = {} +profiles_to_create = [] +dept_m2m_to_create = [] + +for clipper in clippers: + user = User(username=clipper.uid, email=clipper.email) + users["clipper.uid"] = (user, clipper) + users_to_create.append(user) + +User.objects.bulk_create(users_to_create) + +fiches = {} +references = {} +adresses = [] +devises = {} +numeros = [] +mails = [] + +# On recrée les profils +with open("old_fiches.json") as json_file: + data = json.load(json_file) + for obj in data: + obj_data = obj["fields"] + user, clipper = users[obj_data["id"]] + fiches[obj_data["n_id"]] = Profile( + user=user, + full_name=" ".join(obj_data["prenom"], obj_data["nom"]), + promotion=clipper.promotion, + birth_date=parse_date(obj_data["date_de_naissance"]), + past_studies=obj_data["etudes_passees"] + "\n" + obj_data["etudes"], + experiences=obj_data["experiences"], + thurne=obj_data["thurne"], + text_field=get_text_field(obj_data), + ) + create_phones(data["telephones"], fiches[obj_data["n_id"]], numeros) + create_phones(data["portables"], fiches[obj_data["n_id"]], numeros, name="Portable") + create_mails(data["emails"], fiches[obj_data["n_id"]], numeros) + dept_m2m_to_create.append( + Profile.department.through( + profile=fiches[obj_data["n_id"]], department_id=depts[clipper.dept] + ) + ) + +Profile.objects.bulk_create(fiches.values()) +for dept_m2m in dept_m2m_to_create: + dept_m2m.profile_id = dept_m2m.profile.id +Profile.department.through.objects.bulk_create(dept_m2m_to_create) + +# On récupère les adresses +with open("old_adresses.json") as json_file: + data = json.load(json_file) + for obj in data: + obj_data = obj["fields"] + profile = fiches[obj_data["n_id"]] + adresses.append( + Address( + profile=profile, + name="Adresse", + content=get_address(obj_data), + ) + ) + create_phones(obj_data["telephones"], profile, numeros) + +for p in numeros: + p.profile_id = p.profile.id +Phone.objects.bulk_create(numeros) + +for m in mails: + m.profile_id = m.profile.id +Mail.objects.bulk_create(mails) + From b1e591ce2cf813ccf7083d459610df880c1fa6ca Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Sun, 7 Feb 2021 13:16:03 +0100 Subject: [PATCH 3/4] Update --- transfert.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/transfert.py b/transfert.py index 4da0416..cbe449d 100644 --- a/transfert.py +++ b/transfert.py @@ -59,13 +59,12 @@ def create_mails(s, profile, mails, name="E-mail"): for m in parse_list(s): mails.append(Mail(profile=profile, name=name, content=m)) + # On récupère la liste des élèves à créer ldap = ClipperLDAP() -clipper_list = ldap.get_clipper_list(stdout=sys.stdout) +# Pas besoin de filtrer les users déjà existants +clipper = ldap.get_clipper_list(stdout=sys.stdout) -# On vire les élèves déjà existants -existing_users = set(User.objects.values_list("username", flat=True)) -clippers = [clipper for clipper in clipper_list if clipper.uid not in existing_users] # On récupère la liste des départements depts = { @@ -109,7 +108,9 @@ with open("old_fiches.json") as json_file: text_field=get_text_field(obj_data), ) create_phones(data["telephones"], fiches[obj_data["n_id"]], numeros) - create_phones(data["portables"], fiches[obj_data["n_id"]], numeros, name="Portable") + create_phones( + data["portables"], fiches[obj_data["n_id"]], numeros, name="Portable" + ) create_mails(data["emails"], fiches[obj_data["n_id"]], numeros) dept_m2m_to_create.append( Profile.department.through( @@ -144,4 +145,3 @@ Phone.objects.bulk_create(numeros) for m in mails: m.profile_id = m.profile.id Mail.objects.bulk_create(mails) - From ebab4f5cb2c1e698f5725b473c73a7a8d1fc3307 Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Fri, 8 Oct 2021 17:58:41 +0200 Subject: [PATCH 4/4] =?UTF-8?q?M=C3=A0j=20du=20script=20de=20transfert,=20?= =?UTF-8?q?et=20correction=20de=20l'affichage=20de=20certaines=20infos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fiches/models.py | 4 + fiches/templates/fiches/fiche.html | 6 +- fiches/views.py | 12 +- transfert.py | 231 ++++++++++++++++++++--------- 4 files changed, 176 insertions(+), 77 deletions(-) diff --git a/fiches/models.py b/fiches/models.py index 355736f..095620e 100644 --- a/fiches/models.py +++ b/fiches/models.py @@ -40,6 +40,10 @@ class Profile(models.Model): def __str__(self): return self.full_name + @property + def age(self): + return self.day.year - self.birth_date.year + def birthday(self): return self.birth_date.strftime("%d%m") diff --git a/fiches/templates/fiches/fiche.html b/fiches/templates/fiches/fiche.html index 201a7b2..00dc20b 100644 --- a/fiches/templates/fiches/fiche.html +++ b/fiches/templates/fiches/fiche.html @@ -106,7 +106,7 @@
{% trans "Études passées" %} - {{ profile.past_studies }} + {{ profile.past_studies|linebreaksbr }}
{% endif %} @@ -114,7 +114,7 @@
{% trans "Expériences passées" %} - {{ profile.experiences }} + {{ profile.experiences|linebreaksbr }}
{% endif %} @@ -122,7 +122,7 @@ {% if profile.text_field %}
{% trans "Champ libre" %} -

{{ profile.text_field }}

+

{{ profile.text_field|linebreaksbr }}

{% endif %} diff --git a/fiches/views.py b/fiches/views.py index e506055..6e061a6 100644 --- a/fiches/views.py +++ b/fiches/views.py @@ -2,11 +2,9 @@ from datetime import date, timedelta from django.contrib.auth.decorators import login_required from django.core.mail import send_mail -from django.db.models import Q -from django.forms import formset_factory -from django.forms.models import model_to_dict +from django.db.models import DateTimeField, Q, Value from django.http import HttpResponseRedirect -from django.shortcuts import get_object_or_404, redirect, render +from django.shortcuts import get_object_or_404 from django.template.loader import render_to_string from django.urls import reverse, reverse_lazy from django.utils import timezone @@ -23,7 +21,7 @@ from fiches.forms import ( SearchForm, SocialFormSet, ) -from fiches.models import Address, Department, Mail, Phone, Profile, Social +from fiches.models import Department, Profile from fiches.utils import get_ldap_infos @@ -151,14 +149,14 @@ class BirthdayView(ListView): context["result"] = list( Profile.objects.filter( birth_date__day=today.day, birth_date__month=today.month - ) + ).annotate(day=Value(today, output_field=DateTimeField())) ) for i in range(1, 7): today = today + timedelta(days=1) context["result"] += list( Profile.objects.filter( birth_date__day=today.day, birth_date__month=today.month - ) + ).annotate(day=Value(today, output_field=DateTimeField())) ) return context diff --git a/transfert.py b/transfert.py index cbe449d..ca56105 100644 --- a/transfert.py +++ b/transfert.py @@ -1,72 +1,82 @@ import json import os import sys - from datetime import datetime import django from django.contrib.auth import get_user_model +print("\nTransfert des fiches annuaires :") + # Configuration +print("Paramétrage de Django...", end=" ") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "annuaire.settings") django.setup() User = get_user_model() -from fiches.management.commands._ldap import ClipperLDAP -from fiches.models import Address, Department, Mail, Phone, Profile +from authens.models import CASAccount # noqa + +from fiches.management.commands._ldap import ClipperLDAP # noqa +from fiches.models import Address, Department, Mail, Phone, Profile # noqa + +print("[ok]") + # Utilitaires def parse_date(s): try: - return datetime.strptime(s, "%d/%m/%Y").date() - except ValueError: - return "" + return datetime.strptime(s, "%Y-%m-%d").date() + except (ValueError, TypeError): + return None def get_text_field(data): text = "" - if data["interets"]: - text += "Mes intérêts :\n" + data["interets"] + "\n\n" - if data["pages_web"]: - text += "Mes pages web :\n" + data["pages_web"] + "\n\n" - if data["commentaires"]: - text += data["commentaires"] + "\n\n" + if data["interests"]: + text += "Mes intérêts :\n" + data["interests"] + "\n\n" + if data["websites"]: + text += "Mes pages web :\n\n" + data["websites"] + "\n\n" + if data["comments"]: + text += data["comments"] + "\n\n" return text def get_address(data): - content = data["lignes"] + "\n" - if data["code_postal"] and data["ville"]: - content += data["code_postal"] + ", " + data["ville"] - elif data["code_postal"] or data["ville"]: - content += data["code_postal"] + data["ville"] - if data["pays"]: - content += ", " + data["pays"] + content = data["lines"] + "\n" + if data["zip"] and data["city"]: + content += data["zip"] + ", " + data["city"] + elif data["zip"] or data["city"]: + content += data["zip"] + data["city"] + if data["country"]: + content += ", " + data["country"] return content def parse_list(s): - return [p for p in s.split(",").split("\n").split(";") if p] + s = s or "" + return [p for p in s.replace(",", ";").replace("\n", ";").split(";") if p] def create_phones(s, profile, numeros, name="Téléphone"): for p in parse_list(s): - numeros.append(Phone(profile=profile, name=name, content=p)) + numeros.append(Phone(profile=profile, name=name, number=p)) def create_mails(s, profile, mails, name="E-mail"): for m in parse_list(s): - mails.append(Mail(profile=profile, name=name, content=m)) + mails.append(Mail(profile=profile, name=name, mail=m)) -# On récupère la liste des élèves à créer +print("Récupération des comptes clipper...", end=" ") + ldap = ClipperLDAP() -# Pas besoin de filtrer les users déjà existants -clipper = ldap.get_clipper_list(stdout=sys.stdout) +clippers = {c.uid: c for c in ldap.get_clipper_list(stdout=sys.stdout)} + +print("[ok]") -# On récupère la liste des départements depts = { dept: Department.objects.get_or_create(name=dept)[0].id for dept in ldap.verbose_depts.values() @@ -77,12 +87,30 @@ users = {} profiles_to_create = [] dept_m2m_to_create = [] -for clipper in clippers: + +print("Création des comptes...", end=" ") + +for clipper in clippers.values(): user = User(username=clipper.uid, email=clipper.email) - users["clipper.uid"] = (user, clipper) users_to_create.append(user) User.objects.bulk_create(users_to_create) +users = {u.username: (u, clippers[u.username]) for u in User.objects.all()} + +print("[ok]") + + +print("Création des comptes Authens...", end=" ") + +cas_accounts = [] + +for (u, c) in users.values(): + cas_accounts.append(CASAccount(user=u, cas_login=c.uid, entrance_year=c.year)) + +CASAccount.objects.bulk_create(cas_accounts) + +print("[ok]") + fiches = {} references = {} @@ -90,58 +118,127 @@ adresses = [] devises = {} numeros = [] mails = [] +fiches_pk = {} + +print("Récupération des anciennes fiches :") # On recrée les profils with open("old_fiches.json") as json_file: data = json.load(json_file) for obj in data: - obj_data = obj["fields"] - user, clipper = users[obj_data["id"]] - fiches[obj_data["n_id"]] = Profile( - user=user, - full_name=" ".join(obj_data["prenom"], obj_data["nom"]), - promotion=clipper.promotion, - birth_date=parse_date(obj_data["date_de_naissance"]), - past_studies=obj_data["etudes_passees"] + "\n" + obj_data["etudes"], - experiences=obj_data["experiences"], - thurne=obj_data["thurne"], - text_field=get_text_field(obj_data), - ) - create_phones(data["telephones"], fiches[obj_data["n_id"]], numeros) - create_phones( - data["portables"], fiches[obj_data["n_id"]], numeros, name="Portable" - ) - create_mails(data["emails"], fiches[obj_data["n_id"]], numeros) - dept_m2m_to_create.append( - Profile.department.through( - profile=fiches[obj_data["n_id"]], department_id=depts[clipper.dept] - ) - ) + if obj["model"] == "annuaire.fiches2021": + obj_data = obj["fields"] + try: + user, clipper = users[obj_data["login"]] + fiches_pk[obj["pk"]] = user.username + fiches[obj_data["login"]] = Profile( + user=user, + full_name=" ".join((obj_data["firstname"], obj_data["lastname"])), + promotion=clipper.year, + birth_date=parse_date((obj_data["birthdate"] or "")), + past_studies=( + (obj_data["past_studies"] or "") + + "\n" + + (obj_data["studies"] or "") + ).strip(), + experiences=(obj_data["experiences"] or ""), + thurne=(obj_data["room"] or ""), + text_field=get_text_field(obj_data), + ) + create_phones(obj_data["phones"], fiches[obj_data["login"]], numeros) + create_phones( + obj_data["mobiles"], + fiches[obj_data["login"]], + numeros, + name="Portable", + ) + create_mails(obj_data["emails"], fiches[obj_data["login"]], mails) + dept_m2m_to_create.append( + Profile.department.through( + profile=fiches[obj_data["login"]], + department_id=depts[clipper.dept], + ) + ) + except KeyError: + print(f"\tLogin inconnu : {obj_data['login']}") + elif obj["model"] == "annuaire.lesreferences2021": + try: + username = fiches_pk[obj["pk"]] + surnom = obj["fields"]["nickname"] + if surnom: + fiche = fiches[username] + if fiche.nickname: + fiche.nickname += ", " + fiche.nickname += surnom + except KeyError: + pass + elif obj["model"] == "annuaire.adresses2021": + try: + username = fiches_pk[obj["pk"]] + obj_data = obj["fields"] + fiche = fiches[username] + a = get_address(obj_data).strip() + if a: + adresses.append(Address(profile=fiche, name="Adresse", content=a)) + except KeyError: + pass + elif obj["model"] == "annuaire.devises2021": + try: + username = fiches_pk[obj["pk"]] + obj_data = obj["fields"] + fiche = fiches[username] + if obj_data["quote"]: + fiche.text_field += f"\n{obj_data['quote']}" + if obj_data["source"]: + fiche.text_field += f" ({obj_data['source']})" + if obj_data["author"]: + fiche.text_field += f", ({obj_data['author']})" + if a: + adresses.append(Address(profile=fiche, name="Adresse", content=a)) + except KeyError: + pass + + +print("Création des nouvelles fiches fiches...", end=" ") Profile.objects.bulk_create(fiches.values()) + +profils = {p.user.username: p for p in Profile.objects.select_related("user")} + +print("[ok]") + + +print("Rattachement des départements...", end=" ") + for dept_m2m in dept_m2m_to_create: - dept_m2m.profile_id = dept_m2m.profile.id + dept_m2m.profile = profils[dept_m2m.profile.user.username] Profile.department.through.objects.bulk_create(dept_m2m_to_create) -# On récupère les adresses -with open("old_adresses.json") as json_file: - data = json.load(json_file) - for obj in data: - obj_data = obj["fields"] - profile = fiches[obj_data["n_id"]] - adresses.append( - Address( - profile=profile, - name="Adresse", - content=get_address(obj_data), - ) - ) - create_phones(obj_data["telephones"], profile, numeros) +print("[ok]") + + +print("Création des numéros de téléphone...", end=" ") for p in numeros: - p.profile_id = p.profile.id + p.profile = profils[p.profile.user.username] Phone.objects.bulk_create(numeros) +print("[ok]") + + +print("Création des adresses mail...", end=" ") + for m in mails: - m.profile_id = m.profile.id + m.profile = profils[m.profile.user.username] Mail.objects.bulk_create(mails) + +print("[ok]") + + +print("Création des adresses...", end=" ") + +for a in adresses: + a.profile = profils[a.profile.user.username] +Address.objects.bulk_create(adresses) + +print("[ok]")