How to limit the approve action only for the manager of team - python-3.x

I'm using odoo11 and i have installed a custom module to calculate the overtime, i've many team leaders, each team leader has a number of employee.
I want to limit the approve action for the manager in a way every manager approve request of his own employees only.
I have override the approve action to verify if the person who's gone approve is his manager or not but always it allows any manager to approve all the requests. Here is code :
overtime.py
class BtHrOvertime(models.Model):
_name = "bt.hr.overtime"
_description = "Bt Hr Overtime"
_rec_name = 'employee_id'
_order = 'id desc'
employee_id = fields.Many2one('hr.employee', string="Employee")
manager_id = fields.Many2one('hr.employee', string='Manager')
start_date = fields.Datetime('Date check in')
end_date = fields.Datetime('Date check out')
overtime_hours = fields.Float('Overtime Hours')
notes = fields.Text(string='Notes')
state = fields.Selection([('draft', 'Draft'), ('confirm', 'Waiting for Approval'), ('refuse', 'Refused'),
('validate', 'Approved'), ('cancel', 'Cancelled')], default='draft', copy=False)
attendance_id = fields.Many2one('hr.attendance', string='Attendance')
user_id = fields.Many2one('res.users', string='User', related='employee_id.user_id', related_sudo=True,
compute_sudo=True, store=True, default=lambda self: self.env.uid, readonly=True)
parent_id = fields.Many2one('bt.hr.overtime', string='Parent', copy=False)
#api.multi
def action_approve(self):
if (self.employee_id.parent_id.user_id.id != uid):
raise exceptions.UserError(_('You cannot approve.'))
elif self.attendance_id.check_in and self.attendance_id.check_out:
start_date = datetime.datetime.strptime(self.attendance_id.check_in, DEFAULT_SERVER_DATETIME_FORMAT)
end_date = datetime.datetime.strptime(self.attendance_id.check_out, DEFAULT_SERVER_DATETIME_FORMAT)
difference = end_date - start_date
hour_diff = str(difference).split(':')[0]
min_diff = str(difference).split(':')[1]
tot_diff = hour_diff + '.' + min_diff
actual_working_hours = float(tot_diff)
for record in self:
if actual_working_hours > 9:
record.overtime_hours = actual_working_hours - 9
record.start_date = record.attendance_id.check_in
record.end_date = record.attendance_id.check_out
else:
record.overtime_hours = 0
record.start_date = record.attendance_id.check_in
record.end_date = record.attendance_id.check_out
return self.write({'state': 'validate'})

Please use the below code or checking:
if (self.employee_id.parent_id.user_id.id != self.env.user.id):
raise exceptions.UserError(_('You cannot approve.'))
I think that employee_id.parent_id is the manager of the employee. Also please be informed that you can create a new user group
<record id="group_is_manager" model="res.groups">
<field name="name">Is a manager?</field>
</record>
For the Manager users you can check this group and give this group for approve button
<button name="" string="" type="" groups="module_name.group_is_manager"/>
Hence, the button will be visible to those users who have this group.

Related

Telegram Bot profile with calendar

I am writing a bot profile. After the answer, the following question should be asked. In one of the steps you need to select a date. I use a ready-made calendar. But after choosing a date, the next question is not asked, but the script does not crash, only waits for input and throws the Exception defined in the code below. How to fix that would bring up the next question "What is your name?". Thank. Here is the part of the code that includes the previous calendar question and the next question:
def process_Personenanzahl_step(message):
try:
chat_id = message.chat.id
user = user_dict[chat_id]
user.carModel = message.text
markup = types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)
itembtn1 = types.KeyboardButton('1')
itembtn2 = types.KeyboardButton('2')
itembtn3 = types.KeyboardButton('3')
itembtn4 = types.KeyboardButton('4')
itembtn5 = types.KeyboardButton('5')
markup.add(itembtn1, itembtn2, itembtn3, itembtn4, itembtn5)
msg = bot.send_message(chat_id, 'Qun', reply_markup=markup)
bot.register_next_step_handler(msg, check_calendar_messages)
except Exception as e:
bot.reply_to(message, 'ooops!!')
calendar_1 = CallbackData("calendar_1", "action", "year", "month", "day")
def check_calendar_messages(message):
now = datetime.datetime.now() # Get the current date
bot.send_message(
message.chat.id,
"Selected date",
reply_markup=telebot_calendar.create_calendar(
name=calendar_1.prefix,
year=now.year,
month=now.month, # Specify the NAME of your calendar
),
)
#bot.callback_query_handler(func=lambda call: call.data.startswith(calendar_1.prefix))
def callback_inline(call: object) -> object:
# At this point, we are sure that this calendar is ours. So we cut the line by the separator of our calendar
name, action, year, month, day = call.data.split(calendar_1.sep)
# Processing the calendar. Get either the date or None if the buttons are of a different type
date = telebot_calendar.calendar_query_handler(
bot=bot, call=call, name=name, action=action, year=year, month=month, day=day
)
# There are additional steps. Let's say if the date DAY is selected, you can execute your code. I sent a message.
if action == "DAY":
msg = bot.send_message(
chat_id=call.from_user.id,
text=f"You have chosen {date.strftime('%d.%m.%Y')}",
reply_markup=ReplyKeyboardRemove(),
)
print(f"{calendar_1}: Day: {date.strftime('%d.%m.%Y')}")
bot.register_next_step_handler(msg, process_fullname_step)
def process_fullname_step(message):
try:
chat_id = message.chat.id
user_dict[chat_id] = User(message.text)
markup = types.ReplyKeyboardRemove(selective=False)
msg = bot.send_message(chat_id, 'What is your name?', reply_markup=markup)
bot.register_next_step_handler(msg, process_fullname_step)
except Exception as e:
bot.reply_to(message, 'ooops!!')

