Merge branch '16.0' of github.com:guohuadeng/app-odoo into 16.0

This commit is contained in:
Ivan x360
2023-08-22 12:08:13 +08:00
36 changed files with 495 additions and 52 deletions

View File

@@ -2,12 +2,12 @@
<odoo>
<data noupdate="0">
<!-- 时间格式 -->
<record id="base.lang_zh_CN" model="res.lang">
<record id="base.lang_zh_CN" model="res.lang" context="{'lang': 'zh_CN'}">
<field name="name">中文</field>
<field name="date_format">%Y-%m-%d</field>
<field name="time_format">%H:%M:%S</field>
</record>
<record id="base.lang_en" model="res.lang">
<record id="base.lang_en" model="res.lang" context="{'lang': 'zh_CN'}">
<field name="name">English</field>
</record>
</data>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="base.public_partner" model="res.partner">
<record id="base.public_partner" model="res.partner" context="{'lang': 'zh_CN'}">
<field name="name">公共访客用户</field>
</record>
</data>

View File

@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="sales_team.team_sales_department" model="crm.team">
<record id="sales_team.team_sales_department" model="crm.team" context="{'lang': 'zh_CN'}">
<field name="name">中国</field>
</record>
<record id="sales_team.team_sales_department" model="crm.team" context="{'lang': 'en'}">
<field name="name">China</field>
</record>
</data>
</odoo>

View File

