Skip to Content
Odoo Menu
  • Prijavi
  • Try it free
  • Aplikacije
    Finance
    • Knjigovodstvo
    • Obračun
    • Stroški
    • Spreadsheet (BI)
    • Dokumenti
    • Podpisovanje
    Prodaja
    • CRM
    • Prodaja
    • POS Shop
    • POS Restaurant
    • Naročnine
    • Najem
    Spletne strani
    • Website Builder
    • Spletna trgovina
    • Blog
    • Forum
    • Pogovor v živo
    • eUčenje
    Dobavna veriga
    • Zaloga
    • Proizvodnja
    • PLM
    • Nabava
    • Vzdrževanje
    • Kakovost
    Kadri
    • Kadri
    • Kadrovanje
    • Odsotnost
    • Ocenjevanja
    • Priporočila
    • Vozni park
    Marketing
    • Družbeno Trženje
    • Email Marketing
    • SMS Marketing
    • Dogodki
    • Avtomatizacija trženja
    • Ankete
    Storitve
    • Projekt
    • Časovnice
    • Storitve na terenu
    • Služba za pomoč
    • Načrtovanje
    • Termini
    Produktivnost
    • Razprave
    • Odobritve
    • IoT
    • Voip
    • Znanje
    • WhatsApp
    Third party apps Odoo Studio Odoo Cloud Platform
  • Industrije
    Trgovina na drobno
    • Book Store
    • Trgovina z oblačili
    • Trgovina s pohištvom
    • Grocery Store
    • Trgovina s strojno opremo računalnikov
    • Trgovina z igračami
    Food & Hospitality
    • Bar and Pub
    • Restavracija
    • Hitra hrana
    • Guest House
    • Beverage Distributor
    • Hotel
    Nepremičnine
    • Real Estate Agency
    • Arhitekturno podjetje
    • Gradbeništvo
    • Estate Management
    • Vrtnarjenje
    • Združenje lastnikov nepremičnin
    Svetovanje
    • Računovodsko podjetje
    • Odoo Partner
    • Marketinška agencija
    • Law firm
    • Pridobivanje talentov
    • Audit & Certification
    Proizvodnja
    • Tekstil
    • Metal
    • Pohištvo
    • Hrana
    • Brewery
    • Poslovna darila
    Health & Fitness
    • Športni klub
    • Trgovina z očali
    • Fitnes center
    • Wellness Practitioners
    • Lekarna
    • Frizerski salon
    Trades
    • Handyman
    • IT Hardware & Support
    • Sistemi sončne energije
    • Izdelovalec čevljev
    • Čistilne storitve
    • HVAC Services
    Ostali
    • Neprofitna organizacija
    • Agencija za okolje
    • Najem oglasnih panojev
    • Fotografija
    • Najem koles
    • Prodajalec programske opreme
    Browse all Industries
  • Skupnost
    Learn
    • Tutorials
    • Dokumentacija
    • Certifikati
    • Šolanje
    • Blog
    • Podcast
    Empower Education
    • Education Program
    • Scale Up! Business Game
    • Visit Odoo
    Get the Software
    • Prenesi
    • Compare Editions
    • Releases
    Collaborate
    • Github
    • Forum
    • Dogodki
    • Prevodi
    • Become a Partner
    • Services for Partners
    • Register your Accounting Firm
    Get Services
    • Find a Partner
    • Find an Accountant
    • Meet an advisor
    • Implementation Services
    • Sklici kupca
    • Podpora
    • Upgrades
    Github Youtube Twitter Linkedin Instagram Facebook Spotify
    +1 (650) 691-3277
    Get a demo
  • Določanje cen
  • Pomoč

Odoo is the world's easiest all-in-one management software.
It includes hundreds of business apps:

  • CRM
  • e-Commerce
  • Knjigovodstvo
  • Zaloga
  • PoS
  • Projekt
  • MRP
