首页 > 代码库 > odoo之ERP系统
odoo之ERP系统
odoo大纲
第一部分:数据库postgressql 大象
第二部分:ORM(API)
第三部分:客户端
用python软件写:
.py文件
包含两部分:1、自定义部分,由自己写,定义类和功能。
2、继承部分,针对的是原生的模块,继承他原有的功能,添加新的方法。
.xml文件
视图部分:最常用的是form视图和tree视图,等等其他视图,还有页签和其他控件按钮
<style>p { line-height: 120% } a:link { }</style>
Openerp 基本数据类型:
char: 字符型,size属性定义字符串长度。
text:
文本型,没有长度限制。
boolean:
布尔型(true,
false)
integer: 整数。
float:
浮点型,如
‘rate‘
: fields.float(‘Relative Change rate‘,digits=(12,6)),
digits定义整数部分和小数部分的位数。
date:
日期型
time:
时间型
datetime:
日期时间型
binary:
二进制型
复杂类型:selection, function, related, reference;
selection
Python代码
-
selection: 下拉框字段。定义一个下拉框,允许用户选择值。如:‘state‘: fields.selection(((‘n‘,‘Unconfirmed‘),(‘c‘,‘Confirmed‘)),‘State‘, required=True),这表示state字段有两个选项(‘n‘,‘Unconfirmed‘)和(‘c‘,‘Confirmed‘)。
function
Python代码
-
#函数型,该类型的字段,字段值由函数计算而得,不存储在数据表中。其定义格式为:
-
fields.function(fnct, arg=None, fnct_inv=None, fnct_inv_arg=None, type=‘float‘, fnct_search=None, obj=None, method=False, store=True)
-
-
#· type 是函数返回值的类型。
-
#· method 为True表示本字段的函数是对象的一个方法,为False表示是全局函数,不是对象的方法。如果method=True,obj指定method的对象。
-
#· fcnt 是函数或方法,用于计算字段值。如果method = true, 表示fcnt是对象的方法,其格式如下:def fnct(self, cr, uid, ids, field_name, args, context),否则,其格式如下:def fnct(cr, table, ids, field_name, args, context)。ids是系统传进来的当前存取的record id。field_name是本字段名,当一个函数用于多个函数字段类型时,本参数可区分字段。args是‘arg=None‘传进来的参数。
-
#· fcnt_inv是用于写本字段的函数或方法。如果method = true, 其格式是:def fcnt_inv(self, cr, uid, ids, field_name, field_value, args, context),否则格式为:def fcnt_inv(cr, table, ids, field_name, field_value, args, context)
-
#· fcnt_search 定义该字段的搜索行为。如果method = true, 其格式为:def fcnt_search(self, cr, uid, obj, field_name, args),否则格式为:def fcnt_search(cr, uid, obj, field_name, args)
-
#· store 表示是否希望在数据库中存储本字段值,缺省值为False。不过store还有一个增强形式,格式为 store={‘object_name‘:(function_name,[‘field_name1‘,‘field_name2‘],priority)} ,其含义是,如果对象‘object_name‘的字段[‘field_name1‘,‘field_name2‘]发生任何改变,系统将调用函数function_name,函数的返回结果将作为参数(arg)传送给本字段的主函数,即fnct。
Python代码 related
-
#关联字段,表示本字段引用关联表中的某字段。
-
格式为:fields.related(关系字段,引用字段,type, relation, string, ...),关系字段是本对象的某字段(通常是one2many or many2many),引用字段是通过关系字段关联的数据表的字段,type是引用字段的类型,
-
-
如果type是many2one or many2many, relation指明关联表。例子如下:
-
‘address‘: fields.one2many(‘res.partner.address‘, ‘partner_id‘, ‘Contacts‘),
-
‘city‘:fields.related(‘address‘,‘city‘,type=‘char‘, string=‘City‘),
-
‘country‘:fields.related(‘address‘,‘country_id‘,type=‘many2one‘, relation=‘res.country‘, string=‘Country‘),
-
这里,city引用address的city字段,country引用address的country对象。在address的关联对象res.partner.address中,country_id是many2one类型的字段,所以type=‘many2one‘, relation=‘res.country‘。
reference
引用型,格式为:fields.reference(字段名,
selection, size, ... )。其中selection是:
1)返回tuple列表的函数,或者
2)表征该字段引用哪个对象(or
model)的tuples列表。reference字段在数据库表中的存储形式是(对象名,ID),如(product.product,3)表示引用对象product.product(数据表product_product)中id=3的数据。reference的例子:
def
_links_get(self, cr, uid):
cr.execute(‘select object,name from
res_request_link order by priority‘)
return
cr.fetchall()
...
‘ref‘:fields.reference(‘Document
Ref 2‘, selection=_links_get,
size=128),
...
上例表示,字段ref可以引用哪些对象类型的resource,可引用的对象类型从下拉框选择。下拉框的选项由函数_links_get返回,是(object,name)对的列表,如[("product.product","Product"),
("account.invoice","Invoice"),
("stock.production.lot","Production Lot")] 。
关系类型:one2one, one2many, many2one, many2many
Openerp
one2one:
一对一关系,格式为:fields.one2one(关联对象Name,
字段显示名,
... )。在V5.0以后的版本中不建议使用,而是用many2one替代。
many2one:
多对一关系,格式为:fields.many2one(关联对象Name,
字段显示名,
...
)。可选参数有:ondelete,可选值为"cascade"和"null",缺省值为"null",表示one端的record被删除后,many端的record是否级联删除。
one2many:
一对多关系,格式为:fields.one2many(关联对象Name,
关联字段,
字段显示名,
... ),例:‘address‘:
fields.one2many(‘res.partner.address‘, ‘partner_id‘,
‘Contacts‘)。
many2many:
多对多关系。例如:
‘category_id‘:fields.many2many(‘res.partner.category‘,‘res_partner_category_rel‘,‘partner_id‘,‘category_id‘,‘Categories‘),
表示以多对多关系关联到对象res.partner.category,关联表为‘res_partner_category_rel‘,关联字段为‘partner_id‘和‘category_id‘。当定义上述字段时,OpenERP会自动创建关联表为‘res_partner_category_rel‘,它含有关联字段‘partner_id‘和‘category_id‘。
change_default:别的字段的缺省值是否可依赖于本字段,缺省值为:False。例子(参见res.partner.address),
‘zip‘:
fields.char(‘Zip‘, change_default=True,
size=24),
这个例子中,可以根据zip的值设定其它字段的缺省值,例如,可以通过程序代码,如果zip为200000则city设为“上海”,如果zip为100000则city为“北京”。
readonly:
本字段是否只读,缺省值:False。
required:
本字段是否必须的,缺省值:False。
states:
定义特定state才生效的属性,格式为:{‘name_of_the_state‘:
list_of_attributes},其中list_of_attributes是形如[(‘name_of_attribute‘,
value), ...]的tuples列表。例子(参见account.transfer):
‘partner_id‘:
fields.many2one(‘res.partner‘, ‘Partner‘,
states={‘posted‘:[(‘readonly‘,True)]}),
string:
字段显示名,任意字符串。
translate:
本字段值(不是字段的显示名)是否可翻译,缺省值:False。
size:
字段长度。
priority:
domain:
域条件,缺省值:[]。在many2many和many2one类型中,字段值是关联表的id,域条件用于过滤关联表的record。例子:
‘default_credit_account_id‘:
fields.many2one(‘account.account‘, ‘Default Credit Account‘,
domain="[(‘type‘,‘!=‘,‘view‘)]"),
本例表示,本字段关联到对象(‘account.account‘)中的,type不是‘view‘的record。
invisible:
本字段是否可见,即是否在界面上显示本字段,缺省值True。
selection:
只用于reference字段类型,参见前文reference的说明
Attributs
说明
?context:
在context
中增加一些变量,这些变量可用于on_change方法及domain条件式。
?on_change:
当本字段值改变时,调用Server端函数。例子:
on_change=”onchange_shop_id(shop_id)”.
?relation:当本字段是一个引用其他数据表的id
时,指定关联数据表名。通常用在related
和
function
类型的字段中。
?
级联关系:
?ondelete
?set
null: 删除主记录时候,从记录到主记录的引用置为null。
?set
default: 删除主记录时候,从记录到主记录的引用置为缺省值。
?cascade:
删除主记录时候,级联删除从记录。
?restrict:
如果有从记录,不允许删除主记录。
?no
action: 不采取任何动作,即删除主记录,但保留从记录不变。
模板中的标签统一都是以"t-"开始的。
t-name 用于指明模板的名称
t-extend 用于指明该模板是继承自另外哪一个模板,后面会带父模板的名称,如:t-extend=“Login"
t-jQuery 一个jQuery的选择器,后面指明选择器的定义,如:t-jquery=".oe_logiin"
t-operation 一般跟在t-jquery后面,指明选择器找到元素后执行的动作,其值有:append(追加)、replace(替换)
t-if 用于指明元素在页面产生的条件,后面是带一个JavaScript的表达式,返回True或False
t-att-### 用于指明一个元素的属性值,###是元素的属性名称,如:t-att-value="http://www.mamicode.com/javascript表达式"
t-foreach 用于指明一个循环调用,后面一般带的是一个数组
t-as 用于取得循环中的单个值,与t-foreach搭配使用,后面带的是一个变量名,可以循环中使用变量取值
t-esc 用于一个文字输出
t-call 用于调用另外模板,后面带一个模板的名称
t-set 用于设定一个变量,后面带变量的名称,一般跟t-value搭配使用
t-value 用于指定某个变量或元素的值
然后就是基本的函数:
python常用方法集合: _get: def get_partner_sequence(self,cr,uid,partner_id,context=None): code="stock_picking_outgoing_no_%d" %(partner_id) no=self.pool.get(‘ir.sequence‘).get(cr, uid, code, context=context) if no==False: self.create_new_sequence(cr,uid,code,partner_id) no=self.pool.get(‘ir.sequence‘).get(cr, uid, code, context=context) partner_ids=self.pool.get(‘res.partner‘).search(cr,uid,[(‘id‘,‘=‘,partner_id)]) partner_obj=self.pool.get(‘res.partner‘).browse(cr,uid,partner_ids) no = "%s-%s" %(partner_obj.code,no) return no -crete: def create(self, cr, uid, vals, context=None): context = context or {} origin=vals[‘origin‘] sql=‘select a.name from sale_origin a left join sale_order b on a.id=b.sale_origin_id where b.name=\‘%s\‘‘%(origin) cr.execute(sql) if cr.rowcount>0: dict1=cr.dictfetchall()[0] origin=dict1[‘name‘]+‘-‘+origin vals.update({‘origin‘:origin}) sql=‘select a.name from purchase_origin a left join purchase_order b on a.id=b.purchase_origin_id where b.name=\‘%s\‘‘%(origin) cr1=cr cr1.execute(sql) if cr1.rowcount>0: dict2=cr1.dictfetchall()[0] origin=dict2[‘name‘]+‘-‘+origin vals.update({‘origin‘:origin}) ptype_id = vals.get(‘picking_type_id‘, context.get(‘default_picking_type_id‘, False)) ptype_obj=self.pool.get(‘stock.picking.type‘).browse(cr, uid, ptype_id, context=context) obj_data = http://www.mamicode.com/self.pool.get(‘ir.model.data‘) location_customers_id = obj_data.xmlid_to_res_id(cr, uid, ‘stock.stock_location_customers‘) location_workshop_id = obj_data.xmlid_to_res_id(cr, uid, ‘mrp.stock_location_workshop‘) # 根据客户来生成不同的编号 if ptype_obj.default_location_dest_id.id==location_customers_id \ and ptype_obj.code==‘outgoing‘ \ and ptype_obj.default_location_src_id.id!=location_workshop_id: if (‘name‘ not in vals) or (vals.get(‘name‘) in (‘/‘, False)): partner_id = vals.get(‘partner_id‘) vals[‘name‘] = self.get_partner_sequence(cr,uid,partner_id) new_id=super(stock_picking, self).create(cr, uid, vals, context) self.action_confirm(cr, uid, [new_id], context=context) return new_id _write方法: #修改单据下的日期和单头一样 def write(self,cr,uid,ids,vals,context=None): if ‘date_done‘ in vals and vals.get(‘date_done‘): obj=self.pool(‘stock.move‘) move_ids=obj.search(cr,uid,[(‘picking_id‘,‘=‘,ids[0])]) obj.write(cr,uid,move_ids,{‘date‘:vals.get(‘date_done‘)}) return super(stock_picking, self).write(cr, uid,ids, vals, context) _brown方法和search方法用法:
def action_create_wave(self,cr,uid,ids,context=None):
if not context:
context={}
selfobj=self.browse(cr,uid,ids[0],context=context)
pickids=pickobj.search(cr,uid,[(‘origin‘,‘like‘,selfobj.name)])
.......
.......
.......
大致用法就是这样
默认信息带出来的写法:
_defaults={
‘product_qty‘:1,
‘price‘:1,
‘stste‘:‘draft‘,
}
get-search-browse方法共用
点击备注id带出他的内容:
def sale_requirements_change(self,cr,uid,ids,requirements_id=None,context=None):
result={}
if requirements_id:
require_ids=self.pool.get(‘custorment.requirement‘).search(cr,uid,[(‘id‘,‘=‘,requirements_ids)])
obj=self.pool.get(‘custorment.requirement‘).browse(cr,uid,require_ids,context=None)
result[‘requirement_text‘]=obj.name
else:
result[‘requirement_text‘]=return{‘value‘:result}
name_search: 固定用法 # 输入工序序号会自动带出工序名 def name_search(self, cr,user,name=‘‘, args=None, operator=‘ilike‘, context=None, limit=100): if not args: args=[] args=args[:] ids=[] if name: ids=self.search(cr,user,[(‘sequence‘,‘ilike‘,name)]+args,limit=limit,context=context) else: ids=self.search(cr,user,args,limit=limit,context=context) return self.name_get(cr,user,ids,context)class:
用法
class
mrp_routing_workcenter_ref(osv.osv):
_inherit=‘mrp.routing.workcenter‘ _columns={ ‘ban_channeng‘:fields.float(u‘班产能‘,digits=(5,1)), ‘machine_id‘:fields.many2one(‘mrp.machine‘,u‘机台‘), ‘user_id‘:fields.many2one(‘res.users‘,u‘工人‘), ‘workcenter_proline‘:fields.one2many(‘routing.workcenter.price‘,‘workcenter_proid‘,u‘单身关联‘, copy=True), ‘produce_description‘:fields.char(u‘工序描述‘,), ‘yjweight‘:fields.float(string=u‘应交重量‘,digits=(6,2)), } _defaults={ ‘produce_description‘:‘‘, } 取消关联def
unlink(
self
, cr, uid, ids, context=
None
):
sale_origins = self.read(cr, uid, ids, [‘state‘], context=context) unlink_ids = [] for s in sale_origins: if s[‘state‘] in [‘draft‘,‘cancel‘]: unlink_ids.append(s[‘id‘]) else: raise osv.except_osv((u‘警告!‘),(u‘已确认订单不可删除‘)) return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
odoo之ERP系统