From 7ad9c080d62bf3891516cfe81baf705d2eb39e0b Mon Sep 17 00:00:00 2001 From: "Lina Eweis (liew)" Date: Tue, 9 May 2023 08:50:19 +0000 Subject: [PATCH] [IMP] iap: refactor iap accounts Information about iap services and current credit available to view from odoo Can edit some iap services fields from odoo (warn me, warn threshold and warn email) Change the redirect route of view services to view my IAP accounts Add button to buy credits from the form view of iap accounts closes odoo/odoo#121398 Signed-off-by: Louis Baudoux (lba) --- addons/iap/models/iap_account.py | 129 ++++++++++++++++++++++- addons/iap/security/ir.model.access.csv | 1 + addons/iap/views/iap_views.xml | 58 ++++++++-- addons/iap/views/res_config_settings.xml | 2 +- 4 files changed, 178 insertions(+), 12 deletions(-) diff --git a/addons/iap/models/iap_account.py b/addons/iap/models/iap_account.py index a214bf3370f..739d4230635 100644 --- a/addons/iap/models/iap_account.py +++ b/addons/iap/models/iap_account.py @@ -8,6 +8,7 @@ import werkzeug.urls from odoo import api, fields, models from odoo.addons.iap.tools import iap_tools +from odoo.exceptions import AccessError _logger = logging.getLogger(__name__) @@ -19,9 +20,96 @@ class IapAccount(models.Model): _rec_name = 'service_name' _description = 'IAP Account' - service_name = fields.Char() - account_token = fields.Char(default=lambda s: uuid.uuid4().hex) + name = fields.Char() + service_name = fields.Char(readonly=True) + account_token = fields.Char( + default=lambda s: uuid.uuid4().hex, + help="Account token is your authentication key for this service. Do not share it.", + size=43) company_ids = fields.Many2many('res.company') + account_info_id = fields.Many2one( + 'iap.account.info', compute='_compute_info', inverse='_inverse_info', search='_search_info') + account_info_ids = fields.One2many( + 'iap.account.info', 'account_id', + invisible=True, string="Accounts from IAP") + balance = fields.Char(compute='_compute_balance') + description = fields.Char(related='account_info_id.description') + warn_me = fields.Boolean( + related='account_info_id.warn_me', + help="We will send you an email when your balance gets below that threshold", + readonly=False) + warning_threshold = fields.Float(related='account_info_id.warning_threshold', readonly=False) + warning_email = fields.Char(related='account_info_id.warning_email', readonly=False) + show_token = fields.Boolean() + + @api.model + def get_view(self, view_id=None, view_type='form', **kwargs): + res = super().get_view(view_id, view_type, **kwargs) + if view_type == 'tree': + self.env['iap.account'].get_services() + return res + + @api.depends('account_info_ids') + def _compute_info(self): + for account in self: + if account.account_info_ids: + account.account_info_id = account.account_info_ids[-1] + + @api.depends('account_info_id') + def _compute_balance(self): + for account in self: + account.balance = f'{account.account_info_id.balance} {account.account_info_id.unit_name}' if account.account_info_id else "0 Credits" + + def _inverse_info(self): + for account in self: + if account.account_info_ids: + # delete previous reference + account_info = account.env['iap.account.info'].browse(account.account_info_ids[0].id) + account_info.account_id = False + # set new reference + account.account_info_id.account_id = account + + def _search_info(self, operator, value): + return [] + + def write(self, values): + res = super(IapAccount, self).write(values) + iap_edits = ['warn_me', 'warning_threshold', 'warning_email'] + if any(edited_attribute in values for edited_attribute in iap_edits): + try: + route = '/iap/update-warning-odoo' + endpoint = iap_tools.iap_get_endpoint(self.env) + url = endpoint + route + data = { + 'account_token': self.mapped('account_token')[0], + 'dbuuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'), + 'warn_me': values.get('warn_me'), + 'warning_threshold': values.get('warning_threshold'), + 'warning_email': values.get('warning_email'), + } + iap_tools.iap_jsonrpc(url=url, params=data) + except AccessError as e: + _logger.warning('Save service error : %s', str(e)) + return res + + def get_services(self): + try: + route = '/iap/services-token' + endpoint = iap_tools.iap_get_endpoint(self.env) + url = endpoint + route + account_tokens = self.env['iap.account'].sudo().search([]).mapped('account_token') + params = { + 'dbuuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'), + 'iap_accounts': account_tokens, + } + services = iap_tools.iap_jsonrpc(url=url, params=params) + for service in services: + account_id = self.env['iap.account'].sudo().search( + [('account_token', '=', service['account_token'])]).ids[0] + service['account_id'] = account_id + self.env['iap.account.info'].create(service) + except AccessError as e: + _logger.warning('Get services error : %s', str(e)) @api.model def get(self, service_name, force_create=True): @@ -74,14 +162,15 @@ class IapAccount(models.Model): return accounts[0] @api.model - def get_credits_url(self, service_name, base_url='', credit=0, trial=False): + def get_credits_url(self, service_name, base_url='', credit=0, trial=False, account_token=False): """ Called notably by ajax crash manager, buy more widget, partner_autocomplete, sanilmail. """ dbuuid = self.env['ir.config_parameter'].sudo().get_param('database.uuid') if not base_url: endpoint = iap_tools.iap_get_endpoint(self.env) route = '/iap/1/credit' base_url = endpoint + route - account_token = self.get(service_name).account_token + if not account_token: + account_token = self.get(service_name).account_token d = { 'dbuuid': dbuuid, 'service_name': service_name, @@ -92,6 +181,19 @@ class IapAccount(models.Model): d.update({'trial': trial}) return '%s?%s' % (base_url, werkzeug.urls.url_encode(d)) + def action_buy_credits(self): + for account in self: + return { + 'type': 'ir.actions.act_url', + 'url': self.env['iap.account'].get_credits_url( + account_token=account.account_token, + service_name=account.service_name, + ), + } + + def action_toggle_show_token(self): + for account in self: + account.show_token = not account.show_token @api.model def get_account_url(self): """ Called only by res settings """ @@ -130,8 +232,25 @@ class IapAccount(models.Model): } try: credit = iap_tools.iap_jsonrpc(url=url, params=params) - except Exception as e: + except AccessError as e: _logger.info('Get credit error : %s', str(e)) credit = -1 return credit + + +class IAPAccountInfo(models.TransientModel): + _name = 'iap.account.info' + _description = 'IAP Account Info' + _transient_max_hours = 1 + + account_id = fields.Many2one('iap.account', string='IAP Account') + account_token = fields.Char() + balance = fields.Float(string='Balance', digits=(16, 4), default=0) + account_uuid_hashed = fields.Char(string='Account UUID', invisible=True) + service_name = fields.Char(string='Related Service') + description = fields.Char() + warn_me = fields.Boolean('Warn me', default=False) + warning_threshold = fields.Float('Threshold') + warning_email = fields.Char() + unit_name = fields.Char(default='Credits') diff --git a/addons/iap/security/ir.model.access.csv b/addons/iap/security/ir.model.access.csv index 80fd4e2212f..fa02197e407 100644 --- a/addons/iap/security/ir.model.access.csv +++ b/addons/iap/security/ir.model.access.csv @@ -1,3 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_client_iap_account_manager,iap.account.manager,model_iap_account,base.group_system,1,1,1,1 access_client_iap_account_user,iap.account.user,model_iap_account,base.group_user,1,0,1,0 +access_iap_account_info,access_iap_account_info,iap.model_iap_account_info,base.group_user,1,1,1,1 diff --git a/addons/iap/views/iap_views.xml b/addons/iap/views/iap_views.xml index 129a2f0c296..1a85c07adeb 100644 --- a/addons/iap/views/iap_views.xml +++ b/addons/iap/views/iap_views.xml @@ -9,9 +9,51 @@
- - - + + + + + + + + + +