diff --git a/.copier-answers.yml b/.copier-answers.yml index ffa6db748f..8fe3865b04 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,8 +1,8 @@ # Do NOT update manually; changes here will be overwritten by Copier -_commit: v1.14.2 -_src_path: git+https://github.com/oca/oca-addons-repo-template +_commit: v1.22 +_src_path: https://github.com/OCA/oca-addons-repo-template.git ci: GitHub -dependency_installation_mode: OCA +convert_readme_fragments_to_markdown: false generate_requirements_txt: true github_check_license: true github_ci_extra_env: {} @@ -11,14 +11,14 @@ github_enable_makepot: true github_enable_stale_action: true github_enforce_dev_status_compatibility: true include_wkhtmltopdf: false +odoo_test_flavor: OCB odoo_version: 12.0 org_name: Odoo Community Association (OCA) org_slug: OCA -rebel_module_groups: [] -repo_description: null +rebel_module_groups: +- hr_timesheet_begin_end_no_end +repo_description: 'TODO: add repo description.' repo_name: Odoo Timesheet Management Modules repo_slug: timesheet repo_website: https://github.com/OCA/timesheet -travis_apt_packages: [] -travis_apt_sources: [] diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index f86d418269..0c862ddae0 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -13,7 +13,7 @@ jobs: pre-commit: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions/setup-python@v2 with: python-version: "3.6" @@ -27,6 +27,15 @@ jobs: run: pip install pre-commit - name: Run pre-commit run: pre-commit run --all-files --show-diff-on-failure --color=always + env: + # Consider valid a PR that changes README fragments but doesn't + # change the README.rst file itself. It's not really a problem + # because the bot will update it anyway after merge. This way, we + # lower the barrier for functional contributors that want to fix the + # readme fragments, while still letting developers get README + # auto-generated (which also helps functionals when using runboat). + # DOCS https://pre-commit.com/#temporarily-disabling-hooks + SKIP: oca-gen-addon-readme - name: Check that all files generated by pre-commit are in git run: | newfiles="$(git ls-files --others --exclude-from=.gitignore)" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 1693a1253b..fa17fcd4e8 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Stale PRs and issues policy - uses: actions/stale@v4 + uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # General settings. @@ -48,7 +48,7 @@ jobs: # * Issues that are pending more information # * Except Issues marked as "no stale" - name: Needs more information stale issues policy - uses: actions/stale@v4 + uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} ascending: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 20bf055d40..776b85f426 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest name: Detect unreleased dependencies steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: | for reqfile in requirements.txt test-requirements.txt ; do if [ -f ${reqfile} ] ; then @@ -35,11 +35,14 @@ jobs: fail-fast: false matrix: include: - - container: ghcr.io/oca/oca-ci/py3.6-odoo12.0:latest + - container: ghcr.io/oca/oca-ci/py3.6-ocb12.0:latest + include: "hr_timesheet_begin_end_no_end" + name: test with OCB makepot: "true" - name: test with Odoo - container: ghcr.io/oca/oca-ci/py3.6-ocb12.0:latest + exclude: "hr_timesheet_begin_end_no_end" name: test with OCB + makepot: "true" services: postgres: image: postgres:9.6 @@ -49,8 +52,11 @@ jobs: POSTGRES_DB: odoo ports: - 5432:5432 + env: + INCLUDE: "${{ matrix.include }}" + EXCLUDE: "${{ matrix.exclude }}" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: persist-credentials: false - name: Install addons and dependencies @@ -63,7 +69,9 @@ jobs: run: oca_init_test_database - name: Run tests run: oca_run_tests - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} - name: Update .pot files run: oca_export_and_push_pot https://x-access-token:${{ secrets.GIT_PUSH_TOKEN }}@github.com/${{ github.repository }} if: ${{ matrix.makepot == 'true' && github.event_name == 'push' && github.repository_owner == 'OCA' }} diff --git a/.gitignore b/.gitignore index 9c283fd41f..0090721f5d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ __pycache__/ *.py[cod] /.venv /.pytest_cache +/.ruff_cache # C extensions *.so diff --git a/.oca_hooks.cfg b/.oca_hooks.cfg new file mode 100644 index 0000000000..1f3e3e4267 --- /dev/null +++ b/.oca_hooks.cfg @@ -0,0 +1,2 @@ +[MESSAGES_CONTROL] +disable=xml-deprecated-data-node,xml-deprecated-tree-attribute diff --git a/README.md b/README.md index 85bddac620..c87e4e95c4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ # Odoo Timesheet Management Modules -None +TODO: add repo description. diff --git a/hr_timesheet_activity_begin_end/models/account_analytic_line.py b/hr_timesheet_activity_begin_end/models/account_analytic_line.py index ebac126754..7e7a1014be 100644 --- a/hr_timesheet_activity_begin_end/models/account_analytic_line.py +++ b/hr_timesheet_activity_begin_end/models/account_analytic_line.py @@ -1,10 +1,11 @@ # Copyright 2015 Camptocamp SA - Guewen Baconnier # Copyright 2017 Tecnativa, S.L. - Luis M. Ontalba +# Copyright 2024 Coop IT Easy SC - Carmen Bianca BAKKER # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from datetime import timedelta -from odoo import models, fields, api, exceptions, _ +from odoo import _, api, exceptions, fields, models from odoo.tools.float_utils import float_compare @@ -15,55 +16,90 @@ class AccountAnalyticLine(models.Model): time_start = fields.Float(string='Begin Hour') time_stop = fields.Float(string='End Hour') - @api.constrains('time_start', 'time_stop', 'unit_amount') - def _check_time_start_stop(self): + @api.onchange("time_start", "time_stop", "project_id") + def onchange_hours_start_stop(self): + self.unit_amount = self.unit_amount_from_start_stop() + + def _validate_start_before_stop(self): + value_to_html = self.env["ir.qweb.field.float_time"].value_to_html + for line in self: + if line.time_stop < line.time_start: + raise exceptions.ValidationError( + _("The beginning hour (%s) must " "precede the ending hour (%s).") + % ( + value_to_html(line.time_start, None), + value_to_html(line.time_stop, None), + ) + ) + + def _validate_unit_amount_equal_to_time_diff(self): + value_to_html = self.env["ir.qweb.field.float_time"].value_to_html + for line in self: + hours = line.unit_amount_from_start_stop() + rounding = self.env.ref("uom.product_uom_hour").rounding + if hours and float_compare( + hours, line.unit_amount, precision_rounding=rounding + ): + raise exceptions.ValidationError( + _( + "The duration (%s) must be equal to the difference " + "between the hours (%s)." + ) + % ( + value_to_html(line.unit_amount, None), + value_to_html(hours, None), + ) + ) + + def _overlap_domain(self): self.ensure_one() - value_to_html = self.env['ir.qweb.field.float_time'].value_to_html - start = timedelta(hours=self.time_start) - stop = timedelta(hours=self.time_stop) - if stop < start: - raise exceptions.ValidationError( - _('The beginning hour (%s) must ' - 'precede the ending hour (%s).') % - (value_to_html(self.time_start, None), - value_to_html(self.time_stop, None)) - ) - hours = (stop - start).seconds / 3600 - rounding = self.env.ref("uom.product_uom_hour").rounding - if (hours and - float_compare(hours, self.unit_amount, precision_rounding=rounding)): - raise exceptions.ValidationError( - _('The duration (%s) must be equal to the difference ' - 'between the hours (%s).') % - (value_to_html(self.unit_amount, None), - value_to_html(hours, None)) - ) - # check if lines overlap - others = self.search([ - ('id', '!=', self.id), - ('user_id', '=', self.user_id.id), - ('date', '=', self.date), - ('time_start', '<', self.time_stop), - ('time_stop', '>', self.time_start), - ]) - if others: - message = _("Lines can't overlap:\n") - message += '\n'.join(['%s - %s' % - (value_to_html(line.time_start, None), - value_to_html(line.time_stop, None)) - for line - in (self + others).sorted( - lambda l: l.time_start - )]) - raise exceptions.ValidationError(message) + return [ + ("id", "!=", self.id), + ("user_id", "=", self.user_id.id), + ("date", "=", self.date), + ("time_start", "<", self.time_stop), + ("time_stop", ">", self.time_start), + ] - @api.onchange('time_start', 'time_stop') - def onchange_hours_start_stop(self): - start = timedelta(hours=self.time_start) - stop = timedelta(hours=self.time_stop) + def _validate_no_overlap(self): + value_to_html = self.env["ir.qweb.field.float_time"].value_to_html + for line in self: + others = self.search(line._overlap_domain()) + if others: + message = _("Lines can't overlap:\n") + message += "\n".join( + [ + "%s - %s" + % ( + value_to_html(line.time_start, None), + value_to_html(line.time_stop, None), + ) + for line in (line + others).sorted(lambda l: l.time_start) + ] + ) + raise exceptions.ValidationError(message) + + @api.constrains("time_start", "time_stop", "unit_amount") + def _check_time_start_stop(self): + self._validate_start_before_stop() + self._validate_unit_amount_equal_to_time_diff() + self._validate_no_overlap() + + @api.model + def _hours_from_start_stop(self, time_start, time_stop): + start = timedelta(hours=time_start) + stop = timedelta(hours=time_stop) if stop < start: - return - self.unit_amount = (stop - start).seconds / 3600 + # Invalid case, but return something sensible. + return 0 + return (stop - start).seconds / 3600 + + def unit_amount_from_start_stop(self): + self.ensure_one() + # Don't handle non-timesheet lines. + if not self.project_id: + return 0 + return self._hours_from_start_stop(self.time_start, self.time_stop) def merge_timesheets(self): # pragma: no cover """This method is needed in case hr_timesheet_sheet is installed""" diff --git a/hr_timesheet_activity_begin_end/readme/newsfragments/693.bugfix.1.rst b/hr_timesheet_activity_begin_end/readme/newsfragments/693.bugfix.1.rst new file mode 100644 index 0000000000..056c17a06b --- /dev/null +++ b/hr_timesheet_activity_begin_end/readme/newsfragments/693.bugfix.1.rst @@ -0,0 +1 @@ +Fixed the test to use timesheet lines instead of bare analytic lines. diff --git a/hr_timesheet_activity_begin_end/readme/newsfragments/693.feature.1.rst b/hr_timesheet_activity_begin_end/readme/newsfragments/693.feature.1.rst new file mode 100644 index 0000000000..366ce40d00 --- /dev/null +++ b/hr_timesheet_activity_begin_end/readme/newsfragments/693.feature.1.rst @@ -0,0 +1 @@ +Refactored the module to be more extensible. diff --git a/hr_timesheet_activity_begin_end/tests/test_timesheet_begin_end.py b/hr_timesheet_activity_begin_end/tests/test_timesheet_begin_end.py index 620e6d8c1f..a8e2c88958 100644 --- a/hr_timesheet_activity_begin_end/tests/test_timesheet_begin_end.py +++ b/hr_timesheet_activity_begin_end/tests/test_timesheet_begin_end.py @@ -9,17 +9,16 @@ class TestBeginEnd(common.TransactionCase): def setUp(self): super(TestBeginEnd, self).setUp() self.timesheet_line_model = self.env['account.analytic.line'] - self.analytic = self.env.ref('analytic.analytic_administratif') - self.user = self.env.ref('base.user_root') + self.project = self.env.ref('project.project_project_1') + self.employee = self.env.ref('hr.employee_qdp') self.base_line = { 'name': 'test', 'date': fields.Date.today(), 'time_start': 10., 'time_stop': 12., - 'user_id': self.user.id, 'unit_amount': 2., - 'account_id': self.analytic.id, - 'amount': -60., + 'project_id': self.project.id, + 'employee_id': self.employee.id, } def test_onchange(self): @@ -27,6 +26,7 @@ def test_onchange(self): 'name': 'test', 'time_start': 10., 'time_stop': 12., + 'project_id': self.project.id, }) line.onchange_hours_start_stop() self.assertEquals(line.unit_amount, 2) diff --git a/hr_timesheet_begin_end_no_end/README.rst b/hr_timesheet_begin_end_no_end/README.rst new file mode 100644 index 0000000000..5e65ba1e93 --- /dev/null +++ b/hr_timesheet_begin_end_no_end/README.rst @@ -0,0 +1,88 @@ +========================================== +Timesheet - Begin/End Hours with empty end +========================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:6f9bf57eb39a36725b852081172b71f26e16fed507227ba22b894d0f1ed0d8e5 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Ftimesheet-lightgray.png?logo=github + :target: https://github.com/OCA/timesheet/tree/16.0/hr_timesheet_begin_end_no_end + :alt: OCA/timesheet +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/timesheet-16-0/timesheet-16-0-hr_timesheet_begin_end_no_end + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/timesheet&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Allow to insert begin hour without end hour on the timesheet. The benefit of +doing this is that you can save your begin hour at the start of your day/task, +and come back later to save the end hour. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Coop IT Easy SC + +Contributors +~~~~~~~~~~~~ + +* `Coop IT Easy SC `_: + + * Carmen Bianca BAKKER + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-carmenbianca| image:: https://github.com/carmenbianca.png?size=40px + :target: https://github.com/carmenbianca + :alt: carmenbianca + +Current `maintainer `__: + +|maintainer-carmenbianca| + +This module is part of the `OCA/timesheet `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/hr_timesheet_begin_end_no_end/__init__.py b/hr_timesheet_begin_end_no_end/__init__.py new file mode 100644 index 0000000000..3eb78877c5 --- /dev/null +++ b/hr_timesheet_begin_end_no_end/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2024 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +from . import models diff --git a/hr_timesheet_begin_end_no_end/__manifest__.py b/hr_timesheet_begin_end_no_end/__manifest__.py new file mode 100644 index 0000000000..5fe339296a --- /dev/null +++ b/hr_timesheet_begin_end_no_end/__manifest__.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2024 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +{ + "name": "Timesheet - Begin/End Hours with empty end", + "summary": ( + "Allow to insert begin hour without end hour, which the user may fill" + " in later." + ), + "version": "12.0.1.0.0", + "category": "Human Resources", + "website": "https://github.com/OCA/timesheet", + "author": "Coop IT Easy SC, Odoo Community Association (OCA)", + "maintainers": ["carmenbianca"], + "license": "AGPL-3", + "depends": ["hr_timesheet_activity_begin_end"], +} diff --git a/hr_timesheet_begin_end_no_end/models/__init__.py b/hr_timesheet_begin_end_no_end/models/__init__.py new file mode 100644 index 0000000000..84f4adcd2b --- /dev/null +++ b/hr_timesheet_begin_end_no_end/models/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2024 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +from . import account_analytic_line diff --git a/hr_timesheet_begin_end_no_end/models/account_analytic_line.py b/hr_timesheet_begin_end_no_end/models/account_analytic_line.py new file mode 100644 index 0000000000..5a0fcdd75e --- /dev/null +++ b/hr_timesheet_begin_end_no_end/models/account_analytic_line.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2024 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + + +from odoo import models + + +class AccountAnalyticLine(models.Model): + _inherit = "account.analytic.line" + + def _validate_start_before_stop(self): + for line in self: + if line.time_stop: + super(AccountAnalyticLine, line)._validate_start_before_stop() + return diff --git a/hr_timesheet_begin_end_no_end/readme/CONTRIBUTORS.rst b/hr_timesheet_begin_end_no_end/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..f1ac675779 --- /dev/null +++ b/hr_timesheet_begin_end_no_end/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Coop IT Easy SC `_: + + * Carmen Bianca BAKKER diff --git a/hr_timesheet_begin_end_no_end/readme/DESCRIPTION.rst b/hr_timesheet_begin_end_no_end/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..8376256322 --- /dev/null +++ b/hr_timesheet_begin_end_no_end/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +Allow to insert begin hour without end hour on the timesheet. The benefit of +doing this is that you can save your begin hour at the start of your day/task, +and come back later to save the end hour. diff --git a/hr_timesheet_begin_end_no_end/static/description/index.html b/hr_timesheet_begin_end_no_end/static/description/index.html new file mode 100644 index 0000000000..76647fd432 --- /dev/null +++ b/hr_timesheet_begin_end_no_end/static/description/index.html @@ -0,0 +1,427 @@ + + + + + +Timesheet - Begin/End Hours with empty end + + + +
+

