From 9ae2ff1a2b999f86e452737c999b288e73bdf419 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Tue, 30 May 2023 11:26:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BC=81=E4=B8=9A=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_wxwork_approval/__init__.py | 2 + sf_wxwork_approval/__manifest__.py | 46 ++++ sf_wxwork_approval/controllers/__init__.py | 5 + sf_wxwork_approval/controllers/controllers.py | 69 ++++++ sf_wxwork_approval/models/__init__.py | 9 + sf_wxwork_approval/models/model.py | 52 +++++ .../models/res_config_setting.py | 39 ++++ .../models/we_approval_record.py | 40 ++++ sf_wxwork_approval/models/wx_work_api.py | 208 ++++++++++++++++++ .../models/wxwork_approval_template.py | 40 ++++ .../wxwork_approval_template_controls.py | 112 ++++++++++ .../wxwork_approval_template_summary.py | 31 +++ sf_wxwork_approval/models/wxwork_config.py | 24 ++ sf_wxwork_approval/models/wxwork_settings.py | 12 + .../security/ir.model.access.csv | 11 + .../views/res_config_settings_views.xml | 31 +++ sf_wxwork_approval/views/views.xml | 58 +++++ .../views/wxwork_approval_approval_line.xml | 95 ++++++++ .../views/wxwork_approval_template_view.xml | 137 ++++++++++++ .../views/wxwork_config_view.xml | 34 +++ .../views/wxwork_settings_view.xml | 43 ++++ 21 files changed, 1098 insertions(+) create mode 100644 sf_wxwork_approval/__init__.py create mode 100644 sf_wxwork_approval/__manifest__.py create mode 100644 sf_wxwork_approval/controllers/__init__.py create mode 100644 sf_wxwork_approval/controllers/controllers.py create mode 100644 sf_wxwork_approval/models/__init__.py create mode 100644 sf_wxwork_approval/models/model.py create mode 100644 sf_wxwork_approval/models/res_config_setting.py create mode 100644 sf_wxwork_approval/models/we_approval_record.py create mode 100644 sf_wxwork_approval/models/wx_work_api.py create mode 100644 sf_wxwork_approval/models/wxwork_approval_template.py create mode 100644 sf_wxwork_approval/models/wxwork_approval_template_controls.py create mode 100644 sf_wxwork_approval/models/wxwork_approval_template_summary.py create mode 100644 sf_wxwork_approval/models/wxwork_config.py create mode 100644 sf_wxwork_approval/models/wxwork_settings.py create mode 100644 sf_wxwork_approval/security/ir.model.access.csv create mode 100644 sf_wxwork_approval/views/res_config_settings_views.xml create mode 100644 sf_wxwork_approval/views/views.xml create mode 100644 sf_wxwork_approval/views/wxwork_approval_approval_line.xml create mode 100644 sf_wxwork_approval/views/wxwork_approval_template_view.xml create mode 100644 sf_wxwork_approval/views/wxwork_config_view.xml create mode 100644 sf_wxwork_approval/views/wxwork_settings_view.xml diff --git a/sf_wxwork_approval/__init__.py b/sf_wxwork_approval/__init__.py new file mode 100644 index 00000000..9d794022 --- /dev/null +++ b/sf_wxwork_approval/__init__.py @@ -0,0 +1,2 @@ +# from . import controllers +from . import models diff --git a/sf_wxwork_approval/__manifest__.py b/sf_wxwork_approval/__manifest__.py new file mode 100644 index 00000000..ad336c83 --- /dev/null +++ b/sf_wxwork_approval/__manifest__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name': '机企猫 企业微信审批', + 'version': '1.0', + 'summary': 'jikimo_wxwork_approval', + 'sequence': 14, + 'description': """ +这是一个用于企业微信审批的模块 +==================== + """, + 'category': 'bfm', + 'author': 'jikimo', + 'website': 'https://bfm.r.jikimo.com', + 'depends': ['web'], + 'data': [ + # 定义权限组放在最上面 + # 权限组 + # 'views/views.xml', + # 'views/res_config_settings_views.xml', + 'security/ir.model.access.csv', + 'views/wxwork_config_view.xml', + 'views/views.xml', + 'views/wxwork_settings_view.xml', + 'views/wxwork_approval_template_view.xml', + 'views/wxwork_approval_approval_line.xml', + + # 'views/res_config_settings_views.xml', + + ], + + 'assets': { + + 'web.assets_qweb': [ + ], + 'web.assets_backend': [ + + ], + + }, + + 'installable': True, + 'application': True, + # 'auto_install': False, + 'license': 'LGPL-3', +} diff --git a/sf_wxwork_approval/controllers/__init__.py b/sf_wxwork_approval/controllers/__init__.py new file mode 100644 index 00000000..f4d7db1e --- /dev/null +++ b/sf_wxwork_approval/controllers/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +from . import controllers + + diff --git a/sf_wxwork_approval/controllers/controllers.py b/sf_wxwork_approval/controllers/controllers.py new file mode 100644 index 00000000..e52058d4 --- /dev/null +++ b/sf_wxwork_approval/controllers/controllers.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +import ast +import base64 +import io +import json +import os +import random +import time + +import re + +from stl import mesh +from werkzeug import urls + +import odoo +from odoo.exceptions import ValidationError +import requests +from odoo import http +from odoo.http import request, Response +from odoo.modules import get_resource_path +from odoo.tools.translate import _ +import logging + +_logger = logging.getLogger(__name__) + + +class WechatAuthController(http.Controller): + + @http.route('/wechat_auth/callback', auth='public', type='http', csrf=False) + def wechat_auth_callback(self, **kwargs): + _logger.info('wechat_auth_callback=============:%s' % kwargs) + code = kwargs.get('code') + if not code: + return "缺少授权码 (code)" + + # 获取 access_token 和 UserId + corp_id = 'wweaf7f1caab27a136' + secret = 'UA95oJsgeS6cZrq_9ijaG68n0MIWFVv1nyxVnHnqiQQ' + token_url = f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corp_id}&corpsecret={secret}' + token_response = requests.get(token_url).json() + access_token = token_response.get('access_token') + + user_info_url = f'https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token={access_token}&code={code}' + user_info_response = requests.get(user_info_url).json() + user_id = user_info_response.get('UserId') + + if not user_id: + return "获取用户信息失败" + + # 根据 UserId 查询或创建 Odoo 用户 + user = request.env['res.users'].sudo().search([('wechat_user_id', '=', user_id)]) + + if not user: + # 获取企业微信用户详细信息 + user_detail_url = f'https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={access_token}&userid={user_id}' + user_detail_response = requests.get(user_detail_url).json() + + # 创建 Odoo 用户 + user_data = { + 'login': user_detail_response.get('email'), + 'name': user_detail_response.get('name'), + 'email': user_detail_response.get('email'), + 'wechat_user_id': user_id, + } + user = request.env['res.users'].sudo().create(user_data) + + # 自动登录 Odoo 用户 + request.session.authenticate(request.session.db, user.login, user.password_crypt) + return http.local_redirect('/web') diff --git a/sf_wxwork_approval/models/__init__.py b/sf_wxwork_approval/models/__init__.py new file mode 100644 index 00000000..96798de7 --- /dev/null +++ b/sf_wxwork_approval/models/__init__.py @@ -0,0 +1,9 @@ +from . import model +from . import wxwork_config +from . import wxwork_approval_template +from . import wxwork_approval_template_controls +from . import wxwork_settings +from . import wxwork_approval_template_summary +from . import we_approval_record + +# from . import res_config_setting diff --git a/sf_wxwork_approval/models/model.py b/sf_wxwork_approval/models/model.py new file mode 100644 index 00000000..ba1cf15a --- /dev/null +++ b/sf_wxwork_approval/models/model.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +import re +import logging +import time +import requests +from datetime import datetime +import base64 +import hashlib +from odoo import fields, models, api +import json +import requests +from odoo.http import request +from odoo.exceptions import ValidationError +from odoo.exceptions import UserError + + + +_logger = logging.getLogger(__name__) + + +# 审批管理 +class WxWorkApproval(models.Model): + _name = 'wxwork.approval.record' + _description = '审批记录' + + approval_type = fields.Many2one('wxwork.approval.template', string='审批模板名称') + approval_num = fields.Char(string='审批单据编号') + initiator = fields.Many2one('hr.employee', string='发起人') + # approver = fields.Many2one('hr.employee', string='审批人') + approval_state = fields.Selection([ + ('draft', '提交审批'), + ('pending', '审批中'), + ('approved', '已批准'), + ('rejected', '已拒绝') + ], string='审批状态', default='草稿') + approval_time = fields.Datetime(string='审批发起时间') + note = fields.Text(string='备注') + # + # # 根据具体业务需要添加其他字段 + # leave_type = fields.Selection([ + # ('annual_leave', 'Annual Leave'), + # ('sick_leave', 'Sick Leave'), + # ('personal_leave', 'Personal Leave') + # ], string='请假类型') + # leave_days = fields.Float(string='Leave Days') + # overtime_hours = fields.Float(string='Overtime Hours') + + + + + + diff --git a/sf_wxwork_approval/models/res_config_setting.py b/sf_wxwork_approval/models/res_config_setting.py new file mode 100644 index 00000000..cb3f98fc --- /dev/null +++ b/sf_wxwork_approval/models/res_config_setting.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Part of SmartGo. See LICENSE file for full copyright and licensing details. +import logging + +from odoo import api, fields, models, _ + +_logger = logging.getLogger(__name__) + + +class WxWorkConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + wxwork_corp_id = fields.Char(string='企业微信CorpID') + wxwork_secret = fields.Char(string='企业微信Secret') + + + @api.model + def get_values(self): + """ + 重载获取参数的方法,参数都存在系统参数中 + :return: + """ + values = super(WxWorkConfigSettings, self).get_values() + config = self.env['ir.config_parameter'].sudo() + wxwork_corp_id = config.get_param('wxwork_corp_id', default='') + wxwork_secret = config.get_param('wxwork_secret', default='') + values.update( + wxwork_corp_id=wxwork_corp_id, + wxwork_secret=wxwork_secret, + + + ) + return values + + def set_values(self): + super(WxWorkConfigSettings, self).set_values() + ir_config = self.env['ir.config_parameter'].sudo() + ir_config.set_param("wxwork_corp_id", self.wxwork_corp_id or "") + ir_config.set_param("wxwork_secret", self.wxwork_secret or "") diff --git a/sf_wxwork_approval/models/we_approval_record.py b/sf_wxwork_approval/models/we_approval_record.py new file mode 100644 index 00000000..a7a9b351 --- /dev/null +++ b/sf_wxwork_approval/models/we_approval_record.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +from odoo import api, fields, models + + +class WeApprovalRecord(models.Model): + _name = 'we.approval.record' + _description = '审批记录' + + sp_no = fields.Char('审批单号') + employee_id = fields.Many2one('hr.employee', '审批人', index=True) + state = fields.Selection([('1', '审批中'), ('2', '已同意'), ('3', '已驳回'), ('4', '已转审')], string='审批状态') + approval_time = fields.Datetime('审批时间') + approval_options = fields.Char('审批意见') + + def create_approve_record(self, sp_no, userid, sp_state, approval_time, approval_options): + """ + 创建审批记录 + :param sp_no: + :param userid: + :param sp_state: + :param approval_time: + :param approval_options: + :return: + """ + employee_obj = self.env['hr.employee'].search([('we_employee_id', '=', userid)]) + approval_order = self.env['we.approval.record'].search( + [('employee_id', '=', employee_obj.id), ('sp_no', '=', sp_no)]) + vals = { + 'sp_no': sp_no, + 'employee_id': employee_obj.id, + 'state': sp_state, + 'approval_time': approval_time, + 'approval_options': approval_options + } + if not approval_order: + approval_order = super(WeApprovalRecord, self).create(vals) + else: + approval_order.write(vals) + return approval_order diff --git a/sf_wxwork_approval/models/wx_work_api.py b/sf_wxwork_approval/models/wx_work_api.py new file mode 100644 index 00000000..eb1b4130 --- /dev/null +++ b/sf_wxwork_approval/models/wx_work_api.py @@ -0,0 +1,208 @@ +# wxwork_api.py + +import requests + + +class WxWorkAPI: + def __init__(self, corp_id, secret): + self.corp_id = corp_id + self.secret = secret + self.access_token = self.get_access_token() + # self.type = type + + def get_access_token(self): + url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={self.corp_id}&corpsecret={self.secret}" + response = requests.get(url) + result = response.json() + if 'access_token' in result: + return result['access_token'] + else: + raise Exception(f"获取AccessToken失败: {result}") + + def create_approval_request(self, approval_data): + url = f"https://qyapi.weixin.qq.com/cgi-bin/oa/applyevent?access_token={self.access_token}" + headers = {'Content-Type': 'application/json'} + response = requests.post(url, json=approval_data, headers=headers) + result = response.json() + if result['errcode'] == 0: + print(result) + return result['sp_no'] + else: + raise Exception(f"发起审批请求失败: {result}") + + def get_approval_result(self, event_id): + url = f"https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token={self.access_token}" + headers = {'Content-Type': 'application/json'} + data = {"apply_eventid": event_id} + response = requests.post(url, json=data, headers=headers) + result = response.json() + if result['errcode'] == 0: + return result + else: + raise Exception(f"获取审批结果失败: {result}") + + def upload_temp_file(self): + """ + 上传临时素材 + :return: + """ + url = f"https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token={self.access_token}&type=file" + headers = {'Content-Type': 'application/json'} + file_path = '长沙研究院2023年月度考勤.xlsx' + media_type = 'file' + with open(file_path, 'rb') as f: + file_content = f.read() + files = {'media': (file_path, file_content)} + # response = requests.post(url=url.format(access_token=access_token, type=media_type), files=files) + response = requests.post(url=url, files=files) + result = response.json() + print('upload_result%s' % result) + return result['media_id'] + + +template_id_dict = {"test": "ZvmJBAt7U2iUju9JLePxfkfuN22meQMVTAHymA"} +creator_userid = "MaGuangWei" +corid = 'wweaf7f1caab27a136' +secret = 'L6z-kjrUBOWfhBiLOmX_fNSY3jydDkLUNNWnemafn00' +wx = WxWorkAPI(corid, secret) +media_id = wx.upload_temp_file() +print(media_id) +# access = wx.get_access_token() +approval_datas = { + "creator_userid": creator_userid, + "template_id": template_id_dict['test'], + "use_template_approver": 0, + # "choose_department": 2, + "approver": [ + { + "attr": 2, + "userid": ["MaGuangWei", "YangJinLing"] + }, + { + "attr": 1, + "userid": ["MaGuangWei"] + } + ], + "notifyer": ["MaGuangWei", "PengYuBo"], + # "notifyer": ["MaGuangWei"], + "notify_type": 1, + "apply_data": { + "contents": [ + # 申请事项 + { + "control": "Text", + "id": "Text-1640339319582", + "value": { + "text": "测试测试测试测试测试" + } + }, + # 申请内容 + { + "control": "Textarea", + "id": "Textarea-1640339335659", + "value": { + "text": "odoo>>>企业微信审批" + } + }, + # 附件 + { + "control": "File", + "id": "File-1640339381728", + "value": { + "files": [ + { + "file_id": media_id + } + ] + } + + }, + + ] + }, + "summary_list": [ + { + "summary_info": [{ + "text": "测试附件上传", + "lang": "zh_CN" + }] + }, + # { + # "summary_info": [{ + # "text": "摘要第2行", + # "lang": "zh_CN" + # }] + # }, + # { + # "summary_info": [{ + # "text": "摘要第3行", + # "lang": "zh_CN" + # }] + # } + ] +} +wx.create_approval_request(approval_datas) +print('创建成功') + +aa = {"errcode": 0, "errmsg": "ok", "template_names": [{"text": "对接开发测试", "lang": "zh_CN"}], "template_content": { + "controls": [{"property": {"control": "Text", "id": "Text-1640339319582", + "title": [{"text": "申请事项", "lang": "zh_CN"}], + "placeholder": [{"text": "请输入申请事项", "lang": "zh_CN"}], "require": 1, "un_print": 0, + "un_replace": 0, "display": 1}}, + { + "property": {"control": "Textarea", "id": "Textarea-1640339335659", + "title": [{"text": "申请内容", "lang": "zh_CN"}], + "placeholder": [{"text": "请输入申请详情描述", "lang": "zh_CN"}], "require": 1, "un_print": 0, + "un_replace": 0, "display": 1}}, + { + "property": {"control": "Textarea", "id": "Textarea-1684823453770", + "title": [{"text": "多行文本", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], "require": 0, "un_print": 0}}, + { + "property": {"control": "Money", "id": "Money-1684823460232", + "title": [{"text": "金额", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], "require": 0, "un_print": 0}}, + { + "property": {"control": "Contact", "id": "Contact-1684823477216", + "title": [{"text": "部门", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], "require": 0, "un_print": 0}, + "config": {"contact": {"type": "multi", "mode": "department"}}}, + { + "property": {"control": "Contact", "id": "Contact-1684823465317", + "title": [{"text": "成员", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], "require": 0, "un_print": 0}, + "config": {"contact": {"type": "multi", "mode": "user"}}}, + { + "property": {"control": "Table", "id": "Table-1684823492261", + "title": [{"text": "明细", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], "require": 0, "un_print": 0}, + "config": {"table": {"children": [{"property": {"control": "Selector", + "id": "Selector-1684823501307", + "title": [{"text": "单选", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], + "require": 0, "un_print": 0}, "config": { + "selector": {"type": "single", "exp_type": 0, "options": [ + {"key": "option-1684823501307", "value": [{"text": "选项1", "lang": "zh_CN"}]}, + {"key": "option-1684823501308", "value": [{"text": "选项2", "lang": "zh_CN"}]}], + "op_relations": [], + "external_option": {"use_external_option": False, "external_url": ""}}}}, { + "property": {"control": "Selector", + "id": "Selector-1684823504236", + "title": [{"text": "多选", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], + "require": 0, "un_print": 0}, "config": { + "selector": {"type": "multi", "exp_type": 0, "options": [ + {"key": "option-1684823504236", "value": [{"text": "选项1", "lang": "zh_CN"}]}, + {"key": "option-1684823504237", "value": [{"text": "选项2", "lang": "zh_CN"}]}], + "op_relations": [], + "external_option": {"use_external_option": False, "external_url": ""}}}}], + "stat_field": [], "sum_field": [], "print_format": 0}}}, + { + "property": {"control": "RelatedApproval", "id": "RelatedApproval-1684823485883", + "title": [{"text": "关联申请单", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], "require": 0, "un_print": 0}}, + { + "property": {"control": "File", "id": "File-1640339381728", + "title": [{"text": "附件", "lang": "zh_CN"}], + "placeholder": [{"text": "", "lang": "zh_CN"}], "require": 0, "un_print": 0, + "un_replace": 0, "display": 1}, "config": {"file": {"is_only_photo": 0}}}]}} diff --git a/sf_wxwork_approval/models/wxwork_approval_template.py b/sf_wxwork_approval/models/wxwork_approval_template.py new file mode 100644 index 00000000..f60663c0 --- /dev/null +++ b/sf_wxwork_approval/models/wxwork_approval_template.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +import logging +from odoo import api, fields, models +from odoo.exceptions import UserError + +_logger = logging.getLogger(__name__) + + +class WxWorkApprovalTemplate(models.Model): + _name = 'wxwork.approval.template' + _description = "企业微信审批模板" + + process_code = fields.Char(string='模板id') + name = fields.Char(string='模板名称') + # content_ids = fields.Many2many('wxwork.approval.template.controls', string='模板内容') + content_ids = fields.One2many('wxwork.approval.template.controls', 'template_id', string='模板内容') + company_id = fields.Many2one('res.company', '公司', default=lambda self: self.env.user.company_id.id) + creator_userid = fields.Many2one('res.users', '创建者', default=lambda self: self.env.user.id) + use_template_approver = fields.Selection([ + ('0', '自选审批人'), + ('1', '预设审批人') + ], string='审批人模式', default='0') + choose_department = fields.Char(string='提单部门') + approver = fields.One2many('wxwork.approval.approver_line', 'main_id', string='审批流程') + notifyer = fields.Many2many('res.users', string='抄送人userid列表') + notify_type = fields.Selection([ + ('1', '提单时抄送'), + ('2', '单据通过后抄送'), + ('3', '提单和单据通过后抄送'), + ]) + summary_info_ids = fields.One2many('wxwork.approval.template.summary', 'template_id', string='模板摘要') + + related_records_count = fields.Integer(string="关联记录数", compute="_compute_related_records_count") + + @api.depends("summary_info_ids") + def _compute_related_records_count(self): + for record in self: + record.related_records_count = len(record.summary_info_ids) + + diff --git a/sf_wxwork_approval/models/wxwork_approval_template_controls.py b/sf_wxwork_approval/models/wxwork_approval_template_controls.py new file mode 100644 index 00000000..cc5e4273 --- /dev/null +++ b/sf_wxwork_approval/models/wxwork_approval_template_controls.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +import logging +from odoo import api, fields, models +from odoo.exceptions import UserError + +_logger = logging.getLogger(__name__) + + +class WxWorkApprovalTemplate(models.Model): + _name = 'wxwork.approval.template.controls' + _description = "企业微信审批模板控件" + _rec_name = "title" + + SELECTION_RELATION = { + '申请事项': {'id': 'Text-1640339319582', 'control': 'Text', 'value': '{"text": "文本填写的内容"}'}, + '申请内容': {'id': 'Textarea-1640339335659', 'control': 'Textarea', 'value': '{"text": "文本填写的内容"}'}, + '多行文本': {'id': 'Textarea-1684823453770', 'control': 'Textarea', 'value': '{"text": "文本填写的内容"}'}, + '金额': {'id': 'Money-1684823460232', 'control': 'Money', 'value': '{"new_money": "0"}'}, + '部门': {'id': 'Contact-1684823477216', 'control': 'Contact', + 'value': '{"departments":[{"openapi_id":"2","name":"销售部"},{"openapi_id":"3","name":"生产部"}]}'}, + '成员': {'id': 'Contact-1684823465317', 'control': 'Contact', + 'value': '{"members":[{"userid":"WuJunJie","name":"Jackie"},{"userid":"WangXiaoMing","name":"Tom"}]}'}, + '明细': {'id': 'Table-1684823492261', 'control': 'Table', + 'value': '{"children":[{"list":[' + '{"control":"Text","id":"Text-15111111111","title":' + '[{"text":"明细内文本控件","lang":"zh_CN"}],"value":{"text":"明细文本1"}},' + '{"control":"Money","id":"Text-15111111112","title":[{"text":"明细内金额控件","lang":"zh_CN"}],' + '"value":{"new_money":"700"}}]},' + '{"list":[{"control":"Text","id":"Text-15111111111",' + '"title":[{"text":"明细内文本控件","lang":"zh_CN"}],"value":{"text":"明细文本2"}},' + '{"control":"Money","id":"Text-15111111112","title":[{"text":"明细内金额控件","lang":"zh_CN"}],' + '"value":{"new_money":"900"}}]}]}'}, + '关联申请单': {'id': 'RelatedApproval-1684823485883', 'control': 'RelatedApproval', + 'value': '{"related_approval":[{"sp_no":"202011180001"}]}'}, + '附件': {'id': 'File-1640339381728', 'control': 'File', + 'value': '{"files":[{"file_id":"1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K1aaa"}]}'}, + '数字': {'id': 'File-1640339381728', 'control': 'Number', 'value': '{"new_number": "700"}'}, + '日期/日期+时间': {'id': 'File-1640339381728', 'control': 'Date', + 'value': '{"date": {"type": "day","s_timestamp": "1569859200"}}'}, + '单选/多选': {'id': 'File-1640339381728', 'control': 'Selector', + 'value': '{"selector": ' + '{"type": "multi","options": [{"key": "option-15111111111"},{"key": "option-15222222222"}]}}' + }, + '说明文字': {'id': 'File-1640339381728', 'control': 'Tips'}, + '位置': {'id': 'File-1640339381728', 'control': 'Location', + 'value': '{"location":{"latitude":"30.547239","longitude":"104.063291",' + '"title":"腾讯科技(成都)有限公司(腾讯成都大厦)",' + '"address":"四川省成都市武侯区天府三街198号腾讯成都大厦A座","time":1605690460}}'}, + '公式': {'id': 'File-1640339381728', 'control': 'Formula', 'value': '{"formula":{"value":"5.0"}}'}, + '时长': {'id': 'File-1640339381728', 'control': 'DateRange', + 'value': '{"date_range":{"new_begin":1570550400,"new_end":1570593600,"new_duration":86400}}'}, + '请假组件': {'id': 'File-1640339381728', 'control': 'Vacation', + 'value': '{"vacation":{"selector":{"type":"single","options":[{"key":"3",' + '"value":[{"text":"病假","lang":"zh_CN"}]}],"exp_type":0},' + '"attendance":{"date_range":{"type":"hour","new_begin":1568077200,' + '"new_end":1568368800,"new_duration":291600},"type":1}}}'}, + '出差/外出/加班组件': {'id': 'File-1640339381728', 'control': 'Attendance', + 'value': '{"attendance":{"date_range":{"type":"halfday","new_begin":1570550400,' + '"new_end":1570593600,"new_duration":86400},"type":4}}'}, + + } + + title = fields.Selection( + selection=[(key, key) for key in SELECTION_RELATION.keys()], + string='控件名称', + ) + template_id = fields.Many2one('wxwork.approval.template', string='模板名称') + control_id = fields.Char(string='控件ID') + control = fields.Char(string='控件类型') + value = fields.Char(string='内容') + + placeholder = fields.Char(string='占位符') + require = fields.Boolean(string='必填', compute='_compute_require') + un_print = fields.Boolean(string='不打印') + un_replace = fields.Boolean(string='不替换') + display = fields.Boolean(string='显示', compute='_compute_display') + + @api.onchange('title') + def _onchange_title(self): + if self.title: + related_values = WxWorkApprovalTemplate.SELECTION_RELATION[self.title] + self.control_id = related_values['id'] + self.control = related_values['control'] + + # 特殊处理:对于"说明文字",将"value"设置为空字符串 + if self.control == 'Tips': + self.value = '' + else: + self.value = related_values['value'] + + @api.depends('title') + def _compute_require(self): + for record in self: + record.require = record.title in ['申请事项', '申请内容'] + + @api.depends('title') + def _compute_display(self): + for record in self: + record.display = record.title in ['申请事项', '申请内容'] + + +class ApproverLine(models.Model): + _name = 'wxwork.approval.approver_line' + + main_id = fields.Many2one('wxwork.approval.template', string='主模型') + userid = fields.Many2many('res.users', string='审批人userid列表') + attr = fields.Selection([('1', '或签'), ('2', '会签')], string='节点审批方式') + + +class ResUserAddShow(models.Model): + _inherit = 'res.users' + _rec_name = 'name' diff --git a/sf_wxwork_approval/models/wxwork_approval_template_summary.py b/sf_wxwork_approval/models/wxwork_approval_template_summary.py new file mode 100644 index 00000000..6326c7d0 --- /dev/null +++ b/sf_wxwork_approval/models/wxwork_approval_template_summary.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +import logging +from odoo import api, fields, models +from odoo.exceptions import UserError, ValidationError + +_logger = logging.getLogger(__name__) + + +class WxWorkApprovalTemplateSummary(models.Model): + _name = 'wxwork.approval.template.summary' + _description = "企业微信审批模板摘要" + # _rec_name = "title" + + template_id = fields.Many2one('wxwork.approval.template', string='模板名称') + text = fields.Char(string='摘要行显示文字', size=20) + lang = fields.Selection([ + ('zh_CN', '中文'), + ('en', '英文') + ], string='控件类型', default='中文') + + # @api.constrains('template_id') + # def _check_max_records(self): + # for record in self: + # # 统计与当前template_id相关联的记录数 + # related_records_count = self.search_count([ + # ('template_id', '=', record.template_id.id) + # ]) + # + # # 如果记录数大于3,则引发异常 + # if related_records_count > 3: + # raise ValidationError("最多只能有三条记录") diff --git a/sf_wxwork_approval/models/wxwork_config.py b/sf_wxwork_approval/models/wxwork_config.py new file mode 100644 index 00000000..93bb31b3 --- /dev/null +++ b/sf_wxwork_approval/models/wxwork_config.py @@ -0,0 +1,24 @@ +# models/wxwork_config.py + +from odoo import fields, models + + +class WxWorkConfigSettings(models.TransientModel): + _name = 'wxwork.config.settings' + _inherit = 'res.config.settings' + + wxwork_corp_id = fields.Char(string='企业微信CorpID') + wxwork_secret = fields.Char(string='企业微信Secret') + + def set_values(self): + super(WxWorkConfigSettings, self).set_values() + self.env['ir.config_parameter'].set_param('wxwork.corp_id', self.wxwork_corp_id) + self.env['ir.config_parameter'].set_param('wxwork.secret', self.wxwork_secret) + + def get_values(self): + res = super(WxWorkConfigSettings, self).get_values() + res.update( + wxwork_corp_id=self.env['ir.config_parameter'].get_param('wxwork.corp_id'), + wxwork_secret=self.env['ir.config_parameter'].get_param('wxwork.secret'), + ) + return res diff --git a/sf_wxwork_approval/models/wxwork_settings.py b/sf_wxwork_approval/models/wxwork_settings.py new file mode 100644 index 00000000..4e048263 --- /dev/null +++ b/sf_wxwork_approval/models/wxwork_settings.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +from odoo import api, fields, models + + +class WxSettings(models.Model): + _name = 'wxwork.settings' + _description = '企业微信设置' + + wx_work_app = fields.Char(string='企业微信应用名称') + wx_work_corp_id = fields.Char(string='企业微信CorpID') + wx_work_secret = fields.Char(string='企业微信Secret') diff --git a/sf_wxwork_approval/security/ir.model.access.csv b/sf_wxwork_approval/security/ir.model.access.csv new file mode 100644 index 00000000..e3840580 --- /dev/null +++ b/sf_wxwork_approval/security/ir.model.access.csv @@ -0,0 +1,11 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_wxwork_config_settings,wxwork.config.settings,model_wxwork_config_settings,base.group_user,1,1,1,1 +access_wxwork_approval_record,wxwork.approval.record,model_wxwork_approval_record,base.group_user,1,1,1,1 +access_wxwork_approval_template,wxwork.approval.template,model_wxwork_approval_template,base.group_user,1,1,1,1 +access_wxwork_approval_template_controls,wxwork.approval.template.controls,model_wxwork_approval_template_controls,base.group_user,1,1,1,1 +access_wxwork_approval_approver_line,wxwork.approval.approver_line,model_wxwork_approval_approver_line,base.group_user,1,1,1,1 +access_wxwork_settings,wxwork.settings,model_wxwork_settings,base.group_user,1,1,1,1 +access_wxwork_approval_template_summary,wxwork.approval.template.summary,model_wxwork_approval_template_summary,base.group_user,1,1,1,1 + + + diff --git a/sf_wxwork_approval/views/res_config_settings_views.xml b/sf_wxwork_approval/views/res_config_settings_views.xml new file mode 100644 index 00000000..9a214b32 --- /dev/null +++ b/sf_wxwork_approval/views/res_config_settings_views.xml @@ -0,0 +1,31 @@ + + + + + res.config.settings.wx.work.view.form.inherit.bpm + res.config.settings + + + +
+

