工业控制领域,目前可以说三家分晋:传统的Windows桌面、精致的Android系统、开放的以树莓派IoT为代表的Linux平台,都可以很好的形成一体化闭环。
odoo是幸福的,居然可以同时桥接这三者,根据不同的场景取其精华组合最佳应用实践,期待未来鸿蒙杀入后会有更多的选择与无限的想象空间。
工业控制领域,目前可以说三家分晋:传统的Windows桌面、精致的Android系统、开放的以树莓派IoT为代表的Linux平台,都可以很好的形成一体化闭环。
odoo是幸福的,居然可以同时桥接这三者,根据不同的场景取其精华组合最佳应用实践,期待未来鸿蒙杀入后会有更多的选择与无限的想象空间。
OdooApp联系人、频道、活动、聊天等即时通讯应用基础设施
相关partner联系人快速筛选与多维搜索,详情资料手机电话号码直拨、网站浏览、电邮发送与私信
相关channel频道自助加入与群聊退出、私密群组邀请多人语音视频通话、白板会议共享
相关activity实时提醒活动流程待办事宜,点击动作查看相关模型视图进行记录集操作
相关chat聊天支持文本、语音、表情、图片、视频、文件、拍照、摄像、扫码等功能
odoo原生对于oa工作流与审批的支持有不少短板,也尝试过各种深度二次开发,这其中最难实现的是h5端天生有限的通知触达能力,当然这也是接下来odooapp必须要解决的问题,所以im模块在移动端的地位是非常重要的。
还有一种轻量方式就是直接集成进国民企业应用app里,比如企业微信、钉钉、飞书,天然的全方位实时消息通知,随时随地审批,可自定义审批模板,支持会签、或签、上级审批、条件审批,适应各种工作流程。
具体到应用层面又有两种模式:
1、odoo每个模型都可对应企微后台的多个审批模板,每条记录则可根据自定义条件状态由后台推送单据必要内容信息来发起审批流,当app端审批状态发生变化后,会以服务端异步消息通知的方式实时回调微信应用模块做相应的处理。
2、odoo每个模型都可对应企微后台的多个流程模板,每条记录则可根据app内嵌web前端由用户直接操作拉起流程申请界面,经过用户确认信息和流程来提交申请,当app端走完所有流程后回写相关审批结果信息以完成一次审批流程。
OdooApp基础设施IM原生WebSocket客户端重构完毕,信息流与业务流终将融为一体,未来ERP模块就跟公众号服务一样简单易用。
OdooMail模块Discuss讨论菜单虽然是排序第一的应用,但是多年以来一直被忽视,如今趁着原生移动端立项研发的春风和知名即时通讯国民应用的交互体验习惯凤凰涅槃,再加上各种来源的ChatBot智能AI机器人的加持,整套未来企业级应用操作系统的消息总线底层架构就这样应运而生了。
通用app产品诞生已经有三年了,依托开源odoo巨人的肩膀,前两年都在website架构无代码全网通领域深耕,去年以来则是在portal框架客户和供应商门户协同方向发展,而本月将正式开始迈入欧度主流的erp内部管理阶段。
强大odoo的web路由模式里,可以用低代码快速生成模块、视图、动作、菜单、权限等基础元素和相关的业务逻辑与报表模板,如果我们在原生app层面可以直接用jsonrpc协议对接这些基础设施接口来渲染出各种手机平台操作系统ui交互的话,那完全可以横空出世一套全新的移动端开发体系。
现在电视屏幕越做越大,且自带OS操作系统的智能电视一定会是未来的主流,传统各种BI数据大屏都是以有线连接或无线投屏模式输送给电视端,纯粹是当一个外接显示器的方式使用,完全没有用上现代Smart智能电视的特性。
odootv客户端就是用来解决这一个问题,无需外接键盘和鼠标,充分利用原生电视配套的遥控器来做操作控制和语音输入。可以想象,以后基于odoo设计的智能大屏,可以随时用遥控器来切换各种上下文视图,比如生产车间派工大屏上展示着当日的所有派工订单,操作者可以直接根据现场情况对屏幕上的信息进行排序、标记、就绪、完成等所见即所得操作。
odoo广州帽峰山基地挂牌,乡村振兴时代,新农村包围城市策略逐渐开始落地,欢迎来和我们一起依山傍水。。。
基地坐落于山脚萤泉谷养生文化邨,集山脉、森林、湖泊、山泉为一体,交通便利出则繁华入则桃园,是天然且理想的一线城市近郊研发与培训基地。
从疫情开始迭代了近三年的OdooApp极速版重大更新:全面支持欧度WebSite模块低代码配置底部自定义TabBar标签导航栏,突破平台原生只允许绑定页面访问无法直接Button操作,且最多只能支持到五个的数量限制,Icon则支持直接使用FontAwesome图标字体大小可随意调,也可以用网络图片来表达选中态和默认态,还支持右上角Badge信息,同时接入全局标准的默认主题色和自定义色,至此odoo移动端和小程序的本土化应用又上了一个大台阶。
b/s系统以前集成闭源硬件比较麻烦,当年做欧度地产管理系统时,需要在认购签约与财务收款环节快速刷卡验证客户二代身份证信息,根据当时的sdk能力,h5浏览器最佳的方案是模拟hid键盘输入,可以将读取到的所有文本信息字段用分隔符组合成长字符串输入到odoo前端window窗口并通过onkeydown事件获得并拆分成具体业务模型字段输出到编辑状态的表单视图上。
该方案优势是不用任何插件就可以兼容所有浏览器,缺点是焦点聚焦input输入框时前端还需要额外再跳转下一个分段输入处理,以及非文本字段如身份证照片二进制数据就无法获得,虽然理论上也可以通过编码成base64字符串一并处理,但是实际中会影响整个交互体验效率。
这些年由于IE浏览器的彻底没落,原来主流的ActiveX控件模式也跟着完全淘汰,各大商业硬件纷纷推出了HttpServer或WebSocket应用api接口替代,这不仅让桌面Web系统甚至移动App小程序都非常容易的通过网络来共享集成专业硬件服务。
odoo序列standard模式其实是pg数据库sequence特性的无代码应用,分别在sql层封装了db序列的创建、删除、修改、查询和预测下一号码的基础能力。然后再根据实施灵活性增强了前后缀、长度不足补0、每个日期范围使用不同序列的层级关系等扩展功能。
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
def _create_sequence(cr, seq_name, number_increment, number_next): """ Create a PostreSQL sequence. """ if number_increment == 0: raise UserError(_('Step must not be zero.')) sql = "CREATE SEQUENCE %s INCREMENT BY %%s START WITH %%s" % seq_name cr.execute(sql, (number_increment, number_next)) def _drop_sequences(cr, seq_names): """ Drop the PostreSQL sequences if they exist. """ names = sql.SQL(',').join(map(sql.Identifier, seq_names)) # RESTRICT is the default; it prevents dropping the sequence if an # object depends on it. cr.execute(sql.SQL("DROP SEQUENCE IF EXISTS {} RESTRICT").format(names)) def _alter_sequence(cr, seq_name, number_increment=None, number_next=None): """ Alter a PostreSQL sequence. """ if number_increment == 0: raise UserError(_("Step must not be zero.")) cr.execute("SELECT relname FROM pg_class WHERE relkind=%s AND relname=%s", ('S', seq_name)) if not cr.fetchone(): # sequence is not created yet, we're inside create() so ignore it, will be set later return statement = sql.SQL("ALTER SEQUENCE") + sql.Identifier(seq_name) params = [] if number_increment is not None: statement += sql.SQL("INCREMENT BY") + sql.Placeholder() params.append(number_increment) if number_next is not None: statement += sql.SQL("RESTART WITH") + sql.Placeholder() params.append(number_next) cr.execute(statement.join(' '), params) def _select_nextval(cr, seq_name): cr.execute("SELECT nextval(%s)", [seq_name]) return cr.fetchone() def _predict_nextval(self, seq_id): """Predict next value for PostgreSQL sequence without consuming it""" # Cannot use currval() as it requires prior call to nextval() seqname = 'ir_sequence_%s' % seq_id seqtable = sql.Identifier(seqname) query = sql.SQL("""SELECT last_value, (SELECT increment_by FROM pg_sequences WHERE sequencename = %s), is_called FROM {}""") params = [seqname] if self.env.cr._cnx.server_version < 100000: query = sql.SQL("SELECT last_value, increment_by, is_called FROM {}") params = [] self.env.cr.execute(query.format(seqtable), params) (last_value, increment_by, is_called) = self.env.cr.fetchone() if is_called: return last_value + increment_by # sequence has just been RESTARTed to return last_value next time return last_value |
odoo同时也额外用select for update nowait数据锁能力来互补实现了一套无间隔的no_gap模式,用来弥补纯sequence在欧度无处不在的事务应用中不会被连带回滚的特性,牺牲一些性能换取序列绝对连号用于某些特殊高要求的场景。如业财一体化应用中的会计分录凭证编号。
1 2 3 4 5 6 |
def _update_nogap(self, number_increment): number_next = self.number_next self._cr.execute("SELECT number_next FROM %s WHERE id=%%s FOR UPDATE NOWAIT" % self._table, [self.id]) self._cr.execute("UPDATE %s SET number_next=number_next+%%s WHERE id=%%s " % self._table, (number_increment, self.id)) self.invalidate_cache(['number_next'], [self.id]) return number_next |