Epicor REST help

Hello, I am trying to create a receipt entry with REST api using EpicorRest Helper. I’m getting a error and I can’t figure out why.

    int vendorNum = 156;
            int poNum = 544650;
            string packSlip = "123";

            var ReceiptDS = new Dictionary<string, object>
            {
                {"ds", new Dictionary<string, object>
                    {
                        {"RcvHead", null },
                        {"RcvHeadAttch", null },
                        {"RcvHeadTax", null },
                        {"RcvDtl", null },
                        {"RcvDtlAttch", null },
                        {"RcvDtlAttrValueSet", null },
                        {"RcvDtlTax", null },
                        {"RcvDuty", null },
                        {"RcvMisc", null },
                        {"RcvMiscTax", null },
                        {"LegalNumGenOpts", null },
                        {"PendingRcvDtl", null }
                    }
                },
            };

            var inputData = new Dictionary<string, object>
                {
                    {"ds", ReceiptDS},
                    {"vendorNum", vendorNum},
                    {"purPoint", ""},
                    {"poNum", poNum }
                };

            var getHead = EpicorRest.BoPost("ERP.BO.ReceiptSvc", "GetNewRcvHeadWithPONum", JsonConvert.SerializeObject(inputData));

            //var result = JsonConvert.DeserializeAnonymousType(response, new Dictionary<string, object>());
            print("Testing");
            if (getHead.IsErrorResponse)
            {
                //Trigger email
                Debug.Print(getHead.ResponseError);
            }
            else
            {

                Debug.Print("success");
                //var receiptDS = JsonConvert.DeserializeAnonymousType(getHead.ToString(), new Dictionary<string, object>());

                var newReceiptDtlDs = new Dictionary<string, object>
                {
                    {"ds", ReceiptDS},
                    {"vendorNum", vendorNum},
                    {"purPoint", ""},
                    {"packSlip", packSlip }
                };
                var getDtl = EpicorRest.BoPost("ERP.BO.ReciptSvc", "GetNewRcvDtl", JsonConvert.SerializeObject(newReceiptDtlDs));
                if (getDtl.IsErrorResponse)
                {
                    Debug.Print(getDtl.ResponseError);
                }
                else
                {
                    Debug.Print(getDtl.ResponseBody);
                    Debug.Print("Success");
                }
            }

and the error I am getting is this:

    Testing
    success
    Unexpected character encountered while parsing value: S. Path '', line 0, position 0.

it’s happening on this line: var getDtl = EpicorRest.BoPost("ERP.BO.ReciptSvc", "GetNewRcvDtl", JsonConvert.SerializeObject(newReceiptDtlDs));

dynamic dataSet = new { vendorNum = record.VendorNum, purPoint = record.PurPoint, packSlip = record.PackSlip, ds = new { } };
var RecDtlObj = EpicorRest.BoPost("Erp.BO.ReceiptSvc", "GetNewRcvDtl", dataSet);

This is how I made that call.

I don’t think you need to do that JsonConvert.SerializeObject stuff. The helper will do that for you. It just needs a dynamic object.

4 Likes

Very nice, you dumbed down my code by a lot :thinking:

Are you able to share more of this code? Like how you add the PO lines and send it back through

It’s pretty straight forward. You follow the trace and make the dynamic object just like I showed you. If you pull up swagger, you will see the parameters and the dataset required for the call.

Here’s another snippet that should get you the pattern for getting a new one then passing the dataset around the methods. I would recommend setting up a test system with postman so you can see the datasets.

var emptyds = new { ds = new { } };
var poDataSet = EpicorRest.BoPost("Erp.BO.POSvc", "GetNewPOHeader", emptyds);
dynamic DataSetIn = new { VendID = Settings.Default.VendorID, ds = poDataSet.ResponseData.parameters.ds };
poDataSet = EpicorRest.BoPost("Erp.BO.POSvc", "ChangeVendor", DataSetIn, callContextHeader);
1 Like

