REST, Unmodified Row, Modified Row, Etc - External App

so when you say “pre” and “post” update. You mean I should duplicate the record object, leave one RowMod blank and set the other to U?

Edit (@klincecum): Split from related topic:

Yes, for the business object methods that require an unmodified row, and a modified row, that’s exactly right.

Ideally, the unmodified row, with rowmod “”, should be really the way it was retrieved, that way conditions and such in other bpms will work properly.

And…

Episode 4 Nbc GIF by Brooklyn Nine-Nine

2 Likes

Well Thank you for the welcome! :smiley: I’m glad to be here.

Im building an api that pulls data from one database, reformats it and submits to Kinetic. I’ve used the trace feature to match the necessary calls and formats, including the specific rowmod values depending on the method type. My calls go through successfully on Epicor’s rest help site, postman, and within my app. However, the records are not actually showing up in our tables.

I tried incrementing the laborhed and labordtl sequences, because I had a suspicion that the rows were being replaced instead of making a new one. However, that didnt make a difference. Now i’m wondering if maybe it has something to do with SysRevID and SysRowID. I know those fields are usually automatically incremented when records are created through MES, however I’m not sure how I should approach that in the API call.

I’m at the verrrrrrry end of building this app. I may have jinxed it this morning by saying I would probably finish it today :upside_down_face:

Any other ideas for me?

Have you added any logging to validate the information is coming through? If it were going through correctly you should have records.

I do have lots of logging. All status codes come back 200. I even tried to follow the steps in the Rest Help site. All of those came back successful also, yet there are no new rows.

So, you’re seeing evidence of your traffic in the server logs as well then?

Let’s see some code.

I have not checked our server logs. Only when using the MES to make the requests. I will check with my IT guys in the AM to see that.

I wasnt sure if it was appropriate to paste, but here is an upload
Program.cs (125.3 KB)

If you would prefer screenshots, let me know

Nice clean looking code you got there, unfortunately I don’t have time to wade through all that, though now I want to… :rofl:

Could you pull out a specific example either in your code, or in postman, something that is not behaving like you’d expect?

You can do a direct paste in a post like this:

Also, still going to help, but I should point you to a recent post I made, with my take on the subject…

Well… this is the last update to input nonwork labor hours into Erp.LaborHed and Erp.LaborDtl. I’ve modified the RowMods to be empty strings as I see in the trace log. All functions before this one as well as this one is successful. However, there is not a row appearing in either table.

I’m wondering if the issue is related to the laborHed/Dtl sequences or the sysrow/sysrev IDs. Maybe they aren’t being incremented properly and they are updating rows that already exist? I’m not sure how I would successfully increment the IDs or sequences without running the risk of replacing another row if this is the case.


        public static void FinalUpdateToLaborRecord(JObject completedRecord)
        {
            Console.WriteLine("");
            Console.WriteLine("Step 26:");
            Console.WriteLine("Modify RowMod for Update");

            // Define arrays to alter RowMod
            JArray laborhedArray = (JArray)completedRecord["ds"]?["LaborHed"];
            JArray laborDtlArray = (JArray)completedRecord["ds"]?["LaborDtl"];

            // Update RowMod property in laborhedArray
            if (laborhedArray != null && laborhedArray.Count > 0)
            {
                foreach (JObject obj in laborhedArray.Cast<JObject>())
                {
                    obj["RowMod"] = "";
                }
            }

            // Update RowMod property in laborDtlArray
            if (laborDtlArray != null && laborDtlArray.Count > 0)
            {

                foreach (JObject obj in laborDtlArray.Cast<JObject>())
                {
                    obj["RowMod"] = "";
                }
            }


            string strCompletedRecord = completedRecord.ToString();

            try
            {
                Console.WriteLine("");
                Console.WriteLine("Step 27:");
                Console.WriteLine("Update Labor Record Again");

                using var client = CreateEpicorClient();
                var request = new HttpRequestMessage(HttpMethod.Post, StaticConfigurationClass.GetKineticTestURL() + "/api/v1/Erp.BO.LaborSvc/Update");
                var content = new StringContent(strCompletedRecord, Encoding.UTF8, "application/json");
                // Assign content to the request
                request.Content = content;

                var response = client.SendAsync(request).Result;
                response.EnsureSuccessStatusCode();
                string UpdateLaborResponse = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine($"LaborHed Record successfully updated for employee {completedRecord["ds"]["LaborDtl"][0]["EmployeeNum"]}");

                ValidateChargeRate(completedRecord);

            }
            catch (HttpRequestException ex)
            {
                // Handle HTTP request exceptions
                Console.WriteLine($"****************************HTTP request failed updating employee {completedRecord["ds"]["LaborDtl"][0]["EmployeeNum"]}'s final Labor record in Kinetic: {ex.Message}****************************");
            }
            catch (Exception ex)
            {
                // Handle other exceptions
                Console.WriteLine($"****************************An error occurred getting employee {completedRecord["ds"]["LaborDtl"][0]["EmployeeNum"]}'s final Labor record in Kinetic: {ex.Message}****************************");
            }
        }

