Skip to content

Instantly share code, notes, and snippets.

@seocam
Last active January 17, 2024 23:31
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save seocam/27dedc6164f0e0e31295a0ec7fcfa601 to your computer and use it in GitHub Desktop.
Save seocam/27dedc6164f0e0e31295a0ec7fcfa601 to your computer and use it in GitHub Desktop.
Converte CSV para um arquivo OFX aceito pela contabilizei
#!/usr/bin/env python
import argparse
import calendar
import itertools as it
from datetime import datetime
from csv2ofx import utils
from csv2ofx.mappings.default import mapping
from csv2ofx.ofx import OFX
from meza.io import IterStringIO, read_csv
def get_start_end(year, month):
last_day = calendar.monthrange(year, month)[1]
start = datetime(year, month, 1, 0, 0, 0)
end = datetime(year, month, last_day, 23, 59, 59)
return start, end
def get_first_record_year_month(filepath):
records = read_csv(filepath)
for record in records:
date = datetime.strptime(record["Date"], "%Y-%m-%d")
return date.year, date.month
def convert_to_ofx(filepath):
year, month = get_first_record_year_month(filepath)
start, end = get_start_end(year, month)
mapping["currency"] = "BRL"
ofx = OFX(mapping, def_type="CHECKING", start=start, end=end)
records = read_csv(filepath)
groups = ofx.gen_groups(records)
trxns = ofx.gen_trxns(groups)
cleaned_trxns = ofx.clean_trxns(trxns)
data = utils.gen_data(cleaned_trxns)
content = it.chain(
[
"OFXHEADER:100\n",
ofx.header(language="POR"),
ofx.gen_body(data),
ofx.footer(),
]
)
return b"\n".join(IterStringIO(content))
def get_parser():
parser = argparse.ArgumentParser(
description="Converte CSV para um OFX importável pela Contabilizei"
)
parser.add_argument("csv_file", help="Path of the input CSV file")
parser.add_argument("ofx_file", help="Path of the output OFX file")
return parser
def run():
args = get_parser().parse_args()
ofx_str = convert_to_ofx(args.csv_file)
with open(args.ofx_file, "w") as output:
output.write(ofx_str.decode("utf-8"))
if __name__ == "__main__":
run()
@seocam
Copy link
Author

seocam commented Sep 19, 2019

O arquivo CSV precisa ter os seguintes campos: Row, Account, Date, Amount, Reference, Num, Description, Notes

Row: número da linha (precisa ser único dentro do arquivo CSV)
Account: número da agência sem o dígito + número da conta corrente com o dígito.
Date: data em que a transação ocorreu
Amount: valor em reais (negativo pra retiradas/despesas ou positivo para depósitos/receitas)
Reference: referência bancária que aparece no extrato (exemplo: DEB PACOTE TARIFAS)
Num: número do documento (no extrato costuma aparecer com "DOC.:")
Description (opcional): descrição da transação
Notes (opcional): notas/comentário sobre a transação

Todos os campos precisam existir no CSV mas os opcionais não precisam ser preenchidos.
A primeira linha do arquivo CSV precisa conter o header com o nome dos campos.

Este script depende da lib csv2ofx (https://github.com/reubano/csv2ofx).

O script foi criado porque o NuConta PJ não exporta OFX e a contabilizei cobra ~R$20 para converter um extrato em OFX.
Enquanto o NuBank não libera o OFX esse script deve quebrar um galho.

@f4b10goncalves
Copy link

Também estou com o mesmo problema de enviar OFX para a Contabilizei, só que com o PagBank (PagSeguro). Vou tentar adaptar seu script para consumir o CSV exportado pelo PagBank, que é diferente do exportado pelo NuBank. Você poderia compartilhar um exemplo de arquivo OFX aceito pela Contabilizei, por favor?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment