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.

Asesoria Especializada

Consultoria desde $15 USD por Hora.

Publicidad

viernes, 2 de diciembre de 2016

Retornar un reporte mediante una función Python en Odoo

Retornar un reporte mediante un botón en Odoo


    
La ejecución y el manejo de los reportes mediante funciones en odoo, se hace de la siguiente manera:

# -*- coding: utf-8 -*-
def print_report(self):
    return self.env['report'].get_action(self, 'modulo.nombre_tecnico_reporte')

La parte importante en este boton es invocar el reporte correcto, primero el nombre del modulo seguido de un punto y por ultimo el nombre tecnico del reporte.

Otra parte importante es que self contiene los ids de los registros que tenemos que imprimir, entonces si queremos imprimir varios registros al mismo tiempo bastaría con tener una instancia de ellos.



Invocando Acciones en los Flujos de Odoo

Ejecutar una Transición de Estado con la API Odoo



    Para todos los que venimos de la programación con el Framework de OpenERP hacia la API de Odoo, observamos que todo es mas sencillo, se eliminaron pasos, parámetros, etc., bueno  esto cambio también en la invocación de flujos (workflow), ahora ejecutar la transición de un estado a otro en las clases que utilizan aún estos se realiza de la siguiente manera:

# -*- coding: utf-8 -*-

invoice_obj = self.env['account.invoice'].sudo()

invoice_br = invoice_obj.browse([id_factura])

invoice_br.signal_workflow('invoice_open')

La parte clave para ejecutar la transicion es el método signal_workflow propio de las clase principal models.Model de la API.

Anteriormente utilizábamos la herramienta netsvc de Odoo, la cual fue eliminada a partir de la versión Odoo 8.0


jueves, 1 de diciembre de 2016

Herencia de Clases Web en Odoo

Heredar Clases Web en Odoo (http.Controller)



    Un tema muy importante que ha empezado a tomar importancia en Odoo es el desarrollo y las modificaciones del E-commerce desafortunadamente no tenemos mucha información así que estaré subiendo temas y mis propias investigaciones:

Lo primero con lo que quiero empezar es como hacer herencia de una clase web, esto se realiza de una forma muy sencilla:

  1. Debemos importar la clase a la cual vamos a heredar por ejemplo si queremos heredar la clase website_sale lo haríamos de la siguiente manera:

    from openerp.addons.website_sale.controllers.main import website_sale
    

    Observamos que básicamente hacemos un recorrido de toda la ruta de archivos hasta llegar al que contiene la clase a heredar.

  2. Segundo creamos la clase y la heredamos:

  3. class website_sale_extension(website_sale):
    
    
  4. Con esto podremos hacer uso de los metodos propios de website_sale, podremos extenderlos o reemplazarlos.
Un ejemplo seria el siguiente, en donde arregle un Bug que tenia Odoo al momento de procesar un pago:

# -*- coding: utf-8 -*-
from openerp import http
from openerp import SUPERUSER_ID
from openerp.api import Environment
from openerp.addons.web.http import request

import logging
import werkzeug

from openerp import http
from openerp import tools
from openerp.tools.translate import _
from openerp.addons.website.models.website import slug
from openerp.addons.website_sale.controllers.main import website_sale

PPG = 20 # Products Per Page
PPR = 4  # Products Per Row

