Odoo 10 - Adding an Order Line Tree Field to Custo

2019-05-10 03:18发布

问题:

I would like to add an order line field with a tree view much like those found in the Sales and Repairs modules. In those modules, there is a nice section at the bottom of the form that allows you to enter products and prices in a list. I believe those are handled by the sale.order.line and mrp.repair.line models.

Here is a picture of what I am talking about: Sale Order Lines

My goal is to get something like this into my own custom module. I have tried:

  • Adding a One2many field with sale.order.line (sale_order_line = fields.One2many('sale.order.line', 'order_id', string='Order Lines',)). With a proper view, this line lets gives me almost what I want. However, when I try to save the record, it gives me a "Record does not exist or has been deleted" error.
  • Adding a One2many field with mrp.repair.line (mrp_repair_line = fields.One2many('mrp.repair.line', 'repair_id', 'Operation Lines', copy=True, readonly=False,)). Again, this almost works but it says "You have to select a pricelist in the Repair form ! Please set one before choosing a product" when I try to save the record.
  • Following this method to get the sale order lines to work with my module. I get a validation error when I try to save the record. It gives me a hint as to what is wrong (object with reference: Product Unit of Measure - product.uom), but I cannot solve this issue.
  • Creating my own order line model with its own field and One2many/Many2one relations based on code in the sales and mrp_repair modules. This actually allows me to save the record, but I cannot figure out how to add any more fields than just product_id (product_id = fields.Many2one('product.product', 'Product', required=False)).

Here is what I have done so far. I have commented out the fields showing my different attempts at coming up with a solution. The last two lines show my attempt at getting price and taxes to appear in my custom order lines.

models.py

from odoo import models, fields, api
from odoo.addons import decimal_precision as dp

class mymodule_base(models.Model):
    _name = 'mymodule.mymodule'
    _description = 'Order'

    # sale_order_line = fields.One2many('sale.order.line', 'order_id', string='Order Lines',)

    # mrp_repair_line = fields.One2many('mrp.repair.line', 'repair_id', 'Operation Lines', copy=True, readonly=False,)

    # custom_order_line = fields.One2many('mymodule.line', 'order_id', 'Operation Lines')

class mymodule_line(models.Model): # My custom order lines model
    _name = 'mymodule.line'
    _description = 'Order Line'

    order_id = fields.Many2one('mymodule.mymodule', 'Order')

    product_id = fields.Many2one('product.product', 'Product', required=False)

    # tax_id = fields.Many2many('account.tax', 'repair_operation_line_tax','repair_operation_line_id', 'tax_id', 'Taxes')

    # price = fields.Many2many('product.product', 'list_price', 'Price')

views.xml

<odoo>
    <data>
        <!-- FORM VIEW -->
        <record id="mymodule.form" model="ir.ui.view">
            <field name="name">MyModule Form</field>
            <field name="model">mymodule.mymodule</field>
            <field name="arch" type="xml">
                <notebook>
                    <!-- Order Lines -->
                    <page string="Order Lines">
                        <field name="sale_order_line">
                            <tree string="Order Lines" editable="bottom">
                                <field name="product_id"/>
                            </tree>
                        </field>
                    </page>
                </notebook>
            </field>
        </record>
    </data>
</odoo>

Where should I go from here? I would greatly appreciate any help.

EDIT Here are a few details about what I am trying to achieve with my order line. In my order line, I would like to have the following fields:

  • Product name
  • Product description
  • Product quantity
  • Product price
  • Taxes
  • Subtotal

Much like in the sale order line, I want defaults in the other fields to be set based on what is in the product name (product_id) field. For instance, based on the product selected, the price and taxes fields would be automatically filled in to reflect the price and taxes associated with that product. These fields would also need to be able to be modified easily as, for my particular needs, the price, taxes, and description may change depending on the situation. I have already tried to add the price and tax fields but I ran into issues. I could not figure out how to correctly default these fields to reflect what is already associated with each product.

回答1:

Firstly, reusing an existing model (sale.order.line or mrp.repair.line) for an unrelated model is a bad idea. Each model should have a specific purpose and only be used for that purpose. You haven't mentioned what your field will be used for, but typically I would suggest using your mymodule.line example.

Just to clarify, the type of field you're referring to is called a One2many field. It's just a group of records from another model (mymodule.line that are linked to a given record from the current model (mymodule.mymodule).

Typically, when you receive errors on saving a line on the One2many field, it's probably because a required field (for the mymodule.line model) is not set. This is the most likely reason you were getting errors with the first two attempts. It's typically hard to debug because the required field is either invisible or possibly not on the view at all.

I cannot figure out how to add any more fields than just product_id

You'll need to define all of the fields you want to have on your mymodule.line. What fields are you trying to add and what trouble are you having?



回答2:

I have found a solution.

In the following example, I use an onchange method to fill the description, price, and tax_id fields with the appropriate values and text based on the fields defined in the product being selected. Whenever the product_id field is changed, the previously mentioned fields automatically update with new information based on the newly selected product.

models.py

# -*- coding: utf-8 -*-

from odoo import models, fields, api
from odoo.addons import decimal_precision as dp

class mymodule_base(models.Model):
    _name = 'mymodule.mymodule' # model name
    _description = 'My Module'

    order_lines = fields.One2many('mymodule.line', 'line_id', 'Order Lines')

class mymodule_line(models.Model):
    _name = 'mymodule.line'
    _description = 'My Module Order Lines'

    line_id = fields.Many2one('mymodule.mymodule', string='Order') 

    product_id = fields.Many2one('product.template', string='Product') # Product name

    tax_id = fields.Many2many('account.tax', string='Taxes') # Product default taxes

    price = fields.Float(string='Price')

    description = fields.Text(string='Description')

    # Onchange method fills description, price, and tax_id fields based on product_id
    @api.onchange('product_id')
    def _onchange_product_id(self):
        self.description = self.product_id.description_sale # Fill description box from description_sale
        self.price = self.product_id.lst_price # Fill price box with default product price
        self.tax_id = self.product_id.taxes_id # Fill tax box with default tax (many2many)

views.xml

<record id="mymodule.form" model="ir.ui.view">
    <field name="name">My Module Form</field>
    <field name="model">mymodule.mymodule</field>
    <field name="arch" type="xml">
        <form>
            <sheet>
                <notebook>
                    <!-- Order Lines -->
                    <page string="Order Lines">
                        <field name="order_lines" mode="tree,kanban">
                            <tree string="Order Lines" editable="bottom">
                                <field name="product_id"/>
                                <field name="description"/>
                                <field name="price"/>
                                <field name="tax_id" widget="many2many_tags" domain="[('type_tax_use','=','sale')]"/>
                            </tree>
                        </field>
                    </page>
                </notebook>
            </sheet>
        </form>
    </field>
</record>

This works quite well for me, but if there is a better way of implementing this feature, I am open to suggestions. Thanks to travisw for pointing me in the right direction!