diff --git a/odf_data_quality_dashboard/__init__.py b/odf_data_quality_dashboard/__init__.py
new file mode 100644
index 00000000..cde864ba
--- /dev/null
+++ b/odf_data_quality_dashboard/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
diff --git a/odf_data_quality_dashboard/__manifest__.py b/odf_data_quality_dashboard/__manifest__.py
new file mode 100644
index 00000000..2e2cc17b
--- /dev/null
+++ b/odf_data_quality_dashboard/__manifest__.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': 'ODF Data Quality Dashboard',
+ 'version': '18.0.1.0.0',
+ 'summary': 'Data Quality Dashboard for Odoo',
+ 'author': 'Odoo Community Association (OCA), Odoo Data Flow',
+ 'website': 'https://github.com/OCA/odoo-data-flow',
+ 'license': 'AGPL-3',
+ 'category': 'Tools',
+ 'depends': ['base'],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'views/data_quality_issue_views.xml',
+ 'views/menus.xml',
+ 'data/scheduled_actions.xml',
+ ],
+ 'installable': True,
+}
diff --git a/odf_data_quality_dashboard/data/scheduled_actions.xml b/odf_data_quality_dashboard/data/scheduled_actions.xml
new file mode 100644
index 00000000..ba733c32
--- /dev/null
+++ b/odf_data_quality_dashboard/data/scheduled_actions.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ Data Quality: Run Checks
+
+ code
+ model._run_data_quality_checks()
+
+ 1
+ days
+ -1
+
+
+
+
+
diff --git a/odf_data_quality_dashboard/models/__init__.py b/odf_data_quality_dashboard/models/__init__.py
new file mode 100644
index 00000000..3a7acc89
--- /dev/null
+++ b/odf_data_quality_dashboard/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import data_quality_issue
diff --git a/odf_data_quality_dashboard/models/data_quality_issue.py b/odf_data_quality_dashboard/models/data_quality_issue.py
new file mode 100644
index 00000000..9d3ea3ca
--- /dev/null
+++ b/odf_data_quality_dashboard/models/data_quality_issue.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+from odoo import api, fields, models
+from odoo.addons.base.models.res_partner import Partner
+
+
+class DataQualityIssue(models.Model):
+ _name = 'odf.data.quality.issue'
+ _description = 'Data Quality Issue'
+
+ name = fields.Char(
+ string='Name',
+ required=True,
+ )
+ issue_type = fields.Char(
+ string='Issue Type',
+ )
+ related_record = fields.Reference(
+ selection=[
+ ('res.partner', 'Partner'),
+ ('product.product', 'Product'),
+ ],
+ string='Related Record',
+ )
+ status = fields.Selection(
+ selection=[
+ ('new', 'New'),
+ ('in_progress', 'In Progress'),
+ ('resolved', 'Resolved'),
+ ],
+ string='Status',
+ default='new',
+ )
+ notes = fields.Text(
+ string='Notes',
+ )
+
+ @api.model
+ def _run_data_quality_checks(self):
+ self._check_partner_vat()
+
+ @api.model
+ def _check_partner_vat(self):
+ """Check for partners with invalid VAT."""
+ from datetime import timedelta
+ yesterday = fields.Datetime.now() - timedelta(days=1)
+ partners_to_check = self.env['res.partner'].search([
+ ('write_date', '>=', fields.Datetime.to_string(yesterday)),
+ ('vat', '!=', False),
+ ('vat', '!=', ''),
+ ])
+ for partner in partners_to_check:
+ # This is a placeholder for a real VAT validation.
+ # For this example, we consider a VAT invalid if it has less than 3 chars.
+ if len(partner.vat) < 3:
+ # Avoid creating duplicate issues for the same partner.
+ existing_issue = self.search_count([
+ ('related_record', '=', f'res.partner,{partner.id}'),
+ ('issue_type', '=', 'Invalid VAT'),
+ ('status', '!=', 'resolved'),
+ ])
+ if not existing_issue:
+ self.create({
+ 'name': f"Invalid VAT number for '{partner.display_name}'",
+ 'issue_type': 'Invalid VAT',
+ 'related_record': f'res.partner,{partner.id}',
+ })
diff --git a/odf_data_quality_dashboard/security/ir.model.access.csv b/odf_data_quality_dashboard/security/ir.model.access.csv
new file mode 100644
index 00000000..89e0284d
--- /dev/null
+++ b/odf_data_quality_dashboard/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_odf_data_quality_issue_user,odf.data.quality.issue.user,model_odf_data_quality_issue,base.group_user,1,1,1,1
diff --git a/odf_data_quality_dashboard/views/data_quality_issue_views.xml b/odf_data_quality_dashboard/views/data_quality_issue_views.xml
new file mode 100644
index 00000000..bb42fe49
--- /dev/null
+++ b/odf_data_quality_dashboard/views/data_quality_issue_views.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+ odf.data.quality.issue.form
+ odf.data.quality.issue
+
+
+
+
+
+
+
+ odf.data.quality.issue.kanban
+ odf.data.quality.issue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ odf.data.quality.issue.tree
+ odf.data.quality.issue
+
+
+
+
+
+
+
+
+
+
+
+
+ Data Quality Issues
+ odf.data.quality.issue
+ kanban,tree,form
+
+
+
+
diff --git a/odf_data_quality_dashboard/views/menus.xml b/odf_data_quality_dashboard/views/menus.xml
new file mode 100644
index 00000000..31f26015
--- /dev/null
+++ b/odf_data_quality_dashboard/views/menus.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+