I have not used the EpicorRest Helper, so I can’t help you there, but here is some food for thought for your receipt process based on my past experience coding against the REST API for PO Receipts and the slow unraveling of requirements:

  • Erp.BO.ReceiptSvc/Receipts // Receipt Header
  • Erp.BO.ReceiptSvc/RcvDtls // for each Receipt Detail
  • consider/be mindful of UOMs
  • consider multiple releases, whether received complete, received to job or inventory, inspection needed
  • if you need to generate lots: Erp.BO.LotSelectUpdateSvc/GenerateNewLotNum
  • to update a heat number for specific lot based on user input: Erp.BO.LotSelectUpdateSvc/LotSelectUpdates

Yes this is what I got for the methods:

image

But I also gotta use this one to get the number of lines that the PO has. It’s all a big learning curve but with everyone’s help here and the already posted topics even though there is like 4 :frowning: are all helpful

image

If that is all done then how would you get the data out of responsedata since it returns a string? You would have to convert it no? I am trying to do something like this to add all the po lines:

dynamic searchPOS = EpicorRest.BoPost("Erp.BO.PORelSearchSvc", "GetRowsExcludeGlobal", new { whereClausePoRel = $"PONum = {po}", excludeGlobal = true, pageSize = 100, morePages = false, absolutePage = 0 }); ;

                    if (searchPOS.IsErrorResponse)
                    {
                        print(searchPOS.ResponseError);
                    }
                    else
                    {
                        var polines = searchPOS.ResponseData;
                        foreach(var result in polines)
                        {
                            var GetDtlPOLineInfo = EpicorRest.BoPost("Erp.BO.ReceiptSvc", "GetDtlPOLineInfo", new { vendorNum = vendor, purPoint = "", packSlip = ps, packLine = result.poLine, serialWarning = "" });

                        }
                    }

The object is created to it’s accessible as

searchPOS.RepsonseData.---whaevercomeesbackinJson

This is why you should try your calls in postman because you can see the structure of the data. The helper is de serializing it all for you.

ResponseData is not a JSON string is a dynamic object. Like @Banderson said you just addressed it like you would any other object.

ds = mrResponse.ResponseData.parameters.ds;
                        ds.MoveRequest[0].LotNumber = bd.Batch;
                        ds.MoveRequest[0].RequestQty = qtyToMove.ToString();
                        ds.MoveRequest[0].EmpId = string.Empty;
                        ds.MoveRequest[0].PCID = partBinRecord.PCID;

Just throwing it out there as an idea but based on the above, it looks like creating an Epicor Function to create the receipt would be far simpler and better. That way it could be structured from an external integration to be just the following steps:

  1. Call a custom MassReceiptPO Epicor Function
    ** Params: vendorNum, poNum, packSlip
    ** Return: receiptDS

  2. [OPTIONAL] Update receiptDS response quantities

  3. [OPTIONAL] Post updated receiptDS to either another function or standard BO REST API service

Minimizing the Epicor specific logic contained within external systems/integrations is almost always better and easier to maintain/support.

2 Likes

Oh wait so Epicor Functions do all of other BO’s to do something simple as creating a receipt? I do not have v2 currently so I don’t know much about the Epicor functions. I get this when trying to access the v2 help:

Epicor Functions can be used for lots of purposes. Including the creation of custom REST API services with simplified service signatures.

As they are developed and maintained within the Epicor ICE framework, similar to how BPMs are, they’re generally far easier to create and maintain as they are generally built with direct references to the standard, and custom, Business Object (BO) services. Therefore, features/functionality like intellisense works (well Epicor’s version anyway) and all of the BO method and data model details are inherently available.

Maybe try:

  1. https://%servername%/%instance%/apps/resthelp/#/select-efx/v2//
  2. Checking/fixing the certificate error shown in your screenshot
