[ADD]added project_scrum module

This commit is contained in:
Poojan
2021-04-06 11:07:19 +05:30
parent 0f352bf03b
commit c7a7a474fa
48 changed files with 6679 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import models

View File

@@ -0,0 +1,41 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Project Scrum',
'version': '2.0',
'category': 'Project',
'author': 'FlectraHQ',
'website': 'https://flectrahq.com',
'sequence': 40,
'summary': 'A module for Scrum implementation',
'depends': [
'project', 'resource'
],
'data': [
'security/ir.model.access.csv',
'views/other_views.xml',
'views/project_sprint_views.xml',
'views/project_story_views.xml',
'views/project_team_views.xml',
'views/release_planning_views.xml',
'views/cron_view.xml',
'views/retrospective_method_views.xml',
'views/retrospective_views.xml',
'report/project_scrum_report.xml',
'report/release_planning_template.xml',
'report/project_sprint_template.xml',
'data/sprint_sequence.xml',
'data/project_sprint_data.xml',
'data/project_task_sequence.xml',
],
'demo': [
'demo/project_scrum_demo.xml',
'demo/project_story_demo.xml',
'demo/project_release_planning_demo.xml',
'demo/retrospective_demo.xml',
'demo/project_task_demo.xml',
],
'license': 'LGPL-3',
'installable': True,
'auto_install': False
}

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<data noupdate="1">
<!-- Sprint-related subtypes for messaging / Chatter -->
<record id="state_sprint_draft" model="mail.message.subtype">
<field name="name">Sprint Draft</field>
<field name="res_model">project.sprint</field>
<field name="default" eval="True"/>
<field name="description">Sprint Draft</field>
</record>
<record id="state_sprint_in_progress" model="mail.message.subtype">
<field name="name">Sprint In Progress</field>
<field name="res_model">project.sprint</field>
<field name="default" eval="True"/>
<field name="description">Sprint In Progress</field>
</record>
<record id="state_sprint_pending" model="mail.message.subtype">
<field name="name">Sprint Pending</field>
<field name="res_model">project.sprint</field>
<field name="default" eval="True"/>
<field name="description">Sprint Pending</field>
</record>
<record id="state_sprint_done" model="mail.message.subtype">
<field name="name">Sprint Done</field>
<field name="res_model">project.sprint</field>
<field name="default" eval="True"/>
<field name="description">Sprint Done</field>
</record>
<record id="state_sprint_cancel" model="mail.message.subtype">
<field name="name">Sprint Cancel</field>
<field name="res_model">project.sprint</field>
<field name="default" eval="True"/>
<field name="description">Sprint Cancel</field>
</record>
<!-- Project-related subtypes for messaging / Chatter -->
<record id="state_project_sprint_draft" model="mail.message.subtype">
<field name="name">Sprint Draft</field>
<field name="sequence">10</field>
<field name="res_model">project.team</field>
<field name="default" eval="True"/>
<field name="parent_id" eval="ref('state_sprint_draft')"/>
<field name="relation_field">team_id</field>
</record>
<record id="state_project_sprint_in_progress" model="mail.message.subtype">
<field name="name">Sprint In Progress</field>
<field name="sequence">10</field>
<field name="res_model">project.team</field>
<field name="default" eval="True"/>
<field name="parent_id" eval="ref('state_sprint_in_progress')"/>
<field name="relation_field">team_id</field>
</record>
<record id="state_project_sprint_pending" model="mail.message.subtype">
<field name="name">Sprint Pending</field>
<field name="sequence">10</field>
<field name="res_model">project.team</field>
<field name="default" eval="True"/>
<field name="parent_id" eval="ref('state_sprint_pending')"/>
<field name="relation_field">team_id</field>
</record>
<record id="state_project_sprint_done" model="mail.message.subtype">
<field name="name">Sprint Done</field>
<field name="sequence">10</field>
<field name="res_model">project.team</field>
<field name="default" eval="True"/>
<field name="parent_id" eval="ref('state_sprint_done')"/>
<field name="relation_field">team_id</field>
</record>
<record id="state_project_sprint_cancel" model="mail.message.subtype">
<field name="name">Sprint Cancel</field>
<field name="sequence">10</field>
<field name="res_model">project.team</field>
<field name="default" eval="True"/>
<field name="parent_id" eval="ref('state_sprint_cancel')"/>
<field name="relation_field">team_id</field>
</record>
</data>
</flectra>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<data noupdate="1">
<record id="seq_tasks" model="ir.sequence">
<field name="name">Tasks</field>
<field name="code">project.task</field>
<field name="prefix">TSK</field>
<field name="padding">3</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
</record>
</data>
</flectra>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<data>
<!-- Sequence for Sprint -->
<record id="seq_sprint" model="ir.sequence">
<field name="name">Sprints</field>
<field name="code">project.sprint</field>
<field name="prefix">SP</field>
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
</data>
</flectra>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<flectra>
<data noupdate="1">
<!--
release.planning Demo Data
-->
<record id="release_planning_1" model="release.planning">
<field name="name">Release of Development</field>
<field name="release_date" eval="DateTime.today() - relativedelta(days=5,hours=20,minutes=2,seconds=10)"/>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
</record>
<record id="release_planning_2" model="release.planning">
<field name="name">Release of Design &amp; Documentation</field>
<field name="release_date" eval="DateTime.today() - relativedelta(days=3,hours=21,minutes=4,seconds=19)"/>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
</record>
<record id="release_planning_3" model="release.planning">
<field name="name">Release Access Rights Allocation</field>
<field name="release_date" eval="DateTime.today() + relativedelta(days=5,hours=22,minutes=5,seconds=25)"/>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
</record>
<record id="release_planning_4" model="release.planning">
<field name="name">Release Mail Configuration &amp; Improved Dashboard</field>
<field name="release_date" eval="DateTime.today() - relativedelta(days=25,hours=23,minutes=6,seconds=34)"/>
<field name="sprint_id" ref="project_scrum.project_sprint_3"/>
</record>
<record id="release_planning_5" model="release.planning">
<field name="name">Scrum Updates</field>
<field name="release_date" eval="DateTime.today() - relativedelta(days=6,hours=24,minutes=8,seconds=55)"/>
<field name="sprint_id" ref="project_scrum.project_sprint_3"/>
</record>
</data>
</flectra>

View File

@@ -0,0 +1,297 @@
<?xml version="1.0" encoding="UTF-8"?>
<flectra>
<data noupdate="1">
<!--
user.role Demo Data
-->
<record id="user_role_1" model="user.role">
<field name="name">Manager</field>
<field name="code">M</field>
</record>
<record id="user_role_2" model="user.role">
<field name="name">Developer</field>
<field name="code">D</field>
</record>
<record id="user_role_3" model="user.role">
<field name="name">Tester</field>
<field name="code">T</field>
</record>
<!--
res.users Demo Data
-->
<record id="user_1" model="res.users">
<field name="name">Chris Gardner</field>
<field name="login">chris@demo.com</field>
<field name="role_id" ref="project_scrum.user_role_1"/>
</record>
<record id="user_2" model="res.users">
<field name="name">Oskar Schindler</field>
<field name="login">oskar@demo.com</field>
<field name="role_id" ref="project_scrum.user_role_2"/>
</record>
<record id="user_3" model="res.users">
<field name="name">Andy Dufresne</field>
<field name="login">andy@demo.com</field>
<field name="role_id" ref="project_scrum.user_role_3"/>
</record>
<!-- Project -->
<record id="demo_project_1" model="project.project">
<field name="name">Project Scrum</field>
<field name="user_id" ref="base.user_root"/>
<field name="company_id" ref="base.main_company"/>
<field name="privacy_visibility">employees</field>
<field name="partner_id">1</field>
<field name="sequence">10</field>
<field name="resource_calendar_id">1</field>
<field name="type_ids"
eval="[(6, 0, [ref('project.project_stage_0'),
ref('project.project_stage_1'),
ref('project.project_stage_3'), ref('project.project_stage_2')])]"/>
</record>
<!--
project.team Demo Data
-->
<record id="project_team_1" model="project.team">
<field name="name">Project Module Team</field>
<field name="project_id" ref="demo_project_1"/>
<field name="member_ids" eval="[(6, 0, [ref('project_scrum.user_1'), ref('project_scrum.user_2')])]"/>
<field name="master_id" ref="project_scrum.user_1"/>
<field name="strength">Technical, Functional</field>
<field name="description">Description for the Project team...</field>
</record>
<record id="project_team_2" model="project.team">
<field name="name">Sales Team</field>
<field name="project_id" ref="demo_project_1"/>
<field name="member_ids"
eval="[(6, 0, [ref('project_scrum.user_1'), ref('project_scrum.user_2'), ref('project_scrum.user_3')])]"/>
<field name="master_id" ref="project_scrum.user_2"/>
<field name="strength">Functional</field>
<field name="description">Description for the Sales team...</field>
</record>
<record id="project_team_3" model="project.team">
<field name="name">Sales and Purchase Team</field>
<field name="project_id" ref="demo_project_1"/>
<field name="member_ids"
eval="[(6, 0, [ref('project_scrum.user_1'), ref('project_scrum.user_2'), ref('project_scrum.user_3')])]"/>
<field name="master_id" ref="project_scrum.user_3"/>
<field name="strength">Technical, Functional</field>
<field name="description">Description for the team...</field>
</record>
<record id="resource.resource_calendar_std" model="resource.calendar">
<field name="no_of_hours">8</field>
<field name="no_of_days">5</field>
</record>
<record id="resource.resource_calendar_std_35h" model="resource.calendar">
<field name="no_of_hours">7</field>
<field name="no_of_days">5</field>
</record>
<!--
project.sprint Demo Data
-->
<record id="project_sprint_1" model="project.sprint">
<field name="project_id" ref="demo_project_1"/>
<field name="name">Module Development</field>
<field name="state">draft</field>
<field name="team_id" ref="project_scrum.project_team_1"/>
<field name="start_date" eval="(DateTime.today() - relativedelta(days=8))"/>
<field name="end_date" eval="(DateTime.today() + relativedelta(days=8))"/>
<field name="goal_of_sprint">Develop Module with Documentation</field>
<field name="hour">11</field>
<field name="time_zone">am</field>
<field name="meeting_date" eval="(DateTime.today() - relativedelta(days=8))"/>
<field name="productivity_hours">8.00</field>
<field name="holiday_type">hours</field>
<field name="holiday_count">1.00</field>
</record>
<record id="project_sprint_2" model="project.sprint">
<field name="project_id" ref="demo_project_1"/>
<field name="name">Access Rights &amp; Testing</field>
<field name="state">in_progress</field>
<field name="team_id" ref="project_scrum.project_team_2"/>
<field name="start_date" eval="(DateTime.today() + relativedelta(days=8))"/>
<field name="end_date" eval="(DateTime.today() + relativedelta(days=22))"/>
<field name="goal_of_sprint">Access Rights Allocation</field>
<field name="hour">15</field>
<field name="time_zone">pm</field>
<field name="meeting_date" eval="(DateTime.today() + relativedelta(days=8))"/>
<field name="productivity_hours">7.00</field>
<field name="holiday_type">hours</field>
<field name="holiday_count">1.00</field>
</record>
<record id="project_sprint_3" model="project.sprint">
<field name="project_id" ref="demo_project_1"/>
<field name="name">Implement Mailing Functionality</field>
<field name="state">cancel</field>
<field name="team_id" ref="project_scrum.project_team_3"/>
<field name="start_date" eval="(DateTime.today() + relativedelta(days=22))"/>
<field name="end_date" eval="(DateTime.today() + relativedelta(days=36))"/>
<field name="goal_of_sprint">Mailing and Workflow</field>
<field name="hour">15</field>
<field name="time_zone">pm</field>
<field name="meeting_date" eval="(DateTime.today() + relativedelta(days=22))"/>
<field name="productivity_hours">7.00</field>
<field name="holiday_type">hours</field>
<field name="holiday_count">1.00</field>
</record>
<record id="project_sprint_4" model="project.sprint">
<field name="project_id" ref="demo_project_1"/>
<field name="name">Dashboard Improvements</field>
<field name="state">in_progress</field>
<field name="team_id" ref="project_scrum.project_team_3"/>
<field name="start_date" eval="(DateTime.today() + relativedelta(days=38))"/>
<field name="end_date" eval="(DateTime.today() + relativedelta(days=52))"/>
<field name="goal_of_sprint">Exclusive Dashboard</field>
<field name="hour">10</field>
<field name="time_zone">am</field>
<field name="meeting_date" eval="(DateTime.today() + relativedelta(days=38))"/>
<field name="productivity_hours">7.00</field>
<field name="holiday_type">hours</field>
<field name="holiday_count">1.00</field>
</record>
<record id="project_sprint_5" model="project.sprint">
<field name="project_id" ref="demo_project_1"/>
<field name="name">Project Integration</field>
<field name="state">pending</field>
<field name="team_id" ref="project_scrum.project_team_1"/>
<field name="start_date" eval="(DateTime.today() + relativedelta(days=52))"/>
<field name="end_date" eval="(DateTime.today() + relativedelta(days=66))"/>
<field name="goal_of_sprint">Integrating Project</field>
<field name="hour">12</field>
<field name="time_zone">pm</field>
<field name="meeting_date" eval="(DateTime.today() + relativedelta(days=52))"/>
<field name="productivity_hours">7.00</field>
<field name="holiday_type">hours</field>
<field name="holiday_count">1.00</field>
</record>
<!--
sprint.planning.line Demo Data
-->
<record id="sprint_planning_line_1" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_1"/>
<field name="role_id" ref="project_scrum.user_role_1"/>
<field name="available_per">100</field>
<field name="off_hours">10.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
</record>
<record id="sprint_planning_line_2" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_2"/>
<field name="role_id" ref="project_scrum.user_role_2"/>
<field name="available_per">80</field>
<field name="off_hours">8.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
</record>
<record id="sprint_planning_line_3" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_3"/>
<field name="role_id" ref="project_scrum.user_role_2"/>
<field name="available_per">40</field>
<field name="off_hours">4.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
</record>
<record id="sprint_planning_line_4" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_1"/>
<field name="role_id" ref="project_scrum.user_role_3"/>
<field name="available_per">95</field>
<field name="off_hours">1.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
</record>
<record id="sprint_planning_line_5" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_2"/>
<field name="role_id" ref="project_scrum.user_role_2"/>
<field name="available_per">90</field>
<field name="off_hours">1.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
</record>
<record id="sprint_planning_line_6" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_3"/>
<field name="role_id" ref="project_scrum.user_role_2"/>
<field name="available_per">90</field>
<field name="off_hours">1.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
</record>
<record id="sprint_planning_line_7" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_1"/>
<field name="role_id" ref="project_scrum.user_role_1"/>
<field name="available_per">80</field>
<field name="off_hours">2.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_3"/>
</record>
<record id="sprint_planning_line_8" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_2"/>
<field name="role_id" ref="project_scrum.user_role_2"/>
<field name="available_per">80</field>
<field name="off_hours">1.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_3"/>
</record>
<record id="sprint_planning_line_9" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_3"/>
<field name="role_id" ref="project_scrum.user_role_3"/>
<field name="available_per">90</field>
<field name="off_hours">1.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_3"/>
</record>
<record id="sprint_planning_line_10" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_1"/>
<field name="role_id" ref="project_scrum.user_role_1"/>
<field name="available_per">90</field>
<field name="off_hours">1.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_4"/>
</record>
<record id="sprint_planning_line_11" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_2"/>
<field name="role_id" ref="project_scrum.user_role_2"/>
<field name="available_per">100</field>
<field name="off_hours">1.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_4"/>
</record>
<record id="sprint_planning_line_12" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_3"/>
<field name="role_id" ref="project_scrum.user_role_3"/>
<field name="available_per">80</field>
<field name="off_hours">2.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_4"/>
</record>
<record id="sprint_planning_line_13" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_1"/>
<field name="role_id" ref="project_scrum.user_role_1"/>
<field name="available_per">90</field>
<field name="off_hours">2.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_5"/>
</record>
<record id="sprint_planning_line_14" model="sprint.planning.line">
<field name="user_id" ref="project_scrum.user_3"/>
<field name="role_id" ref="project_scrum.user_role_3"/>
<field name="available_per">90</field>
<field name="off_hours">1.00</field>
<field name="sprint_id" ref="project_scrum.project_sprint_5"/>
</record>
</data>
</flectra>

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<flectra>
<data noupdate="1">
<!--
story.priority Demo Data
-->
<record id="story_priority_1" model="story.priority">
<field name="name">High</field>
<field name="code">HIGH</field>
</record>
<record id="story_priority_2" model="story.priority">
<field name="name">Medium</field>
<field name="code">MEDIUM</field>
</record>
<record id="story_priority_3" model="story.priority">
<field name="name">Low</field>
<field name="code">LOW</field>
</record>
<!--
story.type Demo Data
-->
<record id="story_type_1" model="story.type">
<field name="name">Descriptive Story</field>
<field name="code">Desc</field>
</record>
<record id="story_type_2" model="story.type">
<field name="name">Brief Story</field>
<field name="code">Brief</field>
</record>
<!--
project.story Demo Data
-->
<record id="project_story_1" model="project.story">
<field name="name">Development</field>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
<field name="priority_id" ref="project_scrum.story_priority_2"/>
<field name="story_type_id" ref="project_scrum.story_type_2"/>
<field name="description">Begin development...</field>
</record>
<record id="project_story_2" model="project.story">
<field name="name">Designing</field>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
<field name="priority_id" ref="project_scrum.story_priority_2"/>
<field name="story_type_id" ref="project_scrum.story_type_1"/>
<field name="description">Begin Designing...</field>
</record>
<record id="project_story_3" model="project.story">
<field name="name">Testing Workflow</field>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
<field name="priority_id" ref="project_scrum.story_priority_1"/>
<field name="story_type_id" ref="project_scrum.story_type_2"/>
<field name="description">Workflow testing...</field>
</record>
</data>
</flectra>

