#api.constrains is not working properly - odoo

In the 'project.project' model I wrote a function to validate 'start Date' and 'end date' for this I used onchange function.The function is working and giving warning but record is creating. Actually if there is any error means record cannot be saved because I am using #api.constrains below is my code.
py.code:
#api.onchange('date','date_start')
#api.constrains('date','date_start')
def cheking_field_date(self):
self.t1 = self.date_start
self.t2 = self.date
if self.t2 == False:
pass
else:
if str(self.t1) > str(self.t2):
raise Warning('The Deadline Date is Invalid')
else:
pass
But When I was Editing the record if any change in date field means than everything is fine(i.e. validation problem in 'start date' and 'end date').At that time the record is not saving.Why this type problem is coming can any one help me please.

You need to take care of following points:
No need to use #api.onchange
Remove unnecessary variables.
Write only condition that you want to raise warning.
Try with following code.
#api.one
#api.constrains('date','date_start')
def cheking_field_date(self):
if self.date_start and self.date:
if self.date_start > self.date:
raise Warning('The Deadline Date is Invalid')

Related

Onchange issue on the Date / Datetime field

Impacted versions: 12
Steps to reproduce: If we set a onchange function for a Date field and if that onchange function has some code to raise a ValidationError or UserError.
Current behavior: Then the onchange function keeps executing if you click on the Date field to select, means without changing the date, it executes. So the error popup appear again and again. So not able to change the date.
Expected behavior: As I checked with Char field it works fine. So the onchange function has to be only executed for the Date field when the current value in the field is different from the last value.
Sample code:
#api.onchange('today_date')
def change_date(self):
if self.today_date == datetime.datetime.today().date():
raise ValidationError("Selected today's Date >>>>>>>>>>>>>>")
When I select todays date in the field, it raise the error. Now I want to select some other date and clicked the field to change, before I change it gives the error again and again.
I faced this issue with Odoo ver 12.
Odoo 13 and 14 don't have this type of issue.
Odoo github Issue
Just make a small change in your code
#api.onchange('today_date')
def change_date(self):
if self.today_date != self.check_date:
self.check_date = self.today_date
if self.today_date == datetime.datetime.today().date():
raise ValidationError("Selected today's Date >>>>>>>>>>>>>>")
Here I'm supposing another datetime field to store last datetime for future validation.
Since you mentioned Odoo v12 only has this issue. I would put the check in the write method. I highly recommend that you check and use the fields.Date or fields.Datetime methods. So you don't have to try to match the format importing datetime, etc.
def write(self, vals):
if 'today_date' in vals:
if fields.Date.to_date(vals['today_date']) == fields.Date.today:
raise ValidationError("Selected today's Date >>>>>>>>>>>>>>")
return super(ClassName, self).write(vals)

Recordset is empty regardless of decorator

I'm trying to get the ID of the currency in a Journal Item but I get a False boolean value for some reason.
Here's the relevant code:
class JournalItem(models.Model):
_name = "account.move.line"
_inherit = "account.move.line"
def _get_current_rate(self):
...
print(self.currency_id.id)
#currency_id is a Many2one field of comodel res.currency.
rate = fields.Float(string="Rate", digits=(12, 6),
default=_get_current_rate)
Which outputs:
False
I toyed around with the #api.multi and #api.one decorators but noticed no changes. Feels like I'm missing something crucial.
Update 1:
self is account.move.line() when checked
This should be like account.move.line(1, 2, 3, 4, ...) maybe it's something to do with the default attribute, will update as I figure it out.
Update 2:
The main thing here is the lack of a currency, it persists even when given a valid Journal Entry record number
From the 'account' module:
#api.model
def _get_currency(self):
currency = False
context = self._context or {}
if context.get('default_journal_id', False):
currency = self.env['account.journal'].browse(context['default_journal_id']).currency_id
return currency
This is unlikely to be the issue since currency_id returns a res.currency object, it's only when I further look into it that I get False return values.
Update 3:
It appears that currencies not explicitly set during transaction creation are set to False, this is likely the source of my troubles. Fixed by testing for it and replacing by environment's default.
Methods for default values always have an empty recordset. You should fill the value in one of the following ways:
compute the value and store it (little hint: call the currency field rate with the journal entries date in context --> currency.with_context(date=<journal_entry_date>).rate --> because this field is computed and context date is taken into the computation)
override create/write and try to figure out the rate

