You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1000 lines
						
					
					
						
							48 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							1000 lines
						
					
					
						
							48 KiB
						
					
					
				| # -*- coding: utf-8 -*- | |
| ############################################################################# | |
| # | |
| #    Cybrosys Technologies Pvt. Ltd. | |
| # | |
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |
| #    Author: Vishnuraj P (odoo@cybrosys.com) | |
| # | |
| #    You can modify it under the terms of the GNU LESSER | |
| #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | |
| # | |
| #    This program is distributed in the hope that it will be useful, | |
| #    but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | |
| #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | |
| # | |
| #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | |
| #    (LGPL v3) along with this program. | |
| #    If not, see <http://www.gnu.org/licenses/>. | |
| # | |
| ############################################################################# | |
| import base64 | |
| from datetime import datetime, timezone | |
| from hubspot import HubSpot | |
| from hubspot.crm.deals import BatchInputSimplePublicObjectBatchInput | |
| from hubspot.crm.deals import SimplePublicObjectInput | |
| import requests | |
| from odoo import fields, models, _ | |
| from odoo.exceptions import AccessError | |
| 
 | |
| 
 | |
| class HubspotConnector(models.Model): | |
|     """ | |
|     Model for hubspot connector to set up the credentials and contains | |
|     methods for various sync operations. | |
|     Methods: | |
|         action_connect(self): | |
|             CONNECT smart button action to check the hubspot account with | |
|             provided credentials, if account exist it connects, and shows the | |
|             sync options. | |
|         action_contact_sync(self): | |
|             Button action for sync contacts based on user preference. | |
|         action_company_sync(self): | |
|             Button action for sync company based on user preference. | |
|         action_deal_sync(self): | |
|             Button action for sync deals based on user preference. | |
|         #--- Contacts Various Sync Methods ---# | |
|         action_export_partner(self): | |
|             Method for exporting contacts when the contact is not available in | |
|             hubspot. | |
|         action_import_partner(self): | |
|             Method for importing contacts when the contact is not available in | |
|             odoo. | |
|         action_update_hub_partner(self): | |
|             Method for update contacts in hubspot, based on odoo contacts, | |
|         action_update_odoo_partner(self): | |
|             Method for update contacts in odoo, based on hubspot contacts, | |
|         #--- Various Sync Methods for Company ---# | |
|         action_export_company(self): | |
|             Method for exporting company when the company is not available in | |
|             hubspot. | |
|         action_import_company(self): | |
|             Method for importing company when the company is not available in | |
|             odoo. | |
|         action_update_hub_company(self): | |
|             Method for update company in hubspot, based on odoo company. | |
|         action_update_odoo_company(self): | |
|             Method for update company in odoo, based on hubspot company. | |
|         #--- Various Sync Methods for Deals ---# | |
|         action_export_deals(self): | |
|             Method for exporting deals when the deals are not available in | |
|             hubspot. | |
|         action_import_deals(self): | |
|             Method for importing deals when the deals are not available in | |
|             odoo. | |
|         action_update_hub_deals(self): | |
|             Method for update deals in hubspot, based on odoo deals. | |
|         action_update_odoo_deals(self): | |
|             Method for update deals in odoo, based on hubspot deals. | |
|     """ | |
|     _name = 'hubspot.connector' | |
|     _description = 'HubSpot Connector' | |
| 
 | |
|     state = fields.Selection(string="State", | |
|                              selection=[("disconnected", "Disconnected"), | |
|                                         ("connected", "Connected")], | |
|                              default="disconnected", | |
|                              help="Shows the connection is true or false") | |
|     name = fields.Char(string="Connector Name", help="name of the instance") | |
|     access_key = fields.Char(string="Access Token", | |
|                              help="Private app key of hubspot account") | |
|     owner_id = fields.Char(string="Owner ID", required=True, | |
|                            help="Owner ID of Hubspot account") | |
|     connection = fields.Boolean(string="Connection", | |
|                                 help="Shows connected to hubspot or nor") | |
|     # Toggles for Contacts sync | |
|     import_contacts = fields.Boolean(string="Import Contacts", | |
|                                      help="This will enable import of contact " | |
|                                           "from hubspot to odoo") | |
|     export_contacts = fields.Boolean(string="Export Contacts", | |
|                                      help="This will enable export of contact " | |
|                                           "from odoo to hubspot") | |
|     update_odoo_contacts = fields.Boolean(string="Update Odoo Contacts", | |
|                                           help="This will update contact in " | |
|                                                "odoo from hubspot data") | |
|     update_hub_contacts = fields.Boolean(string="Update Hubspot Contacts", | |
|                                          help="This will update contact in " | |
|                                               "hubspot from odoo data") | |
|     # Toggles for Company sync | |
|     import_company = fields.Boolean(string="Import Company", | |
|                                     help="This will enable import of companies" | |
|                                          "from hubspot to odoo") | |
|     export_company = fields.Boolean(string="Export Company", | |
|                                     help="This will enable export of companies " | |
|                                          "from Odoo to HubSpot") | |
|     update_odoo_company = fields.Boolean(string="Update Odoo Company", | |
|                                          help="This will update company in odoo" | |
|                                               "from hubspot data") | |
|     update_hub_company = fields.Boolean(string="Update Hubspot Company", | |
|                                         help="This will update company in " | |
|                                              "hubspot from odoo data") | |
|     # Toggles for Deals sync | |
|     export_deals = fields.Boolean( | |
|         string="Export Deals", | |
|         help="This will enable export of deals from odoo to hubspot") | |
|     import_deals = fields.Boolean( | |
|         string="Import Deals", | |
|         help="This will enable import of deals from hubspot to odoo") | |
|     update_odoo_deals = fields.Boolean( | |
|         string="Update Odoo Deals", | |
|         help="This will update deals in odoo from hubspot data") | |
|     update_hub_deals = fields.Boolean( | |
|         string="Update Hubspot Deals", | |
|         help="This will update deals in hubspot from odoo data") | |
|     # Contacts last sync Times | |
|     contacts_last_imported = fields.Datetime( | |
|         string="Contact Last Imported", readonly=True, | |
|         help="This is the last imported time") | |
|     contacts_last_exported = fields.Datetime( | |
|         string="Contact Last Exported", readonly=True, | |
|         help="This is the last exported time") | |
|     hub_contact_last_updated = fields.Datetime( | |
|         string="Hubspot Contacts Updated", readonly=True, | |
|         help="Last Hubspot Contacts Updated Time") | |
|     odoo_contact_last_updated = fields.Datetime( | |
|         string="Odoo Contacts Updated", readonly=True, | |
|         help="Last Odoo Contacts Updated Time") | |
|     # Company last sync Times | |
|     company_last_imported = fields.Datetime( | |
|         string="Company Last Imported", readonly=True, | |
|         help="This is the last imported time") | |
|     company_last_exported = fields.Datetime( | |
|         string="Company Last Exported", readonly=True, | |
|         help="This is the last exported time") | |
|     hub_company_last_updated = fields.Datetime( | |
|         string="Hubspot Company Updated", readonly=True, | |
|         help="Last Hubspot Company Updated Time") | |
|     odoo_company_last_updated = fields.Datetime( | |
|         string="Odoo Company Updated", readonly=True, | |
|         help="Last Odoo Company Updated Time") | |
|     # Deals last sync Times | |
|     deals_last_imported = fields.Datetime( | |
|         string="Deals Last Imported", readonly=True, | |
|         help="This is the last imported time") | |
|     deals_last_exported = fields.Datetime( | |
|         string="Deals Last Exported", readonly=True, | |
|         help="This is the last exported time") | |
|     hub_deal_last_updated = fields.Datetime( | |
|         string="Hubspot Deal Updated", readonly=True, | |
|         help="Last Hubspot Deal Updated Time") | |
|     odoo_deal_last_updated = fields.Datetime( | |
|         string="Odoo Deal Updated", readonly=True, | |
|         help="Last Odoo Deal Updated Time") | |
| 
 | |