View File

@@ -0,0 +1,236 @@
<?xml version="1.0" encoding="UTF-8"?>
<flectra>
<data>
<!--
project.task Demo Data
-->
<record id="project_task_1" model="project.task">
<field name="name">Creating Objects</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=5)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
<field name="start_date" eval="DateTime.today() - relativedelta(days=5)"/>
<field name="end_date" eval="DateTime.today() - relativedelta(days=2)"/>
<field name="story_id" ref="project_scrum.project_story_2"/>
<field name="velocity">30</field>
<field name="release_planning_id" ref="project_scrum.release_planning_1"/>
<field name="description">Creating necessary objects...</field>
<field name="sequence">11</field>
<field name="partner_id">1</field>
</record>
<record id="project_task_2" model="project.task">
<field name="name">Creating Views</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">0</field>
<field name="date_deadline" eval="DateTime.today()"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
<field name="start_date" eval="DateTime.today() - relativedelta(days=2)"/>
<field name="end_date" eval="DateTime.today()"/>
<field name="story_id" ref="project_scrum.project_story_1"/>
<field name="velocity">20</field>
<field name="release_planning_id" ref="project_scrum.release_planning_2"/>
<field name="description">Creating view for objects...</field>
<field name="sequence">12</field>
<field name="partner_id">1</field>
<field name="stage_id" ref="project.project_stage_2"/>
</record>
<record id="project_task_3" model="project.task">
<field name="name">Access Rights</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=15)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=10)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=13)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">15</field>
<field name="release_planning_id" ref="project_scrum.release_planning_3"/>
<field name="description">Necessary rights for different objects...</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
<field name="stage_id" ref="project.project_stage_2"/>
</record>
<record id="project_task_4" model="project.task">
<field name="name">Creating Mail Templates</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=27)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_3"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=25)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=27)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">15</field>
<field name="release_planning_id" ref="project_scrum.release_planning_4"/>
<field name="description">Create different mail templates...</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
<field name="stage_id" ref="project.project_stage_2"/>
</record>
<record id="project_task_6" model="project.task">
<field name="name">Mailing Functionality</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=31)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_3"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=29)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=31)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">20</field>
<field name="release_planning_id" ref="project_scrum.release_planning_5"/>
<field name="description">Send Mails....</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
</record>
<record id="project_task_7" model="project.task">
<field name="name">Rights division for different modules</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=4)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=1)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=4)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">25</field>
<field name="release_planning_id" ref="project_scrum.release_planning_5"/>
<field name="description">Rights division...</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
</record>
<record id="project_task_8" model="project.task">
<field name="name">Rights allocation</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=15)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=13)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=15)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">30</field>
<field name="release_planning_id" ref="project_scrum.release_planning_1"/>
<field name="description">Rights Allocation...</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
</record>
<record id="project_task_9" model="project.task">
<field name="name">Testing with different Users</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=18)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=16)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=18)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">25</field>
<field name="release_planning_id" ref="project_scrum.release_planning_2"/>
<field name="description">Testing with different users to ensure users have got the necessary access...</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
<field name="stage_id" ref="project.project_stage_2"/>
</record>
<record id="project_task_10" model="project.task">
<field name="name">Dashboard Design</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=43)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_4"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=40)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=43)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">35</field>
<field name="release_planning_id" ref="project_scrum.release_planning_3"/>
<field name="description">Design for dashboard...</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
</record>
<record id="project_task_11" model="project.task">
<field name="name">View Rendering</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=47)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_4"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=43)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=47)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">20</field>
<field name="release_planning_id" ref="project_scrum.release_planning_4"/>
<field name="description">Render views...</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
<field name="stage_id" ref="project.project_stage_2"/>
</record>
<record id="project_task_12" model="project.task">
<field name="name">Enhancements</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=51)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_4"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=48)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=51)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">25</field>
<field name="release_planning_id" ref="project_scrum.release_planning_5"/>
<field name="description">Improvements for dashboard....</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
<field name="stage_id" ref="project.project_stage_2"/>
</record>
<record id="project_task_13" model="project.task">
<field name="name">Objects Integration</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=55)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_5"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=53)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=55)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">25</field>
<field name="release_planning_id" ref="project_scrum.release_planning_1"/>
<field name="description">Integrate objects....</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
</record>
<record id="project_task_14" model="project.task">
<field name="name">View Enhancements</field>
<field name="project_id" ref="demo_project_1"/>
<field name="priority">1</field>
<field name="date_deadline" eval="DateTime.today() + relativedelta(days=58)"/>
<field name="company_id">1</field>
<field name="sprint_id" ref="project_scrum.project_sprint_5"/>
<field name="start_date" eval="DateTime.today() + relativedelta(days=56)"/>
<field name="end_date" eval="DateTime.today() + relativedelta(days=58)"/>
<field name="story_id" ref="project_scrum.project_story_3"/>
<field name="velocity">20</field>
<field name="release_planning_id" ref="project_scrum.release_planning_2"/>
<field name="description">View Enhancements...</field>
<field name="sequence">13</field>
<field name="partner_id">1</field>
<field name="stage_id" ref="project.project_stage_2"/>
</record>
</data>
</flectra>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<flectra>
<data noupdate="1">
<!--
retrospective.method Demo Data
-->
<record id="retrospective_method_1" model="retrospective.method">
<field name="name">Went Well</field>
<field name="description">Whatever we developed or improved, it went well</field>
</record>
<record id="retrospective_method_2" model="retrospective.method">
<field name="name">Needs Improvement</field>
<field name="description">We have found some some tasks or ideas, which needs improvements</field>
</record>
<record id="retrospective_method_3" model="retrospective.method">
<field name="name">Stop</field>
<field name="description">Now Stop Working of worthless task and go through new ideas we found.</field>
</record>
<!--
retrospective Demo Data
-->
<record id="retrospective_1" model="retrospective">
<field name="name">Sprint Module Retrospective</field>
<field name="retrospective_method_id" ref="project_scrum.retrospective_method_1"/>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
</record>
<record id="retrospective_2" model="retrospective">
<field name="name">Scrum Documentation Retrospective</field>
<field name="retrospective_method_id" ref="project_scrum.retrospective_method_2"/>
<field name="sprint_id" ref="project_scrum.project_sprint_1"/>
</record>
<record id="retrospective_3" model="retrospective">
<field name="name">Access Right Retrospective</field>
<field name="retrospective_method_id" ref="project_scrum.retrospective_method_2"/>
<field name="sprint_id" ref="project_scrum.project_sprint_2"/>
</record>
<!--
retrospective.lines Demo Data
-->
<record id="retrospective_line_1" model="retrospective.lines">
<field name="message">Tasks have been done well.</field>
<field name="retrospective_id" ref="project_scrum.retrospective_1"/>
</record>
<record id="retrospective_line_2" model="retrospective.lines">
<field name="message">Add new description as per new added modules.</field>
<field name="retrospective_id" ref="project_scrum.retrospective_2"/>
</record>
<record id="retrospective_line_3" model="retrospective.lines">
<field name="message">Implement New Access Rights according to the new modules added</field>
<field name="retrospective_id" ref="project_scrum.retrospective_3"/>
</record>
</data>
</flectra>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import project_sprint
from . import project_story
from . import project_team
from . import release_planning
from . import retrospective_method
from . import retrospective

View File

@@ -0,0 +1,653 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import models, fields, api, _
from flectra.exceptions import ValidationError
from datetime import datetime, timedelta, date
class ProjectSprint(models.Model):
_name = "project.sprint"
_inherit = 'mail.thread'
_description = "Sprint of the Project"
_rec_name = 'sprint_seq'
sprint_seq = fields.Char(
string="Reference", readonly=True)
name = fields.Char("Sprint Name", required=True,
tracking=True)
goal_of_sprint = fields.Char("Goal of Sprint", tracking=True)
meeting_date = fields.Datetime("Planning Meeting Date", required=True,
tracking=True)
hour = fields.Float(string="Hour", tracking=True)
time_zone = fields.Selection([
('am', 'AM'),
('pm', 'PM'),
], tracking=True)
estimated_velocity = fields.Integer(
compute="_compute_calculate_estimated_velocity", string="Estimated Velocity",
store=True, tracking=True)
actual_velocity = fields.Integer(
compute="_compute_calculate_actual_velocity", string="Actual Velocity",
store=True, tracking=True)
sprint_planning_line = fields.One2many(
'sprint.planning.line', 'sprint_id', string="Sprint Planning Lines")
project_id = fields.Many2one('project.project', string="Project",
tracking=True)
start_date = fields.Date(string="Start Date", tracking=True)
end_date = fields.Date(string="End Date", tracking=True)
working_days = fields.Integer(
compute="_compute_calculate_business_days", string="Business Days",
store=True, tracking=True)
productivity_hours = fields.Float(string="Productivity Hours",
tracking=True)
productivity_per = fields.Float(
compute="_compute_calculate_productivity_per", string="Productivity (%)",
store=True, tracking=True)
holiday_type = fields.Selection(
[('hours', 'Hours'), ('days', 'Days')],
string="Holiday (Hours / Days)", default='hours',
tracking=True)
holiday_count = fields.Float(string="Holiday Count",
tracking=True)
holiday_days = fields.Float(
compute="_compute_calculate_holiday_days", string="Holiday Days", store=True,
tracking=True)
state = fields.Selection([
('draft', 'Draft'),
('in_progress', 'In Progress'),
('pending', 'Pending'),
('done', 'Done'),
('cancel', 'Cancel')], string="State", default='draft',
tracking=True)
team_id = fields.Many2one('project.team', string="Team",
tracking=True, required=True)
task_line = fields.One2many('project.task', 'sprint_id', string='Tasks')
color = fields.Integer('Color Index')
task_count = fields.Integer(compute='_compute_task_count', store=True)
@api.depends("task_line")
def _compute_task_count(self):
for record in self:
record.task_count = len(record.task_line)
duration = fields.Integer(
"Duration (In Days)", compute='_compute_days_calculate', store=True,
tracking=True)
@api.depends("start_date")
def _compute_days_calculate(self):
for days in self:
if days.start_date and days.end_date:
diff = datetime.strptime(
str(days.end_date), '%Y-%m-%d').date() - datetime.strptime(
str(days.start_date), '%Y-%m-%d').date()
days.duration = diff.days
def _compute_get_task_count(self):
for record in self:
record.number_of_tasks = record.env['project.task'].search_count([
('sprint_id', '=', record.id)])
number_of_tasks = fields.Integer(
string="# of tasks", compute="_compute_get_task_count")
def _compute_get_story_count(self):
for record in self:
count = record.env['project.story'].search_count([
('sprint_id', '=', record.id)])
record.number_of_stories = count
number_of_stories = fields.Integer(
string="# of stories", compute="_compute_get_story_count")
def _compute_get_retrospective_count(self):
for record in self:
count = record.env['retrospective'].search_count([
('sprint_id', '=', record.id)])
record.number_of_retrospectives = count
number_of_retrospectives = fields.Integer(
string="# of Retrospectives", compute="_compute_get_retrospective_count")
@api.depends('task_line', 'task_line.stage_id', 'task_line.sprint_id',
'estimated_velocity', 'start_date', 'end_date', 'project_id',
'team_id')
def _compute_calculate_tasks_json(self):
data = []
for record in self:
task_ids = self.env['project.task'].search([
('sprint_id', '=', record.id)])
velocity = record.estimated_velocity or 1.0
for task in task_ids:
data.append({
'task': task.task_seq or '/',
'velocity': task.velocity or 0,
'per': round(((float(task.velocity) * 100) / float(
velocity)), 2)
})
record.tasks_json = data
tasks_json = fields.Char(
string="Tasks", compute="_compute_calculate_tasks_json", store=True)
def get_data(self):
task_dict_list = []
for record in self:
task_pool = self.env['project.task'].search([
('sprint_id', '=', record.id)])
for task in task_pool:
task_dict = {
'reference': task.task_seq,
'name': task.name,
'velocity': task.velocity,
'start_date': task.start_date,
'end_date': task.end_date,
'actual_end_date': task.actual_end_date,
'assigned_to': task.user_id.name,
'state': task.stage_id.name,
}
task_dict_list.append(task_dict)
return task_dict_list
def set_state_open(self):
self.state = 'in_progress'
def set_state_cancel(self):
self.state = 'cancel'
def set_state_pending(self):
self.state = 'pending'
def redirect_to_view(self, model, caption):
return {
'name': (_(caption)),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': model,
'domain': [('sprint_id', '=', self.id)],
'context': {
'default_sprint_id': self.id,
'default_project_id': self.project_id.id
}
}
def action_view_tasks(self):
return self.redirect_to_view("project.task", "Tasks")
def action_view_stories(self):
return self.redirect_to_view("project.story", "Stories")
def action_view_release_planning(self):
return self.redirect_to_view("release.planning", "Release Planning")
def action_view_retrospective(self):
return self.redirect_to_view("retrospective", "Retrospective")
@api.constrains('start_date', 'end_date')
def check_dates(self):
if self.start_date and self.end_date and (
self.start_date > self.end_date):
raise ValidationError(
"Start Date can not be greater than End date, Dude!")
@api.onchange('holiday_type')
def onchange_holiday_type(self):
self.holiday_count = 0.0
self.holiday_days = 0.0
@api.depends('project_id', 'project_id.no_of_days', 'start_date',
'end_date')
def _compute_calculate_business_days(self):
for record in self:
if record.start_date and record.end_date:
days_dict = {
0: (1, 2, 3, 4, 5, 6, 7),
1: (2, 3, 4, 5, 6, 7),
2: (3, 4, 5, 6, 7),
3: (4, 5, 6, 7),
4: (5, 6, 7),
5: (6, 7),
6: (7,),
7: (),
}
start = datetime.strptime(str(record.start_date), "%Y-%m-%d").date()
end = datetime.strptime(str(record.end_date), "%Y-%m-%d").date()
delta = timedelta(days=1)
days = 0
if record.project_id and end > start:
working_days = record.project_id.no_of_days
non_working_days = days_dict[working_days]
while end != start:
end -= delta
if end.isoweekday() not in non_working_days:
days += 1
record.working_days = days
@api.depends('project_id', 'project_id.no_of_hours', 'productivity_hours')
def _compute_calculate_productivity_per(self):
for record in self:
project_id = record.project_id
no_of_hours = project_id.no_of_hours if project_id else 0
prod_hours = record.productivity_hours
if project_id and no_of_hours > 0 and prod_hours:
record.productivity_per = (prod_hours / no_of_hours) * 100
@api.depends('project_id', 'project_id.no_of_hours', 'holiday_count')
def _compute_calculate_holiday_days(self):
for record in self:
if record.holiday_type == 'days' and record.project_id:
hours = record.holiday_count * record.project_id.no_of_hours
record.holiday_days = hours
@api.depends('project_id', 'task_line', 'task_line.velocity')
def _compute_calculate_estimated_velocity(self):
for record in self:
task_ids = record.env['project.task'].search([
('sprint_id', '=', record.id)
])
total_velocity = sum([
task.velocity for task in task_ids if task.velocity])
record.estimated_velocity = total_velocity
@api.depends('project_id', 'end_date', 'task_line', 'task_line.velocity',
'task_line.stage_id')
def _compute_calculate_actual_velocity(self):
for record in self:
task_ids = record.env['project.task'].search([
('sprint_id', '=', record.id),
('actual_end_date', '<=', record.end_date),
])
total_velocity = sum([
task.velocity for task in task_ids if task.velocity])
record.actual_velocity = total_velocity
@api.onchange('duration')
def onchange_start_date(self):
if self.start_date:
end_date = datetime.strptime(
str(self.start_date), '%Y-%m-%d') + timedelta(days=self.duration)
self.end_date = end_date
def check_sprint_state(self):
for record in self.search([('state', '!=', 'done')]):
if record.end_date and record.end_date < fields.Date.today():
record.state = 'done'
@api.constrains('sprint_planning_line')
def check_users_in_planning_line(self):
user_list = []
for user in self.sprint_planning_line:
if user.user_id.id not in user_list:
user_list.append(user.user_id.id)
else:
raise ValidationError(
"You can't add the same user twice in Sprint Planning!")
@api.model
def create(self, vals):
vals['sprint_seq'] = self.env[
'ir.sequence'].next_by_code('project.sprint')
res = super(ProjectSprint, self).create(vals)
partner_list = []
mail_channel_id = self.env['mail.channel'].sudo().search([
('name', '=', 'Project Sprint')
])
if mail_channel_id:
mail_channel_ids = self.env['mail.followers'].sudo().search([
('channel_id', '=', mail_channel_id.id),
('res_model', '=', res._name),
('res_id', '=', res.id),
])
if not mail_channel_ids:
self.env['mail.followers'].sudo().create({
'channel_id': mail_channel_id.id,
'res_model': res._name,
'res_id': res.id,
})
if 'team_id' in vals:
team_id = self.env['project.team'].browse(vals['team_id'])
partner_list += [member.partner_id.id
for member in team_id.member_ids]
for follower in partner_list:
if follower:
mail_follower_ids = self.env['mail.followers'].sudo().search([
('res_id', '=', res.id),
('partner_id', '=', follower),
('res_model', '=', res._name),
])
if not mail_follower_ids:
self.env['mail.followers'].sudo().create({
'res_id': res.id,
'res_model': res._name,
'partner_id': follower,
'team_id': team_id.id,
})
return res
def write(self, vals):
res = super(ProjectSprint, self).write(vals)
if 'team_id' in vals:
team_id = self.env['project.team'].browse(vals['team_id'])
else:
team_id = self.team_id
delete_team_id = self.env['mail.followers'].sudo().search([
('team_id', '!=', team_id.id),
('res_id', '=', self.id),
])
delete_team_id.unlink()
partner_list = [member.partner_id.id for member in team_id.member_ids]
for follower in partner_list:
if follower:
mail_follower_ids = self.env['mail.followers'].sudo().search([
('res_id', '=', self.id),
('partner_id', '=', follower),
('res_model', '=', self._name),
])
if not mail_follower_ids:
self.env['mail.followers'].sudo().create({
'res_id': self.id,
'res_model': self._name,
'partner_id': follower,
'team_id': team_id.id,
})
return res
def _track_subtype(self, init_values):
self.ensure_one()
if 'state' in init_values and self.state == 'draft':
return self.env.ref('project_scrum.state_sprint_draft')
elif 'state' in init_values and self.state == 'in_progress':
return self.env.ref('project_scrum.state_sprint_in_progress')
elif 'state' in init_values and self.state == 'pending':
return self.env.ref('project_scrum.state_sprint_pending')
elif 'state' in init_values and self.state == 'done':
return self.env.ref('project_scrum.state_sprint_done')
elif 'state' in init_values and self.state == 'cancel':
return self.env.ref('project_scrum.state_sprint_cancel')
return super(ProjectSprint, self)._track_subtype(init_values)
class Project(models.Model):
_inherit = "project.project"
def _compute_sprint_count(self):
for project in self:
count = project.env['project.sprint'].search_count([
('project_id', '=', project.id)
])
project.sprint_count = count
sprint_count = fields.Integer(
compute="_compute_sprint_count", string="No. of sprints related to")
def show_sprints(self):
self.ensure_one()
return {
'name': ("Sprints"),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'project.sprint',
'domain': [('project_id', '=', self.id)]
}
no_of_hours = fields.Integer(
related="resource_calendar_id.no_of_hours",
string="Working Hour(s) per Day", store=True)
no_of_days = fields.Integer(
related="resource_calendar_id.no_of_days",
string="Working Day(s) per Week", store=True)
task_type_ids = fields.Many2many(
'project.task.type', 'project_task_type_rel', 'project_id', 'type_id',
string='Project(s)')
class SprintPlanningLine(models.Model):
_name = "sprint.planning.line"
@api.depends('available_per', 'sprint_id.project_id',
'sprint_id.project_id.no_of_hours',
'sprint_id', 'sprint_id.working_days')
def _compute_calculate_hours(self):
for record in self:
project_id = record.sprint_id.project_id
no_of_hours = project_id and project_id.no_of_hours or 0.0
calc = (record.available_per *
record.sprint_id.working_days * no_of_hours) / 100
record.productivity_hours = float(calc)
@api.depends('sprint_id', 'available_per', 'sprint_id.working_days',
'sprint_id.productivity_hours')
def _compute_calculate_sprint_hours(self):
for record in self:
hours = (record.available_per * record.sprint_id.working_days *
record.sprint_id.productivity_hours) / 100
record.sprint_hours = hours
@api.depends('sprint_id', 'sprint_id.holiday_count',
'sprint_id.holiday_days', 'sprint_hours', 'off_hours')
def _compute_calculate_total_hours(self):
for record in self:
if record.sprint_id.holiday_type == 'hours':
hours = (record.sprint_hours - record.sprint_id.holiday_count -
record.off_hours)
else:
hours = (record.sprint_hours - record.sprint_id.holiday_days -
record.off_hours)
record.total_hours = hours
sprint_id = fields.Many2one('project.sprint', string="Sprint")
user_id = fields.Many2one('res.users', string="User")
role_id = fields.Many2one(
related="user_id.role_id", string="Role", store=True)
available_per = fields.Integer(string="Available (%)")
productivity_hours = fields.Float(
compute="_compute_calculate_hours", string="Productivity Hour(s)", store=True)
sprint_hours = fields.Float(
compute="_compute_calculate_sprint_hours", string="Sprint Hour(s)", store=True)
off_hours = fields.Float(string="Off Hour(s)")
total_hours = fields.Float(
compute="_compute_calculate_total_hours", string="Total Hour(s)", store=True)
class UserRole(models.Model):
_name = "user.role"
name = fields.Char(string="Role")
code = fields.Char(string="Code")
class ResUsers(models.Model):
_inherit = "res.users"
role_id = fields.Many2one("user.role", string="User Role")
class ProjectTask(models.Model):
_inherit = "project.task"
sprint_id = fields.Many2one(
'project.sprint', string="Sprint", tracking=True)
velocity = fields.Integer(string="Velocity", tracking=True)
story_id = fields.Many2one(
'project.story', string="Story", tracking=True)
release_planning_id = fields.Many2one(
"release.planning", string="Release Planning",
tracking=True)
start_date = fields.Date(string="Start Date", tracking=True)
end_date = fields.Date(string="End Date", tracking=True)
actual_end_date = fields.Date(
compute='_compute_calculate_actual_end_date', string="Actual End Date",
store=True, tracking=True
)
task_seq = fields.Char(
string="Reference", tracking=True,
default=lambda self: self.env['ir.sequence'].next_by_code(
'project.task') or '/')
@api.depends('stage_id')
def _compute_calculate_actual_end_date(self):
for stage in self:
if stage.stage_id.name == 'Done':
stage.actual_end_date = date.today()
@api.onchange('story_id')
def onchange_story(self):
if self.story_id:
self.description = self.story_id.description
@api.constrains('start_date', 'end_date')
def check_dates(self):
if self.sprint_id:
start_date = self.sprint_id.start_date
end_date = self.sprint_id.end_date
if self.start_date and start_date and (
self.start_date < start_date):
raise ValidationError(
"Start date is not valid according to the Sprint.")
if self.end_date and end_date and (self.end_date > end_date):
raise ValidationError(
"End date is not valid according to the Sprint.")
@api.model
def create(self, vals):
res = super(ProjectTask, self).create(vals)
partner_list = [
member.partner_id.id
for member in res.sprint_id.team_id.member_ids
]
for follower in partner_list:
if follower:
mail_follower_ids = self.env['mail.followers'].sudo().search([
('res_id', '=', res.id),
('partner_id', '=', follower),
('res_model', '=', self._name),
])
if not mail_follower_ids:
self.env['mail.followers'].sudo().create({
'res_id': res.id,
'res_model': self._name,
'partner_id': follower,
'team_id': res.sprint_id.team_id.id,
})
return res
def write(self, vals):
res = super(ProjectTask, self).write(vals)
if len(self._ids) == 0:
if self.task_seq == '/':
vals['task_seq'] = self.env['ir.sequence'].next_by_code(
'project.task')
data = []
for record in self:
task_ids = self.search([
('sprint_id', '=', record.sprint_id.id)])
for task in task_ids:
data.append({
'task': task.task_seq or '/',
'velocity': task.velocity or 0,
'per': round(((float(task.velocity) * 100) / float(
record.sprint_id.estimated_velocity)), 2)
if record.sprint_id.estimated_velocity > 0 else 0
})
record.sprint_id.write({'tasks_json': data})
if 'sprint_id' in vals:
sprint_id = self.env['project.sprint'].browse(vals['sprint_id'])
team_id = sprint_id.team_id
else:
team_id = self.sprint_id.team_id
delete_team_id = self.env['mail.followers'].sudo().search([
('team_id', '!=', team_id.id),
('res_id', '=', self.id),
])
delete_team_id.unlink()
partner_list = [member.partner_id.id for member in team_id.member_ids]
for follower in partner_list:
if follower:
mail_follower_ids = self.env['mail.followers'].sudo().search([
('res_id', '=', self.id),
('partner_id', '=', follower),
('res_model', '=', self._name),
])
if not mail_follower_ids:
self.env['mail.followers'].sudo().create({
'res_id': self.id,
'res_model': self._name,
'partner_id': follower,
'team_id': team_id.id,
})
return res
class MailFollowers(models.Model):
_inherit = "mail.followers"
team_id = fields.Many2one("project.team", string="Project Team")
class ResourceCalendar(models.Model):
_inherit = "resource.calendar"
no_of_hours = fields.Integer(string="No. of Hour(s) a Day", default=8)
no_of_days = fields.Integer(string="No. of Day(s) a Week", default=5)
@api.constrains('no_of_hours', 'no_of_days', 'attendance_ids')
def _check_days_hours(self):
week_days = {
0: 'Monday',
1: 'Tuesday',
2: 'Wednesday',
3: 'Thursday',
4: 'Friday',
5: 'Saturday',
6: 'Sunday'
}
for resource in self:
res = {}
current_hours = resource.no_of_hours
current_days = resource.no_of_days
if current_days > 7 or current_days < 1:
raise ValidationError(_(
"No. of Days should be in between 1 - 7."))
for attendance in resource.attendance_ids:
day = attendance.dayofweek
diff = abs(attendance.hour_from - attendance.hour_to)
if day not in res:
res[day] = diff
else:
res[day] += diff
if current_days and len(res) > current_days:
raise ValidationError(_(
"You can not Add Working Hour(s) for more than %s\
different days.") % current_days)
for day, hours in sorted(list(res.items())):
if current_hours and hours > current_hours:
raise ValidationError(_(
"Invalid hours for %s!\n\nWorking hours per day should\
not be greater than %s.") % (week_days[int(day)],
current_hours))

