Openerp calculate qty and date listing - reporting

I am very new to openerp, and have been given a task. My firts question which sounds silly is, how can I stirp datefield to just a month on openerp. 2. with the code below am trying to get a balance of water in reservoirs basically calculating from water meter in - meter out to get balance this has to work like a quantity in stock control
def _water_balance(self, cr, uid, ids, field_name, arg, context):
res = {}
bal = 0.0
for rec in self.browse(cr, uid, ids, context=context):
for traject in rec.trajectory_ids:
trajectory_balance = self.pool.get('supply.trajectory').browse(cr, uid, traject.id , context=context).trajectory_balance
bal += float(trajectory_balance)
res[rec.id] = bal
return res

You can get month from datetime field using strftime function like,
month = datetimefield.strftime("%m") # Month of the datetimefield
month = datetime.now().strftime("%m") # Current month
Just changed few code try following,
def _water_balance(self, cr, uid, ids, field_name, arg, context):
res = {}
for rec in self.browse(cr, uid, ids, context=context):
res[rec.id] = 0.00
bal = 0.0
for traject in rec.trajectory_ids:
bal += float(traject.trajectory_balance)
res[rec.id] = bal
return res

Related

Filter a Query Set

The following view works great. I pass in student_id and I get a queryset of headers and attendance days related to that student_id. My challenge is that I cannot figure out how to filter my attendance_days queryset by a specific date or date range.
I have tried variations of:
attendance_days = student.zzabsentdetail_set.order_by('-absent_date').filter('absent_date' is between '2021-02-01' and '2021-02-26')
or
attendance_days = student.zzabsentdetail_set.order_by('-absent_date').filter('absent_date' > '2021-02-01')
I would like to filter my zzabsent_detail queryset by absent date on that line if possible.
Here is my view:
def absent_detail(request, student_id):
"""Show student & attendance info"""
student = Student.objects.get(id=student_id)
header = student.zzheader_set.order_by('id')
attendance_days = student.zzabsentdetail_set.order_by('-absent_date')
context = {'student': student, 'header': header, 'attendance_days':
attendance_days}
return render(request, 'learning_logs/absent_detail_99.html', context)
You can do this with a __range lookup [Django-doc]:
attendance_days = student.zzabsentdetail_set.filter(
absent_date__range=('2021-02-01', '2021-02-26')
).order_by('-absent_date')
here the two bounds are inclusive, so items on February 1st, or February 26th will be included as well.
or you can work with the __gt lookup [Django-doc] to express that the value should be greater than a given value:
attendance_days = student.zzabsentdetail_set.filter(
absent_date__gt='2021-02-01'
).order_by('-absent_date')
for the last 10 days, you can work with a date object instead of a string, so:
from datetime import timedelta
from django.utils.timezone import now
from_dt = now().date()-timedelta(days=10)
attendance_days = student.zzabsentdetail_set.filter(
absent_date__gt=from_dt
).order_by('-absent_date')

Rewrite an OpenERP 7 method to Odoo 8 syntax?

I have the following OpenERP 7 method:
# Function to get the vat number (CIF/NIF) and then show it on invoice form view
def _get_vat_num(self, cr, uid, ids, field_name, args=None, context=None):
partner_pool = self.pool.get('res.partner')
invoice_pool = self.pool.get('account.invoice')
res = {}
for inv in self.browse(cr, uid, ids, context=context):
invoice = invoice_pool.browse(cr,uid, inv.id, context=None)
partner = partner_pool.browse(cr, uid, invoice.partner_id.id, context=None)
res[inv.id] = partner.vat
return res
inv_vat = fields.Char(compute='_get_vat_num', string="CIF/NIF")
I need to rewrite it to Odoo v8 syntax. I have tried but it doesn't work:
def _get_vat_num(self):
partner_pool = self.env['res.partner']
invoice_pool = self.env['account.invoice']
res = {}
for inv in self.browse(self.id):
invoice = invoice_pool.browse(inv.id)
partner = partner_pool.browse(invoice.partner_id.id)
res[inv.id] = partner.vat
return res
What should be the correct code?
It looks like you're setting a functional field. You should instead be able to define the field as a related field like so:
inv_vat = fields.Char(string="VAT", related="partner_id.vat")
If you really want it as a functional field, this is how you would do it
inv_vat = fields.Char(string="VAT", compute="_get_vat_num")
def _get_vat_num(self):
# self is a recordset of account.invoice records
for invoice in self:
# to set a functional field, you just assign it
invoice.inv_vat = invoice.partner_id.vat
Check out the recordset documentation: https://www.odoo.com/documentation/8.0/reference/orm.html#recordsets
And the computed fields documentation:
https://www.odoo.com/documentation/8.0/reference/orm.html#computed-fields

How do I get a count of values by month in linq to sql?

I have a table of feedback scores, which essentially contains a date field and a "score" field (which may be "happy", "neutral" or "sad").
I want to return a query which gives me the count of each score by month, like this:
However, my query isn't grouping correctly - I'm basically getting three rows for each month (one row for "happy", one for "neutral" and one for "sad", like this:
How do I aggregate the data together?
My query at the moment is this:
var monthlyScore = from f in db.tl_feedbacks
group f by new { month = f.timestamp.Month, year = f.timestamp.Year, score = f.tl_feedback_score.score } into g
select new
{
dt = string.Format("{0}/{1}", g.Key.month, g.Key.year),
happyCount = g.Where(x => x.tl_feedback_score.score == "happy").Count(),
neutralCount = g.Where(x => x.tl_feedback_score.score == "neutral").Count(),
sadCount = g.Where(x => x.tl_feedback_score.score == "sad").Count(),
total = g.Count()
};
Remove , score = f.tl_feedback_score.score from your grouping.

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.

Searching between two dates with Ruby IMAP

I am new to Ruby, I'm trying to return the number of emails between 9am and 11am.
For example.
#received_today = imap.search(["SINCE", #today.strftime("%d-%b-%Y-%H"):"BEFORE", #today.strftime("%d-%b-%Y-%H")]).count.to_s
I know this is wrong, but it's my closest guess on how to do this. Any help would be highly appreciated.
Maybe something like this:
require 'date'
start_time = Net::IMAP.format_datetime(DateTime.strptime("09:00", "%H:%M"))
end_time = Net::IMAP.format_datetime(DateTime.strptime("11:00", "%H:%M"))
#received_today = imap.search(["SINCE", start_time, "BEFORE", end_time ]).count
UPDATE:
Try #2 :)
Since imap SEARCH command ignores the time part in SINCE and BEFORE conditions this should work:
require 'date'
today = Net::IMAP.format_date(Date.today)
start_time = DateTime.strptime("09:00", "%H:%M")
end_time = DateTime.strptime("11:00", "%H:%M")
#received_today = imap.search(["ON", today]) # get sequence nums of todays emails
# fetch the INTERNALDATE-s and count the ones in the timeframe
count = imap.fetch(#received_today, "INTERNALDATE").count{ |data|
time = DateTime.parse(data.attr["INTERNALDATE"])
time.between? start_time, end_time
}

Resources