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

miƩrcoles, 27 de mayo de 2015

Estructura de las Agrupaciones en Vistas Formulario

Col y Colspan


    En Odoo la forma de estructurar y mostrar los Campos para las Vistas Formulario, con un orden especifico y agrupado por ciertos datos, es realizado mediante los atributos col y colspan, bĆ”sicamente una Vista Formulario esta divida en 4 Secciones, 2 Para los textos de los campos y los otros 2 para sus Valores.

    Por defecto Odoo utiliza una columna para el Texto y 3 para el Valor del Campo, lo que se conoce como colspan="4", si necesitas utilizar una agrupación de 2 campos por linea, utilizamos col="4".

Columnas de un Formulario:

Codigo:
<form>
┌───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │
└───┴───┴───┴───┘
</form>
Ejemplo de un Grupo col="4", en donde toma 2 columnas para texto y 2 para los Valores.
Codigo:
<group col="4">
    <field name="input" />
    <field name="inpt2" />

</group>
┌───────┬───────┬───────┬───────┐
│ label │ input │ labl2 │ inpt2 │
└───────┴───────┴───────┴───────┘

Ejemplos de Agrupaciones Colspan:
Codigo:
<group>
    <field name="inpt4"/>
</group>

<group col="4">
  <field name="input" />
  <field name="inpt2" />
</group>
┌───────┬───────────────────────┐
│ labl4 │ inpt4_______________  │
├───────┼───────┬───────┬───────┤
│ label │ input │ labl2 │ inpt2 │
└───────┴───────┴───────┴───────┘

<group colspan="1">
   <field name="input" />
</group>
<group colspan="4">
   <field name="inpt4"/>
</group>
<group col="1">
   <field name="inpt2" />
</group>
┌───────┬───────┬───────┬───────┐
│ label │ input │       │       │
├───────┼───────┴───────┴───────┤
│ labl4 │ inpt4_______________  │
├───────┼───────┬───────┬───────┤
│ labl2 │ inpt2 │       │       │
└───────┴───────┴───────┴───────┘

Puedes crear Subgrupos de Campos como en el siguiente Ejemplo:
Codigo:
<group col="2" colspan="2">
   <field name="a" />
   <field name="b" />
</group>
<group col="6" colspan="2">
   <field name="d" />
   <field name="e" />
   <field name="f" />
</group>

 ─

│       │       │                │                │
├───────┴───────┼────────────────┴────────────────┤
│ ┌────┬───┐    │  ┌────┬───┬────┬───┬────┬───┐   │
│ │ lb │ a │    │  │ lb │ d │ lb │ e │ lb │ f │   │
│ ├────┼───┤    │  └────┴───┴────┴───┴────┴───┘   │
│ │ lb │ b │    │                                 │
│ └────┴───┘    │                                 │
├───────┬───────┼────────────────┬────────────────┤
│       │       │                │                │

 ─
Gracias por su Visita!

Corregir el Error de la Zona Horario en Odoo (OpenERP)


