<div dir="ltr"><div>Pessoal,</div><div><br></div><div>Eu sou um usuário assíduo do Nubank há vários anos, desde o "primeiro lote" de clientes.</div><div><br></div><div>E nesse tempo todo eu faço sempre um trabalho manual de estruturar os registros para importar para o GnuCash. Eu faço esse trabalho sacal pelos seguintes motivos:</div><div><br></div><div>1) A cada fatura a data que aparece em uma compra, nem sempre é a dada do dia que ela realmente aconteceu. Numa compra a vista, aparece ou a data do mesmo dia ou do dia seguinte. <br></div><div>2) Quando a compra é parcelada, ele mostra a data em que foi processado naquele mês. Ou seja olhando para a fatura, você não faz ideia qual foi a data da compra.</div><div>3) Eu sempre formato o descritivo da compra para mostrar a Data + Descritivo + Parcela. Exemplo: 2020-02-08 - Estabelecimento XPTO (1/3)</div><div><br></div><div>Então resolvi criar um script em python para fazer esse trabalho por mim e gerar um CSV.</div><div><br></div><div>OBS: Tem muito tempo que não programo (pelo menos a lógica ainda está fresca). Meu conhecimento em Python tende a ZERO.</div><div><br></div><div>Compartilho com vocês o script abaixo. Para os entendidos de python, favor não me esculhambar (ver OBS acima). <br></div><div>Fiquem à vontade para incrementar e fazer os devidos tratamentos de erro (nem me preocupei com isso). Foco no MVP!</div><div>Próximos passos, se eu tiver vontade (e saco), gerar OFX.<br></div><div><br></div><div>

