Odoo Prevent Selected Duplicate Record in One2many Field - odoo

I want to prevent the selected record to show again in the combo box.
As you can see, the 710 - Maleo show again after I selected that record before.
Field declaration for One2many field
class RMReservationOrderLine(models.Model):
_name = "rm.reservation.order.line"
_description = "Reservation Order Line"
room_line_ids = fields.One2many('rm.reservation.room.line', 'order_id', string='Rooms')
Model class for One2many field
class RMReservationRoomLine(models.Model):
_name = "rm.reservation.room.line"
_description = "Reservation Room Line"
order_id = fields.Many2one('rm.reservation.order.line', string='Order', required=True, ondelete='cascade')
room_id = fields.Many2one('rm.room', string='Room', required=True)
UPDATE
Since my model class for the One2many field just have a single field, room_id, I just change the One2many field to Many2many. Because by default Many2many field prevent duplicate record.
But I still want to know how to prevent duplicate records if I use the One2many field, In case I have more than 1 field in the model class for One2many.

I think this is the same case as you want.
I already modified the Sales Order, so when the product in the sales order line it's already selected then the product will not be shown again in the selected product.
I used odoo-14 and inherited the sales.order.line and modified the function product_id_change() to become:
#api.onchange('product_id')
def product_id_change(self):
values = super(SaleOrderLine, self).product_id_change()
filter_product_ids = [data.product_id.id for data in self.order_id.order_line]
if values is None:
values = {}
values['domain'] = {'product_id' : [('id', 'not in', filter_product_ids)]}
return values

Related

Odoo Create Model Programmatically and Add/Append to One2many Field

So I have a Sale model and SaleLine model. Sale model have a field sale_line_ids as One2many from SaleLine model.
Sale
class Sale(models.Model):
_name = 'store.sale'
_description = 'Store Sale'
...
sale_line_ids = fields.One2many('store.sale_line', 'sale_id', string='Sale Lines')
...
Sale Line
class SaleLine(models.Model):
_name = 'store.sale_line'
_description = 'Store Sale Line'
sale_id = fields.Many2one('store.sale', string='Sale Reference', ondelete='cascade', index=True)
product_id = fields.Many2one('store.product', string='Product', required=True)
quantity = fields.Integer(string='Quantity', required=True)
I want to create SaleLine model programmatically and add that model to sale_line_ids field. How can I do that?
This answer is what I actually want to implement. However, the model is immediately saved to a database. I need to create a SaleLine model using env[].create({}) method.
self.env['store.sale_line'].create({
'sale_id': rec.id,
'product_id': id_from_another_model,
'quantity': quantity_from_another_model,
})
After that, I need to commit in order to save the data in a database.
self.env.cr.commit()
UPDATE
The previous answer required record to store directly. The best answer to solve the problem is to create temporary record that only saved when user click the save button.
Syntax
(0, 0, { values })
First create sale_line list
sale_line = []
for data in list_of_data:
sale_line.append([0, 0, {
'sale_id': data['sale_id'],
'product_id': data['product_id'],
'quantity': data['quantity'],
}])
Assign sale_line list to sale_line_ids field
self.write({'sale_line_ids': sale_line})
And override the create method to commit the change
#api.model
def create(self, values):
self.env.cr.commit() # This is the important part
return super(Sale, self).create(values)

How to get value on one field based on two different fields

So Im creating a hotel management module . I have the option to filter rooms based on bed_type and tag. Tag contains different facilities like AC, TV etc. So an user will come and select a bed_type and the facilities he wants and in the third field it should show the rooms that have the given configuration if not available an error messages should come. SO i created a onchange function to do this , but i dint know how to include the tags in it. Im doing it on odoo v14. m
This is the model for the room
from odoo import api, fields, models, _
class HotelRoom(models.Model):
_name = 'hotel.room'
_description = 'hotel room'
_rec_name = 'room_number'
room_number = fields.Char('Room Number', required=True)
room_rent = fields.Monetary('Room Rent')
tag = fields.Many2many('hotel.tags', string='Facilities')
dormitory_count = fields.Integer('Dormitory count')
bed_type = fields.Selection([
('single', 'Single'),
('double', 'Double'),
('dormitory', 'Dormitory')
], required=True, default='other')
This is the model for the reception
class HotelAccommodation(models.Model):
_name = 'accommodation.room'
_description = 'Reception'
bed_type = fields.Selection([
('single', 'Single'),
('double', 'Double'),
('dormitory', 'Dormitory')
], required=True, string= 'Bed type')
state = fields.Selection([
('draft','Draft'),
('check-in','Check-In'),
('check-out', "Check-Out"),
('cancel','Cancel'),
], required=True, default='draft', tracking=True)
tag = fields.Many2many('hotel.tags', string='Facilities')
room_id = fields.Many2one('hotel.room', string='Room')
Using this I can filter the rooms based on the bed_type but I need to have the tags as well.I tried giving it inside the domain but its not working .
#api.onchange('bed_type')
def filter_room(self):
for rec in self:
return {'domain': {'room_id': [('bed_type', '=', rec.bed_type)]}}
You need also to add the tag field to the domain and to the onchange decorator, so the method will be called when the tag field is modified.
The method is invoked on a pseudo-record that contains the values present in the form, you do not need to loop over self.
Try the following example:
#api.onchange('bed_type', 'tag')
def filter_room(self):
return {'domain': {'room_id': [('bed_type', '=', self.bed_type), ('tag', 'in', self.tag.ids)]}}
You can use _compute fields with the store option = True
take a look https://www.odoo.com/documentation/14.0/reference/orm.html#computed-fields

How to create a record for field using many2one in Odoo 13?