i have added a field in existing module "hr.payslip" from my module.How to show the data of that field

an existing module is present i.e hr.payslip,In that module i have added a field from my module . now i want to display the value of that field in hr.payslip module.
models/emailpayslip.py
#api.multi #Decorate a record-style method where 'self' is a recordset. The method typically defines an operation on records.
def send_email(self):
ir_model_data = self.env['ir.model.data']
payslip_obj = self.env['hr.payslip']
ids = self.env.context.get('active_ids', [])
ctx = dict()
employee_name = ''
for id_vals in ids:
payslip_browse = payslip_obj.browse(id_vals)
global email
email = payslip_browse.employee_id.work_email
store_email.sql_example(self,email)#calling method of store_email model
if payslip_browse.employee_id.work_email:
template_id = ir_model_data.get_object_reference('Payslip', 'email_template_payslip')[1]
ctx.update({
'default_model': 'hr.payslip',
'default_res_id': payslip_browse.id,
'default_use_template': bool(template_id),
'default_template_id': template_id,
'default_composition_mode': 'comment',
'email_to': payslip_browse.employee_id.work_email,
})
mail_id = self.env['mail.template'].browse(template_id).with_context(ctx).send_mail(payslip_browse.id, True)
This model is used to create a new table in database and store email to which the payslip is send and date of payslip send
class store_email(models.Model):
_name = "store.email"
sendemail = fields.Char(
string='Send Email',
default=lambda self: self._get_default_name(),
)
no_of_times = fields.Integer(string='No of Times')
date_of_email_send = fields.Date(
string="Date of Email",
default=lambda self: fields.datetime.now())
#api.model
def _get_default_name(self):
return "test"
#api.multi
def sql_example(self,temp):
dob = datetime.today()
self.env.cr.execute("SELECT * FROM store_email WHERE sendemail = %s",(temp,))
res = self.env.cr.fetchall()
if res == []:
count = 1
self.env.cr.execute("INSERT INTO store_email (sendemail,no_of_times,date_of_email_send) VALUES (%s,%s,%s)",(temp,count,dob))
self.env.cr.commit()
else:
for x in res:
count = x[7] + 1
self.env.cr.execute("UPDATE store_email SET date_of_email_send=%s,no_of_times=%s WHERE sendemail=%s",(dob,count,temp))
self.env.cr.commit()
Model to add a field in hr.payslip ,Which show last payslip send date
class Add_Field(models.Model):
_inherit = "hr.payslip"
last_payslip_send = fields.Date(string='Last Payslip Send')
#api.multi
def last_send_payslip(self):
self.env.cr.execute("SELECT * FROM store_email WHERE sendemail=%s",(email,))
res = self.env.cr.fetchall()
my addfile.xml
add_newfield
screenshort of the page where i have added the field
this page cntain the screenshort
You can use compute or default function to load value in to field or you can also pass value while creating record
default function example:
name = fields.Char(
string='Name',
default=lambda self: self._get_default_name(),
)
#api.model
def _get_default_name(self):
return "test"
Refer this link for computed fields

Create Sale Order Line in route_id on-change method

I have to create sale order line in on change of route_id, but i am trying to using self.copy() method, but there is issue of order_id.
I didn't get order_id, because I need current record id of Sale Order instead of NewId.
#api.multi
#api.onchange('route_id')
def _onchange_route_id(self):
# Ht stock route dosen't have enough quantity, add new sale order line
remain_qty = 0
route_ht_stock = self.env.ref('custom_stock.route_warehouse0_ht_stock', raise_if_not_found=False)
if self.route_id.id == route_ht_stock.id:
if not self.product_id.qty_available >= self.product_uom_qty:
remain_qty = self.product_uom_qty - self.product_id.qty_available
new_line = self.copy(default = {'order_id': self.order_id}))

select on sub query peewee

