diff --git a/pos_timesheet/README.rst b/pos_timesheet/README.rst new file mode 100644 index 000000000..574c9217c --- /dev/null +++ b/pos_timesheet/README.rst @@ -0,0 +1,46 @@ +.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg + :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 + +POS Timesheet +============= +Efficiently track employees' work hours in POS. + +Configuration +============= +No configuration + +Company +------- +* `Cybrosys Techno Solutions `__ + +License +------- +General Public License, Version 3 (LGPL v3). +(http://www.gnu.org/licenses/lgpl-3.0-standalone.html) + +Credits +------- +Developer: (V16) Mohammed Hisam , 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/pos_timesheet/__init__.py b/pos_timesheet/__init__.py new file mode 100644 index 000000000..fa220822b --- /dev/null +++ b/pos_timesheet/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Mohammed Hisam (odoo@cybrosysy.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import models diff --git a/pos_timesheet/__manifest__.py b/pos_timesheet/__manifest__.py new file mode 100644 index 000000000..6446efbe0 --- /dev/null +++ b/pos_timesheet/__manifest__.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Mohammed Hisam (odoo@cybrosysy.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +{ + "name": "POS Timesheet", + "version": "16.0.1.0.0", + "category": "Point of Sale", + "summary": """Efficiently track employees' work hours in POS.""", + "description": """This module enhances the Point of Sale (POS) functionality by automatically + calculating timesheets for employees based on their activities in the POS.""", + "author": "Cybrosys Techno Solutions", + "company": "Cybrosys Techno Solutions", + "maintainer": "Cybrosys Techno Solutions", + "website": "https://www.cybrosys.com", + "depends": ["point_of_sale", "hr_timesheet", "project"], + "data": [ + "views/res_config_settings_views.xml", + "views/pos_session_views.xml", + ], + "assets": { + "point_of_sale.assets": [ + "pos_timesheet/static/src/css/worked_hour_popup.css", + "pos_timesheet/static/src/js/model.js", + "pos_timesheet/static/src/js/Chrome.js", + "pos_timesheet/static/src/js/TimeSheetButton.js", + "pos_timesheet/static/src/js/Popups/ClosePosPopup.js", + "pos_timesheet/static/src/js/Popups/WorkedHourPopup.js", + "pos_timesheet/static/src/xml/Chrome.xml", + "pos_timesheet/static/src/xml/TimeSheetButton.xml", + "pos_timesheet/static/src/xml/CashMoveButton.xml", + "pos_timesheet/static/src/xml/Popups/WorkedHourPopup.xml", + ], + }, + "images": ["static/description/banner.png"], + "license": "LGPL-3", + "installable": True, + "auto_install": False, + "application": False, +} diff --git a/pos_timesheet/doc/RELEASE_NOTES.md b/pos_timesheet/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..8530493d0 --- /dev/null +++ b/pos_timesheet/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 20.03.2024 +#### Version 16.0.1.0.0 +#### ADD +- Initial commit for POS Timesheet diff --git a/pos_timesheet/models/__init__.py b/pos_timesheet/models/__init__.py new file mode 100644 index 000000000..446cb0f25 --- /dev/null +++ b/pos_timesheet/models/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Mohammed Hisam (odoo@cybrosysy.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import res_config_settings +from . import pos_config +from . import pos_session diff --git a/pos_timesheet/models/pos_config.py b/pos_timesheet/models/pos_config.py new file mode 100644 index 000000000..46994c0fe --- /dev/null +++ b/pos_timesheet/models/pos_config.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Mohammed Hisam (odoo@cybrosysy.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import fields, models + + +class PosConfig(models.Model): + """Inherits the PosConfig class for adding fields""" + _inherit = 'pos.config' + + time_log = fields.Boolean(string="Time Log", default=False, + help="Track employees timesheet in pos") + project_id = fields.Many2one( + 'project.project', + string="Project", + ondelete='cascade', + help="Project for the timesheet") diff --git a/pos_timesheet/models/pos_session.py b/pos_timesheet/models/pos_session.py new file mode 100644 index 000000000..57a459565 --- /dev/null +++ b/pos_timesheet/models/pos_session.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Mohammed Hisam (odoo@cybrosysy.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import api, fields, models, _ + + +class PosSession(models.Model): + """Inherits the PosSession class for adding fields and functions""" + + _inherit = "pos.session" + + task_id = fields.Many2one( + "project.task", + string="Task", + help="Session Timesheet Task", + ondelete="cascade", + default=False, + ) + + @api.model_create_multi + def create(self, vals_list): + """Create Task for add timesheet""" + result = super().create(vals_list) + + if result.config_id.module_pos_hr and result.config_id.time_log: + result.task_id = self.env["project.task"].create( + { + "name": result.name, + "project_id": result.config_id.project_id.id, + "company_id": result.config_id.company_id.id, + } + ) + return result + + def _pos_ui_models_to_load(self): + """loads models to the UI""" + result = super()._pos_ui_models_to_load() + result.append("account.analytic.line") + return result + + def _loader_params_account_analytic_line(self): + """Returns loader params for account""" + return { + "search_params": { + "domain": [ + ("task_id", "=", self.task_id.id), + ("date", "=", fields.Date.context_today(self)), + ], + "fields": ["employee_id", "unit_amount"], + }, + } + + def _get_pos_ui_account_analytic_line(self, params): + """Returns the account analytics line for the pos""" + return ( + self.env["account.analytic.line"] + .sudo() + .search_read(**params["search_params"]) + ) + + def _loader_params_pos_session(self): + """Loading parameters to the session""" + result = super()._loader_params_pos_session() + result["search_params"]["fields"].append("task_id") + return result + + def set_timesheet(self, data): + """Update Timesheet of the employee""" + for timesheet in data: + if timesheet["workMinutes"] > 0: + hours = timesheet["workMinutes"] / 60 + session_id = self.browse(timesheet["sessionId"]) + timestamp_seconds = timesheet["checkInTime"] / 1000 + date_time = fields.datetime.fromtimestamp(timestamp_seconds) + date_only = date_time.date() + sudo_timesheet = self.env["account.analytic.line"].sudo() + employee_timesheet = sudo_timesheet.search( + [ + ("task_id", "=", session_id.task_id.id), + ("date", "=", date_only), + ("employee_id", "=", timesheet["cashierId"]), + ], + limit=1, + ) + if employee_timesheet: + employee_timesheet.unit_amount += hours + else: + sudo_timesheet.create( + { + "task_id": session_id.task_id.id, + "employee_id": timesheet["cashierId"], + "name": session_id.name, + "date": date_only, + "unit_amount": hours, + } + ) + return True + + def action_show_time_log(self): + """Show the task its contained timesheet for the session""" + return { + "name": _("Time Log"), + "type": "ir.actions.act_window", + "res_model": "project.task", + "view_mode": "form", + "res_id": self.task_id.id, + } diff --git a/pos_timesheet/models/res_config_settings.py b/pos_timesheet/models/res_config_settings.py new file mode 100644 index 000000000..4ac05d50d --- /dev/null +++ b/pos_timesheet/models/res_config_settings.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Mohammed Hisam (odoo@cybrosysy.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + """Inherits the default settings for the ResConfig model""" + _inherit = 'res.config.settings' + + pos_time_log = fields.Boolean( + related="pos_config_id.time_log", + string="Time Log", + help="Track employees timesheet in pos", + readonly=False) + pos_project_id = fields.Many2one( + related='pos_config_id.project_id', + string="Project", + help="Project for the timesheet", + readonly=False) diff --git a/pos_timesheet/static/description/assets/icons/check.png b/pos_timesheet/static/description/assets/icons/check.png new file mode 100755 index 000000000..c8e85f51d Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/check.png differ diff --git a/pos_timesheet/static/description/assets/icons/chevron.png b/pos_timesheet/static/description/assets/icons/chevron.png new file mode 100755 index 000000000..2089293d6 Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/chevron.png differ diff --git a/pos_timesheet/static/description/assets/icons/cogs.png b/pos_timesheet/static/description/assets/icons/cogs.png new file mode 100755 index 000000000..95d0bad62 Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/cogs.png differ diff --git a/pos_timesheet/static/description/assets/icons/consultation.png b/pos_timesheet/static/description/assets/icons/consultation.png new file mode 100755 index 000000000..8319d4baa Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/consultation.png differ diff --git a/pos_timesheet/static/description/assets/icons/ecom-black.png b/pos_timesheet/static/description/assets/icons/ecom-black.png new file mode 100755 index 000000000..a9385ff13 Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/ecom-black.png differ diff --git a/pos_timesheet/static/description/assets/icons/education-black.png b/pos_timesheet/static/description/assets/icons/education-black.png new file mode 100755 index 000000000..3eb09b27b Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/education-black.png differ diff --git a/pos_timesheet/static/description/assets/icons/hotel-black.png b/pos_timesheet/static/description/assets/icons/hotel-black.png new file mode 100755 index 000000000..130f613be Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/hotel-black.png differ diff --git a/pos_timesheet/static/description/assets/icons/license.png b/pos_timesheet/static/description/assets/icons/license.png new file mode 100755 index 000000000..a5869797e Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/license.png differ diff --git a/pos_timesheet/static/description/assets/icons/lifebuoy.png b/pos_timesheet/static/description/assets/icons/lifebuoy.png new file mode 100755 index 000000000..658d56ccc Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/lifebuoy.png differ diff --git a/pos_timesheet/static/description/assets/icons/manufacturing-black.png b/pos_timesheet/static/description/assets/icons/manufacturing-black.png new file mode 100755 index 000000000..697eb0e9f Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/manufacturing-black.png differ diff --git a/pos_timesheet/static/description/assets/icons/pos-black.png b/pos_timesheet/static/description/assets/icons/pos-black.png new file mode 100755 index 000000000..97c0f90c1 Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/pos-black.png differ diff --git a/pos_timesheet/static/description/assets/icons/puzzle.png b/pos_timesheet/static/description/assets/icons/puzzle.png new file mode 100755 index 000000000..65cf854e7 Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/puzzle.png differ diff --git a/pos_timesheet/static/description/assets/icons/restaurant-black.png b/pos_timesheet/static/description/assets/icons/restaurant-black.png new file mode 100755 index 000000000..4a35eb939 Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/restaurant-black.png differ diff --git a/pos_timesheet/static/description/assets/icons/service-black.png b/pos_timesheet/static/description/assets/icons/service-black.png new file mode 100755 index 000000000..301ab51cb Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/service-black.png differ diff --git a/pos_timesheet/static/description/assets/icons/trading-black.png b/pos_timesheet/static/description/assets/icons/trading-black.png new file mode 100755 index 000000000..9398ba2f1 Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/trading-black.png differ diff --git a/pos_timesheet/static/description/assets/icons/training.png b/pos_timesheet/static/description/assets/icons/training.png new file mode 100755 index 000000000..884ca024d Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/training.png differ diff --git a/pos_timesheet/static/description/assets/icons/update.png b/pos_timesheet/static/description/assets/icons/update.png new file mode 100755 index 000000000..ecbc5a01a Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/update.png differ diff --git a/pos_timesheet/static/description/assets/icons/user.png b/pos_timesheet/static/description/assets/icons/user.png new file mode 100755 index 000000000..6ffb23d9f Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/user.png differ diff --git a/pos_timesheet/static/description/assets/icons/wrench.png b/pos_timesheet/static/description/assets/icons/wrench.png new file mode 100755 index 000000000..6c04dea0f Binary files /dev/null and b/pos_timesheet/static/description/assets/icons/wrench.png differ diff --git a/pos_timesheet/static/description/assets/misc/categories.png b/pos_timesheet/static/description/assets/misc/categories.png new file mode 100755 index 000000000..bedf1e0b1 Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/categories.png differ diff --git a/pos_timesheet/static/description/assets/misc/check-box.png b/pos_timesheet/static/description/assets/misc/check-box.png new file mode 100755 index 000000000..42caf24b9 Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/check-box.png differ diff --git a/pos_timesheet/static/description/assets/misc/compass.png b/pos_timesheet/static/description/assets/misc/compass.png new file mode 100755 index 000000000..d5fed8faa Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/compass.png differ diff --git a/pos_timesheet/static/description/assets/misc/corporate.png b/pos_timesheet/static/description/assets/misc/corporate.png new file mode 100755 index 000000000..2eb13edbf Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/corporate.png differ diff --git a/pos_timesheet/static/description/assets/misc/customer-support.png b/pos_timesheet/static/description/assets/misc/customer-support.png new file mode 100755 index 000000000..79efc72ed Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/customer-support.png differ diff --git a/pos_timesheet/static/description/assets/misc/cybrosys-logo.png b/pos_timesheet/static/description/assets/misc/cybrosys-logo.png new file mode 100755 index 000000000..cc3cc0ccf Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/cybrosys-logo.png differ diff --git a/pos_timesheet/static/description/assets/misc/features.png b/pos_timesheet/static/description/assets/misc/features.png new file mode 100755 index 000000000..b41769f77 Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/features.png differ diff --git a/pos_timesheet/static/description/assets/misc/logo.png b/pos_timesheet/static/description/assets/misc/logo.png new file mode 100755 index 000000000..478462d3e Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/logo.png differ diff --git a/pos_timesheet/static/description/assets/misc/pictures.png b/pos_timesheet/static/description/assets/misc/pictures.png new file mode 100755 index 000000000..56d255fe9 Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/pictures.png differ diff --git a/pos_timesheet/static/description/assets/misc/pie-chart.png b/pos_timesheet/static/description/assets/misc/pie-chart.png new file mode 100755 index 000000000..426e05244 Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/pie-chart.png differ diff --git a/pos_timesheet/static/description/assets/misc/right-arrow.png b/pos_timesheet/static/description/assets/misc/right-arrow.png new file mode 100755 index 000000000..730984a06 Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/right-arrow.png differ diff --git a/pos_timesheet/static/description/assets/misc/star.png b/pos_timesheet/static/description/assets/misc/star.png new file mode 100755 index 000000000..2eb9ab29f Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/star.png differ diff --git a/pos_timesheet/static/description/assets/misc/support.png b/pos_timesheet/static/description/assets/misc/support.png new file mode 100755 index 000000000..4f18b8b82 Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/support.png differ diff --git a/pos_timesheet/static/description/assets/misc/whatsapp.png b/pos_timesheet/static/description/assets/misc/whatsapp.png new file mode 100755 index 000000000..d513a5356 Binary files /dev/null and b/pos_timesheet/static/description/assets/misc/whatsapp.png differ diff --git a/pos_timesheet/static/description/assets/modules/1.png b/pos_timesheet/static/description/assets/modules/1.png new file mode 100644 index 000000000..5ecc4d883 Binary files /dev/null and b/pos_timesheet/static/description/assets/modules/1.png differ diff --git a/pos_timesheet/static/description/assets/modules/2.png b/pos_timesheet/static/description/assets/modules/2.png new file mode 100644 index 000000000..d1d3775d6 Binary files /dev/null and b/pos_timesheet/static/description/assets/modules/2.png differ diff --git a/pos_timesheet/static/description/assets/modules/3.png b/pos_timesheet/static/description/assets/modules/3.png new file mode 100644 index 000000000..dcbd0cb06 Binary files /dev/null and b/pos_timesheet/static/description/assets/modules/3.png differ diff --git a/pos_timesheet/static/description/assets/modules/4.png b/pos_timesheet/static/description/assets/modules/4.png new file mode 100644 index 000000000..fd1f87699 Binary files /dev/null and b/pos_timesheet/static/description/assets/modules/4.png differ diff --git a/pos_timesheet/static/description/assets/modules/5.png b/pos_timesheet/static/description/assets/modules/5.png new file mode 100644 index 000000000..05c8b4a69 Binary files /dev/null and b/pos_timesheet/static/description/assets/modules/5.png differ diff --git a/pos_timesheet/static/description/assets/modules/6.png b/pos_timesheet/static/description/assets/modules/6.png new file mode 100644 index 000000000..f5c24146b Binary files /dev/null and b/pos_timesheet/static/description/assets/modules/6.png differ diff --git a/pos_timesheet/static/description/assets/screenshots/1.png b/pos_timesheet/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..5b3a97b6d Binary files /dev/null and b/pos_timesheet/static/description/assets/screenshots/1.png differ diff --git a/pos_timesheet/static/description/assets/screenshots/2.png b/pos_timesheet/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..f0d4cc1e9 Binary files /dev/null and b/pos_timesheet/static/description/assets/screenshots/2.png differ diff --git a/pos_timesheet/static/description/assets/screenshots/3.png b/pos_timesheet/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..e853afbe8 Binary files /dev/null and b/pos_timesheet/static/description/assets/screenshots/3.png differ diff --git a/pos_timesheet/static/description/assets/screenshots/4.png b/pos_timesheet/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..568d9d5b3 Binary files /dev/null and b/pos_timesheet/static/description/assets/screenshots/4.png differ diff --git a/pos_timesheet/static/description/assets/screenshots/5.png b/pos_timesheet/static/description/assets/screenshots/5.png new file mode 100644 index 000000000..75dec5fdf Binary files /dev/null and b/pos_timesheet/static/description/assets/screenshots/5.png differ diff --git a/pos_timesheet/static/description/assets/screenshots/hero.gif b/pos_timesheet/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..f55e00626 Binary files /dev/null and b/pos_timesheet/static/description/assets/screenshots/hero.gif differ diff --git a/pos_timesheet/static/description/banner.png b/pos_timesheet/static/description/banner.png new file mode 100644 index 000000000..9185cf32f Binary files /dev/null and b/pos_timesheet/static/description/banner.png differ diff --git a/pos_timesheet/static/description/icon.png b/pos_timesheet/static/description/icon.png new file mode 100644 index 000000000..cf58f0526 Binary files /dev/null and b/pos_timesheet/static/description/icon.png differ diff --git a/pos_timesheet/static/description/index.html b/pos_timesheet/static/description/index.html new file mode 100755 index 000000000..92b07ffe5 --- /dev/null +++ b/pos_timesheet/static/description/index.html @@ -0,0 +1,543 @@ +
+ +
+ +
+
+ Enterprise +
+
+ Community +
+
+ Odoo sh +
+
+
+ +
+
+
+ +

+ POS Timesheet +

+

Add Timesheet For POS

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

Explore This + Module

+
+ + + + +
+
+ +
+

Overview +

+
+
+
+ This module enhances the Point of Sale (POS) functionality by automatically + calculating timesheets for employees based on their activities in the POS. +
+ +
+ + + +
+
+ +
+

Features +

+
+
+
+
+ + Add Timesheet for employees based on their activities in the POS. +
+
+ + View the employees' worked hours in real-time in the POS. +
+
+
+
+ + Track Employee activity in POS online/offline mode. +
+
+ + Using Project and Tasks makes it easier. +
+
+
+ + + +
+
+ +
+

Screenshots +

+
+
+
+
+

Enable Multi Employee per Session, then the Time Log option will be visible in the Configuration Settings of POS and you can also set a project for the timesheet.

+ +
+ +
+

The employee can view the total work hours, last check-in time, and time worked since the last check-in time by clicking the clock icon in the header.

+ +
+ +
+ +
+ +
+

You can easily navigate to the task associated with the session by clicking timelog smart tab.

+ +
+ +
+

You can see all the employees timesheet in the task timesheet tab.

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

+ Related + 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

+
+
+
+
+
+
+
+ +
+
+
+ \ No newline at end of file diff --git a/pos_timesheet/static/src/css/worked_hour_popup.css b/pos_timesheet/static/src/css/worked_hour_popup.css new file mode 100644 index 000000000..ae36e56bf --- /dev/null +++ b/pos_timesheet/static/src/css/worked_hour_popup.css @@ -0,0 +1,15 @@ +.total-worked { + color: #714B67; + font-weight: bold; +} + +.current-worked { + color: #017e84; + font-weight: bold; + margin-left: 10px; +} + +.checked-in { + color: #5eb937; +} + diff --git a/pos_timesheet/static/src/js/Chrome.js b/pos_timesheet/static/src/js/Chrome.js new file mode 100644 index 000000000..d39441f4b --- /dev/null +++ b/pos_timesheet/static/src/js/Chrome.js @@ -0,0 +1,35 @@ +/** @odoo-module **/ + +import Chrome from "point_of_sale.Chrome"; +import Registries from "point_of_sale.Registries"; + + +const PosTimeSheetChrome = (Chrome) => + class extends Chrome { + + + /** + * @override + * Add timesheet in to server when go to backend + */ + async _closePos() { + if (this.env.pos.config.module_pos_hr & this.env.pos.config.time_log) { + return this.env.pos._handleTimesheet(() => super._closePos(...arguments)); + } else { + return await super._closePos(...arguments); + } + } + + /** + *@override + * Save Worked hours with CheckoutTime and WorkedMinutes in localStorage + * on beforeunload - closing the browser, reloading or going to other page. + */ + _onBeforeUnload() { + super._onBeforeUnload(...arguments); + const timesheetData = this.env.pos.prepareTimesheet(); + localStorage.setItem('timesheetData', JSON.stringify(timesheetData)); + } + }; + +Registries.Component.extend(Chrome, PosTimeSheetChrome); diff --git a/pos_timesheet/static/src/js/Popups/ClosePosPopup.js b/pos_timesheet/static/src/js/Popups/ClosePosPopup.js new file mode 100644 index 000000000..24a43173e --- /dev/null +++ b/pos_timesheet/static/src/js/Popups/ClosePosPopup.js @@ -0,0 +1,24 @@ +/** @odoo-module **/ + +import ClosePosPopup from "point_of_sale.ClosePosPopup"; +import Registries from "point_of_sale.Registries"; + +const NewClosePosPopup = (ClosePosPopup) => + class extends ClosePosPopup { + + /** + * @override + * Add timesheet in to server when Close Session. + */ + async closeSession() { + if (this.env.pos.config.module_pos_hr & this.env.pos.config.time_log) { + return this.env.pos._handleTimesheet(() => + super.closeSession(...arguments) + ); + } else { + return await super.closeSession(...arguments); + } + } + }; + +Registries.Component.extend(ClosePosPopup, NewClosePosPopup); diff --git a/pos_timesheet/static/src/js/Popups/WorkedHourPopup.js b/pos_timesheet/static/src/js/Popups/WorkedHourPopup.js new file mode 100644 index 000000000..525ad5e45 --- /dev/null +++ b/pos_timesheet/static/src/js/Popups/WorkedHourPopup.js @@ -0,0 +1,114 @@ +/** @odoo-module **/ + +import Registries from "point_of_sale.Registries"; +import AbstractAwaitablePopup from "point_of_sale.AbstractAwaitablePopup"; +import { _lt } from "@web/core/l10n/translation"; + +const { onMounted, onWillUnmount, useState } = owl; + + + +class WorkedHourPopup extends AbstractAwaitablePopup { + /** + * @override + * Sets up SetInterval to show realtime worked time. + */ + setup() { + super.setup(...arguments); + this.state = useState({ + workedTime: '', + totalWorkedTime: '' + }) + onMounted(()=> { + this.workedTime(); + this.totalWorkedTime(); + this.interval = setInterval(()=>{ + this.workedTime(); + this.totalWorkedTime(); + }, 1000); + }) + onWillUnmount(()=> { + clearInterval(this.interval); + }) + + } + + + /** + * Getter for the check-in time. + * @returns {string} Formatted check-in time. + */ + get checkInTime() { + const timesheetData = JSON.parse(localStorage.getItem('timesheetData')); + const checkInTime = timesheetData ? timesheetData.at(-1)['checkInTime'] : Date.now(); + const formattedDate = new Intl.DateTimeFormat('en-US', { + hour: '2-digit', + minute: '2-digit', + hour12: true + }).format(checkInTime); + return formattedDate; + } + + /** + * Getter for the current worked time. + * Assign {string} Formatted current worked time in to this.state.workedTime. + */ + workedTime() { + const [hours, minutes, seconds] = this.currentWorkedTime(); + this.state.workedTime = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`; + } + + /** + * Getter for the total today's worked time. + * Assign {string} Formatted total worked time in to this.state.totalWorkedTime. + */ + totalWorkedTime() { + let minutes = 0; + const workerData = this.env.pos.workedTime; + const timesheetData = JSON.parse(localStorage.getItem('timesheetData')); + const cashierId = this.env.pos.cashier.id; + + if (timesheetData) { + const cashierLocalTimesheet = timesheetData.filter(data => data.cashierId === cashierId && data?.workMinutes); + minutes += cashierLocalTimesheet.reduce((sum, data) => sum + data.workMinutes, 0); + } + + const cashierData = workerData.find(data => data['cashierId'] === cashierId); + + minutes += cashierData ? parseInt(cashierData['minutes']) : 0; + + const [currentHours, currentMinutes, seconds] = this.currentWorkedTime(); + let hours = currentHours; + minutes += currentMinutes; + + const extraHour = Math.floor(minutes / 60); + minutes %= 60; + hours += extraHour; + + this.state.totalWorkedTime = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`; + } + + /** + * Retrieves the current worked time. + * @returns {Array} Array containing hours and minutes of current worked time. + */ + currentWorkedTime() { + const timesheetData = JSON.parse(localStorage.getItem('timesheetData')); + const checkInTime = timesheetData ? timesheetData.at(-1)['checkInTime'] : Date.now(); + const currentTime = Date.now(); + const differenceMs = Math.abs(currentTime - checkInTime); + const hours = Math.floor(differenceMs / (1000 * 60 * 60)); + const minutes = Math.floor((differenceMs % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((differenceMs % (1000 * 60)) / 1000); + return [hours, minutes, seconds]; + } + +} +WorkedHourPopup.template = "WorkedHourPopup"; +WorkedHourPopup.defaultProps = { + cancelText: _lt("Cancel"), + title: _lt("Worked Hours"), + confirmKey: false, +}; + +Registries.Component.add(WorkedHourPopup); diff --git a/pos_timesheet/static/src/js/TimeSheetButton.js b/pos_timesheet/static/src/js/TimeSheetButton.js new file mode 100644 index 000000000..59aca9720 --- /dev/null +++ b/pos_timesheet/static/src/js/TimeSheetButton.js @@ -0,0 +1,16 @@ +/** @odoo-module **/ + +import PosComponent from "point_of_sale.PosComponent"; +import Registries from "point_of_sale.Registries"; + //Timesheet Button in Header of Pos + class TimeSheetButton extends PosComponent { + /** + * Show WorkedHourPopup + */ + async onClick(){ + await this.showPopup('WorkedHourPopup'); + } + } + TimeSheetButton.template = "TimeSheetButton"; + + Registries.Component.add(TimeSheetButton); diff --git a/pos_timesheet/static/src/js/model.js b/pos_timesheet/static/src/js/model.js new file mode 100644 index 000000000..6c1a611ce --- /dev/null +++ b/pos_timesheet/static/src/js/model.js @@ -0,0 +1,156 @@ +/** @odoo-module **/ + +import { PosGlobalState } from 'point_of_sale.models'; +import Registries from 'point_of_sale.Registries'; + +const NewPosGlobalState = (PosGlobalState) => class NewPosGlobalState extends PosGlobalState { + /** + * @override + * load employees timesheet of this session + */ + async _processData(loadedData) { + await super._processData(...arguments); + if (this.config.module_pos_hr && this.config.time_log) { + this.timesheet = loadedData['account.analytic.line']; + this.workedTime = this.getWorkedTime(); + } + } + + /** + * Retrieves worked time data and sets it to the POS instance. + */ + getWorkedTime() { + const datas = this.timesheet; + const workedTime = datas.map(data => ({ + 'cashierId': data['employee_id'][0], + 'minutes': Math.floor(data['unit_amount'] * 60) + })); + return workedTime; + } + + /** + * @override + * If the 'Multi Employee persession' and 'Time Log' enabled in POS configuration, + * handles timesheet processing before resetting the cashier. + */ + + reset_cashier() { + if (this.config.module_pos_hr && this.config.time_log) { + return this._handleTimesheet(() => super.reset_cashier(...arguments)); + } else { + return super.reset_cashier(...arguments); + } + } + + /** + * @override + * If the 'Multi Employee persession' and 'Time Log' enabled in POS configuration, + * handles timesheet processing before setting cashier. + * @param {Object} employee - Employee object representing the cashier. + */ + set_cashier(employee) { + if (this.config.module_pos_hr && this.config.time_log) { + return this._handleTimesheet(() => super.set_cashier(...arguments), employee); + } else { + return super.set_cashier(...arguments); + } + } + + /** + * Handles timesheet processing asynchronously. + * Executes a callback function and handles timesheet operations based on the POS configuration. + * @param {Function} callback - Callback function to execute. + * @param {Object} employee - Employee object representing the cashier or null. + */ + + _handleTimesheet(callback, employee = null) { + const data = this.prepareTimesheet(); + return this.sendTimesheet(data) + .then(response => { + this.setTimesheet(response, employee); + }) + .catch(errData => { + this.setTimesheet(errData, employee); + }) + .finally(() => { + callback(); + }); + } + + /** + * Sets the timesheet data to localStorage. + * @param {Array} timesheetData - Timesheet data to set. + * @param {Object} employee - Employee object representing the cashier. + */ + setTimesheet(timesheetData, employee = null) { + if (employee) { + const cashierData = { + cashierId: employee.id, + checkInTime: Date.now(), + sessionId: this.pos_session.id + }; + if (timesheetData) { + timesheetData.push(cashierData); + } else { + timesheetData = [cashierData]; + } + } + localStorage.setItem('timesheetData', JSON.stringify(timesheetData)); + } + + /** + * Sends timesheet data to the server. + * @param {Array} timesheetData - Timesheet data to send. + * @return {null} success or no timesheetData, if error {Object} timesheetData + */ + sendTimesheet(timesheetData) { + return new Promise((resolve, reject) => { + if (timesheetData) { + this.env.services.rpc({ + model: 'pos.session', + method: 'set_timesheet', + args: [[], timesheetData], + }).then(res => { + timesheetData.forEach(data => { + let index = this.workedTime.findIndex(item => item.cashierId === data.cashierId); + if (index !== -1) { + this.workedTime[index].minutes += data.workMinutes; + } else { + this.workedTime.push({ cashierId: data.cashierId, minutes: data.workMinutes }); + } + }); + resolve(null); + }) + .catch(err => { + reject(timesheetData); + }); + } else { + resolve(null); + } + }); + } + + /** + * Prepares timesheet data for sending to the server. + * Checks for existing timesheet data in localStorage and adjusts work minutes. + * @returns {Array|null} Prepared timesheet data. + */ + prepareTimesheet() { + const timesheetData = JSON.parse(localStorage.getItem('timesheetData')); + + if (timesheetData && timesheetData.length != 0){ + if (!timesheetData.at(-1).hasOwnProperty('checkOutTime')) { + timesheetData.at(-1)['checkOutTime'] = Date.now(); + const timeDiff = timesheetData.at(-1)['checkOutTime'] - timesheetData.at(-1)['checkInTime']; + timesheetData.at(-1)['workMinutes'] = Math.floor(timeDiff / (1000 * 60)); + if (timesheetData.at(-1)['workMinutes'] <= 0) { + timesheetData.pop(); + } + } + return timesheetData; + } + return null; + } +} + +Registries.Model.extend(PosGlobalState, NewPosGlobalState); diff --git a/pos_timesheet/static/src/xml/CashMoveButton.xml b/pos_timesheet/static/src/xml/CashMoveButton.xml new file mode 100644 index 000000000..a0e9e5471 --- /dev/null +++ b/pos_timesheet/static/src/xml/CashMoveButton.xml @@ -0,0 +1,15 @@ + + + + + + +
+ + Cash In/Out +
+
+
+ +
diff --git a/pos_timesheet/static/src/xml/Chrome.xml b/pos_timesheet/static/src/xml/Chrome.xml new file mode 100644 index 000000000..2a016203d --- /dev/null +++ b/pos_timesheet/static/src/xml/Chrome.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/pos_timesheet/static/src/xml/Popups/WorkedHourPopup.xml b/pos_timesheet/static/src/xml/Popups/WorkedHourPopup.xml new file mode 100644 index 000000000..46387f45b --- /dev/null +++ b/pos_timesheet/static/src/xml/Popups/WorkedHourPopup.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/pos_timesheet/static/src/xml/TimeSheetButton.xml b/pos_timesheet/static/src/xml/TimeSheetButton.xml new file mode 100644 index 000000000..cd3393f23 --- /dev/null +++ b/pos_timesheet/static/src/xml/TimeSheetButton.xml @@ -0,0 +1,10 @@ + + + + +
+ +
+
+ +
diff --git a/pos_timesheet/views/pos_session_views.xml b/pos_timesheet/views/pos_session_views.xml new file mode 100644 index 000000000..762a1681d --- /dev/null +++ b/pos_timesheet/views/pos_session_views.xml @@ -0,0 +1,19 @@ + + + + pos.time.log.session.form.view + pos.session + + + + + + + + + + diff --git a/pos_timesheet/views/res_config_settings_views.xml b/pos_timesheet/views/res_config_settings_views.xml new file mode 100644 index 000000000..eabaf7dce --- /dev/null +++ b/pos_timesheet/views/res_config_settings_views.xml @@ -0,0 +1,40 @@ + + + + + res.config.settings.view.form.inherit.pos + res.config.settings + + + +
+
+ +
+
+ Time Log + +
+ Automatically record employees' work hours in the + timesheet +
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file