Programacion Interactiva

Descubre una Nueva y Poderosa Herramienta.

FrameWork de Nueva Generacion

Acceso a tu Informacion desde cualquier Dispositivo con Navegador.

Enfoque en el Backend

Frontend de forma facil con Odoo y XML.

Creacion de Verticales

Creacion de nuevas Verticales Conquistando nuevos Mercados.

Tu marca aqui mismo

Llega a miles de personas.

Publicidad

Mostrando las entradas con la etiqueta development. Mostrar todas las entradas
Mostrando las entradas con la etiqueta development. Mostrar todas las entradas

viernes, 10 de junio de 2016

Generación de Codigos de Barra PDF417 con Python y la libreria Elaphe

Códigos de Barra PDF 417 con Elaphe y Odoo



Instalamos la libreia elaphe la cual sera nuestra herramienta principal en este ejercicio:

sudo apt-get install python-elaphe

Si utilizamos el gestor de librerias Pip:

sudo pip install elaphe

Como cualquier otra libreria necesitamos importarla en nuestro codigo:
>>> from elaphe import barcode

Un ejemplo completo utilizando elaphe y codigo de barras pdf 417:

from elaphe import barcode
bc = barcode('pdf417', "Bienvenidos a poncesoft.blogspot.com", options=dict(eclevel=2, compact=True, columns=2, rows=10), margin=1, scale=2)
bc.save('test.png')

El primer parĆ”metro de la función barcode es el tipo de código de barras a generar, el segundo es la cadena que convertiremos a  imagen utilizando código de barras

Otros códigos de barra que podemos implementar con la librerĆ­a elaphe son:

