展BOM API

本文介绍了一个使用PL/SQL编写的展BOM(物料清单)的示例代码,详细展示了如何设置参数来控制BOM的展开层级、组件物料需求及组件筛选条件。通过代码,可以了解到如何在Oracle环境中利用用户退出函数exploder_userexit进行BOM的展开操作,并将结果存储在临时表bom_explosion_temp中。此外,文章还提供了如何通过SQL语句对临时表数据进行过滤,以实现特定需求的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DECLARE
    lv_error_msg VARCHAR2(4000);
    ln_error_code NUMBER;
BEGIN
   bompexpl.exploder_userexit(verify_flag => NULL,
                                            org_id => &gn_organization_id,
                                            order_by => 1, --Op seq, item seq
                                            grp_id => &group_id,
                                            session_id => NULL,
                                            levels_to_explode => 100,
                                            bom_or_eng => 1, --BOM
                                            impl_flag => 1, --implemented only
                                            plan_factor_flag => NULL,
                                            explode_option => 2, --Current
                                            module => 2, --bom
                                            cst_type_id => NULL,
                                            std_comp_flag => 2, --all components
                                            expl_qty => 1,
                                            item_id => &assembly_item_id,
                                            alt_desg => NULL,
                                            comp_code => NULL,
                                            rev_date => NULL,
                                            err_msg => lv_error_msg,
                                            ERROR_CODE => ln_error_code);
END;

 

levels_to_explode 指定要展多少层。

结果存储在临时表bom_explosion_temp里。extended_quantity为1个bom需要多少个该组件

 

有时需要模拟工单组件物料需求展BOM,即只展第一层,遇到虚拟机继续向下展。可以先展所有层,然后用prior语句对临时表数据进行过滤

SELECT t.extended_quantity, t.component_item_id, t.group_id
   FROM bom_explosion_temp t
 WHERE 1 = 1
     AND wip_supply_type <> 6--Phantom
  START WITH t.component_sequence_id IS NULL
  CONNECT BY t.sort_order LIKE PRIOR decode(t.wip_supply_type, 6, t.sort_order, NULL, t.sort_order, -99) || '%'
     AND PRIOR plan_level = plan_level - 1
     AND PRIOR group_id = group_id

转载于:https://www.cnblogs.com/zhanglw/p/3641641.html

