From 0b5b43646b92298dddcdb7eec1a590d90cadd1e8 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Thu, 29 Feb 2024 14:21:05 +0700 Subject: Update feature user activity log with utm source --- indoteknik_custom/__manifest__.py | 3 +- indoteknik_custom/models/__init__.py | 2 +- indoteknik_custom/models/user_activity_log.py | 188 ------------------ indoteknik_custom/models/web_logging/__init__.py | 2 + .../models/web_logging/user_activity_log.py | 219 +++++++++++++++++++++ .../models/web_logging/web_utm_source.py | 17 ++ indoteknik_custom/security/ir.model.access.csv | 1 + indoteknik_custom/views/user_activity_log.xml | 69 ------- .../views/web_logging/user_activity_log.xml | 69 +++++++ .../views/web_logging/web_utm_source.xml | 45 +++++ 10 files changed, 356 insertions(+), 259 deletions(-) delete mode 100755 indoteknik_custom/models/user_activity_log.py create mode 100644 indoteknik_custom/models/web_logging/__init__.py create mode 100644 indoteknik_custom/models/web_logging/user_activity_log.py create mode 100644 indoteknik_custom/models/web_logging/web_utm_source.py delete mode 100755 indoteknik_custom/views/user_activity_log.xml create mode 100644 indoteknik_custom/views/web_logging/user_activity_log.xml create mode 100644 indoteknik_custom/views/web_logging/web_utm_source.xml diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 30e8e176..571b36c3 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -27,7 +27,8 @@ 'views/purchase_pricelist.xml', 'views/sale_monitoring.xml', 'views/sale_monitoring_detail.xml', - 'views/user_activity_log.xml', + 'views/web_logging/user_activity_log.xml', + 'views/web_logging/web_utm_source.xml', 'views/user_company_request.xml', 'views/vit_kelurahan.xml', 'views/vit_kecamatan.xml', diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 7c5e46e6..69cbffca 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -33,7 +33,6 @@ from . import stock_picking_return from . import stock_picking_type from . import stock_picking from . import stock_vendor -from . import user_activity_log from . import user_company_request from . import users from . import website_brand_homepage @@ -103,3 +102,4 @@ from . import report_logbook_sj from . import role_permission from . import cust_commision from . import report_stock_forecasted +from . import web_logging \ No newline at end of file diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py deleted file mode 100755 index 9630e3ab..00000000 --- a/indoteknik_custom/models/user_activity_log.py +++ /dev/null @@ -1,188 +0,0 @@ -from odoo import models, fields, api -from odoo.http import request -from datetime import datetime, timedelta -import logging, re -import requests -import json - -_logger = logging.getLogger(__name__) - - -class UserActivityLog(models.Model): - _name = 'user.activity.log' - _rec_name = 'page_title' - - page_title = fields.Char(string="Judul Halaman") - url = fields.Char(string="URL") - ip_address = fields.Char('IP Address') - ip_address_lookup = fields.Text('IP Address Lookup') - ip_location_city = fields.Text('IP Location City') - ip_location_country = fields.Text('IP Location Country') - ip_location_country_code = fields.Text('IP Location Country Code') - ip_location_map = fields.Html('Embedded Map', compute='_compute_ip_location_map', sanitize=False) - res_user_id = fields.Many2one("res.users", string="User") - email = fields.Char(string="Email") - update_product = fields.Boolean(string="Update Product") - product_id = fields.Many2one('product.template', string='Product') - - def _parse_json(self, json_string, key): - result = '' - if json_string: - json_object = json.loads(json_string) - if key in json_object: - result = json_object[key] - return result - - def _compute_ip_location_map(self): - self.ip_location_map = "" - ip_location_lat = self._parse_json(self.ip_address_lookup, 'lat') - ip_location_lon = self._parse_json(self.ip_address_lookup, 'lon') - url = 'https://maps.google.com/maps?q=%s,%s&hl=id&z=15&output=embed' % (ip_location_lat, ip_location_lon) - if ip_location_lat and ip_location_lon: - self.ip_location_map = "" - - def _parse_ip_location(self): - domain = [ - ('ip_address_lookup', '!=', False), - ('ip_location_city', '=', False), - ('ip_location_country', '=', False), - ('ip_location_country_code', '=', False), - ] - logs = self.search(domain, limit=200, order='create_date asc') - for log in logs: - log.ip_location_city = self._parse_json(log.ip_address_lookup, 'city') - log.ip_location_country = self._parse_json(log.ip_address_lookup, 'country') - log.ip_location_country_code = self._parse_json(log.ip_address_lookup, 'countryCode') - - def _load_ip_address_lookup(self): - domain = [ - ('ip_address', '!=', False), - ('ip_address_lookup', '=', False), - ] - logs = self.search(domain, limit=45, order='create_date asc') - for log in logs: - try: - ipinfo = requests.get('http://ip-api.com/json/%s' % log.ip_address).json() - del ipinfo['status'] - log.ip_address_lookup = json.dumps(ipinfo, indent=4, sort_keys=True) - except: - log.ip_address_lookup = '' - self._parse_ip_location() - - def record_activity(self): - try: - httprequest = request.httprequest - if httprequest.remote_addr != '127.0.0.1': - self.env['user.activity.log'].sudo().create([{ - 'page_title': request.env['ir.config_parameter'].get_param('web.base.url'), - 'url': httprequest.base_url, - 'ip_address': httprequest.remote_addr - }]) - return True - except: - return False - - def compile_product(self): - logs = self.env['user.activity.log'].search([ - ('email', '!=', False), - ('product_id', '=', False), - ('url', 'ilike', 'https://indoteknik.co%/shop/product/%'), - ('url', 'not ilike', 'shopping') - ], limit=1000, order='create_date desc') - for log in logs: - _logger.info(log.url) - strip_index = i = 0 - for c in log.url: - if c == '-': - strip_index = i - i += 1 - product_id = log.url[strip_index + 1:len(log.url)] - if '#' in product_id: - continue - if any(ch.isalpha() for ch in product_id): - continue - product = self.env['product.template'].search([ - ('id', '=', product_id) - ]) - log.product_id = product - - def clean_activity_log(self): - current_time = datetime.now() - delta_time = current_time - timedelta(days=180) - - delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') - self.env['user.activity.log'].search([ - ('create_date', '<', delta_time), - ('email', '=', 'False'), - ]).unlink() - - def reset_rank_search_weekly(self): - templates = self.env['product.template'].search([ - ('type', '=', 'product'), - ('active', '=', True), - ('search_rank_weekly', '>', 0), - ]) - for template in templates: - template.search_rank_weekly = 0 - template.solr_flag = 2 - - def update_rank_search_weekly(self): - current_time = datetime.now() - delta_time = current_time - timedelta(days=7) - - delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') - - activity_logs = self.env['user.activity.log'].search([ - ('url', 'ilike', 'https://indoteknik.com%/shop/product/%'), - ('create_date', '>', delta_time), - ('url', 'not ilike', 'shopping'), - ], limit=2000, order='create_date DESC') - - for activity_log in activity_logs: - _logger.info(activity_log.url) - strip_index = i = 0 - for c in activity_log.url: - if c == '-': - strip_index = i - i += 1 - _logger.info(activity_log.url[strip_index + 1:len(activity_log.url)]) - product_id = activity_log.url[strip_index + 1:len(activity_log.url)] - if '#' in product_id: - continue - if any(ch.isalpha() for ch in product_id): - continue - template = self.env['product.template'].search([ - ('id', '=', int(product_id)) - ], limit=1) - if template: - template.search_rank_weekly += 1 - template.solr_flag = 2 - - def update_rank_search(self): - activity_logs = self.env['user.activity.log'].search([ - ('url', 'ilike', '%/shop/product/%'), - ('update_product', '!=', True), - ], limit=1000, order='create_date DESC') - - for activity_log in activity_logs: - _logger.info(activity_log.url) - strip_index = i = 0 - for c in activity_log.url: - if c == '-': - strip_index = i - i += 1 - _logger.info(activity_log.url[strip_index + 1:len(activity_log.url)]) - product_id = activity_log.url[strip_index + 1:len(activity_log.url)] - if '#' in product_id: - continue - if any(ch.isalpha() for ch in product_id): - continue - template = self.env['product.template'].search([ - ('id', '=', int(product_id)) - ], limit=1) - if template: - template.search_rank += 1 - activity_log.update_product = True - - - diff --git a/indoteknik_custom/models/web_logging/__init__.py b/indoteknik_custom/models/web_logging/__init__.py new file mode 100644 index 00000000..9c686e54 --- /dev/null +++ b/indoteknik_custom/models/web_logging/__init__.py @@ -0,0 +1,2 @@ +from . import web_utm_source +from . import user_activity_log \ No newline at end of file diff --git a/indoteknik_custom/models/web_logging/user_activity_log.py b/indoteknik_custom/models/web_logging/user_activity_log.py new file mode 100644 index 00000000..f48e9352 --- /dev/null +++ b/indoteknik_custom/models/web_logging/user_activity_log.py @@ -0,0 +1,219 @@ +import json +import logging +import re +from datetime import datetime, timedelta + +import requests +from odoo import fields, models, api +from odoo.http import request +from urllib.parse import urlparse, parse_qs + +_logger = logging.getLogger(__name__) + + +class UserActivityLog(models.Model): + _name = 'user.activity.log' + _rec_name = 'page_title' + + page_title = fields.Char(string="Judul Halaman") + url = fields.Char(string="URL") + res_user_id = fields.Many2one("res.users", string="User") + email = fields.Char(string="Email") + update_product = fields.Boolean(string="Update Product") + product_id = fields.Many2one('product.template', string='Product') + utm_source_id = fields.Many2one('web.utm.source', string='UTM Source') + + ip_address = fields.Char('IP Address') + ip_address_lookup = fields.Text('IP Address Lookup') + ip_location_city = fields.Text('IP Location City') + ip_location_country = fields.Text('IP Location Country') + ip_location_country_code = fields.Text('IP Location Country Code') + ip_location_map = fields.Html('Embedded Map', compute='_compute_ip_location_map', sanitize=False) + + + # @api.constrains('url') + # def _constrains_url(self): + # for rec in self: + # rec.fill_utm_source() + @api.model + def create(self, vals): + result = super(UserActivityLog, self).create(vals) + result.fill_utm_source() + return result + + def fill_utm_source(self): + for rec in self: + if not rec.url: + rec.utm_source_id = False + continue + + parsed_url = urlparse(rec.url) + params = parse_qs(parsed_url.query) + utm_source_value = params.get('utm_source') + + if not utm_source_value: continue + + utm_source = self.env['web.utm.source'].find_or_create_key(utm_source_value[0]) + rec.utm_source_id = utm_source.id or False + + def _parse_json(self, json_string, key): + result = '' + if json_string: + json_object = json.loads(json_string) + if key in json_object: + result = json_object[key] + return result + + def _compute_ip_location_map(self): + self.ip_location_map = "" + ip_location_lat = self._parse_json(self.ip_address_lookup, 'lat') + ip_location_lon = self._parse_json(self.ip_address_lookup, 'lon') + url = 'https://maps.google.com/maps?q=%s,%s&hl=id&z=15&output=embed' % (ip_location_lat, ip_location_lon) + if ip_location_lat and ip_location_lon: + self.ip_location_map = "" + + def _parse_ip_location(self): + domain = [ + ('ip_address_lookup', '!=', False), + ('ip_location_city', '=', False), + ('ip_location_country', '=', False), + ('ip_location_country_code', '=', False), + ] + logs = self.search(domain, limit=200, order='create_date asc') + for log in logs: + log.ip_location_city = self._parse_json(log.ip_address_lookup, 'city') + log.ip_location_country = self._parse_json(log.ip_address_lookup, 'country') + log.ip_location_country_code = self._parse_json(log.ip_address_lookup, 'countryCode') + + def _load_ip_address_lookup(self): + domain = [ + ('ip_address', '!=', False), + ('ip_address_lookup', '=', False), + ] + logs = self.search(domain, limit=45, order='create_date asc') + for log in logs: + try: + ipinfo = requests.get('http://ip-api.com/json/%s' % log.ip_address).json() + del ipinfo['status'] + log.ip_address_lookup = json.dumps(ipinfo, indent=4, sort_keys=True) + except: + log.ip_address_lookup = '' + self._parse_ip_location() + + def record_activity(self): + try: + httprequest = request.httprequest + if httprequest.remote_addr != '127.0.0.1': + self.env['user.activity.log'].sudo().create([{ + 'page_title': request.env['ir.config_parameter'].get_param('web.base.url'), + 'url': httprequest.base_url, + 'ip_address': httprequest.remote_addr + }]) + return True + except: + return False + + def compile_product(self): + logs = self.env['user.activity.log'].search([ + ('email', '!=', False), + ('product_id', '=', False), + ('url', 'ilike', 'https://indoteknik.co%/shop/product/%'), + ('url', 'not ilike', 'shopping') + ], limit=1000, order='create_date desc') + for log in logs: + _logger.info(log.url) + strip_index = i = 0 + for c in log.url: + if c == '-': + strip_index = i + i += 1 + product_id = log.url[strip_index + 1:len(log.url)] + if '#' in product_id: + continue + if any(ch.isalpha() for ch in product_id): + continue + product = self.env['product.template'].search([ + ('id', '=', product_id) + ]) + log.product_id = product + + def clean_activity_log(self): + current_time = datetime.now() + delta_time = current_time - timedelta(days=180) + + delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') + self.env['user.activity.log'].search([ + ('create_date', '<', delta_time), + ('email', '=', 'False'), + ]).unlink() + + def reset_rank_search_weekly(self): + templates = self.env['product.template'].search([ + ('type', '=', 'product'), + ('active', '=', True), + ('search_rank_weekly', '>', 0), + ]) + for template in templates: + template.search_rank_weekly = 0 + template.solr_flag = 2 + + def update_rank_search_weekly(self): + current_time = datetime.now() + delta_time = current_time - timedelta(days=7) + + delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') + + activity_logs = self.env['user.activity.log'].search([ + ('url', 'ilike', 'https://indoteknik.com%/shop/product/%'), + ('create_date', '>', delta_time), + ('url', 'not ilike', 'shopping'), + ], limit=2000, order='create_date DESC') + + for activity_log in activity_logs: + _logger.info(activity_log.url) + strip_index = i = 0 + for c in activity_log.url: + if c == '-': + strip_index = i + i += 1 + _logger.info(activity_log.url[strip_index + 1:len(activity_log.url)]) + product_id = activity_log.url[strip_index + 1:len(activity_log.url)] + if '#' in product_id: + continue + if any(ch.isalpha() for ch in product_id): + continue + template = self.env['product.template'].search([ + ('id', '=', int(product_id)) + ], limit=1) + if template: + template.search_rank_weekly += 1 + template.solr_flag = 2 + + def update_rank_search(self): + activity_logs = self.env['user.activity.log'].search([ + ('url', 'ilike', '%/shop/product/%'), + ('update_product', '!=', True), + ], limit=1000, order='create_date DESC') + + for activity_log in activity_logs: + _logger.info(activity_log.url) + strip_index = i = 0 + for c in activity_log.url: + if c == '-': + strip_index = i + i += 1 + _logger.info(activity_log.url[strip_index + 1:len(activity_log.url)]) + product_id = activity_log.url[strip_index + 1:len(activity_log.url)] + if '#' in product_id: + continue + if any(ch.isalpha() for ch in product_id): + continue + template = self.env['product.template'].search([ + ('id', '=', int(product_id)) + ], limit=1) + if template: + template.search_rank += 1 + activity_log.update_product = True + + + diff --git a/indoteknik_custom/models/web_logging/web_utm_source.py b/indoteknik_custom/models/web_logging/web_utm_source.py new file mode 100644 index 00000000..baeb0e9b --- /dev/null +++ b/indoteknik_custom/models/web_logging/web_utm_source.py @@ -0,0 +1,17 @@ +from odoo import fields, models + + +class UserActivityLog(models.Model): + _name = 'web.utm.source' + + name = fields.Char(string='Name') + key = fields.Char(string='Key', unique=True) + + def find_or_create_key(self, key): + utm_source = self.search([('key', '=', key)], limit=1) + if not utm_source: + utm_source = self.create({ + 'name': key, + 'key': key + }) + return utm_source \ No newline at end of file diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 5af34c11..65bd6e90 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -8,6 +8,7 @@ access_x_partner_purchase_order,access.x.partner.purchase.order,model_x_partner_ access_x_product_tags,access.x.product.tags,model_x_product_tags,,1,1,1,1 access_stock_vendor,access.stock.vendor,model_stock_vendor,,1,1,1,1 access_user_activity_log,access.user.activity.log,model_user_activity_log,,1,1,1,1 +access_web_utm_source,access.web.utm.source,model_web_utm_source,,1,1,1,1 access_purchase_pricelist,access.purchase.pricelist,model_purchase_pricelist,,1,1,1,1 access_sale_monitoring,access.sale.monitoring,model_sale_monitoring,,1,1,1,1 access_sale_monitoring_detail,access.sale.monitoring.detail,model_sale_monitoring_detail,,1,1,1,1 diff --git a/indoteknik_custom/views/user_activity_log.xml b/indoteknik_custom/views/user_activity_log.xml deleted file mode 100755 index 91c14b4d..00000000 --- a/indoteknik_custom/views/user_activity_log.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - user.activity.log.tree - user.activity.log - - - - - - - - - - - - - - - user.activity.log.form - user.activity.log - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - User Activity Log - ir.actions.act_window - user.activity.log - tree,form - - - -
\ No newline at end of file diff --git a/indoteknik_custom/views/web_logging/user_activity_log.xml b/indoteknik_custom/views/web_logging/user_activity_log.xml new file mode 100644 index 00000000..ec6d1fa2 --- /dev/null +++ b/indoteknik_custom/views/web_logging/user_activity_log.xml @@ -0,0 +1,69 @@ + + + + user.activity.log.tree + user.activity.log + + + + + + + + + + + + + + user.activity.log.form + user.activity.log + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + User Activity Log + ir.actions.act_window + user.activity.log + tree,form + + + +
\ No newline at end of file diff --git a/indoteknik_custom/views/web_logging/web_utm_source.xml b/indoteknik_custom/views/web_logging/web_utm_source.xml new file mode 100644 index 00000000..6ffbd95f --- /dev/null +++ b/indoteknik_custom/views/web_logging/web_utm_source.xml @@ -0,0 +1,45 @@ + + + + web.utm.source.tree + web.utm.source + + + + + + + + + + web.utm.source.form + web.utm.source + +
+ + + + + + + + +
+
+
+ + + Web UTM Source + ir.actions.act_window + web.utm.source + tree,form + + + +
\ No newline at end of file -- cgit v1.2.3