2022-02-03 00:05:59 +01:00
|
|
|
import csv
|
|
|
|
from itertools import islice
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
from beancount.ingest import cache, importer # type: ignore
|
|
|
|
|
|
|
|
|
|
|
|
INDEX_DATE = 0
|
|
|
|
INDEX_TRANSACTION_NUMBER = 1
|
|
|
|
INDEX_LABEL = 2
|
|
|
|
INDEX_DEBIT = 3
|
|
|
|
INDEX_CREDIT = 4
|
|
|
|
INDEX_DETAIL = 5
|
|
|
|
|
|
|
|
|
|
|
|
def is_valid_header(header: list[str]) -> bool:
|
|
|
|
return (
|
|
|
|
header[INDEX_DATE] == "Date"
|
|
|
|
and header[INDEX_TRANSACTION_NUMBER] == "Numéro d'opération"
|
|
|
|
and header[INDEX_LABEL] == "Libellé"
|
|
|
|
and header[INDEX_DEBIT] == "Débit"
|
|
|
|
and header[INDEX_CREDIT] == "Crédit"
|
|
|
|
and header[INDEX_DETAIL] == "Détail"
|
|
|
|
)
|
|
|
|
|
2022-02-01 23:17:34 +01:00
|
|
|
|
|
|
|
class CaisseDEpargneImporter(importer.ImporterProtocol):
|
2022-02-03 00:05:59 +01:00
|
|
|
def identify(self, file: cache._FileMemo) -> bool:
|
|
|
|
try:
|
|
|
|
# NOTE: beancount.ingest.cache._FileMemo handles automatic encoding
|
|
|
|
# detection
|
|
|
|
lines: list[str] = file.head().splitlines()
|
|
|
|
csv_reader = csv.reader(
|
|
|
|
lines, delimiter=";", strict=True, quoting=csv.QUOTE_NONE
|
|
|
|
)
|
|
|
|
|
|
|
|
# header is actually on the 5th line, the previous ones contain
|
|
|
|
# miscellaneous information
|
|
|
|
header: Optional[list[str]] = next(islice(csv_reader, 4, None))
|
|
|
|
|
|
|
|
if header is None:
|
|
|
|
return False
|
|
|
|
return is_valid_header(header)
|
2022-02-01 23:17:34 +01:00
|
|
|
|
2022-02-03 00:05:59 +01:00
|
|
|
except:
|
|
|
|
return False
|