From bb7d5e02944f9fb34b37dbeb359cafaa39106ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Alan=20Ramos=20Rodri=CC=81guez?= Date: Wed, 29 Sep 2021 09:12:40 -0500 Subject: [PATCH] [IMP] project_scrum: black, isort, prettier --- project_scrum/__manifest__.py | 62 +++--- .../data/project_scrum_test_task_view.xml | 8 +- project_scrum/data/sequences_projects.xml | 3 +- project_scrum/demo/project_scrum_demo.xml | 185 ++++++++++-------- project_scrum/models/project_project.py | 21 +- project_scrum/models/project_scrum_actors.py | 6 +- project_scrum/models/project_scrum_meeting.py | 77 ++++---- project_scrum/models/project_scrum_sprint.py | 113 ++++++----- project_scrum/models/project_scrum_test.py | 58 +++--- project_scrum/models/project_scrum_us.py | 120 ++++++------ project_scrum/models/project_task.py | 144 +++++++------- project_scrum/readme/USAGE.rst | 4 +- project_scrum/security/project_security.xml | 6 +- project_scrum/security/res_groups.xml | 4 +- project_scrum/tests/test_project_scrum.py | 179 +++++++++-------- project_scrum/views/mail_template.xml | 23 +-- project_scrum/views/menu.xml | 38 ++-- project_scrum/views/project_project.xml | 112 +++++++---- project_scrum/views/project_scrum_meeting.xml | 93 ++++++--- project_scrum/views/project_scrum_sprint.xml | 123 ++++++++---- project_scrum/views/project_scrum_test.xml | 87 +++++--- project_scrum/views/project_scrum_us.xml | 101 ++++++---- project_scrum/views/project_task.xml | 47 +++-- setup/project_scrum/odoo/addons/project_scrum | 1 + setup/project_scrum/setup.py | 6 + 25 files changed, 932 insertions(+), 689 deletions(-) create mode 120000 setup/project_scrum/odoo/addons/project_scrum create mode 100644 setup/project_scrum/setup.py diff --git a/project_scrum/__manifest__.py b/project_scrum/__manifest__.py index 57436d8..23973c8 100644 --- a/project_scrum/__manifest__.py +++ b/project_scrum/__manifest__.py @@ -1,37 +1,37 @@ # Copyright <2017> # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { - 'name': 'Project Scrum', - 'summary': 'Use Scrum Method to manage your project', - 'version': '12.0.1.0.0', - 'category': 'Project Management', - 'author': "Odoo Community Association (OCA)", - 'website': 'https://github.com/OCA/project-agile', - 'depends': [ - 'base_setup', - 'project', - 'project_task_code', - 'project_stage_state', - 'mail', - 'hr_timesheet', + "name": "Project Scrum", + "summary": "Use Scrum Method to manage your project", + "version": "12.0.1.0.0", + "category": "Project Management", + "author": "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/project-agile", + "depends": [ + "base_setup", + "project", + "project_task_code", + "project_stage_state", + "mail", + "hr_timesheet", ], - 'data': [ - 'views/mail_template.xml', - 'views/project_scrum_us.xml', - 'views/project_scrum_meeting.xml', - 'views/project_task.xml', - 'views/project_scrum_sprint.xml', - 'views/project_scrum_test.xml', - 'views/project_project.xml', - 'views/menu.xml', - 'data/sequences_projects.xml', - 'data/project_scrum_test_task_view.xml', - 'security/ir.model.access.csv', - 'security/project_security.xml', - 'security/res_groups.xml', + "data": [ + "views/mail_template.xml", + "views/project_scrum_us.xml", + "views/project_scrum_meeting.xml", + "views/project_task.xml", + "views/project_scrum_sprint.xml", + "views/project_scrum_test.xml", + "views/project_project.xml", + "views/menu.xml", + "data/sequences_projects.xml", + "data/project_scrum_test_task_view.xml", + "security/ir.model.access.csv", + "security/project_security.xml", + "security/res_groups.xml", ], - 'demo': ['demo/project_scrum_demo.xml'], - 'installable': True, - 'license': 'AGPL-3', - 'application': True, + "demo": ["demo/project_scrum_demo.xml"], + "installable": True, + "license": "AGPL-3", + "application": True, } diff --git a/project_scrum/data/project_scrum_test_task_view.xml b/project_scrum/data/project_scrum_test_task_view.xml index c115939..f625a0d 100644 --- a/project_scrum/data/project_scrum_test_task_view.xml +++ b/project_scrum/data/project_scrum_test_task_view.xml @@ -1,13 +1,13 @@ - + - + Create Tasks from Test Cases - + code ir.actions.server self.test_task(cr, uid, object, pool) - + diff --git a/project_scrum/data/sequences_projects.xml b/project_scrum/data/sequences_projects.xml index 563c070..c323eb6 100644 --- a/project_scrum/data/sequences_projects.xml +++ b/project_scrum/data/sequences_projects.xml @@ -1,5 +1,4 @@ - - + diff --git a/project_scrum/demo/project_scrum_demo.xml b/project_scrum/demo/project_scrum_demo.xml index 7be3761..e2ad3ed 100644 --- a/project_scrum/demo/project_scrum_demo.xml +++ b/project_scrum/demo/project_scrum_demo.xml @@ -1,198 +1,211 @@ - + - + True - + Project Scrum 3 - + employees - + Model for Testing Scrum using in projects project_scrum True - + Project Testing Scrum 3 - + employees - + Model for Testing Scrum using in projects project_scrum2 Sprint 1 - + + weeks=1)).strftime('%Y-%m-%d')" + /> - pending + weeks=1)).strftime('%Y-%m-%d')" + /> + pending - + Sprint 2 - + + weeks=3)).strftime('%Y-%m-%d')" + /> - pending + weeks=2)).strftime('%Y-%m-%d')" + /> + pending - + Sprint 3 - + + weeks=2)).strftime('%Y-%m-%d')" + /> - open + weeks=3)).strftime('%Y-%m-%d')" + /> + open Testing Sprint 1 - + + weeks=4)).strftime('%Y-%m-%d')" + /> - open + weeks=5)).strftime('%Y-%m-%d')" + /> + open - + Testing Sprint 2 - + + weeks=6)).strftime('%Y-%m-%d')" + /> - open + weeks=7)).strftime('%Y-%m-%d')" + /> + open - + - - - + + + 0 - + Detecting problems 3 - + - + - - - + + + 0 - + Define layout 3 - + - + - - - + + + 0 - + Test Define layout 3 - + - + User Story 1 - + Description Test - + User Story 2 - + Sprint Test - + User Story 3 - + Working Flow Test - + User Story 4 - + User Friendly Test User Story Testing 1 - + Description Test - + User Story Testing 2 - + Description Scrum Test - + - - - + + + yesterday is history today is present tomorrow is a mystery - - - - + + + + yesterday is a mystery today is history tomorrow is a present - - - - + + + + Fantasy is reality Aliens exist There is nothing that is true @@ -200,25 +213,25 @@ Test Case 2 - - - - + + + + - + Test Case 3 - - - - + + + + Testing Scrum Case 1 - - - - + + + + diff --git a/project_scrum/models/project_project.py b/project_scrum/models/project_project.py index 6470c5d..872089a 100644 --- a/project_scrum/models/project_project.py +++ b/project_scrum/models/project_project.py @@ -1,10 +1,10 @@ # Copyright <2017> # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import models, fields +from odoo import fields, models class ProjectProject(models.Model): - _inherit = 'project.project' + _inherit = "project.project" sprint_ids = fields.One2many( comodel_name="project.scrum.sprint", @@ -27,34 +27,33 @@ class ProjectProject(models.Model): string="Test Cases", ) sprint_count = fields.Integer( - compute='_compute_sprint_count', + compute="_compute_sprint_count", string="# Sprints", index=True, ) user_story_count = fields.Integer( - compute='_compute_user_story_count', + compute="_compute_user_story_count", string="# User Stories", ) meeting_count = fields.Integer( - compute='_compute_meeting_count', + compute="_compute_meeting_count", string="# Meetings", ) test_case_count = fields.Integer( - compute='_compute_test_case_count', + compute="_compute_test_case_count", string="# Test Cases", ) use_scrum = fields.Boolean() default_sprintduration = fields.Integer( - string='Calendar', + string="Calendar", required=False, default=14, - help="Default Sprint time for this project, in days" + help="Default Sprint time for this project, in days", ) manhours = fields.Integer( - string='Man Hours', + string="Man Hours", required=False, - help="How many hours you expect this project " - "needs before it's finished" + help="How many hours you expect this project " "needs before it's finished", ) description = fields.Html() diff --git a/project_scrum/models/project_scrum_actors.py b/project_scrum/models/project_scrum_actors.py index 19c1a62..79b2bdf 100644 --- a/project_scrum/models/project_scrum_actors.py +++ b/project_scrum/models/project_scrum_actors.py @@ -1,10 +1,10 @@ # Copyright <2017> # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import models, fields +from odoo import fields, models class ProjectScrumActors(models.Model): - _name = 'project.scrum.actors' - _description = 'Actors in user stories' + _name = "project.scrum.actors" + _description = "Actors in user stories" name = fields.Char(required=True) diff --git a/project_scrum/models/project_scrum_meeting.py b/project_scrum/models/project_scrum_meeting.py index 2daf104..d04c507 100644 --- a/project_scrum/models/project_scrum_meeting.py +++ b/project_scrum/models/project_scrum_meeting.py @@ -1,98 +1,97 @@ # Copyright <2017> # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import models, fields, api, _ +from odoo import _, api, fields, models class ProjectScrumMeeting(models.Model): - _name = 'project.scrum.meeting' - _description = 'Project Scrum Daily Meetings' - _inherit = ['mail.thread', 'mail.activity.mixin'] + _name = "project.scrum.meeting" + _description = "Project Scrum Daily Meetings" + _inherit = ["mail.thread", "mail.activity.mixin"] project_id = fields.Many2one( - comodel_name='project.project', - string='Project', - ondelete='cascade', + comodel_name="project.project", + string="Project", + ondelete="cascade", index=True, - track_visibility='onchange', + track_visibility="onchange", change_default=True, required=True, ) sprint_id = fields.Many2one( - comodel_name='project.scrum.sprint', - string='Sprint', + comodel_name="project.scrum.sprint", + string="Sprint", ) datetime_meeting = fields.Datetime( - string='Date and Time of the meeting', + string="Date and Time of the meeting", required=True, ) user_id_meeting = fields.Many2one( - comodel_name='res.users', - string='Meeting Organizer', + comodel_name="res.users", + string="Meeting Organizer", required=True, - default=lambda self: self.env.user + default=lambda self: self.env.user, ) question_yesterday = fields.Html( - string='Description Yesterday', + string="Description Yesterday", required=True, ) question_today = fields.Html( - string='Description Today', + string="Description Today", required=True, ) question_blocks = fields.Html( - string='Description', + string="Description", required=False, ) question_backlog = fields.Selection( - [('yes', 'Yes'), ('no', 'No')], - string='Backlog Accurate?', + [("yes", "Yes"), ("no", "No")], + string="Backlog Accurate?", required=False, - default='yes', + default="yes", ) company_id = fields.Many2one( - related='project_id.company_id', + related="project_id.company_id", ) @api.multi def name_get(self): result = [] for rec in self: - name = '' + name = "" if rec.project_id: name = "%s - %s - %s" % ( rec.project_id.name, rec.user_id_meeting.name, - rec.datetime_meeting) + rec.datetime_meeting, + ) else: - name = "%s - %s" % ( - rec.user_id_meeting.name, - rec.datetime_meeting) + name = "%s - %s" % (rec.user_id_meeting.name, rec.datetime_meeting) result.append((rec.id, name)) return result @api.multi def send_email(self): self.ensure_one() - template = self.env.ref('project_scrum.email_template_id', False) + template = self.env.ref("project_scrum.email_template_id", False) compose_form = self.env.ref( - 'mail.email_compose_message_wizard_form', + "mail.email_compose_message_wizard_form", False, ) ctx = dict( - default_model='project.scrum.meeting', + default_model="project.scrum.meeting", default_res_id=self.id, default_use_template=bool(template), default_template_id=template.id, - default_composition_mode='comment', + default_composition_mode="comment", ) return { - 'name': _('Compose Email'), - 'type': 'ir.actions.act_window', - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'mail.compose.message', - 'views': [(compose_form.id, 'form')], - 'view_id': compose_form.id, - 'target': 'new', - 'context': ctx, + "name": _("Compose Email"), + "type": "ir.actions.act_window", + "view_type": "form", + "view_mode": "form", + "res_model": "mail.compose.message", + "views": [(compose_form.id, "form")], + "view_id": compose_form.id, + "target": "new", + "context": ctx, } diff --git a/project_scrum/models/project_scrum_sprint.py b/project_scrum/models/project_scrum_sprint.py index f0d6ec9..7b46744 100644 --- a/project_scrum/models/project_scrum_sprint.py +++ b/project_scrum/models/project_scrum_sprint.py @@ -1,27 +1,33 @@ # Copyright <2017> # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import models, fields, api from datetime import date, timedelta +from odoo import api, fields, models + class ProjectScrumSprint(models.Model): - _name = 'project.scrum.sprint' - _description = 'Project Scrum Sprint' - _order = 'date_start desc' + _name = "project.scrum.sprint" + _description = "Project Scrum Sprint" + _order = "date_start desc" def get_current_sprint(self, project_id): - scrum_obj = self.env['project.scrum.sprint'] - sprint = scrum_obj.search([ - '&', '&', - ('date_start', '<=', date.today()), - ('date_stop', '>=', date.today()), - ('project_id', '=', project_id) - ], limit=1) + scrum_obj = self.env["project.scrum.sprint"] + sprint = scrum_obj.search( + [ + "&", + "&", + ("date_start", "<=", date.today()), + ("date_stop", ">=", date.today()), + ("project_id", "=", project_id), + ], + limit=1, + ) return sprint def time_cal(self): - diff = fields.Date.from_string(self.date_stop) - \ - fields.Date.from_string(self.date_start) + diff = fields.Date.from_string(self.date_stop) - fields.Date.from_string( + self.date_start + ) if diff.days <= 0: return 1 return diff.days + 1 @@ -30,54 +36,54 @@ def _compute_task_count(self): for p in self: p.task_count = len(p.task_ids) - name = fields.Char(string='Sprint Name', required=True) + name = fields.Char(string="Sprint Name", required=True) meeting_ids = fields.One2many( - comodel_name='project.scrum.meeting', - inverse_name='sprint_id', - string='Daily Scrum', + comodel_name="project.scrum.meeting", + inverse_name="sprint_id", + string="Daily Scrum", ) user_id = fields.Many2one( - comodel_name='res.users', - string='Assigned to', + comodel_name="res.users", + string="Assigned to", index=True, ) - date_start = fields.Date(string='Starting Date') - date_stop = fields.Date(string='Ending Date') + date_start = fields.Date(string="Starting Date") + date_stop = fields.Date(string="Ending Date") description = fields.Text() project_id = fields.Many2one( - comodel_name='project.project', - string='Project', - ondelete='cascade', - track_visibility='onchange', + comodel_name="project.project", + string="Project", + ondelete="cascade", + track_visibility="onchange", change_default=True, required=True, index=True, help="If you have [?] in the project name, " - "it means there are no analytic account linked to this project." + "it means there are no analytic account linked to this project.", ) product_owner_id = fields.Many2one( - comodel_name='res.users', - string='Product Owner', + comodel_name="res.users", + string="Product Owner", required=False, help="The person who responsible for the product", ) scrum_master_id = fields.Many2one( - comodel_name='res.users', - string='Scrum Master', + comodel_name="res.users", + string="Scrum Master", required=False, help="The person who maintains the processes for the product", ) us_ids = fields.Many2many( - comodel_name='project.scrum.us', - string='User Stories', + comodel_name="project.scrum.us", + string="User Stories", ) task_ids = fields.One2many( - comodel_name='project.task', - inverse_name='sprint_id', + comodel_name="project.task", + inverse_name="sprint_id", ) - task_count = fields.Integer(compute='_compute_task_count') + task_count = fields.Integer(compute="_compute_task_count") review = fields.Html( - string='Sprint Review', + string="Sprint Review", default="""

    What was the goal of this sprint?
