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

jueves, 30 de julio de 2015

Eliminacion en Cascada y Restricciones en campos Many2One

Eliminacion en Cascada y Restricciones en campos Many2One

    Un Error muy comĆŗn durante la programación de clases y en especial al utilizar los campos Many2One y One2Many en Odoo es la definición de los atributos.
Existe uno en especial llamado "ondelete", este atributo tiene 3 funciones:

  1. Cascade. Permite eliminar los registros ligados a una clase, cuando tiene un campo one2many.
  2. Restrict. Impide la eliminación de la fila referenciada. 
  3. Set null. Modifica el campo a Nulo ó False, cuando el registro de la relación sea Eliminado.

Un ejemplo de ondelete:

class ejemplo_clase(osv.osv):
    _name = 'ejemplo.clase'
    _description = 'Descripcion del Modelo'
    _columns = {
        'lineas': fields.one2many('ref_id','ejemplo.linea', 'Linea'),
    }

class ejemplo_linea(osv.osv):
    _name = 'ejemplo.linea'
    _description = 'Descripcion del Modelo'
    _columns = {
        'ref_id': fields.many2one('ejemplo.clase', 'Referencia', ondelete="cascade"),
    }

    Lo que pasara en el ejemplo anterior es que cuando se borre un registro de la tabla ejemplo_clase, se borraran los registros de la tabla ejemplo_linea que tenga asignados.


jueves, 16 de julio de 2015

Mostrar Columnas Ocultas en Clases Odoo

Agregar Columnas Ocultas en Vistas Odoo


    En Odoo, por defecto cada vez que se crea una nueva Clase, esta se convierte a una tabla de nuestra Base de Datos, este proceso es administrado por el ORM del Framework, durante esta conversión el sistema creara 5 columnas de forma automĆ”tica:


  1. id: Este Campo es la llave principal de todas las Tablas.
  2. create_uid: Usuario que creo un registro.
  3. create_date: Fecha en la que se creó el registro.
  4. write_uid: Usuario que modifico un registró.
  5. write_date: Fecha en la que se modifico el registró.
    Las columnas anteriores, sirven de alguna manera para auditar la información, en ocasiones es necesario alguna de estas Columnas en nuestras vistas, pero como son manejadas internamente por el Framework, por defecto no podemos agregarlas directamente.

Para AƱadirlas a una vista, se debe hacer lo siguiente:

1. Heredar la Clase y aƱadir las columnas como campos, teniendo cuidado de definir el tipo exacto como esta en la Tabla:


class mi_clase(osv.osv):
_name='mi.clase'
_columns={
    'create_uid': fields.many2one('res.users', 'Creado Por', readonly=True),
}

mi_clase()

2. Lo ultimo es añadirlo a nuestra Vista ó Vistas:

<record model='ir.ui.view' id='mi_clase_form'>
    <field name='priority'>3</field>
    <field name='type'>form</field>
    <field name='model'>mi.clase</field>
    <field name='arch' type='xml'>
    <form string="Clase Ejemplo">
        <field name="create_uid"/></field>
    </form>
</record>




Instalacion de Odoo desde Repositorios Linux

INSTALACIƓN DE ODOO EN 3 PASOS



Pasos:

1. Abrimos una Terminal, en ubuntu presionamos las teclas Alt+Ctrl+T y nos logeamos como root

2.  Ejecutamos wget -O - https://nightly.odoo.com/odoo.key | apt-key add -
echo "deb http://nightly.odoo.com/8.0/nightly/deb/ ./" >> /etc/apt/sources.list

3. Tecleamos apt-get update && apt-get install odoo.


Listo, tenemos Odo corriendo en el puerto 8069.





viernes, 3 de julio de 2015

Herencia Reportes Qweb en Odoo

Herencia Templates Qweb

    Algó muy Ćŗtil y necesario para el desarrollo Odoo es la herencia, en mas de una ocasión esto nos ah salvado y ayudado para adaptar el Sistema, Qweb Reports no se queda atras e implementa la herencia de las Vistas que son las que generan nuestros Reportes, para elló utilizaremos la herramienta xml Xpath.

    La forma de  heredar es simple, utilizaremos el ID de la vista del reporte, tal cual lo hacemos con las Vistas de Formulatios y aƱadimos, modificamos ó reemplazamos un elemento.

