Files
enterprise-addons/whatsapp_identifiers/models/res_partner.py
T

89 lines
4.9 KiB
Python

import logging
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class ResPartner(models.Model):
_inherit = 'res.partner'
# See docs for more details, especially the incoming message format
# https://developers.facebook.com/documentation/business-messaging/whatsapp/business-scoped-user-ids/#incoming-messages-webhooks-1
# Global unique id for a whatsapp user, only provided by the API if we contact the user using a phone number first
wa_id = fields.Char(string='WhatsApp number identifier', help='Phone number as stored by WhatsApp', index='btree_not_null')
# Business-scoped ids for a whatsapp user: one per account, as a BSUID is only valid for calls made
# through the same WhatsApp account (or an account from the same business portfolio, which we don't model).
# To be sudoed as needed since only useful technically, and only makes sense to access if one has access to the partner
wa_bsuid_ids = fields.One2many('whatsapp.partner.bsuid', 'partner_id', string='WhatsApp Business-Scoped User IDs', groups='whatsapp.group_whatsapp_admin')
wa_bsuid = fields.Char(string='Whatsapp Business-Scoped User ID', compute='_compute_wa_bsuid', inverse='_inverse_wa_bsuid', groups='whatsapp.group_whatsapp_admin')
@api.depends_context('whatsapp_account_id')
@api.depends('wa_bsuid_ids')
def _compute_wa_bsuid(self):
wa_account_id = self.env.context.get('whatsapp_account_id')
if isinstance(wa_account_id, self.env.registry['whatsapp.account']):
wa_account_id = wa_account_id.id
if not wa_account_id:
self.wa_bsuid = ''
return
wa_bsuids = self.env['whatsapp.partner.bsuid'].sudo().search([('partner_id', 'in', self.ids), ('wa_account_id', '=', wa_account_id)])
wa_bsuid_by_partner = {entry.partner_id: entry.bsuid for entry in wa_bsuids}
for partner in self:
partner.wa_bsuid = wa_bsuid_by_partner.get(partner, '')
def _inverse_wa_bsuid(self):
wa_account_id = self.env.context.get('whatsapp_account_id')
if isinstance(wa_account_id, self.env.registry['whatsapp.account']):
wa_account_id = wa_account_id.id
if not wa_account_id:
return
wa_bsuids = self.env['whatsapp.partner.bsuid'].sudo().search([('partner_id', 'in', self.ids), ('wa_account_id', '=', wa_account_id)])
bsuid_entry_by_partner = {entry.partner_id: entry for entry in wa_bsuids}
to_create = []
to_delete = []
for partner in self:
partner_bsuid = bsuid_entry_by_partner.get(partner)
if not partner_bsuid and partner.wa_bsuid:
to_create.append({'partner_id': partner.id, 'wa_account_id': wa_account_id, 'bsuid': partner.wa_bsuid})
elif partner_bsuid and partner.wa_bsuid:
partner_bsuid.bsuid = partner.wa_bsuid
elif partner_bsuid and not partner.wa_bsuid:
to_delete.append(partner_bsuid.id)
self.env['whatsapp.partner.bsuid'].create(to_create)
self.env['whatsapp.partner.bsuid'].browse(to_delete).unlink()
def _find_from_whatsapp_identifiers(self, identifiers, wa_account_id=None):
partner = super()._find_from_whatsapp_identifiers(identifiers, wa_account_id=wa_account_id)
if not partner and (bsuid := identifiers.get('bsuid')):
bsuid_domain = [('bsuid', '=', bsuid)]
if wa_account_id:
bsuid_domain.append(('wa_account_id', '=', wa_account_id.id))
partner = self.env['whatsapp.partner.bsuid'].sudo().search(bsuid_domain, limit=1).partner_id
if not partner and (wa_id := identifiers.get('wa_id')):
partner = self.env['res.partner'].search([('wa_id', '=', wa_id)], limit=1)
return partner
def _get_create_values_from_whatsapp_identifiers(self, identifiers):
partner_create_vals = super()._get_create_values_from_whatsapp_identifiers(identifiers)
if bsuid := identifiers.get('bsuid'):
country = self.env['res.country']
split_bsuid = bsuid.split('.')
if len(split_bsuid) == 2:
country = self.env['res.country'].search([('code', '=', split_bsuid[0].upper())], limit=1)
if country:
partner_create_vals['country_id'] = country.id
else:
_logger.warning('Unexpected format for bsuid: %s. No country could be fetched.', bsuid)
if wa_id := identifiers.get('wa_id'):
partner_create_vals['wa_id'] = wa_id
return partner_create_vals
def _update_from_whatsapp_identifiers(self, identifiers, wa_account_id):
super()._update_from_whatsapp_identifiers(identifiers, wa_account_id)
if bsuid := identifiers.get('bsuid'):
self.with_context(whatsapp_account_id=wa_account_id).wa_bsuid = bsuid
if wa_id := identifiers.get('wa_id'):
self.wa_id = wa_id