542 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			542 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Python
		
	
	
| import logging
 | ||
| import hashlib
 | ||
| from datetime import datetime
 | ||
| 
 | ||
| _logger = logging.getLogger(__name__)
 | ||
| from odoo import api, fields, models, _
 | ||
| from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
 | ||
| 
 | ||
| EMAIL_PATTERN = '([^ ,;<@]+@[^> ,;]+)'
 | ||
| unwanted_data = ['_links', 'modules']
 | ||
| replacement_of_key = [('id', 'list_id')]
 | ||
| DATE_CONVERSION = ['date_created', 'last_sub_date', 'last_unsub_date', 'campaign_last_sent']
 | ||
| 
 | ||
| NOT_REQUIRED_ON_UPDATE = ['color', 'list_id', 'web_id', 'from_name', 'from_email', 'subject', 'partner_id',
 | ||
|                           'account_id',
 | ||
|                           'date_created', 'list_rating',
 | ||
|                           'subscribe_url_short', 'subscribe_url_long', 'beamer_address', 'id', 'display_name',
 | ||
|                           'create_uid', 'create_date', 'write_uid', 'write_date', '__last_update', '__last_update',
 | ||
|                           'statistics_ids', 'stats_overview_ids', 'stats_audience_perf_ids', 'stats_campaign_perf_ids',
 | ||
|                           'stats_since_last_campaign_ids', 'lang_id', 'odoo_list_id', 'last_create_update_date',
 | ||
|                           'is_update_required', 'contact_ids', 'subscription_contact_ids', 'mailchimp_list_id']
 | ||
| 
 | ||
| 
 | ||
| class MassMailingList(models.Model):
 | ||
|     _inherit = "mail.mass_mailing.list"
 | ||
| 
 | ||
|     def _compute_contact_nbr(self):
 | ||
|         self.env.cr.execute('''
 | ||
|             select
 | ||
|                 list_id, count(*)
 | ||
|             from
 | ||
|                 mail_mass_mailing_contact_list_rel r
 | ||
|                 left join mail_mass_mailing_contact c on (r.contact_id=c.id)
 | ||
|             where
 | ||
|                 c.opt_out <> true
 | ||
|                 AND c.is_email_valid = TRUE  
 | ||
|                 AND c.email IS NOT NULL              
 | ||
|             group by
 | ||
|                 list_id
 | ||
|         ''')
 | ||
|         data = dict(self.env.cr.fetchall())
 | ||
|         for mailing_list in self:
 | ||
|             mailing_list.contact_nbr = data.get(mailing_list.id, 0)
 | ||
| 
 | ||
|     contact_nbr = fields.Integer(compute="_compute_contact_nbr", string='Number of Contacts')
 | ||
| 
 | ||
| 
 | ||
| class MailChimpLists(models.Model):
 | ||
|     _name = "mailchimp.lists"
 | ||
|     _inherits = {'mail.mass_mailing.list': 'odoo_list_id'}
 | ||
|     _description = "MailChimp Audience"
 | ||
| 
 | ||
|     def _compute_contact_unsub_nbr(self):
 | ||
|         self.env.cr.execute('''
 | ||
|             select
 | ||
|                 list_id, count(*)
 | ||
|             from
 | ||
|                 mail_mass_mailing_contact_list_rel r
 | ||
|                 left join mail_mass_mailing_contact c on (r.contact_id=c.id)
 | ||
|             where
 | ||
|                 COALESCE(c.opt_out,TRUE) = TRUE AND
 | ||
|                 COALESCE(c.is_email_valid,TRUE) = TRUE
 | ||
|                 AND c.email IS NOT NULL
 | ||
|             group by
 | ||
|                 list_id
 | ||
|         ''')
 | ||
|         data = dict(self.env.cr.fetchall())
 | ||
|         for mailing_list in self:
 | ||
|             mailing_list.contact_unsub_nbr = data.get(mailing_list.odoo_list_id.id, 0)
 | ||
| 
 | ||
|     def _compute_contact_cleaned_nbr(self):
 | ||