Ejemplo Herencia Xpath en Qweb Reports

Vamos a heredar el reporte de Albaran y modificar el cuerpo del Reporte, por ejemplo aƱadimos una tabla para tener un espacio para firmar la entrada y salida de Almacen.

El codigo para aƱadir estas firmas es:

<table border="0" style="border-collapse:collapse;color:000000;width:100%" cellpadding="3" cellspacing="3">
    <tr>
        <td  class="text-center" >________________________</td>
        <td  class="text-center" >________________________</td>
    </tr>
    <tr >
         <td class="text-center" >
             <strong>Nombre y Firma Entrega</strong>
         </td>
     <td class="text-center" >
          <strong>Nombre y Firma Recepcion</strong>
      </td>
                            
     </tr>
</table>

Heredamos la vista Qweb por medio del ID:

<template id="report_header_custom" inherit_id="stock.report_picking">
    <xpath expr="//div[@class='page']" position="replace">
        <div class="page">
            Aquí va nuestro código .......
        </div>
    </xpath>
 </template>

Al final  asĆ­ quedo mi  nueva Vista para el Reporte de AlbarĆ”n:

<!-- Template Final -->
    <template id="report_header_custom" inherit_id="stock.report_picking">
            <xpath expr="//div[@class='page']" position="replace">
                <div class="page">
                    <div class="row"><div class="col-xs-4 pull-right">
                    <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('Code128', o.name, 600, 100)" style="width:300px;height:50px;"/>
                    </div></div>
                    <div class="row">
                        <div class="col-xs-6">
                            <div t-if="o.picking_type_id.code=='incoming' and o.partner_id">
                                <span><strong>Supplier Address:</strong></span>
                            </div>
                            <div t-if="o.picking_type_id.code=='internal' and o.partner_id">
                                <span><strong>Warehouse Address:</strong></span>
                            </div>
                            <div t-if="o.picking_type_id.code=='outgoing' and o.partner_id">
                                <span><strong>Customer Address:</strong></span>
                            </div>
                            <div t-if="o.partner_id" name="partner_header">
                                <div t-field="o.partner_id" t-field-options="{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;address&quot;, &quot;name&quot;, &quot;phone&quot;, &quot;fax&quot;], &quot;no_marker&quot;: true}"/>
                                <p t-if="o.partner_id.vat">VAT: <span t-field="o.partner_id.vat"/></p>
                            </div>
                        </div>
                        <div class="col-xs-5 col-xs-offset-1">
                            <div t-if="o.move_lines and o.move_lines[0].partner_id and o.move_lines[0].partner_id.id != o.partner_id.id">
                                <span><strong>Delivery Address:</strong></span>
                                <div t-field="o.move_lines[0].partner_id" t-field-options="{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;address&quot;, &quot;name&quot;, &quot;phone&quot;, &quot;fax&quot;], &quot;no_marker&quot;: true}"/>
                            </div>
                            <div t-if="o.picking_type_id.code != 'internal' and (not o.move_lines or not o.move_lines[0].partner_id) and o.picking_type_id.warehouse_id.partner_id">
                                <span><strong>Warehouse Address:</strong></span>
                                <div t-field="o.picking_type_id.warehouse_id.partner_id" t-field-options="{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;address&quot;, &quot;name&quot;, &quot;phone&quot;, &quot;fax&quot;], &quot;no_marker&quot;: true}"/>
                            </div>
                        </div>
                    </div>
                    <h2>
                    <span t-field="o.picking_type_id"/>:
                    <span t-field="o.name"/>
                    </h2>
                    <table class="table table-condensed">
                    <thead>
                        <tr>
                            <th><strong>Order (Origin)</strong></th>
                            <th><strong>State</strong></th>
                            <th><strong>Commitment Date</strong></th>
                            <th name="td_sched_date_h"><strong>Scheduled Date</strong></th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>
                                <span t-field="o.origin"/>
                            </td>
                            <td>
                                <span t-field="o.state"/>
                            </td>
                            <td>
                                <span t-field="o.date"/>
                            </td>
                            <td name="td_sched_date">
                                <span t-field="o.min_date"/>
                            </td>
                        </tr>
                    </tbody>
                    </table>
                    <br/>
                    <br/>
                    <table class="table table-condensed" t-if="not o.pack_operation_ids">
                      <thead>
                        <tr>
                            <th><strong>Product</strong></th>
                            <th class="text-center"><strong>Quantity</strong></th>
                            <t t-if="o.picking_type_id.code != 'incoming'">
                            <th><strong>Source</strong></th></t>
                            <th><strong>Barcode</strong></th>
                            <t t-if="o.picking_type_id.code != 'outgoing'"><th><strong class="text-center">Destination</strong></th></t>
                        </tr>
                      </thead>
                      <tbody>
                        <tr t-foreach="o.move_lines" t-as="move">
                            <td><span t-field="move.product_id"/></td>
                            <td class="text-right"><span t-field="move.product_uom_qty"/> <span t-field="move.product_uom" groups="product.group_uom"/></td>
                            <t t-if="o.picking_type_id.code != 'incoming'"><td><span t-field="move.location_id"/></td></t>
                            <td>
                                <span t-if="move.product_id and move.product_id.ean13">
                                    <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('EAN13', move.product_id.ean13, 600, 100)" style="width:300px;height:50px"/>
                                </span>
                            </td>
                            <t t-if="o.picking_type_id.code != 'outgoing'"><td><span t-field="move.location_dest_id"/></td></t>
                        </tr>
                      </tbody>
                    </table>
                    <table class="table table-condensed" t-if="o.pack_operation_ids">
                      <thead>
                        <tr>
                            <th><strong>Product</strong></th>

                            <th class="text-right"><strong>Quantity</strong></th>
                            <t t-if="o.picking_type_id.code != 'incoming'"><th><strong>Source</strong></th></t>
                            <th><strong>Barcode</strong></th>
                            <t t-if="o.picking_type_id.code != 'outgoing'"><th><strong>Destination</strong></th></t>
                        </tr>
                      </thead>
                      <tbody>
                        <tr t-foreach="o.pack_operation_ids" t-as="pack_operation">
                            <td><span t-field="pack_operation.product_id"/>
                                <t t-if="not pack_operation.product_id and pack_operation.package_id"><span t-field="pack_operation.package_id"/></t></td>

                            <td class="text-right"><span t-field="pack_operation.product_qty"/> <span t-field="pack_operation.product_uom_id" groups="product.group_uom"/></td>
                            <t t-if="o.picking_type_id.code != 'incoming'"><td><span t-field="pack_operation.location_id"/>
                                <span t-if="pack_operation.package_id">:</span>
                                <span t-field="pack_operation.package_id"/>
                                <span t-if="pack_operation.lot_id">:</span>
                                <span t-field="pack_operation.lot_id"/>
                                </td>
                            </t>
                            <td>
                                <span t-if="pack_operation.lot_id">
                                    <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('Code128', pack_operation.lot_id.name, 600, 100)" style="width:300px;height:50px"/>
                                </span>
                                <span t-if="pack_operation.product_id and not pack_operation.lot_id and pack_operation.product_id.ean13">
                                    <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('EAN13', pack_operation.product_id.ean13, 600, 100)" style="width:300px;height:50px"/>
                                </span>
                                <span t-if="pack_operation.package_id and not pack_operation.product_id">
                                    <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('Code128', pack_operation.package_id.name, 600, 100)" style="width:300px;height:50px"/>
                                </span>
                            </td>
                            <t t-if="o.picking_type_id.code != 'outgoing'"><td><span t-field="pack_operation.location_dest_id"/>
                                <span t-if="pack_operation.result_package_id">:</span>
                                <span t-field="pack_operation.result_package_id"/>
                            </td></t>
                        </tr>
                      </tbody>
                    </table>
                    <br/>
                    <br/>
                    <br/>
                    <br/>
                    <br/>
                    <br/>
                    <table border="0" style="border-collapse:collapse;color:000000;width:100%" cellpadding="3" cellspacing="3">
                        <tr>
                            <td  class="text-center" >________________________</td>
                            <td  class="text-center" >________________________</td>
                        </tr>
                        <tr >
                            <td class="text-center" >
                               <strong>Nombre y Firma Entrega</strong>
                            </td>
                            <td class="text-center" >
                               <strong>Nombre y Firma Recepcion</strong>
                            </td>
                            
                        </tr>
                    </table>

                </div>
            </xpath>
        </template>




