odoo广州帽峰山基地挂牌,乡村振兴时代,新农村包围城市策略逐渐开始落地,欢迎来和我们一起依山傍水。。。
基地坐落于山脚萤泉谷养生文化邨,集山脉、森林、湖泊、山泉为一体,交通便利出则繁华入则桃园,是天然且理想的一线城市近郊研发与培训基地。
odoo广州帽峰山基地挂牌,乡村振兴时代,新农村包围城市策略逐渐开始落地,欢迎来和我们一起依山傍水。。。
基地坐落于山脚萤泉谷养生文化邨,集山脉、森林、湖泊、山泉为一体,交通便利出则繁华入则桃园,是天然且理想的一线城市近郊研发与培训基地。
如果说开源Odoo对标的是商业Sap的话,那欧度地产CRM和ERP就是源码交付可私有化部署可无代码定制实施的明源地产系统了。这能让那些有理想有抱负不内卷爱降维打击的甲方IT团队可以自主掌控一切,用OpenERP的集团化多公司开放基础架构实现适合且完全属于自己的房地产业财一体化系统。以上这个基于Python来连接一切的未来技术您准备好了吗?
ODOO列表视图序号后端解决方案
市场上很多是基于前端二次开发的,比如在列表头增加首列做为序号列,由于需要对列表的页面结构进行一些覆盖式的修改,导致不同版本之间的兼容性很差,且同类型模块之间也很容易冲突
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 |
''' author: i@renjie.me ''' class Sequence(models.AbstractModel): _name = 'renjie.sequence' _description = u'序号类' sequence = fields.Integer(u'序号', default=0) @api.model def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None): res = super(Sequence, self).search_read(domain, fields, offset, limit, order) if fields and "sequence" in fields: index = offset for rec in res: index += 1 rec["sequence"] = index return res @api.multi def read(self, fields=None, load='_classic_read'): res = super(Sequence, self).read(fields, load=load) if fields and "sequence" in fields: index = 0 for rec in res: index += 1 rec["sequence"] = index return res |
上述代码将虚拟序号的功能封装为标准抽象模型,适用于模块按需继承给视图直接使用即可
ODOO一对多对多混合字段模型
原生的One2many和Many2many已经可以解决大部分模型之间的关系映射,但在一些特殊场景下还是需要混合两者优点形成一个新的关系模型
如生产制造相关的部件与工序:一个部件是由多个工序所组成,而其工序之间还有调整顺序等要求;一个工序可以在多个部件里的不同位置所引用,也可以在同一个部件里不同顺序多次引用
标准的一对多模型桥接做映射可以自定义明细行顺序、独立参数。缺点是只能一个个添加,无法直接打开被桥接的模型进行操作
标准的多对多模型直接做映射可以批量选择、直接编辑。缺点是不可重复且没有顺序及独立参数,后续基本没有可扩展的灵活性
混合的一对多对多模型则是结合上述两者各自优势进行互补以达到可用性层面的最佳用户体验
ODOO12新起点
终于迎来了12,也是传说中期待的双数版本号
去年这个时候是11,虽也惊喜,但毕竟是python2到3的过渡期,有历史责任包袱的产品还是需要双兼容,于是那个版本是从7持续以来第一个被忽视的版本
所以我们现在的感觉就如同当年还在Windows Mobile的odoo78910,因为专注取舍错过了整个Symbian过渡时期,然后一口气飞奔进入iOS/Android双雄争霸时代
这比喻也许有些夸张,但对定位为开源企业级应用操作系统的我们来说,还是比较合适的:)
随着新产品线开始全面拥抱odoo12已经一个月有余,目前各种感觉都很顺畅,真不愧是一个全新的高起点定制系统:
框架模式方面基本成型,落后的能淘汰的都淘汰了,缺陷的能优化的也都优化了,结构上开始趋向稳定,预计未来大版本升级会容易很多
数据库方面过去成熟稳定的PostgreSQL9低版本已经无法胜任,久违的ORM开始慢慢的启用了一些新特性,长远发展看pg10+要成为标配
XML视图方面更新了更为严谨的rng约束,各种元素及属性将不可随意添加或缺失,有效的规范了页面结构的整体质量
CSS样式方面预处理器由Less改成了与整体框架更为融洽的Scss,核心的Bootstrap库大版本也从经典的3升级到了最新的4,感觉表现层这系列折腾起码要稳定几年了
Python方面彻底进入3时代,以后可能还有一些3.7前后版本的对应兼容库问题,但总算是完全告别2时代了
JavaScript方面基本已经将odoo9以来奠定的框架基础改造至极限,虽不能说很完美,但这一路优化过来已属不易,二次可开发的地方也越多越完善,将来Hack代码的机会不多了
其他应用层面的变化太多就不一一列举了,这里就重点说一个原来的document模块要废弃了,其在表单顶部工具栏的文档附件管理已被底部的mail消息日志功能所整合替代。长远看这也是一个很好的改进,只是可惜了原来依赖该基础模块的一大波第三方模块要被迫转型升级。考虑到要适应多年以来形成的附件操作习惯突然改变,同时我们自己也有直接间接依赖的几十号各类模块需要以空间换时间的兼容使用,特此立项从12版本开始上架维护用于替代的Document Sidebar模块,该应用市场链接https://apps.odoo.com/apps/modules/12.0/document_sidebar/
ODOO集成Excel xls和xlsx文件读写库
开源物以类聚角度LibreOffice Calc的ods格式是整合电子表格的最佳选择,但由于Excel尾大不掉还有着2003及之前xls格式和2007及之后xlsx格式的历史问题
存储:原生Binary字段是最合适的,但不管最终是文件存储还是数据库存储,程序上都是以base64库的encodestring编码和decodestring解码进行出入
前端:SheetJS库可以用来做附件和报表的预览应用及所见即所得数据的快速结构化导出
后端:xlrd+xlwt、XlsxWriter、OpenPyXL三大Python库各有所长又相互制衡反垄断,根据场景自由组合起来可以做各种类型复杂应用。StringIO和BytesIO可用于中转处理过程中的内存临时存储,避免了要生成和清理文件的麻烦
ODOO列表视图动态行选择字段
由于框架模型限定了选择字段是需要事先定义的,也就是选择下拉内容是确定且固定的,对应成列表视图则是每一行都是相同有限的选择
比如以上这种每一个物料都有自己的颜色和规格明细组合,这与odoo原生的产品变体刚好相反,后者是由产品属性及值自动生成所有排列组合的变体,前者则根据实际有限的明细反推出其属性集合
最后体现在一些行业应用中,比如鞋服箱包产品款式的BOM配色配码,其颜色尺码的表头是由产品基础属性组成动态列,而颜色规格的配置行则是根据所选物料的不同集合来动态限定范围选择列,间接实现每一行的Many2one和Selection字段都是独立定义
ODOO微信用户信息同步问题
Python使用http高级requests库来对接微信开放平台和公众平台非常干净利落,主要两个小问题需要注意一下:
1、用户昵称乱码
正常拉取用户信息所返回的内容编码不太友好,读取时乱码,需要显式设定lang和encoding
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
''' author: i@renjie.me ''' def get_sns_user_info(self, sns_token, openid): url = self.get_api_url("api") + "/sns/userinfo" params = dict( access_token = sns_token, openid = openid, lang = "en", ) res = requests.get(url, params=params) res.encoding = 'utf-8' ret = res.json() log = "get_sns_user_info: sns_token(%s) openid(%s) ret(%s)" % (sns_token, openid, ret) if "nickname" in ret: _logger.info(log) return ret else: _logger.error(log) |
2、用户头像时效
如只保存头像链接,若用户更换头像,原有链接将失效,需要用Binary字段存储一份图片二进制base64编码的副本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
''' author: i@renjie.me headimgurl = fields.Char(u'头像地址', readonly=True) head = fields.Binary(u"头像", attachment=True, readonly=True) ''' @api.multi def write(self, vals): if "headimgurl" in vals: if vals.get("headimgurl"): res = requests.get(vals["headimgurl"]) vals["head"] = res.content.encode('base64') else: vals["head"] = "" return super(UsersWechat, self).write(vals) |
ODOO表单视图动作编辑模式打开
表单有两种模式,分别是view浏览和edit编辑,一般通过动作跳转的默认都是浏览模式,需要额外点击编辑按扭切换成编辑模式,对一些要求快速编辑的场景来说显得有些多余
ODOO10截止目前的版本已经可以直接通过action flags对象来透传initial_mode参数,具体用法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
''' author: i@renjie.me ''' @api.multi def action_edit_partner(self): self.ensure_one() return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'res.partner', 'res_id': 1, 'context': self.env.context, 'flags': {'initial_mode': 'edit'}, } |
早期的版本虽然不支持,但是对于dict类型来说,也是可以通过return透传给前端拿到,只需额外添加一个通用的桥接口中转下即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * author: i@renjie.me */ var FormView = require('web.FormView'); FormView.include({ init : function(parent, dataset, views, flags, options){ var self = this; options = options || {}; if(flags && flags.initial_mode){ options.initial_mode = flags.initial_mode; } self._super.apply(self, arguments); } }); |
ODOO列表视图动态列
由于框架模型限定了字段是需要事先定义的,也就是个数是确定的,对应成列表视图仅仅是显示或者不显示这些字段而已
一些特殊的场景,比如工时单记录,根据项目在列表视图上一行行的填写工时就变得非常重复和多余,可惜官方没有改造列表视图使其获得通用能力,而是专门为之新开发了一个项目日期横排组件级视图,使得应用范围比较窄,多些固定列或者非时间动态列的情况下就无法直接使用了
一些行业的应用,比如服装行业的尺码横排,动态列一般是浮点型价格或者整型数量,而固定列除了颜色之外,一般还有批次、仓位、款式、订单等组合。前期也参考了工时单和Grid视图的优秀设计,甚至尝试基于其进行二次开发改良,但最终还是选择最普遍的原生列表视图为基础进行扩展,希望最终用户可以获得习惯一致的体验,同时也对经典视图深入发展多元化应用进行了一次实打实的尝试