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