Llamar funciones python desde Qweb Reports

Funciones Python desde Qweb Reports



    Qweb Reports el nuevo Reporteador para Odoo, ofrece muchas ventajas como lo ofrecĆ­a anteriormente RML, en ocaciones no podemos ejecutar directamente una operacion en Qweb o necesitamos tener un resultado de una funcion, esto es muy sencillo en RML, vamos a tomar como ejemplo las Facturas y voy a ejecutar un metodo desde el reporte Qweb, para calcular manualmente el total de un producto:


Qweb


<span  t-esc="line.subtotal_manual(line.price_unit,line.quantity)"/>

    Como podemos observar line es mi variable de iteracion para obtener los valores de invoice_lines, las lineas de Factura, para ejecutar un metodo llamado subtotal_manual. Este metodo que estamos utilizando no existe en el objecto account.invoice.line, asĆ­ que tendremos que crearlo.

Clases Python

# -*- encoding: utf-8 -*-
############################################################################
#    (c) 2015 German Ponce Dominguez
#    All Rights Reserved.
#    info skype: german_442 email: (german.ponce@outlook.com)
############################################################################

from openerp.osv import fields, osv
from openerp.tools.translate import _
from datetime import datetime, timedelta
from openerp import SUPERUSER_ID

class account_invoice_line(osv.osv):
    _name = 'account.invoice.line'
    _inherit ='account.invoice.line'
    _columns = {

        }

    _defaults = {
        }

    def subtotal_manual(self, price, qty):
        return price*qty

    En la clase python account_invoice_line, se aƱade el metodo que queremos ejecutar, esto sera variable de acuerdo al objecto en donde quieran ejecutar su funcion.


