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, 16 de junio de 2016

Leer y ordenar archivos por fecha de Creación desde Python

Leer y Ordenar Archivos por su fecha de Creación (Antiguedad Descendente Antiguo --> Reciente)



Este pequeño codigo es muy util en la creación de colas de lectura ordenadas por antiguedad del archivo.

Primero haremos uso de 2 librerías:
  1. glob
  2. os
Las importamos en nuestro codigo como cualquier otra libreria:

import glob
import os

Ahora un ejemplo del Codigo:

import glob
import os

search_dir = "/mi_ruta_archivos/"
files = filter(os.path.isfile, glob.glob(search_dir + "*"))
files.sort(key=lambda x: os.path.getmtime(x))
files = [str(x) for x in files]

print "####### ARCHIVOS ORDENADOS POR ANTIGUEDAD", files

Un ejemplo de cada elemento de la lista files es "/mi_ruta_archivos/archivo1.txt"

viernes, 10 de junio de 2016

Generación de Codigos de Barra PDF417 con Python y la libreria Elaphe

Códigos de Barra PDF 417 con Elaphe y Odoo



Instalamos la libreia elaphe la cual sera nuestra herramienta principal en este ejercicio:

sudo apt-get install python-elaphe

Si utilizamos el gestor de librerias Pip:

sudo pip install elaphe

Como cualquier otra libreria necesitamos importarla en nuestro codigo:
>>> from elaphe import barcode

Un ejemplo completo utilizando elaphe y codigo de barras pdf 417:

from elaphe import barcode
bc = barcode('pdf417', "Bienvenidos a poncesoft.blogspot.com", options=dict(eclevel=2, compact=True, columns=2, rows=10), margin=1, scale=2)
bc.save('test.png')

El primer parámetro de la función barcode es el tipo de código de barras a generar, el segundo es la cadena que convertiremos a  imagen utilizando código de barras

Otros códigos de barra que podemos implementar con la librería elaphe son:

