WebAPI--发货通知下推销售出库接口示例原创
金蝶云社区-湖南吴双得
湖南吴双得
10人赞赏了该文章 2,348次浏览 未经作者许可,禁止转载编辑于2022年09月30日 18:58:43
summary-icon摘要由AI智能服务提供

在ERP与WMS对接的业务场景中,需要实现WMS出入库时调用星空的源单下推出入库单据。提出了两种API接口方案:调用星空下推接口或带关联关系的保存接口。根据单据转换需求,详细说明了发货通知单下推销售出库单的三种调用层次:完整下推、按行下推并修改、及因批号等原因需拆分行并重建数据包的处理方法,包括请求JSON中的CustomParams参数的使用、单据转换插件的实现逻辑以及如何在下推后修改数据包。

业务场景:ERP与WMS对接时,常会需要实现在WMS出入库,同时调用星空的源单下推出入库单据。

解决方案:API接口有两种方案:一是调用星空下推接口,二是调用星空关联关系的保存接口。  
                 如果考虑以后有配置单据转换,从源单 带信息到 下游单据,则使用下推接口更合适。

发货通知下推销售出库下推接口的调用有三个层次:

一、按发货通知单信息完整下推,销售出库需要的字段都在发货通知单上保存,则调用标准的下推接口即可。

     即: 

{

    "Ids": "",

    "Numbers": [],

    "EntryIds": "",

    "RuleId": "",

    "TargetBillTypeId": "",

    "TargetOrgId": 0,

    "TargetFormId": "",

    "IsEnableDefaultRule": "false",

    "IsDraftWhenSaveFail": "false"

}


二、按发货通知单行下推,不存在拆分行,但需要在销售出库单上录入信息。

     则需要单据转换插件+请求JSON的 "CustomParams": 包。

{

    "Ids": "",

    "Numbers": [],

    "EntryIds":   "100279,100279",

    "RuleId": "DeliveryNotice-OutStock",

    "TargetBillTypeId":   "",

    "TargetOrgId": 0,

    "TargetFormId": "",

    "IsEnableDefaultRule":   "false",

    "IsDraftWhenSaveFail":   "false",

    "CustomParams": {

        "EtyIds":   ["100279","100279"],

        "QmEntryID": ["100173","100174"],

        "StockId":   ["100205","100205"],

        "Lot":   ["PC52121414XJKP201031","PC52121414XJKP201104"],

        "RealQty": [109,89]

    }

}

单据转换插件中实现取参数值,并修改下推后的数据包

取参数值 
            bool Entryid = this.Option.TryGetVariableValue<JSONArray>("EtyIds", out Ids);
            bool Stock = this.Option.TryGetVariableValue<JSONArray>("StockId", out custStock);
            bool Lot = this.Option.TryGetVariableValue<JSONArray>("Lot", out custLot);
            bool Qty = this.Option.TryGetVariableValue<JSONArray>("RealQty", out custQty);
            bool QmEntryID = this.Option.TryGetVariableValue<JSONArray>("QmEntryID", out qmEntryID);
