Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[16.0][ADD] project_scrum #1329

Merged
merged 1 commit into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions project_scrum/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
=============
Project Scrum
=============

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:1e5f918a26b23d5518e54987bea92f39913aa9d2f54c771f71a1c6572d5601ba
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproject-lightgray.png?logo=github
:target: https://github.com/OCA/project/tree/16.0/project_scrum
:alt: OCA/project
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/project-16-0/project-16-0-project_scrum
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/project&target_branch=16.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This addon allow you to manage your project with scrum methodology.

**Table of contents**

.. contents::
:local:

Usage
=====

This addon you can create and manage your project with scrum methodology.
For create a sprint you need to go to the project and click on the "Sprint" button.
You can create a sprint with a name, a start date, an end date, a project and a objetive.
You can create a sprint from configuration menu.
You can access the all options from the project options on kanban view or from project view form.
From the project options on kanban view you can access the sprint timeline view and the backlog view.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/project/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/project/issues/new?body=module:%20project_scrum%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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

Credits
=======

Authors
~~~~~~~

* Binhex

Contributors
~~~~~~~~~~~~

* `Binhex <https://www.binhex.cloud>_`:

* Adasat Torres de León <[email protected]>


Maintainers
~~~~~~~~~~~

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

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

.. |maintainer-adasatorres| image:: https://github.com/adasatorres.png?size=40px
:target: https://github.com/adasatorres
:alt: adasatorres

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-adasatorres|