|     def action_connect(self): | |
|         """ | |
|         Method for testing connection; if credentials are correct connects | |
|         and shows sync options, if connected disconnects. | |
|         """ | |
|         if not self.connection: | |
|             owners_endpoint = 'https://api.hubapi.com/owners/v2/owners' | |
|             headers = {'Authorization': f'Bearer {self.access_key}'} | |
|             try: | |
|                 response = requests.get(owners_endpoint, headers=headers) | |
|                 if response.status_code == 200: | |
|                     data = response.json() | |
|                     if str(data[0]['ownerId']) == self.owner_id: | |
|                         self.connection = True | |
|                         self.state = "connected" | |
|                 else: | |
|                     raise AccessError(_("Error when Fetching account info")) | |
|             except requests.exceptions.RequestException: | |
|                 return None | |
|         else: | |
|             self.connection = False | |
|             self.state = "disconnected" | |
| 
 | |
|     def action_contact_sync(self): | |
|         """ | |
|         Method used to sync contacts it calls methods for import, export and | |
|         update contacts methods when user need specific condition on sync | |
|         """ | |
|         rainbow_msg = "Congrats, " | |
|         if self.export_contacts: | |
|             exported_count = self.action_export_partner() | |
|             if exported_count > 0: | |
|                 rainbow_msg += f"# {exported_count} Contacts Exported" | |
|         if self.import_contacts: | |
|             imported_count = self.action_import_partner() | |
|             if imported_count > 0: | |
|                 rainbow_msg += f", # {imported_count} Contacts Imported" | |
|         if self.update_hub_contacts: | |
|             hub_update_count = self.action_update_hub_partner() | |
|             if hub_update_count > 0: | |
|                 rainbow_msg += f", #{hub_update_count} Hubspot Contacts Updated" | |
|         if self.update_odoo_contacts: | |
|             odoo_update_count = self.action_update_odoo_partner() | |
|             if odoo_update_count > 0: | |
|                 rainbow_msg += f", # {odoo_update_count} Odoo Contacts Updated" | |
|         # If there is no sync option modifies data | |
|         if rainbow_msg == "Congrats, ": | |
|             rainbow_msg += "Contacts are already synced" | |
|         # Rainbow man displays status of sync | |
|         return { | |
|             'effect': { | |
|                 'fadeout': 'slow', | |
|                 'message': rainbow_msg, | |
|                 'type': 'rainbow_man' | |
|             } | |
|         } | |
| 
 | |
|     def action_company_sync(self): | |
|         """ | |
|         Method used to sync company it calls methods for import, export and | |
|         update company methods when user need specific condition on sync | |
|         """ | |
|         rainbow_msg = "Congrats, " | |
|         if self.export_company: | |
|             exported_count = self.action_export_company() | |
|             if exported_count > 0: | |
|                 rainbow_msg += f"# {exported_count} Companies Exported" | |
|         if self.import_company: | |
|             imported_count = self.action_import_company() | |
|             if imported_count > 0: | |
|                 rainbow_msg += f", # {imported_count} Companies Imported" | |
|         if self.update_hub_company: | |
|             hub_update_count = self.action_update_hub_company() | |
|             if hub_update_count > 0: | |
|                 rainbow_msg += (f", # {hub_update_count}" | |
|                                 f" Hubspot Companies Updated") | |
|         if self.update_odoo_company: | |
|             odoo_update_count = self.action_update_odoo_company() | |
|             if odoo_update_count > 0: | |
|                 rainbow_msg += f", # {odoo_update_count} Odoo Companies Updated" | |
|         if rainbow_msg == "Congrats, ": | |
|             rainbow_msg += "Companies are already synced" | |
|         return { | |
|             'effect': { | |
|                 'fadeout': 'slow', | |
|                 'message': rainbow_msg, | |
|                 'type': 'rainbow_man' | |
|             } | |
|         } | |
| 
 | |
