Odoo - How to search by date - odoo

I want to search a list of object based on date field
reservations = self.env['rm.reservation'].search([
('check_in', '=', self.check_in)
])
But when I run the Odoo, I get a runtime error
ValueError: Invalid field rm.reservation.check_in in leaf ('check_in', '=', datetime.date(2021, 12, 20))
This is the check_in field declaration in the reservation model class
check_in = fields.Date(string='Check In', required=True,
default=lambda self: fields.date.today())

Sorry this is my fault, I should call
reservations = self.env['rm.reservation.room.line'].search([
('check_in', '=', self.check_in)
])
And this is solve the problem

Related

Update value of field of another model from a create method of another model

I want to update value of field state from another model in odoo 14.Using the following code it is not working
_inherit = 'crm.lead'
lead_details_id = fields.Many2one('leads.details', string="Lead Id")
def create(self, vals):
if vals.get('lead_details_id'):
detail = self.env['leads.details'].search([('id', '=', vals.get('lead_details_id'))])
if detail:
detail.write({'state':'customer'})
return super(LeadDetailsInh, self).create(vals)

I am trying to fetch the product line of custom module in product line of invoice module in odoo 15

I have inherited account.move model and added job_card_id field(many2one) in it, as shown as below :
Image
Below given is Image of Selected Job Card :
Image
Below given is code of my model and I also tried creating function below fields :
class JobCard(models.Model):
_name = "job.card"
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = "Job Card Master"
_rec_name = 'job_card_number'
job_card_number = fields.Char(string='Job Card No.', readonly=True)
customer_id = fields.Many2one('res.partner', string="Customer Name", tracking=True)
vehicle_id = fields.Many2one('res.partner.line', string="Vehicle", tracking=True,
domain="[('x_customer_id','=',customer_id)]")
date_time_of_invoice = fields.Datetime(string='Date & Time of Invoice', tracking=True, default=fields.Datetime.now)
start_date_time = fields.Datetime(string='Start Date & Time', tracking=True)
end_date_time = fields.Datetime(string='End Date & Time', tracking=True)
priority = fields.Selection([
('0', 'Normal'),
('1', 'Low'),
('2', 'High'),
('3', 'Very High')], string="Priority") # priority widget
state = fields.Selection([
('draft', 'Draft'),
('in_progress', 'In Progress'),
('done', 'Done'),
('cancel', 'Cancelled')], string="Status", default='draft', required=True) # status bar
active = fields.Boolean(string="Active", default=True, tracking=True)
x_product_ids = fields.Many2many('job.card.line', 'product_id', string="Job Card Details")
x_quantity_ids = fields.One2many('job.card.line', 'quantity', string="Job Card Details")
x_price_ids = fields.One2many('job.card.line', 'price', string="Job Card Details")
x_total_ids = fields.One2many('job.card.line', 'total', string="Job Card Details")
x_employee_ids = fields.One2many('job.card.line', 'employee_id', string="Job Card Details")
x_job_card_ids = fields.One2many('job.card.line', 'job_card_id', string="Job Card Details")
job_card_count = fields.Integer(compute='compute_job_card_count', string='Job Card Count')
def get_invoice_line_vals(self):
vals_list = []
for job_card_line in self.x_product_ids:
vals_list.append({
' price_unit': job_card_line.price_unit,
'quantity': job_card_line.quantity
})
return vals_list
Below given is code of inherited model and also added onchange function :
class CustomInvoice(models.Model):
_inherit = "account.move"
job_card_id = fields.Many2one('job.card', string="Job Card", domain="[('customer_id','=',partner_id)]",
tracking=True)
#api.onchange('job_card_id')
def _onchange_job_card_id(self):
# creates your invoice lines vals according to your values
invoice_lines_vals = self.job_card_id.get_invoice_line_vals()
self.update({'invoice_line_ids': [(5, 0)] + [(0, 0, vals) for vals in invoice_lines_vals]})
Below given is code of my job card line :
class JobCardLine(models.Model):
_name = "job.card.line"
job_card_id = fields.Many2one('job.card', string="Job Card Id", tracking=True)
product_id = fields.Many2one('product.template', string="Product", tracking=True)
quantity = fields.Integer(string="Quantity", tracking=True)
# price = fields.Char(string="Price")
price = fields.Float(string="Price")
total = fields.Integer(string='Total', compute='_compute_total', tracking=True,
help="This field will be calculated from quantity and price !")
employee_id = fields.Many2one('hr.employee', string="Employee", tracking=True)
x_job_card_id = fields.Many2one('res.partner', string="Vehicle Details")
#api.onchange('product_id')
def _on_change_product_id(self):
self.price = self.product_id.list_price
#api.depends('quantity', 'price')
def _compute_total(self):
print("self........", self)
for rec in self:
rec.total = rec.quantity * rec.price
Actually I wanted to add product line of selected job card into Invoice product line automatically when I select the job card.
But I am getting error as shown below :
Error
You got that error because you have no field named line_ids in job.card model. Maybe you need to change it to x_product_ids.
The TyprError (int object is not iterable) is caused by the first tuple passed to the write method :
(6, 0, 0)
Odoo expects the third parameter to be iterable. If you need to clear the list, use (5,0)
Avoid calling the write method inside an onchange function. You can read the following danger notice in the official onchange documentation:
DangerSince #onchange returns a recordset of pseudo-records, calling any one of the CRUD methods (create(), read(), write(), unlink()) on the aforementioned recordset is undefined behaviour, as they potentially do not exist in the database yet.Instead, simply set the record’s field like shown in the example above or call the update() method.
Edit:
You have two errors in get_invoice_line_vals function
1/ ValueError:
Invalid field ' price_unit' on model 'account.move.line'
You need to remove the space at the beginning.
2/ AttributeError:
'job.card.line' object has no attribute 'price_unit'.
Use the price field instead.

