Mixoo

Hi, 好久不见


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

  • 搜索

在centos7上安装odoo13

发表于 2020-05-05 | 分类于 odoo

安装

yum install epel-release

sudo root

yum -y groupinstall “Development tools”
yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
yum install libffi-devel -y

cd /opt # 待安装的目录
wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
tar -xvJf Python-3.7.0.tar.xz

如何将“业界毒瘤”闭源模块清除

发表于 2020-04-28 | 分类于 odoo

业界毒瘤

相信很多人之所以选择odoo就是因为它开源开放,虽然官方近些年来为了恰饭推出了企业版付费的模式,但节操仍在——企业版代码依旧开源开放。但是最近在客户项目中,突然发现了几个国产的微信公众号平台相关的模块,使用了闭源的方式——交付到客户手里的是加密过后的二进制代码。

这样做的带来的隐患有:

  • 源代码掌握在别人手中,出了问题只能找作者修改。
  • 一旦作者失联,项目将不可维护。
  • 数据产生之后将骑虎难下,议价权完全掌握在原作者手中。
  • 二进制代码不能Review,焉知其中没有后门或者在代码中下毒?

清除方法

首先,确认你没有生产数据在其中,否则,将会导致数据丢失。

闭源模块带来的问题之一就是本地调试极其不方便,代码出了问题无法调试。对于一个已经安装了闭源模块的数据库来说,我们可以通过一下步骤进行清除:

在数据库中,将闭源模块的安装状态设置为to remove:

1
update ir_module_module set state = 'to remove' where name ilike '%oe_jia%' and state='installed'

然后,重启服务,odoo将自动跳过这些模块,使你能够正常登录。

登录以后,找到应用,将这些毒瘤模块一一卸载清除:

呵呵,卸载时居然报错了:

忠告

不要使用不提供源码的第三方模块,因为这将对你的项目造成不可预估的风险,对你的金钱来说也可能是一笔无底洞,对后期接手项目的维护人员来说,更将是一场灾难。

odoo中的外协加工

发表于 2020-04-21 | 分类于 odoo

本文基于odoo 13.0 企业版

时间来到了2020年,传闻13.0中原生集成了生产模块的外协加工功能,今天我们就来一探究竟。

启用外协设置

首先,我们需要先启用外协设置,在设置-操作-外协:

启用外协之后,我们在BOM的选项中会有一个Subcontracting的选项:

我们在创建BOM的时候选择该选项,并将选中要生产该产品的外包厂。

采购或直接从外包厂收货

odoo原生的设计支持两种外包模式,一种是从外包厂直接采购成品回来,另外一种是直接从外包厂将成品(半成品)收货。

从外包厂采购成品

我们先来看如何操作直接从外包厂采购成品回来。

首先,创建一个采购单,供应商选BOM中设置好的的外包厂:

单击确认,采购单会自动生成如下单据:

这个单据不同于我们普通的采购单,向导界面中显示的要消耗的原材料。从技术的角度上将,普通入库单中显示的是stock.move或者stock.move.line,而这里显示的是mrp.product.produce.line。

单击保存,系统将自动生成如下的库存移动:

原材料

subcontracting location—->production location

成品

production location —-> subcontracting_location
subcontracting location —–> stock

subcontracting location 是挂载在Partner Location下面的内部库位。

当我们完成收货,将会看到成品位于Stock库位,并且会消耗掉subcontracting location中相应的原材料数量。

直接从外包厂收货

直接从外包厂进货意味着不需要创建采购单,我们直接在入库单里手动创建一个入库单即可:

剩下的步骤同采购入库相同。

odoo 回退的单据不能使用推拉物流规则

发表于 2020-04-20 | 分类于 odoo

原本的设计

客户的需求是要将供应商发来的货物运送到质检仓库进行质检,将不合格的产品退回给供应商退换货,换回来的货依旧要走质检流程。因此,设计的流程如下图:

