function to get enddate from startdate & duration in openerp - odoo

this is the first code
class timetable_timetable(osv.osv):
_name='timetable.timetable'
_columns={
'name': fields.char('Name',size="64",required=True),
'course': fields.many2one('college.course','Course'),
'semester': fields.many2one('course.semester','Semester'),
'subject' : fields.one2many('timetable.subjects','timetable_id','Subject')
}
timetable_timetable()
this is the second code
class timetable_subjects(osv.osv):
_name = 'timetable.subjects'
_columns ={
'timetable_id' : fields.many2one('timetable.timetable','Time Table'),
'subject_id': fields.many2one('semester.subject','Subject'),
'start_date': fields.datetime('Start Date',store=True),
'duration' : fields.float('Duration',size=64,required=True),
'end_date' : fields.datetime('End Date',store=True),
'professor' : fields.many2one('professor.professor','Professor')
}
timetable_subjects()
i want to make a function on_change which returns me end_date from start_date & duration. So how can i make that function.

def on_change(self, cr, uid, ids, t_date, duration):
res = {'end_date': False}
if t_date:
now = datetime.strptime(t_date, '%Y-%m-%d %H:%M:%S')
e_date = now + timedelta(hours=duration)
print e_date
f_date = datetime.strftime(e_date, '%Y-%m-%d %H:%M:%S')
res['end_date'] = f_date
return {'value': res}

Write this code in your onchange method for end_date,
from datetime import datetime
from dateutil.relativedelta import relativedelta
def my_onchange(self, cr, uid, ids, s_date, duration):
return {'value': {'end_date': (datetime.strptime(s_date,'%Y-%m-%d %H:%M:%S') + relativedelta(days=duration)).strftime('%Y-%m-%d %H:%M:%S')}}
If your duration is in terms of months or years, write relativedelta(months=duration) for months and relativedelta(years=duration) for years and same way for hours or minutes or seconds.

Related

