Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[12.0][ADD] hr_timesheet_begin_end_no_end #694

Draft
wants to merge 4 commits into
base: 12.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .copier-answers.yml
Original file line number Diff line number Diff line change
@@ -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: {}
Expand All @@ -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: []

11 changes: 10 additions & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
18 changes: 13 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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' }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ __pycache__/
*.py[cod]
/.venv
/.pytest_cache
/.ruff_cache

# C extensions
*.so
Expand Down
2 changes: 2 additions & 0 deletions .oca_hooks.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[MESSAGES_CONTROL]
disable=xml-deprecated-data-node,xml-deprecated-tree-attribute
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

# Odoo Timesheet Management Modules

None
TODO: add repo description.

<!-- /!\ do not modify below this line -->

Expand Down
130 changes: 83 additions & 47 deletions hr_timesheet_activity_begin_end/models/account_analytic_line.py
Original file line number Diff line number Diff line change
@@ -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


Expand All @@ -15,55 +16,90 @@
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()

Check warning on line 21 in hr_timesheet_activity_begin_end/models/account_analytic_line.py

View check run for this annotation

Codecov / codecov/patch

hr_timesheet_activity_begin_end/models/account_analytic_line.py#L21

Added line #L21 was not covered by tests

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(

Check warning on line 43 in hr_timesheet_activity_begin_end/models/account_analytic_line.py

View check run for this annotation

Codecov / codecov/patch

hr_timesheet_activity_begin_end/models/account_analytic_line.py#L43

Added line #L43 was not covered by tests
_(
"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")

Check warning on line 69 in hr_timesheet_activity_begin_end/models/account_analytic_line.py

View check run for this annotation

Codecov / codecov/patch

hr_timesheet_activity_begin_end/models/account_analytic_line.py#L69

Added line #L69 was not covered by tests
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)

Check warning on line 80 in hr_timesheet_activity_begin_end/models/account_analytic_line.py

View check run for this annotation

Codecov / codecov/patch

hr_timesheet_activity_begin_end/models/account_analytic_line.py#L80

Added line #L80 was not covered by tests

@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

Check warning on line 101 in hr_timesheet_activity_begin_end/models/account_analytic_line.py

View check run for this annotation

Codecov / codecov/patch

hr_timesheet_activity_begin_end/models/account_analytic_line.py#L101

Added line #L101 was not covered by tests
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"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed the test to use timesheet lines instead of bare analytic lines.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Refactored the module to be more extensible.
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ 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):
line = self.timesheet_line_model.new({
'name': 'test',
'time_start': 10.,
'time_stop': 12.,
'project_id': self.project.id,
})
line.onchange_hours_start_stop()
self.assertEquals(line.unit_amount, 2)
Expand Down
Loading
Loading