先安OpenERP博客

开放 协作 分享 双赢

基于开源ERP定制的信息化之路

企业信息化的路径一般有“直接采购成品软件”和“自主开发两条路”。

通用的产品功能不可能完全匹配企业需求,只能削足适履(咨询公司叫BPR业务流程重组)。在没怎么穿过鞋(信息化基础薄弱),满脚老茧的中国企业,削是必要的。只是,削的时候毕竟疼(改革带来的不安全感和重组带来的利益重新分配),没有很强势的咨询公司和软件品牌,很难推动。

所以很多公司选择自己从头开发,先走“数据信息化”这第一步。非常弱势,开始很愉快(袜子适应脚),越做越头大(补丁多了,底子不硬)。而且非专业IT公司对开发人员的能力、待遇和管理水平都比较低,这就是码农。

开源软件介于两者之间,核心功能用软件标准的,刚性需求二次开发。与自建相比收效更快,平台更好。跟支持二次开发的成品软件相比,企业自由度更高。通用部分和定制部分源代码的控制权都在企业自己手里,不会绑定供应商。所以总体拥有成本低。

为什么选择了时区后时间还是不对?

因为你是将服务器运行在windows系统上的,由于windows系统本身的问题,OpenERP服务器实际上是无法正确取到windows的时区设置,所以就fallback到UTC时间。所以要使OpenERP服务器正确设定时区,你可以在OpenERP服务器的配置文件(openerp_server.conf)文件中注明: timezone = Asia/Shanghai

或在openerp服务器启动时,输入命令行参数:openerp-server –timezone=Asia/Shanghai -s

或更简单的办法:如果你的服务器和客户端运行在同样的时区,不要在用户的时区设置里设置时区,留空即可

OpenERP v6.1 二次开发教程(一)

开发案例

通过此案例,你可以了解到:

1.一个基本的OpenERP模块的构成

2.字段的定义方法

3.视图定义定义的方法(表单视图,列表视图,视图动作,菜单)

需求

1.输入和查询课程,把信息储存到课程对象里
2.课程包含以下信息:名称,价格,天数,开始日期,教师,学员
3.每个课程可以有多个学员,要记录学员的姓名、电话、电子邮件
4.课程可以添加教材和作业等文档附件
5.用户可以设置默认值以加速输入
6.可以按名称查询课程,也可以用其他信息查找课程,并保存常用查询条件
7.可以导出课程信息到excel文件,并支持导入
8.可以按日期查看课程,并调整课程时间
9.老师只能看到自己的课程

写一个模块

结构

模块名就叫做oecn_training,然后它下面有四个文件,分别如下。

--oecn_training
    |--__init__.py
    |--__openerp__.py
    |--lesson.py
    |--lesson_view.xml

__init__.py

__init__.py文件是Python 的模块描述,因为OpenERP模块也是一个普通的Python模块。

# -*- encoding: utf-8 -*-
import lesson #导入包含Python代码的所有文件和目录

 

__openerp__.py

__openerp__.py文件(在6.0之前的版本也叫__terp__.py)它包含一个Python的字典声明这个模块的相关信息:模块名字,依赖关系,说明和组成。

{
   "name" : "OECN Training", #模块名
   "version" : "1.0",        #模块版本
   "description" : 'OECN Training Demo', #模块说明
   "author" : "Shine IT",    #作者
   "website" : "http://www.openerp.cn", #网址
   "depends" : [],                      #依赖的模块
   "update_xml" : ["lesson_view.xml"],  #模块更新的时候会读入的文件
   "installable" : True,                #可否安装
   "category":'Generic Modules/Others'  #模块类型
}

lesson.py

# -*- coding: utf-8 -*-
from osv import fields, osv

class oecn_training_lesson(osv.osv):
    _name = 'oecn.training.lesson'
    _discription = 'OECN 培训课程'
    _columns = {
       'name':fields.char('课程名',size=64,select=True),
       'date_start':fields.date('开始日期',select=True),
       'total_day':fields.float('总天数',digits=(16,1)),
       'teacher':fields.many2one('res.users','授课老师'),
       'students':fields.many2many('res.partner',string='学生'),
       'price':fields.float('价格',digits=(16,2)),
        }
oecn_training_lesson()

lesson_view.xml