@@ -87,7 +93,7 @@ def _compute_task_count(self):

""", ) retrospective = fields.Html( - string='Sprint Retrospective', + string="Sprint Retrospective", default="""

    What will you start doing in next sprint?

@@ -104,32 +110,35 @@ def _compute_task_count(self): ) planned_hours = fields.Float( multi="planned_hours", - string='Planned Hours', - help='Estimated time to do the task, ' - 'usually set by the project manager when the task is in draft state.', + string="Planned Hours", + help="Estimated time to do the task, " + "usually set by the project manager when the task is in draft state.", ) - state = fields.Selection([ - ('draft', 'Draft'), - ('open', 'Open'), - ('pending', 'Pending'), - ('cancel', 'Cancelled'), - ('done', 'Done')], - string='State', + state = fields.Selection( + [ + ("draft", "Draft"), + ("open", "Open"), + ("pending", "Pending"), + ("cancel", "Cancelled"), + ("done", "Done"), + ], + string="State", required=False, ) company_id = fields.Many2one( - related='project_id.company_id', + related="project_id.company_id", ) - @api.onchange('project_id') + @api.onchange("project_id") def onchange_project_id(self): if self.project_id and self.project_id.manhours: self.planned_hours = self.project_id.manhours else: self.planned_hours = 0.0 - @api.onchange('date_start') + @api.onchange("date_start") def onchange_date_start(self): if self.date_start and self.project_id: - self.date_stop = fields.Date.from_string(self.date_start) +\ - timedelta(days=self.project_id.default_sprintduration) + self.date_stop = fields.Date.from_string(self.date_start) + timedelta( + days=self.project_id.default_sprintduration + ) diff --git a/project_scrum/models/project_scrum_test.py b/project_scrum/models/project_scrum_test.py index d3a76b2..ced1689 100644 --- a/project_scrum/models/project_scrum_test.py +++ b/project_scrum/models/project_scrum_test.py @@ -1,53 +1,50 @@ # Copyright <2017> # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import models, fields, api +from odoo import api, fields, models class ProjectScrumTest(models.Model): - _name = 'project.scrum.test' - _order = 'sequence_test' - _description = 'Project Scrum Test' + _name = "project.scrum.test" + _order = "sequence_test" + _description = "Project Scrum Test" name = fields.Char(required=True) project_id = fields.Many2one( - comodel_name='project.project', - string='Project', - ondelete='cascade', + comodel_name="project.project", + string="Project", + ondelete="cascade", index=True, required=True, - track_visibility='onchange', + track_visibility="onchange", change_default=True, ) sprint_id = fields.Many2one( - comodel_name='project.scrum.sprint', - string='Sprint', + comodel_name="project.scrum.sprint", + string="Sprint", ) user_story_id_test = fields.Many2one( comodel_name="project.scrum.us", string="User Story", ) - description_test = fields.Html(string='Description') - sequence_test = fields.Integer(string='Sequence', index=True) - stats_test = fields.Selection([ - ('draft', 'Draft'), - ('in progress', 'In Progress'), - ('cancel', 'Cancelled')], - string='State', + description_test = fields.Html(string="Description") + sequence_test = fields.Integer(string="Sequence", index=True) + stats_test = fields.Selection( + [("draft", "Draft"), ("in progress", "In Progress"), ("cancel", "Cancelled")], + string="State", required=False, ) company_id = fields.Many2one( - related='project_id.company_id', + related="project_id.company_id", ) - color = fields.Integer(related='project_id.color') + color = fields.Integer(related="project_id.color") def _resolve_project_id_from_context(self): context = self.env.context - if type(context.get('default_project_id')) in (int, int): - return context['default_project_id'] - if isinstance(context.get('default_project_id'), str): - project_name = context['default_project_id'] - project_ids = self.env['project.project'].name_search( - name=project_name) + if type(context.get("default_project_id")) in (int, int): + return context["default_project_id"] + if isinstance(context.get("default_project_id"), str): + project_name = context["default_project_id"] + project_ids = self.env["project.project"].name_search(name=project_name) if len(project_ids) == 1: return project_ids[0][0] return None @@ -55,10 +52,13 @@ def _resolve_project_id_from_context(self): @api.model def _read_group_us_id(self, present_ids, domain, **kwargs): project_id = self._resolve_project_id_from_context() - user_stories = self.env['project.scrum.us'].search( - [('project_id', '=', project_id)]).name_get() + user_stories = ( + self.env["project.scrum.us"] + .search([("project_id", "=", project_id)]) + .name_get() + ) return user_stories, None _group_by_full = { - 'user_story_id_test': _read_group_us_id, - } + "user_story_id_test": _read_group_us_id, + } diff --git a/project_scrum/models/project_scrum_us.py b/project_scrum/models/project_scrum_us.py index 0386d8a..bff3315 100644 --- a/project_scrum/models/project_scrum_us.py +++ b/project_scrum/models/project_scrum_us.py @@ -1,92 +1,93 @@ # Copyright <2017> # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import models, fields, api +from odoo import api, fields, models class ProjectScrumUs(models.Model): - _name = 'project.scrum.us' - _description = 'Project Scrum Use Stories' - _order = 'reference' - _inherit = ['mail.thread', 'mail.activity.mixin'] + _name = "project.scrum.us" + _description = "Project Scrum Use Stories" + _order = "reference" + _inherit = ["mail.thread", "mail.activity.mixin"] @api.model def create(self, vals): - vals['reference'] = self.env['ir.sequence'].next_by_code('user.story') + vals["reference"] = self.env["ir.sequence"].next_by_code("user.story") return super().create(vals) @api.model def _get_moscow_field(self): - return self.env['project.task']._get_moscow_field() + return self.env["project.task"]._get_moscow_field() @api.model def _get_value_field(self): - return self.env['project.task']._get_value_field() + return self.env["project.task"]._get_value_field() @api.model def _get_risk_field(self): - return self.env['project.task']._get_risk_field() + return self.env["project.task"]._get_risk_field() @api.model def _get_kano_field(self): - return self.env['project.task']._get_kano_field() + return self.env["project.task"]._get_kano_field() - name = fields.Char(string='User Story', required=True) - color = fields.Integer(related='project_id.color') - description = fields.Html(string='Description',) + name = fields.Char(string="User Story", required=True) + color = fields.Integer(related="project_id.color") + description = fields.Html( + string="Description", + ) actor_ids = fields.Many2many( - comodel_name='project.scrum.actors', - string='Actor', + comodel_name="project.scrum.actors", + string="Actor", ) project_id = fields.Many2one( - comodel_name='project.project', - string='Project', - ondelete='set null', + comodel_name="project.project", + string="Project", + ondelete="set null", index=True, - track_visibility='onchange', + track_visibility="onchange", change_default=True, required=True, ) sprint_ids = fields.Many2many( - comodel_name='project.scrum.sprint', - string='Sprint', - group_expand='_read_group_sprint_id', + comodel_name="project.scrum.sprint", + string="Sprint", + group_expand="_read_group_sprint_id", ) task_ids = fields.One2many( - comodel_name='project.task', - inverse_name='us_id', + comodel_name="project.task", + inverse_name="us_id", ) task_test_ids = fields.One2many( - comodel_name='project.scrum.test', - inverse_name='user_story_id_test', + comodel_name="project.scrum.test", + inverse_name="user_story_id_test", ) - task_count = fields.Integer(compute='_compute_task_count', store=True) + task_count = fields.Integer(compute="_compute_task_count", store=True) test_ids = fields.One2many( - comodel_name='project.scrum.test', - inverse_name='user_story_id_test', + comodel_name="project.scrum.test", + inverse_name="user_story_id_test", ) - test_count = fields.Integer(compute='_compute_test_count', store=True) + test_count = fields.Integer(compute="_compute_test_count", store=True) sequence = fields.Integer() - company_id = fields.Many2one( - related='project_id.company_id', - store=True - ) - moscow = fields.Selection('_get_moscow_field', string='Moscow') - value = fields.Selection('_get_value_field', string='Value') - risk = fields.Selection('_get_risk_field', string='Risk') - kano = fields.Selection('_get_kano_field', string='Kano') + company_id = fields.Many2one(related="project_id.company_id", store=True) + moscow = fields.Selection("_get_moscow_field", string="Moscow") + value = fields.Selection("_get_value_field", string="Value") + risk = fields.Selection("_get_risk_field", string="Risk") + kano = fields.Selection("_get_kano_field", string="Kano") reference = fields.Char( - 'Number', + "Number", index=True, readonly=True, copy=False, - default='/', + default="/", ) - kanban_state = fields.Selection([ - ('normal', 'Mark as impeded'), - ('blocked', 'Mark as waiting'), - ('done', 'Mark item as defined and ready for implementation')], - 'Kanban State', - default='blocked', + kanban_state = fields.Selection( + [ + ("normal", "Mark as impeded"), + ("blocked", "Mark as waiting"), + ("done", "Mark item as defined and ready for implementation"), + ], + "Kanban State", + default="blocked", ) @api.depends("task_ids") @@ -100,22 +101,22 @@ def _compute_test_count(self): p.test_count = len(p.test_ids) def _resolve_project_id_from_context(self): - """ Returns ID of project based on the value of 'default_project_id' - context key, or None if it cannot be resolved to a single - project. + """Returns ID of project based on the value of 'default_project_id' + context key, or None if it cannot be resolved to a single + project. """ context = self.env.context - project_project_model = self.env['project.project'] - if type(context.get('default_project_id')) in (int, int): - return context['default_project_id'] - if isinstance(context.get('default_project_id'), str): - project_name = context['default_project_id'] + project_project_model = self.env["project.project"] + if type(context.get("default_project_id")) in (int, int): + return context["default_project_id"] + if isinstance(context.get("default_project_id"), str): + project_name = context["default_project_id"] project_ids = project_project_model.with_context(context) - project_ids = project_ids.name_search(project_name, operator='=') + project_ids = project_ids.name_search(project_name, operator="=") if not project_ids: project_ids = project_ids.name_search( project_name, - operator='=ilike', + operator="=ilike", ) if not project_ids: project_ids.name_search(name=project_name) @@ -126,6 +127,9 @@ def _resolve_project_id_from_context(self): @api.model def _read_group_sprint_id(self, present_ids, domain, **kwargs): project_id = self._resolve_project_id_from_context() - sprints = self.env['project.scrum.sprint'].search( - [('project_id', '=', project_id)], order='sequence').name_get() + sprints = ( + self.env["project.scrum.sprint"] + .search([("project_id", "=", project_id)], order="sequence") + .name_get() + ) return sprints, None diff --git a/project_scrum/models/project_task.py b/project_scrum/models/project_task.py index ca29976..453cea8 100644 --- a/project_scrum/models/project_task.py +++ b/project_scrum/models/project_task.py @@ -1,6 +1,6 @@ # Copyright <2017> # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import models, fields, api +from odoo import api, fields, models class ProjectTask(models.Model): @@ -9,121 +9,131 @@ class ProjectTask(models.Model): @api.model def _get_moscow_field(self): - return [('1', 'must'), - ('2', 'should'), - ('3', 'could'), - ('4', 'wont'), - ('not_set', 'Not Set')] + return [ + ("1", "must"), + ("2", "should"), + ("3", "could"), + ("4", "wont"), + ("not_set", "Not Set"), + ] @api.model def _get_value_field(self): return [ - ('0', '0'), - ('1', '1'), - ('2', '2'), - ('3', '3'), - ('5', '5'), - ('8', '8'), - ('13', '13'), - ('20', '20'), - ('40', '40'), - ('100', '100'), - ('00', 'Not Set'), + ("0", "0"), + ("1", "1"), + ("2", "2"), + ("3", "3"), + ("5", "5"), + ("8", "8"), + ("13", "13"), + ("20", "20"), + ("40", "40"), + ("100", "100"), + ("00", "Not Set"), ] @api.model def _get_risk_field(self): return [ - ('0', '0'), - ('1', '1'), - ('2', '2'), - ('3', '3'), - ('5', '5'), - ('8', '8'), - ('13', '13'), - ('20', '20'), - ('40', '40'), - ('100', '100'), - ('00', 'Not Set'), + ("0", "0"), + ("1", "1"), + ("2", "2"), + ("3", "3"), + ("5", "5"), + ("8", "8"), + ("13", "13"), + ("20", "20"), + ("40", "40"), + ("100", "100"), + ("00", "Not Set"), ] @api.model def _get_kano_field(self): return [ - ('excitement', 'Excitement'), - ('indifferent', 'Indifferent'), - ('mandatory', 'Mandatory'), - ('performance', 'Performance'), - ('questionable', 'Questionable'), - ('reverse', 'Reverse'), - ('not_set', 'Not Set'), + ("excitement", "Excitement"), + ("indifferent", "Indifferent"), + ("mandatory", "Mandatory"), + ("performance", "Performance"), + ("questionable", "Questionable"), + ("reverse", "Reverse"), + ("not_set", "Not Set"), ] actor_ids = fields.Many2many( - comodel_name='project.scrum.actors', - string='Actor', + comodel_name="project.scrum.actors", + string="Actor", ) sprint_id = fields.Many2one( - comodel_name='project.scrum.sprint', - string='Sprint', + comodel_name="project.scrum.sprint", + string="Sprint", ) us_id = fields.Many2one( - comodel_name='project.scrum.us', - string='User Stories', + comodel_name="project.scrum.us", + string="User Stories", index=True, ) - use_scrum = fields.Boolean(related='project_id.use_scrum', readonly=1) + use_scrum = fields.Boolean(related="project_id.use_scrum", readonly=1) current_sprint = fields.Boolean( - compute='_compute_current_sprint', - string='Current Sprint', - search='_search_current_sprint', + compute="_compute_current_sprint", + string="Current Sprint", + search="_search_current_sprint", ) - moscow = fields.Selection('_get_moscow_field') - value = fields.Selection('_get_value_field') - risk = fields.Selection('_get_risk_field') - kano = fields.Selection('_get_kano_field') - color = fields.Integer(related='project_id.color') + moscow = fields.Selection("_get_moscow_field") + value = fields.Selection("_get_value_field") + risk = fields.Selection("_get_risk_field") + kano = fields.Selection("_get_kano_field") + color = fields.Integer(related="project_id.color") - @api.depends('sprint_id') + @api.depends("sprint_id") def _compute_current_sprint(self): for rec in self: - sprint = self.env['project.scrum.sprint'].get_current_sprint( - rec.project_id.id) + sprint = self.env["project.scrum.sprint"].get_current_sprint( + rec.project_id.id + ) if sprint: rec.current_sprint = sprint.id == rec.sprint_id.id else: rec.current_sprint = False def _search_current_sprint(self, operator, value): - project_id = self.env.context.get('default_project_id', None) - sprint = self.env['project.scrum.sprint'].get_current_sprint( - project_id) - return [('sprint_id', '=', sprint and sprint.id or None)] + project_id = self.env.context.get("default_project_id", None) + sprint = self.env["project.scrum.sprint"].get_current_sprint(project_id) + return [("sprint_id", "=", sprint and sprint.id or None)] @api.model def _read_group_sprint_id(self, present_ids, domain, **kwargs): - project = self.env['project.project'].browse( - self._resolve_project_id_from_context()) + project = self.env["project.project"].browse( + self._resolve_project_id_from_context() + ) if project.use_scrum: - sprints = self.env['project.scrum.sprint'].search( - [('project_id', '=', project.id)], order='sequence').name_get() + sprints = ( + self.env["project.scrum.sprint"] + .search([("project_id", "=", project.id)], order="sequence") + .name_get() + ) return sprints, None else: return [], None @api.model def _read_group_us_id(self, present_ids, domain, **kwargs): - project = self.env['project.project'].browse( - self._resolve_project_id_from_context()) + project = self.env["project.project"].browse( + self._resolve_project_id_from_context() + ) if project.use_scrum: - user_stories = self.env['project.scrum.us'].search( - [('project_id', '=', project.id)], order='sequence').name_get() + user_stories = ( + self.env["project.scrum.us"] + .search([("project_id", "=", project.id)], order="sequence") + .name_get() + ) return user_stories, None else: return [], None @api.multi def get_formview_id(self): - if all(self.mapped('use_scrum')): - return self.env.ref('project_scrum.view_ps_sprint_task_form2').id + if all(self.mapped("use_scrum")): + return self.env.ref("project_scrum.view_ps_sprint_task_form2").id return super().get_formview_id() diff --git a/project_scrum/readme/USAGE.rst b/project_scrum/readme/USAGE.rst index 4f5a427..6e7f95e 100644 --- a/project_scrum/readme/USAGE.rst +++ b/project_scrum/readme/USAGE.rst @@ -1,8 +1,8 @@ This module implements all concepts defined by the scrum project management methodology for IT companies: -- Project with sprints, product owner, scrum master -- Sprints with reviews, daily meetings, feedbacks +- Project with sprints, product owner, scrum master +- Sprints with reviews, daily meetings, feedbacks - Product backlog - Sprint backlog diff --git a/project_scrum/security/project_security.xml b/project_scrum/security/project_security.xml index 895472e..836d1a2 100644 --- a/project_scrum/security/project_security.xml +++ b/project_scrum/security/project_security.xml @@ -1,4 +1,4 @@ - + @@ -78,9 +78,7 @@ User Story Project manager [(1, '=', 1)] - +
diff --git a/project_scrum/security/res_groups.xml b/project_scrum/security/res_groups.xml index ef01b1d..5d2a791 100644 --- a/project_scrum/security/res_groups.xml +++ b/project_scrum/security/res_groups.xml @@ -1,4 +1,4 @@ - + @@ -8,7 +8,7 @@ Scrum Role Scrum Master - + Scrum Role Development Team diff --git a/project_scrum/tests/test_project_scrum.py b/project_scrum/tests/test_project_scrum.py index d6ad3ea..3ea7bf0 100644 --- a/project_scrum/tests/test_project_scrum.py +++ b/project_scrum/tests/test_project_scrum.py @@ -1,9 +1,10 @@ # Copyright 2018 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import logging -from odoo.tests.common import TransactionCase -from odoo import fields, models, SUPERUSER_ID + +from odoo import SUPERUSER_ID, fields, models from odoo.exceptions import UserError +from odoo.tests.common import TransactionCase _logger = logging.getLogger(__name__) @@ -14,16 +15,16 @@ class TestProjectScrum(TransactionCase): def setUp(self): super().setUp() - self.project_project_obj = self.env['project.project'] - self.project_scrum_actors_obj = self.env['project.scrum.actors'] - self.project_scrum_meeting_obj = self.env['project.scrum.meeting'] - self.project_scrum_sprint_obj = self.env['project.scrum.sprint'] - self.project_scrum_test_obj = self.env['project.scrum.test'] - self.project_scrum_us_obj = self.env['project.scrum.us'] - self.project_task_obj = self.env['project.task'] + self.project_project_obj = self.env["project.project"] + self.project_scrum_actors_obj = self.env["project.scrum.actors"] + self.project_scrum_meeting_obj = self.env["project.scrum.meeting"] + self.project_scrum_sprint_obj = self.env["project.scrum.sprint"] + self.project_scrum_test_obj = self.env["project.scrum.test"] + self.project_scrum_us_obj = self.env["project.scrum.us"] + self.project_task_obj = self.env["project.task"] def test_crud_operations(self): - _logger.debug('Testing CRUD operations on the models of project_scrum') + _logger.debug("Testing CRUD operations on the models of project_scrum") self._test_create() self._test_get_formview_id() self._test_read() @@ -32,106 +33,108 @@ def test_crud_operations(self): self._test_unlink() def _test_create(self): - _logger.debug('Testing create operations') + _logger.debug("Testing create operations") self.project_project_vals = { - 'name': 'test', - 'use_scrum': True, - 'default_sprintduration': 20, - 'manhours': 17, - 'alias_name': 'project', - 'privacy_visibility': 'followers', - 'description': '

Description

', + "name": "test", + "use_scrum": True, + "default_sprintduration": 20, + "manhours": 17, + "alias_name": "project", + "privacy_visibility": "followers", + "description": "

Description

", } self.project_project = self.project_project_obj.create( self.project_project_vals, ) - self.project_scrum_actors_vals = {'name': 'Actor'} + self.project_scrum_actors_vals = {"name": "Actor"} self.project_scrum_actors = self.project_scrum_actors_obj.create( self.project_scrum_actors_vals, ) self.project_scrum_meeting_vals = { - 'project_id': self.project_project.id, - 'datetime_meeting': fields.Datetime.now(), - 'user_id_meeting': SUPERUSER_ID, - 'question_yesterday': '

Question1?

', - 'question_today': '

Question2?

', - 'question_blocks': '

Question3?

', - 'question_backlog': 'no', + "project_id": self.project_project.id, + "datetime_meeting": fields.Datetime.now(), + "user_id_meeting": SUPERUSER_ID, + "question_yesterday": "

Question1?

", + "question_today": "

Question2?

", + "question_blocks": "

Question3?

", + "question_backlog": "no", } self.project_scrum_meeting = self.project_scrum_meeting_obj.create( self.project_scrum_meeting_vals, ) self.project_scrum_sprint_vals = { - 'name': 'Name', - 'user_id': SUPERUSER_ID, - 'date_start': fields.Date.today(), - 'date_stop': fields.Date.today(), - 'description': 'Description', - 'project_id': self.project_project.id, - 'product_owner_id': SUPERUSER_ID, - 'scrum_master_id': SUPERUSER_ID, - 'review': '

Review

', - 'retrospective': '

Retrospective

', - 'sequence': 123, - 'planned_hours': 14, - 'state': 'open', + "name": "Name", + "user_id": SUPERUSER_ID, + "date_start": fields.Date.today(), + "date_stop": fields.Date.today(), + "description": "Description", + "project_id": self.project_project.id, + "product_owner_id": SUPERUSER_ID, + "scrum_master_id": SUPERUSER_ID, + "review": "

Review

", + "retrospective": "

Retrospective

", + "sequence": 123, + "planned_hours": 14, + "state": "open", } self.project_scrum_sprint = self.project_scrum_sprint_obj.create( self.project_scrum_sprint_vals, ) self.project_scrum_test_vals = { - 'name': 'Name', - 'project_id': self.project_project.id, + "name": "Name", + "project_id": self.project_project.id, } self.project_scrum_test = self.project_scrum_test_obj.create( self.project_scrum_test_vals, ) self.project_scrum_us_vals = { - 'name': 'Scrum us', - 'description': '

Description

', - 'project_id': self.project_project.id, - 'sequence': 123, - 'moscow': self.project_scrum_us_obj._get_moscow_field()[-1][0], - 'value': self.project_scrum_us_obj._get_value_field()[-1][0], - 'risk': self.project_scrum_us_obj._get_risk_field()[-1][0], - 'kano': self.project_scrum_us_obj._get_kano_field()[-1][0], - 'reference': 'Reference', - 'kanban_state': 'done', + "name": "Scrum us", + "description": "

Description

", + "project_id": self.project_project.id, + "sequence": 123, + "moscow": self.project_scrum_us_obj._get_moscow_field()[-1][0], + "value": self.project_scrum_us_obj._get_value_field()[-1][0], + "risk": self.project_scrum_us_obj._get_risk_field()[-1][0], + "kano": self.project_scrum_us_obj._get_kano_field()[-1][0], + "reference": "Reference", + "kanban_state": "done", } self.project_scrum_us = self.project_scrum_us_obj.create( self.project_scrum_us_vals, ) self.project_task_vals = { - 'name': 'A Task', - 'user_id': SUPERUSER_ID, - 'sprint_id': self.project_scrum_sprint.id, - 'date_start': fields.Datetime.now(), - 'description': '

Description

', - 'moscow': self.project_scrum_us_obj._get_moscow_field()[-1][0], - 'value': self.project_scrum_us_obj._get_value_field()[-1][0], - 'risk': self.project_scrum_us_obj._get_risk_field()[-1][0], - 'kano': self.project_scrum_us_obj._get_kano_field()[-1][0], + "name": "A Task", + "user_id": SUPERUSER_ID, + "sprint_id": self.project_scrum_sprint.id, + "date_start": fields.Datetime.now(), + "description": "

Description

", + "moscow": self.project_scrum_us_obj._get_moscow_field()[-1][0], + "value": self.project_scrum_us_obj._get_value_field()[-1][0], + "risk": self.project_scrum_us_obj._get_risk_field()[-1][0], + "kano": self.project_scrum_us_obj._get_kano_field()[-1][0], } self.project_task = self.project_task_obj.create( self.project_task_vals, ) def _test_get_formview_id(self): - self.project_task.write({'project_id': self.project_project.id}) + self.project_task.write({"project_id": self.project_project.id}) self.assertEquals( self.project_task.get_formview_id(), - self.env.ref('project_scrum.view_ps_sprint_task_form2').id) - self.project_project.write({'use_scrum': False}) + self.env.ref("project_scrum.view_ps_sprint_task_form2").id, + ) + self.project_project.write({"use_scrum": False}) self.assertNotEqual( self.project_task.get_formview_id(), - self.env.ref('project_scrum.view_ps_sprint_task_form2').id) + self.env.ref("project_scrum.view_ps_sprint_task_form2").id, + ) # reset data as before testing function - self.project_project.write({'use_scrum': True}) + self.project_project.write({"use_scrum": True}) with self.assertRaises(UserError): - self.project_task.write({'project_id': False}) + self.project_task.write({"project_id": False}) def _test_read(self): - _logger.debug('Testing read') + _logger.debug("Testing read") for key in self.project_project_vals.keys(): attr = getattr(self.project_project, key) if issubclass(type(attr), models.Model): @@ -149,8 +152,9 @@ def _test_read(self): self.project_scrum_actors_vals[key], ) for key in filter( - lambda x: x not in ['message_follower_ids', 'name'], - self.project_scrum_meeting_vals.keys()): + lambda x: x not in ["message_follower_ids", "name"], + self.project_scrum_meeting_vals.keys(), + ): attr = getattr(self.project_scrum_meeting, key) if issubclass(type(attr), models.Model): attr = attr.id @@ -175,8 +179,9 @@ def _test_read(self): self.project_scrum_test_vals[key], ) for key in filter( - lambda x: x not in ['message_follower_ids'], - self.project_scrum_us_vals.keys()): + lambda x: x not in ["message_follower_ids"], + self.project_scrum_us_vals.keys(), + ): attr = getattr(self.project_scrum_us, key) if issubclass(type(attr), models.Model): attr = attr.id @@ -185,8 +190,9 @@ def _test_read(self): self.project_scrum_us_vals[key], ) for key in filter( - lambda x: x not in ['message_follower_ids', 'code'], - self.project_task_vals.keys()): + lambda x: x not in ["message_follower_ids", "code"], + self.project_task_vals.keys(), + ): attr = getattr(self.project_task, key) if issubclass(type(attr), models.Model): attr = attr.id @@ -196,13 +202,16 @@ def _test_read(self): ) def _test_assertions(self): - _logger.debug('Testing assertions') + _logger.debug("Testing assertions") self.assertEquals( self.project_scrum_meeting.name_get()[0][1], - '%s - %s - %s' % - (self.project_scrum_meeting.project_id.name, + "%s - %s - %s" + % ( + self.project_scrum_meeting.project_id.name, self.project_scrum_meeting.user_id_meeting.name, - self.project_scrum_meeting.datetime_meeting)) + self.project_scrum_meeting.datetime_meeting, + ), + ) self.assertEquals(self.project_scrum_sprint.task_count, 1) self.assertEquals(self.project_project.sprint_count, 1) self.assertEquals(self.project_project.user_story_count, 1) @@ -210,22 +219,22 @@ def _test_assertions(self): self.assertEquals(self.project_project.test_case_count, 1) def _test_write(self): - _logger.debug('Testing write') + _logger.debug("Testing write") self.project_project.write(self.project_project_vals) self.project_scrum_actors.write(self.project_scrum_actors_vals) - del self.project_scrum_meeting_vals['message_follower_ids'] - self.project_scrum_meeting.with_context( - {'tracking_disable': True}).write( - self.project_scrum_meeting_vals) + del self.project_scrum_meeting_vals["message_follower_ids"] + self.project_scrum_meeting.with_context({"tracking_disable": True}).write( + self.project_scrum_meeting_vals + ) self.project_scrum_sprint.write(self.project_scrum_sprint_vals) self.project_scrum_test.write(self.project_scrum_test_vals) - del self.project_scrum_us_vals['message_follower_ids'] + del self.project_scrum_us_vals["message_follower_ids"] self.project_scrum_us.write(self.project_scrum_us_vals) - del self.project_task_vals['message_follower_ids'] + del self.project_task_vals["message_follower_ids"] self.project_task.write(self.project_task_vals) def _test_unlink(self): - _logger.debug('Testing unlinks') + _logger.debug("Testing unlinks") self.assertEquals(self.project_scrum_actors.unlink(), True) self.assertEquals(self.project_scrum_meeting.unlink(), True) self.assertEquals(self.project_scrum_sprint.unlink(), True) diff --git a/project_scrum/views/mail_template.xml b/project_scrum/views/mail_template.xml index 0b3e1d3..98988e1 100644 --- a/project_scrum/views/mail_template.xml +++ b/project_scrum/views/mail_template.xml @@ -1,4 +1,4 @@ - + @@ -9,20 +9,21 @@ or ''} ${object.datetime_meeting or ''} - + ${object.user_id_meeting or ''} -

Name: ${object.user_id_meeting}

-

Date: ${object.datetime_meeting}


What - did you do since the last meeting?

${object.question_yesterday} -

What do you plan to do till - the next meeting?

${object.question_today}

Are - there anything blocking you?

${object.question_blocks}

+

Name: ${object.user_id_meeting}

+

Date: ${object.datetime_meeting}


What + did you do since the last meeting?

${object.question_yesterday} +

What do you plan to do till + the next meeting?

${object.question_today}

Are + there anything blocking you?

${object.question_blocks}

]]>
diff --git a/project_scrum/views/menu.xml b/project_scrum/views/menu.xml index f1393f0..ea0667b 100644 --- a/project_scrum/views/menu.xml +++ b/project_scrum/views/menu.xml @@ -1,54 +1,62 @@ - + + sequence="3" + /> + sequence="3" + /> + action="action_show_scrum_projects" + /> + action="action_show_scrum_tasks" + /> + parent="menu_scrum_all" + sequence="20" + action="action_ps_us_all" + /> + parent="menu_scrum_all" + sequence="21" + action="action_ps_sprint_all" + /> + action="action_ps_meeting_all" + /> + action="action_ps_tc_all" + /> diff --git a/project_scrum/views/project_project.xml b/project_scrum/views/project_project.xml index 4e41f48..fc0a5aa 100644 --- a/project_scrum/views/project_project.xml +++ b/project_scrum/views/project_project.xml @@ -1,4 +1,4 @@ - + @@ -25,7 +25,7 @@
-
@@ -40,7 +40,7 @@ 'search_default_project_id': [active_id], 'default_project_id': active_id, } - +