<div style="color:rgb(212,212,212);background-color:rgb(30,30,30);font-family:Consolas,"Courier New",monospace;font-weight:normal;font-size:14px;line-height:19px;white-space:pre"><div><span style="color:rgb(106,153,85)"># Monta arquivo CSV com extrato de fatura em formato CSV</span></div><div><span style="color:rgb(106,153,85)">#</span></div><div><span style="color:rgb(106,153,85)"># Cada linha do CSV possui</span></div><div><span style="color:rgb(106,153,85)">#   DATA = data da fatura, no formato YYYY-MM-DD</span></div><div><span style="color:rgb(106,153,85)">#   DESCRICAO = <DATA DA COMPRA> - <DESCRICAO> <(X/Y)>, onde:</span></div><div><span style="color:rgb(106,153,85)">#       <DATA DA COMPRA> = data original em que foi feita a compra</span></div><div><span style="color:rgb(106,153,85)">#       <DESCRICAO> = descritivo que vem na fatura (transacao)</span></div><div><span style="color:rgb(106,153,85)">#       <(X/Y)> = se a compra for parcelada, X é a parcela corrente e Y é o total de parcelas</span></div><div><span style="color:rgb(106,153,85)">#       Exemplo: 2020-02-08 - Estabelecimento XPTO (1/3)</span></div><div><span style="color:rgb(106,153,85)">#   VALOR = valor do item na fatura</span></div><div><span style="color:rgb(106,153,85)">#</span></div><div><span style="color:rgb(106,153,85)"># Exemplo de linha no CSV:</span></div><div><span style="color:rgb(106,153,85)">#       2020-03-05;2020-02-08 - Estabelecimento XPTO (1/3);50,00</span></div><div><span style="color:rgb(106,153,85)">#   </span></div><div><span style="color:rgb(106,153,85)"># Forma de uso</span></div><div><span style="color:rgb(106,153,85)">#   python extrato.py <CPF> <SENHA> <DATA NO FORMATO YYYY-MM-DD></span></div><div><span style="color:rgb(106,153,85)">#</span></div><div><span style="color:rgb(106,153,85)"># Dependência do pynubank (versao 1.0.1 que dá suporte ao QRCode)</span></div><div><span style="color:rgb(106,153,85)">#   <a href="https://github.com/andreroggeri/pynubank/tree/1.0.1">https://github.com/andreroggeri/pynubank/tree/1.0.1</a></span></div><br><div><span style="color:rgb(197,134,192)">from</span><span style="color:rgb(212,212,212)"> pynubank.nubank </span><span style="color:rgb(197,134,192)">import</span><span style="color:rgb(212,212,212)"> Nubank</span></div><br><div><span style="color:rgb(197,134,192)">import</span><span style="color:rgb(212,212,212)"> sys</span></div><div><span style="color:rgb(197,134,192)">import</span><span style="color:rgb(212,212,212)"> locale</span></div><div><span style="color:rgb(212,212,212)">locale.setlocale(locale.LC_ALL, </span><span style="color:rgb(206,145,120)">'pt_BR.UTF-8'</span><span style="color:rgb(212,212,212)">)</span></div><br><div><span style="color:rgb(212,212,212)">cpf </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> sys.argv[</span><span style="color:rgb(181,206,168)">1</span><span style="color:rgb(212,212,212)">]</span></div><div><span style="color:rgb(212,212,212)">pwd </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> sys.argv[</span><span style="color:rgb(181,206,168)">2</span><span style="color:rgb(212,212,212)">]</span></div><div><span style="color:rgb(212,212,212)">bill_date </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> sys.argv[</span><span style="color:rgb(181,206,168)">3</span><span style="color:rgb(212,212,212)">]</span></div><div><span style="color:rgb(212,212,212)">output_file_path </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(206,145,120)">'COLOCAR O CAMINHO DO ARQUIVO CSV AQUI</span><span style="color:rgb(206,145,120)">'</span></div><br><div><span style="color:rgb(106,153,85)">#busca fatura com base em uma data</span></div><div><span style="color:rgb(86,156,214)">def</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(220,220,170)">get_bill_by_date</span><span style="color:rgb(212,212,212)">(</span><span style="color:rgb(156,220,254)">bills</span><span style="color:rgb(212,212,212)">, </span><span style="color:rgb(156,220,254)">date</span><span style="color:rgb(212,212,212)">):</span></div><div><span style="color:rgb(212,212,212)">    </span><span style="color:rgb(197,134,192)">for</span><span style="color:rgb(212,212,212)"> b </span><span style="color:rgb(86,156,214)">in</span><span style="color:rgb(212,212,212)"> bills:</span></div><div><span style="color:rgb(212,212,212)">        </span><span style="color:rgb(197,134,192)">if</span><span style="color:rgb(212,212,212)"> b[</span><span style="color:rgb(206,145,120)">'summary'</span><span style="color:rgb(212,212,212)">][</span><span style="color:rgb(206,145,120)">'due_date'</span><span style="color:rgb(212,212,212)">] </span><span style="color:rgb(212,212,212)">==</span><span style="color:rgb(212,212,212)"> date:</span></div><div><span style="color:rgb(212,212,212)">            </span><span style="color:rgb(197,134,192)">return</span><span style="color:rgb(212,212,212)"> b</span></div><div><span style="color:rgb(212,212,212)">    </span><span style="color:rgb(197,134,192)">return</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">None</span></div><br><div><span style="color:rgb(106,153,85)">#busca transacao com base no id (href)</span></div><div><span style="color:rgb(86,156,214)">def</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(220,220,170)">get_transaction_by_id</span><span style="color:rgb(212,212,212)">(</span><span style="color:rgb(156,220,254)">transactions</span><span style="color:rgb(212,212,212)">, </span><span style="color:rgb(156,220,254)">id</span><span style="color:rgb(212,212,212)">):</span></div><div><span style="color:rgb(212,212,212)">    </span><span style="color:rgb(197,134,192)">for</span><span style="color:rgb(212,212,212)"> t </span><span style="color:rgb(86,156,214)">in</span><span style="color:rgb(212,212,212)"> transactions:</span></div><div><span style="color:rgb(212,212,212)">        </span><span style="color:rgb(197,134,192)">if</span><span style="color:rgb(212,212,212)"> t[</span><span style="color:rgb(206,145,120)">'href'</span><span style="color:rgb(212,212,212)">] </span><span style="color:rgb(212,212,212)">==</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(220,220,170)">id</span><span style="color:rgb(212,212,212)">:</span></div><div><span style="color:rgb(212,212,212)">            </span><span style="color:rgb(197,134,192)">return</span><span style="color:rgb(212,212,212)"> t</span></div><div><span style="color:rgb(212,212,212)">    </span><span style="color:rgb(197,134,192)">return</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">None</span></div><br><div><span style="color:rgb(106,153,85)">#formata a descricao da transacao</span></div><div><span style="color:rgb(86,156,214)">def</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(220,220,170)">get_formated_description</span><span style="color:rgb(212,212,212)">(</span><span style="color:rgb(156,220,254)">bill_item</span><span style="color:rgb(212,212,212)">, </span><span style="color:rgb(156,220,254)">transaction</span><span style="color:rgb(212,212,212)">):</span></div><div><span style="color:rgb(212,212,212)">    description </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(206,145,120)">'</span><span style="color:rgb(86,156,214)">{}</span><span style="color:rgb(206,145,120)"> - </span><span style="color:rgb(86,156,214)">{}</span><span style="color:rgb(206,145,120)">'</span><span style="color:rgb(212,212,212)">.format(transaction[</span><span style="color:rgb(206,145,120)">'time'</span><span style="color:rgb(212,212,212)">][:</span><span style="color:rgb(181,206,168)">10</span><span style="color:rgb(212,212,212)">], bill_item[</span><span style="color:rgb(206,145,120)">'title'</span><span style="color:rgb(212,212,212)">])</span></div><div><span style="color:rgb(212,212,212)">    </span><span style="color:rgb(197,134,192)">if</span><span style="color:rgb(212,212,212)"> bi[</span><span style="color:rgb(206,145,120)">'charges'</span><span style="color:rgb(212,212,212)">] </span><span style="color:rgb(212,212,212)">></span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(181,206,168)">1</span><span style="color:rgb(212,212,212)">:</span></div><div><span style="color:rgb(212,212,212)">        description </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> description </span><span style="color:rgb(212,212,212)">+</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(206,145,120)">' (</span><span style="color:rgb(86,156,214)">{}</span><span style="color:rgb(206,145,120)">/</span><span style="color:rgb(86,156,214)">{}</span><span style="color:rgb(206,145,120)">)'</span><span style="color:rgb(212,212,212)">.format(bi[</span><span style="color:rgb(206,145,120)">'index'</span><span style="color:rgb(212,212,212)">] </span><span style="color:rgb(212,212,212)">+</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(181,206,168)">1</span><span style="color:rgb(212,212,212)">,  bi[</span><span style="color:rgb(206,145,120)">'charges'</span><span style="color:rgb(212,212,212)">])</span></div><div><span style="color:rgb(212,212,212)">    </span><span style="color:rgb(197,134,192)">return</span><span style="color:rgb(212,212,212)"> description</span></div><br><div><span style="color:rgb(212,212,212)">nu </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> Nubank()</span></div><div><span style="color:rgb(212,212,212)">uuid, qr_code </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> nu.get_qr_code()</span></div><div><span style="color:rgb(212,212,212)">qr_code.print_ascii(</span><span style="color:rgb(156,220,254)">invert</span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(86,156,214)">True</span><span style="color:rgb(212,212,212)">)</span></div><div><span style="color:rgb(220,220,170)">input</span><span style="color:rgb(212,212,212)">(</span><span style="color:rgb(206,145,120)">'Após escanear o QRCode pressione enter para continuar'</span><span style="color:rgb(212,212,212)">)</span></div><br><div><span style="color:rgb(106,153,85)"># Somente após escanear o QRCode você pode chamar a linha abaixo</span></div><div><span style="color:rgb(212,212,212)">nu.authenticate_with_qr_code(cpf, pwd, uuid)</span></div><br><div><span style="color:rgb(106,153,85)">#recupera as transacoes</span></div><div><span style="color:rgb(212,212,212)">nubank_transactions </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> nu.get_card_statements()</span></div><br><div><span style="color:rgb(106,153,85)">#recupera as faturas</span></div><div><span style="color:rgb(212,212,212)">nubank_bills </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> nu.get_bills()</span></div><br><div><span style="color:rgb(106,153,85)">#busca fatura com base em uma data</span></div><div><span style="color:rgb(212,212,212)">nubank_bill </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> get_bill_by_date(nubank_bills, bill_date)</span></div><br><div><span style="color:rgb(106,153,85)">#recupera os detalhes da fatura</span></div><div><span style="color:rgb(212,212,212)">nubank_bill_details </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> nu.get_bill_details(nubank_bill)</span></div><br><div><span style="color:rgb(212,212,212)">csv_output </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(220,220,170)">open</span><span style="color:rgb(212,212,212)">(output_file_path,</span><span style="color:rgb(206,145,120)">'w'</span><span style="color:rgb(212,212,212)">)</span></div><div><span style="color:rgb(212,212,212)">csv_output.write(</span><span style="color:rgb(206,145,120)">'DATA;DESCRICAO;VALOR'</span><span style="color:rgb(212,212,212)">)</span></div><br><div><span style="color:rgb(197,134,192)">for</span><span style="color:rgb(212,212,212)"> bi </span><span style="color:rgb(86,156,214)">in</span><span style="color:rgb(212,212,212)"> nubank_bill_details[</span><span style="color:rgb(206,145,120)">'bill'</span><span style="color:rgb(212,212,212)">][</span><span style="color:rgb(206,145,120)">'line_items'</span><span style="color:rgb(212,212,212)">]:</span></div><div><span style="color:rgb(212,212,212)">    </span><span style="color:rgb(197,134,192)">if</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(206,145,120)">'href'</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">in</span><span style="color:rgb(212,212,212)"> bi:</span></div><div><span style="color:rgb(212,212,212)">        t </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> get_transaction_by_id(nubank_transactions, bi[</span><span style="color:rgb(206,145,120)">'href'</span><span style="color:rgb(212,212,212)">])</span></div><div><span style="color:rgb(212,212,212)">        row </span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(206,145,120)">'</span><span style="color:rgb(215,186,125)">\n</span><span style="color:rgb(206,145,120)">'</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(212,212,212)">+</span><span style="color:rgb(212,212,212)"> bill_date </span><span style="color:rgb(212,212,212)">+</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(206,145,120)">';'</span></div><div><span style="color:rgb(212,212,212)">        row </span><span style="color:rgb(212,212,212)">+=</span><span style="color:rgb(212,212,212)"> get_formated_description(bi, t) </span><span style="color:rgb(212,212,212)">+</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(206,145,120)">';'</span></div><div><span style="color:rgb(212,212,212)">        row </span><span style="color:rgb(212,212,212)">+=</span><span style="color:rgb(212,212,212)"> locale.currency(bi[</span><span style="color:rgb(206,145,120)">'amount'</span><span style="color:rgb(212,212,212)">] </span><span style="color:rgb(212,212,212)">/</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(181,206,168)">100</span><span style="color:rgb(212,212,212)">, </span><span style="color:rgb(156,220,254)">grouping</span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(86,156,214)">True</span><span style="color:rgb(212,212,212)">, </span><span style="color:rgb(156,220,254)">symbol</span><span style="color:rgb(212,212,212)">=</span><span style="color:rgb(86,156,214)">None</span><span style="color:rgb(212,212,212)">)        </span></div><div><span style="color:rgb(212,212,212)">        csv_output.write(row)</span></div><br><div><span style="color:rgb(212,212,212)">csv_output.close()</span></div></div>

</div><div><br></div><div><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>Atenciosamente,<div><br>
<b>Danilo Freitas da Costa</b>
<br></div></div></div></div></div></div></div></div></div>