viernes, 19 de junio de 2015

Instalacion Wkhtmltopdf Ubuntu 13.x y 14.x, CentOS y otras distros de Linux.

Instalación fÔcil y rÔpida de la Aplicación Wkhtmltopdf para Odoo (OpenERP)




    Cuando instalamos webkit_reports en Odoo (OpenERP), muchas veces tenemos dificultades con la versión de esta aplicación, en mi caso perdĆ­ 2 dĆ­as probando versiones y diversas instalaciones que encontraba en Internet, normalmente me arrojaba errores como:

  • No connect to X Server.
  • Permission Denied.
  • Errores de la Carpeta /tmp.
    La instalación que me funciono, fue instalando manualmente la herramienta, los pasos son muy sencillos:
  1. Descargar Wkhtml desde GitHub de la url: https://github.com/germanponce/wkhtmltopdf.
  2. Entramos a la carpeta wkhtmltopdf con el comando cd wkhtmltopdf
  3. Descomprime la aplicación con el comando tar -xjvf wkhtmltopdf-0.11.0_rc1-static-amd64.tar.bz2
  4. Renombramos la aplicación mv wkhtmltopdf-amd64 wkhtmltopdf
  5. Como ultimo paso vamos a crear 2 copias, primero sudo cp wkhtmltopdf /usr/bin/ y segundo sudo cp wkhtmltopdf /usr/local/bin.
  6. Hacemos una prueba final wkhtmltopdf http://www.google.com Test.pdf
Listo tenemos funcionando WebKit ...


Nota: Mas Versiones Estables en http://download.gna.org/wkhtmltopdf/0.12/0.12.1/
                

martes, 16 de junio de 2015

Instalacion Automatica y Configuracion como Parametro de Wkhtmltopdf en Ubuntu y Odoo

Instalacion de un directorio para la LibrerĆ­a Wkhtmtopdf



    Muchas veces tenemos problemas con esta librerĆ­a en Odoo (OpenERP), ya que se necesita la instalación de una Aplicación nueva, para ello la solución rĆ”pida seria utilizar este comando para sistemas basados en Debian:

sudo apt-get install wkhtmltopdf

Ahora una alternativa es descargar el modulo desde github, con el comando:

git clone https://github.com/wkhtmltopdf/wkhtmltopdf.git

Ahora debemos Crear un Parametro del Sistema en Configuracion --> Tecnico --> Parametros --> Parametros del Sistema, con las siguientes Caracteristicas:



