diff --git a/hr_leave_dashboard/README.rst b/hr_leave_dashboard/README.rst new file mode 100644 index 000000000..f3d443bb4 --- /dev/null +++ b/hr_leave_dashboard/README.rst @@ -0,0 +1,54 @@ +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg + :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Hr Leave Dashboard +================== +This module helps you to brings a multipurpose graphical dashboard for Time Off module and making the relationship management better and easier. + +Installation +============ + - www.odoo.com/documentation/15.0/setup/install.html + - Install our custom addon + +Configuration +============= +* No additional configurations needed. + +Company +------- +* `Cybrosys Techno Solutions `__ + +License +------- +General Public License, Version 3 (AGPL v3). +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Credits +------- +* Developer: (v15) Safa Faheem, + (v16) Rahul Rajeev, + (v17) Safa Faheem, +Contact: odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/hr_leave_dashboard/__init__.py b/hr_leave_dashboard/__init__.py new file mode 100644 index 000000000..b7ffce683 --- /dev/null +++ b/hr_leave_dashboard/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import models +from . import report diff --git a/hr_leave_dashboard/__manifest__.py b/hr_leave_dashboard/__manifest__.py new file mode 100644 index 000000000..87399f0d5 --- /dev/null +++ b/hr_leave_dashboard/__manifest__.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +{ + 'name': "Hr Leave Dashboard", + 'version': '15.0.1.0.0', + 'category': 'Human Resources', + 'summary': """Advanced Leave Dashboard helps to view your and your + subordinate's details""", + 'description': """Advanced Leave Dashboard brings a multipurpose graphical + dashboard for Time Off module and making the relationship management better + and easier""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['base', 'hr_holidays', 'hr_org_chart'], + 'data': [ + 'report/hr_leave_reports.xml', + 'report/hr_leave_report_templates.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'hr_leave_dashboard/static/src/js/time_off_emp_dashboard.js', + 'hr_leave_dashboard/static/src/css/hr_leave_dashboard.css', + 'hr_leave_dashboard/static/src/scss/variables.scss', + 'hr_leave_dashboard/static/src/scss/hr_org_chart.scss', + 'hr_leave_dashboard/static/src/scss/time_off_dashboard.scss', + 'hr_holidays/static/src/scss/time_off.scss', + ], + 'web.assets_qweb': [ + 'hr_leave_dashboard/static/src/xml/emp_org_chart_templates.xml', + 'hr_leave_dashboard/static/src/xml/time_off_calendar.xml', + ] + }, + 'external_dependencies': { + 'python': ['pandas'], + }, + 'images': ['static/description/banner.png'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/hr_leave_dashboard/doc/RELEASE_NOTES.md b/hr_leave_dashboard/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..b2aeca7bd --- /dev/null +++ b/hr_leave_dashboard/doc/RELEASE_NOTES.md @@ -0,0 +1,7 @@ +## Module + +#### 08.08.2024 +#### Version 15.0.1.0.0 +#### ADD + +- Initial Commit Hr Leave Dashboard diff --git a/hr_leave_dashboard/models/__init__.py b/hr_leave_dashboard/models/__init__.py new file mode 100644 index 000000000..b3dd9d9d2 --- /dev/null +++ b/hr_leave_dashboard/models/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import hr_leave diff --git a/hr_leave_dashboard/models/hr_leave.py b/hr_leave_dashboard/models/hr_leave.py new file mode 100644 index 000000000..4eb4a4d29 --- /dev/null +++ b/hr_leave_dashboard/models/hr_leave.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +import pytz +from odoo import api, fields, models + + +class HrLeave(models.Model): + """Inherit the model hr.leave to introduce supplementary functionality + aimed at incorporating specific employee details.""" + _inherit = 'hr.leave' + + def _prepare_employee_data(self, employee): + """Function to prepare employee data for the dashboard""" + return { + 'id': employee.id, + 'name': employee.name, + 'job_id': employee.job_id.name, + 'approval_status_count': self.get_approval_status_count(employee.id) + } + + @api.model + def get_current_employee(self): + """This function fetches current employee details in a dictionary""" + current_employee = self.env.user.employee_ids + current_shift = self.get_current_shift() + upcoming_holidays = self.get_upcoming_holidays() + absentees = self.get_absentees() + approval_status_count = self.get_approval_status_count(current_employee.id) + return { + 'id': current_employee.id, + 'name': current_employee.name, + 'job_id': current_employee.job_id.id, + 'image_1920': current_employee.image_1920, + 'work_email': current_employee.work_email, + 'work_phone': current_employee.work_phone, + 'resource_calendar_id': current_employee.resource_calendar_id.name, + 'link': '/mail/view?model=%s&res_id=%s' % ( + 'hr.employee.public', current_employee.id,), + 'department_id': current_employee.department_id.name, + 'company': current_employee.company_id.name, + 'job_position': current_employee.job_id.name, + 'parent_id': current_employee.parent_id.ids, + 'child_ids': current_employee.child_ids.ids, + 'child_all_count': current_employee.child_all_count, + 'manager': self._prepare_employee_data( + current_employee.parent_id) if ( + current_employee.parent_id) else {}, + 'manager_all_count': len(current_employee.parent_id.ids), + 'children': [self._prepare_employee_data(child) for child in + current_employee.child_ids if + child != current_employee], + 'current_shift': current_shift, + 'upcoming_holidays': upcoming_holidays, + 'absentees': absentees, + 'approval_status_count': approval_status_count, + 'is_manager': self.env.user.has_group('hr_holidays.group_hr_holidays_manager') + } + + @api.model + def get_absentees(self): + """The function retrieves a list of employees who are absent on the + current date by querying the hr_leave table and comparing the + date_from and date_to fields of validated leave requests. It returns + a list of dictionaries containing the employee's name, employee_id, + date_from, and date_to""" + current_employee = self.env.user.employee_ids + children = [self._prepare_employee_data(child) for child in + current_employee.child_ids if + child != current_employee] + child_list = [child.get('id') for child in children] + if len(child_list) > 1: + query = "SELECT employee_id,name,date_from,date_to FROM hr_leave " \ + "INNER JOIN hr_employee ON hr_leave.employee_id = " \ + "hr_employee.id WHERE state = 'validate' AND " \ + "employee_id in %s" % str(tuple(child_list)) + self._cr.execute(query) + elif len(child_list) == 1: + query = "SELECT employee_id,name,date_from,date_to FROM hr_leave " \ + "INNER JOIN hr_employee ON hr_leave.employee_id = " \ + "hr_employee.id WHERE state = 'validate' AND " \ + "employee_id = %s" % child_list[0] + self._cr.execute(query) + leave = self._cr.dictfetchall() + absentees = [ + leave[leave_date] for leave_date in range(len(leave)) + if leave[leave_date].get('date_from') <= fields.datetime.now() <= leave[ + leave_date].get('date_to') + ] + return absentees + + @api.model + def get_current_shift(self): + """ This function fetches current employee's current shift""" + current_employee = self.env.user.employee_ids + employee_tz = current_employee.tz or self.env.context.get('tz') + employee_pytz = pytz.timezone(employee_tz) if employee_tz else pytz.utc + employee_datetime = fields.datetime.now().astimezone(employee_pytz) + hour = employee_datetime.strftime("%H") + minute = employee_datetime.strftime("%M") + day = employee_datetime.strftime("%A") + time = hour + '.' + minute + day_num = '0' if day == 'Monday' else '1' if day == 'Tuesday' \ + else '2' if day == 'Wednesday' else '3' if day == 'Thursday' \ + else '4' if day == 'Friday' else '5' if day == 'Saturday' else '6' + for shift in current_employee.resource_calendar_id.attendance_ids: + if shift.dayofweek == day_num and shift.hour_from <= float( + time) <= shift.hour_to: + return shift.name + return False + + @api.model + def get_upcoming_holidays(self): + """ This function fetches upcoming holidays""" + current_employee = self.env.user.employee_ids + employee_tz = current_employee.tz or self.env.context.get('tz') + employee_pytz = pytz.timezone(employee_tz) if employee_tz else pytz.utc + employee_datetime = fields.datetime.now().astimezone(employee_pytz) + query = "SELECT * FROM public.resource_calendar_leaves WHERE " \ + "resource_id is null" + self._cr.execute(query) + holidays = self._cr.dictfetchall() + upcoming_holidays = [holiday for holiday in holidays if + employee_datetime.date() < holiday.get( + 'date_to').date()] + return upcoming_holidays + + @api.model + def get_approval_status_count(self, current_employee): + """ This function fetches approval status count""" + return { + 'validate_count': self.env['hr.leave'].search_count([ + ('employee_id', '=', current_employee), + ('state', '=', 'validate') + ]), + 'confirm_count': self.env['hr.leave'].search_count([ + ('employee_id', '=', current_employee), + ('state', '=', 'confirm') + ]), + 'refuse_count': self.env['hr.leave'].search_count([ + ('employee_id', '=', current_employee), + ('state', '=', 'refuse') + ]) + } + + @api.model + def get_all_validated_leaves(self): + """ This function fetches all validated leaves""" + leaves = self.env['hr.leave'].search([('state', '=', 'validate')]) + all_validated_leaves = [ + { + 'id': leave.id, + 'employee_id': leave.employee_id.id, + 'employee_name': leave.employee_id.name, + 'request_date_from': leave.request_date_from, + 'request_date_to': leave.request_date_to, + 'leave_type_id': leave.holiday_status_id.id, + 'leave_type': leave.holiday_status_id.name, + 'number_of_days': leave.number_of_days + } + for leave in leaves + ] + return all_validated_leaves diff --git a/hr_leave_dashboard/report/__init__.py b/hr_leave_dashboard/report/__init__.py new file mode 100644 index 000000000..52c92cf26 --- /dev/null +++ b/hr_leave_dashboard/report/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import hr_leave_report diff --git a/hr_leave_dashboard/report/hr_leave_report.py b/hr_leave_dashboard/report/hr_leave_report.py new file mode 100644 index 000000000..8ea11e9db --- /dev/null +++ b/hr_leave_dashboard/report/hr_leave_report.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +import pandas +from datetime import timedelta +from odoo import api, fields, models +from odoo.tools import date_utils + + +class HrLeaveReport(models.AbstractModel): + """Model for the dashboard for viewing the employees leave""" + _name = 'report.hr_leave_dashboard.hr_leave_report' + _description = 'HR Leave Report' + + @api.model + def _get_report_values(self, docids, data=None): + """Function for getting the report values""" + if data.get('duration') == 'this_month': + option = pandas.date_range( + date_utils.start_of(fields.Date.today(), 'month'), + date_utils.end_of(fields.Date.today(), 'month') - timedelta( + days=0), + freq='d').strftime( + "%Y-%m-%d").tolist() + elif data.get('duration') == 'this_year': + option = pandas.date_range( + date_utils.start_of(fields.Date.today(), 'year'), + date_utils.end_of(fields.Date.today(), 'year') - timedelta( + days=0), + freq='d').strftime( + "%Y-%m-%d").tolist() + elif data.get('duration') == 'this_week': + option = pandas.date_range( + date_utils.start_of(fields.Date.today(), 'week'), + date_utils.end_of(fields.Date.today(), 'week') - timedelta( + days=0), + freq='d').strftime( + "%Y-%m-%d").tolist() + else: + option = [str(fields.Date.today())] + if not self.env.user.employee_ids.child_ids: + query = """SELECT l.id, lt.id as hr_leave_type_id, e.id as + emp_id, e.name as emp_name, e.department_id as emp_department, + e.parent_id as emp_parent_id, request_date_from, request_date_to, + l.number_of_days, lt.name as leave_type, + SUM(al.number_of_days) AS allocated_days, SUM(CASE WHEN l.state = + 'validate' THEN l.number_of_days ELSE 0 END) AS taken_days, + SUM(al.number_of_days) - SUM(CASE WHEN l.state = 'validate' THEN + l.number_of_days ELSE 0 END) AS balance_days FROM hr_employee e + inner join hr_leave_allocation al ON al.employee_id = e.id inner + join hr_leave l on l.employee_id = e.id inner join hr_leave_type + lt on l.holiday_status_id = lt.id WHERE l.state = 'validate' AND + e.department_id = '%s' GROUP BY e.id,lt.id,l.id""" % \ + self.env.user.employee_ids.department_id.id + else: + query = """SELECT l.id, lt.id as hr_leave_type_id, e.id as + emp_id, e.name as emp_name, e.department_id as emp_department, + e.parent_id as emp_parent_id, request_date_from, request_date_to, + l.number_of_days, lt.name as leave_type, + SUM(al.number_of_days) AS allocated_days, SUM(CASE WHEN l.state = + 'validate' THEN l.number_of_days ELSE 0 END) AS taken_days, + SUM(al.number_of_days) - SUM(CASE WHEN l.state = 'validate' THEN + l.number_of_days ELSE 0 END) AS balance_days FROM hr_employee e + inner join hr_leave_allocation al ON al.employee_id = e.id inner + join hr_leave l on l.employee_id = e.id inner join hr_leave_type + lt on l.holiday_status_id = lt.id WHERE l.state = 'validate' + GROUP BY e.id,lt.id,l.id""" + + self.env.cr.execute(query) + leave_data = self.env.cr.dictfetchall() + filtered_list = [] + filtered_tuple = [] + for leave in leave_data: + leave_list = pandas.date_range(leave.get('request_date_from'), + leave.get( + 'request_date_to') - timedelta( + days=1), freq='d').strftime( + "%Y-%m-%d").tolist() + for date in leave_list: + if date in option: + filtered_list.append(leave) + break + for leave in filtered_list: + if (leave.get('hr_leave_type_id'), leave.get('emp_id')) in \ + filtered_tuple: + filtered_list.remove(leave) + else: + filtered_tuple.append( + (leave.get('hr_leave_type_id'), leave.get('emp_id'))) + return { + 'duration': data.get('duration'), + 'filtered_list': filtered_list, + } diff --git a/hr_leave_dashboard/report/hr_leave_report_templates.xml b/hr_leave_dashboard/report/hr_leave_report_templates.xml new file mode 100644 index 000000000..0c85ee162 --- /dev/null +++ b/hr_leave_dashboard/report/hr_leave_report_templates.xml @@ -0,0 +1,89 @@ + + + + + diff --git a/hr_leave_dashboard/report/hr_leave_reports.xml b/hr_leave_dashboard/report/hr_leave_reports.xml new file mode 100644 index 000000000..a7e32cc9f --- /dev/null +++ b/hr_leave_dashboard/report/hr_leave_reports.xml @@ -0,0 +1,11 @@ + + + + + Leave report + hr.leave.report + qweb-pdf + hr_leave_dashboard.hr_leave_report + hr_leave_dashboard.hr_leave_report + + diff --git a/hr_leave_dashboard/static/description/assets/icons/check.png b/hr_leave_dashboard/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/check.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/chevron.png b/hr_leave_dashboard/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/chevron.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/cogs.png b/hr_leave_dashboard/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/cogs.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/consultation.png b/hr_leave_dashboard/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/consultation.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/ecom-black.png b/hr_leave_dashboard/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/ecom-black.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/education-black.png b/hr_leave_dashboard/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/education-black.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/hotel-black.png b/hr_leave_dashboard/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/hotel-black.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/license.png b/hr_leave_dashboard/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/license.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/lifebuoy.png b/hr_leave_dashboard/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/lifebuoy.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/manufacturing-black.png b/hr_leave_dashboard/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/manufacturing-black.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/pos-black.png b/hr_leave_dashboard/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/pos-black.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/puzzle.png b/hr_leave_dashboard/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/puzzle.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/restaurant-black.png b/hr_leave_dashboard/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/restaurant-black.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/service-black.png b/hr_leave_dashboard/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/service-black.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/trading-black.png b/hr_leave_dashboard/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/trading-black.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/training.png b/hr_leave_dashboard/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/training.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/update.png b/hr_leave_dashboard/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/update.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/user.png b/hr_leave_dashboard/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/user.png differ diff --git a/hr_leave_dashboard/static/description/assets/icons/wrench.png b/hr_leave_dashboard/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/icons/wrench.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/categories.png b/hr_leave_dashboard/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/categories.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/check-box.png b/hr_leave_dashboard/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/check-box.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/compass.png b/hr_leave_dashboard/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/compass.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/corporate.png b/hr_leave_dashboard/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/corporate.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/customer-support.png b/hr_leave_dashboard/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/customer-support.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/cybrosys-logo.png b/hr_leave_dashboard/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/cybrosys-logo.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/features.png b/hr_leave_dashboard/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/features.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/logo.png b/hr_leave_dashboard/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/logo.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/pictures.png b/hr_leave_dashboard/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/pictures.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/pie-chart.png b/hr_leave_dashboard/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/pie-chart.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/right-arrow.png b/hr_leave_dashboard/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/right-arrow.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/star.png b/hr_leave_dashboard/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/star.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/support.png b/hr_leave_dashboard/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/support.png differ diff --git a/hr_leave_dashboard/static/description/assets/misc/whatsapp.png b/hr_leave_dashboard/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/misc/whatsapp.png differ diff --git a/hr_leave_dashboard/static/description/assets/modules/chatter_view.jpg b/hr_leave_dashboard/static/description/assets/modules/chatter_view.jpg new file mode 100644 index 000000000..8890ee31d Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/modules/chatter_view.jpg differ diff --git a/hr_leave_dashboard/static/description/assets/modules/dynamic_financial_reports.png b/hr_leave_dashboard/static/description/assets/modules/dynamic_financial_reports.png new file mode 100644 index 000000000..5238bdeab Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/modules/dynamic_financial_reports.png differ diff --git a/hr_leave_dashboard/static/description/assets/modules/hid_menu.png b/hr_leave_dashboard/static/description/assets/modules/hid_menu.png new file mode 100644 index 000000000..6bc155887 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/modules/hid_menu.png differ diff --git a/hr_leave_dashboard/static/description/assets/modules/login_style.png b/hr_leave_dashboard/static/description/assets/modules/login_style.png new file mode 100644 index 000000000..e20126a45 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/modules/login_style.png differ diff --git a/hr_leave_dashboard/static/description/assets/modules/login_user.png b/hr_leave_dashboard/static/description/assets/modules/login_user.png new file mode 100644 index 000000000..4fbe85ac1 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/modules/login_user.png differ diff --git a/hr_leave_dashboard/static/description/assets/modules/qr_code.png b/hr_leave_dashboard/static/description/assets/modules/qr_code.png new file mode 100644 index 000000000..6bc155887 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/modules/qr_code.png differ diff --git a/hr_leave_dashboard/static/description/assets/screenshots/hero.gif b/hr_leave_dashboard/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..d06aecc69 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/screenshots/hero.gif differ diff --git a/hr_leave_dashboard/static/description/assets/screenshots/hr_leave_dashboard_01.png b/hr_leave_dashboard/static/description/assets/screenshots/hr_leave_dashboard_01.png new file mode 100644 index 000000000..dd4ebc812 Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/screenshots/hr_leave_dashboard_01.png differ diff --git a/hr_leave_dashboard/static/description/assets/screenshots/hr_leave_dashboard_02.png b/hr_leave_dashboard/static/description/assets/screenshots/hr_leave_dashboard_02.png new file mode 100644 index 000000000..6f0f8557a Binary files /dev/null and b/hr_leave_dashboard/static/description/assets/screenshots/hr_leave_dashboard_02.png differ diff --git a/hr_leave_dashboard/static/description/banner.png b/hr_leave_dashboard/static/description/banner.png new file mode 100644 index 000000000..421fb55cf Binary files /dev/null and b/hr_leave_dashboard/static/description/banner.png differ diff --git a/hr_leave_dashboard/static/description/icon.png b/hr_leave_dashboard/static/description/icon.png new file mode 100644 index 000000000..d5ad0d6a5 Binary files /dev/null and b/hr_leave_dashboard/static/description/icon.png differ diff --git a/hr_leave_dashboard/static/description/index.html b/hr_leave_dashboard/static/description/index.html new file mode 100644 index 000000000..4de544b9b --- /dev/null +++ b/hr_leave_dashboard/static/description/index.html @@ -0,0 +1,524 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+
+ +
+
+
+ +

+ Hr Leave Dashboard

+

+ This Module Helps You View Your and Your Subordinate's Details. +

+ + +
+
+
+
+ +
+ x +
+ +
+

+ Explore This Module

+
+ + + +
+
+ +
+

+ Overview

+
+
+
+ This module helps you view your and your subordinate's details and approval status of your all employees. With this module, you can print hr leave report on basis of today, this week, this month and this year in pdf format. +
+
+ + +
+
+ +
+

+ Features

+
+
+
+
+ + Hr Leave Dashboard. +
+
+
+
+ + HR Leave PDF Report. +
+
+
+ + +
+
+ +
+

+ Screenshots

+
+
+
+
+

+ HR Leave Dashboard

+ +
+
+

+ HR Leave PDF Report

+ +
+
+
+ + +
+
+

Suggested Products

+
+ +
+
+ + +
+
+ +
+

+ Our Services

+
+
+
+
+
+ +
+
+ Odoo Customization
+
+
+
+ +
+
+ Odoo Implementation
+
+
+
+ +
+
+ Odoo Support
+
+
+
+ +
+
+ Hire Odoo Developer
+
+
+
+ +
+
+ Odoo Integration
+
+
+
+ +
+
+ Odoo Migration
+
+
+
+ +
+
+ Odoo Consultancy
+
+
+
+ +
+
+ Odoo Implementation
+
+
+
+ +
+
+ Odoo Licensing Consultancy
+
+
+
+ + +
+
+ +
+

+ Our Industries

+
+
+
+
+
+ +
+ Trading
+

+ Easily procure and sell your products

+
+
+
+
+ +
+ POS
+

+ Easy configuration and convivial experience

+
+
+
+
+ +
+ Education
+

+ A platform for educational management

+
+
+
+
+ +
+ Manufacturing
+

+ Plan, track and schedule your operations

+
+
+
+
+ +
+ E-commerce & Website
+

+ Mobile friendly, awe-inspiring product pages

+
+
+
+
+ +
+ Service Management
+

+ Keep track of services and invoice

+
+
+
+
+ +
+ Restaurant
+

+ Run your bar or restaurant methodically

+
+
+
+
+ +
+ Hotel Management
+

+ An all-inclusive hotel management application

+
+
+
+
+ + + +
+
+ +
+

+ Support

+
+
+
+
+
+
+ +
+
+

Need Help?

+

Got questions or need help? + Get in touch.

+ +

+ odoo@cybrosys.com

+
+
+
+
+
+
+
+ +
+
+

WhatsApp

+

Say hi to us on WhatsApp!

+ +

+ +91 86068 27707

+
+
+
+
+
+
+
+ +
+
+
+ diff --git a/hr_leave_dashboard/static/src/css/hr_leave_dashboard.css b/hr_leave_dashboard/static/src/css/hr_leave_dashboard.css new file mode 100644 index 000000000..83272a579 --- /dev/null +++ b/hr_leave_dashboard/static/src/css/hr_leave_dashboard.css @@ -0,0 +1,89 @@ +td.fc-day.fc-widget-content.fc-public-holiday{ + background-color:red !important; +} +td.fc-day.fc-widget-content.fc-sat{ + background-color:red !important; +} +td.fc-day.fc-widget-content.fc-sun{ + background-color:red !important; +} +.o_timeoff_duration{ + margin-top:12px !important; + font-size: 30px; + font-weight: bold; +} +.employee_details{ + font-size:12px !important; + margin-top: 12px; + margin-bottom: 12px; +} +.o_timeoff_card:not(:last-child) { + font-size: 12px !important; + padding: 12px !important; + position:relative; +} +.o_timeoff_card .o_timeoff_duration{ + margin-bottom:12px !important; +} +.o_treeEntry:before, .o_treeEntry:after{ + background: #7a539e !important; +} +.duration{ + width: 190px; + float: left; + margin: 1px 2px 0px 10px; + height: 29px; + padding: 5px; + margin-bottom: 21px; +} +.time_off_dashboard_table tr th{ + background-color: #eaeef3 !important; + font-size: 11px; +} +.employee_image{ + border-radius: 50%; + width: 50px; + height: 50px; + overflow: hidden; + position: relative; +} +.employee_name{ + font-size: 16px !important; + width: 165px; + /* position: absolute; */ + right:62px; + top:24px; +} +.employee_box{ + display:flex; + justify-content:center; + align-items:center; +} +.divider-box{ +float: left; + margin-bottom: 12px; + text-align: center; + display: flex; + align-items: center; + justify-content: center; +} +.box-content{ +width: 100%; + margin-right: 2px; + padding: 10px; + display: flex; + align-items: center; + justify-content: center; + height: 80px; + margin-top: 0px; + border: 1px solid #cebce1; + background-color: #eaedf3; + color: #573674; +} +.divide-leave{ +padding:10px; +border: 1px solid #cebce1; +background-color: #eaedf3; +color: #573674; +margin-top:10px; +} diff --git a/hr_leave_dashboard/static/src/js/time_off_emp_dashboard.js b/hr_leave_dashboard/static/src/js/time_off_emp_dashboard.js new file mode 100644 index 000000000..0ff69dc6f --- /dev/null +++ b/hr_leave_dashboard/static/src/js/time_off_emp_dashboard.js @@ -0,0 +1,435 @@ +odoo.define('hr_leave_dashboard.TimeOffDashboard', function(require) { + 'use strict'; + + var core = require('web.core'); + const config = require('web.config'); + + var CalendarRenderer = require("web.CalendarRenderer"); + var CalendarPopover = require("web.CalendarPopover") + var CalendarController = require("web.CalendarController"); + var CalendarModel = require("web.CalendarModel"); + var viewRegistry = require('web.view_registry'); + + var CalendarView = require("web.CalendarView"); + var QWeb = core.qweb; + var _t = core._t; + var session = require('web.session'); + +// Extending the calendar view to add the details to the dashboard. + var TimeOffCalendarController = CalendarController.extend({ + events: _.extend({}, CalendarController.prototype.events, { + 'click .btn-time-off': '_onNewTimeOff', + 'click .btn-allocation': '_onNewAllocation', + 'click .print-pdf-report': 'printPdfReport', + }), + + /** + * @override + */ + start: function () { + this.$el.addClass('o_timeoff_calendar'); + return this._super(...arguments); + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Render the buttons and add new button about + * time off and allocations request + * + * @override + */ + + renderButtons: function ($node) { + this._super.apply(this, arguments); + + $(QWeb.render('hr_holidays.dashboard.calendar.button', { + time_off: _t('New Time Off'), + request: _t('Allocation Request'), + })).appendTo(this.$buttons); + + if ($node) { + this.$buttons.appendTo($node); + } else { + this.$('.o_calendar_buttons').replaceWith(this.$buttons); + } + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + _getNewTimeOffContext: function() { + const { date_from, date_to } = this.model._getTimeOffDates(moment()); + return { + 'default_date_from': date_from, + 'default_date_to': date_to, + 'lang': this.context.lang + } + }, + + /** + * Action: create a new time off request + * + * @private + */ + _onNewTimeOff: function () { + this._rpc({ + model: 'ir.ui.view', + method: 'get_view_id', + args: ['hr_holidays.hr_leave_view_form_dashboard_new_time_off'], + }).then((ids) => { + this.timeOffDialog = new dialogs.FormViewDialog(this, { + res_model: "hr.leave", + view_id: ids, + context: this._getNewTimeOffContext(), + title: _t("New time off"), + disable_multiple_selection: true, + on_saved: () => { + this.reload(); + }, + }); + this.timeOffDialog.open(); + }); + }, + + /** + * Action: create a new allocation request + * + * @private + */ + _onNewAllocation: function () { + let self = this; + + self._rpc({ + model: 'ir.ui.view', + method: 'get_view_id', + args: ['hr_holidays.hr_leave_allocation_view_form_dashboard'], + }).then(function(ids) { + self.allocationDialog = new dialogs.FormViewDialog(self, { + res_model: "hr.leave.allocation", + view_id: ids, + context: { + 'default_state': 'confirm', + 'lang': self.context.lang, + }, + title: _t("New Allocation"), + disable_multiple_selection: true, + on_saved: function() { + self.reload(); + }, + }); + self.allocationDialog.open(); + }); + }, +// Action to print the pdf report of the timeoff. + printPdfReport: function () { + const duration = $(this.el.querySelectorAll("#duration")).val(); + var self = this + this._rpc({ + model: 'hr.leave', + method: 'get_all_validated_leaves', + args: [ + + ], + }).then(function(data) { + var action = { + type: "ir.actions.report", + report_type: "qweb-pdf", + report_name: "hr_leave_dashboard.hr_leave_report", + report_file: "hr_leave_dashboard.hr_leave_report", + data: { + 'duration': duration, + 'all_validated_leaves': data, + } + } + return self.do_action(action) + }) + }, + + /** + * @override + */ + _setEventTitle: function () { + return _t('Time Off Request'); + }, + }); + + + var TimeOffCalendarPopover = CalendarPopover.extend({ + template: 'hr_holidays.calendar.popover', + + init: function (parent, eventInfo) { + this._super.apply(this, arguments); + const state = this.event.extendedProps.record.state; + this.canDelete = state && ['validate', 'refuse'].indexOf(state) === -1; + this.canEdit = state !== undefined; + this.displayFields = []; + + if (this.modelName === "hr.leave.report.calendar") { + const duration = this.event.extendedProps.record.display_name.split(':').slice(-1); + this.display_name = _.str.sprintf(_t("Time Off : %s"), duration); + } else { + this.display_name = this.event.extendedProps.record.display_name; + } + }, + }); + + var TimeOffPopoverRenderer = CalendarRenderer.extend({ + template: "TimeOff.CalendarView.extend", + /** + * We're overriding this to display the weeknumbers on the year view + * + * @override + * @private + */ + _getFullCalendarOptions: function () { + const oldOptions = this._super(...arguments); + // Parameters + oldOptions.views.dayGridYear.weekNumbers = true; + oldOptions.views.dayGridYear.weekNumbersWithinDays = false; + return oldOptions; + }, + + config: _.extend({}, CalendarRenderer.prototype.config, { + CalendarPopover: TimeOffCalendarPopover, + }), + + _getPopoverParams: function (eventData) { + let params = this._super.apply(this, arguments); + let calendarIcon; + let state = eventData.extendedProps.record.state; + + if (state === 'validate') { + calendarIcon = 'fa-calendar-check-o'; + } else if (state === 'refuse') { + calendarIcon = 'fa-calendar-times-o'; + } else if(state) { + calendarIcon = 'fa-calendar-o'; + } + + params['title'] = eventData.extendedProps.record.display_name.split(':').slice(0, -1).join(':'); + params['template'] = QWeb.render('hr_holidays.calendar.popover.placeholder', {color: this.getColor(eventData.color_index), calendarIcon: calendarIcon}); + return params; + }, + + _render: function () { + var self = this; + return this._super.apply(this, arguments).then(function () { + self.$el.parent().find('.o_calendar_mini').hide(); + }); + }, + /** + * @override + * @private + */ + _renderCalendar: function() { + this._super.apply(this, arguments); + let weekNumbers = this.$el.find('.fc-week-number'); + weekNumbers.each( function() { + let weekRow = this.parentNode; + // By default, each month has 6 weeks displayed, hide the week number if there is no days for the week + if(!weekRow.children[1].classList.length && !weekRow.children[weekRow.children.length-1].classList.length) { + this.innerHTML = ''; + } + }); + }, + }); + + var TimeOffCalendarRenderer = TimeOffPopoverRenderer.extend({ + _render: function () { + var self = this; + return this._super.apply(this, arguments).then(function () { + return self._rpc({ + model: 'hr.leave.type', + method: 'get_days_all_request', + context: self.state.context, + }); + }).then(function (result) { + self._rpc({ + model: 'hr.leave', + method: 'get_current_employee', + }).then(function (res) { + self.$el.parent().find('.o_calendar_mini').hide(); + self.$el.parent().find('.o_timeoff_container').remove(); + self._rpc({ + route: '/hr/get_org_chart', + params: { + employee_id: res.id, + context: session.user_context, + }, + }) + .then(function (data) { + if (result.length > 0) { + if (config.device.isMobile) { + result.forEach((data) => { + const elem = QWeb.render('hr_holidays.dashboard_calendar_header_mobile', { + timeoff: data, + }); + self.$el.find('.o_calendar_filter_item[data-value=' + data[3] + '] .o_cw_filter_title').append(elem); + }); + } else { + const elem = QWeb.render('hr_holidays.dashboard_calendar_header', { + timeoffs: result, + employee: res, + employee_org: data, + }); + self.$el.before(elem); + } + } + $('[data-toggle="popover"]').each(function () { + $(this).popover({ + html: true, + title: function () { + var $title = $(QWeb.render('hr_orgchart_emp_popover_title', { + employee: { + name: $(this).data('emp-name'), + id: $(this).data('emp-id'), + }, + })); + $title.on('click', + '.o_employee_redirect', _.bind(self._onEmployeeRedirect, self)); + return $title; + }, + container: this, + placement: 'left', + trigger: 'focus', + content: function () { + var $content = $(QWeb.render('hr_orgchart_emp_popover_content', { + employee: { + id: $(this).data('emp-id'), + name: $(this).data('emp-name'), + direct_sub_count: parseInt($(this).data('emp-dir-subs')), + indirect_sub_count: parseInt($(this).data('emp-ind-subs')), + }, + })); + $content.on('click', + '.o_employee_sub_redirect', _.bind(self._onEmployeeSubRedirect, self)); + return $content; + }, + template: QWeb.render('hr_orgchart_emp_popover', {}), + }); + }); + }); + }) + }); + }, +// Function to redirect toi the employee form view. + _onEmployeeRedirect: function (event) { + var self = this; + event.preventDefault(); + var employee_id = parseInt($(event.currentTarget).data('employee-id')); + return this._rpc({ + model: 'hr.employee', + method: 'get_formview_action', + args: [employee_id], + }).then(function(action) { + return self.do_action(action); + }); + }, +// Function to redirect to the sub employee's form view + _onEmployeeSubRedirect: function (event) { + event.preventDefault(); + var employee_id = parseInt($(event.currentTarget).data('employee-id')); + var employee_name = $(event.currentTarget).data('employee-name'); + var type = $(event.currentTarget).data('type') || 'direct'; + var self = this; + if (employee_id) { + this._getSubordinatesData(employee_id, type).then(function(data) { + var domain = [['id', 'in', data]]; + return self._rpc({ + model: 'hr.employee', + method: 'get_formview_action', + args: [employee_id], + }).then(function(action) { + action = _.extend(action, { + 'name': _t('Team'), + 'view_mode': 'kanban,list,form', + 'views': [[false, 'kanban'], [false, 'list'], [false, 'form']], + 'domain': domain, + 'context': { + 'default_parent_id': employee_id, + } + }); + delete action['res_id']; + return self.do_action(action); + }); + }); + } + }, +// Function to get the details of sub employees. + _getSubordinatesData: function (employee_id, type) { + return this._rpc({ + route: '/hr/get_subordinates', + params: { + employee_id: employee_id, + subordinates_type: type, + context: session.user_context, + }, + }); + }, + + }); + + const TimeOffCalendarModel = CalendarModel.extend({ + calendarEventToRecord(event) { + const res = this._super(...arguments); + if (['day', 'week'].includes(this.data.scale)) { + const { date_from, date_to } = this._getTimeOffDates(event.start.clone()); + + res['date_from'] = date_from; + res['date_to'] = date_to; + } + + return res; + }, + + _getTimeOffDates(date_from) { + date_from.set({ + 'hour': 0, + 'minute': 0, + 'second': 0 + }); + let date_to = date_from.clone().set({ + 'hour': 23, + 'minute': 59, + 'second': 59 + }); + + date_from.subtract(this.getSession().getTZOffset(date_from), 'minutes'); + date_from = date_from.locale('en').format('YYYY-MM-DD HH:mm:ss'); + date_to.subtract(this.getSession().getTZOffset(date_to), 'minutes'); + date_to = date_to.locale('en').format('YYYY-MM-DD HH:mm:ss'); + + return { + date_from, + date_to, + } + }, + }); + + var TimeOffCalendarView = CalendarView.extend({ + config: _.extend({}, CalendarView.prototype.config, { + Controller: TimeOffCalendarController, + Renderer: TimeOffCalendarRenderer, + Model: TimeOffCalendarModel, + }), + }); + + /** + * Calendar shown in the "Everyone" menu + */ + var TimeOffCalendarAllView = CalendarView.extend({ + config: _.extend({}, CalendarView.prototype.config, { + Controller: TimeOffCalendarController, + Renderer: TimeOffPopoverRenderer, + Model: TimeOffCalendarModel, + }), + }); + + viewRegistry.add('time_off_calendar', TimeOffCalendarView); + viewRegistry.add('time_off_calendar_all', TimeOffCalendarAllView); +}); + diff --git a/hr_leave_dashboard/static/src/scss/hr_org_chart.scss b/hr_leave_dashboard/static/src/scss/hr_org_chart.scss new file mode 100644 index 000000000..5e505c6e9 --- /dev/null +++ b/hr_leave_dashboard/static/src/scss/hr_org_chart.scss @@ -0,0 +1,213 @@ +$tmp-gap-base: $o-hr-org-chart-entry-pic-size*0.7; + +// ORGANIGRAM LINES +.o_org_chart_group_down { + position: relative; +} + +.o_org_chart_group_down { + padding-left: $tmp-gap-base; + height: fit-content; + + &:before { + @include o-hr-org-chart-line; + border-left-width: $o-hr-org-chart-entry-line-w; + height: 100%; + @include o-position-absolute( + $top: $o-hr-org-chart-entry-v-gap*-1, + $left: $tmp-gap-base*0.5 + $o-hr-org-chart-entry-pic-size*0.1 + $o-hr-org-chart-entry-line-w*0.5 + ); + } + + .o_org_chart_entry { + &:before { + @include o-hr-org-chart-line; + border-top-width: $o-hr-org-chart-entry-line-w; + @include size($tmp-gap-base, 0); + @include o-position-absolute( + $left: $tmp-gap-base*-0.5 + $o-hr-org-chart-entry-pic-size*0.1 + $o-hr-org-chart-entry-line-w*0.5, + $top: $o-hr-org-chart-entry-pic-size*0.5 + ); + } + + &:last-of-type { + &:before { + height: 50%; + } + + } + + &.o_org_chart_more { + margin-top: $o-hr-org-chart-entry-v-gap; + + &:before { + top: 15px; + } + } + } +} + +// ORGANIGRAM DESIGN +.o_org_chart_entry { + margin-bottom: $o-hr-org-chart-entry-v-gap; + overflow: visible; + margin-top: 0; + + &, .o_media_left, .media-body { + position: relative; + } + + .o_media_left { + padding-right: 10px; + } + + .media-body { + vertical-align: middle; + + .badge { + float: right; + cursor: pointer; + margin-right: 5px; + color: gray('600'); + background: $o-hr-org-chart-bg; + border: 1px solid gray('600'); + &:hover { + color: $o-brand-primary; + border-color: $o-brand-primary; + } + &:focus { + outline: none; + } + } + + strong { + display: block; + line-height: 1.2; + font-size: 11px; + color: lighten(gray('600'), 15%); + } + } + + .o_media_object { + display: block; + width: $o-hr-org-chart-entry-pic-size*0.8; + height: $o-hr-org-chart-entry-pic-size*0.8; + margin: $o-hr-org-chart-entry-pic-size*0.1; + box-shadow: 0 0 0 $o-hr-org-chart-entry-line-w darken($o-hr-org-chart-bg, 20%); + background-size: cover; + background-position: center center; + background-color: $o-view-background-color; + + &.card { + height: 20px; + box-shadow: none; + border-color: transparent; + padding: 0; + position: relative; + color: $body-color; + + .o_org_chart_show_more { + line-height: 13px; + } + + &:hover { + border-color: $o-hr-org-chart-entry-border-color; + color:$o-brand-primary; + } + } + } + + &.o_org_chart_entry_manager, &.o_org_chart_entry_sub { + .o_media_left { + padding-right: 0; + } + .media-body > a { + padding-left: 10px; + max-width: 100%; + display: block; + + .o_media_heading { + color: lighten(gray('600'), 5%); + font-size: 13px; + } + } + + &:hover { + .o_media_object { + box-shadow: 0 0 0 $o-hr-org-chart-entry-line-w*2 rgba($o-brand-primary, 0.6); + } + .media-body > a { + .o_media_heading { + color: $o-brand-primary; + } + strong { + color: lighten(gray('600'), 5%); + } + } + } + } + + &.o_org_chart_entry_self { + &:not(:first-child) { + margin-top: $o-hr-org-chart-entry-v-gap*1.5; + } + + strong { + color: $text-muted; + } + + .o_media_object { + width: $o-hr-org-chart-entry-pic-size; + height: $o-hr-org-chart-entry-pic-size; + margin: 0; + border: $o-hr-org-chart-entry-line-w*2 solid $o-brand-primary; + box-shadow: inset 0 0 0 $o-hr-org-chart-entry-line-w*2 white; + } + + .media-body { + opacity: 1; + } + } +} + + +// POP OVER +.o_org_chart_popup.popover { + max-width: 400px; + margin-right: 5px; + min-width:230px; + + .popover-header { + height: 47px; + line-height: 33px; + padding-right: 50px; + + > a { + @include o-position-absolute($right: 14px); + } + + span { + @include size(30px, 30px); + margin-right: 10px; + border-radius: 100%; + background-position: center; + background-size: cover; + float: left; + box-shadow: 0 1px 1px; + } + } + .table { + margin-bottom: 0; + } +} + +// Right to Left specific style to flip the popover arrow +.o_rtl { + .o_org_chart_popup.popover .arrow { + left: 100%; + -webkit-transform: matrix(-1, 0, 0, 1, 0, 0); + -moz-transform: matrix(-1, 0, 0, 1, 0, 0); + -o-transform: matrix(-1, 0, 0, 1, 0, 0); + transform: matrix(-1, 0, 0, 1, 0, 0); + } +} diff --git a/hr_leave_dashboard/static/src/scss/time_off_dashboard.scss b/hr_leave_dashboard/static/src/scss/time_off_dashboard.scss new file mode 100644 index 000000000..70158547f --- /dev/null +++ b/hr_leave_dashboard/static/src/scss/time_off_dashboard.scss @@ -0,0 +1,10 @@ +.o_timeoff_dashboard { + display: flex; + justify-content: space-between; + height: auto; + box-shadow: inset 0 -1px 0 $border-color; + position: sticky; + top: 0; + z-index: 100; + background-color: $o-webclient-background-color; +} diff --git a/hr_leave_dashboard/static/src/scss/variables.scss b/hr_leave_dashboard/static/src/scss/variables.scss new file mode 100644 index 000000000..142ebf9ab --- /dev/null +++ b/hr_leave_dashboard/static/src/scss/variables.scss @@ -0,0 +1,14 @@ +$o-hr-org-chart-bg: white; +$o-hr-org-chart-border-color: $o-brand-secondary; + +$o-hr-org-chart-entry-v-gap: 6px; +$o-hr-org-chart-entry-pic-size: 46px; +$o-hr-org-chart-entry-line-w: 1px; +$o-hr-org-chart-entry-border-color: darken($o-hr-org-chart-bg, 25%); + +// MIXINS +@mixin o-hr-org-chart-line { + content: ''; + background-color: $o-hr-org-chart-bg; + border: 0px solid $o-hr-org-chart-entry-border-color; +} diff --git a/hr_leave_dashboard/static/src/xml/emp_org_chart_templates.xml b/hr_leave_dashboard/static/src/xml/emp_org_chart_templates.xml new file mode 100644 index 000000000..149754197 --- /dev/null +++ b/hr_leave_dashboard/static/src/xml/emp_org_chart_templates.xml @@ -0,0 +1,169 @@ + + diff --git a/hr_leave_dashboard/static/src/xml/time_off_calendar.xml b/hr_leave_dashboard/static/src/xml/time_off_calendar.xml new file mode 100644 index 000000000..f9dfb2894 --- /dev/null +++ b/hr_leave_dashboard/static/src/xml/time_off_calendar.xml @@ -0,0 +1,245 @@ + + + +
+ +
+
+ + + + +
+ + + +
+ HOURS + DAYS + AVAILABLE +
+ + + +
+ HOURS + DAYS + TAKEN +
+
+
+
+ + + + + + + + + + + +
+
+ + + +
+ + + +
+
+
+
+ Job Position: + +
+
+
+
+ Working Hours: + +
+
+
+
+ EMAIL: +
+
+
+
+ PHONE: +
+
+
+
+ Department: +
+
+
+
+ Company: +
+
+
+
+ + + +
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + + + + +
+
+ Current Shift: +
+
+
+
Upcoming Holidays
+ +
+ +
+
+ () +
+
+
+
+
On Leave
+ +
+ +
+
+
+
+
+ + + +
+ + + +
+ Approved +
+ + + +
+ To Approve +
+ + + +
+ Refused +
+
+
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + + +
NameApprovedTo ApproveRefused
+
+
+
+
+
+
+
\ No newline at end of file