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

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))

Nginx SSL - ERR_SSL_PROTOCOL_ERROR - No se puede conectar por SSL (Solución)

Solución al error con Nginx ERR_SSL_PROTOCOL_ERROR




139857146823744:error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:../ssl/record/rec_layer_s3.c:1528:SSL alert number 80


El error esta en la configuración de nuestro sitio nginx, para ser exactos en el apartado de configuración ssl debemos modificar y de ser necesario cambiar o reemplazar los sig. parÔmetros:


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


TEST de CONEXION SSL



openssl s_client -connect jlbelleza.es:443 -servername midominio.mx


El parƔmetro midominio.mx es el sitio al cual se estƔn conectando e implementando el certificado SSL.

Implementando STP con Python

Como utilizar SFTP desde Python


El fragmento para poder copiar un archivo a un servidor sftp es el siguiente:
import paramiko
import os

paramiko.util.log_to_file('logfile.log')

host = "101.102.103.104"
port = 22
transport = paramiko.Transport((host, port))
password = "pass"
username = "user"
transport.connect(username = username, password = password)


sftp = paramiko.SFTPClient.from_transport(transport)

filepath = '~/remote/file'
localpath = '~/local/file'
sftp.get(filepath, localpath)

sftp.close()
transport.close()

Espero que les sea de utilizad.

Solucion al error con la libreria sassc: error: no such option: --stdin ()

Solución al error con la libreria sassc
error: no such option: --stdin




Solución al Error:
sassc: error: no such option: --stdin

Line 13 in 3c11cf9
libsass==0.12.3

Como verÔn la solución es la versión de la librería.

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;
}