Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Intuitive interface for creating Sync Links for Odoo records #394

Closed
Closed
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
1 change: 1 addition & 0 deletions sync_record_mapping/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import wizard
23 changes: 23 additions & 0 deletions sync_record_mapping/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Remember to bump the module version every time you make a change!

{
"name": "Record Mapping for Sync Studio",
"summary": "Adds a more intuitive interface for managing manual record mappings between Odoo and external systems.",
"version": "14.0.1.0.0",
"category": "Extra Tools",
"author": "Butopea, " "Mohammad Tomaraei",
"website": "https://butopea.com",
"license": "AGPL-3",
"depends": ["base", "sync"],
"qweb": [
"views/debug.xml"
],
"data": [
"security/ir.model.access.csv",
"views/assets.xml",
"wizard/sync_record_mapping_wizard.xml"
],
"installable": True,
"application": False,
"auto_install": False,
}
3 changes: 3 additions & 0 deletions sync_record_mapping/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sync_record_mapping_wizard_user,sync.record.mapping.wizard user,model_sync_record_mapping_wizard,sync.sync_group_user,1,1,1,1
access_sync_record_mapping_wizard_dev,sync.record.mapping.wizard dev,model_sync_record_mapping_wizard,sync.sync_group_dev,1,1,1,1
Binary file added sync_record_mapping/static/description/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions sync_record_mapping/static/src/js/debug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
odoo.define('sync_record_mapping.DebugManager.Backend', function (require) {
"use strict";

var core = require('web.core');
var DebugManager = require('web.DebugManager.Backend');

var _t = core._t;
/**
* adds a new method available for the debug manager, called by the "Manage Record Mappings" button.
*
*/
DebugManager.include({
getRecordMappings: function () {
var selectedIDs = this._controller.getSelectedIds();
if (!selectedIDs.length) {
console.warn(_t("At least one record must be selected to manage record mappings."));
return;
}
this.do_action({
type: 'ir.actions.act_window',
name: _t('Manage Record Mappings'),
res_model: 'sync.record.mapping.wizard',
views: [[false, 'form']],
target: 'new',
view_mode: 'form',
domain: [['res_id', '=', selectedIDs[0]], ['model', '=', this._controller.modelName]],
context: {
default_res_model: this._controller.modelName,
default_res_id: selectedIDs[0],
},
});
},
});

});
10 changes: 10 additions & 0 deletions sync_record_mapping/views/assets.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="assets_backend" name="sync_record_mapping assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/sync_record_mapping/static/src/js/debug.js"></script>
</xpath>
</template>
</data>
</odoo>
15 changes: 15 additions & 0 deletions sync_record_mapping/views/debug.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-extend="WebClient.DebugManager.View">
<t t-jquery="a[data-action='get_metadata']" t-operation="after">
<a
role="menuitem"
href="#"
data-action="getRecordMappings"
class="dropdown-item"
>
Manage Record Mappings
</a>
</t>
</t>
</templates>
1 change: 1 addition & 0 deletions sync_record_mapping/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import sync_record_mapping_wizard
50 changes: 50 additions & 0 deletions sync_record_mapping/wizard/sync_record_mapping_wizard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError


class SyncRecordMappingWizard(models.TransientModel):
_name = 'sync.record.mapping.wizard'

res_model = fields.Char('Odoo Model')
res_id = fields.Many2oneReference('Related Document ID', model_field='res_model')

@staticmethod
def record_mapping_domain(res_id, res_model):
return [
'&',
'&',
('system2', '=', '__odoo__'),
('ref2', '=', str(res_id)),
('model', '=', res_model)
]

@api.depends('res_model', 'res_id')
def _compute_record_mapping_ids(self):
self.ensure_one()
if not self.res_model or not self.res_id:
raise UserError(_('Invalid model or record.'))
record_mapping_ids = self.env['sync.link'].search(
self.record_mapping_domain(self.res_id, self.res_model)
)
if record_mapping_ids:
self.record_mapping_ids = [(6, 0, record_mapping_ids.ids)]
else:
self.record_mapping_ids = False

def _inverse_record_mapping_ids(self):
""" Detects changes in record mappings to delete the records """
self.ensure_one()
record_mapping_ids = self.env['sync.link'].search(
self.record_mapping_domain(self.res_id, self.res_model)
)
# TODO: Could this possibly cause a race condition?
record_mapping_ids_to_delete = record_mapping_ids - self.record_mapping_ids
if record_mapping_ids_to_delete:
record_mapping_ids_to_delete.unlink()

record_mapping_ids = fields.Many2many(
'sync.link',
compute='_compute_record_mapping_ids',
inverse='_inverse_record_mapping_ids',
store=True
)
72 changes: 72 additions & 0 deletions sync_record_mapping/wizard/sync_record_mapping_wizard.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_sync_record_mapping_wizard_form" model="ir.ui.view">
<field name="name">sync.record.mapping.wizard.form</field>
<field name="model">sync.record.mapping.wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form create="0">
<field name="res_model" invisible="1"/>
<field name="res_id" invisible="1"/>
<group>
<!-- Redundant domain definition, because using the domain argument in the field definition
initially yields an empty domain, but it remains on the record selection popup. -->
<field
name="record_mapping_ids"
nolabel="1"
domain="[
'&amp;',
'&amp;',
('system1', '=', '__external__'),
('system2', '=', '__odoo__'),
('ref2', '=', str(res_id)),
('model', '=', res_model),
]"
context="{
'tree_view_ref':'sync_record_mapping.view_record_mapping_ids_tree',
'form_view_ref':'sync_record_mapping.view_record_mapping_ids_form',
'default_system1': '__external__',
'default_system2': '__odoo__',
'default_model': res_model,
'default_ref2': res_id
}"
/>
</group>
</form>
</field>
</record>
<record id="view_record_mapping_ids_tree" model="ir.ui.view">
<field name="name">sync.record.mapping.ids.tree</field>
<field name="model">sync.link</field>
<field name="mode">primary</field>
<field name="arch" type="xml">
<tree>
<field name="relation"/>
<field name="system1" invisible="1"/>
<field name="ref1" string="External Reference"/>
<field name="model" invisible="1"/>
<field name="ref2" invisible="1"/>
<field name="system2" invisible="1"/>
<field name="date" invisible="1"/>
</tree>
</field>
</record>
<record id="view_record_mapping_ids_form" model="ir.ui.view">
<field name="name">sync.record.mapping.ids.form</field>
<field name="model">sync.link</field>
<field name="mode">primary</field>
<field name="arch" type="xml">
<form>
<group>
<field name="relation"/>
<field name="system1" invisible="1"/>
<field name="ref1" string="External Reference"/>
<field name="model" invisible="1"/>
<field name="ref2" invisible="1"/>
<field name="system2" invisible="1"/>
<field name="date" invisible="1"/>
</group>
</form>
</field>
</record>
</odoo>