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.