In search view filter by related one2many field - odoo

I have inherited account.account model and added a move_ids One2many field related to account.move.line model:
class ViewSumasYSaldos(models.Model):
_inherit = "account.account"
moves_ids = fields.One2many('account.move.line', 'account_id', string="Account moves")
So now I need, in a search view, filter by date field from moves_ids. Is there any way to do this?
I need something like this:
<search>
<field string="Year" filter_domain="[('move_ids.date', '=', self]" />
</search>

I had found the solution and answer myself,
<field string="Year" name="year" filter_domain="[('moves_ids.date', '>=', str(self) + '-01-01'), ('moves_ids.date', '<=', str(self) + '-12-31')]" />
where 'self' is the year.

Related

Odoo : limit editable rows on editable tree

Suppose I have an editable tree
<tree editable="top">
<field name="date">
<field name="value">
</tree>
Now suppose I want to let the user edit the values for 3 most recent dates, but the others should remain readonly.
How would I do that ?
Well, you could add a boolen field to the model. which will be a computed field. based on that field you could apply the read-only attrs as following:
class TheModel(models.Model):
_name = 'The.Model'
old_dated = fields.Boolean(compute='_old_dated_rec')
date = fields.Date()
value = fields.Integer()
#api.model
def _old_dated_rec(self):
"""define the condition of old dated records which could be as"""
recent_rec = self.search([], order='date desc', limit=3)
old_rec = self.search([('id', 'not in', recent_rec._ids)])
old_rec.write({'old_dated': True})
Then you could apply a scheduler to run everyday calling such method
<field name="old_dated" invisible="1" />
<field name="date" attrs="{'readonly':[('the_boolen_field','=',True)]}"/>
in such way, the compute method will update the boolean field.

Remove create and edit depending up on value of another field in odoo11

Need to remove create and edit in partner_id field in sales order depending on value of another field. I found one similar answer but it not working.
<field name="partner_id" position="replace">
<field name="partner_id" string="partner" domain=[('customer','=',True),('sale_invoice_type','=',sale_invoice_type)]" context="{'search_default_customer':1, 'show_address': 1,'default_sale_invoice_type':sale_invoice_type}" attrs=" {'invisible': [('sale_invoice_type', '=', 'cash')]}" options='{"always_reload": True, "no_create_edit": True}'/>
<field name="partner_id" domain="[('customer','=',True),('sale_invoice_type','=',sale_invoice_type)]" context="{'search_default_customer':1, 'show_address': 1,'default_sale_invoice_type':sale_invoice_type}" attrs="{'invisible': [('sale_invoice_type', '=', 'credit')]}" options='{"always_reload": True}'/>
</field>
When the sale_invoice_type is cash edit and create should be removed
First the domain of both field should look like this
<field .... attrs=" {'invisible': [('sale_invoice_type', '!=', 'cash')]}"/>
<field .... attrs=" {'invisible': [('sale_invoice_type', '=', 'cash')]}"/>
IF The solution didn't work because you should not have the same
field two time in your view Odoo will be confused witch one to pass.
But you can workaround it by creating a new field.
In your model define another partner field just a dummy one to use it instead of
the real partner_id but make sure that both field at the end of write and create
will always be equal.
partner_no_create = fields.Man.......
In your code make sure that this two field always equal:
# I think this onchage handle the cases in Odoo views
#api.onchange('partner_id')
def set_partner_no_create(self):
if self.sale_invoice_type != 'cash':
self.partner_no_create = self.partner_id
#api.onchange('partner_no_create')
def set_partner_no_create(self):
if self.sale_invoice_type == 'cash':
self.partner_id = self.partner_no_create
In your XML
<field name="partner_no_create" string="partner" domain="[('customer','=',True),('sale_invoice_type','=',sale_invoice_type)]"
context="{'search_default_customer':1, 'show_address': 1,'default_sale_invoice_type':sale_invoice_type}"
attrs=" {'invisible': [('sale_invoice_type', '!=', 'cash')]}" options='{"always_reload": True, "no_create_edit": True}'/>
<field name="partner_id" domain="[('customer','=',True),('sale_invoice_type','=',sale_invoice_type)]"
context="{'search_default_customer':1, 'show_address': 1,'default_sale_invoice_type':sale_invoice_type}"
attrs="{'invisible': [('sale_invoice_type', '=', 'cash')]}" options='{"always_reload": True}'/>
But still have to handle more cases specially when the record is updated or create from RPC call, you need to
override create and write method to handle all cases.

