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

miƩrcoles, 8 de julio de 2020

Instalar Python-Pip Ubuntu 20.04/18.04

Instalación de Python PIP en Ubuntu 20.04


Solución al Error E: Unable to locate package python-pip



sudo apt-get install software-properties-common
sudo apt-add-repository universe
sudo apt-get update
sudo apt-get install python-pip

Instalación Alternativa

sudo add-apt-repository universesudo apt update sudo apt install python2
Usamos curl para descargar el get-pip.py script:
curl https://bootstrap.pypa.io/get-pip.py --output get-pip.py
Una ves descargado el script lo instalamos:
sudo python2 get-pip.py

jueves, 2 de julio de 2020

Tabla HTML a Imagen con Python

Codigo HTML volcado a una imagen con Python


https://pypi.org/project/imgkit/



EJEMPLO:


import imgkit

body = """
<html>
  <head>
    <meta name="imgkit-format" content="png"/>
    <meta name="imgkit-orientation" content="Landscape"/>
  </head>
  Hello World!
  </html>
"""

imgkit.from_string(body, 'out.png')


EJEMPLO CON UNA TABLA:




body_html="""
<style type="text/css">
.tg  {border-collapse:collapse;border-color:#aabcfe;border-spacing:0;}
.tg td{background-color:#e8edff;border-color:#aabcfe;border-style:solid;border-width:1px;color:#669;
  font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:15px 15px;word-break:normal;}
.tg th{background-color:#b9c9fe;border-color:#aabcfe;border-style:solid;border-width:1px;color:#039;
  font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-0lax{text-align:left;vertical-align:top}
</style>
<table class="tg">
<tbody>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
  <tr>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
    <td class="tg-0lax"></td>
  </tr>
</tbody>
</table>
"""


imgkit.from_string(body_html, '/tmp/tabla.png')


Para Ajustar el tamaƱo de la Imagen podemos enviar el parƔmetro options:


options = {'width': 350, 'disable-smart-width': ''}

imgkit.from_string(body_html, '/tmp/tabla.png', options=options)


La librerĆ­a depende de la utilidad WKHTMLTOPDF asi que asegurense de tenerla instalada antes de descargarla.


sudo apt-get install wkhtmltox




jueves, 25 de junio de 2020

AƱadir Firmas en Reportes Qweb Odoo

Firmas en Reporte Qweb


    Es muy comĆŗn que algunos documentos puedan ser requeridos con firmas de autorización o responsables o la firma de la recepción del cliente en un AlbarĆ”n, esto es muy sencillo a continuación voy a emplear un ejemplo hecho en el reporte de Licitaciones:



<template id="report_purchaserequisitions_signatures" inherit_id="purchase_requisition.report_purchaserequisitions">
        <xpath expr="//div[@class='oe_structure'][2]" position="after">
           <div style="position:absolute;top:850px; page-break-inside: avoid;">
                <table border="0" style="border-collapse:collapse;color:000000;width:100%" cellpadding="3" cellspacing="3">
                   <tr>
                        <td class="text-center">
                            <strong style="font-size:12px;">Responsable</strong>
                        </td>
                          <td class="text-center">
                              <strong style="font-size:12px;">Autorizó</strong>
                          </td>
                    </tr>
                    <tr>
                         <td><br/></td>
                         <td><br/></td>
                     </tr>
                    <tr>
                        <td class="text-center">________________________</td>
                        <td class="text-center">________________________</td>
                    </tr>
                    
                     <tr>
                        <td class="text-center">
                            <strong style="font-size:12px;"><span t-field="o.user_id.partner_id"/></strong>
                        </td>
                        <td class="text-center">
                            <strong style="font-size:12px;"><span t-field="o.user_approved_id.partner_id"/></strong>
                        </td>
                     </tr>
                </table>
                        
            </div>
        </xpath>
    </template>

En el ejemplo anterior de autorización lo mas importante es mencionar que el campo user_approve_id es un campo añadido por medio de herencia de clases y este valor se ingresa al confirmar una Licitación.

El estilo empleado:


style="position:absolute;top:850px; page-break-inside: avoid;"

Tiene como función que las firmas aparezcan al final del documento

jueves, 18 de junio de 2020

Install OpenJDK 11 Linux - Instalar OpenJDK 11 en Linux

Step 1 – Search OpenJDK Packages

OpenJDK packages are available under native apt repositories. You can simply use apt-cache search command to search the available java version for your Ubuntu system.
apt-cache search openjdk
As per above output, you can see openjdk-11-* and openjdk-8-* is available in the package manager.

