changeset dca2bc7ae397 in modules/project:default
details: https://hg.tryton.org/modules/project?cmd=changeset;node=dca2bc7ae397
description:
Make project status configurable
issue7746
review64411002
diffstat:
CHANGELOG | 2 +
__init__.py | 4 +
doc/index.rst | 26 +++--
exceptions.py | 4 +
ir.py | 15 +++
message.xml | 14 ++-
setup.py | 4 +-
tests/scenario_project_status.rst | 85 +++++++++++++++++
tests/test_project.py | 12 ++-
view/work_form.xml | 8 +-
view/work_list.xml | 2 +-
view/work_list_children.xml | 2 +-
view/work_list_simple.xml | 2 +-
view/work_status_form.xml | 24 +++++
view/work_status_list.xml | 8 +
view/work_tree.xml | 2 +-
view/work_tree_simple.xml | 2 +-
work.py | 180 ++++++++++++++++++++++++++++++++-----
work.xml | 95 +++++++++++--------
19 files changed, 400 insertions(+), 91 deletions(-)
diffs (749 lines):
diff -r 6fb9a7793bdf -r dca2bc7ae397 CHANGELOG
--- a/CHANGELOG Sat Dec 14 10:47:54 2019 +0100
+++ b/CHANGELOG Tue Jan 28 11:45:54 2020 +0100
@@ -1,3 +1,5 @@
+* Make project status configurable
+
Version 5.4.0 - 2019-11-04
* Bug fixes (see mercurial logs for details)
diff -r 6fb9a7793bdf -r dca2bc7ae397 __init__.py
--- a/__init__.py Sat Dec 14 10:47:54 2019 +0100
+++ b/__init__.py Tue Jan 28 11:45:54 2020 +0100
@@ -2,6 +2,7 @@
# this repository contains the full copyright notices and license terms.
from trytond.pool import Pool
+from . import ir
from . import work
from . import timesheet
from . import party
@@ -9,9 +10,12 @@
def register():
Pool.register(
+ # Before Work because status default value is read from WorkStatus
+ work.WorkStatus,
work.Work,
timesheet.Line,
timesheet.Work,
+ ir.ActWindow,
module='project', type_='model')
Pool.register(
party.PartyReplace,
diff -r 6fb9a7793bdf -r dca2bc7ae397 doc/index.rst
--- a/doc/index.rst Sat Dec 14 10:47:54 2019 +0100
+++ b/doc/index.rst Tue Jan 28 11:45:54 2020 +0100
@@ -4,7 +4,6 @@
The Project module provides the concepts of project and task and the
basis for simple project management.
-
Work Effort
***********
@@ -12,19 +11,24 @@
for instance to transform a task into a project if it gets bigger and need to
be split. The following fields are defined on the model:
-
- Name: The name of the Project/Task.
- Type: Can be *Project* or *Task*.
-- State: Can be *Opened* or *Done*.
-- Parent and Children: Define the tree structure of projects and
- tasks.
-- Party and Party Address: The optional party (and the contact
- address) for which the project is made. Available on projects.
-- Timesheet Available: Register the work for timesheets.
+- Status: The current status of the work.
+- Parent and Children: Define the tree structure of projects and tasks.
+- Party and Party Address: The optional party (and the contact address) for
+ which the project is made. Available on projects.
+- Timesheet, start and end: Allow to enter timesheet for this work.
- Effort: The estimated effort of a task.
-- Total Effort: Available on projects. Gives the total effort of the
- sub-tasks (I.E. tasks of the project and tasks of the sub-projects)
- of the current project.
+- Total Effort: Available on projects. Gives the total effort of the sub-tasks
+ (I.E. tasks of the project and tasks of the sub-projects) of the current
+ project.
- Progress: The progression on the task.
- Total Progress: Gives the total of progress of the sub-tasks.
- Comment: A description.
+
+
+Work Status
+***********
+
+The Work Status defines the possible status of projects and tasks. A minimal
+progress can be defined to enforce on works in this status.
diff -r 6fb9a7793bdf -r dca2bc7ae397 exceptions.py
--- a/exceptions.py Sat Dec 14 10:47:54 2019 +0100
+++ b/exceptions.py Tue Jan 28 11:45:54 2020 +0100
@@ -6,3 +6,7 @@
class WorkValidationError(ValidationError):
pass
+
+
+class WorkProgressValidationError(WorkValidationError):
+ pass
diff -r 6fb9a7793bdf -r dca2bc7ae397 ir.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ir.py Tue Jan 28 11:45:54 2020 +0100
@@ -0,0 +1,15 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+from trytond.pool import Pool, PoolMeta
+
+
+class ActWindow(metaclass=PoolMeta):
+ __name__ = 'ir.action.act_window'
+
+ def get_domains(self, name):
+ domains = super().get_domains(name)
+ if self.res_model == 'project.work':
+ pool = Pool()
+ WorkStatus = pool.get('project.work.status')
+ domains = WorkStatus.get_window_domains(self)
+ return domains
diff -r 6fb9a7793bdf -r dca2bc7ae397 message.xml
--- a/message.xml Sat Dec 14 10:47:54 2019 +0100
+++ b/message.xml Tue Jan 28 11:45:54 2020 +0100
@@ -3,14 +3,20 @@
this repository contains the full copyright notices and license terms. -->
<tryton>
<data grouped="1">
- <record model="ir.message" id="msg_work_invalid_parent_state">
- <field name="text">To open work "%(child)s", you must open its
parent "%(parent)s".</field>
+ <record model="ir.message" id="msg_work_invalid_progress_status">
+ <field name="text">To set work "%(work)s" in "%(status)s" status,
you must increase its progress up to at least %(progress)s.</field>
</record>
- <record model="ir.message" id="msg_work_invalid_children_state">
- <field name="text">To close work "%(parent)s", you must close its
child "%(child)s".</field>
+ <record model="ir.message" id="msg_work_children_progress">
+ <field name="text">To complete work "%(work)s" you must complete
also all its children.</field>
+ </record>
+ <record model="ir.message" id="msg_work_parent_progress">
+ <field name="text">To re-open work "%(work)s" you must re-open
also its parent "%(parent)s".</field>
</record>
<record model="ir.message" id="msg_erase_party_opened_project">
<field name="text">You cannot erase party "%(party)s" while they
have opened projects with company "%(company)s".</field>
</record>
+ <record model="ir.message" id="msg_domain_all">
+ <field name="text">All</field>
+ </record>
</data>
</tryton>
diff -r 6fb9a7793bdf -r dca2bc7ae397 setup.py
--- a/setup.py Sat Dec 14 10:47:54 2019 +0100
+++ b/setup.py Tue Jan 28 11:45:54 2020 +0100
@@ -57,6 +57,7 @@
requires.append(get_require_version('trytond_%s' % dep))
requires.append(get_require_version('trytond'))
+tests_require = [get_require_version('proteus')]
dependency_links = []
if minor_version % 2:
dependency_links.append('https://trydevpi.tryton.org/')
@@ -84,7 +85,7 @@
package_data={
'trytond.modules.project': (info.get('xml', [])
+ ['tryton.cfg', 'view/*.xml', 'locale/*.po', 'icons/*.svg',
- '*.fodt']),
+ '*.fodt', 'tests/*.rst']),
},
classifiers=[
'Development Status :: 5 - Production/Stable',
@@ -134,4 +135,5 @@
""",
test_suite='tests',
test_loader='trytond.test_loader:Loader',
+ tests_require=tests_require,
)
diff -r 6fb9a7793bdf -r dca2bc7ae397 tests/scenario_project_status.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/scenario_project_status.rst Tue Jan 28 11:45:54 2020 +0100
@@ -0,0 +1,85 @@
+=======================
+Project Status Scenario
+=======================
+
+Imports::
+
+ >>> from proteus import Model
+ >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.modules.company.tests.tools import create_company
+
+Activate project::
+
+ >>> config = activate_modules('project')
+
+Create a company::
+
+ >>> _ = create_company()
+
+Create status::
+
+ >>> WorkStatus = Model.get('project.work.status')
+ >>> in_progress = WorkStatus(name="In-Progress", types=['project'])
+ >>> in_progress.progress = 0.1
+ >>> in_progress.save()
+ >>> open, = WorkStatus.find([('name', '=', "Open")])
+ >>> done, = WorkStatus.find([('name', '=', "Done")])
+
+Create a project with a task::
+
+ >>> Work = Model.get('project.work')
+
+ >>> project = Work(type='project', name="Project")
+ >>> project.status == open
+ True
+ >>> task = project.children.new(name="Task")
+ >>> task.status == open
+ True
+
+ >>> project.save()
+ >>> task, = project.children
+
+Open the project::
+
+ >>> project.status = in_progress
+ >>> project.progress
+ 0.1
+ >>> project.save()
+
+Try to complete project without task::
+
+ >>> project.status = done
+ >>> project.progress
+ 1.0
+ >>> project.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ WorkProgressValidationError: ...
+
+ >>> task.progress = 1
+ >>> task.save()
+ >>> project.save()
+
+Try to re-open task without project::
+
+ >>> task.progress = 0.5
+ >>> task.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ WorkProgressValidationError: ...
+
+Change progress with updating status::
+
+ >>> project.progress = 0.8
+ >>> project.save() # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ WorkProgressValidationError: ...
+
+ >>> project.status = in_progress
+ >>> project.save()
+
+Re-open task::
+
+ >>> task.progress = 0.5
+ >>> task.save()
diff -r 6fb9a7793bdf -r dca2bc7ae397 tests/test_project.py
--- a/tests/test_project.py Sat Dec 14 10:47:54 2019 +0100
+++ b/tests/test_project.py Tue Jan 28 11:45:54 2020 +0100
@@ -1,11 +1,14 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
+import datetime
+import doctest
import unittest
-import datetime
import trytond.tests.test_tryton
+from trytond.pool import Pool
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
-from trytond.pool import Pool
+from trytond.tests.test_tryton import doctest_checker
+from trytond.tests.test_tryton import doctest_teardown
from trytond.transaction import Transaction
from trytond.modules.company.tests import create_company, set_company
@@ -187,4 +190,9 @@
suite = trytond.tests.test_tryton.suite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
ProjectTestCase))
+ suite.addTests(doctest.DocFileSuite(
+ 'scenario_project_status.rst',
+ tearDown=doctest_teardown, encoding='utf-8',
+ checker=doctest_checker,
+ optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite
diff -r 6fb9a7793bdf -r dca2bc7ae397 view/work_form.xml
--- a/view/work_form.xml Sat Dec 14 10:47:54 2019 +0100
+++ b/view/work_form.xml Tue Jan 28 11:45:54 2020 +0100
@@ -42,10 +42,10 @@
<newline/>
<separator name="comment" colspan="6"/>
<field name="comment" colspan="6"/>
- <group col="4" colspan="6" id="state_buttons">
- <group col="2" colspan="2" id="state">
- <label name="state"/>
- <field name="state"/>
+ <group col="4" colspan="6" id="status_buttons">
+ <group col="2" colspan="2" id="status">
+ <label name="status"/>
+ <field name="status" widget="selection"/>
</group>
<group col="-1" colspan="2" id="buttons">
</group>
diff -r 6fb9a7793bdf -r dca2bc7ae397 view/work_list.xml
--- a/view/work_list.xml Sat Dec 14 10:47:54 2019 +0100
+++ b/view/work_list.xml Tue Jan 28 11:45:54 2020 +0100
@@ -6,6 +6,6 @@
<field name="timesheet_duration"/>
<field name="total_effort"/>
<field name="type"/>
- <field name="state"/>
+ <field name="status"/>
<field name="total_progress" widget="progressbar" expand="1"/>
</tree>
diff -r 6fb9a7793bdf -r dca2bc7ae397 view/work_list_children.xml
--- a/view/work_list_children.xml Sat Dec 14 10:47:54 2019 +0100
+++ b/view/work_list_children.xml Tue Jan 28 11:45:54 2020 +0100
@@ -6,5 +6,5 @@
<field name="timesheet_duration"/>
<field name="total_effort"/>
<field name="type"/>
- <field name="state"/>
+ <field name="status"/>
</tree>
diff -r 6fb9a7793bdf -r dca2bc7ae397 view/work_list_simple.xml
--- a/view/work_list_simple.xml Sat Dec 14 10:47:54 2019 +0100
+++ b/view/work_list_simple.xml Tue Jan 28 11:45:54 2020 +0100
@@ -4,5 +4,5 @@
<tree>
<field name="rec_name" expand="1"/>
<field name="type"/>
- <field name="state"/>
+ <field name="status"/>
</tree>
diff -r 6fb9a7793bdf -r dca2bc7ae397 view/work_status_form.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/view/work_status_form.xml Tue Jan 28 11:45:54 2020 +0100
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
+this repository contains the full copyright notices and license terms. -->
+<form>
+ <label name="name"/>
+ <field name="name"/>
+ <group colspan="2" col="-1" id="checkboxes">
+ <label name="active"/>
+ <field name="active" xexpand="0" width="25"/>
+ <label name="default"/>
+ <field name="default" xexpand="0" width="25"/>
+ <label name="count"/>
+ <field name="count" xexpand="0" width="25"/>
+ <label name="sequence"/>
+ <field name="sequence"/>
+ </group>
+ <label name="types"/>
+ <field name="types" yexpand="0"/>
+ <label name="progress"/>
+ <group col="-1" id="progress">
+ <field name="progress" factor="100" xexpand="0"/>
+ <label name="progress" string="%" xalign="0.0" xexpand="1"/>
+ </group>
+</form>
diff -r 6fb9a7793bdf -r dca2bc7ae397 view/work_status_list.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/view/work_status_list.xml Tue Jan 28 11:45:54 2020 +0100
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
+this repository contains the full copyright notices and license terms. -->
+<tree sequence="sequence">
+ <field name="name"/>
+ <field name="types"/>
+ <field name="default"/>
+</tree>
diff -r 6fb9a7793bdf -r dca2bc7ae397 view/work_tree.xml
--- a/view/work_tree.xml Sat Dec 14 10:47:54 2019 +0100
+++ b/view/work_tree.xml Tue Jan 28 11:45:54 2020 +0100
@@ -6,6 +6,6 @@
<field name="timesheet_duration"/>
<field name="total_effort"/>
<field name="type"/>
- <field name="state"/>
+ <field name="status"/>
<field name="total_progress" widget="progressbar" expand="1"/>
</tree>
diff -r 6fb9a7793bdf -r dca2bc7ae397 view/work_tree_simple.xml
--- a/view/work_tree_simple.xml Sat Dec 14 10:47:54 2019 +0100
+++ b/view/work_tree_simple.xml Tue Jan 28 11:45:54 2020 +0100
@@ -4,5 +4,5 @@
<tree sequence="sequence">
<field name="name" expand="1"/>
<field name="type"/>
- <field name="state"/>
+ <field name="status"/>
</tree>
diff -r 6fb9a7793bdf -r dca2bc7ae397 work.py
--- a/work.py Sat Dec 14 10:47:54 2019 +0100
+++ b/work.py Tue Jan 28 11:45:54 2020 +0100
@@ -5,16 +5,115 @@
from sql import Null
+from trytond.cache import Cache
from trytond.i18n import gettext
-from trytond.model import ModelView, ModelSQL, fields, sequence_ordered, tree
-from trytond.pyson import Eval
+from trytond.model import (
+ ModelView, ModelSQL, fields, sequence_ordered, tree, DeactivableMixin)
from trytond.transaction import Transaction
from trytond.pool import Pool
+from trytond.pyson import Eval, PYSONEncoder
from trytond.tools import reduce_ids, grouped_slice
-from .exceptions import WorkValidationError
+from .exceptions import WorkProgressValidationError
+
+
+class WorkStatus(DeactivableMixin, sequence_ordered(), ModelSQL, ModelView):
+ 'Work Status'
+ __name__ = 'project.work.status'
+
+ _get_default_status_cache = Cache('project_work_status.get_default_status')
+ _get_window_domains_cache = Cache('project_work_status.get_window_domains')
+
+ types = fields.MultiSelection(
+ 'get_types', "Types",
+ help="The type of works which can use this status.")
+ name = fields.Char("Name", required=True, translate=True)
+ progress = fields.Float(
+ "Progress",
+ domain=['OR',
+ ('progress', '=', None),
+ [
+ ('progress', '>=', 0),
+ ('progress', '<=', 1),
+ ],
+ ],
+ help="The minimum progress required for this status.")
+ default = fields.Boolean(
+ "Default",
+ help="Check to use as default status for the type.")
+ count = fields.Boolean(
+ "Count",
+ help="Check to show the number of works in this status.")
+
+ @classmethod
+ def get_types(cls):
+ pool = Pool()
+ Work = pool.get('project.work')
+ return Work.fields_get(['type'])['type']['selection']
-__all__ = ['Work']
+ @classmethod
+ def get_default_status(cls, type_=None):
+ if type_ is None:
+ return None
+ status = cls._get_default_status_cache.get(type_, -1)
+ if status != -1:
+ return status
+ records = cls.search([
+ ('types', 'in', type_),
+ ('default', '=', True)
+ ], limit=1)
+ if records:
+ status = records[0].id
+ else:
+ status = None
+ cls._get_default_status_cache.set(type, status)
+ return status
+
+ @classmethod
+ def create(cls, vlist):
+ cls._get_default_status_cache.clear()
+ cls._get_window_domains_cache.clear()
+ return super().create(vlist)
+
+ @classmethod
+ def write(cls, *args):
+ super().write(*args)
+ cls._get_default_status_cache.clear()
+ cls._get_window_domains_cache.clear()
+
+ @classmethod
+ def delete(cls, status):
+ cls._get_default_status_cache.clear()
+ cls._get_window_domains_cache.clear()
+ super().delete(status)
+
+ @classmethod
+ def get_window_domains(cls, action):
+ pool = Pool()
+ Data = pool.get('ir.model.data')
+ if action.id == Data.get_id('project', 'act_project_tree'):
+ return cls._get_window_domains([x[0] for x in cls.get_types()])
+ elif action.id == Data.get_id('project', 'act_project_form'):
+ return cls._get_window_domains(['project'])
+ elif action.id == Data.get_id('project', 'act_task_form'):
+ return cls._get_window_domains(['task'])
+
+ @classmethod
+ def _get_window_domains(cls, types):
+ key = tuple(sorted(types))
+ domains = cls._get_window_domains_cache.get(key)
+ if domains is not None:
+ return domains
+ encoder = PYSONEncoder()
+ domains = []
+ for status in cls.search([('types', 'in', types)]):
+ domain = encoder.encode([('status', '=', status.id)])
+ domains.append((status.name, domain, status.count))
+ if domains:
+ domains.append(
+ (gettext('project.msg_domain_all'), '[]', False))
+ cls._get_window_domains_cache.set(key, domains)
+ return domains
class Work(sequence_ordered(), tree(separator='\\'), ModelSQL, ModelView):
@@ -94,10 +193,9 @@
('company', '=', Eval('company', -1)),
],
depends=['company'])
- state = fields.Selection([
- ('opened', 'Opened'),
- ('done', 'Done'),
- ], 'State', required=True, select=True)
+ status = fields.Many2One(
+ 'project.work.status', "Status", required=True, select=True,
+ domain=[('types', 'in', Eval('type'))], depends=['type'])
@staticmethod
def default_type():
@@ -107,9 +205,11 @@
def default_company(cls):
return Transaction().context.get('company')
- @staticmethod
- def default_state():
- return 'opened'
+ @classmethod
+ def default_status(cls):
+ pool = Pool()
+ WorkStatus = pool.get('project.work.status')
+ return WorkStatus.get_default_status(cls.default_type())
@classmethod
def default_left(cls):
@@ -198,6 +298,25 @@
where=timesheet.id == work_id))
table_project_work.drop_column('work')
+ # Migration from 5.4: replace state by status
+ table_project_work.not_null_action('state', action='remove')
+
+ @fields.depends('type', 'status')
+ def on_change_type(self):
+ pool = Pool()
+ WorkState = pool.get('project.work.status')
+ if (self.type
+ and (not self.status
+ or self.type not in self.status.types)):
+ self.status = WorkState.get_default_status(self.type)
+
+ @fields.depends('status', 'progress')
+ def on_change_status(self):
+ if (self.status
+ and self.status.progress is not None
+ and self.status.progress > (self.progress or -1.0)):
+ self.progress = self.status.progress
+
@classmethod
def index_set_field(cls, name):
index = super(Work, cls).index_set_field(name)
@@ -209,22 +328,33 @@
def validate(cls, works):
super(Work, cls).validate(works)
for work in works:
- work.check_state()
+ work.check_work_progress()
- def check_state(self):
- if (self.state == 'opened'
- and (self.parent and self.parent.state == 'done')):
- raise WorkValidationError(
- gettext('project.msg_work_invalid_parent_state',
- child=self.rec_name,
+ def check_work_progress(self):
+ pool = Pool()
+ progress = -1 if self.progress is None else self.progress
+ if (self.status.progress is not None
+ and progress < self.status.progress):
+ Lang = pool.get('ir.lang')
+ lang = Lang.get()
+ raise WorkProgressValidationError(
+ gettext('project.msg_work_invalid_progress_status',
+ work=self.rec_name,
+ progress=lang.format('%.2f%%', self.status.progress * 100),
+ status=self.status.rec_name))
+ if (self.status.progress == 1.0
+ and not all(c.progress == 1.0 for c in self.children)):
+ raise WorkProgressValidationError(
+ gettext('project.msg_work_children_progress',
+ work=self.rec_name,
+ status=self.status.rec_name))
+ if (self.parent
+ and self.parent.progress == 1.0
+ and not self.progress == 1.0):
+ raise WorkProgressValidationError(
+ gettext('project.msg_work_parent_progress',
+ work=self.rec_name,
parent=self.parent.rec_name))
- if self.state == 'done':
- for child in self.children:
- if child.state == 'opened':
- raise WorkValidationError(
- gettext('project.msg_work_invalid_children_state',
- parent=self.rec_name,
- child=child.rec_name))
@property
def effort_hours(self):
diff -r 6fb9a7793bdf -r dca2bc7ae397 work.xml
--- a/work.xml Sat Dec 14 10:47:54 2019 +0100
+++ b/work.xml Tue Jan 28 11:45:54 2020 +0100
@@ -3,6 +3,49 @@
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
+ <record model="ir.ui.view" id="work_status_view_list">
+ <field name="model">project.work.status</field>
+ <field name="type">tree</field>
+ <field name="name">work_status_list</field>
+ </record>
+ <record model="ir.ui.view" id="work_status_view_form">
+ <field name="model">project.work.status</field>
+ <field name="type">form</field>
+ <field name="name">work_status_form</field>
+ </record>
+ <record model="ir.action.act_window" id="act_work_status">
+ <field name="name">Work Status</field>
+ <field name="res_model">project.work.status</field>
+ </record>
+ <record model="ir.action.act_window.view" id="act_work_status_view1">
+ <field name="sequence" eval="10"/>
+ <field name="view" ref="work_status_view_list"/>
+ <field name="act_window" ref="act_work_status"/>
+ </record>
+ <record model="ir.action.act_window.view" id="act_work_status_view2">
+ <field name="sequence" eval="20"/>
+ <field name="view" ref="work_status_view_form"/>
+ <field name="act_window" ref="act_work_status"/>
+ </record>
+ <menuitem parent="menu_configuration" sequence="20"
+ action="act_work_status" id="menu_work_status"/>
+
+ <record model="ir.model.access" id="access_work_status">
+ <field name="model" search="[('model', '=',
'project.work.status')]"/>
+ <field name="perm_read" eval="True"/>
+ <field name="perm_write" eval="False"/>
+ <field name="perm_create" eval="False"/>
+ <field name="perm_delete" eval="False"/>
+ </record>
+ <record model="ir.model.access" id="access_work_status_admin">
+ <field name="model" search="[('model', '=',
'project.work.status')]"/>
+ <field name="group" ref="group_project_admin"/>
+ <field name="perm_read" eval="True"/>
+ <field name="perm_write" eval="True"/>
+ <field name="perm_create" eval="True"/>
+ <field name="perm_delete" eval="True"/>
+ </record>
+
<record model="ir.ui.view" id="work_view_tree">
<field name="model">project.work</field>
<field name="type">tree</field>
@@ -98,19 +141,6 @@
<field name="view" ref="work_view_form"/>
<field name="act_window" ref="act_project_tree"/>
</record>
- <record model="ir.action.act_window.domain"
id="act_project_tree_opened">
- <field name="name">Opened</field>
- <field name="sequence" eval="10"/>
- <field name="domain" eval="[('state', '=', 'opened')]" pyson="1"/>
- <field name="count" eval="True"/>
- <field name="act_window" ref="act_project_tree"/>
- </record>
- <record model="ir.action.act_window.domain" id="act_project_tree_done">
- <field name="name">Done</field>
- <field name="sequence" eval="20"/>
- <field name="domain" eval="[('state', '=', 'done')]" pyson="1"/>
- <field name="act_window" ref="act_project_tree"/>
- </record>
<menuitem parent="menu_project" action="act_project_tree"
id="menu_project_tree" sequence="20"/>
@@ -132,19 +162,6 @@
<field name="view" ref="work_view_form"/>
<field name="act_window" ref="act_project_form"/>
</record>
- <record model="ir.action.act_window.domain"
id="act_project_form_opened">
- <field name="name">Opened</field>
- <field name="sequence" eval="10"/>
- <field name="domain" eval="[('state', '=', 'opened')]" pyson="1"/>
- <field name="count" eval="True"/>
- <field name="act_window" ref="act_project_form"/>
- </record>
- <record model="ir.action.act_window.domain" id="act_project_form_done">
- <field name="name">Done</field>
- <field name="sequence" eval="20"/>
- <field name="domain" eval="[('state', '=', 'done')]" pyson="1"/>
- <field name="act_window" ref="act_project_form"/>
- </record>
<menuitem parent="menu_project_tree" action="act_project_form"
id="menu_project_form"/>
@@ -166,19 +183,6 @@
<field name="view" ref="work_view_form"/>
<field name="act_window" ref="act_task_form"/>
</record>
- <record model="ir.action.act_window.domain" id="act_task_form_opened">
- <field name="name">Opened</field>
- <field name="sequence" eval="10"/>
- <field name="domain" eval="[('state', '=', 'opened')]" pyson="1"/>
- <field name="count" eval="True"/>
- <field name="act_window" ref="act_task_form"/>
- </record>
- <record model="ir.action.act_window.domain" id="act_task_form_done">
- <field name="name">Done</field>
- <field name="sequence" eval="20"/>
- <field name="domain" eval="[('state', '=', 'done')]" pyson="1"/>
- <field name="act_window" ref="act_task_form"/>
- </record>
<menuitem parent="menu_project_tree" action="act_task_form"
id="menu_task_form"/>
@@ -226,4 +230,17 @@
</record>
</data>
+ <data noupdate="1">
+ <record model="project.work.status" id="work_open_status">
+ <field name="name">Open</field>
+ <field name="default" eval="True"/>
+ <field name="count" eval="True"/>
+ <field name="types" eval="['project', 'task']"/>
+ </record>
+ <record model="project.work.status" id="work_done_status">
+ <field name="name">Done</field>
+ <field name="progress" eval="1.0"/>
+ <field name="types" eval="['project', 'task']"/>
+ </record>
+ </data>
</tryton>