254 lines
12 KiB
Python
254 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import random
|
|
import requests
|
|
from urllib.parse import urlencode
|
|
import uuid
|
|
from odoo import models, fields, api, tools, _
|
|
from odoo.exceptions import UserError, ValidationError
|
|
|
|
|
|
class SlideChannel(models.Model):
|
|
_inherit = 'slide.channel'
|
|
|
|
uuid = fields.Char('UUID', required=True, copy=False, readonly=True, default=lambda self: uuid.uuid4(),
|
|
tracking=True)
|
|
code = fields.Char('Code', required=True, copy=False, readonly=True, default=lambda self: _('New'), tracking=True)
|
|
instance_arrangement = fields.Selection(
|
|
[('share', 'Share'), ('exclude', 'Exclude'), ('both', 'Both'), ('no_need', 'No Need')], required=True,
|
|
default="no_need", string="Instance Arrangement")
|
|
|
|
shared_instance_count = fields.Integer('Shared Instance Count', default=1)
|
|
instance_base = fields.Many2one('ospp.instance', string="Instance Base")
|
|
instance_ids = fields.One2many('channel.instance', 'channel_id', string="Instances")
|
|
shared_instance_demo_data = fields.Boolean('Shared Instance Demo Data', default=True)
|
|
excluded_instance_demo_data = fields.Boolean('Excluded Instance Demo Data', default=False)
|
|
|
|
# @api.depends('slide_partner_ids')
|
|
def action_generate_instance(self):
|
|
instance_obj = self.env['channel.instance'].sudo()
|
|
partner_obj = self.env['slide.channel.partner'].sudo()
|
|
for rec in self:
|
|
if rec.instance_arrangement not in ['no_need'] and not (rec.instance_arrangement and rec.instance_base):
|
|
raise ValidationError(_("No Instance Arrangement or Base provided!"))
|
|
|
|
partner_ids = partner_obj.search([('channel_id', '=', rec.id)])
|
|
|
|
rec.message_unsubscribe(partner_ids=[x.partner_id.id for x in partner_ids])
|
|
|
|
if not rec.instance_ids:
|
|
if rec.instance_arrangement in ['share', 'both']:
|
|
vals = []
|
|
for i in range(rec.shared_instance_count):
|
|
service_name = f"{rec.code}{i}"
|
|
val = {
|
|
"name": service_name,
|
|
"channel_id": rec.id,
|
|
"instance_id": rec.instance_base and rec.instance_base.id,
|
|
"service_name": service_name,
|
|
"service_url": f"{rec.instance_base.service_scheme}://{service_name}.{rec.instance_base.service_base_host}",
|
|
"admin_account": f"{rec.user_id.email}",
|
|
"admin_password": f"{random.randint(10000000,99999999)}",
|
|
"user_scope": [(6, 0, partner_ids.ids)],
|
|
"type": "share",
|
|
"demo_data": rec.shared_instance_demo_data
|
|
}
|
|
vals.append(val)
|
|
instance_obj.create(vals)
|
|
|
|
if rec.instance_arrangement in ['exclude', 'both']:
|
|
vals = []
|
|
for partner_id in partner_ids:
|
|
service_name = f"{rec.code}{partner_id.partner_id.code}"
|
|
val = {
|
|
"name": service_name,
|
|
"channel_id": rec.id,
|
|
"instance_id": rec.instance_base and rec.instance_base.id,
|
|
"service_name": service_name,
|
|
"service_url": f"{rec.instance_base.service_scheme}://{service_name}.{rec.instance_base.service_base_host}",
|
|
"admin_account": f"{partner_id.partner_email}",
|
|
"admin_password": f"{random.randint(10000000,99999999)}",
|
|
"user_scope": [(6, 0, partner_id.ids)],
|
|
"type": "exclude",
|
|
"demo_data": rec.excluded_instance_demo_data
|
|
}
|
|
vals.append(val)
|
|
instance_obj.create(vals)
|
|
else:
|
|
if rec.instance_arrangement in ['share', 'both']:
|
|
vals = []
|
|
for i in range(rec.shared_instance_count):
|
|
service_name = f"{rec.code}{i}"
|
|
instance_id = instance_obj.search([('name', '=', service_name), ('channel_id', '=', rec.id)])
|
|
if not instance_id:
|
|
val = {
|
|
"name": service_name,
|
|
"channel_id": rec.id,
|
|
"instance_id": rec.instance_base and rec.instance_base.id,
|
|
"service_name": service_name,
|
|
"service_url": f"{rec.instance_base.service_scheme}://{service_name}.{rec.instance_base.service_base_host}",
|
|
"admin_account": f"{rec.user_id.email}",
|
|
"admin_password": f"{random.randint(10000000,99999999)}",
|
|
"user_scope": [(6, 0, partner_ids.ids)],
|
|
"type": "share",
|
|
"demo_data": rec.shared_instance_demo_data
|
|
}
|
|
vals.append(val)
|
|
if vals:
|
|
instance_obj.create(vals)
|
|
|
|
if rec.instance_arrangement in ['exclude', 'both']:
|
|
vals = []
|
|
for partner_id in partner_ids:
|
|
service_name = f"{rec.code}{partner_id.partner_id.code}"
|
|
instance_id = instance_obj.search([('name', '=', service_name), ('channel_id', '=', rec.id)])
|
|
if not instance_id:
|
|
val = {
|
|
"name": service_name,
|
|
"channel_id": rec.id,
|
|
"instance_id": rec.instance_base and rec.instance_base.id,
|
|
"service_name": service_name,
|
|
"service_url": f"{rec.instance_base.service_scheme}://{service_name}.{rec.instance_base.service_base_host}",
|
|
"admin_account": f"{partner_id.partner_email}",
|
|
"admin_password": f"{random.randint(10000000,99999999)}",
|
|
"user_scope": [(6, 0, partner_id.ids)],
|
|
"type": "exclude",
|
|
"demo_data": rec.excluded_instance_demo_data
|
|
}
|
|
vals.append(val)
|
|
if vals:
|
|
instance_obj.create(vals)
|
|
|
|
def name_get(self):
|
|
# Prefetch the fields used by the `name_get`, so `browse` doesn't fetch other fields
|
|
self.browse(self.ids).read(['name', 'code'])
|
|
return [(channel.id, '%s%s' % (channel.code and '[%s] ' % channel.code or '', channel.name))
|
|
for channel in self]
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
if 'company_id' in vals:
|
|
self = self.with_company(vals['company_id'])
|
|
if vals.get('code', _("New")) == _("New"):
|
|
seq_date = None
|
|
vals['code'] = self.env['ir.sequence'].next_by_code('slide.channel', sequence_date=seq_date) or _("New")
|
|
|
|
return super().create(vals_list)
|
|
|
|
|
|
class ChannelInstance(models.Model):
|
|
_name = "channel.instance"
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
_description = "Channel Instance"
|
|
|
|
sequence = fields.Integer('Sequence', default=10)
|
|
uuid = fields.Char(
|
|
'UUID', required=True, copy=False, readonly=True, default=lambda self: uuid.uuid4(), tracking=True)
|
|
code = fields.Char('Code', required=True, copy=False, readonly=True, default=lambda self: _('New'), tracking=True)
|
|
channel_id = fields.Many2one('slide.channel', required=True, string="Channel")
|
|
instance_id = fields.Many2one('ospp.instance', required=True, string="Instance")
|
|
name = fields.Char('Name', required=True)
|
|
service_name = fields.Char('Service Name', required=True)
|
|
service_url = fields.Char('Service URL', required=True)
|
|
user_scope = fields.Many2many('slide.channel.partner', string="User Scope")
|
|
admin_account = fields.Char('Admin Account')
|
|
admin_password = fields.Char('Admin Password')
|
|
active = fields.Boolean('Active', default=True)
|
|
type = fields.Selection([('share', 'Share'), ('exclude', 'Exclude')], string="Type", required=True, default='share')
|
|
instance_created = fields.Boolean('Instance Created', default=False)
|
|
message = fields.Text('Message')
|
|
demo_data = fields.Boolean('Demo Data', default=True)
|
|
is_notified = fields.Boolean('Is Notified', default=False)
|
|
|
|
def action_post_instance(self):
|
|
"""
|
|
发送实训环境地址和登录信息给用户...
|
|
:return:
|
|
"""
|
|
partner_obj = self.env['slide.channel.partner'].sudo()
|
|
for rec in self:
|
|
subject = f"通知: 《{rec.channel_id.name}》实训环境已经生成"
|
|
html_body = f"""
|
|
<div>@{', '.join([x.partner_id.name for x in rec.user_scope])} 您的实训环境已经创建!\n </div>
|
|
<div>环境: {rec.service_url} \n</div>
|
|
<div>账号: {rec.admin_account} \n</div>
|
|
<div>密码: {rec.admin_password} \n</div>
|
|
<div>课程: {self.env['ir.config_parameter'].sudo().get_param("web.base.url")}/slides/{rec.channel_id.id} \n</div>
|
|
|
|
<div>预祝学习愉快!</div>
|
|
"""
|
|
partner_ids = partner_obj.search([('channel_id', '=', rec.channel_id.id)])
|
|
rec.channel_id.message_unsubscribe(partner_ids=[x.partner_id.id for x in partner_ids])
|
|
|
|
partner_ids = [x.partner_id.id for x in rec.user_scope]
|
|
kwargs = {}
|
|
rec.channel_id.with_context(mail_create_nosubscribe=True).message_post(
|
|
subject=subject,
|
|
body=html_body,
|
|
subtype_xmlid='website_slides.mt_channel_slide_published',
|
|
email_layout_xmlid='mail.mail_notification_light',
|
|
partner_ids=partner_ids,
|
|
notified_partner_ids=[],
|
|
**kwargs,
|
|
)
|
|
rec.is_notified = True
|
|
return True
|
|
|
|
def action_generate_instance(self):
|
|
for rec in self:
|
|
if rec.instance_created:
|
|
return True
|
|
|
|
url = f"{rec.instance_id.management_api}/web/database/create"
|
|
master_pwd = f"{rec.instance_id.management_secret}"
|
|
dbname = rec.service_name
|
|
login = rec.admin_account
|
|
password = rec.admin_password
|
|
phone = ''
|
|
lang = 'zh_CN'
|
|
country_code = 'cn'
|
|
demo = 1 if rec.demo_data else 0
|
|
|
|
headers = {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
'Cookie': 'frontend_lang=en_US; session_id=645c41edf8f8c7e1e983ba0f5bd9e94d9a3bd4bc'
|
|
}
|
|
|
|
payload = {
|
|
'master_pwd': master_pwd,
|
|
'name': dbname,
|
|
'login': login,
|
|
'password': password,
|
|
'phone': phone,
|
|
'lang': lang,
|
|
'country_code': country_code,
|
|
'demo': demo
|
|
}
|
|
|
|
response = requests.request("POST", url, headers=headers, data=urlencode(payload), verify=False)
|
|
rec.message = response.text
|
|
if response.status_code == 200 and 'error' not in response.text:
|
|
rec.instance_created = True
|
|
return True
|
|
|
|
def name_get(self):
|
|
# Prefetch the fields used by the `name_get`, so `browse` doesn't fetch other fields
|
|
self.browse(self.ids).read(['name', 'code'])
|
|
return [(channel.id, '%s%s' % (channel.code and '[%s] ' % channel.code or '', channel.name))
|
|
for channel in self]
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
if 'company_id' in vals:
|
|
self = self.with_company(vals['company_id'])
|
|
if vals.get('code', _("New")) == _("New"):
|
|
seq_date = None
|
|
vals['code'] = self.env['ir.sequence'].next_by_code(
|
|
'channel.instance', sequence_date=seq_date) or _("New")
|
|
|
|
return super().create(vals_list)
|
|
|
|
|