Here, you can create new tasks @@ -53,14 +53,14 @@ tree - - + + form - - + + @@ -71,38 +71,51 @@ - - - + position="attributes" + > %(act_project_tasks)d - + - + @@ -123,17 +136,21 @@ - + Project Description - - + + @@ -144,29 +161,45 @@ Tasks - + Sprints - + User Stories - + Meetings - + @@ -181,16 +214,15 @@ project.project form kanban,form - + {'default_use_scrum': True} [('use_scrum', '=', True)] + (0, 0, {'view_mode': 'form', 'view_id': ref('edit_ps_project')})]" + /> diff --git a/project_scrum/views/project_scrum_meeting.xml b/project_scrum/views/project_scrum_meeting.xml index 2e2c3d2..d6abd27 100644 --- a/project_scrum/views/project_scrum_meeting.xml +++ b/project_scrum/views/project_scrum_meeting.xml @@ -1,4 +1,4 @@ - + project.scrum.meeting.tree @@ -24,29 +24,39 @@ - - - @@ -64,11 +76,15 @@ - + }" + > @@ -81,15 +97,17 @@ - + }" + > - + @@ -114,8 +132,7 @@ project.scrum.sprint calendar - + @@ -126,8 +143,12 @@ project.scrum.sprint.gantt project.scrum.sprint - + @@ -160,30 +181,58 @@ - + - + - + - + - + - + - + diff --git a/project_scrum/views/project_scrum_test.xml b/project_scrum/views/project_scrum_test.xml index 7448e47..7cc4550 100644 --- a/project_scrum/views/project_scrum_test.xml +++ b/project_scrum/views/project_scrum_test.xml @@ -1,4 +1,4 @@ - + @@ -17,16 +17,25 @@