@@ -10,7 +10,7 @@
{
'name': 'ChatGPT4,Google Bard, AiGC Center.Ai服务中心聚合全网Ai',
'version': '16.23.07.29',
'version': '16.23.08.15',
'author': 'odooai.cn',
'company': 'odooai.cn',
'maintainer': 'odooai.cn',
@@ -61,6 +61,7 @@
'views/ai_robot_views.xml',
'views/res_partner_ai_use_views.xml',
'views/res_users_views.xml',
'views/mail_channel_views.xml',
],
'assets': {
'mail.assets_messaging': [

View File

@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from . import res_partner
from . import mail_channel
from . import res_config_settings
from . import ai_robot
from . import res_partner
from . import res_partner_ai_use
from . import res_users
from . import mail_message

View File

@@ -15,8 +15,84 @@ _logger = logging.getLogger(__name__)
class Channel(models.Model):
_inherit = 'mail.channel'
def get_openai_context(self, channel_id, author_id, answer_id, minutes=30, chat_count=1):
is_private = fields.Boolean(string="私有频道", default=False, help="私人频道不公开,可邀请及清退指定用户")
# 因为 channel_member_ids 不好处理,在此增加此字段
# 主Ai
ai_partner_id = fields.Many2one(comodel_name="res.partner", string="专属主Ai", required=False,
domain=[('gpt_id', '!=', None), ('is_chat_private', '=', True)],
default=lambda self: self._app_get_m2o_default('ai_partner_id'),
help="主Ai是主要对话对象当没有@操作时由主Ai回答", )
ext_ai_partner_id = fields.Many2one(comodel_name="res.partner", string="辅助Ai",
domain=[('gpt_id', '!=', None), ('is_chat_private', '=', True)],
help="通过 @辅助Ai 可以让辅助Ai回答问题", )
description = fields.Char('Ai角色设定', help="填写后Ai将以您设定的身份与你交互你是一个在航空航天领域的专家。不填则根据问题智能处理")
set_max_tokens = fields.Selection([
('300', '简短'),
('600', '标准'),
('1000', '中等'),
('2000', '长篇'),
('3000', '超长篇'),
('32000', '32K'),
], string='响应篇幅限制', default='600', help="越大返回内容越多,计费也越多")
set_chat_count = fields.Selection([
('none', 'Ai自动判断'),
('1', '1标准'),
('3', '3强关联'),
('5', '5超强关联'),
], string="上下文相关", default='1', help="0-5设定后会将最近n次对话发给Ai有助于他更好的回答但太大费用也高")
set_temperature = fields.Selection([
('2', '天马行空'),
('1.5', '创造性'),
('1', '标准'),
('0.6', '理性'),
('0.1', '保守'),
], string="创造性", default='1', help="0-21值越大越富有想像力越小则越保守")
set_top_p = fields.Selection([
('0.9', '严谨惯性思维'),
('0.6', '标准推理'),
('0.4', '跳跃性'),
('0.1', '随便'),
], string="思维连贯性", default='0.6', help="0-1值越大越倾向大众化的连贯思维")
# 避免使用常用词
set_frequency_penalty = fields.Selection([
('2', '老学究-晦涩难懂'),
('1.5', '学院派-较多高级词'),
('1', '标准'),
('0.1', '少常用词'),
('-1', '通俗易懂'),
('-2', '大白话'),
], string='语言风格', default='1', help="-2~2值越大越少使用常用词")
set_presence_penalty = fields.Selection([
('2', '多样强迫症'),
('1.5', '新颖化'),
('1', '标准'),
('0.1', '允许常规重复'),
('-1', '允许较多重复'),
('-2', '更多强调重复'),
], string='用词多样性', default='1', help="-2~2值越大越少重复词")
# todo: 这里用 compute?
max_tokens = fields.Integer('最长响应Token', default=600, help="越大返回内容越多,计费也越多")
chat_count = fields.Integer(string="上下文数量", default=0, help="0~3设定后会将最近n次对话发给Ai有助于他更好的回答")
temperature = fields.Float(string="创造性值", default=1, help="0~2值越大越富有想像力越小则越保守")
top_p = fields.Float(string="连贯性值", default=0.6, help="0~1值越大越富有想像力越小则越保守")
frequency_penalty = fields.Float('避免常用词值', default=1, help="-2~2值越大越少使用常用词")
presence_penalty = fields.Float('避免重复词值', default=1, help="-2~2值越大越少重复词")
is_current_channel = fields.Boolean('是否当前用户默认频道', compute='_compute_is_current_channel', help='是否当前用户默认微信对话频道')
def name_get(self):
result = []
for c in self:
if c.channel_type == 'channel' and c.is_private:
pre = '[私]'
else:
pre = ''
result.append((c.id, "%s%s" % (pre, c.name or '')))
return result
def get_openai_context(self, channel_id, author_id, answer_id, minutes=30, chat_count=0):
# 上下文处理,要处理群的方式,以及独聊的方式
# azure新api 处理
context_history = []
@@ -39,7 +115,10 @@ class Channel(models.Model):
domain = expression.AND([domain, [('date', '>=', afterTime)]])
else:
domain = expression.AND([domain, [('author_id', '=', answer_id.id)]])
ai_msg_list = message_model.with_context(tz='UTC').search(domain, order="id desc", limit=chat_count)
if chat_count == 0:
ai_msg_list = []
else:
ai_msg_list = message_model.with_context(tz='UTC').search(domain, order="id desc", limit=chat_count)
for ai_msg in ai_msg_list:
# 判断这个 ai_msg 是不是ai发有才 insert。 判断 user_msg 是不是 user发的有才 insert
user_msg = ai_msg.parent_id.sudo()
@@ -95,7 +174,9 @@ class Channel(models.Model):
# 不处理 一般notify但处理欢迎
if '<div class="o_mail_notification' in message.body and message.body != _('<div class="o_mail_notification">joined the channel</div>'):
return rdata
return rdata
if 'o_odoobot_command' in message.body:
return rdata
if channel_type == 'chat':
channel_partner_ids = self.channel_partner_ids
@@ -155,7 +236,8 @@ class Channel(models.Model):
# elif user_id.gpt_id and not is_allow:
# # 暂时有限用户的Ai
# raise UserError(_('此Ai暂时未开放请联系管理员。'))
if hasattr(ai, 'is_translator') and ai.is_translator:
return rdata
chatgpt_channel_id = self.env.ref('app_chatgpt.channel_chatgpt')
if message.body == _('<div class="o_mail_notification">joined the channel</div>'):
@@ -186,12 +268,14 @@ class Channel(models.Model):
openai.api_key = api_key
# 非4版本取0次。其它取3 次历史
chat_count = 3
if '4' in ai.ai_model:
if '4' in ai.ai_model or '4' in ai.name:
chat_count = 1
if hasattr(self, 'chat_count'):
if self.chat_count > 0:
chat_count = 1
else:
chat_count = chat_count
if author_id != answer_id.id and self.channel_type == 'chat':
# 私聊
_logger.info(f'私聊:author_id:{author_id},partner_chatgpt.id:{answer_id.id}')

View File

@@ -1,9 +1,58 @@
# -*- coding: utf-8 -*-
from odoo import fields, models
from odoo import fields, models, api
class ResPartner(models.Model):
_inherit = "res.partner"
gpt_id = fields.Many2one('ai.robot', string='Bind to ChatGpt')
is_chat_private = fields.Boolean('Allow Chat Private', default=False)
@api.model
def im_search(self, name, limit=20):
users = self.env['res.users'].search([
('id', '!=', self.env.user.id),
('name', 'ilike', name),
('active', '=', True),
('share', '=', False),
('is_chat_private', '=', True)
], order='gpt_id, name, id', limit=limit)
return list(users.partner_id.mail_partner_format().values())
def mail_partner_format(self, fields=None):
# 直接覆盖原生,增加 gpt_id 字段
partners_format = dict()
if not fields:
fields = {'id': True, 'name': True, 'email': True, 'active': True, 'im_status': True, 'gpt_id': 0, 'user': {}}
for partner in self:
data = {}
if 'id' in fields:
data['id'] = partner.id
if 'name' in fields:
name = partner.name
# 英文不好分,暂时不隐名
# if not partner.related_user_id.gpt_id:
# name = partner.name[0] + '*' * (len(partner.name) - 1)
data['name'] = name
if 'email' in fields:
data['email'] = partner.email
if 'active' in fields:
data['active'] = partner.active
if 'im_status' in fields:
data['im_status'] = partner.im_status
if 'gpt_id' in fields:
data['gpt_id'] = partner.gpt_id.id if partner.gpt_id else 0
if 'user' in fields:
internal_users = partner.user_ids - partner.user_ids.filtered('share')
main_user = internal_users[0] if len(internal_users) > 0 else partner.user_ids[0] if len(partner.user_ids) > 0 else self.env['res.users']
data['user'] = {
"id": main_user.id,
"isInternalUser": not main_user.share,
} if main_user else [('clear',)]
# if 'guest' in self.env.context or not self.env.user.has_group('base.group_erp_manager'):
# 完全不显示 邮箱
data.pop('email', None)
partners_format[partner] = data
return partners_format

View File

@@ -14,3 +14,4 @@ class ResUsers(models.Model):
], string='Allowed Conversation Mode', default='all', ondelete='set default')
gpt_wl_partners = fields.Many2many('res.partner', 'res_partner_ai_use', 'ai_user_id', 'name', string='Allowed Partners')
gpt_demo_time = fields.Integer('Default Demo Time', default=0)
is_chat_private = fields.Boolean('Allow Chat Private', default=False, related='partner_id.is_chat_private', inherited=True, readonly=False)