ValueError: Expected singleton: daily.attendance.line(123,124,125

#api.model
def create(self, vals):
curr = datetime.now()
new_date = datetime.strftime(curr, '%Y-%m-%d')
cal_obj = self.env['daily.attendance'].search([])
#api.constrains('date')
def _date_test_unique(self):
for rec in self:
if self.search_count([('date', '=', rec.date)]) > 1:
raise ValidationError(_('Current Date Attendance Already Existed!'))
#api.onchange('user_id')
def onchange_department(self):
if self.user_id == True:
emps = self.env['hr.employee'].search([])
emp_attd = []
from datetime import datetime
now = datetime.now() # current date and time
check_in = now.strftime('%Y-%m-%d %H:%M:%S')
check_in_from = now.strftime('%Y-%m-%d 05:30')
check_out = now.strftime('%Y-%m-%d %H:%M:%S')
check_out_from = now.strftime('%Y-%m-%d 14:30')
for emp in emps:
vals = {
'employe_id':emp.id,
'check_in': check_in_from,
'check_out': check_out_from,
'is_present': True
}
emp_attd.append([0, 0, vals])
self.update({
'employee_ids': emp_attd,
})
else:
self.employee_ids = False
return {
'type': 'ir.actions.client',
'tag': 'reload',
}
The error happens when Odoo tries to get employee_ids value from a record set but it expects a record.
for emp in self.employee_ids:
You need to loop over self then access employee_ids field value for each record:
Example:
def attendance_validate(self):
for rec in self:
for emp in rec.employee_ids:
You should move the following code outside the for loop
self.write({'state': 'validate', })
Example:
hr_attendance = self.env['hr.attendance']
for rec in self:
for emp in rec.employee_ids:
if emp.is_present == True:
attd_crete_id = hr_attendance .create({'employee_id': emp.employe_id.id,
'check_in': emp.check_in,
'check_out': emp.check_out,
})
rec.write({
'state': 'validate',
})
...
Probably you need to call write state to validate when the attendance_validate method succeed (at the end)
improvement:
The following expression
if emp.is_present == True:
can be simplified to:
if emp.is_present:
You are using two fields is_present and is_absent, you can simply use is_present and when its value is False (not set) the employee is absent.
You need to remove the second if statement, which is useless
elif emp.is_absent == True:
if emp.is_absent == True:
Avoid raising a validation error in the create method because it will break the workflow, instead you can define a constraint on date field:
#api.constrains('date')
def _date_test_unique(self):
for rec in self:
if self.search_count([('date', '=', rec.date)]) > 1:
raise ValidationError(_('Current Date Attendance Already Existed!'))
Update:
The create method should return the newly created record:
#api.model
def create(self, vals):
res = super(CLASS_NAME, self).create(vals)
# Your code
return res
write a for loop before the if statement
#api.onchange('is_present')
def onchange_attendance(self):
for rec in self:
if rec.is_present:
rec.is_absent = False

How to solve singleton error while looping in odoo?

Kindly find the code given below which raises singleton error while executing and please let me know how to loop to select a particular record. Any help is appreciatable!
Code:
#api.model
def create(self, vals):
curr = datetime.now()
new_date = datetime.strftime(curr, '%Y-%m-%d')
cal_obj = self.env['daily.attendance'].search([])
if cal_obj:
for co in cal_obj:
co.date
if co.date == new_date:
raise ValidationError(_('''Current Date Attendance Already Exist!'''))
return super(DailyAttendance, self).create(vals)
#api.onchange('user_id')
def onchange_department(self):
if self.user_id == True:
emps = self.env['hr.employee'].search([])
emp_attd = []
from datetime import datetime
now = datetime.now() # current date and time
check_in = now.strftime('%Y-%m-%d %H:%M:%S')
check_in_from = now.strftime('%Y-%m-%d 05:30')
check_out = now.strftime('%Y-%m-%d %H:%M:%S')
check_out_from = now.strftime('%Y-%m-%d 14:30')
for emp in emps:
vals = {
'employe_id':emp.id,
'check_in': check_in_from,
'check_out': check_out_from,
'is_present': True
To avoid singleton error, kindly add loop for self as given below:
#api.onchange('user_id')
def onchange_department(self):
for rec in self:
if rec.user_id == True:
emps = rec.env['hr.employee'].search([])
emp_attd = []
from datetime import datetime
now = datetime.now() # current date and time
check_in = now.strftime('%Y-%m-%d %H:%M:%S')
check_in_from = now.strftime('%Y-%m-%d 05:30')
check_out = now.strftime('%Y-%m-%d %H:%M:%S')
check_out_from = now.strftime('%Y-%m-%d 14:30')
for emp in emps:
vals = {
'employe_id':emp.id,
'check_in': check_in_from,
'check_out': check_out_from,
'is_present': True

Calling method and field from other model in odoo

these are my 1st model, method, and fields
class overtime(models.Model):
_name = 'overtime'
def calc_overtime(self, start_date, end_date):
#import pdb;pdb.set_trace()
f = '%Y-%m-%d %H:%M:%S'
d1 = datetime.strptime(start_date, f)
d2 = datetime.strptime(end_date, f)
timeDiff = d2-d1
hours = float(timeDiff.total_seconds()/3600)
return hours
start_date = fields.Datetime('Start Date', required=True, default=lambda *a : time.strftime("%Y-%m-%d"+" "+"%H:%M:%S")
, readonly=True, states={'draft': [('readonly', False)]})
end_date = fields.Datetime('End Date', required=True, default=lambda *a : time.strftime("%Y-%m-%d"+" "+"%H:%M%S")
, readonly=True, states={'draft': [('readonly', False)]})
and these are my 2nd model, method and field
class overtime_details(models.Model):
_name='overtime_details'
def function(self):
"calling calc_overtime"
ovrtm = fields.Float('Overtime Hour(s)')
how do i call the calc_overtime method, start_date and end_date as parameters, in the overtime details class by using "self.pool.get"
or "self.env". and make the result as ovrtm field's value. Thanks before
I think you don't need to calculate the nb of hours in the first class, The function sould be in the second class, and add a One2many field.
class overtime(models.Model):
_name = 'overtime'
start_date = fields.Datetime('Start Date', required=True, default=lambda *a : time.strftime("%Y-%m-%d"+" "+"%H:%M:%S")
, readonly=True, states={'draft': [('readonly', False)]})
end_date = fields.Datetime('End Date', required=True, default=lambda *a : time.strftime("%Y-%m-%d"+" "+"%H:%M%S")
, readonly=True, states={'draft': [('readonly', False)]})
class overtime_details(models.Model):
_name='overtime_details'
def compute_houres(self, start_date, end_date):
d1 = self.overtime_id.end_date
d2 = self.overtime_id.start_date
f = '%Y-%m-%d %H:%M:%S'
d1 = datetime.strptime(start_date, f)
d2 = datetime.strptime(end_date, f)
timeDiff = d2-d1
hours = float(timeDiff.total_seconds()/3600)
self.ovrtm = hours
overtime_id = fields.Many2one('overtime', 'Réference', ondelete='cascade'),
ovrtm = fields.Float(compute='compute_houres')

AttributeError: 'model.name' object has no attribute 'generate'

I'm trying to call a function from a wizard button but I get this error:
AttributeError: 'model.name' object has no attribute 'generate'
AttributeError: 'model.name' object has no attribute 'generate'
this is my model code:
class wizard(models.TransientModel):
_name = 'model.name'
department_id = fields.Many2one('hr.department')
employee_id = fields.Many2one('hr.employee')
date_from = fields.Date(string = 'Start Date', required = True)
date_to = fields.Date(string = 'End Date', required = True)
state = fields.Selection([('draft', 'Draft'), ('verify', 'Waiting'),('done', 'Done'),('cancel', 'Rejected'),])
def generate(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
In the xml file:
<button name ="generate" type="object" string="Generate" class="oe_highlight"/>
Thank you
There is indentation issue in your code, fields and methods which are belongs to class must be the next level in indentation.
class wizard(models.TransientModel):
_name = 'model.name'
department_id = fields.Many2one('hr.department')
employee_id = fields.Many2one('hr.employee')
date_from = fields.Date(string = 'Start Date', required = True)
date_to = fields.Date(string = 'End Date', required = True)
state = fields.Selection([('draft', 'Draft'), ('verify', 'Waiting'), ('done', 'Done'),('cancel', 'Rejected'),])
def generate(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'state': 'draft'}, context=context)

how to calculate no of days between two dates using with onchange function in openerp?

I've created a custom field called caldays in payslip screen and in this field I want to get days between from_date and to_date in openerp with onchange function please help me with code
I got below code but how can I put it onchange function
datej = str(payslip.date_to)
datek = str(payslip.date_from)
dj = datej[-2:]
x=0
new = 0
while (x<=31):
x= x+1
if str(x) == dj or "0"+str(x) == dj:
new= x
dk = datek[-2:]
y=0
old = 0
while (y<=31):
y= y+1
if str(y) == dk or "0"+str(y) == dk:
old= y
caldays = new-old + 1
result = caldays
Try this, this will give no. of days, you have to give two arguments in this, i.e
date_from and date_to. Don't forget to import (import datetime and import math)
you can put your fields in xml,
<field name="date_from" on_change="get_number_of_days(date_from,date_to)"/>
<field name="date_to" on_change="get_number_of_days(date_from,date_to)"/>
<field name="number_of_days_temp"/>
and for your py file,
def get_number_of_days(self, date_from, date_to):
"""Returns a float equals to the timedelta between two dates given as string."""
if (date_to and date_from) and (date_from <= date_to):
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
from_dt = datetime.datetime.strptime(date_from, DATETIME_FORMAT)
to_dt = datetime.datetime.strptime(date_to, DATETIME_FORMAT)
timedelta = to_dt - from_dt
diff_day = timedelta.days + float(timedelta.seconds) / 86400
result['value']['number_of_days_temp'] = round(math.floor(diff_day))+1
else:
result['value']['number_of_days_temp'] = 0
return result
Hope this will help you.