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, 21 de mayo de 2020

Solución al error con Nginx ssl_error_bad_cert_domain

Solución al Error ssl_error_bad_cert_domain


Si tenemos un error al configurar nuestro dominio nginx con letsencrypt se debe a que el certificado ssl requiere expandir a ambas url, para ello ejecutamos el comando:

 letsencrypt certonly --standalone -d midominio.mx -d www.midominio.mx


La configuración de nginx quedaria (midominio.mx) --> /etc/nginx/sites-enabled:

upstream oddo {
    server 127.0.0.1:8069;
}

server {
    listen      443 default;
    server_name midominio.mx www.midominio.mx;

    access_log  /var/log/nginx/oddo.access.log;
    error_log   /var/log/nginx/oddo.error.log;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/midominio.mx/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/midominio.mx/privkey.pem;
    keepalive_timeout   60;

    #ssl_ciphers             HIGH:!ADH:!MD5;
    #ssl_protocols           SSLv3 TLSv1;
    ssl_prefer_server_ciphers on;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    proxy_buffers 16 64k;
    proxy_buffer_size 128k;

    location / {
        proxy_pass  http://oddo;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_redirect off;

        proxy_set_header    Host            $host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto https;
        proxy_read_timeout 300000;

    }

    location ~* /web/static/ {
        proxy_cache_valid 200 60m;
        proxy_buffering on;
        expires 864000;
        proxy_pass http://oddo;
    }
}

server {
    listen      80;
    server_name midominio.mx www.midominio.mx;

    add_header Strict-Transport-Security max-age=2592000;
    rewrite ^/.*$ https://$host$request_uri? permanent;
}

domingo, 29 de marzo de 2020

Presicion Decimal en Odoo 13

Creación de Campos con Decimales Dinamicos




Como habíamos mencionado en post anteriores podemos definir una presicion dinÔmica que nos permita gestionar de forma modificable el no. de decimales para la definición de los campos en una clase.

<?xml version="1.0" encoding="UTF-8"?>
<odoo>
   <data>
  <!--  Mi presicion decimal-->

  <record model="decimal.precision" id="precision_discounts">
    <field name="name">Discount</field>
    <field name="digits">6</field>
  </record>  

   </data>
</odoo>

Al instalar nuestro modulo o actualizarlo, nos creara el registro correspondiente al XML:


El valor digits es el numero de decimales que tendra el campo que lo utilice como su presición decimal.

El paso final es asignar esta presición en la creación del campo en una clase Odoo.

# -*- coding: utf-8 -*-
from openerp.exceptions import UserError
from openerp import api, fields, models, _, tools

class Accountinvoice(models.Model):
    _inherit = 'account.invoice'
    _name = 'account.invoice'
    
    invoice_discount_amount = fields.Float(digits='Discount', 
                                string='Descuento Total en Monto')


En el ejemplo anterior herede facturas y cree mi campo llamado Descuento Total con 6 Decimales en su parte flotante, el campo se visualiza de la siguiente manera en el Sistema:

Si modificamos la presición decimal a 4.


Veriamos el campo actualizado y los registros anteriores redondeados al nuevo numero de decimales.

Una presición puede ser reutilzada muchas veces no es necesario crear una por cada campo a menos que el proceso lo requiera.

Espero que les ayude esta información y no se olviden dejar sus comentarios.




martes, 25 de febrero de 2020

Campo Binario B64 a Archivo Temporal Python

Binario B64 a Archivo Fisico Temporal


Ultimamente me han pedido desarrollar reportes en Excel, para esto me apoyo mucho de la libreria xlsxwriter o del modulo report_xlsx, pero muchas veces es necesario utilizar el logo dentro del reporte, en Qweb seria muy sencillo ya que la utilidad hace la conversión del binario, pero en mi caso no fue asi, existen 2 maneras de hacerlo metiendo la ruta fisica del archivo dentro de nuestro moulo o la segunda la cual vengo a enseñarles, guardar el campo a un archivo temporal, en el siguiente ejemplo cree 2 funciones para guardar el logo dato que requiero para dar formato a mi excel.


import tempfile
import base64
import binascii
import os

class ClaseOdoo(models.Model):
    _name = 'mi.clase'
    _inherit ='mi.clase'

    def b64str_to_tempfile(self, b64_str=None, file_suffix=None, file_prefix=None):
        """
        @param b64_str : Text in Base_64 format for add in the file
        @param file_suffix : Sufix of the file
        @param file_prefix : Name of file in TempFile
        """

        (fileno, fname) = tempfile.mkstemp(file_suffix, file_prefix)
        f = open(fname, 'wb')
        f.write(base64.decodestring(b64_str or ''))
        f.close()
        os.close(fileno)
        return fname



    def logo_b64_str_to_physical_file(self, b64_str, file_extension='png', prefix='company_logo'):

        certificate_lib = self.env['facturae.certificate.library']
        b64_temporal_route = self.b64str_to_tempfile(base64.encodestring(''), 
                                                          file_suffix='.%s' % file_extension, 
                                                          file_prefix='odoo__%s__' % prefix)
        _logger.info("\n### b64_temporal_route %s " % b64_temporal_route)
        ### Guardando el Logo  ###
        f = open(b64_temporal_route, 'wb')
        f.write(base64.b64decode(b64_str))
        f.close()
        file_result = open(b64_temporal_route, 'rb').read()
        return file_result, b64_temporal_route