Raise UserError only if none fields selected

I added my custom field to res.partner model and when I'm creating partner if branch_id is checked I want to that one of 3 fields should be selected. If some of the fields are not selected then I want to raise UserError.
But now it raises UserError even if I one of the fields is selected.
class ResPartner(models.Model):
_inherit = 'res.partner'
branch_id = fields.Many2one('branch.responsibility','Responsibility by branch')
drawer_id = fields.Many2one(
'furniture.parts.type', string='Drawer Type',
domain=[('type', '=', 'drawer')], )
flexible_id = fields.Many2one(
'furniture.parts.type', string='Flexible Type',
domain=[('type', '=', 'flexible')],)
runner_id = fields.Many2one(
'furniture.parts.type', string='Runner Type',
domain=[('type', '=', 'runner')], )
#api.model
def create(self, vals):
if vals.get('branch_id'):
if not vals['drawer_id'] or not vals['flexible_id'] or not vals['runner_id']:
raise UserError('You need to chose values from notebook raport data')
return super(ResPartner, self).create(vals)
UPDATE.
for write method, I tried this as CZoellner suggested for create but always get True True True for fields_to_check_in_vals
#api.multi
def write(self, vals):
if vals.get('branch_id') or vals.get('drawer_id') or vals.get('flexible_id') or vals.get('runner_id') or
vals.get('group_1_id') or vals.get('group_2_id')or
vals.get('group_3_id'):
fields_to_check = ['drawer_id', 'flexible_id', 'runner_id', 'group_1_id', 'group_2_id', 'group_3_id']
fields_to_check_in_vals = [f in self for f in fields_to_check]
if not any(fields_to_check_in_vals):
raise UserError('If branch is selected then you need to select one of the fields from data raport')
> return super(ResPartner, self).write(vals)
Your logic says, that all 3 fields have to be set. You could use any here:
if vals.get('branch_id'):
fields_to_check = ['drawer_id', 'flexible_id', 'runner_id']
fields_to_check_in_vals = [f in vals for f in fields_to_check]
if not any(fields_to_check_in_vals):
raise UserError()
Edit: the write method is a bit more tricky. Usually it is a multi record method, so a for each loop on self should be implemented. Then you'll need to use either getattr or just (it's suggested in the Odoo doc) treat the recordset like a dict. And then it could be, that the change happens right on the write call. So you have to check both the persisted and the new values:
for record in self:
if vals.get('branch_id'):
fields_to_check = ['drawer_id', 'flexible_id', 'runner_id']
fields_to_check_dict = {f:record[f] for f in fields_to_check}
fields_to_check_dict.update({f:f in vals for f in fields_to_check})
if not any(fields_to_check_dict.values()):
raise UserError()
That's a bit complicated. You could also first call super and just check after that. Raising an exception will rollback all changes, so nothing will happen.
res = super(MyModel, self).write(vals)
for record in self:
if vals.get('branch_id'):
fields_to_check = ['drawer_id', 'flexible_id', 'runner_id']
fields_to_check_in_record = [record[f] for f in fields_to_check]
if not any(fields_to_check_in_record):
raise UserError()
return res

