class HrEmployeeLanguage(models.Model): _name = 'hr.employee.language' _description = 'HR Employee Language' name = fields.Selection( tools.scan_languages(), string="Language", required=True, ) description = fields.Char(size=64, ) employee_id = fields.Many2one( 'hr.employee', string="Employee", required=True, ) can_read = fields.Boolean( string="Read", default=True, ) can_write = fields.Boolean( string="Write", default=True, ) can_speak = fields.Boolean( string="Speak", default=True, ) can_listen = fields.Boolean( string="Listen", default=True, )
class HrLanguage(models.Model): _name = 'hr.language' name = fields.Selection( tools.scan_languages(), "Language", required=True, ) description = fields.Char( "Description", size=64, required=True, ) employee_id = fields.Many2one( 'hr.employee', "Employee", required=True, ) can_read = fields.Boolean( "Read", default=True, oldname='read', ) can_write = fields.Boolean( "Write", default=True, oldname='write', ) can_speak = fields.Boolean( "Speak", default=True, oldname='speak', )
class SaasPortalPlan(models.Model): _name = 'saas_portal.plan' name = fields.Char('Plan', required=True) summary = fields.Char('Summary') template_id = fields.Many2one('saas_portal.database', 'Template', ondelete='restrict') demo = fields.Boolean('Install Demo Data') maximum_allowed_dbs_per_partner = fields.Integer(help='maximum allowed non-trial databases per customer', require=True, default=0) maximum_allowed_trial_dbs_per_partner = fields.Integer(help='maximum allowed trial databases per customer', require=True, default=0) max_users = fields.Char('Initial Max users', default='0') total_storage_limit = fields.Integer('Total storage limit (MB)') block_on_expiration = fields.Boolean('Block clients on expiration', default=False) block_on_storage_exceed = fields.Boolean('Block clients on storage exceed', default=False) def _get_default_lang(self): return self.env.lang def _default_tz(self): return self.env.user.tz lang = fields.Selection(scan_languages(), 'Language', default=_get_default_lang) tz = fields.Selection(_tz_get, 'TimeZone', default=_default_tz) sequence = fields.Integer('Sequence') state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', compute='_get_state', store=True) expiration = fields.Integer('Expiration (hours)', help='time to delete database. Use for demo') _order = 'sequence' dbname_template = fields.Char('DB Names', help='Used for generating client database domain name. Use %i for numbering. Ignore if you use manually created db names', placeholder='crm-%i.odoo.com') server_id = fields.Many2one('saas_portal.server', string='SaaS Server', ondelete='restrict', help='User this saas server or choose random') website_description = fields.Html('Website description') logo = fields.Binary('Logo') @api.one @api.depends('template_id.state') def _get_state(self): if self.template_id.state == 'template': self.state = 'confirmed' else: self.state = 'draft' @api.one def _new_database_vals(self, vals): vals['max_users'] = self.max_users vals['total_storage_limit'] = self.total_storage_limit vals['block_on_expiration'] = self.block_on_expiration vals['block_on_storage_exceed'] = self.block_on_storage_exceed return vals @api.multi def create_new_database(self, **kwargs): return self._create_new_database(**kwargs) @api.multi def _create_new_database(self, dbname=None, client_id=None, partner_id=None, user_id=None, notify_user=False, trial=False, support_team_id=None, async=None, owner_password=None):
class ProductAttributeValueSaaS(models.Model): _inherit = "product.attribute.value" def _get_default_lang(self): return self.env.user.lang saas_lang = fields.Selection(scan_languages(), 'Language', default=_get_default_lang) template_ids = fields.Many2many('saas_portal.database', 'product_attribute_value_saas_templates', 'value_id', 'template_id', string='SaaS Templates')
class PartnerLanguange(models.Model): _name = "partner.language" _description = "Contact Language Proficiency" name = fields.Selection( selection=tools.scan_languages(), string="Language", required=True ) description = fields.Char(string="Description", size=64, required=False) partner_id = fields.Many2one( comodel_name="res.partner", string="Partner", required=True ) read_rating = fields.Selection( string="Reading", selection=LANGUAGE_RATING, required=True, default="0", ) write_rating = fields.Selection( string="Writing", selection=LANGUAGE_RATING, required=True, default="0", ) speak_rating = fields.Selection( string="Speaking", selection=LANGUAGE_RATING, required=True, default="0", ) listen_rating = fields.Selection( string="Listening", selection=LANGUAGE_RATING, required=True, default="0", ) @api.constrains( "partner_id", "name", ) def _check_no_duplicate_language(self): obj_language = self.env["partner.language"] for language in self: criteria = [ ("id", "!=", language.id), ("partner_id", "=", language.partner_id.id), ("name", "=", language.name), ] result = obj_language.search_count(criteria) if result > 0: msg = _("No duplicate language") raise UserError(msg)
class SaasPortalAddExistingDatabase(models.TransientModel): """ Model to add an existing template db """ _name = 'saas_portal.add_existing_template' @api.model def _get_default_name_txt(self): return "%s %s" % (self.subdomain or '', self.db_primary_lang or '') subdomain = fields.Char(string='Subdomain', required=False) name_txt = fields.Char('Name', required=True, default=_get_default_name_txt) server_id = fields.Many2one('saas_portal.server', string='Server', required=True) domain = fields.Char(related='server_id.name', string='Server Domain', readonly=True) db_primary_lang = fields.Selection(scan_languages(), 'Database primary language') plan_id = fields.Many2one('saas_portal.plan', string='Add To Plan') password = fields.Char(required=True) @api.multi def add(self): new_db = self.subdomain + '.' + self.server_id.domain saas_portal_database = self.env['saas_portal.database'] if saas_portal_database.search([('name', '=', new_db)]): raise ValidationError( _("This database already exists: " "'%s'") % new_db) vals = { 'subdomain': self.subdomain, 'name_txt': self.name_txt, 'server_id': self.server_id.id, 'state': 'template', 'db_type': 'template', 'db_primary_lang': self.db_primary_lang, 'password': self.password, } if self.plan_id: vals.update(plan_ids=[(4, self.plan_id.id)]) new_template = saas_portal_database.create(vals) if self.plan_id and not self.plan_id.template_id: self.plan_id.template_id = new_template.id return {'type': 'ir.actions.act_window_close'}
class hr_language(models.Model): _name = 'hr.language' _inherit = ['mail.thread'] name = fields.Selection( tools.scan_languages(), string='Language', required=True, ) employee_id = fields.Many2one('hr.employee', string='Employee', required=True) can_read = fields.Selection(AVAILABLE_PRIORITIES, 'Read') can_write = fields.Selection(AVAILABLE_PRIORITIES, 'Write') can_speak = fields.Selection(AVAILABLE_PRIORITIES, 'Speak') date = fields.Date('Update date') note = fields.Text('Commentaires', translate=True)
class SaasClient(models.AbstractModel): """ This model is used or inherited by modules as: saas_portal.client and saas_server.client """ _name = 'saas_base.client' _description = 'SaaS client instances base data' users_len = fields.Integer('Count users', readonly=True, help='Actual created internal users') max_users = fields.Char('Max users allowed', readonly=True, help='Overall internal user limit') file_storage = fields.Integer('File storage (MB)', readonly=True, help='Used file storage') db_storage = fields.Integer('DB storage (MB)', readonly=True, help='Used database storage') total_storage_limit = fields.Integer('Total storage limit (MB)', readonly=True, default=0, help='Overall storage limit') # Following fields where in saas_portal.client before total_storage = fields.Integer('Used storage (MB)', compute='_get_storage_client_sum', help='from Client') trial = fields.Boolean('Trial', help='indication of trial clients', default=False, readonly=True) client_primary_lang = fields.Selection(scan_languages(), 'Primary language', readonly=False) expiration_datetime = fields.Datetime(string="Expiration") expired = fields.Boolean('Expired') @api.multi # @api.depends('state') def _get_storage_client_sum(self): for record in self: record.total_storage = record.file_storage + record.db_storage
class SaasPortalPlan(models.Model): _name = 'saas_portal.plan' name = fields.Char('Plan', required=True) summary = fields.Char('Summary') template_id = fields.Many2one('saas_portal.database', 'Template', ondelete='restrict') demo = fields.Boolean('Install Demo Data') maximum_allowed_dbs_per_partner = fields.Integer( help='maximum allowed non-trial databases per customer', require=True, default=0) maximum_allowed_trial_dbs_per_partner = fields.Integer( help='maximum allowed trial databases per customer', require=True, default=0) max_users = fields.Char('Initial Max users', default='0') total_storage_limit = fields.Integer('Total storage limit (MB)') block_on_expiration = fields.Boolean('Block clients on expiration', default=False) block_on_storage_exceed = fields.Boolean('Block clients on storage exceed', default=False) def _get_default_lang(self): return self.env.lang def _default_tz(self): return self.env.user.tz lang = fields.Selection(scan_languages(), 'Language', default=_get_default_lang) tz = fields.Selection(_tz_get, 'TimeZone', default=_default_tz) sequence = fields.Integer('Sequence') state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', compute='_get_state', store=True) expiration = fields.Integer('Expiration (hours)', help='time to delete database. Use for demo') _order = 'sequence' grace_period = fields.Integer('Grace period (days)', help='initial days before expiration') dbname_template = fields.Char( 'DB Names', help= 'Used for generating client database domain name. Use %i for numbering. Ignore if you use manually created db names', placeholder='crm-%i.odoo.com') server_id = fields.Many2one('saas_portal.server', string='SaaS Server', ondelete='restrict', help='User this saas server or choose random') website_description = fields.Html('Website description') logo = fields.Binary('Logo') on_create = fields.Selection([ ('login', 'Log into just created instance'), ], string="Workflow on create", default='login') on_create_email_template = fields.Many2one( 'mail.template', default=lambda self: self.env.ref( 'saas_portal.email_template_create_saas')) @api.one @api.depends('template_id.state') def _get_state(self): if self.template_id.state == 'template': self.state = 'confirmed' else: self.state = 'draft' @api.multi def _new_database_vals(self, vals): self.ensure_one() vals['max_users'] = self.max_users vals['total_storage_limit'] = self.total_storage_limit vals['block_on_expiration'] = self.block_on_expiration vals['block_on_storage_exceed'] = self.block_on_storage_exceed return vals @api.multi def _prepare_owner_user_data(self, user_id): """ Prepare the dict of values to update owner user data in client instalnce. This method may be overridden to implement custom values (making sure to call super() to establish a clean extension chain). """ self.ensure_one() owner_user = self.env['res.users'].browse(user_id) or self.env.user owner_user_data = { 'user_id': owner_user.id, 'login': owner_user.login, 'name': owner_user.name, 'email': owner_user.email, 'password_crypt': owner_user.password_crypt, } return owner_user_data @api.multi def create_new_database(self, **kwargs): return self._create_new_database(**kwargs) @api.multi def _create_new_database(self, dbname=None, client_id=None, partner_id=None, user_id=None, notify_user=False, trial=False, support_team_id=None, async=None): self.ensure_one() server = self.server_id if not server: server = self.env['saas_portal.server'].get_saas_server() # server.action_sync_server() if not partner_id and user_id: user = self.env['res.users'].browse(user_id) partner_id = user.partner_id.id if not trial and self.maximum_allowed_dbs_per_partner != 0: db_count = self.env['saas_portal.client'].search_count([ ('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', False) ]) if db_count >= self.maximum_allowed_dbs_per_partner: raise MaximumDBException( "Limit of databases for this plan is %(maximum)s reached" % {'maximum': self.maximum_allowed_dbs_per_partner}) if trial and self.maximum_allowed_trial_dbs_per_partner != 0: trial_db_count = self.env['saas_portal.client'].search_count([ ('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', True) ]) if trial_db_count >= self.maximum_allowed_trial_dbs_per_partner: raise MaximumTrialDBException( "Limit of trial databases for this plan is %(maximum)s reached" % {'maximum': self.maximum_allowed_trial_dbs_per_partner}) vals = { 'name': dbname or self.generate_dbname(), 'server_id': server.id, 'plan_id': self.id, 'partner_id': partner_id, 'trial': trial, 'support_team_id': support_team_id, } client = None if client_id: vals['client_id'] = client_id client = self.env['saas_portal.client'].search([('client_id', '=', client_id)]) vals = self._new_database_vals(vals) if client: client.write(vals) else: client = self.env['saas_portal.client'].create(vals) client_id = client.client_id owner_user_data = self._prepare_owner_user_data(user_id) client.period_initial = trial and self.expiration trial_expiration_datetime = ( fields.Datetime.from_string(client.create_date) + timedelta(hours=client.period_initial) ).strftime(DEFAULT_SERVER_DATETIME_FORMAT) initial_expiration_datetime = ( fields.Datetime.from_string(client.create_date) + timedelta( self.grace_period)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) state = { 'd': client.name, 'public_url': client.public_url, 'e': trial and trial_expiration_datetime or initial_expiration_datetime, 'r': client.public_url + 'web', 'owner_user': owner_user_data, 't': client.trial, } if self.template_id: state.update({'db_template': self.template_id.name}) scope = ['userinfo', 'force_login', 'trial', 'skiptheuse'] req, req_kwargs = server._request_server( path='/saas_server/new_database', state=state, client_id=client_id, scope=scope, ) res = requests.Session().send(req, **req_kwargs) if res.status_code != 200: raise Warning('Error on request: %s\nReason: %s \n Message: %s' % (req.url, res.reason, res.content)) data = simplejson.loads(res.text) params = { 'state': data.get('state'), 'access_token': client.oauth_application_id._get_access_token(user_id, create=True), } url = '{url}?{params}'.format(url=data.get('url'), params=werkzeug.url_encode(params)) auth_url = url # send email if there is mail template record template = self.on_create_email_template if template: client.message_post_with_template(template.id, composition_mode='comment') client.write({ 'expiration_datetime': trial and trial_expiration_datetime or initial_expiration_datetime }) client.send_params_to_client_db() # TODO make async call of action_sync_server here # client.server_id.action_sync_server() client.sync_client() return { 'url': url, 'id': client.id, 'client_id': client_id, 'auth_url': auth_url }
class SaasPortalPlan(models.Model): _name = 'saas_portal.plan' name = fields.Char('Plan', required=True) summary = fields.Char('Summary') template_id = fields.Many2one('saas_portal.database', 'Template', ondelete='restrict') demo = fields.Boolean('Install Demo Data') maximum_allowed_dbs_per_partner = fields.Integer(help='maximum allowed non-trial databases per customer', require=True, default=0) maximum_allowed_trial_dbs_per_partner = fields.Integer(help='maximum allowed trial databases per customer', require=True, default=0) max_users = fields.Char('Initial Max users', default='0') total_storage_limit = fields.Integer('Total storage limit (MB)') block_on_expiration = fields.Boolean('Block clients on expiration', default=False) block_on_storage_exceed = fields.Boolean('Block clients on storage exceed', default=False) def _get_default_lang(self): return self.env.lang def _default_tz(self): return self.env.user.tz lang = fields.Selection(scan_languages(), 'Language', default=_get_default_lang) tz = fields.Selection(_tz_get, 'TimeZone', default=_default_tz) sequence = fields.Integer('Sequence') state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', compute='_get_state', store=True) expiration = fields.Integer('Expiration (hours)', help='time to delete database. Use for demo') _order = 'sequence' grace_period = fields.Integer('Grace period (days)', help='initial days before expiration') dbname_template = fields.Char('DB Names', help='Used for generating client database domain name. Use %i for numbering. Ignore if you use manually created db names', placeholder='crm-%i.odoo.com') server_id = fields.Many2one('saas_portal.server', string='SaaS Server', ondelete='restrict', help='User this saas server or choose random') website_description = fields.Html('Website description') logo = fields.Binary('Logo') on_create = fields.Selection([ ('login', 'Log into just created instance'), ('email', 'Go to information page that says to check email for credentials') ], string="Workflow on create", default='email') on_create_email_template = fields.Many2one('mail.template', default=lambda self: self.env.ref('saas_portal.email_template_create_saas')) @api.one @api.depends('template_id.state') def _get_state(self): if self.template_id.state == 'template': self.state = 'confirmed' else: self.state = 'draft' @api.multi def _new_database_vals(self, vals): self.ensure_one() vals['max_users'] = self.max_users vals['total_storage_limit'] = self.total_storage_limit vals['block_on_expiration'] = self.block_on_expiration vals['block_on_storage_exceed'] = self.block_on_storage_exceed return vals @api.multi def _prepare_owner_user_data(self, owner_user, owner_password): """ Prepare the dict of values to update owner user data in client instalnce. This method may be overridden to implement custom values (making sure to call super() to establish a clean extension chain). """ self.ensure_one() owner_user_data = { 'user_id': owner_user.id, 'login': owner_user.login, 'password': owner_password, 'name': owner_user.name, 'email': owner_user.email, } return owner_user_data @api.multi def create_new_database(self, **kwargs): return self._create_new_database(**kwargs) @api.multi def _create_new_database(self, dbname=None, client_id=None, partner_id=None, user_id=None, notify_user=False, trial=False, support_team_id=None, async=None, owner_password=None):
class SaasDuplicateTemplateWizard(models.TransientModel): _name = 'saas_portal.duplicate_template.wizard' _description = 'SaaS Portal Duplicate Template Wizard' @api.model def _get_template_id(self): return self._context.get('active_id', False) template_id = fields.Many2one(comodel_name="saas_portal.database", string="Template", required=True, ondelete="cascade", default=_get_template_id, auto_join=True) template_domain = fields.Char(related='template_id.domain', store=True, string='Domain', readonly=True) new_name = fields.Char(string="New subdomain name") lang = fields.Selection(scan_languages(), 'Language') @api.multi def registry(self, new=False, **kwargs): self.ensure_one() m = odoo.modules.registry.Registry return m.new(self.new_name + '.' + self.template_id.domain, **kwargs) @api.multi def duplicate_template(self): new_db = self.new_name + '.' + self.template_id.domain if self.template_id: saas_portal_database = self.env['saas_portal.database'] if saas_portal_database.search([('name', '=', new_db)]): raise ValidationError( _("This database already exists: " "'%s'") % new_db) db._drop_conn(self.env.cr, self.template_id.name) db.exp_duplicate_database(self.template_id.name, new_db) new_template = saas_portal_database.create({ 'subdomain': self.new_name, 'server_id': self.template_id.server_id.id, 'db_primary_lang': self.lang, 'state': 'template', 'db_type': 'template' }) if self.lang: with self.registry().cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, self._context) # load a new language: load_language(env.cr, self.lang) # set this language for all partner records: for partner in env['res.partner'].search([]): partner.lang = self.lang # if website is installed, also load the language if env['ir.module.module'].search([ ('name', '=', 'website') ]).state in ('installed', 'to upgrade'): website = env["website"].get_current_website() wiz = env["base.language.install"].create( {"lang": self.lang}) wiz.website_ids = website wiz.lang_install() res_lang_id = env['res.lang'].search([('code', '=', self.lang)]) if res_lang_id: # make it a default website language website.default_lang_id = res_lang_id action = self.env.ref('saas_portal.action_templates').read()[0] if action: action['views'] = [ (self.env.ref('saas_portal.view_databases_form').id, 'form') ] action['res_id'] = new_template.ids[0] else: action = {'type': 'ir.actions.act_window_close'} return action
def _get_lang(self): return tools.scan_languages()
class SaasPortalDatabase(models.Model): # gets inherited by saas_portal.client _name = 'saas_portal.database' _description = 'Saas database instances' _inherits = {'oauth.application': 'oauth_application_id'} _order = 'identifier' @api.model def _get_default_name_txt(self): return "%s %s" % (self.name or '', self.db_primary_lang or '') @api.multi @api.depends('subdomain', 'domain') def _compute_db_name(self): for record in self: subdomain = record.subdomain domain = record.domain record.name = "%s.%s" % (subdomain, domain) name = fields.Char('Database name', compute='_compute_db_name', store=True) name_txt = fields.Char('Name', required=True, default=_get_default_name_txt) identifier = fields.Char('Identifier', readonly=True, default=lambda self: _('New')) summary = fields.Char('Summary', compute='_get_compose_summary', store=True) oauth_application_id = fields.Many2one('oauth.application', 'OAuth Application', required=True, ondelete='cascade') # Todo needs to be readonly = False for now to work, should be taken from client form. server_id = fields.Many2one('saas_portal.server', ondelete='restrict', string='Server', readonly=False, required=True) server_db_name = fields.Char(related='server_id.name', string='Server Database name', readonly=True) subdomain = fields.Char('Sub Domain', required=True) domain = fields.Char(related='server_id.name', string='Server Domain', readonly=True) server_type = fields.Selection(related='server_id.server_type', string='SaaS Server Type', readonly=True) product_type = fields.Selection( related='server_id.branch_product_type', string='Product type', readonly=True, help='Which product the SaaS Server is hosting') odoo_version = fields.Selection(related='server_id.odoo_version', string='Odoo version', readonly=True, help='Which Odoo version is hosted') state = fields.Selection([ ('draft', 'New'), ('open', 'Running'), ('open_err', 'Running with Error'), ('open_failed', 'Running Failed'), ('cancelled', 'Cancelled'), ('pending', 'Pending'), ('deleted', 'Deleted'), ('template', 'Template'), ], 'State', default='draft', track_visibility='onchange') db_type = fields.Selection([ ('client', 'Client'), ('template', 'Template'), ('other', 'Other'), ], 'DB Type', default='client', track_visibility='onchange') host = fields.Char(related='server_id.name', string='Host', readonly=True) db_primary_lang = fields.Selection(scan_languages(), 'Database primary language') public_url = fields.Char(compute='_compute_public_url') # Todo use of password is not yet clear? password = fields.Char('Default Database Password') plan_ids = fields.Many2many('saas_portal.plan', 'saas_portal_database_templates', 'template_id', 'plan_id', string='SaaS Plans') _sql_constraints = [('name_unique', 'unique(name)', 'Database name already exists.')] @api.multi def name_get(self): res = [] for record in self: if record.db_primary_lang: res.append((record.id, '%s [%s]' % (record.name, record.db_primary_lang))) else: res.append((record.id, record.name)) return res @api.multi def _get_compose_summary(self): for record in self: subdomain = record.subdomain or '' lang = record.db_primary_lang or '' summary = "Template %s, %s" % (subdomain, lang) record.summary = summary @api.model def create(self, vals): if vals.get('identifier', _('New')) == _('New'): vals['identifier'] = self.env['ir.sequence'].next_by_code( 'saas_portal.database') or _('New') if vals.get('name') and not vals.get( 'subdomain', False) and not vals.get('name_txt', False): vals['subdomain'] = vals['name'] vals['name_txt'] = vals['name'] return super(SaasPortalDatabase, self).create(vals) @api.multi def _compute_public_url(self): for record in self: scheme = record.server_id.request_scheme db_name = record.name port = record.server_id.request_port public_url = "%s://%s" % (scheme, db_name) if scheme == 'http' and port != 80 or scheme == 'https' and port != 443: public_url = public_url + ':' + str(port) record.public_url = public_url + '/' @api.multi def _backup(self): ''' call to backup database ''' self.ensure_one() state = { 'd': self.name, 'client_id': self.client_id, } req, req_kwargs = self.server_id._request_server( path='/saas_server/backup_database', state=state, client_id=self.client_id) res = requests.Session().send(req, **req_kwargs) _logger.info('backup database: %s', res.text) if not res.ok: raise Warning( _('Reason: %s \n Message: %s') % (res.reason, res.content)) data = simplejson.loads(res.text) if not isinstance(data[0], dict): raise Warning(data) if data[0]['status'] != 'success': warning = data[0].get( 'message', _('Could not backup database; please check your logs')) raise Warning(warning) return True @api.multi def action_sync_server(self): for record in self: record.server_id.action_sync_server() @api.multi def duplicate_template_button(self): view_id = self.env.ref( 'saas_portal.saas_plan_duplicate_template_wizard_form') context = self._context.copy() context.update(active_id=self.id) return { 'name': _('Duplicate A Template'), 'type': 'ir.actions.act_window', 'res_model': 'saas_portal.duplicate_template.wizard', 'view_mode': 'form', 'view_type': 'form', 'views': [(view_id.id, 'form')], 'target': 'new', 'context': context } @api.multi def delete_template(self): self.ensure_one() res = self.delete_database_server(force_delete=True) return res @api.multi def login_to_db(self): view_id = self.env.ref( 'saas_portal.saas_plan_duplicate_template_wizard_form') context = self._context.copy() context.update(active_id=self.id) return { 'name': _('Duplicate A Template'), 'type': 'ir.actions.act_window', 'res_model': 'saas_portal.duplicate_template.wizard', 'view_mode': 'form', 'view_type': 'form', 'views': [(view_id.id, 'form')], 'target': 'new', 'context': context } @api.model def _proceed_url(self, url): return { 'type': 'ir.actions.act_url', 'target': 'new', 'name': 'Redirection', 'url': url } @api.multi def _request_url(self, path): r = self[0] state = { 'd': r.name, 'host': r.host, 'public_url': r.public_url, 'client_id': r.client_id, } url = r.server_id._request(path=path, state=state, client_id=r.client_id) return url @api.multi def _request(self, path): url = self._request_url(path) return self._proceed_url(url) @api.multi def edit_database(self): """Obsolete. Use saas_portal.edit_database widget instead""" for database_obj in self: return database_obj._request('/saas_server/edit_database') @api.multi def delete_database(self): for database_obj in self: return database_obj._request('/saas_server/delete_database') @api.multi def upgrade(self, payload=None): config_obj = self.env['saas.config'] res = [] if payload is not None: # maybe use multiprocessing here for database_obj in self: res.append( config_obj.do_upgrade_database(payload.copy(), database_obj)) return res @api.multi def delete_database_server(self, **kwargs): self.ensure_one() return self._delete_database_server(**kwargs) @api.multi def _delete_database_server(self, force_delete=False): for database in self: state = { 'd': database.name, 'client_id': database.client_id, } if force_delete: state['force_delete'] = 1 req, req_kwargs = database.server_id._request_server( path='/saas_server/delete_database', state=state, client_id=database.client_id) res = requests.Session().send(req, **req_kwargs) _logger.info('delete database: %s', res.text) if res.status_code != 500: database.state = 'deleted' @api.multi def show_upgrade_wizard(self): obj = self[0] return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'saas.config', 'target': 'new', 'context': { 'default_action': 'upgrade', 'default_database': obj.name } }
class SaasPortalPlan(models.Model): _name = 'saas_portal.plan' _description = 'SaaS Plan (templates)' _order = 'sequence' name = fields.Char('Plan', required=True) summary = fields.Char('Summary') template_id = fields.Many2one('saas_portal.database', 'DB Template', required=True, ondelete='restrict') demo = fields.Boolean('Install Demo Data') maximum_allowed_dbs_per_partner = fields.Integer( help='maximum allowed non-trial databases per customer', require=True, default=10) maximum_allowed_trial_dbs_per_partner = fields.Integer( help='maximum allowed trial databases per customer', require=True, default=2) max_users = fields.Integer('Initial Max users', default='0', help='leave 0 for no limit') max_storage = fields.Integer('Total storage limit (MB)', Default=200, help='leave 0 for no limit') block_on_expiration = fields.Boolean('Block clients on expiration', default=True) block_on_storage_exceed = fields.Boolean( 'Block clients when they reach the storage limit', default=True) def _get_default_lang(self): return self.env.user.lang def _default_tz(self): return self.env.user.tz lang = fields.Selection(scan_languages(), 'Language', default=_get_default_lang) tz = fields.Selection(_tz_get, 'TimeZone', default=_default_tz) sequence = fields.Integer('Sequence') state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', compute='_compute_get_state', store=True) expiration = fields.Integer('Expiration (hours)', default=48, help='time to delete database. Use for trial') grace_period = fields.Integer('Grace period (days)', default=14, help='initial days before expiration') dbname_template = fields.Char( 'Default DB subdomain', help= 'Used for generating client database subdomain name. Use %i for numbering. ' 'Ignore if you use manually created db names', default='trial%i', placeholder='trial-crm-%i') branch_id = fields.Many2one('saas_portal.server_branch', string='SaaS Server Branch', ondelete='restrict', required=True, help='Use this Server Branch for this plan') server_id = fields.Many2one(related='branch_id.active_server', String='Active Server', help="Active Server for new instances") active_domain_name = fields.Char(related='branch_id.active_domain_name', string='Active Domain Name', help="Active Domain for new instances") domain = fields.Char(related='branch_id.active_server.domain', string='Server Domain', readonly=True) upgrade_path_ids = fields.Many2many('saas_portal.plan', 'saas_portal_plan_upgrade_rel', 'plan_id', 'upgrade_plan_id', string='Potential Plans To Upgrade To') downgrade_path_ids = fields.Many2many( 'saas_portal.plan', 'saas_portal_plan_downgrade_rel', 'plan_id', 'downgrade_plan_id', string='Potential Plans To Downgrade To') website_description = fields.Html('Website description') logo = fields.Binary('Logo') on_create = fields.Selection([ ('login', 'Log into just created instance'), ], string="Workflow on create", default='login') on_create_email_template = fields.Many2one( 'mail.template', default=lambda self: self.env.ref( 'saas_portal.email_template_create_saas')) @api.multi @api.depends('template_id.state') def _compute_get_state(self): for plan in self: if plan.template_id.state == 'template': plan.state = 'confirmed' else: plan.state = 'draft' @api.multi def _new_database_vals(self, vals): self.ensure_one() vals['max_users'] = vals.get('max_users', self.max_users) # vals['total_storage_limit'] = vals.get('total_storage_limit', # self.total_storage_limit) vals['block_on_expiration'] = vals.get('block_on_expiration', self.block_on_expiration) vals['block_on_storage_exceed'] = vals.get( 'block_on_storage_exceed', self.block_on_storage_exceed) return vals @api.multi def _prepare_owner_user_data(self, user_id): """ Prepare the dict of values to update owner user data in client instalnce. This method may be overridden to implement custom values (making sure to call super() to establish a clean extension chain). """ self.ensure_one() owner_user = self.env['res.users'].browse(user_id) or self.env.user owner_user_data = { 'user_id': owner_user.id, 'login': owner_user.login, 'name': owner_user.name, 'email': owner_user.email, 'password_crypt': owner_user.password_crypt, } return owner_user_data @api.multi def _get_expiration(self, trial): self.ensure_one() trial_hours = trial and self.expiration initial_expiration_datetime = datetime.now() trial_expiration_datetime = (initial_expiration_datetime + timedelta( hours=trial_hours)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) return trial and trial_expiration_datetime or initial_expiration_datetime.strftime( DEFAULT_SERVER_DATETIME_FORMAT) @api.multi def create_new_database(self, **kwargs): return self._create_new_database(**kwargs) @api.multi def _create_new_database(self, dbname=None, client_id=None, partner_id=None, user_id=None, notify_user=True, order_id=None, trial=False, support_team_id=None, async=None, lang=None, template_db=None):