|         self.env.cr.execute('''
 | ||
|             select
 | ||
|                 list_id, count(*)
 | ||
|             from
 | ||
|                 mail_mass_mailing_contact_list_rel r
 | ||
|                 left join mail_mass_mailing_contact c on (r.contact_id=c.id)
 | ||
|             where
 | ||
|                 COALESCE(c.is_email_valid,FALSE) = FALSE
 | ||
|                 AND c.email IS NOT NULL
 | ||
|             group by
 | ||
|                 list_id
 | ||
|         ''')
 | ||
|         data = dict(self.env.cr.fetchall())
 | ||
|         for mailing_list in self:
 | ||
|             mailing_list.contact_cleaned_nbr = data.get(mailing_list.odoo_list_id.id, 0)
 | ||
| 
 | ||
|     def _compute_contact_total_nbr(self):
 | ||
|         self.env.cr.execute('''
 | ||
|             select
 | ||
|                 list_id, count(*)
 | ||
|             from
 | ||
|                 mail_mass_mailing_contact_list_rel r
 | ||
|                 left join mail_mass_mailing_contact c on (r.contact_id=c.id)
 | ||
|             where
 | ||
|                 c.email IS NOT NULL
 | ||
|             group by
 | ||
|                 list_id
 | ||
|         ''')
 | ||
|         data = dict(self.env.cr.fetchall())
 | ||
|         for mailing_list in self:
 | ||
|             mailing_list.contact_total_nbr = data.get(mailing_list.odoo_list_id.id, 0)
 | ||
| 
 | ||
|     def _is_update_required(self):
 | ||
|         for record in self:
 | ||
|             if record.write_date and record.last_create_update_date and record.write_date > record.last_create_update_date:
 | ||
|                 record.is_update_required = True
 | ||
|             else:
 | ||
|                 record.is_update_required = False
 | ||
| 
 | ||
|     # name = fields.Char("Name", required=True, help="This is how the list will be named in MailChimp.")
 | ||
|     color = fields.Integer('Color Index', default=0)
 | ||
|     list_id = fields.Char("Audience ID", copy=False, readonly=True)
 | ||
|     web_id = fields.Char("Website Identification", readonly=True)
 | ||
|     partner_id = fields.Many2one('res.partner', string="Contact", ondelete='restrict')
 | ||
|     permission_reminder = fields.Text("Permission Reminder", help="Remind recipients how they signed up to your list.")
 | ||
|     use_archive_bar = fields.Boolean("Use Archive Bar",
 | ||
|                                      help="Whether campaigns for this list use the Archive Bar in archives by default.")
 | ||
| 
 | ||
|     notify_on_subscribe = fields.Char("Email Subscribe Notifications To",
 | ||
|                                       help="The email address to send subscribe notifications to. \n Additional email addresses must be separated by a comma.")
 | ||
|     notify_on_unsubscribe = fields.Char("Email Unsubscribe Notifications To",
 | ||
|                                         help="The email address to send unsubscribe notifications to. \n Additional email addresses must be separated by a comma.")
 | ||
|     date_created = fields.Datetime("Creation Date", readonly=True)
 | ||
|     list_rating = fields.Selection([('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5')],
 | ||
|                                    "List Rating")
 | ||
|     email_type_option = fields.Boolean("Let users pick plain-text or HTML emails.",
 | ||
|                                        help="Whether the list suports multiple formats for emails. When set to true, subscribers can choose whether they want to receive HTML or plain-text emails. When set to false, subscribers will receive HTML emails, with a plain-text alternative backup.")
 | ||
|     subscribe_url_short = fields.Char("Subscribe URL Short", readonly=True)
 | ||
|     subscribe_url_long = fields.Char("Subscribe URL Long", readonly=True,
 | ||
|                                      help="The full version of this list’s subscribe form (host will vary).")
 | ||
|     beamer_address = fields.Char("Beamer Address", readonly=True)
 | ||
|     visibility = fields.Selection([('pub', 'Yes. My campaigns are public, and I want them to be discovered.'),
 | ||
|                                    ('prv', 'No, my campaigns for this list are not public.')],
 | ||
|                                   help="Whether this list is public or private.")
 | ||
|     double_optin = fields.Boolean("Enable double opt-in",
 | ||
|                                   help="Whether or not to require the subscriber to confirm subscription via email.")
 | ||
|     has_welcome = fields.Boolean("Send a Final Welcome Email",
 | ||
|                                  help="Whether or not this list has a welcome automation connected. Welcome Automations: welcomeSeries, singleWelcome, emailFollowup.")
 | ||
|     marketing_permissions = fields.Boolean("Enable GDPR fields",
 | ||
|                                            help="Whether or not the list has marketing permissions (eg. GDPR) enabled.")
 | ||
|     from_name = fields.Char("Default From Name", required=True)
 | ||
|     from_email = fields.Char("Default From Email Address", required=True)
 | ||
|     subject = fields.Char("Default Email Subject")
 | ||
|     lang_id = fields.Many2one('res.lang', string="Language")
 | ||
| 
 | ||
|     odoo_list_id = fields.Many2one('mail.mass_mailing.list', string='Odoo Mailing List', required=True,
 | ||
|                                    ondelete="cascade")
 | ||
|     contact_unsub_nbr = fields.Integer(compute="_compute_contact_unsub_nbr", string='Number of Unsubscribed Contacts')
 | ||
|     contact_cleaned_nbr = fields.Integer(compute="_compute_contact_cleaned_nbr", string='Number of Cleaned Contacts')
 | ||
|     contact_total_nbr = fields.Integer(compute="_compute_contact_total_nbr", string='Number of Total Contacts')
 | ||
|     statistics_ids = fields.One2many('mailchimp.lists.stats', 'list_id', string="Statistics",
 | ||
|                                      help="Stats for the list. Many of these are cached for at least five minutes.")
 | ||
|     stats_overview_ids = fields.One2many('mailchimp.lists.stats', 'list_id', string="Statistics",
 | ||
|                                          help="Stats for the list. Many of these are cached for at least five minutes.")
 | ||
|     stats_audience_perf_ids = fields.One2many('mailchimp.lists.stats', 'list_id', string="Statistics",
 | ||
|                                               help="Stats for the list. Many of these are cached for at least five minutes.")
 | ||
|     stats_campaign_perf_ids = fields.One2many('mailchimp.lists.stats', 'list_id', string="Statistics",
 | ||
|                                               help="Stats for the list. Many of these are cached for at least five minutes.")
 | ||
|     stats_since_last_campaign_ids = fields.One2many('mailchimp.lists.stats', 'list_id', string="Statistics",
 | ||
|                                                     help="Stats for the list. Many of these are cached for at least five minutes.")
 | ||
|     account_id = fields.Many2one("mailchimp.accounts", string="Account", required=True)
 | ||
|     last_create_update_date = fields.Datetime("Last Create Update")
 | ||
|     write_date = fields.Datetime('Update on', index=True, readonly=True)
 | ||
|     is_update_required = fields.Boolean("Update Required?", compute="_is_update_required")
 | ||
|     member_since_last_changed = fields.Datetime("Fetch Member Since Last Change", copy=False)
 | ||
|     segment_ids = fields.One2many("mailchimp.segments", 'list_id', string="Segments", copy=False)
 | ||
|     merge_field_ids = fields.One2many("mailchimp.merge.fields", 'list_id', string="Merge Fields", copy=False)
 | ||
| 
 | ||
|     @api.multi
 | ||
|     def unlink(self):
 | ||
|         odoo_lists = self.mapped('odoo_list_id')
 | ||
|         super(MailChimpLists, self).unlink()
 | ||
|         return odoo_lists.unlink()
 | ||
| 
 | ||
|     def action_view_recipients(self):
 | ||
|         action = self.env.ref('mass_mailing.action_view_mass_mailing_contacts_from_list').read()[0]
 | ||
|         action['domain'] = [('list_ids', 'in', self.odoo_list_id.ids)]
 | ||
|         ctx = {'default_list_ids': [self.odoo_list_id.id]}
 | ||
|         if self.env.context.get('show_total', False):
 | ||
|             action['context'] = ctx
 | ||
|         if self.env.context.get('show_sub', False):
 | ||
|             ctx.update({'search_default_not_opt_out': 1})
 | ||
|             action['context'] = ctx
 | ||
|         if self.env.context.get('show_unsub', False):
 | ||
|             ctx.update({'search_default_unsub_contact': 1})
 | ||
|             action['context'] = ctx
 | ||
|         if self.env.context.get('show_cleaned', False):
 | ||
|             ctx.update({'search_default_cleaned_contact': 1})
 | ||
|             action['context'] = ctx
 | ||
|         return action
 | ||
| 
 | ||
|     @api.model
 | ||
|     def _prepare_vals_for_update(self):
 | ||
|         self.ensure_one()
 | ||
|         prepared_vals = {}
 | ||
|         for field_name in self.fields_get_keys():
 | ||
|             if hasattr(self, field_name) and field_name not in NOT_REQUIRED_ON_UPDATE:
 | ||
|                 prepared_vals.update({field_name: getattr(self, field_name)})
 | ||
|         partner_id = self.partner_id
 | ||
|         prepared_vals['contact'] = {'company': partner_id.name, 'address1': partner_id.street,
 | ||
|                                     'address2': partner_id.street2, 'city': partner_id.city,
 | ||
|                                     'state': partner_id.state_id.name or '', 'zip': partner_id.zip,
 | ||
|                                     'country': partner_id.country_id.code, 'phone': partner_id.phone}
 | ||
|         prepared_vals['campaign_defaults'] = {'from_name': self.from_name, 'from_email': self.from_email,
 | ||
|                                               'subject': self.subject or '', 'language': self.lang_id.iso_code or ''}
 | ||
|         return prepared_vals
 | ||
| 
 | ||
|     @api.multi
 | ||
|     def export_in_mailchimp(self):
 | ||
|         for list in self:
 | ||
|             prepared_vals = list._prepare_vals_for_update()
 | ||
|             response = list.account_id._send_request('lists', prepared_vals, method='POST')
 | ||
|         return True
 | ||
| 
 | ||
|     @api.multi
 | ||
|     def update_in_mailchimp(self):
 | ||
|         for list in self:
 | ||
|             prepared_vals = list._prepare_vals_for_update()
 | ||
|             response = list.account_id._send_request('lists/%s' % list.list_id, prepared_vals, method='PATCH')
 | ||
|             list.write({'last_create_update_date': fields.Datetime.now()})
 | ||
|         return True
 | ||
| 
 | ||
|     @api.model
 | ||
|     def _find_partner(self, location):
 | ||
|         partners = self.env['res.partner']
 | ||
|         state = self.env['res.country.state']
 | ||
|         domain = []
 | ||
|         if 'address1' in location and 'city' in location and 'company' in location:
 | ||
|             domain.append(('name', '=', location['company']))
 | ||
|             domain.append(('street', '=', location['address1']))
 | ||
|             domain.append(('city', '=', location['city']))
 | ||
|             if location.get('state'):
 | ||
|                 domain.append(('state_id.name', '=', location['state']))
 | ||
|             if location.get('zip'):
 | ||
|                 domain.append(('zip', '=', location['zip']))
 | ||
|             partners = partners.search(domain, limit=1)
 | ||
|         if not partners:
 | ||
|             country_id = self.env['res.country'].search([('code', '=', location['country'])], limit=1)
 | ||
|             if country_id and location['state']:
 | ||
|                 state = self.env['res.country.state'].search(
 | ||
|                     ['|', ('name', '=', location['state']), ('code', '=', location['state']),
 | ||
|                      ('country_id', '=', country_id.id)], limit=1)
 | ||
|             elif location['state']:
 | ||
|                 state = self.env['res.country.state'].search(
 | ||
|                     ['|', ('name', '=', location['state']), ('code', '=', location['state'])],
 | ||
|                     limit=1)
 | ||
|             location.update({'name': location.pop('company'), 'street': location.pop('address1'),
 | ||
|                              'street2': location.pop('address2'), 'state_id': state.id, 'country_id': country_id.id})
 | ||
|             partners = partners.create(location)
 | ||
|         return partners
 | ||
| 
 | ||
|     @api.multi
 | ||
|     def create_or_update_list(self, values_dict, account=False):
 | ||
|         list_id = values_dict.get('id')
 | ||
|         existing_list = self.search([('list_id', '=', list_id)])
 | ||
|         stats = values_dict.pop('stats', {})
 | ||
|         values_dict.update(values_dict.pop('campaign_defaults'))
 | ||
|         lang_id = self.env['res.lang'].search([('iso_code', '=', values_dict.get('language', 'en'))])
 | ||
|         for item in unwanted_data:
 | ||
|             values_dict.pop(item)
 | ||
|         for old_key, new_key in replacement_of_key:
 | ||
|             values_dict[new_key] = values_dict.pop(old_key)
 | ||
|         for item in DATE_CONVERSION:
 | ||
|             if values_dict.get(item, False) == '':
 | ||
|                 values_dict[item] = False
 | ||
|             if values_dict.get(item, False):
 | ||
|                 values_dict[item] = account.covert_date(values_dict.get(item))
 | ||
|         values_dict.update({'account_id': account.id})
 | ||
|         partner = self._find_partner(values_dict.pop('contact'))
 | ||
|         values_dict.update(
 | ||
|             {'partner_id': partner.id, 'lang_id': lang_id.id, 'list_rating': str(values_dict.pop('list_rating', '0'))})
 | ||
|         if not existing_list:
 | ||
|             existing_list = self.create(values_dict)
 | ||
|         else:
 | ||
|             existing_list.write(values_dict)
 | ||
|         existing_list.create_or_update_statistics(stats)
 | ||
|         # existing_list.fetch_members()
 | ||
|         existing_list.fetch_segments()
 | ||
|         existing_list.fetch_merge_fields()
 | ||
|         existing_list.write({'last_create_update_date': fields.Datetime.now()})
 | ||
|         return True
 | ||
| 
 | ||
|     @api.multi
 | ||
|     def import_lists(self, account=False):
 | ||
|         if not account:
 | ||
|             raise Warning("MailChimp Account not defined to import lists")
 | ||
|         response = account._send_request('lists', {}, method='GET')
 | ||
|         for list in response.get('lists'):
 | ||
|             self.create_or_update_list(list, account=account)
 | ||
|         return True
 | ||
| 
 | ||
|     @api.one
 | ||
|     def refresh_list(self):
 | ||
|         if not self.account_id:
 | ||
|             raise Warning("MailChimp Account not defined to Refresh list")
 | ||
|         response = self.account_id._send_request('lists/%s' % self.list_id, {})
 | ||
|         self.create_or_update_list(response, account=self.account_id)
 | ||
|         return True
 | ||
| 
 | ||
|     @api.multi
 | ||
|     def create_or_update_statistics(self, stats):
 | ||
|         self.ensure_one()
 | ||
|         self.statistics_ids.unlink()
 | ||
|         for item in DATE_CONVERSION:
 | ||
|             if stats.get(item, False):
 | ||
|                 stats[item] = self.account_id.covert_date(stats.get(item))
 | ||
|             else:
 | ||
|                 stats[item] = False
 | ||
|         self.write({'statistics_ids': [(0, 0, stats)]})
 | ||
|         return True
 | ||
| 
 | ||
|     @api.one
 | ||
|     def fetch_merge_fields(self):
 | ||
|         mailchimp_merge_field_obj = self.env['mailchimp.merge.fields']
 | ||
|         if not self.account_id:
 | ||
|             raise Warning("MailChimp Account not defined to Fetch Merge Field list")
 | ||
|         count = 1000
 | ||
|         offset = 0
 | ||
|         merge_field_list = []
 | ||
|         prepared_vals = {}
 | ||
|         while True:
 | ||
|             prepared_vals.update({'count': count, 'offset': offset,
 | ||
|                                   'fields': 'merge_fields.merge_id,merge_fields.tag,merge_fields.name,merge_fields.type,merge_fields.required,merge_fields.default_value,merge_fields.public,merge_fields.display_order,merge_fields.list_id,merge_fields.options'})
 | ||
|             response = self.account_id._send_request('lists/%s/merge-fields' % self.list_id, {}, params=prepared_vals)
 | ||
|             if len(response.get('merge_fields')) == 0:
 | ||
|                 break
 | ||
|             if isinstance(response.get('merge_fields'), dict):
 | ||
|                 merge_field_list = [response.get('merge_fields')]
 | ||
|             else:
 | ||
|                 merge_field_list += response.get('merge_fields')
 | ||
|             offset = offset + 1000
 | ||
|         for merge_field in merge_field_list:
 | ||
|             if not merge_field.get('merge_id', False):
 | ||
|                 continue
 | ||
|             merge_field_id = mailchimp_merge_field_obj.search([('merge_id', '=', merge_field.get('merge_id')), ('list_id', '=', self.id)])
 | ||