what should I add to display the value of fields correctly?

what should I add to display user_id and cat correctly
#api.model
def create(self, vals):
record=super(test, self).create(vals)
if vals['total'] > 0:
vals['date'] = fields.Datetime.now()
self.env['journal'].create({
'user_id': record.patient_id,
'cat': record.cat,})
....
.....
on the tree view (journal):
user_id is displayed as test.user(6,)
cat is displayed as cat1
EDITS:
class test(models.Model):
_name = 'test'
cat = fields.Selection(
required=True,
related='test_type_cat.name',
store=True,
)
user_id = fields.Many2one('res.users', string='user', readonly=True,)
.....
#api.model
def create(self, vals):
record=super(test, self).create(vals)
if vals['total'] > 0:
vals['date'] = fields.Datetime.now()
self.env['journal'].create({
'patient_id': record.patient_id.name,
'cat': record.cat,
'user_id': record.user_id.name,
})
record.total = 0
return record
why does it work with .name and not .id ?
for m2o field should I pass the integer value ? if it is the case why does it work here with .name ? and what about m2m and o2m?
this worked for you because you are creating a record in model: journal not in test model.
and if you go to journal model you will find that patient_id is Char field not a many2one field.
so if you pass: record.patient_id you are passing an object and it's converted to char this is why you get test(1,). because pateint_id is a many2one field in test model witch mean is an object.
Hope this clear thing little bit for you.

RML report openerp 7

How to get the field which is present in sale.order in invoice report. So invoice report use the model account.invoice, if i add a function in report.py it allow only self.cr,self.uid because we are not using osv.memory. So how to get the value of cust_ref_value from sale.order to invoice report.
We can track from the Source Document
In report.py we need to make a function and pass origin in it.
def __init__(self, cr, uid, name, context):
super(your_report_calss_name, self).__init__(cr, uid, name, context)
self.localcontext.update({
'time': time,
'get_cust_ref_val': self._get_cust_ref_val,
})
This method will check like origin is SO or PO or OUT/###:SO### or IN/###:PO### so following case be here
def _get_cust_ref_val(self, origin)
if 'SO' in origin:
if 'OUT/' in origin:
so_name = str(origin).split(':')[1]
sale_id = self.pool.get('sale.order').search(self.cr, self.uid, [('name', '=', so_name)]
if sale_id:
sale = self.pool.get('sale.order').browse(self.cr, self.uid, sale_id)
return sale.cust_ref_value
else:
sale_id = self.pool.get('sale.order').search(self.cr, self.uid, [('name', '=', origin)]
if sale_id:
sale = self.pool.get('sale.order').browse(self.cr, self.uid, sale_id)
return sale.cust_ref_value
else:
return ''
and from the rml side
[[ get_cust_ref_val(inv.origin) ]]