diff --git a/sync_record_mapping/__init__.py b/sync_record_mapping/__init__.py
new file mode 100644
index 00000000..40272379
--- /dev/null
+++ b/sync_record_mapping/__init__.py
@@ -0,0 +1 @@
+from . import wizard
diff --git a/sync_record_mapping/__manifest__.py b/sync_record_mapping/__manifest__.py
new file mode 100644
index 00000000..72cdef93
--- /dev/null
+++ b/sync_record_mapping/__manifest__.py
@@ -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,
+}
diff --git a/sync_record_mapping/security/ir.model.access.csv b/sync_record_mapping/security/ir.model.access.csv
new file mode 100644
index 00000000..f8114db5
--- /dev/null
+++ b/sync_record_mapping/security/ir.model.access.csv
@@ -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
\ No newline at end of file
diff --git a/sync_record_mapping/static/description/icon.png b/sync_record_mapping/static/description/icon.png
new file mode 100644
index 00000000..2ad931db
Binary files /dev/null and b/sync_record_mapping/static/description/icon.png differ
diff --git a/sync_record_mapping/static/src/js/debug.js b/sync_record_mapping/static/src/js/debug.js
new file mode 100644
index 00000000..ec06ebeb
--- /dev/null
+++ b/sync_record_mapping/static/src/js/debug.js
@@ -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],
+ },
+ });
+ },
+});
+
+});
diff --git a/sync_record_mapping/views/assets.xml b/sync_record_mapping/views/assets.xml
new file mode 100644
index 00000000..a655ba14
--- /dev/null
+++ b/sync_record_mapping/views/assets.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/sync_record_mapping/views/debug.xml b/sync_record_mapping/views/debug.xml
new file mode 100644
index 00000000..a64d9811
--- /dev/null
+++ b/sync_record_mapping/views/debug.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Manage Record Mappings
+
+
+
+
diff --git a/sync_record_mapping/wizard/__init__.py b/sync_record_mapping/wizard/__init__.py
new file mode 100644
index 00000000..b0c91b8a
--- /dev/null
+++ b/sync_record_mapping/wizard/__init__.py
@@ -0,0 +1 @@
+from . import sync_record_mapping_wizard
diff --git a/sync_record_mapping/wizard/sync_record_mapping_wizard.py b/sync_record_mapping/wizard/sync_record_mapping_wizard.py
new file mode 100644
index 00000000..e77fb9e3
--- /dev/null
+++ b/sync_record_mapping/wizard/sync_record_mapping_wizard.py
@@ -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
+ )
\ No newline at end of file
diff --git a/sync_record_mapping/wizard/sync_record_mapping_wizard.xml b/sync_record_mapping/wizard/sync_record_mapping_wizard.xml
new file mode 100644
index 00000000..1c5f4aeb
--- /dev/null
+++ b/sync_record_mapping/wizard/sync_record_mapping_wizard.xml
@@ -0,0 +1,72 @@
+
+
+
+ sync.record.mapping.wizard.form
+ sync.record.mapping.wizard
+ form
+
+
+
+
+
+ sync.record.mapping.ids.tree
+ sync.link
+ primary
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sync.record.mapping.ids.form
+ sync.link
+ primary
+
+
+
+
+