0

Odoo community version 11.0-20190311

I have a parent class (dt_tst001) with a o2m field (itens) related to a class (dt_tst002), with another o2m field (tributos) related to a third class (dt_tst003).

In the parent class there is another field (seguro_total) and when its value is changed I need to start a recalculation (_upd_seguro) of field (seguro) in the second class and fields (base_calculo, valor_tributo) in the third class.

The recalculation in the second class is working, but not in the third one.

Debuging step by step the values are updated but when checking the form, it shows the original values, and this values are sent to the database.

Sample code:

class DT_TST001(models.Model):
    _name = "dt_tst001"
    _rec_name = "documento"

    documento = fields.Char(string = "Documento", size = 9, required = True)
    seguro_total = fields.Float(string = "Seguro total")
    itens = fields.One2many("dt_tst002", inverse_name = "documento_id", required = True)

    @api.onchange('seguro_total')
    def _upd_seguro(self):
        for item in self.itens:
            item.update({
                'seguro' : ((item.quantidade * item.valor_unitario) / item.valor_total) * self.seguro_total})

            for tributo in item.tributos:
                tributo.update({'base_calculo' : (item.valor_total + item.seguro)})
                tributo.update({'valor_tributo' : (item.valor_total + item.seguro) * tributo.aliquota / 100})


class DT_TST002(models.Model):
    _name = "dt_tst002"
    _rec_name = "documento_id"

    documento_id = fields.Many2one("dt_tst001", string = "Documento", required = True, ondelete='cascade')
    produto_id = fields.Char(string = "Produto", size = 15, required = True)
    quantidade = fields.Float(string="Quantidade", default = 0.00)
    valor_unitario = fields.Float(string="Valor unitário", required = True, default = 0.00)
    valor_total = fields.Float(string="Valor total", required = True, default = 0.00)
    seguro = fields.Float(string="Seguro", compute='_recalc_impostos', store=True)
    tributos = fields.One2many("dt_tst003", inverse_name = "item_id")

    @api.onchange('quantidade', 'valor_unitario', 'seguro')
    def _upd_valor_total(self):
        self.valor_total = (self.quantidade * self.valor_unitario) + self.seguro


class DT_TST003(models.Model):
    _name = "dt_tst003"

    item_id = fields.Many2one("dt_tst002", string = "Ítem", required = True, ondelete='cascade')
    tributo_id = fields.Char(string = "Tributo", size = 15, required = True)
    base_calculo = fields.Float(string = "Base de cálculo")
    aliquota = fields.Float(string = "Alíquota")
    valor_tributo = fields.Float(string = "Valor do tributo")

    @api.multi
    def name_get(self):
        result = []
        for m_tst003 in self:
            name = m_tst003.item_id.documento_id._name + " - " + m_tst003.item_id._name + " - " + m_tst003.tributo_id._name
            result.append((m_tst003.id, name))
        return result

Sample view definition:

<odoo>
    <data>
        <!-- VIEWS PARA NOTAS DE ENTRADA -->
        <record model="ir.ui.view" id="tst001_form">
            <field name="model">dt_tst001</field>
            <field name="name">tst001_form</field>
            <field name="arch" type="xml">
                <form string="Documento de entrada">
                    <group colspan="1" style="margin: 0px">
                        <field name="documento" style="text-transform: uppercase;"/>
                        <field name="seguro_total"/>
                    </group>
                    <notebook>
                        <page string="Ítens">
                            <group>
                                <h6>
                                    <field name="itens" context="{'form_view_ref' : 'dt_tst.tst002_form',
'tree_view_ref' : 'dt_tst.tst002_tree',
'default_itens' : itens}" force_save="1" class="oe_horizontal_separator oe_clear"/>
                                </h6>
                            </group>
                        </page>
                    </notebook>
                </form>
            </field>
        </record>

        <record model="ir.ui.view" id="tst001_tree">
            <field name="model">dt_tst001</field>
            <field name="name">tst001_tree</field>
            <field name="arch" type="xml">
                <tree string="Documentos de entrada">
                    <field name="documento"/>
                    <field name="seguro_total"/>
                </tree>
            </field>
        </record>

        <!-- ITENS -->
        <record model="ir.ui.view" id="tst002_form">
            <field name="model">dt_tst002</field>
            <field name="name">tst002_form</field>
            <field name="arch" type="xml">
                <form string="Ítem de documento de entrada">
                    <group style="margin: 0px">
                        <group colspan="4" style="margin: 0px">
                            <field name="produto_id"/>
                        </group>
                        <group colspan="4" style="margin: 0px">
                            <group style="margin: 0px">
                                <field name="quantidade"/>
                            </group>
                            <group style="margin: 0px">
                                <field name="valor_unitario"/>
                            </group>
                            <group colspan="4" style="margin: 0px">
                                <field name="valor_total" readonly="1" options='{"always_reload": True}' />
                            </group>
                        </group>
                        <group colspan="4" style="margin: 0px">
                            <field name="seguro"/>
                        </group>
                        <field name="valor_total" invisible="1"/>
                    </group>
                    <notebook>
                        <page string="Tributos">
                            <group>
                                <h6>
                                    <field name="tributos" context="{'form_view_ref' : 'dt_test.tst003_form',
