How to make result from one odoo field to affect the result of another field - odoo-10

I have a time difference field
time_diff = fields.Char(string="Time Difference", required=False, )
and a sla field in odoo
sla_state = fields.Selection(string="SLA", selection=[('past sla', 'Past SLA'), ('within sla', 'Within SLA'), ], required=False, )
i want to set a condition where if time difference is greater than 1
the sla state automatically populates to Past SLA
Below is my function
#api.onchange('time_diff')
def get_sla(self):
if self.time_diff >= 1:
self.sla_state == 'past sla'
else:
self.sla_state == 'within sla'
But its not working what might be the issue
Please help.

The problem is you are comparing the string with integer. Data type of 'time_diff' is string. So string can not be compared with integer. Convert the string to integer using int()
#api.onchange('time_diff')
def get_sla(self):
if self.time_dif:
if int(self.time_diff) >= 1:
self.sla_state == 'past sla'
else:
self.sla_state == 'within sla'

Related

how to extract the today's date out of the date column using SQL query?

I assume I would need to change query in order to sort the data with today's date.
Please tell me how to change it though...
SQL QUERY in ToDoDao
#Query("SELECT * FROM todo_table WHERE date(date) = date('now')")
fun getTodayList(): Flow<List<ToDoTask>>
DATABASE
#Entity(tableName = DATABASE_TABLE)
data class ToDoTask(
#PrimaryKey(autoGenerate = true) val id: Int = 0,
#ColumnInfo(name = "title") val title: String,
#ColumnInfo(name = "description") val description: String,
#ColumnInfo(name = "priority") val priority: Priority,
#ColumnInfo(name = "date") val date: String,
#ColumnInfo(name = "favorite") var favorite: Boolean)
date val in ViewModel class
val date : MutableState<String> = mutableStateOf("")
datas inserted
enter image description here
I have tried the code below and I was able to activate the function as the query as I intented, so I think the query is the issue here.
#Query("SELECT * FROM todo_table WHERE date = '2023-2-14'")
fun getTodayList(): Flow<List<ToDoTask>>
The Issue
The issue is that the SQLite date function expects the date to be in an accepted format.
YYYY-M-DD is not such a format and will result in null rather than a date. YYYY-MM-DD is an accepted format (see https://www.sqlite.org/lang_datefunc.html#time_values). That is leading zeros are used to expand single digit numbers to 2 digit numbers for the month and day of month values.
The Fix (not recommended)
To fix the issue you have shown, you could use (see the However below):-
#Query("SELECT * FROM todo_table WHERE date(substr(date,1,5)||CASE WHEN substr(date,7,1) = '-' THEN '0' ELSE '' END ||substr(date,6)) = date('now');")
If the month was 2 numerics i.e. MM (e.g. 02 for February) then the above would not be necessary.
The CASE WHEN THEN ELSE END construct is similar to IF THEN ELSE END. see https://www.sqlite.org/lang_expr.html#the_case_expression. This is used to add the additional leading 0, when omitted, to the string used by the date function.
However, the above would not cater for days that have the leading 0 omitted for the first 9 days of the month. This due to the 4 permutations of the format (YYYY-MM-DD, YYYY-MM-D, YYYY-M-D and YYYY-M-DD) would be more complex e.g.
#Query("SELECT * FROM todo_table WHERE date(CASE WHEN length(date) = 8 THEN substr(date,1,5)||'0'||substr(date,6,1)||'-0'||substr(date,8) WHEN length(date) = 9 AND substr(date,7,1) = '-' THEN substr(date,1,5)||'0'||substr(date,6) WHEN length(date) = 9 AND substr(date,8,1) = '-' THEN substr(date,1,8)||'0'||substr(date,9) ELSE date END) = date('now');")
Recommended Fix
The recommended fix is to store values using one of the accepted formats rather than try to manipulate values to be an accepted date to then be worked upon using the date and time functions.

Python Datetime string parsing: How to know what has been parsed?

I want to use Python to parse a user input string and need to know which portion of date has been specified, e.g.,
"Jan. 2017" => Month = 1, Year = 2017
The result should tell me only month and year are specified in the string, and return those values, while:
"2003-05-01"
specifies day, month and year.
I tried to use dateutil.parser.parse, and gave it a rare default date value. e.g., 1900/01/01, and then compare the parsed result with the default date and see the difference. But if the month or day are both 1 in the parsed result,
it needs one more round of parsing with a different default value, in order to rule out the possibility of it being the default value, or from the user input.
The above way seems quirky. Is there a library for me to parse commonly used date string format and knowing what has been parsed?
I ended up doing the quirky way:
from dateutil.parser import parse
# parse the date str, and return day/month/year specified in the string.
# the value is None if the string does not have information
def parse_date(date_str):
# choose two different dates and see if two parsed results
default_date1 = datetime.datetime(1900, 1, 1, 0, 0)
default_date2 = datetime.datetime(1901, 12, 12, 0, 0)
year = None
month = None
day = None
try:
parsed_result1 = parse(date_str, default=default_date1)
parsed_result2 = parse(date_str, default=default_date2)
if parsed_result1.year == parsed_result2.year: year = parsed_result2.year
if parsed_result1.month == parsed_result2.month: month = parsed_result2.month
if parsed_result1.day == parsed_result2.day: day = parsed_result2.day
return year, month, day
except ValueError:
return None, None, None

openerp domain filters how to compare 2 fields in object?

In Odoo/OpenERP I want to make a filter to compare field1 and field2 of the same object like below.
Plz let me know how to make this filter work, adding filter on partners search form:
<field name="credit_limit"/>
<field name="credit"/>
<filter name="credit limit" domain="[('credit','>',credit_limit)]"/>
Applying this filter gives below error:
Uncaught Error: Failed to evaluate search criterions:
{"code":400,"message":"Evaluation Error","data":{"type":"local_exception","debug":"Local evaluation failure\nNameError: name 'credit_limit' is not defined\n\n{\"domains\":[[],\"[('customer','=',1)]\",\"[('credit','=',credit_limit)]\"],\"contexts\":[{\"lang\":\"en_US\",\"tz\":\"Africa/Cairo\",\"uid\":1,\"search_default_customer\":1}],\"group_by_seq\":[]}"}}
I googled many times to find a solution without finding anyone .
the simple form [('credit_limit','<',credit)] always returns the error "can not convert string to float" where string is credit and float is credit_limit.
is there any way to say [('credit_limit','<',valueof(credit))] or [('field1','=',valueof(field2))] ??
Regards,
You need to create a function field with a search function to do that.
Here is an example, using the 'old api' syntax:
class SomeModel(orm.Model):
_name = 'some.model'
def _func_credit_limit_exceeded(self, cr, uid, ids,
field_name, arg, context):
"""compute the value of the function field"""
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = record.credit > record.credit_limit
return res
def _func_search_credit_limit_exceeded(self, cr, uid, obj,
name, criterion, context):
"""we only support a search on the form
('column_name', '=', boolean) or ('column_name', '!=', boolean)
"""
match_ids = []
field, op, value = criterion
# argument processing
if op == '!=':
value = not value
elif op != '=':
raise ValueError('Unsupported operator')
# build the search query
if value = True:
comparison = '>'
else:
comparison = '<='
query = 'SELECT id FROM some_model ' \
'WHERE credit %s credit_limit' % comparison
# get the ids matching the search
# and return the corresponding domain
cr.execute(query)
for row in cr.fetchall():
match_ids.append(row[0])
if match_ids:
# return domain matching the selected ids
return [('id', 'in', match_ids)]
else:
# return a domain which will never yield a result
return [('id', '=', 0)]
_columns = {'credit': fields.float('Credit'),
'credit_limit': fields.float('Credit Limit'),
'credit_limit_exceeded':
fields.function(_func_credit_limit_exceeded,
fnct_search=_func_search_credit_limit_exceeded,
string='Credit Limit Exceeded',
type='boolean'),
}
For numeric fields, you can create a computed field which counts the difference of the two field. if the result is 0 they are equal, if negative the 2nd is greater if positive the first is greater.

Rails Auto-populate form field based off of date input

I have a Rails 3.2.18 app where in my form I have a field for age (int) and date of birth (datetime). I will be using a simple jQuery date picker to select the DOB.
Here's what I want to happen.
The first field is the DOB (Date of birth). I want to select that, and as soon as it's selected I'd like to calculate the age and automatically fill the age field based off of that selection.
I think I can do it somehow by creating a method on the model that calculates the age, but I'm not sure how to populate it in the age field. Perhaps some Javascript or something?
Any help would be greatly appreciated.
Below is a method I wrote for another app that calculates age based on DOB and can be used in a view:
def age(dob)
now = Time.zone.now.to_date
now.year - patient_dob.year - ((now.month > patient_dob.month || (now.month == patient_dob.month && now.day >= patient_dob.day)) ? 0 : 1)
end
What you are suggesting is not possible to do in Ruby. You can use JavaScript.
It's not possible to calculate the age, based on user input, without first traveling to the server, calculating the age, and then rendering the result to the client. The model has no knowledge of the date that the user puts in; this is, unless you submit the form, of course.
It's possible to submit the form via Ajax. For example, some sites let you fill in a zip code, and then they prefil the address for you. What is really happening is, behind the scenes, the browser is sending an ajax request to a server that returns an address.
In your case you shouldn't have to do that since calculating the age in JavaScript is very easy. It's also quicker to do it on the client since it saves you the round trip to the server.
Take a look at this answer which shows you how to calculate a persons age based on an input date.
If you are using Rails you will likely be using jQuery. In which case you can do something like this:
$('#date_input').on('change', function () {
date = $(this).val();
age = getAge(date);
$('#age_input').val(age);
});
# This is taken directly from this answer: https://stackoverflow.com/a/7091965/276959
function getAge(dateString) {
var today = new Date();
var birthDate = new Date(dateString);
var age = today.getFullYear() - birthDate.getFullYear();
var m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
return age;
}
Then, on the server you may want to recalculate the age before you save the data into the database. This is because nothing stops the user from submitting a false age directly. Either by filling it in, or by altering the DOM.
class Person
before_save :set_age
private
def set_age
self.age = # Calculate age here.
end
end
See this answer on how to calculate age using Ruby, which looks identical to the code you have in your question.
This is a more client side javascript way to achieve this with date accuracy using server.
In your rails view when parent page loads
<%= javascript_tag do%>
var currDate = new Date('<%= Date.today%>');
<%end%>
In your js file (i assumed date-picker to be the input selected using date picker.)
function calcAge(dateString) {
var birthDate = new Date(#('date_picker').val());
var age = currDate.getFullYear() - birthDate.getFullYear();
var m = currDate.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && currDate.getDate() < birthDate.getDate())) {
age--;
}
return age;
}
Then just need to call calcAge on date selected event and the
return age;
can change to set value on an input field
$('#ageField').val(age);

LINQ - Return Value From Field With A Max Value if No Rows Found

I have a table like this...
ID Description LowThreshold HighThreshold
1 BAD 0.0 .69
2 MEETS .70 .89
3 GOOD .90 2
The object here is to write a LINQ query that will select the right Description based on a given decimal. For instance .75 is between .70 and .89, so it would return “MEETS”. BUT, the kicker is, if the Number is higher than all the ranges, automatically return the Description for the record with the highest HighThreshold. So, if I pass in 5, I should get “GOOD” returned.
I have this so far, but it errors out with scores higher than 2, obviously:
private string GetEvaluationDescription (decimal score)
{
string evaluationText = myContext.PerformanceRanges.Where
(e =>
e.LowThreshold <= score
&&
e.HighThreshold >= score
)
.Select(eval => eval.Description).First().ToString();
}
I'd like to accomplish this with just this one query, but my imagination isn't getting me there. I attempted what I found in this post but couldn't get it to work
What about this:
var range = myContext.PerformanceRanges
.SingleOrDefault(e=>e.LowThreshold <= score && e.HighThreshold >= score)??
PerformanceRanges.Single(
e=>e.HighThreshold == PerformanceRanges
.Max(p=> p.HighThreshold)
);
string evaluationText = range.Description;
The range query will select the element that matches with the Thereshold ranges, and if the value is greater (the first query will return null), it will select the greatest range.
What about this:
string evaluationText = myContext.PerformanceRanges.Where
(e =>
(e.LowThreshold <= score
&&
e.HighThreshold >= score) ||
(e.HighThreshold ==
myContext.PerformanceRanges.Max (
x => x.HighThreshold)
&& score > e.HighThreshold )
)
.Select(eval => eval.Description).First().ToString();

Resources