# -*- coding: utf-8 -*- from odoo.osv import expression from odoo import models, fields, tools, api class TxDataDict(models.Model): _name = 'tx.data.dict' _inherit = ['mail.thread', 'mail.activity.mixin'] _description = '数据字典' _rec_name = "display_name" _order = "sequence" sequence = fields.Integer(string='序号', default=1) name = fields.Char(string="名称") display_name = fields.Char(string="显示名称", compute="_compute_display_name") code = fields.Char(string="编码") category = fields.Selection([("key", "字典项"), ("value", "字典值")], string="类型", default="value") parent_id = fields.Many2one("tx.data.dict", string="字典项", domain='[("category", "=", "key")]') child_ids = fields.One2many("tx.data.dict", "parent_id", string="字典值") parent_code = fields.Char(related="parent_id.code", string="字典项编码") remarks = fields.Char(string="备注") company_id = fields.Many2one("res.company", string="所属公司", default=lambda self: self.env.company.id) _sql_constraints = [('unique_code', 'UNIQUE(code)', '编码必须唯一')] @api.model def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): if name != '': domain = [('name', operator, name)] return self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid) return super(TxDataDict, self)._name_search(name=name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid) def _compute_display_name(self): for r in self: if r.category == "key": r.display_name = f"{r.code} {r.name}" else: r.display_name = f"{r.parent_code}/{r.code} {r.name}" def _get_dict_values(self): result = [{"id": 0, "name": "全部", "code": "", "parentId": 0, "parentName": "", "parentCode": ""}] for child_id in self.child_ids: parent_id = child_id.parent_id result.append({"id": child_id.id, "name": child_id.name, "code": child_id.code, "parentId": parent_id.id, "parentName": parent_id.name, "parentCode": parent_id.code}) return result class TxMenu(models.Model): _name = "tx.menu" _inherit = ['mail.thread', 'mail.activity.mixin'] _description = "网站菜单" _order = "sequence" sequence = fields.Integer(string='序号', default=1) name = fields.Char(string="名称") description = fields.Char(string="描述") icon = fields.Image(string="图标") img = fields.Image(string="图片") return_url = fields.Char(string="跳转路由") parent_id = fields.Many2one("tx.menu", string="上级菜单") res_model = fields.Many2one("ir.model", string="所属模型") child_ids = fields.One2many("tx.menu", "parent_id", string="下级菜单") class TxSystemLog(models.Model): _name = "tx.system.log" _description = "系统日志" _auto = False _order = "message_id desc" message_id = fields.Integer(string="消息ID") model_id = fields.Many2one("ir.model", string="数据模型") res_id = fields.Integer(string="来源记录") author_id = fields.Many2one("res.partner", string="用户") message = fields.Html(string="消息", sanitize=False) def init(self): tools.drop_view_if_exists(self._cr, self._table) self._cr.execute(""" CREATE OR REPLACE VIEW %s AS ( SELECT row_number() over(order by mm.id) AS id, mm.id AS message_id, im.id AS model_id, mm.res_id AS res_id, mm.author_id AS author_id, (CASE WHEN mm.body != '' THEN mm.body ELSE (CASE WHEN mtv.field_type = 'char' THEN mtv.field_desc || ': ' || mtv.old_value_char || ' --> ' || mtv.new_value_char WHEN mtv.field_type = 'float' THEN mtv.field_desc || ': ' || mtv.old_value_float || ' --> ' || mtv.new_value_float WHEN mtv.field_type = 'text' THEN mtv.field_desc || ': ' || mtv.old_value_text || ' --> ' || mtv.new_value_text WHEN mtv.field_type = 'integer' THEN mtv.field_desc || ': ' || mtv.old_value_integer || ' --> ' || mtv.new_value_integer WHEN mtv.field_type = 'datetime' THEN mtv.field_desc || ': ' || mtv.old_value_datetime || ' --> ' || mtv.new_value_datetime ELSE NULL END) END) AS message FROM mail_message mm LEFT JOIN mail_tracking_value mtv ON mm.id = mtv.mail_message_id LEFT JOIN ir_model im ON im.model = mm.model WHERE mm.subtype_id = 2 ORDER BY mm.id DESC ) """% (self._table))