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

1# -*- coding: utf-8 -*- 

2 

3from odoo import models, fields, api, _ 

4from odoo.exceptions import UserError 

5import logging 

6 

7_logger = logging.getLogger(__name__) 

8 

9 

10class ResConfigSettings(models.TransientModel): 

11 _inherit = 'res.config.settings' 

12 

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 ) 

36 

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 ) 

56 

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 ) 

64 

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 ) 

72 

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') 

79 

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 ) 

88 

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 

94 

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 

105 

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', '') 

110 

111 if not api_key: 

112 raise UserError(_('Please enter your LOX API key first and save the settings.')) 

113 

114 api = self.env['lox.api'].create_client_from_params(api_url, api_key) 

115 

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)) 

138 

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', '') 

143 

144 if not api_key: 

145 raise UserError(_('Please enter your LOX API key first and save the settings.')) 

146 

147 api = self.env['lox.api'].create_client_from_params(api_url, api_key) 

148 

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' 

154 

155 base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url', '') 

156 

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 } 

166 

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)) 

188 

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') 

192 

193 if source_registered != 'True': 

194 raise UserError(_('Please register the source first using the "Register Source" button.')) 

195 

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 } 

203 

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 } 

212 

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 } 

221 

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 }