__init__.py
文件没啥好改动的,然后我们再看到main_model.py文件,这一次进行了较多地方的改动。
from openerp import models, fields, apiimport loggingclass Qingjd(models.Model):_name = 'qingjia.qingjd'name = fields.Many2one('hr.employee', string="申请人", readonly=True)manager = fields.Many2one('hr.employee', string="主管",readonly=True)beginning = fields.Datetime(string="开始时间", required=True,default = fields.Datetime.now())ending = fields.Datetime(string="结束时间", required=True)reason = fields.Text(string="请假事由",required=True)accept_reason = fields.Text(string="同意理由",default="同意。")#########compute 没有写入数据库 on the fly 可以被workflow的condition调用current_name = fields.Many2one('hr.employee', string="当前登录人",compute="_get_current_name")is_manager = fields.Boolean(compute='_get_is_manager')######state = fields.Selection([('draft', "草稿"),('confirmed', '待审核'),('accepted', '批准'),('rejected', '拒绝'),],string='状态',default='draft',readonly=True)@api.model#使用新的apidef _get_default_name(self):uid = self.env.uidres = self.env['resource.resource'].search([('user_id','=',uid)])name = res.nameemployee = self.env['hr.employee'].search([('name_related','=',name)])# for i in self.env.user:# 说明其是recordset# print('hello')return employee@api.modeldef _get_default_manager(self):#单记录recordset可以直接用点记号读取属性值uid = self.env.uidres = self.env['resource.resource'].search([('user_id','=',uid)])name = res.nameemployee = self.env['hr.employee'].search([('name_related','=',name)])logging.info("myinfo {}".format(employee.parent_id))return employee.parent_id # 似乎有这种数字引用方法值得我们注意_defaults = {'name' : _get_default_name ,'manager' : _get_default_manager ,}def _get_is_manager(self):###这里return不起作用print('----------test')print(self.current_name, self.manager,self.env.uid)if self.current_name == self.manager:self.is_manager = Trueelse:self.is_manager = Falsedef _get_current_name(self):uid = self.env.uidres = self.env['resource.resource'].search([('user_id','=',uid)])name = res.nameemployee = self.env['hr.employee'].search([('name_related','=',name)])self.current_name = employee##############################def draft(self, cr, uid, ids, context=None):if context is None:context={}self.write(cr,uid,ids,{'state':'draft'},context=context)return Truedef confirm(self, cr, uid, ids, context=None):if context is None:context={}self.write(cr,uid,ids,{'state':'confirmed'},context=context)return Truedef accept(self, cr, uid, ids, context=None):if context is None:context={}self.write(cr,uid,ids,{'state':'accepted'},context=context)print('你的请假单被批准了')return Truedef reject(self, cr, uid, ids, context=None):if context is None:context={}self.write(cr,uid,ids,{'state':'rejected'},context=context)print('抱歉,你的请假单没有被批准。')return True
读者不要着急,这里的内容我会慢慢讲解的。然后views.xml改成了这个样子:
<?xml version="1.0"?><openerp><data><!-- 打开请假单动作--><act_window id="action_qingjia_qingjd"name="请假单"res_model="qingjia.qingjd"view_mode="tree,form" /><!--表单视图--><record id="qingjia_qingjd_form" model="ir.ui.view"><field name="name">qing jia dan form</field><field name="model">qingjia.qingjd</field><field name="arch" type="xml"><form><header><button name="btn_confirm" type="workflow" states="draft"string="发送" class="oe_highlight" /><button name="btn_accept" type="workflow" states="confirmed"string="批准" class="oe_highlight"/><button name="btn_reject" type="workflow" states="confirmed"string="拒绝" class="oe_highlight"/><field name="state" widget="statusbar" statusbar_visible="draft,confirmed,accepted,rejected" class="oe_highlight" type="workflow"/></header><sheet><group name="group_top" string="请假单"><group name="group_left"><field name="name"/><field name="beginning"/></group><group name="group_right"><field name="manager"/><field name="ending"/></group></group><group name="group_below"><field name="reason"/></group></sheet></form></field></record><!--tree视图--><record id="qingjia_qingjd_tree" model="ir.ui.view"><field name="name">qing jia dan tree</field><field name="model">qingjia.qingjd</field><field name="arch" type="xml"><tree><field name="name"/><field name="beginning"/><field name="ending"/><field name="state"/></tree></field></record><!--加入菜单--><menuitem id="menu_qingjia" name="请假" sequence="0"></menuitem><menuitem id="menu_qingjia_qingjiadan" name="请假单" parent="menu_qingjia"></menuitem><menuitem id="menu_qingjia_qingjiadan_qingjiadan" parent="menu_qingjia_qingjiadan" action="action_qingjia_qingjd"></menuitem></data></openerp>
除了跟着main_model.py文件里面的一些修改而更改外,最值得一提的就是button的 type 属性设置为了 "workflow" 。如果还是设置为 "object" ,当你点击按钮的时候,该模型就应该提供对应按钮name 的一个方法,这个方法将执行某些动作。这里要强调的就是这样简单的object按钮是不和后面谈到的工作流的概念兼兼容的。如果按钮的type还是设置为object,那么其是不发送工作流的signal的。更多工作流的细节等下再谈。
然后还编写了一个工作流的workflow.xml文件:
<?xml version="1.0" ?><openerp><data noupdate="0"><record id="wkf_qingjia" model="workflow" ><field name="name">wkf.qingjia</field><field name="osv">qingjia.qingjd</field><field name="on_create">True</field></record><record id="act_draft" model="workflow.activity" ><field name="wkf_id" ref="wkf_qingjia" /><field name="name">draft</field><field name="flow_start" eval="True"/><field name="kind">function</field><field name="action">draft()</field></record><record id="act_confirm" model="workflow.activity" ><field name="wkf_id" ref="wkf_qingjia" /><field name="name">confirm</field><field name="kind">function</field><field name="action">confirm()</field></record><record id="act_accept" model="workflow.activity" ><field name="wkf_id" ref="wkf_qingjia" /><field name="name">accept</field><field name="kind">function</field><field name="flow_stop">True</field><field name="action">accept()</field></record><record id="act_reject" model="workflow.activity" ><field name="wkf_id" ref="wkf_qingjia" /><field name="name">reject</field><field name="kind">function</field><field name="action">reject()</field></record><record model="workflow.transition" id="qingjia_draft2confirm"><field name="act_from" ref="act_draft" /><field name="act_to" ref="act_confirm" /><field name="signal">btn_confirm</field></record><record model="workflow.transition" id="qingjia_confirm2accept"><field name="act_from" ref="act_confirm" /><field name="act_to" ref="act_accept" /><field name="signal">btn_accept</field><field name="condition">is_manager</field></record><record model="workflow.transition" id="qingjia_confirm2reject"><field name="act_from" ref="act_confirm" /><field name="act_to" ref="act_reject" /><field name="signal">btn_reject</field><field name="condition">is_manager</field></record></data></openerp>
然后 __openerp__.py
文件没做什么修改,就把上面的workflow.xml加进来,然后depends将base改为了hr,因为等下一些功能是依赖官方内置模块hr(人资管理模块)的。
读者可以按照上面的描述先看看这个请假模块第二版是什么样子,下面是一个简单的示意图:
Figure 29: 请假模块第二版
这么一张简单的图并没很好地第二版的加强功能说明出来,建议读者新建几个用户,然后在人力资源那里把员工和部门设置好,尤其是部门主管等信息。然后读者可以尝试以一个普通员工来新建一个请假单,编辑,保存,发送。然后接下来的批准和拒绝按钮该普通员工是不能点击的(工作流的condition控制的),而只有主管才可以正常点击批准或拒绝按钮。
这里我只进行简略的讨论,具体该表格的细节请读者自己用pgadmin3软件查看之。
base.group_user
。
工作流对象算是Odoo框架里面颇具特色的一部分,其在网页视图中对应的菜单是: 设置→工作流→工作流。对应的模型是 workflow ,但并没有workflow这个表格,要说对应的话应该是wkf这个表格,然后还有wkf_activity表格等。
Odoo工作流的图标视图如下图所示是一个不错的查看和管理当前工作流程的工具:
Figure 30: 工作流图表视图示意图其中节点叫做“活动(activity)”,然后弧线连接叫做“转变(transition)”。活动描述了Odoo服务器应该完成的一些工作,比如:改变某些记录的状态,发送email等等。转变则控制了从活动到活动之间的工作流。
转变可以增加属性如条件、信号、触发器等。这样工作流的行为是取决于用户的动作(如点击某个按钮),或某个记录值的更改或任意的python代码。总而言之,Odoo工作流系统提供了:
工作流和模型关联在一起,具体某个模型新建一个对象就会是实例化一个工作流对象。然后该工作流对象应该有个状态记录,服务器重启之后工作流还是在那个状态下,也就是已经执行了的都不会执行了。
<record id="wkf_qingjia" model="workflow" > <field name="name">wkf.qingjia</field> <field name="osv">qingjia.qingjd</field> <field name="on_create">True</field> </record>
首先是定义了本工作流对象,model=workflow,id是多少,这个id很重要,等下本工作流对象里面的活动和转变都要用到这个id。
然后field定义了
<record id="act_draft" model="workflow.activity" > <field name="wkf_id" ref="wkf_qingjia" /> <field name="name">draft</field> <field name="flow_start" eval="True"/> <field name="kind">function</field> <field name="action">draft()</field> </record>
这里创建了一个节点活动对象:
kind 有四种 dummy function subflow stop all
action 具体的动作(于模型上)
flow_stop 一个工作流的完成就是所有的活动有flow_stop属性的都设置为了 True
<record model="workflow.transition" id="holiday_draft2confirm"> <!-- 1. draft->submitted (confirm signal) --> <field name="act_from" ref="act_draft" /> <field name="act_to" ref="act_confirm" /> <field name="signal">confirm</field> <field name="condition">can_reset</field> <field name="group_id" ref="base.group_user"/> </record>
转变对象属于 workflow.transition 模型。
act_from 何活动出发 act_to 到何活动去 signal
condition
2.1.2 Accessing Current User self.env.user
'lang' ('self.env.lang').
default 使用lambda语句 其默认接受self参数, 即本模型具体的对象。
ir.module.category