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

lunes, 27 de marzo de 2017

Modulo de Captura de Datos para pagos con Tarjeta en TPV

Captura de los Ćŗltimos 4 DĆ­gitos para Pagos en el Punto de Venta



Un dato importante para el uso de puntos de venta en México es la obtención y resguardo de los últimos 4 dígitos de pagos con tarjeta de crédito/débito esto nos ayuda en auditorias y obtención de reportes como cierres de caja, etc.

Al no encontrar ningún modulo relacionado en la tienda de Odoo me di a la tarea de crear este modulo y compartirlo con la comunidad en estos tiempos donde ya no encontramos módulos útiles que sean gratuitos.

El modulo añade un input en la captura del pago donde podemos capturar la información de cada pago con tarjeta:


El input captura solamente 4 dígitos como mÔximo, para validar la seguridad de la información del Cliente.


La información enviada mediante es campo es guardada en el registro de Pedido del POS:


El campo donde observaremos la información tiene por nombre últimos 4 Digitos:



La liga del modulo es la siguiente, por el momento solo funciona en Odoo 9 y 10:

viernes, 10 de marzo de 2017

Herencia de propiedades en Vistas Formulario

Recepción de Propiedades mediante el contexto Odoo de las Vistas Formulario


Una propiedad muy interesante en la programación Odoo es poder heredar propiedades, valores, etc.
Esto es posible gracias a un parametro heredable en todos los aspectos de Odoo (Funciones, Vistas, Acciones de Ventana. etc..) llamado context.

Existe una infinidad de usos que podemos darle al contexto de odoo, desde enviar una cantidad infinita de variables en este parÔmetro dentro de una función, hasta la posibilidad de heredar valores desde la vista formulario en campos relación.

Dentro de nuestro formulario podemos enviar valores al contexto como lo mencione anteriormente, por ejemplo en la relación de lineas de pedido (order_line_ids) enviare el Almacén del Pedido, esto lo haria en la vista de esta manera:

<field name="order_line_ids" context ="{'warehouse_id': warehouse_id} />

En este ejemplo el campo warehouse_id es necesario que exista en la vista de donde lo enviamos, acto seguido si definimos cualquier mƩtodo dentro del registro de ventas, podemos observar dentro del contexto el campo warehouse_id con el AlmacƩn del Pedido de Venta.



lunes, 13 de febrero de 2017

Inserción de Datos a una nueva tabla desde una consulta SQL

Insertar Datos a una tabla Many2many desde una consulta SQL


Un problema que tuve al momento de generar una base de datos nueva y cargar un catalogo de productos fue que olvide activar una ruta creada, entonces me surgió una duda como puedo insertar datos a una tabla relacional producto de un campo many2many desde una consulta SQL sin usar funciones en la base de datos, pues la respuesta fue muy sencilla y a continuación les describo mi script:

insert into stock_route_product(product_id,route_id) select id as product_id,
5 as route_id from product_template;


  • Primero detectamos la tabla many2many2 que contiene la información por la cual se crean las relaciones.
  • Segundo ingresamos las 2 columnas que se necesitan para obtener la relación muchos a muchos, en mi caso la ruta que querĆ­a insertar era la que tenia el ID 5 para cada producto.
  • Por ultimo hice la consulta de la tabla product_template y de forma automĆ”tica PostreSQL inserto cada registro de la tabla mencionada y su relación correspondiente en la tabla de rutas.


Espero les sea de ayuda.


viernes, 27 de enero de 2017

Automatización de Respaldos de Bases de Datos Odoo desde Bash

Automatización de Respaldos en Odoo desde Bash



  1. Crear un Script (Backup-Script) en la Ruta /var/scripts/dump_db.sh
    #!/bin/sh    
    hostname='hostname'
    
    ##########################################
    ## Odoo Backup
    ## Respaldo de las Bases: odoodb1, odoob2
    ##########################################
    
    # Detener el Servicio de Odoo
    /etc/init.d/odoo-server stop
    
    # Dump DB (Backup de 2 Bases de Datos)
    for db in odoodb1 odoodb2
    do
      date='date +"%Y%m%d_%H%M%N"' # Respaldo con la fecha actual.
      filename="/var/pgdump/${hostname}_${db}_${date}.sql"
      pg_dump -E UTF-8 -p 5433 -F p -b -f $filename $db
      gzip $filename # Comprimiendo la Base de Datos
    done
    
    # Iniciando el servicio de Odoo nuevamente
    /etc/init.d/odoo-server start
    
    exit 0
    
  2. Script de Eliminación de los Backups, creamos un script en la ruta /var/scripts/housekeeping.sh (Solo borrara backups con una antiguedad de 30 dias para atras).
    #!/bin/sh
    path=/var/pgdump
    logfile=/var/log/$0
    
    rm -f $logfile
    for file in 'find /var/pgdump/ -mtime +30 -type f -name *.sql.gz'
    do
      echo "Borrando: " $file >> $logfile
      rm $file
    done
    
    exit 0 
  3. Programar la ejecucion de los scripts, modificamos el crontab en  /etc/crontab. La programación de los Backups se ejecutara a la 1 am y la limpieza de backups a las 5 am.
    # m h dom mon dow user  command
    0 1 * * * postgres /var/scripts/dump_db.sh
    0 5 * * * postgres /var/scripts/housekeeping.sh

