Correção para salvar declarações.
[cascardo/irpf-gui.git] / src / contribuinte.py
1 # coding=utf-8
2 #
3 #   Copyright 2013-2014 Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
4 #
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.
9 #
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.
14 #
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
19 import dirs
20 import os
21 import form
22 import ocupacoes
23 import declaracoes
24
25 class OcupacaoForm(form.OptionsForm):
26     def __init__(self, ocupacoes, contribuinte):
27         g = ocupacoes.groups()
28         l = []
29         for i in sorted(g):
30             l.extend(g[i])
31         o = map(lambda x: (x[0], x[3]), l)
32         form.OptionsForm.__init__(self, u"Ocupações", o, contribuinte.get_campo_contribuinte("ocupacaoPrincipal"))
33         self.ocupacoes = ocupacoes
34         self.contribuinte = contribuinte
35     def set_value(self, value):
36         form.OptionsForm.set_value(self, value)
37         self.contribuinte.set_campo_contribuinte("ocupacaoPrincipal", value)
38
39 class ContribuinteForm(form.StringForm):
40     def __init__(self, name, attr, contribuinte):
41         self.contribuinte = contribuinte
42         self.attr = attr
43         form.StringForm.__init__(self, name, self.contribuinte.get_campo_contribuinte(self.attr))
44     def set_value(self, value):
45         form.StringForm.set_value(self, value)
46         self.contribuinte.set_campo_contribuinte(self.attr, value)
47
48 class Contribuinte:
49     def __init__(self, cpf):
50         irpf_dir = dirs.get_default_irpf_dir()
51         self.cpf = self._minimize_cpf(cpf)
52
53         if not self._validate_cpf(self.cpf):
54             raise RuntimeError("Invalid CPF: " + self.cpf)
55
56         if not os.path.exists(irpf_dir.get_resource_dir()):
57             raise RuntimeError("O caminho para o resource não existe: " + \
58                     irpf_dir.get_resource_dir())
59
60         if not os.path.exists(irpf_dir.get_userdata_dir()):
61             raise RuntimeError("O caminho para os dados não existe: " + \
62                     irpf_dir.get_userdata_dir())
63
64         self.cpf_file = irpf_dir.get_userdata_file("%s/%s.xml" % (self.cpf, self.cpf))
65         ncpf = self._normalize_cpf(self.cpf)
66         self.declaracoes = declaracoes.Declaracoes()
67         self.declaracao = self.declaracoes.find("cpf", ncpf)
68         self.dados = xml.dom.minidom.parse(self.cpf_file)
69         self.contribuinte = self.dados.getElementsByTagName("contribuinte")[0]
70
71     # CPF normalizado se parece com 000.000.000-00
72     def _normalize_cpf(self, cpf):
73         ncpf = ""
74         for i in cpf:
75             if len(ncpf) == 3 or len(ncpf) == 7:
76                 ncpf += '.'
77             if len(ncpf) == 11:
78                 ncpf += '-'
79             if len(ncpf) == 14:
80                 break
81             if ord(i) >= ord('0') and ord(i) <= ord('9'):
82                 ncpf += i
83         if len(ncpf) != 14:
84             raise RuntimeError("Invalid CPF")
85         return ncpf
86
87     # CPF minimizado se parece com 01234567890
88     def _minimize_cpf(self, cpf):
89         return self._minimize_valor(cpf)
90
91     def _minimize_valor(self, valor):
92         nvalor = ''.join(e for e in valor if e.isalnum())
93         return str(nvalor)
94
95     def _validate_cpf(self, cpf):
96         if len(cpf) != 11:
97             return False
98         return self._validate_generico(cpf)
99
100     def _validate_generico(self, valor):
101         def calcula_digito_verificador(numero):
102             n = len(numero) + 1
103
104             soma = 0
105             for i in range(n):
106                 if i > len(numero) - 1:
107                     break
108                 soma = soma + int(numero[i]) * ( n - i)
109
110             dv =  soma % 11
111
112             if dv < 2:
113                 dv = 0
114             else:
115                 dv = 11 - dv
116
117             return numero + str(dv)
118
119         mcpf = self._minimize_valor(valor)
120         cpf_sem_dv = mcpf[:-2]
121
122         primeiro_dv = str(calcula_digito_verificador(cpf_sem_dv))
123         segundo_dv = calcula_digito_verificador(primeiro_dv)
124
125         return segundo_dv == mcpf
126
127     def save(self):
128         self.dados.writexml(open(self.cpf_file, "w"))
129         self.declaracoes.save()
130
131     def _get_attr(self, el, attr):
132         if attr in el.attributes.keys():
133             return el.attributes[attr].nodeValue
134         return None
135
136     def _set_attr(self, el, attr, val):
137         el.attributes[attr].nodeValue = val
138
139     def get_declaracao(self, attr):
140         return self.declaracao.get_attr(attr)
141
142     def set_declaracao(self, attr, val):
143         self.declaracao.set_attr(attr, val)
144
145     def get_nome(self):
146         return self.get_declaracao("nome")
147
148     def set_nome(self, nome):
149         self.set_declaracao("nome", nome)
150
151     def get_campo_contribuinte(self, attr):
152         if attr == "nome":
153             return self.get_nome()
154         return self._get_attr(self.contribuinte, attr)
155
156     def set_campo_contribuinte(self, attr, val):
157         if attr == "nome":
158             self.set_nome(val)
159         else:
160             self._set_attr(self.contribuinte, attr, val)
161
162     def form(self):
163         form = []
164         ocup = ocupacoes.Ocupacoes()
165         form.append(ContribuinteForm("Nome", "nome", self))
166         form.append(OcupacaoForm(ocup, self))
167         for i in self.attributes:
168             form.append(ContribuinteForm(i, i, self))
169         return form
170
171     attributes = [
172             "nome",
173             "dataNascimento",
174             "tituloEleitor",
175             "doencaDeficiencia",
176             "exterior",
177             "pais",
178             "cep",
179             "uf",
180             "cidade",
181             "municipio",
182             "tipoLogradouro",
183             "logradouro",
184             "numero",
185             "complemento",
186             "bairro",
187             "bairroExt",
188             "cepExt",
189             "logradouroExt",
190             "numeroExt",
191             "complementoExt",
192             "ocupacaoPrincipal",
193             "codigoExterior",
194             "ddd",
195             "telefone",
196             "naturezaOcupacao",
197             ]
198
199 if __name__ == '__main__':
200     import sys
201     contribuinte = Contribuinte(sys.argv[1])
202     print "Carregando CPF " + contribuinte._normalize_cpf(sys.argv[1])
203
204     if len(sys.argv) == 4:
205         print "Valor anterior: " + contribuinte.get_campo_contribuinte(sys.argv[2])
206         contribuinte.set_campo_contribuinte(sys.argv[2], sys.argv[3])
207         print "Valor atual: " + contribuinte.get_campo_contribuinte(sys.argv[2])
208         print "Salvando..."
209         contribuinte.save()
210     elif len(sys.argv) == 3:
211         campo = sys.argv[2]
212         valor = contribuinte.get_campo_contribuinte(campo)
213         if valor:
214             print ("Valor de " + campo + ": " + valor)
215         else:
216             print ("Campo " + campo + " retornou vazio")
217     else:
218         print "\nCONTRIBUINTE:"
219         for i in Contribuinte.attributes:
220             val = contribuinte.get_campo_contribuinte(i)
221             if val == None:
222                 val = ""
223             print i + ": " + val
224         print "\nDECLARACAO:"
225         for i in declaracoes.Declaracoes.attributes:
226             val = contribuinte.get_declaracao(i)
227             if val == None:
228                 val = ""
229             print i + ": " + val
230
231 # vim:tabstop=4:expandtab:smartindent