import re import hashlib from datetime import datetime from odoo import api, fields, models, _ from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT EMAIL_PATTERN = '([^ ,;<@]+@[^> ,;]+)' def _partner_split_name(partner_name): return [' '.join(partner_name.split()[:-1]), ' '.join(partner_name.split()[-1:])] class massMailingContact(models.Model): _inherit = "mail.mass_mailing.contact" @api.multi def get_partner(self, email): query = """ SELECT id FROM res_partner WHERE LOWER(substring(email, '([^ ,;<@]+@[^> ,;]+)')) = LOWER(substring('{}', '([^ ,;<@]+@[^> ,;]+)'))""".format(email) self._cr.execute(query) return self._cr.fetchone() or False @api.model def create(self, vals): res = super(massMailingContact, self).create(vals) if vals.get('email', False): partner_record = self.get_partner(vals.get('email')) res.related_partner_id = partner_record return res @api.multi def write(self, vals): if vals.get('email', False) and not self._context.get('do_not_update', False): partner_record = self.get_partner(vals.get('email')) vals.update({'related_partner_id': partner_record}) res = super(massMailingContact, self).write(vals) return res @api.depends('subscription_list_ids', 'subscription_list_ids.mailchimp_id', 'subscription_list_ids.list_id') def _get_pending_for_export(self): available_mailchimp_lists = self.env['mailchimp.lists'].search([]) lists = available_mailchimp_lists.mapped('odoo_list_id').ids for record in self: if record.subscription_list_ids.filtered(lambda x: x.list_id.id in lists and not x.mailchimp_id): record.pending_for_export = True else: record.pending_for_export = False @api.depends('email') def _compute_is_email_valid(self): for record in self: record.is_email_valid = re.match(EMAIL_PATTERN, record.email) @api.depends('email') def _compute_related_partner_id(self): for record in self: query = """ SELECT id FROM res_partner WHERE LOWER(substring(email, '([^ ,;<@]+@[^> ,;]+)')) = LOWER(substring('{}', '([^ ,;<@]+@[^> ,;]+)'))""".format(record.email) self._cr.execute(query) partner_record = self._cr.fetchone() if partner_record: record.related_partner_id = partner_record[0] else: record.related_partner_id = False is_email_valid = fields.Boolean(compute='_compute_is_email_valid', store=True) pending_for_export = fields.Boolean(compute="_get_pending_for_export", string="Pending For Export", store=True) related_partner_id = fields.Many2one('res.partner', 'Related Customer', compute="_compute_related_partner_id", help='Display related customer by matching Email address.', store=True) subscription_list_ids = fields.One2many('mail.mass_mailing.list_contact_rel', 'contact_id', string='Subscription Information') def _prepare_vals_for_merge_fields(self, mailchimp_list_id): self.ensure_one() merge_fields_vals = {} partner_id = self.related_partner_id for custom_field in mailchimp_list_id.merge_field_ids: if custom_field.type == 'address' and partner_id: address = {'addr1': partner_id.street or '', 'addr2': partner_id.street2 or '', 'city': partner_id.city or '', 'state': partner_id.state_id.name if partner_id.state_id else '', 'zip': partner_id.zip, 'country': partner_id.country_id.code if partner_id.country_id else ''} merge_fields_vals.update({custom_field.tag: address}) elif custom_field.tag == 'FNAME': merge_fields_vals.update({custom_field.tag: _partner_split_name(self.name)[0] if _partner_split_name(self.name)[0] else _partner_split_name(self.name)[1]}) elif custom_field.tag == 'LNAME': merge_fields_vals.update({custom_field.tag: _partner_split_name(self.name)[1] if _partner_split_name(self.name)[0] else _partner_split_name(self.name)[0]}) elif custom_field.type in ['date', 'birthday']: value = getattr(partner_id or self, custom_field.field_id.name) if custom_field.field_id and hasattr(partner_id or self, custom_field.field_id.name) else '' if value: value = datetime.strptime(value, DEFAULT_SERVER_DATETIME_FORMAT).strftime(custom_field.date_format) # value = value.strftime(custom_field.date_format) merge_fields_vals.update({custom_field.tag: value or ''}) else: value = getattr(partner_id or self, custom_field.field_id.name) if custom_field.field_id and hasattr(partner_id or self, custom_field.field_id.name) else '' merge_fields_vals.update({custom_field.tag: value or ''}) return merge_fields_vals @api.multi def action_export_to_mailchimp(self): available_mailchimp_lists = self.env['mailchimp.lists'].search([]) lists = available_mailchimp_lists.mapped('odoo_list_id').ids for record in self: lists_to_export = record.subscription_list_ids.filtered( lambda x: x.list_id.id in lists and not x.mailchimp_id) for list in lists_to_export: mailchimp_list_id = list.list_id.mailchimp_list_id merge_fields_vals = record._prepare_vals_for_merge_fields(mailchimp_list_id) # address = '' # phone = '' # partner_id = record.related_partner_id # if partner_id: # address = {'addr1': partner_id.street or '', # 'addr2': partner_id.street2 or '', # 'city': partner_id.city or '', # 'state': partner_id.state_id.name if partner_id.state_id else '', # 'zip': partner_id.zip, # 'country': partner_id.country_id.code if partner_id.country_id else ''} # phone = partner_id.phone or partner_id.mobile prepared_vals = {"email_address": record.email.lower(), "status": "unsubscribed" if record.opt_out else "subscribed", "merge_fields": merge_fields_vals, "tags": [tag.name for tag in record.tag_ids]} response = mailchimp_list_id.account_id._send_request('lists/%s/members' % mailchimp_list_id.list_id, prepared_vals, method='POST') if response.get('web_id', False): email_address = response.get('email_address') md5_email = hashlib.md5(email_address.encode('utf-8')).hexdigest() list.write({'mailchimp_id': response.get('web_id', False), 'md5_email': md5_email}) return True @api.multi def action_update_to_mailchimp(self): available_mailchimp_lists = self.env['mailchimp.lists'].search([]) lists = available_mailchimp_lists.mapped('odoo_list_id').ids for record in self: lists_to_export = record.subscription_list_ids.filtered( lambda x: x.list_id.id in lists and x.mailchimp_id) for list in lists_to_export: mailchimp_list_id = list.list_id.mailchimp_list_id merge_fields_vals = record._prepare_vals_for_merge_fields(mailchimp_list_id) # partner_id = record.related_partner_id # address = '' # phone = '' # if partner_id: # address = {'addr1': partner_id.street or '', # 'addr2': partner_id.street2 or '', # 'city': partner_id.city or '', # 'state': partner_id.state_id.name if partner_id.state_id else '', # 'zip': partner_id.zip, # 'country': partner_id.country_id.code if partner_id.country_id else ''} # phone = partner_id.phone or partner_id.mobile prepared_vals = {"email_address": record.email.lower(), "status": "unsubscribed" if record.opt_out else "subscribed", 'merge_fields': merge_fields_vals, } response = mailchimp_list_id.account_id._send_request( 'lists/%s/members/%s' % (mailchimp_list_id.list_id, list.md5_email), prepared_vals, method='PATCH') tag_res = record.update_tag_on_mailchimp(response, mailchimp_list_id, list.md5_email) if response.get('web_id', False): email_address = response.get('email_address') md5_email = hashlib.md5(email_address.encode('utf-8')).hexdigest() list.write({'mailchimp_id': response.get('web_id', False), 'md5_email': md5_email}) return True def update_tag_on_mailchimp(self, response, mailchimp_list_id, md5_email): tag_list = [] tags = response.get('tags', []) and [tag['name'] for tag in response.get('tags', [])] or [] tag_name_list = self.tag_ids.mapped('name') unique_tags = list(set(tags + tag_name_list)) for tag in unique_tags: if tag in tag_name_list: tag_dict = {'name': tag, 'status': 'active'} else: tag_dict = {'name': tag, 'status': 'inactive'} tag_list.append(tag_dict) tag_vals = {'tags': tag_list} tag_res = mailchimp_list_id.account_id._send_request('lists/%s/members/%s/tags' % (mailchimp_list_id.list_id, md5_email), tag_vals, method='POST') return tag_res def fetch_specific_member_data(self, mailchimp_list_id, md5_email): member_response = mailchimp_list_id.account_id._send_request('lists/%s/members/%s' % (mailchimp_list_id.list_id, md5_email), {}, method='GET') tag_list = member_response.get('tags', []) tag_ids = self.env['res.partner.category'] if tag_list: tag_ids = self.env['res.partner.category'].create_or_update_tags(tag_list) return tag_ids