class website_sale_portal_invoice(website_sale):
    def checkout_form_save(self, checkout):
        cr, uid, context, registry = request.cr, request.uid, request.context, request.registry

        order = request.website.sale_get_order(force_create=1, context=context)

        orm_partner = registry.get('res.partner')
        orm_user = registry.get('res.users')
        order_obj = request.registry.get('sale.order')

        partner_lang = request.lang if request.lang in [lang.code for lang in request.website.language_ids] else None

        billing_info = {'customer': True}
        if partner_lang:
            billing_info['lang'] = partner_lang
        billing_info.update(self.checkout_parse('billing', checkout, True))

        # set partner_id
        partner_id = None
        if request.uid != request.website.user_id.id:
            partner_id = orm_user.browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
        elif order.partner_id:
            user_ids = request.registry['res.users'].search(cr, SUPERUSER_ID,
                [("partner_id", "=", order.partner_id.id)], context=dict(context or {}, active_test=False))
            if not user_ids or request.website.user_id.id not in user_ids:
                partner_id = order.partner_id.id

        # save partner informations
        if partner_id and request.website.partner_id.id != partner_id:
            orm_partner.write(cr, SUPERUSER_ID, [partner_id], billing_info, context=context)
        else:
            # create partner
            billing_info['team_id'] = request.website.salesteam_id.id
            partner_id = orm_partner.create(cr, SUPERUSER_ID, billing_info, context=context)
        order.write({'partner_id': partner_id})
        ### Correccion ###
        order.onchange_partner_id()
        ### Error ###
        # order_obj.onchange_partner_id(cr, SUPERUSER_ID, [order.id], context=context)
        order.write({'partner_invoice_id': partner_id})

        # create a new shipping partner
        if checkout.get('shipping_id') == -1:
            shipping_info = self._get_shipping_info(checkout)
            if partner_lang:
                shipping_info['lang'] = partner_lang
            shipping_info['parent_id'] = partner_id
            checkout['shipping_id'] = orm_partner.create(cr, SUPERUSER_ID, shipping_info, context)
        if checkout.get('shipping_id'):
            order.write({'partner_shipping_id': checkout['shipping_id']})

        order_info = {
            'message_partner_ids': [(4, partner_id), (3, request.website.partner_id.id)],
        }
        order_obj.write(cr, SUPERUSER_ID, [order.id], order_info, context=context)

Los puntos a resaltar en el código son los comentarios correccion y error con mi solución.

lunes, 28 de noviembre de 2016

Seleccionar Vista a mostrar en Campos Relacion (Many2One)

Mostrar una Vista especifica en campos relacionales Many2One



     Odoo siempre sorprende en lo flexible y poderoso que puede llegar a ser al momento de desarrollar aplicaciones, en este post mostrare como poder seleccionar una vista especifica para los campos many2one, esto ayuda para tener una segmentación sobre lo que queremos que el usuario vea en la sección principal (menús) y la información que queremos que vea en los campos relación.

<field name="my_field_id" context="{'form_view_ref':'my_module.my_xml_view_id'}"/>

La parte importante es identificar que solo debemos modificar el apartado my_module por el nombre de nuestro modulo que contiene la vista a seleccionar y seguido de un punto y el ID de la vista, esto seria suficiente para poder mostrarle al usuario una vista distinta en los campos many2one.


miércoles, 19 de octubre de 2016

Override de Funciones Javascript en Odoo

Método para Sobrescribir Funciones Javascript en Odoo



Trabajando en algunas modificaciones de apuntes contables me di cuenta que tenemos un filtro "escondido" en las fuentes de javascript la cual limitaba los registros para no mostrar partidas cuyo crédito y débito es 0.0, de alguna forma esto es correcto, pero para algunas personas es importante tener el desglose total de las partidas sin importar los montos, bueno para ello tenia que adentrarme en el archivo llamado account_move_line_quickadd.js y el método search_by_journal_period, para sobrescribir debemos hacer lo siguiente:

  1. Nuestro archivo __openerp__.py debe importar los archivos con codigo Javascript.
        'js': ['static/src/js/move_line_search_view.js'],
    
  2. El archivo  move_line_search_view.js contendra el reemplazo de la funcion, para ello la estructura es la siguiente:
    openerp.journal_entries_report_filter = function (instance) {
        instance.web.account.QuickAddListView.include({
    
            search_by_journal_period: function() {
                /*console.log("HOLA SUPER METODO")*/
                var self = this;
                var domain = [];
                if (self.current_journal !== null) domain.push(
                    ["journal_id", "=", self.current_journal]);
                if (self.current_period !== null) domain.push(
                    ["period_id", "=", self.current_period]);
                self.last_context["journal_id"] = 
                    self.current_journal === null ? false : 
                    self.current_journal;
                if (self.current_period === null) delete 
                    self.last_context["period_id"];
                else self.last_context["period_id"] =  
                    self.current_period;
                self.last_context["journal_type"] = 
                    self.current_journal_type;
                self.last_context["currency"] = 
                    self.current_journal_currency;
                self.last_context["analytic_journal_id"] = 
                    self.current_journal_analytic;
                return self.old_search(
                    new instance.web.CompoundDomain(
                                        self.last_domain, 
                        domain), self.last_context, 
                                    self.last_group_by);
            },
        });
    };
    

    journal_entries_report_filter es el modulo que estoy creando con los nuevos métodos javascript, openerp.journal_entries_report_filter = function (instance) fragmento de código  que crea una instancia de los archivos fuente javascript para instanciar el modulo account y sus recursos, en la siguiente linea apreciamos la referencia (instancia) del modulo account instance.web.account.QuickAddListView.include por ultimo el método search_by_journal_period es el método que estoy reemplazando o sobrescribiendo.