View File

@@ -0,0 +1,153 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import fields, models, api, _
class ProjectStory(models.Model):
_name = "project.story"
_inherit = 'mail.thread'
_description = "Project Story"
_order = "sprint_seq,sequence"
name = fields.Char("Title", required=True, tracking=True)
priority_id = fields.Many2one('story.priority', string="Priority",
tracking=True)
story_type_id = fields.Many2one('story.type', string="Type",
tracking=True)
tags = fields.Char("Tags", tracking=True)
description = fields.Text("Description", tracking=True)
owner_id = fields.Many2one(
'res.users', string="Owner", default=lambda self: self.env.user.id,
tracking=True)
sprint_id = fields.Many2one('project.sprint', string="Sprint",
tracking=True)
estimated_velocity = fields.Integer(
compute="_compute_calculate_estimated_velocity", string="Estimated Velocity",
store=True, tracking=True)
actual_velocity = fields.Integer(
compute="_compute_calculate_actual_velocity", string="Actual Velocity",
store=True, tracking=True)
state = fields.Selection([
('draft', 'Draft'),
('in_progress', 'In Progress'),
('cancel', 'Cancel'),
('done', 'Done'),
], string="states", tracking=True, default="draft")
sequence = fields.Integer(string='Sequence', default=1)
sprint_seq = fields.Char(
related="sprint_id.sprint_seq", string="Reference", readonly=True)
def set_state_active(self):
self.state = "in_progress"
def set_state_cancel(self):
self.state = "cancel"
def set_state_done(self):
self.state = "done"
def action_view_tasks(self):
return {
'name': (_('Tasks')),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'project.task',
'domain': [('sprint_id', '=', self.sprint_id.id)],
'context': {
'default_sprint_id': self.sprint_id.id,
'default_project_id': self.sprint_id.project_id.id,
}
}
@api.depends('sprint_id')
def _compute_calculate_estimated_velocity(self):
for story in self:
task_ids = story.env['project.task'].search([
('sprint_id', '=', story.sprint_id.id)
])
total_velocity = sum([
task.velocity for task in task_ids if task.velocity])
story.estimated_velocity = total_velocity
@api.depends('sprint_id', 'sprint_id.end_date')
def _compute_calculate_actual_velocity(self):
for story in self:
task_ids = story.env['project.task'].search([
('sprint_id', '=', story.sprint_id.id),
('actual_end_date', '<=', story.sprint_id.end_date)
])
total_velocity = sum([
task.velocity for task in task_ids if task.velocity])
story.actual_velocity = total_velocity
@api.model
def create(self, vals):
res = super(ProjectStory, self).create(vals)
partner_list = [
member.partner_id.id for member in res.sprint_id.team_id.member_ids
]
for follower in partner_list:
if follower:
mail_followers_ids = self.env['mail.followers'].sudo().search([
('res_id', '=', res.id),
('partner_id', '=', follower),
('res_model', '=', self._name),
])
if not mail_followers_ids:
self.env['mail.followers'].sudo().create({
'res_id': res.id,
'res_model': self._name,
'partner_id': follower,
'team_id': res.sprint_id.team_id.id,
})
return res
def write(self, vals):
res = super(ProjectStory, self).write(vals)
delete_team_id = self.env['mail.followers'].sudo().search([
('team_id', '!=', self.sprint_id.team_id.id),
('res_id', '=', self.id),
])
delete_team_id.unlink()
partner_list = [
member.partner_id.id for member in
self.sprint_id.team_id.member_ids
]
for follower in partner_list:
if follower:
mail_follower_ids = self.env['mail.followers'].sudo().search([
('res_id', '=', self.id),
('partner_id', '=', follower),
('res_model', '=', self._name),
])
if not mail_follower_ids:
self.env['mail.followers'].sudo().create({
'res_id': self.id,
'res_model': self._name,
'partner_id': follower,
'team_id': self.sprint_id.team_id.id,
})
return res
class StoryPriority(models.Model):
_name = "story.priority"
_inherit = 'mail.thread'
name = fields.Char("Name", tracking=True)
code = fields.Char("Code", tracking=True)
class StoryType(models.Model):
_name = "story.type"
_inherit = 'mail.thread'
name = fields.Char("Name", tracking=True)
code = fields.Char("Code", tracking=True)

View File

@@ -0,0 +1,18 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import models, fields
class ProjectTeam(models.Model):
_name = "project.team"
_inherit = 'mail.thread'
_description = "Project Team"
name = fields.Char("Team Name", required=True, tracking=True)
strength = fields.Text("Team Strength", tracking=True)
member_ids = fields.Many2many("res.users", string="Members")
master_id = fields.Many2one(
"res.users", string="Scrum Master", tracking=True)
description = fields.Html()
project_id = fields.Many2one(
'project.project', string="Project", tracking=True)

View File

@@ -0,0 +1,24 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import models, fields
class ReleasePlanning(models.Model):
_name = "release.planning"
_inherit = 'mail.thread'
name = fields.Char(string="Planning Name", tracking=True)
release_date = fields.Datetime(
string="Release Date", tracking=True)
sprint_id = fields.Many2one(
'project.sprint', string="Sprint", tracking=True)
priority = fields.Selection([
('low', 'Low'),
('medium', 'Medium'),
('high', 'High')], string="Priority", default='low',
tracking=True)
velocity = fields.Integer(
related="sprint_id.estimated_velocity", string="Sprint Velocity",
tracking=True, store=True)
task_id = fields.One2many(
"project.task", "release_planning_id", string="Task")

View File