here is my console after completely running through one employee’s entry.


Step 1:
 Retrieve Approved Non Work Hours from UKG

Step 2:

Extract pertinent data

fromDate: 5/31/2024 12:00:00 AM, toDate: 5/31/2024 12:00:00 AM

Reformatting time to double integers

Step 3:

Retrieving employee profile from UKG

Step 4:

Retrieve employee schedule from UKG

Shift Length successfully parsed: 10 hrs

Default 1st shift hours used.

EmployeeID: 500

Employee Schedule: 07:00 - 11:00

2

Reformatting time to double integers

Step 5:

Identify last to make changes to request.

Non work hours approved by: Paul M. M*********

Step 6:

Assemble profiles with available data

Step 7:

Calculate the difference between base date and request dates

Base Date: 10/30/1953 12:00:00 AM

DateTime: 5/31/2024 7:00:00 AM

Difference in Minutes: 37125060

Step 7:

Calculate the difference between base date and request dates

Base Date: 10/30/1953 12:00:00 AM

DateTime: 5/31/2024 11:00:00 AM

Difference in Minutes: 37125300

Step 8:

Get Labor Record schema from Kinetic.

Step 9:

Assemble profiles according to Kinetic schema

Step 10:

Get Indirect Code

Step 11:

Calculate Labor costs

Step 12:

Create appropriate number of duplicate records for Kinetic

Step 13:

Dessemble row and revision IDs and assign to records appropriately

Step 14:

Create Empty arrays to match schema

Step 15:

Create and fill 'ds' object

Step 16:

Create and fill container object

Employee 500's LaborHdr successfully created
Step 18:
Update Laborhed Record

LaborHed Record successfully updated for employee 500
Step 19:
Get new Labor Detail row

Exception thrown: 'System.Net.Http.HttpRequestException' in System.Net.Http.dll
****************************HTTP request failed creating employee 500's LaborDtlHdr in Kinetic. Status: BadRequest, Error: {"HttpStatus":400,"ReasonPhrase":"REST API Exception","ErrorMessage":"A valid Date is required","ErrorType":"Ice.BLException","ErrorDetails":[{"Message":"A valid Date is required","Type":"Error","Program":"Erp.Services.BO.Labor.dll","Method":"validDate","ColumnNumber":25,"LineNumber":15907}],"CorrelationId":"497e9771-077d-40c4-93b4-3dd78b91bd12"}
Exception thrown: 'System.Net.Http.

Resubmitting employee 500's LaborDtl record in Kinetic with no header.

Employee 500's LaborDtl record has been successfully created


Step 20:
Remove unnecessary keys from outer container and alter RowMod

Step 21:
Retrieve default Labor type for employee

Employee 500's default Labor type successfully retrieved

Step 22:
remove unneccessary key from outer container

Step 23:
Change RowMod values

Step 24:
Change Labor Type
Labor type successfully changed for employee  500

Step 25:
Change Indirect Code
Employee  500's indirect code has been updated

Step 26:
Modify RowMod for Update

Step 27:
Update Labor Record Again
LaborHed Record successfully updated for employee 500

Step 28:
Modify RowMod

Step 29:
Validate Charge Rate
Charge Rate successfully Validated for employee  500's labor record

Step 30:
Add lWeeklyView key and value to record and remove rowMod values

Step 31:
Submit for approval
 Employee  500's labor record successfully submitted for approval

Labor Record successfully imported into Kinetic

RowMod should be either A or U depending on (A)dding a record or (U)pdating a record.

even though the input on the trace has the value as blank?

If you are adding a row it should be A.

additionally, when calling GetNewLaborDtlWithHdr or GetNewLaborHed is that where we’re adding the row(A)? then the updates would be U?

Normally blank is for an unchanged dataset, but AFAIK it will not add a record with a blank rowmod.

Correct.

The trace shows the value after the call if I recall correctly.

Now that’s a mouthfull.

Too Much Eating GIF by Hyper RPG