All apps
You need to be registered to interact with the community.
All Posts People Badges
Ključne besede (View all)
odoo accounting v14 pos v15
About this forum
You need to be registered to interact with the community.
All Posts People Badges
Ključne besede (View all)
odoo accounting v14 pos v15
About this forum
Pomoč

infinite loop with on_change?

Naroči se

Get notified when there's activity on this post

This question has been flagged
on_change
5 Odgovori
13086 Prikazi
Avatar
vgze

Hello, I try add a on_change on two fields (fields A and fields B). I wand that:

  • if user change the fields A that aumaticaly change the fileds B.
  • if user change the fields B that aumaticaly change the fileds A.

I take the 2 events and they work. But when I launch theim together, infinite loop.

It is possible to take what I want to do?

edit:

sale_perso.py:

def price_unit_change(self, cr, uid, ids, price_unit, product):
    result = {}
    if product:
        product_obj = self.pool.get('product.product')
        product_obj = product_obj.browse(cr, uid, product)
        result['coeff'] = price_unit / product_obj.standard_price 
    return {'value': result}

def coeff_change(self, cr, uid, ids, coeff, standard_price):
    result = {}
    result['price_unit'] = coeff * standard_price
    return {'value': result}

sale_perso_view.xml: <openerp> <data>

    <record model="ir.ui.view" id="sale_order_line_type_price">
        <field name="name">sale.order.line.type.price</field>
        <field name="model">sale.order</field>
        <field name="inherit_id" ref="sale.view_order_form"/>
        <field name="arch" type="xml">
           <xpath expr="//field[@name='order_line']/tree//field[@name='price_unit']" position="replace">
                <field name="price_unit"  on_change="price_unit_change(price_unit, product_id)"/>
           </xpath>
           <xpath expr="//field[@name='order_line']/tree//field[@name='price_unit']" position="before">
                <field name="standard_price"/>
                <field name="coeff"  on_change="coeff_change(coeff, standard_price)"/>
            </xpath>
        </field>
    </record>
</data>
</openerp>
0
Avatar
Opusti
ainur rofiq

fields A and B will always have the same value.
on_change event is triggered when focused loses, pressing TAB or ENTER.
Please post your on_change method and XML on_change field. thanks

ainur rofiq

When you change A then on_change(A) is triggered to change B = A. Now B is changed, then on_changed(B) is triggered to change A. At this point there is no change for A, so on_change(A) is not triggered. So there is no infinite loop.

Avatar
Adrian Merrall
Best Answer

Hi,

If you have an on_change on field A that returns

{'value': {'B': new_value,},}

This will then trigger an on_change on B and if this returns

{'value': {'A': new_value,},}

which will trigger the on_change on A and around we go.

A couple of thoughts here:

  1. 6.1 or older, add a hidden field to the form and pass/return that into the on_change events so your on_change event terminates if the hidden field is set.
  2. Version 7 - use the context. In on_change A, set a flag in the context to say it has just run. In the on_change for B, if the flag is in the context, remote it and terminate rather than re-setting A.

In Version 7, just pass the context in your XML like this:

<field name="A" on_change="a_change(A, context) />

HTH,

Adrian, Auckland, NZ

enter code here
1
Avatar
Opusti
Avatar
vgze
Avtor Best Answer

I never used the context dictionnary. I try but, the problem is still here.

sale_perso.py:

def price_unit_change(self, cr, uid, ids, price_unit, product, context):
    result = {}
    lang = context.get('lang',False)
    if context.get('cancel_event',False):
        context = {'lang': lang, 'cancel_event': False}
    else:
        context = {'lang': lang, 'cancel_event': True}
        if product:
            product_obj = self.pool.get('product.product')
            product_obj = product_obj.browse(cr, uid, product)
            result['coeff'] = price_unit / product_obj.standard_price 
    return {'value': result}

def coeff_change(self, cr, uid, ids, coeff, product, context):
    result = {}
    lang = context.get('lang',False)
    if context.get('cancel_event',False):
        context = {'lang': lang, 'cancel_event': False}
    else:
        context = {'lang': lang, 'cancel_event': True}
        if product:
            product_obj = self.pool.get('product.product')
            product_obj = product_obj.browse(cr, uid, product)
            result['price_unit'] = coeff * product_obj.standard_price 
    return {'value': result}

