Tuesday, October 18, 2022

domain many2many fields in odoo 14


In this blog we will explain how to set domain many2many fields in Odoo 14

So let us say that we have four models (restaurants model, food category model, food model and orders model) the restaurant contains many categories, the category can contain many foods , as bellow 

 

class restaurants(models.Model):
    _name = "res.restaurants"
    category_ids = fields.Many2many('res.category', string="categories")
 

 

class Foods(models.Model):
    _name = "res.foods"
    category_id = fields.Many2one('res.category', string="Category")


class Orders(models.Model):
    _name = "res.orders"
    restaurant_id = fields.Many2one('res.restaurants', string="Restaurant")
    foods_ids = fields.Many2many('res.foods', string="Foods")


To create order the user must select the restaurant then select foods , but the system must show the food with category_id in  order.restaurant_id.category_ids

So we can do it by creating function in order model called on-change restaurant_id and this function will set the domain for foods , just as bellow

 

@api.onchange('restaurant_id')
    def _set_foods_domain(self):
        res = {}
        if self.restaurant_id:
            ids_lis = []
    
        food_ids = self.env['res.foods'].search([])
            for food_id in self.category_ids:
                if food_id.id in self.restaurant_id.mapped("category_ids").ids:
                    ids_lis.append(food_id.id)
            res['domain'] = {'food_ids': [('id', 'in', ids_lis)]}
        return res

ValueError: odoo.addons.web.__spec__ is None

 

I was trying to install Odoo 15 in Ubuntu 18.4, but when I was trying to run the odoo server I faced this error

 ValueError: odoo.addons.web.__spec__ is None

and to fix it just I run the command bellow 

sudo pip3 install Jinja2==2.10.1

 

amount in words in odoo 14

 


In this blog we will crate function to convert number amount to words in Odoo 14 

so the input of this function will be (amount as numbers, language code), and the output will be the amount as words , now let us create the function with the name amount_as_text()

def amount_as_text(self,amount,lang):
        text = _(str(self.currency_id.with_context(lang=lang).amount_to_text(amount)))
        return text

 

We can call the function in report templates with Arabic language as bellow

<t t-set="amount_text" t-value="o.amount_as_text(o.amount_total,'ar_001')"/>

Sunday, September 25, 2022

KSA E.Invoice Templates


This module provides 

(1) Six optional templates for KSA invoice
(2) custom options for the default demplate
(3) ability to design new template using GUI




Sunday, August 14, 2022

ModuleNotFoundError: No module named 'pdfkit'


When I was trying to run odoo server it was returning internal server error so I checked the log file and I found this error

ModuleNotFoundError: No module named 'pdfkit'

so to fix it install pdfkit by running the command bellow

sudo pip3 install pdfkit

odoo server wide modules

Odoo server wide modules are modules are supposed to provide features not necessarily tied to a particular database and they are loaded after running the server just as base and web modules , we can use this feature for example if we want to create login API with HTTP type , or API to return the databases list ...etc

How to define custom module as server wide module ?

First : if we are running the server from command line directly we must use --load with the running command 

eg : ./odoo-bin --addons-path='/opt/test/odoo-14.0/addons' --load=base,web,custom_web

Second : if we add odoo as service and created configuration file we can add server_wide_modules inside the configuration file 

eg :
[options]
; This is the password that allows database operations:
admin_passwd = master_admin@ssc
db_host = False
server_wide_modules = base,web,custom_web
db_port = False
db_user = test
db_password = False
addons_path = /opt/test/odoo/addons
logfile = /var/log/test/odoo-test.log
http_port = 8080
limit_request = 8192
limit_time_cpu = 600
limit_time_real = 120000

Tuesday, July 12, 2022

Bearer token authentication in odoo 14

 

In this blog we will explain how to create bearer token authentication in odoo 14 

first we have to know that we have 2 types of authentications in odoo

* Public Authentication 

* User Authentication

but we want to build APIs with the bearer token authentication so 

First : We have to inherit the ir.http model 

Second : create new class function with our authentication name _auth_method_auth_name , just as bellow 

import logging
from odoo.http import request
from odoo.exceptions import AccessDenied
import pprint
from odoo import api, http, models, tools, SUPERUSER_ID, _
from odoo.http import Response