|     def action_deal_sync(self): | |
|         """ | |
|         Method used to sync deals, it calls methods for import, export and | |
|         update deals methods when user need specific condition on sync | |
|         """ | |
|         rainbow_msg = "Congrats, " | |
|         if self.export_deals: | |
|             exported_count = self.action_export_deals() | |
|             if exported_count > 0: | |
|                 rainbow_msg += f"# {exported_count} Deals Exported" | |
|         if self.import_deals: | |
|             imported_count = self.action_import_deals() | |
|             if imported_count > 0: | |
|                 rainbow_msg += f", # {imported_count} Deals Imported" | |
|         if self.update_hub_deals: | |
|             hub_update_count = self.action_update_hub_deals() | |
|             if hub_update_count > 0: | |
|                 rainbow_msg += f", # {hub_update_count} Hubspot Deals Updated" | |
|         if self.update_odoo_deals: | |
|             odoo_update_count = self.action_update_odoo_deals() | |
|             if odoo_update_count > 0: | |
|                 rainbow_msg += f", # {odoo_update_count} Odoo Deals Updated" | |
|         if rainbow_msg == "Congrats, ": | |
|             rainbow_msg += "Deals are already synced" | |
|         return { | |
|             'effect': { | |
|                 'fadeout': 'slow', | |
|                 'message': rainbow_msg, | |
|                 'type': 'rainbow_man' | |
|             } | |
|         } | |
| 
 | |
|     def action_export_partner(self): | |
|         """ | |
|         Method used to Export Contacts from Odoo to Hubspot, also creates | |
|         non-existing odoo_mail and odoo_image_string fields which are not | |
|         present in hubspot and export according data to it. | |
|         """ | |
|         # Set up HubSpot API connection. | |
|         api_key = self.access_key | |
|         base_url = 'https://api.hubapi.com' | |
|         # Lists fields and their properties need to create in hubspot. | |
|         partner_fields = [ | |
|             { | |
|                 'name': 'odoo_mail', | |
|                 'label': 'Mail', | |
|                 'type': 'string' | |
|             }, | |
|             { | |
|                 'name': 'odoo_image_string', | |
|                 'label': 'Image String', | |
|                 'type': 'string' | |
|             }, | |
|         ] | |
|         for field in partner_fields: | |
|             # Check each field in partner_fields exists in HubSpot or not | |
|             endpoint = f"/properties/v1/contacts/properties/named/" \ | |
|                        f"{field['name']}" | |
|             headers = { | |
|                 'Content-Type': 'application/json', | |
|                 'Authorization': f'Bearer {api_key}' | |
|             } | |
|             response = requests.get(base_url + endpoint, headers=headers) | |
|             # Response returns a status code "200" when field exist in hubspot. | |
|             if response.status_code != 200: | |
|                 # Create custom field in HubSpot | |
|                 endpoint = '/properties/v1/contacts/properties' | |
|                 headers = { | |
|                     'Content-Type': 'application/json', | |
|                     'Authorization': 'Bearer {}'.format(api_key) | |
|                 } | |
|                 # Properties of Field ie, going to create | |
|                 payload = { | |
|                     'name': field['name'], | |
|                     'label': field['label'], | |
|                     'description': 'Custom field created form odoo', | |
|                     'groupName': 'contactinformation', | |
|                     'type': field['type'] | |
|                 } | |
|                 # API call for Field creation | |
|                 response = requests.post(base_url + endpoint, json=payload, | |
|                                          headers=headers) | |
|                 # Returns status code "200" when successfully created the field | |
|                 if response.status_code == 200: | |
|                     pass  # Notification : Successfully connected. | |
|                 else: | |
|                     raise AccessError(f"Failed to create {field['name']} field," | |
|                                       f"Status code: {response.status_code}") | |
|         # Setting api client connection via api | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_partners = self.env['res.partner'].search([]) | |
|         success_count = 0 | |
|         # Fetch HubSpot contact's ID as list | |
|         hubspot_partners = [rec.properties['hs_object_id'] | |
|                             for rec in api_client.crm.contacts.get_all()] | |
|         for rec in odoo_partners: | |
|             # If the Odoo contact not present in Hubspot ID list export it | |
|             if rec.hs_object_id not in hubspot_partners: | |
|                 properties = { | |
|                     "firstname": rec.name, | |
|                     "lastname": "", | |
|                     "odoo_mail": rec.email, | |
|                     "phone": rec.phone if rec.phone else None, | |
|                     "company": rec.commercial_company_name or rec.company_name | |
|                     if rec.commercial_company_name or rec.company_name | |
|                     else None, | |
|                     "jobtitle": rec.function if rec.function else None, | |
|                     "website": rec.website if rec.website else None, | |
|                     "address": rec.street + "," + rec.street2 if ( | |
|                             rec.street and rec.street2) else ( | |
|                             rec.street or rec.street2 or ""), | |
|                     "city": rec.city if rec.city else None, | |
|                     "state": rec.state_id.name if rec.state_id else None, | |
|                     "zip": rec.zip if rec.zip else None, | |
|                     "country": rec.country_id.name if rec.country_id else None, | |
|                     "odoo_image_string": base64.b64encode(rec.image_1920). | |
|                     decode('utf-8') if (rec.image_1920 and len(base64.b64encode( | |
|                         rec.image_1920).decode('utf-8')) < 65500) else None, | |
|                 } | |
|                 api_response = api_client.crm.contacts.basic_api.create( | |
|                     simple_public_object_input_for_create= | |
|                     SimplePublicObjectInput(properties)) | |
|                 # If Exported then update Hubspot ID in Odoo | |
|                 if api_response: | |
|                     rec.write({ | |
|                         'hs_object_id': api_response.properties['hs_object_id'], | |
|                         'sync_mode': 'export'}) | |
|                 else: | |
|                     # change it to Failure msg. | |
|                     pass | |
|                 success_count += 1 | |
|         # If Any record exported Create Sync History | |
|         if success_count > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': datetime.now(), | |
|                 'res_model_id': self.env.ref('base.model_res_partner').id, | |
|                 'sync_mode': 'export', | |
|                 'state': 'success', | |
|                 'count': success_count, | |
|             }) | |
|         self.contacts_last_exported = datetime.now() | |
|         # Returns Exported Count | |
|         return success_count | |
| 
 | |
