Move formulário para classe Contribuinte.
[cascardo/irpf-gui.git] / src / contribuinte.py
index 25c997a..3d8e847 100644 (file)
@@ -1,5 +1,6 @@
+# coding=utf-8
 #
-#   Copyright 2013 Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
+#   Copyright 2013-2014 Thadeu Lima de Souza Cascardo <cascardo@cascardo.info>
 #
 #   This program is free software: you can redistribute it and/or modify
 #   it under the terms of the GNU General Public License as published by
 # -*- mode: python; encoding: utf-8; -*-
 import xml.dom.minidom
 import dirs
+import os
+import form
+import ocupacoes
+
+class OcupacaoForm(form.OptionsForm):
+    def __init__(self, ocupacoes, contribuinte):
+        g = ocupacoes.groups()
+        l = []
+        for i in sorted(g):
+            l.extend(g[i])
+        o = map(lambda x: (x[0], x[3]), l)
+        form.OptionsForm.__init__(self, u"Ocupações", o, contribuinte.get_campo_contribuinte("ocupacaoPrincipal"))
+        self.ocupacoes = ocupacoes
+        self.contribuinte = contribuinte
+    def set_value(self, value):
+        form.OptionsForm.set_value(self, value)
+        self.contribuinte.set_campo_contribuinte("ocupacaoPrincipal", value)
+
+class ContribuinteForm(form.StringForm):
+    def __init__(self, name, attr, contribuinte):
+        self.contribuinte = contribuinte
+        self.attr = attr
+        form.StringForm.__init__(self, name, self.contribuinte.get_campo_contribuinte(self.attr))
+    def set_value(self, value):
+        form.StringForm.set_value(self, value)
+        self.contribuinte.set_campo_contribuinte(self.attr, value)
 
 class Contribuinte:
     def __init__(self, cpf):
         irpf_dir = dirs.get_default_irpf_dir()
         self.cpf = self._minimize_cpf(cpf)
+
         if not self._validate_cpf(self.cpf):
             raise RuntimeError("Invalid CPF: " + self.cpf)
+
+        if not os.path.exists(irpf_dir.get_resource_dir()):
+            raise RuntimeError("O caminho para o resource não existe: " + \
+                    irpf_dir.get_resource_dir())
+
+        if not os.path.exists(irpf_dir.get_userdata_dir()):
+            raise RuntimeError("O caminho para os dados não existe: " + \
+                    irpf_dir.get_userdata_dir())
+
         self.cpf_file = irpf_dir.get_userdata_file("%s/%s.xml" % (self.cpf, self.cpf))
         self.iddecl_file = irpf_dir.get_userdata_file("iddeclaracoes.xml")
         self.declaracao = self._find_id()
@@ -32,7 +69,7 @@ class Contribuinte:
     def _find_id(self):
         cpf = self._normalize_cpf(self.cpf)
         self.declaracoes = xml.dom.minidom.parse(self.iddecl_file)
-        for i in self.declaracoes.childNodes[0].childNodes:
+        for i in self.declaracoes.getElementsByTagName("item"):
             if "cpf" in i.attributes.keys():
                 if i.attributes["cpf"].nodeValue == cpf:
                     return i
@@ -56,31 +93,48 @@ class Contribuinte:
 
     # CPF minimizado se parece com 01234567890
     def _minimize_cpf(self, cpf):
-        ncpf = bytearray(self._normalize_cpf(cpf))
-        del ncpf[11]
-        del ncpf[7]
-        del ncpf[3]
-        return str(ncpf)
+        return self._minimize_valor(cpf)
+
+    def _minimize_valor(self, valor):
+        nvalor = ''.join(e for e in valor if e.isalnum())
+        return str(nvalor)
 
     def _validate_cpf(self, cpf):
-        ncpf = self._minimize_cpf(cpf)
-        if len(ncpf) != 11:
+        if len(cpf) != 11:
             return False
-        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
-        if v >= 10:
-            v = 0
-        if v != ord(ncpf[9]) - ord('0'):
-            return False
-        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
-        if v >= 10:
-            v = 0
-        if v != ord(ncpf[10]) - ord('0'):
-            return False
-        return True
+        return self._validate_generico(cpf)
+
+    def _validate_generico(self, valor):
+        def calcula_digito_verificador(numero):
+            n = len(numero) + 1
+
+            soma = 0
+            for i in range(n):
+                if i > len(numero) - 1:
+                    break
+                soma = soma + int(numero[i]) * ( n - i)
+
+            dv =  soma % 11
+
+            if dv < 2:
+                dv = 0
+            else:
+                dv = 11 - dv
+
+            return numero + str(dv)
+
+        mcpf = self._minimize_valor(valor)
+        cpf_sem_dv = mcpf[:-2]
+
+        primeiro_dv = str(calcula_digito_verificador(cpf_sem_dv))
+        segundo_dv = calcula_digito_verificador(primeiro_dv)
+
+        return segundo_dv == mcpf
 
     def save(self):
         self.dados.writexml(open(self.cpf_file, "w"))
         self.declaracoes.writexml(open(self.iddecl_file, "w"))
+
     def _get_attr(self, el, attr):
         if attr in el.attributes.keys():
             return el.attributes[attr].nodeValue
@@ -106,10 +160,20 @@ class Contribuinte:
             return self.get_nome()
         return self._get_attr(self.contribuinte, attr)
 
-    def set_contribuinte(self, attr, val):
+    def set_campo_contribuinte(self, attr, val):
         if attr == "nome":
             self.set_nome(val)
-        self._set_attr(self.contribuinte, attr, val)
+        else:
+            self._set_attr(self.contribuinte, attr, val)
+
+    def form(self):
+        form = []
+        ocup = ocupacoes.Ocupacoes()
+        form.append(ContribuinteForm("Nome", "nome", self))
+        form.append(OcupacaoForm(ocup, self))
+        for i in contribuinte_attributes:
+            form.append(ContribuinteForm(i, i, self))
+        return form
 
 contribuinte_attributes = [
         "nome",
@@ -162,7 +226,7 @@ if __name__ == '__main__':
 
     if len(sys.argv) == 4:
         print "Valor anterior: " + contribuinte.get_campo_contribuinte(sys.argv[2])
-        contribuinte.set_contribuinte(sys.argv[2], sys.argv[3])
+        contribuinte.set_campo_contribuinte(sys.argv[2], sys.argv[3])
         print "Valor atual: " + contribuinte.get_campo_contribuinte(sys.argv[2])
         print "Salvando..."
         contribuinte.save()