# -*- coding: utf-8 -*- import logging import datetime from odoo import models, fields, api, _, modules from odoo.exceptions import ValidationError, UserError _logger = logging.getLogger(__name__) MODEL_DOMAIN = """[ ('is_workflow', '=', True), ('state', '=', 'base'), ('transient', '=', False), '!', '|', '|', '|', '|', '|', '|', '|', ('model', '=ilike', 'res.%'), ('model', '=ilike', 'ir.%'), ('model', '=ilike', 'soong.workflow%'), ('model', '=ilike', 'bus.%'), ('model', '=ilike', 'base.%'), ('model', '=ilike', 'base_%'), ('model', '=', 'base'), ('model', '=', '_unknown'), ]""" class SoongWorkflow(models.Model): _name = "soong.workflow" _description = "Soong Workflow" _order = 'sequence asc' _sql_constraints = [ ("uniq_name", "unique(name)", _("Workflow name must be unique.")), # ("uniq_model", "unique(model_id)", _("Model must be unique.")), ] name = fields.Char(string="Name", help="Give workflow a name.") sequence = fields.Integer(string='序号') model_id = fields.Many2one("ir.model", string="Model", domain=MODEL_DOMAIN, help="Enter business model you would like to modify its workflow.", ) node_ids = fields.One2many(comodel_name="soong.workflow.node", inverse_name="workflow_id", string="Nodes") link_ids = fields.One2many(comodel_name="soong.workflow.link", inverse_name="workflow_id", string="Links") remove_default_btn_until_end = fields.Boolean(string="是否覆盖表头按钮状态", default=False) current_stage_highlight_color = fields.Char(default="rgb(0, 255, 255)", help="The color to highlight the current stage on flow", ) start_date = fields.Date(string="生效日期", copy=False, default=fields.Date.today()) end_date = fields.Date(string="失效日期", copy=False, default=fields.Date.from_string('2099-01-01')) is_enable = fields.Boolean(string="是否启用", default="False", compute="compute_is_enable", store=True) is_enable_return_button = fields.Boolean(string="是否启用收回", default=True) is_enable_transmitted_button = fields.Boolean(string="是否启用转交", default=True) approvals_group_id = fields.Many2one('soong.approval.group', string="审批分组") def copy(self, default=None): workflow_id = self.search([('model_id', '=', self.model_id.id)]) workflow_version = len(workflow_id) + 1 default = dict(default or {}) default.update({ 'name': self.name + '-v' + str(workflow_version), 'model_id': False, 'remove_default_attrs_mod': self.remove_default_attrs_mod, 'current_stage_highlight_color': self.current_stage_highlight_color, }) res = super(SoongWorkflow, self).copy(default) node_dict = dict() button_dict = dict() # 复制节点 for node_id in self.node_ids: new_noode_id = node_id.copy({ 'workflow_id': res.id }) node_dict[node_id.id] = new_noode_id.id # 复制节点-按钮 for button_id in node_id.button_ids: new_button_id = button_id.copy({ 'node_id': new_noode_id.id, 'link_id': False }) if button_id.link_id: if button_id.link_id.id in button_dict: button_dict[button_id.link_id.id] |= new_button_id else: button_dict[button_id.link_id.id] = new_button_id # 复制节点-字段 for field_id in node_id.field_ids: field_id.copy({ 'node_id': new_noode_id.id, }) # 复制链接 for link_id in self.link_ids: new_link_id = link_id.copy({ 'workflow_id': res.id, 'node_from': node_dict[link_id.node_from.id], 'node_to': node_dict[link_id.node_to.id] }) if link_id.id in button_dict: for new_button_id in button_dict[link_id.id]: new_button_id.link_id = new_link_id.id return res @api.depends('start_date', 'end_date') def compute_is_enable(self): for rec in self: if rec.start_date and rec.end_date: if rec.start_date <= fields.Date.today() < rec.end_date: is_enable_ids = self.search([('model_id', '=', self.model_id.id), ('is_enable', '=', True)]) if len(is_enable_ids) <= 1: rec.is_enable = True else: raise UserError('每个模型只能生效一个流程') else: rec.is_enable = False else: rec.is_enable = False @api.constrains("node_ids") def validate_nodes(self): # Objects wkf_node_obj = self.env["soong.workflow.node"] for rec in self: # Must have one flow start node res = rec.node_ids.search_count( [ ("workflow_id", "=", rec.id), ("flow_start", "=", True), ] ) if res > 1: raise ValidationError(_("Workflow must have only one start node.")) # Nodes' sequence must be unique per workflow for node in rec.node_ids: res = wkf_node_obj.search_count( [ ("id", "!=", node.id), ("workflow_id", "=", rec.id), ("sequence", "=", node.sequence), ] ) if res: raise ValidationError( _("Nodes' sequence must be unique per workflow.") ) @api.model_create_multi def create(self, values): for val in values: if not val["node_ids"]: val["node_ids"] = [ (0, 0, { "name": _("拟办"), "sequence": 1, "node_name": "start", "flow_start": True, "button_ids": '' },), (0, 0, { "name": _("结束"), "sequence": 99, "node_name": "end", "flow_end": True, "is_visible": False, },), ] return super().create(values) def action_workflow_diagram(self): self.ensure_one() action = self.env.ref("soong_workflow.action_soong_workflow").read()[0] action["name"] = _("Workflow: %(type_name)s") % {"type_name": self.display_name} action["context"] = {"default_workflow_id": self.id} action["res_id"] = self.id action["views"] = [(False, "diagram_plus"), (False, "form")] return action def create_request(self): self.ensure_one() return { "type": "ir.actions.act_window", "view_mode": "form", "res_model": self.model_id.model, "views": [[False, "form"]], }