odoo自定义模块

odoo自定义模块

复制 http://blog.sunansheng.com/python/odoo/odoo.html 中的请假单例子,创建一个带工作流的例子,工作环境是odoo 10.0
PS:在这个版本中官方自带的请假模块删掉了工作流~~何等的卧槽!

创建模块模版:

python odoo/odoo-bin scaffold qingjia odoo_dev/

odoo_dev目录中可以找到新创建的模块,进入目录以后可以看到如下的目录结构

controllers  demo  __init__.py  __manifest__.py  models  security  views

__init__.py不需要修改
__manifest__.py需要增加一点东西

"application": True,

创建模型

修改models/model.py文件。添加新的模型

# -*- coding: utf-8 -*-

from odoo import models, fields, api

class Qingjd(models.Model):
    _name = 'qingjia.qingjd'
    
    name = fields.Many2one('res.users', string="申请人", required=True)
    days = fields.Float(string="天数", required=True)
    startdate = fields.Date(string="开始日期", required=True)
    reason = fields.Text(string="请假事由")
    
    def send_qingjd(self):
        self.sended = True
        return self.sended
        
    def confirm_qingjd(self):
        self.state = 'confirmed'
        return self.state

修改controller

修改controllers/controller.py文件。由模版创建的controller已经提供了最基础的功能,只需要去掉注释,做简单的修改就可以使用(主要是和新添加的模型做个对应)。

# -*- coding: utf-8 -*-
from odoo import http
class Qingjia(http.Controller):
    @http.route('/qingjia/qingjia', auth='public')
    def index(self, **kw):
        return "Hello, world"
        
    @http.route('/qingjia/qingjia/objects/', auth='public')
    def list(self, **kw):
        return http.request.render('qingjia.listing', {
            'root': '/qingjia/qingjia',
            'objects': http.request.env['qingjia.qingjd'].search([]),
        })

    @http.route('/qingjia/qingjia/objects/<model("qingjia.qingjd"):obj>/', auth='public')
    def object(self, **kw):
        return http.request.render('qingjia.object', {
            'object': obj,
        })

修改模版

controller中,可以看到使用了两个模版qingjia.listingqingjia.object。这两个模版定义在views/templates.xml文件中,只不过现在被注释掉了。只需要去掉注释就可以了,不需要做任何修改。

<odoo>
    <data>
        <template id="listing">
            <ul>
                <li t-foreach="objects" t-as="object">
                    <a t-attf-href="#{ root }/objects/#{ object.id }">
                        <t t-esc="object.display_name"/>
                    </a>
                </li>
            </ul>
        </template>
        <template id="object">
            <h1><t t-esc="object.display_name"/></h1>
            <dl>
                <t t-foreach="object._fields" t-as="field">
                    <dt><t t-esc="field"/></dt>
                    <dd><t t-esc="object[field]/></dd>
                </t>
            </dl>
        </template>
    </data>
</odoo>

修改视图

视图的信息定义在views/views.xml中。模版生成内容都被注释了,直接添加自己的内容好了。我们也可以从零开始。

首先先把文件的框架建好

<odoo>
    <data>
    </data>
</odoo>
修改导航按钮
<menuitem id="menu_qingjia" name="请假" sequence="0"></menuitem>
<menuitem id="menu_qingjia_qingjiadan" name="请假单" parent="menu_qingjia"></menuitem>
<menuitem id="menu_qingjia_qingjiadan_qingjiadan" name="列表" parent="menu_qingjia_qingjiadan" action="action_qingjia_qingjd"></menuitem>

修改列表页

views/views.xml中增加对列表页的定义。可以借鉴模版生成的qingjia.list模版,只需要修改下字段就可以了。

<record model="ir.ui.view" id="qingjia.list">
    <field name="name">qingjia list</field>
    <field name="model">qingjia.qingjd</field>
    <field name="arch" type="xml">
        <tree>
            <field name="name"/>
            <field name="days"/>
            <field name="startdate"/>
        </tree>
    </field>