View File

@@ -1,4 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_gpt_robt_manager,AiRobotUser,model_ai_robot,base.group_erp_manager,1,1,1,1
access_res_partner_ai_use_user,ResPartnerAiUseUser,model_res_partner_ai_use,base.group_user,1,0,0,0
access_res_partner_ai_use_manager,ResPartnerAiUseUser,model_res_partner_ai_use,sales_team.group_sale_manager,1,1,1,1
access_res_partner_ai_use_manager,ResPartnerAiUseUser,model_res_partner_ai_use,base.group_erp_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_gpt_robt_manager AiRobotUser model_ai_robot base.group_erp_manager 1 1 1 1
3 access_res_partner_ai_use_user ResPartnerAiUseUser model_res_partner_ai_use base.group_user 1 0 0 0
4 access_res_partner_ai_use_manager ResPartnerAiUseUser model_res_partner_ai_use sales_team.group_sale_manager base.group_erp_manager 1 1 1 1

View File

@@ -11,6 +11,6 @@
<field name="name">All AI Use</field>
<field ref="model_res_partner_ai_use" name="model_id"/>
<field name="domain_force">[(1,'=',1)]</field>
<field name="groups" eval="[(4, ref('sales_team.group_sale_manager'))]"/>
<field name="groups" eval="[(4, ref('base.group_erp_manager'))]"/>
</record>
</odoo>

