diff --git a/list_view_sticky_header_and_column/README.rst b/list_view_sticky_header_and_column/README.rst
index fd8816471..236e8a22b 100644
--- a/list_view_sticky_header_and_column/README.rst
+++ b/list_view_sticky_header_and_column/README.rst
@@ -1,3 +1,14 @@
+
+.. image:: https://tools.huo15.com/uploads/images/system/logo-colours.png
+ :width: 100
+ :alt: logo
+
+辉火云企业套件社区版 - 附加模块
+===========================
+HuihuoYun Business Suite Community addons
+-----------------------------------------
+
+
.. image:: https://img.shields.io/badge/license-LGPL--3-green.svg
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
diff --git a/list_view_sticky_header_and_column/static/src/js/list_view_sticky_header_and_column.js b/list_view_sticky_header_and_column/static/src/js/list_view_sticky_header_and_column.js
index 3ab2197b4..b88965677 100644
--- a/list_view_sticky_header_and_column/static/src/js/list_view_sticky_header_and_column.js
+++ b/list_view_sticky_header_and_column/static/src/js/list_view_sticky_header_and_column.js
@@ -1,22 +1,173 @@
/** @odoo-module **/
/** This file will used to stick the selected header and column in the list view **/
-import { patch } from "@web/core/utils/patch";
-import { ListRenderer } from "@web/views/list/list_renderer";
+import {patch} from "@web/core/utils/patch";
+import {ListRenderer} from "@web/views/list/list_renderer";
+import {onMounted, onWillUnmount} from "@odoo/owl";
+
+/**
+ * @file list_view_sticky_header_and_column.js
+ * @description 辉火云企业套件
+ * @author Job Zhao - 青岛火一五信息科技有限公司
+ * @contact postmaster@huo15.com | 18554898815
+ * @date 2025/1/28
+ * @copyright 青岛火一五信息科技有限公司 保留所有权利
+ * @see https://www.huo15.com
+ */
patch(ListRenderer.prototype, {
/** super the setup function **/
setup() {
super.setup();
+ // >>> 青岛火一五信息科技有限公司 - JobZhao - postmaster@huo15.com - 2025/1/28
+ onMounted(() => {
+ this.root = this.__owl__.bdom.parentEl;
+ this._adjustColumnWidths();
+ const $thead = $(this.__owl__.bdom.parentEl.querySelectorAll('.o_list_table thead')[0]);
+ $thead.css('z-index', '100000')
+ //移除现有的粘性列和选中标记
+ const $clickedHeader = $(this.__owl__.bdom.parentEl.querySelectorAll('.o_list_table th')[1]);
+ $(this.__owl__.bdom.parentEl.querySelectorAll('.sticky-column')).removeClass('sticky-column');
+ console.log($(this.__owl__.bdom.parentEl.querySelectorAll('.sticky-column')).removeClass('sticky-column'));
+ $(this.__owl__.bdom.parentEl.querySelectorAll('.clicked-header')).removeClass('clicked-header');
+ $clickedHeader.addClass('clicked-header');
+ const columnIndex = $clickedHeader.index();
+
+ //获取表头、表行和表尾的元素
+ const $tableHeaders = $(this.__owl__.bdom.parentEl.querySelectorAll('.o_list_table th'));
+ const $tableRows = $(this.__owl__.bdom.parentEl.querySelectorAll('.o_list_table tr'));
+ const $tfootRow = $(this.__owl__.bdom.parentEl.querySelectorAll('.o_list_table tfoot tr')[0].children);
+ //为选中的列和表头添加粘性效果
+ const $selectedFooterCells = $tfootRow.filter(`td:nth-child(-n+${columnIndex + 1})`);
+ $selectedFooterCells.addClass('sticky-column');
+ const $selectedColumns = $(this.__owl__.bdom.parentEl.querySelectorAll(`.o_data_row td:nth-child(-n+${columnIndex + 1})`));
+ const $selectedHeaderCells = $tableHeaders.filter(`th:nth-child(-n+${columnIndex + 1})`);
+ $tableHeaders.removeClass('sticky-column').css('left', '');
+ $(this.__owl__.bdom.parentEl.querySelectorAll('.o_data_row td')).removeClass('sticky-column').css('left', '');
+ $selectedColumns.addClass('sticky-column');
+ $selectedHeaderCells.addClass('sticky-column');
+ $tableHeaders.filter('.sticky-column').css('top', '0');
+
+ // 调整列的 left 位置
+ const $targetColumn = $selectedColumns.eq(columnIndex);
+ const targetLeftPosition = $targetColumn.position().left;
+ const columnsToAdjust = columnIndex + 1;
+ $tableRows.each(function (index, row) {
+ const $headerCells = $(row).find('th');
+ const $rowCells = $(row).find('td');
+ for (let i = 0; i < columnsToAdjust; i++) {
+ if ($headerCells.eq(i).length > 0) {
+ $headerCells.eq(i).css('left', `${$headerCells.eq(i).position().left}px`);
+ }
+ if ($rowCells.eq(i).length > 0) {
+ $rowCells.eq(i).css('left', `${$rowCells.eq(i).position().left}px`);
+ }
+ }
+ });
+
+ // 监听窗口缩放事件
+ this.resizeObserver = new ResizeObserver(() => {
+ this._adjustColumnWidths();
+ });
+ this.resizeObserver.observe(this.root);
+ });
+ // 在组件卸载时停止监听
+ onWillUnmount(() => {
+ if (this.resizeObserver) {
+ this.resizeObserver.disconnect();
+ }
+ });
+ },
+ /**
+ * 调整列宽和换行逻辑
+ */
+ _adjustColumnWidths() {
+ // >>> 青岛火一五信息科技有限公司 - JobZhao - postmaster@huo15.com - 2025/1/28
+ this.root = this.__owl__.bdom.parentEl;
+
+ const table = this.root.querySelector(".o_list_table"); // 获取表格元素
+ if (!table) return;
+
+ const columns = table.querySelectorAll("th"); // 获取所有表头
+ const rows = table.querySelectorAll(".o_data_row"); // 获取所有数据行
+
+ columns.forEach((column, colIndex) => {
+ let maxWidth = 0;
+ let maxContent = "";
+ const thContent = column.textContent.trim();
+
+ console.log('th length:', thContent.length)
+ // 遍历每一行,找到最长的单元格内容
+ rows.forEach((row) => {
+ const cell = row.querySelector(`td:nth-child(${colIndex + 1})`);
+ if (cell) {
+ const content = cell.textContent.trim();
+ let isChinese = /[\u4e00-\u9fa5]/.test(thContent); // 判断是否包含汉字
+
+ let contentLength = content.length;
+ let thContentLength = thContent.length;
+ if (thContentLength<=2){
+ thContentLength*=1.5;
+ }
+ if (isChinese) {
+ thContentLength *= 2.5;
+ }
+ if (contentLength <= thContentLength) {
+ contentLength = thContentLength;
+ }
+ isChinese = /[\u4e00-\u9fa5]/.test(content); // 判断是否包含汉字
+ if (isChinese) {
+ contentLength *= 2;
+ }
+ // 更新最大宽度和最长内容
+ if (contentLength > maxWidth) {
+ maxWidth = contentLength;
+ maxContent = content;
+ }
+ // 更新最大宽度和最长内容
+ if (contentLength > maxWidth) {
+ maxWidth = contentLength;
+ maxContent = content;
+ }
+ }
+ });
+
+ // 设置列宽
+ if (maxWidth > 0 && maxWidth < 30) {
+ const columnWidth = maxWidth * 1; // 假设每个字符占 8px
+ column.style.minWidth = `${columnWidth}ch`;
+ column.style.maxWidth = `${columnWidth}ch`;
+ column.style.width = `${columnWidth}ch`;
+ } else if (maxWidth >= 30) {
+ column.style.minWidth = `240px`;
+ column.style.maxWidth = `240px`;
+ column.style.width = `240px`;
+ }
+
+
+ // 如果最长内容超过 30 个字符,设置换行
+ if (maxWidth > 30) {
+ rows.forEach((row) => {
+ const cell = row.querySelector(`td:nth-child(${colIndex + 1})`);
+ if (cell) {
+ console.log('cell:', cell)
+ cell.style.whiteSpace = "normal"; // 允许换行
+ cell.style.wordWrap = "break-word"; // 允许长单词换行
+
+ }
+ });
+ }
+ });
},
/**
* function defining the button having t-on-click _onClick
*/
_onClickIcon(ev, record) {
+
ev.preventDefault();
ev.stopPropagation()
+ console.log('target current:', $(ev.currentTarget))
const $clickedHeader = $(ev.currentTarget).closest('th');
const columnIndex = $clickedHeader.index();
- console.log(this.__owl__.bdom.parentEl)
$(this.__owl__.bdom.parentEl.querySelectorAll('.sticky-column')).removeClass('sticky-column');
console.log($(this.__owl__.bdom.parentEl.querySelectorAll('.sticky-column')).removeClass('sticky-column'))
$(this.__owl__.bdom.parentEl.querySelectorAll('.clicked-header')).removeClass('clicked-header');
@@ -42,6 +193,7 @@ patch(ListRenderer.prototype, {
for (let i = 0; i < columnsToAdjust; i++) {
if ($headerCells.eq(i).length > 0) {
$headerCells.eq(i).css('left', `${$headerCells.eq(i).position().left}px`);
+
}
if ($rowCells.eq(i).length > 0) {
$rowCells.eq(i).css('left', `${$rowCells.eq(i).position().left}px`);
diff --git a/list_view_sticky_header_and_column/static/src/scss/list_view_sticky_header_and_column.scss b/list_view_sticky_header_and_column/static/src/scss/list_view_sticky_header_and_column.scss
index 72dc1ebfa..dd90a4e9d 100644
--- a/list_view_sticky_header_and_column/static/src/scss/list_view_sticky_header_and_column.scss
+++ b/list_view_sticky_header_and_column/static/src/scss/list_view_sticky_header_and_column.scss
@@ -1,67 +1,99 @@
.o_action .o_content {
- z-index: 1;
+ z-index: 1;
}
.sticky-column {
- position: sticky !important;
- background-color: white;
- z-index: 2;
+ position: sticky !important;
+ background-color: white;
+ z-index: 2;
}
+
.o_list_view .o_list_table td.sticky-column {
- z-index: 4;
- background-color: white;
+ z-index: 4;
+ background-color: white;
}
+
.o_list_view .o_list_table thead {
- position: sticky;
- top: 0;
- z-index: 3;
- background-color: white;
+ position: sticky;
+ top: 0;
+ z-index: 3;
+ background-color: white;
}
+
.o_list_view .o_list_table th.sticky-column {
- z-index: 4;
- background-color: white;
+ z-index: 4;
+ background-color: white;
}
+
.o_account_reports_page .table-responsive {
- overflow-x: auto;
- overflow-y: visible;
+ overflow-x: auto;
+ overflow-y: visible;
}
+
.table-responsive {
- overflow: visible;
+ overflow: visible;
}
+
.o_list_view .table-responsive .table thead {
- z-index: 1;
+ z-index: 1;
}
+
.o_form_view:not(.o_field_highlight) .o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) {
- --o-input-border-color: transparent;
- //border-style: solid;
- //border-color: #000;
- //border-width: 0px;
- //border-bottom-width: 1px;
+ --o-input-border-color: transparent;
+ //border-style: solid;
+ //border-color: #000;
+ //border-width: 0px;
+ //border-bottom-width: 1px;
}
+
body.white .table {
- width: -webkit-fill-available !important;
+ width: -webkit-fill-available !important;
}
+
.o_list_renderer .o_list_table thead {
- position: sticky;
- top: 0;
- z-index: 6;
+ position: sticky;
+ top: 0;
+ z-index: 6;
}
+
th.sticky-column::before {
- content: "";
- position: absolute;
- width: 5px;
- height: 100%;
- background: white;
- top: 0;
- left: -4px;
+ content: "";
+ position: absolute;
+ width: 5px;
+ height: 100%;
+ background: white;
+ top: 0;
+ left: -4px;
}
+
.fa-thumb-tack {
- display: none;
+ display: none;
}
th:hover .fa-thumb-tack,
th.clicked-header .fa-thumb-tack {
- display: block;
+ display: block;
}
//.o_input:hover{background: #b3c8df!important;}
+
+
+// >>> 青岛火一五信息科技有限公司 - JobZhao - postmaster@huo15.com - 2025/1/28
+// 解决宽度调整
+.o_list_view {
+ .o_list_table {
+ table-layout: auto; // 让表格宽度根据内容自动调整
+ width: 100%; // 确保表格宽度占满容器
+
+ th, td {
+ white-space: nowrap; // 默认不换行
+ overflow: hidden; // 超出部分隐藏
+ text-overflow: ellipsis; // 超出部分显示省略号
+ }
+
+ td.long-text {
+ white-space: normal; // 允许换行
+ word-wrap: break-word; // 允许长单词换行
+ }
+ }
+}
\ No newline at end of file
diff --git a/soong_workflow/models/soong_workflow_log.py b/soong_workflow/models/soong_workflow_log.py
index c506f6dfe..098850c5a 100644
--- a/soong_workflow/models/soong_workflow_log.py
+++ b/soong_workflow/models/soong_workflow_log.py
@@ -38,9 +38,9 @@ class SoongWorkflowLog(models.Model):
done_by = fields.Many2one(comodel_name="res.users", string="审批人")
lase_click_date = fields.Datetime(string="操作时间")
approval_state = fields.Selection([
- ('0', '待审批'),
- ('1', '审批中'),
- ('2', '已审批'),
+ ('0', '待办'),
+ ('1', '办理中'),
+ ('2', '已办结'),
], string='审批状态', default='0')
comment = fields.Char(string="意见")
date_create = fields.Datetime(string="时间", default=lambda self: fields.Datetime.now())
diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py
index 9bf63e307..53439c51a 100644
--- a/soong_workflow/models/soong_workflow_mixin.py
+++ b/soong_workflow/models/soong_workflow_mixin.py
@@ -155,7 +155,7 @@ class SoongWorkflowMixin(models.AbstractModel):
log_ids = fields.One2many(
comodel_name="soong.workflow.log",
inverse_name="res_id",
- string="Logs",
+ string=" ",
domain=lambda self: [("model", "=", self._name)],
auto_join=True,
)
@@ -716,6 +716,8 @@ class SoongWorkflowMixin(models.AbstractModel):
if button.is_highlight:
btn_exec_action_el.set("class", "oe_highlight")
+ # if button.is_high_red:
+ # btn_exec_action_el.set("style", "background-color: red !important;color: white !important;")
if button.has_icon:
btn_exec_action_el.set("icon", button.icon)
if is_review_type_invisible:
diff --git a/soong_workflow/models/soong_workflow_node.py b/soong_workflow/models/soong_workflow_node.py
index dcf96f447..bb5189ed2 100644
--- a/soong_workflow/models/soong_workflow_node.py
+++ b/soong_workflow/models/soong_workflow_node.py
@@ -84,10 +84,9 @@ class SoongWorkflowNode(models.Model):
res_bg_color = fields.Char(compute="_compute_custom_colors", readonly=True, string="Backgroung Color")
res_label_color = fields.Char(compute="_compute_custom_colors", readonly=True, string="Label Color")
- is_carbon_copy = fields.Boolean(string="抄送")
+ is_carbon_copy = fields.Boolean(string="抄送/传阅")
is_apostille = fields.Boolean(string="加签", default=False)
- employee_ids = fields.Many2many('hr.employee', string='抄送人员')
-
+ employee_ids = fields.Many2many('hr.employee', string='抄送/传阅人员')
@api.onchange("is_apostille")
def onchange_is_apostille(self):
@@ -95,7 +94,7 @@ class SoongWorkflowNode(models.Model):
if record.is_apostille:
sequence = max([r.sequence for r in record.button_ids] if record.button_ids else [1])
record.button_ids = [
- (0, 0, {
+ (0, 0, {
"name": _("加签"),
"workflow_id": record.workflow_id,
"node_id": record.id,
@@ -117,60 +116,76 @@ class SoongWorkflowNode(models.Model):
else:
record.button_ids.filtered(lambda r: r.name in ["加签", "加签确认"]).unlink()
-
@api.model_create_multi
def create(self, values):
- for val in values:
- if val['node_name'] != 'end':
- if not val["button_ids"]:
- if val['node_name'] == 'start':
- val["button_ids"] = [
+ records = super().create(values)
+ for record in records:
+ if record.node_name != 'end':
+ if not record.button_ids:
+ if record.node_name == 'start':
+ record.write({"button_ids": [
(0, 0, {
"name": _("转交"),
- "workflow_id": val['workflow_id'],
- "sequence": 1,
- },),
+ "workflow_id": record.workflow_id.id,
+ "sequence": 1}),
(0, 0, {
"name": _("收回"),
- "workflow_id": val['workflow_id'],
+ "workflow_id": record.workflow_id.id,
"sequence": 2,
"action_type": "code",
"code": "obj.action_withdraw()",
- },)]
- elif val['node_name'] == '分发':
- val["button_ids"] = [
- (0, 0, {
- "name": _("分发"),
- "workflow_id": val['workflow_id'],
- "sequence": 1,
- "action_type": "code",
- "has_comment": True,
- },)]
+ })
+ ]})
+ elif record.node_name == '分发':
+ record.write({"button_ids": [(0, 0, {
+ "name": _("分发"),
+ "workflow_id": record.workflow_id.id,
+ "sequence": 1,
+ "action_type": "code",
+ "has_comment": True,
+ })]})
else:
- val["button_ids"] = [
+ record.write({"button_ids": [
(0, 0, {
"name": _("转交"),
- "workflow_id": val['workflow_id'],
+ "workflow_id": record.workflow_id.id,
"sequence": 1,
"action_type": "code",
- "has_comment": True,
- },),
+ "has_comment": True}),
(0, 0, {
"name": _("收回"),
- "workflow_id": val['workflow_id'],
+ "workflow_id": record.workflow_id.id,
"sequence": 2,
"action_type": "code",
- "code": "obj.action_withdraw()",
- },),
+ "code": "obj.action_withdraw()"}),
(0, 0, {
"name": _("退回"),
- "workflow_id": val['workflow_id'],
+ "workflow_id": record.workflow_id.id,
"sequence": 2,
"action_type": "code",
- "has_comment": True,
- },)]
-
- return super().create(values)
+ "has_comment": True})
+ ]})
+ # 运行时执行加载所有form,并且只读
+ model_id = self.env['soong.workflow'].search([('id', '=', record.workflow_id.id), ('is_enable', '=', True)]).model_id
+ form_view = self.env["ir.ui.view"].search([("model", "=", model_id.model), ("type", "=", "form")], limit=1)
+ if form_view:
+ xml_tree = etree.fromstring(form_view.arch)
+ field_names = set()
+ for field_node in xml_tree.xpath("//field"):
+ field_name = field_node.get("name")
+ if field_name:
+ field_names.add(field_name)
+ for field in self.env["ir.model.fields"].search(
+ [("model_id", "=", model_id.id), ("name", "in", list(field_names))]):
+ self.field_ids.create({
+ "model_id": model_id.id,
+ "node_id": record.id,
+ "name": field.id,
+ "readonly": True,
+ })
+ else:
+ raise UserError('该模型未找到form视图')
+ return records
@api.depends("bg_color", "label_color", "use_custom_colors", "flow_start", "flow_end")
def _compute_custom_colors(self):
@@ -205,7 +220,8 @@ class SoongWorkflowNode(models.Model):
# 加载form视图中的字段
for rec in self:
rec.field_ids.unlink()
- form_view = self.env["ir.ui.view"].search([("model", "=", rec.model_id.model), ("type", "=", "form")], limit=1)
+ form_view = self.env["ir.ui.view"].search([("model", "=", rec.model_id.model), ("type", "=", "form")],
+ limit=1)
if form_view:
xml_tree = etree.fromstring(form_view.arch)
field_names = set()
@@ -213,12 +229,13 @@ class SoongWorkflowNode(models.Model):
field_name = field_node.get("name")
if field_name:
field_names.add(field_name)
- for field in self.env["ir.model.fields"].search([("model_id", "=", rec.model_id.id), ("name", "in", list(field_names))]):
+ for field in self.env["ir.model.fields"].search(
+ [("model_id", "=", rec.model_id.id), ("name", "in", list(field_names))]):
rec.field_ids.create({
- "model_id": rec.model_id.id,
- "node_id": rec.id,
- "name": field.id,
- })
+ "model_id": rec.model_id.id,
+ "node_id": rec.id,
+ "name": field.id,
+ })
else:
raise UserError('该模型未找到form视图')
@@ -256,6 +273,7 @@ class SoongWorkflowNodeButton(models.Model):
)
is_highlight = fields.Boolean(string="Is Highlighted", default=True,
help="Control highlighting of the button if needs user attention..", )
+ # is_high_red = fields.Boolean(string="红色突出")
has_icon = fields.Boolean(
string="Has Icon", help="Enable it to add icon to the button."
)
@@ -281,7 +299,8 @@ class SoongWorkflowNodeButton(models.Model):
)
reviewer_id = fields.Many2one(comodel_name="res.users", string="Reviewer")
reviewer_group_id = fields.Many2one(comodel_name="res.groups", string="Reviewer group")
- users_role_id = fields.Many2one(comodel_name="soong.user.role", string="主角色", domain=[('user_type', '!=', 'lv_role')])
+ users_role_id = fields.Many2one(comodel_name="soong.user.role", string="主角色",
+ domain=[('user_type', '!=', 'lv_role')])
reviewer_expression = fields.Text(
string="Review Expression",
default=CONDITION_CODE_TEMP,
@@ -331,7 +350,8 @@ class SoongWorkflowNodeButton(models.Model):
ondelete="cascade",
)
invisible_expression_model = fields.Char(related="workflow_id.model_id.model")
- is_automatic = fields.Boolean('是否自动匹配', default=True, help='该节点默认拟办人员的部门相应人员。必须是系统全局角色')
+ is_automatic = fields.Boolean('是否自动匹配', default=True,
+ help='该节点默认拟办人员的部门相应人员。必须是系统全局角色')
@api.onchange("node_id")
def change_workflow(self):
@@ -430,7 +450,8 @@ class SoongWorkflowNodeButton(models.Model):
elif button_id.review_type == "group":
user_ids += button_id.reviewer_group_id.users.ids
elif button_id.review_type == "user_role":
- user_role_id = self.env['res.users'].search([('employee_id.user_role_id', '=', button_id.users_role_id.id)])
+ user_role_id = self.env['res.users'].search(
+ [('employee_id.user_role_id', '=', button_id.users_role_id.id)])
user_ids += user_role_id.ids
# # 发送信息提醒
# partner_ids = self.sudo().env['res.users'].search([('id', 'in', user_ids)]).mapped('partner_id').ids
diff --git a/soong_workflow/models/soong_workflow_record.py b/soong_workflow/models/soong_workflow_record.py
index b4a6692b1..af3af7c3c 100644
--- a/soong_workflow/models/soong_workflow_record.py
+++ b/soong_workflow/models/soong_workflow_record.py
@@ -24,6 +24,7 @@ class SoongWorkflowRecord(models.Model):
rec.name = False
name = fields.Char(string="Name", compute="compute_name", store=True)
+ code = fields.Char(string="流水号")
res_model = fields.Char(string="Res Model", required=True)
res_id = fields.Integer(string="Res ID", required=True)
users_ids = fields.Many2many('res.users', string="用户")
diff --git a/soong_workflow/templates/soong_workflow_templates.xml b/soong_workflow/templates/soong_workflow_templates.xml
index ea87beaad..72c7cd16d 100644
--- a/soong_workflow/templates/soong_workflow_templates.xml
+++ b/soong_workflow/templates/soong_workflow_templates.xml
@@ -1,19 +1,18 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/soong_workflow/views/menuitem.xml b/soong_workflow/views/menuitem.xml
index 502c546c7..347eb848d 100644
--- a/soong_workflow/views/menuitem.xml
+++ b/soong_workflow/views/menuitem.xml
@@ -14,17 +14,27 @@
sequence="3"/>
+
+
-日程
+ sequence="4"/>
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/soong_workflow/views/soong_workflow_log_views.xml b/soong_workflow/views/soong_workflow_log_views.xml
index 0cb6aac18..166b3d2b1 100644
--- a/soong_workflow/views/soong_workflow_log_views.xml
+++ b/soong_workflow/views/soong_workflow_log_views.xml
@@ -6,6 +6,7 @@
soong.workflow.log
+
diff --git a/soong_workflow/views/soong_workflow_node_views.xml b/soong_workflow/views/soong_workflow_node_views.xml
index b64ad6f62..0dccdf720 100644
--- a/soong_workflow/views/soong_workflow_node_views.xml
+++ b/soong_workflow/views/soong_workflow_node_views.xml
@@ -149,6 +149,7 @@
+
diff --git a/soong_workflow/views/soong_workflow_record.xml b/soong_workflow/views/soong_workflow_record.xml
index 5b8c28c11..3f29695e9 100644
--- a/soong_workflow/views/soong_workflow_record.xml
+++ b/soong_workflow/views/soong_workflow_record.xml
@@ -20,6 +20,7 @@
+
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py
index 79512f52b..659c01328 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard.py
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py
@@ -115,10 +115,10 @@ class SoongWorkflowCommentWizard(models.TransientModel):
self.ensure_one()
cx = self.env.context.copy() or {}
record_id = self.env[self.res_model].search([('id', '=', self.res_id)])
- # 抄送人员
if self.node_btn_name == '转交':
- self_node_id = record_id.workflow_id.node_ids.search(
- [('name', '=', record_id.state), ('workflow_id', '=', record_id.workflow_id.id)])
+ self_node_id = record_id.workflow_id.node_ids.search([('name', '=', record_id.state), ('workflow_id', '=', record_id.workflow_id.id)])
+ # 工作流更新,转交节点日志记录。
+
now_record_obj = self.sudo().env["soong.workflow.log"].search(
[("model", "=", self.res_model),
("res_id", "=", self.res_id),
@@ -128,8 +128,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
("node_btn_id", "=", self.node_btn_id.id),
], order="lase_click_date DESC", limit=1)
if not now_record_obj:
- now_record_obj = self.sudo().env["soong.workflow.log"].create(
- {
+ now_record_obj = self.sudo().env["soong.workflow.log"].create({
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
@@ -139,8 +138,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
"node_btn_id": self.node_btn_id.id,
"lase_click_date": fields.Datetime.now(),
"approval_state": "2"
- }
- )
+ })
now_record_obj.write({"comment": self.comment_note_id.name, "approval_state": "2"})
if self_node_id.is_carbon_copy:
for employee in self_node_id.employee_ids:
@@ -191,14 +189,14 @@ class SoongWorkflowCommentWizard(models.TransientModel):
('department_id', '=', record_id.department_id.id),
('department_ids', 'in', record_id.department_id.id)])
employee_ids = employee_user_role_ids if not is_automatic else employee_user_role_id
- record_obj = self.sudo().env["soong.workflow.log"].search([("model", "=", self.res_model),
- ("res_id", "=", self.res_id),
- ("node_id", "=", next_node_id.id),
- ("workflow_id", "=", record_id.workflow_id.id),
- ("node_btn_name", "=", "0"),
+ record_obj = self.sudo().env["soong.workflow.log"].search([("model", "=", self.res_model), ("res_id", "=", self.res_id)])[-1]
+ # ("node_id", "=", next_node_id.id),
+ # ("workflow_id", "=", record_id.workflow_id.id),
+ # ("node_btn_name", "=", "0"),
# ("node_btn_id", "=", record_id.node_btn_id.id),
- ], order="lase_click_date DESC", limit=1)
- if not record_obj:
+ # ], order="lase_click_date DESC", limit=1)
+ # 生成下一个节点的数据。如果当前节点不等于当前状态创建新数据
+ if record_id.state != record_obj.name:
record_obj = self.sudo().env["soong.workflow.log"].create(
{
"model": self.res_model,
@@ -262,12 +260,6 @@ class SoongWorkflowCommentWizard(models.TransientModel):
}
)
return self.node_btn_id.with_context(cx).run()
- # # 填写审批记录
- # if self.node_btn_name != '加签':
- # self.log_ids.write({"comment": self.comment_note_id.name})
- # # 加签人员写入
- # if self.node_btn_name == '加签':
- # record_id.approval_sign_ids = self.approval_users_ids
# if self.node_btn_name == '分发':
# if self.circulated_employee_ids:
# url = 'https://oa.thtzjt.com/mail/view?model={}&res_id={}'.format(self.res_model, self.res_id)
@@ -282,7 +274,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
# url=url, btntxt="查看详情")
# partner_ids = self.circulated_employee_ids.user_id.partner_id.ids
# self.with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids,'soong_workflow.message_soong_workflow_distribute')
- if self.employee_ids:
- state = self.node_btn_id.node_id.out_link_ids.name.split('-> ')[-1]
- record_id.write({'state': 'end' if state == '结束' else state})
+ if self.employee_ids:
+ state = self.node_btn_id.node_id.out_link_ids.name.split('-> ')[-1]
+ record_id.write({'state': 'end' if state == '结束' else state})
return self.node_btn_id.with_context(cx).run()
diff --git a/yuthon_hr_attendance/models/card_approval.py b/yuthon_hr_attendance/models/card_approval.py
index 621512f71..735cb1ef4 100644
--- a/yuthon_hr_attendance/models/card_approval.py
+++ b/yuthon_hr_attendance/models/card_approval.py
@@ -25,11 +25,10 @@ class CardApprovals(models.Model):
reason_application = fields.Html(string="申请事由")
documents_ids = fields.Many2many('ir.attachment', string="附件")
attendance_id = fields.Many2one('hr.attendance', string="补卡日期")
- replacement_time = fields.Selection([('work', '上班卡'), ('quitting', '下班卡'), ('all', '全天卡')], string="补卡",
- compute='_compute_replacement_time')
+ replacement_time = fields.Selection([('work', '上班卡'), ('quitting', '下班卡'), ('all', '全天卡')], string="补卡")
- @api.depends('attendance_id')
- def _compute_replacement_time(self):
+ @api.onchange('attendance_id')
+ def onchange_replacement_time(self):
for rep in self:
rep.replacement_time = None
if rep.attendance_id.is_early_card and not rep.attendance_id.is_late_card:
diff --git a/yuthon_hr_attendance/views/card_approval.xml b/yuthon_hr_attendance/views/card_approval.xml
index 8943bfa40..ecfd374fb 100644
--- a/yuthon_hr_attendance/views/card_approval.xml
+++ b/yuthon_hr_attendance/views/card_approval.xml
@@ -26,7 +26,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
diff --git a/yuthon_will_task/models/yuthon_will_task.py b/yuthon_will_task/models/yuthon_will_task.py
index 760150d49..46dd505af 100644
--- a/yuthon_will_task/models/yuthon_will_task.py
+++ b/yuthon_will_task/models/yuthon_will_task.py
@@ -52,8 +52,8 @@ class YuthonWillTask(models.Model):
def will_task_time(self):
for i in self.search([('state', '=', 'will')]):
- if datetime.now() + timedelta(hours=8) > self.start_time:
- i.write({'state', 'done'})
+ if datetime.now() + timedelta(hours=8) > i.start_time:
+ i.write({'state': 'done'})
for task in self.search([('state', '=', 'will')]):
now = datetime.now() + timedelta(hours=8)
start_time = task.start_time + timedelta(hours=8)