from elaphe import barcode
barcode('qrcode', 'Hello Barcode Writer In Pure PostScript.', options=dict(version=9, eclevel='M'), margin=10, data_mode='8bits').show()
barcode('code128', '^104^102Count^0990123456789^101!', options=dict(includetext=True), scale=2, margin=1).show()
barcode('pdf417', '^453^178^121^239', options=dict(columns=2, rows=10), margin=1, scale=2).show()
barcode('upc', '78858101497', options=dict(includetext=True), scale=2, margin=1).show()
barcode('royalmail', 'LE28HS9Z', options=dict(includetext=False), scale=2, margin=1).show()
barcode('datamatrix', '^142^164^186', options=dict(columns=32, rows=32), margin=1, scale=2.0).show()
barcode('code11', '0123456789', options=dict(includetext=True), scale=2, margin=1).show()
barcode('code25', '0123456789', options=dict(includetext=False, includecheck=False), scale=2, margin=1).show()
barcode('code39', 'THIS IS CODE39', options=dict(includetext=True), scale=2, margin=1).show()
barcode('code93', 'THIS IS CODE93', options=dict(includetext=True), scale=2, margin=1).show()
barcode('japanpost', '1231FZ13XHS', options=dict(includetext=False), scale=2, margin=1).show()
barcode('azteccode', '00100111001000000101001101111000010100111100101000000110', margin=1).show()
barcode('auspost', '5956439111ABA 9', options=dict(includetext=False), scale=2, margin=1).show()
barcode('ean13', '977147396801', options=dict(includetext=True), scale=2, margin=1).show()
barcode('interleaved2of5', '24012345678905', options=dict(includetext=True), scale=2, margin=1).show()
barcode('raw', '331132131313411122131311333213114131131221323', options=dict(includetext=True), scale=2, margin=1).show()
barcode('kix', '1231FZ13XHS', options=dict(includetext=False), scale=2, margin=1).show()
barcode('postnet', '012345', options=dict(includetext=True), scale=2, margin=1).show()
barcode('pharmacode', '117480', options=dict(includetext=True), scale=2, margin=1).show()
barcode('plessey', '012345ABCD', options=dict(includetext=True), scale=2, margin=1).show()
barcode('symbol', 'fimd', options=dict(includetext=True), scale=2, margin=1).show()
barcode('onecode', '0123456709498765432101234567891', options=dict(includetext=True), scale=2, margin=1).show()
barcode('maxicode', '^059^042^041^059^040^03001^02996152382802^029840^029001^0291Z00004951^029UPSN^02906X610^029159^0291234567^0291^0471^029^029Y^029634 ALPHA DR^029PITTSBURGH^029PA^030^062^004^063', options=dict(mode=2), margin=1, scale=4).show()
barcode('msi', '0123456789', options=dict(includetext=True), scale=2, margin=1).show()
barcode('rss14', '24012345678905', options=dict(linkage=True, includetext=True), scale=2, margin=1).show()
barcode('rationalizedCodabar', 'A012345

Implementación con Odoo

Para nuestros módulos bÔsicamente es lo mismo, pero nos apoyaremos de otras librerias que nos ayudaran a generar archivos en la partición temporal del sistema, primero importamos:

from elaphe import barcode
import os
import base64
import hashlib
import tempfile

Un ejemplo es el siguiente:
# Instanciamos el metodo principal barcode
bc = barcode('pdf417', "Bienvenidos a poncesoft.blogspot.com", options=dict(eclevel=2, compact=False, columns=2, rows=10), margin=1, scale=2)
# Generamos un nombre y ruta temporal
fname=tempfile.NamedTemporaryFile(suffix='.png',delete=False)
# Asigamos el nombre temporal a una variable
temporal_name = fname.name
# Guardamos nuestra imagen generada con elaphe y la ruta temporal
bc.save(fname.name)
# Podemos manipular la imagen ya generada
f = open(fname.name, "r")
data = f.read()
f.close()

jueves, 7 de mayo de 2015

API ODOO: Metaclases y Decodarores

Implementación de la API de Odoo Utilizando Metaclases y Decoradores



API:

    API por sus siglas en Ingles Application Programming Interface ( Interfaz de Programación de Aplicaciones), es el conjunto de subrutinas, funciones y procedimientos (o mĆ©todos, en la programación orientada a objetos) que ofrece cierta biblioteca para ser utilizado por otro software como una capa de abstracción. Son usadas generalmente en las bibliotecas. Fuente: wikipedia.org

Metaclases:

    A metaclase puede definirse como   "Una clase de Clases". En programación orientada a objetos, una metaclase es una clase cuyas instancias son clases. En otras palabras, como los objetos son instancias de una clase, las clases son instancias de una metaclase.

Detalles para Implementar la API en sus Desarrollos:

 Odoo provee 2 formas de Implementar las Clases (Modelos), para la generación de Formularios, podrĆ­amos llamarlas como la forma "Tradicional" y a travĆ©s de "Recordsets". Un recordset es la instancia de una clase, con la referencia del registro en Base de Datos (ID).

    En la forma tradicional utilizamos siempre los parĆ”metros cursor de la base de datos (cr), id usuario (uid), un listado de los Registros (ids) y context, cada vez que definimos un MĆ©todo de la Clase. Utilizando el mĆ©todo por Recordsets mediante Decoradores, estos parĆ”metros estĆ”n ImplĆ­citos dentro de la API, aquĆ­ debemos comprender que si se trabaja con la API de Odoo, todo lo que sea retornado mediante los mĆ©todos del ORM siempre serĆ”n records.

Ejemplo con el Metodo Tradicional:

    modelo = self.pool.get(Modelo.) # Instanciamos una Clase (Modelo)
    ids = modelo.search(cr, uid, [Dominio con Condiciones para la Busqueda], context=context) 
    # Una funcion search con la forma Tradicional siempre Rertorna una lista de IDS
    for rec in modelo.browse(cr, uid, ids, context=context):
        print rec.name
    modelo.write(cr, uid, ids, {Diccionario de Valores a Actualizar}, context=context)

Ejemplo Utilizando la API de Odoo:

    env = env(cr, uid, context)         # cr, uid, context, implicitos en la instancia env
    recs = env[Modelo]                    # Instanciamos una Clase(Modelo) de Odoo
    recs = recs.search([Dominio con Condiciones para la Busqueda de Registros])          
   #  Una busqueda utilizando env y la API, siempre retornada una lista de Recordsets.
    for rec in recs:                             # Podemos recorrer cada record para poder trabajar con ellos.
        print rec.name
    recs.write({Diccionario de Valores a Actualizar})

Como pudimos observar, los parƔmetros tradicionales (cr, uid, ids, context) estƔn Implƭcitos al trabajar con la API de Odoo, algo que puede confundirnos es al momento de trabajar con Ambas.

Decoradores:

Los decoradores en Odoo, son utilizados para tratar de enviar los argumentos que el Sistema sabe que tiene que recibir de forma Obligatoria como el Ejemplo Anterior (cr, uid, ids, context).

Los Decoradores con la API Odoo, nos ayudan a Decorar las funciones tradicionales y a Implementar una nueva Funcionalidad.

Ejemplos:
    
1. @api.cr:

Para decorar funciones que siempre Reciben Como Parametro CR, utilizariamos este Decorador.

    # recs = modelo.browse(cr, uid, ids, context)
    recs.method(args)
    model.method(cr, args)

2. @api.cr_context:

Decoramos Funciones que utilizan siempre 'cr', 'context' como Parametros.
  
3. @api.cr_uid:

Decoramos Funciones que utilizan siempre 'cr', 'uid' como Parametros.

4. @api.cr_uid_context:

Decoramos Funciones que utilizan siempre 'cr', 'uid', 'context' como Parametros. 

    # recs = modelo.browse(cr, uid, ids, context)
    recs.method(args)

    modelo.metodo(cr, uid, args, context=context)

5. @api.cr_uid_id:

Decoramos Funciones que utilizan siempre 'cr', 'uid', 'ids' como Parametros. Podriamos utilizar un Decorador de este tipo para retornar siempre un Recordset sin tener que generar la instancia y pasar los Parametros.


6. @api.cr_uid_id:

Este Ejemplo seria el mas claro si estamos acostumbrados a definir funciones con OpenERP, en donde siempre eran requeridos los parametros 'cr', 'uid', 'id':

    @api.cr_uid_id
    def metodo(self, cr, uid, id, args, context=None):
        ...

7. @api.cr_uid_ids:

Este Decorador seria el mismo que el anterior solo que aquƭ se enviarƭa el parƔmetro IDS con un listado de Registros, en el anterior solo podrƭamos enviar un solo ID.

8. @api.cr_uid_ids_context:

Este Decorador como su nombre lo describe, recibe todos los parametros para poder generar Funciones. Recibe 'cr', 'uid', 'ids', 'context', parametros que siempre necesitamos para trabajar con Odoo.

Decoradores que utiliza la API de Odoo

1. @api.model:

Este Decorador solo genera una Instancia de una Clase en Odoo (Modelo). Su sintaxis es la siguiente:

    @api.model
    def metodo(self, args):
        ...



2. @api.one:

Este decorador sirve para poder obtener un recordset de la Clase, siempre que sea utilizado en un Metodo. Es equivalente a realizar un browse de una Clase de Odoo (self.browse(cr, uid, id, context=None) ), con este decorador podriamos obtener un valor de esa Clase simplemente con retornar self.campo_a_obtener. Su sintaxis es la siguiente:

    @api.one
    def metodo(self, args):
        return self.name

Con el MƩtodo Tradicional Seria:

    def metodo(self, cr, uid, id, context=None):
        inst = self.browse(cr, uid, id, context=None)
        return inst.name

3. @api.multi:

Este Decorador es similar al anterior, solo que aquĆ­ retorna un listado de recordsets. Su sintaxis es la siguiente:

    @api.multi
    def method(self, args):
        ...
       

En la forma tradicional seria definir un ciclo con el metodo Browse:
    
    def metodo(self, cr, uid, ids, context=None):
        for rec in self.browse(cr, uid, ids, context=None)
             print "#### Campo Name de cada Registro >>> ", rec.name
        return True

En la forma tradicional solƭamos obtener los ids a recorrer usando el mƩtodo Search.

4. @api.constrains:

Como podemos observar por su nombre, este decorador nos permite decorar funciones para crear Restricciones a la Inserción de Información, los llamados Constraints. Su sintaxis es la siguiente:

    @api.one
    @api.constrains('name', 'description')
    def _check_description(self):
        if self.name == self.description:
            raise ValidationError("Los Campos Nombre y Descripción no pueden ser los Mismos")

Para que quede claro, un ejemplo con la Forma tradicional:

    def _check_description(self, cr, uid, ids, context=None):
        for rec in self.browse(cr, uid, ids, context=None):
            if rec.name == rec.description:
                 return False
         return True

_constraints = [(_check_description, 'Error: Los Campos Nombre y Descripcion No pueden ser Iguales', ['name','description']), ] 

5. @api.onchange:

    Si has llegado a este Decorador ya tienes la idea de lo que ah tratado de hacer Odoo, que es tratar de Optimizar el Código enfocĆ”ndonos directamente en la lógica del requerimiento, sin tener que ser recurrentes con los parĆ”metros, este Decorador nos sirve para poder crear mĆ©todos on_change (MĆ©todos que se ejecutar al cambiar un Valor del Formulario en donde este asignado este Metodo).
Su sintaxis es la siguiente:

    @api.onchange('partner_id')
    def _onchange_partner(self):
        recs = env['res.partner']                    
        recs = recs.search([('parent_id','=',self.partner_id)]) 

        self.partner_id = recs[0].id

Observamos que ahora ya no es necesario retornar Valores en un diccionario del tipo {'value':{Campos a Actualizar}. Observamos que el Decorador recibe parĆ”metros, que en este caso son los campos que necesitamos para poder trabajar como es  'partner_id'.

Ejemplo con la forma Tradicional:
    def _onchange_partner(self, cr, uid, ids, partner_id, context=None):
          partner_id = self.pool.get('res.partner').search(cr, uid, [('parent_id','=',partner_id)], context)
          if partner_id:
               return {'value':{'partner_id': partner_id[0]}}
          return {}

     

6. @api.depends:

Este Decorador es utilizado para campos Calculados, o campos que requieran obtener un listado de valores:

    pname = fields.Char(compute='_compute_pname')

    @api.one
    @api.depends('partner_id.name', 'partner_id.is_company')
    def _compute_pname(self):
        if self.partner_id.is_company:
            self.pname = (self.partner_id.name or "").upper()
        else:
            self.pname = self.partner_id.name

7.@api.returns:

Decorador que permite retornar instancias de un Modelo. Sus sintaxis es:

    @model
    @returns('res.partner') # Modelo a Recibir
    def find_partner(self, arg):
        ...     # retorna algun recordset


Decoradores para Interactuar con los Nuevos estilos utilizando una version Tradicional.

1. @api.v7:

Este Decorador permite utilizar metodos de la Nueva API, generando Clases (Modelos) de la forma Tradicional. Su sintaxis es:

    @api.v7
    def foo(self, cr, uid, ids, context=None):
        ...

    @api.v8
    def foo(self):
        ...


Decoradores para Interactuar con el estilo Tradicional utilizando una version con la nueva API.

1. @api.v8:

    @api.v8
    def foo(self):
        ...

    @api.v7
    def foo(self, cr, uid, ids, context=None):
        ...

Espero que les pueda ayudar a comprender la nueva API, aun me faltan muchas cosas por Comprender que estarƩ subiendo.


jueves, 10 de abril de 2014

Integracion de Codigos QR con Odoo (OpenERP)

Generar Codigos QR para campos Binary en Odoo (OpenERP)



Para la generación de Códigos QR para OpenERP les enseñare a utilizar 2 Librerias:


Utilizando Python qrtools:


Lo primero que de debemos hacer es instalar la libreria qrtools, para instalarlo debemos descargar el paquete del link oficial:


Lo instalamos como cualquier paquete python con el comando :

sudo python setup.py install

Una vez instalado lo importamos en nuestros archivos .py con la linea siguiente:

from qrtools import QR

Ahora debemos agregar un Campo de Tipo binario por ejemplo:

'cfdi_cbb': fields.binary("CFD-I CBB")


Este campo es un código CBB propio de la facturación electrónica, ahora debemos ingresar la cadena para generar ese codigo CBB:

       qr_string = "La cadena para mi codigo QR" ## Cadena de Texto
       qr_code = QR(data=qr_string.encode('utf-8')) ## Encodeamos a utf8 mi Cadena
       qr_file = open(qr_code.filename, "rb") ## Escribimos la Imagen
       temp_bytes = qr_file.read() ## Leemos la Imagen
       qr_bytes = base64.encodestring(temp_bytes) ## Convertimos la Imagen para Escribirla en Base
       qr_file.close() ## Cerramos la lectura del archivo con la imagen QR

       Lo ultimo es escribir la imagen en el modelo account.invoice:

       account_obj = self.pool.get('account.invoice')
        account_obj.write(cr,uid,[ids_del_registro],{'cfdi_cbb':qr_bytes})




viernes, 24 de enero de 2014

Redes Sociales en nuestros Modelos en OpenERP 7.0 y Odoo (OpenERP 8.0)

Agregar Redes Sociales en OpenERP 7.0 y Odoo (OpenERP 8.0)



    Desde la Versión 7.0 de OpenERP podemos observar en el pie de cualquier formulario la parte de Redes Sociales que de alguna manera de da un Plus a cualquier modelo de datos, para que podamos tener esa aplicación al momento de crear nuestros módulos en OpenERP tendrĆ­amos que agregar en nuestras clases el código siguiente:

1.- En la declaracion de nuestra Clase OSV tendriamos que agregar la linea:

    _inherit = ['mail.thread', 'ir.needaction_mixin'] ### Redes Sociales
  

lunes, 20 de enero de 2014

HERENCIA DE VISTAS Odoo (OPENERP)

HERENCIA DE VISTAS.

Igual que podemos heredar objetos, tambiƩn podemos heredar vistas de la siguiente manera:
<?xml version="1.0" encoding="UTF­8"?>
<openerp>
   <data>
<!­­--

id='res_partner_xxxxx_form_view_inh'
 
Este es el nuevo identificador que identifica a la vista que estamos  definiendo. Tener en cuenta que termina en 'form_view_inh', esto lo hacemos por norma, para identificar que esta vista, es una vista que
hereda De otra.
'name': Mismo nombre que el ID pero separado por '.'
'res.partner': Objeto al que pertenece la vista de la cuĆ”l estamos  heredando.
'inherid_id': AquĆ­ le indicamos el ID de la vista que estamos heredando. La '<carpetapadre> es la primera carpeta que se encuentra  en ADDONS, en la cuĆ”l se encuentra el fichero xml, en el que estĆ”
definida la vista.
-->

<record model="ir.ui.view" id="res_partner_form_view_inh">
      <field name="name">res.partner.form.view.inh</field>
      <field name="model">res.partner</field>
      <field name="type">form</field>
      <field name="inherit_id" ref="carpetapadre.idVistaPadre" />
      <field name="arch" type="xml">
 
         <field name="campoareemplazar" position="after">
 
                  <field name="nuevocampo" />
         </field>
         <notebook position="inside">
               <page string="Literal para la nueva pestaƱa">
                  <group col="2" colspan="2">
                        <separator string="Literal del separador" colspan="2"/>
                        <field name="nuevocampo2"/>
                        <field name="nuevocampo3" nolabel="1"/>
                  </group>
               </page>
         </notebook>
   </field>
   </record>
   </data>
</openerp>

RELACIONES ENTRE OBJETOS.

MANEJO DE CAMPOS RELACIONALES EN Odoo (OPENERP)


one2many (de uno a muchos).

Una relación de uno a muchos sería por ejemplo la relación entre autores y libros. Un autor puede tener escritos varios libros, y varios libros pueden pertenecer a un autor. La relación sería de 1 a N.

Ejemplo de definición de la clase autor:

class mybookstore_author(osv.osv):
   _name ='mybookstore.author'
   _description ='Autores'
   _columns= {
      'name': fields.char('Name', size=64, required="True"),
      'active': fields.boolean('Active'),
      'book_ids': fields.one2many('mybookstore.book', 'author_id', 'Books'),
   }

mybookstore_author()