domingo, 28 de febrero de 2010

Conversión de numeros a letras para openERP

Estoy corriendo la version 5.0.6 (servidor), Python 2.6 y OpenSuse 11.2.

Esta solución esta basada en información encontrada en internet en algunos foros de Python y openERP.

Abrir una consola con el usuario root e ir ar directorio:

/usr/local/lib/python2.6/site-packages/openerp-server/addons/account/report

una vez ahi, editar el archivo invoice.py (yo utilizé el editor vi), debería quedar como: (el código agregado está marcado)

import time
from numero_a_texto import Numero_a_Texto
from report import report_sxw

class account_invoice(report_sxw.rml_parse):
    def __init__(self, cr, uid, name, context):
        super(account_invoice, self).__init__(cr, uid, name, context)
        self.localcontext.update({
            'time': time,
            'obt_texto':self.obt_texto,
            'lang':context['lang'],
        })

    def obt_texto(self,cantidad):
        res=Numero_a_Texto(cantidad)
        return res
report_sxw.report_sxw(
    'report.account.invoice',
    'account.invoice',
    'addons/account/report/invoice.rml',
    parser=account_invoice
)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:


Una vez que esté listo el archivo, crear un nuevo archivo el archivo numero_a_texto.py, este archivo debe contener:

#!/usr/bin/python                  
# -*- coding: utf-8 -*-            

UNIDADES = (
    '',    
    'UN ', 
    'DOS ',
    'TRES ',
    'CUATRO ',
    'CINCO ',
    'SEIS ', 
    'SIETE ',
    'OCHO ', 
    'NUEVE ',
    'DIEZ ', 
    'ONCE ', 
    'DOCE ', 
    'TRECE ',
    'CATORCE ',
    'QUINCE ',
    'DIECISEIS ',
    'DIECISIETE ',
    'DIECIOCHO ',
    'DIECINUEVE ',
    'VEINTE '    
)                
DECENAS = (      
    'VENTI',     
    'TREINTA ',  
    'CUARENTA ', 
    'CINCUENTA ',
    'SESENTA ',  
    'SETENTA ',  
    'OCHENTA ',  
    'NOVENTA ',  
    'CIEN '      
)                
CENTENAS = (     
    'CIENTO ',   
    'DOSCIENTOS ',
    'TRESCIENTOS ',
    'CUATROCIENTOS ',
    'QUINIENTOS ',  
    'SEISCIENTOS ', 
    'SETECIENTOS ', 
    'OCHOCIENTOS ', 
    'NOVECIENTOS '  
)                   
                    
def Numero_a_Texto(number_in):
                             
    converted = ''                             

    if type(number_in) != 'str':
      number = str(number_in)  
    else:                      
      number = number_in       
                                                          
    number_str=number                                     
                                                          
    try:                                                  
      number_int, number_dec = number_str.split(".")      
    except ValueError:                                    
      number_int = number_str                             
      number_dec = ""                                     

    number_str = number_int.zfill(9)
    millones = number_str[:3]      
    miles = number_str[3:6]        
    cientos = number_str[6:]       

    if(millones):
        if(millones == '001'):
            converted += 'UN MILLON '
        elif(int(millones) > 0):    
            converted += '%sMILLONES ' % __convertNumber(millones)
                                                                 
    if(miles):                                                   
        if(miles == '001'):                                      
            converted += 'MIL '                                  
        elif(int(miles) > 0):                                    
            converted += '%sMIL ' % __convertNumber(miles)       
    if(cientos):                                                 
        if(cientos == '001'):                                    
            converted += 'UN '                                   
        elif(int(cientos) > 0):                                  
            converted += '%s ' % __convertNumber(cientos)        

    if number_dec == "":
      number_dec = "00"
    if (len(number_dec) < 2 ):
      number_dec+='0'        

    converted += 'PESOS '+ number_dec + "/100 M.N."

    return converted
                   
def __convertNumber(n):
    output = ''

    if(n == '100'):
        output = "CIEN "
    elif(n[0] != '0'):
        output = CENTENAS[int(n[0])-1]

    k = int(n[1:])
    if(k <= 20):
        output += UNIDADES[k]
    else:
        if((k > 30) & (n[2] != '0')):
            output += '%sY %s' % (DECENAS[int(n[1])-2], UNIDADES[int(n[2])])
        else:
            output += '%s%s' % (DECENAS[int(n[1])-2], UNIDADES[int(n[2])])

    return output
"""
print Numero_a_Texto(9121234.2)
"""


Una vez que este listo en la factura se debe de utilizar la etiqueta [[obt_texto(o.amount_total)]] en donde se requiera imprimir la cantidad en letras.


Notas:
Se debe reiniciar el servidor para que los cambios tengan efecto.
Python es sensible a los espacios tabuladores.

9 comentarios:

  1. Excelente.
    Voy a montar el cambio para proponer ya este de caja para la siguiente versión estable.
    Desde Venezuela!
    1.000.000 Thank
    UN MILLON DE GRACIAS EXACTAS ;-)

    Nhomar Hernandez

    ResponderEliminar
  2. Hola Rodrigo.

    Hicimos un Blueprint en la localizacon de venezuela:}
    https://blueprints.launchpad.net/openerp-venezuela-localization/+spec/numero-a-letras-spanish

    Luego de hacerlo lo propondremos para que se integre y no tengamos que hacer este cambio a futuro, echale un vistazo si tienes algo que agregar.....

    Saludos

    ResponderEliminar
  3. Hola Nhomar gracias, un pequeño aporte comparado a lo hecho por el equipo que diseñó y mantiene OpenERP

    ResponderEliminar
  4. Hola, soy nuevo en OE pero intento darme maña

    Probe todo tu codigo copiando todos los pasos que se enumeran arriba y cunado quiero iniciar el OE Client me dice que no puede acceder a la base.

    No lo pude solucionar reiniciando el servidor

    Me podrias decir que es lo estoy haciendo mal?

    Espero tu respuesta

    Saludos

    Agustin Allera

    ResponderEliminar
  5. Rodrigo y como seria para la version Opern ERp 6.0.3 en microsoft vista? ayudame Soy ing Industrial

    ResponderEliminar
  6. Buenos días Rodrigo ... sé que han pasados ya varios años desde tu solución. Tengo OpenERP 7 utilizandolo con WebKit en servidor Debian Wheezy. He intentado implementar tu solución pero nada .... me sale un error al imprimir. El obt_texto no lo carga parece ser. Gracias

    ResponderEliminar
  7. Buen día Rodrigo, tengo el mismo inconveniente. Tengo el OpenERP 7 y no puedo hacer correr la solución que planteas.

    ResponderEliminar
  8. Acá lo adapté a mis necesidades (Python3). Le hice algunos cambios, obviamente las funciones aceptan parámetros que mi programa necesita, pero todavía no los programé asique los pueden omitir:

    http://codepaste.net/jc3q5u

    ResponderEliminar
  9. Rodrigo muchas gracias!!!
    10 años despues de su publicación!!! y es la mejor opción que encontré, gracias!!!

    ResponderEliminar