@@ -0,0 +1,37 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import models, fields, api
class Retrospective(models.Model):
_name = "retrospective"
_inherit = 'mail.thread'
name = fields.Char(string="Retrospective Name", required=True,
tracking=True)
retrospective_method_id = fields.Many2one(
"retrospective.method", string="Retrospective Method",
tracking=True)
scrum_master = fields.Many2one("res.users", string="Scrum Master",
tracking=True)
sprint_id = fields.Many2one(
"project.sprint", string="Sprint", tracking=True)
retrospective_line_ids = fields.One2many(
"retrospective.lines", "retrospective_id",
string="Retrospective Lines", tracking=True)
start_date = fields.Datetime(string="Start Date")
end_date = fields.Datetime(string="End Date")
@api.onchange('sprint_id')
def on_sprint_id_change(self):
self.scrum_master = self.sprint_id.team_id.master_id.id
class RetrospectiveLines(models.Model):
_name = "retrospective.lines"
user_id = fields.Many2one("res.users", string="User", readonly=True,
required=True,
default=lambda self: self.env.user)
message = fields.Text(string="Message")
retrospective_id = fields.Many2one("retrospective", string="Retrospective")

View File

@@ -0,0 +1,15 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import models, fields
class RetrospectiveMethod(models.Model):
_name = "retrospective.method"
_inherit = 'mail.thread'
_description = "Retrospective Implementation for Project Scrum"
name = fields.Char(
string="Method Name", required=True, tracking=True)
description = fields.Text(
string="Description", tracking=True)

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<data>
<record id="release_planning_report" model="ir.actions.report">
<field name="name">Release Planning Report</field>
<field name="model">release.planning</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">project_scrum.release_planning_template_id</field>
<field name="report_file">project_scrum.release_planning_template_id</field>
<field name="print_report_name">'Release Planning Report - %s' % (object.name)</field>
<field name="binding_model_id" ref="model_release_planning"/>
<field name="binding_type">report</field>
</record>
<record id="project_sprint_report" model="ir.actions.report">
<field name="name">Project Sprint Report</field>
<field name="model">project.sprint</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">project_scrum.project_sprint_template_id</field>
<field name="report_file">project_scrum.project_sprint_template_id</field>
<field name="print_report_name">'Project Sprint Report - %s' % (object.name)</field>
<field name="binding_model_id" ref="model_project_sprint"/>
<field name="binding_type">report</field>
</record>
</data>
</flectra>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<data>
<template id="project_sprint_template_id">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page" t-foreach="docs" t-as="object" style="page-break-after: always;">
<div class="oe_structure"/>
<div class="row">
<div class="col-6 col-md-6 mt16">
<table class="table">
<tr>
<th>Project Name</th>
<td>
<span t-field="object.project_id"/>
</td>
</tr>
<tr>
<th>Sprint Name</th>
<td>
<span t-field="object.name"/>
</td>
</tr>
<tr>
<th>Team Name</th>
<td>
<span t-field="object.team_id"/>
</td>
</tr>
<tr>
<th>Scrum Master</th>
<td>
<span t-field="object.team_id.master_id"/>
</td>
</tr>
<tr>
<th>Start Date</th>
<td>
<span t-field="object.start_date"/>
</td>
</tr>
<tr>
<th>End Date</th>
<td>
<span t-field="object.end_date"/>
</td>
</tr>
<tr>
<th>Estimated Velocity</th>
<td>
<span t-field="object.estimated_velocity"/>
</td>
</tr>
<tr>
<th>Actual Velocity</th>
<td>
<span t-field="object.actual_velocity"/>
</td>
</tr>
</table>
</div>
<div class="col-6 col-md-6 mt16">
<table class="table">
<tr>
<th colspan="3">Team Member(s)</th>
</tr>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
<tr t-foreach="object.team_id.member_ids" t-as="member">
<td>
<span t-field="member.name"/>
</td>
<td>
<span t-field="member.login"/>
</td>
<td>
<span t-field="member.role_id"/>
</td>
</tr>
</table>
</div>
</div>
<h3 class="text-center">Task Details</h3>
<div>
<table class="table">
<tr>
<th>Task Seq.</th>
<th>Task Name</th>
<th>Velocity</th>
<th>Start Date</th>
<th>End Date</th>
<th>Actual End Date</th>
<th>Assigned to</th>
<th>State</th>
</tr>
<tr t-foreach="object.get_data()" t-as="data">
<td>
<span t-esc="data['reference']"/>
</td>
<td>
<span t-esc="data['name']"/>
</td>
<td>
<span t-esc="data['velocity']"/>
</td>
<td>
<span t-esc="data['start_date']"/>
</td>
<td>
<span t-esc="data['end_date']"/>
</td>
<td>
<span t-esc="data['actual_end_date']"/>
</td>
<td>
<span t-esc="data['assigned_to']"/>
</td>
<td>
<span t-esc="data['state']"/>
</td>
</tr>
</table>
</div>
<div class="oe_structure"/>
</div>
</t>
</t>
</template>
</data>
</flectra>

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<data>
<template id="release_planning_template_id">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page" style="page-break-after: always;" t-foreach="docs" t-as="object">
<div class="oe_structure">
<div class="col-xs-12 mt16">
<table class="table">
<tr>
<th>
<b>Planning Name</b>
</th>
<th>
<b>Sprint</b>
</th>
<th>
<b>Priority</b>
</th>
<th>
<b>Release Date</b>
</th>
<th>
<b>Velocity</b>
</th>
</tr>
<tr>
<td>
<span t-field="object.name"/>
</td>
<td>
<span t-field="object.sprint_id"/>
</td>
<td>
<span t-field="object.priority"/>
</td>
<td>
<span t-field="object.release_date"/>
</td>
<td>
<span t-field="object.velocity"/>
</td>
</tr>
</table>
<h3 class="text-center">Task Details</h3>
<table class="table">
<tr>
<th>Task Title</th>
<th>Project</th>
<th>Assigned To</th>
<th>Sprint</th>
<th>Start Date</th>
<th>End Date</th>
<th>Actual End Date</th>
<th>Velocity</th>
<th>Stage</th>
</tr>
<tr t-foreach="object.task_id" t-as="task">
<td>
<span t-field="task.name"/>
</td>
<td>
<span t-field="task.project_id"/>
</td>
<td>
<span t-field="task.user_id"/>
</td>
<td>
<span t-field="task.sprint_id"/>
</td>
<td>
<span t-field="task.start_date"/>
</td>
<td>
<span t-field="task.end_date"/>
</td>
<td>
<span t-field="task.actual_end_date"/>
</td>
<td>
<span t-field="task.velocity"/>
</td>
<td>
<span t-field="task.stage_id"/>
</td>
</tr>
</table>
</div>
</div>
</div>
</t>
</t>
</template>
</data>
</flectra>

View File

@@ -0,0 +1,36 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_project_sprint_user,access_project_sprint_user,model_project_sprint,project.group_project_user,1,1,0,0
access_project_sprint_manager,access_project_sprint_manager,model_project_sprint,project.group_project_manager,1,1,1,1
access_project_story_user,access_project_story_user,model_project_story,project.group_project_user,1,1,0,0
access_project_story_manager,access_project_story_manager,model_project_story,project.group_project_manager,1,1,1,1
access_project_team_user,access_project_team_user,model_project_team,project.group_project_user,1,1,0,0
access_project_team_manager,access_project_team_manager,model_project_team,project.group_project_manager,1,1,1,1
access_role_user,access_role_user,model_user_role,project.group_project_user,1,0,0,0
access_role_manager,access_role_manager,model_user_role,project.group_project_manager,1,1,1,1
access_sprint_planning_line_user,access_sprint_planning_line_user,model_sprint_planning_line,project.group_project_user,1,0,0,0
access_sprint_planning_line_manager,access_sprint_planning_line_manager,model_sprint_planning_line,project.group_project_manager,1,1,1,1
access_story_priority_user,access_story_priority_user,model_story_priority,project.group_project_user,1,0,0,0
access_story_priority_manager,access_story_priority_manager,model_story_priority,project.group_project_manager,1,1,1,1
access_story_type_user,access_story_type_user,model_story_type,project.group_project_user,1,0,0,0
access_story_type_manager,access_story_type_manager,model_story_type,project.group_project_manager,1,1,1,1
access_release_planning_user,access_release_planning_user,model_release_planning,project.group_project_user,1,0,0,0
access_release_planning_manager,access_release_planning_manager,model_release_planning,project.group_project_manager,1,1,1,1
access_retrospective_user,access_retrospective_user,model_retrospective,project.group_project_user,1,1,0,0
access_retrospective_manager,access_retrospective_manager,model_retrospective,project.group_project_manager,1,1,1,1
access_retrospective_method_user,access_retrospective_method_user,model_retrospective_method,project.group_project_user,1,0,0,0
access_retrospective_method_manager,access_retrospective_method_manager,model_retrospective_method,project.group_project_manager,1,1,1,1
access_retrospective_lines_user,access_retrospective_lines_user,model_retrospective_lines,project.group_project_user,1,1,1,1
access_retrospective_lines_manager,access_retrospective_lines_manager,model_retrospective_lines,project.group_project_manager,1,1,1,1
access_project_team_manager_res_users,access_project_team_manager_res_users,base.model_res_users,project.group_project_manager,1,1,0,0
access_project_team_user_res_users,access_project_team_user_res_users,base.model_res_users,project.group_project_user,1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_project_sprint_user access_project_sprint_user model_project_sprint project.group_project_user 1 1 0 0
3 access_project_sprint_manager access_project_sprint_manager model_project_sprint project.group_project_manager 1 1 1 1
4 access_project_story_user access_project_story_user model_project_story project.group_project_user 1 1 0 0
5 access_project_story_manager access_project_story_manager model_project_story project.group_project_manager 1 1 1 1
6 access_project_team_user access_project_team_user model_project_team project.group_project_user 1 1 0 0
7 access_project_team_manager access_project_team_manager model_project_team project.group_project_manager 1 1 1 1
8 access_role_user access_role_user model_user_role project.group_project_user 1 0 0 0
9 access_role_manager access_role_manager model_user_role project.group_project_manager 1 1 1 1
10 access_sprint_planning_line_user access_sprint_planning_line_user model_sprint_planning_line project.group_project_user 1 0 0 0
11 access_sprint_planning_line_manager access_sprint_planning_line_manager model_sprint_planning_line project.group_project_manager 1 1 1 1
12 access_story_priority_user access_story_priority_user model_story_priority project.group_project_user 1 0 0 0
13 access_story_priority_manager access_story_priority_manager model_story_priority project.group_project_manager 1 1 1 1
14 access_story_type_user access_story_type_user model_story_type project.group_project_user 1 0 0 0
15 access_story_type_manager access_story_type_manager model_story_type project.group_project_manager 1 1 1 1
16 access_release_planning_user access_release_planning_user model_release_planning project.group_project_user 1 0 0 0
17 access_release_planning_manager access_release_planning_manager model_release_planning project.group_project_manager 1 1 1 1
18 access_retrospective_user access_retrospective_user model_retrospective project.group_project_user 1 1 0 0
19 access_retrospective_manager access_retrospective_manager model_retrospective project.group_project_manager 1 1 1 1
20 access_retrospective_method_user access_retrospective_method_user model_retrospective_method project.group_project_user 1 0 0 0
21 access_retrospective_method_manager access_retrospective_method_manager model_retrospective_method project.group_project_manager 1 1 1 1
22 access_retrospective_lines_user access_retrospective_lines_user model_retrospective_lines project.group_project_user 1 1 1 1
23 access_retrospective_lines_manager access_retrospective_lines_manager model_retrospective_lines project.group_project_manager 1 1 1 1
24 access_project_team_manager_res_users access_project_team_manager_res_users base.model_res_users project.group_project_manager 1 1 0 0
25 access_project_team_user_res_users access_project_team_user_res_users base.model_res_users project.group_project_user 1 1 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -0,0 +1,108 @@
<section class="container">
<div class="row oe_spaced">
<div class="col-md-12">
<h2 class="oe_slogan">Project Scrum</h2>
</div>
</div>
</section>
<section class="container bg-gray-lighter">
<div class="row oe_spaced mt0">
<div class="col-md-12">
<h3 class="oe_slogan">Sprint</h3>
</div>
<div class="col-md-6">
<p class="text-justify" style="font-size: 15px;">A scrum sprint is a regular, repeatable work cycle in scrum
methodology during which work is completed and made ready for review. Scrum sprints are basic units of
development in the scrum methodology. Generally sprints are 1-2 week(s) long...</p>
</div>
<div class="col-md-6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="sprint_scrum.png" width="100%" alt="Sprint"/>
</div>
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced mt0">
<div class="col-md-12">
<h3 class="oe_slogan">Release Planning</h3>
</div>
<div class="col-md-6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="release_scrum.png" alt="Release Planning"/>
</div>
</div>
<div class="col-md-6">
<p class="text-justify" style="font-size: 15px;">
A very high-level plan for multiple Sprints (e.g. three to twelve iteration) is created during the
Release planning. It is a guideline that reflects expectations about which features will be implemented
and when they are completed. It also serves as a base to monitor progress within the project.
</p>
</div>
</div>
</section>
<section class="container bg-gray-lighter">
<div class="row oe_spaced mt0">
<div class="col-md-12">
<h3 class="oe_slogan">Story</h3>
</div>
<div class="col-md-6">
<p class="text-justify" style="font-size: 15px;">
User Stories are managed in the Product Backlog. The User Stories are ordered according to priority. The
most prioritized user stories are refined to granular level, while the least priority user stories are
kept at a lesser detail level. For every sprint, the most prioritized and hence more granulated user
stories are taken into the sprint backlog. If a user story is to be added to the product backlog, its
priority is first determined, and it is placed according to its place as per the priority.
</p>
</div>
<div class="col-md-6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="story_scrum.png" alt="Story"/>
</div>
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced mt0">
<div class="col-md-12">
<h3 class="oe_slogan">Team</h3>
</div>
<div class="col-md-6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="team_scrum.png" alt="Team"/>
</div>
</div>
<div class="col-md-6">
<p class="text-justify" style="font-size: 15px;">
Within the Scrum Framework all work delivered to the customer is done by dedicated Scrum Teams. A Scrum
Team is a collection of individuals working together to deliver the requested and committed product
increments.
</p>
</div>
</div>
</section>
<section class="container bg-gray-lighter">
<div class="row oe_spaced mt0">
<div class="col-md-12">
<h3 class="oe_slogan">Retrospective</h3>
</div>
<div class="col-md-6">
<p class="text-justify" style="font-size: 15px;">
The sprint retrospective is a meeting facilitated by the ScrumMaster at which the team discusses the
just-concluded sprint and determines what could be changed that might make the next sprint more
productive. The sprint review looks at what the team is building, whereas the retrospective looks at how
they are building it.
</p>
</div>
<div class="col-md-6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="retro_scrum.png" alt="Retrospective"/>
</div>
</div>
</div>
</section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -0,0 +1,8 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from .test_scrum_common import TestScrumCommon
from .test_scrum_team import TestScrumTeam
from .test_scrum_sprint import TestScrumSprint
from .test_scrum_task import TestScrumTask
from .test_scrum_release_planning import TestScrumReleasePlanning
from .test_scrum_story import TestScrumStory