Timesheet - Begin/End Hours with empty end

+ + +

Beta License: AGPL-3 OCA/timesheet Translate me on Weblate Try me on Runboat

+

Allow to insert begin hour without end hour on the timesheet. The benefit of +doing this is that you can save your begin hour at the start of your day/task, +and come back later to save the end hour.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Coop IT Easy SC
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

carmenbianca

+

This module is part of the OCA/timesheet project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/hr_timesheet_begin_end_no_end/tests/__init__.py b/hr_timesheet_begin_end_no_end/tests/__init__.py new file mode 100644 index 0000000000..eae8ab8978 --- /dev/null +++ b/hr_timesheet_begin_end_no_end/tests/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2024 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +from . import test_timesheet_begin_end_no_end diff --git a/hr_timesheet_begin_end_no_end/tests/test_timesheet_begin_end_no_end.py b/hr_timesheet_begin_end_no_end/tests/test_timesheet_begin_end_no_end.py new file mode 100644 index 0000000000..16e702c45b --- /dev/null +++ b/hr_timesheet_begin_end_no_end/tests/test_timesheet_begin_end_no_end.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2024 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +from odoo import exceptions, fields +from odoo.tests.common import TransactionCase + + +class TestBeginEndNoEnd(TransactionCase): + def setUp(self): + super().setUp() + self.project = self.env.ref("project.project_project_1") + self.employee = self.env.ref("hr.employee_qdp") + + def base_line(self): + return { + "name": "test", + "date": fields.Date.today(), + "time_start": 10.0, + "time_stop": 12.0, + "unit_amount": 2.0, + "project_id": self.project.id, + "employee_id": self.employee.id, + } + + def test_check_end_is_zero(self): + line = self.base_line() + line.update({"time_stop": 0}) + # No error. + self.env["account.analytic.line"].create(line) + + def test_check_end_is_not_zero(self): + line = self.base_line() + line_record = self.env["account.analytic.line"].create(line) + with self.assertRaises(exceptions.ValidationError): + line_record.time_stop = 1 + + def test_check_end_is_not_zero_no_record(self): + line = self.base_line() + line.update({"time_stop": 1, "unit_amount": 0}) + with self.assertRaises(exceptions.ValidationError): + self.env["account.analytic.line"].create(line) + + def test_no_overlap(self): + line_1 = self.base_line() + line_1.update({"time_stop": 0, "unit_amount": 0}) + line_2 = line_1.copy() + line_2.update({"time_start": 11.0, "unit_amount": 1}) + line_3 = self.base_line() + # Able to create all without overlap, because time_stop is 0 for two of + # them, and they don't count, even though their start times are + # overlapped with line_3. + self.env["account.analytic.line"].create([line_1, line_2, line_3]) diff --git a/setup/hr_timesheet_begin_end_no_end/odoo/addons/hr_timesheet_begin_end_no_end b/setup/hr_timesheet_begin_end_no_end/odoo/addons/hr_timesheet_begin_end_no_end new file mode 120000 index 0000000000..3bde95d631 --- /dev/null +++ b/setup/hr_timesheet_begin_end_no_end/odoo/addons/hr_timesheet_begin_end_no_end @@ -0,0 +1 @@ +../../../../hr_timesheet_begin_end_no_end \ No newline at end of file diff --git a/setup/hr_timesheet_begin_end_no_end/setup.py b/setup/hr_timesheet_begin_end_no_end/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/hr_timesheet_begin_end_no_end/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)