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, 30 de diciembre de 2015

Instalacion de Odoo 8 en CentOS 7


Instalación de Odoo 8 en 
CentOS 7

Instalación de Odoo 8 en un servidor CentOS 7 con GitHub

Instalación y Configuración de PostgreSQL 9.3

Primero que nada debemos instalar y descargar PostgreSQL del repositorio Oficial:
rpm -Uvh http://yum.postgresql.org/9.3/redhat/rhel-7-x86_64/pgdg-centos93-9.3-1.noarch.rpm  
yum -y install postgresql93 postgresql93-server postgresql93-devel --disablerepo=* --enablerepo=pgdg93  
El segundo paso es habilitar el Servidor PostgreSQL como un servicio del Sistema:
/usr/pgsql-9.3/bin/postgresql93-setup initdb
systemctl enable postgresql-9.3.service  
systemctl start postgresql-9.3  
Creamos un usuario postgres para nuestro servidor Odoo:
su - postgres -c "createuser -s odoo" 2> /dev/null || true  

Instalación de dependencias para Odoo

Necesitaremos instalar las herramientas necesarias:
yum -y groupinstall "Development tools"  
Para la instalación de las dependencias ejecutaremos en una terminal:
yum -y install zlib-devel bzip2-devel openssl openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel libpcap-devel xz-devel git libpng libjpeg libXext curl xorg-x11-font-utils fontconfig python-virtualenv libevent-devel libxml2-devel libxslt-devel openldap-devel openjpeg-devel freetype-devel libjpeg-turbo-devel libtiff-devel kernel-devel  
Habilitaremos repositorios como EPEL:
wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm  
rpm -ivh epel-release-7-5.noarch.rpm  
Instalacion de Wkhtmltopdf:
yum --enablerepo=epel install wkhtmltopdf  
Instalación de la aplicación Python Pip, para el manejo de las librerías en Python:
yum --enablerepo=epel install python-pip  

Descarga de Odoo desde Repositorios Oficiales via GitHub

Clonamos el repositorio oficial en la ruta /opt/ :
git clone --branch 8.0 https://www.github.com/odoo/odoo /opt/odoo

Creación de una Virtual Env para Odoo

Un virtual env es un emulador de librerías Python, que nos permitirá manejar librerías Python de forma independiente en una ruta especifica.

Creamos un nuevo usuario del Sistema, y lo asignamos como propietario de nuestro git clone Odoo /opt/directorio_odoo :
useradd odoo  
chown -R odoo: /opt/odoo  
su - odoo  
Ahora instalaremos las dependencias desde nuestro archivo requirements.txt, ubicado en la instalación de Odoo (requirements.txt):
/bin/virtualenv odoo
source odoo/bin/activate  
PATH=$PATH:/usr/pgsql-9.3/bin  
pip install -r /opt/odoo/requirements.txt  
exit  
Esperamos que finalice la descarga de los paquetes a nuestro entorno virtual.

Creacion del Servicio Odoo (Systemctl)

Generamos el archivo odoo-server.conf:
cat > /etc/odoo-server.conf << EOF  
[options]
admin_passwd = admin  
db_host = False  
db_port = False  
db_user = odoo  
db_password = False  
addons_path = /opt/odoo/addons  
without-demo=all  
no-xmlrpc = True  
no-xmlrpcs = True  
no-netrpc = True  
log_db = False  
log_handler = ['[\'["[\\\':INFO\\\']"]\']']  
log_level = info  
logfile = False  
login_message = False  
logrotate = True  
syslog = False  
EOF  

Generamos el archivo odoo.service (systemctl):

cat > /usr/lib/systemd/system/odoo.service << EOF  
[Unit]
Description=Odoo 8.0 ERP and CRM server  
After=postgresql-9.3.service

[Service]
Type=simple  
User=odoo  
Group=odoo  
ExecStart=/home/odoo/odoo/bin/python /opt/odoo/openerp-server --config=/etc/odoo-server.conf

[Install]
WantedBy=multi-user.target  
EOF  
Puedes usar el siguiente comando para visualizar el log de Odoo en tiempo real: journalctl -f -u odoo.

Pasos Finales

Necesitamos permitir el acceso de información del puerto 8069 en el firewall de CentOS:
firewall-cmd --zone=public --add-port=8069/tcp --permanent  
firewall-cmd --reload  
Finalmente iniciamos el Servicio de Odoo con los comandos:
systemctl enable odoo.service  
systemctl start odoo  
Listo, ahora visualizaremos en nuestro navegador: http://<ip_servidor>:8069


jueves, 24 de diciembre de 2015

Solucion Definitiva a errores Encoding UTF-8 en codigo Python