企业微信环境配置

+
+
+
+
+
+
+
+ +
+
+
+ + + + + diff --git a/sf_wxwork_approval/views/views.xml b/sf_wxwork_approval/views/views.xml new file mode 100644 index 00000000..a35629d0 --- /dev/null +++ b/sf_wxwork_approval/views/views.xml @@ -0,0 +1,58 @@ + + + + wxwork.approval.tree + wxwork.approval.record + + + + + + + + + + + + + + + wxwork.approval.form + wxwork.approval.record + +
+ + + + + + + + + +
+
+
+ + + 审批记录 + ir.actions.act_window + wxwork.approval.record + tree,form + +

+ [审批记录] 还没有哦!点左上角的[创建]按钮,沙发归你了! +

+

+

+
+
+ + + +
\ No newline at end of file diff --git a/sf_wxwork_approval/views/wxwork_approval_approval_line.xml b/sf_wxwork_approval/views/wxwork_approval_approval_line.xml new file mode 100644 index 00000000..91c3bad2 --- /dev/null +++ b/sf_wxwork_approval/views/wxwork_approval_approval_line.xml @@ -0,0 +1,95 @@ + + + + + + 审批人 + wxwork.approval.approver_line + + + + + + + + + + + + + 审批人 + wxwork.approval.approver_line + +
+ + + + + + + +
+
+
+ + + 审批人 + wxwork.approval.approver_line + + + + + + + + + + + + + 审批人 + wxwork.approval.approver_line + +
+ + + + + + + +
+
+
+ + + + 摘要 + wxwork.approval.template.summary + + + + + + + + + + + 摘要 + wxwork.approval.template.summary + +
+ + + + + +
+
+
+ + +
diff --git a/sf_wxwork_approval/views/wxwork_approval_template_view.xml b/sf_wxwork_approval/views/wxwork_approval_template_view.xml new file mode 100644 index 00000000..175ab1dc --- /dev/null +++ b/sf_wxwork_approval/views/wxwork_approval_template_view.xml @@ -0,0 +1,137 @@ + + + + + + 审批模板 + wxwork.approval.template + + + + + + + + + + + + 审批模板 + wxwork.approval.template + +
+ + + + + + + + + + + + + +
+
+
+ + + 审批模板 + wxwork.approval.template + + + + + + +
+
+
+
+ + + +
+
+ +
+
+
+
+
+
+
+ + + 审批模板控件 + wxwork.approval.template.controls + + + + + + + + + + + + + + + + + 审批模板控件 + wxwork.approval.template.controls + +
+ + + + + + + + + + + + +
+
+
+ + + 审批模板 + wxwork.approval.template + kanban,tree,form + +

