Commit c108165f authored by Pierre-Elliott Bécue's avatar Pierre-Elliott Bécue

Scripts de trésorerie permettant de générer/parser des données

 * make_csv construit un csv des opérations relatives aux adhérents
   (cotisation, contribution accès internet, crédit solde)
 * parse_comnpay_csv permet en récupérant le relevé détaillé de comnpay de le
   parser et en produire un fichier de journal pour hledger.
parent b3a24565
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8; mode: python -*-
"""Permet de construire un CSV contenant l'ensemble des contributions
financières des adhérents sur une année civile."""
COMPTE_MEMBRES = "410 Membres"
COMPTE_COTISATIONS = "756 Cotisation"
# Impressions, accès internet
COMPTE_PRESTATIONS = "7061 Contribution accès internet"
COMPTE_SOLDE = "7062 Crédit solde"
FIELD_SEP = ','
CHAMPS = [
'date',
'description',
'amount',
'account1',
'account2'
]
import argparse
import re
import sys
from lc_ldap import shortcuts, objets
def collect_adh_cai(annee):
"""Récupère les données pour l'année fournie"""
out = []
conn = shortcuts.lc_ldap_readonly()
__filtre = u"(&(fid=*)(recuPaiement>=%(annee)s0101000000+0100)(recuPaiement<=%(annee)s1231235959+0100)(!(controle=FALSE)))" % {
'annee': annee,
}
factures = conn.search(
__filtre,
sizelimit=0,
)
for facture in factures:
date = facture['recuPaiement'][0].value.strftime("%d/%m/%Y")
_proprio = facture.proprio()
description = "%s %s" % (
_proprio['prenom'][0] if isinstance(_proprio, objets.adherent) else "Club",
_proprio['nom'][0],
)
for article in facture['article']:
if not u"CAI" in article["code"] and not "ADH" in article["code"] or float(article['pu']) == 0.0:
continue
category = COMPTE_COTISATIONS if article['code'] == u'ADH' else COMPTE_PRESTATIONS
memo = 'Adhésion' if article['code'] == u'ADH' else 'Contribution accès internet'
tn = str(article['pu'])
out.append({
'date': date,
'description': "%s de %s" % (memo, description,),
'amount': tn,
'account1': COMPTE_MEMBRES,
'account2': category,
})
with open("/usr/scripts/var/compta_adh_cai.csv", 'w') as csv_file:
csv_file.write(FIELD_SEP.join(CHAMPS) + "\n")
for entry in out:
csv_file.write(
"%s\n" % (
FIELD_SEP.join(
[
entry[champ]
for champ in CHAMPS
],
),
),
)
def collect_solde(annee):
"""Récupère les updates de solde (entrée d'argent réelle"""
conn = shortcuts.lc_ldap_readonly()
histo_solde_re = re.compile(
r'(?P<date>[0-9]{2}/[0-9]{2}/%s).*credit (?P<montant>[0-9]+.[0.*-9]{1,2}) Euros \[.*(note|carte|comnpay|paypal|intranet).*' % (annee,),
re.IGNORECASE,
)
# Récupère les adhérents dans un tableau.
adherents = conn.search(u'(&(aid=*)(uid=*))', sizelimit=0)
with open('/usr/scripts/var/compta_solde.csv', 'w') as solde_file:
solde_file.write(FIELD_SEP.join(CHAMPS) + '\n')
for adherent in adherents:
for histo_line in adherent['historique']:
z = histo_solde_re.match(unicode(histo_line))
if z is not None:
date = z.groupdict()['date']
montant = "%.2f" % (
float(z.groupdict()['montant']),
)
entry = {
'date': str(date),
'description': str(
"Crédit solde de %s %s" % (
adherent['prenom'][0] if isinstance(adherent, objets.adherent) else "Club",
adherent['nom'][0],
),
),
'amount': str(montant),
'account1': COMPTE_MEMBRES,
'account2': COMPTE_SOLDE,
}
solde_file.write(
FIELD_SEP.join(
[
entry[champ]
for champ in CHAMPS
]
) + '\n'
)
if __name__ == '__main__':
PARSER = argparse.ArgumentParser(description="Production d'un CSV à partir des factures.", add_help=False)
PARSER.add_argument('-c', '--cotis', action='store_true', help='Rapport des cotis/cai')
PARSER.add_argument('-h', '--help', action='store_true', help='Affiche cette aide et quitte.')
PARSER.add_argument('-s', '--solde', action='store_true', help='Uniquement le rapport des soldes')
PARSER.add_argument('-t', '--tout', action='store_true', help='Tout faire')
PARSER.add_argument('annee', type=str, nargs=1, help="L'année pour laquelle le CSV est à produire.")
ARGS = PARSER.parse_args()
if ARGS.help:
PARSER.print_help()
sys.exit(0)
if ARGS.tout:
ARGS.solde = True
ARGS.cotis = True
if ARGS.solde:
collect_solde(ARGS.annee[0])
if ARGS.cotis:
collect_adh_cai(ARGS.annee[0])
#!/bin/bash /usr/scripts/python.sh
# -*- mode: python ; coding: utf-8 -*-
import csv
import sys
import argparse
COMNPAY = "5127 Compte TPE virtuel ComNPay"
MEMBRES = "410 Membres"
SOGE = "5121 Compte Administration Société Générale"
COMMISSION = "62782 Commission transaction ComNPay"
VOL = "62783 Frais de virement ComNPay"
PAIEMENT_DICT = {
'minus': [
MEMBRES,
],
'minus_arg': 'entre',
'plus': [
COMMISSION,
COMNPAY,
],
'plus_arg': 'sort',
'label': 'Transaction liée à un crédit de solde',
}
TYPE_IDX = 4
TO_LOOK = {
'date': 14, # Date
'sort': 15, # Taxe
'entre': 16, # Entré
}
USEFUL_DATA = {
'Facture achat CB VAD 3DS' : PAIEMENT_DICT,
'Encaissement CB VAD' : PAIEMENT_DICT,
'Facture achat Mastercard VAD 3DS zone SEPA' : PAIEMENT_DICT,
'Frais sur Virement' : {
'minus': [
COMNPAY,
],
'minus_arg': 'sort',
'plus': [
VOL,
],
'plus_arg': 'sort',
'label': 'Commission pour virement vers compte externe',
},
'Virement Cpt Externe' : {
'minus': [
COMNPAY,
],
'minus_arg': 'sort',
'plus': [
SOGE,
],
'plus_arg': 'entre',
'label': 'Virement depuis le compte ComNPay vers le compte Société Générale',
},
}
def parse(filename):
"""Parse le fichier ComNpay et produit un csv gérable par hledger"""
entries = [
line
for line in csv.reader(open(filename))
][2:]
with open("/usr/scripts/var/comnpay_parsed.journal", "w") as hledger_journal:
for entry in entries:
op_type = entry[TYPE_IDX]
# La date est sous forme "dd/mm/YYYY HH:MM:SS", on ne veut que le jour/mois/année
# et on veut inverser le format pour hledger.
op_date = "/".join(entry[TO_LOOK['date']].split()[0].split("/")[::-1])
label = USEFUL_DATA[entry[TYPE_IDX]]['label']
minus = USEFUL_DATA[entry[TYPE_IDX]]['minus']
minus_arg = USEFUL_DATA[entry[TYPE_IDX]]['minus_arg']
plus = USEFUL_DATA[entry[TYPE_IDX]]['plus']
plus_arg = USEFUL_DATA[entry[TYPE_IDX]]['plus_arg']
# Écrit la date, suivie d'une espace et de la description de l'opération.
hledger_journal.write(
"%s %s\n" % (
op_date,
label,
),
)
hledger_journal.write(
" %s -%s\n" % (
minus[0],
entry[TO_LOOK[minus_arg]].replace(",", "."),
),
)
for sub in plus:
if sub != plus[-1]:
hledger_journal.write(
" %s %s\n" % (
sub,
entry[TO_LOOK[plus_arg]].replace(",", "."),
),
)
else:
hledger_journal.write(
" %s\n" % (
sub,
),
)
hledger_journal.write("\n")
if __name__ == "__main__":
PARSER = argparse.ArgumentParser(description="Parser le csv des opérations COMNPAY", add_help=False)
PARSER.add_argument('-h', '--help', action='store_true', help='Affiche cette aide et quitte.')
PARSER.add_argument('fichier', type=str, nargs=1, help="Chemin du fichier CSV à parser")
ARGS = PARSER.parse_args()
if ARGS.help:
PARSER.print_help()
sys.exit(0)
parse(ARGS.fichier[0])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment