[IMP] odex_mobile: add push notifications mixin
This commit is contained in:
parent
6d53a4d550
commit
1b8f53c192
|
|
@ -374,11 +374,7 @@ class AttendanceController(http.Controller):
|
||||||
partner_id = emp.user_id.partner_id
|
partner_id = emp.user_id.partner_id
|
||||||
partner_id.send_notification(
|
partner_id.send_notification(
|
||||||
subject, msg, data=None, all_device=True)
|
subject, msg, data=None, all_device=True)
|
||||||
data = {
|
emp.send_push_notification(title=subject, body=msg)
|
||||||
'title':subject,
|
|
||||||
'body':msg,
|
|
||||||
}
|
|
||||||
emp.user_push_notification(data)
|
|
||||||
|
|
||||||
def create_log(self, employee, longitude, latitude):
|
def create_log(self, employee, longitude, latitude):
|
||||||
attendance = http.request.env['attendance.log'].create({
|
attendance = http.request.env['attendance.log'].create({
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,4 @@ from . import hr_firebase_notification
|
||||||
from . import base
|
from . import base
|
||||||
from . import ir_property
|
from . import ir_property
|
||||||
from . import resource
|
from . import resource
|
||||||
|
from . import push_notification_mixin
|
||||||
|
|
@ -4,79 +4,19 @@ from odoo import models,fields,api,_
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
import random
|
import random
|
||||||
import json
|
import json
|
||||||
import json, requests
|
|
||||||
import json, requests, base64
|
|
||||||
import google.auth.transport.requests
|
import google.auth.transport.requests
|
||||||
from google.oauth2 import service_account
|
|
||||||
|
|
||||||
BASE_URL = 'https://fcm.googleapis.com'
|
|
||||||
SCOPES = ['https://www.googleapis.com/auth/firebase.messaging']
|
|
||||||
import tempfile
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class HrEmployee(models.Model):
|
class HrEmployee(models.Model):
|
||||||
_inherit = 'hr.employee'
|
_name = 'hr.employee'
|
||||||
|
_inherit = ['hr.employee', 'push.notification.mixin']
|
||||||
|
|
||||||
device_id = fields.Char(string="Employee Device ")
|
device_id = fields.Char(string="Employee Device ")
|
||||||
fcm_token = fields.Char(string='FCM Token')
|
|
||||||
attendance_log_ids = fields.One2many('attendance.log','employee_id',string="Attendance Log")
|
attendance_log_ids = fields.One2many('attendance.log','employee_id',string="Attendance Log")
|
||||||
message_sent = fields.Boolean(string="Message Sent", default=False)
|
message_sent = fields.Boolean(string="Message Sent", default=False)
|
||||||
# Used internally by the API
|
# Used internally by the API
|
||||||
last_active_time = fields.Datetime(readonly=True)
|
last_active_time = fields.Datetime(readonly=True)
|
||||||
attendance_zone_id = fields.Many2many('attendance.zone', string='Attendance Zone')
|
attendance_zone_id = fields.Many2many('attendance.zone', string='Attendance Zone')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def user_push_notification(self, notification):
|
|
||||||
def _get_access_token(json_file):
|
|
||||||
"""Retrieve a valid access token that can be used to authorize requests.
|
|
||||||
|
|
||||||
:return: Access token.
|
|
||||||
"""
|
|
||||||
credentials = service_account.Credentials.from_service_account_file(
|
|
||||||
json_file, scopes=SCOPES)
|
|
||||||
request = google.auth.transport.requests.Request()
|
|
||||||
credentials.refresh(request)
|
|
||||||
return credentials.token
|
|
||||||
|
|
||||||
try:
|
|
||||||
json_file_name = 'service-account'
|
|
||||||
base64_service_account = base64.decodebytes(self.env.user.company_id.service_account)
|
|
||||||
service_account_json = json.loads(base64_service_account)
|
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
|
||||||
temp_file_path = os.path.join(temp_dir, json_file_name)
|
|
||||||
with open(temp_file_path, 'w') as temp_file:
|
|
||||||
temp_file.write(base64_service_account.decode('UTF-8'))
|
|
||||||
header = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': 'Bearer %s' % (_get_access_token(temp_file_path))
|
|
||||||
}
|
|
||||||
body = json.dumps({
|
|
||||||
"message": {
|
|
||||||
"token": self.fcm_token,
|
|
||||||
"notification": notification,
|
|
||||||
"android": {
|
|
||||||
"notification": {
|
|
||||||
"sound": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"apns": {
|
|
||||||
"payload": {
|
|
||||||
"aps": {
|
|
||||||
"sound": "default"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
FCM_ENDPOINT = 'v1/projects/' + service_account_json['project_id'] + '/messages:send'
|
|
||||||
FCM_URL = BASE_URL + '/' + FCM_ENDPOINT
|
|
||||||
respons = requests.post(url=FCM_URL, data=body, headers=header)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def create_employee_notification(self):
|
def create_employee_notification(self):
|
||||||
emp_notif_obj = self.env['employee.notification']
|
emp_notif_obj = self.env['employee.notification']
|
||||||
holiday_obj = self.env['hr.holidays']
|
holiday_obj = self.env['hr.holidays']
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
import json, requests, base64
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
import google.auth.transport.requests
|
||||||
|
from google.oauth2 import service_account
|
||||||
|
|
||||||
|
BASE_URL = 'https://fcm.googleapis.com'
|
||||||
|
SCOPES = ['https://www.googleapis.com/auth/firebase.messaging']
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class PushNotificationMixin(models.AbstractModel):
|
||||||
|
_name = 'push.notification.mixin'
|
||||||
|
_description = 'Push Notification Mixin'
|
||||||
|
|
||||||
|
fcm_token = fields.Char(string='FCM Token')
|
||||||
|
|
||||||
|
def send_push_notification(self, title, body):
|
||||||
|
def _get_access_token(json_file):
|
||||||
|
"""Retrieve a valid access token that can be used to authorize requests.
|
||||||
|
|
||||||
|
:return: Access token.
|
||||||
|
"""
|
||||||
|
credentials = service_account.Credentials.from_service_account_file(
|
||||||
|
json_file, scopes=SCOPES)
|
||||||
|
request = google.auth.transport.requests.Request()
|
||||||
|
credentials.refresh(request)
|
||||||
|
return credentials.token
|
||||||
|
for rec in self:
|
||||||
|
if not rec.fcm_token:
|
||||||
|
raise UserError(_("FCM Token is required"))
|
||||||
|
if not self.env.user.company_id.service_account:
|
||||||
|
raise UserError(_("Firebase Service Account file is required"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
json_file_name = 'service-account'
|
||||||
|
base64_service_account = base64.decodebytes(self.env.user.company_id.service_account)
|
||||||
|
service_account_json = json.loads(base64_service_account)
|
||||||
|
with tempfile.TemporaryDirectory() as temp_dir:
|
||||||
|
temp_file_path = os.path.join(temp_dir, json_file_name)
|
||||||
|
with open(temp_file_path, 'w') as temp_file:
|
||||||
|
temp_file.write(base64_service_account.decode('UTF-8'))
|
||||||
|
header = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': 'Bearer %s' % (_get_access_token(temp_file_path))
|
||||||
|
}
|
||||||
|
body = json.dumps({
|
||||||
|
"message": {
|
||||||
|
"token": rec.fcm_token,
|
||||||
|
"notification": {
|
||||||
|
"title": title,
|
||||||
|
"body": body
|
||||||
|
},
|
||||||
|
"android": {
|
||||||
|
"notification": {
|
||||||
|
"sound": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"apns": {
|
||||||
|
"payload": {
|
||||||
|
"aps": {
|
||||||
|
"sound": "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
FCM_ENDPOINT = 'v1/projects/' + service_account_json['project_id'] + '/messages:send'
|
||||||
|
FCM_URL = BASE_URL + '/' + FCM_ENDPOINT
|
||||||
|
requests.post(url=FCM_URL, data=body, headers=header)
|
||||||
|
except Exception as e:
|
||||||
|
_logger.error(f"Failed to send push notification for {rec.name}: {e}")
|
||||||
|
|
@ -6,22 +6,13 @@ from odoo import models, fields, api
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class Partner(models.Model):
|
class Partner(models.Model):
|
||||||
_inherit = 'res.partner'
|
_name = 'res.partner'
|
||||||
|
_inherit = ['res.partner', 'push.notification.mixin']
|
||||||
|
|
||||||
firebase_registration_ids = fields.One2many(
|
firebase_registration_ids = fields.One2many(
|
||||||
"firebase.registration", "partner_id", readonly=True
|
"firebase.registration", "partner_id", readonly=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def send_msg(self, partner_ids, msg, subject):
|
|
||||||
emp = self.env['hr.employee'].sudo().search([('user_id', 'in', partner_ids.user_ids.ids)])
|
|
||||||
if emp.user_id.partner_id:
|
|
||||||
partner_id = emp.user_id.partner_id
|
|
||||||
# partner_id.send_notification(subject, msg, data=None, all_device=True)
|
|
||||||
data = {
|
|
||||||
'title':subject,
|
|
||||||
'body':msg,
|
|
||||||
}
|
|
||||||
emp.user_push_notification(data)
|
|
||||||
def send_notification(self, message_title, message_body, data=None, all_device=True):
|
def send_notification(self, message_title, message_body, data=None, all_device=True):
|
||||||
notification_data = {
|
notification_data = {
|
||||||
"title": str(message_title),
|
"title": str(message_title),
|
||||||
|
|
@ -34,7 +25,7 @@ class Partner(models.Model):
|
||||||
notification = self.env['firebase.notification'].sudo().create(notification_data)
|
notification = self.env['firebase.notification'].sudo().create(notification_data)
|
||||||
|
|
||||||
if all_device:
|
if all_device:
|
||||||
self.send_msg(notification.partner_ids,str(message_title),str(message_body))
|
notification.partner_ids.send_push_notification(str(message_title), str(message_body))
|
||||||
for reg in self.firebase_registration_ids:
|
for reg in self.firebase_registration_ids:
|
||||||
reg.with_context(lang=self.lang).send_message(
|
reg.with_context(lang=self.lang).send_message(
|
||||||
message_title,
|
message_title,
|
||||||
|
|
@ -57,25 +48,3 @@ class Partner(models.Model):
|
||||||
message_body,
|
message_body,
|
||||||
data=data
|
data=data
|
||||||
)
|
)
|
||||||
|
|
||||||
def user_push_notification(self, fcm_token):
|
|
||||||
url = "https://fcm.googleapis.com/fcm/send"
|
|
||||||
headers = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': f'key={self.env.user.company_id.fcm_server_key}'
|
|
||||||
}
|
|
||||||
body = json.dumps({
|
|
||||||
"to": fcm_token,
|
|
||||||
"direct_boot_ok": True,
|
|
||||||
"notification": {
|
|
||||||
"title": "Test",
|
|
||||||
"body": "test"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
try:
|
|
||||||
response = requests.post(url=url, data=body, headers=headers)
|
|
||||||
response.raise_for_status()
|
|
||||||
return True
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
_logger.error(f"Failed to send push notification: {e}")
|
|
||||||
return False
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue