Corrige erro ao alterar nome do contribuinte.
[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
20 class Contribuinte:
21     def __init__(self, cpf):
22         irpf_dir = dirs.get_default_irpf_dir()
23         self.cpf = self._minimize_cpf(cpf)
24         if not self._validate_cpf(self.cpf):
25             raise RuntimeError("Invalid CPF: " + self.cpf)
26         self.cpf_file = irpf_dir.get_userdata_file("%s/%s.xml" % (self.cpf, self.cpf))
27         self.iddecl_file = irpf_dir.get_userdata_file("iddeclaracoes.xml")
28         self.declaracao = self._find_id()
29         self.dados = xml.dom.minidom.parse(self.cpf_file)
30         self.contribuinte = self.dados.getElementsByTagName("contribuinte")[0]
31
32     def _find_id(self):
33         cpf = self._normalize_cpf(self.cpf)
34         self.declaracoes = xml.dom.minidom.parse(self.iddecl_file)
35         for i in self.declaracoes.childNodes[0].childNodes:
36             if "cpf" in i.attributes.keys():
37                 if i.attributes["cpf"].nodeValue == cpf:
38                     return i
39         return None
40
41     # CPF normalizado se parece com 000.000.000-00
42     def _normalize_cpf(self, cpf):
43         ncpf = ""
44         for i in cpf:
45             if len(ncpf) == 3 or len(ncpf) == 7:
46                 ncpf += '.'
47             if len(ncpf) == 11:
48                 ncpf += '-'
49             if len(ncpf) == 14:
50                 break
51             if ord(i) >= ord('0') and ord(i) <= ord('9'):
52                 ncpf += i
53         if len(ncpf) != 14:
54             raise RuntimeError("Invalid CPF")
55         return ncpf
56
57     # CPF minimizado se parece com 01234567890
58     def _minimize_cpf(self, cpf):
59         ncpf = bytearray(self._normalize_cpf(cpf))
60         del ncpf[11]
61         del ncpf[7]
62         del ncpf[3]
63         return str(ncpf)
64
65     def _validate_cpf(self, cpf):
66         ncpf = self._minimize_cpf(cpf)
67         if len(ncpf) != 11:
68             return False
69         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
70         if v >= 10:
71             v = 0
72         if v != ord(ncpf[9]) - ord('0'):
73             return False
74         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
75         if v >= 10:
76             v = 0
77         if v != ord(ncpf[10]) - ord('0'):
78             return False
79         return True
80
81     def save(self):
82         self.dados.writexml(open(self.cpf_file, "w"))
83         self.declaracoes.writexml(open(self.iddecl_file, "w"))
84     def _get_attr(self, el, attr):
85         if attr in el.attributes.keys():
86             return el.attributes[attr].nodeValue
87         return None
88
89     def _set_attr(self, el, attr, val):
90         el.attributes[attr].nodeValue = val
91
92     def get_declaracao(self, attr):
93         return self._get_attr(self.declaracao, attr)
94
95     def set_declaracao(self, attr, val):
96         self._set_attr(self.declaracao, attr, val)
97
98     def get_nome(self):
99         return self.get_declaracao("nome")
100
101     def set_nome(self, nome):
102         self.set_declaracao("nome", nome)
103
104     def get_campo_contribuinte(self, attr):
105         if attr == "nome":
106             return self.get_nome()
107         return self._get_attr(self.contribuinte, attr)
108
109     def set_contribuinte(self, attr, val):
110         if attr == "nome":
111             self.set_nome(val)
112         else:
113             self._set_attr(self.contribuinte, attr, val)
114
115 contribuinte_attributes = [
116         "nome",
117         "dataNascimento",
118         "tituloEleitor",
119         "doencaDeficiencia",
120         "exterior",
121         "pais",
122         "cep",
123         "uf",
124         "cidade",
125         "municipio",
126         "tipoLogradouro",
127         "logradouro",
128         "numero",
129         "complemento",
130         "bairro",
131         "bairroExt",
132         "cepExt",
133         "logradouroExt",
134         "numeroExt",
135         "complementoExt",
136         "ocupacaoPrincipal",
137         "codigoExterior",
138         "ddd",
139         "telefone",
140         "naturezaOcupacao",
141         ]
142
143 declaracao_attributes = [
144         "dataUltimoAcesso",
145         "declaracaoRetificadora",
146         "enderecoDiferente",
147         "enderecoMACRede",
148         "exercicio",
149         "nome",
150         "numReciboDecRetif",
151         "numeroReciboDecAnterior",
152         "resultadoDeclaracao",
153         "tipoDeclaracao",
154         "tipoDeclaracaoAES",
155         "transmitida",
156         "versaoBeta"
157         ]
158
159 if __name__ == '__main__':
160     import sys
161     contribuinte = Contribuinte(sys.argv[1])
162     print "Carregando CPF " + contribuinte._normalize_cpf(sys.argv[1])
163
164     if len(sys.argv) == 4:
165         print "Valor anterior: " + contribuinte.get_campo_contribuinte(sys.argv[2])
166         contribuinte.set_contribuinte(sys.argv[2], sys.argv[3])
167         print "Valor atual: " + contribuinte.get_campo_contribuinte(sys.argv[2])
168         print "Salvando..."
169         contribuinte.save()
170     elif len(sys.argv) == 3:
171         campo = sys.argv[2]
172         valor = contribuinte.get_campo_contribuinte(campo)
173         if valor:
174             print ("Valor de " + campo + ": " + valor)
175         else:
176             print ("Campo " + campo + " retornou vazio")
177     else:
178         print "\nCONTRIBUINTE:"
179         for i in contribuinte_attributes:
180             val = contribuinte.get_campo_contribuinte(i)
181             if val == None:
182                 val = ""
183             print i + ": " + val
184         print "\nDECLARACAO:"
185         for i in declaracao_attributes:
186             val = contribuinte.get_declaracao(i)
187             if val == None:
188                 val = ""
189             print i + ": " + val
190
191 # vim:tabstop=4:expandtab:smartindent