View File

@@ -0,0 +1,111 @@
<?xml version="1.0"?>
<odoo>
<data>
<!-- form,原生继承以便管理-->
<record id="ai_mail_channel_view_form" model="ir.ui.view">
<field name="name">ai.mail.channel.form</field>
<field name="model">mail.channel</field>
<field name="mode">extension</field>
<field name="inherit_id" ref="mail.mail_channel_view_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='privacy']" position="before">
<page name="page_user" string="用户设定的角色相关,一般不要调整">
<group>
<group name="role_set" string="Ai常规设定">
<field name="channel_type" readonly="1"/>
<field name="ai_partner_id"
options="{'no_open': True, 'no_create': True}"/>
<field name="ext_ai_partner_id"
options="{'no_open': True, 'no_create': True}"/>
</group>
<group name="param_set" string="Ai角色风格设定">
<div class="o_td_label">
<label for="set_max_tokens"/>
</div>
<field name="set_max_tokens" nolabel="1" required="1"/>
<div class="o_td_label">
<label for="set_chat_count"/>
</div>
<field name="set_chat_count" nolabel="1" required="1"/>
<div class="o_td_label">
<label for="set_temperature"/>
</div>
<field name="set_temperature" nolabel="1" required="1"/>
<div class="o_td_label">
<label for="set_top_p"/>
</div>
<field name="set_top_p" nolabel="1" required="1"/>
<div class="o_td_label">
<label for="set_frequency_penalty"/>
</div>
<field name="set_frequency_penalty" nolabel="1" required="1"/>
<div class="o_td_label">
<label for="set_presence_penalty"/>
</div>
<field name="set_presence_penalty" nolabel="1" required="1"/>
<field name="is_private" readonly="0"/>
<field name="create_uid" readonly="1" options="{'no_open': True, 'no_create': True}"/>
</group>
</group>
</page>
</xpath>
<xpath expr="//field[@name='group_public_id']/.." position="after">
<group string="Ai智能优化设定具体参数">
<field name="chat_count"/>
<p class="ml16 my-n1 mb16" colspan="2">0-3设定后会将最近n次对话发给Ai有助于他更好的回答</p>
<field name="max_tokens"/>
<p class="ml16 my-n1 mb16" colspan="2">最大响应Token,控制返回内容长度</p>
<field name="temperature"/>
<p class="ml16 my-n1 mb16" colspan="2">0-1值越大越富有想像力越小则越保守</p>
<field name="frequency_penalty"/>
<p class="ml16 my-n1 mb16" colspan="2">0-1值越大越少使用常用词</p>
<field name="presence_penalty"/>
<p class="ml16 my-n1 mb16" colspan="2">0-1值越大越少重复词</p>
</group>
</xpath>
</field>
</record>
<!--kanban,原生的处理-->
<record id="ai_mail_channel_view_kanban" model="ir.ui.view">
<field name="model">mail.channel</field>
<field name="inherit_id" ref="mail.mail_channel_view_kanban"/>
<field name="mode">extension</field>
<field name="arch" type="xml">
<xpath expr="//kanban//field[1]" position="before">
<field name="is_private"/>
</xpath>
<xpath expr="//field[@name='description']" position="before">
<em>角色:</em>
</xpath>
<xpath expr="//button[@name='channel_join']" position="replace">
<button attrs="{'invisible':[('is_private','=',True), ('group_ids', '!=', [])]}"
class="btn btn-warning float-end" type="edit">
智能设定
</button>
<button type="object" attrs="{'invisible':['|', ('is_member','=',True), ('group_ids', '!=', [])]}" class="btn btn-primary float-end" name="channel_join">进入频道</button>
</xpath>
<xpath expr="//button[@name='action_unfollow']" position="replace">
<button type="object" attrs="{'invisible':['|', ('is_member','=',False), ('group_ids', '!=', [])]}"
class="btn btn-secondary float-end" name="action_unfollow">暂时离开</button>
</xpath>
</field>
</record>
<!--search 原生处理-->
<record id="ai_mail_channel_view_search" model="ir.ui.view">
<field name="model">mail.channel</field>
<field name="inherit_id" ref="mail.mail_channel_view_search"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="after">
<field name="channel_type"/>
<group expand="0" string="Group By">
<filter string="Channel Type" name="groupby_channel_type" domain="[]" context="{'group_by': 'channel_type'}"/>
</group>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -39,7 +39,7 @@
{
'name': "odooai Odooapp Common Func",
'version': '16.23.05.09',
'version': '16.23.08.17',
'author': 'odooai.cn',
'category': 'Base',
'website': 'https://www.odooai.cn',

View File

@@ -29,6 +29,7 @@ from . import res_users
from . import ir_mail_server
from . import mail_mail
from . import ir_http
from . import app_import

View File

@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
import base64
import io
import csv
import os.path
from odoo import api, fields, models, modules, tools, SUPERUSER_ID, _
from odoo.tools import pycompat
from odoo.tests import common
ADMIN_USER_ID = common.ADMIN_USER_ID
def app_quick_import(cr, content_path, sep=None):
if not sep:
sep = '/'
dir_split = content_path.split(sep)
module_name = dir_split[0]
file_name = dir_split[2]
file_path, file_type = os.path.splitext(content_path)
model_name = file_name.replace(file_type, '')
file_path = modules.get_module_resource(module_name, dir_split[1], file_name)
content = open(file_path, 'rb').read()
uid = SUPERUSER_ID
if model_name == 'mail.channel':
# todo: 创建mail.channel时如果用root用户会报错
uid = 2
env = api.Environment(cr, uid, {})
if file_type == '.csv':
file_type = 'text/csv'
elif file_type in ['.xls', '.xlsx']:
file_type = 'application/vnd.ms-excel'
import_wizard = env['base_import.import'].create({
'res_model': model_name,
'file_name': file_name,
'file_type': file_type,
'file': content,
})
if file_type == 'text/csv':
preview = import_wizard.parse_preview({
'separator': ',',
'has_headers': True,
'quoting': '"',
})
elif file_type == 'application/vnd.ms-excel':
preview = import_wizard.parse_preview({
'has_headers': True,
})
result = import_wizard.execute_import(
preview["headers"],
preview["headers"],
preview["options"]
)

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from . import controllers
from . import models
from . import wizard
from . import hooks

View File

@@ -23,7 +23,7 @@
{
'name': 'odoo 16 Customize OEM(Boost, Data reset)',
'version': '16.23.08.05',
'version': '16.23.08.15',
'author': 'odooai.cn',
'category': 'Extra Tools',
'website': 'https://www.odooai.cn',
@@ -135,6 +135,9 @@
40. Fix support for enterprise version.
41. Fix odoo bug, when click Preferences menu not hide in mobile.
42. Add menu navbar setup for top or bottom. navigator footer support.
43. Check to only Debug / Debug Assets for Odoo Admin. Deny debug from url for other user.
44. Check to stop subscribe and follow. This to make odoo speed up.
45. Add addons path info to module.
This module can help to white label the Odoo.
Also helpful for training and support for your odoo end-user.
@@ -183,5 +186,9 @@
39. 只有系统管理员可以操作快速debug
40. 增强对企业版的支持
41. 修正odoo原生移动端菜单bug点击个人设置时原菜单不隐藏等
42. 可设置导航栏在上方还是下方,分开桌面与移动端.
43. 可设置只允许管理员进入开发者模式不可在url中直接debut=1来调试
44. 可配置停用自动用户订阅功能这会提速odoo减少资源消耗
45. 为应用模块增加模块路径信息
""",
}

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# todo: website 有bug oauth
from . import controllers

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import http
from odoo.addons.portal.controllers.web import Home
from odoo.http import request
class KsHome(Home):
@http.route()
def web_client(self, s_action=None, **kw):
res = super(KsHome, self).web_client(s_action, **kw)
if kw.get('debug') in ['1', 'assets', 'assets,tests']:
config_parameter = request.env['ir.config_parameter'].sudo()
app_debug_only_admin = config_parameter.get_param('app_debug_only_admin')
if request.session.uid and request.env.user.browse(request.session.uid)._is_admin():
pass
else:
if app_debug_only_admin:
return request.redirect('/web/session/logout?debug=0')
return res

View File

@@ -22,5 +22,6 @@
<function model="ir.config_parameter" name="set_param" eval="('app_ribbon_background_color', 'rgba(255,0,0,.4)')"/>
<function model="ir.config_parameter" name="set_param" eval="('app_navbar_pos_pc', 'top')"/>
<function model="ir.config_parameter" name="set_param" eval="('app_navbar_pos_mobile', 'bottom')"/>
<function model="ir.config_parameter" name="set_param" eval="('app_debug_only_admin', 'True')"/>
</data>
</openerp>

View File

@@ -6,5 +6,6 @@ from . import ir_module_module
from . import web_environment_ribbon_backend
from . import ir_http
from . import ir_module_addons_path
from . import mail_thread
# from . import ir_ui_view
# from . import ir_ui_menu

View File

@@ -32,4 +32,7 @@ class IrHttp(models.AbstractModel):
# 增加 bar位置处理
result['app_navbar_pos_pc'] = config_parameter.get_param('app_navbar_pos_pc', 'top')
result['app_navbar_pos_mobile'] = config_parameter.get_param('app_navbar_pos_mobile', 'top')
# 此处直接取,不用 session
result['app_debug_only_admin'] = config_parameter.get_param('app_debug_only_admin')
result['app_stop_subscribe'] = config_parameter.get_param('app_stop_subscribe')
return result

View File

@@ -18,6 +18,7 @@ class IrModule(models.Model):
local_updatable = fields.Boolean('Local updatable', compute=False, default=False, store=True)
addons_path_id = fields.Many2one('ir.module.addons.path', string='Addons Path ID', readonly=True)
addons_path = fields.Char(string='Addons Path', related='addons_path_id.path', readonly=True)
license = fields.Char(readonly=True)
def module_multi_uninstall(self):
""" Perform the various steps required to uninstall a module completely

View File

@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import api, fields, models, _
class MailThread(models.AbstractModel):
_inherit = "mail.thread"
def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None):
""" 停用订阅功能. """
ir_config = self.env['ir.config_parameter']
app_stop_subscribe = True if ir_config.get_param('app_stop_subscribe', False) == "True" else False
if app_stop_subscribe:
return True
else:
return super(MailThread, self).message_subscribe(partner_ids, subtype_ids)
def _message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, customer_ids=None):
""" 停用订阅功能. """
ir_config = self.env['ir.config_parameter']
app_stop_subscribe = True if ir_config.get_param('app_stop_subscribe', False) == "True" else False
if app_stop_subscribe:
return True
else:
return super(MailThread, self)._message_subscribe(partner_ids, subtype_ids, customer_ids)
def _message_auto_subscribe_followers(self, updated_values, default_subtype_ids):
""" 停用订阅功能. """
ir_config = self.env['ir.config_parameter']
app_stop_subscribe = True if ir_config.get_param('app_stop_subscribe', False) == "True" else False
if app_stop_subscribe:
return []
else:
return super(MailThread, self)._message_auto_subscribe_followers(updated_values, default_subtype_ids)
def _message_auto_subscribe_notify(self, partner_ids, template):
""" 停用订阅功能. """
ir_config = self.env['ir.config_parameter']
app_stop_subscribe = True if ir_config.get_param('app_stop_subscribe', False) == "True" else False
if app_stop_subscribe:
return True
else:
return super(MailThread, self)._message_auto_subscribe_notify(partner_ids, template)