Como paso final solo necesitamos el fragmento de codigo que llame a estas funciones:


        company_logo = self.env.user.company_id.logo
        print ("###### company_logo >>>>>>> ", company_logo)
        if company_logo:
            file_result_b64, logo_path_b64 = self.logo_b64_str_to_physical_file(company_logo, 'png', 'company_logo')
            print ("#### logo_path_b64 >>>>>>>> ",logo_path_b64)     
            image_module_path = logo_path_b64
        else:
            module_path = module.get_module_path('mi_modulo')
            #print "########## MODULE PATH >>> ",module_path
            image_module_path = module_path+'/static/img/logo.jpg'

miƩrcoles, 19 de febrero de 2020

Debug en Plantillas Qweb

Debug Qweb en Odoo


Como en el desarrollo de modulos y aplicaciones en Odoo podemos también debuggear nuestras plantillas una practica que nos puede llegar a ser muy util para conocer el momento exacto donde se genera o ejecuta una sentencia, funcion o se manada a ejecutar metodos dentro de nuestro reporte, esto nos facilita la resolución de muchos errores.

Lo unico que necesitamos agregar dentro de nuestro reporte es:



<t t-debug="pdb"/>


Con  ello podremos utilizar dentro de nuestro Debug Python con el metodo set_trace(), habilitamos dentro de nuestro registro de eventos el parametro --log-level=debug y por ultimo solo queda depurar nuestra plantilla XML con pdb.

Odoo Qweb manejo de Ciclos

Loops o Ciclos con




QWeb en Odoo es muy util al momento de realizar o ejecutar funcionalidades como Reportes, Archivos XML etc. todo esto basado en plantillas, pero existen muchas funcionalidades muy utiles que nos pueden ayudar a mejorar el diseƱo de nuestros Reportes, de las cuales les vengo a hablar en este post y son:


  • as_first
  • as_last
  • as_index

t t-foreach="['A','B','C','D','E']" t-as="item">
    <p t-if="item_first">
        Inicio
    </p>
    <p>
        Indice <t t-esc="item_index"/> y resultado <t t-esc="item"/>
    </p>
    <p t-if="item_last">
        Fin
    </p>
</t>

El resultado seria:

Inicio
Indice 0 y resultado A
Indice 1 y resultado B
Indice 2 y resultado C
Indice 3 y resultado D
Indice 4 y resultado E
Fin

Podemos deducir que las palabras clave as_first indica el inicio del loop, as_index el recorrido de nuestro ciclo y as_end si es el ultimo valor de nuestra lista.


martes, 18 de febrero de 2020

Acción Automatizada para Prevenir Registros Duplicados

Acción Automaticas Revisión de Registros



     En el Sistema Odoo existe un menu que muy pocos utilizamos debido a que no sabemos realmente como funciona y sobre todo como explotar todo el potencial que tiene para evitar desarrollar restricciones que serian mucho mas faciles registrar dentro de esta Funcionalidad del Sistema.

El menu tiene por nombre Acciones Automaticas o Automatizadas dentro del menu de Configuración de Odoo.


Primero Crearemos un registro nuevo con el nombre que nos permita identificarlo de manera mas facil.

Lo primero seria:
  • Nombre de la Regla o Acción
  • Modelo al cual Aplicar.
  • Ejecución en este caso al Crear y Actualizar.




Lo segundo es generar el Codigo Python que nos va permitir aplicar la regla o restricción, para ello pulsamos dentro de la Pestaña Opciones y agregamos una Acción en Python.


El Código seria:


