25c997add8a173feb60c10d9ab4af8d83021f95a
[cascardo/irpf-gui.git] / src / contribuinte.py
1 #
2 #   Copyright 2013 Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
3 #
4 #   This program is free software: you can redistribute it and/or modify
5 #   it under the terms of the GNU General Public License as published by
6 #   the Free Software Foundation, either version 3 of the License, or
7 #   (at your option) any later version.
8 #
9 #   This program is distributed in the hope that it will be useful,
10 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #   GNU General Public License for more details.
13 #
14 #   You should have received a copy of the GNU General Public License
15 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 # -*- mode: python; encoding: utf-8; -*-
17 import xml.dom.minidom
18 import dirs
19
20 class Contribuinte:
21     def __init__(self, cpf):
22         irpf_dir = dirs.get_default_irpf_dir()
23         self.cpf = self._minimize_cpf(cpf)
24         if not self._validate_cpf(self.cpf):
25             raise RuntimeError("Invalid CPF: " + self.cpf)
26         self.cpf_file = irpf_dir.get_userdata_file("%s/%s.xml" % (self.cpf, self.cpf))
27         self.iddecl_file = irpf_dir.get_userdata_file("iddeclaracoes.xml")
28         self.declaracao = self._find_id()
29         self.dados = xml.dom.minidom.parse(self.cpf_file)
30         self.contribuinte = self.dados.getElementsByTagName("contribuinte")[0]
31
32     def _find_id(self):
33         cpf = self._normalize_cpf(self.cpf)
34         self.declaracoes = xml.dom.minidom.parse(self.iddecl_file)
35         for i in self.declaracoes.childNodes[0].childNodes:
36             if "cpf" in i.attributes.keys():
37                 if i.attributes["cpf"].nodeValue == cpf:
38                     return i
39         return None
40
41     # CPF normalizado se parece com 000.000.000-00
42     def _normalize_cpf(self, cpf):
43         ncpf = ""
44         for i in cpf:
45             if len(ncpf) == 3 or len(ncpf) == 7:
46                 ncpf += '.'
47             if len(ncpf) == 11:
48                 ncpf += '-'
49             if len(ncpf) == 14:
50                 break
51             if ord(i) >= ord('0') and ord(i) <= ord('9'):
52                 ncpf += i
53         if len(ncpf) != 14:
54             raise RuntimeError("Invalid CPF")
55         return ncpf
56
57     # CPF minimizado se parece com 01234567890
58     def _minimize_cpf(self, cpf):
59         ncpf = bytearray(self._normalize_cpf(cpf))
60         del ncpf[11]
61         del ncpf[7]
62         del ncpf[3]
63         return str(ncpf)
64
65     def _validate_cpf(self, cpf):
66         ncpf = self._minimize_cpf(cpf)
67         if len(ncpf) != 11:
68             return False
69         v = (11 - sum(map(lambda x: x[0]*x[1], zip(range(10, 1, -1), map(lambda x: ord(x) - ord('0'), ncpf[0:9]))))) % 11
70         if v >= 10:
71             v = 0
72         if v != ord(ncpf[9]) - ord('0'):
73             return False
74         v = (11 - sum(map(lambda x: x[0]*x[1], zip(range(11, 1, -1), map(lambda x: ord(x) - ord('0'), ncpf[0:10]))))) % 11
75         if v >= 10:
76             v = 0
77         if v != ord(ncpf[10]) - ord('0'):
78             return False
79         return True
80
81     def save(self):
82         self.dados.writexml(open(self.cpf_file, "w"))
83         self.declaracoes.writexml(open(self.iddecl_file, "w"))
84     def _get_attr(self, el, attr):
85         if attr in el.attributes.keys():
86             return el.attributes[attr].nodeValue
87         return None
88
89     def _set_attr(self, el, attr, val):
90         el.attributes[attr].nodeValue = val
91
92     def get_declaracao(self, attr):
93         return self._get_attr(self.declaracao, attr)
94
95     def set_declaracao(self, attr, val):
96         self._set_attr(self.declaracao, attr, val)
97
98     def get_nome(self):
99         return self.get_declaracao("nome")
100
101     def set_nome(self, nome):
102         self.set_declaracao("nome", nome)
103
104     def get_campo_contribuinte(self, attr):
105         if attr == "nome":
106             return self.get_nome()
107         return self._get_attr(self.contribuinte, attr)
108
109     def set_contribuinte(self, attr, val):
110         if attr == "nome":
111             self.set_nome(val)
112         self._set_attr(self.contribuinte, attr, val)
113
114 contribuinte_attributes = [
115         "nome",
116         "dataNascimento",
117         "tituloEleitor",
118         "doencaDeficiencia",
119         "exterior",
120         "pais",
121         "cep",
122         "uf",
123         "cidade",
124         "municipio",
125         "tipoLogradouro",
126         "logradouro",
127         "numero",
128         "complemento",
129         "bairro",
130         "bairroExt",
131         "cepExt",
132         "logradouroExt",
133         "numeroExt",
134         "complementoExt",
135         "ocupacaoPrincipal",
136         "codigoExterior",
137         "ddd",
138         "telefone",
139         "naturezaOcupacao",
140         ]
141
142 declaracao_attributes = [
143         "dataUltimoAcesso",
144         "declaracaoRetificadora",
145         "enderecoDiferente",
146         "enderecoMACRede",
147         "exercicio",
148         "nome",
149         "numReciboDecRetif",
150         "numeroReciboDecAnterior",
151         "resultadoDeclaracao",
152         "tipoDeclaracao",
153         "tipoDeclaracaoAES",
154         "transmitida",
155         "versaoBeta"
156         ]
157
158 if __name__ == '__main__':
159     import sys
160     contribuinte = Contribuinte(sys.argv[1])
161     print "Carregando CPF " + contribuinte._normalize_cpf(sys.argv[1])
162
163     if len(sys.argv) == 4:
164         print "Valor anterior: " + contribuinte.get_campo_contribuinte(sys.argv[2])
165         contribuinte.set_contribuinte(sys.argv[2], sys.argv[3])
166         print "Valor atual: " + contribuinte.get_campo_contribuinte(sys.argv[2])
167         print "Salvando..."
168         contribuinte.save()
169     elif len(sys.argv) == 3:
170         campo = sys.argv[2]
171         valor = contribuinte.get_campo_contribuinte(campo)
172         if valor:
173             print ("Valor de " + campo + ": " + valor)
174         else:
175             print ("Campo " + campo + " retornou vazio")
176     else:
177         print "\nCONTRIBUINTE:"
178         for i in contribuinte_attributes:
179             val = contribuinte.get_campo_contribuinte(i)
180             if val == None:
181                 val = ""
182             print i + ": " + val
183         print "\nDECLARACAO:"
184         for i in declaracao_attributes:
185             val = contribuinte.get_declaracao(i)
186             if val == None:
187                 val = ""
188             print i + ": " + val
189
190 # vim:tabstop=4:expandtab:smartindent