Odoo custom filter domain field on load view - odoo

I'm making a module for reservations in Odoo 9 and one field of my model is populated based if it's reserved or no. Basically my model is:
class Reservation(models.Model):
....
room_id = fields.Many2one('reservation.room', string="Room")
I've defined an onchange function that return a domain to filter the room_ids that aren't reserved:
#api.onchange('date')
def _set_available_room(self):
.....
return {'domain': {'room_id': [('id', 'in', res)]}}
This works fine and when I set the date, the rooms are filtered ok. My problem is when I save a reservation and enter again to edit it. The room_id field show all values and only when I change the date the room_id is filtered.
I've tried using the domain attribute in the field definition like this, but it doesn't works:
room_id = fields.Many2one('reservation.room', string="Room", domain=lambda self: self._get_available_slots())
How can I filter this field on the load view using my function than search for available rooms?

Related

Show field based on value of another field

I've been trying to show order confirmation date in sale order tree view.
To show it I used 'date_order' like this:
<field name="date_order" string="Confirmation Date" optional="show" attrs="{'invisible':[['state','not in',['sale', 'done']]]}" />
In our setup orders are created manually but also synced from Woocommerce and in those synced orders from web shop date_order is always before the create date.
For example order is created (create_date) 10.08.2022 17:10:20 and confirmed automatically (date_order) 10.08.2022 17:10:11
Somehow, it is confirmed 9s before it is created. Now, i'd like to show date_order only when it's value is > create_date. In other cases i'd like to display create_date in it's place.
Tryed to use attrs for this, I'm not sure if it's even possible:
<field name="date_order" string="Confirmation Date" optional="show" attrs="{'invisible':['&', ['state','not in',['sale', 'done']], ['date_order'], '>', ['create_date']]}" />
The code above gives XMLSyntaxError. Not sure if it's possible to compare values in that manner - and finally how to get one or the other value - I guess my second approach is maybe better.
In second approach I tried to create compute field, like this:
date_order_mine = fields.Char("Potvrdjeeeno", compute="comp_date")
#api.depends('create_date', 'date_order', 'order_line')
def comp_date(self):
for order in self:
for line in order.order_line:
if line.create_date < line.date_order:
return line.date_order
else:
return line.create_date
This code gives me AttributeError: 'sale.order.line' object has no attribute 'date_order'
Since I'm so new to Odoo and Python dev I'm not sure what should I do here to compare values of this fields and to return one or other based on conditions - if someone can help I will appreciate it.
The domain used in attrs is not valid, domains should be a list of criteria, each criterion being a triple (either a list or a tuple) of:
(field_name, operator, value)
In your second approach, the date_order field is on the parent model sale.order (order) and to access the date order from order lines , use the order_id field like following:
line.order_id.date_order
To set the value of date_order_mine to create_date or date_order you do not need the order lines and also the computed method should assign the compute value:
Computed Fields
Fields can be computed (instead of read straight from the database) using the compute parameter. It must assign the computed value to the field.
Example:
date_order_mine = fields.Datetime("Potvrdjeeeno", compute="comp_date")
#api.depends('create_date', 'date_order')
def comp_date(self):
for order in self:
if order.create_date < order.date_order:
order.date_order_mine = order.date_order
else:
order.date_order_mine = order.create_date

how can I create a computed fields that is depending on another model

I have two models reservation(inherit from sale.order) and places . I want to make a one2many field in the places model so when a reservation(sale.order) is confirmed, the new customer who reserved the place is added to this field
here is my code
model reservation
from odoo import fields, models,api,_
from odoo.exceptions import Validation-error
class Customers2(models.Model):
_inherit='sale.order'
client=fields.Many2one('res.partner',string='client')
secure_place=fields.Many2one(comodel_name='product.template',string='Secure place')
guests=fields.Integer(string='guests')
hotel_reser=fields.Many2one('product.template')
start_date=fields.Datetime(string='start date')
end_date=fields.Datetime(string='end date')
reserv_price=fields.Monetary(string='Price')
currency_id = fields.Many2one(comodel_name='res.currency',string='Currency')
reserv_status = fields.Selection(
[('C', 'Confirmed'), ('D', 'Draft')],
string='Reservation type')
model places
from odoo import fields , models,api
class Place(models.Model):
_inherit='product.template'
hotel=fields.Selection([('H', 'Habit'),('Y','Yasmine'),('M','movenpick')],string='Hotel')
type_of_room=fields.Selection([('S', 'spa'),('M','meeting room'),('N','Nightclub')],string='Room')
reserv_persons=fields.One2many('sale.order','hotel_reser',string='clients reserved',compute='_compute_reservations')
To add the new customer who reserved the place in the reserv_persons field, the related model should be res.partner and its type many2many.
You want to use a computed field (the value is computed when needed), so you can search for sale orders in the sale state to show all customers who reserved the place
Example:
from odoo import api, fields, models, _, Command
class Place(models.Model):
_inherit = 'product.template'
reserv_persons = fields.Many2many('res.partner', string='clients reserved', compute='_compute_reservations')
def _compute_reservations(self):
sale_order = self.env['sale.order']
for tmpl in self:
tmpl.reserv_persons = [Command.link(so.client.id) for so in sale_order.search(
[('secure_place', '=', tmpl.id), ('state', '=', 'sale')])]
The Command used above is a special command to manipulate the relation of One2many and Many2many