How to get values in onchange with sudo()

I have added one onchange method, in that onchange method I have used sudo() while accessing many2one field.
But with sudo(), I am not able to get record's values with sudo.
So how can I get values of onchange record (<odoo.models.NewId object at 0x7fba62f7b3d8>) with sudo().
Here is sample code :
#api.onchange('product_id')
def onchange_product_id(self):
for record in self:
print(record.product_id)
print(record.sudo().product_id)
Actual result :
product.product(13,)
product.product()
Expected result :
product.product(13,)
product.product(13,)
That's because the recordset doesn't exist outside the current transaction. So your current user can see the contents but other users can't.
The code looks good to me, in fact, if you see path_to_v12/addons/hr_expense/models/hr_expense.py lines 563-567, you'll see a similar code:
#api.onchange('employee_id')
def _onchange_employee_id(self):
self.address_id = self.employee_id.sudo().address_home_id
self.department_id = self.employee_id.department_id
self.user_id = self.employee_id.expense_manager_id or
self.employee_id.parent_id.user_id

Expected singleton odoo 9

After enter 2 and more new row in tree view and click on save get error
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: my.model(2116, 2117)
My source code:
#api.depends('start', 'finish','stop')
def total_fun(self):
time1 = datetime.strptime(self.start, "%Y-%m-%d %H:%M:%S")
time2 = datetime.strptime(self.finish, "%Y-%m-%d %H:%M:%S")
self.total = round(((time2 - time1).seconds / float(60*60) - self.stop))
Error message says -> expected singleton this means: you are using recordset instead of record.
To fix this use
for rec in self:
in the begining of function, and then use rec instead of self
As you can see in the error message Expected singleton: my.model(2116, 2117)
By default in odoo the self is always a recordSet (means it can contain more then one record.) so when you do self.getSomeField here odoo will be confused wich record you want to get the value from.
if you don't tell odoo that make sure that the self will always contain one record when you acces an attribute if the recordSet contains more than one record this error is raised.
Now how to tell odoo make sure there is always one record is by adding #api.one decorator to the method. but is not recommended because odoo in your case there is two record so he will loop and call the method for each record and pass a recordSet that have only that record. imagine that you execute a search or any communication with database.
so don't use #api.one only if you are sure of what you are doing because you can make 10000 method call and interact with database.
like this example using #api.one:
# every call to this method you will execute a search.
self.env['some.model'].search([('m2o_id' , '=', self.id)]
you can do this before the loop:
# one query for all record with one call to the method
result = self.env['some.model'].search([('m2o_id' , 'in', self.ids)]
for rec in self:
# use result here
# or here ..

Rails query not returning updated record

Rails is not returning the updated version of a record.
I have two methods in a model, submit_job(sig, label, jobtype) for submitting a job to a db that will get processed on the backend, and then poll_result(id) which will poll that submitted job every second to see when it completes, and then return the results from the completed job to the user.
My issue is that the poll_result(id) method is never getting the updated record.
def self.poll_result(id)
change = false
Workbench.where("id = ?", id).each do |sig|
if sig.resultsready.to_i == 1
change = true
end
end
return change
end
All this does is comeback with the results from my original insert over and over, as I can see when I have it print out the results of the record it is accessing. I am looking directly at the database and can see that it is calling the right ID, and that the record has been updated. resultsready is set to 1 in the database, the loop should end and it should return back, but it just gets stuck in an infinite loop.
My assumption is that it is somehow getting an old/stale record that is being cached somehow, but I cannot for the life of me figure out how to force it to get the new record.
Thank You,
-Dennis
Using the Workbench.connection.clear_query_cache fixed the issue! To be specific, I added it at the controller level, right before calling Workbench.poll_result(id)