跳转至

标准BOM清单拆分

功能描述

多级 BOM 导入用于存储标准格式的 BOM 清单,需根据标准格式的 BOM 清单层级,从最下级 BOM 开始创建工艺 BOM表单数据,逐层完成上级 BOM 的建立。

例如下图清单将拆分为三个 BOM 清单: 1. 层级编码 2 的02.FJ.CN.0004 附件包高配版 FJBG
2. 层级编码 1 的02.ZJ.0001 主机 12450H
3. 当前产品03.PC.0004 DIY主机 随客户定制

通过以下操作执行生成工艺 BOM功能:

菜单 > 生成工艺 BOM

执行生成工艺 BOM后,会在工艺 BOM表中创建对应的记录。

代码示例

多级 BOM 导入列表前端代码

读取当前选中的数据,并传递到后台执行逻辑。

/*
* $.ListView.GetSelected()获取选中的记录
* $.ListView.RefreshView()刷新列表
* $.ListView.Post()请求后台
* $.ListView.InitQueryItems()修改过滤条件
* $.ListView.RefreshView()刷新页面
* $.ListView.ActionPreDo() 按钮执行之前的事件
*/

$.ListView.ActionPreDo = function(actionCode){
    if(actionCode == "ConversionProcessBom"){
        //确认提示框
        $.IConfirm("BOM版本确认", "若BOM版本不填写,系统会自动生成版本号,点击确认后开始生成工艺BOM。", function( data ) {
            //data为点击按钮返回值,确认为true,取消为false
            if( data ) {
                //点击确认执行事件,传递当前选中的数据到后端执行生成工艺BOM
                $.ListView.Post(actionCode,{}, 
                function(data){
                    console.log(data);
                    if(data.ReturnData && data.ReturnData.ImportResult){
                        const successCount = data.ReturnData.ImportResult.SuccessCount;
                        const failCount = data.ReturnData.ImportResult.FailCount;
                        $.IShowTip("已完成生成工艺BOM,成功"+ successCount + "条,失败" + failCount + "条");
                    }
                    else if(data.Errors.length > 0){
                        $.IShowError(data.Errors[0]);
                    }
                    //刷新列表数据
                    $.ListView.RefreshView();
                });
            }
            if( !data ) {
                //点击取消执行事件
                return false;
            }
        });
        return false;
    }
};

多级 BOM 导入列表后端代码

  1. 接收前端的数据。
  2. 将数据转换为树结构。
  3. 后序遍历树,先生成子节点的工艺 BOM,再生成父节点的工艺 BOM。
  4. 提交并返回结果。

