From 4c1be032e736ef04647a0abda745b50308e1650a Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 5 Oct 2023 17:12:50 +0630 Subject: [PATCH 01/26] [ADD] data_migration --- data_migration/__init__.py | 1 + data_migration/__manifest__.py | 16 +++++ .../data/data_migration_scheduler.xml | 13 ++++ data_migration/models/__init__.py | 2 + data_migration/models/odoo_instance.py | 15 +++++ .../models/partner_data_migration.py | 66 +++++++++++++++++++ data_migration/readme/DESCRIPTION.rst | 1 + data_migration/security/ir.model.access.csv | 3 + data_migration/views/odoo_instance_views.xml | 45 +++++++++++++ .../data_migration/odoo/addons/data_migration | 1 + setup/data_migration/setup.py | 6 ++ 11 files changed, 169 insertions(+) create mode 100644 data_migration/__init__.py create mode 100644 data_migration/__manifest__.py create mode 100644 data_migration/data/data_migration_scheduler.xml create mode 100644 data_migration/models/__init__.py create mode 100644 data_migration/models/odoo_instance.py create mode 100644 data_migration/models/partner_data_migration.py create mode 100644 data_migration/readme/DESCRIPTION.rst create mode 100644 data_migration/security/ir.model.access.csv create mode 100644 data_migration/views/odoo_instance_views.xml create mode 120000 setup/data_migration/odoo/addons/data_migration create mode 100644 setup/data_migration/setup.py diff --git a/data_migration/__init__.py b/data_migration/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/data_migration/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/data_migration/__manifest__.py b/data_migration/__manifest__.py new file mode 100644 index 00000000..8e9c60a6 --- /dev/null +++ b/data_migration/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Data Migration", + "version": "15.0.1.0.0", + "category": "Tools", + "author": "Quartile Limited", + "website": "https://www.quartile.co", + "license": "AGPL-3", + "data": [ + "security/ir.model.access.csv", + "data/data_migration_scheduler.xml", + "views/odoo_instance_views.xml", + ], + "installable": True, +} diff --git a/data_migration/data/data_migration_scheduler.xml b/data_migration/data/data_migration_scheduler.xml new file mode 100644 index 00000000..6457a352 --- /dev/null +++ b/data_migration/data/data_migration_scheduler.xml @@ -0,0 +1,13 @@ + + + + Partner Data Migration from another odoo instance + 1 + days + -1 + code + model._run_partner_data_migration() + + + + diff --git a/data_migration/models/__init__.py b/data_migration/models/__init__.py new file mode 100644 index 00000000..8afcab81 --- /dev/null +++ b/data_migration/models/__init__.py @@ -0,0 +1,2 @@ +from . import odoo_instance +from . import partner_data_migration diff --git a/data_migration/models/odoo_instance.py b/data_migration/models/odoo_instance.py new file mode 100644 index 00000000..9f632aac --- /dev/null +++ b/data_migration/models/odoo_instance.py @@ -0,0 +1,15 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class OdooInstance(models.Model): + _name = "odoo.instance" + _description = "Odoo Instances" + + name = fields.Char(string="Name", required=True) + instance_url = fields.Char(required=True) + instance_db = fields.Char(required=True) + login = fields.Char(required=True) + password = fields.Char(required=True) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py new file mode 100644 index 00000000..c5ee339d --- /dev/null +++ b/data_migration/models/partner_data_migration.py @@ -0,0 +1,66 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import xmlrpc.client + +from odoo import SUPERUSER_ID, api, models + + +class PartnerDataMigration(models.Model): + _name = "partner.data.migration" + + def _run_partner_data_migration(self): + instance = self.env["odoo.instance"].search([]) + # Authenticate for v11 + common_v11 = xmlrpc.client.ServerProxy( + "{}/xmlrpc/2/common".format(instance.instance_url) + ) + uid_v11 = common_v11.authenticate( + instance.instance_db, instance.login, instance.password, {} + ) + # Fetch partners from v11 + models_v11 = xmlrpc.client.ServerProxy( + "{}/xmlrpc/2/object".format(instance.instance_url) + ) + domain = [("user_ids", "=", False)] + partners_v11 = models_v11.execute_kw( + instance.instance_db, + uid_v11, + instance.password, + "res.partner", + "search_read", + [domain], + ) + # Insert partners into v15 with all fields and their original IDs + env = api.Environment(self.env.cr, SUPERUSER_ID, {}) + for partner in partners_v11: + if partner.pop("customer", False): + partner["customer_rank"] = 1 + if partner.pop("supplier", False): + partner["supplier_rank"] = 1 + fields_to_remove = [ + "image", + "image_medium", + "image_small", + "message_last_post", + "opt_out", + "website_message_ids", + "debit_limit", + "ref_company_ids", + "last_time_entries_checked", + "website_meta_title", + "website_meta_description", + "website_meta_keywords", + "website_description", + "website_short_description", + "contracts_count", + ] + for field in fields_to_remove: + partner.pop(field, None) + for field, value in list( + partner.items() + ): # We use list() to copy items as we're modifying the dictionary during iteration + if isinstance(value, tuple) or isinstance(value, list): + partner.pop(field, None) + # Directly create the partner in the current v15 database using the fetched data + env["res.partner"].create(partner) diff --git a/data_migration/readme/DESCRIPTION.rst b/data_migration/readme/DESCRIPTION.rst new file mode 100644 index 00000000..ccbbf117 --- /dev/null +++ b/data_migration/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module reads the data from another odoo instance and create in current odoo instance. diff --git a/data_migration/security/ir.model.access.csv b/data_migration/security/ir.model.access.csv new file mode 100644 index 00000000..583c8d60 --- /dev/null +++ b/data_migration/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_odoo_instance,odoo.instance,model_odoo_instance,base.group_system,1,1,1,1 +access_partner_data_migration,partner.data.migration,model_partner_data_migration,base.group_system,1,1,1,1 diff --git a/data_migration/views/odoo_instance_views.xml b/data_migration/views/odoo_instance_views.xml new file mode 100644 index 00000000..053d793c --- /dev/null +++ b/data_migration/views/odoo_instance_views.xml @@ -0,0 +1,45 @@ + + + + odoo.instance.tree + odoo.instance + + + + + + + + odoo.instance.form + odoo.instance + +
+ + + + + + + + + +
+
+
+ + Odoo Instance + odoo.instance + + + +
diff --git a/setup/data_migration/odoo/addons/data_migration b/setup/data_migration/odoo/addons/data_migration new file mode 120000 index 00000000..eceadc08 --- /dev/null +++ b/setup/data_migration/odoo/addons/data_migration @@ -0,0 +1 @@ +../../../../data_migration \ No newline at end of file diff --git a/setup/data_migration/setup.py b/setup/data_migration/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/data_migration/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From b87e081768dfeeee368a821d0c99193efd980e2c Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Fri, 6 Oct 2023 11:15:17 +0630 Subject: [PATCH 02/26] adjustments --- .../data/data_migration_scheduler.xml | 1 + data_migration/models/__init__.py | 1 + .../models/partner_data_migration.py | 69 +++++++++++++------ data_migration/models/res_partner.py | 10 +++ data_migration/views/odoo_instance_views.xml | 2 +- 5 files changed, 61 insertions(+), 22 deletions(-) create mode 100644 data_migration/models/res_partner.py diff --git a/data_migration/data/data_migration_scheduler.xml b/data_migration/data/data_migration_scheduler.xml index 6457a352..4e324969 100644 --- a/data_migration/data/data_migration_scheduler.xml +++ b/data_migration/data/data_migration_scheduler.xml @@ -8,6 +8,7 @@ code model._run_partner_data_migration() + diff --git a/data_migration/models/__init__.py b/data_migration/models/__init__.py index 8afcab81..7895507d 100644 --- a/data_migration/models/__init__.py +++ b/data_migration/models/__init__.py @@ -1,2 +1,3 @@ from . import odoo_instance from . import partner_data_migration +from . import res_partner diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index c5ee339d..0577ec43 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -31,36 +31,63 @@ def _run_partner_data_migration(self): "search_read", [domain], ) + top_level_partners = [ + partner for partner in partners_v11 if not partner.get("parent_id") + ] + child_partners = [ + partner for partner in partners_v11 if partner.get("parent_id") + ] # Insert partners into v15 with all fields and their original IDs env = api.Environment(self.env.cr, SUPERUSER_ID, {}) - for partner in partners_v11: + fields_to_remove = [ + "image", + "image_medium", + "image_small", + "message_last_post", + "opt_out", + "website_message_ids", + "debit_limit", + "ref_company_ids", + "last_time_entries_checked", + "website_meta_title", + "website_meta_description", + "website_meta_keywords", + "website_description", + "website_short_description", + "contracts_count", + ] + for partner in top_level_partners: if partner.pop("customer", False): partner["customer_rank"] = 1 if partner.pop("supplier", False): partner["supplier_rank"] = 1 - fields_to_remove = [ - "image", - "image_medium", - "image_small", - "message_last_post", - "opt_out", - "website_message_ids", - "debit_limit", - "ref_company_ids", - "last_time_entries_checked", - "website_meta_title", - "website_meta_description", - "website_meta_keywords", - "website_description", - "website_short_description", - "contracts_count", - ] for field in fields_to_remove: partner.pop(field, None) - for field, value in list( - partner.items() - ): # We use list() to copy items as we're modifying the dictionary during iteration + for field, value in list(partner.items()): + # We use list() to copy items as we're modifying the dictionary during iteration if isinstance(value, tuple) or isinstance(value, list): partner.pop(field, None) # Directly create the partner in the current v15 database using the fetched data + partner["old_id"] = partner["id"] + env["res.partner"].create(partner) + + for partner in child_partners: + if partner.pop("customer", False): + partner["customer_rank"] = 1 + if partner.pop("supplier", False): + partner["supplier_rank"] = 1 + for field in fields_to_remove: + partner.pop(field, None) + for field, value in list(partner.items()): + # We use list() to copy items as we're modifying the dictionary during iteration + if field != "parent_id" and ( + isinstance(value, tuple) or isinstance(value, list) + ): + partner.pop(field, None) + if partner.get("parent_id"): + parent_id = self.env["res.partner"].search( + [("old_id", "=", partner["parent_id"][0])] + ) + partner["parent_id"] = parent_id.id + # Directly create the partner in the current v15 database using the fetched data env["res.partner"].create(partner) diff --git a/data_migration/models/res_partner.py b/data_migration/models/res_partner.py new file mode 100644 index 00000000..696dc451 --- /dev/null +++ b/data_migration/models/res_partner.py @@ -0,0 +1,10 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + old_id = fields.Integer() diff --git a/data_migration/views/odoo_instance_views.xml b/data_migration/views/odoo_instance_views.xml index 053d793c..66ac7145 100644 --- a/data_migration/views/odoo_instance_views.xml +++ b/data_migration/views/odoo_instance_views.xml @@ -20,7 +20,7 @@ - + From a9a96c0952a3216218a94740457fbe83a68ec16b Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Tue, 10 Oct 2023 16:23:16 +0630 Subject: [PATCH 03/26] update --- data_migration/__manifest__.py | 1 + data_migration/models/__init__.py | 1 + data_migration/models/data_migration.py | 25 +++++++++++++++ .../models/partner_data_migration.py | 20 +++--------- data_migration/security/ir.model.access.csv | 1 + data_migration/views/odoo_instance_views.xml | 2 +- res_users_data_migration/__init__.py | 1 + res_users_data_migration/__manifest__.py | 13 ++++++++ .../data/user_migration_scheduler.xml | 14 +++++++++ res_users_data_migration/models/__init__.py | 2 ++ res_users_data_migration/models/res_users.py | 10 ++++++ .../models/user_data_migration.py | 31 +++++++++++++++++++ .../readme/DESCRIPTION.rst | 1 + .../security/ir.model.access.csv | 2 ++ .../odoo/addons/res_users_data_migration | 1 + setup/res_users_data_migration/setup.py | 6 ++++ 16 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 data_migration/models/data_migration.py create mode 100644 res_users_data_migration/__init__.py create mode 100644 res_users_data_migration/__manifest__.py create mode 100644 res_users_data_migration/data/user_migration_scheduler.xml create mode 100644 res_users_data_migration/models/__init__.py create mode 100644 res_users_data_migration/models/res_users.py create mode 100644 res_users_data_migration/models/user_data_migration.py create mode 100644 res_users_data_migration/readme/DESCRIPTION.rst create mode 100644 res_users_data_migration/security/ir.model.access.csv create mode 120000 setup/res_users_data_migration/odoo/addons/res_users_data_migration create mode 100644 setup/res_users_data_migration/setup.py diff --git a/data_migration/__manifest__.py b/data_migration/__manifest__.py index 8e9c60a6..0a802861 100644 --- a/data_migration/__manifest__.py +++ b/data_migration/__manifest__.py @@ -7,6 +7,7 @@ "author": "Quartile Limited", "website": "https://www.quartile.co", "license": "AGPL-3", + "depends": ["base"], "data": [ "security/ir.model.access.csv", "data/data_migration_scheduler.xml", diff --git a/data_migration/models/__init__.py b/data_migration/models/__init__.py index 7895507d..75497bff 100644 --- a/data_migration/models/__init__.py +++ b/data_migration/models/__init__.py @@ -1,3 +1,4 @@ +from . import data_migration from . import odoo_instance from . import partner_data_migration from . import res_partner diff --git a/data_migration/models/data_migration.py b/data_migration/models/data_migration.py new file mode 100644 index 00000000..ad9415c1 --- /dev/null +++ b/data_migration/models/data_migration.py @@ -0,0 +1,25 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import xmlrpc.client + +from odoo import models + + +class DataMigration(models.AbstractModel): + _name = "data.migration" + _description = "Data Migration" + + def _data_migration_authentication(self): + instance = self.env["odoo.instance"].search([]) + # Authenticate for v11 + common_v11 = xmlrpc.client.ServerProxy( + "{}/xmlrpc/2/common".format(instance.instance_url) + ) + uid_v11 = common_v11.authenticate( + instance.instance_db, instance.login, instance.password, {} + ) + models_v11 = xmlrpc.client.ServerProxy( + "{}/xmlrpc/2/object".format(instance.instance_url) + ) + return instance, uid_v11, models_v11 diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index 0577ec43..deee078a 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -1,35 +1,24 @@ # Copyright 2023 Quartile Limited # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -import xmlrpc.client from odoo import SUPERUSER_ID, api, models class PartnerDataMigration(models.Model): _name = "partner.data.migration" + _inherit = "data.migration" + _description = "Partner Data Migration" def _run_partner_data_migration(self): - instance = self.env["odoo.instance"].search([]) - # Authenticate for v11 - common_v11 = xmlrpc.client.ServerProxy( - "{}/xmlrpc/2/common".format(instance.instance_url) - ) - uid_v11 = common_v11.authenticate( - instance.instance_db, instance.login, instance.password, {} - ) - # Fetch partners from v11 - models_v11 = xmlrpc.client.ServerProxy( - "{}/xmlrpc/2/object".format(instance.instance_url) - ) - domain = [("user_ids", "=", False)] + instance, uid_v11, models_v11 = self._data_migration_authentication() partners_v11 = models_v11.execute_kw( instance.instance_db, uid_v11, instance.password, "res.partner", "search_read", - [domain], + [], ) top_level_partners = [ partner for partner in partners_v11 if not partner.get("parent_id") @@ -90,4 +79,5 @@ def _run_partner_data_migration(self): ) partner["parent_id"] = parent_id.id # Directly create the partner in the current v15 database using the fetched data + partner["old_id"] = partner["id"] env["res.partner"].create(partner) diff --git a/data_migration/security/ir.model.access.csv b/data_migration/security/ir.model.access.csv index 583c8d60..3ae12474 100644 --- a/data_migration/security/ir.model.access.csv +++ b/data_migration/security/ir.model.access.csv @@ -1,3 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_odoo_instance,odoo.instance,model_odoo_instance,base.group_system,1,1,1,1 +access_data_migration,data.migration,model_data_migration,base.group_system,1,1,1,1 access_partner_data_migration,partner.data.migration,model_partner_data_migration,base.group_system,1,1,1,1 diff --git a/data_migration/views/odoo_instance_views.xml b/data_migration/views/odoo_instance_views.xml index 66ac7145..6fa73d29 100644 --- a/data_migration/views/odoo_instance_views.xml +++ b/data_migration/views/odoo_instance_views.xml @@ -20,7 +20,7 @@ - + diff --git a/res_users_data_migration/__init__.py b/res_users_data_migration/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/res_users_data_migration/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/res_users_data_migration/__manifest__.py b/res_users_data_migration/__manifest__.py new file mode 100644 index 00000000..bc80eabf --- /dev/null +++ b/res_users_data_migration/__manifest__.py @@ -0,0 +1,13 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "User Data Migration", + "version": "15.0.1.0.0", + "category": "Tools", + "author": "Quartile Limited", + "website": "https://www.quartile.co", + "license": "AGPL-3", + "depends": ["data_migration"], + "data": ["security/ir.model.access.csv", "data/user_migration_scheduler.xml"], + "installable": True, +} diff --git a/res_users_data_migration/data/user_migration_scheduler.xml b/res_users_data_migration/data/user_migration_scheduler.xml new file mode 100644 index 00000000..3d8e73d1 --- /dev/null +++ b/res_users_data_migration/data/user_migration_scheduler.xml @@ -0,0 +1,14 @@ + + + + User Data Migration from another odoo instance + 1 + days + -1 + code + model._run_user_data_migration() + + + + + diff --git a/res_users_data_migration/models/__init__.py b/res_users_data_migration/models/__init__.py new file mode 100644 index 00000000..b30b3081 --- /dev/null +++ b/res_users_data_migration/models/__init__.py @@ -0,0 +1,2 @@ +from . import user_data_migration +from . import res_users diff --git a/res_users_data_migration/models/res_users.py b/res_users_data_migration/models/res_users.py new file mode 100644 index 00000000..bfd353d0 --- /dev/null +++ b/res_users_data_migration/models/res_users.py @@ -0,0 +1,10 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResUsers(models.Model): + _inherit = "res.users" + + old_id = fields.Integer() diff --git a/res_users_data_migration/models/user_data_migration.py b/res_users_data_migration/models/user_data_migration.py new file mode 100644 index 00000000..934bff59 --- /dev/null +++ b/res_users_data_migration/models/user_data_migration.py @@ -0,0 +1,31 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +from odoo import SUPERUSER_ID, api, models + + +class UserDataMigration(models.Model): + _name = "user.data.migration" + _inherit = "data.migration" + + def _run_user_data_migration(self): + instance, uid_v11, models_v11 = self._data_migration_authentication() + users_v11 = models_v11.execute_kw( + instance.instance_db, + uid_v11, + instance.password, + "res.partner", + "search_read", + ) + env = api.Environment(self.env.cr, SUPERUSER_ID, {}) + for user in users_v11: + user = self.env["res.users"].search([("login", "=", user["login"])]) + if user: + continue + user["old_id"] = user["id"] + partner_id = self.env["res.partner"].search( + [("old_id", "=", user["partner_id"][0])] + ) + user["parent_id"] = partner_id.id + env["res.users"].create(user) diff --git a/res_users_data_migration/readme/DESCRIPTION.rst b/res_users_data_migration/readme/DESCRIPTION.rst new file mode 100644 index 00000000..9d1e7e51 --- /dev/null +++ b/res_users_data_migration/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module reads the user data from another odoo instance and create in current odoo instance. diff --git a/res_users_data_migration/security/ir.model.access.csv b/res_users_data_migration/security/ir.model.access.csv new file mode 100644 index 00000000..86c4fc26 --- /dev/null +++ b/res_users_data_migration/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_user_data_migration,user.data.migration,model_user_data_migration,base.group_system,1,1,1,1 diff --git a/setup/res_users_data_migration/odoo/addons/res_users_data_migration b/setup/res_users_data_migration/odoo/addons/res_users_data_migration new file mode 120000 index 00000000..dee182de --- /dev/null +++ b/setup/res_users_data_migration/odoo/addons/res_users_data_migration @@ -0,0 +1 @@ +../../../../res_users_data_migration \ No newline at end of file diff --git a/setup/res_users_data_migration/setup.py b/setup/res_users_data_migration/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/res_users_data_migration/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From f5628f6a8e81ed10715f1453803d41ef1b01e99a Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Tue, 10 Oct 2023 17:04:06 +0630 Subject: [PATCH 04/26] adj --- data_migration/models/partner_data_migration.py | 1 + .../models/user_data_migration.py | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index deee078a..bac64481 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -44,6 +44,7 @@ def _run_partner_data_migration(self): "website_description", "website_short_description", "contracts_count", + "commercial_partner_country_id", ] for partner in top_level_partners: if partner.pop("customer", False): diff --git a/res_users_data_migration/models/user_data_migration.py b/res_users_data_migration/models/user_data_migration.py index 934bff59..8f151270 100644 --- a/res_users_data_migration/models/user_data_migration.py +++ b/res_users_data_migration/models/user_data_migration.py @@ -15,17 +15,22 @@ def _run_user_data_migration(self): instance.instance_db, uid_v11, instance.password, - "res.partner", + "res.users", "search_read", + [], ) env = api.Environment(self.env.cr, SUPERUSER_ID, {}) for user in users_v11: - user = self.env["res.users"].search([("login", "=", user["login"])]) - if user: + user_id = self.env["res.users"].search([("login", "=", user["login"])]) + if user_id: continue - user["old_id"] = user["id"] partner_id = self.env["res.partner"].search( [("old_id", "=", user["partner_id"][0])] ) - user["parent_id"] = partner_id.id - env["res.users"].create(user) + user_data = { + "name": user["name"], + "login": user["login"], + # "password": hashlib.sha256(user["password"].encode()).hexdigest(), + "partner_id": partner_id.id, + } + env["res.users"].create(user_data) From e666dd8e687f2dc91196fe89f85b416eec85e1dc Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Wed, 11 Oct 2023 10:09:35 +0630 Subject: [PATCH 05/26] [ADD] product_category_data_migration --- data_migration/models/odoo_instance.py | 2 +- product_category_data_migration/__init__.py | 1 + .../__manifest__.py | 16 +++++ .../product_category_migration_scheduler.xml | 16 +++++ .../models/__init__.py | 2 + .../models/product_category.py | 10 ++++ .../models/product_category_data_migration.py | 59 +++++++++++++++++++ .../readme/DESCRIPTION.rst | 1 + .../security/ir.model.access.csv | 2 + .../addons/product_category_data_migration | 1 + .../product_category_data_migration/setup.py | 6 ++ 11 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 product_category_data_migration/__init__.py create mode 100644 product_category_data_migration/__manifest__.py create mode 100644 product_category_data_migration/data/product_category_migration_scheduler.xml create mode 100644 product_category_data_migration/models/__init__.py create mode 100644 product_category_data_migration/models/product_category.py create mode 100644 product_category_data_migration/models/product_category_data_migration.py create mode 100644 product_category_data_migration/readme/DESCRIPTION.rst create mode 100644 product_category_data_migration/security/ir.model.access.csv create mode 120000 setup/product_category_data_migration/odoo/addons/product_category_data_migration create mode 100644 setup/product_category_data_migration/setup.py diff --git a/data_migration/models/odoo_instance.py b/data_migration/models/odoo_instance.py index 9f632aac..3ba4b5cd 100644 --- a/data_migration/models/odoo_instance.py +++ b/data_migration/models/odoo_instance.py @@ -8,7 +8,7 @@ class OdooInstance(models.Model): _name = "odoo.instance" _description = "Odoo Instances" - name = fields.Char(string="Name", required=True) + name = fields.Char(required=True) instance_url = fields.Char(required=True) instance_db = fields.Char(required=True) login = fields.Char(required=True) diff --git a/product_category_data_migration/__init__.py b/product_category_data_migration/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/product_category_data_migration/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/product_category_data_migration/__manifest__.py b/product_category_data_migration/__manifest__.py new file mode 100644 index 00000000..c242511f --- /dev/null +++ b/product_category_data_migration/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Product Category Data Migration", + "version": "15.0.1.0.0", + "category": "Tools", + "author": "Quartile Limited", + "website": "https://www.quartile.co", + "license": "AGPL-3", + "depends": ["product"], + "data": [ + "security/ir.model.access.csv", + "data/product_category_migration_scheduler.xml", + ], + "installable": True, +} diff --git a/product_category_data_migration/data/product_category_migration_scheduler.xml b/product_category_data_migration/data/product_category_migration_scheduler.xml new file mode 100644 index 00000000..af0b5895 --- /dev/null +++ b/product_category_data_migration/data/product_category_migration_scheduler.xml @@ -0,0 +1,16 @@ + + + + Product Category Data Migration from another odoo instance + 1 + days + -1 + code + model._run_product_category_data_migration() + + + + + diff --git a/product_category_data_migration/models/__init__.py b/product_category_data_migration/models/__init__.py new file mode 100644 index 00000000..4b9f236b --- /dev/null +++ b/product_category_data_migration/models/__init__.py @@ -0,0 +1,2 @@ +from . import product_category_data_migration +from . import product_category diff --git a/product_category_data_migration/models/product_category.py b/product_category_data_migration/models/product_category.py new file mode 100644 index 00000000..4be55826 --- /dev/null +++ b/product_category_data_migration/models/product_category.py @@ -0,0 +1,10 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ProductCategory(models.Model): + _inherit = "product.category" + + old_id = fields.Integer() diff --git a/product_category_data_migration/models/product_category_data_migration.py b/product_category_data_migration/models/product_category_data_migration.py new file mode 100644 index 00000000..9ebd22b3 --- /dev/null +++ b/product_category_data_migration/models/product_category_data_migration.py @@ -0,0 +1,59 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +from odoo import SUPERUSER_ID, api, models + + +class ProductCategoryDataMigration(models.Model): + _name = "product.category.data.migration" + _inherit = "data.migration" + + def _run_product_category_data_migration(self): + instance, uid_v11, models_v11 = self._data_migration_authentication() + category_v11 = models_v11.execute_kw( + instance.instance_db, + uid_v11, + instance.password, + "product.category", + "search_read", + [], + ) + top_level_category = [ + category for category in category_v11 if not category.get("parent_id") + ] + child_category = [ + category for category in category_v11 if category.get("parent_id") + ] + env = api.Environment(self.env.cr, SUPERUSER_ID, {}) + for category in top_level_category: + category_id = self.env["product.category"].search( + [("name", "=", category["name"])] + ) + if category_id: + continue + category_data = { + "old_id": category["id"], + "name": category["name"], + # selection field doesn't store value in db + # "property_cost_method":category["property_cost_method"], + # "inventory_valuation": category["inventory_valuation"], + } + env["product.category"].create(category_data) + for category in child_category: + category_id = self.env["product.category"].search( + [("name", "=", category["name"])] + ) + if category_id: + continue + parent_id = self.env["product.category"].search( + [("old_id", "=", category["parent_id"][0])] + ) + category_data = { + "old_id": category["id"], + "name": category["name"], + # "property_cost_method":category["property_cost_method"], + # "inventory_valuation": category["inventory_valuation"], + "parent_id": parent_id.id, + } + env["product.category"].create(category_data) diff --git a/product_category_data_migration/readme/DESCRIPTION.rst b/product_category_data_migration/readme/DESCRIPTION.rst new file mode 100644 index 00000000..9e6eb76b --- /dev/null +++ b/product_category_data_migration/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module reads the product category data from another odoo instance and create in current odoo instance. diff --git a/product_category_data_migration/security/ir.model.access.csv b/product_category_data_migration/security/ir.model.access.csv new file mode 100644 index 00000000..dc1b2b88 --- /dev/null +++ b/product_category_data_migration/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_product_category_data_migration,product_category.data.migration,model_product_category_data_migration,base.group_system,1,1,1,1 diff --git a/setup/product_category_data_migration/odoo/addons/product_category_data_migration b/setup/product_category_data_migration/odoo/addons/product_category_data_migration new file mode 120000 index 00000000..d5eb3e56 --- /dev/null +++ b/setup/product_category_data_migration/odoo/addons/product_category_data_migration @@ -0,0 +1 @@ +../../../../product_category_data_migration \ No newline at end of file diff --git a/setup/product_category_data_migration/setup.py b/setup/product_category_data_migration/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/product_category_data_migration/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 0767657dd090a1cc96137a663abd089d04517015 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 12 Oct 2023 10:31:16 +0630 Subject: [PATCH 06/26] adj --- .../models/partner_data_migration.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index bac64481..27b49bd6 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -19,6 +19,7 @@ def _run_partner_data_migration(self): "res.partner", "search_read", [], + {"limit": 100}, ) top_level_partners = [ partner for partner in partners_v11 if not partner.get("parent_id") @@ -45,6 +46,30 @@ def _run_partner_data_migration(self): "website_short_description", "contracts_count", "commercial_partner_country_id", + "calendar_last_notif_ack", + "is_invoice_issuer", + "member_group_id", + "seller", + "state", + "set_seller_wise_settings", + "gender", + "identification_number", + "date_of_birth", + "remaining_point_limit", + "commission", + "auto_product_approve", + "seller_payment_limit", + "next_payment_request", + "total_mp_payment", + "paid_mp_payment", + "balance_mp_payment", + "available_amount", + "profile_image", + "cart_update_message", + "task_count", + "cashable_amount", + "sol_count", + "allow_product_variants", ] for partner in top_level_partners: if partner.pop("customer", False): From 7806d7b2ee69e09e7f9c0ca03045261cb702a3be Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 12 Oct 2023 11:49:59 +0630 Subject: [PATCH 07/26] add queue_job --- data_migration/__manifest__.py | 2 +- .../models/partner_data_migration.py | 66 ++++++++----------- .../models/user_data_migration.py | 14 ++-- 3 files changed, 38 insertions(+), 44 deletions(-) diff --git a/data_migration/__manifest__.py b/data_migration/__manifest__.py index 0a802861..0b7c75bb 100644 --- a/data_migration/__manifest__.py +++ b/data_migration/__manifest__.py @@ -7,7 +7,7 @@ "author": "Quartile Limited", "website": "https://www.quartile.co", "license": "AGPL-3", - "depends": ["base"], + "depends": ["base", "queue_job"], "data": [ "security/ir.model.access.csv", "data/data_migration_scheduler.xml", diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index 27b49bd6..3d070bd0 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -1,7 +1,6 @@ # Copyright 2023 Quartile Limited # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - from odoo import SUPERUSER_ID, api, models @@ -19,7 +18,6 @@ def _run_partner_data_migration(self): "res.partner", "search_read", [], - {"limit": 100}, ) top_level_partners = [ partner for partner in partners_v11 if not partner.get("parent_id") @@ -27,7 +25,14 @@ def _run_partner_data_migration(self): child_partners = [ partner for partner in partners_v11 if partner.get("parent_id") ] - # Insert partners into v15 with all fields and their original IDs + + for partner in top_level_partners: + self.with_delay()._process_partner_migration(partner, is_child=False) + + for partner in child_partners: + self.with_delay()._process_partner_migration(partner, is_child=True) + + def _process_partner_migration(self, partner, is_child=False): env = api.Environment(self.env.cr, SUPERUSER_ID, {}) fields_to_remove = [ "image", @@ -71,39 +76,26 @@ def _run_partner_data_migration(self): "sol_count", "allow_product_variants", ] - for partner in top_level_partners: - if partner.pop("customer", False): - partner["customer_rank"] = 1 - if partner.pop("supplier", False): - partner["supplier_rank"] = 1 - for field in fields_to_remove: - partner.pop(field, None) - for field, value in list(partner.items()): - # We use list() to copy items as we're modifying the dictionary during iteration - if isinstance(value, tuple) or isinstance(value, list): - partner.pop(field, None) - # Directly create the partner in the current v15 database using the fetched data - partner["old_id"] = partner["id"] - env["res.partner"].create(partner) - for partner in child_partners: - if partner.pop("customer", False): - partner["customer_rank"] = 1 - if partner.pop("supplier", False): - partner["supplier_rank"] = 1 - for field in fields_to_remove: + if partner.pop("customer", False): + partner["customer_rank"] = 1 + if partner.pop("supplier", False): + partner["supplier_rank"] = 1 + + for field in fields_to_remove: + partner.pop(field, None) + + for field, value in list(partner.items()): + if (not is_child or field != "parent_id") and ( + isinstance(value, tuple) or isinstance(value, list) + ): partner.pop(field, None) - for field, value in list(partner.items()): - # We use list() to copy items as we're modifying the dictionary during iteration - if field != "parent_id" and ( - isinstance(value, tuple) or isinstance(value, list) - ): - partner.pop(field, None) - if partner.get("parent_id"): - parent_id = self.env["res.partner"].search( - [("old_id", "=", partner["parent_id"][0])] - ) - partner["parent_id"] = parent_id.id - # Directly create the partner in the current v15 database using the fetched data - partner["old_id"] = partner["id"] - env["res.partner"].create(partner) + + if is_child and partner.get("parent_id"): + parent_id = env["res.partner"].search( + [("old_id", "=", partner["parent_id"][0])] + ) + partner["parent_id"] = parent_id.id + + partner["old_id"] = partner["id"] + env["res.partner"].create(partner) diff --git a/res_users_data_migration/models/user_data_migration.py b/res_users_data_migration/models/user_data_migration.py index 8f151270..600fa59a 100644 --- a/res_users_data_migration/models/user_data_migration.py +++ b/res_users_data_migration/models/user_data_migration.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import SUPERUSER_ID, api, models +from odoo import models class UserDataMigration(models.Model): @@ -19,11 +19,13 @@ def _run_user_data_migration(self): "search_read", [], ) - env = api.Environment(self.env.cr, SUPERUSER_ID, {}) for user in users_v11: - user_id = self.env["res.users"].search([("login", "=", user["login"])]) - if user_id: - continue + # Use with_delay() to add each user creation to the job queue + self.with_delay()._create_user_job(user) + + def _create_user_job(self, user): + user_id = self.env["res.users"].search([("login", "=", user["login"])]) + if not user_id: partner_id = self.env["res.partner"].search( [("old_id", "=", user["partner_id"][0])] ) @@ -33,4 +35,4 @@ def _run_user_data_migration(self): # "password": hashlib.sha256(user["password"].encode()).hexdigest(), "partner_id": partner_id.id, } - env["res.users"].create(user_data) + self.env["res.users"].create(user_data) From d17eda767e855d24b4d6f4182a67916416c0cb1e Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Mon, 16 Oct 2023 13:50:10 +0630 Subject: [PATCH 08/26] update --- data_migration/models/__init__.py | 1 + .../models/data_migration_mapping.py | 25 ++++ .../models/partner_data_migration.py | 120 +++++++++++------- data_migration/security/ir.model.access.csv | 1 + 4 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 data_migration/models/data_migration_mapping.py diff --git a/data_migration/models/__init__.py b/data_migration/models/__init__.py index 75497bff..9f9119a3 100644 --- a/data_migration/models/__init__.py +++ b/data_migration/models/__init__.py @@ -1,4 +1,5 @@ from . import data_migration +from . import data_migration_mapping from . import odoo_instance from . import partner_data_migration from . import res_partner diff --git a/data_migration/models/data_migration_mapping.py b/data_migration/models/data_migration_mapping.py new file mode 100644 index 00000000..39890258 --- /dev/null +++ b/data_migration/models/data_migration_mapping.py @@ -0,0 +1,25 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class DataMigrationMapping(models.AbstractModel): + _name = "data.migration.mapping" + + def map_many2one_field_by_name(self, env, model_name, field_value): + """ + Return the ID of a record in the specified model based on its name. + + :param env: Odoo environment. + :param model_name: The name of the model (e.g., 'res.partner'). + :param field_value: Tuple containing the ID and name of the record in the old system. + :return: ID of the record in the new system with the same name. + """ + + if not isinstance(field_value, (tuple, list)): + return field_value + + _, name = field_value + record = env[model_name].search([("name", "=", name)], limit=1) + return record.id if record else False diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index 3d070bd0..02334adb 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -6,10 +6,66 @@ class PartnerDataMigration(models.Model): _name = "partner.data.migration" - _inherit = "data.migration" + _inherit = ["data.migration", "data.migration.mapping"] _description = "Partner Data Migration" def _run_partner_data_migration(self): + required_fields = [ + "is_invoice_issuer", + "team_id", + "identification_type_id", + "occupation_id", + "website_published", + # "seller", # Not migrated yet + # "commission", # Not migrated yet + "date_of_birth", + "company_id", + "date", + "title", + "parent_id", + # "user_id", # user migration will handle it. + "active", + "customer", + "supplier", + "employee", + "state_id", + "country_id", + "is_company", + # "commercial_partner_id", # compute function will handle it. + "name", + "display_name", + "lang", + "tz", + # "state", # not migrated yet. + "vat", + "website", + "comment", + "barcode", + "return_policy", + "invoice_warn", + "invoice_warn_msg", + "picking_warn", + "function", + "type", + "street", + "street2", + "zip", + "city", + "picking_warn_msg", + "sale_warn", + "email", + "phone", + "mobile", + "sale_warn_msg", + "shipping_policy", + "purchase_warn", + "purchase_warn_msg", + "profile_msg", + "identification_number", + "company_name", + "fax", + "gender", + ] instance, uid_v11, models_v11 = self._data_migration_authentication() partners_v11 = models_v11.execute_kw( instance.instance_db, @@ -18,6 +74,7 @@ def _run_partner_data_migration(self): "res.partner", "search_read", [], + {"fields": required_fields}, ) top_level_partners = [ partner for partner in partners_v11 if not partner.get("parent_id") @@ -34,57 +91,28 @@ def _run_partner_data_migration(self): def _process_partner_migration(self, partner, is_child=False): env = api.Environment(self.env.cr, SUPERUSER_ID, {}) - fields_to_remove = [ - "image", - "image_medium", - "image_small", - "message_last_post", - "opt_out", - "website_message_ids", - "debit_limit", - "ref_company_ids", - "last_time_entries_checked", - "website_meta_title", - "website_meta_description", - "website_meta_keywords", - "website_description", - "website_short_description", - "contracts_count", - "commercial_partner_country_id", - "calendar_last_notif_ack", - "is_invoice_issuer", - "member_group_id", - "seller", - "state", - "set_seller_wise_settings", - "gender", - "identification_number", - "date_of_birth", - "remaining_point_limit", - "commission", - "auto_product_approve", - "seller_payment_limit", - "next_payment_request", - "total_mp_payment", - "paid_mp_payment", - "balance_mp_payment", - "available_amount", - "profile_image", - "cart_update_message", - "task_count", - "cashable_amount", - "sol_count", - "allow_product_variants", - ] + many2one_field_mapping = { + "team_id": "crm.team", + "identification_type_id": "identification.type", + "occupation_id": "res.occupation", + "company_id": "res.company", + "state_id": "res.country.state", + "country_id": "res.country", + } if partner.pop("customer", False): partner["customer_rank"] = 1 if partner.pop("supplier", False): partner["supplier_rank"] = 1 + date_of_birth = partner.pop("date_of_birth", False) + if date_of_birth: + partner["date_birth"] = date_of_birth - for field in fields_to_remove: - partner.pop(field, None) - + for field, model in many2one_field_mapping.items(): + if field in partner: + partner[field] = self.map_many2one_field_by_name( + env, model, partner[field] + ) for field, value in list(partner.items()): if (not is_child or field != "parent_id") and ( isinstance(value, tuple) or isinstance(value, list) diff --git a/data_migration/security/ir.model.access.csv b/data_migration/security/ir.model.access.csv index 3ae12474..bd03c71f 100644 --- a/data_migration/security/ir.model.access.csv +++ b/data_migration/security/ir.model.access.csv @@ -1,4 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_odoo_instance,odoo.instance,model_odoo_instance,base.group_system,1,1,1,1 access_data_migration,data.migration,model_data_migration,base.group_system,1,1,1,1 +access_data_migration_mapping,data.migration.mapping,model_data_migration_mapping,base.group_system,1,1,1,1 access_partner_data_migration,partner.data.migration,model_partner_data_migration,base.group_system,1,1,1,1 From 1e0da0749463c5a9dcd6e71add6423ec1e9a3c19 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Mon, 16 Oct 2023 15:28:10 +0630 Subject: [PATCH 09/26] upd --- data_migration/models/partner_data_migration.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index 02334adb..bef27acf 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -16,8 +16,6 @@ def _run_partner_data_migration(self): "identification_type_id", "occupation_id", "website_published", - # "seller", # Not migrated yet - # "commission", # Not migrated yet "date_of_birth", "company_id", "date", @@ -36,7 +34,6 @@ def _run_partner_data_migration(self): "display_name", "lang", "tz", - # "state", # not migrated yet. "vat", "website", "comment", From caba0bf158f6b7e94faa44240dfcf53674c2bf5a Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Tue, 17 Oct 2023 14:07:39 +0630 Subject: [PATCH 10/26] partner title mapping --- data_migration/models/partner_data_migration.py | 1 + 1 file changed, 1 insertion(+) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index bef27acf..19e7ccdc 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -95,6 +95,7 @@ def _process_partner_migration(self, partner, is_child=False): "company_id": "res.company", "state_id": "res.country.state", "country_id": "res.country", + "title": "res.partner.title", } if partner.pop("customer", False): From 2c142b6db591b0c7e2251afbe2f7f23f1939abf3 Mon Sep 17 00:00:00 2001 From: kanda999 Date: Tue, 17 Oct 2023 09:50:43 +0000 Subject: [PATCH 11/26] add offset and limit --- .../models/partner_data_migration.py | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index 19e7ccdc..0e1abe7d 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -64,27 +64,33 @@ def _run_partner_data_migration(self): "gender", ] instance, uid_v11, models_v11 = self._data_migration_authentication() - partners_v11 = models_v11.execute_kw( - instance.instance_db, - uid_v11, - instance.password, - "res.partner", - "search_read", - [], - {"fields": required_fields}, - ) - top_level_partners = [ - partner for partner in partners_v11 if not partner.get("parent_id") - ] - child_partners = [ - partner for partner in partners_v11 if partner.get("parent_id") - ] + offset = 0 + limit = 1000 + while True: + partners_v11 = models_v11.execute_kw( + instance.instance_db, + uid_v11, + instance.password, + "res.partner", + "search_read", + [], + {"fields": required_fields, "offset": offset, "limit": limit}, + ) + if not partners_v11: + break + top_level_partners = [ + partner for partner in partners_v11 if not partner.get("parent_id") + ] + child_partners = [ + partner for partner in partners_v11 if partner.get("parent_id") + ] + offset += limit - for partner in top_level_partners: - self.with_delay()._process_partner_migration(partner, is_child=False) + for partner in top_level_partners: + self.with_delay()._process_partner_migration(partner, is_child=False) - for partner in child_partners: - self.with_delay()._process_partner_migration(partner, is_child=True) + for partner in child_partners: + self.with_delay()._process_partner_migration(partner, is_child=True) def _process_partner_migration(self, partner, is_child=False): env = api.Environment(self.env.cr, SUPERUSER_ID, {}) From 18ca04c9706bf686fbd1280ee82060c23fa72cdc Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Wed, 18 Oct 2023 13:37:14 +0630 Subject: [PATCH 12/26] add readme --- data_migration/README.rst | 55 +++ data_migration/static/description/index.html | 409 ++++++++++++++++++ product_category_data_migration/README.rst | 55 +++ .../static/description/index.html | 409 ++++++++++++++++++ res_users_data_migration/README.rst | 55 +++ .../static/description/index.html | 409 ++++++++++++++++++ 6 files changed, 1392 insertions(+) create mode 100644 data_migration/README.rst create mode 100644 data_migration/static/description/index.html create mode 100644 product_category_data_migration/README.rst create mode 100644 product_category_data_migration/static/description/index.html create mode 100644 res_users_data_migration/README.rst create mode 100644 res_users_data_migration/static/description/index.html diff --git a/data_migration/README.rst b/data_migration/README.rst new file mode 100644 index 00000000..c00b1b8b --- /dev/null +++ b/data_migration/README.rst @@ -0,0 +1,55 @@ +============== +Data Migration +============== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:6c1038d7a9cbeb2c3c5c88f83aa1b8fde46f13df62710fdcca509f7481c735fd + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/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-qrtl%2Fsst--custom-lightgray.png?logo=github + :target: https://github.com/qrtl/sst-custom/tree/15.0/data_migration + :alt: qrtl/sst-custom + +|badge1| |badge2| |badge3| + +This module reads the data from another odoo instance and create in current odoo instance. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +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 +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Quartile Limited + +Maintainers +~~~~~~~~~~~ + +This module is part of the `qrtl/sst-custom `_ project on GitHub. + +You are welcome to contribute. diff --git a/data_migration/static/description/index.html b/data_migration/static/description/index.html new file mode 100644 index 00000000..720aa902 --- /dev/null +++ b/data_migration/static/description/index.html @@ -0,0 +1,409 @@ + + + + + + +Data Migration + + + +
+

