I am able to create an invoice head, input the final price of the header, set invoice date, attach receipt lines, set invoice terms, and input Ref PO through the REST API using Python. I am having issues with setting the “Apply Date” and the “Due Date” through the API. My “Due Date” is supposed to be the Invoice Date + however many days the terms code calls for, but it seems like the APInvHed table doesn’t update that automatically when it is set through the API. As for the Apply Date, I am setting all the correct items in the payload (what the REST API Swagger calls for), and I believe I am calling the correct sequence of operations that the UI calls:
GetvalidEAD
OnChangeofApplyDateWithDateCheck
PreUpdate
UpdateMaster
The function runs without issue, but after UpdateMaster gets called, the date gets reset back to whatever date was set through the UI (or if I make the header through the API, it would be today’s date). I am also making sure that the date I set is valid because I can set the same date in the UI with no issue. I am not sure the best course of action for this. Perhaps there are some settings within Epicor that need to be set for my conditions? I can make my code available upon request.
Thanks.
The next suggestion, which is universally rejected by almost everyone at first, is to put the Kinetic business calls in an Epicor Function instead of in the REST client. This reduces the number of calls on the wire and keeps Epicor implementation details out of your client potentially reducing upgrading work. You get to set the shape of the data sent to and from the client. It does require C# knowledge though.
Thanks for the reply.
I just used the Inspect → Network took within Microsoft edge to see my API call sequence within the UI.
Also, I am pretty new to Epicor (my company just hired me less than a month ago to do some AI/automation stuff so I am learning this fresh) so could you spell that out a little more? Thanks!
Turns out you have to make a separate API call while you make the header. I found out a while ago to change the invoice amount you have to call “/ChangeInvoiceVendorAmt” and return the ds that comes out of that. What I found out now is that you have to do something similar for changing the apply date. You need to call “/OnChangeofApplyDateWithDateCheck” right after you make the header, then return the ds for that. By extension, to make other changes to the header you can call other functions, using the ds from the previous inputs. I used it for “/ChangeTermsCode” to also populate the due date. After all that, you call an update with your final ds to the master table.
In this example I have a vendor lookup so I can easily find the respective terms codes for my specific vendors.
Note my separate API calls after I create the header, but before I update the master table. Don’t forget to change the row to “U” for “update” for the table to accept your new dataset (invoice header information). This allows you to make whatever change you need to your header and have all the amounts (including the variance) to update automatically. The apply date needs to be in “YYYY-MM-DDT:00:00:00” format for Epicor to accept it. No C# necessary!
Sure, but a little history. When Epicor moved from Vantage 6 (VB6) to Vantage 8 (.NET), they completely separated the user interface from the business logic. They created business objects that the UI called, and all of the work was done at the server, in principle. The advantage was that one could have multiple UIs that used the same backend. There was a classic client, DMT (Data Management Tool), and the Business Object Tester. For most changes at the server, little or changes were required at the clients. At E10.2.500, Epicor introduced two styles of REST wrappers around the Business Objects: OData and RPC. The RPC versions mirror the current methods of the objects while another wrapper implemented an OData abstraction around these objects. The classic client (and RPC REST) is noisy over the wire. State has to be maintained by the client, there are a lot of calls made, and you had to make sure the client libraries matched the version on the server. If you’re on a local LAN, you don’t really notice it. But if you’re a remote user in the cloud or in another country, you do feel it. In Kinetic, everything is REST (mostly RPC). During this transition, we’re still making the same number of calls as the classic client, so it is a little noisier than it could be.
Later, Epicor released Epicor Functions. Functions give you a way to create your own DLLs, albeit limited, on the server in a supported way. Now one can create a REST endpoint with a signature that we control. This allows us to package up all the data in a shape we wish and make a single call. The function receives the input variables and can make all of the same business object calls at the server but at the .NET level. When finished, it can pass back multiple output variables of your design.
Let’s compare the two methods:
Most people, like yourself and even Epicor with the current Kinetic client, start with the tightly coupled, noisy client. They call each method over the wire. The client needs to know what the methods are and all of the parameters they require. If a new version breaks this flow, we need to update all clients that use this flow. If there are connectivity issues, the client needs to handle that.
With Functions, our tasks become more atomic. There are fewer calls with larger payloads. The function still needs to know the business flow, but for changes, we only have to fix the function and not chase down every integration.
In your example, you could have a function that only requires this signature:
InvoiceNum, PONum, InvoiceDate
The function knows the VendorNum from the PO, and the InvoiceDateSpecified will probably always be true in this situation.
Moreover, you could send a JSON object with an array of the above parameters and update all invoices in a single call and returning an array with the success of each invoice.
So, yes. You got it to work. But we earned some technical debt. The upgrades in the future will require more testing. Functions can be tested outside of each client, making upgrades easier. The person who does the client side also needs to know how Kinetic works. With functions, you could farm out that work if your Python/React/Angular dev doesn’t know or want to know about C# and Kinetic.
Functions bring us back to that clean separation goal of Vantage 8.