ComptaClub/src/comptabilite/forms.py

283 lines
9.2 KiB
Python

# coding=utf-8
import csv
import math
import datetime
from django import forms
from .models import Transaction
class TransactionForm(forms.ModelForm):
class Meta:
model = Transaction
fields = [
"registrationDate",
"totalAmount",
"description",
"is_done",
"notes",
"counterpart",
"bkAmount",
"bxAmount",
"transaction_type",
"amount",
"otherDescription",
"account_number",
]
class MyDialect(csv.Dialect):
strict = True
skipinitialspace = True
quoting = csv.QUOTE_ALL
delimiter = ";"
quotechar = '"'
lineterminator = "\n"
# class KeytradeForm(TransactionForm):
# def __init__(self, item):
# current_dict = {
# 'registrationDate': datetime.datetime.strptime(row.get('Date'), '%d.%m.%Y'),
# 'totalAmount': float(row.get('Montant')),
# 'bkAmount': float(row.get('Montant')),
# 'amount': float(row.get('Montant')),
# 'transaction_type': 5,
# 'description': row.get('Description'),
# 'is_done': True,
# 'is_simulated': False,
# 'counterpart': row.get('Compte'),
# 'bxAmount': 0,
# 'otherDescription': row.get('Description'),
# 'account_number': row.get('Compte'),
# 'notes': row.get('Description'),
# }
# # Par défaut on considère que le montant est positif et
# # est donc une recette. Il faut donc corrigé si nécessaire.
# # id "Autre dépense" = 4 | id "Autre recette" = 5
# word = "cotisation"
# if current_dict['totalAmount'] < 0:
# current_dict['transaction_type'] = 4
# current_dict['totalAmount'] = math.fabs(current_dict['totalAmount'])
# current_dict['bkAmount'] = current_dict['totalAmount']
# current_dict['amount'] = current_dict['totalAmount']
# elif word in current_dict['description'].lower():
# current_dict['transaction_type'] = 6
# if current_dict['counterpart'] == "-":
# current_dict['counterpart'] = 'KEYTRADE'
# current_dict['transaction_type'] = 3
# super().init(current_dict)
# class CrelanForm(TransactionForm):
# def __init__(self, item):
# current_dict = {
# 'registrationDate': datetime.datetime.strptime(row.get('Date'), '%d/%m/%Y'),
# 'totalAmount': float(row.get('Montant')),
# 'bkAmount': float(row.get('Montant')),
# 'amount': float(row.get('Montant')),
# 'transaction_type': 5,
# 'description': row.get('Communication'),
# 'is_done': True,
# 'is_simulated': False,
# 'counterpart': row.get('Contrepartie'),
# 'bxAmount': 0,
# 'otherDescription': row.get("Type d'opération"),
# 'account_number': row.get('Compte contrepartie'),
# }
# # Par défaut on considère que le montant est positif et
# # est donc une recette. Il faut donc corrigé si nécessaire.
# # id "Autre dépense" = 4 | id "Autre recette" = 5
# word = "cotisation"
# if current_dict['totalAmount'] < 0:
# current_dict['transaction_type'] = 4
# current_dict['totalAmount'] = math.fabs(current_dict['totalAmount'])
# current_dict['bkAmount'] = current_dict['totalAmount']
# current_dict['amount'] = current_dict['totalAmount']
# elif word in current_dict['description'].lower():
# current_dict['transaction_type'] = 6
# if not current_dict['counterpart'] and not current_dict['description']:
# current_dict['counterpart'] = 'CRELAN'
# current_dict['description'] = row.get("Type d'opération")
# current_dict['transaction_type'] = 3
# current_dict['notes'] = current_dict['description']
# super().init(current_dict)
def import_csv_transaction(file, bank):
"""
Lit un fichier CSV exporté d'un compte et ajoute les lignes
dans la DB. Voici la liste des colonnes, DANS L'ORDRE, qui doivent être
présente dans le fichier (normalement, elles y sont de base) pour que
l'import se passe bien.
Args:
file (path): chemin vers le fichier à lire
bank (str): nom de la banque
Returns:
records_added (int): nombre de lignes insérées dans la base de données
errors (array): liste des erreurs rencontrées
"""
with open(file, "r") as csvfile:
errors = []
records_added = 0
reader = csv.DictReader(csvfile, dialect=MyDialect())
for row in reader:
if bank == "crelan":
myDict = map_crelan_dict(row)
else:
myDict = map_keytrade_dict(row)
form = TransactionForm(myDict)
if form.is_valid():
form.save()
records_added += 1
else:
print("Ligne en erreur…")
for key, value in form.errors.items():
print(key, "->", value)
errors.append(form.errors)
return records_added, errors
def get_key(current_dict, key, cast_type=None):
if cast_type:
return cast_type(current_dict.get(key)) if current_dict.get(key, None) else None
return current_dict.get(key, None)
def map_crelan_dict(row):
"""
Transforme une ligne du fichier CSV en dictionnaire pour le remplissage
d'un formulaire.
Args:
row (dictionary): transaction financière provenant du fichier CSV
Returns:
current_dict (dictionary): renvoie un dictionnaire pouvant être injecté dans un
transaction form.
"""
amount = get_key(row, "Montant", float)
current_dict = {
"registrationDate": datetime.datetime.strptime(row.get("Date"), "%d/%m/%Y")
if row.get("Date", None)
else None,
"totalAmount": amount,
"bkAmount": amount,
"amount": amount,
"transaction_type": 5,
"description": row.get("Communication")
if row.get("Communication", None)
else None,
"is_done": True,
"is_simulated": False,
"counterpart": row.get("Contrepartie")
if row.get("Contrepartie", None)
else None,
"bxAmount": 0,
"otherDescription": row.get("Type d'opération")
if row.get("Type d'opération", None)
else None,
"account_number": row.get("Compte contrepartie")
if row.get("Compte contrepartie", None)
else None,
}
current_dict = update_transaction_dict(current_dict)
if not current_dict["counterpart"] and not current_dict["description"]:
current_dict["counterpart"] = "CRELAN"
current_dict["description"] = row.get("Type d'opération")
current_dict["transaction_type"] = 3
current_dict["notes"] = current_dict["description"]
return current_dict
def map_keytrade_dict(row):
"""
Transforme une ligne du fichier CSV en dictionnaire pour le remplissage
d'un formulaire.
Args:
row (dictionary): transaction financière provenant du fichier CSV
Returns:
dictionary: renvoie un dictionnaire pouvant être injecté dans un
transaction form.
"""
amount = get_key(row, "Montant", float)
description = get_key(row, "Description")
account = get_key(row, "Compte")
current_dict = {
"registrationDate": datetime.datetime.strptime(row.get("Date"), "%d.%m.%Y")
if row.get("Date", None)
else None,
"totalAmount": amount,
"bkAmount": amount,
"amount": amount,
"transaction_type": 5,
"description": description,
"is_done": True,
"is_simulated": False,
"counterpart": account,
"bxAmount": 0,
"otherDescription": description,
"account_number": account,
"notes": description,
}
current_dict = update_transaction_dict(current_dict)
if current_dict["counterpart"] == "-":
current_dict["counterpart"] = "KEYTRADE"
current_dict["transaction_type"] = 3
return current_dict
def update_transaction_dict(current_dict):
"""
Par défaut on considère que le montant est positif et est donc une recette. Il faut donc
corriger, si nécessaire, le type de transaction et d'autres informations.
id "Autre dépense" = 4
id "Autre recette" = 5
Args:
current_dic (dictionary): dictionnaire pouvent être donné à un TransactionForm
Returns:
dictionary: renvoie un dictionnaire pouvant être injecté dans un
transaction form.
"""
word = "cotisation"
if current_dict["totalAmount"] is not None and current_dict["totalAmount"] < 0:
current_dict["transaction_type"] = 4
current_dict["totalAmount"] = math.fabs(current_dict["totalAmount"])
current_dict["bkAmount"] = current_dict["totalAmount"]
current_dict["amount"] = current_dict["totalAmount"]
elif (
current_dict["description"] is not None
and word in current_dict["description"].lower()
):
current_dict["transaction_type"] = 6
return current_dict