sale_perso_view.xml:

  <?xml version="1.0"?>
    <openerp>
    <data>
       <record model="ir.ui.view" id="sale_order_line_type_price">
        <field name="name">sale.order.line.type.price</field>
        <field name="model">sale.order</field>
        <field name="inherit_id" ref="sale.view_order_form"/>
        <field name="arch" type="xml">
           <xpath expr="//field[@name='order_line']/tree//field[@name='price_unit']" position="replace">
                <field name="price_unit"  on_change="price_unit_change(price_unit, product_id, context)"/>
            </xpath>
           <xpath expr="//field[@name='order_line']/tree//field[@name='price_unit']" position="after">
                <field name="type_price"/>
            </xpath>
           <xpath expr="//field[@name='order_line']/tree//field[@name='price_unit']" position="before">
                <field name="list_price"/>
                <field name="prixmat"/>
                <field name="standard_price"/>
                <field name="coeff"  on_change="coeff_change(coeff, product_id, context)"/>
            </xpath>
           <xpath expr="//field[@name='order_line']/tree//field[@name='name']" position="after">
                <field name="marque"/>
            </xpath>
        </field>
    </record>
    </data>
    </openerp>
0
Avatar
Opusti
Avatar
Christophe Combelles
Best Answer

Hi, I was able to reproduce the issue an found no obvious way to do so. So I entered a new bug report #1203343 (sorry, no "karma" to post the full link :-/)

0
Avatar
Opusti
Avatar
Edison Ibáñez
Best Answer

I had the same problem, solved it updating the context before checking if the previous value was modified

def onchange_comision_value(self, cr, uid, ids, comision, context):
    res = {}
    ctx = dict(context)
    ctx.update
    if context.get('cancel_event', False):
        ctx.update({'cancel_event': False,})
    else:
        ctx.update({'cancel_event': True,})
        for i in self.browse(cr,uid,ids):
            aux_percent = ( comision * 100 ) / i.amount_untaxed
            res['comision_percent'] = aux_percent
    return {'value': res}

def onchange_comision_percent(self, cr, uid, ids, comision_percent, context):
    res = {}
    ctx = dict(context)
    ctx.update
    if context.get('cancel_event', False):
        ctx.update({'cancel_event': False,})
    else:
        ctx.update({'cancel_event': True,})
        for i in self.browse(cr,uid,ids):
            aux_comision = ( i.amount_untaxed * comision_percent ) / 100
            res['comision'] = aux_comision
    return {'value': res}

<field name='comision_percent' class="oe_custom_input  oe_inline" nolabel="1" on_change="onchange_comision_percent(comision_percent, context)" /> %% 
 <field name='comision' string='Comision' class="oe_inline" widget='monetary' options="{'currency_field': 'currency_id'}" on_change="onchange_comision_value(comision, context)" />

I hope that even you need

Greetings.

0
Avatar
Opusti
Avatar
Edison Ibáñez
Best Answer

the solution for your problem, here in the module fleet epecificamente in part:

    def on_change_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
    #need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
    #make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
    #liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
    #of 3.0/2=1.5)
    #If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine
    #onchange. And in order to verify that there is no change in the result, we have to limit the precision of the 
    #computation to 2 decimal
    liter = float(liter)
    price_per_liter = float(price_per_liter)
    amount = float(amount)
    if liter > 0 and price_per_liter > 0 and round(liter*price_per_liter,2) != amount:
        return {'value' : {'amount' : round(liter * price_per_liter,2),}}
    elif amount > 0 and liter > 0 and round(amount/liter,2) != price_per_liter:
        return {'value' : {'price_per_liter' : round(amount / liter,2),}}
    elif amount > 0 and price_per_liter > 0 and round(amount/price_per_liter,2) != liter:
        return {'value' : {'liter' : round(amount / price_per_liter,2),}}
    else :
        return {}