View File

@@ -54,6 +54,12 @@ class ResConfigSettings(models.TransientModel):
('bottom', 'Bottom'),
# ('left', 'Left'),
], config_parameter='app_navbar_pos_mobile')
# 安全与提速
app_debug_only_admin = fields.Boolean('Debug for Admin', config_parameter='app_debug_only_admin',
help="Check to only Debug / Debug Assets for Odoo Admin. Deny debug from url for other user.")
app_stop_subscribe = fields.Boolean('Stop Odoo Subscribe', help="Check to stop subscribe and follow. This to make odoo speed up.",
config_parameter='app_stop_subscribe')
def set_module_url(self):
sql = "UPDATE ir_module_module SET website = '%s' WHERE license like '%s' and website <> ''" % (self.app_enterprise_url, 'OEEL%')

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 KiB

After

Width:  |  Height:  |  Size: 449 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 258 KiB

View File

@@ -47,7 +47,12 @@
<div class="oe_span12">
<h2 class="oe_slogan">This is a Long Term Support Apps.</h2>
<div class="oe_demo" style=" margin: 30px auto 0; padding: 0 15px 0 0; border:none; width: 96%;">
<h3>Update: v16.23.05.24</h3>
<h3>Update: v16.23.08.15</h3>
<p>43. Check to only Debug / Debug Assets for Odoo Admin. Deny debug from url for other user.</p>
<p>44. Check to stop subscribe and follow. This to make odoo speed up.</p>
<h3>Update: v16.23.07.25</h3>
<p>42. Add menu navbar setup for top or bottom. navigator footer support.</p>
<h3>Update: v16.23.07.14</h3>
<p>41. Fix odoo bug, when click Preferences menu not hide in mobile.</p>
<h3>Update: v16.23.05.04</h3>
<p>Fix bug in mobile view in popup menu.</p>