Step 2 – Install JAVA (OpenJDK)

Use the below command to install OpenJDK on your Debian based systems using the package manager from the default repository. The below commands will install Java Development Kit (JDK) and Java Runtime Environment (JRE) both on your system. You can install JRE package only to setup Runtime Environment only.
OpenJDK 11
sudo apt-get install openjdk-11-jre openjdk-11-jdk
OpenJDK 8
sudo apt-get install openjdk-8-jre openjdk-8-jdk

viernes, 12 de junio de 2020

Campos solo lectura en grupos especificos

Como visualizar campos en solo lectura dependiendo de un grupo de usuarios



Lo primero es crear tu grupo:


    <record id="purchase_fields_readonly" model="res.groups"> 

        <field name="name">Compras - Campos en solo lectura</field>

    </record>

Posterior heredar tu vista  y poner dentro de la vista heredada los grupos que podrĆ”n visualizarla:


      <record model="ir.ui.view" id="purchase_fields_readonly">
        <field name="name">purchase.order</field>
        <field name="model">purchase.order</field>
        <field name="inherit_id" ref="purchase.purchase_order_form"/>
        <field name="groups_id" eval="[(6, 0, [ref('purchase_readonly_fields.purchase_fields_readonly') ])]" />                
        <field name="arch" type="xml">
            <xpath expr="//field[@name='order_line']/tree/field[@name='date_planned']" position="attributes">
                <attribute name="context">{'readonly_by_pass': True}</attribute>
                <attribute name="readonly">1</attribute>
                <attribute name="required">False</attribute>
            </xpath>
        </field>
      </record>

Del resto se encarga Odoo al renderizar las vistas por usuario y los permisos de acceso a determinadas vistas.

sƔbado, 6 de junio de 2020

Mineria del archivo log de Odoo

Comando para obtener información del archivo de registro (log)




Alguna ves te has visto en la necesitad de saber quien elimino ciertos registros de una tabla en el sistema Odoo, esto no lo podemos conocer en una base de datos de postgres o no sin tener los conocimientos avanzados que nos permitan realizar una consulta o una configuración dentro del gestor de base de datos ya que Odoo no guarda esa información dentro del sistema, una opción muy facil es utilizar nuestro archivo log, para ello podemos utilizar el siguiente comando:



find /var/log/odoo/odoo-server.log -exec grep 'deleted mail.message' '{}' +


Lo mas importante dentro del comando es el mensaje que queremos buscar dentro de nuestro archivo log, por ejemplo quien elimino los registros de la tabla de  mensajerĆ­a, esto al final arrojara tanta información de acuerdo al tamaƱo de nuestra base de datos, podemos minimizar los registros aƱadiendo mas filtros a la bĆŗsqueda como por ejemplo un periodo de x a y fechas:



viernes, 5 de junio de 2020

Separar parte numƩrica de una secuencia establecida

Separar la parte numƩrica y cadena en un valor de secuencia



     El titulo suena un poco extraƱo lo se, pero la idea principal es tratar de separar la parte numerica dentro de una secuencia o una cadena de caracteres, esto lo tuve que realizar para una modificación dentro de Odoo para obtener el folio y la secuencia, para lograrlo solo utilize una expresión regular que espero les pueda servir:




            #### Division Caracteres y Enteros ####

            import re

            folio_invoice = 'FAC04445'
            expresion_re = re.compile("([a-zA-Z]+)([0-9]+)")
            m_re = expresion_re.match(folio_invoice)
            group_1 = m_re.group(1)
            group_2 = m_re.group(2)



Alternativa:


temp_string = "Hi my age is 32 years and 250 days12"
print(temp_string)

numbers = [int(temp)for temp in temp_string.split() if temp.isdigit()]

print(numbers)

Resultado:

Hi my age is 32 years and 250 days12
[32, 250]

Mi función Final:

 
def get_split_integer_part( cadena):
    cadena = cadena.replace('-',' ').replace('/',' ').replace('_',' ').replace('*',' ').replace('+',' ')
    numbers = [int(temp)for temp in cadena.split() if temp.isdigit()]
    if not numbers:
        expresion_re = re.compile("([a-zA-Z]+)([0-9]+)")
        m_re = expresion_re.match(cadena)
        try:
            group_1 = m_re.group(1)
            group_2 = m_re.group(2)
            numbers = [group_2]
        except:
            expresion_re = re.compile("([0-9]+)([a-zA-Z]+)")
            m_re = expresion_re.match(cadena)
            try:
                group_1 = m_re.group(1)
                group_2 = m_re.group(2)
                numbers = [group_1]
            except:
                numbers = []
    if not numbers:
        return [0]
    return numbers

