Contribuinte deve seguir interface de atributos.
[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 get_attr(self, attr):
163         return self.get_campo_contribuinte(attr)
164
165     def set_attr(self, attr, val):
166         self.set_campo_contribuinte(attr, val)
167
168     def form(self):
169         form = []
170         ocup = ocupacoes.Ocupacoes()
171         form.append(ContribuinteForm("Nome", "nome", self))
172         form.append(OcupacaoForm(ocup, self))
173         for i in self.attributes:
174             form.append(ContribuinteForm(i, i, self))
175         return form
176
177     attributes = [
178             "nome",
179             "dataNascimento",
180             "tituloEleitor",
181             "doencaDeficiencia",
182             "exterior",
183             "pais",
184             "cep",
185             "uf",
186             "cidade",
187             "municipio",
188             "tipoLogradouro",
189             "logradouro",
190             "numero",
191             "complemento",
192             "bairro",
193             "bairroExt",
194             "cepExt",
195             "logradouroExt",
196             "numeroExt",
197             "complementoExt",
198             "ocupacaoPrincipal",
199             "codigoExterior",
200             "ddd",
201             "telefone",
202             "naturezaOcupacao",
203             ]
204
205 if __name__ == '__main__':
206     import sys
207     contribuinte = Contribuinte(sys.argv[1])
208     print "Carregando CPF " + contribuinte._normalize_cpf(sys.argv[1])
209
210     if len(sys.argv) == 4:
211         print "Valor anterior: " + contribuinte.get_campo_contribuinte(sys.argv[2])
212         contribuinte.set_campo_contribuinte(sys.argv[2], sys.argv[3])
213         print "Valor atual: " + contribuinte.get_campo_contribuinte(sys.argv[2])
214         print "Salvando..."
215         contribuinte.save()
216     elif len(sys.argv) == 3:
217         campo = sys.argv[2]
218         valor = contribuinte.get_campo_contribuinte(campo)
219         if valor:
220             print ("Valor de " + campo + ": " + valor)
221         else:
222             print ("Campo " + campo + " retornou vazio")
223     else:
224         print "\nCONTRIBUINTE:"
225         for i in Contribuinte.attributes:
226             val = contribuinte.get_campo_contribuinte(i)
227             if val == None:
228                 val = ""
229             print i + ": " + val
230         print "\nDECLARACAO:"
231         for i in declaracoes.Declaracoes.attributes:
232             val = contribuinte.get_declaracao(i)
233             if val == None:
234                 val = ""
235             print i + ": " + val
236
237 # vim:tabstop=4:expandtab:smartindent