This module is part of the `OCA/project <https://github.com/OCA/project/tree/16.0/project_scrum>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
3 changes: 3 additions & 0 deletions project_scrum/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from . import models
23 changes: 23 additions & 0 deletions project_scrum/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2024 Binhex - Adasat Torres de León (https://www.binhex.cloud)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

{
"name": "Project Scrum",
"version": "16.0.1.0.0",
"category": "Project",
"website": "https://github.com/OCA/project",
"author": "Binhex, Odoo Community Association (OCA)",
"license": "AGPL-3",
"installable": True,
"application": False,
"summary": "This addon allow use the scrum methodology in projects",
"depends": ["project_timeline"],
"data": [
"security/ir.model.access.csv",
"views/project_sprint_views.xml",
"views/project_task_views.xml",
"views/project_views.xml",
"data/ir_cron_data.xml",
],
"maintainers": ["adasatorres"],
}
14 changes: 14 additions & 0 deletions project_scrum/data/ir_cron_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="cron_update_sprint_state" model="ir.cron">
<field name="name">Update sprint state</field>
<field name="model_id" ref="model_project_sprint" />
<field name="interval_number">5</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="state">code</field>
<field name="code">
model.cron_update_sprint_state()
</field>
</record>
</odoo>
3 changes: 3 additions & 0 deletions project_scrum/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import project_sprint
from . import project
from . import project_task
65 changes: 65 additions & 0 deletions project_scrum/models/project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from odoo import _, fields, models


class ProjectProject(models.Model):
_inherit = "project.project"

sprint_ids = fields.One2many(
comodel_name="project.sprint",
inverse_name="project_id",
string="Sprints",
)
sprint_count = fields.Integer(compute="_compute_sprint_count")
backlog_count = fields.Integer(compute="_compute_backlog_count")

def _compute_backlog_count(self):
for project in self:
project.backlog_count = len(
project.task_ids.filtered(
lambda task: not task.sprint_id and task.kanban_state != "done"
)
)

def _compute_sprint_count(self):
unassigned_sprint_count = self.env["project.sprint"].search(
[("project_id", "=", False)], count=True
)
for project in self:
project.sprint_count = len(project.sprint_ids) + unassigned_sprint_count

def action_sprints(self):
self.ensure_one()
return {
"name": _("Sprints"),
"type": "ir.actions.act_window",
"res_model": "project.sprint",
"view_mode": "tree,form,timeline",
"domain": ["|", ("project_id", "=", self.id), ("project_id", "=", False)],
"context": {"default_project_id": self.id},
}

def action_backlog(self):
self.ensure_one()
return {
"name": _("Backlog"),
"type": "ir.actions.act_window",
"res_model": "project.task",
"view_mode": "tree,form",
"domain": [
("project_id", "=", self.id),
("sprint_id", "=", False),
("kanban_state", "!=", "done"),
],
"context": {"default_project_id": self.id},
}

def action_sprint_timeline(self):
self.ensure_one()
return {
"name": _("Sprint Timeline"),
"type": "ir.actions.act_window",
"res_model": "project.task",
"view_mode": "timeline",
"domain": [("project_id", "=", self.id), ("sprint_id", "!=", False)],
"context": {"default_project_id": self.id, "no_create": True},
}
132 changes: 132 additions & 0 deletions project_scrum/models/project_sprint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from dateutil.relativedelta import relativedelta

from odoo import _, api, fields, models

DATE_OPTIONS = [
("1_weeks", _("1 Week")),
("2_weeks", _("2 Weeks")),
("1_months", _("1 Month")),
("2_months", _("2 Month")),
("1_years", _("1 Year")),
("2_years", _("2 Years")),
("custom", _("Custom")),
]


class ProjectSprint(models.Model):
_name = "project.sprint"
_inherit = ["mail.thread", "mail.activity.mixin"]
_description = "Project Sprint"
_sql_constraints = [
(
"date_check",
"CHECK (date_start <= date_end)",
_("Error: End date must be greater than start date!"),
),
]

name = fields.Char(required=True, tracking=True)
user_ids = fields.Many2many(
comodel_name="res.users",
string="Members",
required=True,
domain="[('share', '=', False), ('active', '=', True)]",
tracking=True,
relation="project_sprint_user_rel",
)
description = fields.Text(tracking=True)
project_id = fields.Many2one(
comodel_name="project.project",
string="Project",
tracking=True,
)
task_ids = fields.One2many(
comodel_name="project.task",
inverse_name="sprint_id",
string="Tasks",
domain="[('project_id', '=', project_id)]",
)
date_start = fields.Date(
string="Start Date", default=fields.Date.today, required=True
)
date_option = fields.Selection(
selection=DATE_OPTIONS, default=DATE_OPTIONS[0][0], required=True
)
date_end = fields.Date(
string="End Date",
required=True,
compute="_compute_date_end",
store=True,
readonly=False,
)
state = fields.Selection(
selection=[
("draft", "Draft"),
("in_progress", "In progress"),
("done", "Done"),
],
default="draft",
)
tasks_count = fields.Integer(compute="_compute_tasks_count")

def _compute_tasks_count(self):
for sprint in self:
sprint.tasks_count = len(sprint.task_ids)

def action_start(self):
self.write({"state": "in_progress"})

def action_done(self):
self.write({"state": "done"})
self._check_task_state()

def action_tasks(self):
self.ensure_one()
return {
"name": _("Tasks"),
"type": "ir.actions.act_window",
"res_model": "project.task",
"view_mode": "tree,form",
"domain": [("sprint_id", "=", self.id)],
"context": {
"default_project_id": self.project_id.id,
"default_sprint_id": self.id,
},
}

@api.model
def cron_update_sprint_state(self):
date = fields.Date.today()
for sprint in self.search([("state", "=", "draft")]):
if date >= sprint.date_start:
sprint.write({"state": "in_progress"})

for sprint in self.search([("state", "=", "in_progress")]):
if date >= sprint.date_end:
sprint.write({"state": "done"})
sprint._check_task_state()

def _check_task_state(self):
self.ensure_one()
in_progress_sprints = self.project_id.sprint_ids.filtered(
lambda sprint: sprint.state == "in_progress"
)
self.task_ids.filtered(lambda task: task.kanban_state != "done").write(
{
"sprint_id": (
in_progress_sprints[0].id if in_progress_sprints else False
),
"user_ids": False,
}
)

@api.depends("date_start", "date_option")
def _compute_date_end(self):
for record in self:
if record.date_option != "custom":
num, interval = record.date_option.split("_")
record.date_end = record.date_start + relativedelta(
**{interval: int(num)}
)
else:
record.date_end = record.date_start + relativedelta(days=1)
30 changes: 30 additions & 0 deletions project_scrum/models/project_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class ProjectTask(models.Model):
_inherit = "project.task"

sprint_id = fields.Many2one(
comodel_name="project.sprint",
string="Sprint",
tracking=True,
domain="['|', ('project_id', '=', False), ('project_id', '=', project_id)]",
)

sprint_state = fields.Selection(
related="sprint_id.state", string="Sprint State", store=True
)

@api.constrains("user_ids")
def _check_user_ids(self):
for task in self:
if task.user_ids and task.sprint_id:
if not task.user_ids <= task.sprint_id.user_ids:
raise ValidationError(
_("The assignees must be part of the sprint.")
)

@api.onchange("sprint_id")
def _onchange_sprint_id(self):
self.user_ids = False
4 changes: 4 additions & 0 deletions project_scrum/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* `Binhex <https://www.binhex.cloud>_`:

* Adasat Torres de León <[email protected]>

1 change: 1 addition & 0 deletions project_scrum/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This addon allow you to manage your project with scrum methodology.
6 changes: 6 additions & 0 deletions project_scrum/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This addon you can create and manage your project with scrum methodology.
For create a sprint you need to go to the project and click on the "Sprint" button.
You can create a sprint with a name, a start date, an end date, a project and a objetive.
You can create a sprint from configuration menu.
You can access the all options from the project options on kanban view or from project view form.
From the project options on kanban view you can access the sprint timeline view and the backlog view.
3 changes: 3 additions & 0 deletions project_scrum/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_project_sprint_user,project.sprint.user,model_project_sprint,project.group_project_user,1,0,0,0
access_project_sprint_admin,project.sprint.admin,model_project_sprint,project.group_project_manager,1,1,1,1
Binary file added project_scrum/static/description/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading