Skip to content

Commit

Permalink
Moved deduplicator module from social-registry repo
Browse files Browse the repository at this point in the history
Signed-off-by: Lalith Kota <[email protected]>
  • Loading branch information
lalithkota committed Nov 18, 2024
1 parent b9c7098 commit 84c052c
Show file tree
Hide file tree
Showing 19 changed files with 425 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ addon | version | maintainers | summary
[g2p_registry_addl_info_rest_api](g2p_registry_addl_info_rest_api/) | 17.0.1.4.0 | | G2P Registry: Additional Info REST API
[g2p_registry_base](g2p_registry_base/) | 17.0.1.4.0 | | G2P Registry: Base
[g2p_registry_datashare_websub](g2p_registry_datashare_websub/) | 17.0.1.4.0 | | G2P Registry Datashare: WebSub
[g2p_registry_deduplication_deduplicator](g2p_registry_deduplication_deduplicator/) | 17.0.0.0.0 | | OpenG2P Registry Deduplication - Deduplicator
[g2p_registry_documents](g2p_registry_documents/) | 17.0.1.4.0 | | G2P Registry: Documents
[g2p_registry_encryption](g2p_registry_encryption/) | 17.0.1.4.0 | | G2P Registry: Encryption
[g2p_registry_group](g2p_registry_group/) | 17.0.1.4.0 | | G2P Registry: Groups
Expand Down
3 changes: 3 additions & 0 deletions g2p_registry_deduplication_deduplicator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# OpenG2P Registry Deduplication - Deduplicator