- -
+
@@ -101,14 +110,20 @@

- +

- +

@@ -117,9 +132,12 @@ - + domain="[('project_id', '=' , project_id)]" + /> @@ -136,7 +154,9 @@ - + }" + > - + @@ -157,11 +177,14 @@ - + }" + > @@ -171,9 +194,12 @@
- + groups="base.group_user" + />
@@ -186,8 +212,9 @@ tree + colors="brown:moscow in ('1'); blue:moscow in ('2'); grey:moscow + in ('3'); green:moscow in('4') red:moscow in('5') " + > @@ -220,8 +247,12 @@ - + @@ -257,5 +288,5 @@ The user stories of scrum. - - + + diff --git a/project_scrum/views/project_task.xml b/project_scrum/views/project_task.xml index f0e4cae..c3d0380 100644 --- a/project_scrum/views/project_task.xml +++ b/project_scrum/views/project_task.xml @@ -1,4 +1,4 @@ - + @@ -12,10 +12,16 @@ - - + + @@ -28,23 +34,25 @@ 99 - + + domain="[('project_id', '=', project_id)]" + /> + domain="[('project_id', '=', project_id)]" + /> - - - - + + + + @@ -61,11 +69,13 @@ string="Sprint" name="sprint_id" context="{'default_project_id':project_id}" - domain="[('project_id', '=', project_id)]"/> + domain="[('project_id', '=', project_id)]" + /> + domain="[('project_id', '=', project_id)]" + /> @@ -88,7 +98,8 @@ name="view_ids" eval="[(5, 0, 0), (0, 0, {'view_mode': 'tree', 'view_id': ref('view_ps_sprint_task_tree2')}), - (0, 0, {'view_mode': 'form', 'view_id': ref('view_ps_sprint_task_form2')})]" /> + (0, 0, {'view_mode': 'form', 'view_id': ref('view_ps_sprint_task_form2')})]" + /> @@ -109,7 +120,8 @@ name="view_ids" eval="[(5, 0, 0), (0, 0, {'view_mode': 'tree', 'view_id': ref('view_ps_sprint_task_tree2')}), - (0, 0, {'view_mode': 'form', 'view_id': ref('view_ps_sprint_task_form2')})]" /> + (0, 0, {'view_mode': 'form', 'view_id': ref('view_ps_sprint_task_form2')})]" + /> @@ -122,7 +134,8 @@ name="view_ids" eval="[(5, 0, 0), (0, 0, {'view_mode': 'tree', 'view_id': ref('view_ps_sprint_task_tree2')}), - (0, 0, {'view_mode': 'form', 'view_id': ref('view_ps_sprint_task_form2')})]" /> + (0, 0, {'view_mode': 'form', 'view_id': ref('view_ps_sprint_task_form2')})]" + /> diff --git a/setup/project_scrum/odoo/addons/project_scrum b/setup/project_scrum/odoo/addons/project_scrum new file mode 120000 index 0000000..80f9edb --- /dev/null +++ b/setup/project_scrum/odoo/addons/project_scrum @@ -0,0 +1 @@ +../../../../project_scrum \ No newline at end of file diff --git a/setup/project_scrum/setup.py b/setup/project_scrum/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/project_scrum/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)