event/models/res_partner.py

88 lines
3.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
import binascii
import hmac
import requests
import werkzeug.urls
from odoo import api, fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
event_count = fields.Integer(
'# Events', compute='_compute_event_count', groups='event.group_event_registration_desk')
static_map_url = fields.Char(compute="_compute_static_map_url")
static_map_url_is_valid = fields.Boolean(compute="_compute_static_map_url_is_valid")
def _compute_event_count(self):
self.event_count = 0
for partner in self:
partner.event_count = self.env['event.event'].search_count([('registration_ids.partner_id', 'child_of', partner.ids)])
@api.depends('zip', 'city', 'country_id', 'street')
def _compute_static_map_url(self):
for partner in self:
partner.static_map_url = partner._google_map_signed_img(zoom=13, width=598, height=200)
@api.depends('static_map_url')
def _compute_static_map_url_is_valid(self):
"""Compute whether the link is valid.
This should only remain valid for a relatively short time.
Here, for the duration it is in cache.
"""
session = requests.Session()
for partner in self:
url = partner.static_map_url
if not url:
partner.static_map_url_is_valid = False
continue
is_valid = False
# If the response isn't strictly successful, assume invalid url
try:
res = session.get(url, timeout=2)
if res.ok and not res.headers.get('X-Staticmap-API-Warning'):
is_valid = True
except requests.exceptions.RequestException:
pass
partner.static_map_url_is_valid = is_valid
def action_event_view(self):
action = self.env["ir.actions.actions"]._for_xml_id("event.action_event_view")
action['context'] = {}
action['domain'] = [('registration_ids.partner_id', 'child_of', self.ids)]
return action
def _google_map_signed_img(self, zoom=13, width=298, height=298):
"""Create a signed static image URL for the location of this partner."""
GOOGLE_MAPS_STATIC_API_KEY = self.env['ir.config_parameter'].sudo().get_param('google_maps.signed_static_api_key')
GOOGLE_MAPS_STATIC_API_SECRET = self.env['ir.config_parameter'].sudo().get_param('google_maps.signed_static_api_secret')
if not GOOGLE_MAPS_STATIC_API_KEY or not GOOGLE_MAPS_STATIC_API_SECRET:
return None
# generate signature as per https://developers.google.com/maps/documentation/maps-static/digital-signature#server-side-signing
location_string = f"{self.street}, {self.city} {self.zip}, {self.country_id and self.country_id.display_name or ''}"
params = {
'center': location_string,
'markers': f'size:mid|{location_string}',
'size': f"{width}x{height}",
'zoom': zoom,
'sensor': "false",
'key': GOOGLE_MAPS_STATIC_API_KEY,
}
unsigned_path = '/maps/api/staticmap?' + werkzeug.urls.url_encode(params)
try:
api_secret_bytes = base64.urlsafe_b64decode(GOOGLE_MAPS_STATIC_API_SECRET + "====")
except binascii.Error:
return None
url_signature_bytes = hmac.digest(api_secret_bytes, unsigned_path.encode(), 'sha1')
params['signature'] = base64.urlsafe_b64encode(url_signature_bytes)
return 'https://maps.googleapis.com/maps/api/staticmap?' + werkzeug.urls.url_encode(params)