View File

@@ -0,0 +1,79 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra.tests import common
class TestScrumCommon(common.SavepointCase):
def setUp(self):
super(TestScrumCommon, self).setUp()
self.teams = [
self.env.ref('project_scrum.project_team_1'),
self.env.ref('project_scrum.project_team_2'),
self.env.ref('project_scrum.project_team_3')
]
self.user_roles = [
self.env.ref('project_scrum.user_role_1'),
self.env.ref('project_scrum.user_role_2'),
self.env.ref('project_scrum.user_role_3')
]
self.sprints = [
self.env.ref('project_scrum.project_sprint_1'),
self.env.ref('project_scrum.project_sprint_2'),
self.env.ref('project_scrum.project_sprint_3'),
self.env.ref('project_scrum.project_sprint_4'),
self.env.ref('project_scrum.project_sprint_5')
]
self.project_tasks = [
self.env.ref('project_scrum.project_task_1'),
self.env.ref('project_scrum.project_task_2'),
self.env.ref('project_scrum.project_task_3'),
self.env.ref('project_scrum.project_task_4'),
self.env.ref('project_scrum.project_task_6'),
self.env.ref('project_scrum.project_task_7'),
self.env.ref('project_scrum.project_task_8'),
self.env.ref('project_scrum.project_task_9'),
self.env.ref('project_scrum.project_task_10'),
self.env.ref('project_scrum.project_task_11'),
self.env.ref('project_scrum.project_task_12'),
self.env.ref('project_scrum.project_task_13'),
self.env.ref('project_scrum.project_task_14')
]
self.users = [
self.env.ref('project_scrum.user_1'),
self.env.ref('project_scrum.user_2'),
self.env.ref('project_scrum.user_3')
]
self.release_plans = [
self.env.ref('project_scrum.release_planning_1'),
self.env.ref('project_scrum.release_planning_2'),
self.env.ref('project_scrum.release_planning_3'),
self.env.ref('project_scrum.release_planning_4'),
self.env.ref('project_scrum.release_planning_5')
]
self.story_priorities = [
self.env.ref('project_scrum.story_priority_1'),
self.env.ref('project_scrum.story_priority_2'),
self.env.ref('project_scrum.story_priority_3')
]
self.story_types = [
self.env.ref('project_scrum.story_type_1'),
self.env.ref('project_scrum.story_type_2')
]
self.stories = [
self.env.ref('project_scrum.project_story_1'),
self.env.ref('project_scrum.project_story_2'),
self.env.ref('project_scrum.project_story_3')
]
self.project = self.env.ref('project_scrum.demo_project_1')
self.sprint_planning_line = self.env['sprint.planning.line']

View File

@@ -0,0 +1,22 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from logging import info
from .test_scrum_common import TestScrumCommon
class TestScrumReleasePlanning(TestScrumCommon):
def setUp(self):
super(TestScrumReleasePlanning, self).setUp()
def test_scrum_release_planning(self):
if not self.release_plans:
raise AssertionError(
'Error in data. Please check for release planning.')
info('Details of release planning:')
for plan in self.release_plans:
info('Release Plan : %s' % plan.name)
info(' Release Date : %s' % plan.release_date)
info(' Sprint : %s' % plan.sprint_id.name)
info(' Priority : %s' % plan.priority)
info(' Sprint Velocity : %s' % plan.velocity)

View File

@@ -0,0 +1,62 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from logging import info
from .test_scrum_common import TestScrumCommon
class TestScrumSprint(TestScrumCommon):
def setUp(self):
super(TestScrumSprint, self).setUp()
def test_scrum_sprint(self):
# self.check_user_roles(self.user_roles)
self.check_sprint(self.sprints)
def check_user_roles(self, roles):
if not roles:
raise AssertionError('Error in data. Please check user role data.')
info('Details of Roles :')
info('Code : name')
for role in roles:
info(' %s : %s' % (role.code, role.name))
def check_sprint(self, sprints):
if not sprints:
raise AssertionError('Error in data. Please check sprint data.')
info('Details of Sprints :')
for sprint in sprints:
info('Sprint : %s' % sprint.name)
info(' Sequence : %s' % sprint.sprint_seq)
info(' Project : %s' % sprint.project_id.name)
info(' Team : %s' % sprint.team_id.name)
info(' Date : %s - %s' % (sprint.start_date, sprint.end_date))
info(' Planning Meeting Date : %s' % sprint.meeting_date)
info(' Goal of Sprint : %s' % sprint.goal_of_sprint)
info(' Daily Scrum Time : %f' % sprint.hour)
info(' Duration (In Days): %d' % sprint.duration)
info(' Estimated Velocity : %d' % sprint.estimated_velocity)
info(' Actual Velocity : %d' % sprint.actual_velocity)
info(' Business Days : %d' % sprint.working_days)
info(' Holiday (Hours / Days) : %s' % sprint.holiday_type)
info(' Holiday Count : %f' % sprint.holiday_count)
info(' Productivity Hours : %s' % sprint.productivity_hours)
info(' Productivity : %f' % sprint.productivity_per)
lines = self.sprint_planning_line.search(
[('sprint_id', '=', sprint.id)])
if not lines:
raise AssertionError(
'Error in data. Please check spring planning lines '
'for sprint %s' % sprint.name)
info(' Spring Planning :')
for line in lines:
info(' User : %s' % line.user_id.name)
info(' Role : %s' % line.role_id.name)
info(' Available : %s' % line.available_per)
info(' Productivity Hour : '
'%s' % line.productivity_hours)
info(' Sprint hour : %s' % line.sprint_hours)
info(' Off Hour : %s' % line.off_hours)
info(' Total Hour: %s' % line.total_hours)

View File

@@ -0,0 +1,56 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from logging import info
from .test_scrum_common import TestScrumCommon
class TestScrumStory(TestScrumCommon):
def setUp(self):
super(TestScrumStory, self).setUp()
def test_scrum_story(self):
if not self.story_priorities:
raise AssertionError(
'Error in data. Please check for story priorities.')
self.check_priority(self.story_priorities)
if not self.story_types:
raise AssertionError(
'Error in data. Please check for story types.')
self.check_type(self.story_types)
if not self.stories:
raise AssertionError(
'Error in data. Please check for story data.')
self.check_story(self.stories)
def check_priority(self, priorities):
info('Details of Priorities :')
info(' Code : Name')
for priority in priorities:
info(' %s : %s' % (priority.code, priority.name))
def check_type(self, types):
info('Details of Story Types :')
info(' Code : Name')
for typ in types:
info(' %s : %s' % (typ.code, typ.name))
def check_story(self, stories):
info('Details of Stories:')
for story in stories:
if not story.name:
raise AssertionError(
'Error in data. Please check for story name.')
info('Story : %s' % story.name)
if not story.sprint_id:
raise AssertionError(
'Error in data. Please check for story sprint value.')
info(' Sprint : %s' % story.sprint_id.name)
info(' Priority : %s' % story.priority_id.name)
info(' Owner : %s' % story.owner_id.name)
info(' Type : %s' % story.story_type_id.name)
info(' Actual Velocity : %d' % story.actual_velocity)
info(' Estimated Velocity : %s' % story.estimated_velocity )
info(' Description : %s' % story.description)

View File

@@ -0,0 +1,42 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from logging import info
from .test_scrum_common import TestScrumCommon
class TestScrumTask(TestScrumCommon):
def setUp(self):
super(TestScrumTask, self).setUp()
def test_scrum_task(self):
if not self.project_tasks:
raise AssertionError('Error in data. Please Check Project Tasks.')
info('Details of tasks:')
for task in self.project_tasks:
if not task.name:
raise AssertionError(
'Error in data. Please Check Project Tasks Name.')
info('Details of : %s' % task.name)
if not task.project_id:
raise AssertionError(
'Error in data. Please Check Project Tasks Project.')
info(' Project : %s' % task.project_id.name)
if not task.sprint_id:
raise AssertionError(
'Error in data. Please Check Project Tasks Sprint.')
info(' Sprint : %s' % task.sprint_id.name)
info(' Assigned to : %s' % task.user_id.name)
info(' Company : %s' % task.company_id.name)
if not task.start_date and task.end_date:
raise AssertionError(
'Error in data. Please Check Project Tasks Date.')
info(' Date : %s - %s' % (task.start_date, task.end_date))
info(' Actual End Date : %s' % task.actual_end_date)
info(' Deadline : %s' % task.date_deadline)
info(' Reference : %s' % task.task_seq)
info(' Story : %s' % task.story_id.name)
info(' Velocity : %d' % task.velocity)
info(' Release Planning : %s' % task.release_planning_id.name)
info(' Priority : %s' % task.priority)
info(' Description : %s' % task.description)

View File

@@ -0,0 +1,30 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from logging import info
from .test_scrum_common import TestScrumCommon
class TestScrumTeam(TestScrumCommon):
def setUp(self):
super(TestScrumTeam, self).setUp()
def test_scrum_team(self):
if not self.teams:
raise AssertionError(
'Error in data. Please check for Team in Scrum.')
info('Details of Teams of Scrum.....')
for team in self.teams:
if not (team.name and team.project_id):
raise AssertionError(
'Error in data. Please check for Team in Scrum.')
info('Team Name : %s' % team.name)
info(' Description : %s' % team.description)
info(' Strength : %s' % team.strength)
info(' Project : %s' % team.project_id.name)
info(' Scrum Master : %s' % team.master_id.name)
if team.member_ids:
info(' Members : %d' % len(team.member_ids))
for member in team.member_ids:
info(' %s' % member.name)

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="cron_check_sprint_state" model="ir.cron">
<field name="name">Sprint State</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="model_id" ref="project_scrum.model_project_sprint"/>
<field name="state">code</field>
<field name="code">model.check_sprint_state()</field>
<field name="active" eval="False"/>
</record>
</flectra>

View File