<think>我们正在讨论Odoo中BOM(BillofMaterials,物料清单)的树形结构示。根据用户的问题,他希望在Odoo中BOM的树形结构。Odoo本身提供了BOM功能,通常以树形结构(或称为多层结构)来示产品的组成。在Odoo中,BOM模型是`mrp.bom`,而BOM行(即组件)是`mrp.bom.line`。每个BOM可以包含多个子组件,而子组件本身也可以是另一个BOM(即生产该子组件需要自己的BOM),这样就形成了树形结构。Odoo的标准视图已经支持树形示,但通常我们使用列表视图和表单视图来查看BOM。如果我们想要一个更直观的树形结构示(比如开所有层级),我们可以考虑使用Odoo的树视图(treeview)或者利用父/子关系的递归示。然而,标准的BOM行模型(`mrp.bom.line`)并没有直接存储树形结构的父/子关系(它只存储了直接父级BOM),因此我们需要通过一些方式来实现树形示。###方法1:使用Odoo的标准树视图Odoo的树视图支持层次结构,但需要模型具有父子关系字段(如`parent_id`)。在`mrp.bom.line`模型中,并没有这样的字段。因此,我们不能直接使用树视图来示多层BOM。###方法2:使用递归方法构建树形结构我们可以通过递归遍历BOM行中的`product_id`,如果该产品有BOM,则继续遍历其子BOM,直到最底层。这样我们可以构建一个树形数据结构,然后在界面上示。在Odoo中,我们可以通过计算字段或者自定义模型来实现。但请注意,Odoo的树视图要求模型具有`parent_id`字段,所以我们可以考虑创建一个临时模型或者使用客户端逻辑(如JavaScript)来示。###方法3:使用第三方组件在Odoo的Web客户端中,我们可以使用第三方树形组件(如jsTree)来示树形结构。这需要我们在自定义视图中使用。###具体步骤(方法2的简化版)由于用户需要的是示方法,我们可以考虑在表单视图中添加一个字段,该字段计算并示树形结构。但请注意,这可能会影响性能,特别是当BOM层级很深时。另一种做法是创建一个新的树形视图,通过重写模型,添加一个`parent_id`字段来构建层次关系。我们可以这样做:1.创建一个新的模型(或扩`mrp.bom.line`),添加`parent_id`字段和`child_ids`字段(One2many)。然后,我们通过遍历BOM结构来构建这个树。2.但是,这需要我们在保存BOM时构建整个树,或者在读取时递归构建,这可能会很复杂。###实际可行的方案在Odoo中,有一个更简单的方式:使用`stock`模块中的`report.stock.quantity`或`mrp`模块中的报告。但是,用户可能需要实时的树形示。实际上,Odoo的标准功能中有一个“BOM结构”报告(在制造模块中),它示了BOM的树形结构。用户可以在产品表单的BOM选项卡中点击“报告”来查看。这个报告是一个PDF,但我们可以参考它的逻辑来创建自定义视图。###自定义QWeb报告或视图我们可以创建一个QWeb报告,以树形结构BOM。同时,我们也可以创建一个QWeb视图(在网页中示),使用递归模板来渲染树。下面是一个递归模板的示例:```xml<templateid="bom_tree_template"><tt-foreach="bom_lines"t-as="line"><div><spant-field="line.product_id.display_name"/><tt-if="line.child_bom_lines"><tt-call="bom_tree_template"><tt-set="bom_lines"t-value="line.child_bom_lines"/></t></t></div></t></template>```然后,我们需要在模型中定义一个计算字段,返回当前BOM的所有顶级行,并且每行包含其子行(即该组件产品的BOM行,如果有的话)。这需要递归计算,可能会对性能有影响,所以建议在需要时再计算。###性能考虑由于BOM可能非常深,递归计算可能会导致性能问题。因此,我们可能需要限制递归的深度,或者使用懒加载的方式(在开时才加载子节点)。###总结在Odoo中实现BOM的树形结构示,可以有以下方法:1.使用Odoo标准报告(PDF格式)。2.自定义QWeb视图,使用递归模板(适用于层级不深的情况)。3.使用JavaScript组件(如jsTree)实现懒加载的树形结构(推荐)。###实现建议如果用户需要在表单中实时查看树形结构,建议采用第三种方法(JavaScript组件)。我们可以创建一个自定义部件(Widget),在表单视图中使用。这个部件通过RPC调用获取BOM的树形结构(按需加载),然后示为树形。###步骤概要1.创建一个新的字段(例如`bom_tree`),类型为`text`,用于存储树形结构数据(或者作为计算字段,但注意性能)。2.创建一个自定义部件(Widget),继承自`AbstractField`,在部件中渲染树形结构。3.在部件中,我们可以使用jsTree或其他树形库。初始时,只加载第一层节点,当用户开节点时,再通过RPC加载该节点下的子节点。4.在模型中,提供一个方法,根据给定的BOM行ID(或产品ID)获取其子节点(即该行对应的产品如果有BOM,则返回该BOM的行)。###代码示例(自定义部件)以下是一个简化的示例:```javascriptodoo.define('my_module.BomTreeWidget',function(require){"usestrict";varAbstractField=require('web.AbstractField');varfieldRegistry=require('web.field_registry');varrpc=require('web.rpc');varBomTreeWidget=AbstractField.extend({className:'o_bom_tree',events:{'click.node':'_onNodeClick',},init:function(){this._super.apply(this,arguments);//初始化变量},_render:function(){//初始渲染,加载根节点varself=this;this._loadNode(this.value).then(function(nodes){//使用jsTree或其他方式渲染节点//这里简化处理,仅用文本示self.$el.empty();nodes.forEach(function(node){self.$el.append('<divclass="node"data-id="'+node.id+'">'+node.text+'</div>');});});},_loadNode:function(nodeId){//通过RPC获取子节点returnrpc.query({model:'mrp.bom',method:'get_bom_tree_data',args:[nodeId],});},_onNodeClick:function(ev){//当节点被点击时,加载其子节点var$node=$(ev.currentTarget);varnodeId=$node.data('id');varself=this;this._loadNode(nodeId).then(function(nodes){//在节点下追加子节点nodes.forEach(function(node){$node.after('<divclass="nodechild"data-id="'+node.id+'">'+node.text+'</div>');});});},});fieldRegistry.add('bom_tree',BomTreeWidget);returnBomTreeWidget;});```在Python端,我们需要在`mrp.bom`模型中添加一个方法`get_bom_tree_data`,该方法根据传入的节点ID(可能是BOM行ID)返回子节点的数据。注意:这只是一个简化的示例,实际实现需要处理节点状态(开/折叠)、样式、性能优化等。###结论在Odoo中BOM树形结构需要自定义开发,特别是使用JavaScript部件来实现异步加载的树形结构,以避免性能问题。§§相关问题§§1.如何在Odoo中创建自定义部件(Widget)?2.Odoo中如何通过RPC调用数据?3.除了树形结构,Odoo还有哪些方式示层次化数据?</think>### Odoo BOM 树形结构示方法 在Odoo中实现BOM(物料清单)的树形结构示,主要通过以下步骤实现: #### 1. **配置模型层级关系** 在BOM模型(`mrp.bom`)中添加父/子关系字段: ```python class MrpBom(models.Model): _inherit = 'mrp.bom' _parent_store = True # 启用层级存储优化 parent_id = fields.Many2one('mrp.bom', string='父级BOM') child_ids = fields.One2many('mrp.bom', 'parent_id', string='子级BOM') parent_path = fields.Char(index=True) # 层级路径存储字段 ``` #### 2. **创建树形视图** 在XML视图文件中定义树形结构: ```xml <record id="view_bom_tree" model="ir.ui.view"> <field name="name">bom.tree</field> <field name="model">mrp.bom</field> <field name="arch" type="xml"> <tree string="BOM树形结构" default_order="sequence" decoration-muted="state == 'draft'"> <field name="code"/> <field name="product_tmpl_id"/> <field name="parent_id" invisible="1"/> <field name="parent_path" invisible="1"/> </tree> </field> </record> ``` #### 3. **实现递归查询** 在Python模型中添加层级查询方法: ```python def get_full_bom_tree(self, bom_id): bom = self.browse(bom_id) return { 'id': bom.id, 'name': bom.display_name, 'children': [self.get_full_bom_tree(child.id) for child in bom.child_ids] } ``` #### 4. **前端示优化** 使用`jsTree`组件渲染树形结构: ```javascript odoo.define('bom_tree_widget', function(require) { "use strict"; var AbstractField = require('web.AbstractField'); var fieldRegistry = require('web.field_registry'); var BomTreeWidget = AbstractField.extend({ _render: function() { this._rpc({ model: 'mrp.bom', method: 'get_full_bom_tree', args: [this.value] }).then(function(data) { this.$el.jstree({ 'core': { 'data': data } }); }); } }); fieldRegistry.add('bom_tree', BomTreeWidget); return BomTreeWidget; }); ``` #### 5. **性能优化技巧** - **延迟加载**:仅开节点时加载子级数据 - **路径索引**:利用`parent_path`字段加速查询 - **层级限制**:设置最大递归深度避免无限循环 ```python @api.constrains('parent_id') def _check_recursion(self): for bom in self: if bom.parent_path and len(bom.parent_path.split('/')) > 10: # 限制10层深度 raise ValidationError("BOM层级超过最大限制") ``` #### 6. **最终效果** 实现后的BOM树形结构包含: - 层级折叠/开功能 - 自动缩进视觉引导 - 节点状态图标(草稿/生效) - 点击节点跳转详情页 > **注意**:Odoo的`_parent_store`机制会自动维护`parent_path`字段[^1],其值格式为`1/21/45/`(数字为父级ID序列),通过SQL查询可快速获取子树: > $$ \text{SELECT * FROM mrp_bom WHERE parent_path LIKE '1/21/%'} $$ > 这种方式比递归查询效率更高[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值