|             merge_field.update({'list_id': self.id})
 | ||
|             if merge_field.get('options', {}).get('date_format'):
 | ||
|                 date_format = merge_field.pop('options', {}).get('date_format')
 | ||
|                 date_format = date_format.replace("MM", '%m')
 | ||
|                 date_format = date_format.replace("DD", '%d')
 | ||
|                 date_format = date_format.replace("YYYY", '%Y')
 | ||
|                 merge_field.update({'date_format': date_format})
 | ||
|             if not merge_field_id:
 | ||
|                 mailchimp_merge_field_obj.create(merge_field)
 | ||
|             if merge_field_id:
 | ||
|                 merge_field_id.write(merge_field)
 | ||
|         return merge_field_list
 | ||
| 
 | ||
|     @api.one
 | ||
|     def fetch_segments(self):
 | ||
|         mailchimp_segments_obj = self.env['mailchimp.segments']
 | ||
|         if not self.account_id:
 | ||
|             raise Warning("MailChimp Account not defined to Fetch Segments list")
 | ||
|         count = 1000
 | ||
|         offset = 0
 | ||
|         segments_list = []
 | ||
|         prepared_vals = {}
 | ||
|         while True:
 | ||
|             prepared_vals.update({'count': count, 'offset': offset})
 | ||
|             response = self.account_id._send_request('lists/%s/segments' % self.list_id, {}, params=prepared_vals)
 | ||
|             if len(response.get('segments')) == 0:
 | ||
|                 break
 | ||
|             if isinstance(response.get('segments'), dict):
 | ||
|                 segments_list = [response.get('segments')]
 | ||
|             else:
 | ||
|                 segments_list += response.get('segments')
 | ||
|             offset = offset + 1000
 | ||
|         for segment in segments_list:
 | ||
|             if not segment.get('id', False):
 | ||
|                 continue
 | ||
|             segment_id = mailchimp_segments_obj.search([('mailchimp_id', '=', segment.get('id'))])
 | ||
|             name = segment.get('name')
 | ||
|             if segment.get('type') == 'static':
 | ||
|                 name = "Tags : %s" % name
 | ||
|             vals = {'mailchimp_id': segment.get('id'), 'name': name, 'list_id': self.id}
 | ||
|             if not segment_id:
 | ||
|                 mailchimp_segments_obj.create(vals)
 | ||
|             if segment_id:
 | ||
|                 segment_id.write(vals)
 | ||
|         return segments_list
 | ||
| 
 | ||
|     def _prepare_vals_for_to_create_partner(self, merge_field_vals):
 | ||
|         prepared_vals = {}
 | ||
|         for custom_field in self.merge_field_ids:
 | ||
|             if custom_field.type == 'address':
 | ||
|                 address_dict = merge_field_vals.get(custom_field.tag)
 | ||
|                 if not address_dict:
 | ||
|                     continue
 | ||
|                 state_id = False
 | ||
|                 country = self.env['res.country'].search([('code', '=', address_dict.get('country', ''))], limit=1)
 | ||
|                 if country:
 | ||
|                     state_id = self.env['res.country.state'].search(
 | ||
|                         ['|', ('name', '=', address_dict['state']),
 | ||
|                          ('code', '=', address_dict['state']),
 | ||
|                          ('country_id', '=', country.id)], limit=1)
 | ||
|                 prepared_vals.update({
 | ||
|                     'street': address_dict.get('addr1', ''),
 | ||
|                     'street2': address_dict.get('addr2', ''),
 | ||
|                     'city': address_dict.get('city', ''),
 | ||
|                     'zip': address_dict.get('zip', ''),
 | ||
|                     'state_id': state_id.id if state_id else False,
 | ||
|                     'country_id': country.id,
 | ||
|                 })
 | ||
|             elif custom_field.tag in ['FNAME', 'LNAME'] and not prepared_vals.get('name', False):
 | ||
|                 prepared_vals.update({'name': "%s %s" % (merge_field_vals.get('FNAME'), merge_field_vals.get('LNAME'))})
 | ||
|             elif custom_field.field_id and custom_field.type in ['date', 'birthday']:
 | ||
|                 value = merge_field_vals.get(custom_field.tag)
 | ||