<?xml version="1.0" encoding="utf-8"?>
<openerp>
    <data>
    <!--定义表单视图-->
        <record model="ir.ui.view" id="oecn_training_lesson_from_view">
            <field name="name">oecn.training.lesson.form</field>
            <field name="type">form</field>
            <field name="model">oecn.training.lesson</field>
            <field name="arch" type="xml">
                <field name="name"/>
                <field name="date_start"/>
                <field name="total_day"/>
                <field name="price"/>
                <field name="teacher"/>
                <field name="students" colspan="4"/>
            </field>
        </record>
        <!--定义列表视图-->
        <record model="ir.ui.view" id="oecn_training_lesson_tree_view">
            <field name="name">oecn.training.lesson.tree</field>
            <field name="type">tree</field>
            <field name="model">oecn.training.lesson</field>
            <field name="arch" type="xml">
                <field name="name"/>
                <field name="date_start"/>
                <field name="teacher"/>
                <field name="price" sum="合计"/>
            </field>
        </record>
<!--定义视图动作-->
    <record model="ir.actions.act_window"  id="action_oecn_training_lesson">
        <field name="name">oecn.training.lesson.action</field>
        <field name="res_model">oecn.training.lesson</field>
        <field name="view_type">form</field>
        <field name="view_mode">form,tree</field>
        <field name="view_id" ref="oecn_training_lesson_tree_view"/>
    </record>
<!--定义菜单-->
    <menuitem id="oecn_menu" name="OECN"/>
    <menuitem id="oecn_training_menu" name="OECN Training" parent="oecn_menu"/>
    <menuitem id="oecn_training_lesson_menu" name="OECN training Lesson" parent="oecn_training_menu" action="action_oecn_training_lesson"/>
</data>
</openerp>

安装一个模块

1.确保在扩展视图下(右上角小齿轮->首选项->扩展)

2.更新模块列表(设置->模块->更新模块列表)

3.搜索自己的模块(设置->模块->模块)

4.安装后重启服务器

以上内容已经收录在 OpenERP中文顾问社区的wiki

大家只要注册了就可以随意修改,欢迎大家添砖加瓦

小改动大幅提升mrp运算效率

我们的一个客户最近说,他们在进行mrp运算的时候OpenERP服务器的postgreSQl进程占用100%的CPU,而运算的过程持续了三天都没结束。

此客户是一家电子商务公司,前台使用Mangento网店,销售订单和库存信息与后台的OpenERP系统同步。当上千张订单从OpenERP-Mangento连接器导入OpenERP后,OpenERP据此生成大量的补货单。我们读了一下代码,发现现有的程序在搜索这些补货单时,使用了一个不带索引的字段planned_date进行排序,这是造成性能瓶颈的原因。

进一步调查发现根本不需要做这个排序,只需要去掉它并并增加一个state条件即可拿到更优的结果。方案十分有效,mrp计划在1小时内运行成功。为了更有效使用内存,我们还在每500个补货单强制commit一次。这个修改已被官方接受并合并到最新的开发版本中。

=== modified file 'procurement/schedulers.py'
--- procurement/schedulers.py 2011-01-14 00:11:01 +0000
+++ procurement/schedulers.py 2012-03-25 14:30:26 +0000
@@ -53,11 +53,12 @@