from elaphe import barcode
barcode('qrcode', 'Hello Barcode Writer In Pure PostScript.', options=dict(version=9, eclevel='M'), margin=10, data_mode='8bits').show()
barcode('code128', '^104^102Count^0990123456789^101!', options=dict(includetext=True), scale=2, margin=1).show()
barcode('pdf417', '^453^178^121^239', options=dict(columns=2, rows=10), margin=1, scale=2).show()
barcode('upc', '78858101497', options=dict(includetext=True), scale=2, margin=1).show()
barcode('royalmail', 'LE28HS9Z', options=dict(includetext=False), scale=2, margin=1).show()
barcode('datamatrix', '^142^164^186', options=dict(columns=32, rows=32), margin=1, scale=2.0).show()
barcode('code11', '0123456789', options=dict(includetext=True), scale=2, margin=1).show()
barcode('code25', '0123456789', options=dict(includetext=False, includecheck=False), scale=2, margin=1).show()
barcode('code39', 'THIS IS CODE39', options=dict(includetext=True), scale=2, margin=1).show()
barcode('code93', 'THIS IS CODE93', options=dict(includetext=True), scale=2, margin=1).show()
barcode('japanpost', '1231FZ13XHS', options=dict(includetext=False), scale=2, margin=1).show()
barcode('azteccode', '00100111001000000101001101111000010100111100101000000110', margin=1).show()
barcode('auspost', '5956439111ABA 9', options=dict(includetext=False), scale=2, margin=1).show()
barcode('ean13', '977147396801', options=dict(includetext=True), scale=2, margin=1).show()
barcode('interleaved2of5', '24012345678905', options=dict(includetext=True), scale=2, margin=1).show()
barcode('raw', '331132131313411122131311333213114131131221323', options=dict(includetext=True), scale=2, margin=1).show()
barcode('kix', '1231FZ13XHS', options=dict(includetext=False), scale=2, margin=1).show()
barcode('postnet', '012345', options=dict(includetext=True), scale=2, margin=1).show()
barcode('pharmacode', '117480', options=dict(includetext=True), scale=2, margin=1).show()
barcode('plessey', '012345ABCD', options=dict(includetext=True), scale=2, margin=1).show()
barcode('symbol', 'fimd', options=dict(includetext=True), scale=2, margin=1).show()
barcode('onecode', '0123456709498765432101234567891', options=dict(includetext=True), scale=2, margin=1).show()
barcode('maxicode', '^059^042^041^059^040^03001^02996152382802^029840^029001^0291Z00004951^029UPSN^02906X610^029159^0291234567^0291^0471^029^029Y^029634 ALPHA DR^029PITTSBURGH^029PA^030^062^004^063', options=dict(mode=2), margin=1, scale=4).show()
barcode('msi', '0123456789', options=dict(includetext=True), scale=2, margin=1).show()
barcode('rss14', '24012345678905', options=dict(linkage=True, includetext=True), scale=2, margin=1).show()
barcode('rationalizedCodabar', 'A012345

Implementación con Odoo

Para nuestros módulos básicamente es lo mismo, pero nos apoyaremos de otras librerias que nos ayudaran a generar archivos en la partición temporal del sistema, primero importamos:

from elaphe import barcode
import os
import base64
import hashlib
import tempfile

Un ejemplo es el siguiente:
# Instanciamos el metodo principal barcode
bc = barcode('pdf417', "Bienvenidos a poncesoft.blogspot.com", options=dict(eclevel=2, compact=False, columns=2, rows=10), margin=1, scale=2)
# Generamos un nombre y ruta temporal
fname=tempfile.NamedTemporaryFile(suffix='.png',delete=False)
# Asigamos el nombre temporal a una variable
temporal_name = fname.name
# Guardamos nuestra imagen generada con elaphe y la ruta temporal
bc.save(fname.name)
# Podemos manipular la imagen ya generada
f = open(fname.name, "r")
data = f.read()
f.close()

Solucion de Error PostgreSQL Encoding Latin en lugar de UTF-8 y Unable to Login en Odoo


Cambiar Codificación Latin -> UTF-8 PostgreSQL & Odoo




    Este Error me causo conflicto al tratar de crear una Maquina Virtual para migrar una instancia de Odoo al instalar las dependencias que necesita este maravilloso ERP, el motor de Base de Datos (PostgreSQL) y por ultimo restablecer la Base de Datos, me di cuenta que no podía acceder a la base restablecida en la parte web me arrojaba el error "Unable to Login" y en el archivo log una serie de errores relacionados con los accesos a la base de datos.

Primero verifique mis bases de Datos con el comando:

sudo su postgres

psql -l


Veriamos algo similar a:

         Name            |   Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
----------------------------+-----------+----------+-------------+-------------+-----------------------
 Mi_Base_Odoo               | odoo      | LATIN1     | LATIN1 | LATIN1 | 
 postgres                   | postgres  | LATIN1     | LATIN1 | LATIN1 | 
 template0                  | postgres  | LATIN1     | LATIN1 | LATIN1 | =c/postgres          +
                            |           |          |             |             | postgres=CTc/postgres
 template1                  | postgres  | LATIN1     | LATIN1 | LATIN1 | =c/postgres          +


Este fue el problema principal por el que no podia acceder a mi Base de Datos, la solución fue cambiar la encodificación de la base principal de postgres y template1.

Ejecutaremos esta seria de comandos en la terminal de PostgreSQL, que básicamente creara nuevamente la base principal de postgresq Template1:

sudo su postgres
psql
update pg_database set datistemplate=false where datname='template1';
drop database Template1;
create database template1 with owner=postgres encoding='UTF-8'
lc_collate='en_US.utf8' lc_ctype='en_US.utf8' template template0;
update pg_database set datistemplate=true where datname='template1';

Si nos muestra error en_US, instalamos:
locale-gen en_US.UTF-8 
Cambiamos el encoding de nuestra base postgres:

update pg_database set encoding=6 where datname='postgres';

Si necesitan conocer mas acerca de como asignar la codificación dejo esta imagen:



Ahora borramos y restauramos nuestra base de Datos y esta tendrá la codificación correcta.

En Ubuntu también debemos asignar Correctamente la codificación unicode.

1. Ejecutamos el comando que generara archivos locales con la codificación Unicode:

update pg_database set encoding=6 where datname='postgres';

2. Actualizamos el archivo /etc/default/locale con los valores correctos (o usamos update-locale LANG=xx LC_CTYPE=xx ...), si optamos por actualizar el archivo tendremos que poner estos cambios:

 $ sudo cat - > /etc/default/locale <<EOF
 LANG=en_US.UTF-8
 LANGUAGE=
 LC_CTYPE="en_US.UTF-8"
 LC_NUMERIC="en_US.UTF-8"
 LC_TIME="en_US.UTF-8"
 LC_COLLATE="en_US.UTF-8"
 LC_MONETARY="en_US.UTF-8"
 LC_MESSAGES="en_US.UTF-8"
 LC_PAPER="en_US.UTF-8"
 LC_NAME="en_US.UTF-8"
 LC_ADDRESS="en_US.UTF-8"
 LC_TELEPHONE="en_US.UTF-8"
 LC_MEASUREMENT="en_US.UTF-8"
 LC_IDENTIFICATION="en_US.UTF-8"
 LC_ALL=en_US.UTF-8
 EOF

Reiniciamos nuestro servidor Odoo y podemos trabajar de forma correcta.

jueves, 9 de junio de 2016

Trabajando con Symfony2 y Odoo (OpenERP)

Symfony2 & Odoo (OpenERP)



    Symfony es un completo framework diseñado para optimizar, gracias a sus características, el desarrollo de las aplicaciones web. Para empezar, separa la lógica de negocio, la lógica de servidor y la presentación de la aplicación web. Usa un entorno de desarrollo MVC (Modelo Vista Controlador) similar al Framework de Odoo, este framework se usa para el desarrollo de aplicaciones en PHP.

1.1. Instalación de LAMP

LAMP son las siglas de linux apache mysql php. Symfony necesita de un servidor LAMP para poder funcionar. A continuación veremos como instalar un servidor LAMP en nuestro sistema. En primer lugar instalaremos apache:
$ sudo apt-get install apache2

Posteriomente instalamos php:
$ sudo apt-get install php5 libapache2-mod-php5 php-cli php-mysql
y reiniciamos apache:
$ sudo service apache2 restart
por último instalamos mysql:
$ sudo apt-get install mysql-server mysql-client libmysqlclient-dev
durante el proceso de instalación nos pedirá que asignemos contraseña al usuario root de mysql.
Adicionalmente, podemos instalar también phpmyadmin para ayudarnos con la configuración de mysql:
$ sudo apt-get install phpmyadmin
y creamos un enlace simbólico para acceder:
$ sudo ln -s /usr/share/phpmyadmin /var/www
Ahora podremos acceder mediante la url 192.168.0.122/phpmyadmin.

1.2. Instalación de composer

Composer es un gestor de dependencias para un proyecto php. Para instalar composer primero debemos instalar curl
$ sudo apt-get install curl
Posteriomente instalamos composer:
$ curl -s https://getcomposer.org/installer | php
Si todo ha funcionado bien, en el directorio donde te encuentras veras un nuevo fichero llamado composer.phar. Para comprobar que se ha instalado correctamente, ejecuta el siguiente comando que muestra el menú de opciones de Composer:
$ php composer.phar
Instalar Composer de esta manera es correcto, pero te obliga a realizar una nueva instalación para cada proyecto Symfony2. Si tienes muchos proyectos, es mucho mejor que instales Composer de forma global en tu ordenador, para que todos los proyectos utilicen la misma versión de Composer.
Para instalar Composer globalmente, mueve el archivo composer.phar a algún directorio ejecutable del sistema, como por ejemplo:
$ sudo mv composer.phar /usr/local/bin/composer
Comprueba que todo funciona bien ejecutando el comando composer sin opciones desde cualquier directorio del sistema. La instalación global de Composer también facilita su mantenimiento, ya que sólo hay que ejecutar el siguiente comando para actualizar la versión de Composer de todos los proyectos:
$ sudo composer self-update

1.3. Instalación de Symfony

Gracias a composer la instalación de Symfony se reduce a un simple comando de consola:
php composer.phar create-project symfony/framework-standard-edition nuestra_ruta/ 2.3.6
por ejemplo:
php composer.phar create-project symfony/framework-standard-edition /home/user/openerp/ 2.3.6
En caso de haber instalado composer globalmente:
composer create-project symfony/framework-standard-edition nuestra_ruta/ 2.3.6
El proceso de instalación nos ira pidiendo los datos de configuración de nuestro servidor. Podemos introducirlos en el momento o introducirlos a mano en el fichero app/config/parameters.yml
Una vez instalado, hay que borrar el bundle AcmeDemo:
Eliminar carpeta AcmeBundle de src
Eliminar $bundles[] = new AcmeDemoBundleAcmeDemoBundle(); del fichero app/AppKernel.php
Eliminar bloque referente AcmeDemo en app/config/routing_dev.yml

2. Conectar Symfony con OpenErp

Ya tenemos instalado Symfony en nuestro sistema, ahora vamos a ver como realizar la conexión con nuestro OpenERP.

2.1. Crear bundle conexión OpenERP

Un bundle se Symfony es el equivalente de un módulo de OpenERP, contiene todos los ficheros que proporcionan una nueva funcionalidad a nuestra aplicación web.
Para generar un bundle, debemos ejecutar en el directorio de nuestro proyecto Symfony:
$ php app/console generate:bundle
Esto nos mostrara un asistente para generar nuestro bundle:
Bundle Namespace: Openerp/ConnectBundle
Bundle Name: ConnectBundle
Target directory: Pulsamos enter (valor por defecto)
Configuration format: yml
Do you want to generate the whole directory structure?: pulsamos enter (valor por defecto)
Do you confirm generator?: pulsamos enter (valor por defecto)
Confirm automatic update of your kernel?: Pulsamos enter (valor por defecto)
Si vamos a la carpeta src de nuestro proyecto, podremos ver como se ha generado el nuevo Bundle, OpenERP.

connect

2.2. Generar entidad datos OpenERP

Una opción de configuración que podemos utilizar para no tener que introducir los datos de conexión en cada acceso, es generar una entidad de conexión a OpenERP para almacenar los parámetros de conexión. Una entidad es un fichero php que se encarga de interactuar con la base de datos de nuestro proyecto.
Para generar esta entidad debemos ejecutar en el directorio de nuestro proyecto Symfony el siguiente comando:
$ php app/console doctrine:generate:entity
Esto nos mostrara un asistente para generar nuestra entidad:
The Entity shortcut name: ConnectBundle:OpenERP
Configuration format (yml, xml, php, or annotation) [annotation]: pulsamos enter 

New field name (press  to stop adding fields): server
Field type [string]: pulsamos enter
Field length [255]: 100

New field name (press  to stop adding fields): bda
Field type [string]: pulsamos enter
Field length [255]: 100

New field name (press  to stop adding fields): username
Field type [string]: pulsamos enter
Field length [255]: 100

New field name (press  to stop adding fields): password
Field type [string]: pulsamos enter
Field length [255]: 255

New field name (press  to stop adding fields): pulsamos enter

Do you want to generate an empty repository class [no]? No 

Do you confirm generation [yes]? Yes
Con esto ya hemos generado el código de nuestra endidad, el cual podremos ver en la carpeta Entity de nuestro bundle.
Si queremos mapear esta entidad con nuestra base de datos, debemos ejecutar el siguiente comando en la consola:
$ php app/console doctrine:schema:create
Una vez creada la entidad, podemos crear datos de conexión para nuestra entidad mediante el phpmyadmin indicando la url de nuestro servidor, la base de datos a la cual nos vamos a conectar, el usuario y la contraseña.

2.3. Generar controlador OpenERP

Un controlador es un fichero que incluye la funcionalidad de nuestro bundle. Normalmente un controlador accede a la entidad de nuestro bundle, para acceder a la información de nuestra base de datos, y devuelve una vista, que muestra en pantalla esta información. Vamos a generar un controlador nuevo para conectar a OpenERP.
El primer paso sería descargar la liberia de conexion a OpenERP de la siguiente url https://github.com/tejastank/openerp-php-connector e incluirla en la carpeta controller de nuestro bundle.
require_once __DIR__.'/openerp/openerp.class.php';
En este ejemplo la libreria de conexión a OpenERP se ha guardado en la carpeta openerp del controlador.
Con todo esto, podemos desarrollar nuestra conexión simple mediante el siguiente controlador:
<?php
    namespace OpenerpConnectBundleController;

    use SymfonyBundleFrameworkBundleControllerController;
    use OpenerpConnectBundleEntityOpenerp;
    use SymfonyComponentHttpFoundationRequest;

   require_once __DIR__.'/openerp/openerp.class.php';

   class DefaultController extends Controller
   {

       public function indexAction($name)
        {
           return $this->render('ConnectBundle:Default:index.html.twig', array('name' => $name));
       }

       public function loginAction(Request $request)
       {

           $openerp = new Openerp();
           $form = $this->createFormBuilder($openerp)
             ->add('username', 'text')
             ->add('password', 'password')
             ->getForm();

           if ($request->isMethod('POST')) 
           {
                $form->bind($request);
              if ($form->isValid()) 
              {
                    $em = $this->getDoctrine()->getManager();
                    $shop = $em->getRepository('ConnectBundle:Openerp')->findOneBy(array('id' => 1));
                 $rpc = new OpenERP();
                 $uid = $rpc->login($shop->getUsername(), $shop->getPassword(), $shop->getBda());
                 $name = $rpc->read(array($uid), array('name'), 'res.users');
                 return $this->render('ConnectBundle:Default:welcome.html.twig', array(
                    'name' => $name[0]['name'],));
              }
           }
          return $this->render('ConnectBundle:Default:login.html.twig', array(   
          'form' => $form->createView(),
            ));
       }
    }
Este controlador genera un formulario simple para introducir el usuario y contraseña de un usuario de OpenERP. Una vez validado el formulario, busca el nombre del usuario que se ha conectado y devuelve una página con el mensaje “Bienvenido” mas el nombre de este usuario.

Las vistas para este controlador son las que se devuelven en el return:
return $this->render('ConnectBundle:Default:login.html.twig', array('form' => $form->createView(),));
return $this->render('ConnectBundle:Default:welcome.html.twig', array('name' => $name[0]['name'],));
Y se deben crear en la carpeta Resources/views del bundle, conteniendo el siguiente código:
<!-- login.html.twig -->
<form action="{{ path('portada')}}" method="post" {{ form_enctype(form)}}>
{{ form_widget(form)}}
<input type="submit"/>
</form>
<!-- welcome.html.twig -->
<h1>Bienvenido {{ name}}</h1>
Por último, hay que crear el path del controlador. Para ello hay que añadir las siguientes líneas en el fichero routing.yml que se encuentra en la carpeta app/config de nuestro proyecto:
portada:
path: /
defaults: { _controller: ConnectBundle:Default:login}
Ahora si accedemos a 192.168.0.122/symfony/web/app_dev.php podremos ver nuestro formularío de acceso.

Con todo esto hemos conseguido generar un bundle de conexión a OpenERP que puede ser incluido en otros bundles facilitando con esto acceder a los datos de OpenERP.

3. Conexión OpenERP con Symfony

Symfony funciona como un servicio rest, el cual nos permite acceder a la información mediante una url que accede a un método definido en un controlador. A continuación veremos un ejemplo de como conectar OpenERP con Symfony.
En primer lugar vamos a crear un módulo de OpenERP que genere una vista con un boton que nos permita enviar todos los productos de nuestro sistema a Symfony.
Definimos la clase:
class symfony(osv.osv_memory):
 _name = 'symfony'
symfony()
Con su vista asociada:
<?xml version="1.0" encoding="UTF-8"?>
    <openerp>
        <data>
            <record id="sync_products_form" model="ir.ui.view">
                <field name="name">sync.products.form</field>
                <field name="model">symfony</field>
                <field name="type">form</field>
                <field name="arch"type="xml">
                    <form string = "Sync Products">
                        <button name="sync_products" string="Sync" type="object" icon="gtk-apply"/>
                    </form>
                </field>
           </record>
         <record id="action_sync_products" model="ir.actions.act_window">
              <field name="name">Sync Products</field>
              <field name="type">ir.actions.act_window</field>
              <field name="res_model">symfony</field>
              <field name="view_type">form</field>
              <field name="view_mode">form</field>
              <field name="view_id" ref="sync_products_form"/>
              <field name="target">new</field>
          </record>
          <menuitem id="menu_sync_product" name="Sync Products"
          parent="stock.menu_stock_product" sequence="6"
          action="action_sync_products"/>
      </data>
    </openerp>
Y el metódo de sincronización:
def sync_products(self, cr, uid, ids, context = None):
   product_obj = self.pool.get("product.template")
      product_ids = product_obj.search(cr, uid, [], context = context)
   products = []

   for product in product_obj.browse(cr, uid, product_ids, context = context):
       product_dict = {}
        product_dict['name'] = product.name
                product_dict['list_price'] = product.list_price
                product_dict['standard_price'] = product.standard_price
                product_dict['description'] = product.description
                products.append(product_dict)

    products_json = json.dumps(products)
    url = "http://192.168.0.122/symfony/web/app_dev.php/get_products"
        f = urllib2.urlopen(url, products_json)
    response = f.read()
    f.close()
Como podemos observar el método recupera todos los productos que tenemos en el sistema, los codifica en json y los envia al controlador get_products.
El siguiente paso seria definir este controlador en nuestro sistema Symfony:
public function get_productsAction()
{
    $em = $this->getDoctrine()->getManager(); 
    $products = json_decode($this->get('request')->getContent(), true);
        foreach ($products as $p)
       {
        $product = new Product();
                $product->setName($p['name']);
                $product->setListPrice($p['list_price']);
                $product->setStandardPrice($p['standard_price']);
                $product->setDescription($p['description']);
                $em->persist($product);
   }
   $em->flush();
      return new Response("ok");
}
Y añadirlo a nuestro routing.yml:
getProducts:
    path: /get_products
    defaults: { _controller: ConnectBundle:Default:get_products}
Como podemos observar en el código de nuestro controlador, existe una nueva entidad llamada Product que es la que se encarga de almacenar los productos. Para generarla utilizaremos la consola de Symfony:
$ php app/console doctrine:generate:entity

The Entity shortcut name: ConnectBundle:Product
Configuration format (yml, xml, php, or annotation) [annotation]: 
pulsamos enter

New field name (press  to stop adding fields): name
Field type [string]: 
pulsamos enter

Field length [255]: 
pulsamos enter

New field name (press  to stop adding fields): list_price
Field type [string]: decimal

New field name (press  to stop adding fields): standard_price
Field type [string]: decimal

New field name (press  to stop adding fields): description
Field type [string]: text

New field name (press  to stop adding fields): 
pulsamos enter

Do you want to generate an empty repository class [no]? 
pulsamos enter

Do you confirm generation [yes]? 
pulsamos enter
Por último, actualizamos el esquema de nuestra base de datos.
$ php app/console doctrine:schema:update --force
Con esto ya podemos ejecutar nuestro módulo de OpenERP y realizar la conexión que nos importara todos los productos.
productos

4. Conclusiones

Como hemos podido observar en este artículo, la conexión a OpenERP con Symfony es muy sencilla. Debemos incluir la librería de conexión de php a OpenERP en un nuevo bundle de conexión. Este nuevo bundle podra ser incluido en otros bundles facilitando con esto el acceso de Symfony a OpenErp.

En cuanto a la conexión de OpenErp con Symfony, también hemos podido comprobar que es bastante sencilla ya que Symfony actua como un servicio rest muy facil de acceder. Simplemente debemos llamar desde OpenErp al método de Symfony que queramos acceder.

En resumen, generar un nuevo proyecto web con Symfony que acceda a OpenERP es muy sencillo, lo cual nos permite generar proyectos como tiendas online mediante el respaldo de OpenERP.