jueves, 4 de junio de 2020

Validar un rango de fechas en Odoo por medio de atributos en la vistas

Restricción en periodo de fechas




     Dentro de Odoo muchas veces requerimos tener un asistente que nos obtenga información dentro de un periodo establecido por el usuario o para determinar la validez de un documento dentro del mismo periodo. Al realizar este tipo de modificaciones o asistentes muchas veces descartamos o llegamos a ignorar la validación del periodo que el usuario introduce que en ocasiones puede ser un Bug que no permita la funcionalidad correcta al buscar información, una solución simple seria aƱadir un constraint para que por medio de python validarĆ­amos la información pero dentro de las mismas vistas podemos determinar esta validación sin programar nada adicional.

La sintaxis es la siguiente:

<field name="start_date" widget="daterange" options='{"related_end_date": "end_date"}'/>


El parĆ”metro o campo start_date hace referencia a nuestra fecha inicial y para la fecha final tenemos end_date


Para realizar la validacion basta con aƱadir las opciones que podemos visualizar en la sintaxis:

options='{"related_end_date": "end_date"}'

Recordemos que start_date y end_date son los nombres con los cuales generamos los campos en Odoo, pero no es obligatorio que se llamen exactamente como en el ejemplo.

Desabilitar Fines de Semana en campos Fecha Odoo

No permitir la selección de fines de semana en campos de tipo fecha



Existe un atributo dentro de Odoo que nos permite restringir la selección de fines de semana en campos de tipo fecha, lo cual nos deja lo que conocemos como días hÔbiles L-V pero que puede ser configurado de acuerdo a lo requerido.

El ejemplo seria:

options='{"datepicker": {"daysOfWeekDisabled": [0, 6]}}'

Dentro del campo de fecha de expiación en las cotizaciones, al seleccionar un día L - V no tendríamos problemas:


Pero al seleccionar por ejemplo el dĆ­a sabado:

Como vemos el icono de bloqueo no dejarĆ­a seleccionar el dĆ­a que no esta permitido.


Como observamos en la imagen el parametro tiene por nombre daysOfWeekDisabled


miƩrcoles, 3 de junio de 2020

Consulta SQL en Odoo implementando nuestra Zona horaria

Consulta SQL en Odoo corrigiendo el error de la zona horaria en el resultado de la consulta de un periodo



     La siguiente Consulta SQL resuelve el error de la Zona Horario Odoo, como sabran la base de datos se encuentra en UTC o zona horaria central por lo cual visualmente dentro del sistema se realiza la conversión a la zona horaria del usuario y se muestra correctamente, pero en base de datos podemos tener una diferencia en campos fecha/hora, por lo cual al realizar una consulta esta puede abarcar un periodo que no es correcto, para ello lo unico que requerimos es dentro de la conulta convertir la columna de fecha/hora a nuestra zona horaria, para este ejemplo utilizare la zona horaria de Mexico UTC-6.

Las librerias que utilizaremos son:


from datetime import timedelta, datetime



La clave esta en convertir la columna fecha/hora a UTC-6

   

        start_period = self.date_start + " 00:00:01"
        start_period_strp = datetime.strptime(start_period, '%Y-%m-%d %H:%M:%S')
        start_period_tz = fields.Datetime.context_timestamp(self, 
        timestamp=start_period_strp)
        end_period = self.date_stop + " 23:59:59"
        end_period_strp = datetime.strptime(end_period, '%Y-%m-%d %H:%M:%S')
        end_period_tz = fields.Datetime.context_timestamp(self, 
        timestamp=end_period_strp)
        get_list_contacts_partner = self.get_parners_list(self.supplier_id)

        product_list = []


        cr.execute("""

            insert into supplier_puchase_detail_record(  supplier_id,

                                                        product_id,

                                                        uom_id,

                                                        qty_total,

                                                        qty_available

                                                        )

            select  %s,

                    stock_move.product_id,

                    stock_move.product_uom,

                    sum(stock_move.product_uom_qty),

                    0.0

            from stock_move

                 join stock_picking

                   on stock_move.picking_id = stock_picking.id

                 join purchase_order_line

                   on purchase_order_line.id = stock_move.purchase_line_id

            where stock_picking.partner_id in %s

            and (stock_picking.date_done at time zone 'UTC-6') between %s and %s

            group by stock_move.product_id, stock_move.product_uom

           

            """, (self.supplier_id.id,
                  tuple(get_list_contacts_partner), 
                  start_period_tz, end_period_tz))