I am wondering if I can do select() on sub_query.
I am able to do join sub_query with any peewee.Model. But when I wrote a sub_query and I wanted to just group by with one of the column
e.g. sub_query.select(sub_query.c.column_1, fn.COUNT(sub_query.c.column2)alias('col2_count')).group_by(sub_query.c.column_1)
query was not nested and was giving SQL syntax error.
(Can't reveal the code)
(I have done alias() on sub_query)
Edit
Example:
class Product(Model):
id = PrimaryKeyField()
name = CharField()
created_date = DateField()
class Part(Model):
id = PrimaryKeyField()
product = ForeignKeyField(Product)
name = CharField()
class ProductError(Model):
id = PrimaryKeyField()
product = ForeignKeyField(Product)
note = CharField()
class PartError(Model):
id = PrimaryKeyField()
part = ForeignKeyField(Part)
error = ForeignKeyField(ErrorMaster)
Here Product can have general error and
parts can have specific error which are predefined in ErrorMaster
I just want to know count of product which have errors against total products date wise. (error is product error or error in any part)
So sub_query is something like
sub_q = Product.select(
Product.created_date,
Product.id.alias('product_id'),
fn.IF(# checks if product has error
ProductError.is_null(True), if no product error check part error
fn.IF(fn.COUNT(PartError.id) == 0, 0, 1), # checks if error count > 0 then there is error in part
1
).alias('is_error')
).join(Part, on=Product.id == Part.product)
.join(ProductError, JOIN_LEFT_OUTER, on=Product.id == ProductError.product)
.join(PartError, JOIN_LEFT_OUTER, on=PartError.part == Part.id)
.where(Product.created_date.between(from_date, to_date))
.group_by(Product.id).alias('some_alias')
# below does not work but I can do this in sql
query = sub_q.select(sub_q.c.created_date,
fn.COUNT(sub_q.c.product_id).alias('total_products'),
fn.SUM(sub_q.c.is_error).alias('product_with_errors'))
.group_by(sub_q.c.created_date)

How to store multiple values in One2many field through odoo website

I have made a Bulk Inquiry form in odoo website. In which the fields category, qty, brand are to be repeated on clicking Click To Select More Products
Webpage Image:
The problem which I am facing is, values of first row are stored in database but fails to store the values for the next product/category and I have to store it in One2many field
Here is my code (controllers.py):
#http.route(['/website_form/'], auth='public', website=True,methods=['POST', 'GET'], csrf=False, type="http")
def bulkorder(self, **kwargs):
if kwargs:
contact_name = kwargs.get('contact_name')
phone = kwargs.get('phone')
email_from = kwargs.get('email_from')
partner_name = kwargs.get('partner_name')
designation = kwargs.get('designation')
gst_no = kwargs.get('gst_no')
name = kwargs.get('name')
description = kwargs.get('description')
category = kwargs.get('category')
quantity = kwargs.get('quantity')
brand = kwargs.get('brand')
select_type = kwargs.get('select_type')
lines = [(0,0,{'category':category,
'quantity':quantity,
'brand':brand})]
user_data = {
'contact_name': contact_name,
'phone': phone,
'email_from': email_from,
'partner_name': partner_name,
'designation': designation,
'gst_no': gst_no,
'name':name,
'description': description,
'select_type': select_type,
'bulk_order_line':lines,
'select_type':select_type,
}
store = http.request.env['bulk.order']
store.create(user_data)
store.bulk_order_line.write({})
return http.local_redirect('/contactus-thank-you')
models.py:
from odoo import models, fields, api,_
from odoo.exceptions import UserError
from odoo import SUPERUSER_ID
class EIndustry_bulkorder(models.Model):
_name = 'bulk.order'
contact_name=fields.Char(string="Full Name")
phone=fields.Char(string="Phone Number", limit=10)
email_from=fields.Char(string="Email")
partner_name=fields.Char(string="Company Name")
designation=fields.Char(string="Designation")
gst_no=fields.Char(string="GST Number")
name=fields.Char(string="Subject")
description=fields.Char(string="Your Question")
category=fields.Char(string="Product/Category")
quantity=fields.Char(string="quantity")
brand=fields.Char(string="Brand/Make")
lead=fields.Char(string="Lead")
select_type=fields.Many2one('bulk.retailer' , string="Profession",
required=True , store = True)
bulk_order_line = fields.One2many('bulk.bulk_order_lines','bulk_order_line_id',
string='Bulk Order Lines')
class retailerType(models.Model):
_name='bulk.retailer'
name = fields.Char(string="Retailer Name")
class BulkOrderLine(models.Model):
_name = 'bulk.bulk_order_lines'
bulk_order_line_id=fields.Many2one('bulk.order','bulk_order_line',
ondelete='cascade', index=True, copy=False)
category=fields.Char(string="Product/Category")
quantity=fields.Char(string="Quantity")
brand=fields.Char(string="Brand")

Resources