odoo中的取消保留错误问题的处理方法

发表于 2020-04-20 | 分类于 odoo

本文适用于12.0

在使用库存过程中如果操作不是很严格,会出现下面的错误消息:

1
It is not possible to unreserve more products of xxxxx than you have in stock.

出现该问题的原因就是本来应该属于次单据的保留数量被非法占有或移动走了。

解决方案就是找到xxxx对应的stock_move 将其模型中的product_qty字段的数量重置为0即可。

1
update stock_move_line set product_qty = 0 where id = ;

odoo产品信息添加可用库存

发表于 2020-04-15 | 分类于 odoo

添加可用库存的必要性

odoo当前版本(12,13)中的产品信息中有在手数量和预测数量,在手数量指的是当前库存中实际存在的库存数量,预测数量指的是包含即将入库和即将出库的一个库存预测值。预测数量 = 在手数量 + 即将入库数量 - 即将出库数量。即将在这里的意思当然就是尚未完成的状态。

但是在实际使用的过程中,我们往往还关心另一个很重要的参数,可用数量。可用数量 = 在手数量 - 已预留数量。遗憾的是odoo官方并未提供这个字段。因此,我们需要手动实现它。

odoo的库存模型stock.quant中已经有了在手数量quantity和已预留数量reserved_quantity,因此可用数量的值可以通过定义一个计算字段available_qty:

1
2
3
4
5
6
7
avaliable_qty = fields.Float(
"可用库存", compute="_get_avaliable_qty", store=True)

@api.one
@api.depends("quantity", "reserved_quantity")
def _get_avaliable_qty(self):
self.avaliable_qty = self.quantity - self.reserved_quantity

实际效果

odoo字段继承改写类型报错问题

发表于 2020-04-05 | 分类于 odoo

本文基于13.0

由于开发需要,想要把hr模块中的address_home_id改成文本类型,本来以为很简单的事情,很快码好了代码,但是却发现后台报错了,直接导致了系统进入不了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/modules/registry.py", line 85, in new
odoo.modules.load_modules(registry._db, force_demo, status, update_module)
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/modules/loading.py", line 416, in load_modules
force, status, report, loaded_modules, update_module, models_to_check)
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/modules/loading.py", line 312, in load_marked_modules
perform_checks=perform_checks, models_to_check=models_to_check
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/modules/loading.py", line 194, in load_module_graph
registry.setup_models(cr)
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/modules/registry.py", line 247, in setup_models
model._setup_fields()
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/models.py", line 2684, in _setup_fields
field.setup_full(self)
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/fields.py", line 420, in setup_full
self._setup_related_full(model)
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/fields.py", line 476, in _setup_related_full
field.setup_full(target)
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/fields.py", line 420, in setup_full
self._setup_related_full(model)
File "/mnt/hgfs/codes/odoo/odoo-13.0/odoo/fields.py", line 475, in _setup_related_full
field = target._fields[name]
AttributeError: 'bool' object has no attribute '_fields'

本来一度以为是13.0又变更了API,不支持通过继承的方式改变字段的类型了,后来google也没发现类似的错误,于是只跟踪debug。

1
2
3
4
5
6
7
8
9
10
11
12
13
def _setup_related_full(self, model):
""" Setup the attributes of a related field. """
# fix the type of self.related if necessary
if isinstance(self.related, str):
self.related = tuple(self.related.split('.'))

# determine the chain of fields, and make sure they are all set up
target = model
for name in self.related:
field = target._fields[name]
field.setup_full(target)
target = target[name]
...

输出日志发现

1
2
3
4
5
6
7
8
9
10
---------
mobile_phone hr.employee()
---------
employee_id res.users()
---------
phone hr.employee()
---------
address_home_id hr.employee()
---------
phone False

在setup addreess_home_id字段之后,又去setup了phone,这就有点微妙了。