El nombre del parƔmetro es webkit_path y el valor es la ruta en donde descargaste el modulo wkhtmltopdf /home/config/wkhtmltopdf , en este caso lo puse en mi home, asƭ que el valor queda como en la Imagen.

martes, 9 de junio de 2015

Pagos Inteligentes

Filtrar Lineas de Pago para Aplicar el Pago Correcto.



    Al aplicar un pago en Odoo, todos hemos notado que nos despliega todos los pagos disponibles para el Cliente, en ocasiones eliminar las lineas que no necesitamos se vuelve una tarea muy "Engorrosa", para ello este pequeƱo modulo que eh desarrollado permite filtrar las facturas que vamos a pagar, como muestra la Imagen:


    Lo Ćŗnico que necesitamos es seleccionar las Facturas a Pagar y pulsar el Boton Aplicar Filtro, ubicado del lado derecho de la pantalla.

El modulo funciona para OpenERP (Version 7.0) y Odoo.

Pulda aqui para descargar: Modulo_Filtrar_Pagos

lunes, 1 de junio de 2015

Modulo para el Envio Massivo de Facturas y XML


Buenas Tardes a todos, revisando el Baul de mis Desarrollos encontré un modulo que puede serles muy útil, este modulo permite ó agrega la funcionalidad de poder enviar en un solo mail las facturas y XML que corresponden a un cliente, esto nos facilita seleccionar los Registros de las facturas que le hayamos realizado al cliente y enviarlas en un solo Correo.

Pasos para la Instalación:

  1. Primero que nada necesitamos tener Instalada y Configurada nuestra localización Mexicana de Vauxxo:
  2. Una vez instalada y Configurada, necesitamos descargar en nuestros Addons el modulo de envío Masivo de Emails, el modulo de Facturación con Jasper Reports y el modulo Jasper Reports:
  3. Una vez hecho esto Actualizamos la Lista de Modulos de Nuestra Base en OpenERP y nos debera Aparecer el siguiente Modulo:
  4. Pulsamos Instalar y automÔticamente Instalara el Modulo Jasper Reports, Modulo Facturación con Jasper Reports y el Envió Masivo de Correos.
  5. Una vez Instalado Ahora tenemos en Facturas un Nuevo Asistente para Enviar Facturas:
  6. Ahora solo debemos Seleccionar del Listado de Facturas Aquellas que vamos a Enviar:
  7. Seleccionamos Mas y el Asistente para Enviar Facturas,  Seleccionamos el campo Adjuntar Facturas:

  8. Al Pulsar Enviar Automaticamente Cargara los PDF y XML que contengan los Registros seleccionados y nos Mostrara el Cuerpo del Mensaje y el Listado de Archivos, con el correo Seleccionado del Cliente al que se le envian las Facturas:

  9. Listo Eso es Todo Espero les sea Ćŗtil, si descubren algĆŗn Bug pueden enviarme un correo.

jueves, 28 de mayo de 2015

Eliminar los Valores predefinidos por el Usuario

Eliminar los Valores predefinidos por el Usuario


    Es muy comĆŗn que el administrador del Sistema le aplique un valor predeterminado a un Campo(s), como puede ser detalles en Notas, Referencias, Ubicaciones por default, y cuando queremos Eliminarlas no sabemos en donde se Almacenan.

Ejemplo, yo aplico un texto en Notas con la leyenda: "UNA VEZ SALIDA LA MERCANCƍA NO SE ACEPTAN DEVOLUCIONES, REVƍSELA ANTES DE SALIR DE LA TIENDA" y la defino por default para que cada Factura lleve impresa la misma.


    Si en algĆŗn punto de la Empresa decide cambiar y tener garantĆ­a en sus productos, esta leyenda ya no sera necesaria, entonces para evitarle al usuario tener que eliminarla cada vez que crea una Factura, debemos eliminar ese valor del Sistema.

Para eliminar campos con valores por defecto, vamos a ir al menú del Sistema Configuración --> Técnico --> Acciones --> Predeterminados Predefinidos por el Usuario.

AquĆ­ solo tendremos que aplicar los filtros para encontrar nuestro campo.


Ahora solo lo seleccionamos y pulsamos Eliminar.