Checando a existência dos diretórios antes de prosseguir
[cascardo/irpf-gui.git] / src / contribuinte.py
1 #
2 #   Copyright 2013 Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
3 #
4 #   This program is free software: you can redistribute it and/or modify
5 #   it under the terms of the GNU General Public License as published by
6 #   the Free Software Foundation, either version 3 of the License, or
7 #   (at your option) any later version.
8 #
9 #   This program is distributed in the hope that it will be useful,
10 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #   GNU General Public License for more details.
13 #
14 #   You should have received a copy of the GNU General Public License
15 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 # -*- mode: python; encoding: utf-8; -*-
17 import xml.dom.minidom
18 import dirs
19 import os
20
21 class Contribuinte:
22     def __init__(self, cpf):
23         irpf_dir = dirs.get_default_irpf_dir()
24         self.cpf = self._minimize_cpf(cpf)
25
26         if not self._validate_cpf(self.cpf):
27             raise RuntimeError("Invalid CPF: " + self.cpf)
28
29         if not os.path.exists(irpf_dir.get_resource_dir()):
30             raise RuntimeError("O caminho para o resource não existe: " + \
31                     irpf_dir.get_resource_dir())
32
33         if not os.path.exists(irpf_dir.get_userdata_dir()):
34             raise RuntimeError("O caminho para os dados não existe: " + \
35                     irpf_dir.get_userdata_dir())
36
37         self.cpf_file = irpf_dir.get_userdata_file("%s/%s.xml" % (self.cpf, self.cpf))
38         self.iddecl_file = irpf_dir.get_userdata_file("iddeclaracoes.xml")
39         self.declaracao = self._find_id()
40         self.dados = xml.dom.minidom.parse(self.cpf_file)
41         self.contribuinte = self.dados.getElementsByTagName("contribuinte")[0]
42
43     def _find_id(self):
44         cpf = self._normalize_cpf(self.cpf)
45         self.declaracoes = xml.dom.minidom.parse(self.iddecl_file)
46         for i in self.declaracoes.childNodes[0].childNodes:
47             if "cpf" in i.attributes.keys():
48                 if i.attributes["cpf"].nodeValue == cpf:
49                     return i
50         return None
51
52     # CPF normalizado se parece com 000.000.000-00
53     def _normalize_cpf(self, cpf):
54         ncpf = ""
55         for i in cpf:
56             if len(ncpf) == 3 or len(ncpf) == 7:
57                 ncpf += '.'
58             if len(ncpf) == 11:
59                 ncpf += '-'
60             if len(ncpf) == 14:
61                 break
62             if ord(i) >= ord('0') and ord(i) <= ord('9'):
63                 ncpf += i
64         if len(ncpf) != 14:
65             raise RuntimeError("Invalid CPF")
66         return ncpf
67
68     # CPF minimizado se parece com 01234567890
69     def _minimize_cpf(self, cpf):
70         ncpf = bytearray(self._normalize_cpf(cpf))
71         del ncpf[11]
72         del ncpf[7]
73         del ncpf[3]
74         return str(ncpf)
75
76     def _validate_cpf(self, cpf):
77         ncpf = self._minimize_cpf(cpf)
78         if len(ncpf) != 11:
79             return False
80         v = (11 - sum(map(lambda x: x[0]*x[1], zip(range(10, 1, -1), map(lambda x: ord(x) - ord('0'), ncpf[0:9]))))) % 11
81         if v >= 10:
82             v = 0
83         if v != ord(ncpf[9]) - ord('0'):
84             return False
85         v = (11 - sum(map(lambda x: x[0]*x[1], zip(range(11, 1, -1), map(lambda x: ord(x) - ord('0'), ncpf[0:10]))))) % 11
86         if v >= 10:
87             v = 0
88         if v != ord(ncpf[10]) - ord('0'):
89             return False
90         return True
91
92     def save(self):
93         self.dados.writexml(open(self.cpf_file, "w"))
94         self.declaracoes.writexml(open(self.iddecl_file, "w"))
95     def _get_attr(self, el, attr):
96         if attr in el.attributes.keys():
97             return el.attributes[attr].nodeValue
98         return None
99
100     def _set_attr(self, el, attr, val):
101         el.attributes[attr].nodeValue = val
102
103     def get_declaracao(self, attr):
104         return self._get_attr(self.declaracao, attr)
105
106     def set_declaracao(self, attr, val):
107         self._set_attr(self.declaracao, attr, val)
108
109     def get_nome(self):
110         return self.get_declaracao("nome")
111
112     def set_nome(self, nome):
113         self.set_declaracao("nome", nome)
114
115     def get_campo_contribuinte(self, attr):
116         if attr == "nome":
117             return self.get_nome()
118         return self._get_attr(self.contribuinte, attr)
119
120     def set_campo_contribuinte(self, attr, val):
121         if attr == "nome":
122             self.set_nome(val)
123         else:
124             self._set_attr(self.contribuinte, attr, val)
125
126 contribuinte_attributes = [
127         "nome",
128         "dataNascimento",
129         "tituloEleitor",
130         "doencaDeficiencia",
131         "exterior",
132         "pais",
133         "cep",
134         "uf",
135         "cidade",
136         "municipio",
137         "tipoLogradouro",
138         "logradouro",
139         "numero",
140         "complemento",
141         "bairro",
142         "bairroExt",
143         "cepExt",
144         "logradouroExt",
145         "numeroExt",
146         "complementoExt",
147         "ocupacaoPrincipal",
148         "codigoExterior",
149         "ddd",
150         "telefone",
151         "naturezaOcupacao",
152         ]
153
154 declaracao_attributes = [
155         "dataUltimoAcesso",
156         "declaracaoRetificadora",
157         "enderecoDiferente",
158         "enderecoMACRede",
159         "exercicio",
160         "nome",
161         "numReciboDecRetif",
162         "numeroReciboDecAnterior",
163         "resultadoDeclaracao",
164         "tipoDeclaracao",
165         "tipoDeclaracaoAES",
166         "transmitida",
167         "versaoBeta"
168         ]
169
170 if __name__ == '__main__':
171     import sys
172     contribuinte = Contribuinte(sys.argv[1])
173     print "Carregando CPF " + contribuinte._normalize_cpf(sys.argv[1])
174
175     if len(sys.argv) == 4:
176         print "Valor anterior: " + contribuinte.get_campo_contribuinte(sys.argv[2])
177         contribuinte.set_campo_contribuinte(sys.argv[2], sys.argv[3])
178         print "Valor atual: " + contribuinte.get_campo_contribuinte(sys.argv[2])
179         print "Salvando..."
180         contribuinte.save()
181     elif len(sys.argv) == 3:
182         campo = sys.argv[2]
183         valor = contribuinte.get_campo_contribuinte(campo)
184         if valor:
185             print ("Valor de " + campo + ": " + valor)
186         else:
187             print ("Campo " + campo + " retornou vazio")
188     else:
189         print "\nCONTRIBUINTE:"
190         for i in contribuinte_attributes:
191             val = contribuinte.get_campo_contribuinte(i)
192             if val == None:
193                 val = ""
194             print i + ": " + val
195         print "\nDECLARACAO:"
196         for i in declaracao_attributes:
197             val = contribuinte.get_declaracao(i)
198             if val == None:
199                 val = ""
200             print i + ": " + val
201
202 # vim:tabstop=4:expandtab:smartindent