if record.default_code:
   existing_product = env['product.template'].search(
[('id','!=',record.id),
('default_code','=',record.default_code)
])
   if existing_product:
     raise Warning("La Referencia Interna ya existe en 
                    otro Producto en el Sistema.!")


Espero que les sea de utilidad.

Actualizar Modulo en Multiples Bases de Datos - Odoo

Actualización de Modulos en multiples Bases de Datos




El dia de hoy traigo un Query que nos permite actualizar un modulo  en multiples Bases de Datos de Odoo corriendo en una misma instancia y versión de Odoo.

Script escrito en Bash con codigo Python:


#!/usr/bin/env python

from datetime import date
import subprocess, xmlrpclib, sys, os, psycopg2, pexpect

# Database info
db_user = 'odoo'
db_passwd = ''
db_host = 'localhost'
db_port = 5432
db_name = 'postgres'
oerp_conf = '/opt/odoo/odoo.conf'
oerp_bin = "/opt/odoo/odoo-bin"
module_to_upgrade = "modulo_a_actualizar"

today = date.today()
log_date = today.strftime('%Y%m%d')
log_name = "update-{}.log".format(log_date)
base_dir = os.getcwd()

with open(log_name, 'a+') as log_file:

  # Get list of databases
  db = psycopg2.connect(user=       db_user, 
                        password=   db_passwd,
                        host=       db_host,
                        port=       db_port,
                        database=   db_name)
  cr = db.cursor()
  cr.execute("select datname from pg_database where datdba=(select usesysid from pg_user where usename='{}') order by datname".format(db_user))
  dblist = [str(name) for (name,) in cr.fetchall()]

  for database in dblist:
    # Wait for server to upgrade database, then kill it
    print "Actualizando Base de Datos {}...".format(database)
    
    dbupdate_cmd = "{} shell -c {} --database={} --update={}".format(oerp_bin, oerp_conf, database, module_to_upgrade) 
    output = pexpect.spawn(dbupdate_cmd)
    try:
      # to catch this string loading.py was altered (line 461)
      output.expect('.*Modulos Cargados.', timeout=600)

    except pexpect.ExceptionPexpect as e:
      print "Se Agoto el tiempo de espera en la actualización {}. Intente actualizar Manualmente la Base de Datos con el comando '{}'.".format(database, dbupdate_cmd)
    output.kill(0)
    status = "Base de Datos Actualizada {}.".format(database)
    print status
    log_file.write(status + "\n")

Los Parametros principales a modificar son:

  • oerp_conf
    • Es la ruta del archivo de configuración de Odoo, normalmente se encuentra dentro de /etc/odoo/odoo-server.conf
  • oerp_bin
    • Ruta del programa de administración de Odoo, se encuentra dentro de la ruta de instalación del ERP.



Fuente: http://soft29.info/blog/entry/odoo-module-upgrade-on-multiple

lunes, 3 de febrero de 2020

Uso de CFDI en Punto de Venta - Facturación Electronica


POS - Uso de CFDI 

Odoo 13.0



El siguiente modulo nos permite seleccionar el Uso de CFDI con el cual generaremosl a Factura Electronica para nuestros clientes, dentro de las principales caracteristicas  del modulo que voy a presentarles podremos encontrar:


  • Selección de Uso de CFDI desde el Formulario de Clientes

  • Selección del USo de CFDI desde el Formulario de Clientes en el Punto de Venta.


  • Visualización al seleccionar clientes en el Punto de Venta

  • Como ultima funcionalidad automaticamente relaciona el Uso de CFDI del cliente al seleccionarlo dentro de Formulario de Facturación.

El modulo lo podran descargar desde:


Con el nombre pos_customer_uso_cfdi







miƩrcoles, 29 de enero de 2020

Funcion copy_from para Importar Tablas desde Archivos Excel (CSV)

Importar Archivos CSV desde Funciones Python en Odoo



Lo primero es conocer la función llamada copy_from la cual forma parte del cursor que podemos instanciar por medio de la linea:

self.env.cr.copy_from


Parametros Necesarios para la Función

  1. CSV: Archivo de Excel en formato csv con la información de la tabla.
  2. Tabla: Nombre de la tabla a la cual sera volcada la información del archivo.
  3. Separador: Simbolo separador de la inforamción del CSV ( , por ejemplo)
  4. Columnas: Columnas separadas por el simbolo del Archivo.


Ejecución del Metodo

Lo primero es instanciar el cursor, el cual se encuentra dentro del entorno o contexto general de la API de Odoo.

  1. Para instanciar el cursor utilizamos "self.env.cr" y para crear una tabla "self.env.cr.execute"
  2. AƱadir la Ruta del CSV
  3. Crear la estructura en un arreglo tipo lista con las columnas del CSV.
  4. Volcar el CSV utilizando la función  "self.env.cr.copy_from"
  5. Cerrar el Archivo CSV.

self.env.cr.execute(""" CREATE TABLE IF NOT EXISTS odooacademy(
fecha_nacimiento date, edad integer,
nombre_curso text,
nombre_completo text)""")
self.env.cr.commit()
csv_file= open(filepath,"r")
columns=['fecha_nacimiento','edad','nombre_curso','nombre_completo']
self.env.cr.copy_from(csv_file, 'odooacademy', sep=',', columns=columns)
self.env.cr.commit()
csv_file.close()
Gracias por visitar mi Blog. ;-)

martes, 28 de enero de 2020

Instalar Python 3.7 en Ubuntu 16.04

Paso 1 - Instalación de Python 3.7 mediante Repositorios Externos.

  • Actualizamos los Paquetes y Repositorios necesarios
apt update
sudo apt install software-properties-common
  • AƱadimos el Repositorio
sudo add-apt-repository ppa:deadsnakes/ppa
Note: Puede pedirte Enter pasa continuar.
  • Una vez que termine la actualización, instalamos el paquete con el comando:
sudo apt install python3.7
Comprobamos la versión instalada:
python3.7 --version

Paso 2 Actualizamos las Alternativas de Python

sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 2



Paso 3 - Selecciona la opción Principal

sudo update-alternatives --config python3




Step 4 - Probar el Resultado

python3 -V

Notas:
Debemos instalar lo siguiente:

  • sudo apt-get install python3-pip
  • sudo apt-get install python3.7-sqlalchemy
  • sudo apt-get install python3.7-dev
  • sudo pip3 install --upgrade --force-reinstall setuptools