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.
 
 
 
 
 

279 lines
13 KiB

# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
import json
import requests
from odoo import models, fields
from odoo.exceptions import ValidationError
class MailerCloudApiSync(models.Model):
"""
Model representing the synchronization configuration for Mailercloud API.
This model stores information about the Mailercloud API synchronization, including the API key,
synchronization status, user details, plan information, associated mailing list, contact mappings,
and synchronization activity.
"""
_name = 'mailer.cloud.api.sync'
_description = 'Mail Cloud API'
api_key = fields.Char(
string='Api Key',
required=True,
help='API key for connecting to Mailercloud.')
active = fields.Boolean(
string='Active',
help='Check to activate the Mailercloud API synchronization.')
email = fields.Char(
string='Email',
help='Email associated with the Mailercloud API user.')
name = fields.Char(
string="Name",
help='Name associated with the Mailercloud API user.')
plan = fields.Char(
string='Plan',
help='Current plan of the Mailercloud API user.')
remaining_contacts = fields.Integer(
string='Remaining Contacts',
help='Remaining contact quota in the Mailercloud API user\'s plan.')
total_contacts = fields.Integer(
string='Total Contacts',
help='Total contact quota in the Mailercloud API user\'s plan.')
used_contacts = fields.Integer(
string='Used Contacts',
help='Number of contacts used in the Mailercloud API user\'s plan.')
list_id = fields.Many2one(
'mailer.cloud.list', string='Mailing List',
help='Default mailing list associated with the Mailercloud API user.')
contact_mapping_ids = fields.One2many(
'contact.sync', 'sync_id', string='Contact Mapping Ids',
help='Mappings between Odoo contact fields and Mailercloud properties for synchronization.')
contact_sync_active = fields.Boolean(string='Contact Sync Active',
help='Check to activate contact synchronization with Mailercloud.')
contact_sync_time = fields.Datetime(string='Contact Sync time',
help='Timestamp of the last contact synchronization activity.')
def action_sync(self):
"""
Test connection to Mailercloud API and synchronize information.
This function tests the connection to the Mailercloud API and retrieves information
about the API user's plan. It updates the relevant fields in the current record and triggers
synchronization of lists and properties associated with the API user.
:raises: ValidationError if there is an issue with the API connection or synchronization process.
"""
self.write({'contact_mapping_ids': [(5, 0, 0)]})
try:
url = "https://cloudapi.mailercloud.com/v1/client/plan"
payload = ""
headers = {
'Authorization': self.api_key,
'Content-Type': 'application/json'
}
response = requests.request("GET", url, headers=headers, data=payload)
if response.status_code == 200:
self.write({
'email': response.json()['data']['email'],
'name': response.json()['data']['name'],
'plan': response.json()['data']['plan'],
'remaining_contacts': response.json()['data'][
'remaining_contacts'],
'total_contacts': response.json()['data'][
'total_contacts'],
'used_contacts': response.json()['data']['used_contacts'],
'active': True,
'contact_mapping_ids':
[(0, 0, {'property_id': self.env.ref(
'mailer_cloud_connector.property_data_name').id,
'contact_fields': 'name'}),
(0, 0, {'property_id': self.env.ref(
'mailer_cloud_connector.property_data_email').id,
'contact_fields': 'email'})]
})
self.get_list(self.id)
self.get_properties()
else:
raise ValidationError(response.json()['errors'][0]['message'])
except Exception as e:
raise ValidationError(e)
def get_list(self, user):
"""
Retrieve Mailercloud lists associated with the current API user.
This function sends a request to the Mailercloud API to retrieve lists related to the
current API's authorization. It processes the response and creates records in the 'mailer.cloud.list'
model in Odoo.
:param user: The authorization user associated with the lists.
:raises: ValidationError if there is an issue with the retrieval or record creation process.
"""
self.env['mailer.cloud.list'].search([]).unlink()
try:
url = "https://cloudapi.mailercloud.com/v1/lists/search"
payload = json.dumps({
"limit": 100,
"list_type": 1,
"page": 1,
"search_name": "",
"sort_field": "name",
"sort_order": "asc"
})
headers = {
'Authorization': self.api_key,
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
if response.status_code == 200:
for rec in response.json()['data']:
self.env['mailer.cloud.list'].create({
'name': rec['name'],
'mailer_cloud': rec['id'],
'authorization_id': user,
})
elif response.status_code == 400:
raise ValidationError(response.json()['error']['message'])
elif response.status_code == 401:
raise ValidationError(response.json()['errors'][0]['message'])
except Exception as e:
raise ValidationError(e)
def get_properties(self):
"""
Retrieve Mailercloud contact properties associated with the current API.
This function sends a request to the Mailercloud API to retrieve contact properties
related to the current API's authorization. It processes the response and inserts
new properties into the 'mailer.cloud.properties' model in Odoo.
:raises: ValidationError if there is an issue with the retrieval or insertion process.
"""
try:
url = "https://cloudapi.mailercloud.com/v1/contact/property/search"
payload = json.dumps({
"limit": 100,
"page": 1,
"search": ""
})
headers = {
'Authorization': self.api_key,
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
if response.status_code == 200:
for record in response.json()['data']:
if record['field_value'] not in self.env['mailer.cloud.properties'].search(
[('authorization_id', '=', False)]).mapped('name'):
if record['field_type'] == 'Text':
type_name = 'text'
elif record['field_type'] == 'Number':
type_name = 'number'
elif record['field_type'] == 'Date':
type_name = 'date'
elif record['field_type'] == 'Textarea':
type_name = 'textarea'
self.env.cr.execute("""INSERT INTO mailer_cloud_properties(
mailer_cloud,name,type,authorization_id)VALUES('%s','%s','%s',%s)""" % (
record['id'], record['field_value'], type_name, self.id))
elif response.status_code == 400:
raise ValidationError(response.json()['error']['message'])
elif response.status_code == 401:
raise ValidationError(response.json()['errors'][0]['message'])
except Exception as e:
raise ValidationError(e)
def action_contact_sync(self):
"""
Synchronize contacts with Mailercloud.
This function synchronizes contacts from Odoo's 'res.partner' model to Mailercloud.
It constructs the contact details and sends a batch request to the Mailercloud
API for contact synchronization.
:raises: ValidationError if there is an issue with the synchronization process.
"""
if self.list_id:
try:
contact_details = []
contact_details.clear()
res = self.env['res.partner'].search([], limit=50)
for j in res:
contact_details_dict = {}
contact_details_dict.clear()
for i in range(
len(self.contact_mapping_ids.mapped(
'property_id.name'))):
if self.env['mailer.cloud.properties'].search(
[('id', '=',
self.contact_mapping_ids.mapped(
'property_id')[
i].id)]).mailer_cloud:
contact_details_dict['custom_fields'] = {
self.contact_mapping_ids.mapped(
'property_id.mailer_cloud')[i]: self.env['res.partner'].search_read(
[('id', '=', j.id)], [self.contact_mapping_ids.mapped('contact_fields')[i]])[0][
self.contact_mapping_ids.mapped(
'contact_fields')[i]] or ' '}
for key, value in contact_details_dict['custom_fields'].items():
if isinstance(value, float):
contact_details_dict[
'custom_fields'].update(
{key: round(value)})
else:
contact_details_dict[
self.contact_mapping_ids.mapped(
'property_id.name')[
i]] = self.env['res.partner'].search_read(
[('id', '=', j.id)], [
self.contact_mapping_ids.mapped(
'contact_fields')[i]])[0][
self.contact_mapping_ids.mapped(
'contact_fields')[i]] or ' '
for key, value in contact_details_dict.items():
if isinstance(value, float):
contact_details_dict.update({key: round(value)})
contact_details.append(contact_details_dict)
url = "https://cloudapi.mailercloud.com/v1/contacts/batch"
payload = json.dumps({
"contacts": contact_details,
"list_id": self.list_id.mailer_cloud
})
headers = {
'Authorization': self.api_key,
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
if response.status_code == 200:
self.write({
'contact_sync_active': True,
'contact_sync_time': fields.Datetime.now()
})
elif response.status_code == 400:
raise ValidationError(response.json()['errors']['message'])
elif response.status_code == 401:
raise ValidationError(
response.json()['errors'][0]['message'])
except Exception as e:
raise ValidationError(e)
else:
raise ValidationError("Please Choose a List")