Data Migration

+ + +

Beta License: AGPL-3 qrtl/sst-custom

+

This module reads the data from another odoo instance and create in current odoo instance.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +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 +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Quartile Limited
  • +
+
+
+

Maintainers

+

This module is part of the qrtl/sst-custom project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/product_category_data_migration/README.rst b/product_category_data_migration/README.rst new file mode 100644 index 00000000..49cb6aa3 --- /dev/null +++ b/product_category_data_migration/README.rst @@ -0,0 +1,55 @@ +=============================== +Product Category Data Migration +=============================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:37897a8f49ed10be45a95cd7bd2883bd6dd2962e2da3299d59c0b71cdb6af45b + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/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-qrtl%2Fsst--custom-lightgray.png?logo=github + :target: https://github.com/qrtl/sst-custom/tree/15.0/product_category_data_migration + :alt: qrtl/sst-custom + +|badge1| |badge2| |badge3| + +This module reads the product category data from another odoo instance and create in current odoo instance. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +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 +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Quartile Limited + +Maintainers +~~~~~~~~~~~ + +This module is part of the `qrtl/sst-custom `_ project on GitHub. + +You are welcome to contribute. diff --git a/product_category_data_migration/static/description/index.html b/product_category_data_migration/static/description/index.html new file mode 100644 index 00000000..315efa19 --- /dev/null +++ b/product_category_data_migration/static/description/index.html @@ -0,0 +1,409 @@ + + + + + + +Product Category Data Migration + + + +
+