Nota: no se olviden de tener como dependencia
Espero que les ayude en algún momento.



viernes, 14 de octubre de 2016

Forzar la Escritura de Base de Datos en Procesos Odoo

Forzar un Commit a la Base de Datos


    Muchos de nosotros en el ambiente de programación Odoo hemos notado una funcionalidad bastante interesante, poderosa y buena para evitar concurrencia de información basura en el Sistema y es la escritura a la Base de Datos mediante Odoo, durante la ejecución de una función (proceso) Odoo no realiza cambios en la Base de Datos hasta no terminar la ejecución correcta de la misma, si ocurre un error durante la ejecución Odoo hace un reverse a lo que se había realizado anteriormente, así evita que se guarde información basura o se llegaran a duplicar registros.
    Esto es muy útil, pero en ocasiones llegamos a tener la necesidad de forzar la escritura a la Base de Datos ya sea por el tamaño de recursos del Servidor (Memoria RAM), por bloqueos generados por el Servidor PostgreSQL (max_locks_per_transaction) o simplemente queremos que cierta información recabada no se pierda, por ejemplo en la lectura de archivos binarios de una ruta x, que al ser procesados son eliminados del servidor, en este proceso no podemos perder la información ya generada, así que podríamos forzar la escritura a la Base de Datos, otro ejemplo podria ser al generar reportes contables en donde la cantidad de información es en volúmenes considerablemente grandes y la memoria podria saturarse.

Para forzar la escritura de la Base de Datos basta con insertar este pequeño fragmente de codigo en la parte de nuestro código donde queremos forzar la escritura:

self.env.cr.commit()

lunes, 10 de octubre de 2016

Instalación de Odoo 10 en CentOS 7




Instalación de Odoo 10 en 
CentOS 7

Instalación de Odoo 10 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 subversion git bzr bzrtools postgresql python-all-dev python-dev python-setuptools libxml2-dev libxslt1-dev libevent-dev libsasl2-dev libldap2-dev pkg-config libtiff5-dev libjpeg8-dev libjpeg-dev zlib1g-dev libfreetype6-dev liblcms2-dev liblcms2-utils libwebp-dev tcl8.6-dev tk8.6-dev python-tk libyaml-dev fontconfig node-less python-pip gdebi-core python-dateutil python-feedparser python-ldap python-libxslt1 python-lxml python-mako python-openid python-psycopg2 python-pybabel python-pychart python-pydot python-pyparsing python-reportlab python-simplejson python-tz python-vatnumber python-vobject python-webdav python-werkzeug python-xlwt python-yaml python-zsi python-docutils python-psutil python-mock python-unittest2 python-jinja2 python-pypdf python-decorator python-requests python-passlib python-pil
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  
Instalación 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 10.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.

Creación 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,/opt/odoo/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 10.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/odoo-bin --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


Instalacion Odoo 10 en Ubuntu Server