I have 3 models. I used One2many field o put the tree view of model 3 in form view of model 1 and 2.
1/ bao_hiem.py with one2many field:
lstd_baohiem = fields.One2many('lich.su', 'name')
thamchieu = fields.Char('Tham chiếu')
2/ dieu_chinh.py with one2many field:
lstd_dieuchinh = fields.One2many('lich.su', 'name')
thamchieu = fields.Char('Tham chiếu')
And 3/ lich_su.py with many2one field:
name = fields.Many2one('bao.hiem')
name_id = fields.Many2one('bao.hiem')
thamchieu = fields.Char('Tham chiếu')
I want to pass the values (eg: 'name', 'thamchieu') from dieu_chinh.py to lich_su.py and auto record with all those values via a button. So that, in the user's form view of model 1 and 2 can show the recorded value also, called the activity history of 1 user.
The code for the button like this:
def chapthuan(self):
giatri_lstd = self.env['lich.su']
gt = {
'name' : self.name.id,
'thamchieu' : self.thamchieu,
'thoigian' : self.thoigian
}
list_lstd_dieuchinh=[]
for line in self.lstd_dieuchinh :
art = {}
art['name'] = line.name.id
art['lstd_dieuchinh'] = line.lstd_dieuchinh
art['thamchieu'] = line.thamchieu
art['thoigian'] = line.thoigian
list_lstd_dieuchinh.append((0, 0, art))
gt.update({ # add the list of command to gt
'thamchieu': list_lstd_dieuchinh
})
giatri_lstd = giatri_lstd.create(gt)
return True
After click the button 'chapthuan', it can pass the value and create the record with the field 'name', 'date'. But with the field: 'thamchieu' which has relation many2one with model2 is still not worked.
I must select manually in the form view of the user.
So how to create a record with many2one field?
Please help!
Thank you
https://www.odoo.com/documentation/13.0/reference/orm.html#create-update
You are trying to create records by (0, 0, {values}) to name_id by the way of x2many field.
But name_id is Many2one field. That's your programming error.
But the error log you showed happened when you are trying to remove a record that already links to another record. So what I said above is not the main problem... Anyway, I'm a little confused with your code, it looks not so good

How to save One2many fields values?

I am adding custom One2many field in sale.order form view just below the sale.order.line.
I am computing values on_change it is displaying values but when I am going to save the sales order it is generating error that
ValueError: Wrong value for tax.lines.order_id: sale.order(24,)
Python:
class SaleOrderInherit(models.Model):
_inherit = ['sale.order']
tax_line = fields.One2many('tax.lines', 'order_id', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True, auto_join=True)
#on.change('partner_id')
def calculating_tax(self):
//After some code
self.env['tax.lines'].create({
'tax_id': tax['tid'],
'name': tax['name'],
'amount': tax['tax'],
'order_id': self.id
})
class TaxLines(models.Model):
_name = 'tax.lines'
tax_id = fields.Char('Tax Id')
name = fields.Char('Tax Name')
amount = fields.Char('Tax Amount')
order_id = fields.Many2one('sale.order', string='Tax Report', ondelete='cascade', index=True, copy=False)
Because I am creating one2many field before creating the order.
But is there any way to get rid of this problem.
Edit:
Error after replacing my code with Charif DZ code:
Never create records in onchange events they are immidiatly saved in database what if the user decided to cancel the order, instead of create use new with create an object but doesn't save it in database.
def calculating_tax(self):
//After some code
# to add record to your o2m use `|` oprator
# if you want to clear record before start adding new records make sure to empty your field first by an empty record set like this
# self.tax_line = self.env['tax.lines'] do this before the for loop that is used to fill-up the field not put it inside or you will get only the last record
self.tax_line |= self.env['tax.lines'].new({
'tax_id': tax['tid'],
'name': tax['name'],
'amount': tax['tax'],
# 'order_id': self.id remove the many2one because it's handled automaticly by the one2many
})
I hope this help you good luck

Custom data in one2many field in Odoo

I am working on this Odoo assignment. I have to make a custom module in which the requirement is like this.
There is a form say "Notebook" it contains a field that comes from 'hr.employee' i.e. Many2one. Next thing this form will contain is a table which 3 columns (Quality, Score, Comment). Now Qualities must be a master table which contains many qualities name.
I have achieved this task in the way SalesOrder form works i.e. for a particular sales order there are multiple sales lines.
But I want all the qualities to be there on form with default score value of 0.
Here is the code
Please tell me the resolution
class qualities_fields(models.Model):
_name = "ayda.qualities.fields"
_description = "Contains only Attributes"
#api.multi
def name_get(self):
data = []
for rows in self:
value = ''
value += rows.quality_name
data.append((rows.id, value))
return data
quality_name = fields.Char(string="Quality Name")
class qualities_data(models.Model):
_name = "qualities.data"
_description = "All points mandatory to be filled"
quality_id = fields.Many2one('notebook', string="Quality IDs")
quality_name = fields.Many2one('qualities.fields', string="Quality Name")
score = fields.Integer(string="Score")
comment = fields.Char(string="Comment")
class notebook(models.Model):
_name = "notebook"
_description = "Checking one2many of qualities"
def createRecords(self):
cr = self.pool.cursor()
quantity_fields = self.pool.get('qualities.fields').search(cr, self.env.uid, [])
quantity_lines = []
for field in quantity_fields:
quality_data = {
'quality_id' : self.id,
'quality_name' : field.id,
'score' : 0,
'comment' : ''
}
quantity_lines.append(quality_data)
return quantity_lines
name = fields.Many2one('hr.employee', string="Name")
qualities_line = fields.One2many('qualities.data', 'quality_id', string="Qualities Line", default=createRecords)
There's an easier way to do this, on the field definition just set the default score to 0
score = fields.Integer(string="Score", default=0)
That way all scores would be zero when they're created