def on_change_price_per_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
    #need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
    #make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
    #liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
    #of 3.0/2=1.5)
    #If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine
    #onchange. And in order to verify that there is no change in the result, we have to limit the precision of the 
    #computation to 2 decimal
    liter = float(liter)
    price_per_liter = float(price_per_liter)
    amount = float(amount)
    if liter > 0 and price_per_liter > 0 and round(liter*price_per_liter,2) != amount:
        return {'value' : {'amount' : round(liter * price_per_liter,2),}}
    elif amount > 0 and price_per_liter > 0 and round(amount/price_per_liter,2) != liter:
        return {'value' : {'liter' : round(amount / price_per_liter,2),}}
    elif amount > 0 and liter > 0 and round(amount/liter,2) != price_per_liter:
        return {'value' : {'price_per_liter' : round(amount / liter,2),}}
    else :
        return {}

def on_change_amount(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
    #need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
    #make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
    #liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
    #of 3.0/2=1.5)
    #If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine
    #onchange. And in order to verify that there is no change in the result, we have to limit the precision of the 
    #computation to 2 decimal
    liter = float(liter)
    price_per_liter = float(price_per_liter)
    amount = float(amount)
    if amount > 0 and liter > 0 and round(amount/liter,2) != price_per_liter:
        return {'value': {'price_per_liter': round(amount / liter,2),}}
    elif amount > 0 and price_per_liter > 0 and round(amount/price_per_liter,2) != liter:
        return {'value': {'liter': round(amount / price_per_liter,2),}}
    elif liter > 0 and price_per_liter > 0 and round(liter*price_per_liter,2) != amount:
        return {'value': {'amount': round(liter * price_per_liter,2),}}
    else :
        return {}

there is this doing the same thing you wantthe solution for your problem, here in the fleet module

0
Avatar
Opusti
Enjoying the discussion? Don't just read, join in!

Create an account today to enjoy exclusive features and engage with our awesome community!

Prijavi
Related Posts Odgovori Prikazi Aktivnost
How to use On change function? Solved
on_change
Avatar
Avatar
Avatar
Avatar
10
jun. 16
34062
Lines Functional values how to shows before saving the record
on_change
Avatar
Avatar
1
okt. 15
10186
Two on_change methods for the same field
on_change
Avatar
Avatar
4
avg. 15
4414
How to make an on_change event for a one2many related field
on_change
Avatar
Avatar
1
mar. 15
5486
how to use on_change attribute ?
on_change
Avatar
1
mar. 15
4640
Community
  • Tutorials
  • Dokumentacija
  • Forum
Open Source
  • Prenesi
  • Github
  • Runbot
  • Prevodi
Services
  • Odoo.sh Hosting
  • Podpora
  • Nadgradnja
  • Custom Developments
  • Izobraževanje
  • Find an Accountant
  • Find a Partner
  • Become a Partner
About us
  • Our company
  • Sredstva blagovne znamke
  • Kontakt
  • Zaposlitve
  • Dogodki
  • Podcast
  • Blog
  • Stranke
  • Pravno • Zasebnost
  • Varnost
الْعَرَبيّة Català 简体中文 繁體中文 (台灣) Čeština Dansk Nederlands English Suomi Français Deutsch हिंदी Bahasa Indonesia Italiano 日本語 한국어 (KR) Lietuvių kalba Język polski Português (BR) română русский язык Slovenský jazyk slovenščina Español (América Latina) Español ภาษาไทย Türkçe українська Tiếng Việt

Odoo is a suite of open source business apps that cover all your company needs: CRM, eCommerce, accounting, inventory, point of sale, project management, etc.

Odoo's unique value proposition is to be at the same time very easy to use and fully integrated.

Website made with

Odoo Experience on YouTube

1. Use the live chat to ask your questions.
2. The operator answers within a few minutes.

Live support on Youtube
Watch now