procurement_obj = self.pool.get('procurement.order')
if not ids:
- ids = procurement_obj.search(cr, uid, [], order="date_planned")
- for id in ids:
+ ids = procurement_obj.search(cr, uid, [('state', '=', 'exception')])
+ qty_procs = len(ids)
+ for i, id in enumerate(ids, 1):
wf_service.trg_validate(uid, 'procurement.order', id, 'button_restart', cr)
- if use_new_cursor:
- cr.commit()
+ if ((i%500 == 0) or (qty_procs == i)) and use_new_cursor:
+ cr.commit()
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
maxdate = (datetime.today() + relativedelta(days=company.schedule_range)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
start_date = time.strftime('%Y-%m-%d, %Hh %Mm %Ss')

 

oecn_help 模块介绍,大家一起完善中文顾问社区wiki

  我们最近做了一个oecn_help,是一个OpenERP model和module查询的模块,直接连到 www.openerp-china.org 上面,旨在一起构建一个中文的OpenERP wiki 百科,现在支持6.1和6.0.x。
使用方法如下:
通过蓝色小问号(6.0.x是通过侧边栏)把你拉中文社区的资料里面。
6.1 and 6.0.x
————————————–
 
——————————————————————————————
点击后会直接进入相关的model的wiki页面(当然了wiki里面的资料有的是旧的,社群成员也在不断更新,也需要大家一起动手完善)—>
——————————————————————————————
模块菜单里也有对于此模块的中文帮助文档
官方apps下载地址,欢迎提出各种建议。
谢谢大家。

__openerp__.py的演变

OpenERP版本经历了5.0.x,6.0.x,6.1,他们的__openerp__.py文件的键值也添加了或者改变了。不过放心,一切都向后兼容(我们还可以看到不少标准模块还在使用旧语法)

来源官方mail-list

6.0变化

———————————–

  • -’data‘代替了’ini_xml’和’update_xml’。这样更为直观,以为内它一般包含各种文件类型(CSV,YAML,XML)而区分它们 init/update则可以通过在xml内使用 <data noupdate=”1″>标示。
  • -’demo‘代替’demo_xml’,基于同样的原因(仅在演示的时候使用)
  • -’test‘是在demo数据导入后,导入的测试文件。当所有的测试文件处理完后,所有的测试操作会回滚到之前的默认值。(cfr –test-* 服务器参数)
  • -’web‘(布尔类型),用于标记模块是否复制和加载到web客户端

6.1 更新

———————————–

  • -新的’js‘,’css‘,’qweb‘用于声明web的源文件(按照惯例他们一般在 /static/src/ 下)
  • -’web‘(布尔类型)被取消,现在任何含有’js’,'css’,'qweb’的模块将不再需要转移到web客户端。因为web客户端已经默认被server包含了,当没有包含的时候,web应用模块会被复制到web模块下。
  • -’active‘(布尔类型)会改名为’auto_install’防止和OpenERP的软删除的’active’属性混淆。’auto_install’会他的所有依赖模块安装完后安装。如果它没有依赖的模块则会在新建数据库的时候被安装(像’base’)
  • -‘complexity’(easy|normal|expert)是一个新的可选字段,用于描述一个模块对于用户的友好程度。
  • -‘application’(布尔类型),标记一个模块是否为“应用程序”,如果是则会在模块的默认视图中展现出来(kanban视图)
  • -’category‘:可以通过把模块类别设置为’hidden’或者’hidden’的子类别,把某些模块隐藏起来(技术模块/自动安装的模块),如果用户是属于Technical Features group这个权限组,则可以在列表视图看到一个按钮来显示他们。
  • -(隐藏的)您可以在你的模块/static/src/img/icon.png 里添加你的模块图标(最好是透明的PNG),不需要在配置文件定义,默认是使用base模块的图标,这些图标将会在看板视图显示出来。

全局变化(所有的版本)

———————————–

以下元数据的扩展,更好的展示你的模块:

  • -’description‘支持RST语法(包含主要的一部分)
  • -’images‘(路径列表)可以添加说明截图。

 

 

在GTUG集会上秀OpenERP

上次Pycon中国大会,OpenERP作为python社区里的另类应用,只取得了15分钟的快速演讲资格,主题被主持人生生截断。这次GTUG的阅读聚会,面向的还是Python程序员,相同的组织者和主持人邀我痛快地讲一次。一个产品介绍一个开发演示,各一小时,很给力。

NetCycle提供的场地很赞,内环工厂改造的loft风格建筑。食堂和会议室都很豪华,据说椅子要8000元一把。

第一个主题是在GAE上搭自己的Blog,流程和我们常用的goAgent类似,如果墙没问题,还是pythoner搭独立博客的一个好选择。

第二个主题是OpenERP简介,使用了社区里讨论过的PPT,多次使用了“忽悠”、“赚钱”、“免费”等常技术人员反感的字眼,但反响不错。

第三个主题是OpenERP二次开发演示,用一个培训课程对象完整演示了OpenERP的快速开发能力。Joshua毫不紧张,半小时内有条不紊地逐个实现了9条预定的需求。赢得满堂赞许和惊艳。

这次演讲很成功,之后还会找更多机会向技术人员展示OpenERP,鼓励他们加入社区,共同把蛋糕做大!