ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] #### 工作流 工作流是与动态业务对象相关联的模型。工作流也用于跟踪动态演进的进程。 > 练习伪工作流 > 在授课模型上添加一个字段`state`,用于定义一个工作流程。授课存在三个可能的状态:Draft(草稿,默认值)、Confirmed(已确认)、Done(已完成)。在授课的form视图中,添加一个只读字段用于显示课程状态,并可以通过按钮来改变状态。有效的状态值迁移包括: > > * Draft->Confirmed > * Confirmed->Draft > * Confirmed->Done > * Done->Draft 1. 添加一个新的字段`state` 2. 添加状态迁移方法,这个方法可以被form表单的按钮所调用,用以更改授课的状态 3. 将相关按钮添加到授课的form视图 `openacademy/models.py` ~~~ attendees_count = fields.Integer( string="Attendees count", compute='_get_attendees_count', store=True) state = fields.Selection([ ('draft', "Draft"), ('confirmed', "Confirmed"), ('done', "Done"), ], default='draft') @api.multi def action_draft(self): self.state = 'draft' @api.multi def action_confirm(self): self.state = 'confirmed' @api.multi def action_done(self): self.state = 'done' @api.depends('seats', 'attendee_ids') def _taken_seats(self): for r in self: ~~~ `openacademy/views/openacademy.xml` ~~~ <field name="model">openacademy.session</field> <field name="arch" type="xml"> <form string="Session Form"> <header> <button name="action_draft" type="object" string="Reset to draft" states="confirmed,done"/> <button name="action_confirm" type="object" string="Confirm" states="draft" class="oe_highlight"/> <button name="action_done" type="object" string="Mark as done" states="confirmed" class="oe_highlight"/> <field name="state" widget="statusbar"/> </header> <sheet> <group> <group string="General"> ~~~ 工作流可以与Odoo中的任何对象关联,并且可完全定制化。工作流用于构造和管理业务对象和文档的生命周期,并且通过图形化工具定义转换器、触发器等。工作流、动作(节点或操作)和迁移(条件)通常以XML记录行的形式定义。在工作流进行导航的标签称为工作项。 > 警告 > 与模型相关的工作流仅在创建模型记录时被创建。因此,在工作流定义之前创建的授课实例是没有与之对应的工作流实例的。 > > 练习工作流 > 使用真正的授课工作流替换之前的伪工作流。修改授课的form视图,按钮将调用工作流而不是调用模型的方法。 `openacademy/__manifest__.py` ~~~ 'templates.xml', 'views/openacademy.xml', 'views/partner.xml', 'views/session_workflow.xml', ], # only loaded in demonstration mode 'demo': [ ~~~ `openacademy/models.py` ~~~ ('draft', "Draft"), ('confirmed', "Confirmed"), ('done', "Done"), ]) @api.multi def action_draft(self): ~~~ `openacademy/views/openacademy.xml` ~~~ <field name="arch" type="xml"> <form string="Session Form"> <header> <button name="draft" type="workflow" string="Reset to draft" states="confirmed,done"/> <button name="confirm" type="workflow" string="Confirm" states="draft" class="oe_highlight"/> <button name="done" type="workflow" string="Mark as done" states="confirmed" class="oe_highlight"/> <field name="state" widget="statusbar"/> ~~~ `openacademy/views/session_workflow.xml` ~~~ <odoo> <data> <record model="workflow" id="wkf_session"> <field name="name">OpenAcademy sessions workflow</field> <field name="osv">openacademy.session</field> <field name="on_create">True</field> </record> <record model="workflow.activity" id="draft"> <field name="name">Draft</field> <field name="wkf_id" ref="wkf_session"/> <field name="flow_start" eval="True"/> <field name="kind">function</field> <field name="action">action_draft()</field> </record> <record model="workflow.activity" id="confirmed"> <field name="name">Confirmed</field> <field name="wkf_id" ref="wkf_session"/> <field name="kind">function</field> <field name="action">action_confirm()</field> </record> <record model="workflow.activity" id="done"> <field name="name">Done</field> <field name="wkf_id" ref="wkf_session"/> <field name="kind">function</field> <field name="action">action_done()</field> </record> <record model="workflow.transition" id="session_draft_to_confirmed"> <field name="act_from" ref="draft"/> <field name="act_to" ref="confirmed"/> <field name="signal">confirm</field> </record> <record model="workflow.transition" id="session_confirmed_to_draft"> <field name="act_from" ref="confirmed"/> <field name="act_to" ref="draft"/> <field name="signal">draft</field> </record> <record model="workflow.transition" id="session_done_to_draft"> <field name="act_from" ref="done"/> <field name="act_to" ref="draft"/> <field name="signal">draft</field> </record> <record model="workflow.transition" id="session_confirmed_to_done"> <field name="act_from" ref="confirmed"/> <field name="act_to" ref="done"/> <field name="signal">done</field> </record> </data> </odoo> ~~~ > 提示 > 要检查授课实例对应的工作流实例是否被正确创建,可以:**设置->技术->工作流->实例** > > 练习自动状态迁移 > 当超过一半座席被保留时,自动将授课的状态从*Draft*迁移到*Confirmed*。 `openacademy/views/session_workflow.xml` ~~~ <field name="act_to" ref="done"/> <field name="signal">done</field> </record> <record model="workflow.transition" id="session_auto_confirm_half_filled"> <field name="act_from" ref="draft"/> <field name="act_to" ref="confirmed"/> <field name="condition">taken_seats > 50</field> </record> </data> </odoo> ~~~ > 练习服务器动作 > 用服务器动作替换用于同步授课状态的Python方法。工作流和服务器动作都可以从UI创建。 `openacademy/views/session_workflow.xml` ~~~ <field name="on_create">True</field> </record> <record model="ir.actions.server" id="set_session_to_draft"> <field name="name">Set session to Draft</field> <field name="model_id" ref="model_openacademy_session"/> <field name="code"> model.search([('id', 'in', context['active_ids'])]).action_draft() </field> </record> <record model="workflow.activity" id="draft"> <field name="name">Draft</field> <field name="wkf_id" ref="wkf_session"/> <field name="flow_start" eval="True"/> <field name="kind">dummy</field> <field name="action"></field> <field name="action_id" ref="set_session_to_draft"/> </record> <record model="ir.actions.server" id="set_session_to_confirmed"> <field name="name">Set session to Confirmed</field> <field name="model_id" ref="model_openacademy_session"/> <field name="code"> model.search([('id', 'in', context['active_ids'])]).action_confirm() </field> </record> <record model="workflow.activity" id="confirmed"> <field name="name">Confirmed</field> <field name="wkf_id" ref="wkf_session"/> <field name="kind">dummy</field> <field name="action"></field> <field name="action_id" ref="set_session_to_confirmed"/> </record> <record model="ir.actions.server" id="set_session_to_done"> <field name="name">Set session to Done</field> <field name="model_id" ref="model_openacademy_session"/> <field name="code"> model.search([('id', 'in', context['active_ids'])]).action_done() </field> </record> <record model="workflow.activity" id="done"> <field name="name">Done</field> <field name="wkf_id" ref="wkf_session"/> <field name="kind">dummy</field> <field name="action"></field> <field name="action_id" ref="set_session_to_done"/> </record> <record model="workflow.transition" id="session_draft_to_confirmed"> ~~~ ##### 安全 安全是为了实现统一的安全策略而进行配置的访问控制机制。 **基于组的访问控制机制** 组是通过在`res.groups`模型的记录行来创建的,并通过菜单访问权限来限制权限。但是,即使没有菜单,对象仍然可以间接被访问,因此必须为组定义实际的对象级权限(读取、写入、创建、取消关联)。一般通过模块中的CSV文件插入。也可以通过字段的`groups`属性来限制对视图或对象上特定字段的访问。 **访问权限** 访问权限通过`ir.model.access`的记录行来定义。每个访问权限与模型、组(或者非全局访问的组)相关联,并且是一组权限:读取、写入、创建、取消关联。这些访问权限一般通过`ir.model.access.csv`这个CSV文件创建。 ~~~ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink access_idea_idea,idea.idea,model_idea_idea,base.group_user,1,1,1,0 access_idea_vote,idea.vote,model_idea_vote,base.group_user,1,1,1,0 ~~~ > 练习 > 通过Odoo界面添加访问控制权限 > 建立一个新用户`John Smith`,然后建立`OpenAcademy/Session Read`组,并赋予这个组对*授课*模型的读权限。 > > 1. 建立一个新用户`John Smit`通过 **设置->用户->用户** > 2. 建立一个新组`session_read`通过 **设置->用户->组**,这个组拥有对*授课*模型的读权限 > 3. 编辑`John Smith`用户,把他加入到`session_read`组 > 4. 以`John Smith`身份登录系统,检查权限是否正确。 * * * > 练习 > 通过数据文件添加访问控制权限: > > * 建立一个组`OpenAcademy / Manager`,这个组对开放学院的所有模型都有完全权限。 > * 让`Session`和`Course`对所有用户可读 > * 建立新的文件`openacademy/security/security.xml`用来定义`OpenAcademy Manager`组 > * 编辑文件`openacademy/security/ir.model.access.csv`来添加对模型的访问权限 > * 最后更新`openacademy/__manifest__.py`来添加新的数据文件 `openacademy/__manifest__.py` ~~~ # always loaded 'data': [ 'security/security.xml', 'security/ir.model.access.csv', 'templates.xml', 'views/openacademy.xml', 'views/partner.xml', ~~~ `openacademy/security/ir.model.access.csv` ~~~ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink course_manager,course manager,model_openacademy_course,group_manager,1,1,1,1 session_manager,session manager,model_openacademy_session,group_manager,1,1,1,1 course_read_all,course all,model_openacademy_course,,1,0,0,0 session_read_all,session all,model_openacademy_session,,1,0,0,0 ~~~ `openacademy/security/security.xml` ~~~ <odoo> <data> <record id="group_manager" model="res.groups"> <field name="name">OpenAcademy / Manager</field> </record> </data> </odoo> ~~~ **记录规则** 记录规则限制对给定模型的记录子集的访问权限。一个规则就是`ir.rule`模型的一行记录,并且将其关联到模型、数组(many2many字段)、或domain。domain指定了对那些记录有访问权限。 这是一个记录规则的例子,这个规则防止非`cancel`状态的负责人被删除。请注意,`groups`字段的值必须遵守与ORM的`write()`方法一样的规则。 ~~~ <record id="delete_cancelled_only" model="ir.rule"> <field name="name">Only cancelled leads may be deleted</field> <field name="model_id" ref="crm.model_crm_lead"/> <field name="groups" eval="[(4, ref('sales_team.group_sale_manager'))]"/> <field name="perm_read" eval="0"/> <field name="perm_write" eval="0"/> <field name="perm_create" eval="0"/> <field name="perm_unlink" eval="1" /> <field name="domain_force">[('state','=','cancel')]</field> </record> ~~~ > 练习记录规则 > 为*授课*模型和*OpenAcademy / Manager*组添加记录规则,这个记录规则限制只有课程负责人可以对课程进行`write`和`unlink`操作,如果课程还没有负责人,这个组的所有用户都可以编辑它。在`openacademy/security/security.xml`文件中创建新的规则: > `openacademy/security/security.xml` > ``` > > OpenAcademy / Manager > ~~~ <record id="only_responsible_can_modify" model="ir.rule"> <field name="name">Only Responsible can modify Course</field> <field name="model_id" ref="model_openacademy_course"/> <field name="groups" eval="[(4, ref('openacademy.group_manager'))]"/> <field name="perm_read" eval="0"/> <field name="perm_write" eval="1"/> <field name="perm_create" eval="0"/> <field name="perm_unlink" eval="1"/> <field name="domain_force"> ['|', ('responsible_id','=',False), ('responsible_id','=',user.id)] </field> </record> </data> ~~~ ``` 作者:luohuayong 链接:http://www.jianshu.com/p/6979497c4082 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。