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

Mostrando las entradas con la etiqueta python. Mostrar todas las entradas
Mostrando las entradas con la etiqueta python. Mostrar todas las entradas

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




miƩrcoles, 3 de junio de 2020

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.

lunes, 1 de julio de 2019

Facturación Electrónica CFDI 3.3 con Complemento de Pagos para Odoo 8, Odoo 9 y Odoo 10

Factura Electrónica CFDI 3.3 con Integración de Pagos Electrónicos
(Complemento de Pagos)


Introducción a Facturación Electrónica CFDI 3.3

La Migración de Esquemas de Facturación Electrónica CFDI 3.2 a 3.3 se presento a comienzos del Año 2016 el cual tiene como objetivo cambiar la factura electrónica con el uso de plantillas y catÔlogos, con la finalidad de tener uniformidad en los datos registrados y que permitan a la autoridad fiscal identificar al contribuyente emisor y el tipo de transacción, los periodos de emisión del CFDI y fundamentalmente las fechas y formas de pago de los CFDI.

Este nuevo esquema se presenta como Opcional a partir del 1ro de Julio y como Obligatorio a partir del 1ro de Diciembre.

Debido a este nuevo reto y al mismo tiempo Obligación Fiscal, nos dimos a la tarea de desarrollar esta Solución Integrada 100 % a Odoo desde la Versión 7 (OpenERP) hasta Odoo 10.

El proceso es bastante sencillo y transparente para los usuarios finales.

Dentro de los cambios principales observaremos los CatƔlogos:
  • Uso CFDI
  • Formas de Pago
  • MĆ©todos de Pago
  • Impuestos
  • Catalogo Productos/Servicios
  • Unidades de Medida
  • Códigos Postales
Para el Uso de Comercio Exterior:
  • Ciudades
  • Localidades
  • Colonias
  • Paises
  • Estados
  • Pedimentos
  • Aduanas
Podemos observar toda la funcionalidad en el siguiente vĆ­deo:


Localizacion Mexicana Odoo con Facturacion Electronica 3.3

Cualquier información: info@argil.mx


miƩrcoles, 18 de julio de 2018

Mejorar DesempeƱo de Odoo 8, 9 ,10 y 11 con PostgreSQL 10

Odoo Consultants

Mejorar el DesempeƱo de Odoo y Optimizar Consultas a la Base


Con la llegada de PostgreSQL 10, el rendimiento de Odoo puede aumentar beneficiandose de las nuevas funcionalidades como las funciones de consultas paralelas. Desde el lado de PostgreSQL, esta es una excelente noticia porque esto significa que muchas consultas SELECT operadas del lado del ORM de Odoo se pueden ejecutar mas rapido de lo que solian ser. Dentro de las ventajas encontramos:

  • Resultados mas rapidos en las consultas ( PostgreSQL mejora el desempeƱo hasta 32 veces mas rapida la respues que en versiones como 9.5)
  • Mejora los modos de Indexacion GIN, BRIN y B-tree.
  • Mejora la compresión de filas y tablas.
Sin embargo, cuando miramos el desempeƱo de Odoo, debemos entender que Odoo no tiene la capacidad para  utilizar estas funcionalidades de forma eficiente, ya que lo anterior implica 2 factores principales que estan ausentes en Odoo:

  • Una estrategia de indexación evolucionada orientada de acuerdo a los contenidos (Odoo solo maneja el tipo B-tree como estandar)
  • Capacidad para optimizar el Analisis de Indexación ( debe hacerse del lado de PostgreSQL y no es accesible del lado de Odoo)
En general, el cambiar las versiones de anteriores de PostgreSQL para migrar a las nuevas versiones sin realizar ajustes adecuados en su motor de base de datos y sus modelos de datos no proporcionarƔ ninguna mejora visible en tƩrminos de rendimiento y tiempos de consulta / respuesta.

Puedes verificar la relevancia y efiniencia del Indice desde el lado de PostgreSQL ejecutando el siguiente escript:


SELECT
schemaname,
relname,
idx_scan,
seq_scan,
cast(idx_scan AS numeric) / (idx_scan + seq_scan) AS idx_scan_pct
FROM pg_stat_user_tables WHERE (idx_scan + seq_scan)>0 ORDER BY idx_scan_pct;
Esto ayudara a mejorar la eficiencia de la indexación  en comparación con la lectura secuencial. Por supuesto, la idea es reducir los escaneos secuenciales tanto como sean posible, ya que consumen mas recursos y generan mas bloqueos de tablas / memoria / consumo de Procesamiento (CPU).

Fuente de Consulta:

lunes, 11 de junio de 2018

Agregar Formato a Campos Fecha Reportes Qweb Odoo