Display multiple one2many field with different domain dynamically?

I have a model(modelA) with one2many field related to another model(modelB) and one of the fields in modelB is a category field, which is a many2one field. The requirement is to have a one2many field displayed for each category. So if there are 2 categories named 'category1' and 'category2', the form view of modelA should have 2 one2many fields, one which displays records of having category1 and another for category2(which could possibly done using domain).
For eg modelA and modelB has the following structure.
class classA(models.Model):
_name = 'modelA'
modelA_one2manyfield = fields.One2many('modelB', 'modelB_many2onefield')
class classB(models.Model):
_name = 'modelB'
name = fields.Char()
category = fields.Many2one('modelC')
modelB_many2onefield = fields.Many2one('modelA')
How would i go about implementing a form view for modelA so that for each category(which can be added by the user, hence there can be of any number of categories) there is a seperate one2many field.
What you are asking take a lot of time to give a very good answer one of the way that i think you need to try is override the fields_view_get because this is the method that retreive the view and here you can change the arch field to add a costum field take a look at this tutorial :
Tutorial for dynamic view
but i think you will have a problem, because even when you put the domain on the one2many field in XML, odoo will not filter
the record when the loading happen on the view :
<!-- here all record are shown but the expected behavior is the one2many should be empty -->
<field name="one2many_field_name" readonly="1" nolabel="1" domain="[('id', '=', False)]">
but when i add this field to the python declaration
# here no record will be shown on the view and that's what was expected
one2many_field_name = fields.One2many(..., domain=[('id', '=', False)])
so the question adding one2many field to arch via fields_view_get is easy but the problem is filtring data !!
It's technically not possible. Because you can't have 2 times the same field in the same view.
But you can create a specific widget to showing what you want. How you can see in the timesheet view (My Current timesheet menu).
This is a little tutorial to created a widget.
https://www.odoo.com/documentation/10.0/howtos/web.html#widgets-basics
This not an answer but you can say a tutorial example of dynamic view :
modul structur:
->dynamic_view
--> __ini__.py
--> models.py
--> views.xml
--> __manifest__.py
__manifest__.py :
# -*- coding: utf-8 -*-
{
'name' : 'Dynamic view',
'version' : '1.0',
'summary': 'Tutorial for Dynamic view',
'sequence': 30,
'description': """
This Module is for showing that you can update the code of the view
when it's called and even create new field without having to use python
code at all
""",
'category': 'StackOverFlow',
'depends' : ['base_setup',],
'data': [
'views.xml'
],
'installable': True,
'application': True,
'auto_install': False,
}
__init__.py :
# -*- coding: utf-8 -*-
from . import models
models.py :
# -*- coding: utf-8 -*-
from odoo import models, fields, api
class Person(models.Model):
_name = "training.person"
name = fields.Char("Full name")
class Car(models.Model):
_name = "training.car"
name = fields.Char("Car name")
mark_id = fields.Many2one(comodel_name="training.mark", string="Mark")
owner_id = fields.Many2one(comodel_name="training.person", string="Owner")
person_view_id = "dynamic_view.dgapr_form_person"
# here default arch value body in the view contains only
# name field but as we create new mark we add others field
person_view_arch = """
<group>
<field name="name"/>
</group>
"""
class Mark(models.Model):
_name = "training.mark"
name = fields.Char("Mark")
#api.model
def create(self, values):
"""
when we create a category we add one2many field to person view
TODO: when we unlink a category we need to remove the one2many
name of field is : x_mark_{id of deleted record}
"""
rec_id = super(Mark, self).create(values)
o2m_field = {
# fields created using orm method must start with x_
"name": "x_mark_%s"% rec_id.id,
"field_description": "Mark %s" % rec_id.name,
"ttype": "one2many",
"relation": "training.car",
"relation_field": "owner_id",
"stored": True,
"domain": "[('mark_id','=', %s)]"%rec_id.id,
"model_id": self.env.ref("dynamic_view.model_training_person").id,
}
# add on2many field to ir.model.fields
self.env["ir.model.fields"].create(o2m_field)
self.update_arch()
return rec_id
def update_arch(self):
"""
when ever we create or delete a mark record
we need to update the the view to add new one2many field
if we want to hide the one2many field in view that don't have
any record we should create compute field to use attrs features
"""
view_id = self.env.ref(person_view_id)
o2m_fields_ids = self.env['ir.model.fields'].search(
[
('model_id', '=', self.env.ref("dynamic_view.model_training_person").id),
('ttype', 'like', 'one2many'),
('relation_field', 'like', 'owner_id')
])
o2many_arch = ""
for o2m_id in o2m_fields_ids:
o2many_arch = o2many_arch + """
<group col="1" string="%s">
<field name="%s" noloable="1" />
</group>
""" % (o2m_id.field_description, o2m_id.name,)
arch_begin = """
<form>
<sheet>
"""
arch_close = """
</sheet>
</form>
"""
arch_body = person_view_arch + o2many_arch
new_arch = arch_begin + arch_body + arch_close
# update the arch of the view in database
view_id.arch = new_arch
views.xml:
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="dgapr_form_car" model="ir.ui.view">
<field name="name">car.form</field>
<field name="model">training.car</field>
<field name="arch" type="xml">
<form >
<sheet>
<group>
<field name="name"/>
<field name="mark_id"/>
<field name="owner_id"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="dgapr_action_car" model="ir.actions.act_window">
<field name="name">Cars</field>
<field name="res_model">training.car</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_root_training" name="Training"/>
<menuitem id="menu_ch_car" name="Cars" parent="menu_root_training" action="dgapr_action_car"/>
<record id="dgapr_form_person" model="ir.ui.view">
<field name="name">dgapr.form.person</field>
<field name="model">training.person</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
</group>
</sheet>
</form>
</field>
</record>
</data>
</odoo>
i found out that you can create field using ORM method even compute field. i think creating a widget is better but good to know that wen can create costum fields .
Hope this helps you
Note i didn't create a menu for person record but you can see the view by clicking on the owner_id in the car form if the new one2many field not shown just refresh the page.