|     def action_import_partner(self): | |
|         """ | |
|         Method used fetch data from Hubspot and creates contacts based on it. | |
|         """ | |
|         # Fields needs to fetch from hubspot. | |
|         needed_fields = [ | |
|             "firstname", "lastname", "email", "phone", "company", "jobtitle", | |
|             "website", "address", "city", "state", "zip", "country", | |
|             "odoo_mail", "odoo_image_string", "hs_object_id" | |
|         ] | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_partners = self.env['res.partner'].search([]).mapped( | |
|             'hs_object_id') | |
|         # Getting needed fields from hubspot | |
|         hubspot_partners = api_client.crm.contacts.get_all( | |
|             properties=needed_fields) | |
|         partners_to_create = [] | |
|         success_count = 0 | |
|         # Creates Dictionaries from country and state model to fetch | |
|         # state_id and country_id | |
|         state_dict = {state['name']: state['id'] for state in self.env[ | |
|             'res.country.state'].search_read([], ['name'])} | |
|         country_dict = {country['name']: country['id'] for country in self.env[ | |
|             'res.country'].search_read([], ['name'])} | |
|         for rec in hubspot_partners: | |
|             # If hubspot record not present in odoo records creates it. | |
|             if rec.properties['hs_object_id'] not in odoo_partners: | |
|                 partners_to_create.append({ | |
|                     'name': rec.properties['firstname'] + '' + rec.properties[ | |
|                         'lastname'] if rec.properties[ | |
|                         'lastname'] else rec.properties['firstname'], | |
|                     'email': rec.properties['email'] if rec.properties[ | |
|                         'email'] else rec.properties[ | |
|                         'odoo_mail'] if rec.properties['odoo_mail'] else None, | |
|                     'phone': rec.properties['phone'], | |
|                     'function': rec.properties['jobtitle'], | |
|                     'website': rec.properties['website'], | |
|                     'street': rec.properties['address'], | |
|                     'city': rec.properties['city'], | |
|                     'zip': rec.properties['zip'], | |
|                     'state_id': state_dict.get(str(rec.properties['state']), | |
|                                                None), | |
|                     'country_id': country_dict.get( | |
|                         str(rec.properties['country']), None), | |
|                     'image_1920': base64.b64decode( | |
|                         rec.properties['odoo_image_string']) if rec.properties[ | |
|                         'odoo_image_string'] else None, | |
|                     'hs_object_id': rec.properties['hs_object_id'], | |
|                     'sync_mode': 'import' | |
|                 }) | |
|                 # counting total records created | |
|                 success_count += 1 | |
|         if partners_to_create: | |
|             self.env['res.partner'].sudo().create(partners_to_create) | |
|         # If new record created, then creates sync history. | |
|         if success_count > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': datetime.now(), | |
|                 'res_model_id': self.env.ref('base.model_res_partner').id, | |
|                 'sync_mode': 'import', | |
|                 'state': 'success', | |
|                 'count': success_count, | |
|             }) | |
|         self.contacts_last_imported = datetime.now() | |
|         return success_count | |
| 
 | |