|                 if value and custom_field.field_id.ttype in ['date']:
 | ||
|                     if len(value.split('/')) > 1:
 | ||
|                         value = datetime.strptime(value, custom_field.date_format).strftime(DEFAULT_SERVER_DATE_FORMAT)
 | ||
|                 prepared_vals.update({custom_field.field_id.name: value or False})
 | ||
|             elif custom_field.field_id:
 | ||
|                 prepared_vals.update({custom_field.field_id.name: merge_field_vals.get(custom_field.tag)})
 | ||
|         return prepared_vals
 | ||
| 
 | ||
|     @api.one
 | ||
|     def fetch_members(self):
 | ||
|         mailing_contact_obj = self.env['mail.mass_mailing.contact']
 | ||
|         state = self.env['res.country.state']
 | ||
|         country = self.env['res.country']
 | ||
|         if not self.account_id:
 | ||
|             raise Warning("MailChimp Account not defined to Fetch Member list")
 | ||
|         if not self.merge_field_ids:
 | ||
|             return True
 | ||
|         count = 1000
 | ||
|         offset = 0
 | ||
|         members_list = []
 | ||
|         members_list_to_create = []
 | ||
|         prepared_vals = {}
 | ||
|         if self.member_since_last_changed:
 | ||
|             prepared_vals.update({'since_last_changed': datetime.strptime(self.member_since_last_changed, DEFAULT_SERVER_DATETIME_FORMAT).strftime("%Y-%m-%dT%H:%M:%S+00:00")})
 | ||
|         while True:
 | ||
|             prepared_vals.update({'count': count, 'offset': offset, 'fields': 'members.email_address,members.merge_fields,members.tags,members.web_id,members.status'})
 | ||
|             response = self.account_id._send_request('lists/%s/members' % self.list_id, {}, params=prepared_vals)
 | ||
|             if len(response.get('members')) == 0:
 | ||
|                 break
 | ||
|             # if isinstance(response.get('members'), dict):
 | ||
|             #     members_list += [response.get('members')]
 | ||
|             if isinstance(response.get('members'), dict):
 | ||
|                 members_data = [response.get('members')]
 | ||
|             else:
 | ||
|                 members_data = response.get('members')
 | ||
|             offset = offset + 1000
 | ||
|             for member in members_data:
 | ||
|                 if not member.get('email_address', False):
 | ||
|                     continue
 | ||
|                 update_partner_required = True
 | ||
|                 contact_id = mailing_contact_obj.search([('email', '=', member.get('email_address'))])
 | ||
|                 create_vals = member.get('merge_fields')
 | ||
|                 prepared_vals_for_create_partner = self._prepare_vals_for_to_create_partner(create_vals)
 | ||
|                 name = "%s %s" % (create_vals.pop('FNAME'), create_vals.pop('LNAME'))
 | ||
|                 tag_ids = self.env['res.partner.category']
 | ||
|                 tag_list = member.get('tags')
 | ||
|                 if tag_list:
 | ||
|                     tag_ids = self.env['res.partner.category'].create_or_update_tags(tag_list)
 | ||
|                 prepared_vals_for_create_partner.update({'category_id': [(6, 0, tag_ids.ids)]})
 | ||
|                 if not contact_id:
 | ||
|                     if not self.account_id.auto_create_member:
 | ||
|                         continue
 | ||
|                     self.update_partner_detail(name, member.get('email_address'), prepared_vals_for_create_partner)
 | ||
|                     update_partner_required = False
 | ||
|                     contact_id = mailing_contact_obj.create(
 | ||
|                         {'name': name, 'email': member.get('email_address'),
 | ||
|                          'country_id': prepared_vals_for_create_partner.get('country_id', False) or False})
 | ||
|                 if contact_id:
 | ||
|                     md5_email = hashlib.md5(member.get('email_address').encode('utf-8')).hexdigest()
 | ||
|                     vals = {'list_id': self.odoo_list_id.id, 'contact_id': contact_id.id,
 | ||
|                             'mailchimp_id': member.get('web_id'), 'md5_email': md5_email}
 | ||
|                     status = member.get('status', '')
 | ||
|                     if update_partner_required:
 | ||
|                         self.update_partner_detail(name, member.get('email_address'), prepared_vals_for_create_partner)
 | ||