Product Category Data Migration

+ + +

Beta License: AGPL-3 qrtl/sst-custom

+

This module reads the product category data from another odoo instance and create in current odoo instance.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +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 +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Quartile Limited
  • +
+
+
+

Maintainers

+

This module is part of the qrtl/sst-custom project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/res_users_data_migration/README.rst b/res_users_data_migration/README.rst new file mode 100644 index 00000000..c9eeaa07 --- /dev/null +++ b/res_users_data_migration/README.rst @@ -0,0 +1,55 @@ +=================== +User Data Migration +=================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:b806a3379a38836cafb2a005dbd7b5443de499aba661047bab8522fcbc7cf614 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/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-qrtl%2Fsst--custom-lightgray.png?logo=github + :target: https://github.com/qrtl/sst-custom/tree/15.0/res_users_data_migration + :alt: qrtl/sst-custom + +|badge1| |badge2| |badge3| + +This module reads the user data from another odoo instance and create in current odoo instance. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +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 +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Quartile Limited + +Maintainers +~~~~~~~~~~~ + +This module is part of the `qrtl/sst-custom `_ project on GitHub. + +You are welcome to contribute. diff --git a/res_users_data_migration/static/description/index.html b/res_users_data_migration/static/description/index.html new file mode 100644 index 00000000..ea727c9d --- /dev/null +++ b/res_users_data_migration/static/description/index.html @@ -0,0 +1,409 @@ + + + + + + +User Data Migration + + + +
+