Solución a cualquier error UTF-8 en la Interfaz Odoo


    Muchas veces en la programación Python, podemos tener errores al momento de cargar Etiquetas de Campos en las Vistas Odoo, esto debido al uso de caracteres especiales en la escritura Latina, la solución es muy sencilla en el encabezado de nuestros archivos fuente (Python files), debemos cargar la librería sys y hacer un reload con la encodificación UTF-8.

import sys
reload(sys)  
sys.setdefaultencoding('utf8')

Unir Archivos PDF en uno solo desde Python

Unir Archivos PDF con la librería PyPdf


Esto nos puede servir para retornar un archivo PDF con la unión de varios reportes a la vez.


# Cargamos la libreria
from pyPdf import PdfFileWriter, PdfFileReader

# Creamos una funcion que automatice la union de los archivos pdf
def append_pdf(input,output):
    [output.addPage(input.getPage(page_num)) for page_num in range(input.numPages)]

# Instanciamos la escritura de archivos PDF de la libreria pypdf
output = PdfFileWriter()

# Añadimos los reportes, estos podemos cargarlos desde archivos temporales
append_pdf(PdfFileReader(file("Reporte01.pdf","rb")),output)
append_pdf(PdfFileReader(file("Reporte02.pdf","rb")),output)

# Escribimos la Salida Final del Reporte
output.write(file("UnionFinalPDF.pdf","wb"))

Felices Fiestas!!! 

martes, 15 de diciembre de 2015

Herencia de Acciones en Odoo

Heredar Acciones de Ventana en Odoo



La Herencia de acciones de ventana es similar a heredar Vistas, la estructura es la siguiente:


<record id="module_name.record_id" model="campo">
    <field name="campo">Nuevo Valor del Campo</field>
</record>

martes, 1 de diciembre de 2015

ODOO V8 API: Decorator and Metaclass Part 2

ODOO V8 API: Everything about Decorator and Metaclass

2014-11-15 20:10:10

API

An API(Application Programming Interface) is a set of defined functions and procedures that allow the creation of applications which access the features or data of an operating system, application, or other service. (Source Google)

Metaclass

A metaclass is defined as "the class of a class". Any class whose instances are themselves classes, is a metaclass. (Source wikipedia)