1 Like
    int vendor = 156;
            int po = 544650;
            string ps = "123";


            var dataSet = new { vendorNum = vendor, purPoint = "", poNum = po, ds = new { } };


            var getHead = EpicorRest.BoPost("ERP.BO.ReceiptSvc", "GetNewRcvHeadWithPONum", dataSet);


            if (getHead.IsErrorResponse)
            {
                Debug.Print(getHead.ResponseError);
               
            }
            else
            {
                var dataSet2 = new { vendorNum = vendor, purPoint = "", packSlip = ps, ds = getHead.ResponseData.parameters.ds };
                var getDtl = EpicorRest.BoPost("Erp.BO.ReceiptSvc", "GetNewRcvDtl", dataSet2);

                if (getDtl.IsErrorResponse)
                {
                    Debug.Print(getDtl.ResponseError);
                }
                else
                {


                    var GetDtlPOLineInfo = EpicorRest.BoPost("Erp.BO.ReceiptSvc", "GetDtlPOLineInfo", new { ds = getDtl.ResponseData.parameters.ds, vendorNum = vendor, purPoint = "", packSlip = ps, packLine = 0, poLine = 1, serialWarning = "" });
                    var test = EpicorRest.BoPost("Erp.BO.ReceiptSvc", "CheckDtlJobStatus", new { poNum = po, poLine = 1, poRelNum = 1, jobNum = "", poQuestion = "", questionMsg = "", warnMsg = "" });
                    if (test.IsErrorResponse)
                    {
                        print(test.ResponseError);
                    }
                    else
                    {
                        var test2 = EpicorRest.BoPost("Erp.BO.ReceiptSvc", "GetDtlPORelInfo", new { ds = getDtl.ResponseData.parameters.ds, vendorNum = vendor, purPoint = "", packSlip = ps, packLine = 0, poRelNum = 1 });
                        if (test2.IsErrorResponse)
                        {
                            print(test2.ResponseError);
                        }
                        else
                        {
                            print(test2.ResponseData);
                            var updateMaster = EpicorRest.BoPost("Erp.BO.ReceiptSvc", "UpdateMaster", new
                            {

                                //Method Parameters
                                ds = getDtl.ResponseData.parameters.ds,
                                RunChkLCAmtBeforeUpdate = true,
                                RunChkHdrBeforeUpdate = true,
                                ipVendorNum = 156,
                                ipPurPoint = "",
                                ipPackSlip = "123",
                                ipPackLine = 0,
                                cLCAmtMessage = "",
                                opUpliftWarnMsg = "",
                                opReceiptWarnMsg = "",
                                opArriveWarnMsg = "",
                                lRunChkDtl = true,
                                qMessageStr = "",
                                sMessageStr = "",
                                lcMessageStr = "",
                                pcMessageStr = "",
                                lRunChkDtlCompliance = true,
                                qDtlComplianceMsgStr = "",
                                lRunCheckCompliance = false,
                                lCompliant = false,
                                lRunPreUpdate = true,
                                lRequiresUserInput = false,
                                lRunCreatePartLot = false,
                                partNum = "CYT-856C07",
                                lotNum = "",
                                lOkToUpdate = true,
                                lUpdateWasRun = false,
                                wrnLines = "",
                            });


                            if (updateMaster.IsErrorResponse)
                            {
                                print(updateMaster.ResponseError);
                            }
                            else
                            {
                                print(updateMaster.ResponseBody);
                            }
                        }
                    }
                    
                }
            }

Cause this is what I am currently trying to do to at least just get one i’m walking down the trace and all the BO’s needing called.

What is the issue with this code you posted? Where does it break? how far does it get?

On test2 it is erroring out with A valid PO Release is required. but the poreleasenum is set to 1 statically. Also he was talking about making this a function and doing it that way so I feel like i’m doing it all wrong lol

Check the approval status. You’ll have to make sure that the PO isn’t approved to make changes.

Never mind, you’re making the receipt here. But double check the PO. Try with the BL tester to see if it’s working there too.

As far as functions go, both ways are valid ways that will work. Using a function keeps more of the processing on the server side and fully within epicor, so it could be considered better long term and performance wise. But you can march through the BO’s the same way with REST and the custom BO objects.

1 Like

My functions are not showing up on that rest help link.

and here is the help page:

Did you authorize that function to that company? On the security tab of the function.

Yes I have it authorized in the security tab. I even just authed all companies and still doesn’t show up for any of them.