Skip to content

Instantly share code, notes, and snippets.

@renzon
Created March 2, 2026 11:44
Show Gist options
  • Select an option

  • Save renzon/6d90ccfee88731259e52292f7c07ac10 to your computer and use it in GitHub Desktop.

Select an option

Save renzon/6d90ccfee88731259e52292f7c07ac10 to your computer and use it in GitHub Desktop.
Importador Nubank OFX - Categorização automática com 434 regras (Beancount)
import re
from datetime import date
from beancount.ingest.importer import ImporterProtocol
from beancount.core import amount, data
from ofxparse import OfxParser
_prefix_account_dct = {
'Desconto Antecipação': 'Income:Business:Nubank:Desconto',
# '':'Expenses:Mercado',
'Ederson':'Expenses:Mercado',
'Muniz':'Expenses:Mercado',
'Jim.Com':'Expenses:Mercado',
'Ricardo':'Expenses:Mercado',
'Alvino':'Expenses:Mercado',
'Banca do Silvio':'Expenses:Mercado',
'Bdm Mercado':'Expenses:Mercado',
'Jessianetobias':'Expenses:Mercado',
'Armazemda':'Expenses:Mercado',
'Karina Aparecida':'Expenses:Mercado',
'Juliocesarde':'Expenses:Mercado',
'Diego':'Expenses:Mercado',
'Mp *Thais':'Expenses:Mercado',
'Mp *Aguadecocosjc':'Expenses:Mercado',
'Lilianepaivasilva':'Expenses:Mercado',
'Teresinha':'Expenses:Mercado',
'Gabriel Figueiredo':'Expenses:Mercado',
'Cafe do Joao':'Expenses:Mercado',
'Vandersondinisda':'Expenses:Mercado',
'Jnt Legumes e Verduras':'Expenses:Mercado',
'31.529.460 Leandro':'Expenses:Mercado',
'Almir Faria':'Expenses:Mercado',
'Assai':'Expenses:Mercado',
'46.398.651 Francesca':'Expenses:Mercado',
'Paygo*Joao':'Expenses:Mercado',
'Gigiomaster':'Expenses:Mercado',
'Orgair Joaquim ':'Expenses:Mercado',
'Rigonan Paes':'Expenses:Mercado',
'Miyaguis':'Expenses:Mercado',
'Nagumo':'Expenses:Mercado',
'Andrezapaulo':'Expenses:Mercado',
'Ademirlemospontes':'Expenses:Mercado',
'Familho':'Expenses:Mercado',
'Casa de Carnes Majesta':'Expenses:Mercado',
'Diegohenrique':'Expenses:Mercado',
'P. M Furuiama Sandova':'Expenses:Mercado',
'Janeaparecida':'Expenses:Mercado',
'Deboraalexandre':'Expenses:Mercado',
'Leandroaparecido':'Expenses:Mercado',
'Paygo*Joao Aparecido':'Expenses:Mercado',
'Mp *Almir':'Expenses:Mercado',
'N S A Comercio de Alim':'Expenses:Mercado',
'Mp *Almir':'Expenses:Mercado',
'Leonardomartinsde':'Expenses:Mercado',
'Rubensrosella':'Expenses:Mercado',
'Marcia da Rocha Onari':'Expenses:Mercado',
'Amandamartins':'Expenses:Mercado',
'Lojas Americanas': 'Expenses:Mercado',
'Minuto Pa': 'Expenses:Mercado',
'Pao de Acucar': 'Expenses:Mercado',
'N S A Foods': 'Expenses:Mercado',
'Supermercado Maximo': 'Expenses:Mercado',
'Emporio de Paes Integr': 'Expenses:Mercado',
'Oba Hortifruti': 'Expenses:Mercado',
'Carrefour': 'Expenses:Mercado',
'Urbanova Carnes': 'Expenses:Mercado',
'Alvino\'S Confeitaria': 'Expenses:Mercado',
'Almirfaria': 'Expenses:Mercado',
'Devid': 'Expenses:Mercado',
'Fruit City': 'Expenses:Mercado',
'Padaria e Confeitaria': 'Expenses:Mercado',
'Cleyton G. Montuan': 'Expenses:Mercado',
'la Sardina': 'Expenses:Mercado',
'Sams': 'Expenses:Mercado',
'Villa Hortifruti': 'Expenses:Mercado',
'Sebastiaocarlosde': 'Expenses:Mercado',
'Jonathanmarcelo': 'Expenses:Mercado',
'Rogeralvesdemelo': 'Expenses:Mercado',
'Marlyarnautpena': 'Expenses:Mercado',
'Fsf Comercio de Alime': 'Expenses:Mercado',
'Expenses:Mercado': 'Expenses:Mercado',
'Tentacao': 'Expenses:Mercado',
'Granovie Mercado Nat': 'Expenses:Mercado',
'Tercioluizcaldas': 'Expenses:Mercado',
'Ricardopescados': 'Expenses:Mercado',
'Villarreal': 'Expenses:Mercado',
'Alexcasaltavieira': 'Expenses:Mercado',
'Mp *Fabiotourrj': 'Expenses:Mercado',
'Tauste': 'Expenses:Mercado',
'Emporio Santa Gula': 'Expenses:Mercado',
'Guilherme da S Leal': 'Expenses:Mercado',
'Padaria': 'Expenses:Mercado',
'Aparecidadefatima': 'Expenses:Mercado',
'Carol Alimentos Aparec': 'Expenses:Mercado',
'Zelainepescados': 'Expenses:Mercado',
'David': 'Expenses:Mercado',
'Pg *Mada Comercio de R': 'Expenses:Mercado',
'Ldonizettidefaria': 'Expenses:Mercado',
'Sitio Verde': 'Expenses:Mercado',
'Josericardopralon': 'Expenses:Mercado',
'Mercadinho Saturno': 'Expenses:Mercado',
'39452045tania': 'Expenses:Mercado',
'Amandamartins':'Expenses:Mercado',
'Marcelodefaria':'Expenses:Mercado',
'Supermercado Jk':'Expenses:Mercado',
'Marcelavitoriano':'Expenses:Mercado',
# '':'Expenses:Restaurante',
'Diallalopesdias':'Expenses:Restaurante',
'Golden':'Expenses:Restaurante',
'Estacao Coronel':'Expenses:Restaurante',
'Fbr':'Expenses:Restaurante',
'Segretini':'Expenses:Restaurante',
'Leandro':'Expenses:Mercado',
'Fairy Cake':'Expenses:Restaurante',
'Empanada':'Expenses:Restaurante',
'Kfc':'Expenses:Restaurante',
'Sapore':'Expenses:Restaurante',
'Gopag S*Ponto da Parri':'Expenses:Restaurante',
'Ifd':'Expenses:Restaurante',
'Grand Parrilla':'Expenses:Restaurante',
'Bigjohnburguer':'Expenses:Restaurante',
'Sjkbarerestaurant':'Expenses:Restaurante',
'Divino Fogao':'Expenses:Restaurante',
'Elianeferreirade':'Expenses:Restaurante',
'Loja Nova - Bullguer':'Expenses:Restaurante',
'Frangoefilegrill':'Expenses:Restaurante',
'Pointdoacai':'Expenses:Restaurante',
'Nsa Comercio Alimentos':'Expenses:Restaurante',
'Churraskilo':'Expenses:Restaurante',
'Cristiane Tieko':'Expenses:Restaurante',
'Leandro Aparecido ':'Expenses:Restaurante',
'Aguadecocos':'Expenses:Restaurante',
'Fazenda da Comadre':'Expenses:Restaurante',
'Rrpgelateria':'Expenses:Restaurante',
'Chiquinho':'Expenses:Restaurante',
'Xun Barbaresco':'Expenses:Restaurante',
'Mp *Helena':'Expenses:Restaurante',
'Mara Cakes':'Expenses:Restaurante',
'Hokkaido':'Expenses:Restaurante',
'Pointdoacai"':'Expenses:Restaurante',
'Cacau Show':'Expenses:Restaurante',
'Subway':'Expenses:Restaurante',
'Toquedenut':'Expenses:Restaurante',
'Zp*Barbaresco Express':'Expenses:Restaurante',
'Pastel da Neni':'Expenses:Restaurante',
'Hoken Sushi':'Expenses:Restaurante',
'Gelateria Borelli':'Expenses:Restaurante',
'Cafe Donuts':'Expenses:Restaurante',
'Reaiche':'Expenses:Restaurante',
'Melt':'Expenses:Restaurante',
'Restaurante':'Expenses:Restaurante',
'Xttbarbaresco':'Expenses:Restaurante',
'Ternopil':'Expenses:Restaurante',
'Rei do Mate Vale Sul':'Expenses:Restaurante',
'Troina':'Expenses:Restaurante',
'Lanchonete':'Expenses:Restaurante',
'Container Burger':'Expenses:Restaurante',
'Maicon Douglas de Oliv':'Expenses:Restaurante',
'Bom Pastel':'Expenses:Restaurante',
'Lcs Vale Restaurante':'Expenses:Restaurante',
'Orient Express':'Expenses:Restaurante',
'Boali - Colinas Shop':'Expenses:Restaurante',
'Fwl Alimentos':'Expenses:Restaurante',
'Bacio Di Latte': 'Expenses:Restaurante',
'Oakberry Acai': 'Expenses:Restaurante',
'Espresso Latte': 'Expenses:Restaurante',
'Mc Donalds': 'Expenses:Restaurante',
'Ifood': 'Expenses:Restaurante',
'Zig*Fazenda da Vovo': 'Expenses:Restaurante',
'Demoiselle Restaurante': 'Expenses:Restaurante',
'Sheriff Beer Bbq': 'Expenses:Restaurante',
'Kiosque Kalango': 'Expenses:Restaurante',
'Mais1 Cafe Sp': 'Expenses:Restaurante',
'Oakberry Acai': 'Expenses:Restaurante',
'Pizza': 'Expenses:Restaurante',
'Outback': 'Expenses:Restaurante',
'Ifd*': 'Expenses:Restaurante',
'Apa Vale': 'Expenses:Restaurante',
'Chale da Pamonha': 'Expenses:Restaurante',
'Spetinho': 'Expenses:Restaurante',
'Boteco': 'Expenses:Restaurante',
'Asami Sushi': 'Expenses:Restaurante',
'Patia': 'Expenses:Restaurante',
'Barbaresco': 'Expenses:Restaurante',
'Al Badah': 'Expenses:Restaurante',
'Coco Bambu': 'Expenses:Restaurante',
'Jardim do Cafe': 'Expenses:Restaurante',
'Fuxiqueira Santos': 'Expenses:Restaurante',
'Sandra Uema Sao Vicent': 'Expenses:Restaurante',
'Capodarte Oscar': 'Expenses:Restaurante',
'Acqio*Up Urbapizza': 'Expenses:Restaurante',
'Posto 012 e Esporte': 'Expenses:Restaurante',
'Cap Quiero': 'Expenses:Restaurante',
'Expenses:Unknown':'Expenses:Restaurante',
'Toca do Mineiro':'Expenses:Restaurante',
'Lig Lig':'Expenses:Restaurante',
# '':'Expenses:Familia:Saude',
'Hospital Policlin':'Expenses:Familia:Saude',
'Drogasil':'Expenses:Familia:Saude',
'Byoformula Sjc':'Expenses:Familia:Saude',
'Mercadopago *Growthsu':'Expenses:Familia:Saude',
'Pg *Pp Reggia':'Expenses:Familia:Saude',
'Hosp Vivalle':'Expenses:Familia:Saude',
'Pg *Pp Terapeutica':'Expenses:Familia:Saude',
'Farma':'Expenses:Familia:Saude',
'Cipax':'Expenses:Familia:Saude',
'Original Nutri':'Expenses:Familia:Saude',
'Hakim Farma':'Expenses:Familia:Saude',
'Raia': 'Expenses:Familia:Saude',
'Elisvacinas': 'Expenses:Familia:Saude',
'Drogaria': 'Expenses:Familia:Saude',
'Pg *Medmanipulado': 'Expenses:Familia:Saude',
'Mp *Growthsupplements': 'Expenses:Familia:Saude',
'Terapeutica Farmacia': 'Expenses:Familia:Saude',
# '':'Expenses:Transporte:Carro',
'Bp Crs':'Expenses:Transporte:Carro',
'Urentcar':'Expenses:Transporte:Carro',
'Gp Negocios Lava Rapid':'Expenses:Transporte:Carro',
'Maxx Jato':'Expenses:Transporte:Carro',
'Postosete':'Expenses:Transporte:Carro',
'Allpark':'Expenses:Transporte:Carro',
'Auto Posto':'Expenses:Transporte:Carro',
'Vallparking':'Expenses:Transporte:Carro',
'Mss Park Estacionament':'Expenses:Transporte:Carro',
'Mobiciti':'Expenses:Transporte:Carro',
'Cpark':'Expenses:Transporte:Carro',
'Ayuni Centro Automot':'Expenses:Transporte:Carro',
'NuTag':'Expenses:Transporte:Carro',
'Posto-2504-Colinas':'Expenses:Transporte:Carro',
'Mhh':'Expenses:Transporte:Carro',
'MOBILICIDADE':'Expenses:Transporte:Carro',
'Zae':'Expenses:Transporte:Carro',
'Auto Posto':'Expenses:Transporte:Carro',
'Estacionamento': 'Expenses:Transporte:Carro',
'Autoposto': 'Expenses:Transporte:Carro',
'Ancar Parking': 'Expenses:Transporte:Carro',
'Transação de NuTag': 'Expenses:Transporte:Carro',
'Executive Parking': 'Expenses:Transporte:Carro',
'Colinas Pay': 'Expenses:Transporte:Carro',
'Yelum': 'Expenses:Transporte:Carro',
'Liberty Seguros': 'Expenses:Transporte:Carro',
# '':'Expenses:Transporte:Uber',
'Buser': 'Expenses:Transporte:Uber',
'Uber': 'Expenses:Transporte:Uber',
'Movida': 'Expenses:Transporte:Uber',
# '':'Expenses:Lazer',
'Vale Eventos':'Expenses:Lazer',
'Mp *Camilashesebr':'Expenses:Lazer',
'Senhor Smart':'Expenses:Lazer',
'Pg *Pedido Pago Intern':'Expenses:Lazer',
'Swsjcroupase':'Expenses:Lazer',
'Nagata Shoes':'Expenses:Lazer',
'Eccere Centro':'Expenses:Lazer',
'On Mart ':'Expenses:Lazer',
'Julliekelly':'Expenses:Lazer',
'Asa*Gabriel':'Expenses:Lazer',
'Stb*Buscacenter':'Expenses:Lazer',
'Angel Presentes':'Expenses:Lazer',
'Trailler':'Expenses:Lazer',
'Du Chapeu':'Expenses:Lazer',
'Du Chapeu':'Expenses:Lazer',
'Aqualanches':'Expenses:Lazer',
'Wdn':'Expenses:Lazer',
'Bazar Baby Kids':'Expenses:Lazer',
'Surbanova':'Expenses:Lazer',
'00355 Sh Colinas':'Expenses:Lazer',
'00030 Sh Centervale':'Expenses:Lazer',
'Empreendimentos Turist':'Expenses:Lazer',
'Lxj Presentes':'Expenses:Lazer',
'Reve Perfumes':'Expenses:Lazer',
'Animalia':'Expenses:Lazer',
'Glow Park':'Expenses:Lazer',
'Casa de Bolos Urbanova':'Expenses:Lazer',
'Pesqueiro':'Expenses:Lazer',
'Mio':'Expenses:Lazer',
'Hillarius':'Expenses:Lazer',
'Cinemark':'Expenses:Lazer',
'Fontanezi Franquias':'Expenses:Lazer',
'Tcketnamao':'Expenses:Lazer',
'Stafeba*Lanchdinossa':'Expenses:Lazer',
'Georgesseven':'Expenses:Lazer',
'Idealizzare':'Expenses:Lazer',
'Cervejaria':'Expenses:Lazer',
'Domis Milho':'Expenses:Lazer',
'Sorveteira':'Expenses:Lazer',
'Zig*Sea Lounge':'Expenses:Lazer',
'Dibran Turismo':'Expenses:Lazer',
'Zp *Elo7 Elo7':'Expenses:Lazer',
'Shein':'Expenses:Lazer',
'Vivara':'Expenses:Lazer',
'Shx':'Expenses:Lazer',
'Saborqueromais':'Expenses:Lazer',
'Paroquia':'Expenses:Lazer',
'Tecplant':'Expenses:Lazer',
'Jian Presentes':'Expenses:Lazer',
'King Bike':'Expenses:Lazer',
'Sp Sao Jose Campos Val':'Expenses:Lazer',
'Vmt Telecomunicacoes':'Expenses:Lazer',
'8gs Diversoes':'Expenses:Lazer',
'Oitopeia':'Expenses:Lazer',
'Pousada':'Expenses:Lazer',
'Redecine-Valesul Cine':'Expenses:Lazer',
'Sorveteria':'Expenses:Lazer',
'Mambuca Village':'Expenses:Lazer',
'Acqualanches':'Expenses:Lazer',
'Zp *Thermas':'Expenses:Lazer',
'Redecine-Valesul ':'Expenses:Lazer',
'Kopenhagen':'Expenses:Lazer',
'Lvmlojade':'Expenses:Lazer',
'Shopping Certer Valle':'Expenses:Lazer',
'Daiso':'Expenses:Lazer',
'Easyjet':'Expenses:Lazer',
'7071 Sao Jose dos Ca':'Expenses:Lazer',
'Quintal Bar Food Skate':'Expenses:Lazer',
'Lojas Renascer':'Expenses:Lazer',
'Sympla':'Expenses:Lazer',
'Toykidzmachine': 'Expenses:Lazer',
'Festou': 'Expenses:Lazer',
'Netflix': 'Expenses:Lazer',
'S J': 'Expenses:Lazer',
'Pg *Ton Maria Eduard': 'Expenses:Lazer',
'Jetshr': 'Expenses:Lazer',
'Jetshr': 'Expenses:Lazer',
'Sonia Batistela':'Expenses:Lazer',
'Pe de Moleque da Barra':'Expenses:Lazer',
# '':'Expenses:Familia:Priscila',
'Botiques':'Expenses:Familia:Priscila',
'Mundo do Cabeleireiro':'Expenses:Familia:Priscila',
'Otica Urbanova':'Expenses:Familia:Priscila',
'Fcs Diagnostico Odont':'Expenses:Familia:Priscila',
'Julio Cesar':'Expenses:Familia:Priscila',
'Polyotica':'Expenses:Familia:Priscila',
'Mp *Dceatariesmal':'Expenses:Familia:Priscila',
'Fashion Biju':'Expenses:Familia:Priscila',
'We Pink':'Expenses:Familia:Priscila',
'Masterformula':'Expenses:Familia:Priscila',
'Toy Life':'Expenses:Familia:Priscila',
'Studio Velocity':'Expenses:Familia:Priscila',
'Jefferson Fernando':'Expenses:Familia:Priscila',
'Trhs Amis Boutique':'Expenses:Familia:Priscila',
'Polyotica Colinas':'Expenses:Familia:Priscila',
'Studio Francesca Bian':'Expenses:Familia:Priscila',
'D. Cestari Esmalteria':'Expenses:Familia:Priscila',
'Matsunos':'Expenses:Familia:Priscila',
'Urba Cell':'Expenses:Familia:Priscila',
'Loungerie':'Expenses:Familia:Priscila',
'Lojas Renner':'Expenses:Familia:Priscila',
'Youcom':'Expenses:Familia:Priscila',
'Accv Calcados':'Expenses:Familia:Priscila',
'Apple.Com': 'Expenses:Familia:Priscila',
'Lemoa Cosmeticos': 'Expenses:Familia:Priscila',
'Uni Esmalteria': 'Expenses:Familia:Priscila',
# '':'Expenses:Cachorro',
'Manavet Servicos Vete':'Expenses:Cachorro',
'Popular Pet': 'Expenses:Cachorro',
# '':'Expenses:Familia:Filhos',
'Gift Mix Papelaria':'Expenses:Familia:Filhos',
'Stb*Fofo Papelaria':'Expenses:Familia:Filhos',
'Big Jump Park Rio':'Expenses:Familia:Filhos',
'Gigio':'Expenses:Familia:Filhos',
'Livestorebrasi':'Expenses:Familia:Filhos',
'Gigafesta':'Expenses:Familia:Filhos',
'Franco Bolfarini':'Expenses:Familia:Filhos',
'Leitura Colinas':'Expenses:Familia:Filhos',
'Nutrebem':'Expenses:Familia:Filhos',
'Facilivro':'Expenses:Familia:Filhos',
'D.D.K.S Confeccoes':'Expenses:Familia:Filhos',
'Mercadolivre*Trwindus':'Expenses:Familia:Filhos',
'Kalunga':'Expenses:Familia:Filhos',
'Inovathi':'Expenses:Familia:Filhos',
'Cea Vsu 203':'Expenses:Familia:Filhos',
'Decathlon':'Expenses:Familia:Filhos',
'Fr4 Fitness': 'Expenses:Familia:Filhos',
'Rm Confeccoes': 'Expenses:Familia:Filhos',
'Gracie Barra': 'Expenses:Familia:Filhos',
'Papelaria': 'Expenses:Familia:Filhos',
'Arena': 'Expenses:Familia:Filhos',
'Tribo do Papel': 'Expenses:Familia:Filhos',
'Puket': 'Expenses:Familia:Filhos',
'Don Guillermo': 'Expenses:Familia:Filhos',
'Pbkids Brinquedos':'Expenses:Familia:Filhos',
'Baby Hair':'Expenses:Familia:Filhos',
'Ri Happy Brinquedos':'Expenses:Familia:Filhos',
# '':'Expenses:Familia:Renzo',
'Granovie':'Expenses:Familia:Renzo',
'Prainha':'Expenses:Familia:Renzo',
'Greenn**Educacao Real':'Expenses:Familia:Renzo',
'Asaas *Tudo':'Expenses:Familia:Renzo',
'Fisia Nfs2050':'Expenses:Familia:Renzo',
'Farma Reggia Farm':'Expenses:Familia:Renzo',
'Xtrack Sjc':'Expenses:Familia:Renzo',
'Centauro':'Expenses:Familia:Renzo',
'Hering':'Expenses:Familia:Renzo',
'Fisia Nike Ecommer':'Expenses:Familia:Renzo',
'Ppro *Microsoft': 'Expenses:Familia:Renzo',
'Penaareiasports': 'Expenses:Familia:Renzo',
'Abraao Barbearia': 'Expenses:Familia:Renzo',
'Casa das Cuecas': 'Expenses:Familia:Renzo',
'Democrata': 'Expenses:Familia:Renzo',
'Centauro Ce85': 'Expenses:Familia:Renzo',
'Insider Come': 'Expenses:Familia:Renzo',
'Cyclex': 'Expenses:Familia:Renzo',
'S Stein Joalheiros': 'Expenses:Familia:Renzo',
'Quiosquepenaareia':'Expenses:Familia:Renzo',
# '':'Assets:Caixa:Nubank:Renzo',
'Pgz*Oreidamot':'Assets:Bens:Moto',
'Pagamento recebido': 'Assets:Caixa:Nubank:Renzo',
# '':'Expenses:SeguroDeVida',
'Prudent*Apol': 'Expenses:SeguroDeVida',
# '':'Equity:PythonPro:Estorno',
'Microsoft': 'Equity:PythonPro:Estorno',
# '': 'Expenses:Casa',
'Arranjos': 'Expenses:Casa',
'Mp *4produtos': 'Expenses:Casa',
'Emporio Verde Garden': 'Expenses:Casa',
'Hvn': 'Expenses:Casa',
'Rw Negocios Comerciai': 'Expenses:Casa',
'Condominio': 'Expenses:Casa',
'Sodimac': 'Expenses:Casa',
'Belcenter': 'Expenses:Casa',
'Havan': 'Expenses:Casa',
'Conta Vivo': 'Expenses:Casa',
'Americanas *Electrolu': 'Expenses:Casa',
'Leroy Merlin': 'Expenses:Casa',
'Construdecor S A': 'Expenses:Casa',
'Bradesco Auto Re': 'Expenses:Casa',
'Lavtop': 'Expenses:Casa',
'Varejao': 'Expenses:Casa',
}
_renzo_memo_patterns = {
'Pagamento de fatura': 'Liabilities:Cartoes:Nubank',
'ARMANDA FATIMA DOS SANTOS': 'Assets:Caixa:Inter:Amanda',
'Armanda Fatima dos Santos': 'Assets:Caixa:Inter:Amanda',
'RENZO DOS SANTOS NUCCITELLI': 'Assets:Caixa:Inter:Renzo',
'DEV PRO': 'Income:Work:DevPro:Distribuicao:Renzo',
'PRISCILA FERNANDES': 'Assets:Caixa:Inter:Priscila',
'CIRURGIA PLASTICA PAULO DOMENICO': 'Expenses:Familia:Priscila',
'Detran': 'Expenses:Transporte:Carro',
'PORTO SEGURO': 'Expenses:Familia:Saude',
}
_amanda_memo_patterns = {
'ARMANDA FATIMA DOS SANTOS': 'Assets:Caixa:Inter:Amanda',
'Armanda Fatima dos Santos': 'Assets:Caixa:Inter:Amanda',
'RENZO DOS SANTOS NUCCITELLI': 'Assets:Caixa:Inter:Renzo',
'PRISCILA FERNANDES': 'Assets:Caixa:Inter:Priscila',
'Priscila Fernandes': 'Assets:Caixa:Inter:Priscila',
'NUTROCLINIC': 'Expenses:Familia:Saude',
'PORTO SEGURO': 'Expenses:Familia:Saude',
u'Aplicação RDB': 'Assets:Investimentos:RendaFixa:Nubank:Amanda',
'Resgate RDB': 'Assets:Investimentos:RendaFixa:Nubank:Amanda',
'Marcio Antonio Filipini Martinez': 'Expenses:Familia:Renzo',
}
class AccountImporter(ImporterProtocol):
def __init__(self, account_id, account_name, memo_patterns):
self.account_id = account_id
self.account_name = account_name
self.memo_patterns = memo_patterns
self.file_re = re.compile(rf'NU_{account_id}_\d{{2}}\w{{3}}\d{{4}}_\d{{2}}\w{{3}}\d{{4}}\.ofx')
def extract(self, file, existing_entries=None):
entries = []
with open(file.name, 'rb') as fileobj:
ofx = OfxParser.parse(fileobj)
statement = ofx.account.statement
for idx, transaction in enumerate(statement.transactions):
meta = data.new_metadata(file.name, idx)
meta['nubank_id'] = transaction.id
counterpart = 'Expenses:Unknown'
for pattern, account in self.memo_patterns.items():
if pattern in transaction.memo:
counterpart = account
break
beancount_transaction = data.Transaction(
meta, transaction.date.date(), self.FLAG, None, transaction.memo,
data.EMPTY_SET,
data.EMPTY_SET, [
data.Posting(self.account_name,
amount.Amount(transaction.amount, 'BRL'),
None, None, None, None),
data.Posting(counterpart,
amount.Amount(-transaction.amount, 'BRL'),
None, None, None, None),
])
entries.append(beancount_transaction)
meta = data.new_metadata(file.name, idx + 1)
balance = data.Balance(
meta,
statement.balance_date.date(),
self.account_name,
amount.Amount(statement.balance, 'BRL'),
None, None
)
entries.append(balance)
return entries
def name(self):
return f'NubankConta:{self.account_name}'
def identify(self, file):
return bool(self.file_re.search(file.name))
def file_account(self, file):
return self.account_name
def file_date(self, file):
return None
class CreditCardImporter(ImporterProtocol):
file_re = re.compile(r'Nubank_(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d)\.ofx')
def extract(self, file, existing_entries=None):
entries = []
with open(file.name) as fileobj:
ofx = OfxParser.parse(fileobj)
statement = ofx.account.statement
for idx, transaction in enumerate(statement.transactions):
meta = data.new_metadata(file.name, idx)
meta['nubank_id'] = transaction.id
expense_account = 'Expenses:Unknown'
for prefix, account in _prefix_account_dct.items():
if transaction.memo.startswith(prefix):
expense_account = account
break
beacount_transaction = data.Transaction(
meta, transaction.date.date(), self.FLAG, None, transaction.memo,
data.EMPTY_SET,
data.EMPTY_SET, [
data.Posting('Liabilities:Cartoes:Nubank', amount.Amount(transaction.amount, 'BRL'),
None, None,
None, None),
data.Posting(expense_account, amount.Amount(-transaction.amount, 'BRL'),
None,
None, None, None),
])
entries.append(beacount_transaction)
meta = data.new_metadata(file.name, idx + 1)
balance = data.Balance(
meta,
statement.balance_date.date(),
'Liabilities:Cartoes:Nubank',
amount.Amount(statement.balance, 'BRL'),
None, None
)
entries.append(balance)
return entries
def name(self):
return 'Nubank'
def identify(self, file):
# Match if the filename is as downloaded
return bool(self.file_re.search(file.name))
def file_name(self, file):
dt = self.file_date(file)
return f'Nubank_{dt.year}_{dt.month:02d}_{dt.day:02d}.ofx'
def file_account(self, file):
return 'Liabilities:Cartoes:Nubank'
def file_date(self, file):
match = self.file_re.search(file.name)
if match:
year = match.group('year')
month = match.group('month')
return date(int(year), int(month), 1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment