案例分享,自定义API进行采购收料单拆分入库
金蝶云社区-因扎吉
因扎吉
6人赞赏了该文章 1393次浏览 未经作者许可,禁止转载编辑于2018年05月21日 18:44:58

业务背景:仓管员手持移动设备,对采购收料进行实际入库,在手机APP、PDA等移动设备上选择收料单,录入仓库、仓位、数量等信息,移动设备回传数据到K\3 Cloud端,Cloud自动进行收料通知单下推采购入库单,并根据传过来的仓库、仓位、数量信息进行保存、拆分分录等操作。
下面讲解怎么自定义API处理将收料单的一条分录进行下推,并进行修改数据和拆分入库分录。
根据需求,我们定义好客户端(发送端/移动设备app端)需要发送的数据字段:
收料单分录id,入库数量,入库仓库,入库仓位。
因为一个收料单分录可能入到不同的仓库仓位,所以我们这里一个收料单分录要可以对应多个入库数量、入库仓库、仓位。

1.客户端发送数据
//客户端发送的json数据
            JObject json_root = new JObject();
            JArray json_entrys = new JArray();
            json_root.Add("entrys", json_entrys);

            //收料单分录id为100016
            JObject json_entry = new JObject();
            json_entry.Add("recEntryId", 100016);

            //第一个入库 为数量5,仓库编码为CK_001 ,仓位(id)为100005
            JArray json_entrys_details = new JArray();
            JObject json_entrys_detail_item = new JObject();
            json_entrys_detail_item.Add("qty",5);
            json_entrys_detail_item.Add("stocknumber", "CK_001");
            json_entrys_detail_item.Add("stockLocId", 100005);
            json_entrys_details.Add(json_entrys_detail_item);

           //第一个入库 为数量6,仓库编码为CK_001 ,仓位(id)为100006
            json_entrys_detail_item = new JObject();
            json_entrys_detail_item.Add("qty",6);
            json_entrys_detail_item.Add("stocknumber", "CK_001");
            json_entrys_detail_item.Add("stockLocId", 100006);
            json_entrys_details.Add(json_entrys_detail_item);

            json_entry.Add("details", json_entrys_details);

            json_entrys.Add(json_entry);


数据结构格式后结果:
1.png 这段json数据结构的意思是要将分录id为100016收料单分录进行下推入库单,并拆分出共两条入库单分录。其中一条仓库为CK_001仓位为100005,数量为5,另外一条仓库为CK_001仓位为100006,数量为6 。
2.服务端接收数据
因为cloud通版的api并不支持这类需求,因此需要自己写自定义接口来处理。
首先我们自己新建一个代码类库项目,引用相关的bos组件,然后新建一个接口,继承BOS相关的接口服务。
InstockService : KDBaseService
2.1在自定义接口中,我们搜集下传入的收料单分录id,然后调用下推服务进行下推采购入库单。
JObject jObj_Root = JObject.Parse(parameter);

            List<RecData> recData = new List<RecData>();
            List<long> srcEntryIds = new List<long>();
            JArray jArr_recDataEntrys = jObj_Root["entrys"] as JArray;

            foreach (JObject item in jArr_recDataEntrys)
            {
                long recEntryId = GetNullableLong(item, "recEntryId");
                var jObj_entry_detail = item["details"] as JArray;
                foreach (JObject detailItem in jObj_entry_detail)
                {
                    decimal qty = GetNullableDecimal(detailItem, "qty");
                    string stockNumber = Convert.ToString(detailItem["stocknumber"]);
                    long stockLocId = GetNullableLong(detailItem, "stockLocId");

                    recData.Add(new RecData()
                    {
                        RecEntryId = recEntryId,
                        Qty = qty,
                        StockNumber = stockNumber,
                        StockLocId = stockLocId
                    });
                }
                srcEntryIds.Add(recEntryId);
            }

            srcEntryIds = srcEntryIds.Distinct().ToList();

            //通版根据收料单下推入库单单,一行收料单只会生成一行入库单。需要在后面代码中处理关联复制行
            DynamicObject[] instockBillDataArr = PushRecBills(this.KDContext.Session.AppContext, srcEntryIds);
            if (instockBillDataArr == null || instockBillDataArr.Length <= 0)
            {
                throw new Exception("下推失败,请检查输入参数");
            }


2.2 调用下推后,下推接口会返回下推的入库单的数据包。因为通版的下推功能一行收料单分录只会生成一行入库单,所以我们要处理下推后的数据包,根据客户端发来的json数据的拆分行数量对入库单分录数据进行相当于关联复制行的拆分。即客户端要求拆多少条,我们就关联复制行多少次。
    //入库单单据
            foreach (var billItem in instockBillDataArr)
            {
                //入库单分录
                var entrys = billItem["InStockEntry"] as DynamicObjectCollection;
                List<Tuple<int, int>> linkCopyCount = new List<Tuple<int, int>>();
                int index = 0;
                foreach (var entryItem in entrys)
                {
                    DynamicObjectCollection links = entryItem["FInStockEntry_Link"] as DynamicObjectCollection;
                    //从link数据找到上游单据分录id,不考虑合并情况
                    long srcEntryId = Convert.ToInt64(links[0]["SID"]);

                    var recEntryData = jArr_recDataEntrys.Where(p => GetNullableLong((JObject)p, "recEntryId") == srcEntryId).FirstOrDefault();

                    var jObj_entry_detail = recEntryData["details"] as JArray;
                    int needCopyCount = jObj_entry_detail.Count - 1;

                    if (needCopyCount > 0)
                    {
                        linkCopyCount.Add(new Tuple<int, int>(index, needCopyCount));
                    }
                    index++;
                }

                //关联复制数据
                foreach (var tupleItem in linkCopyCount)
                {
                    int indexSeq = tupleItem.Item1;
                    DynamicObject needCopyDy = entrys[indexSeq];

                    for (int i = 0; i < tupleItem.Item2; i++)
                    {
                        DynamicObject copyedDy = (DynamicObject)Kingdee.BOS.Orm.OrmUtils.Clone(needCopyDy);
                        copyedDy["seq"] = entrys.Count + 1;

                        entrys.Add(copyedDy);
                    }
                }

            }


2.3 暂存下拆分分录后的入库单数据包

   //暂存采购入库单,暂存后才会有内码
            IOperationResult draftResult = DraftInstockData(instockBillDataArr);


//private IOperationResult DraftInstockData(DynamicObject[] instockBillDataArr)
        //{
        //    //暂存目标单数据
        //    OperateOption option = OperateOption.Create();
        //    //option.SetIgnoreWarning(false);
        //    FormMetadata formMetaData = (FormMetadata)MetaDataServiceHelper.Load(this.KDContext.Session.AppContext, InstockBillFormId);
        //    return BusinessDataServiceHelper.Draft(this.KDContext.Session.AppContext, formMetaData.BusinessInfo, instockBillDataArr, option);
        //}




2.4 调用通版的入库单保存api对入库单分录进行修改(修改数量、仓库、仓位)
if (draftResult.IsSuccess == false)
            {
                throw new Exception("暂存采购入库单失败!");
            }

            List<InstockData> lingTracks = new List<InstockData>();
            foreach (var billItem in draftResult.SuccessDataEnity)
            {
                long instockBillId = Convert.ToInt64(billItem["id"]);
                var entrys = billItem["InStockEntry"] as DynamicObjectCollection;
                foreach (var entryItem in entrys)
                {
                    long instockEntryId = Convert.ToInt64(entryItem["id"]);
                    DynamicObjectCollection links = entryItem["FInStockEntry_Link"] as DynamicObjectCollection;
                    foreach (var linkItem in links)
                    {
                        long srcEntryId = Convert.ToInt64(linkItem["SID"]);

                        lingTracks.Add(new InstockData()
                        {
                            InstockBillId = instockBillId,
                            InstockEntryId = instockEntryId,
                            RecEntryId = srcEntryId,
                        });
                    }
                }
            }

            //根据入库单fid分组,有可能生成多个单据
            var billGroupDatas = lingTracks.GroupBy(p => p.InstockBillId);

            foreach (var item in billGroupDatas)
            {
                JObject oJobj_Bill = new JObject();
                JObject oJobj_Model = new JObject();
                JArray entrys = new JArray();

                oJobj_Model.Add("FID", item.Key);

                foreach (var subItem in item)
                {
                    var recDetalItem = recData.Where(p => p.RecEntryId == subItem.RecEntryId && p.IsUsed == false).FirstOrDefault();
                    if (recDetalItem == null)
                    {
                        continue;
                    }

                    recDetalItem.IsUsed = true;

                    JObject entryRow = new JObject();
                    entryRow.Add("FEntryId", subItem.InstockEntryId);
                    entryRow.Add("FRealQty", recDetalItem.Qty);

                    JObject baseData = new JObject();
                    baseData.Add("FNumber", recDetalItem.StockNumber);
                    entryRow.Add("FStockId", baseData);

                    entryRow.Add("FStockLocId", recDetalItem.StockLocId);

                    entrys.Add(entryRow);
                }

                if (entrys.Count > 0)
                {
                    oJobj_Model.Add("FInStockEntry", entrys);

                    oJobj_Bill.Add("Model", oJobj_Model);

                    string jsonStr = oJobj_Bill.ToString();
                    object saveResult = WebApiServiceCall.Save(this.KDContext.Session.AppContext, InstockBillFormId, jsonStr);
                }
            }

自此,全部处理就完成了。

赞 6