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
#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
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
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')
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)
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.