User Data Migration

+ + +

Beta License: AGPL-3 qrtl/sst-custom

+

This module reads the user data from another odoo instance and create in current odoo instance.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +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 +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Quartile Limited
  • +
+
+
+

Maintainers

+

This module is part of the qrtl/sst-custom project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + From 9bdfa42484affd72743c744bee7b026f2d8ed19f Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 1 Feb 2024 17:19:46 +0630 Subject: [PATCH 13/26] [ADD] purchase_order_migration --- purchase_order_migration/__init__.py | 1 + purchase_order_migration/__manifest__.py | 16 ++ .../data/purchase_migration_scheduler.xml | 16 ++ purchase_order_migration/models/__init__.py | 2 + .../models/purchase_order.py | 10 + .../models/purchase_order_migration.py | 171 ++++++++++++++++++ .../security/ir.model.access.csv | 2 + .../odoo/addons/purchase_order_migration | 1 + setup/purchase_order_migration/setup.py | 6 + 9 files changed, 225 insertions(+) create mode 100644 purchase_order_migration/__init__.py create mode 100644 purchase_order_migration/__manifest__.py create mode 100644 purchase_order_migration/data/purchase_migration_scheduler.xml create mode 100644 purchase_order_migration/models/__init__.py create mode 100644 purchase_order_migration/models/purchase_order.py create mode 100644 purchase_order_migration/models/purchase_order_migration.py create mode 100644 purchase_order_migration/security/ir.model.access.csv create mode 120000 setup/purchase_order_migration/odoo/addons/purchase_order_migration create mode 100644 setup/purchase_order_migration/setup.py diff --git a/purchase_order_migration/__init__.py b/purchase_order_migration/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/purchase_order_migration/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/purchase_order_migration/__manifest__.py b/purchase_order_migration/__manifest__.py new file mode 100644 index 00000000..3a71d05f --- /dev/null +++ b/purchase_order_migration/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2024 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Purchase Order Data Migration", + "version": "15.0.1.0.0", + "category": "Tools", + "author": "Quartile Limited", + "website": "https://www.quartile.co", + "license": "AGPL-3", + "depends": ["purchase", "data_migration"], + "data": [ + "security/ir.model.access.csv", + "data/purchase_migration_scheduler.xml", + ], + "installable": True, +} diff --git a/purchase_order_migration/data/purchase_migration_scheduler.xml b/purchase_order_migration/data/purchase_migration_scheduler.xml new file mode 100644 index 00000000..068c9873 --- /dev/null +++ b/purchase_order_migration/data/purchase_migration_scheduler.xml @@ -0,0 +1,16 @@ + + + + Purchase Order Data Migration from another odoo instance + 1 + days + -1 + code + model._run_purchase_order_data_migration() + + + + + diff --git a/purchase_order_migration/models/__init__.py b/purchase_order_migration/models/__init__.py new file mode 100644 index 00000000..6d130de0 --- /dev/null +++ b/purchase_order_migration/models/__init__.py @@ -0,0 +1,2 @@ +from . import purchase_order +from . import purchase_order_migration diff --git a/purchase_order_migration/models/purchase_order.py b/purchase_order_migration/models/purchase_order.py new file mode 100644 index 00000000..c923ce85 --- /dev/null +++ b/purchase_order_migration/models/purchase_order.py @@ -0,0 +1,10 @@ +# Copyright 2024 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class PurchaseOrder(models.Model): + _inherit = "purchase.order" + + old_id = fields.Integer() diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py new file mode 100644 index 00000000..630a5dc7 --- /dev/null +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -0,0 +1,171 @@ +# Copyright 2023 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import SUPERUSER_ID, api, models + + +class PurchaseOrderMigration(models.Model): + _name = "purchase.order.migration" + _inherit = ["data.migration", "data.migration.mapping"] + _description = "Purchase Order Data Migration" + + def _run_purchase_order_data_migration(self): + required_fields = [ + "id", + "origin", + "partner_ref", + "date_order", + "date_approve", + "partner_id", + "dest_address_id", + "currency_id", + "state", + "notes", + "date_planned", + "amount_untaxed", + "amount_tax", + "amount_total", + "fiscal_position_id", + "payment_term_id", + "incoterm_id", + "company_id", + "address", + "remark", + "sale_prediction_amount", + "request_channel_id", + "request_medium_id", + "call_back", + "state_id", + "city", + "street", + "street2", + "zip", + "phone_update", + "phone_search", + "supplier_phone", + "supplier_mobile", + "tentative_name", + "purchase_category_id", + "employee_id", + "shop_id", + "purchase_by_id", + "allow_convert", + # 'sale_order_id', # To check need to migrate or not + ] + instance, uid_v11, models_v11 = self._data_migration_authentication() + offset = 0 + limit = 1000 + while True: + purchase_order_v11 = models_v11.execute_kw( + instance.instance_db, + uid_v11, + instance.password, + "purchase.order", + "search_read", + [], + {"fields": required_fields, "offset": offset, "limit": limit}, + ) + if not purchase_order_v11: + break + offset += limit + + for purchase in purchase_order_v11: + self.with_delay()._process_purchase_order_migration(purchase) + + def _process_purchase_order_migration(self, purchase): + env = api.Environment(self.env.cr, SUPERUSER_ID, {}) + many2one_field_mapping = { + "incoterm_id": "account.incoterms", + "fiscal_position_id": "account.fiscal.position", + "company_id": "res.company", + "payment_term_id": "account.payment.term", + "currency_id": "res.currency", + "dest_address_id": "res.partner", + "partner_id": "res.partner", + "request_channel_id": "request.channel", + "request_medium_id": "request.medium", + "purchase_category_id": "purchase.category", + "employee_id": "hr.employee", + "shop_id": "stock.warehouse", + "purchase_by_id": "hr.employee", + "state_id": "res.country.state", + # 'sale_order_id': 'sale.order', + } + for field, model in many2one_field_mapping.items(): + if field in purchase: + purchase[field] = self.map_many2one_field_by_name( + env, model, purchase[field] + ) + + purchase["old_id"] = purchase["id"] + order = env["purchase.order"].create(purchase) + self.create_purchase_order_line(order) + order.write( + { + "amount_tax": purchase["amount_tax"], + "amount_untaxed": purchase["amount_untaxed"], + "amount_total": purchase["amount_total"], + } + ) + + def create_purchase_order_line(self, order): + required_fields = [ + "account_analytic_id", + "analytic_tag_ids", + "company_id", + "date_planned", + "name", + "price_subtotal", + "price_tax", + "price_total", + "price_unit", + "product_id", + "product_qty", + "product_uom", + "qty_invoiced", + "qty_received", + "taxes_id", + ] + + instance, uid_v11, models_v11 = self._data_migration_authentication() + purchase_order_line_v11 = models_v11.execute_kw( + instance.instance_db, + uid_v11, + instance.password, + "purchase.order.line", + "search_read", + [], + {"fields": required_fields, "domain": [("order_id", "=", order.old_id)]}, + ) + for line in purchase_order_line_v11: + env = api.Environment(self.env.cr, SUPERUSER_ID, {}) + many2one_field_mapping = { + "account_analytic_id": "account.analytic.account", + "analytic_tag_ids": "account.analytic.tag", + "company_id": "res.company", + "product_id": "product.product", + "product_uom": "uom.uom", + } + product_id_info = line["product_id"] + if product_id_info and len(product_id_info) == 2: + if "] " in product_id_info[1]: + # Case: [ID, '[CODE] Name'] + product_name = product_id_info[1].split("] ")[1] + else: + # Case: [ID, 'Name'] + product_name = product_id_info[1] + + line["product_id"] = [product_id_info[0], product_name] + for field, model in many2one_field_mapping.items(): + if field in line and line[field]: + line[field] = self.map_many2one_field_by_name( + env, model, line[field] + ) + for field, value in list(line.items()): + if isinstance(value, tuple) or isinstance(value, list): + line.pop(field, None) + + line["order_id"] = order.id + order_line = env["purchase.order.line"].create(line) + order_line.taxes_id = False + order_line.write({"price_tax": line["price_tax"]}) diff --git a/purchase_order_migration/security/ir.model.access.csv b/purchase_order_migration/security/ir.model.access.csv new file mode 100644 index 00000000..80810bfb --- /dev/null +++ b/purchase_order_migration/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_purchase_order_migration,purchase.order.migration,model_purchase_order_migration,base.group_system,1,1,1,1 diff --git a/setup/purchase_order_migration/odoo/addons/purchase_order_migration b/setup/purchase_order_migration/odoo/addons/purchase_order_migration new file mode 120000 index 00000000..2c545ad2 --- /dev/null +++ b/setup/purchase_order_migration/odoo/addons/purchase_order_migration @@ -0,0 +1 @@ +../../../../purchase_order_migration \ No newline at end of file diff --git a/setup/purchase_order_migration/setup.py b/setup/purchase_order_migration/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/purchase_order_migration/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From f7c70f93531f59a05080720abad5d6a237138923 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Sun, 3 Mar 2024 18:12:05 +0630 Subject: [PATCH 14/26] upd --- .../models/purchase_order_migration.py | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py index 630a5dc7..f41f47df 100644 --- a/purchase_order_migration/models/purchase_order_migration.py +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -9,6 +9,22 @@ class PurchaseOrderMigration(models.Model): _inherit = ["data.migration", "data.migration.mapping"] _description = "Purchase Order Data Migration" + def get_or_create_dummy_product(self): + env = api.Environment(self.env.cr, SUPERUSER_ID, {}) + # Check if the dummy product already exists + dummy_product = env['product.product'].search([('default_code', '=', 'DUMMY_PRODUCT')], limit=1) + if dummy_product: + return dummy_product.id + else: + # If the dummy product does not exist, create it + dummy_product = env['product.product'].create({ + 'name': 'Dummy Product', + 'type': 'product', + 'default_code': 'DUMMY_PRODUCT', + 'taxes_id': False, # Assuming no taxes, adjust if necessary + }) + return dummy_product.id + def _run_purchase_order_data_migration(self): required_fields = [ "id", @@ -119,7 +135,6 @@ def create_purchase_order_line(self, order): "price_tax", "price_total", "price_unit", - "product_id", "product_qty", "product_uom", "qty_invoiced", @@ -143,19 +158,10 @@ def create_purchase_order_line(self, order): "account_analytic_id": "account.analytic.account", "analytic_tag_ids": "account.analytic.tag", "company_id": "res.company", - "product_id": "product.product", "product_uom": "uom.uom", } - product_id_info = line["product_id"] - if product_id_info and len(product_id_info) == 2: - if "] " in product_id_info[1]: - # Case: [ID, '[CODE] Name'] - product_name = product_id_info[1].split("] ")[1] - else: - # Case: [ID, 'Name'] - product_name = product_id_info[1] - - line["product_id"] = [product_id_info[0], product_name] + dummy_product_id = self.get_or_create_dummy_product() + line["product_id"] = dummy_product_id for field, model in many2one_field_mapping.items(): if field in line and line[field]: line[field] = self.map_many2one_field_by_name( From bca025d3c9040db748165e7f9184e69b0f1807f0 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Mon, 4 Mar 2024 09:32:53 +0630 Subject: [PATCH 15/26] upd --- .../models/partner_data_migration.py | 5 +++++ .../models/purchase_order_migration.py | 18 +++++++++++------- .../models/user_data_migration.py | 5 +++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index 0e1abe7d..6bc04c79 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -130,4 +130,9 @@ def _process_partner_migration(self, partner, is_child=False): partner["parent_id"] = parent_id.id partner["old_id"] = partner["id"] + existing_partner = env["res.partner"].search( + [("phone", "=", partner["phone"])], limit=1 + ) + if existing_partner: + return True env["res.partner"].create(partner) diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py index f41f47df..26bdcdf0 100644 --- a/purchase_order_migration/models/purchase_order_migration.py +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -12,17 +12,21 @@ class PurchaseOrderMigration(models.Model): def get_or_create_dummy_product(self): env = api.Environment(self.env.cr, SUPERUSER_ID, {}) # Check if the dummy product already exists - dummy_product = env['product.product'].search([('default_code', '=', 'DUMMY_PRODUCT')], limit=1) + dummy_product = env["product.product"].search( + [("default_code", "=", "DUMMY_PRODUCT")], limit=1 + ) if dummy_product: return dummy_product.id else: # If the dummy product does not exist, create it - dummy_product = env['product.product'].create({ - 'name': 'Dummy Product', - 'type': 'product', - 'default_code': 'DUMMY_PRODUCT', - 'taxes_id': False, # Assuming no taxes, adjust if necessary - }) + dummy_product = env["product.product"].create( + { + "name": "Dummy Product", + "type": "product", + "default_code": "DUMMY_PRODUCT", + "taxes_id": False, # Assuming no taxes, adjust if necessary + } + ) return dummy_product.id def _run_purchase_order_data_migration(self): diff --git a/res_users_data_migration/models/user_data_migration.py b/res_users_data_migration/models/user_data_migration.py index 600fa59a..772bbfc4 100644 --- a/res_users_data_migration/models/user_data_migration.py +++ b/res_users_data_migration/models/user_data_migration.py @@ -35,4 +35,9 @@ def _create_user_job(self, user): # "password": hashlib.sha256(user["password"].encode()).hexdigest(), "partner_id": partner_id.id, } + existing_user = self.env["res.users"].search( + [("login", "=", user["login"])], limit=1 + ) + if existing_user: + return True self.env["res.users"].create(user_data) From f7ddf74542f3c11715927bc0378359d0236a16b4 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 7 Mar 2024 09:05:40 +0630 Subject: [PATCH 16/26] upd --- data_migration/models/partner_data_migration.py | 1 - 1 file changed, 1 deletion(-) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index 6bc04c79..64b1eeaf 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -37,7 +37,6 @@ def _run_partner_data_migration(self): "vat", "website", "comment", - "barcode", "return_policy", "invoice_warn", "invoice_warn_msg", From 8fb030c6e113cad1189f38dc00f952ff161995b0 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 21 Mar 2024 16:58:16 +0700 Subject: [PATCH 17/26] upd --- purchase_order_migration/models/purchase_order_migration.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py index 26bdcdf0..c51d6ac8 100644 --- a/purchase_order_migration/models/purchase_order_migration.py +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -109,14 +109,15 @@ def _process_purchase_order_migration(self, purchase): "shop_id": "stock.warehouse", "purchase_by_id": "hr.employee", "state_id": "res.country.state", - # 'sale_order_id': 'sale.order', + "sale_order_id": "sale.order", } for field, model in many2one_field_mapping.items(): if field in purchase: purchase[field] = self.map_many2one_field_by_name( env, model, purchase[field] ) - + state = purchase["state"] + purchase["state"] = False purchase["old_id"] = purchase["id"] order = env["purchase.order"].create(purchase) self.create_purchase_order_line(order) @@ -125,6 +126,7 @@ def _process_purchase_order_migration(self, purchase): "amount_tax": purchase["amount_tax"], "amount_untaxed": purchase["amount_untaxed"], "amount_total": purchase["amount_total"], + "state": state, } ) From d0885ca1f16ea7b6561736d2b78a35bdb1177246 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Mon, 1 Apr 2024 16:03:27 +0700 Subject: [PATCH 18/26] adj --- data_migration/models/partner_data_migration.py | 1 + purchase_order_migration/models/purchase_order_migration.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index 64b1eeaf..b5a63993 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -133,5 +133,6 @@ def _process_partner_migration(self, partner, is_child=False): [("phone", "=", partner["phone"])], limit=1 ) if existing_partner: + existing_partner.write({"old_id": partner["parent_id"][0]}) return True env["res.partner"].create(partner) diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py index c51d6ac8..7c9001cc 100644 --- a/purchase_order_migration/models/purchase_order_migration.py +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -51,6 +51,7 @@ def _run_purchase_order_data_migration(self): "company_id", "address", "remark", + "picking_type_id", "sale_prediction_amount", "request_channel_id", "request_medium_id", @@ -64,7 +65,6 @@ def _run_purchase_order_data_migration(self): "phone_search", "supplier_phone", "supplier_mobile", - "tentative_name", "purchase_category_id", "employee_id", "shop_id", @@ -110,7 +110,10 @@ def _process_purchase_order_migration(self, purchase): "purchase_by_id": "hr.employee", "state_id": "res.country.state", "sale_order_id": "sale.order", + "picking_type_id": "stock.picking.type", } + description = purchase["picking_type_id"][1].split(": ") + purchase["picking_type_id"][1] = description for field, model in many2one_field_mapping.items(): if field in purchase: purchase[field] = self.map_many2one_field_by_name( From b91cd2d23736a02c1751307f49c5e65a8031c689 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Tue, 2 Apr 2024 12:25:23 +0700 Subject: [PATCH 19/26] adj --- purchase_order_migration/models/purchase_order_migration.py | 1 + 1 file changed, 1 insertion(+) diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py index 7c9001cc..448eea6d 100644 --- a/purchase_order_migration/models/purchase_order_migration.py +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -32,6 +32,7 @@ def get_or_create_dummy_product(self): def _run_purchase_order_data_migration(self): required_fields = [ "id", + "name", "origin", "partner_ref", "date_order", From 1d66b8319f4b755f2556d5637b1861f28ef6ac97 Mon Sep 17 00:00:00 2001 From: kanda999 Date: Thu, 4 Apr 2024 02:07:31 +0000 Subject: [PATCH 20/26] fix partner import --- data_migration/models/partner_data_migration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index b5a63993..b4cad753 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -133,6 +133,6 @@ def _process_partner_migration(self, partner, is_child=False): [("phone", "=", partner["phone"])], limit=1 ) if existing_partner: - existing_partner.write({"old_id": partner["parent_id"][0]}) + existing_partner.write({"old_id": partner["id"]}) return True env["res.partner"].create(partner) From 5f582a84a26bd4013457847db94e2d139aa2a821 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 4 Apr 2024 09:14:49 +0700 Subject: [PATCH 21/26] upd --- purchase_order_migration/models/purchase_order_migration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py index 448eea6d..007df863 100644 --- a/purchase_order_migration/models/purchase_order_migration.py +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -114,7 +114,7 @@ def _process_purchase_order_migration(self, purchase): "picking_type_id": "stock.picking.type", } description = purchase["picking_type_id"][1].split(": ") - purchase["picking_type_id"][1] = description + purchase["picking_type_id"][1] = description[1] for field, model in many2one_field_mapping.items(): if field in purchase: purchase[field] = self.map_many2one_field_by_name( From 432fc99f851e915bde40c2068ee277ec9fa84804 Mon Sep 17 00:00:00 2001 From: kanda999 Date: Thu, 4 Apr 2024 09:22:04 +0000 Subject: [PATCH 22/26] Adj --- purchase_order_migration/models/purchase_order_migration.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py index 007df863..a2745879 100644 --- a/purchase_order_migration/models/purchase_order_migration.py +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -115,6 +115,9 @@ def _process_purchase_order_migration(self, purchase): } description = purchase["picking_type_id"][1].split(": ") purchase["picking_type_id"][1] = description[1] + if "," in purchase["partner_id"][1]: + description = purchase["partner_id"][1].split(", ") + purchase["partner_id"][1] = description[1] for field, model in many2one_field_mapping.items(): if field in purchase: purchase[field] = self.map_many2one_field_by_name( From 0d4fa10c35cf307893f15bd28766bf0200edb435 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 4 Apr 2024 17:08:21 +0700 Subject: [PATCH 23/26] adj --- data_migration/models/partner_data_migration.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/data_migration/models/partner_data_migration.py b/data_migration/models/partner_data_migration.py index b4cad753..d452bff9 100644 --- a/data_migration/models/partner_data_migration.py +++ b/data_migration/models/partner_data_migration.py @@ -72,7 +72,7 @@ def _run_partner_data_migration(self): instance.password, "res.partner", "search_read", - [], + [[('active', 'in', [True, False])]], {"fields": required_fields, "offset": offset, "limit": limit}, ) if not partners_v11: @@ -129,10 +129,4 @@ def _process_partner_migration(self, partner, is_child=False): partner["parent_id"] = parent_id.id partner["old_id"] = partner["id"] - existing_partner = env["res.partner"].search( - [("phone", "=", partner["phone"])], limit=1 - ) - if existing_partner: - existing_partner.write({"old_id": partner["id"]}) - return True env["res.partner"].create(partner) From 99d7cc9c3ffb1edb44099caf4ceedd90a6f5fd6a Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Tue, 16 Apr 2024 16:39:29 +0700 Subject: [PATCH 24/26] adj --- data_migration/models/data_migration_mapping.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_migration/models/data_migration_mapping.py b/data_migration/models/data_migration_mapping.py index 39890258..2b024977 100644 --- a/data_migration/models/data_migration_mapping.py +++ b/data_migration/models/data_migration_mapping.py @@ -22,4 +22,6 @@ def map_many2one_field_by_name(self, env, model_name, field_value): _, name = field_value record = env[model_name].search([("name", "=", name)], limit=1) + if not record and model_name == "res.partner": + record = env[model_name].search([("name", "=", name),('active', 'in', [True, False])], limit=1) return record.id if record else False From c5a70e3e95268dc8e09368e8959634399712be68 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Tue, 16 Apr 2024 16:45:52 +0700 Subject: [PATCH 25/26] adj --- data_migration/models/data_migration_mapping.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/data_migration/models/data_migration_mapping.py b/data_migration/models/data_migration_mapping.py index 2b024977..c5335830 100644 --- a/data_migration/models/data_migration_mapping.py +++ b/data_migration/models/data_migration_mapping.py @@ -20,8 +20,10 @@ def map_many2one_field_by_name(self, env, model_name, field_value): if not isinstance(field_value, (tuple, list)): return field_value - _, name = field_value - record = env[model_name].search([("name", "=", name)], limit=1) - if not record and model_name == "res.partner": - record = env[model_name].search([("name", "=", name),('active', 'in', [True, False])], limit=1) + old_id, name = field_value + if model_name == "res.partner": + record = env[model_name].search([("old_id", "=", old_id),('active', 'in', [True, False])], limit=1) + else: + record = env[model_name].search([("name", "=", name)], limit=1) + return record.id if record else False From fa74617dd2c243e4437a5820b71e07deb5b27ee4 Mon Sep 17 00:00:00 2001 From: kanda999 Date: Fri, 19 Apr 2024 07:54:47 +0000 Subject: [PATCH 26/26] adjtment --- purchase_order_migration/models/purchase_order_migration.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/purchase_order_migration/models/purchase_order_migration.py b/purchase_order_migration/models/purchase_order_migration.py index a2745879..007df863 100644 --- a/purchase_order_migration/models/purchase_order_migration.py +++ b/purchase_order_migration/models/purchase_order_migration.py @@ -115,9 +115,6 @@ def _process_purchase_order_migration(self, purchase): } description = purchase["picking_type_id"][1].split(": ") purchase["picking_type_id"][1] = description[1] - if "," in purchase["partner_id"][1]: - description = purchase["partner_id"][1].split(", ") - purchase["partner_id"][1] = description[1] for field, model in many2one_field_mapping.items(): if field in purchase: purchase[field] = self.map_many2one_field_by_name(