8b7fb8eb57105a5452b69e537ee379f05914034d
[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.declaracao = declaracoes.Declaracoes().find("cpf", ncpf)
67         self.dados = xml.dom.minidom.parse(self.cpf_file)
68         self.contribuinte = self.dados.getElementsByTagName("contribuinte")[0]
69
70     # CPF normalizado se parece com 000.000.000-00
71     def _normalize_cpf(self, cpf):
72         ncpf = ""
73         for i in cpf:
74             if len(ncpf) == 3 or len(ncpf) == 7:
75                 ncpf += '.'
76             if len(ncpf) == 11:
77                 ncpf += '-'
78             if len(ncpf) == 14:
79                 break
80             if ord(i) >= ord('0') and ord(i) <= ord('9'):
81                 ncpf += i
82         if len(ncpf) != 14:
83             raise RuntimeError("Invalid CPF")
84         return ncpf
85
86     # CPF minimizado se parece com 01234567890
87     def _minimize_cpf(self, cpf):
88         return self._minimize_valor(cpf)
89
90     def _minimize_valor(self, valor):
91         nvalor = ''.join(e for e in valor if e.isalnum())
92         return str(nvalor)
93
94     def _validate_cpf(self, cpf):
95         if len(cpf) != 11:
96             return False
97         return self._validate_generico(cpf)
98
99     def _validate_generico(self, valor):
100         def calcula_digito_verificador(numero):
101             n = len(numero) + 1
102
103             soma = 0
104             for i in range(n):
105                 if i > len(numero) - 1:
106                     break
107                 soma = soma + int(numero[i]) * ( n - i)
108
109             dv =  soma % 11
110
111             if dv < 2:
112                 dv = 0
113             else:
114                 dv = 11 - dv
115
116             return numero + str(dv)
117
118         mcpf = self._minimize_valor(valor)
119         cpf_sem_dv = mcpf[:-2]
120
121         primeiro_dv = str(calcula_digito_verificador(cpf_sem_dv))
122         segundo_dv = calcula_digito_verificador(primeiro_dv)
123
124         return segundo_dv == mcpf
125
126     def save(self):
127         self.dados.writexml(open(self.cpf_file, "w"))
128         self.declaracao.save()
129
130     def _get_attr(self, el, attr):
131         if attr in el.attributes.keys():
132             return el.attributes[attr].nodeValue
133         return None
134
135     def _set_attr(self, el, attr, val):
136         el.attributes[attr].nodeValue = val
137
138     def get_declaracao(self, attr):
139         return self.declaracao.get_attr(attr)
140
141     def set_declaracao(self, attr, val):
142         self.declaracao.set_attr(attr, val)
143
144     def get_nome(self):
145         return self.get_declaracao("nome")
146
147     def set_nome(self, nome):
148         self.set_declaracao("nome", nome)
149
150     def get_campo_contribuinte(self, attr):
151         if attr == "nome":
152             return self.get_nome()
153         return self._get_attr(self.contribuinte, attr)
154
155     def set_campo_contribuinte(self, attr, val):
156         if attr == "nome":
157             self.set_nome(val)
158         else:
159             self._set_attr(self.contribuinte, attr, val)
160
161     def form(self):
162         form = []
163         ocup = ocupacoes.Ocupacoes()
164         form.append(ContribuinteForm("Nome", "nome", self))
165         form.append(OcupacaoForm(ocup, self))
166         for i in self.attributes:
167             form.append(ContribuinteForm(i, i, self))
168         return form
169
170     attributes = [
171             "nome",
172             "dataNascimento",
173             "tituloEleitor",
174             "doencaDeficiencia",
175             "exterior",
176             "pais",
177             "cep",
178             "uf",
179             "cidade",
180             "municipio",
181             "tipoLogradouro",
182             "logradouro",
183             "numero",
184             "complemento",
185             "bairro",
186             "bairroExt",
187             "cepExt",
188             "logradouroExt",
189             "numeroExt",
190             "complementoExt",
191             "ocupacaoPrincipal",
192             "codigoExterior",
193             "ddd",
194             "telefone",
195             "naturezaOcupacao",
196             ]
197
198 if __name__ == '__main__':
199     import sys
200     contribuinte = Contribuinte(sys.argv[1])
201     print "Carregando CPF " + contribuinte._normalize_cpf(sys.argv[1])
202
203     if len(sys.argv) == 4:
204         print "Valor anterior: " + contribuinte.get_campo_contribuinte(sys.argv[2])
205         contribuinte.set_campo_contribuinte(sys.argv[2], sys.argv[3])
206         print "Valor atual: " + contribuinte.get_campo_contribuinte(sys.argv[2])
207         print "Salvando..."
208         contribuinte.save()
209     elif len(sys.argv) == 3:
210         campo = sys.argv[2]
211         valor = contribuinte.get_campo_contribuinte(campo)
212         if valor:
213             print ("Valor de " + campo + ": " + valor)
214         else:
215             print ("Campo " + campo + " retornou vazio")
216     else:
217         print "\nCONTRIBUINTE:"
218         for i in Contribuinte.attributes:
219             val = contribuinte.get_campo_contribuinte(i)
220             if val == None:
221                 val = ""
222             print i + ": " + val
223         print "\nDECLARACAO:"
224         for i in declaracoes.Declaracoes.attributes:
225             val = contribuinte.get_declaracao(i)
226             if val == None:
227                 val = ""
228             print i + ": " + val
229
230 # vim:tabstop=4:expandtab:smartindent