diff --git a/soong_workflow/__manifest__.py b/soong_workflow/__manifest__.py index f87a30909..c38276846 100644 --- a/soong_workflow/__manifest__.py +++ b/soong_workflow/__manifest__.py @@ -47,8 +47,11 @@ 'web.assets_backend': [ 'soong_workflow/static/src/css/record_scss.scss', 'soong_workflow/static/src/css/button_css.scss', + 'soong_workflow/static/src/css/urgency_level.scss', 'soong_workflow/static/src/js/view_button.js', 'soong_workflow/static/src/js/select_create_dialog.js', + 'soong_workflow/static/src/js/urgency_level_widget.js', + 'soong_workflow/static/src/js/urgency_level_widget.xml', 'soong_workflow/static/src/diagram_plus_dialog/*', ], }, diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py index fcd04ba59..87e584576 100644 --- a/soong_workflow/models/soong_workflow_mixin.py +++ b/soong_workflow/models/soong_workflow_mixin.py @@ -667,6 +667,10 @@ class SoongWorkflowMixin(models.AbstractModel): sorted_logs = rec.log_ids.sorted(lambda log: log.id) if sorted_logs and sorted_logs[-1].lase_click_date: node_update_time = sorted_logs[-1].lase_click_date + + # 补丁:如果审批状态已经是结束,但还没拿到时间,则尝试用当前时间作为办结时间 + if not node_update_time and record_obj.approve_state == 'end': + node_update_time = fields.Datetime.now() except Exception as e: _logger.debug(f"Failed to get node_update_time: {e}") diff --git a/soong_workflow/models/soong_workflow_record.py b/soong_workflow/models/soong_workflow_record.py index e4625d0fe..4df2a92d6 100644 --- a/soong_workflow/models/soong_workflow_record.py +++ b/soong_workflow/models/soong_workflow_record.py @@ -79,12 +79,33 @@ class SoongWorkflowRecord(models.Model): ) priority = fields.Selection([('0', 'Normal'), ('1', 'Urgent')], 'Priority', default='0', index=True) + + urgency_level = fields.Selection( + [('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], + string='紧急度', + compute='_compute_urgency_level', + store=False + ) is_company = fields.Boolean(string="本公司", default=True, compute='_compute_is_company',search='_search_part_of_company') # 办结时间(上一节点的结束时间) node_update_time = fields.Datetime(string="办结时间") + @api.depends('res_model', 'res_id') + def _compute_urgency_level(self): + """从关联的业务模型中获取urgency_level值""" + for record in self: + record.urgency_level = 'normal' # 默认值 + if record.res_model and record.res_id: + try: + target_record = self.env[record.res_model].browse(record.res_id) + if target_record.exists() and hasattr(target_record, 'urgency_level'): + record.urgency_level = target_record.urgency_level or 'normal' + except Exception as e: + _logger.warning(f"Failed to get urgency_level from {record.res_model}: {e}") + record.urgency_level = 'normal' + @api.depends_context('uid', 'company') @api.depends('company_id') def _compute_is_company(self): @@ -622,6 +643,48 @@ class SoongWorkflowRecord(models.Model): }, } + def action_update_history_end_time(self): + """ + 批量计算已结束流程的办结时间 + """ + # 寻找所有审批状态为结束(end)且办结时间为空的记录 + records = self.search([ + ('approve_state', '=', 'end'), + ('node_update_time', '=', False) + ]) + + count = 0 + for rec in records: + if not rec.res_model or not rec.res_id: + continue + + try: + # 获取对应的业务单据 + source_record = self.env[rec.res_model].browse(rec.res_id) + if not source_record.exists(): + continue + + # 提取该单据最后一条审批日志的时间 + if hasattr(source_record, 'log_ids') and source_record.log_ids: + # 按ID排序,取最后一条记录 + sorted_logs = source_record.log_ids.sorted(lambda l: l.id) + if sorted_logs and sorted_logs[-1].lase_click_date: + # 更新办结时间 + rec.write({'node_update_time': sorted_logs[-1].lase_click_date}) + count += 1 + except Exception as e: + _logger.error(f"计算记录 {rec.id} 办结时间失败: {e}") + + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'title': '处理完成', + 'message': f'成功更新了 {count} 条记录的办结时间', + 'sticky': False, + } + } + diff --git a/soong_workflow/static/src/css/urgency_level.scss b/soong_workflow/static/src/css/urgency_level.scss new file mode 100644 index 000000000..9d1d962f0 --- /dev/null +++ b/soong_workflow/static/src/css/urgency_level.scss @@ -0,0 +1,23 @@ +.urgency-badge { + display: inline-block; + padding: 2px 6px; + font-weight: bold; + border-radius: 3px; + min-width: 30px; + text-align: center; +} + +.urgency-normal { + background-color: white; + color: #333; +} + +.urgency-urgent { + background-color: #ffc107; + color: #000; +} + +.urgency-emergency { + background-color: #dc3545; + color: #fff; +} diff --git a/soong_workflow/static/src/js/urgency_level_widget.js b/soong_workflow/static/src/js/urgency_level_widget.js new file mode 100644 index 000000000..09603500b --- /dev/null +++ b/soong_workflow/static/src/js/urgency_level_widget.js @@ -0,0 +1,41 @@ +/** @odoo-module **/ // 声明这是一个Odoo模块,Odoo 17+必须有这个声明 + +// 从Odoo核心库导入注册表工具,用于注册自定义组件 +import { registry } from "@web/core/registry"; +// 从OWL框架导入Component基类,OWL是Odoo的前端框架 +import { Component } from "@odoo/owl"; + +// 定义紧急度徽章Widget类,继承自OWL的Component基类 +export class UrgencyLevelWidget extends Component { + // 指定使用的XML模板名称,对应urgency_level_widget.xml中的模板 + static template = "soong_workflow.UrgencyLevelWidget"; + + // getter方法:根据紧急度值返回对应的CSS类名 + get urgencyClass() { + // 从props中获取当前记录的urgency_level字段值 + const level = this.props.record.data.urgency_level; + // 如果是急件,返回黄色样式类名 + if (level === 'urgent') { + return 'urgency-urgent'; + // 如果是特急件,返回红色样式类名 + } else if (level === 'emergency') { + return 'urgency-emergency'; + } + // 默认返回白色样式类名(普件) + return 'urgency-normal'; + } + + // getter方法:判断是否显示"急"字徽章 + get isVisible() { + // 从props中获取当前记录的urgency_level字段值 + const level = this.props.record.data.urgency_level; + // 只有当值存在且不是'normal'时才显示(即只显示急件和特急件) + return level && level !== 'normal'; + } +} + +// 将自定义Widget注册到Odoo的字段组件注册表中 +// 注册名为"urgency_level_badge",在视图中通过widget="urgency_level_badge"使用 +registry.category("fields").add("urgency_level_badge", { + component: UrgencyLevelWidget, // 指定使用的组件类 +}); diff --git a/soong_workflow/static/src/js/urgency_level_widget.xml b/soong_workflow/static/src/js/urgency_level_widget.xml new file mode 100644 index 000000000..0c8d7df86 --- /dev/null +++ b/soong_workflow/static/src/js/urgency_level_widget.xml @@ -0,0 +1,12 @@ + + + + + + + + + + 急 + + diff --git a/soong_workflow/views/soong_workflow_record.xml b/soong_workflow/views/soong_workflow_record.xml index 81aa6eea3..3da7be2c6 100644 --- a/soong_workflow/views/soong_workflow_record.xml +++ b/soong_workflow/views/soong_workflow_record.xml @@ -92,6 +92,8 @@ groups="soong_workflow.group_soong_workflow_manager"/>