@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<!-- Project form inherited -->
<record id="view_project_form_inherited" model="ir.ui.view">
<field name="name">Project inherited form</field>
<field name="model">project.project</field>
<field name="inherit_id" ref="project.edit_project"/>
<field name="arch" type="xml">
<field name="user_id" position="replace">
<field name="user_id" options="{'no_create': True, 'no_create_edit': True}"/>
</field>
<field name="company_id" position="replace">
<field name="company_id" options="{'no_create': True, 'no_create_edit': True}"/>
</field>
<field name="partner_id" position="replace">
<field name="partner_id" options="{'no_create': True, 'no_create_edit': True}"/>
</field>
<xpath expr="//field[@name='user_id']" position="before">
<field name="no_of_hours" invisible="1"/>
<field name="no_of_days" invisible="1"/>
</xpath>
<xpath expr="//button[@name='attachment_tree_view']" position="after">
<button class="oe_stat_button" name="show_sprints" type="object" icon="fa fa-dot-circle-o">
<field string="Sprints" name="sprint_count" widget="statinfo"/>
</button>
</xpath>
<!-- <xpath expr="//group[@name='misc']/group[1]" position="replace">-->
<!-- <group string="Configuration">-->
<!-- <field name="sequence" position="replace">-->
<!-- <field name="sequence"/>-->
<!-- </field>-->
<!-- </group>-->
<!-- </xpath>-->
<!-- <xpath expr="//group[@name='misc']/group[2]" position="replace">-->
<!-- <group string="Time Scheduling">-->
<!-- <field name="resource_calendar_id" position="replace">-->
<!-- <field name="resource_calendar_id"/>-->
<!-- </field>-->
<!-- </group>-->
<!-- </xpath>-->
<xpath expr="//notebook/page[@name='settings']" position="after">
<page string="Stages">
<field name="task_type_ids"/>
</page>
</xpath>
</field>
</record>
<!-- User Inherited view -->
<record id="view_users_form_inherited" model="ir.ui.view">
<field name="name">Users inherited form</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='access_rights']" position="inside">
<group string="User Role">
<field name="role_id" options="{'no_create': True, 'no_create_edit': True}"/>
</group>
</xpath>
</field>
</record>
<!-- Tasks Inherited view -->
<record id="view_tasks_form_inherited" model="ir.ui.view">
<field name="name">Tasks inherited form</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="project.view_task_form2"/>
<field name="arch" type="xml">
<field name="project_id" position="replace">
<field name="project_id" options="{'no_create': True, 'no_create_edit': True}"/>
<field name="task_seq"/>
</field>
<field name="user_id" position="replace">
<field name="user_id" options="{'no_create': True, 'no_create_edit': True}"/>
</field>
<field name="company_id" position="replace">
<field name="company_id" options="{'no_create': True, 'no_create_edit': True}"/>
</field>
<field name="partner_id" position="replace">
<field name="partner_id" options="{'no_create': True, 'no_create_edit': True}"/>
<field name="story_id" options="{'no_create': True, 'no_create_edit': True}"/>
<field name="velocity"/>
<field name="release_planning_id" options="{'no_create': True, 'no_create_edit': True}"/>
</field>
<field name="tag_ids" position="replace">
<field name="tag_ids" options="{'no_create': True, 'no_create_edit': True}" widget="many2many_tags"/>
</field>
<xpath expr="//field[@name='project_id']" position="after">
<field name="sprint_id" options="{'no_create': True, 'no_create_edit': True}"/>
</xpath>
</field>
</record>
<!-- Task Search view inherited -->
<record id="view_tasks_search_inherited" model="ir.ui.view">
<field name="name">Tasks inherited search</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="project.view_task_search_form"/>
<field name="arch" type="xml">
<xpath expr="//group/filter[@name='project']" position="before">
<filter string="Sprint" name="group_by_sprint" context="{'group_by': 'sprint_id'}"/>
</xpath>
<xpath expr="//search/field[@name='name']" position="after">
<field name="sprint_id"/>
</xpath>
</field>
</record>
<!-- Task Tree view inherited -->
<record id="view_tasks_tree_inherited" model="ir.ui.view">
<field name="name">Tasks inherited tree</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="project.view_task_tree2"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='date_deadline']" position="after">
<field name="sprint_id"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="actual_end_date"/>
<field name="velocity"/>
</xpath>
</field>
</record>
<record id="action_inherited_task" model="ir.actions.act_window">
<field name="name">Tasks</field>
<field name="res_model">project.task</field>
<field name="view_mode">kanban,tree,form</field>
<field name="context">{
'search_default_sprint_id': [active_id],
'default_sprint_id': active_id,
}
</field>
<field name="search_view_id" ref="project.view_task_search_form"/>
</record>
<!-- Resource Calendar -->
<record id="view_resource_calendar_inherited" model="ir.ui.view">
<field name="name">Resource Calendar</field>
<field name="model">resource.calendar</field>
<field name="inherit_id" ref="resource.resource_calendar_form"/>
<field name="arch" type="xml">
<field name="name" position="after">
<group col="4" colspan="4">
<field name="no_of_hours"/>
<field name="no_of_days"/>
</group>
</field>
</field>
</record>
</flectra>

View File

@@ -0,0 +1,320 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_project_sprint_form" model="ir.ui.view">
<field name="name">project.sprint</field>
<field name="model">project.sprint</field>
<field name="arch" type="xml">
<form string="Project Sprint">
<header>
<button name="set_state_open" string="Open" type="object"
class="oe_highlight"
attrs="{'invisible': [('state', '!=', 'draft')]}"/>
<button name="set_state_cancel" string="Cancel"
type="object" class="oe_highlight"
attrs="{'invisible': [('state', 'in', ('done', 'cancel'))]}"/>
<button name="set_state_pending" string="Pending"
type="object" class="oe_highlight"
attrs="{'invisible': [('state', 'not in', ('in_progress', 'draft'))]}"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_button_box" name="task_button_box">
<button name="action_view_tasks" string="Tasks"
type="object" class="oe_stat_button"
icon="fa-tasks"/>
<button name="action_view_stories" string="Stories"
type="object" class="oe_stat_button"
icon="fa-pencil"/>
<button name="action_view_release_planning"
string="Release Planning"
type="object" class="oe_stat_button"
icon="fa-rocket"/>
<button name="action_view_retrospective"
string="Retrospectives"
type="object" class="oe_stat_button"
icon="fa-backward"/>
</div>
<div class="oe_title">
<h1 class="o_row">
<field name="name" placeholder="Sprint Name"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
</h1>
</div>
<div col="2">
<br/>
<h2 class="o_row">
<field name="sprint_seq" nolabel="1" readonly="1"/>
</h2>
</div>
<group>
<group col="2">
<field name="project_id"
options="{'no_create': True, 'no_create_edit': True}"
required="1"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="start_date" required="1"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="meeting_date"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
</group>
<group>
<field name="team_id"
options="{'no_create': True, 'no_create_edit': True}"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="end_date"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="goal_of_sprint"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
</group>
<group>
<field name="duration"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
</group>
<group>
<label for="hour" string="Daily Scrum Time"/>
<div class="o_address_format">
<field name="hour" widget="float_time"
class="o_address_city"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="time_zone" class="o_address_city"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
</div>
<field name="estimated_velocity"/>
<field name="actual_velocity"/>
</group>
</group>
<notebook>
<page string="Sprint Planning">
<group name="sprint_planning" col="4">
<field name="working_days"/>
<field name="productivity_hours"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="holiday_type"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="productivity_per"/>
<field name="holiday_count"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="holiday_days"
attrs="{'invisible': [('holiday_type', '=', 'hours')]}"/>
</group>
<field name="sprint_planning_line" nolabel="1"
attrs="{'readonly': [('state', '!=', 'draft')]}">
<tree editable="bottom">
<field name="user_id"
options="{'no_create': True, 'no_create_edit': True}"
required="1"/>
<field name="role_id"/>
<field name="available_per"/>
<field name="productivity_hours"/>
<field name="sprint_hours"/>
<field name="off_hours"/>
<field name="total_hours"
sum="Total Capacity"/>
</tree>
</field>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="view_project_sprint_tree" model="ir.ui.view">
<field name="name">project.sprint.tree</field>
<field name="model">project.sprint</field>
<field name="arch" type="xml">
<tree string="Project Sprint">
<field name="sprint_seq"/>
<field name="name"/>
<field name="project_id"/>
<field name="goal_of_sprint"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="view_sprint_search" model="ir.ui.view">
<field name="name">project.sprint.search</field>
<field name="model">project.sprint</field>
<field name="arch" type="xml">
<search string="Sprints">
<field name="name"/>
<field name="project_id"/>
<filter string="Draft" name="filter_draft"
domain="[('state', '=', 'draft')]"/>
<filter string="In Progress" name="filter_progress"
domain="[('state', '=', 'in_progress')]"/>
<filter string="Done" name="filter_done"
domain="[('state', '=', 'done')]"/>
<filter string="Cancel" name="filter_cancel"
domain="[('state', '=', 'cancel')]"/>
<filter string="Project" name="group_by_project"
context="{'group_by': 'project_id'}"/>
</search>
</field>
</record>
<!--
Sprint Kanban View
-->
<record id="view_project_sprint_kanban" model="ir.ui.view">
<field name="name">project.sprint.kanban</field>
<field name="model">project.sprint</field>
<field name="arch" type="xml">
<kanban string="Scrum Kanban"
class="o_emphasize_colors o_kanban_dashboard oe_background_grey o_kanban_dashboard o_account_kanban o_slide_kanban breadcrumb_item active"
edit="false">
<field name="color"/>
<field name="task_line"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{kanban_color(0)} oe_kanban_global_click ">
<div class="o_kanban_card_header">
<div class="o_kanban_card_header_title mb16">
<div class="o_primary">
<a type="edit" class="mr-auto">
<field name="name" class="o_primary"/>
</a>
</div>
</div>
</div>
<div class="container o_kanban_card_content mt0">
<div class="row mb16">
<div class="col-12 o_kanban_primary_right">
<div class="d-flex">
<span class="mr-auto mb0">
Start Date
</span>
<field name="start_date"/>
</div>
<div class="d-flex">
<span class="mr-auto mb0">
End Date
</span>
<field name="end_date"/>
</div>
<div class="d-flex">
<span class="mr-auto mb0">
Estimated Velocity
</span>
<field name="estimated_velocity"/>
</div>
<div class="d-flex">
<span class="mr-auto mb0">
Duration
</span>
<field name="duration"/>
</div>
</div>
</div>
<a name="action_view_tasks" type="object">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="task_count"/>
</span>
<span name="total_slides_label" class="o_stat_text">Tasks</span>
</div>
</a>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!--
Sprint Calendar View
-->
<record id="view_project_sprint_calendar" model="ir.ui.view">
<field name="name">project.sprint.calendar</field>
<field name="model">project.sprint</field>
<field name="arch" type="xml">
<calendar string="Project Sprint" color="project_id"
date_start="meeting_date">
<field name="name"/>
<field name="project_id"/>
<field name="start_date"/>
</calendar>
</field>
</record>
<record id="action_project_sprint" model="ir.actions.act_window">
<field name="name">Sprint</field>
<field name="res_model">project.sprint</field>
<field name="view_mode">kanban,tree,form,calendar</field>
<field name="view_id" ref="view_project_sprint_kanban"/>
<field name="search_view_id" ref="view_sprint_search"/>
</record>
<menuitem name="Scrum" id="menu_scrum" parent="project.menu_main_pm"
sequence="1"/>
<menuitem
id="menu_sprint"
parent="menu_scrum"
action="action_project_sprint"
sequence="1"
/>
<!-- User Role views -->
<record id="view_user_role_tree" model="ir.ui.view">
<field name="name">user.role</field>
<field name="model">user.role</field>
<field name="arch" type="xml">
<tree string="User Role">
<field name="name"/>
<field name="code"/>
</tree>
</field>
</record>
<record id="view_user_role_form" model="ir.ui.view">
<field name="name">user.role</field>
<field name="model">user.role</field>
<field name="arch" type="xml">
<form string="User Role">
<sheet>
<group col="4">
<field name="name" required="1"/>
<field name="code"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_user_role" model="ir.actions.act_window">
<field name="name">Roles</field>
<field name="res_model">user.role</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="view_user_role_tree"/>
</record>
<menuitem
id="menu_user_role"
parent="base.menu_users"
action="action_user_role"
sequence="2"
/>
<record id="mail_followers_inherit_id" model="ir.ui.view">
<field name="name">mail.followers</field>
<field name="model">mail.followers</field>
<field name="inherit_id" ref="mail.view_mail_subscription_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='subtype_ids']" position="after">
<field name="team_id" invisible="1"/>
</xpath>
</field>
</record>
</flectra>

View File

