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
1<template id="sales_report" inherit_id="sale.report_saleorder_document">2 <xpath expr="//div[@id='informations']" position="replace">3 <div class="row mt-4 mb-4" id="informations">4 <div t-if="doc.client_order_ref" class="col-auto col-3 mw-100 mb-2" name="informations_reference">5 <strong>Your Reference:</strong>6 <p class="m-0" t-field="doc.client_order_ref"/>7 </div>8 <div t-if="doc.date_order" class="col-auto col-3 mw-100 mb-2" name="informations_date">9 <strong t-if="doc.state in ['draft', 'sent']">Quotation Date:</strong>10 <strong t-else="">Order Date:</strong>11 <p class="m-0" t-field="doc.date_order" t-options='{"widget": "date"}'/>12 </div>13 <div t-if="doc.validity_date and doc.state in ['draft', 'sent']" class="col-auto col-3 mw-100 mb-2" name="expiration_date">14 <strong>Expiration:</strong>15 <p class="m-0" t-field="doc.validity_date"/>16 </div>17 <div t-if="doc.user_id.name" class="col-auto col-3 mw-100 mb-2">18 <strong>Salesperson:</strong>19 <p class="m-0" t-field="doc.user_id"/>20 </div>21 <t t-set="qr_code_url" t-value="doc._get_qr_code_link_to_report()"/>22 <div class="col-2 align-items-center">23 <div>24 <img t-att-src="'data:image/png;base64,%s' % qr_code_url" style="width:150px;height:150px;"/>25 </div>26 </div>27 </div>28 </xpath>29</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
1from odoo import api, fields, models, _2import qrcode3import base644from io import BytesIO56class SaleOrderInherit(models.Model):7 _inherit = 'sale.order'89 def generate_qr(self, txt=''):10 qr_code = qrcode.QRCode(version=4, box_size=4, border=1)11 qr_code.add_data(txt)12 qr_code.make(fit=True)13 qr_img = qr_code.make_image()14 im = qr_img._img.convert("RGB")15 buffered = BytesIO()16 im.save(buffered, format="JPEG")17 img_str = base64.b64encode(buffered.getvalue()).decode('ascii')18 return img_str1920 def _get_qr_code_link_to_report(self):21 base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')22 current_id = self.id23 action_id = self.env.ref('sale.action_orders')24 menu_id = self.env.ref('sale.sale_menu_root')25 cids = self.env.company2627 if self.state != 'sent':28 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"29 else:30 base_url = f"{base_url}/sale-order?{self.name}"3132 base64_qr = self.generate_qr(base_url)33 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
1from odoo import http2from odoo.http import request34class SaleOrderController(http.Controller):56 @http.route(['/sale-order'], type='http', auth="user", website=True)7 def sale_order_state_controller(self, **kw):8 base_url = http.request.env['ir.config_parameter'].get_param('web.base.url')9 query_string = http.request.httprequest.query_string1011 sale_order = request.env['sale.order'].sudo().search([('name', '=', query_string)])12 sale_order.state = 'sale' # Update state to 'Sales Order'1314 current_id = sale_order.id15 action_id = request.env.ref('sale.action_orders')16 menu_id = request.env.ref('sale.sale_menu_root')17 cids = request.env.company1819 values = {20 'so_name': sale_order,21 '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"22 }23 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
1<template id="controller_template">2 <t t-call="website.layout">3 <div id="wrap">4 <div class="oe_structure">5 <section data-snippet-id="text-block" class="mb16">6 <div class="container">7 <div class="row">8 <div class="col-md-12 text-center mb16 message" data-snippet-id="colmd">9 <style>10 .message { margin-top: 100px; }11 .button a {12 background-color: #714B67;13 padding: 0.5rem 2rem;14 border-radius: 10px;15 text-decoration: none;16 color: white;17 }18 </style>19 <p><strong>Your Sale Order </strong>20 <span style="color:red" t-esc="so_name.name"/>21 has been moved to <strong t-esc="so_name.state"></strong>22 </p>23 <p>Do you want to redirect to the Sale Order?</p>24 <div class="button">25 <t t-set="url" t-value="so_url"/>26 <a t-attf-href="{{url}}">Yes</a>27 </div>28 </div>29 </div>30 </div>31 </section>32 </div>33 </div>34 </t>35</template>




How It Works
- When a user scans the QR code from the PDF, it redirects to a webpage based on the sale order state.
- If the sale order is in the "Quotation Sent" state, the user is taken to a confirmation page.
- Clicking "Yes" on the confirmation page redirects to the sale order form view in Odoo.
- 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.



