From 5d9572f152e1a8ce40ba90df236749c008512d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Mon, 21 Apr 2025 08:24:42 +0800 Subject: [PATCH] 1 --- docx_report_pro/controllers/controllers.py | 4 +- docx_report_pro/models/ir_actions_report.py | 19 +++- docx_report_pro/views/views.xml | 11 +- search_panel_extension/__manifest__.py | 2 +- .../static/src/js/search_model.js | 72 ++++++------ .../wizard/soong_workflow_comment_wizard.py | 4 +- tree_view_advanced_filter/__init__.py | 1 + tree_view_advanced_filter/override_relaxng.py | 21 ++++ tree_view_advanced_filter/rng/tree_view.rng | 104 ++++++++++++++++++ .../list_arch_parser.js | 19 ++++ .../src/tree_view_advanced_filter/tree.js | 1 + 11 files changed, 208 insertions(+), 50 deletions(-) create mode 100644 tree_view_advanced_filter/override_relaxng.py create mode 100644 tree_view_advanced_filter/rng/tree_view.rng create mode 100644 tree_view_advanced_filter/static/src/tree_view_advanced_filter/list_arch_parser.js diff --git a/docx_report_pro/controllers/controllers.py b/docx_report_pro/controllers/controllers.py index 39db997bb..8377cfbbd 100644 --- a/docx_report_pro/controllers/controllers.py +++ b/docx_report_pro/controllers/controllers.py @@ -152,7 +152,9 @@ class ReportControllerDocx(ReportController): ids = [int(x) for x in docids.split(",")] obj = request.env[report.model].browse(ids) if report.print_report_name and not len(obj) > 1: - report_name = safe_eval(report.print_report_name, {"object": obj, "time": time}) + report_name = safe_eval( + report.print_report_name, {"object": obj, "time": time} + ) filename = "%s.%s" % (report_name, extension) response.headers.add( "Content-Disposition", content_disposition(filename) diff --git a/docx_report_pro/models/ir_actions_report.py b/docx_report_pro/models/ir_actions_report.py index af51a4be8..246f8aaa6 100644 --- a/docx_report_pro/models/ir_actions_report.py +++ b/docx_report_pro/models/ir_actions_report.py @@ -171,6 +171,23 @@ class IrActionsReport(models.Model): def _render_docx(self, report_ref, res_ids, data=None): return self.render_docx(report_ref, res_ids, data) + def _get_context(self, doc): + # [XSK] TODO(2025/4/20 22:01): + # 改成递归获取关联字段, + # 但是可能会存在无限递归的字段,需要注意 + # 可以添加最大递归层级,超过最大递归层级时停止递归 + deep_field_type = ['many2one', 'many2many', 'one2many'] + doc.ensure_one() + context = doc.sudo().read()[0] + fields_dict = doc.fields_get() + for field, field_info in fields_dict.items(): + try: + if field_info['type'] in deep_field_type: + context[field] = doc[field].sudo().read() + except Exception as e: + _logger.error("Error get field " + field + " in model " + doc._name + " " + str(e)) + return context + @api.model def render_docx(self, report_ref, docids, data=None): self = self.sudo() @@ -195,7 +212,7 @@ class IrActionsReport(models.Model): for doc in data["docs"]: # add all record fields by default data to insert - context = doc.sudo().read()[0] + context = self._get_context(doc) # add prepare python method data to insert if self.python_function_prepare: diff --git a/docx_report_pro/views/views.xml b/docx_report_pro/views/views.xml index f4ef16ed6..cbcd4bb78 100644 --- a/docx_report_pro/views/views.xml +++ b/docx_report_pro/views/views.xml @@ -15,13 +15,13 @@ + invisible="report_type not in ['docx']" /> + invisible="report_type not in ['docx']" /> - - + + Change rights and give all users access + writing to the directory you want the documents to be saved in: /tmp/backups

- - 报表类型 -
diff --git a/search_panel_extension/__manifest__.py b/search_panel_extension/__manifest__.py index 4f7553f81..c583e9f4c 100644 --- a/search_panel_extension/__manifest__.py +++ b/search_panel_extension/__manifest__.py @@ -9,7 +9,7 @@ 'license': 'LGPL-3', 'depends': ['base', 'sale_management'], 'data': [ - 'views/product_views.xml', + # 'views/product_views.xml', ], 'assets': { 'web.assets_backend': [ diff --git a/search_panel_extension/static/src/js/search_model.js b/search_panel_extension/static/src/js/search_model.js index e2b5b6c1d..a29db4d47 100644 --- a/search_panel_extension/static/src/js/search_model.js +++ b/search_panel_extension/static/src/js/search_model.js @@ -1,7 +1,7 @@ /** @odoo-module */ -import {SearchModel} from "@web/search/search_model"; -import {Domain} from "@web/core/domain"; -import {patch} from "@web/core/utils/patch"; +import { SearchModel } from "@web/search/search_model"; +import { Domain } from "@web/core/domain"; +import { patch } from "@web/core/utils/patch"; export function childrenSize(children) { if (children instanceof Map) { @@ -10,16 +10,15 @@ export function childrenSize(children) { return children.length } else if (children instanceof Object) { return Object.keys(children).length > 0 - } else { + }else { return false } } patch(SearchModel.prototype, { - _createFilterTree(sectionId, result) { - debugger; + _createFilterTree(sectionId, result) { super._createFilterTree(sectionId, result) - let {values} = result; + let { values } = result; const filter = this.sections.get(sectionId) const valIds = result['values'].map(item => item.id).filter(item => item) @@ -28,28 +27,30 @@ patch(SearchModel.prototype, { groups.forEach((group, key) => { // 求和 // Array.from(group.values.values()).map(item => item.__count).reduce((acc, cur) => acc + cur, 0) - group.__count = (values.find(item => item.id === key)?.__count ?? 0) - if (!key) { + group.__count = values.find(item => item.id === key)?.__count ?? 0; + if (!key) return; + + const currentItem = values.find(item => item.id === key); // 集中获取当前项 + const group_id = currentItem?.group_id; + + const parentGroup = valIds.includes(group_id) + ? groups.get(group_id) + : groups.get(false); + + if (!parentGroup) return; + + // 统一处理子节点逻辑 + if (group_id === key) { + group.parent = false; return; } - const group_id = values.find(item => item.id === key)?.group_id - if (valIds.includes(group_id)) { - if (group_id === key) { - group.parent = false; - return; - } - if (!childrenSize(groups.get(group_id).children)) { - groups.get(group_id).children = new Map() - } - groups.get(group_id).children.set(key, group) - } else { - if (!groups.get(false)) return; - if (!childrenSize(groups.get(false).children)) { - groups.get(group_id).children = new Map() - } - groups.get(false).children.set(key, group) + + if (!parentGroup.children || !childrenSize(parentGroup.children)) { + parentGroup.children = new Map(); } - group.parent = group_id; + + parentGroup.children.set(key, group); + group.parent = parentGroup === groups.get(false) ? false : group_id; }) } filter.groups = groups; @@ -96,8 +97,8 @@ patch(SearchModel.prototype, { if (groups) { groups.forEach((group, key) => { // Array.from(group.values.values()).map(item => item.__count).reduce((acc, cur) => acc + cur, 0) - group.__count = (Array.from(section?.values?.values() ?? []).find(item => item.id === key)?.__count ?? 0); - const group_id = Array.from(section?.values?.values() ?? []).find(item => item.id === key)?.group_id; + group.__count = (section.values.values().find(item => item.id === key)?.__count ?? 0) + const group_id = section.values.values().find(item => item.id === key)?.group_id if (ids.includes(group_id)) { if (group_id === key) { group.parent = false; @@ -109,11 +110,8 @@ patch(SearchModel.prototype, { groups.get(group_id).children.set(key, group) } else { if (!groups.get(false)) return; - // if (!childrenSize(groups.get(false).children)) { - // groups.get(group_id).children = new Map() - // } - if (!childrenSize(groups.get(group_id).children)) { - groups.get(group_id).children = new Map(); + if (!childrenSize(groups.get(false).children)) { + groups.get(group_id).children = new Map() } groups.get(false).children.set(key, group) } @@ -130,7 +128,6 @@ patch(SearchModel.prototype, { // debugger; const domain = []; const domainList = []; - function addCondition(fieldName, valueMap) { const ids = []; for (const [valueId, value] of valueMap) { @@ -143,12 +140,11 @@ patch(SearchModel.prototype, { domainList.push(it); } } - for (const filter of this.filters) { if (filter.id === excludedFilterId) { continue; } - const {fieldName, groups, values} = filter; + const { fieldName, groups, values } = filter; if (groups) { for (const group of groups.values()) { addCondition(fieldName, group.values); @@ -163,8 +159,8 @@ patch(SearchModel.prototype, { _getGroupDomain(filter) { // debugger; - const {fieldName, groups, enableCounters} = filter; - const {type: fieldType} = this.searchViewFields[fieldName]; + const { fieldName, groups, enableCounters } = filter; + const { type: fieldType } = this.searchViewFields[fieldName]; const groupDomain = super._getGroupDomain(filter); diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py index 6628d59cf..b32980686 100644 --- a/soong_workflow/wizard/soong_workflow_comment_wizard.py +++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py @@ -96,8 +96,8 @@ class SoongWorkflowCommentWizard(models.TransientModel): employee_user_role_id = self.env['hr.employee'].search( ['|', ('user_role_id', '=', link_users_id.id), ('user_role_ids', 'in', link_users_id.id), '|', ('department_id', '=', record_id.department_id.parent_id.id), ('department_ids', 'in', record_id.department_id.parent_id.id)]) - self.employee_trans_domain_ids = employee_user_role_ids if next_is_automatic else employee_user_role_id - self.employee_ids = employee_user_role_ids if next_is_automatic else employee_user_role_id + self.employee_trans_domain_ids = employee_user_role_ids if not next_is_automatic else employee_user_role_id + self.employee_ids = employee_user_role_ids if not next_is_automatic else employee_user_role_id if '分发' in ret.name: self.employee_ids = record_id.users_id.employee_id diff --git a/tree_view_advanced_filter/__init__.py b/tree_view_advanced_filter/__init__.py index 40a96afc6..be0b804c9 100644 --- a/tree_view_advanced_filter/__init__.py +++ b/tree_view_advanced_filter/__init__.py @@ -1 +1,2 @@ # -*- coding: utf-8 -*- +from . import override_relaxng diff --git a/tree_view_advanced_filter/override_relaxng.py b/tree_view_advanced_filter/override_relaxng.py new file mode 100644 index 000000000..d7cd6fb72 --- /dev/null +++ b/tree_view_advanced_filter/override_relaxng.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +import os +import logging +from lxml import etree +from odoo import tools +from odoo.tools import view_validation + +_logger = logging.getLogger(__name__) + +_relaxng_cache = view_validation._relaxng_cache +_relaxng_cache['tree'] = None + + +with tools.file_open(os.path.join(os.path.dirname(__file__), 'rng', 'tree_view.rng')) as frng: + try: + text = frng.read() + relaxng_doc = etree.fromstring(text.encode('utf-8')) + _relaxng_cache['tree'] = etree.RelaxNG(relaxng_doc) + except Exception as error: + _logger.exception('Failed to load RelaxNG XML schema for views validation, {error}'.format(error=error)) + _relaxng_cache['search'] = None diff --git a/tree_view_advanced_filter/rng/tree_view.rng b/tree_view_advanced_filter/rng/tree_view.rng new file mode 100644 index 000000000..bd0b869ff --- /dev/null +++ b/tree_view_advanced_filter/rng/tree_view.rng @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tree_view_advanced_filter/static/src/tree_view_advanced_filter/list_arch_parser.js b/tree_view_advanced_filter/static/src/tree_view_advanced_filter/list_arch_parser.js new file mode 100644 index 000000000..3f1606bd6 --- /dev/null +++ b/tree_view_advanced_filter/static/src/tree_view_advanced_filter/list_arch_parser.js @@ -0,0 +1,19 @@ +/** @odoo-module **/ +import { archParseBoolean } from "@web/views/utils"; +import { patch } from "@web/core/utils/patch"; +import { visitXML, parseXML } from "@web/core/utils/xml"; +import { ListArchParser } from "@web/views/list/list_arch_parser"; + + +patch(ListArchParser.prototype, { + + parse(arch, models, modelName) { + let parse_return = super.parse(arch, models, modelName); + visitXML(arch, (node) => { + if (["tree", "list"].includes(node.tagName)){ + parse_return.advanced_filter = archParseBoolean(arch.getAttribute("advanced_filter"), false); + } + }); + return parse_return + } +}) \ No newline at end of file diff --git a/tree_view_advanced_filter/static/src/tree_view_advanced_filter/tree.js b/tree_view_advanced_filter/static/src/tree_view_advanced_filter/tree.js index a63450689..8c3dd0f9c 100644 --- a/tree_view_advanced_filter/static/src/tree_view_advanced_filter/tree.js +++ b/tree_view_advanced_filter/static/src/tree_view_advanced_filter/tree.js @@ -26,6 +26,7 @@ export const ListRendererCust = { }, _renderSearchPanel: async function () { + if (!this.props.archInfo.advanced_filter) return; // await loadJS("https://cdn.jsdelivr.net/jquery/latest/jquery.min.js") // await loadJS("https://cdn.jsdelivr.net/momentjs/latest/moment.min.js") // await loadJS("https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js")