Some Explanations what we can do with metaclass

  • Enforce different inheritance semantics, e.g. automatically call base class methods when a derived class overrides.
  • Implement class methods (e.g. if the first argument is not named 'self') for precondition and post-condition checking.
  • Implement that each instance is initialized with copies of all class variables.
  • Implement a different way to store instance variables (e.g. in a list kept outside the the instance but indexed by the instance's id()).
  • Automatically wrap or trap all or certain methods:
  • Used for tracing
  • Used for precondition and post-condition checking
  • Used for synchronized methods
  • Used for automatic value caching

Metaclass's new and init:

To control the creation and initialization of the class in the metaclass, you can implement the metaclass's new method and/or init constructor. Most real-life metaclasses will probably override just one of them. new should be implemented when you want to control the creation of a new object (class in our case), and init should be implemented when you want to control the initialization of the new object after it has been created.

Features of New API

Api is bridge filling the gap between old "traditional" and new "record" style
In old traditional style , Parameter like database cursor, user id, context dictionary, and record are manually passed in the function in the form of parameters such as (cr, uid, ids, context) Example
model = self.pool.get(MODEL)
ids = model.search(cr, uid, DOMAIN, context=context)
for rec in model.browse(cr, uid, ids, context=context):
print rec.name
model.write(cr, uid, ids, VALUES, context=context)
In new API style those are hidden into model instances, which gives it more pythonic and object-oriented feel. which can be access as (self.cr, self.uid ..)
example above(old style)can be written as:
recs = self.env[MODEL] # retrieve an instance of MODEL
recs = recs.search(DOMAIN) # search returns a recordset
for rec in recs: # iterate over the records
print rec.name
recs.write(VALUES) # update all records in recs
Methods written in the "traditional" style are automatically decorated, following some heuristics based on parameter names.

Meta classes

class Meta(type): It is used to automatically decorates traditional-style methods by guessing their API. It also implements the inheritance of the :func:'returns' decorators.
Metaclass's __new:__ It is used to automatically decorates traditional-style methods by guessing their API.

Decorator's

A decorator is just a callable that takes a function as an argument and returns a replacement function
The Decorator's which is used to decorate the traditional-style method:
@api.cr: Decorate a traditional-style method that takes 'cr' as a parameter. Such a method may be called in both record and traditional styles, like:
@api.cr_context: Decorate a traditional-style method that takes 'cr', 'context' as parameters.
@api.cr_uid: Decorate a traditional-style method that takes 'cr', 'uid' as parameters.
@api.cr_uid_context: Decorate a traditional-style method that takes 'cr', 'uid', 'context' as parameters. Such a method may be called in both record and traditional styles, like:
recs.method(args) model.method(cr, uid, args, context=context)
@api.cr_uid_ids: Decorate a traditional-style method that takes 'cr', 'uid', 'ids' as parameters. Such a method may be called in both record and traditional styles. In the record style, the method automatically loops on records.
@api.cr_uid_id_context: Decorate a traditional-style method that takes 'cr', 'uid', 'id', 'context' as parameters. Such a method:
@api.cr_uid_ids_context: Decorate a traditional-style method that takes 'cr', 'uid', 'ids', 'context' as parameters. Such a method:
The Decorator's which is used to decorate the new record-style method:
@api.model: Decorate a record-style method where 'self' is a recordset, but its contents is not relevant, only the model is. Such a method:
@api.model
def method(self, args):
    ...
may be called in both record and traditional styles, like:
# recs = model.browse(cr, uid, ids, context)
recs.method(args)

model.method(cr, uid, args, context=context)
Notice that no 'ids' are passed to the method in the traditional style.
@api.one: Decorate a record-style method where 'self' is expected to be a singleton instance. The decorated method automatically loops on records, and makes a list with the results. In case the method is decorated with @returns, it concatenates the resulting instances. Such a method:
@api.one
def method(self, args):
    return self.name
may be called in both record and traditional styles, like::
# recs = model.browse(cr, uid, ids, context)
names = recs.method(args)

names = model.method(cr, uid, ids, args, context=context)
Each time 'self' is redefined as current record.
@api.multi: Decorate a record-style method where 'self' is a recordset. The method typically defines an operation on records. Such a method:
@api.multi
def method(self, args):
    ...
may be called in both record and traditional styles, like::
# recs = model.browse(cr, uid, ids, context)
recs.method(args)

model.method(cr, uid, ids, args, context=context)
@api.constrains: Decorates a constraint checker. Each argument must be a field name used in the check:
@api.one
@api.constrains('name', 'description')
def _check_description(self):
    if self.name == self.description:
        raise ValidationError("Fields name and description must be different")
Invoked on the records on which one of the named fields has been modified.
Should raise :class:'~openerp.exceptions.ValidationError' if the validation failed.
@api.onchange: Return a decorator to decorate an onchange method for given fields. Each argument must be a field name:
@api.onchange('partner_id')
def _onchange_partner(self):
    self.message = "Dear %s" % (self.partner_id.name or "")
In the form views where the field appears, the method will be called when one of the given fields is modified. The method is invoked on a pseudo-record that contains the values present in the form. Field assignments on that record are automatically sent back to the client.
@api.depends: Return a decorator that specifies the field dependencies of a "compute" method (for new-style function fields). Each argument must be a string that consists in a dot-separated sequence of field names:
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
One may also pass a single function as argument. In that case, the dependencies are given by calling the function with the field's model.
@api.returns: Return a decorator for methods that return instances of 'model'.
:param model: a model name, or 'self' for the current model

:param downgrade: a function 'downgrade(value)' to convert the
    record-style 'value' to a traditional-style output
The decorator adapts the method output to the api style: 'id', 'ids' or 'False' for the traditional style, and recordset for the record style:
@model
@returns('res.partner')
def find_partner(self, arg):
    ...     # return some record

# output depends on call style: traditional vs record style
partner_id = model.find_partner(cr, uid, arg, context=context)

# recs = model.browse(cr, uid, ids, context)
partner_record = recs.find_partner(arg)
Note that the decorated method must satisfy that convention.
Those decorators are automatically inherited: a method that overrides a decorated existing method will be decorated with the same '@returns(model)'.
The Decorator's which is used to decorate a method that supports the old-style API only:
  1. @api.v7:
Decorate a method that supports the old-style api only. A new-style api may be provided by redefining a method with the same name and decorated with :func:'~.v8':
@api.v7
def foo(self, cr, uid, ids, context=None):
    ...

@api.v8
def foo(self):
    ...
Note that the wrapper method uses the docstring of the first method.
The Decorator's which is used to decorate a method that supports the new-style API only:
  1. @api.v8:
Decorate a method that supports the new-style api only. An old-style api may be provided by redefining a method with the same name and decorated with :func:'~.v7':
@api.v8
def foo(self):
    ...

@api.v7
def foo(self, cr, uid, ids, context=None):
    ...
Note that the wrapper method uses the docstring of the first method.