Instalación Odoo 10 en Linux, Ubuntu 15.x , Ubuntu 16.x y Ubuntu Server


PASOS PARA LA INSTALACIÓN: 

Antes que nada necesitamos instalar las dependencias que utiliza Odoo (una dependencia es una aplicación o una biblioteca requerida por otro programa para poder funcionar correctamente. Por ello se dice que dicho programa depende de tal aplicación o biblioteca).
Antes de instalar las dependencias, necesitamos una actualizacion de los repositorios:
sudo apt-get update && sudo apt-get upgrade
Abrimos una Terminal de Ubuntu o una manera rápida es presionando las teclas Alt+Ctrl+T y escribimos lo siguiente:
sudo apt-get install subversion git bzr bzrtools python-pip postgresql python-all-dev 
python-dev python-setuptools libxml2-dev libxslt1-dev libevent-dev libsasl2-dev
libldap2-dev pkg-config libtiff5-dev libjpeg8-dev libjpeg-dev zlib1g-dev libfreetype6-dev 
liblcms2-dev liblcms2-utils libwebp-dev tcl8.6-dev tk8.6-dev python-tk libyaml-dev 
fontconfig node-less python-pip gdebi-core python-dateutil python-feedparser python-ldap
python-libxslt1 python-lxml python-mako python-openid python-psycopg2 python-pybabel 
python-pychart python-pydot python-pyparsing python-reportlab python-simplejson python-tz 
python-vatnumber python-vobject python-webdav python-werkzeug python-xlwt python-yaml 
python-zsi python-docutils python-psutil python-mock python-unittest2 python-jinja2 
python-pypdf python-decorator python-requests python-passlib python-pil -y
Nota: Debemos copiar y pegar las dependencias en un bloc de notas y quitar los saltos de linea que tiene el formato del Blog.
Creamos un directorio en la ruta /opt llamada Odoo:
cd /opt
Despues:
sudo mkdir odoo
Cambiamos los permisos de la carpeta odoo al usuario que usara esta ruta (german es el usuario del sistema):
sudo chown german.german * -R odoo
Descargamos Odoo desde el Repositorio Oficial:
sudo git clone https://www.github.com/odoo/odoo --depth 1 --branch 10.0 --single-branch .
Instalamos las dependencias de la aplicación:
sudo pip install -r /opt/odoo/doc/requirements.txt
sudo pip install -r /opt/odoo/requirements.txt

Creamos nuestro Usuario Postgres
Entramos al prompt de postgres:
sudo su postgres
Creamos el Usuario:
createuser -s -P -e odoo
Tecleamos la contraseña (odoo) 2 veces. Ahora para evitar algún error modificamos el template principal de postgres (template1)
psql template1
Y una vez dentro del template:
alter role odoo with password 'odoo';
Para salir del prompt de postgres solo ejecutamos:
psql \q
Creamos nuestro archivo de configuracion de Odoo, para ello vamos al directorio de instalación (/opt/odoo/) y ejecutamos:
python odoo-bin -c odoo.conf -s
Lo que estamos haciendo es crear un archivo de configuración para Odoo.
Ahora debemos pausar la ejecución del servidor con la combinación de teclas ctr+c.
Listo, ahora editamos el archivo de configuración llamado odoo.conf, con el editor vi, vim, nano o gedit si están en modo gráfico y modificamos los valores:
db_host = localhost
db_maxconn = 64
db_name = False
db_password = odoo
db_port = 5432
db_template = template1
db_user = odoo
Guardamos y ahora para ejecutar el servidor odoo, usamos el comando:
python odoo-bin -c odoo.conf
En la ruta /opt/odoo
NOTAS: 
En ocasiones el Firewall de Linux, puede bloquear nuestro puerto en donde iniciamos Odoo, entonces debemos ejecutar los siguientes comandos:
sudo ufw allow ssh
sudo ufw allow 8069/tcp
sudo ufw enable

miércoles, 28 de septiembre de 2016

Nuevos atributos para Color en Vistas Avanzadas Odoo