|     def action_update_hub_partner(self): | |
|         """ Method used to update hubspot contacts based on odoo contacts. """ | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_partners = self.env['res.partner'].search([]) | |
|         odoo_partners_list = odoo_partners.mapped('hs_object_id') | |
|         hubspot_partners = api_client.crm.contacts.get_all() | |
|         update_success = 0 | |
|         data_to_update = [] | |
|         for rec in hubspot_partners: | |
|             # Checking the hubspot contact present in odoo | |
|             # then take the corresponding odoo record | |
|             if rec.properties['hs_object_id'] in odoo_partners_list: | |
|                 odoo_record = self.env['res.partner'].search( | |
|                     [('hs_object_id', '=', rec.properties['hs_object_id'])]) | |
|                 # If the corresponding odoo record is last updated then | |
|                 # update hubspot record based on that | |
|                 if odoo_record.write_date > ( | |
|                         self.hub_contact_last_updated or rec.updated_at. | |
|                         astimezone(timezone.utc).replace(tzinfo=None)): | |
|                     data_to_update.append({ | |
|                         'id': rec.properties['hs_object_id'], | |
|                         'properties': { | |
|                             "firstname": odoo_record.name, | |
|                             "lastname": "", | |
|                             "odoo_mail": odoo_record.email, | |
|                             "phone": odoo_record.phone, | |
|                             "company": odoo_record.commercial_company_name | |
|                                        or odoo_record.company_name, | |
|                             "jobtitle": odoo_record.function, | |
|                             "website": odoo_record.website, | |
|                             "address": odoo_record.street + "," + | |
|                                        odoo_record.street2 if ( | |
|                                     odoo_record.street and odoo_record.street2) | |
|                             else (odoo_record.street | |
|                                   or odoo_record.street2 or ""), | |
|                             "city": odoo_record.city if odoo_record.city | |
|                             else None, | |
|                             "state": odoo_record.state_id.name | |
|                             if odoo_record.state_id else None, | |
|                             "zip": odoo_record.zip if odoo_record.zip else None, | |
|                             "country": odoo_record.country_id.name | |
|                             if odoo_record.country_id else None, | |
|                             "odoo_image_string": base64.b64encode( | |
|                                 odoo_record.image_1920).decode('utf-8') if ( | |
|                                     odoo_record.image_1920 and len( | |
|                                 base64.b64encode( | |
|                                     odoo_record.image_1920).decode( | |
|                                     'utf-8')) < 65500) else "", | |
|                         } | |
|                     }) | |
|                     update_success += 1 | |
|         # Batch Update of record to hubspot. | |
|         api_client.crm.contacts.batch_api.update( | |
|             batch_input_simple_public_object_batch_input= | |
|             BatchInputSimplePublicObjectBatchInput(data_to_update)) | |
|         self.hub_contact_last_updated = datetime.now() | |
|         if update_success > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.hub_contact_last_updated, | |
|                 'res_model_id': self.env.ref('base.model_res_partner').id, | |
|                 'sync_mode': 'hub_updated', | |
|                 'state': 'success', | |
|                 'count': update_success, | |
|             }) | |
|         # Returns successfully updated count. | |
|         return update_success | |
| 
 | |
|     def action_update_odoo_partner(self): | |
|         """Method used to update odoo partner based on the hubspot contacts.""" | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_partners = self.env['res.partner'].search([]) | |
|         # Fields need to fetch from hubspot. | |
|         needed_fields = [ | |
|             "firstname", "lastname", "email", "phone", "company", "jobtitle", | |
|             "website", "address", "city", "state", "zip", "country", | |
|             "odoo_mail", "odoo_image_string", "hs_object_id" | |
|         ] | |
|         hubspot_partners = api_client.crm.contacts.get_all( | |
|             properties=needed_fields) | |
|         hubspot_partners_list = [rec.properties['hs_object_id'] | |
|                                  for rec in hubspot_partners] | |
|         update_success = 0 | |
|         # Creates Dictionaries from country and state model to fetch | |
|         # state_id and country_id | |
|         state_dict = {state['name']: state['id'] for state in self.env[ | |
|             'res.country.state'].search_read([], ['name'])} | |
|         country_dict = {country['name']: country['id'] for country in self.env[ | |
|             'res.country'].search_read([], ['name'])} | |
|         for rec in odoo_partners: | |
|             # If odoo record present in hubspot record then teke | |
|             # corresponding hubspot record | |
|             if rec.hs_object_id in hubspot_partners_list: | |
|                 hubspot_partner = {h.id: h for h in hubspot_partners} | |
|                 hub_record = hubspot_partner.get(rec.hs_object_id, None) | |
|                 # If hubspot record is recently updated, then update | |
|                 # odoo record based on that | |
|                 if hub_record.updated_at.astimezone(timezone.utc).replace( | |
|                         tzinfo=None) > ( | |
|                         self.odoo_contact_last_updated or rec.write_date): | |
|                     data_to_update = { | |
|                         'name': hub_record.properties[ | |
|                                     'firstname'] + '' + hub_record.properties[ | |
|                                     'lastname'] if hub_record.properties[ | |
|                             'lastname'] else hub_record.properties['firstname'], | |
|                         'email': hub_record.properties[ | |
|                             'email'] if hub_record.properties[ | |
|                             'email'] else hub_record.properties[ | |
|                             'odoo_mail'] if hub_record.properties[ | |
|                             'odoo_mail'] else None, | |
| 
 | |
|                         'phone': hub_record.properties['phone'], | |
|                         'function': hub_record.properties['jobtitle'], | |
|                         'website': hub_record.properties['website'], | |
|                         'street': hub_record.properties['address'], | |
|                         'city': hub_record.properties['city'], | |
|                         'zip': hub_record.properties['zip'], | |
|                         'state_id': state_dict.get(str(hub_record.properties[ | |
|                                                            'state']), None), | |
|                         'country_id': country_dict.get( | |
|                             str(hub_record.properties['country']), None), | |
| 
 | |
|                         'image_1920': base64.b64decode( | |
|                             hub_record.properties[ | |
|                                 'odoo_image_string']) if hub_record.properties[ | |
|                             'odoo_image_string'] else None, | |
|                     } | |
|                     update_success += 1 | |
|                     rec.write(data_to_update) | |
|         self.odoo_contact_last_updated = datetime.now() | |
|         # If there is any contact updated then creates sync history. | |
|         if update_success > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.odoo_contact_last_updated, | |
|                 'res_model_id': self.env.ref('base.model_res_partner').id, | |
|                 'sync_mode': 'odoo_updated', | |
|                 'state': 'success', | |
|                 'count': update_success, | |
|             }) | |
|         # Returns updated record's count. | |
|         return update_success | |
| 
 | |