two many2many fields with different partner

i have two fields that should be related to res.partner
in partner_ids i want to choose partner and in recipients_ids i want to choose another partner that will get a copy of the document. the problem that in form view if i change partner_ids or recipient_ids both fields became the same. how can i do that i can choose different partners in those fields?
partners_ids = fields.Many2many('res.partner', string='Companys Names')
recipients_ids = fields.Many2many('res.partner', string='Copys for')
You are getting the error because the two field work on the same table in postgres
because odoo create a table for that name like this:
current_model_name_co_model_name_rel
in your case
your_model_res_partner_rel
so you need to tell odoo that every field has it's own relation
partners_ids = fields.Many2many('res.partner', # co_model
'your_model_partners_rel', # relation name change your_model to much your model name
string='Companys Names')
recipients_ids = fields.Many2many('res.partner',
'your_model_recipients_rel',
string='Copys for')
when you create m2m field it's better to specify this value by keyarguement
_name = 'my.model'
# exmple
user_ids = fields.Many2many(comodel_name='res.users', # name of the model
relation='my_model_users_rel', # name of relation in postgres
column1='session_id', # id reference to current mode
column2='user_id', # id reference to co_model
string='Allowed users')

Odoo 8 : how to link a Many2one field automatically with the parent model?

I created a new model 'sale.order.category' in order to group Sale Order Lines in specific subcategories (allowing to display subtotals, etc.)
class SaleOrderCategory(models.Model):
_name = 'sale.order.category'
name = fields.Char('Name', required=True)
line_ids = fields.One2many('sale.order.line', 'category_id', 'Order Lines in this category')
order_id = fields.Many2one('sale.order', 'Order', required=True, readonly=True)
class SaleOrder(models.Model):
_name = 'sale.order'
_inherit = 'sale.order'
order_category_ids = fields.One2many('sale.order.category', 'order_id', 'Categories in this order', readonly=True, copy=True)
Just for info, here is my Order lines tree view modification to add the Category column :
<!-- adds a category column in the order lines list -->
<xpath expr="//field[#name='order_line']/tree/field[#name='name']" position="after">
<field name="category_id"/>
</xpath>
My question is : how can I automatically populate the order_id field with the current Sales Order ID when I create a new Category through the Order Lines Tree (inside a Sales Order) ?
Many thanks,
Max
Preliminary remark: your use case seems related to what the official sale_layout module does, so you might want to have a look at it before going any further. Perhaps you could extend it instead of starting from scratch.
Next, the most basic answer to your question is to pass a default value for the order_id field of your sale.order.category model when you create it from the view. You can do that by setting a context with an appropriate default value on the many2one field from which you will create the value:
<xpath expr="//field[#name='order_line']/tree/field[#name='name']" position="after">
<field name="category_id" context="{'default_order_id': parent.id}"/>
</xpath>
Your category_id field is defined on the sale.order.line tree view, so parent will dynamically refer to the parent record inside the web client interface, here the sale.order.
However this option will not work well:
When you're creating a new sales order, you will have to create your categories before the sales order is even saved, so there is no possible value for order_id yet. For this reason, you cannot make order_id required, and you will have to set its value again later, or you will need to save your orders before starting to add the categories.
You already have an order_lines one2many field in your sale.order.category model. The order_id field is redundant with the line_ids field, because all lines presumably belong to the same order.
A simple alternative would be to entirely omit the order_id field (use lines_id[0].order_id when you need it), or to replace it with a related field that will be automatically computed from the lines (it will take the value from the first order line):
order_id = fields.Many2one('sale.order', related='line_ids.order_id', readonly=True)
What you should do depends on your requirements, it's difficult to say based only on your question.

how to show a computed one2many field Odoo(api v8)

I want to know how to show a one2many computed field in a tree view, I tried the following code but without results:
#api.one
def _compute_o2m_field(self):
related_recordset = self.env["product.product"].search([])
self.productos = related_recordset
products = fields.One2many(string="products", compute='_compute_o2m_field')
any idea?,
thanks
#api.one
def _compute_o2m_field(self):
related_recordset = self.env["product.product"].search([])
self.products = related_recordset.ids
products = fields.One2many('product.product','many2onefieldonproduct',string="products", compute='_compute_o2m_field')
Computed Fields
There is no more direct creation of fields.function.
Instead you add a compute kwarg. The value is the name of the function as a string or a function. This allows to
have fields definition atop of class
Your compute function should be like this,
#api.multi
def _compute_o2m_field(self):
related_recordset = self.env["product.product"].search([])
for obj in self:
obj.products = related_recordset
One2many
Store a relation against many rows of co-model.
Specific options:
• comodel_name: name of the opposite model
• comodel_name: relational column of the opposite model
So, your field definition should be like this,
products = fields.One2many(comodel_name,comodel_name,string="products", compute='_compute_o2m_field')