View File

@@ -29,6 +29,14 @@
<field name="app_navbar_pos_mobile"/>
</group>
</group>
<group string="Security and Boost" name="app_security_boost">
<group>
<field name="app_debug_only_admin"/>
</group>
<group>
<field name="app_stop_subscribe"/>
</group>
</group>
<group string="User Menu">
<group>
<field name="app_show_lang"/>

View File

@@ -25,6 +25,9 @@
<field name="model">ir.module.module</field>
<field name="inherit_id" ref="base.view_module_filter" />
<field name="arch" type="xml">
<field name="name" position="after">
<field name="author"/>
</field>
<filter name="not_installed" position="after">
<filter name="is_local_updatable" string="Local updatable" domain="[('local_updatable', '=', True)]"/>
</filter>
@@ -33,25 +36,22 @@
</xpath>
</field>
</record>
<record id="app_module_form" model="ir.ui.view">
<field name="name">app.ir.module.module.form</field>
<field name="model">ir.module.module</field>
<field name="inherit_id" ref="base.module_form" />
<field name="arch" type="xml">
<h3 class="oe_fade" position="attributes">
<attribute name="groups">app_odoo_customize.group_show_author_in_apps</attribute>
</h3>
<field name="website" position="attributes">
<attribute name="groups">app_odoo_customize.group_show_author_in_apps</attribute>
</field>
<xpath expr="//notebook/page/group" position="inside">
<group name="module_path">
<field name="addons_path_id" invisible="1"/>
<field name="addons_path" groups="base.group_no_one"/>
</group>
</xpath>
<field name="inherit_id" ref="base.module_form"/>
<field name="arch" type="xml">
<h3 class="oe_fade" position="attributes">
<attribute name="groups">app_odoo_customize.group_show_author_in_apps</attribute>
</h3>
<field name="category_id" position="after">
<field name="addons_path_id" invisible="1"/>
<field name="addons_path" groups="base.group_no_one"/>
</field>
</field>
</record>
<record id="app_module_view_kanban" model="ir.ui.view">
<field name="name">ir.module.module.kanban.inherit.base</field>
<field name="model">ir.module.module</field>