@@ -0,0 +1,262 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_project_story_form" model="ir.ui.view">
<field name="name">project.story.form</field>
<field name="model">project.story</field>
<field name="arch" type="xml">
<form string="Project Story">
<header>
<button name="set_state_active" string="Open" type="object" class="oe_highlight" states="draft,cancel"/>
<button name="set_state_cancel" string="Cancel" type="object" class="oe_highlight" states="in_progress"/>
<button name="set_state_done" string="Done" type="object" class="oe_highlight" states="in_progress"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_button_box" name="task_button_box">
<button name="action_view_tasks" string="Tasks"
type="object" class="oe_stat_button"
icon="fa-tasks"/>
</div>
<div>
<h3 class="o_row">
<field name="name" placeholder="As a &lt;role&gt; I can &lt;capability&gt;, so that &lt;receive benefit&gt;"/>
</h3>
</div>
<group name="story_main_fields" col="4">
<field name="sprint_id" options="{'no_create': True, 'no_create_edit': True}"/>
<field name="priority_id" options="{'no_create': True, 'no_create_edit': True}"/>
<field name="story_type_id" options="{'no_create': True, 'no_create_edit': True}"/>
<field name="owner_id" readonly="1"/>
<field name="tags"/>
<field name="estimated_velocity"/>
<field name="actual_velocity"/>
</group>
<notebook>
<page string="Description">
<field name="description"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="view_project_story_tree" model="ir.ui.view">
<field name="name">project.story.tree</field>
<field name="model">project.story</field>
<field name="arch" type="xml">
<tree string="Project Story">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="owner_id"/>
<field name="sprint_id"/>
<field name="priority_id"/>
<field name="story_type_id"/>
</tree>
</field>
</record>
<record id="view_project_story_kanban" model="ir.ui.view">
<field name="name">view.project.story.kanban</field>
<field name="model">project.story</field>
<field name="arch" type="xml">
<kanban default_group_by="sprint_id">
<field name="name"/>
<field name="sprint_id"/>
<field name="owner_id"/>
<field name="priority_id"/>
<field name="story_type_id"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click">
<div class="o_dropdown_kanban dropdown">
<a role="button" class="dropdown-toggle btn" data-toggle="dropdown" href="#">
<span class="fa fa-ellipsis-v" title="Options for kanban view"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<t t-if="widget.editable">
<li>
<a type="edit">Edit</a>
</li>
</t>
<t t-if="widget.deletable">
<li>
<a type="delete">Delete</a>
</li>
</t>
</ul>
</div>
<div class="o_kanban_card_header">
<div class="o_kanban_card_header_title mb16">
<div class="o_primary">
<t t-esc="record.name.value"/>
</div>
</div>
</div>
<div class="container o_kanban_card_content">
<div class="row">
<div class="col-xs-6 o_kanban_primary_left">
</div>
</div>
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<span t-if="record.priority_id.raw_value"
class="small text-muted"><t t-esc="record.priority_id.value"/></span>
<span t-if="record.priority_id.raw_value and record.story_type_id.raw_value"
class="small text-muted">|</span>
<span t-if="record.story_type_id.raw_value"
class="small text-muted"><t t-esc="record.story_type_id.value"/></span>
</div>
<div class="oe_kanban_bottom_right">
<img t-att-src="kanban_image('res.users', 'image_small', record.owner_id.raw_value)"
t-att-title="record.owner_id.value" width="24" height="24" class="oe_kanban_avatar"
alt="Image"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="view_project_story_search" model="ir.ui.view">
<field name="name">project.story.search</field>
<field name="model">project.story</field>
<field name="arch" type="xml">
<search string="Story">
<field name="name"/>
<field name="sprint_id"/>
<!-- <filter string="Product Backlog" domain="[('sprint_id', '=', False)]"/>-->
<filter string="Sprint" name="group_by_sprint" context="{'group_by': 'sprint_id'}"/>
<filter string="Owner" name="group_by_owner" context="{'group_by': 'owner_id'}"/>
<filter string="Priority" name="group_by_priority" context="{'group_by': 'priority_id'}"/>
<filter string="Type" name="group_by_type" context="{'group_by': 'story_type_id'}"/>
</search>
</field>
</record>
<record id="action_project_story_sprint" model="ir.actions.act_window">
<field name="name">Project Story</field>
<field name="res_model">project.story</field>
<field name="view_mode">tree,kanban,form</field>
<field name="view_id" ref="view_project_story_tree"/>
<field name="search_view_id" ref="view_project_story_search"/>
</record>
<record id="open_view_project_story_sprint_kanban" model="ir.actions.act_window.view">
<field name="sequence" eval="0"/>
<field name="view_mode">kanban</field>
<field name="act_window_id" ref="action_project_story_sprint"/>
</record>
<record id="open_view_project_story_sprint_tree" model="ir.actions.act_window.view">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="act_window_id" ref="action_project_story_sprint"/>
</record>
<record id="open_view_project_story_sprint_form" model="ir.actions.act_window.view">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="act_window_id" ref="action_project_story_sprint"/>
</record>
<menuitem name="Story" id="menu_story" parent="menu_scrum" action="action_project_story_sprint" sequence="7"/>
<!-- Story Priority views -->
<record id="view_story_priority_tree" model="ir.ui.view">
<field name="name">story.priority</field>
<field name="model">story.priority</field>
<field name="arch" type="xml">
<tree string="Priority">
<field name="name"/>
<field name="code"/>
</tree>
</field>
</record>
<record id="view_story_priority_form" model="ir.ui.view">
<field name="name">story.priority</field>
<field name="model">story.priority</field>
<field name="arch" type="xml">
<form string="Priority">
<sheet>
<group col="4">
<field name="name" required="1"/>
<field name="code"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="action_story_priority" model="ir.actions.act_window">
<field name="name">Story Priorities</field>
<field name="res_model">story.priority</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="view_story_priority_tree"/>
</record>
<menuitem
id="menu_story_priority"
parent="project.menu_project_config"
action="action_story_priority"
groups="project.group_project_manager"
sequence="1"
/>
<!-- Story Type views -->
<record id="view_story_type_tree" model="ir.ui.view">
<field name="name">story.type</field>
<field name="model">story.type</field>
<field name="arch" type="xml">
<tree string="Type">
<field name="name"/>
<field name="code"/>
</tree>
</field>
</record>
<record id="view_story_type_form" model="ir.ui.view">
<field name="name">story.type</field>
<field name="model">story.type</field>
<field name="arch" type="xml">
<form string="Type">
<sheet>
<group col="4">
<field name="name" required="1"/>
<field name="code"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="action_story_type" model="ir.actions.act_window">
<field name="name">Story Types</field>
<field name="res_model">story.type</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="view_story_type_tree"/>
</record>
<menuitem
id="menu_story_type"
parent="project.menu_project_config"
action="action_story_type"
groups="project.group_project_manager"
sequence="2"
/>
</flectra>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_project_team_form" model="ir.ui.view">
<field name="name">project.team</field>
<field name="model">project.team</field>
<field name="arch" type="xml">
<form string="Project Team">
<sheet>
<div class="oe_title">
<h1 class="o_row">
<field name="name" placeholder="Team Name"/>
</h1>
</div>
<group col="4">
<field name="project_id" options="{'no_create': True, 'no_create_edit': True}" required="1"/>
<field name="member_ids" widget="many2many_tags"
options="{'no_create': True, 'no_create_edit': True}"/>
<field name="master_id" options="{'no_create': True, 'no_create_edit': True}"
domain="[('id', 'in', member_ids)]"/>
</group>
<group col="2">
<field name="strength"/>
</group>
<notebook>
<page string="Description">
<field name="description"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="view_project_team_tree" model="ir.ui.view">
<field name="name">project.team</field>
<field name="model">project.team</field>
<field name="arch" type="xml">
<tree string="Project Team">
<field name="name"/>
<field name="master_id"/>
<field name="strength"/>
</tree>
</field>
</record>
<record id="action_project_team" model="ir.actions.act_window">
<field name="name">Project Team</field>
<field name="res_model">project.team</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="view_project_team_tree"/>
</record>
<menuitem name="Team" id="menu_team" parent="menu_scrum" action="action_project_team" sequence="10"/>
</flectra>

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_release_planning_form" model="ir.ui.view">
<field name="name">release.planning.form</field>
<field name="model">release.planning</field>
<field name="arch" type="xml">
<form string="Release Planning">
<sheet>
<group col="4">
<field name="name" required="1"/>
<field name="release_date"/>
<field name="sprint_id" options="{'no_create': True, 'no_create_edit': True}"/>
<field name="priority"/>
<field name="velocity"/>
</group>
<notebook>
<page string="Tasks">
<field name="task_id" widget="one2many_list"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="view_release_planning_tree" model="ir.ui.view">
<field name="name">release.planning.tree</field>
<field name="model">release.planning</field>
<field name="arch" type="xml">
<tree string="Release Planning">
<field name="name" required="1"/>
<field name="release_date"/>
<field name="sprint_id"/>
<field name="priority"/>
<field name="velocity"/>
</tree>
</field>
</record>
<record id="view_release_planning_calendar" model="ir.ui.view">
<field name="name">release.planning.calendar</field>
<field name="model">release.planning</field>
<field name="arch" type="xml">
<calendar string="Release Planning" color="sprint_id" date_start="release_date">
<field name="sprint_id"/>
<field name="release_date"/>
<field name="priority"/>
</calendar>
</field>
</record>
<record id="action_release_planning" model="ir.actions.act_window">
<field name="name">Release Planning</field>
<field name="res_model">release.planning</field>
<field name="view_mode">tree,form,calendar</field>
<field name="view_id" ref="view_release_planning_tree"/>
</record>
<menuitem
id="menu_release_planning"
parent="menu_scrum"
action="action_release_planning"
sequence="5"
/>
</flectra>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="retrospective_method_form_view" model="ir.ui.view">
<field name="name">Retrospective Method</field>
<field name="model">retrospective.method</field>
<field name="arch" type="xml">
<form string="Retrospective Method">
<sheet>
<group>
<group>
<field name="name"/>
</group>
</group>
<notebook>
<page string="Description">
<field name="description"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="retrospective_method_tree_view" model="ir.ui.view">
<field name="name">Retrospective Method</field>
<field name="model">retrospective.method</field>
<field name="arch" type="xml">
<tree string="Retrospective Methods">
<field name="name"/>
</tree>
</field>
</record>
<record id="action_retrospective_method_tree_view" model="ir.actions.act_window">
<field name="name">Retrospective Method</field>
<field name="res_model">retrospective.method</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="retrospective_method_tree_view"/>
</record>
<menuitem name="Retrospective" id="retrospective_menu_id" parent="project.menu_main_pm" sequence="1"/>
<menuitem
id="retrospective_method"
parent="retrospective_menu_id"
groups="project.group_project_manager"
action="action_retrospective_method_tree_view"
sequence="5"
/>
</flectra>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="retrospective_form_view_id" model="ir.ui.view">
<field name="name">Retrospective</field>
<field name="model">retrospective</field>
<field name="arch" type="xml">
<form string="Retrospective">
<sheet>
<group>
<group>
<field name="name"/>
<field name="retrospective_method_id"
options="{'no_create': True, 'no_create_edit': True}"/>
<field name="start_date"/>
<field name="end_date"/>
</group>
<group>
<field name="sprint_id" options="{'no_create': True, 'no_create_edit': True}"/>
<field name="scrum_master" options="{'no_create': True, 'no_create_edit': True}"/>
</group>
</group>
<notebook>
<page string="Retrospective Lines">
<field name="retrospective_line_ids" widget="one2many_list"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="retrospective_tree_view_id" model="ir.ui.view">
<field name="name">Retrospective</field>
<field name="model">retrospective</field>
<field name="arch" type="xml">
<tree string="Retrospectives">
<field name="retrospective_method_id"/>
<field name="scrum_master"/>
<field name="sprint_id"/>
<field name="start_date"/>
<field name="end_date"/>
</tree>
</field>
</record>
<record id="action_retrospective_tree_view_id" model="ir.actions.act_window">
<field name="name">Retrospective</field>
<field name="res_model">retrospective</field>
<field name="view_mode">form,tree</field>
<field name="view_id" ref="retrospective_tree_view_id"/>
</record>
<record id="retrospective_lines_tree_view_id" model="ir.ui.view">
<field name="name">Retrospective Line</field>
<field name="model">retrospective.lines</field>
<field name="arch" type="xml">
<tree editable="bottom">
<field name="user_id"/>
<field name="message"/>
</tree>
</field>
</record>
<menuitem
name="Retrospective"
id="retrospective_id"
parent="retrospective_menu_id"
action="action_retrospective_tree_view_id"
sequence="1"
/>
</flectra>