3 # Copyright 2013-2014 Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17 # -*- mode: python; encoding: utf-8; -*-
18 import xml.dom.minidom
24 class OcupacaoForm(form.OptionsForm):
25 def __init__(self, ocupacoes, contribuinte):
26 g = ocupacoes.groups()
30 o = map(lambda x: (x[0], x[3]), l)
31 form.OptionsForm.__init__(self, u"Ocupações", o, contribuinte.get_campo_contribuinte("ocupacaoPrincipal"))
32 self.ocupacoes = ocupacoes
33 self.contribuinte = contribuinte
34 def set_value(self, value):
35 form.OptionsForm.set_value(self, value)
36 self.contribuinte.set_campo_contribuinte("ocupacaoPrincipal", value)
38 class ContribuinteForm(form.StringForm):
39 def __init__(self, name, attr, contribuinte):
40 self.contribuinte = contribuinte
42 form.StringForm.__init__(self, name, self.contribuinte.get_campo_contribuinte(self.attr))
43 def set_value(self, value):
44 form.StringForm.set_value(self, value)
45 self.contribuinte.set_campo_contribuinte(self.attr, value)
48 def __init__(self, cpf):
49 irpf_dir = dirs.get_default_irpf_dir()
50 self.cpf = self._minimize_cpf(cpf)
52 if not self._validate_cpf(self.cpf):
53 raise RuntimeError("Invalid CPF: " + self.cpf)
55 if not os.path.exists(irpf_dir.get_resource_dir()):
56 raise RuntimeError("O caminho para o resource não existe: " + \
57 irpf_dir.get_resource_dir())
59 if not os.path.exists(irpf_dir.get_userdata_dir()):
60 raise RuntimeError("O caminho para os dados não existe: " + \
61 irpf_dir.get_userdata_dir())
63 self.cpf_file = irpf_dir.get_userdata_file("%s/%s.xml" % (self.cpf, self.cpf))
64 self.iddecl_file = irpf_dir.get_userdata_file("iddeclaracoes.xml")
65 self.declaracao = self._find_id()
66 self.dados = xml.dom.minidom.parse(self.cpf_file)
67 self.contribuinte = self.dados.getElementsByTagName("contribuinte")[0]
70 cpf = self._normalize_cpf(self.cpf)
71 self.declaracoes = xml.dom.minidom.parse(self.iddecl_file)
72 for i in self.declaracoes.getElementsByTagName("item"):
73 if "cpf" in i.attributes.keys():
74 if i.attributes["cpf"].nodeValue == cpf:
78 # CPF normalizado se parece com 000.000.000-00
79 def _normalize_cpf(self, cpf):
82 if len(ncpf) == 3 or len(ncpf) == 7:
88 if ord(i) >= ord('0') and ord(i) <= ord('9'):
91 raise RuntimeError("Invalid CPF")
94 # CPF minimizado se parece com 01234567890
95 def _minimize_cpf(self, cpf):
96 return self._minimize_valor(cpf)
98 def _minimize_valor(self, valor):
99 nvalor = ''.join(e for e in valor if e.isalnum())
102 def _validate_cpf(self, cpf):
105 return self._validate_generico(cpf)
107 def _validate_generico(self, valor):
108 def calcula_digito_verificador(numero):
113 if i > len(numero) - 1:
115 soma = soma + int(numero[i]) * ( n - i)
124 return numero + str(dv)
126 mcpf = self._minimize_valor(valor)
127 cpf_sem_dv = mcpf[:-2]
129 primeiro_dv = str(calcula_digito_verificador(cpf_sem_dv))
130 segundo_dv = calcula_digito_verificador(primeiro_dv)
132 return segundo_dv == mcpf
135 self.dados.writexml(open(self.cpf_file, "w"))
136 self.declaracoes.writexml(open(self.iddecl_file, "w"))
138 def _get_attr(self, el, attr):
139 if attr in el.attributes.keys():
140 return el.attributes[attr].nodeValue
143 def _set_attr(self, el, attr, val):
144 el.attributes[attr].nodeValue = val
146 def get_declaracao(self, attr):
147 return self._get_attr(self.declaracao, attr)
149 def set_declaracao(self, attr, val):
150 self._set_attr(self.declaracao, attr, val)
153 return self.get_declaracao("nome")
155 def set_nome(self, nome):
156 self.set_declaracao("nome", nome)
158 def get_campo_contribuinte(self, attr):
160 return self.get_nome()
161 return self._get_attr(self.contribuinte, attr)
163 def set_campo_contribuinte(self, attr, val):
167 self._set_attr(self.contribuinte, attr, val)
171 ocup = ocupacoes.Ocupacoes()
172 form.append(ContribuinteForm("Nome", "nome", self))
173 form.append(OcupacaoForm(ocup, self))
174 for i in contribuinte_attributes:
175 form.append(ContribuinteForm(i, i, self))
178 contribuinte_attributes = [
206 declaracao_attributes = [
208 "declaracaoRetificadora",
214 "numeroReciboDecAnterior",
215 "resultadoDeclaracao",
222 if __name__ == '__main__':
224 contribuinte = Contribuinte(sys.argv[1])
225 print "Carregando CPF " + contribuinte._normalize_cpf(sys.argv[1])
227 if len(sys.argv) == 4:
228 print "Valor anterior: " + contribuinte.get_campo_contribuinte(sys.argv[2])
229 contribuinte.set_campo_contribuinte(sys.argv[2], sys.argv[3])
230 print "Valor atual: " + contribuinte.get_campo_contribuinte(sys.argv[2])
233 elif len(sys.argv) == 3:
235 valor = contribuinte.get_campo_contribuinte(campo)
237 print ("Valor de " + campo + ": " + valor)
239 print ("Campo " + campo + " retornou vazio")
241 print "\nCONTRIBUINTE:"
242 for i in contribuinte_attributes:
243 val = contribuinte.get_campo_contribuinte(i)
247 print "\nDECLARACAO:"
248 for i in declaracao_attributes:
249 val = contribuinte.get_declaracao(i)
254 # vim:tabstop=4:expandtab:smartindent