'tree_view_ref' : 'dt_test.tst003_tree',
'default_tributos' : tributos,
'default_valor_total' : valor_total}" force_save="1" class="oe_horizontal_separator oe_clear"/>
                                </h6>
                            </group>
                        </page>
                    </notebook>
                </form>
            </field>
        </record>

        <record model="ir.ui.view" id="dt_fis.tst002_tree">
            <field name="model">dt_tst002</field>
            <field name="name">tst002_tree</field>
            <field name="arch" type="xml">
                <tree string="Ítens de documentos de entrada">
                    <field name="produto_id"/>
                    <field name="quantidade"/>
                    <field name="valor_unitario"/>

                    <!-- Enviar campos invisíveis para que seu conteúdo seja resgatado no formulário -->
                    <field name="seguro" invisible="1"/>
                    <field name="tributos" invisible="1"/>
                </tree>
            </field>
        </record>

        <!-- VIEWS PARA DOCUMENTOS DE ENTRADA E SAÍDA -->
        <record model="ir.ui.view" id="tst003_form">
            <field name="model">dt_tst003</field>
            <field name="name">tst003_form</field>
            <field name="arch" type="xml">
                <form string="Tributos de ítem de documento fiscal">
                    <sheet>
                        <group>
                            <field name="tributo_id"/>
                            <field name="base_calculo"/>
                            <field name="aliquota"/>
                            <field name="valor_tributo"/>
                        </group>
                    </sheet>
                </form>
            </field>
        </record>

        <record model="ir.ui.view" id="tst003_tree">
            <field name="model">dt_tst003</field>
            <field name="name">tst003_tree</field>
            <field name="arch" type="xml">
                <tree string="Tributos de ítem de documento fiscal">
                    <field name="tributo_id"/>
                    <field name="base_calculo"/>
                    <field name="aliquota"/>
                    <field name="valor_tributo"/>
                </tree>
            </field>
        </record>

        <record model="ir.actions.act_window" id="dt_test.tst001_action">
            <field name="name">Documentos de entrada - teste</field>
            <field name="res_model">dt_tst001</field>
            <field name="view_mode">tree,form</field>
            <field name="view_type">form</field>
            <field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('tst001_tree')}),
(0, 0, {'view_mode': 'form', 'view_id': ref('tst001_form')})]"/>
            <field name="view_type">form</field>
        </record>

        <menuitem name="Documentos de entrada" id="dt_test.tst001_menu" parent="dt_test.tst_menu_registros" action="dt_test.tst001_action" sequence="10"/>
    </data>
</odoo>

Thank you!

kerbrose
  • 1,095
  • 2
  • 11
  • 22

1 Answers1

0

well, it seems in the second class it is working because seguro field of class DT_TST002 is computed based on _recalc_impostos function. it doesn't use on_change. one more thing to note, is there are no relation between class DT_TST001 & DT_TST003.

according to your comment the on_change method would be like the following:

@api.onchange('seguro_total')
    def _upd_seguro(self):
        for item in self.itens:
            seguro = ((item.quantidade * item.valor_unitario) / item.valor_total) * self.seguro_total
            tributes = []
            for tributo in item.tributos:
                base_calculo = (item.valor_total + item.seguro)
                valor_tributo = (item.valor_total + item.seguro) * tributo.aliquota / 100
                tributes.append((1, tributo.id, {'base_calculo' : base_calculo, 'valor_tributo' : valor_tributo}))
            item.update({
                'seguro' : seguro
                'tributos' : tributes,
                })

also, please note that you can deal with relational fields as following

(0, 0,  { values })    link to a new record that needs to be created with the given values dictionary
(1, ID, { values })    update the linked record with id = ID (write *values* on it)
(2, ID)                remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well)
(3, ID)                cut the link to the linked record with id = ID (delete the relationship between the two objects but does not delete the target object itself)
(4, ID)                link to existing record with id = ID (adds a relationship)
(5)                    unlink all (like using (3,ID) for all linked records)
(6, 0, [IDs])          replace the list of linked IDs (like using (5) then (4,ID) for each ID in the list of IDs)
kerbrose
  • 1,095
  • 2
  • 11
  • 22
  • The dt_tst003 class is not directly related to dt_tst001 class. It represents taxes that are related to items of a invoice (dt_tst002). The field seguro_total (dt_tst001) is a value that is suposed to be distributed proportionaly between the dt_tst002 instances, in the field seguro. This field seguro will participate in the base value to calculate the valor_tributo (dt_tst003). Anyway I am trying to follow your advice. Thanks for the rapid answer. – Wallace Muniz Sep 07 '20 at 23:56
  • Hello. Unfortunately it's not working yet. As a example, suppose in the first moment a invoice is filled. Then an item, with quantidade=1 and valor_unitario=500. Then a tribute is created with base_calculo=500. Save the tribute and invoice item. The user could inform some value to field seguro_total=30, for example, in the invoice. On this moment a recalculation must update the seguro=30 (wich is happening) for the item and base_calculo of the tribute to 530, (wich is not happening). Thank you again. – Wallace Muniz Sep 08 '20 at 15:24
  • I'm sorry, I don't get it. – kerbrose Sep 09 '20 at 06:16