|
@@ -0,0 +1,302 @@
|
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
|
+##############################################################################
|
|
|
|
+#
|
|
|
|
+# OpenERP, Open Source Management Solution
|
|
|
|
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
|
|
|
+#
|
|
|
|
+# This program is free software: you can redistribute it and/or modify
|
|
|
|
+# it under the terms of the GNU Affero General Public License as
|
|
|
|
+# published by the Free Software Foundation, either version 3 of the
|
|
|
|
+# License, or (at your option) any later version.
|
|
|
|
+#
|
|
|
|
+# This program is distributed in the hope that it will be useful,
|
|
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
+# GNU Affero General Public License for more details.
|
|
|
|
+#
|
|
|
|
+# You should have received a copy of the GNU Affero General Public License
|
|
|
|
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
+#
|
|
|
|
+##############################################################################
|
|
|
|
+
|
|
|
|
+from openerp import models, fields, tools, api, _
|
|
|
|
+from openerp.exceptions import ValidationError
|
|
|
|
+from math import floor
|
|
|
|
+import re
|
|
|
|
+import sys
|
|
|
|
+import logging
|
|
|
|
+
|
|
|
|
+# logger = logging.getlogger(__name__)
|
|
|
|
+
|
|
|
|
+class res_partner(models.Model):
|
|
|
|
+ _name = 'res.partner'
|
|
|
|
+ _inherit = 'res.partner'
|
|
|
|
+ _description = 'Add extra data to SET'
|
|
|
|
+
|
|
|
|
+ digitointer = fields.Char('RUC Internacional', size=13)
|
|
|
|
+ dv= fields.Char('Digito Verificador', size=1)
|
|
|
|
+ esinternacional = fields.Boolean(string='Es internacional' ,default = False)
|
|
|
|
+ retencion = fields.Boolean(string='Retiene IVA' ,default = False)
|
|
|
|
+ retentor_renta = fields.Boolean(string='Retentor renta' ,default = False)
|
|
|
|
+ porcentaje_retencion = fields.Integer('Porcentaje de Retención')
|
|
|
|
+ porcentaje_retencion_renta = fields.Integer('Porcentaje de Retención Renta')
|
|
|
|
+ porcentaje_retencion_absorbida = fields.Integer('Porcentaje de Retención Absorbida')
|
|
|
|
+ retiene_iva_cliente = fields.Boolean(string='Es agente retentor' ,default = False)
|
|
|
|
+ concepto_iva = fields.Selection([('femenino','Femenino'),('masculino','Masculino')],'Concepto IVA')
|
|
|
|
+ concepto_renta = fields.Char('Concepto renta')
|
|
|
|
+ rucdv = fields.Char('R.U.C.', size=12)
|
|
|
|
+ naturaleza_receptor = fields.Selection([('1','Contribuyente'),('2','No contribuyente')],'Naturaleza receptor')
|
|
|
|
+ naturaleza_vendedor = fields.Selection([('1','No contribuyente'),('2','Extranjero')],'Naturaleza vendedor')
|
|
|
|
+ nivel = fields.Integer('Nivel', size=2)
|
|
|
|
+ nombre_fantasia = fields.Char('Nombre de fantasia')
|
|
|
|
+ ci = fields.Char('CI', size=13)
|
|
|
|
+ nro_casa = fields.Integer('Nro. Casa')
|
|
|
|
+ nro_documento = fields.Char('Nro. Documento')
|
|
|
|
+ timbrado = fields.Char('Timbrado')
|
|
|
|
+ tipo_documento_identidad = fields.Char('Tipo Documento Identidad')
|
|
|
|
+ iva_retencion_10 = fields.Integer('Porcentaje de retención sobre el IVA 10%')
|
|
|
|
+ iva_retencion_5 = fields.Integer('Porcentaje de retención sobre el IVA 5%')
|
|
|
|
+ tipo_documento_receptor = fields.Selection([('1','Cédula paraguaya'),('2','Pasaporte'),('3','Cédula extranjera'),('4','Carnet de residencia'),('5','Innominado'),('6','Tarjeta diplomática de exoneración fiscal')],'Tipo Documento Receptor')
|
|
|
|
+ tipo_documento_vendedor = fields.Selection([('1','Cédula paraguaya'),('2','Pasaporte'),('3','Cédula extranjera'),('4','Carnet de residencia')],'Tipo Documento Vendedor')
|
|
|
|
+ tipo_operacion = fields.Selection([('1','B2B'),('2','B2C'),('3','B2G'),('4','B2F')],'Tipo Operación')
|
|
|
|
+ situacion = fields.Selection([('contribuyente','Contribuyente'),('nocontribuyente','No contribuyente')],'Situación')
|
|
|
|
+ # activity_id = fields.Many2one("economic.activity",
|
|
|
|
+ # string="Default Economic Activity",
|
|
|
|
+ # context={'active_test': False})
|
|
|
|
+ # economic_activities_ids = fields.Many2many('economic.activity',
|
|
|
|
+ # string='Economic Activities',
|
|
|
|
+ # context={'active_test': False})
|
|
|
|
+ tipo_identificacion = fields.Selection([('1','Cédula paraguaya'),('2','RUC'),('3','Cédula extranjera'),('4','Carnet de residencia'),('5','Innominado')],'Tipo de Identificación')
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # @api.constrains("ruc")
|
|
|
|
+ # def constrains_py_doc_number(self):
|
|
|
|
+ # for partner in self:
|
|
|
|
+ # if not partner.tipo_identificacion and not partner.ruc:
|
|
|
|
+ # continue
|
|
|
|
+ # elif not partner.tipo_identificacion and partner.ruc and not partner.parent_id:
|
|
|
|
+ # raise ValidationError(_("Seleccione un tipo de documento"))
|
|
|
|
+ # elif partner.tipo_identificacion and not partner.ruc:
|
|
|
|
+ # raise ValidationError(_("El campo RUC no puede estar vacio"))
|
|
|
|
+ # vat = partner.ruc
|
|
|
|
+ # if partner.tipo_identificacion == '2':
|
|
|
|
+ # check = self._validate_ruc(vat)
|
|
|
|
+ # if not check:
|
|
|
|
+ # raise ValidationError(_('El número de RUC [%s] no es válido' % vat))
|
|
|
|
+ # elif partner.tipo_identificacion == '1':
|
|
|
|
+ # check = self._validate_ci(vat)
|
|
|
|
+ # if not check:
|
|
|
|
+ # raise ValidationError(_('El número de identificación [%s] no es válido' % vat))
|
|
|
|
+ # else:
|
|
|
|
+ # continue
|
|
|
|
+ #
|
|
|
|
+ # @staticmethod
|
|
|
|
+ # def _validate_ruc(vat):
|
|
|
|
+ # factor = '43298765432'
|
|
|
|
+ # sum = 0
|
|
|
|
+ # dig_check = None
|
|
|
|
+ # if len(vat) != 12:
|
|
|
|
+ # return False
|
|
|
|
+ # try:
|
|
|
|
+ # int(vat)
|
|
|
|
+ # except ValueError:
|
|
|
|
+ # return False
|
|
|
|
+ # for f in range(0, 11):
|
|
|
|
+ # sum += int(factor[f]) * int(vat[f])
|
|
|
|
+ # subtraction = 11 - floor((sum % 11))
|
|
|
|
+ # if subtraction < 10:
|
|
|
|
+ # dig_check = subtraction
|
|
|
|
+ # elif subtraction == 10:
|
|
|
|
+ # dig_check = ""
|
|
|
|
+ # elif subtraction == 11:
|
|
|
|
+ # dig_check = 0
|
|
|
|
+ #
|
|
|
|
+ # if not int(vat[11]) == dig_check:
|
|
|
|
+ # return False
|
|
|
|
+ # return True
|
|
|
|
+ #
|
|
|
|
+ # @staticmethod
|
|
|
|
+ # # def _validate_ci(vat):
|
|
|
|
+ #
|
|
|
|
+ # def _validate_ci(vat):
|
|
|
|
+ # logging.warning(vat)
|
|
|
|
+ # ruc = ''
|
|
|
|
+ # basemax = 7
|
|
|
|
+ # for c in str(vat).replace('-', ''):
|
|
|
|
+ # ruc += c.isdigit() and c or str(ord(c))
|
|
|
|
+ # k = 2
|
|
|
|
+ # total = 0
|
|
|
|
+ #
|
|
|
|
+ # for c in reversed(ruc[:-1]):
|
|
|
|
+ # n = int(c)
|
|
|
|
+ # if n > basemax:
|
|
|
|
+ # k = 2
|
|
|
|
+ # total += n * k
|
|
|
|
+ # k += 1
|
|
|
|
+ # resto = total % basemax
|
|
|
|
+ # if resto > 1:
|
|
|
|
+ # n = basemax - resto
|
|
|
|
+ # else:
|
|
|
|
+ # n = 0
|
|
|
|
+ # return n == int(ruc[-1])
|
|
|
|
+ # vat = vat.replace("-", "").replace('.', '')
|
|
|
|
+ # sum = 0
|
|
|
|
+ # if not vat:
|
|
|
|
+ # return False
|
|
|
|
+ # try:
|
|
|
|
+ # int(vat)
|
|
|
|
+ # except ValueError:
|
|
|
|
+ # return False
|
|
|
|
+ # vat = "%08d" % int(vat)
|
|
|
|
+ # long = len(vat)
|
|
|
|
+ # if long > 8:
|
|
|
|
+ # return False
|
|
|
|
+ # code = [2, 9, 8, 7, 6, 3, 4]
|
|
|
|
+ # for f in range(0, long - 1):
|
|
|
|
+ # sum += int(vat[f]) * int(code[f])
|
|
|
|
+ # total = sum + int(vat[-1])
|
|
|
|
+ # subtraction = total % 10
|
|
|
|
+ # if subtraction != 0:
|
|
|
|
+ # return False
|
|
|
|
+ # return True
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ # """
|
|
|
|
+ # El numero de una cédula de identidad tiene exactamente 7 dígitos al cual se le adiciona
|
|
|
|
+ # un dígito verificador.
|
|
|
|
+ #
|
|
|
|
+ # Es así que un número valido debe respetar el siguiente formato:
|
|
|
|
+ #
|
|
|
|
+ # a.bcd.efg-h
|
|
|
|
+ #
|
|
|
|
+ # El dígito posterior al guión (h) es también llamado dígito verificador.
|
|
|
|
+ #
|
|
|
|
+ # Para obtener h debemos:
|
|
|
|
+ #
|
|
|
|
+ # Multiplicar a,b,c,d,e,f,g por las siguientes constantes:
|
|
|
|
+ # (a; b; c; d; e; f; g) .* (2; 9; 8; 7; 6; 3; 4)
|
|
|
|
+ #
|
|
|
|
+ # El resultado de la suma s = 2*a + 9*b + 8*c + 7*d + 6*e + 3*f + 4*g es dividido por 10
|
|
|
|
+ # quedándonos con resto (M = s modulo 10)
|
|
|
|
+ #
|
|
|
|
+ # Finalmente h = (10 - M) % 10
|
|
|
|
+ #
|
|
|
|
+ # Ejemplo practico:
|
|
|
|
+ # Si la CI es 1.234.567:
|
|
|
|
+ #
|
|
|
|
+ # s = 2*1 + 9*2 + 8*3 + 7*4 + 6*5 + 3*6 + 4*7 = 148
|
|
|
|
+ # M = 148 % 10 = 8
|
|
|
|
+ # h = (10 - 8) % 10 = 2
|
|
|
|
+ # Obteniendo que 1.234.567-2 es un número de CI valido.
|
|
|
|
+ # """
|
|
|
|
+
|
|
|
|
+ # class res_partner(models.Model):
|
|
|
|
+ # _inherit = 'res.partner'
|
|
|
|
+
|
|
|
|
+ # code = [2, 9, 8, 7, 6, 3, 4]
|
|
|
|
+ #
|
|
|
|
+ # # def __init__(self, vat):
|
|
|
|
+ # """ Inicializa la clase
|
|
|
|
+ # Asigna un numero de cedula a la propiedad publica numero
|
|
|
|
+ #
|
|
|
|
+ # Args:
|
|
|
|
+ # numero: un numero de cedula entre 6 y 7 digitos, puede ser int o string
|
|
|
|
+ # """
|
|
|
|
+ # self.ruc = vat
|
|
|
|
+ # self._verifier = ""
|
|
|
|
+ #
|
|
|
|
+ # @property
|
|
|
|
+ # def numero(self):
|
|
|
|
+ # """ propiedad de lectura
|
|
|
|
+ #
|
|
|
|
+ # Returns:
|
|
|
|
+ # _numero: la propiedad privada de numero de cedula ya normalizada
|
|
|
|
+ # """
|
|
|
|
+ # return self._ruc
|
|
|
|
+ #
|
|
|
|
+ # @numero.setter
|
|
|
|
+ # def numero(self, val):
|
|
|
|
+ # """ asigna a la propiedad privada el numero de cedula asignado a numero,
|
|
|
|
+ # lo normaliza y valida
|
|
|
|
+ # Args:
|
|
|
|
+ # val (int o string): el numero de cedula
|
|
|
|
+ #
|
|
|
|
+ # """
|
|
|
|
+ # try:
|
|
|
|
+ # if isinstance(val, str):
|
|
|
|
+ # # si la cedula es un string, le saco el formato (puntos y guiones)
|
|
|
|
+ # numUpdated = re.sub(r"[\.|\-]", "", val)
|
|
|
|
+ # self._ruc = numUpdated
|
|
|
|
+ # else:
|
|
|
|
+ # self._ruc = str(val)
|
|
|
|
+ #
|
|
|
|
+ # if not self._ruc.isnumeric():
|
|
|
|
+ # sys.exit("cedula should be only numbers")
|
|
|
|
+ #
|
|
|
|
+ # if (len(self._ruc) < 6 or len(self._ruc) > 7):
|
|
|
|
+ # sys.exit("invalid cedula length...")
|
|
|
|
+ #
|
|
|
|
+ # except:
|
|
|
|
+ # sys.exit(
|
|
|
|
+ # "Cedula conversion error, check cedula length, value or format.")
|
|
|
|
+ #
|
|
|
|
+ # @property
|
|
|
|
+ # def verifier(self):
|
|
|
|
+ # """propiedad de lectura del digito verificador
|
|
|
|
+ #
|
|
|
|
+ # Returns:
|
|
|
|
+ # int: digito verificador
|
|
|
|
+ # """
|
|
|
|
+ # return self._verifier
|
|
|
|
+ #
|
|
|
|
+ # def __acumSequence(self, seq, index):
|
|
|
|
+ # """ funcion recursiva privada que suma los digitos de una cedula
|
|
|
|
+ #
|
|
|
|
+ # Args:
|
|
|
|
+ # seq: el numero en la constante SEQUENCE
|
|
|
|
+ # index (int): la posicion en ambos arrays (secuencia y cedula)
|
|
|
|
+ # Deben matchear en posicion
|
|
|
|
+ #
|
|
|
|
+ # ** NOTA: como la correspondencia debe ser 1:1 seq y _numero, en caso de ser
|
|
|
|
+ # una cedula de 6 digitos se podia haber agregado un 0 al inicio de _numero para comenzar
|
|
|
|
+ # con el mismo largo (7 digitos), pero asi es mas divertido :D
|
|
|
|
+ #
|
|
|
|
+ # Returns:
|
|
|
|
+ # int: la acumulacion de la suma de digito de self._numero * digito de secuencia
|
|
|
|
+ # """
|
|
|
|
+ # if index < (len(seq) - 1):
|
|
|
|
+ # return (seq[index] * int(self._ruc[index])) + self.__acumSequence(seq, index + 1)
|
|
|
|
+ # return seq[index] * int(self._ruc[index])
|
|
|
|
+ #
|
|
|
|
+ # def getVerifierDigit(self):
|
|
|
|
+ # """ calculo de digito verificador
|
|
|
|
+ #
|
|
|
|
+ # Returns:
|
|
|
|
+ # int: digito verificador
|
|
|
|
+ # """
|
|
|
|
+ # try:
|
|
|
|
+ # digit_diff = (len(self.code) - len(self._ruc))
|
|
|
|
+ # if digit_diff >= 0:
|
|
|
|
+ # acum = 0
|
|
|
|
+ # acum = self.__acumSequence(self.code[digit_diff:], 0)
|
|
|
|
+ # mod = (acum % 10)
|
|
|
|
+ # verifier = ((10 - mod) % 10)
|
|
|
|
+ # self._verifier = str(verifier)
|
|
|
|
+ # return verifier
|
|
|
|
+ # except:
|
|
|
|
+ # print("ERROR: unknown error, check params!")
|
|
|
|
+ #
|
|
|
|
+ # def formatCedula(self):
|
|
|
|
+ # """ formatea un numero de cedula al formato de puntos y guion
|
|
|
|
+ # ej: 12345678 => 1.234.567-8
|
|
|
|
+ #
|
|
|
|
+ # Returns:
|
|
|
|
+ # string: el numero de cedula completo y formateado
|
|
|
|
+ # """
|
|
|
|
+ # self.getVerifierDigit()
|
|
|
|
+ # if len(self.ruc) == 6:
|
|
|
|
+ # return self.ruc[:3] + '.' + self.ruc[3:] + '-' + self.verifier
|
|
|
|
+ # return self.ruc[:1] + '.' + self.ruc[1:4] + '.' + self.ruc[4:] + '-' + self.verifier
|