Refer to https://docs.openg2p.org.
2 changes: 2 additions & 0 deletions g2p_registry_deduplication_deduplicator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Part of OpenG2P Social Registry. See LICENSE file for full copyright and licensing details.
from . import models
32 changes: 32 additions & 0 deletions g2p_registry_deduplication_deduplicator/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Part of OpenG2P Social Registry. See LICENSE file for full copyright and licensing details.
{
"name": "OpenG2P Registry Deduplication - Deduplicator",
"category": "G2P",
"version": "17.0.0.0.0",
"sequence": 1,
"author": "OpenG2P",
"website": "https://openg2p.org",
"license": "LGPL-3",
"depends": [
"g2p_registry_individual",
],
"external_dependencies": {},
"data": [
"security/ir.model.access.csv",
"data/default_deduplicator_config.xml",
"views/deduplicator_config_view.xml",
"views/individual_view.xml",
"views/res_config_view.xml",
],
"assets": {
"web.assets_backend": [
"g2p_registry_deduplication_deduplicator/static/src/js/view_duplicates.js",
"g2p_registry_deduplication_deduplicator/static/src/xml/view_duplicates_template.xml",
],
},
"demo": [],
"images": [],
"application": True,
"installable": True,
"auto_install": False,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<record model="g2p.registry.deduplication.deduplicator.config" id="default_deduplicator_config">
<field name="name">Default</field>
<field name="active" eval="1" />
</record>
<function
model="ir.config_parameter"
name="set_param"
eval="('g2p_registry_deduplication_deduplicator.deduplicator_config_id', ref('g2p_registry_deduplication_deduplicator.default_deduplicator_config'))"
/>
</odoo>
4 changes: 4 additions & 0 deletions g2p_registry_deduplication_deduplicator/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Part of OpenG2P. See LICENSE file for full copyright and licensing details.
from . import registrant
from . import dedupe_config
from . import res_config_settings
106 changes: 106 additions & 0 deletions g2p_registry_deduplication_deduplicator/models/dedupe_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import logging
import os

import requests

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError

_logger = logging.getLogger(__name__)


class G2PDedupeConfigField(models.Model):
_name = "g2p.registry.deduplication.deduplicator.config.field"
_description = "Deduplicator Config Field"

name = fields.Char(required=True)
fuzziness = fields.Char()
weightage = fields.Float()
exact = fields.Boolean()

dedupe_config_id = fields.Many2one(
"g2p.registry.deduplication.deduplicator.config", ondelete="cascade", required=True
)


class G2PDedupeConfig(models.Model):
_name = "g2p.registry.deduplication.deduplicator.config"
_description = "Deduplicator Config"

name = fields.Char(required=True)

config_name = fields.Char(required=True, default="default")

dedupe_service_base_url = fields.Char(
default=os.getenv(
"DEDUPLICATOR_SERVICE_BASE_URL", "http://socialregistry-deduplicator-openg2p-deduplicator"
)
)
dedupe_service_api_timeout = fields.Integer(default=10)

config_index_name = fields.Char(default="res_partner")
config_fields = fields.One2many(
"g2p.registry.deduplication.deduplicator.config.field", "dedupe_config_id"
)
config_score_threshold = fields.Float()

active = fields.Boolean(required=True)

_sql_constraints = [
("unique_config_name", "unique (config_name)", "Dedupe Config with same config name already exists !")
]

def save_upload_config(self):
for rec in self:
res = requests.put(
f"{rec.dedupe_service_base_url.rstrip('/')}/config/{rec.config_name}",
timeout=rec.dedupe_service_api_timeout,
json={
"index": rec.config_index_name,
"fields": [
{
"name": rec_field.name,
"fuzziness": rec_field.fuzziness,
"boost": rec_field.weightage,
**({"query_type": "term"} if rec_field.exact else {}),
}
for rec_field in rec.config_fields
],
"score_threshold": rec.config_score_threshold,
"active": rec.active,
},
)
try:
res.raise_for_status()
except Exception as e:
_logger.exception("Error uploading config")
raise ValidationError(_("Error uploading config")) from e

@api.model
def get_configured_deduplicator(self):
dedupe_config_id = (
self.env["ir.config_parameter"]
.sudo()
.get_param("g2p_registry_deduplication_deduplicator.deduplicator_config_id", None)
)
return self.browse(int(dedupe_config_id)) if dedupe_config_id else None

@api.model
def get_duplicates_by_record_id(self, record_id, config_id=None):
if config_id:
dedupe_config = self.browse(config_id)
else:
dedupe_config = self.get_configured_deduplicator()
res = requests.get(
f"{dedupe_config.dedupe_service_base_url.rstrip('/')}/getDuplicates/{record_id}",
timeout=dedupe_config.dedupe_service_api_timeout,
)
try:
res.raise_for_status()
except Exception as e:
raise ValidationError(_("Error retrieving duplicates")) from e
duplicates = res.json().get("duplicates")
for entry in duplicates:
duplicate_record = self.env["res.partner"].sudo().browse(entry.get("id"))
entry["name"] = duplicate_record.name
return duplicates
18 changes: 18 additions & 0 deletions g2p_registry_deduplication_deduplicator/models/registrant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from odoo import _, models


class Registrant(models.Model):
_inherit = "res.partner"

def view_deduplicator_duplicates(self):
self.ensure_one()
return {
"type": "ir.actions.client",
"tag": "g2p_registry_deduplication_deduplicator.view_duplicates_client_action",
"target": "new",
"name": _("Duplicates"),
"params": {
"record_id": self.id,
},
"context": {},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Part of OpenG2P. See LICENSE file for full copyright and licensing details.

from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

deduplicator_config_id = fields.Many2one(
"g2p.registry.deduplication.deduplicator.config",
config_parameter="g2p_registry_deduplication_deduplicator.deduplicator_config_id",
)
3 changes: 3 additions & 0 deletions g2p_registry_deduplication_deduplicator/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
g2p_registry_deduplication_deduplicator_config_admin,Deduplicator Config Admin Access,g2p_registry_deduplication_deduplicator.model_g2p_registry_deduplication_deduplicator_config,g2p_registry_base.group_g2p_admin,1,1,1,1
g2p_registry_deduplication_deduplicator_config_registrar,Deduplicator Config Registrar Access,g2p_registry_deduplication_deduplicator.model_g2p_registry_deduplication_deduplicator_config,g2p_registry_base.group_g2p_registrar,1,1,1,0
g2p_registry_deduplication_deduplicator_config_user,Deduplicator Config User Access,g2p_registry_deduplication_deduplicator.model_g2p_registry_deduplication_deduplicator_config,base.group_user,1,0,0,0

g2p_registry_deduplication_deduplicator_config_field_admin,Deduplicator Config Field Admin Access,g2p_registry_deduplication_deduplicator.model_g2p_registry_deduplication_deduplicator_config_field,g2p_registry_base.group_g2p_admin,1,1,1,1
g2p_registry_deduplication_deduplicator_config_field_registrar,Deduplicator Config Field Registrar Access,g2p_registry_deduplication_deduplicator.model_g2p_registry_deduplication_deduplicator_config_field,g2p_registry_base.group_g2p_registrar,1,1,1,0
g2p_registry_deduplication_deduplicator_config_field_user,Deduplicator Config Field User Access,g2p_registry_deduplication_deduplicator.model_g2p_registry_deduplication_deduplicator_config_field,base.group_user,1,0,0,0
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/** @odoo-module **/

import {Component, useState} from "@odoo/owl";
import {_t} from "@web/core/l10n/translation";
import {registry} from "@web/core/registry";
import {useService} from "@web/core/utils/hooks";

export class ViewDeduplicatorDuplicates extends Component {
setup() {
this.recordId = this.props.action.params.record_id;

this.state = useState({dataLoading: "not_loaded"});
this.displayError = "";
this.duplicatesData = [];

this.ormService = useService("orm");
const self = this;
this.ormService
.call("g2p.registry.deduplication.deduplicator.config", "get_duplicates_by_record_id", [
this.recordId,
])
.then((res) => {
self.duplicatesData = res;
self.state.dataLoading = "loaded";
})
.catch((err) => {
console.error("Cannot retrieve duplicates", err);
self.displayError = _t("Cannot retrieve duplicates") + err;
self.state.dataLoading = "error";
});
}
}

ViewDeduplicatorDuplicates.template = "g2p_registry_deduplicator_view_duplicates_tpl";

registry
.category("actions")
.add("g2p_registry_deduplication_deduplicator.view_duplicates_client_action", ViewDeduplicatorDuplicates);
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" ?>
<template xml:space="preserve">
<t t-name="g2p_registry_deduplicator_view_duplicates_tpl">
<t t-if="this.state.dataLoading === 'not_loaded'">
<!-- TODO: loading animation -->
</t>
<t t-elif="this.state.dataLoading === 'loaded'">
<t t-call="g2p_registry_deduplicator_view_duplicates_data_tpl" />
</t>
<t t-elif="this.state.dataLoading === 'error'">
<p><t t-esc="this.displayError" /></p>
</t>
</t>
<t t-name="g2p_registry_deduplicator_view_duplicates_data_tpl">
<table class="o_list_table table table-sm table-hover o_list_table_ungrouped table-striped">
<thead>
<tr>
<th
data-name="id_type"
class="align-middle o_column_sortable cursor-pointer opacity-trigger-hover"
>
<span class="d-block min-w-0 text-truncate">ID</span>
<i class="fa fa-lg fa-angle-down opacity-0 opacity-75-hover" />
</th>
<th
data-name="value"
class="align-middle o_column_sortable cursor-pointer opacity-trigger-hover"
>
<span class="d-block min-w-0 text-truncate">Name</span>
<i class="fa fa-lg fa-angle-down opacity-0 opacity-75-hover" />
</th>
<th
data-name="expiry_date"
class="align-middle o_column_sortable cursor-pointer opacity-trigger-hover"
>
<span class="d-block min-w-0 text-truncate flex-grow-1">Score</span>
<i class="fa fa-lg fa-angle-down opacity-0 opacity-75-hover" />
</th>
</tr>
</thead>
<tbody class="ui-sortable">
<t t-if="this.duplicatesData">
<t t-foreach="this.duplicatesData" t-as="duplicate" t-key="duplicate.id">
<tr>
<td><t t-esc="duplicate.id" /></td>
</tr>
<tr>
<td><t t-esc="duplicate.name" /></td>
</tr>
<tr>
<td><t t-esc="duplicate.match_score" /></td>
</tr>
</t>
</t>
<t t-else="">
<!-- TODO: Render no duplicates -->
</t>
</tbody>
</table>
</t>
</template>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_g2p_registry_deduplicator_config_tree" model="ir.ui.view">
<field name="name">view_g2p_registry_deduplicator_config_tree</field>
<field name="model">g2p.registry.deduplication.deduplicator.config</field>
<field name="priority" eval="1" />
<field name="arch" type="xml">
<tree>
<field name="name" />
<field name="config_name" />
<field name="config_index_name" />
</tree>
</field>
</record>

<record id="view_g2p_registry_deduplicator_config_form" model="ir.ui.view">
<field name="name">view_g2p_registry_deduplicator_config_form</field>
<field name="model">g2p.registry.deduplication.deduplicator.config</field>
<field name="priority" eval="1" />
<field name="arch" type="xml">
<form>
<header>
<button
type="object"
class="btn-success"
name="save_upload_config"
title="Sync Config"
string="Sync Config"
/>
</header>
<group name="dedupe_config_base" string="Base">
<field name="name" />
<field name="config_name" />
</group>
<group name="dedupe_config_params" string="Parameters">
<field name="config_index_name" />
<field name="dedupe_service_base_url" />
<field name="config_fields">
<tree editable="bottom">
<field name="name" />
<field name="fuzziness" />
<field name="weightage" />
<field name="exact" />
</tree>
</field>
<field name="config_score_threshold" />
</group>
</form>
</field>
</record>

<record id="action_deduplicator_config" model="ir.actions.act_window">
<field name="name">Deduplicator Config</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">g2p.registry.deduplication.deduplicator.config</field>
<field name="view_mode">tree,form</field>
<field name="context">{}</field>
<field name="domain">[]</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Add an Deduplicator Config!
</p><p>
Click the create button to configure a new Deduplicator.
</p>
</field>
</record>

<menuitem
id="g2p_registry_deduplicator_config_menu"
name="Deduplicator Configs"
action="action_deduplicator_config"
parent="g2p_registry_base.g2p_configuration_menu_root"
sequence="2000"
groups="g2p_registry_base.group_g2p_admin,g2p_registry_base.group_g2p_registrar"
/>
</odoo>
Loading

0 comments on commit 84c052c

Please sign in to comment.