Corregir el Error de la Zona Horario en Formularios Odoo (OpenERP




    Muchos Tenemos Errores al momento de generar, Facturas, Pedidos de Venta, Compras, etc..., debido a que Odoo maneja el horario EstĆ”ndar y aunque se configura la Zona Horaria Correcta para cada usuario, esta no se ve reflejada.

Si tu no encuentras Solución Para este Error, aquí te presento la Solución:

Primero Tenemos que tener Instaladas las librerias:

  • datetime
  • pytz
  • time

Ahora en Odoo importamos estas librerias:
from datetime import date, datetime, timedelta
import time
import pytz

Ahora un ejemplo, primero tomare la fecha actual que me ofrece odoo y la transformare a la Zona Horaria del Usuario Logeado:
date_now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
start = datetime.strptime(date_now, "%Y-%m-%d %H:%M:%S")
user = self.pool.get('res.users').browse(cr, uid, uid)
tz = pytz.timezone(user.tz) if user.tz else pytz.utc
start = pytz.utc.localize(start).astimezone(tz)     
tz_date = start.strftime("%Y-%m-%d %H:%M:%S")
### tz_date es la fecha correcta con la zona hroaria
print "########################## DATE FINAL TZ >>> ", tz_date

Si necesitƔramos corregir la fecha y hora de un registro bastaria con hacerlo de la siguiente forma:

for rec in self.browse(cr, uid, ids, context):
    field_date = rec.date ## Campo Fecha del Formulario
    start = datetime.strptime(field_date, "%Y-%m-%d %H:%M:%S")
    user = self.pool.get('res.users').browse(cr, uid, uid)
    tz = pytz.timezone(user.tz) if user.tz else pytz.utc
    start = pytz.utc.localize(start).astimezone(tz)     
    tz_date = start.strftime("%Y-%m-%d %H:%M:%S")
    ### tz_date es la fecha correcta con la zona hroaria
    print "########################## DATE FINAL TZ >>> ", tz_date

Como vimos en el ejemplo anterior, primero obtenemos el valor de campo fecha/fecha_hora, despuƩs solo hacemos unas conversiones para pasarlo a la librerƭa pytz.


Espero que les sea de ayuda.



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.


miƩrcoles, 29 de abril de 2015

Contabilidad electrónica OpenERP 7

      

Contabilidad Electronica para Odoo (OpenERP 7)


    Ante la nueva obligación de llevar y presentar la contabilidad electrónica surgida desde 2014, surgen muchas dudas y preocupaciones para la Comunidad Empresarial (PYMES), que utiliza OpenERP (Odoo) como su Sistema de Gestión y Administración, ahora vengo hablarles de un Modulo de Contabilidad Electronica muy Funcional y que cumple hasta el momento con los lineamientos principales requeridos por el SAT, el modulo fue desarrollado por el Ing. LĆ”zaro RodriguĆ©z Triana, por el momento no se tiene Liberado para la Comunidad pero se pretende Liberarlo en unos meses, en cuanto se haya recuperado el monto de la Investigación y el desarrollo, pero por una pequeƱa cuota de recuperación puedes Obtener el Modulo Funcionando en tu Empresa en el momento que tu decidas, una de las Ventajas es que obtienes el Código Fuente del Modulo para poder estudiarlo y mejorarlo.

Les Hablare sobre la funcionalidad:


Para poder cumplir con estas nuevas obligaciones en  OpenERP existe el módulo econtabilidad, el cual contiene las siguientes caracterĆ­sticas:





A continuación algunas capturas del módulo que se ha adaptado para OpenERP 7:


CatƔlogos de:

Bancos:



Monedas:


Código agrupador:



El cual generÔ archivos .xml para catÔlogo de cuentas, balanza de comprobación y pólizas.

ImÔgenes de validación

CatƔlogo de Cuentas
Balanza Mensual


Pólizas

MĆ”s información en el anexo 24.

Pueden ponerse en Contacto conmigo para Mayor Información.



lunes, 6 de abril de 2015

Separar Archivos Adjuntos de la Base de Datos

Creación de Directorio para los Archivos Binarios


    Como ya sabemos OpenERP (Odoo) tiene la capacidad de poder adjuntar una gran cantidad de archivos en cada registro, llamados archivos adjuntos, en MĆ©xico comĆŗnmente lo utilizamos para la Facturación Electrónica y tener el control de los archivos XML y PDF en cada registro. 
    Por defecto el Sistema los almacena en la Base de datos en un proceso de conversión conocido como "Encoding", el cual tiene ventajas y desventajas.

Ventajas:
  • Los Respaldos de Base de Datos, incluyen los archivos adjuntos.
  • Mayor control sobre los documentos.

Desventajas:
    • La Base de datos incrementa su tamaƱo de forma considerable.
    • El proceso de Encoding puede tener errores con caracteres especiales.
    Una ventaja que tenemos con OpenERP (Odoo), es que por medio de parĆ”metros podemos separar los archivos Binarios de la Base de Datos, para ello vamos a Configuración --> ParĆ”metros --> ParĆ”metros del Sistema.

    Creamos un nuevo  registro con los siguientes valores:


    Ahora donde vemos estos archivos, para ello en el servidor buscamos la instalación del Sistema, en mi caso /opt/openerp/70-TMS-FLETES/server/openerp/filestore.

        La carpeta filestore es el valor del parĆ”metro anterior, dentro tendremos el nombre de la Base de Datos y al final cada documento adjunto, podrĆ­amos cambiar filestore por documentos o un nombre x.
    Dentro de la carpeta con el nombre de nuestra base de Datos, cada ves que se adjunten documentos en un registro del OpenERP, el sistema creara una subcarpeta y esta lo ligara al mismo, sin pasar por el proceso de "Encoding".