</record>
修改详情页
<record id="action_qingjia_qingjd" model="ir.actions.act_window">
    <field name="name">请假单</field>
    <field name="res_model">qingjia.qingjd</field>
    <field name="view_mode">tree,form</field>
</record>

注意:tree,form之间不能有空格,不然会报错~~~

也可以对详情页进行定制

<record id="action_qingjia_qingjd" model="ir.actions.act_window">
    <field name="name">请假单</field>
    <field name="res_model">qingjia.qingjd</field>
    <field name="arch" type="xml">
        <form>
        <sheet>
        <label for="name"/><field name="name"/>
        <label for="days"/><field name="days"/>
        <label for="startdate"/><field name="startdate"/>
        <label for="reason"/><field name="reason"/>
        </sheet>
        </form>
    </field>
</record>

也可以

<record id="action_qingjia_qingjd" model="ir.actions.act_window">
    <field name="name">请假单</field>
    <field name="res_model">qingjia.qingjd</field>
    <field name="arch" type="xml">
        <form>
        <group>
            <field name="name"/>
            <field name="days"/>
            <field name="startdate"/>
            <field name="reason"/>
        </group>
        </form>
    </field>
</record>

目前这个例子还比较简单,看不出来group的作用。

完成以上内容,就可以试着安装一下新模块了。

工作流

为了实现工作流,需要对模型进行修改

修改模型

注意 odoo 10 不再支持旧版的api,即

    def draft(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'state':'draft'}, context=context)
        return True

新版本里,从某种意义上对api进行了一些简化

    @api.model
    def draft(self):
        self.write({'state':'draft'})
        return True

以下为完整代码

class Qingjd(models.Model):
    _name = 'qingjia.qingjd'
    name = fields.Many2one('res.users', string="申请人", required=True)
    manager = fields.Many2one('res.users', string="主管", required=True)
    beginning = fields.Date(string="开始日期", required=True, default=fields.Datetime.now())
    ending = fields.Date(string="结束日期", required=True)
    reason = fields.Text(string="请假事由", required=True)
    accept_reason = fields.Text(string="同意理由", default="同意")

    current_name = fields.Many2one('res.users', 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
    def _get_default_name(self):
        uid = self.env.uid
        res = self.env['resource.resource'].search([('user_id', '=', uid)]) 
        name = res.name
        employee = self.env['hr.employee'].search([('name_related','=',name)])
        return employee

    @api.model
    def _get_default_manager(self):
        uid = self.env.uid
        res = self.env['resource.resource'].search([('user_id', '=', uid)])
        name = res.name
        employee = self.env['hr.employee'].search([('name_related','=',name)])
        return employee.parent_id
    

    defaults = {'name':_get_default_name,'manager':_get_default_manager,}

    def _get_is_manager(self):
        if self.current_name == self.manager:
            self.is_manager = True
        else:
            self.is_manager = False

    def _get_current_name(self):
        uid = self.env.uid
        res = self.env['res.users'].search([('id', '=', uid)])
        self.current_name = res

    @api.model
    def draft(self):
        self.write({'state':'draft'})
        return True

    @api.model
    def confirm(self):
        self.write({'state':'confirmed'})
        return True

    @api.model
    def accept(self):
        self.write({'state':'accepted'})
        return True

    @api.model
    def reject(self):
        self.write({'state':'rejected'})
        return True
增加视图
<record model="ir.ui.view" id="qingjia.qingjia_qingjd_form">
        <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>
增加工作流
<odoo>
    <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="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 id="qingjia_draft2confirm" model="workflow.transition">
            <field name="act_from" ref="act_draft"/>
            <field name="act_to" ref="act_confirm"/>
            <field name="signal">btn_confirm</field>
        </record>
        <record id="qingjia_confirm2accept" model="workflow.transition">
            <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 id="qingjia_confirm2reject" model="workflow.transition">
            <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>
</odoo>

完整的项目:https://github.com/asdfsx/qingjia

 
comments powered by Disqus