opt app_common 及app_saas 相关,但没检查

This commit is contained in:
Ivan Office
2025-01-26 00:42:35 +08:00
parent 0c93e27528
commit ec4186a53d
13 changed files with 421 additions and 286 deletions

View File

@@ -25,12 +25,12 @@
from . import base
from . import ir_ui_view
from . import ir_cron
from . import res_users
from . import ir_mail_server
from . import mail_mail
from . import ir_http
from . import app_import
from . import res_partner
from . import res_config_settings

View File

@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
import base64
import io
import csv
import os.path
from odoo import api, fields, models, modules, tools, SUPERUSER_ID, _
from odoo.tests import common
ADMIN_USER_ID = common.ADMIN_USER_ID
from odoo.tools import pycompat
def app_quick_import(env, content_path, sep=None, context={}):
def app_quick_import(env, content_path, sep=None):
if not sep:
sep = '/'
dir_split = content_path.split(sep)
@@ -24,8 +26,7 @@ def app_quick_import(env, content_path, sep=None, context={}):
file_type = 'text/csv'
elif file_type in ['.xls', '.xlsx']:
file_type = 'application/vnd.ms-excel'
import_wizard = env['base_import.import'].with_context(context)
import_wizard = import_wizard.create({
import_wizard = env['base_import.import'].create({
'res_model': model_name,
'file_name': file_name,
'file_type': file_type,
@@ -41,12 +42,8 @@ def app_quick_import(env, content_path, sep=None, context={}):
preview = import_wizard.parse_preview({
'has_headers': True,
})
else:
preview = False
if preview:
import_wizard.execute_import(
preview["headers"],
preview["headers"],
preview["options"]
)
result = import_wizard.execute_import(
preview["headers"],
preview["headers"],
preview["options"]
)

View File

@@ -1,18 +1,19 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from odoo.http import request
import requests
import base64
from io import BytesIO
import uuid
from PIL import Image
from datetime import date, datetime, time
import pytz
import logging
from odoo import models, fields, api, _
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from odoo.http import request
_logger = logging.getLogger(__name__)
# 常规的排除的fields
@@ -52,7 +53,7 @@ EXCLU_FIELDS = [
class Base(models.AbstractModel):
_inherit = 'base'
@api.model
def _app_check_sys_op(self):
if self.env.user.has_group('base.group_erp_manager'):
@@ -75,7 +76,10 @@ class Base(models.AbstractModel):
else:
if not domain:
domain = self._fields[fieldname].domain or []
rec = self.env[self._fields[fieldname].comodel_name].sudo().search(domain, limit=1)
try:
rec = self.env[self._fields[fieldname].comodel_name].search(domain, limit=1)
except Exception as e:
rec = self.env[self._fields[fieldname].comodel_name].search([], limit=1)
return rec.id if rec else False
return False
@@ -127,6 +131,7 @@ class Base(models.AbstractModel):
'website_id': False,
'res_model': self._name,
'res_id': self.id,
'public': True,
})
attachment.generate_access_token()
return attachment
@@ -149,6 +154,7 @@ class Base(models.AbstractModel):
'website_id': False,
'res_model': self._name,
'res_id': self.id,
'public': True,
})
attachment.generate_access_token()
return attachment
@@ -157,11 +163,33 @@ class Base(models.AbstractModel):
return False
else:
return False
@api.model
def _get_video_url2attachment(self, url):
if not self._app_check_sys_op():
return False
video, file_name = get_video_url2attachment(url)
if video and file_name:
try:
attachment = self.env['ir.attachment'].create({
'datas': video,
'name': file_name,
'website_id': False,
'res_model': self._name,
'res_id': self.id,
'public': True,
})
attachment.generate_access_token()
return attachment
except Exception as e:
_logger.error('get_video_url2attachment error: %s' % str(e))
return False
else:
return False
def get_ua_type(self):
return get_ua_type()
def get_image_from_url(url):
if not url:
return None
@@ -179,7 +207,7 @@ def get_image_url2attachment(url):
try:
if url.startswith('//'):
url = 'https:%s' % url
response = requests.get(url, timeout=30)
response = requests.get(url, timeout=90)
except Exception as e:
return None, None
# 返回这个图片的base64编码
@@ -193,11 +221,31 @@ def get_image_base642attachment(data):
return None
try:
image_data = data.split(',')[1]
file_name = str(uuid.uuid4()) + '.png'
return image_data, file_name
img = Image.open(BytesIO(base64.b64decode(image_data)))
img = img.convert('RGB')
output = BytesIO()
img.save(output, format='JPEG')
file_name = str(uuid.uuid4()) + '.jpeg'
jpeg_data = output.getvalue()
jpeg_base64 = base64.b64encode(jpeg_data)
return jpeg_base64, file_name
except Exception as e:
return None, None
def get_video_url2attachment(url):
if not url:
return None
try:
if url.startswith('//'):
url = 'https:%s' % url
response = requests.get(url, timeout=90)
video_content = response.content
except Exception as e:
return None, None
# return this video in base64
base64_video = base64.b64encode(video_content)
file_name = url.split('/')[-1]
return base64_video, file_name
def get_ua_type():
ua = request.httprequest.headers.get('User-Agent')
@@ -232,11 +280,15 @@ def get_ua_type():
and ('miniProgram' in ua or 'MiniProgram' in ua or 'MiniProgramEnv' in ua or 'wechatdevtools' in ua):
# 微信小程序及开发者工具
utype = 'wxapp'
elif 'wxwork' in ua:
utype = 'qwapp'
elif 'MicroMessenger' in ua:
# 微信浏览器
utype = 'wxweb'
elif 'cn.erpapp.o20sticks.App' in ua:
# 安卓app
utype = 'native_android'
elif 'BytedanceWebview' in ua:
utype = 'dyweb'
# _logger.warning('=========get ua %s,%s' % (utype, ua))
return utype

View File

@@ -22,9 +22,9 @@ class IrMailServer(models.Model):
if email_to.find('no-reply@odooai.cn') != -1 or email_to.find('postmaster-odoo@odooai.cn') != -1:
pass
elif email_to.find('example.com') != -1 or email_to.find('@sunpop.cn') != -1 or email_to.find('@odooapp.cn') != -1:
_logger.error(_("=================Email to ignore: %s") % email_to)
_logger.warning(_("=================Email to ignore: %s") % email_to)
raise AssertionError(_("Email to ignore: %s") % email_to)
return super(IrMailServer, self).send_email(message, mail_server_id, smtp_server, smtp_port,
smtp_user, smtp_password, smtp_encryption, smtp_ssl_certificate, smtp_ssl_private_key,
smtp_user, smtp_password, smtp_encryption, smtp_ssl_certificate, smtp_ssl_private_key,
smtp_debug, smtp_session)

View File

@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
from odoo import api, models, tools, SUPERUSER_ID
from odoo.modules.module import get_resource_path
from odoo.tools import file_open
from odoo.tools import misc
from odoo.tools import view_validation
from odoo.tools.view_validation import _relaxng_cache, validate, _validators
from odoo.tools.safe_eval import safe_eval
@@ -14,10 +15,10 @@ def app_relaxng(view_type):
""" Return a validator for the given view type, or None. """
if view_type not in _relaxng_cache:
# tree, search 特殊
if view_type in ['tree', 'search']:
_file = get_resource_path('app_common', 'rng', '%s_view.rng' % view_type)
if view_type in ['list', 'search']:
_file = misc.file_path('app_common/rng/%s_view.rng' % view_type)
else:
_file = get_resource_path('base', 'rng', '%s_view.rng' % view_type)
_file = misc.file_path('base/rng/%s_view.rng' % view_type)
with tools.file_open(_file) as frng:
try:
relaxng_doc = etree.parse(frng)
@@ -28,15 +29,15 @@ def app_relaxng(view_type):
return _relaxng_cache[view_type]
view_validation.relaxng = app_relaxng
#
# class View(models.Model):
# _inherit = 'ir.ui.view'
#
# def __init__(self, env, ids, prefetch_ids):
# # 这里应该是无必要,但为了更安全
# super(View, self).__init__(env, ids, prefetch_ids)
# view_validation.relaxng = app_relaxng
#
# # todo: 有可能需要处理增加的 header等标签
# # 直接重写原生方法
# # def transfer_node_to_modifiers(node, modifiers, context=None, in_tree_view=False):
# todo: 有可能需要处理增加的 header等标签
# 直接重写原生方法
# def transfer_node_to_modifiers(node, modifiers, context=None, in_tree_view=False):

View File

@@ -7,9 +7,10 @@ _logger = logging.getLogger(__name__)
class MailMail(models.Model):
_inherit = "mail.mail"
# 猴子补丁模式,改默认发邮件逻辑
def _send(self, auto_commit=False, raise_exception=False, smtp_session=None, alias_domain_id=False):
def _send(self, auto_commit=False, raise_exception=False, smtp_session=None, alias_domain_id=False,
mail_server=False, post_send_callback=None):
for m in self:
email_to = m.email_to
# 忽略掉无效email避免被ban
@@ -17,8 +18,8 @@ class MailMail(models.Model):
if email_to.find('no-reply@odooai.cn') != -1 or email_to.find('postmaster-odoo@odooai.cn') != -1:
pass
elif email_to.find('example.com') != -1 or email_to.find('@sunpop.cn') != -1 or email_to.find('@odooapp.cn') != -1:
_logger.error(_("=================Email to ignore: %s") % email_to)
_logger.warning(_("=================Email to ignore: %s") % email_to)
self = self - m
if not self:
return True
return super(MailMail, self)._send(auto_commit, raise_exception, smtp_session, alias_domain_id)
return super(MailMail, self)._send(auto_commit, raise_exception, smtp_session, alias_domain_id, mail_server, post_send_callback)

View File

@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
import logging
from odoo import api, fields, models, _
from odoo.exceptions import UserError, ValidationError
_logger = logging.getLogger(__name__)
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
app_saas_ok = fields.Boolean('Enable CN SaaS', help="Checked to Enable www.odooapp.cn cloud service.", default=True, config_parameter='app_saas_ok')

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="app_res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.app_common</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<!-- 以下有些设置主要是为了兼容18-->
<xpath expr="//div[@data-key='general_settings']" position="before">
<div class="app_settings_block ml8" data-string="odoAi Cloud" string="odooAi Cloud" data-key="app_common"
logo="/app_common/static/description/odooai.png" groups="base.group_erp_manager">
<div id="app_slot1" class="o_hidden"></div>
<div id="app_odooai_banner" class="row app_settings_header my-0 ms-0 mw-100 bg-warning bg-opacity-25" name="app_settings_header">
<div class="col-lg-12 col-md-12 ms-0 o_setting_box">
<div class="o_setting_right_pane border-start-0 ms-0 ps-0">
<div class="content-group">
<div class="row mt8">
<div name="app_odooai_link">
<a href="https://www.odooai.cn" target="_blank">Visit our website for more apps and Support.
https://www.odooai.cn
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<h2>Setup the communication to odooAi Cloud</h2>
<div class="row mt16 o_settings_container" name="odooai_cloud_block">
<setting id="odooai_cloud_block_title" class="mt16 o_settings_container"
title="Setup the communication to odooAi Cloud" string="Setup the communication to odooAi Cloud">
<div name="app_odooapp_link">
<a href="https://www.odooapp.cn" target="_blank">Get the Industry Apps, Themes and Support from China odooapp store.
https://www.odooapp.cn
</a>
</div>
</setting>
<div class="col-lg-6 col-12 o_setting_box" id="odooai_cloud_saas_ok">
<div class="o_setting_left_pane">
<field name="app_saas_ok"/>
</div>
<div class="o_setting_right_pane">
<label for="app_saas_ok"/>
<div class="content-group">
<div>
<p class="text-warning">Checked and Save to Enable odoo China cloud service.</p>
<p class="ml4">
Easy Get Odoo Chinese App, Theme, and industry solution. You can get the SaaS client from
<br/>
<a href="https://www.odooapp.cn/apps/modules/app_saas" class="o_doc_link ml8"
target="_blank">https://www.odooapp.cn/apps/modules/app_saas
</a>
</p>
</div>
</div>
</div>
</div>
</div>
<div id="app_slot2" class="o_hidden"></div>
</div>
</xpath>
</field>
</record>
<record id="action_odooai_cloud_config" model="ir.actions.act_window">
<field name="name">odooAi Cloud</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.config.settings</field>
<field name="view_mode">form</field>
<field name="target">inline</field>
<field name="context">{'module' : 'app_common', 'bin_size': False}</field>
</record>
</data>
</odoo>