Si queremos que nuestro Respaldo pese mucho menos podrĆ­amos comprimirlo con la librerĆ­a 7zip en lugar de gzip:



7zr a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on Mi_Backup.7z /path/to/database.dump


Nota: La detención del proceso de Odoo, puede variar dependiendo la instalación que hayan realizado, podría ser simplemente service odoo stop/start o podemos matar el proceso directamente con sudo fuser -k 8069/tcp.

miƩrcoles, 25 de enero de 2017

Obtener ID de registro desde datos XML Odoo

MƩtodo para obtener el ID de la tabla desde el ID de una Vista de un modulo Odoo



Se que el titulo sonada un poco extraƱo, pero la idea es muy sencilla, existe un metodo de Odoo que te permite obtener el ID de un registro ya creado en la base de datos, enviandole el ID con el cual lo creamos desde un XML, para que sea un poco mas claro vamos a analizarlo.

  • Normalmente creamos un registro desde un XML de la siguiente manera:
<record id="product_uom_categ_kgm" model="product.uom.categ">
            <field name="name">Weight</field>
</record>
     


El ejemplo anterior es una categorĆ­a creada desde el modulo product.

  • Si necesitĆ”ramos saber el ID que tiene esa categorĆ­a en la base de datos:

          La manera natural o normal que yo realizarĆ­a es:
          categ_id = self.env['product.category'].search([('name','=','Weight'])
         Utilizando el mĆ©todo de odoo seria de la siguiente manera:
          uom_categ_id = self.env['ir.model.data'].xmlid_to_res_id( 'product.product_uom_categ_kgm')

Los parĆ”metros que recibe son:

  • Nombre del Modulo.
  • ID del registro en el XML.


En resumen el metodo xml_to_res_id, te permite conocer el ID de cualquier registro en cualquier tabla siempre y cuando se haya creado desde un XML en un modulo de Odoo.


jueves, 12 de enero de 2017

Reset Password Odoo desde Base de Datos

Actualizar contraseƱa de usuarios Odoo desde la Base de Datos


Anteriormente en versiones 7 de Odoo (OpenERP) podiamos consultar la contraseƱa de un usuario mediante la columna password  de la tabla res_users, a partir de la versión 8 aƱaden una seguridad extra que es el HASH (Encriptación) de las mismas, como administradores de Odoo muchas veces tenemos que consultar o resetear las contraseƱas de algunos usuarios para ello basta con ejecutar el siguiente script sql desde la base de datos:

UPDATE res_users SET password='', password_crypt='HASH' WHERE id=1;

Dentro de la variable password pondriamos la nueva contraseƱa que puede ser la que el usuario prefiera.


Odoo 8.0:

Change the password directly in the Postgres Database, as it is saved in plain text:
~$  sudo su postgres
~$  psql
postgres=# \connect Your_Database_Name
You are now connected to database "Your_database_Name" as user "postgres"
YOurDatabase_Name=# update res_users set password='YourNewPassword' where id='1';

Odoo 9.0 and Odoo 10.0:

Create a hash and then change the hash in the Postgres database:
~$ python
>>> from passlib.context import CryptContext
>>> print CryptContext(['pbkdf2_sha512']).encrypt('YourNewPassword')
Copy the Hash created
Ctrl D
~$  sudo su postgres~$  psqlpostgres=# \connect Your_Database_NameYou are now connected to database "Your_database_Name" as user "postgres"
YOurDatabase_Name=# UPDATE res_users SET password='', password_crypt='YourCopiedHash' WHERE id=1;YOurDatabase_Name=# \q

Odoo 11:

Create a hash using Python 3 and change the hash in the Postgres database:
~$ python3
>>> from passlib.context import CryptContext
>>> setpw = CryptContext(schemes=['pbkdf2_sha512'])
>>> setpw.encrypt('YourNewPassword')
Copy the Hash created
Ctrl D
~$  sudo su postgres
~$  psql
postgres=# \connect Your_Database_Name
You are now connected to database "Your_database_Name" as user "postgres"
YOurDatabase_Name=# UPDATE res_users SET password='', password_crypt='YourCopiedHash' WHERE id=1;
YOurDatabase_Name=# \q

Odoo 12 and Odoo 13:

Create a hash using Python 3 and change the hash in the Postgres database:
~$ python3
>>> from passlib.context import CryptContext
>>> setpw = CryptContext(schemes=['pbkdf2_sha512'])
>>> setpw.encrypt('YourNewPassword')
Copy the Hash created
Ctrl D
~$  sudo su postgres
~$  psql
postgres=# \connect Your_Database_Name
You are now connected to database "Your_database_Name" as user "postgres"
YOurDatabase_Name=# UPDATE res_users SET password='YourCopiedHash' WHERE id=2;YOurDatabase_Name=# \q

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.