|     def action_export_company(self): | |
|         """ Method to export companies to hubspot. """ | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_companies = self.env['res.company'].search([]) | |
|         hubspot_companies = [] | |
|         success_count = 0 | |
|         for rec in api_client.crm.companies.get_all(): | |
|             hubspot_companies.append(rec.properties['hs_object_id']) | |
|         for rec in odoo_companies: | |
|             # If odoo record not present in hubspot record create it | |
|             # via api call | |
|             if rec.hs_object_id not in hubspot_companies: | |
|                 properties = { | |
|                     "name": rec.name, | |
|                     "domain": rec.website, | |
|                     "description": rec.company_details if rec.company_details | |
|                     else None, | |
|                     "phone": rec.phone, | |
|                     "address": rec.street + "," + rec.street2 if ( | |
|                             rec.street and rec.street2) else ( | |
|                             rec.street or rec.street2 or ""), | |
|                     "city": rec.city, | |
|                     "state": rec.state_id.name if rec.state_id else None, | |
|                     "zip": rec.zip if rec.zip else None, | |
|                     "country": rec.country_id.name if rec.country_id else None, | |
|                     "industry": "", | |
|                 } | |
|                 # API call for create company record on hubspot. | |
|                 api_response = api_client.crm.companies.basic_api.create( | |
|                     simple_public_object_input_for_create= | |
|                     SimplePublicObjectInput(properties)) | |
|                 # After exporting save the unique hubspot id on that record | |
|                 if api_response: | |
|                     rec.write({ | |
|                         'hs_object_id': api_response.properties['hs_object_id'], | |
|                         'sync_mode': 'export' | |
|                     }) | |
|                 success_count += 1 | |
|         self.company_last_exported = datetime.now() | |
|         # If there is any record exported then creates history record. | |
|         if success_count > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.company_last_exported, | |
|                 'res_model_id': self.env.ref('base.model_res_company').id, | |
|                 'sync_mode': 'export', | |
|                 'state': 'success', | |
|                 'count': success_count, | |
|             }) | |
|         # Returns the exported count. | |
|         return success_count | |
| 
 | |
|     def action_import_company(self): | |
|         """ Method to Import record from hubspot """ | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_companies = self.env['res.company'].search([]).mapped( | |
|             'hs_object_id') | |
|         # The fields need to fetch from hubspot. | |
|         needed_fields = [ | |
|             "hs_object_id", "name", "domain", "website", "description", "phone", | |
|             "city", "state", "country", "zip" | |
|         ] | |
|         hubspot_companies = api_client.crm.companies.get_all( | |
|             properties=needed_fields) | |
|         companies_to_create = [] | |
|         success_count = 0 | |
|         # Creates Dictionaries from country and state model to fetch | |
|         # state_id and country_id | |
|         state_dict = {state['name']: state['id'] for state in self.env[ | |
|             'res.country.state'].search_read([], ['name'])} | |
|         country_dict = {country['name']: country['id'] for country in self.env[ | |
|             'res.country'].search_read([], ['name'])} | |
|         for rec in hubspot_companies: | |
|             # If hubspot record not present in odoo record, create new record. | |
|             if rec.properties['hs_object_id'] not in odoo_companies: | |
|                 companies_to_create.append({ | |
|                     'name': rec.properties['name'], | |
|                     'website': rec.properties['domain'], | |
|                     'company_details': rec.properties['description'], | |
|                     'phone': rec.properties['phone'], | |
|                     'city': rec.properties['city'], | |
|                     'state_id': state_dict.get(str(rec.properties['state']), | |
|                                                None), | |
|                     'country_id': country_dict.get( | |
|                         str(rec.properties['country']), None), | |
|                     'zip': rec.properties['zip'], | |
|                     'hs_object_id': rec.properties['hs_object_id'], | |
|                     'sync_mode': 'import', | |
|                 }) | |
|                 success_count += 1 | |
|         if companies_to_create: | |
|             self.env['res.company'].sudo().create(companies_to_create) | |
|         self.deals_last_imported = datetime.now() | |
|         # If any new record created then create history record. | |
|         if success_count > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.deals_last_imported, | |
|                 'res_model_id': self.env.ref('base.model_res_company').id, | |
|                 'sync_mode': 'import', | |
|                 'state': 'success', | |
|                 'count': success_count, | |
|             }) | |
|         # Returns the created record count. | |
|         return success_count | |
| 
 | |
|     def action_update_hub_company(self): | |
|         """ Method to update hubspot record based on odoo records """ | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_company = self.env['res.company'].search([]) | |
|         odoo_company_list = odoo_company.mapped('hs_object_id') | |
|         hubspot_company = api_client.crm.companies.get_all() | |
|         update_success = 0 | |
|         data_to_update = [] | |
|         for rec in hubspot_company: | |
|             # If hubspot record present in odoo record then take | |
|             # corresponding odoo record | |
|             if rec.properties['hs_object_id'] in odoo_company_list: | |
|                 odoo_record = self.env['res.company'].search( | |
|                     [('hs_object_id', '=', rec.properties['hs_object_id'])]) | |
|                 # If odoo record is recently updated then update hubspot record. | |
|                 if odoo_record.write_date > ( | |
|                         self.hub_company_last_updated or rec.updated_at. | |
|                         astimezone(timezone.utc).replace(tzinfo=None)): | |
|                     data_to_update.append({ | |
|                         'id': rec.properties['hs_object_id'], | |
|                         'properties': { | |
|                             "name": odoo_record.name, | |
|                             "domain": odoo_record.website, | |
|                             "description": odoo_record.company_details | |
|                             if odoo_record.company_details else None, | |
|                             "phone": odoo_record.phone, | |
|                             "address": odoo_record.street + "," + | |
|                                        odoo_record.street2 | |
|                             if (odoo_record.street and odoo_record.street2) | |
|                             else (odoo_record.street | |
|                                   or odoo_record.street2 or ""), | |
|                             "city": odoo_record.city, | |
|                             "state": odoo_record.state_id.name | |
|                             if odoo_record.state_id else None, | |
|                             "zip": odoo_record.zip if odoo_record.zip else None, | |
|                             "country": odoo_record.country_id.name | |
|                             if odoo_record.country_id else None, | |
|                             "industry": "", | |
|                         } | |
|                     }) | |
|                     update_success += 1 | |
|         api_client.crm.companies.batch_api.update( | |
|             batch_input_simple_public_object_batch_input= | |
|             BatchInputSimplePublicObjectBatchInput(data_to_update)) | |
|         self.hub_company_last_updated = datetime.now() | |
|         if update_success > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.hub_company_last_updated, | |
|                 'res_model_id': self.env.ref('base.model_res_company').id, | |
|                 'sync_mode': 'hub_updated', | |
|                 'state': 'success', | |
|                 'count': update_success, | |
|             }) | |
|         # Returns the updated count. | |
|         return update_success | |
| 
 | |