Formatear la salida de los Campos Fecha en Reportes Qweb Odoo



     Dentro de Odoo todo es manejado de forma central, la zona horaria, el formato de campos de tipo fecha, etc., esto normalmente ocasiona que se tengan que editar o modificar ciertos reportes para que utilicen nuestras particularidades, tal es el caso de los campos de tipo Fecha/Fecha Hora, en mexico la nomenclatura es dia-mes-aƱo de forma estandar odoo la envia aƱo-mes-dia, para corregir esto en los reportes basta con enviar las opciones para formatear la fecha.

Por ejemplo, yo tengo un reporte con el campo fecha de envio (send_date) la salida estandar de este campo en un reporte Qweb seria:

<span t-field="o.send_date" ></span>

Si agregamos el formato dd/mm/yyyy

<span t-field="o.send_date" t-options='{"format": "dd/MM/yyyy"}'></span>



Formato Fecha Hora:

       <span t-field="o.date_order" t-options='{"format":"dd-MM-yyyy hh:mm:ss"}'/>

Creacion de Codigos de Barra en Reportes Qweb Odoo

Inserción de Codigos de Barra en Reportes Qweb Odoo


En esta ocasión les vengo a brindar información acerca de los Codigos de barra en reportes Qweb y como generarlos, estos muchas veces nos son requeridos para reportes de Almacen, etc.

Dentro de los reportes Odoo encontramos todo lo necesario para generarlos, no es necesario integrar nadad "adicional" o computar nuestros campos binarios para generar estas imagenes, aunque conocer como se calculan tambiƩn es util.

Odoo nos permite generar imagenes de Codigo de barra de los siguientes tipos:
  • Codabar
  • Code11
  • Code128
  • EAN13
  • EAN8
  • Extended39
  • Extended93
  • FIM
  • I2of5
  • MSI
  • POSTNET
  • QR
  • Standard39
  • Standard93
  • UPCA
  • USPS_4State
Como una utileria adicional para los desarrolladores, Odoo aƱadio un previsualizador, el cual nos permite visualizar y generar nuestra imagen a partir de una URL, por ejemplo si visualizo en mi navegador:

http://localhost:10869/report/barcode/Code128/FURN001



Como podemos observar la URL se compone de la dirección /report/barcode/ + tipo de codigo + cadena a convertir


Automaticamente nos genera una imagen en codigo de barras.


Para insertarla en nuestro Reporte Qweb se realiza mediante la siguiente estructura:

<img t-if="o.product_id.barcode" 
    t-att-src="'/report/barcode/Code128/%s' % 'FURN001' "
                           style="width:100%;height:20%;" />

Podemos observar que utiliza la estructura mencionada anteriormente, podemos cambiar la cadena FURN001  para que sea tomada de forma dinamica colocando nuestra variable usada en el reporte por ejemplo, para tomar la referencia del Producto en mi reporte:

<img t-if="o.product_id.barcode" 
 t-att-src="'/report/barcode/Code128/%s' % o.product_id.default_code "
 style="width:100%;height:20%;" />

El resultado seria:


No se olviden dejar sus comentarios.

lunes, 21 de mayo de 2018

Creación de Campos con Precisión Decimal Dinamica en Odoo

Creación de Campos con Decimales Dinamicos




Un aspecto fundamental en la parte administrativa es la contable donde la presición decimal debe ser muy controlada, tanto en la generación de reportes como en la creación de algunos formularios.

Dentro de las muchas bondades que siempre describo en mis articulos, Odoo cuenta con una presición dinamica, esta precisón puede ser moderada por el usuario final (cliente), esto le ayudara a aumentar o disminuir el numero de decimales en Odoo de acuerdo a sus necesidades y sin tener que programar o editar el codigo fuente.

La precisión decimal la encontramos en el Menu Configuración --> Tenico --> Estructura de la Base de Datos --> Presición Decimal.

El primer paso es crear tu precisión Decimal mediante una vista XML.

<?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
import openerp.addons.decimal_precision as dp

