odoo中可以生成利用'ir.sequence'模型来生成单据的序列号,每次生成单据的时候都会自动生成,用起来还是非常方便的。这里主要介绍两种方式生成序列号,一种是借助XML。另一种是全python代码,但是本质都是通过操作'ir.sequence'模型来完成。
第一种:借助XML方式,一般是在项目的data文件夹下面创建一个ir_sequence.xml文件。
<record id="sequence_hg_contract" model="ir.sequence">
<field name="name">合同的序号规则</field>
<field name="code">yf.contract</field>
<field name="prefix">YF%(year)s-%(month)s-%(day)s</field>
<field name="padding">4</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
</record>
name: 名字随便取
code:这个是用来获取序列号的,需保证唯一性
prefix:前缀,可以是固定的字面量也可以是组合参数
padding:流水号位数
number_increment: 步长,即序列号增长的长度,默认值为1。
number_next: 下一序列号数字。
在模型中获取序列号,一般是写在create方法中,使用next_by_code()方法来获取序列号,此方法有两个参数,第一个是就是在xml中的code,第二个是序列日期。
@api.model
def create(self, values):
"""
生成用访合同号
"""
times = fields.Date.today()
values['name'] = self.env['ir.sequence'].next_by_code('hg.contract', times)
return super(HgSparePartsContract, self).create(values)
比较常用的是通过XML这种方式,但是笔者觉得纯代码的方式更好一些,简单介绍一下:
@api.model
def create(self, vals):
now_date = (datetime.datetime.utcnow() + datetime.timedelta(hours=8)).date()
name = vals.get('name')
if not name:
vals['name'] = self._pro_name(vals.get('purchase_type'), vals.get('department_id'))
new_id = super(PurchaseOrder, self).create(vals)
def _pro_name(self, purchase_type, department):
code = 'purchase.order'
pre = '%(y)s-%(month)s-'
if purchase_type == 'reagent':
department_name = self.env['hr.department'].sudo().search([('id', '=', department)]).name
code = 'purchase.order' + '.' + str(department_name)
pre = str(department_name) + '-%(y)s-%(month)s-'
new_sn = self.env['ir.sequence'].get(code)
if new_sn:
return new_sn
else:
try:
self.env['ir.sequence'].sudo().create({'name': u'采购单', 'code': code,
'prefix': pre,
'padding': 4,
'number_increment': 1, 'number_next_actual': 1,
'implementation': 'standard',
'active': True, 'company_id': False})
except Exception as e:
print(e)
new_sn = self.env['ir.sequence'].get(code)
if new_sn:
return new_sn
先说一下具体需求:采购单分成两类,动物采购和其他采购。如果是动物采购序号规则是:年-月-日-四位流水;如果是其他采购序列号规则是:部门名称-年-月-四位流水(一个部门一套流水号)。
简单说一下这两部分代码,单据在创建的时候去创建序列号,_pro_name()方法是用来生成序列号的,之所以要传入两个值,根据purchase_type来判断采购单的类型,默认为动物采购,如果是动物采购,那么code就是'purchase.order',prefix的值为'%(y)s-%(month)s-',其次在判断当前code是否存在,如果存在则返回,不存在则新建;对于其他采购来说,code为'purchase.order.部门名称',prefix的值为'部门名称-%(y)s-%(month)s-',这样的话,就能实现每一个部门都有自己一套流水,同时还能区分采购单的类型。
在介绍一种每个月重置流水号(每个月的流水号从1开始)
def resetting(self, day=1):
if (datetime.datetime.now() + datetime.timedelta(hours=8)).day == day:
result = self.env['ir.sequence'].search([('code', 'like', 'purchase.order')])
dt = datetime.datetime.utcnow() + relativedelta.relativedelta(months=1)
for rec in result:
if rec.code == 'yi.purchase.order':
rec.prefix = f'{dt.year}-{dt.month:02}-'
rec.number_next_actual = 1
else:
pre = str(rec.code.split('.')[-1])
rec.prefix = f'{pre}-{dt.year}-{dt.month:02}-'
rec.number_next_actual = 1
这个写一个定时任务就可以实现,只要输入day的值就能实现在几月几号实现序列号重置:因为笔者采购单分为两种类型,其中部门还有自己的流水,所以在获取的时候进行了like,然后循环判断处理每一个序列号。
在odoo的技术--》设置--》序号中可以对序列号进行管理