|     def action_update_odoo_company(self): | |
|         """ Method to update odoo company records based on hubspot record. """ | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_company = self.env['res.company'].search([]) | |
|         # Needed fields to fetch from hubspot. | |
|         needed_fields = [ | |
|             "hs_object_id", "name", "domain", "website", "description", "phone", | |
|             "city", "state", "country", "zip" | |
|         ] | |
|         hubspot_company = api_client.crm.companies.get_all( | |
|             properties=needed_fields) | |
|         hubspot_company_list = [rec.properties['hs_object_id'] | |
|                                 for rec in hubspot_company] | |
|         update_success = 0 | |
|         # Creates Dictionaries from country and state model to fetch | |
|         # state_id and country_id. | |
|         state_dict = {state['name']: state['id'] for state in self.env[ | |
|             'res.country.state'].search_read([], ['name'])} | |
|         country_dict = {country['name']: country['id'] for country in self.env[ | |
|             'res.country'].search_read([], ['name'])} | |
|         for rec in odoo_company: | |
|             # If the odoo company record is present in hubspot company, | |
|             # take the corresponding hubspot record. | |
|             if rec.hs_object_id in hubspot_company_list: | |
|                 hubspot_company_dict = {h.id: h for h in hubspot_company} | |
|                 hub_record = hubspot_company_dict.get(rec.hs_object_id, None) | |
|                 # If the hubspot record is recently modified then update | |
|                 # odoo record based on that. | |
|                 if hub_record.updated_at.astimezone(timezone.utc).replace( | |
|                         tzinfo=None) > rec.write_date: | |
|                     data_to_update = { | |
|                         'name': hub_record.properties['name'], | |
|                         'website': hub_record.properties['domain'], | |
|                         'company_details': hub_record.properties['description'], | |
|                         'phone': hub_record.properties['phone'], | |
|                         'city': hub_record.properties['city'], | |
|                         'state_id': state_dict.get(str(hub_record.properties[ | |
|                                                            'state']), None), | |
|                         'country_id': country_dict.get( | |
|                             str(hub_record.properties['country']), None), | |
|                         'zip': hub_record.properties['zip'], | |
|                     } | |
|                     update_success += 1 | |
|                     rec.write(data_to_update) | |
|         self.odoo_company_last_updated = datetime.now() | |
|         if update_success > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.odoo_company_last_updated, | |
|                 'res_model_id': self.env.ref('base.model_res_company').id, | |
|                 'sync_mode': 'odoo_updated', | |
|                 'state': 'success', | |
|                 'count': update_success, | |
|             }) | |
|         # Returns updated count. | |
|         return update_success | |
| 
 | |
|     def action_export_deals(self): | |
|         """ Method for export deals from odoo to hubspot """ | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_deals = self.env['crm.lead'].search([]) | |
|         hubspot_deals = [] | |
|         success_count = 0 | |
|         for rec in api_client.crm.deals.get_all(): | |
|             hubspot_deals.append(rec.properties['hs_object_id']) | |
|         for rec in odoo_deals: | |
|             # If the deal present in odoo not available in hubspot | |
|             # creates it via api call. | |
|             if rec.hs_object_id not in hubspot_deals: | |
|                 properties = { | |
|                     "dealname": rec.name, | |
|                     "amount": rec.expected_revenue if rec.expected_revenue | |
|                     else None, | |
|                     "closedate": rec.date_deadline if rec.date_deadline else '', | |
|                     "createdate": rec.create_date.strftime( | |
|                         '%Y-%m-%dT%H:%M:%SZ') if rec.create_date else None, | |
|                 } | |
|                 # API call to create deals in hubspot. | |
|                 api_response = api_client.crm.deals.basic_api.create( | |
|                     simple_public_object_input_for_create= | |
|                     SimplePublicObjectInput(properties)) | |
|                 # If the record is created in hubspot then store the unique | |
|                 # hubspot id in deal record in odoo too. | |
|                 if api_response: | |
|                     rec.write({ | |
|                         'hs_object_id': api_response.properties['hs_object_id'], | |
|                         'sync_mode': 'export' | |
|                     }) | |
|                 success_count += 1 | |
|         self.deals_last_exported = datetime.now() | |
|         # If there is any record exported then creates history record | |
|         if success_count > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.deals_last_exported, | |
|                 'res_model_id': self.env.ref('crm.model_crm_lead').id, | |
|                 'sync_mode': 'export', | |
|                 'state': 'success', | |
|                 'count': success_count, | |
|             }) | |
|         # Returns the exported count. | |
|         return success_count | |
| 
 | |