class Accountinvoice(models.Model):
    _inherit = 'account.invoice'
    _name = 'account.invoice'
    
    invoice_discount_amount = fields.Float(digits=dp.get_precision('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, 1 de agosto de 2017

Localización Mexicana para Odoo 10

Adaptaciones Contables para MƩxico


Hola a todos, este pequeño Post es para anunciar la Localización Mexicana para la version 10 de Odoo, una cosa importante que quiero resaltar es que esta localizacion es compatible con la version Comunitaria y la Version Enterprise de Odoo, algunas de sus funcionalidades mas importantes son:
  • Contabilidad Electrónica
    • Catalogo de Cuentas XML
    • Balanza de Comprobación
    • Complementos XML
    • Plan de Cuentas
    • Auxiliares Contables
    • Polizas
  • Facturación Electrónica
  • DIOT
  • Catalogo de Cuentas JerĆ”rquico
  • Reportes IFRS
  • Reclasificacion de Impuestos
  • Periodos Fiscales y AƱos Fiscales
  • Mucho mas ....


Facturacion electronica CFDI 3.3 con complemento de Pagos:

https://poncesoft.blogspot.mx/2017/09/facturacion-electronica-cfdi-33-con.html


Cualquier información: info@argil.mx


martes, 4 de julio de 2017

Consulta de Fecha Actual a traves de la API de Odoo

Consulta de la Fecha Actual utilizando Odoo


    La API de Odoo incorpora en la clase fields la posibilidad de manipular los valores de los campos de tipo fecha/fecha hora, lo cual podemos utilizar para poder consultar la fecha actual en la zona horaria que deseemos:

Fields - Date

  • context_today Retorna la Fecha en Zona horaria del Usuario.
  • today Retorna la fecha del Sistema Operativo en un String
  • from_string Retorna una fecha desde un string a una instancia datetime.date() 
  • to_string rCaso contrario, devuelve una fecha en formato de texto desde una instancia de Fecha datetime.date()
Ejemplos GrĆ”ficos
>>> from openerp import fields

>>> adate = fields.Date()
>>> fields.Date.today()
'2014-06-15'
>>> fields.Date.context_today(self)
'2014-06-15'
>>> fields.Date.context_today(self, timestamp=datetime.datetime.now())
'2014-06-15'
>>> fields.Date.from_string(fields.Date.today())
datetime.datetime(2014, 6, 15, 19, 32, 17)
>>> fields.Date.to_string(datetime.datetime.today())
'2014-06-15'

Fields - Datetime

Los valores disponibles para fecha Hora son los siguientes:
  • context_timestamp Retorna la fecha y hora en formato de Zona Horaria del Usuario.
  • now Retorna la fecha y hora del Sistema Operativo
  • from_string Retorna la fecha y hora en formato de texto desde una instancia datetime.date
  • to_string Retorna una instancia de fecha en formato datetime.date desde una fecha de Texto.
Ejemplos GrƔficos:
>>> fields.Datetime.context_timestamp(self, timestamp=datetime.datetime.now())
datetime.datetime(2014, 6, 15, 21, 26, 1, 248354, tzinfo=<DstTzInfo 'Europe/Brussels' CEST+2:00:00 DST>)
>>> fields.Datetime.now()
'2014-06-15 19:26:13'
>>> fields.Datetime.from_string(fields.Datetime.now())
datetime.datetime(2014, 6, 15, 19, 32, 17)
>>> fields.Datetime.to_string(datetime.datetime.now())
'2014-06-15 19:26:13'

lunes, 3 de julio de 2017

Mensaje de Confirmación en la ejecución de Botones

Mensaje de Confirmación en funciones ejecutadas desde una Vista



    En la definición de Botones de Tipo Objeto podemos aƱadir un nuevo atributo el cual nos pedirĆ” una segunda confirmación para desencadenar el proceso que hayamos programado, el atributo es muy sencillo y tiene por nombre confirm mas el mensaje que deseamos enviar al Usuario, el fragmento es el siguiente:


<button name="mi_metodo_odoo" type="object" string="Ejecutar 
Proceso" confirm="Estas Seguro que deseas pulsar este Boton?" />

El Resultado durante la ejecución es la siguiente:


Como podemos observar existe una doble validación del botón para poder evitar algún click por accidente, este tipo de advertencias podrÔn utilizarse en procesos clave de nuestros desarrollos.




jueves, 20 de abril de 2017

Localización Mexicana para Odoo 8, Odoo 9 y Odoo 10

Adaptaciones Contables para México en cualquier Versión de Odoo


Hola a todos, este pequeño Post es para anunciar la Localización Mexicana para cualquier versión de Odoo (Odoo 8, Odoo 9 y Odoo 10), la cual incluye entre lo mas destacado:
  • Contabilidad Electrónica
    • Catalogo de Cuentas XML
    • Balanza de Comprobación
    • Complementos XML
    • Plan de Cuentas
    • Auxiliares Contables
    • Polizas
  • Facturación Electrónica
  • DIOT
  • Catalogo de Cuentas JerĆ”rquico
  • Reportes IFRS
  • Reclasificacion de Impuestos
  • Periodos Fiscales y AƱos Fiscales
  • Mucho mas ....



Facturacion electronica CFDI 3.3 con complemento de Pagos:

https://poncesoft.blogspot.mx/2017/09/facturacion-electronica-cfdi-33-con.html


Cualquier información: info@argil.mx


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, 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.