Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions vcp_management/README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

==============
VCP Management
==============
Expand All @@ -17,7 +13,7 @@ VCP Management
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fversion--control--platform-lightgray.png?logo=github
Expand Down
1 change: 1 addition & 0 deletions vcp_management/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from . import models
from . import reports
1 change: 1 addition & 0 deletions vcp_management/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"security/ir.model.access.csv",
"data/ir_cron.xml",
"templates/templates.xml",
"reports/vcp_management_report.xml",
"views/vcp_comment.xml",
"views/vcp_review.xml",
"views/vcp_request.xml",
Expand Down
2 changes: 1 addition & 1 deletion vcp_management/models/vcp_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class VcpComment(models.Model):
readonly=True,
store=True,
)
created_at = fields.Datetime(readonly=True)
created_at = fields.Datetime(readonly=True, index=True)
updated_at = fields.Datetime(readonly=True)
request_id = fields.Many2one(
comodel_name="vcp.request",
Expand Down
4 changes: 2 additions & 2 deletions vcp_management/models/vcp_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ class VcpRequest(models.Model):
)
is_merged = fields.Boolean(readonly=True)
is_draft = fields.Boolean(readonly=True)
created_at = fields.Datetime(readonly=True)
created_at = fields.Datetime(readonly=True, index=True)
updated_at = fields.Datetime(readonly=True)
closed_at = fields.Datetime(readonly=True)
closed_at = fields.Datetime(readonly=True, index=True)
number = fields.Integer(readonly=True)
label_ids = fields.Many2many(
comodel_name="vcp.request.label",
Expand Down
2 changes: 1 addition & 1 deletion vcp_management/models/vcp_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class VcpReview(models.Model):
partner_id = fields.Many2one(
related="user_id.partner_id",
)
submitted_at = fields.Datetime(readonly=True)
submitted_at = fields.Datetime(readonly=True, index=True)
repository_id = fields.Many2one(
related="request_id.repository_id",
readonly=True,
Expand Down
1 change: 1 addition & 0 deletions vcp_management/reports/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import vcp_management_report
101 changes: 101 additions & 0 deletions vcp_management/reports/vcp_management_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Copyright 2026 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
from odoo.tools import SQL


class VCPManagementReport(models.Model):
_name = "vcp.management.report"
_description = "VCP Statistics"
_auto = False
_log_access = False
_rec_name = "user_id"
_order = "date desc"

platform_id = fields.Many2one("vcp.platform")
user_id = fields.Many2one("vcp.user")
organization_id = fields.Many2one("vcp.organization")
repository_id = fields.Many2one("vcp.repository")
date = fields.Datetime()
merged_pr_count = fields.Integer()
created_pr_count = fields.Integer()
review_count = fields.Integer()
comment_count = fields.Integer()

def _get_table_definition(self):
return {
"created_prs": {
"table": "vcp_request",
"date": "t.created_at",
"created_pr_count": "1",
},
"merged_prs": {
"table": "vcp_request",
"date": "t.closed_at",
"merged_pr_count": "1",
"filter": "t.is_merged = True",
},
"reviews": {
"table": "vcp_review",
"date": "t.submitted_at",
"review_count": "1",
},
"comments": {
"table": "vcp_comment",
"date": "t.created_at",
"comment_count": "1",
},
}

@property
def _table_query(self) -> SQL:
return SQL(self._get_sql_definition())

def _get_sql_definition(self):
definition = self._get_table_definition().items()
union_queries = []
element_number = 0
for table_name, table_def in definition:
union_queries.append(
self._get_table_query(
table_name, table_def, element_number, len(definition)
)
)
element_number += 1
return " UNION ALL ".join(union_queries)

def _get_table_query(self, table_name, table_def, element_number, total_elements):
from_definition = self._get_from_definition(table_name, table_def)
select_fields = self._get_select_fields(
table_def, element_number, total_elements
)
select_fields_str = ", ".join(select_fields)
filter_condition = (
f"WHERE {table_def['filter']}" if "filter" in table_def else ""
)
return f"""
SELECT
{select_fields_str}
FROM {from_definition}
{filter_condition}
"""

def _get_from_definition(self, table_name, table_def):
table = table_def.get("table", table_name)
repository_id = table_def.get("repository_id", "t.repository_id")
return f"{table} AS t LEFT JOIN vcp_repository AS r ON {repository_id} = r.id"

def _get_select_fields(self, table_def, element_number, total_elements):
organization = table_def.get("organization_id", "t.organization_id")
return [
f"{element_number}+{total_elements}*t.id AS id",
f"{table_def.get('platform_id', 'r.platform_id')} AS platform_id",
f"{organization} AS organization_id",
f"{table_def.get('user_id', 't.user_id')} AS user_id",
f"{table_def.get('repository_id', 't.repository_id')} AS repository_id",
f"{table_def.get('date', 't.create_date')} AS date",
f"{table_def.get('merged_pr_count', 0)} AS merged_pr_count",
f"{table_def.get('created_pr_count', 0)} AS created_pr_count",
f"{table_def.get('review_count', 0)} AS review_count",
f"{table_def.get('comment_count', 0)} AS comment_count",
]
37 changes: 37 additions & 0 deletions vcp_management/reports/vcp_management_report.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2026 Dixmit
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="vcp_management_report_pivot_view">
<field name="model">vcp.management.report</field>
<field name="arch" type="xml">
<pivot string="Invoices Analysis" sample="1">
<field name="user_id" type="row" />
<field name="date" type="col" />
<field name="merged_pr_count" type="measure" />
</pivot>
</field>
</record>
<record model="ir.ui.view" id="vcp_management_report_search_view">
<field name="model">vcp.management.report</field>
<field name="arch" type="xml">
<search>
<field name="user_id" />
<field name="organization_id" />
<field name="repository_id" />
<field name="platform_id" />
<separator />
<filter name="filter_date" date="date" />
</search>
</field>
</record>

<record model="ir.actions.act_window" id="vcp_management_report_act_window">
<field name="name">Reporting</field>
<field name="path">vcp-report</field>
<field name="res_model">vcp.management.report</field>
<field name="view_mode">pivot</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
</odoo>
1 change: 1 addition & 0 deletions vcp_management/security/ir.model.access.csv
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ access_organization,Access Organizations,model_vcp_organization,group_vcp_user,1
manage_organization,Manage Organizations,model_vcp_organization,group_vcp_manager,1,1,1,1
access_vcp_rule,Access VCP Rules,model_vcp_rule,group_vcp_user,1,0,0,0
manage_vcp_rule,Manage VCP Rules,model_vcp_rule,group_vcp_manager,1,1,1,1
access_vcp_report,Access VCP REport,model_vcp_management_report,group_vcp_manager,1,0,0,0
46 changes: 20 additions & 26 deletions vcp_management/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<title>VCP Management</title>
<style type="text/css">

/*
Expand Down Expand Up @@ -360,21 +360,16 @@
</style>
</head>
<body>
<div class="document">
<div class="document" id="vcp-management">
<h1 class="title">VCP Management</h1>


<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="vcp-management">
<h1>VCP Management</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:b2557a3fa2705c48d7fc80b1fc2df6bb92e35858bcd0d25a892fa6cad65a0664
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/version-control-platform/tree/18.0/vcp_management"><img alt="OCA/version-control-platform" src="https://img.shields.io/badge/github-OCA%2Fversion--control--platform-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/version-control-platform-18-0/version-control-platform-18-0-vcp_management"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/version-control-platform&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/version-control-platform/tree/18.0/vcp_management"><img alt="OCA/version-control-platform" src="https://img.shields.io/badge/github-OCA%2Fversion--control--platform-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/version-control-platform-18-0/version-control-platform-18-0-vcp_management"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/version-control-platform&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>Creates a set of modules used for handling a version control patform.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
Expand Down Expand Up @@ -406,41 +401,41 @@ <h1>VCP Management</h1>
</ul>
</div>
<div class="section" id="use-cases-context">
<h2><a class="toc-backref" href="#toc-entry-1">Use Cases / Context</a></h2>
<h1><a class="toc-backref" href="#toc-entry-1">Use Cases / Context</a></h1>
<p>The aim of this module is to allow any community to import data from a
version control system.</p>
<p>The system should be done in a way that is agnostic to the system and
the connections are handled directly by specific modules.</p>
<div class="section" id="definitions">
<h3><a class="toc-backref" href="#toc-entry-2">Definitions</a></h3>
<h2><a class="toc-backref" href="#toc-entry-2">Definitions</a></h2>
<div class="section" id="hosts">
<h4><a class="toc-backref" href="#toc-entry-3">Hosts</a></h4>
<h3><a class="toc-backref" href="#toc-entry-3">Hosts</a></h3>
<p>Hosts are the origin of data. Each host has a type that helps us know
how to integrate with the system. For example, on Github there is only
one host (github.com). However, in Gitlab there could be one for each
instance that we are integrating too.</p>
</div>
<div class="section" id="platform">
<h4><a class="toc-backref" href="#toc-entry-4">Platform</a></h4>
<h3><a class="toc-backref" href="#toc-entry-4">Platform</a></h3>
<p>We understand that a platform is an entity that can provide code and
information to our Version Control Platform (VCP). A platform could be
an organization on Github (like OCA) or Gitlab for example.</p>
</div>
<div class="section" id="repository">
<h4><a class="toc-backref" href="#toc-entry-5">Repository</a></h4>
<h3><a class="toc-backref" href="#toc-entry-5">Repository</a></h3>
<p>A repository is an origin of code. For example, <a class="reference external" href="https://github.com/OCA/version-control-platform">this
repository</a> could be
a VCP repository.</p>
</div>
<div class="section" id="requests">
<h4><a class="toc-backref" href="#toc-entry-6">Requests</a></h4>
<h3><a class="toc-backref" href="#toc-entry-6">Requests</a></h3>
<p>A request is what contributors do to propose new codes. In Github it is
a Pull request, however in Gitlab it is called Merge Request.</p>
<p>When a user makes a review on a request, it markes their resolution and
some comments. That would correspond to Reviews and Comments.</p>
</div>
<div class="section" id="rules">
<h4><a class="toc-backref" href="#toc-entry-7">Rules</a></h4>
<h3><a class="toc-backref" href="#toc-entry-7">Rules</a></h3>
<p>Inside a Platform or repository, we can apply some rules to get some
basic statistics. This rules are usually done by downloading the code
locally and then it can give some basic information like number of lines
Expand All @@ -449,20 +444,20 @@ <h4><a class="toc-backref" href="#toc-entry-7">Rules</a></h4>
</div>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-8">Usage</a></h2>
<h1><a class="toc-backref" href="#toc-entry-8">Usage</a></h1>
<div class="section" id="creation">
<h3><a class="toc-backref" href="#toc-entry-9">Creation</a></h3>
<h2><a class="toc-backref" href="#toc-entry-9">Creation</a></h2>
<p>First step is to create a Platform. In the platform we need to set the
host (you might need to create it on gitlab) and add some Platform Keys.</p>
<p>This keys will allow us to integrate with the origin system.</p>
</div>
<div class="section" id="refresh">
<h3><a class="toc-backref" href="#toc-entry-10">Refresh</a></h3>
<h2><a class="toc-backref" href="#toc-entry-10">Refresh</a></h2>
<p>By default, the system provides some refresh rules for platforms and
repositories, however we can deactivate or activate it manualy.</p>
</div>
<div class="section" id="management-of-rules">
<h3><a class="toc-backref" href="#toc-entry-11">Management of rules</a></h3>
<h2><a class="toc-backref" href="#toc-entry-11">Management of rules</a></h2>
<p>One of the capabilities of this module is the generation of rules.</p>
<p>This rules allow us to know some information of the repository.</p>
<p>By default, the system adds some rules aligned with odoo to make it
Expand All @@ -479,23 +474,23 @@ <h3><a class="toc-backref" href="#toc-entry-11">Management of rules</a></h3>
</div>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-12">Bug Tracker</a></h2>
<h1><a class="toc-backref" href="#toc-entry-12">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/version-control-platform/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/version-control-platform/issues/new?body=module:%20vcp_management%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-13">Credits</a></h2>
<h1><a class="toc-backref" href="#toc-entry-13">Credits</a></h1>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-14">Authors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-14">Authors</a></h2>
<ul class="simple">
<li>Dixmit</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-15">Contributors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-15">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://dixmit.com">Dixmit</a><ul>
<li>Enric Tobella</li>
Expand All @@ -508,7 +503,7 @@ <h3><a class="toc-backref" href="#toc-entry-15">Contributors</a></h3>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-16">Maintainers</a></h3>
<h2><a class="toc-backref" href="#toc-entry-16">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
Expand All @@ -521,6 +516,5 @@ <h3><a class="toc-backref" href="#toc-entry-16">Maintainers</a></h3>
</div>
</div>
</div>
</div>
</body>
</html>
8 changes: 8 additions & 0 deletions vcp_management/views/menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@
action="vcp_request_act_window"
sequence="20"
/>
<menuitem id="vcp_reporting" name="Reporting" sequence="60">
<menuitem
id="vcp_management_report_menu"
name="Management Reporting"
action="vcp_management_report_act_window"
sequence="10"
/>
</menuitem>

<menuitem id="vcp_technical_menu" name="Technical" sequence="70">
<menuitem
Expand Down
Loading