|     def action_import_deals(self): | |
|         """ Method to import deals record from hubspot to odoo. """ | |
|         # Needed fields to fetch from hubspot. | |
|         needed_fields = [ | |
|             "dealname", "amount", "closedate" | |
|         ] | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_deals = self.env['crm.lead'].search([]).mapped('hs_object_id') | |
|         hubspot_deals = api_client.crm.deals.get_all(properties=needed_fields) | |
|         deals_to_create = [] | |
|         success_count = 0 | |
|         for rec in hubspot_deals: | |
|             # If hubspot record not present in odoo creates the record. | |
|             if rec.properties['hs_object_id'] not in odoo_deals: | |
|                 deals_to_create.append({ | |
|                     'name': rec.properties['dealname'] or 'Lead', | |
|                     'expected_revenue': rec.properties['amount'], | |
|                     'date_deadline': rec.properties['closedate'], | |
|                     'hs_object_id': rec.properties['hs_object_id'], | |
|                     'sync_mode': 'import', | |
|                 }) | |
|                 success_count += 1 | |
|         if deals_to_create: | |
|             self.env['crm.lead'].sudo().create(deals_to_create) | |
|         self.deals_last_imported = datetime.now() | |
|         # If create any records then creates the history for it. | |
|         if success_count > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.deals_last_imported, | |
|                 'res_model_id': self.env.ref('crm.model_crm_lead').id, | |
|                 'sync_mode': 'import', | |
|                 'state': 'success', | |
|                 'count': success_count, | |
|             }) | |
|         # Return the created records count. | |
|         return success_count | |
| 
 | |
|     def action_update_hub_deals(self): | |
|         """ Method for update hubspot record based on odoo record. """ | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_deal = self.env['crm.lead'].search([]) | |
|         odoo_deal_list = odoo_deal.mapped('hs_object_id') | |
|         hubspot_deal = api_client.crm.deals.get_all() | |
|         update_success = 0 | |
|         data_to_update = [] | |
|         for rec in hubspot_deal: | |
|             # If hubspot record present in odoo records then take the | |
|             # corresponding odoo record. | |
|             if rec.properties['hs_object_id'] in odoo_deal_list: | |
|                 odoo_record = self.env['crm.lead'].search( | |
|                     [('hs_object_id', '=', rec.properties['hs_object_id'])]) | |
|                 # If the odoo record is recently modified then update hubspot | |
|                 # record based on that. | |
|                 if odoo_record.write_date > rec.updated_at.astimezone( | |
|                         timezone.utc).replace(tzinfo=None): | |
|                     data_to_update.append({ | |
|                         'id': rec.properties['hs_object_id'], | |
|                         'properties': { | |
|                             "dealname": odoo_record.name, | |
|                             "amount": odoo_record.expected_revenue | |
|                             if odoo_record.expected_revenue else None, | |
|                             "closedate": odoo_record.date_deadline | |
|                             if odoo_record.date_deadline else '', | |
|                             "createdate": odoo_record.create_date.strftime( | |
|                                 '%Y-%m-%dT%H:%M:%SZ') if odoo_record.create_date | |
|                             else None, | |
|                         } | |
|                     }) | |
|                     update_success += 1 | |
|         api_client.crm.deals.batch_api.update( | |
|             batch_input_simple_public_object_batch_input= | |
|             BatchInputSimplePublicObjectBatchInput(data_to_update)) | |
|         self.hub_deal_last_updated = datetime.now() | |
|         # Creates history record when any deal updated. | |
|         if update_success > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.hub_deal_last_updated, | |
|                 'res_model_id': self.env.ref('crm.model_crm_lead').id, | |
|                 'sync_mode': 'hub_updated', | |
|                 'state': 'success', | |
|                 'count': update_success, | |
|             }) | |
|         # Returns the updated count. | |
|         return update_success | |
| 
 | |
|     def action_update_odoo_deals(self): | |
|         """ Method to update odoo leads based on hubspot records. """ | |
|         api_client = HubSpot(access_token=self.access_key) | |
|         odoo_deal = self.env['crm.lead'].search([]) | |
|         # Needed field to fetch from hubspot. | |
|         needed_fields = ["dealname", "hs_object_id", "amount", "closedate"] | |
|         hubspot_deal = api_client.crm.deals.get_all( | |
|             properties=needed_fields) | |
|         hubspot_deal_list = [rec.properties['hs_object_id'] | |
|                              for rec in hubspot_deal] | |
|         update_success = 0 | |
|         for rec in odoo_deal: | |
|             # If odoo record present in hubspot record, take the hubspot record. | |
|             if rec.hs_object_id in hubspot_deal_list: | |
|                 hubspot_deal_dict = {h.id: h for h in hubspot_deal} | |
|                 hub_record = hubspot_deal_dict.get(rec.hs_object_id, None) | |
|                 # If the hubspot record is recently modified then | |
|                 # update odoo record based on that. | |
|                 if hub_record.updated_at.astimezone(timezone.utc).replace( | |
|                         tzinfo=None) > rec.write_date: | |
|                     data_to_update = { | |
|                         'name': hub_record.properties['dealname'] or 'Lead', | |
|                         'expected_revenue': hub_record.properties['amount'], | |
|                         'date_deadline': hub_record.properties['closedate'], | |
|                     } | |
|                     update_success += 1 | |
|                     rec.write(data_to_update) | |
|         self.odoo_deal_last_updated = datetime.now() | |
|         # Creates history record based on updated records count. | |
|         if update_success > 0: | |
|             self.env['hubspot.sync.history'].sudo().create({ | |
|                 'date': self.odoo_deal_last_updated, | |
|                 'res_model_id': self.env.ref('crm.model_crm_lead').id, | |
|                 'sync_mode': 'odoo_updated', | |
|                 'state': 'success', | |
|                 'count': update_success, | |
|             }) | |
|         # returns the updated count. | |
|         return update_success
 | |
| 
 |