+ 请创建模板,填写模板id然后点击获取模板详情!!! +

+
+
+ + + 审批模板控件 + wxwork.approval.template.controls + tree,kanban,form + +

+ 请创建模板控件!!! +

+
+
+ + + + + + +
diff --git a/sf_wxwork_approval/views/wxwork_config_view.xml b/sf_wxwork_approval/views/wxwork_config_view.xml new file mode 100644 index 00000000..53a4153a --- /dev/null +++ b/sf_wxwork_approval/views/wxwork_config_view.xml @@ -0,0 +1,34 @@ + + + wxwork.config.settings.form + wxwork.config.settings + +
+
+
+ + +
+
+
+ + + 企业微信设置 + wxwork.config.settings + form + inline + + + +
diff --git a/sf_wxwork_approval/views/wxwork_settings_view.xml b/sf_wxwork_approval/views/wxwork_settings_view.xml new file mode 100644 index 00000000..904fd019 --- /dev/null +++ b/sf_wxwork_approval/views/wxwork_settings_view.xml @@ -0,0 +1,43 @@ + + + + + 企业微信设置 + wxwork.settings + + + + + + + + + + 企业微信设置 + wxwork.settings + +
+ + + + + +
+
+
+ + + 企业微信设置 + wxwork.settings + tree,form + +

+ 请设置企业微信参数!!! +

+
+
+ + + +