View File

@@ -9,8 +9,8 @@
<xpath expr="//search">
<searchpanel view_types="list,kanban,pivot,graph,activity,search" class="app_test">
<field name="categ_id" text="name" enable_counters="1" expand="1" limit="1000"/>
<field name="type" enable_counters="1"/>
<field name="product_tag_ids" select="multi" enable_counters="1"/>
<field name="type"/>
<field name="product_tag_ids" select="multi"/>
</searchpanel>
</xpath>
</field>

View File

@@ -8,7 +8,7 @@
<field name="arch" type="xml">
<xpath expr="//search">
<searchpanel view_types="list,kanban,pivot,graph">
<field name="status" enable_counters="1"/>
<field name="state" enable_counters="1"/>
<field name="invoice_status" enable_counters="1"/>
<field name="partner_id" filter_domain="[('customer_rank','&gt;', 0)]" limit="1000" enable_counters="1"/>
<field name="team_id" enable_counters="1"/>

View File

@@ -18,4 +18,13 @@
Discard
</xpath>
</t>
<!-- 创建移到左边-->
<t t-name="app_web_enterprise.FormControlPanel" t-inherit="web.FormControlPanel" t-inherit-mode="extension">
<xpath expr="//div[hasclass('o_cp_bottom_right')]//t[3]" position="replace"/>
<!-- <xpath expr="//t[t-slot='control-panel-create-button']" position="replace"/>-->
<!-- <xpath expr="//div[hasclass('o_cp_top_left')]" position="replace"/>-->
<xpath expr="//div[hasclass('o_cp_top_left')]" position="inside">
<t t-slot="control-panel-create-button" />
</xpath>
</t>
</templates>

