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
Related
I want to get id from url when i click the button.
This is URL, id is 69:
http://localhost:8069/web#id=69&cids=1&menu_id=385&action=507&model=inventory.menu&view_type=form
I need to get this id in many2one field.
This is my wizard py file:
from odoo import api,fields,models
class ReduceInventoryWizard(models.TransientModel):
_name = "reduce.inventory.wizard"
_description = "Reduce Inventory Wizard"
inventory_ids = fields.Many2one('inventory.menu', string="Ürün Referans No: ", default=lambda self: self.env['inventory.menu'].search([('id', '=', 69)], limit=1))
As you can see, ('id', '=', 69) this is running but just one product. I want the information of that product to come automatically when I click the button in which product.
I tried this one: ('id', '=', self.id). But is not working.
In this situation there should be active_id or better active_ids in Odoo's context.
So you just can set the default parameter to use a default method, which will either return a value or an empty recordset:
def default_my_many2one_field_id(self):
active_ids = self.env.context.get("active_ids")
if active_ids:
return self.env["another.model"].browse(active_ids[0])
return self.env["another.model"]
my_many2one_field_id = fields.Many2one(
comodel_name="another.model", string="My M2o Field",
default=default_my_many2one_field_id)
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)
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
Put fields of an employee in accounting through a module
Hi. I am creating a module for a client that has a specific need. He wants us to add a price per hour to employees. That is, the price charged by the employee each hour of work. Then create a small expense report that goes into accounting.
The first thing I have done is to modify the employee module using _inherit to add two fields. Nickname that allows employees to filter by nickname. And the hourly price of that employee (what this employee charges for every hour).
employee example changes
The second has been to create a new model that allows adding employees and importing said data. In addition to adding a description.
form example
The challenge now is to link this information to the accounting module so that it will appreciate as a Journal Item and then have the copy confirmed to be appreciated as a Journal Entries.
I am really new in the development of odoo and there are many things that I am still assimilating. So the questions I have are the following:
How could I do this?
Do I have a problem with what I have done so far?
It is my first post and I would appreciate the help. Thanks in advance.
This its the code:
class EmpleadoObra(models.Model):
_inherit = 'hr.employee'
apodo = fields.Char('apodo', readonly=False, store=True)
precio_por_hora = fields.Float('Salario por hora', store=True)
#api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
args = args or []
recs = self.browse()
if name:
recs = self.search(['|', ('apodo', 'ilike', name), ('name', operator, name) ] + args, limit=limit)
return recs.name_get()
class EmpleadosProductos(models.Model):
_name = "employee.as.product"
# _inherits = {'hr.employee' : 'empleado_id'}
employee_line = fields.One2many(
'employee.line',
'id',
string='Employee Lines'
)
class EmployeLine(models.Model):
_name = 'employee.line'
descripcion = fields.Text(string='Descripción', required=False)
employee_id = fields.Many2one(
'hr.employee',
string="Empleado",
requiered=True,
change_default=True
)
apodo = fields.Char('apodo', readonly=False)
precio_por_hora = fields.Float('precio_por_hora')
_rec_name = 'apodo'
#api.onchange('employee_id')
def onchange_employee_id(self):
addr = {}
if not self.employee_id.display_name:
return addr
if not self.employee_id.apodo:
self.apodo = "no apodo"
else:
self.apodo = self.employee_id.apodo
self.precio_por_hora = self.employee_id.precio_por_hora
return addr
I have two models:
medical.lab.test.type
This is my class:
class MedicalLabTestType(models.Model):
_name = "medical.lab.test.type"
_description = "Medical Lab Test Types"
name = fields.Char(
'Test',
help='Name of test type, such as X-Ray, Hemogram, Biopsy, etc.',
required=True,
)
code = fields.Char(
'Code',
size=128,
help='Short name or code for test type.',
required=True,
)
description = fields.Text('Description')
Test_Prix = fields.Float(
string='Price of the test',
required=True,
)
Nbr_days = fields.Integer(
string='Number of days to have results',
required=True,
)
and
medical.lab
This is my class:
class MedicalLab(models.Model):
_name = 'medical.lab'
_description = "Medical Labs"
test_type_id = fields.Many2one(
string='Test Type',
comodel_name='medical.lab.test.type',
help='Lab test type.',
)
physician_id = fields.Many2one(
string='Pathologist',
comodel_name='medical.physician',
help='Pathologist that performed the exam.',
)
request_physician_id = fields.Many2one(
string='Requesting Physician',
comodel_name='medical.physician',
help='Physician that requested the exam.',
)
The problem is to show on the view the value of Test_Prix and Nbr_days once I choose a Test
How should i proceed?, should I use an onchange function!!!
to show field of selected m2o on the current view you should use
related field.
in your midecal.lab model add:
# related field should always keep the same type Foalt Float, Char Char
# and it's recommended that you put readonly because if you edit
# the value the value will be edited in the related record when you save
Test_Prix = fields.Float(
retlated='test_type_id.Test_Prix',
readonly=True
)
Nbr_days = fields.Integer(
retlated='test_type_id.Nbr_days',
readonly=True
)
and now you can add this two field to you view like
NB: related field are not stored in database they work as proxy if you
want to create the field in the database use store=True
EDITS :
use onchange not compute field is computed
date_perform = fields.Datetime( string='Date of Results', )
#api.onchange('date_request', 'Nbr_days')
def _compute_date_result(self):
for record in self:
business_days_to_add = record.Nbr_days
current_date = fields.Datetime.from_string(record.date_request)
.....