Changing Sale Order State via QR Code Scan in Odoo 17
In this approach, we leverage Odoo's controller functionality to establish a connection between a URL and a webpage.

In this approach, we leverage Odoo’s controller functionality to establish a connection between a URL and a webpage.

Adding a QR Code to the Sale Order PDF

First, we extend the sale order report template to embed a QR code in the generated PDF:

xml

<template id="sales_report" inherit_id="sale.report_saleorder_document">
    <xpath expr="//div[@id=’informations’]" position="replace">
        <div class="row mt-4 mb-4" id="informations">
            <div t-if="doc.client_order_ref" class="col-auto col-3 mw-100 mb-2" name="informations_reference">
                <strong>Your Reference:</strong>
                <p class="m-0" t-field="doc.client_order_ref"/>
            </div>
            <div t-if="doc.date_order" class="col-auto col-3 mw-100 mb-2" name="informations_date">
                <strong t-if="doc.state in [‘draft’, ‘sent’]">Quotation Date:</strong>
                <strong t-else="">Order Date:</strong>
                <p class="m-0" t-field="doc.date_order" t-options='{"widget": "date"}’/>
            </div>
            <div t-if="doc.validity_date and doc.state in [‘draft’, ‘sent’]" class="col-auto col-3 mw-100 mb-2" name="expiration_date">
                <strong>Expiration:</strong>
                <p class="m-0" t-field="doc.validity_date"/>
            </div>
            <div t-if="doc.user_id.name" class="col-auto col-3 mw-100 mb-2">
                <strong>Salesperson:</strong>
                <p class="m-0" t-field="doc.user_id"/>
            </div>
            <t t-set="qr_code_url" t-value="doc._get_qr_code_link_to_report()"/>
            <div class="col-2 align-items-center">
                <div>
                    <img t-att-src="’data:image/png;base64,%s’ % qr_code_url" style="width:150px;height:150px;"/>
                </div>
            </div>
        </div>
    </xpath>
</template>

The QR code will contain a dynamically generated URL based on the sale order’s state:

  • If the sale order is in the “Quotation Sent” state, the QR code will link to a custom webpage.
  • For other states, scanning the QR code will redirect to the sale order form view.

Generating the QR Code in Odoo

We extend the sale.order model to generate QR codes dynamically:

python

from odoo import api, fields, models, _
import qrcode
import base64
from io import BytesIO

class SaleOrderInherit(models.Model):
_inherit = ‘sale.order’

def generate_qr(self, txt=”):
qr_code = qrcode.QRCode(version=4, box_size=4, border=1)
qr_code.add_data(txt)
qr_code.make(fit=True)
qr_img = qr_code.make_image()
im = qr_img._img.convert("RGB")
buffered = BytesIO()
im.save(buffered, format="JPEG")
img_str = base64.b64encode(buffered.getvalue()).decode(‘ascii’)
return img_str

def _get_qr_code_link_to_report(self):
base_url = self.env[‘ir.config_parameter’].sudo().get_param(‘web.base.url’)
current_id = self.id
action_id = self.env.ref(‘sale.action_orders’)
menu_id = self.env.ref(‘sale.sale_menu_root’)
cids = self.env.company

if self.state != ‘sent’:
base_url = f"{base_url}/web#id={current_id}&cids={cids.id}&menu_id={menu_id.id}&action={action_id.id}&model=sale.order&view_type=form"
else:
base_url = f"{base_url}/sale-order?{self.name}"

base64_qr = self.generate_qr(base_url)
return base64_qr

Handling QR Code Redirection via Controller

When the QR code is scanned and the URL contains /sale-order, a controller will be triggered to update the sale order’s state:

python

from odoo import http
from odoo.http import request

class SaleOrderController(http.Controller):

@http.route([‘/sale-order’], type=’http’, auth="user", website=True)
def sale_order_state_controller(self, **kw):
base_url = http.request.env[‘ir.config_parameter’].get_param(‘web.base.url’)
query_string = http.request.httprequest.query_string

sale_order = request.env[‘sale.order’].sudo().search([(‘name’, ‘=’, query_string)])
sale_order.state = ‘sale’ # Update state to ‘Sales Order’

current_id = sale_order.id
action_id = request.env.ref(‘sale.action_orders’)
menu_id = request.env.ref(‘sale.sale_menu_root’)
cids = request.env.company

values = {
‘so_name’: sale_order,
‘so_url’: f"{base_url}/web#id={current_id}&cids={cids.id}&menu_id={menu_id.id}&action={action_id.id}&model=sale.order&view_type=form"
}
return request.render("testmodule.controller_template", values)

Custom Web Page for Sale Order State Update

The following template displays a confirmation message when the sale order state is updated and provides a redirection button:

xml

<template id="controller_template">
<t t-call="website.layout">
<div id="wrap">
<div class="oe_structure">
<section data-snippet-id="text-block" class="mb16">
<div class="container">
<div class="row">
<div class="col-md-12 text-center mb16 message" data-snippet-id="colmd">
<style>
.message { margin-top: 100px; }
.button a {
background-color: #714B67;
padding: 0.5rem 2rem;
border-radius: 10px;
text-decoration: none;
color: white;
}
</style>
<p><strong>Your Sale Order </strong>
<span style="color:red" t-esc="so_name.name"/>
has been moved to <strong t-esc="so_name.state"></strong>
</p>
<p>Do you want to redirect to the Sale Order?</p>
<div class="button">
<t t-set="url" t-value="so_url"/>
<a t-attf-href="{{url}}">Yes</a>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
</t>
</template>

How It Works

  1. When a user scans the QR code from the PDF, it redirects to a webpage based on the sale order state.
  2. If the sale order is in the “Quotation Sent” state, the user is taken to a confirmation page.
  3. Clicking “Yes” on the confirmation page redirects to the sale order form view in Odoo.
  4. The sale order state is updated to “Sales Order” automatically.

This implementation enables seamless state updates and navigation for sales orders via QR code scanning.