后来,突然想到,address_home_id肯定是被别的字段做了关联引用,从而导致了一旦变更了本字段的类型,会导致之前代码中关联的字段不能正确挂载而导致报错。

多公司下的税率设置

发表于 2020-03-18 | 分类于 odoo

事情的起因是这样的,公司的odoo系统使用了多公司,集团零售门店部门使用的是B公司,供应链系统使用的是A公司,某天B公司的采购报告,下不了采购单,提示res.company对象因为Rule的问题,没有访问权限。从后台日志中可以看到,B在下单的时候试图访问A公司的资料。

既然是安全规则的问题,那么我就去看了一下公司对象的设置,一切正常。奇怪的是B公司的采购明明只有B公司的访问权限,为什么要去访问A公司的资料呢?

根据前端提示的报错代码,定位到了,B公司采购在下单的时候使用了A公司的供应商税。问题又来了,B公司下采购单,为什么要访问A公司的税种呢?后来发现,A公司的采购税居然在B公司下可见,显然,税的访问设置出了问题。

我们找到税率的安全规则,看到了如下的访问设置:

1
[(1,'=',1)]

显然,这里的设置是不对的,改为

1
[('company_id','child_of',[user.company_id.id])]

即恢复正常。

结论

从上面的过程中,我们可以反思Odoo是如何处理多公司条件下的税种隔离方案,靠的就是安全规则,不同公司的人看到的税种不一样。而对于成本价,odoo的处理方式是另外一种,改天再细谈。

在odoo中使用Swagger

发表于 2020-02-27 | 分类于 odoo

感谢OCA为我们提供了基础模块

做后台的同学一定听说过swagger的大名,现在改名叫OpenApi了,简单说就是一个提供了方便测试的接口界面。跟我们做对接的人,打开界面就能轻松地知道如何正确的调用我们的接口和接收返回值。

网上比较多的是flask和swagger结合的例子,如果我们想要在odoo中实现类似的REST Swagger模式,我们可以按照下面的方式进行。

安装依赖

本文依赖于OCA的一个模块base_rest,读者可以自行搜索,也可以关注odoohub回复base_rest获取下载链接。

编写接口

由于odoo自带的jsonrpc并不能满足我们的需求(我们不可能给第三方系统的人提供一种类似res.partner的对象,并给他们解释对象的意思),因此,我们需要重新定义一些业务接口。

定义一个新的Service

我们把新的API接口定义为一个Service,继承base.rest.service这个对象,并定义好usage、description等属性。

1
2
3
4
5
6
7
8
class AladinService(Component):
_inherit = "base.rest.service"
_name = "aladin.service"
_usage = "Aladin"
_collection = "base.rest.aladin.services"
_description = """
阿拉丁业务API
"""

定义接口

rest_api借助cerberus(Cerberus是一个用于Python的轻量级且可扩展的数据验证库)来验证我们输入的字段值。

一个典型的get接口可以写成下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@skip_secure_response
def get(self, _id, size):
"""
Get partner's image
"""
field = "image"
if size == "small":
field = "image_small"
elif size == "medium":
field = "image_medium"
status, headers, content = self.env["ir.http"].binary_content(
model="res.partner", id=_id, field=field, env=self.env
)
if not content:
raise MissingError(_("No image found for partner %s") % _id)
image_base64 = base64.b64decode(content)
headers.append(("Content-Length", len(image_base64)))
response = request.make_response(image_base64, headers)
response.status_code = status
return response

其中方法的描述会自动加载到swagger的方法描述中。

定义API路径

在controller中,定义API接口的路径:

1
2
3
4
class BaseRestDemoPrivateApiController(main.RestController):
_root_path = "/base_rest_demo_api/private/"
_collection_name = "base.rest.demo.private.services"
_default_auth = "user"

base_rest提供了基本的权限认证,基于odoo自身的账户设置。_default_auth的可选值有public和user。两个值会被加载到controller的auth参数中,以用来标识验证方法。