Populate other field with value

I have a test many2one field. When it is populated I want the partner_id field to use the partner associated with that field. Following is not working:
<field name="partner_id" required="1"/>
<field name="x_test" context="{'partner_id': parent.partner_id}" />
you should try this :
<field name="x_test" context="{'default_partner_id': partner_id}" />
I don't know what you mean by parent.partner_id this works if you have a field named parent in the same view.
i assume you wanna put same value of partner_id in x_test field, then use related field
partner_id = fields.Many2one('res.partner', string="partner")
x_test = fields.Many2one('res.partner',related='partner_id', string="X Test")
in XML
<field name="partner_id" required="1"/>
<field name="x_test" />

Adding a field in parent view

i am having some problems when i try to add a field in the parent view.
The class is:
class VademecumFraccionamiento(models.Model):
_name = 'farmacia.vademecum_fraccionamiento'
_inherits={
'farmacia.vademecum': 'vademecum_id'
}
hijo = fields.Many2one('farmacia.vademecum_fraccionamiento', string="Artículo hijo", index=True)
vademecum_id = fields.Many2one('farmacia.vademecum', string='Artículo Padre', required=True, ondelete='cascade', index=True)
The xml is:
<record model="ir.ui.view" id="farmacia_vademecum_fraccionamiento_form_view">
<field name="name">farmacia_vademecum_fraccionamiento.form</field>
<field name="model">farmacia.vademecum</field>
<field name="inherit_id" ref="farmacia_vademecum.farmacia_vademecum_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page[#string='lalala']" position="after">
<page string="Fracc">
</page>
</xpath>
<xpath expr="//page[#string='Fracc']" position="inside">
<group>
<field name="vademecum_id">
</field>
</group>
</xpath>
</field>
</record>
The error is:
Error details:
The field vademecum_id not exists
I don't know how to solve that.
Thanks in advance
You should refer addons/product/product_view.xml for more help, in which you will get all the answers of your questions related to inheritance.
I would change the code to:
_columns = {
'hijo' : fields.Many2one('farmacia.vademecum_fraccionamiento', string="Artículo hijo", index=True),
'vademecum_id' : fields.Many2one('farmacia.vademecum', string='Artículo Padre', required=True, ondelete='cascade', index=True),
}
This will add the fields to your model
There are two concepts in odoo for field inheritance.
_inherit : can be used in case you want to extend existing model.
Example: adding birth date field in res.partner model
class res_partner(models.Model):
_inherit = 'res.partner'
birth_date = fields.Date('Birthdate')
_inherits : can be used in case you want to adept module field in current model.
Example: Using customer fields in student model,
class Student(models.Model):
_name = 'stundent.student'
_inherits = {'res.partner': partner_id}
partner_id = fields.Many2one('res.partner', 'Partner')
after adding a partner_id field in your model you can use all the fields of partner in xml view of student form & tree.
Hope this helps.