Decoradores para vistas de Lista Odoo 9


    En OpenERP 7 y Odoo 8.0 teníamos la posibilidad de añadir atributos de color (color) y fuente (font) en las vistas de lista, para poder identificarlas de una manera mas sencilla, en Odoo 9.0 encontré que cambio un poco y ahora utiliza atributos especiales para ello (decoradores), veamos un ejemplo:

Vista con Colores en versiones anteriores a Odoo 9.0

<tree string="Pedidos de Venta" colors="blue:state=='confirmed'" >
    .....
    .....
    .....
</tree>

Atributos para Colores en Odoo 9.0

<tree string="Pedidos de Venta" decoration-info="state=='confirmed'">
    .....
    .....
    .....
</tree>

Otros decoradores son:
  • decoration-bf - Lineas en BOLD 
  • decoration-it - Lineas en ITALICS 
  • decoration-danger - Color LIGHT RED 
  • decoration-info - Color LIGHT BLUE 
  • decoration-muted - Color LIGHT GRAY 
  • decoration-primary - Color LIGHT PURPLE 
  • decoration-success - Color LIGHT GREEN 
  • decoration-warning - Color LIGHT BROWN

lunes, 19 de septiembre de 2016

Widget Boton Contador de Elementos en Formularios Odoo


Para añadir un botón en un formulario con un contador de los elementos que mostrará (como el de la imagen superior), debemos calcular el número de resultados en un campo y, posteriormente, mostrarlo:
1
2
3
4
5
6
7
8
serials_qty = fields.Integer(
        compute="_get_serials_qty",
        readonly=True)
 
@api.one
def _get_serials_qty(self):
     cond = [('partner_id', '=', self.id)]
     self.serials_qty = len(self.env['stock.production.lot'].search(cond))
1
2
3
4
5
6
7
8
<div class="oe_right oe_button_box" name="contact_buttons">
     <button class="oe_inline oe_stat_button" type="action" icon="fa-list"
              name="%(client_serial_numbers.act_contact_serial_numbers)d">
              <field name="serials_qty"
                     string="Núm. de serie"
                     widget="statinfo" />
     </button>
</div>
En el xml definimos un div como el mostrado y dentro de la etiqueta button insertamos el campo en el que hemos calculado la cantidad, con el atributo statinfo.
Fuente Tomada de Odootricks

Añadir Fuentes TTF a Informes Qweb

Para cambiar la fuente a un informe, debemos seguir estos pasos:
Primero, descargar la fuente con formato .ttf de internet. Es muy fácil encontrar la fuente que queremos buscando un poco. Segundo, abrir el código de nuestro informe y definirnos una nueva font-family de la siguiente manera:
1
2
3
4
5
6
7
8
9
10
11
<div class="header">
      <style type="text/css">
             <![CDATA[
                        @font-face {
                          font-family: 'MyFontName';
                          src: url('module_name/static/src/font/cour.ttf') format('truetype');
                        }
               ]]>
       </style>
---
</div>
Por último, la utilizamos:
1
<span style="font-family:'MyFontName';" t-field="o.company_id.name" /><br />
Fuente Tomada de Odootricks

Añadir Direccion de Partner en Reportes Qweb de forma Facil


En el sistema Qweb the Odoo existen widgets para distintos ámbitos, pero en esta entrada vamos a hablar sobre el widget the contact
Este widget nos hace la vida más fácil porque con solo una linea y pocos parametros nos muestra toda la información de un cliente.
Código ejemplo:
1
2
3
<div t-field="o.partner_id"  
         t-field-options='{"widget": "contact", "fields": ["name", "address", "city", 
         "phone", "mobile", "fax", "website", "email"],   "no_marker": true}'/>
En este ejemplo podemos ver todos los posibles parametros:
  • name
  • address
  • country_image
  • city
  • phone
  • mobile
  • fax
  • website
  • email
Pero si usted no tiene suficiente con estos parametros en este link puede encontrar información de como añadir uno nuevo.
Fuente Tomada de Odootricks