|                     contact_vals = {'opt_out': True} if status == 'unsubscribed' else {'opt_out': False}
 | ||
|                     if status == 'cleaned':
 | ||
|                         contact_vals.update({'is_email_valid': False, 'opt_out': True})
 | ||
|                     contact_vals.update({'tag_ids': [(6, 0, tag_ids.ids)]})
 | ||
|                     contact_id.write(contact_vals)
 | ||
|                     existing_define_list = contact_id.subscription_list_ids.filtered(
 | ||
|                         lambda x: x.list_id.id == self.odoo_list_id.id)
 | ||
|                     if existing_define_list:
 | ||
|                         existing_define_list.write(vals)
 | ||
|                     else:
 | ||
|                         contact_id.subscription_list_ids.create(vals)
 | ||
|             self._cr.commit()
 | ||
|         self.write({'member_since_last_changed': fields.Datetime.now()})
 | ||
|         return members_list
 | ||
| 
 | ||
|     @api.multi
 | ||
|     def update_partner_detail(self, name, email, partner_detail):
 | ||
|         query = """
 | ||
|                 SELECT id 
 | ||
|                   FROM res_partner
 | ||
|                 WHERE LOWER(substring(email, '([^ ,;<@]+@[^> ,;]+)')) = LOWER(substring('{}', '([^ ,;<@]+@[^> ,;]+)'))""".format(email)
 | ||
|         self._cr.execute(query)
 | ||
|         partner_id = self._cr.fetchone()
 | ||
|         partner_id = partner_id[0] if partner_id else False
 | ||
|         if partner_id:
 | ||
|             partner_id = self.env['res.partner'].browse(partner_id)
 | ||
|             if partner_detail:
 | ||
|                 partner_id.write(partner_detail)
 | ||
|         else:
 | ||
|             if self.account_id.auto_create_member and self.account_id.auto_create_partner:
 | ||
|                 partner_detail.update({
 | ||
|                     'email': email,
 | ||
|                     'is_company': False,
 | ||
|                     'type': 'contact',
 | ||
|                 })
 | ||
|                 self.env['res.partner'].create(partner_detail)
 | ||
|         return True
 | ||
| 
 | ||
|     @api.model
 | ||
|     def fetch_member_cron(self):
 | ||
|         account_obj = self.env['mailchimp.accounts']
 | ||
|         for record in account_obj.search([('auto_refresh_member', '=', True)]):
 | ||
|             list_ids = self.search([('account_id', '=', record.id)])
 | ||
|             for list in list_ids:
 | ||
|                 list.fetch_members()
 | ||
|         return True
 | ||
| 
 | ||
| 
 | ||
| class MailChimpListsStats(models.Model):
 | ||
|     _name = "mailchimp.lists.stats"
 | ||
|     _description = "MailChimp Statistics"
 | ||
| 
 | ||
|     list_id = fields.Many2one("mailchimp.lists", string="MailChimp List", required=True, ondelete='cascade')
 | ||
|     member_count = fields.Integer("Subscribed Count")
 | ||
|     unsubscribe_count = fields.Integer("Unsubscribe Count")
 | ||
|     cleaned_count = fields.Integer("Cleaned Count")
 | ||
|     member_count_since_send = fields.Integer("Subscribed Count")
 | ||
|     unsubscribe_count_since_send = fields.Integer("Unsubscribe Count")
 | ||
|     cleaned_count_since_send = fields.Integer("Cleaned Count")
 | ||
|     campaign_count = fields.Integer("Campaign Count")
 | ||
|     campaign_last_sent = fields.Datetime("Campaign Last Sent")
 | ||
|     merge_field_count = fields.Integer("Merge Count")
 | ||
|     avg_sub_rate = fields.Float("Average Subscription Rate")
 | ||
|     avg_unsub_rate = fields.Float("Average Unsubscription Rate")
 | ||
|     target_sub_rate = fields.Float("Average Subscription Rate")
 | ||
|     open_rate = fields.Float("Open Rate")
 | ||
|     click_rate = fields.Float("Click Rate")
 | ||
|     last_sub_date = fields.Datetime("Date of Last Subscribe")
 | ||
|     last_unsub_date = fields.Datetime("Date of Last Unsubscribe")
 |