Coverage for models / res_config_settings.py: 34%
80 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-28 01:16 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-28 01:16 +0000
1# -*- coding: utf-8 -*-
3from odoo import models, fields, api, _
4from odoo.exceptions import UserError
5import logging
7_logger = logging.getLogger(__name__)
10class ResConfigSettings(models.TransientModel):
11 _inherit = 'res.config.settings'
13 # LOX API Settings
14 lox_api_url = fields.Char(
15 string='LOX API URL',
16 config_parameter='lox_backup.api_url',
17 default='https://api.lox.io',
18 help='LOX API base URL',
19 )
20 lox_api_key = fields.Char(
21 string='LOX API Key',
22 config_parameter='lox_backup.api_key',
23 help='Your LOX API key from app.lox.io',
24 )
25 lox_source_id = fields.Char(
26 string='Source ID',
27 config_parameter='lox_backup.source_id',
28 readonly=True,
29 help='Registered source ID in LOX system',
30 )
31 lox_source_registered = fields.Boolean(
32 string='Source Registered',
33 config_parameter='lox_backup.source_registered',
34 readonly=True,
35 )
37 # Backup Components
38 lox_backup_database = fields.Boolean(
39 string='Backup Database',
40 config_parameter='lox_backup.backup_database',
41 default=True,
42 help='Include PostgreSQL database in backups',
43 )
44 lox_backup_filestore = fields.Boolean(
45 string='Backup Filestore',
46 config_parameter='lox_backup.backup_filestore',
47 default=True,
48 help='Include filestore (attachments) in backups',
49 )
50 lox_backup_modules = fields.Boolean(
51 string='Backup Modules Info',
52 config_parameter='lox_backup.backup_modules',
53 default=True,
54 help='Include list of installed modules and their versions',
55 )
57 # Retention Settings
58 lox_retention_days = fields.Integer(
59 string='Retention Days',
60 config_parameter='lox_backup.retention_days',
61 default=30,
62 help='Number of days to retain backups in LOX storage',
63 )
65 # Tags
66 lox_default_tags = fields.Char(
67 string='Default Tags',
68 config_parameter='lox_backup.default_tags',
69 default='odoo,automated',
70 help='Comma-separated tags to apply to all backups',
71 )
73 # Connection Status (computed)
74 lox_connection_status = fields.Selection([
75 ('unknown', 'Not tested'),
76 ('connected', 'Connected'),
77 ('error', 'Error'),
78 ], string='Connection Status', compute='_compute_lox_connection_status')
80 lox_last_backup = fields.Datetime(
81 string='Last Backup',
82 compute='_compute_lox_stats',
83 )
84 lox_total_backups = fields.Integer(
85 string='Total Backups',
86 compute='_compute_lox_stats',
87 )
89 @api.depends('lox_api_key')
90 def _compute_lox_connection_status(self):
91 for record in self:
92 status = self.env['ir.config_parameter'].sudo().get_param('lox_backup.connection_status', 'unknown')
93 record.lox_connection_status = status
95 def _compute_lox_stats(self):
96 for record in self:
97 logs = self.env['lox.backup.log'].search([
98 ('status', '=', 'completed'),
99 ])
100 record.lox_total_backups = len(logs)
101 if logs:
102 record.lox_last_backup = max(logs.mapped('create_date'))
103 else:
104 record.lox_last_backup = False
106 def action_lox_test_connection(self):
107 """Test API connection"""
108 api_url = self.env['ir.config_parameter'].sudo().get_param('lox_backup.api_url', 'https://api.lox.io')
109 api_key = self.env['ir.config_parameter'].sudo().get_param('lox_backup.api_key', '')
111 if not api_key:
112 raise UserError(_('Please enter your LOX API key first and save the settings.'))
114 api = self.env['lox.api'].create_client_from_params(api_url, api_key)
116 try:
117 result = api.test_connection()
118 if result.get('success'):
119 self.env['ir.config_parameter'].sudo().set_param('lox_backup.connection_status', 'connected')
120 return {
121 'type': 'ir.actions.client',
122 'tag': 'display_notification',
123 'params': {
124 'title': _('Success'),
125 'message': _('Connection to LOX API successful! Tenant: %s') % result.get('data', {}).get('name', 'Unknown'),
126 'type': 'success',
127 'sticky': False,
128 }
129 }
130 else:
131 self.env['ir.config_parameter'].sudo().set_param('lox_backup.connection_status', 'error')
132 raise UserError(_('Connection failed: %s') % result.get('error', 'Unknown error'))
133 except UserError:
134 raise
135 except Exception as e:
136 self.env['ir.config_parameter'].sudo().set_param('lox_backup.connection_status', 'error')
137 raise UserError(_('Connection failed: %s') % str(e))
139 def action_lox_register_source(self):
140 """Register this Odoo instance as a backup source"""
141 api_url = self.env['ir.config_parameter'].sudo().get_param('lox_backup.api_url', 'https://api.lox.io')
142 api_key = self.env['ir.config_parameter'].sudo().get_param('lox_backup.api_key', '')
144 if not api_key:
145 raise UserError(_('Please enter your LOX API key first and save the settings.'))
147 api = self.env['lox.api'].create_client_from_params(api_url, api_key)
149 # Get Odoo info
150 db_name = self.env.cr.dbname
151 odoo_version = self.env['ir.module.module'].search([
152 ('name', '=', 'base')
153 ], limit=1).installed_version or 'unknown'
155 base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url', '')
157 source_data = {
158 'name': f'Odoo - {db_name}',
159 'source_type': 'odoo',
160 'metadata': {
161 'database': db_name,
162 'odoo_version': odoo_version,
163 'base_url': base_url,
164 }
165 }
167 try:
168 result = api.register_source(source_data)
169 if result.get('id'):
170 self.env['ir.config_parameter'].sudo().set_param('lox_backup.source_id', result['id'])
171 self.env['ir.config_parameter'].sudo().set_param('lox_backup.source_registered', 'True')
172 return {
173 'type': 'ir.actions.client',
174 'tag': 'display_notification',
175 'params': {
176 'title': _('Success'),
177 'message': _('Source registered successfully with ID: %s') % result['id'],
178 'type': 'success',
179 'sticky': False,
180 }
181 }
182 else:
183 raise UserError(_('Registration failed: %s') % result.get('error', 'Unknown error'))
184 except UserError:
185 raise
186 except Exception as e:
187 raise UserError(_('Registration failed: %s') % str(e))
189 def action_lox_run_backup(self):
190 """Open backup wizard"""
191 source_registered = self.env['ir.config_parameter'].sudo().get_param('lox_backup.source_registered', 'False')
193 if source_registered != 'True':
194 raise UserError(_('Please register the source first using the "Register Source" button.'))
196 return {
197 'name': _('Run Backup'),
198 'type': 'ir.actions.act_window',
199 'res_model': 'lox.backup.wizard',
200 'view_mode': 'form',
201 'target': 'new',
202 }
204 def action_lox_view_backups(self):
205 """View all backup logs"""
206 return {
207 'name': _('Backup History'),
208 'type': 'ir.actions.act_window',
209 'res_model': 'lox.backup.log',
210 'view_mode': 'tree,form',
211 }
213 def action_lox_view_schedules(self):
214 """View all backup schedules"""
215 return {
216 'name': _('Backup Schedules'),
217 'type': 'ir.actions.act_window',
218 'res_model': 'lox.backup.schedule',
219 'view_mode': 'tree,form',
220 }
222 def action_lox_view_profiles(self):
223 """View all backup profiles"""
224 return {
225 'name': _('Backup Profiles'),
226 'type': 'ir.actions.act_window',
227 'res_model': 'lox.backup.profile',
228 'view_mode': 'tree,form',
229 }