How to solve singleton error while looping in odoo? - 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

Related

Condition while creating Product in Module, Odoo

I have an Inventory module. I want to check db before creating data. Check for reference code. If ref_code already exist then cancel the creation.
This is my .py file:
ref_code = fields.Char(string="Referans Numarası: ", required=True, tracking=True, related="products_id.ref_no")
#product_name = fields.Char(string="Ürün Adı: ", required=True, tracking=True)
product_description = fields.Char(string="Ürün Tanımı: ", tracking=True,)
teslim_alan = fields.Char(string="Teslim Alan: ", required=True, tracking=True,)
teslim_eden = fields.Char(string="Teslim Eden: ", required=True, tracking=True,)
quantity = fields.Float(string="Miktar: ", required=True, tracking=True)
price = fields.Float(string="Fiyat(€): ", required=True, tracking=True, related="products_id.unit_price")
unit_price = fields.Float(string="Birim Fiyat(€): ", compute="_unitPriceCalcuteFunc")
scrap_quantity = fields.Float(string="Hurdaya Taşınacak Miktar: ")
warehouse_id = fields.Many2one('ware.houses', string='Depo Adı: ')
products_id = fields.Many2one('products', string='Ürün: ')
state = fields.Selection([
('unapproved', 'Çıkış İçin Onay Verilmedi.'),
('approved', 'Çıkış İçin Onay verildi.')], string="Status", default="unapproved", tracking=True)
cikis_line_ids = fields.One2many('inventory.out.report.lines', 'inventory_id', string='Çıkış Listesi')
#api.model
def create(self, values):
global count
count = 0
value = self.env['inventory.menu'].search([])
for record in values:
for v in value:
print(v.ref_code, record.ref_code)
if(v.ref_code == record.ref_code):
count += 1
return print("Zaten Var!")
if(count == 0):
return super(InventoryMenu, self).create(values)
I can find the all data in db. It is ok. But the current data is not exist, i can't use it. I need the compare current data with db data.
How can i do it? Many thanks..
#api.model
def create(self, values):
global count
count = 0
value = self.env['inventory.menu'].search([])
for v in value:
if(v.ref_code == values['ref_code']):
count += 1
return print("Zaten Var!")
if(count == 0):
return super(InventoryMenu, self).create(values)
enter code here
You can search for the specific ref_code. Just didn't do something like search([]) cause it's contrproductive.
#api.model
def create(self, values):
ref_codes_count = self.env['inventory.menu'].search(
[("ref_code", "=", values.get("ref_code"))],
count=True,
)
if not ref_codes_count:
return super(InventoryMenu, self).create(values)
or you can try to use something like this
#api.model
def create(self, values):
self.env.cr.execute(
"SELECT COUNT(*) FROM module_name.model_name WHERE ref_code='%s'" %
values.get("ref_code")
)
ref_codes_count = self.env.cr.fetchall()[0]
if not ref_codes_count:
return super(InventoryMenu, self).create(values)

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

Check if dataframe contain Date or Time

I want to check if dataframe contain a date or datetime value in python dataframe. It is possible to do it ?
df = {'Latitude':['19.34', '19.42', '-4.34', '35.10'],
'Date':['2019-03-13', '2016-07-08', '2018-03-08', '2014-01-17']}
and make a function to check date
def CheckDate():
return True
CheckDate(df)
True
Just use in:
df = {'Latitude':['19.34', '19.42', '-4.34', '35.10'],
'Date':['2019-03-13', '2016-07-08', '2018-03-08', '2014-01-17']}
'2019-03-13' in df['Date']
True
'2019-03-30' in in df['Date']
False
In function it would look like this:
def checkDate(df, date)
return date in df['Date']
You can try below code to check if a given date exists in a dataframe:
yourdate = '2018-03-08'
print((df['Date'] == yourdate).any())
output:
True
Alternatively, you can try this:
print('2018-03-08' in df['Date'].values)
output:
True
Desired Code:
def checkDate(df, date):
if date in df['Date'].values:
return True
return False
df = pd.DataFrame({'Latitude':['19.34', '19.42', '-4.34', '35.10'],
'Date':['2019-03-13', '2016-07-08', '2018-03-08', '2014-01-17']})
print(checkDate(df, '2018-03-08'))
print(checkDate(df, '2018-03-09'))
output:
True
False
You can also write you function like this:
def checkDate(df, date):
return date in df['Date'].values

Odoo 9 context value missing in override method

in odoo9 I override the search_read method. The super method works ok. With the data returned I want to make a filter, the filter is on the context, the value was asigned on the click of the button comming from the view.
<button name="status_instalacion" string="Instalación" type="action" icon="fa-wrench fa-2x" context="{'stage_id' : 1, 'current_id': active_id}"/>
The problem occurs when I query the context in the search_read method. It exists but doesn't have the values I placed
context on click of button:
self._context
{u'lang': u'en_US', u'stage_id': 1, u'tz': False, u'uid': 1, u'current_id': 40, u'tipo_validacion': u'Sistemas Cr\xedticos', u'sistema_critico': u'AGUA'}
the stage_id is the value I want
context on read_search:
self._context
{u'lang': u'en_US', u'bin_size': True, u'tipo_validacion': u'Sistemas Cr\xedticos', u'tz': False, u'uid': 1,
u'active_test': False, u'sistema_critico': u'AGUA'}
as you can see the 'stage_id' value is missing
Tried also assigning the value to a property of the class, but the value never changes it is always the initial value.
from logging import getLogger
from openerp import api, fields, models
_logger = getLogger(__name__)
class MgmtsystemSistemasEquipos(models.Model):
""" Equipos."""
_name = 'mgmtsystem.sistemas.equipos'
dmy = 99 # ---> this value never changes
def dummy(self): # ---> tried calling a function. not work
return self.dmy
def set_dummy(self, id): # ----> set the value
self.dmy = id or self.dmy
codigo = fields.Char(
string=u'Código',
help=u"Código equipo",
required=True,
size=30)
name = fields.Char(
string=u'Nombre equipo',
required=True,
readonly=False,
index=True,
help="Nombre corto equipo",
size=30)
stage_id = fields.Many2one(
'mgmtsystem.action.stage',
'Fase',
default=_default_stage,
readonly=True)
#api.multi
def status_instalacion(self):
import pudb
pu.db
# save value to variable dmy to retrieve later
id = self._context.get('stage_id')
self.set_dummy(id)
#api.model
def search_read(
self, domain=None, fields=None, offset=0,
limit=None, order=None):
import pudb
pu.db
# here the variable allways has the original value (99)
current_stage_id = self.dmy
current_stage_id = self.dummy()
current_stage_id = getattr(self, dmy)
res = super(MgmtsystemSistemasEquipos, self).search_read(
domain, fields, offset, limit, order)
current_id = res[0]['id']
valid_protocols_ids = self._get_ids(
current_stage_id, current_id,
'mgmtsystem_equipos_protocolos',
'mgmtsystem_equipos_protocolos_rel',
'protocolo_id')
# # remove ids
res[0]['protocolos_ids'] = valid_protocols_ids
res[0]['informes_ids'] = valid_informes_ids
res[0]['anexos_ids'] = valid_anexos_ids
return res
# #api.multi
def _get_ids(self, current_stage_id, current_id, model, model_rel, field_rel):
import pudb
pu.db
# in this method the value of the variable is allways the original
current_stage_id = self.dummy()
sql = """ select a.id from
%s as a
join %s as b
on a.id = b.%s where b.equipo_id = %s
and a.stage_id = %s; """ % (model, model_rel, field_rel,
current_id, current_stage_id)
import psycopg2
try:
self.env.cr.execute(sql)
except psycopg2.ProgrammingError, ex:
message = 'Error trying to download data from server. \n {0} \n {1}'.format(ex.pgerror, sql)
_logger.info(message)
return False
rows = self.env.cr.fetchall()
list_of_ids = []
for row in rows:
list_of_ids.append(row[0])
return list_of_ids
I don't know Python very well, and thats the cause of my misunderstanding of how to read the value of the variable.
But then again, Why is the context modified in the search_read method?.
Thank you.
You should try following.
#api.model
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):
import pudb
pu.db
# Here you need to get the value from the context.
current_stage_id = self._context.get('stage_id', getattr(self, dmy))
res = super(MgmtsystemSistemasEquipos, self).search_read(domain=domain, fields=fields, offset=offset, limit=limit, order=order)
current_id = res[0]['id']
valid_protocols_ids = self._get_ids(
current_stage_id, current_id,
'mgmtsystem_equipos_protocolos',
'mgmtsystem_equipos_protocolos_rel',
'protocolo_id')
# # remove ids
res[0]['protocolos_ids'] = valid_protocols_ids
res[0]['informes_ids'] = valid_informes_ids
res[0]['anexos_ids'] = valid_anexos_ids
return res
In your code those lines won't work just because there is no recordset available in self (it's correct behaviour search_read must have #api.model decorator).
# here the variable allways has the original value (99)
current_stage_id = self.dmy
current_stage_id = self.dummy()
current_stage_id = getattr(self, dmy)
So just remove those and lines and apply some other logic to get data.

function to get enddate from startdate & duration in openerp

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.