_logger = logging.getLogger(__name__)

class IrHttp(models.AbstractModel):
    _inherit = 'ir.http'

    @classmethod
    def _auth_method_api_token(cls):
        headers = request.httprequest.environ
        api_token = headers.get("HTTP_AUTHORIZATION")
        api_token = str(api_token)
        token = api_token.replace("Bearer ","")
        user_token = token.replace("'","")
        check_user = 0

        if api_token and 'Bearer' in api_token:
            user_ids = request.env['res.users'].sudo().search([])
            for user in user_ids:
                if user_token == user.access_token:
                    check_user = 1
            if check_user != 0:
                return True
            else:
                raise AccessDenied()
        else:
            raise AccessDenied()

In this case we created bearer token authentication with the name api_token 

Third : use the new authentication 

Eg :
@http.route('/api_name, type='http', auth='api_token', methods=['POST'], csrf=False)

 

Monday, July 4, 2022

Change user password with function in odoo

In this blog we will explain how to change user password with function in odoo 

Example : 

    We created view with button that call wizard enable user to enter new password and click button to change his password with the new one , so this button must call python function that change his password and this function can be just as bellow 


def change_password(self,user_id,new_password):
        user = self.env['res.users'].search([('id','=',user_id)])
        user.sudo().write({'password':new_password})

Generate access token in odoo

In this blog we will explain how to generate access token in odoo for each user step by step , so 

1- create new class which is inherits res.users class

2- create new char field which will contain the token , and it must be compute field

3- create function to generate the token

as bellow 

from odoo import models, fields, api, _
import hashlib
import hmac
import base64
import string
import math, random
from passlib import pwd, hash


class ResUsers(models.Model):
    _inherit = 'res.users'

    access_token = fields.Char(string="Access Token", readonly=True, compute='generate_access_token')

    def generate_access_token(self):
        for rec in self:
            token = ""

            # first way
            # pre_token = rec.name+rec.login
            # token = hash.pbkdf2_sha512.hash(pre_token)

            # second way
            hash_object = hashlib.sha256(rec.password.encode())
            token = hash_object.hexdigest()

            rec.sudo().write({'access_token': token})


Create url for pdf file in odoo

 

In this blog we will explain how to create url for pdf file in odoo


for an example : we want to generate url for the pdf invoice , so we can create function that takes the invoice id and return the url for the pdf invoice as bellow 

 

from odoo import api , fields, models,SUPERUSER_ID,_

    def generate_pdf_invoice_url(self , invoice_id):

        # pdf = request.env.ref('module_name.report_action_id').with_user(SUPERUSER_ID)._render_qweb_pdf([invoice_id.id])
        pdf = request.env.ref('account.account_invoices').with_user(SUPERUSER_ID)._render_qweb_pdf([invoice_id.id])

        pdf_invoice = request.env['ir.attachment'].sudo().create({
            'name': invoice_id.name,
            'type': 'binary',
            'datas': base64.b64encode(pdf[0]),
            'store_fname': invoice_id.name,
            'res_model': 'account.payment',
            'res_id': invoice_id.id,
            'mimetype': 'application/x-pdf'
        })
        pdf_file_url + 'http://'+request.httprequest.__dict__['environ']['HTTP_HOST']+'/web/content/%s' % (pdf_invoice.id)
        
        return pdf_file_url
           

Create url for image in odoo


Let us say we are building an APIs for our odoo system and we have to build api to return the product data and we must return the product image as url so we can create function that generate this url as bellow

 

First :

 
@http.route(['/web/product_image',
        '/web/product_image/<int:rec_id>',
        '/web/product_image/<int:rec_id>/<string:field>',
        '/web/product_image/<int:rec_id>/<string:field>/<string:model>/'], type='http', auth="public")
    def content_image_partner(self, rec_id, field='image_128', model='product.template', **kwargs):
        return self._content_image(id=rec_id, model='product.template', field=field,
            placeholder='user_placeholder.jpg') 

 

 Second :

def _content_image(self, xmlid=None, model='ir.attachment', id=None, field='datas',
                       filename_field='name', unique=None, filename=None, mimetype=None,
                       download=None, width=0, height=0, crop=False, quality=0, access_token=None,
                       placeholder=None, **kwargs):
        status, headers, image_base64 = request.env['ir.http'].binary_content(
            xmlid=xmlid, model=model, id=id, field=field, unique=unique, filename=filename,
            filename_field=filename_field, download=download, mimetype=mimetype,
            default_mimetype='image/png', access_token=access_token)

        return Binary._content_image_get_response(
            status, headers, image_base64, model=model, id=id, field=field, download=download,
            width=width, height=height, crop=crop, quality=quality,
            placeholder=placeholder)

 

Third : 

def generate_product_image_url(self,product_id):
        img_url = ''
        # or we can set default image for each product as
        # img_url = 'http://'+request.httprequest.__dict__['environ']['HTTP_HOST']+'/module_name/static/src/img/default.png'
        request.env.cr.execute(
            "SELECT id FROM ir_attachment WHERE res_model='product.template' and res_id=%s",[product_id]
        )
        if request.env.cr.fetchone():
            img_url_pre = 'http://'+request.httprequest.__dict__['environ']['HTTP_HOST']+'/web/product_image/%s/image_1920/product.template' % product_id,
            img_url = img_url_pre[0]
                
        return img_url

Load image from binary file in odoo

 


In this blog we will give an example how to load image from binary file in odoo using http controller function

    so let us say that we made an integration with external api to get new customer data with is include image_file and we want to save this image into odoo database , so first we must create function that takes the image_file as an input and return the image as data (read the binary file), second we can pass the image data to image field in res.partner object in odoo to create new customer with image , and the function can be just as bellow 

 

def load_image_from_binary_file(self, file):
        return base64.b64encode(file.read())

Load image from url in odoo


In this blog we will give an example how to load image from url in odoo using http controller function

    so let us say that we made an integration with external api to get new customer data with is include image_url field and we want to save this image into odoo database , so first we must create function that takes the image_url as an input and return the image as data , second we can pass the image data to image field in res.partner object in odoo to create new customer with image , and the function can be just as bellow 

 

def load_image_from_url(self, url):
        data = base64.b64encode(requests.get(url.strip()).content).replace(b'\n', b'')
        return data

current url in odoo


 

if we want to get the server URL for the current odoo module we can get it as below
 

#for python model 

server_url = self.env['ir.config_parameter'].get_param('web.base.url')

 

#for http.controller

1/ from odoo.http import request

2/ server_url = request.env['ir.config_parameter'].get_param('web.base.url')

Saturday, April 16, 2022

TypeError: Object of type datetime is not JSON serializable

 

This error "TypeError: Object of type datetime is not JSON serializable" happens when we try to convert data with date time into json dictionary , so to fix this error we have to convert the data to string first then put it in the dictionary and then we can convert the dictionary to json format
...
for example if we want to create api with odoo to return the data for sale order , so we can put the sale order data as bellow 

order_data = {
            'id':order_id.id,
            'name':order_id.name,
            'customer':{'id':order_id.partner_id.id,'name':order_id.partner_id.name},
            'salesperson':{'id':order_id.user_id.id,'name':order_id.user_id.name},
            'date_order':str(order_id.date_order),
            'state':order_id.state,
            'products':order_products,
            'untaxed_amount':order_id.amount_untaxed,
            'total_tax': order_id.amount_tax,
            'total_amount':order_id.amount_total,
     }

return Response(json.dumps(order_data),headers=headers)

ssh

In this blog we will explain some commands to deal with remote server from ubuntu terminal using SSH

1: Connect to remote server using ssh by the command bellow 

     sudo ssh remote_user_name@remote_ip

 

2: Connect to remote server with key.pem using ssh by the command bellow

    sudo ssh remote_user_name@remote_ip -i /path/key.pem

 

3/ copy folder with it's content from the remote server to local device

    sudo scp -r remote_user@remote_server_ip:/opt/example /home/local_folder

    sudo scp -i /path/key.pem -r remote_user@remote_server_ip:/opt/example /home/local_folder

Odoo Invoice Qr code issues

There are two main issues must of us facing with the QR code in Odoo invoice & these issues are 1/ QR code displayed as broken image w...