Transaction API tabs with locked fields for primary key

I’m attempting to write a Transaction API call into a tightly integrated client’s Epicor system that will receive POs utilizing our data from a PO receipt JSON our system generates upon confirmation.

The issue we’re running into is that the item_id field on the PO receipt screen is locked for inventory updates. Only the quantity field can be filled in (which is true on the standard PO Receiving screen also in the P21 UI.

If you feed it multiple “Rows”, they don’t seem to apply to different rows in the UI - as if you’d press the down arrow after you enter a quantity. E.g. There are 4 lines on the PO Item A,B,C,D with quantities 310, 103, 206, 403. The error coming back that we get at the end, after submitting the transaction set, is that the quantity entered is greater than the quantity for the item - I believe implying 403 > 310 - but there may be another reason for the error?

Hoping someone knows how to force the quantity to correspond to the correct item. I noticed in the transaction template definition there is a “ParentText”: “Items” - but I cannot find an example of how to utilize this in the transaction.

Code in C# (only relevant bits included… please ask if more context is needed):

DataElement lotQtyElement = new DataElement();
lotQtyElement.Name = "TABPAGE_LOT_BIN_XREF.tabpage_lot_bin_xref";
lotQtyElement.Type = DataElementType.Form;
lotQtyElement.Keys = new List<string> { "lot_cd", "item_id" };

DataElement itemQtyElement = new DataElement();
itemQtyElement.Name = "TABPAGE_17.tp_17_dw_17";
itemQtyElement.Type = DataElementType.Form;
itemQtyElement.Keys = new List<string> { "item_id"};

// "receipt" below refers to the JSON object from the third party warehousing system confirming a receipt.

// This pulls back the existing PO receipt inventory lines in the correct order so we can match up our fed in quantities in the right order
ServiceDefinition purchaseOrderReceiptServiceDef = transactionRestClient.GetServiceDefinition("PurchaseOrderReceipt");
TransactionStateRequest transactionStateRequest = new TransactionStateRequest();
transactionStateRequest.ServiceName = purchaseOrderReceiptServiceDef.Template.TransactionSet.Name;
transactionStateRequest.TransactionStates.Add(new TransactionState("TABPAGE_1.tp_1_dw_po", "po_no", receipt.AsnId));  
TransactionSet retrievedTransactionSet = transactionRestClient.GetTransactionState(transactionStateRequest);

DataElement dataElement = retrievedTransactionSet.Transactions[0].DataElements
            .Find(element => element.Name == "TABPAGE_17.tp_17_dw_17");
			
<< itemQtyElements are created to line up with the DataElement found above - cannot use the actual rows in the one above because nearly all the fields are locked >>

foreach (var line in sortedLines) //Lines are presorted to be in the same order as the existing PO in P21.
{

	<< unitQuantity (received quantity) calculated from UOM conversion and receipt quantity here >>
 
    var lotRowToAdd = new P21.Transactions.Model.V2.Row()
    {
        Edits = new List<Edit>
		{
			new Edit("item_id", line.ItemId),
			new Edit("lot_cd", "lot" ),
			new Edit("bin_cd", "bin"),
			new Edit("unit_quantity", unitQuantity.ToString())
		}
    };
	lotQtyElement.Rows.Add(lotRowToAdd);
	
	
	var itemQtyToAdd = new P21.Transactions.Model.V2.Row()
	{
    
		Edits = new List<Edit>
		{

			new Edit("unit_quantity", unitQuantity.ToString()),

			// new Edit("item_id", line.ItemId)  This must be commented out because it returns an error on submission because the field is locked.
		}
	};
	<< itemQtyToAdd is added to the list of Rows in itemQtyElement in the same order as the actual PO line in P21 here. >>
}
	transactions = new TransactionSet
	{

		Name = "PurchaseOrderReceipt",
		Transactions = new List<P21.Transactions.Model.V2.Transaction>
		{
			new P21.Transactions.Model.V2.Transaction
			{
				DataElements = new List<DataElement>
				{

					new DataElement
					{
						Name = "TABPAGE_1.tp_1_dw_po",
						Type = DataElementType.Form,
						Keys = new List<string>{"po_no"},
						Rows = new List<P21.Transactions.Model.V2.Row>
						{
							new P21.Transactions.Model.V2.Row
							{
								Edits = new List<Edit>
								{
									new Edit("po_no", receipt.AsnId),
									new Edit("location_id", receipt.location),
								}
							}
						}
					},
					itemQtyElement,
					lotQtyElement, 
				}
			}
		}
	};
}

result = transactionRestClient.ProcessTransactionSet(transactions);

Quick update here because I think I’ve solved this - more testing may confirm. First issue is that the DataElement Type for the lots and items should be a ‘List’ - which seems to allow the item_id to be present even if the field is locked. Second, similar to how you click in P21 on an item and then the Lot and Bin tab will ‘lock’ to that item, the DataElements must reflect this clicking around in the UI to make it work properly. Even though the Lot/Bin tab allows the entry of the item_id, it must be ‘opened’ (new DataElement) sequentially from the correct Item in the Items (tp_17_dw_17) tab and then you must open a new DataElement to switch back to the Item tab between each item. Note that this also means the API cannot handle POs that are not consolidated by Item because the item_id is the only key available.

Hope this helps someone as I’ve tried so many different things before finally arriving at a seemingly working solution here.

1 Like