From 3bcebb7bd540489e0c85247919924c3207974602 Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Thu, 12 Nov 2020 16:39:56 -0300 Subject: [PATCH] [NEW] Segmento E --- febraban/cnab240/statement/__init__.py | 1 + febraban/cnab240/statement/occurrences.py | 55 +++++++ febraban/cnab240/statement/parser.py | 137 ++++++++++++++++++ febraban/cnab240/tests/statement/__init__.py | 0 .../cnab240/tests/statement/parserTest.py | 41 ++++++ sample-statement-parser.py | 38 +++++ 6 files changed, 272 insertions(+) create mode 100644 febraban/cnab240/statement/__init__.py create mode 100644 febraban/cnab240/statement/occurrences.py create mode 100644 febraban/cnab240/statement/parser.py create mode 100644 febraban/cnab240/tests/statement/__init__.py create mode 100644 febraban/cnab240/tests/statement/parserTest.py create mode 100644 sample-statement-parser.py diff --git a/febraban/cnab240/statement/__init__.py b/febraban/cnab240/statement/__init__.py new file mode 100644 index 0000000..07c3095 --- /dev/null +++ b/febraban/cnab240/statement/__init__.py @@ -0,0 +1 @@ +from .parser import StatementParser diff --git a/febraban/cnab240/statement/occurrences.py b/febraban/cnab240/statement/occurrences.py new file mode 100644 index 0000000..b25b969 --- /dev/null +++ b/febraban/cnab240/statement/occurrences.py @@ -0,0 +1,55 @@ +# coding: utf-8 + +debit_occurrences = { + '101': 'Cheque Compensado', + '102': 'Encargos', + '103': 'Estornos', + '104': 'Lançamento Avisado', + '105': 'Tarifas', + '106': 'Aplicação', + '107': 'Empréstimo / Financiamento', + '108': 'Câmbio', + '109': 'CPMF', + '110': 'IOF', + '111': 'Imposto de Renda', + '112': 'Pagamento Fornecedores', + '113': 'Pagamentos Salário', + '114': 'Saque Eletrônico', + '115': 'Ações', + '117': 'Transferência entre Contas', + '118': 'Devolução da Compensação', + '119': 'Devolução de Cheque Depositado', + '120': 'Transferência Interbancária (DOC, TED)', + '121': 'Antecipação a Fornecedores', + '122': 'OC / AEROPS', + '123': 'Saque em Espécie', + '124': 'Cheque Pago', + '125': 'Pagamentos Diversos', + '126': 'Pagamento de Tributos', + '127': 'Cartão de crédito - Pagamento de fatura de cartão de crédito da própria IF', +} + +credit_occurrences = { + '201': 'Depósito em Cheque', + '202': 'Crédito de Cobrança', + '203': 'Devolução de Cheques', + '204': 'Estornos', + '205': 'Lançamento Avisado', + '206': 'Resgate de Aplicação', + '207': 'Empréstimo / Financiamento', + '208': 'Câmbio', + '209': 'Transferência Interbancária (DOC, TED)', + '210': 'Ações', + '211': 'Dividendos', + '212': 'Seguro', + '213': 'Transferência entre Contas', + '214': 'Depósitos Especiais', + '215': 'Devolução da Compensação', + '216': 'OCT', + '217': 'Pagamentos Fornecedores', + '218': 'Pagamentos Diversos', + '219': 'Recebimento de Salário', + '220': 'Depósito em Espécie', + '221': 'Pagamento de Tributos', + '222': 'Cartão de Crédito - Recebíveis de cartão de crédito', +} diff --git a/febraban/cnab240/statement/parser.py b/febraban/cnab240/statement/parser.py new file mode 100644 index 0000000..4cdaf68 --- /dev/null +++ b/febraban/cnab240/statement/parser.py @@ -0,0 +1,137 @@ +from .occurrences import debit_occurrences, credit_occurrences + + +class Statement: + + def __init__( + self, content=None, bank_code=None, branch_number=None, branch_code=None, + account_number=None, account_code=None, start_date=None, + start_amount_in_cents=None, start_debit_credit=None, stop_date=None, + stop_amount_in_cents=None, stop_debit_credit=None, line_quantity=None, + debit_sum_in_cents=None, credit_sum_in_cents=None, currency=None): + self.content = content or [] + self.bank_code = bank_code + self.branch_number = branch_number + self.branch_code = branch_code + self.account_number = account_number + self.account_code = account_code + self.start_date = start_date + self.start_amount_in_cents = start_amount_in_cents + self.start_debit_credit = start_debit_credit + self.stop_date = stop_date + self.stop_amount_in_cents = stop_amount_in_cents + self.stop_debit_credit = stop_debit_credit + self.line_quantity = line_quantity + self.debit_sum_in_cents = debit_sum_in_cents + self.credit_sum_in_cents = credit_sum_in_cents + self.currency = currency + self.amount = 0 + self.lines = [] + + +class StatementLine: + + def __init__(self, content=None, occurrence=None, cpmf=None, date_account=None, + date_move=None, amountInCents=None, debit_credit=None, + bank_history_code=None, bank_history_description=None, + document_number=None, amount=None): + self.content = content or [] + self.cpmf = cpmf + self.date_account = date_account + self.date_move = date_move + self.amountInCents = amountInCents + self.debit_credit = debit_credit + self.occurrence = occurrence + self.bank_history_code = bank_history_code + self.bank_history_description = bank_history_description + self.document_number = document_number + self.amount = amount + + def occurrenceText(self): + if self.occurrence and self.debit_credit == 'C': + return credit_occurrences[self.occurrence] + elif self.occurrence and self.debit_credit == 'D': + return debit_occurrences[self.occurrence] + + def contentText(self, breakLine="\n"): + return breakLine.join(self.content) + + +class StatementParser: + + def __init__(self, lines): + self._lines = lines + self.statement = None + + @classmethod + def parseFile(cls, file): + lines = file.readlines() + statement = StatementParser(lines) + return statement.parseLines() + + @classmethod + def parseText(cls, text): + lines = text.splitlines()[:-1] + statement = StatementParser(lines) + return statement.parseLines() + + def _prepare_statement_header(self, line): + self.statement = Statement( + content=[line], + bank_code=line[0:3], + branch_number=line[52:57], + branch_code=line[57:58], + account_number=line[58:70], + account_code=line[57:58], + start_date=line[142:150], + start_amount_in_cents=int(line[150:168]), + start_debit_credit=line[168:169], + currency=line[170:173] + ) + + def _prepare_statement_footer(self, line): + self.statement.content.append(line) + self.statement.stop_date = line[142:150] + self.statement.stop_amount_in_cents = int(line[150:168]) + self.statement.stop_debit_credit = line[168:169] + self.statement.line_quantity = int(line[170:176]) + self.statement.debit_sum_in_cents = int(line[176:194]) + self.statement.credit_sum_in_cents = int(line[194:212]) + + def _prepare_statement_line(self, line): + statement_line = StatementLine() + statement_line.content.append(line) + statement_line.occurrence = line[15:17] + statement_line.cpmf = line[133:134] + statement_line.date_account = line[134:142] + statement_line.date_move = line[142:150] + statement_line.amountInCents = int(line[150:168]) + statement_line.debit_credit = line[168:169] + statement_line.occurrence = line[169:172] + statement_line.bank_history_code = line[172:176] + statement_line.bank_history_description = line[176:201] + statement_line.document_number = line[201:240] + + if statement_line.debit_credit == 'C': + statement_line.amount = statement_line.amountInCents / 100 + elif statement_line.debit_credit == 'D': + statement_line.amount = - statement_line.amountInCents / 100 + self.statement.amount += statement_line.amount + self.statement.lines.append(statement_line) + + def parseLines(self): + for line in self._lines: + + if line[7] in ["0", "9"]: + continue + if line[7] == "1" and line[8] == "E": + if not self.statement: + self._prepare_statement_header(line) + + if line[7] == "5": + self._prepare_statement_footer(line) + + if line[7] == "3" and line[13] == "E": + self._prepare_statement_line(line) + + return self.statement diff --git a/febraban/cnab240/tests/statement/__init__.py b/febraban/cnab240/tests/statement/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/febraban/cnab240/tests/statement/parserTest.py b/febraban/cnab240/tests/statement/parserTest.py new file mode 100644 index 0000000..ee416b4 --- /dev/null +++ b/febraban/cnab240/tests/statement/parserTest.py @@ -0,0 +1,41 @@ +from unittest.case import TestCase +from febraban.cnab240.statement import StatementParser + +returnFile = \ +""" +07700000 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA BANCO INTER S.A. 21211202016361800001610100000 000 +07700011E0440033 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 17082020000000000000732846CFBRL00016 +0770001300001E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S1908202019082020000000000000082240D1127059PAGAMENTO DE TITULO 026135 +0770001300002E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2008202020082020000000000000264357D1127045PAGAMENTO DE CONVENIO 000000 +0770001300003E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2008202020082020000000000000433675D1127045PAGAMENTO DE CONVENIO 000000 +0770001300004E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2008202020082020000000000000084054D1127045PAGAMENTO DE CONVENIO 000000 +0770001300005E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2008202020082020000000000000200000C2067211RESGATE 672827 +0770001300006E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2108202021082020000000000000144000C2017193DEPOSITO BOLETO 24 HORAS 000000 +0770001300007E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2108202021082020000000000000600000C2017193DEPOSITO BOLETO 24 HORAS 000000 +0770001300008E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2108202021082020000000000000100000C2017193DEPOSITO BOLETO 24 HORAS 000000 +0770001300009E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2108202021082020000000000000131800C2017193DEPOSITO BOLETO 24 HORAS 000000 +0770001300010E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2108202021082020000000000000098000C2017193DEPOSITO BOLETO 24 HORAS 000000 +0770001300011E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2108202021082020000000000000080000C2017193DEPOSITO BOLETO 24 HORAS 000000 +0770001300012E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2408202024082020000000000000300000D1207065TED ENVIADA 025012 +0770001300013E 223130935000198 0000190000014054310 KMEE INFORMATICA LTDA 00 S2508202025082020000000000000076900C2097067TED RECEBIDA 671091 +07700015 223130935000198 0000190000014054310 00000000000000000000000000000000000000000000000000000025082020000000000000999220CF000015000000000001164326000000000001430700 +07799999 000001000017000001 +""".strip() + + +class ParserTest(TestCase): + + def testReturnStatementFile(self): + statement = StatementParser.parseText(returnFile) + + debit = 0 + credit = 0 + + for line in statement.lines: + if line.debit_credit == 'D': + debit += line.amountInCents + elif line.debit_credit == 'C': + credit += line.amountInCents + + self.assertEqual(statement.debit_sum_in_cents, debit) + self.assertEqual(statement.credit_sum_in_cents, credit) diff --git a/sample-statement-parser.py b/sample-statement-parser.py new file mode 100644 index 0000000..5af5d62 --- /dev/null +++ b/sample-statement-parser.py @@ -0,0 +1,38 @@ +from febraban.cnab240.statement import StatementParser + +file = open("output.RET", "r") + +statement = StatementParser.parseFile(file) + +debit = 0 +credit = 0 + +print(statement.bank_code) +print(statement.branch_number, '-', statement.branch_code) +print(statement.account_number, '-', statement.account_code) + +for line in statement.lines: + print(line.occurrence) + print(line.cpmf) + print(line.date_account) + print(line.date_move) + print(line.amountInCents) + print(line.debit_credit) + print(line.amountInCents) + print(line.occurrence) + print(line.bank_history_code) + print(line.bank_history_description) + print(line.bank_history_description) + print(line.occurrenceText()) + print(line.contentText()) + + if line.debit_credit == 'D': + debit += line.amountInCents + elif line.debit_credit == 'C': + credit += line.amountInCents + +if not statement.debit_sum_in_cents == debit: + raise Exception + +if not statement.credit_sum_in_cents == credit: + raise Exception