取下推后数据包
    var entityRows = e.TargetExtendedDataEntities.FindByEntityKey("FEntity"); // 销售出库单单据体标识
    if (entityRows != null)
    {
        foreach (var entityRow in entityRows)
        {
            var entityId = (entityRow.DataEntity["FEntity_Link"] as DynamicObjectCollection)[0]["SId"]; //利用关系表获取分录当前行id
            int i = 0;
            foreach (var id in Ids)
            {
  
 修改数据包
    if (Qty)
    {
        entityRow.DataEntity["RealQty"] = custQty[i];                 //修改实收数量                                   
        entityRow.DataEntity["PriceUnitQty"] = custQty[i];            //修改计价数量
        entityRow.DataEntity["PriceBaseQty"] = custQty[i];            //修改计价基本数量
        //entityRow.DataEntity["ExtAuxUnitQty"] = custQty[i];          //修改实收数量(辅单位)数量
        entityRow.DataEntity["BaseunitQty"] = custQty[i];             //修改库存基本数量
        entityRow.DataEntity["SalUnitQty"] = custQty[i];        //修改销售数量
        entityRow.DataEntity["SalBaseQty"] = custQty[i];    //修改销售基本数量
    }


三、按发货通知单下推,但因批号、质检等原因,需要拆分行,且标准产品还因库存原因 拣货

      则需要对下推后数据包 重新按 "CustomParams": 包 组织行。

1、先循环标准产生生成的数据包,删除 拆分出来的行,确保每行发货通知单只一行

    for(int i = 0 ;i < entityDatas.Count;i++)
    {
        DynamicObject entityData = entityDatas[i];
        DynamicObjectCollection linkRows = linkEntity.DynamicProperty.GetValue(entityData) as DynamicObjectCollection;
        string strQmEntryID = entityData["QmEntryID"].ToString();
        string srcEntryId = "";
        foreach (var linkRow in linkRows)
        {
            if (QmEntryID)
            {
                srcEntryId = linkRow["SId"].ToString() + strQmEntryID;
            }
            else 
            {
                srcEntryId = linkRow["SId"].ToString();
            }
            if (!srcEntryId.IsNullOrEmptyOrWhiteSpace())
            {
                if (srcEntryIds.Contains(srcEntryId) || QmEntryID && !strqmEntryID.Contains(strQmEntryID))
                {
                    //需要删除的行
                    delEntrys.Add(i, entityData);
                }
                else
                {
                    srcEntryIds.Add(srcEntryId);
                }
            }
        }
    }


2、删行,并且清除实体

    //删除重复行,
    foreach (var delEntry in delEntrys)
    {
        //要删除单据数据包(FBillHead)的表体行 , 
        entityDatas.Remove(delEntry.Value);
        // 删除 表体数据包 的行
        e.TargetExtendedDataEntities.RemoveExtendedDataEntity("FEntity", delEntry.Key);
    }


3、根据"CustomParams": 包重建实体行,并修改数据

                //循环CustomParams数据包,以数据包行数为准
                foreach (var id in Ids)
                {
                    if (QmEntryID)
                    {
                        strQMandSRCEntryID = id.ToString() + qmEntryID[j].ToString();
                    }
                    else
                    {
                        strQMandSRCEntryID = id.ToString();
                    }
                    if (!srcEntryIds.Contains(strQMandSRCEntryID))
                    {
                        throw new Exception($"CustomParams数据包第{j + 1}行数据【"+ id.ToString() + "】找不到对应的上游单据");
                    }
                    //循环源单表体,找到正确的源单行
                    for (int i = 0; i < entityLength; i++)
                    {
                        ExtendedDataEntity entityRow = entityRows[i];
                        var entityId = (entityRow.DataEntity["FEntity_Link"] as DynamicObjectCollection)[0]["SId"]; //利用关系表获取分录当前行id
                        string strRowQMEntryID = entityRow["QmEntryID"].ToString();
                        if (id.Equals(entityId) && (qmEntryID == null || qmEntryID != null && qmEntryID[j].Equals(strRowQMEntryID)))
                        {
                            //本行已经更新过
                            if (isUpdateRows.ContainsKey(i))
                            {
                                //复制行,并更新
                                DynamicObject newRowObj = (DynamicObject)entityDatas[i].Clone(false, true);
                                //新增数据包行
                                entityDatas.Insert(entityDatas.Count, newRowObj);
                                //构建实体行
                                ExtendedDataEntity newEntityRow = new ExtendedDataEntity(newRowObj, entityRow.DataEntityIndex, entityDatas.Count);
                                UpdateEntity(e.TargetBusinessInfo, newEntityRow, Stock, long.Parse(custStock[j].ToString()), Lot, custLot[j].ToString(), Qty, decimal.Parse(custQty[j].ToString()), strOrgID);
                                newEntityRows.Add(newEntityRow);
                                break;
                            }
                            else
                            {
                                isUpdateRows.Add(i, entityDatas[i]);
                                UpdateEntity(e.TargetBusinessInfo, entityRow,Stock, long.Parse( custStock[j].ToString()), Lot,custLot[j].ToString(), Qty, decimal.Parse(custQty[j].ToString()), strOrgID);
                                BaseDataField stockFld = e.TargetBusinessInfo.GetField("FStockId") as BaseDataField;
                                break;
                            }
                        }
                    }
                    j++;
                }


最后重新添加 目标数据

    e.TargetExtendedDataEntities.AddExtendedDataEntities("FEntity", newEntityRows.ToArray());


这样的单据转换插件+带"CustomParams":包 的接口,就能适应好WMS的复杂应用


图标赞 10
10人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!