View File

@@ -5,6 +5,9 @@
<field name="model">blog.post</field>
<field name="inherit_id" ref="website_blog.view_blog_post_list"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="before">
<field name="id" optional="show"/>
</xpath>
<xpath expr="//field[@name='website_url']" position="attributes">
<attribute name="optional">hide</attribute>
</xpath>
@@ -14,6 +17,9 @@
<xpath expr="//field[@name='is_published']" position="attributes">
<attribute name="optional">show</attribute>
</xpath>
<xpath expr="//field[@name='website_url']" position="after">
<field name="seo_name"/>
</xpath>
<xpath expr="//field[@name='author_id']" position="before">
<field name="visits" optional="show"/>
</xpath>
@@ -32,7 +38,10 @@
<field name="model">blog.post</field>
<field name="inherit_id" ref="website_blog.view_blog_post_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='seo']" position="before">
<xpath expr="//field[@name='tag_ids']" position="after">
<field name="seo_name"/>
</xpath>
<xpath expr="//page[@name='seo']" position="after">
<page name="post_content" string="Content">
<field name="content" widget="html" nolabel="1" class="oe-bordered-editor"
options="{'style-inline': true, 'codeview': true, 'dynamic_placeholder': true}"/>

View File

@@ -7,7 +7,8 @@
<field name="arch" type="xml">
<xpath expr="//search" position="inside">
<searchpanel>
<field name="blog_id" enable_counters="1"/>
<field name="blog_id" enable_counters="1" select="multi"/>
<field name="tag_ids" enable_counters="1" select="multi"/>
</searchpanel>
</xpath>
</field>

View File

@@ -1,16 +1,17 @@
<odoo>
<data>
<!-- Product -->
<record id="app_product_template_search_view" model="ir.ui.view">
<field name="name">app.product.template.search</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="app_product_superbar.app_product_template_search_view"/>
<field name="arch" type="xml">
<xpath expr="//searchpanel//field[@name='categ_id']" position="before">
<field name="public_categ_ids" select="multi" text="name"/>
<field name="website_ribbon_id" select="multi"/>
</xpath>
</field>
</record>
</data>
<data>
<!-- Product -->
<record id="app_product_template_search_view" model="ir.ui.view">
<field name="name">app.product.template.search</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="app_product_superbar.app_product_template_search_view"/>
<field name="arch" type="xml">
<xpath expr="//searchpanel//field[@name='categ_id']" position="before">
<field name="public_categ_ids" enable_counters="1" select="multi" text="name"/>
<field name="website_ribbon_id" enable_counters="1" select="multi"/>
<field name="product_tag_ids" enable_counters="1" select="multi"/>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -25,7 +25,20 @@
<field name="arch" type="xml">
<xpath expr="//page[@name='sales']" position="after">
<page name="shop_desc" string="Website Description" attrs="{'invisible': [('sale_ok','=',False)]}">
<field name="website_description" nolabel="1"/>
<group>
<group>
<!-- 这里加个快速设置 seo url字段-->
<field name="website_meta_title" invisible="1"/>
<field name="website_meta_keywords"/>
<field name="seo_name"/>
</group>
<group>
<field name="website_meta_description"/>
</group>
</group>
<group string="Content">
<field name="website_description" nolabel="1"/>
</group>
</page>
</xpath>
</field>