```csharp using System; using System.Collections.Generic; using System.Text; using H3;

public class D000261308214f17f0b44e0a19bf56bec838feb_ListViewController: H3.SmartForm.ListViewController { public D000261308214f17f0b44e0a19bf56bec838feb_ListViewController(H3.SmartForm.ListViewRequest request): base(request) { }

protected override void OnLoad(H3.SmartForm.LoadListViewResponse response)
{
    base.OnLoad(response);
}

protected override void OnSubmit(string actionName, H3.SmartForm.ListViewPostValue postValue, H3.SmartForm.SubmitListViewResponse response)
{
    if(actionName == "ConversionProcessBom") 
    {
        //获取前端传递过来的当前选中的行数据ID
        string[] selectedObjectIds = postValue.Data["ObjectIds"] as string[];
        //执行逻辑
        BOMImportor importor = new BOMImportor(this.Engine);
        BOMImportResult result = importor.Execute(selectedObjectIds);
        if(response.ReturnData == null) 
        {
            response.ReturnData = new Dictionary<string, object>();
        }
        //返回数据到前端
        response.ReturnData.Add("ImportResult", result.ToDictionary());
    }
    base.OnSubmit(actionName, postValue, response);
}

}

///

/// 多级BOM导入常量 ///

public class BOMImportConstants { public readonly static string Zizhi = "自制"; public readonly static string Weiwai = "委外";

public readonly static string SchemaCode = "D000261308214f17f0b44e0a19bf56bec838feb";

public readonly static string SchemaCode_BillOfMaterials = "D000261Billofmaterials";

public readonly static string FieldCode_ObjectId = BizObjectSchema.PropertyName_ObjectId;
public readonly static string FieldCode_Status = BizObjectSchema.PropertyName_Status;

/// <summary>
/// 产品名称
/// </summary>

public readonly static string FieldCode_MaterialID = "Productname";

public readonly static string FieldCode_BOMVersion = "bomversion";
public readonly static string FieldCode_ReviewResult = "Reviewresult";
public readonly static string FieldCode_GeneratedProcessBom = "IsGenerationProcessBom";

public readonly static string FieldCode_BillOfMaterials_HierarchicalCode = "Hierarchicalcoding";
public readonly static string FieldCode_BillOfMaterials_MaterialID = "Constituentmaterial";
public readonly static string FieldCode_BillOfMaterials_BOMVersion = "bomversion";
public readonly static string FieldCode_BillOfMaterials_Dosage = "dosage";
public readonly static string FieldCode_BillOfMaterials_AttritionRate = "Attritionrate";
//物料获取途径
public readonly static string FieldCode_BillOfMaterials_Accesstomaterials = "Accesstomaterials";

}

///

/// BOM表单常量 ///

public class BOMConstants { public readonly static string SchemaCode = "D000261BOM";

public readonly static string SchemaCode_BillOfMaterials = "D000261BOMDetail";

public readonly static string FieldCode_ObjectId = BizObjectSchema.PropertyName_ObjectId;

/// <summary>
/// 成品物料
/// </summary>

public readonly static string FieldCode_ProductId = "ProductId";
/// <summary>
/// BOM版本
/// </summary>

public readonly static string FieldCode_BOMVersion = "BOMVersion";

public readonly static string FieldCode_ProductCode = "ProductCode";
public readonly static string FieldCode_ProductName = "ProductName";
public readonly static string FieldCode_SpecificationModel = "SpecificationModel";
public readonly static string FieldCode_ProductUnitID = "ProductUnitID";
public readonly static string FieldCode_MaterialAcquisitionMethods = "MaterialAcquisitionMethods";
public readonly static string FieldCode_ProductType = "ProductType";
public readonly static string FieldCode_ReviewResults = "ReviewResults";

/// <summary>
/// 组成物料
/// </summary>

public readonly static string FieldCode_BillOfMaterials_ChildProductId = "ChildProductId";
/// <summary>
/// 组成物料BOM
/// </summary>

public readonly static string FieldCode_BillOfMaterials_NBom = "NBom";
/// <summary>
/// 用量系数
/// </summary>

public readonly static string FieldCode_BillOfMaterials_Dosage = "Dosage";
/// <summary>
/// 损耗率
/// </summary>

public readonly static string FieldCode_BillOfMaterials_LossRate = "LossRate";

public readonly static string FieldCode_BillOfMaterials_ProductCode = "ProductCode";
public readonly static string FieldCode_BillOfMaterials_ProductName = "ProductName";
public readonly static string FieldCode_BillOfMaterials_SpecificationModel = "SpecificationModel";
public readonly static string FieldCode_BillOfMaterials_ProductUnitID = "ProductUnitID";
public readonly static string FieldCode_BillOfMaterials_MAcqMethods = "MAcqMethods";
public readonly static string FieldCode_BillOfMaterials_MIssuanceMethod = "MIssuanceMethod";

}

///

/// 物料信息表单常量 ///

public class ProductsConstants { public readonly static string SchemaCode = "D000261Products";

public readonly static string FieldCode_ObjectId = BizObjectSchema.PropertyName_ObjectId;

/// <summary>
/// 物料编码
/// </summary>

public readonly static string FieldCode_MeterialCode = "MeterialCode";
/// <summary>
/// 物料名称
/// </summary>

public readonly static string FieldCode_ProductName = "ProductName";
/// <summary>
/// 规格型号
/// </summary>

public readonly static string FieldCode_SpecificationModel = "SpecificationModel";
/// <summary>
/// 基本单位
/// </summary>

public readonly static string FieldCode_ProductUnitID = "ProductUnitID";
/// <summary>
/// 物料获取途径
/// </summary>

public readonly static string FieldCode_MaterialAcquisitionMethods = "MaterialAcquisitionMethods";
/// <summary>
/// 发料方式
/// </summary>

public readonly static string FieldCode_MaterialIssuanceMethod = "MaterialIssuanceMethod";
public readonly static string FieldCode_ProductType = "ProductType";

}

///

/// 多级BOM导入项 ///

public class BOMImportItem { public BOMImportItem() { Details = new List(); } public string ObjectId; ///

/// 产品/物料Id ///

public string MaterialId;
public string BOMVersion;
/// <summary>
/// 评审结果
/// </summary>

public string ReviewResult;
/// <summary>
/// 是否已生成工艺BOM
/// </summary>

public bool GeneratedProcessBom;


/// <summary>
/// 组成清单
/// </summary>

public List<BOMImportDetailItem> Details;

public void UpdateGeneratedProcessBOM(IEngine engine, BizObjectSchema schema)
{
    if(schema == null || schema.SchemaCode != BOMImportConstants.SchemaCode)
    {
        return;
    }
    BizObject bo = new BizObject(engine.Organization, engine.BizObjectManager, schema, H3.Organization.User.SystemUserId);
    bo.ObjectId = this.ObjectId;
    bo.Load();
    bo[BOMImportConstants.FieldCode_GeneratedProcessBom] = "是";
    bo.Update();
}

}

//多级BOM导入的物料组成清单实体 public class BOMImportDetailItem { public string ObjectId; public string ParentObjectId; ///

/// 层级编码,示例:1;1.1,1.2,1.3;1.1.1,1.1.2 ///

public string HierarchicalCode;
public string MaterialId;
public string BOMVersion;
/// <summary>
/// 评审结果 继承主表的值
/// </summary>

public string ReviewResult;

/// <summary>
/// 用量
/// </summary>

public double Dosage;
/// <summary>
/// 损耗率
/// </summary>

public double AttritionRate;
//物料获取途径
public string Accesstomaterials;

public BOMImportTreeItem ToTreeItem()
{
    BOMImportTreeItem treeItem = new BOMImportTreeItem();
    treeItem.ObjectId = ObjectId;
    treeItem.HierarchicalCode = HierarchicalCode;
    treeItem.MaterialId = MaterialId;
    treeItem.BOMVersion = BOMVersion;
    treeItem.ReviewResult = ReviewResult;
    treeItem.Dosage = Dosage;
    treeItem.AttritionRate = AttritionRate;
    treeItem.Accesstomaterials = Accesstomaterials;
    return treeItem;
}

}

//多级BOM导入的物料组成清单树结构定义 public class BOMImportTreeItem { public BOMImportTreeItem() { Children = new List(); } ///

/// 主键 ///

public string ObjectId;

/// <summary>
/// 生成BOM后的主键,关联表单使用
/// 创建BOM后返回
/// </summary>

public string BOMId;
/// <summary>
/// 层级编码,示例:1;1.1,1.2,1.3;1.1.1,1.1.2
/// </summary>

public string HierarchicalCode;
/// <summary>
/// 组成物料
/// </summary>

public string MaterialId;
/// <summary>
/// BOM版本号
/// </summary>

public string BOMVersion;
/// <summary>
/// 评审结果
/// </summary>

public string ReviewResult;
/// <summary>
/// 是否已生成工艺BOM
/// </summary>

public bool GeneratedProcessBom;

/// <summary>
/// 用量
/// </summary>

public double Dosage;
/// <summary>
/// 损耗率
/// </summary>

public double AttritionRate;
public string Accesstomaterials;

//子节点
public List<BOMImportTreeItem> Children;

/// <summary>
/// 后序遍历生成BOM
/// 先执行子节点的生成BOM,再生成自己的BOM
/// </summary>

public void GenerateProcessBOM(IEngine engine, BizObjectSchema bomSchema, Dictionary < string, string > ancestorMaterialIdInfo)
{
    if(ancestorMaterialIdInfo == null) 
    {
        ancestorMaterialIdInfo = new Dictionary<string, string>();
    }
    if(!string.IsNullOrEmpty(this.MaterialId)) 
    {
        ancestorMaterialIdInfo.Add(MaterialId, BOMVersion);
    }
    foreach(BOMImportTreeItem child in Children)
    {
        //只包含直系祖先的物料信息+bom版本
        Dictionary < string, string > newAncestorMaterialIdInfo = new Dictionary<string, string>(ancestorMaterialIdInfo);
        if(!string.IsNullOrEmpty(child.BOMVersion) && newAncestorMaterialIdInfo.ContainsKey(child.MaterialId) && child.BOMVersion == newAncestorMaterialIdInfo[child.MaterialId]) 
        {
            BOMImportTreeItem tempTreeItem = child;
            throw new H3Exception("bom循环嵌套,请检查");
        }
        child.GenerateProcessBOM(engine, bomSchema, newAncestorMaterialIdInfo);
    }
    if(this.Children == null || this.Children.Count == 0) 
    {
        //叶子节点不需要生成工艺BOM
        return;
    }
    BOMItem bomItem = this.ToBOMItem();
    this.BOMId = bomItem.Submit(engine, bomSchema);
}

public BOMItem ToBOMItem()
{
    BOMItem item = new BOMItem();
    item.MaterialId = MaterialId;
    item.BOMVersion = BOMVersion;
    item.Reviewresult = this.ReviewResult;

    item.ObjectId = Guid.NewGuid().ToString();
    foreach(BOMImportTreeItem child in Children)
    {
        //这里只需要处理一层
        item.Details.Add(
            new BOMDetailItem
            {
                ObjectId = Guid.NewGuid().ToString(),
                MaterialId = child.MaterialId,
                BOMVersion = child.BOMVersion,
                Dosage = child.Dosage,
                AttritionRate = child.AttritionRate,
                BOMId = child.BOMId
            }
        );
    }
    return item;
}

}

//工艺BOM主表实体 public class BOMItem { public BOMItem() { ObjectId = Guid.NewGuid().ToString(); Details = new List(); } public string ObjectId; ///

/// 产品/物料Id ///

public string MaterialId;

/// <summary>
/// BOM版本
/// </summary>

public string BOMVersion;
//评审结果
public string Reviewresult;

public List<BOMDetailItem> Details;

/// <summary>
/// 构建版本号
/// </summary>

/// <returns></returns>

public string BuildBOMVersion()
{
    return "v1.0-" + DateTime.Now.ToString("yyyyMMdd-HHmmss");
}

/// <summary>
/// 返回主键Id
/// </summary>

/// <param name="engine"></param>

/// <returns></returns>

public string Submit(IEngine engine, BizObjectSchema bomSchema)
{
    //TODO 判断BOM中是否存在该物料,使用MaterialId和BOMVersion查询。
    if(bomSchema == null)
    {
        throw new H3Exception("BOM表单不存在:" + BOMConstants.SchemaCode);
    }
    string existBizObjectId = GetExistBizObjectId(engine);
    if(!string.IsNullOrEmpty(existBizObjectId))
    {
        return existBizObjectId;
    }
    else
    {
        if(string.IsNullOrEmpty(this.BOMVersion))
        {
            this.BOMVersion = BuildBOMVersion();
        }
    }
    BizObject bo = new BizObject(engine.Organization, engine.BizObjectManager, bomSchema, H3.Organization.User.SystemUserId);
    bo.ObjectId = this.ObjectId;
    bo[BOMConstants.FieldCode_ProductId] = this.MaterialId;

    bo[BOMConstants.FieldCode_BOMVersion] = this.BOMVersion;
    bo[BOMConstants.FieldCode_ReviewResults] = this.Reviewresult;
    bo.Status = BizObjectStatus.Effective;
    //模拟关联填充
    VirtualObject meterialVO = QueryUtility.GetVirtualObject(engine.BizObjectManager, MaterialId, ProductsConstants.SchemaCode);
    if(meterialVO != null)
    {
        bo[BOMConstants.FieldCode_ProductCode] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_MeterialCode);
        bo[BOMConstants.FieldCode_ProductName] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_ProductName);
        bo[BOMConstants.FieldCode_SpecificationModel] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_SpecificationModel);
        bo[BOMConstants.FieldCode_ProductUnitID] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_ProductUnitID);
        bo[BOMConstants.FieldCode_MaterialAcquisitionMethods] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_MaterialAcquisitionMethods);
        bo[BOMConstants.FieldCode_ProductType] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_ProductType);
    }
    if(Details == null)
    {
        bo.Submit();
        return bo.ObjectId;
    }
    BizObject[] childBizObjects = new BizObject[Details.Count];

    BizObjectSchema childSchema = bomSchema.GetChildSchema(BOMConstants.SchemaCode_BillOfMaterials);
    if(childSchema == null)
    {
        throw new H3Exception("BOM组成明细子表不存在:" + BOMConstants.SchemaCode_BillOfMaterials);
    }
    for(int i = 0;i < Details.Count; i++)
    {
        childBizObjects[i] = this.Details[i].ToBizObject(engine, childSchema);
    }
    bo[BOMConstants.SchemaCode_BillOfMaterials] = childBizObjects;
    bo.Submit();
    return bo.ObjectId;
}

public string GetExistBizObjectId(IEngine engine)
{
    if(string.IsNullOrEmpty(BOMVersion))
    {
        return string.Empty;
    }
    Filter filter = new Filter();
    And and = new And();
    and.Add(new ItemMatcher(BOMConstants.FieldCode_ProductId, H3.Data.ComparisonOperatorType.Equal, MaterialId));
    and.Add(new ItemMatcher(BOMConstants.FieldCode_BOMVersion, H3.Data.ComparisonOperatorType.Equal, BOMVersion));
    filter.Matcher = and;
    filter.FromRowNum = 0;
    filter.ToRowNum = 1;
    VirtualObject[] vos = QueryUtility.GetVirtualObjects(engine.BizObjectManager, filter, BOMConstants.SchemaCode);
    if(vos != null && vos.Length > 0)
    {
        return vos[0].ObjectId;
    }
    return string.Empty;
}

}

//工艺BOM 子表 BOM组成明细 public class BOMDetailItem { public BOMDetailItem() { ObjectId = Guid.NewGuid().ToString(); }

public string ObjectId;
/// <summary>
/// 物料Id
/// </summary>

public string MaterialId;
public string BOMVersion;

/// <summary>
/// BOM表的主键Id
/// </summary>

public string BOMId;

/// <summary>
/// 用量
/// </summary>

public double Dosage;
/// <summary>
/// 损耗率
/// </summary>

public double AttritionRate;

public BizObject ToBizObject(IEngine engine, BizObjectSchema schema)
{
    // 新增
    BizObject childBo = new BizObject(engine.Organization, engine.BizObjectManager, schema, User.SystemUserId, Company.InternalCompanyId)
    {
        ObjectId = ObjectId,
            CreatedTime = DateTime.Now,
            CreatedBy = User.SystemUserId
    };
    childBo[BOMConstants.FieldCode_BillOfMaterials_ChildProductId] = MaterialId;
    childBo[BOMConstants.FieldCode_BillOfMaterials_NBom] = BOMId;
    childBo[BOMConstants.FieldCode_BillOfMaterials_Dosage] = Dosage;
    childBo[BOMConstants.FieldCode_BillOfMaterials_LossRate] = AttritionRate;

    //模拟关联填充
    VirtualObject meterialVO = QueryUtility.GetVirtualObject(engine.BizObjectManager, MaterialId, ProductsConstants.SchemaCode);
    if(meterialVO != null)
    {
        childBo[BOMConstants.FieldCode_BillOfMaterials_ProductCode] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_MeterialCode);
        childBo[BOMConstants.FieldCode_BillOfMaterials_ProductName] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_ProductName);
        childBo[BOMConstants.FieldCode_BillOfMaterials_SpecificationModel] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_SpecificationModel);
        childBo[BOMConstants.FieldCode_BillOfMaterials_ProductUnitID] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_ProductUnitID);
        childBo[BOMConstants.FieldCode_BillOfMaterials_MAcqMethods] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_MaterialAcquisitionMethods);
        childBo[BOMConstants.FieldCode_BillOfMaterials_MIssuanceMethod] = meterialVO.GetPropertyValue(ProductsConstants.FieldCode_MaterialIssuanceMethod);
    }
    return childBo;
}

}

///

/// 通过多级BOM导入的一条完整数据 + 子表数据转为树结构 ///

public class BOMImportTreeBuilder { private const string RootHierarchicalCode = "root"; // 构建树的方法 public static BOMImportTreeItem BuildTree(BOMImportItem importItem) { BOMImportTreeItem rootItem = new BOMImportTreeItem(); if(importItem == null) { return rootItem; }

    rootItem.ObjectId = importItem.ObjectId;
    rootItem.MaterialId = importItem.MaterialId;
    rootItem.BOMVersion = importItem.BOMVersion;
    rootItem.ReviewResult = importItem.ReviewResult;
    rootItem.GeneratedProcessBom = importItem.GeneratedProcessBom;
    rootItem.HierarchicalCode = RootHierarchicalCode;
    rootItem.Accesstomaterials = BOMImportConstants.Zizhi;

    if(importItem.Details == null)
    {
        return rootItem;
    }
    // 用于快速查找节点的字典
    Dictionary < string, BOMImportTreeItem > detailItemDict = new Dictionary<string, BOMImportTreeItem>();
    detailItemDict.Add(RootHierarchicalCode, rootItem);
    foreach(BOMImportDetailItem detail in importItem.Details)
    {
        //如果有重复的层级编码,只保留第一个
        if(detailItemDict.ContainsKey(detail.HierarchicalCode))
        {
            continue;
        }
        detailItemDict.Add(detail.HierarchicalCode, detail.ToTreeItem());
    }

    foreach(BOMImportDetailItem detail in importItem.Details)
    {
        if(!detailItemDict.ContainsKey(detail.HierarchicalCode))
        {
            continue;
        }
        BOMImportTreeItem treeItem = detailItemDict[detail.HierarchicalCode];
        string parentCode = GetParentHierarchicalCodeCode(detail.HierarchicalCode);

        if(detailItemDict.ContainsKey(parentCode))
        {
            BOMImportTreeItem parent = detailItemDict[parentCode];
            parent.Children.Add(detailItemDict[detail.HierarchicalCode]);
        }
        else
        {
            // 如果父节点不存在,将该项添加到根节点
            throw new H3Exception( "编码" + treeItem.HierarchicalCode + "未查询到上级,请检查");
            //rootItem.Children.Add(treeItem);
        }
    }


    foreach(string key in detailItemDict.Keys) 
    {
        BOMImportTreeItem treeItem = detailItemDict[key];
        if(treeItem.Accesstomaterials != BOMImportConstants.Zizhi && treeItem.Accesstomaterials != BOMImportConstants.Weiwai) 
        {
            continue;
        }
        if(treeItem.Children == null || treeItem.Children.Count == 0) 
        {
            throw new H3Exception("自制、委外物料未设置组成物料,请检查");
        }
    }

    return rootItem;
}

/// <summary>
/// 获取父节点编码的方法
/// 1,2,3 => 父节点为主表
/// 1.1,1.2,1.3 => 父节点为1
/// 1.1.1,1.1.2, => 父节点为1.1
/// 1.1.1.1,1.1.1.2, => 父节点为1.1.1
/// </summary>

/// <param name="code"></param>

/// <returns></returns>

private static string GetParentHierarchicalCodeCode(string code)
{
    if(string.IsNullOrEmpty(code))
    {
        return RootHierarchicalCode;
    }
    int lastDotIndex = code.LastIndexOf('.');
    if(lastDotIndex == -1)
    {
        // 如果没有点号,父节点为根节点
        return RootHierarchicalCode;
    }
    return code.Substring(0, lastDotIndex);
}

}

//查询通用类 public class QueryUtility { public static VirtualObject[] GetVirtualObjects(IBizObjectManager bizObjectManager, H3.Data.Filter.Filter filter, string schemaCode) { int count = 0; Dictionary < string, BizObjectHeader > relatedHeaders = null; Dictionary < string, string > unitTable = null; VirtualObject[] vos = bizObjectManager.GetList(H3.Organization.User.SystemUserId, schemaCode, H3.DataModel.GetListScopeType.GlobalAll, filter, out count, false, out relatedHeaders, out unitTable); return vos; }

public static VirtualObject GetVirtualObject(IBizObjectManager bizObjectManager, string objectId, string schemaCode)
{
    H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter();
    filter.FromRowNum = 0;
    filter.ToRowNum = 1;
    And and = new And();
    and.Add(new ItemMatcher(BizObjectSchema.PropertyName_ObjectId, H3.Data.ComparisonOperatorType.Equal, objectId));
    filter.Matcher = and;
    int count = 0;
    Dictionary < string, BizObjectHeader > relatedHeaders = null;
    Dictionary < string, string > unitTable = null;
    VirtualObject[] vos = bizObjectManager.GetList(H3.Organization.User.SystemUserId,
        schemaCode,
        H3.DataModel.GetListScopeType.GlobalAll,
        filter,
        out count,
        false,
        out relatedHeaders,
        out unitTable);
    if(vos == null || vos.Length == 0)
    {
        return null;
    }
    return vos[0];
}

}

///

/// 执行标准BOM完整清单拆分为多个工艺BOM,返回执行结果 ///

public class BOMImportor { private readonly IEngine _engine; private readonly BizObjectSchema _BOMImportSchema; private readonly BizObjectSchema _BOMSchema; public BOMImportor(IEngine engine) { _engine = engine; _BOMImportSchema = _engine.BizObjectManager.GetPublishedSchema(BOMImportConstants.SchemaCode); _BOMSchema = _engine.BizObjectManager.GetPublishedSchema(BOMConstants.SchemaCode); }

private Filter BuildFilter(string[] selectedObjectIds, int pageSize)
{

    H3.Data.Filter.Filter filter = new H3.Data.Filter.Filter();
    And and = new And();
    if(selectedObjectIds != null && selectedObjectIds.Length > 0)
    {
        and.Add(new ItemMatcher(BizObjectSchema.PropertyName_ObjectId, H3.Data.ComparisonOperatorType.In, selectedObjectIds));
    }
    and.Add(new ItemMatcher(BOMImportConstants.FieldCode_GeneratedProcessBom, H3.Data.ComparisonOperatorType.NotEqual, "是"));
    and.Add(new ItemMatcher(BOMImportConstants.FieldCode_Status, H3.Data.ComparisonOperatorType.Equal, (int) BizObjectStatus.Effective));
    filter.Matcher = and;
    filter.FromRowNum = 0;
    filter.ToRowNum = pageSize;
    filter.SortByCollection = new SortBy[]
    {
        new SortBy(BizObjectSchema.PropertyName_CreatedTime, SortDirection.Ascending)
    };
    return filter;
}

public BOMImportResult Execute(string[] selectedObjectIds)
{
    const int pageSize = 100;
    BOMImportResult result = new BOMImportResult();
    Filter filter = BuildFilter(selectedObjectIds, pageSize);
    VirtualObject[] vos = QueryUtility.GetVirtualObjects(this._engine.BizObjectManager, filter, BOMImportConstants.SchemaCode);
    int length = vos == null ? 0 : vos.Length;
    ExecuteCore(vos, this._BOMSchema, result);
    while(length == pageSize)
    {
        vos = QueryUtility.GetVirtualObjects(this._engine.BizObjectManager, filter, BOMImportConstants.SchemaCode);
        if(vos == null)
        {
            break;
        }
        ExecuteCore(vos, this._BOMSchema, result);
        length = vos.Length;
    }
    if(result.GetTotal() == 1 && !string.IsNullOrEmpty(result.ErrorMessage)) 
    {
        //只有一条数据,直接返回错误信息;
        throw new H3Exception(result.ErrorMessage);
    }
    return result;
}

private void ExecuteCore(VirtualObject[] vos, BizObjectSchema bomSchema, BOMImportResult result)
{
    if(vos == null)
    {
        return;
    }
    foreach(VirtualObject vo in vos)
    {
        try
        {
            ExecuteOne(vo, bomSchema);
            result.SuccessCount++;
        }
        catch(Exception ex)
        {
            result.ErrorMessage = ex.Message;
            result.FailCount++;
        }
    }
}

private bool ExecuteOne(VirtualObject vo, BizObjectSchema bomSchema)
{
    BOMImportItem importItem = GetBOMImportItem(vo);
    if(importItem == null)
    {
        return false;
    }
    BOMImportTreeItem treeItem = BOMImportTreeBuilder.BuildTree(importItem);
    //生成工艺BOM
    Dictionary < string, string > ancestorMaterialIdInfo = new Dictionary<string, string>();
    treeItem.GenerateProcessBOM(_engine, bomSchema, ancestorMaterialIdInfo);
    //更新是否已生成工艺BOM
    importItem.UpdateGeneratedProcessBOM(_engine, _BOMImportSchema);
    return true;
}

private BOMImportItem GetBOMImportItem(VirtualObject vo)
{
    if(vo == null)
    {
        return null;
    }
    BOMImportItem importItem = new BOMImportItem();
    importItem.ObjectId = vo.GetPropertyValue(BizObjectSchema.PropertyName_ObjectId) + string.Empty;
    importItem.BOMVersion = vo.GetPropertyValue(BOMImportConstants.FieldCode_BOMVersion) + string.Empty;
    importItem.MaterialId = vo.GetPropertyValue(BOMImportConstants.FieldCode_MaterialID) + string.Empty;
    importItem.ReviewResult = vo.GetPropertyValue(BOMImportConstants.FieldCode_ReviewResult) + string.Empty;
    importItem.GeneratedProcessBom = vo.GetPropertyValue(BOMImportConstants.FieldCode_GeneratedProcessBom) + string.Empty == "1";

    VirtualObject[] childVos = vo.GetPropertyValue(BOMImportConstants.SchemaCode_BillOfMaterials) as VirtualObject[];
    if(childVos == null)
    {
        return importItem;
    }
    foreach(VirtualObject childVo in childVos)
    {
        BOMImportDetailItem detailItem = new BOMImportDetailItem();
        detailItem.MaterialId = childVo