Skip to content
Extraits de code Groupes Projets
Valider 4d9f997e rédigé par Rémi - Le Filament's avatar Rémi - Le Filament
Parcourir les fichiers

[FIX] use planned_date and add department & project on planned_hours

parent b5ce27eb
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -22,6 +22,7 @@ globals: ...@@ -22,6 +22,7 @@ globals:
odoo: readonly odoo: readonly
openerp: readonly openerp: readonly
owl: readonly owl: readonly
luxon: readonly
# Styling is handled by Prettier, so we only need to enable AST rules; # Styling is handled by Prettier, so we only need to enable AST rules;
# see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890 # see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890
......
[flake8]
max-line-length = 88
max-complexity = 16
# B = bugbear
# B9 = bugbear opinionated (incl line length)
select = C,E,F,W,B,B9
# E203: whitespace before ':' (black behaviour)
# E501: flake8 line length (covered by bugbear B950)
# W503: line break before binary operator (black behaviour)
ignore = E203,E501,W503
per-file-ignores=
__init__.py:F401
...@@ -3,6 +3,7 @@ __pycache__/ ...@@ -3,6 +3,7 @@ __pycache__/
*.py[cod] *.py[cod]
/.venv /.venv
/.pytest_cache /.pytest_cache
/.ruff_cache
# C extensions # C extensions
*.so *.so
...@@ -15,7 +16,6 @@ build/ ...@@ -15,7 +16,6 @@ build/
develop-eggs/ develop-eggs/
dist/ dist/
eggs/ eggs/
lib/
lib64/ lib64/
parts/ parts/
sdist/ sdist/
...@@ -24,6 +24,7 @@ var/ ...@@ -24,6 +24,7 @@ var/
.installed.cfg .installed.cfg
*.egg *.egg
*.eggs *.eggs
.copier-answers.yml
# Installer logs # Installer logs
pip-log.txt pip-log.txt
......
[settings]
; see https://github.com/psf/black
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
combine_as_imports=True
use_parentheses=True
line_length=88
known_odoo=odoo
known_odoo_addons=odoo.addons
sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER
default_section=THIRDPARTY
ensure_newline_before_comments = True
...@@ -6,10 +6,16 @@ exclude: | ...@@ -6,10 +6,16 @@ exclude: |
^setup/|/static/description/index\.html$| ^setup/|/static/description/index\.html$|
# We don't want to mess with tool-generated files # We don't want to mess with tool-generated files
.svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/| .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/|
# Maybe reactivate this when all README files include prettier ignore tags?
^README\.md$|
# Library files can have extraneous formatting (even minimized) # Library files can have extraneous formatting (even minimized)
/static/(src/)?lib/| /static/(src/)?lib/|
# Repos using Sphinx to generate docs don't need prettying # Repos using Sphinx to generate docs don't need prettying
^docs/_templates/.*\.html$| ^docs/_templates/.*\.html$|
# Don't bother non-technical authors with formatting issues in docs
readme/.*\.(rst|md)$|
# Ignore build and dist directories in addons
/build/|/dist/|
# You don't usually want a bot to modify your legal texts # You don't usually want a bot to modify your legal texts
(LICENSE.*|COPYING.*) (LICENSE.*|COPYING.*)
default_language_version: default_language_version:
...@@ -25,30 +31,34 @@ repos: ...@@ -25,30 +31,34 @@ repos:
entry: found forbidden files; remove them entry: found forbidden files; remove them
language: fail language: fail
files: "\\.rej$" files: "\\.rej$"
- id: en-po-files
name: en.po files cannot exist
entry: found a en.po file
language: fail
files: '[a-zA-Z0-9_]*/i18n/en\.po$'
- repo: https://github.com/oca/maintainer-tools - repo: https://github.com/oca/maintainer-tools
rev: 7d8a9f9ad73db0976fb03cbee43d953bc29b89e9 rev: 9a170331575a265c092ee6b24b845ec508e8ef75
hooks: hooks:
# update the NOT INSTALLABLE ADDONS section above # update the NOT INSTALLABLE ADDONS section above
- id: oca-update-pre-commit-excluded-addons - id: oca-update-pre-commit-excluded-addons
- id: oca-fix-manifest-website - id: oca-fix-manifest-website
args: ["https://le-filament.com"] args: ["https://le-filament.com"]
- repo: https://github.com/myint/autoflake - id: oca-gen-addon-readme
rev: v1.4
hooks:
- id: autoflake
args: args:
- --expand-star-imports - --addons-dir=.
- --ignore-init-module-imports - --branch=14.0
- --in-place - --org-name=lefilament
- --remove-all-unused-imports - --repo-name=template_module
- --remove-duplicate-keys - --if-source-changed
- --remove-unused-variables - --keep-source-digest
- repo: https://github.com/psf/black - --convert-fragments-to-markdown
rev: 22.3.0 - repo: https://github.com/OCA/odoo-pre-commit-hooks
rev: v0.0.25
hooks: hooks:
- id: black - id: oca-checks-odoo-module
- id: oca-checks-po
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.6.2 rev: v2.1.2
hooks: hooks:
- id: prettier - id: prettier
name: prettier (with plugin-xml) name: prettier (with plugin-xml)
...@@ -59,7 +69,7 @@ repos: ...@@ -59,7 +69,7 @@ repos:
- --plugin=@prettier/plugin-xml - --plugin=@prettier/plugin-xml
files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$
- repo: https://github.com/pre-commit/mirrors-eslint - repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.15.0 rev: v7.8.1
hooks: hooks:
- id: eslint - id: eslint
verbose: true verbose: true
...@@ -67,7 +77,7 @@ repos: ...@@ -67,7 +77,7 @@ repos:
- --color - --color
- --fix - --fix
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0 rev: v3.2.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
# exclude autogenerated files # exclude autogenerated files
...@@ -89,37 +99,25 @@ repos: ...@@ -89,37 +99,25 @@ repos:
- id: mixed-line-ending - id: mixed-line-ending
args: ["--fix=lf"] args: ["--fix=lf"]
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.32.1 rev: v2.7.2
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: ["--keep-percent-format"] args: ["--keep-percent-format"]
- repo: https://github.com/PyCQA/isort - repo: https://github.com/astral-sh/ruff-pre-commit
rev: 5.10.1 rev: v0.1.3
hooks:
- id: isort
name: isort except __init__.py
args:
- --settings=.
exclude: /__init__\.py$
- repo: https://gitlab.com/PyCQA/flake8
rev: 3.9.2
hooks: hooks:
- id: flake8 - id: ruff
name: flake8 args: [--fix, --exit-non-zero-on-fix]
additional_dependencies: ["flake8-bugbear==20.1.4"] - id: ruff-format
- repo: https://github.com/PyCQA/pylint - repo: https://github.com/OCA/pylint-odoo
rev: v2.11.1 rev: 7.0.2
hooks: hooks:
- id: pylint - id: pylint_odoo
name: pylint with optional checks name: pylint with optional checks
args: args:
- --rcfile=.pylintrc - --rcfile=.pylintrc
- --exit-zero - --exit-zero
verbose: true verbose: true
additional_dependencies: &pylint_deps - id: pylint_odoo
- pylint-odoo==5.0.5
- id: pylint
name: pylint with mandatory checks
args: args:
- --rcfile=.pylintrc-mandatory - --rcfile=.pylintrc-mandatory
additional_dependencies: *pylint_deps
[MASTER] [MASTER]
load-plugins=pylint_odoo load-plugins=pylint_odoo
score=n score=n
...@@ -73,6 +75,7 @@ enable=anomalous-backslash-in-string, ...@@ -73,6 +75,7 @@ enable=anomalous-backslash-in-string,
invalid-commit, invalid-commit,
missing-manifest-dependency, missing-manifest-dependency,
missing-newline-extrafiles, missing-newline-extrafiles,
missing-readme,
no-utf8-coding-comment, no-utf8-coding-comment,
odoo-addons-relative-import, odoo-addons-relative-import,
old-api7-method-defined, old-api7-method-defined,
......
[MASTER] [MASTER]
load-plugins=pylint_odoo load-plugins=pylint_odoo
score=n score=n
......
fix = true
[lint]
extend-select = [
"B",
"C90",
"E501", # line too long (default 88)
"I", # isort
]
exclude = ["setup/*"]
[format]
exclude = ["setup/*"]
[per-file-ignores]
"__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py
"__manifest__.py" = ["B018"] # useless expression
[isort]
section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"]
[isort.sections]
"odoo" = ["odoo"]
"odoo-addons" = ["odoo.addons"]
[mccabe]
max-complexity = 16
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"project_timeline", "project_timeline",
"sale_timesheet", "sale_timesheet",
"ecozimut_mixin", "ecozimut_mixin",
"lefilament_link_sale_project",
], ],
"data": [ "data": [
"security/ir.model.access.csv", "security/ir.model.access.csv",
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<field name="code"> <field name="code">
env["project.task.planned.hour"].search([]).unlink() env["project.task.planned.hour"].search([]).unlink()
env.cr.execute("ALTER SEQUENCE project_task_planned_hour_id_seq RESTART WITH 1") env.cr.execute("ALTER SEQUENCE project_task_planned_hour_id_seq RESTART WITH 1")
model.search([("user_id", "!=", False), ("date_end", "!=", False), ("estimated_remaining_hours", ">", 0.0)])._compute_planned_hour_ids() model.search([("user_id", "!=", False), ("planned_date_end", "!=", False), ("estimated_remaining_hours", ">", 0.0)])._compute_planned_hour_ids()
</field> </field>
<field name="state">code</field> <field name="state">code</field>
<field name="priority" eval="5" /> <field name="priority" eval="5" />
......
...@@ -9,7 +9,7 @@ def _update_tasks_date_end(env): ...@@ -9,7 +9,7 @@ def _update_tasks_date_end(env):
.with_context(active_test=False) .with_context(active_test=False)
.search([("date_deadline", "!=", False)]) .search([("date_deadline", "!=", False)])
): ):
task.date_end = task.date_deadline task.planned_date_end = task.date_deadline
def migrate(cr, version): def migrate(cr, version):
......
from . import account_analytic_line from . import account_analytic_line
from . import account_move from . import account_move
from . import project from . import project
from . import project_overview
from . import project_task_planned_hour from . import project_task_planned_hour
from . import project_task from . import project_task
from . import sale_order_line
# Copyright 2021 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class Project(models.Model):
_inherit = "project.project"
def _get_late_tasks_domain(self):
return [
("project_id", "in", self.ids),
("date_deadline", "<", fields.Date.to_string(fields.Date.today())),
("planned_date_end", "=", False),
]
...@@ -69,11 +69,13 @@ class ProjectTask(models.Model): ...@@ -69,11 +69,13 @@ class ProjectTask(models.Model):
else: else:
task.estimated_remaining_hours = task.manual_remaining_hours task.estimated_remaining_hours = task.manual_remaining_hours
@api.depends("user_id", "date_start", "date_end", "estimated_remaining_hours") @api.depends(
"user_id", "planned_date_start", "planned_date_end", "estimated_remaining_hours"
)
def _compute_planned_hour_ids(self): def _compute_planned_hour_ids(self):
""" """
Les heures planifiées par mois sont calculées à partir des heures restantes estimées Les heures planifiées par mois sont calculées à partir des heures restantes
entre la date du jour et la date de fin, estimées entre la date du jour et la date de fin,
au prorata du nombre de jours dans chaque mois au prorata du nombre de jours dans chaque mois
""" """
date_today = fields.Date.today() date_today = fields.Date.today()
...@@ -81,16 +83,19 @@ class ProjectTask(models.Model): ...@@ -81,16 +83,19 @@ class ProjectTask(models.Model):
task.planned_hour_ids.unlink() task.planned_hour_ids.unlink()
if ( if (
task.user_id task.user_id
and task.date_end and task.planned_date_end
and task.date_end.date() >= date_today and task.planned_date_end.date() >= date_today
and task.estimated_remaining_hours and task.estimated_remaining_hours
and task.estimated_remaining_hours > 0.0 and task.estimated_remaining_hours > 0.0
): ):
if task.date_start and task.date_start.date() > date_today: if (
date_start = task.date_start.date() task.planned_date_start
and task.planned_date_start.date() > date_today
):
date_start = task.planned_date_start.date()
else: else:
date_start = date_today date_start = date_today
date_end = task.date_end.date() date_end = task.planned_date_end.date()
planned_hours_values = [] planned_hours_values = []
# Nombre de jours total entre les 2 dates (intervalle) # Nombre de jours total entre les 2 dates (intervalle)
total_days = (date_end - date_start).days + 1 total_days = (date_end - date_start).days + 1
...@@ -127,7 +132,8 @@ class ProjectTask(models.Model): ...@@ -127,7 +132,8 @@ class ProjectTask(models.Model):
* ((date_end - month_date).days + 1) * ((date_end - month_date).days + 1)
/ total_days / total_days
) )
# Pour tous les mois intermédiaires, on calcule sur la totalité du mois # Pour tous les mois intermédiaires, on calcule sur la totalité
# du mois
else: else:
planned_hours = ( planned_hours = (
task.estimated_remaining_hours task.estimated_remaining_hours
......
...@@ -15,10 +15,14 @@ class ProjectTaskPlannedHour(models.Model): ...@@ -15,10 +15,14 @@ class ProjectTaskPlannedHour(models.Model):
ondelete="cascade", ondelete="cascade",
required=1, required=1,
) )
project_id = fields.Many2one(related="task_id.project_id", store=True)
user_id = fields.Many2one( user_id = fields.Many2one(
comodel_name="res.users", comodel_name="res.users",
string="Assigné à", string="Assigné à",
required=1, required=1,
) )
department_id = fields.Many2one(
related="user_id.employee_id.department_id", store=True
)
planned_hours = fields.Float(string="Heures planifiées") planned_hours = fields.Float(string="Heures planifiées")
date_month = fields.Date("Mois") date_month = fields.Date("Mois")
# © 2018- Le Filament (https://le-filament.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
# ------------------------------------------------------
# Override parent
# ------------------------------------------------------
def _timesheet_create_task_prepare_values(self, project):
values = super()._timesheet_create_task_prepare_values(project)
values["planned_date_end"] = self.estimated_date_invoice
values["date_deadline"] = self.estimated_date_invoice
return values
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<filter <filter
string="A renseigner" string="A renseigner"
name="to_fill" name="to_fill"
domain="['|', '|', '|', ('user_id', '=', []), ('date_start', '=', False), ('date_end', '=', False), ('planned_hours', '=', 0.0)]" domain="['|', '|', '|', ('user_id', '=', []), ('planned_date_start', '=', False), ('planned_date_end', '=', False), ('planned_hours', '=', 0.0)]"
/> />
<separator /> <separator />
</xpath> </xpath>
...@@ -30,8 +30,8 @@ ...@@ -30,8 +30,8 @@
<attribute name="groups">base.group_no_one</attribute> <attribute name="groups">base.group_no_one</attribute>
</field> </field>
<field name="date_deadline" position="after"> <field name="date_deadline" position="after">
<field name="date_start" widget="date" /> <field name="planned_date_start" widget="date" />
<field name="date_end" widget="date" /> <field name="planned_date_end" widget="date" />
</field> </field>
<xpath expr="//field[@name='planned_hours']" position="after"> <xpath expr="//field[@name='planned_hours']" position="after">
...@@ -134,8 +134,12 @@ ...@@ -134,8 +134,12 @@
optional="hide" optional="hide"
attrs="{'invisible': [('is_closed', '=', True)]}" attrs="{'invisible': [('is_closed', '=', True)]}"
/> />
<field name="date_start" optional="show" widget="date" /> <field
<field name="date_end" optional="show" widget="date" /> name="planned_date_start"
optional="show"
widget="date"
/>
<field name="planned_date_end" optional="show" widget="date" />
<field <field
name="tag_ids" name="tag_ids"
widget="many2many_tags" widget="many2many_tags"
...@@ -186,15 +190,15 @@ ...@@ -186,15 +190,15 @@
<xpath expr="//calendar" position="attributes"> <xpath expr="//calendar" position="attributes">
<attribute name="mode" /> <attribute name="mode" />
<attribute name="js_class" /> <attribute name="js_class" />
<attribute name="date_start">date_start</attribute> <attribute name="date_start">planned_date_start</attribute>
<attribute name="date_stop">date_end</attribute> <attribute name="date_stop">planned_date_end</attribute>
</xpath> </xpath>
<field name="date_deadline" position="attributes"> <field name="date_deadline" position="attributes">
<attribute name="groups">base.group_no_one</attribute> <attribute name="groups">base.group_no_one</attribute>
</field> </field>
<field name="date_deadline" position="after"> <field name="date_deadline" position="after">
<field name="date_start" widget="date" /> <field name="planned_date_start" widget="date" />
<field name="date_end" widget="date" /> <field name="planned_date_end" widget="date" />
</field> </field>
</field> </field>
</record> </record>
...@@ -210,7 +214,7 @@ ...@@ -210,7 +214,7 @@
<attribute name="groups">base.group_no_one</attribute> <attribute name="groups">base.group_no_one</attribute>
</field> </field>
<field name="date_deadline" position="after"> <field name="date_deadline" position="after">
<field name="date_end" widget="remaining_days" /> <field name="planned_date_end" widget="remaining_days" />
</field> </field>
</field> </field>
</record> </record>
......
...@@ -13,7 +13,9 @@ ...@@ -13,7 +13,9 @@
<group> <group>
<group> <group>
<field name="user_id" /> <field name="user_id" />
<field name="department_id" />
<field name="task_id" /> <field name="task_id" />
<field name="project_id" />
</group> </group>
<group> <group>
<field name="date_month" /> <field name="date_month" />
...@@ -32,7 +34,9 @@ ...@@ -32,7 +34,9 @@
<tree string="Heures planifiées" create="0" edit="0" delete="0"> <tree string="Heures planifiées" create="0" edit="0" delete="0">
<field name="date_month" /> <field name="date_month" />
<field name="user_id" /> <field name="user_id" />
<field name="department_id" />
<field name="task_id" /> <field name="task_id" />
<field name="project_id" />
<field name="planned_hours" widget="float_time" /> <field name="planned_hours" widget="float_time" />
</tree> </tree>
</field> </field>
...@@ -88,6 +92,30 @@ ...@@ -88,6 +92,30 @@
domain="[]" domain="[]"
context="{'group_by':'date_month'}" context="{'group_by':'date_month'}"
/> />
<filter
string="Utilisateur"
name="group_user"
domain="[]"
context="{'group_by':'user_id'}"
/>
<filter
string="Département"
name="group_department"
domain="[]"
context="{'group_by':'department_id'}"
/>
<filter
string="Tâche"
name="group_task"
domain="[]"
context="{'group_by':'task_id'}"
/>
<filter
string="Projet"
name="group_project"
domain="[]"
context="{'group_by':'project_id'}"
/>
</group> </group>
</search> </search>
</field> </field>
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter