Odoo为序列号管理增加快捷生成日期范围

实现目标

实现后效果如图所示,增加了范围类型、范围开始日期、范围结束日期和一个生成按钮

mark

开发步骤

1、开发前找到修改目标

首先激活开发者模式,通过菜单Settings | Technical | Sequences进入序列编辑界面,通过菜单Open Developer Tools | Edit View: Form查看表单视图,得到需要修改的模型为ir.sequence,视图为base.sequence_view(为了排除翻译导致的名称不一致,这里菜单名和截图使用英文的)

mark

2、创建模块

进入自己的模块目录中,使用脚手架生成模块结构

cd C:/Project/odoo12-x64/source\odoo\custom-addons
C:\Project\venv\odoo12\Scripts\python.exe C:/Project/odoo12-x64/source/odoo-bin scaffold myapp_sequence

mark

3、继承序列模型,添加设置日期范围的字段

1
2
3
4
5
6
7
8
9
10
#models/models.py

from odoo import models, fields, api
class IrSequence(models.Model):
_inherit = 'ir.sequence'

range_type = fields.Selection(selection=[('day','Day'),('week','Week'),('month','Month')],
string='范围类型')
range_from = fields.Date(string='范围开始日期')
range_to = fields.Date(string='范围结束日期')

4、继承序列表单视图,添加字段和按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- views/views.xml -->
<odoo>
<data>
<record model="ir.ui.view" id="sequence_view_inherit">
<field name="name">Sequences Inherit</field>
<field name="model">ir.sequence</field>
<field name="inherit_id" ref="base.sequence_view"/>
<field name="arch" type="xml">
<field name="use_date_range" position="after">
<field name="range_type" attrs="{'invisible': [('use_date_range', '=', False)]}"/>
<button name="create_range" type="object" string="创建日期范围" class="oe_edit_only oe_highlight" attrs="{'invisible': [('use_date_range', '=', False)]}"/>
</field>
<field name="number_next_actual" position="after">
<field name="range_from" attrs="{'invisible': [('use_date_range', '=', False)]}"/>
<field name="range_to" attrs="{'invisible': [('use_date_range', '=', False)]}"/>
</field>
</field>
</record>
</data>
</odoo>

其中

class="oe_edit_only oe_highlight" 表示按钮编辑时可见

attrs="{'invisible': [('use_date_range', '=', False)]}" 表示字段use_date_range为False时隐藏

5、为按钮添加事件函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#models/models.py

import datetime, calendar
from odoo.exceptions import UserError

#在class IrSequence中添加函数
def get_date_range_list(self, start_date, end_date, flags='day'):
result = []
result.append(start_date)
if flags == 'day':
for n in range(int((end_date - start_date).days - 1)):
compute_date = start_date + datetime.timedelta(days=n + 1)
result.append(compute_date)
elif flags == 'week':
for n in range(int((end_date - start_date).days - 1)):
compute_date = start_date + datetime.timedelta(days=n + 1)
if compute_date.weekday() != calendar.MONDAY:
continue
result.append(compute_date)
elif flags == 'month':
for n in range(int((end_date - start_date).days - 1)):
compute_date = start_date + datetime.timedelta(days=n + 1)
if compute_date.day != 1:
continue
result.append(compute_date)
result.append(end_date)
return result

@api.multi
def create_range(self, values):
self.ensure_one()
if not self.range_type or not self.range_from or not self.range_to:
raise UserError('请填写必要的参数(范围类型/范围开始日期/范围结束日期)')
if self.range_from > self.range_to:
raise UserError('范围开始时间不能大于结束时间')
self.date_range_ids.unlink()
date_range = self.get_date_range_list(self.range_from, self.range_to, self.range_type)
print(date_range)
date_range_pair = list(dict(zip(date_range[:-1], date_range[1:])).items())

for date_from ,date_to in date_range_pair:
values = {'number_next_actual': 1, 'date_from':date_from.strftime('%Y-%m-%d'), 'date_to':date_to.strftime('%Y-%m-%d'), 'sequence_id': self.id}
self.date_range_ids.create(values)

6、安装并使用模块

从应用中安装这个模块,进入序列号编辑表单,选择范围类型,范围开始日期和结束日期,点击创建日期范围,将清除之前的日期范围,按照规则重新创建日期范围