这并非当前流行的验证方式,可惜的是oca并没有提供oatuh的验证机制。因此,笔者在实际的应用过程中,借鉴了另外的一个模块restapi的方式。

页面展示

安装模块后,我们可以在Odoo中的模块界面中看到一个swagger的图标:

点击进入swagger api界面:

在odoo中管理微信公众号

发表于 2020-02-17 | 分类于 odoo

odoo用来管理微信公众号是非常合适的,今天我们就来介绍一下正在开发中的微信公众号模块的主要功能。后续功能正在添加中,欢迎持续关注。

接入设置

要使用odoo管理公众号,首先需要对设置公众号的APPID、SCRET和授权等参数。本模块已经做好了设置,用户只需要将相应的参数填入设置中即可完成对接。

其中,公众号APPID、密钥和Token可以在公众号-设置-开发设置中找到。
网页授权设置,是用于Oauth登录的验证文件,用户需要先下载,然后将文件名和文件内容分别填入设置中,即可完成对接。

网页授权要求HTTPS,用户首先需要有备案后的域名和申请HTTPS证书。

基础配置

本模块的基础功能就是对公众号的基础功能进行管理,包括菜单、用户和素材管理三大部分。

菜单管理

最基础的功能就是将微信公众号的菜单管理系统接入到odoo中,用户可以在Odoo中创建、编辑和删除公众号菜单,系统会自动将菜单同步到公众号中。

公众号的菜单分为多种类型,本文提供的测试账号中提供了多种类型的菜单,欢迎测试。

粉丝管理

当用户关注了公众号以后,我们会自动抓去该用户的昵称、头像等基础信息到Odoo中。

素材管理

公众号的素材分为临时素材和永久素材两大类,其涵盖的媒体类型包括了图片、声音、文字、视频、音乐等常见的媒体类型。通过素材管理功能,我们可以直接在odoo中对公众号的素材进行管理。

像图文消息中的图片和音视频等多媒体,都需要先在素材管理中上传,然后在图文消息中应用生成的Media ID,完成关联。

图文消息

本模块也支持对图文消息的编辑和推送,在图文消息中创建一个图文消息非常简单:

点击上传将图文消息上传至微信服务器,为了方便起见,我们可以使用预览功能查看我们刚上传的图文消息:

点击发布可以将图文消息推送给指定的用户

消息管理

消息管理包含消息记录、自动回复、模板消息管理和客服对话等功能。

消息记录

我们这里把用户发送的消息存储了起来,方便归档查询使用。

自动回复

公众号的一大功能就是自动回复,根据不同的事件类型回复不同的内容。

自动回复的类型分为关注事件、收到消息事件和点击了按钮事件。

可以根据不同的事件采用不同的回复动作,支持的动作有:

  • 文本回复
  • 图片回复
  • 语音回复
  • 音乐回复
  • 视频回复
  • 图文回复
  • 代码回复

其中代码回复是本模块特有的功能,支持用户通过伪代码的方式定制灵活可变的回复内容给公众号用户。

例如:

支持输入Python代码,在页面中灵活定制返回内容,不用再每次都修改源代码了。

客服消息

客服消息不支持测试公众号回复

本模块也同样支持客服对话,当公众号用户发起会话时,Odoo回创建一个该用户的对话频道,后台客服人员可以在Odoo中与客户进行对话。

高级配置

OAuth登录

当公司内部用户绑定了微信账号之后,就可以在登录界面通过扫码直接登录,无需输入账号密码。

模板消息

我们可以通过模板消息来实现业务通知。

演示系统地址: demo13-cn.mixoo.cn
账号 demo 密码 demo
演示公众号:

微信公众号测试接口每天有调用次数限制,如果失败,请第二天再试

1234…23
长腿叔叔

长腿叔叔

长腿叔叔的技术博客

229 日志
37 分类
41 标签
GitHub 淘宝
友情链接
  • BUG集散地
© 2021 长腿叔叔
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.2