Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
151ef275c8 | |||
2d803d8d59 | |||
19126e57aa | |||
35d82173c6 | |||
bb709eb2c1 | |||
cfdab63598 | |||
6e4f587cce | |||
88a94c6983 | |||
35fbec4fff | |||
e0d2949b00 | |||
a26450d98d | |||
308ed11077 | |||
9febc4cc55 | |||
87093bc92c | |||
8856641003 | |||
3fec540b67 | |||
b83958fd51 | |||
3e04e9f29a | |||
b438d3a7a5 | |||
b9beb304e6 | |||
602ead50a9 | |||
9d216600f8 | |||
e798bbcc91 | |||
ac82d33c3a | |||
6f7028bb0e | |||
3734eeed87 | |||
7c8ce98489 | |||
5f281b1511 |
35
CHANGELOG.md
35
CHANGELOG.md
@ -1,5 +1,40 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### [v8.0] 2020-09-30
|
||||||
|
- Optimisation de la base INSEE
|
||||||
|
- Création d'une table pour les prénoms, et d'une pour les noms
|
||||||
|
- Ajout d'index
|
||||||
|
- Ajout d'un mécanisme de mise à jour de la base insee
|
||||||
|
|
||||||
|
### [v7.0] 2020-08-04
|
||||||
|
- Convertit les Codes Officiels Géographiques en nom de commune
|
||||||
|
|
||||||
|
### [v6.1] 2020-07-30
|
||||||
|
- BUG: Lorsque maiden_name est None, ne pas essayer de le strip
|
||||||
|
|
||||||
|
### [v6.0] 2020-07-29
|
||||||
|
- Lecture de la liste des membres à partir d'un fichier Excel
|
||||||
|
- Écriture de la liste des membres décédés dans un fichier Excel
|
||||||
|
- Vider le texte de l'IHM lorsqu'on clique sur OK
|
||||||
|
- Fichier BAT pour installer et lancer l'IHM sous Windows
|
||||||
|
- BUG: le traitement rend la main à l'IHM losque terminé
|
||||||
|
- BUG: la barre de progression est remise à zero entre chaque traitement
|
||||||
|
|
||||||
|
### [v5.0] 2020-07-17
|
||||||
|
- Mise en place d'une interface graphique
|
||||||
|
- Ajout d'un fichier install.py
|
||||||
|
|
||||||
|
### [v4.0] - 2020-06-16
|
||||||
|
- Recherche automatique des cookies dans firefox
|
||||||
|
- Supression du fichier settings.py, remplacé par argparse
|
||||||
|
|
||||||
|
### [v3.1] - 2020-06-08
|
||||||
|
- Amélioration de la documentation
|
||||||
|
|
||||||
|
### [v3.0] - 2020-06-07
|
||||||
|
- Réorganisation du code en modules
|
||||||
|
- Ajout du script permettant de créer la base de donnée SQLite
|
||||||
|
|
||||||
### [v2.0] - 2020-06-01
|
### [v2.0] - 2020-06-01
|
||||||
- Le fichier de sortie contient plus d'informations pour faciliter la comparaison (lieu de naissance)
|
- Le fichier de sortie contient plus d'informations pour faciliter la comparaison (lieu de naissance)
|
||||||
- Sortie des paramètres du code et création du fichier settings.py
|
- Sortie des paramètres du code et création du fichier settings.py
|
||||||
|
130
README.md
130
README.md
@ -1,40 +1,43 @@
|
|||||||
# Purge Registres Décès INSEE
|
# Purge Registres Décès INSEE
|
||||||
|
|
||||||
Ce programme s'adresse essentiellement aux greffiers des pieux, paroisse et
|
Ce programme s'adresse essentiellement aux greffiers des pieux,
|
||||||
branches de France, de l'Église de Jésus Christ des Saints des Derniers Jours.
|
paroisse et branches de France, de l'Église de Jésus Christ des Saints
|
||||||
|
des Derniers Jours.
|
||||||
|
|
||||||
## Objectif
|
## Objectif
|
||||||
|
|
||||||
La tenue à jour des registres de l'Église n'est pas une tache aisée. Une des
|
La tenue à jour des registres de l'Église n'est pas une tache
|
||||||
difficultés est liée au fait que lorsqu'un membre s'éloigne de l'Église, ses
|
aisée. Une des difficultés est liée au fait que lorsqu'un membre
|
||||||
informations personnelles (adresse, téléphone, etc) ne sont plus mises à jour.
|
s'éloigne de l'Église, ses informations personnelles (adresse,
|
||||||
|
téléphone, etc) ne sont plus mises à jour.
|
||||||
|
|
||||||
L'INSEE tient un fichier des personnes décédées en France de 1970 à
|
L'INSEE tient un fichier des personnes décédées en France de 1970 à
|
||||||
aujourd'hui. Ce fichier est disponible en [données
|
aujourd'hui. Ce fichier est disponible en [données
|
||||||
ouvertes](https://fr.wikipedia.org/wiki/Donn%C3%A9es_ouvertes) sur [le site du
|
ouvertes](https://fr.wikipedia.org/wiki/Donn%C3%A9es_ouvertes) sur [le
|
||||||
|
site du
|
||||||
gouvernement](https://www.data.gouv.fr/fr/datasets/fichier-des-personnes-decedees/).
|
gouvernement](https://www.data.gouv.fr/fr/datasets/fichier-des-personnes-decedees/).
|
||||||
Ce fichier est une aubaine, car il permet de savoir si un membre de l'Église
|
Ce fichier est une aubaine, car il permet de savoir si un membre de
|
||||||
est décédé sans que nous le sachions. Si une personne figure à la fois dans
|
l'Église est décédé sans que nous le sachions. Si une personne figure
|
||||||
les registres de l'Église et dans le fichier de l'INSEE, alors une mise à jour
|
à la fois dans les registres de l'Église et dans le fichier de
|
||||||
du registre de l'Église est nécessaire.
|
l'INSEE, alors une mise à jour du registre de l'Église est nécessaire.
|
||||||
|
|
||||||
Parcourir à la main le registre de membres de paroisse est une tache longue et
|
Parcourir à la main le registre de membres de paroisse est une tache
|
||||||
fastidieuse. Ce programme permet de comparer automatiquement le registre de
|
longue et fastidieuse. Ce programme permet de comparer automatiquement
|
||||||
paroisse avec le fichier de l'INSEE, et donne la liste des membres trouvés
|
le registre de paroisse avec le fichier de l'INSEE, et donne la liste
|
||||||
dans le fichier de l'INSEE.
|
des membres trouvés dans le fichier de l'INSEE.
|
||||||
|
|
||||||
Le fichier de l'INSEE est actualisé de façon mensuelle. Il semble intéressant
|
Le fichier de l'INSEE est actualisé de façon mensuelle. Il semble
|
||||||
d'utiliser ce programme régulièrement (une fois par an par exemple) pour
|
intéressant d'utiliser ce programme régulièrement (une fois par an par
|
||||||
s'assurer que les registres restent à jour.
|
exemple) pour s'assurer que les registres restent à jour.
|
||||||
|
|
||||||
## Pré-requis
|
## Pré-requis
|
||||||
|
|
||||||
### Logiciels
|
### Logiciels
|
||||||
- Git
|
- Git
|
||||||
- Python 3.6
|
- Python 3.6+
|
||||||
- Virtualenv
|
- Virtualenv
|
||||||
|
|
||||||
Testé uniquement sur GNU/Linux (Ubuntu 18.4)
|
Testé uniquement sur GNU/Linux (Ubuntu 18.4) et Windows
|
||||||
|
|
||||||
### Données
|
### Données
|
||||||
|
|
||||||
@ -45,6 +48,12 @@ ici](https://git.roflcopter.fr/sdjgeek/purge-registres-deces-insee/-/wikis/home#
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
Utiliser le script ```install.py```
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
- Cloner le code
|
- Cloner le code
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -56,49 +65,72 @@ cd purge-registres-deces-insee
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 -m venv localenv
|
python3 -m venv localenv
|
||||||
. localenv/bin/activate
|
source localenv/bin/activate
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
## Utilisation
|
## Utilisation
|
||||||
|
|
||||||
Le début du fichier ```trouver_deces.py``` contient les paramètres à configurer :
|
Aller sur le [site de l'Église](https://lcr.churchofjesuschrist.org),
|
||||||
|
et se connecter au compte SDJ. Cette étape est essencielle pour que
|
||||||
|
le programme puisse accéder aux listes des membres.
|
||||||
|
|
||||||
- chemin_base_donnees : Le chemin vers le fichier téléchargé (me contacter)
|
Pour lancer le prgramme, vous pouvez double cliquer
|
||||||
- numeros_unites : La liste des unités que le programme doit tester. La liste commence par le caractère '['. Les
|
sur ```gui_trouver_decedes.py```, ce qui ouvrira une interface
|
||||||
numéros d'unités sont séparés par des virgules. La liste se termine par le caractère ']'. Par exemple
|
graphique.
|
||||||
[47823, 67745, 31456]
|
|
||||||
- cookie : Les cookies de la session au compte SDJ. Pour obtenir ces cookies il faut
|
|
||||||
1- Ouvrir Firefox
|
|
||||||
2- Ouvrir les outils de développement : CTRL + MAJ + E
|
|
||||||
3- Aller sur le site des outils pour greffiers : https://lds.org/lcr
|
|
||||||
4- Entrer identifiant et mot de passe SDJ
|
|
||||||
5- Aller dans la liste des membres
|
|
||||||
6- Dans l'outil de développement, cliquer sur la dernière ligne
|
|
||||||
7- Dans le panneau de droite, dans la section "En-tête de la requête", rechercher le champ "cookie"
|
|
||||||
8- Copier la valeur contenue dans ce champ
|
|
||||||
- chemin_repertoire_sortie : Le chemin vers le répertoire qui contiendra la fichiers de sortie
|
|
||||||
|
|
||||||
Une fois la configuration effectuée, lancer le script :
|
Si vous préférez la console, vous pouvez aussi faire :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
. localenv/bin/activate
|
source localenv/bin/activate
|
||||||
python trouver_deces.py
|
python purge-registres-deces-insee/trouver_deces.py chemin_base_donnees chemin_repertoire_sortie numeros_unites
|
||||||
```
|
```
|
||||||
|
|
||||||
Le script mettra un peu de temps à s'exécuter. En fin d'exécution, le fichier
|
Avec :
|
||||||
liste_membres_decedes_unite_{unite}.txt contiendra la liste des membres
|
|
||||||
trouvés dans le fichier de l'INSEE. Il est recommandé de contrôler les
|
- chemin_base_donnees : Le chemin vers le [fichier
|
||||||
informations du membres avant de le déclarer comme décédé dans les registres
|
téléchargé](https://git.roflcopter.fr/sdjgeek/purge-registres-deces-insee/-/wikis/home#t%C3%A9l%C3%A9charger-la-base-de-donn%C3%A9e)
|
||||||
de l'Église.
|
|
||||||
|
- chemin_repertoire_sortie : Le chemin vers le répertoire qui
|
||||||
|
contiendra la fichiers de sortie
|
||||||
|
|
||||||
|
- numeros_unites : La liste des unités que le programme doit
|
||||||
|
tester. La liste commence par le caractère '['. Les numéros d'unités
|
||||||
|
sont séparés par des virgules. La liste se termine par le caractère
|
||||||
|
']'. Par exemple [47823, 67745, 31456]
|
||||||
|
|
||||||
|
Le script devrait trouver seul le cookie de session permettant de
|
||||||
|
consulter la liste des membres. Mais en cas d'échec, il est possible
|
||||||
|
de lui donner le chemin vers le fichier SQLite que Firefox utilise
|
||||||
|
pour stocker les cookies avec l'option '-c'. En règle générale ce
|
||||||
|
fichier se trouve le répertoire :
|
||||||
|
|
||||||
|
- sur linux :
|
||||||
|
"~/.mozilla/firefox/<un_code_étrange>.default/cookies.sqlite"
|
||||||
|
|
||||||
|
- sur windows :
|
||||||
|
"C:\Users\<nom_utilisateur>\AppData\Local\Mozilla\Firefox\Profiles\<un_code_étrange>.default\cookies.sqlite"
|
||||||
|
|
||||||
|
Par exemple :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python purge-registres-deces-insee/trouver_deces.py ~/Documents/fichier-des-personnes-decedees.sqlite ~/Documents/ 123,854 -c ~/.mozilla/firefox/8h3jsedf.default/cookies.sqlite
|
||||||
|
```
|
||||||
|
|
||||||
|
Le script mettra un peu de temps à s'exécuter. En fin d'exécution, le
|
||||||
|
fichier liste_membres_decedes_unite_{unite}.txt contiendra la liste
|
||||||
|
des membres trouvés dans le fichier de l'INSEE. Il est recommandé de
|
||||||
|
contrôler les informations du membres avant de le déclarer comme
|
||||||
|
décédé dans les registres de l'Église.
|
||||||
|
|
||||||
## Licence
|
## Licence
|
||||||
|
|
||||||
Copyright (c) 2020 Sdj Geek
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
|
||||||
Ce logiciel est sous licence MIT/X Consortium. Elle donne à toute personne
|
Ce logiciel est sous licence MIT/X Consortium. Elle donne à toute
|
||||||
recevant le logiciel (et ses fichiers) le droit illimité de l'utiliser, le
|
personne recevant le logiciel (et ses fichiers) le droit illimité de
|
||||||
copier, le modifier, le fusionner, le publier, le distribuer, le vendre et le
|
l'utiliser, le copier, le modifier, le fusionner, le publier, le
|
||||||
"sous-licencier" (l'incorporer dans une autre licence). La seule obligation
|
distribuer, le vendre et le "sous-licencier" (l'incorporer dans une
|
||||||
est d'incorporer la notice de licence et de copyright dans toutes les
|
autre licence). La seule obligation est d'incorporer la notice de
|
||||||
copies. Voir le fichier [LICENSE](LICENSE) pour le texte complet.
|
licence et de copyright dans toutes les copies. Voir le fichier
|
||||||
|
[LICENSE](LICENSE) pour le texte complet.
|
||||||
|
52
install.py
Normal file
52
install.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
try:
|
||||||
|
import peewee
|
||||||
|
except ImportError:
|
||||||
|
print("Installing peewee")
|
||||||
|
p = subprocess.Popen([sys.executable, "-m", "pip", "install", "-U", "peewee"],
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
print(p.communicate())
|
||||||
|
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
except ImportError:
|
||||||
|
print("Installing requests")
|
||||||
|
p = subprocess.Popen([sys.executable, "-m", "pip", "install", "-U", "requests"],
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
print(p.communicate())
|
||||||
|
import requests
|
||||||
|
|
||||||
|
try:
|
||||||
|
import browser_cookie3
|
||||||
|
except ImportError:
|
||||||
|
print("Installing browser_cookie3")
|
||||||
|
p = subprocess.Popen([sys.executable, "-m", "pip", "install", "-U", "browser_cookie3"],
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
print(p.communicate())
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pandas
|
||||||
|
except ImportError:
|
||||||
|
print("Installing pandas")
|
||||||
|
p = subprocess.Popen([sys.executable, "-m", "pip", "install", "-U", "pandas"],
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
print(p.communicate())
|
||||||
|
|
||||||
|
try:
|
||||||
|
import xlrd
|
||||||
|
except ImportError:
|
||||||
|
print("Installing xlrd")
|
||||||
|
p = subprocess.Popen([sys.executable, "-m", "pip", "install", "-U", "xlrd"],
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
print(p.communicate())
|
||||||
|
|
||||||
|
try:
|
||||||
|
import numpy
|
||||||
|
except ImportError:
|
||||||
|
print("Installing numpy")
|
||||||
|
p = subprocess.Popen([sys.executable, "-m", "pip", "install", "-U", "numpy"],
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
print(p.communicate())
|
||||||
|
|
255
purge-registres-deces-insee/bdd_insee.py
Executable file
255
purge-registres-deces-insee/bdd_insee.py
Executable file
@ -0,0 +1,255 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
|
||||||
|
Classe d'accès aux données INSEE dans la base SQLite
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import peewee
|
||||||
|
import requests
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
# Objet de connexion à la base
|
||||||
|
database = peewee.SqliteDatabase(None)
|
||||||
|
|
||||||
|
|
||||||
|
# Définition du modèle de donnée
|
||||||
|
class BaseModel(peewee.Model):
|
||||||
|
class Meta:
|
||||||
|
database = database
|
||||||
|
|
||||||
|
|
||||||
|
class LastName(BaseModel):
|
||||||
|
"""Classe contenant tous les noms de famille
|
||||||
|
|
||||||
|
"""
|
||||||
|
last_name = peewee.CharField(unique=True)
|
||||||
|
|
||||||
|
|
||||||
|
class FirstName(BaseModel):
|
||||||
|
"""Classe contenant tous les prénoms
|
||||||
|
|
||||||
|
"""
|
||||||
|
first_name = peewee.CharField(unique=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Person(BaseModel):
|
||||||
|
"""Classe représentant une personne dans la base
|
||||||
|
|
||||||
|
"""
|
||||||
|
first_name = peewee.ForeignKeyField(FirstName)
|
||||||
|
last_name = peewee.ForeignKeyField(LastName)
|
||||||
|
is_woman = peewee.BooleanField()
|
||||||
|
date_naissance = peewee.DateField(index=True)
|
||||||
|
code_lieu_naissance = peewee.CharField()
|
||||||
|
commune_naissance = peewee.CharField()
|
||||||
|
pays_naissance = peewee.CharField()
|
||||||
|
date_deces = peewee.DateField()
|
||||||
|
code_lieu_deces = peewee.CharField()
|
||||||
|
numero_act_deces = peewee.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
class ImportedDataset(BaseModel):
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
dataset = peewee.CharField(unique=True)
|
||||||
|
|
||||||
|
# Gestion de l'accès aux données
|
||||||
|
class BddInsee:
|
||||||
|
"""Classe encapsulant les accès aux données.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, chemin_base_donnees=None):
|
||||||
|
"""Initialisation
|
||||||
|
|
||||||
|
:param chemin_base_donnees: chemin vers le fichier SQLite
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not chemin_base_donnees:
|
||||||
|
chemin_base_donnees = os.path.join(os.path.dirname(os.path.abspath(__file__)), "bdd_insee.sqlite")
|
||||||
|
new = not os.path.isfile(chemin_base_donnees)
|
||||||
|
database.init(chemin_base_donnees)
|
||||||
|
if new:
|
||||||
|
database.create_tables([LastName, FirstName, Person, ImportedDataset])
|
||||||
|
|
||||||
|
# Fonctions d'accès aux données
|
||||||
|
def find_person(self, first_name, last_name, maiden_name, annee_naissance, mois_naissance, jour_naissance):
|
||||||
|
"""Rechercher une personne dans la base
|
||||||
|
|
||||||
|
:param first_name: prénom de la personne à rechercher
|
||||||
|
:param last_name: nom de famille de la personne à rechercher
|
||||||
|
:param maiden_name: nom de jeune fille de la personne à rechercher (None si non défini)
|
||||||
|
:param annee_naissance: année de naissance de la personne à rechercher
|
||||||
|
:param mois_naissance: mois de naissance de la personne à rechercher
|
||||||
|
:param jour_naissance: jour de naissance de la personne à rechercher
|
||||||
|
:returns: liste contenant un dictionnaire par personne trouvée
|
||||||
|
|
||||||
|
"""
|
||||||
|
if maiden_name:
|
||||||
|
# return Person.select().where((Person.annee_naissance == int(annee_naissance))
|
||||||
|
# & (Person.mois_naissance == int(mois_naissance))
|
||||||
|
# & (Person.jour_naissance == int(jour_naissance))
|
||||||
|
# & (Person.first_name.contains(first_name.upper()))
|
||||||
|
# & ((Person.last_name.contains(last_name.upper()))
|
||||||
|
# | Person.last_name.contains(maiden_name.upper())))
|
||||||
|
query = Person.select().join(FirstName).switch(Person).join(LastName)\
|
||||||
|
.where((Person.date_naissance == datetime.date(int(annee_naissance), int(mois_naissance), int(jour_naissance)))
|
||||||
|
& (FirstName.first_name.contains(first_name.upper()))
|
||||||
|
& ((LastName.last_name.contains(last_name.upper()))
|
||||||
|
| LastName.last_name.contains(maiden_name.upper())))
|
||||||
|
else:
|
||||||
|
# return Person.select().where((Person.annee_naissance == int(annee_naissance))
|
||||||
|
# & (Person.mois_naissance == int(mois_naissance))
|
||||||
|
# & (Person.jour_naissance == int(jour_naissance))
|
||||||
|
# & (Person.first_name.contains(first_name.upper()))
|
||||||
|
# & (Person.last_name.contains(last_name.upper())))
|
||||||
|
query = Person.select().join(FirstName).switch(Person).join(LastName)\
|
||||||
|
.where((Person.date_naissance == datetime.date(int(annee_naissance), int(mois_naissance), int(jour_naissance)))
|
||||||
|
& (FirstName.first_name.contains(first_name.upper()))
|
||||||
|
& (LastName.last_name.contains(last_name.upper())))
|
||||||
|
result = list()
|
||||||
|
if query:
|
||||||
|
for row in query:
|
||||||
|
result.append({
|
||||||
|
'first_name': row.first_name.first_name,
|
||||||
|
'last_name': row.last_name.last_name,
|
||||||
|
'date_naissance': row.date_naissance,
|
||||||
|
'code_lieu_naissance': row.code_lieu_naissance,
|
||||||
|
'date_deces': row.date_deces,
|
||||||
|
'code_lieu_deces': row.code_lieu_deces
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Fonctions d'import des données
|
||||||
|
def parse_insee_data(self, data_text):
|
||||||
|
"""Parse le texte d'un fichier de l'INSEE
|
||||||
|
|
||||||
|
:param data_text: texte contenu dans un fichier de l'INSEE
|
||||||
|
:returns: liste de dictionnaires contenant les informations à insérer
|
||||||
|
"""
|
||||||
|
data_list = []
|
||||||
|
for line_number, line in enumerate(data_text.split('\n')):
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
last_name, first_name = line[0:80].strip()[:-1].split("*")
|
||||||
|
except ValueError:
|
||||||
|
if '*' not in line[0:80]:
|
||||||
|
continue
|
||||||
|
raise
|
||||||
|
date_naissance = self.parse_date(int(line[81:85]), int(line[85:87]), int(line[87:89]))
|
||||||
|
date_deces = self.parse_date(int(line[154:158]), int(line[158:160]), int(line[160:162]))
|
||||||
|
data_list.append({'last_name': last_name.upper(),
|
||||||
|
'first_name': first_name.strip('/').upper(),
|
||||||
|
'is_woman': (line[80] == "2"),
|
||||||
|
'date_naissance': date_naissance,
|
||||||
|
'code_lieu_naissance': line[89:94].upper(),
|
||||||
|
'commune_naissance': line[94: 124].strip().upper(),
|
||||||
|
'pays_naissance': line[124: 154].strip().upper(),
|
||||||
|
'date_deces': date_deces,
|
||||||
|
'code_lieu_deces': line[162:167].upper(),
|
||||||
|
'numero_act_deces': line[167:].strip().upper()})
|
||||||
|
except ValueError as e:
|
||||||
|
print(f"Erreur pour parser ligne numéro {line_number}.")
|
||||||
|
print(line)
|
||||||
|
raise
|
||||||
|
return data_list
|
||||||
|
|
||||||
|
def parse_date(self, year, month, day):
|
||||||
|
if year == 0:
|
||||||
|
return datetime.date.min
|
||||||
|
if month == 0:
|
||||||
|
month = 1
|
||||||
|
elif month > 12:
|
||||||
|
month = 12
|
||||||
|
if day == 0:
|
||||||
|
day = 1
|
||||||
|
elif day > 30 and month in [4, 6, 9, 11]:
|
||||||
|
day = 30
|
||||||
|
elif day > 31 and month in [1, 3, 5, 7, 8, 10, 12]:
|
||||||
|
day = 31
|
||||||
|
elif day > 29 and month == 2:
|
||||||
|
day = 29
|
||||||
|
try:
|
||||||
|
date = datetime.date(year, month, day)
|
||||||
|
except ValueError:
|
||||||
|
if month == 2 and day == 29 and year not in [1844, 1848, 1852, 1856, 1860, 1864, 1868, 1872, 1876, 1880,
|
||||||
|
1884, 1888, 1892, 1896, 1904, 1908, 1912, 1916, 1920,
|
||||||
|
1924, 1928, 1932, 1936, 1940, 1944, 1948, 1952, 1956, 1960,
|
||||||
|
1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, 2000,
|
||||||
|
2004, 2008, 2012, 2016, 2020]:
|
||||||
|
day = 28
|
||||||
|
date = datetime.date(year, month, day)
|
||||||
|
return date
|
||||||
|
|
||||||
|
def import_url_list(self, file_path):
|
||||||
|
"""Importer les données à partir d'un fichier contenant les URL
|
||||||
|
|
||||||
|
Un fichier d'URL contient un nom de dataset et une URL par ligne, sapéras par une espace. Chaque URL conduit
|
||||||
|
vers un fichier de l'insée qui doit être importé.
|
||||||
|
|
||||||
|
:param file_path: chemin vers le fichier d'URL
|
||||||
|
"""
|
||||||
|
if not os.path.isfile(file_path):
|
||||||
|
print(f"Le fichier {file_path} est introuvable.")
|
||||||
|
return
|
||||||
|
with open(file_path, 'r') as file_content:
|
||||||
|
for line in file_content.readlines():
|
||||||
|
try:
|
||||||
|
dataset, url = line.split(' ')
|
||||||
|
url = url.strip('\n')
|
||||||
|
except:
|
||||||
|
print(f"Le fichier {file_path} contient une ligne non conforme : {line}.")
|
||||||
|
continue
|
||||||
|
dataset_id = ImportedDataset.select().where(ImportedDataset.dataset == dataset)
|
||||||
|
if not len(dataset_id) == 0:
|
||||||
|
print(f"Le dataset {dataset} ne sera pas traité, car il a déjà été importé.")
|
||||||
|
continue
|
||||||
|
print(f"Importation du dataset {dataset}")
|
||||||
|
print(f"Téléchargement de : '{url}'.")
|
||||||
|
result = requests.get(url)
|
||||||
|
try:
|
||||||
|
result.raise_for_status()
|
||||||
|
except:
|
||||||
|
print(f"Erreur lors du téléchargement du fichier {url}.")
|
||||||
|
continue
|
||||||
|
print("Parse des données téléchargées")
|
||||||
|
data_list = self.parse_insee_data(result.text)
|
||||||
|
self.import_data_list(data_list, dataset)
|
||||||
|
|
||||||
|
def import_data_list(self, data_list, dataset_name):
|
||||||
|
"""Insérer des données dans la base
|
||||||
|
|
||||||
|
:param data_list: liste de dictionnaires contenant les informations à insérer
|
||||||
|
:param dataset_name: nom du jeu de données
|
||||||
|
"""
|
||||||
|
dataset_id = ImportedDataset.select().where(ImportedDataset.dataset == dataset_name)
|
||||||
|
if not len(dataset_id) == 0:
|
||||||
|
print(f"Le dataset {dataset_name} a déjà été importé.")
|
||||||
|
return
|
||||||
|
print(f"Import en base des {len(data_list)} personnes.")
|
||||||
|
with database.atomic():
|
||||||
|
for data in data_list:
|
||||||
|
# Gestion de la clé étrangère prénom
|
||||||
|
first_name = data.pop('first_name')
|
||||||
|
try:
|
||||||
|
first_name_id = FirstName.get(FirstName.first_name == first_name)
|
||||||
|
except peewee.DoesNotExist:
|
||||||
|
first_name_id = FirstName.create(first_name=first_name)
|
||||||
|
data['first_name'] = first_name_id
|
||||||
|
# Gestion de la clé étrangère nom de famille
|
||||||
|
last_name = data.pop('last_name')
|
||||||
|
try:
|
||||||
|
last_name_id = LastName.get(LastName.last_name == last_name)
|
||||||
|
except peewee.DoesNotExist:
|
||||||
|
last_name_id = LastName.create(last_name=last_name)
|
||||||
|
data['last_name'] = last_name_id
|
||||||
|
Person.insert(**data).execute()
|
||||||
|
ImportedDataset.insert(dataset=dataset_name).execute()
|
||||||
|
print("Import terminé")
|
83
purge-registres-deces-insee/completer_bdd_insee.py
Executable file
83
purge-registres-deces-insee/completer_bdd_insee.py
Executable file
@ -0,0 +1,83 @@
|
|||||||
|
"""Copyright (c) 2020 Sdj Geek
|
||||||
|
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Ce programme permet d'insérer les fichiers fournis par l'INSEE dans
|
||||||
|
une base de donnée SQLite.
|
||||||
|
|
||||||
|
Les fichiers fournis par l'INSEE sont disponibles en open data à
|
||||||
|
[cette
|
||||||
|
adresse](https://www.data.gouv.fr/fr/datasets/fichier-des-personnes-decedees/#_). Leur
|
||||||
|
formatage n'est pas très optimisé pour une utilisation dans un
|
||||||
|
programme. L'objet de ce programme est de transformer ces fichiers en
|
||||||
|
une base de donnée SDLite.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Auteur : SDJ GeeK <sdjgeek@protonmail.com>
|
||||||
|
Date : 7 juin 2020
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import peewee
|
||||||
|
|
||||||
|
from bdd_insee import BddInsee
|
||||||
|
|
||||||
|
|
||||||
|
def parse_insee_file(data_file_path):
|
||||||
|
"""Parse un fichier de l'INSEE
|
||||||
|
|
||||||
|
:param data_file_path: chemin vers le fichier à parser
|
||||||
|
:returns: liste de dictionnaires contenant les informations à insérer
|
||||||
|
|
||||||
|
"""
|
||||||
|
data_list = []
|
||||||
|
with open(data_file_path, 'r', encoding='latin1') as data_file:
|
||||||
|
for line in data_file.readlines():
|
||||||
|
try:
|
||||||
|
last_name, first_name = line[0:80].strip()[:-1].split("*")
|
||||||
|
data_list.append({'last_name': last_name.upper(),
|
||||||
|
'first_name': first_name.upper(),
|
||||||
|
'is_woman': (line[80] == "2"),
|
||||||
|
'annee_naissance': int(line[81:85]),
|
||||||
|
'mois_naissance': int(line[85:87]),
|
||||||
|
'jour_naissance': int(line[87:89]),
|
||||||
|
'code_lieu_naissance': line[89:94].upper(),
|
||||||
|
'commune_naissance': line[94: 124].strip().upper(),
|
||||||
|
'pays_naissance': line[124: 154].strip().upper(),
|
||||||
|
'annee_deces': int(line[154:158]),
|
||||||
|
'mois_deces': int(line[158:160]),
|
||||||
|
'jour_deces': int(line[160:162]),
|
||||||
|
'code_lieu_deces': line[162:167].upper(),
|
||||||
|
'numero_act_deces': line[167:].strip().upper()})
|
||||||
|
except ValueError:
|
||||||
|
print("Erreur pour parser ligne :")
|
||||||
|
print(line)
|
||||||
|
continue
|
||||||
|
return data_list
|
||||||
|
|
||||||
|
|
||||||
|
def completer_bdd_insee(chemin_base_donnees, chemin_repertoire_donnees):
|
||||||
|
"""Ajouter des données dans la base
|
||||||
|
|
||||||
|
:param chemin_base_donnees: chemin vers le fichier SQLite
|
||||||
|
:param chemin_repertoire_donnees: chemin vers le répertoire contenant les fichiers de l'INSEE
|
||||||
|
|
||||||
|
"""
|
||||||
|
base_insee = BddInsee(chemin_base_donnees)
|
||||||
|
for file_path in sorted(glob.glob(os.path.join(chemin_repertoire_donnees, "deces-*.txt"))):
|
||||||
|
print(f"Import du fichier {file_path}")
|
||||||
|
data_list = parse_insee_file(file_path)
|
||||||
|
base_insee.import_data_list(data_list)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("bdd_path", type=str, help="Chemin vers le fichier de base de donnée")
|
||||||
|
parser.add_argument("input_dir_path", type=str, help="Chemin vers le répertoire contenant les fichiers de l'INSEE")
|
||||||
|
args = parser.parse_args()
|
||||||
|
completer_bdd_insee(args.bdd_path, args.input_dir_path)
|
54
purge-registres-deces-insee/excel_in.py
Normal file
54
purge-registres-deces-insee/excel_in.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
|
||||||
|
Classe d'accès aux données du site de l'Église
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from membre_base import MembreBase, MembreProvider
|
||||||
|
|
||||||
|
|
||||||
|
class ExcelIn(MembreProvider):
|
||||||
|
|
||||||
|
def __init__(self, excel_path):
|
||||||
|
self.excel_path = excel_path
|
||||||
|
self.dataframe = None
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.dataframe)
|
||||||
|
|
||||||
|
class Member(MembreBase):
|
||||||
|
|
||||||
|
def __init__(self, provider, row):
|
||||||
|
super().__init__(provider)
|
||||||
|
self.r_id = str(row["id"])
|
||||||
|
self.r_first_name = str(row["first_name"]).strip().split(' ')[0].upper()
|
||||||
|
self.r_last_name = str(row["last_name"]).strip().split(' ')[0].upper()
|
||||||
|
self.r_maiden_name = str(row["maiden_name"]).strip().split(' ')[0].upper() if type(row["maiden_name"]) == np.str else None
|
||||||
|
self.r_annee = str(row["annee"])
|
||||||
|
self.r_mois = str(row["mois"])
|
||||||
|
self.r_jour = str(row["jour"])
|
||||||
|
self.r_ville = "<VIDE>"
|
||||||
|
self.r_sexe = "F" if str(row["status"]) == "Female" else "M"
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return os.path.basename(self.excel_path)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self.dataframe = pd.read_excel(self.excel_path, skiprows=[0, 1], usecols="B:E,G:I,K", header=None,
|
||||||
|
names=["last_name", "first_name", "maiden_name", "id", "jour", "mois", "annee",
|
||||||
|
"status"])
|
||||||
|
return len(self.dataframe)
|
||||||
|
|
||||||
|
def get_member_list(self):
|
||||||
|
for index, row in self.dataframe.iterrows():
|
||||||
|
try:
|
||||||
|
yield self.Member(self, row)
|
||||||
|
except ValueError:
|
||||||
|
print(f"Error with member [{row}]")
|
||||||
|
continue
|
30
purge-registres-deces-insee/excel_out.py
Normal file
30
purge-registres-deces-insee/excel_out.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
|
||||||
|
Classe d'accès aux données INSEE dans la base SQLite
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
|
||||||
|
class ExcelOut:
|
||||||
|
|
||||||
|
def __init__(self, out_path):
|
||||||
|
self.out_path = out_path
|
||||||
|
self.data = list()
|
||||||
|
|
||||||
|
def add_member(self, member):
|
||||||
|
self.data.append({
|
||||||
|
'nom_registres': member.get_nom_registres(),
|
||||||
|
'nom_insee': member.get_nom_insee(),
|
||||||
|
'mrn': member.r_id,
|
||||||
|
'death_year': member.i_annee_deces,
|
||||||
|
'death_month': member.i_mois_deces,
|
||||||
|
'death_day': member.i_jour_deces
|
||||||
|
})
|
||||||
|
|
||||||
|
def generate_output(self):
|
||||||
|
df = pd.DataFrame(self.data)
|
||||||
|
df.to_excel(self.out_path)
|
160
purge-registres-deces-insee/gui_trouver_decedes.py
Normal file
160
purge-registres-deces-insee/gui_trouver_decedes.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
|
||||||
|
Ce programme permet de comparer le fichier des personnes décédées établi par l'INSEE avec les registre de membres de
|
||||||
|
l'Église, afin de déterminer si figurent dans nos registre des personnes décédées.
|
||||||
|
|
||||||
|
L'INSEE reçoit des communes les décès enregistrés. Le fichier des personnes décédées établi par l'INSEE est en accès
|
||||||
|
libre sur le site https://www.data.gouv.fr.
|
||||||
|
|
||||||
|
"""
|
||||||
|
import tkinter as tk
|
||||||
|
import tkinter.ttk as ttk
|
||||||
|
import tkinter.filedialog as tkfiledialog
|
||||||
|
from multiprocessing import Process, Pipe
|
||||||
|
|
||||||
|
from trouver_decedes import trouver_decedes
|
||||||
|
|
||||||
|
|
||||||
|
class MainApplication(tk.Frame):
|
||||||
|
def __init__(self, parent, *args, **kwargs):
|
||||||
|
# Worker
|
||||||
|
self.run = False
|
||||||
|
self.pipe = None
|
||||||
|
|
||||||
|
# GUI
|
||||||
|
tk.Frame.__init__(self, parent, *args, **kwargs)
|
||||||
|
self.parent = parent
|
||||||
|
self.frame = tk.Frame(parent)
|
||||||
|
self.frame.pack()
|
||||||
|
|
||||||
|
# Sélection base INSEE
|
||||||
|
self.label_bdd_insee = tk.Label(self.frame, text="Fichier de l'INSEE")
|
||||||
|
self.label_bdd_insee.grid(row=0, column=0, sticky='e')
|
||||||
|
self.value_bdd_insee = tk.StringVar()
|
||||||
|
self.entry_bdd_insee = tk.Entry(self.frame, state='disabled', textvariable=self.value_bdd_insee)
|
||||||
|
self.entry_bdd_insee.grid(row=0, column=1, sticky='ew')
|
||||||
|
self.button_bdd_insee = tk.Button(self.frame, text="...", command=self.command_button_bdd_insee)
|
||||||
|
self.button_bdd_insee.grid(row=0, column=2, sticky='w')
|
||||||
|
|
||||||
|
# Sélection fichier Excel
|
||||||
|
self.label_fichier_excel = tk.Label(self.frame, text="Fichier Excel")
|
||||||
|
self.label_fichier_excel.grid(row=1, column=0, sticky='e')
|
||||||
|
self.value_fichier_excel = tk.StringVar()
|
||||||
|
self.entry_fichier_excel = tk.Entry(self.frame, state='disabled', textvariable=self.value_fichier_excel)
|
||||||
|
self.entry_fichier_excel.grid(row=1, column=1, sticky='ew')
|
||||||
|
self.button_fichier_excel = tk.Button(self.frame, text="...", command=self.command_button_fichier_excel)
|
||||||
|
self.button_fichier_excel.grid(row=1, column=2, sticky='w')
|
||||||
|
|
||||||
|
# Sélection répertoire sortie
|
||||||
|
self.label_dir_out = tk.Label(self.frame, text="Répertoire de sortie")
|
||||||
|
self.label_dir_out.grid(row=2, column=0, sticky='e')
|
||||||
|
self.value_dir_out = tk.StringVar()
|
||||||
|
self.entry_dir_out = tk.Entry(self.frame, state='disabled', textvariable=self.value_dir_out)
|
||||||
|
self.entry_dir_out.grid(row=2, column=1, sticky='ew')
|
||||||
|
self.button_dir_out = tk.Button(self.frame, text="...", command=self.command_button_dir_out)
|
||||||
|
self.button_dir_out.grid(row=2, column=2, sticky='w')
|
||||||
|
|
||||||
|
# Sélection des unités à traiter
|
||||||
|
self.label_units = tk.Label(self.frame, text="Unités à purger")
|
||||||
|
self.label_units.grid(row=3, column=0, sticky='e')
|
||||||
|
self.value_units = tk.StringVar()
|
||||||
|
self.entry_units = tk.Entry(self.frame, textvariable=self.value_units)
|
||||||
|
self.entry_units.grid(row=3, column=1, sticky='ew', columnspan="2")
|
||||||
|
|
||||||
|
# Bouton validation
|
||||||
|
self.button_valid = tk.Button(self.frame, text="Ok", command=self.command_button_valid)
|
||||||
|
self.button_valid.grid(row=4, column=0, columnspan=3)
|
||||||
|
|
||||||
|
# Barre de progression
|
||||||
|
self.progressbar = ttk.Progressbar(self.frame, orient=tk.HORIZONTAL, mode='determinate')
|
||||||
|
self.progressbar.grid(row=5, column=0, columnspan=3, sticky='ew')
|
||||||
|
|
||||||
|
# Affichage des logs
|
||||||
|
self.text_log = tk.Text(self.frame, state='disabled')
|
||||||
|
self.text_log.grid(row=0, column=3, rowspan=6, sticky='nesw')
|
||||||
|
|
||||||
|
def command_button_bdd_insee(self):
|
||||||
|
self.value_bdd_insee.set(tkfiledialog.askopenfilename(title="Fichier de l'INSEE"))
|
||||||
|
|
||||||
|
def command_button_fichier_excel(self):
|
||||||
|
self.value_fichier_excel.set(tkfiledialog.askopenfilename(title="Fichier Excel"))
|
||||||
|
|
||||||
|
def command_button_dir_out(self):
|
||||||
|
self.value_dir_out.set(tkfiledialog.askdirectory(title="Répertoire de sortie"))
|
||||||
|
|
||||||
|
def add_log(self, text):
|
||||||
|
self.text_log.configure(state='normal')
|
||||||
|
self.text_log.insert(tk.END, text)
|
||||||
|
self.text_log.configure(state='disabled')
|
||||||
|
|
||||||
|
def clear_log(self):
|
||||||
|
self.text_log.configure(state='normal')
|
||||||
|
self.text_log.delete('1.0', tk.END)
|
||||||
|
self.text_log.configure(state='disabled')
|
||||||
|
|
||||||
|
def watch(self):
|
||||||
|
if self.run:
|
||||||
|
if self.pipe.poll():
|
||||||
|
message = self.pipe.recv()
|
||||||
|
if message.get('step', False):
|
||||||
|
self.progressbar.step(message['step'])
|
||||||
|
elif message.get('text', False):
|
||||||
|
self.add_log(message['text'])
|
||||||
|
elif 'running' in message:
|
||||||
|
self.run = message['running']
|
||||||
|
elif message.get('set_max', False):
|
||||||
|
self.progressbar["value"] = 0
|
||||||
|
self.progressbar['maximum'] = message['set_max']
|
||||||
|
self.parent.after(100, self.watch)
|
||||||
|
else:
|
||||||
|
self.add_log("\nRecherche terminée\n")
|
||||||
|
self.button_valid.configure(state='normal')
|
||||||
|
|
||||||
|
def command_button_valid(self):
|
||||||
|
self.button_valid.configure(state='disabled')
|
||||||
|
self.clear_log()
|
||||||
|
self.run = True
|
||||||
|
(conn1, conn2) = Pipe()
|
||||||
|
self.pipe = conn1
|
||||||
|
unite = self.value_units.get().split(',')
|
||||||
|
if unite == ['']:
|
||||||
|
unite = None
|
||||||
|
Worker(conn2, self.value_bdd_insee.get(), self.value_fichier_excel.get(), self.value_dir_out.get(), unite).start()
|
||||||
|
self.watch()
|
||||||
|
|
||||||
|
|
||||||
|
class Worker(Process):
|
||||||
|
def __init__(self, pipe, bdd_insee, fichier_excel, dir_out, units):
|
||||||
|
Process.__init__(self)
|
||||||
|
self.pipe = pipe
|
||||||
|
self.bdd_insee = bdd_insee
|
||||||
|
self.fichier_excel = fichier_excel
|
||||||
|
self.dir_out = dir_out
|
||||||
|
self.units = units
|
||||||
|
|
||||||
|
def tracker(self, step=None, text=None, set_max=None, running=None):
|
||||||
|
if step is not None:
|
||||||
|
self.pipe.send({'step': step})
|
||||||
|
elif text is not None:
|
||||||
|
self.pipe.send({'text': text})
|
||||||
|
elif set_max is not None:
|
||||||
|
self.pipe.send({'set_max': set_max})
|
||||||
|
elif running is not None:
|
||||||
|
self.pipe.send({'running': running})
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
trouver_decedes(chemin_base_donnees=self.bdd_insee,
|
||||||
|
excel_path=self.fichier_excel,
|
||||||
|
chemin_repertoire_sortie=self.dir_out,
|
||||||
|
numeros_unites=self.units,
|
||||||
|
tracker=self.tracker)
|
||||||
|
self.pipe.send({'running': False})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title('Recherche des personnes décédées dans les registres')
|
||||||
|
MainApplication(root).pack(side="top", fill="both", expand=True)
|
||||||
|
root.mainloop()
|
116
purge-registres-deces-insee/membre_base.py
Normal file
116
purge-registres-deces-insee/membre_base.py
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from site_opendatasoft import get_ville_from_cog
|
||||||
|
|
||||||
|
|
||||||
|
class MembreBase(ABC):
|
||||||
|
|
||||||
|
def __init__(self, provider):
|
||||||
|
self.provider = provider
|
||||||
|
# Données issues des registres
|
||||||
|
self.r_id = None
|
||||||
|
self.r_first_name = None
|
||||||
|
self.r_last_name = None
|
||||||
|
self.r_maiden_name = None
|
||||||
|
self.r_annee = None
|
||||||
|
self.r_mois = None
|
||||||
|
self.r_jour = None
|
||||||
|
self.r_ville = None
|
||||||
|
self.r_sexe = None
|
||||||
|
|
||||||
|
# Données issues de l'INSEE
|
||||||
|
self.i_first_name = None
|
||||||
|
self.i_last_name = None
|
||||||
|
self.i_annee_naissance = None
|
||||||
|
self.i_mois_naissance = None
|
||||||
|
self.i_jour_naissance = None
|
||||||
|
self.i_ville_naissance = None
|
||||||
|
self.i_annee_deces = None
|
||||||
|
self.i_mois_deces = None
|
||||||
|
self.i_jour_deces = None
|
||||||
|
self.i_ville_deces = None
|
||||||
|
|
||||||
|
def get_nom_registres(self):
|
||||||
|
nom_registres = f"{self.r_last_name}, {self.r_first_name}"
|
||||||
|
if self.r_maiden_name:
|
||||||
|
nom_registres = f"{nom_registres} née {self.r_maiden_name.upper()}"
|
||||||
|
return nom_registres
|
||||||
|
|
||||||
|
def get_nom_insee(self):
|
||||||
|
return f"{self.i_last_name}, {self.i_first_name}"
|
||||||
|
|
||||||
|
def set_insee(self, insee):
|
||||||
|
self.i_first_name = insee['first_name']
|
||||||
|
self.i_last_name = insee['last_name']
|
||||||
|
self.i_annee_naissance = insee['date_naissance'].year
|
||||||
|
self.i_mois_naissance = insee['date_naissance'].month
|
||||||
|
self.i_jour_naissance = insee['date_naissance'].day
|
||||||
|
self.i_ville_naissance = insee['code_lieu_naissance']
|
||||||
|
self.i_annee_deces = insee['date_deces'].year
|
||||||
|
self.i_mois_deces = insee['date_deces'].month
|
||||||
|
self.i_jour_deces = insee['date_deces'].day
|
||||||
|
self.i_ville_deces = insee['code_lieu_deces']
|
||||||
|
|
||||||
|
def convertir_villes_insee(self):
|
||||||
|
old_value = self.i_ville_naissance
|
||||||
|
new_value = None
|
||||||
|
try:
|
||||||
|
int(self.i_ville_naissance)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
new_value = get_ville_from_cog(self.i_ville_naissance)
|
||||||
|
if new_value is not None:
|
||||||
|
self.i_ville_naissance = new_value
|
||||||
|
if old_value == self.i_ville_deces:
|
||||||
|
self.i_ville_deces = new_value
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
int(self.i_ville_deces)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
new_value = get_ville_from_cog(self.i_ville_deces)
|
||||||
|
if new_value is not None:
|
||||||
|
self.i_ville_deces = new_value
|
||||||
|
|
||||||
|
def get_texte_decede(self):
|
||||||
|
if self.r_sexe == "F":
|
||||||
|
feminin = "e"
|
||||||
|
elif self.r_sexe == "M":
|
||||||
|
feminin = ""
|
||||||
|
else:
|
||||||
|
feminin = "(e)"
|
||||||
|
self.convertir_villes_insee()
|
||||||
|
return f"""
|
||||||
|
Le membre {self.get_nom_registres()} ({self.r_id}),
|
||||||
|
né{feminin} le {self.r_jour:0>2}/{self.r_mois:0>2}/{self.r_annee:0>4} à {self.r_ville.upper()}
|
||||||
|
semble être décédé{feminin}.
|
||||||
|
Dans le fichier de l'INSEE on peut trouver {self.get_nom_insee()}
|
||||||
|
né{feminin} le {self.i_jour_naissance:0>2}/{self.i_mois_naissance:0>2}/{self.i_annee_naissance:0>4} à {self.i_ville_naissance}
|
||||||
|
décédé{feminin} le {self.i_jour_deces:0>2}/{self.i_mois_deces:0>2}/{self.i_annee_deces:0>4} à {self.i_ville_deces}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class MembreProvider(ABC):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def load(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_name(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __len__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_member_list(self):
|
||||||
|
pass
|
99
purge-registres-deces-insee/site_eglise.py
Normal file
99
purge-registres-deces-insee/site_eglise.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
|
||||||
|
Classe d'accès aux données du site de l'Église
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import browser_cookie3
|
||||||
|
|
||||||
|
from membre_base import MembreBase, MembreProvider
|
||||||
|
|
||||||
|
|
||||||
|
class SiteEglise(MembreProvider):
|
||||||
|
|
||||||
|
def __init__(self, unite, cookie_path=None):
|
||||||
|
"""
|
||||||
|
:param unite: numéro de l'unité (paroisse, branche)
|
||||||
|
:param cookie_path: chemin vers le répertoire où inscrire les fichiers de sortie
|
||||||
|
"""
|
||||||
|
self.unite = unite
|
||||||
|
self.cookie_jar = browser_cookie3.firefox(cookie_file=cookie_path)
|
||||||
|
self.as_json = None
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.as_json)
|
||||||
|
|
||||||
|
class Membre(MembreBase):
|
||||||
|
|
||||||
|
def __init__(self, provider, data):
|
||||||
|
super().__init__(provider)
|
||||||
|
self.completed = False
|
||||||
|
# Données fournies
|
||||||
|
self.r_id = data['legacyCmisId']
|
||||||
|
self.r_last_name, self.r_first_name = data['nameListPreferredLocal'].upper().split(',')
|
||||||
|
self.r_last_name = self.r_last_name.strip().split(' ')[0]
|
||||||
|
self.r_first_name = self.r_first_name.strip().split(' ')[0]
|
||||||
|
self.r_annee, self.r_mois, self.r_jour = data['birth']['date']['date'].split('-')
|
||||||
|
self.r_sexe = data['sex']
|
||||||
|
# Rechercher le nom de jeune fille si besoin
|
||||||
|
if data['isSpouse']:
|
||||||
|
self.complete()
|
||||||
|
|
||||||
|
def complete(self):
|
||||||
|
if not self.completed:
|
||||||
|
member_profile = self.provider.get_member_profile(self.r_id)
|
||||||
|
self.r_maiden_name = member_profile['individual']['maidenNameGroup']['name1']['family']
|
||||||
|
if self.r_maiden_name is not None:
|
||||||
|
self.r_maiden_name = self.r_maiden_name.strip().split(' ')[0].upper()
|
||||||
|
self.r_ville = member_profile['individual']['birthPlace']
|
||||||
|
if not self.r_ville:
|
||||||
|
self.r_ville = "<VIDE>"
|
||||||
|
self.completed = True
|
||||||
|
|
||||||
|
def set_insee(self, insee):
|
||||||
|
self.complete()
|
||||||
|
super().set_insee(insee)
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return f"Unité_{self.unite}"
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
r = requests.get('https://lcr.churchofjesuschrist.org/services/umlu/report/member-list',
|
||||||
|
params={'lang': "fra", 'unitNumber': self.unite},
|
||||||
|
headers={'Accept': "application/json"},
|
||||||
|
cookies=self.cookie_jar)
|
||||||
|
r.raise_for_status()
|
||||||
|
self.as_json = r.json()
|
||||||
|
return len(self.as_json)
|
||||||
|
|
||||||
|
def get_member_list(self):
|
||||||
|
"""Recevoir la liste des membres
|
||||||
|
|
||||||
|
|
||||||
|
:returns: la liste des membres sous forme d'objet JSON
|
||||||
|
|
||||||
|
"""
|
||||||
|
for member in self.as_json:
|
||||||
|
try:
|
||||||
|
yield self.Membre(self, member)
|
||||||
|
except ValueError:
|
||||||
|
print(f"Error with member [{member['nameListPreferredLocal']}, {member['birth']['date']['date']}]")
|
||||||
|
continue
|
||||||
|
|
||||||
|
def get_member_profile(self, member_id):
|
||||||
|
"""Recevoir les informations sur un membre
|
||||||
|
|
||||||
|
:param member_id: ID du membre
|
||||||
|
:returns: les informations sur le membre sous forme d'objet JSON
|
||||||
|
|
||||||
|
"""
|
||||||
|
r = requests.get(f'https://lcr.churchofjesuschrist.org/records/member-profile/service/{member_id}',
|
||||||
|
params={'lang': "fra"},
|
||||||
|
headers={'Accept': "application/json",
|
||||||
|
'Referer': f"https://lcr.churchofjesuschrist.org/records/member-profile/{member_id}?lang=fra"},
|
||||||
|
cookies=self.cookie_jar)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.json()
|
38
purge-registres-deces-insee/site_opendatasoft.py
Normal file
38
purge-registres-deces-insee/site_opendatasoft.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
|
||||||
|
Classe d'accès aux données du site https://public.opendatasoft.com
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
def get_ville_from_cog(cog):
|
||||||
|
"""
|
||||||
|
Donne le nom de la commune (et son code postal) correspondant au code officiel géographique (cog) donné en entrée.
|
||||||
|
|
||||||
|
:param cog: le code officiel géographique à convertie
|
||||||
|
:return: le nom de la commune (et son code postal). None si la recherche a échoué.
|
||||||
|
"""
|
||||||
|
# Contacter l'API
|
||||||
|
r = requests.get("https://public.opendatasoft.com/api/records/1.0/search/",
|
||||||
|
params={'dataset': "correspondance-code-insee-code-postal",
|
||||||
|
'q': f"insee_com={cog}",
|
||||||
|
'lang': "fr"},
|
||||||
|
headers={'Accept': "application/json"})
|
||||||
|
# Tester la validité de la réponse
|
||||||
|
try:
|
||||||
|
r.raise_for_status()
|
||||||
|
except requests.HTTPError:
|
||||||
|
print(f"Warning get_ville_from_cog: requests return status {r.headers}")
|
||||||
|
return None
|
||||||
|
# Récupérer le résultat
|
||||||
|
result = r.json()
|
||||||
|
# Si résultat non vide
|
||||||
|
if result['nhits'] > 0:
|
||||||
|
# COMMUNE (CODE POSTAL)
|
||||||
|
return f"{result['records'][0]['fields']['nom_comm']} ({result['records'][0]['fields']['postal_code']})"
|
||||||
|
print(f"Warning get_ville_from_cog: no result returned for cog {cog}")
|
||||||
|
return None
|
97
purge-registres-deces-insee/trouver_decedes.py
Executable file
97
purge-registres-deces-insee/trouver_decedes.py
Executable file
@ -0,0 +1,97 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2020 Sdj Geek
|
||||||
|
Voir le fichier LICENSE
|
||||||
|
|
||||||
|
Ce programme permet de comparer le fichier des personnes décédées établi par l'INSEE avec les registre de membres de
|
||||||
|
l'Église, afin de déterminer si figurent dans nos registre des personnes décédées.
|
||||||
|
|
||||||
|
L'INSEE reçoit des communes les décès enregistrés. Le fichier des personnes décédées établi par l'INSEE est en accès
|
||||||
|
libre sur le site https://www.data.gouv.fr.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
|
||||||
|
from bdd_insee import BddInsee
|
||||||
|
from site_eglise import SiteEglise
|
||||||
|
from excel_in import ExcelIn
|
||||||
|
from excel_out import ExcelOut
|
||||||
|
|
||||||
|
|
||||||
|
def default_tracker(step=None, text=None, set_max=None, running=None):
|
||||||
|
if text:
|
||||||
|
print(text)
|
||||||
|
|
||||||
|
|
||||||
|
def trouver_decedes(chemin_base_donnees, numeros_unites, chemin_repertoire_sortie, cookie_path=None, excel_path=None,
|
||||||
|
tracker=None):
|
||||||
|
"""Recherche les personnes décédées dans les registres
|
||||||
|
|
||||||
|
:param chemin_base_donnees: chemin vers le fichier SQLite
|
||||||
|
:param numeros_unites: liste des numéros d'unités à analyser
|
||||||
|
:param chemin_repertoire_sortie: chemin vers le répertoire où inscrire les fichiers de sortie
|
||||||
|
:param cookie_path: chemin vers la base de donnée des cookies
|
||||||
|
:param excel_path: chemin vers le fichier Excel contenant la liste des membres à rechercher
|
||||||
|
:param tracker: Objet permettant de suivre l'avancée du traitement
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Tracker par défaut
|
||||||
|
if tracker is None:
|
||||||
|
tracker = default_tracker
|
||||||
|
# Initialiser les accès aux données INSEE
|
||||||
|
base_insee = BddInsee(chemin_base_donnees)
|
||||||
|
# Initialiser les fournisseurs de liste de membres
|
||||||
|
fournisseurs_membres = list()
|
||||||
|
if excel_path:
|
||||||
|
fournisseurs_membres.append(ExcelIn(excel_path))
|
||||||
|
if numeros_unites:
|
||||||
|
for unite in numeros_unites:
|
||||||
|
fournisseurs_membres.append(SiteEglise(unite, cookie_path))
|
||||||
|
# Boucler sur la liste fournisseurs
|
||||||
|
for member_provider in fournisseurs_membres:
|
||||||
|
tracker(set_max=member_provider.load())
|
||||||
|
tracker(text=f"Recherche dans {member_provider.get_name()}\n")
|
||||||
|
# Récupérer la liste des membres
|
||||||
|
members = member_provider.get_member_list()
|
||||||
|
# Préparer les fichiers de sortie
|
||||||
|
output_base_name = os.path.join(chemin_repertoire_sortie, f"liste_membres_decedes_{member_provider.get_name()}")
|
||||||
|
output_txt = open(output_base_name + ".txt", 'w')
|
||||||
|
output_xls = ExcelOut(output_base_name + ".xlsx")
|
||||||
|
output_txt.write("Les lieux dans le fichier de l'INSEE sont donnés en Code Officiel Géographique en vigueur au moment de la prise en compte du décès\n")
|
||||||
|
# Boucler sur la liste des membres
|
||||||
|
for member in members:
|
||||||
|
query = base_insee.find_person(member.r_first_name, member.r_last_name, member.r_maiden_name,
|
||||||
|
member.r_annee, member.r_mois, member.r_jour)
|
||||||
|
for person in query:
|
||||||
|
member.set_insee(person)
|
||||||
|
text = member.get_texte_decede()
|
||||||
|
tracker(text=text)
|
||||||
|
output_txt.write(text)
|
||||||
|
output_xls.add_member(member)
|
||||||
|
tracker(step=1)
|
||||||
|
# Clore les fichiers de sortie
|
||||||
|
output_txt.close()
|
||||||
|
output_xls.generate_output()
|
||||||
|
tracker(running=False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description='Recherche des personnes décédées dans les registres.')
|
||||||
|
parser.add_argument('chemin_base_donnees', type=str, help="chemin vers la base de données")
|
||||||
|
parser.add_argument('chemin_repertoire_sortie', type=str, help="chemin vers le répertoire de sortie")
|
||||||
|
parser.add_argument('--numeros_unites', '-u', type=str, help="numéros des l'unités à traiter, séparés par des virgules (ex: 123,753,469)")
|
||||||
|
parser.add_argument('--cookie', '-c', type=str, help="chemin vers la base de donnée des cookies de Firefox")
|
||||||
|
parser.add_argument('--excel', '-e', type=str, help="chemin vers le fichier Excel contenant la liste des membres à rechercher")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.numeros_unites:
|
||||||
|
numeros_unites = args.numeros_unites.split(',')
|
||||||
|
else:
|
||||||
|
numeros_unites = list()
|
||||||
|
|
||||||
|
trouver_decedes(chemin_base_donnees=args.chemin_base_donnees,
|
||||||
|
numeros_unites=numeros_unites,
|
||||||
|
chemin_repertoire_sortie=args.chemin_repertoire_sortie,
|
||||||
|
cookie_path=args.cookie,
|
||||||
|
excel_path=args.excel)
|
@ -1,2 +1,6 @@
|
|||||||
peewee
|
peewee
|
||||||
requests
|
requests
|
||||||
|
browser_cookie3
|
||||||
|
pandas
|
||||||
|
xlrd
|
||||||
|
numpy
|
||||||
|
31
settings.py
31
settings.py
@ -1,31 +0,0 @@
|
|||||||
"""
|
|
||||||
Paramètres de l'application
|
|
||||||
- chemin_base_donnees : Le chemin vers le fichier téléchargé sur le site data.gouv.fr
|
|
||||||
- numeros_unites : La liste des unités que le programme doit tester. La liste commence par le caractère '['. Les
|
|
||||||
numéros d'unités sont séparés par des virgules. La liste se termine par le caractère ']'. Par exemple
|
|
||||||
[47823, 67745, 31456]
|
|
||||||
- cookie : Les cookies de la session au compte SDJ. Pour obtenir ces cookies il faut
|
|
||||||
1- Ouvrir Firefox
|
|
||||||
2- Ouvrir les outils de développement : CTRL + MAJ + E
|
|
||||||
3- Aller sur le site des outils pour greffiers : https://lds.org/lcr
|
|
||||||
4- Entrer identifiant et mot de passe SDJ
|
|
||||||
5- Aller dans la liste des membres
|
|
||||||
6- Dans l'outil de développement, cliquer sur la dernière ligne
|
|
||||||
7- Dans le paneau de droite, dans la section "En-tête de la requête", rechercher le champ "cookie"
|
|
||||||
8- Copier la valeur contenue dans ce champ
|
|
||||||
- chemin_repertoire_sortie : Le chemin vers le répertoire qui contiendra la fichiers de sortie
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Chemin complet vers le fichier contenant les registres de l'INSEE.
|
|
||||||
# Pour le télécharger, rendez-vous ici :
|
|
||||||
# https://git.roflcopter.fr/sdjgeek/purge-registres-deces-insee/-/wikis/home#t%C3%A9l%C3%A9charger-la-base-de-donn%C3%A9e
|
|
||||||
chemin_base_donnees = "/chemin/vers/fichier-des-personnes-decedees.sqlite"
|
|
||||||
|
|
||||||
# Numéro des l'unités à contrôler
|
|
||||||
numeros_unites = [47823, 67745, 31456]
|
|
||||||
|
|
||||||
# Cookie de session compte SDJ
|
|
||||||
cookie = ""
|
|
||||||
|
|
||||||
# Chemin vers le répertoire de sortie
|
|
||||||
chemin_repertoire_sortie = "/chemin/vers/repertoire-de-sortie"
|
|
2
start_windows.bat
Normal file
2
start_windows.bat
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
python install.py
|
||||||
|
python purge-registres-deces-insee\gui_trouver_decedes.py
|
@ -1,165 +0,0 @@
|
|||||||
"""
|
|
||||||
Copyright (c) 2020 Sdj Geek
|
|
||||||
|
|
||||||
Voir le fichier LICENSE
|
|
||||||
------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Ce programme permet de comparer le fichier des personnes décédées établi par l'INSEE avec les registre de membres de
|
|
||||||
l'Église, afin de déterminer si figurent dans nos registre des personnes décédées.
|
|
||||||
|
|
||||||
L'INSEE reçoit des communes les décès enregistrés. Le fichier des personnes décédées établi par l'INSEE est en accès
|
|
||||||
libre sur le site https://www.data.gouv.fr.
|
|
||||||
|
|
||||||
Comment utilise ce programme :
|
|
||||||
1) Demander le ficher de l'INSEE à cette adresse : sdjgeek@protonmail.com
|
|
||||||
2) Installer les dépendance du programme : "pip install requests peewee"
|
|
||||||
3) Configurer les paramètres du programme (fichier settings.py)
|
|
||||||
- chemin_base_donnees : Le chemin vers [le fichier téléchargé ici](https://git.roflcopter.fr/sdjgeek/purge-registres-deces-insee/-/wikis/home#t%C3%A9l%C3%A9charger-la-base-de-donn%C3%A9e)
|
|
||||||
- numeros_unites : La liste des unités que le programme doit tester. La liste commence par le caractère '['. Les
|
|
||||||
numéros d'unités sont séparés par des virgules. La liste se termine par le caractère ']'. Par exemple
|
|
||||||
[47823, 67745, 31456]
|
|
||||||
- cookie : Les cookies de la session au compte SDJ. Pour obtenir ces cookies il faut
|
|
||||||
1- Ouvrir Firefox
|
|
||||||
2- Ouvrir les outils de développement : CTRL + MAJ + E
|
|
||||||
3- Aller sur le site des outils pour greffiers : https://lds.org/lcr
|
|
||||||
4- Entrer identifiant et mot de passe SDJ
|
|
||||||
5- Aller dans la liste des membres
|
|
||||||
6- Dans l'outil de développement, cliquer sur la dernière ligne
|
|
||||||
7- Dans le paneau de droite, dans la section "En-tête de la requête", rechercher le champ "cookie"
|
|
||||||
8- Copier la valeur contenue dans ce champ
|
|
||||||
- chemin_repertoire_sortie : Le chemin vers le répertoire qui contiendra la fichiers de sortie
|
|
||||||
4) Exécuter le programme : "python3.6 trouver_decedes.py"
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Auteur : SDJ GeeK <sdjgeek@protonmail.com>
|
|
||||||
Date : 1 juin 2020
|
|
||||||
Version : 2.0
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import peewee
|
|
||||||
import requests
|
|
||||||
|
|
||||||
import settings as param
|
|
||||||
|
|
||||||
###
|
|
||||||
# Base de donnée INSEE
|
|
||||||
database = peewee.SqliteDatabase(param.chemin_base_donnees)
|
|
||||||
|
|
||||||
|
|
||||||
class Person(peewee.Model):
|
|
||||||
last_name = peewee.CharField()
|
|
||||||
first_name = peewee.CharField()
|
|
||||||
is_woman = peewee.BooleanField()
|
|
||||||
annee_naissance = peewee.IntegerField()
|
|
||||||
mois_naissance = peewee.IntegerField()
|
|
||||||
jour_naissance = peewee.IntegerField()
|
|
||||||
code_lieu_naissance = peewee.CharField()
|
|
||||||
commune_naissance = peewee.CharField()
|
|
||||||
pays_naissance = peewee.CharField()
|
|
||||||
annee_deces = peewee.IntegerField()
|
|
||||||
mois_deces = peewee.IntegerField()
|
|
||||||
jour_deces = peewee.IntegerField()
|
|
||||||
code_lieu_deces = peewee.CharField()
|
|
||||||
numero_act_deces = peewee.CharField()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
database = database
|
|
||||||
|
|
||||||
|
|
||||||
def find_person(first_name, last_name, maiden_name, annee_naissance, mois_naissance, jour_naissance):
|
|
||||||
if maiden_name:
|
|
||||||
return Person.select().where((Person.annee_naissance == int(annee_naissance))
|
|
||||||
& (Person.mois_naissance == int(mois_naissance))
|
|
||||||
& (Person.jour_naissance == int(jour_naissance))
|
|
||||||
& (Person.first_name.contains(first_name.upper()))
|
|
||||||
& ((Person.last_name.contains(last_name.upper()))
|
|
||||||
| Person.last_name.contains(maiden_name.upper())))
|
|
||||||
else:
|
|
||||||
return Person.select().where((Person.annee_naissance == int(annee_naissance))
|
|
||||||
& (Person.mois_naissance == int(mois_naissance))
|
|
||||||
& (Person.jour_naissance == int(jour_naissance))
|
|
||||||
& (Person.first_name.contains(first_name.upper()))
|
|
||||||
& (Person.last_name.contains(last_name.upper())))
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
# Registres de l'Église
|
|
||||||
def get_member_list(unit_number, cookie):
|
|
||||||
r = requests.get('https://lcr.churchofjesuschrist.org/services/umlu/report/member-list',
|
|
||||||
params={'lang': "fra", 'unitNumber': unit_number},
|
|
||||||
headers={'Accept': "application/json",
|
|
||||||
'Cookie': cookie})
|
|
||||||
r.raise_for_status()
|
|
||||||
return r.json()
|
|
||||||
|
|
||||||
|
|
||||||
def get_member_profile(member_id, cookie):
|
|
||||||
r = requests.get(f'https://lcr.churchofjesuschrist.org/records/member-profile/service/{member_id}',
|
|
||||||
params={'lang': "fra"},
|
|
||||||
headers={'Accept': "application/json",
|
|
||||||
'Cookie': cookie,
|
|
||||||
'Referer': f"https://lcr.churchofjesuschrist.org/records/member-profile/{member_id}?lang=fra"})
|
|
||||||
r.raise_for_status()
|
|
||||||
return r.json()
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
# Programme principal
|
|
||||||
|
|
||||||
# Boucler sur la liste des unités
|
|
||||||
for unite in param.numeros_unites:
|
|
||||||
print(f"Unité {unite}")
|
|
||||||
# Récupérer la liste des membres
|
|
||||||
members = get_member_list(unite, cookie=param.cookie)
|
|
||||||
|
|
||||||
# Préparer le fichier de sortie
|
|
||||||
output_file = os.path.join(param.chemin_repertoire_sortie, f"liste_membres_decedes_unite_{unite}.txt")
|
|
||||||
with open(output_file, 'w') as out_file:
|
|
||||||
out_file.write("Les lieux dans le fichier de l'INSEE sont donnés en Code Officiel Géographique en vigueur au moment de la prise en compte du décès\n")
|
|
||||||
# Boucler sur la liste des membres
|
|
||||||
for member in members:
|
|
||||||
# Lire les noms et date de naissance
|
|
||||||
name_registre = member['nameListPreferredLocal']
|
|
||||||
full_birthdate = member['birth']['date']['date']
|
|
||||||
maiden_name = None
|
|
||||||
ville_registre = None
|
|
||||||
# S'il s'agit d'une femme mariée, trouver son nom de jeune fille
|
|
||||||
if member['isSpouse']:
|
|
||||||
member_profile = get_member_profile(member['legacyCmisId'], cookie=param.cookie)
|
|
||||||
maiden_name = member_profile['individual']['maidenNameGroup']['name1']['family']
|
|
||||||
ville_registre = member_profile['individual']['birthPlace']
|
|
||||||
try:
|
|
||||||
last_name, first_name = name_registre.split(',')
|
|
||||||
annee_registre, mois_registre, jour_registre = full_birthdate.split('-')
|
|
||||||
except ValueError:
|
|
||||||
print(f"Error with member [{name_registre}, {full_birthdate}]")
|
|
||||||
continue
|
|
||||||
first_name = first_name.strip().split(' ')[0]
|
|
||||||
last_name = last_name.strip().split(' ')[0]
|
|
||||||
query = find_person(first_name, last_name, maiden_name, annee_registre, mois_registre, jour_registre)
|
|
||||||
name_registre = name_registre.upper()
|
|
||||||
if maiden_name:
|
|
||||||
name_registre = f"{name_registre} née {maiden_name.upper()}"
|
|
||||||
if member['sex'] == "F":
|
|
||||||
feminin = "e"
|
|
||||||
else:
|
|
||||||
feminin = ""
|
|
||||||
for person in query:
|
|
||||||
if not ville_registre:
|
|
||||||
member_profile = get_member_profile(member['legacyCmisId'], cookie=param.cookie)
|
|
||||||
ville_registre = member_profile['individual']['birthPlace']
|
|
||||||
if not ville_registre:
|
|
||||||
ville_registre = "<VIDE>"
|
|
||||||
text = f"""
|
|
||||||
Le membre {name_registre},
|
|
||||||
né{feminin} le {jour_registre:0>2}/{mois_registre:0>2}/{annee_registre:0>4} à {ville_registre.upper()}
|
|
||||||
semble être décédé{feminin}.
|
|
||||||
Dans le fichier de l'INSEE on peut trouver {person.last_name}, {person.first_name}
|
|
||||||
né{feminin} le {person.jour_naissance:0>2}/{person.mois_naissance:0>2}/{person.annee_naissance:0>4} à {person.code_lieu_naissance}
|
|
||||||
décédé{feminin} le {person.jour_deces:0>2}/{person.mois_deces:0>2}/{person.annee_deces:0>4} à {person.code_lieu_deces}
|
|
||||||
"""
|
|
||||||
print(text)
|
|
||||||
out_file.write(text)
|
|
Loading…
Reference in New Issue
Block a user