InvTransferSvcContract.CommitTransfer fails when transferring the same part one after the other

I do think so - if my suspicion about the BPM scope being the issue is correct. You could even use BO (reuse alot of your existing code) in a customization as well I’d think. Ultimately the adapter is going to call the BO so I dont expect you gain much from the adapter alone - just ease of use, but since you have most of the code already, I dont see a difference.

I ended up going the adapter route - which was painful. I should have just gone with the BO. Learned that with the adapter you have to merge the dataset into the adapter’s. It does work, however. Two records with the same part are no issue.

This is on a dashboard UI. I’m using filtered rows on a grid where a checkbox is ticked.


		for( int i=0; i < filteredRows.Length;i++)
		{
 		       if((bool)ug.Rows[filteredRows[i].Index].Cells["Calculated_Transfer"].Value)
				{
					bool requiresUserInput = false;
					string msg ="";
					string ptmsg ="";
					MessageBox.Show(ug.Rows[filteredRows[i].Index].Cells["UD100_ShortChar01"].Value.ToString());
					string iPart = ug.Rows[filteredRows[i].Index].Cells["UD100_ShortChar01"].Value.ToString();
					string iUOM = ug.Rows[filteredRows[i].Index].Cells["UD100_ShortChar08"].Value.ToString();



					InvTransferAdapter invTransfer = new InvTransferAdapter(this.oTrans);
					invTransfer.BOConnect();
					Erp.BO.InvTransferDataSet dsInvTrans = invTransfer.GetTransferRecord(iPart,iUOM);

					invTransfer.InvTransferData.Clear();
					invTransfer.InvTransferData.Merge(dsInvTrans);
					invTransfer.InvTransferData.AcceptChanges();
					
					Erp.BO.InvTransferDataSet.InvTransDataTable invTransTable = (Erp.BO.InvTransferDataSet.InvTransDataTable)invTransfer.InvTransferData.InvTrans;
					
					DataRow dr = invTransTable.Rows[0];
					dr["TransferQty"] = (decimal)ug.Rows[filteredRows[i].Index].Cells["UD100_Number01"].Value;					
					dr["FromWareHouseCode"] = ug.Rows[filteredRows[i].Index].Cells["UD100_ShortChar02"].Value.ToString();
					invTransfer.ChangeFromWhse(invTransfer.InvTransferData);
					dr["FromBinNum"] = ug.Rows[filteredRows[i].Index].Cells["UD100_ShortChar03"].Value.ToString();
					invTransfer.ChangeFromBin(invTransfer.InvTransferData);
					dr["ToWarehouseCode"] = ug.Rows[filteredRows[i].Index].Cells["UD100_ShortChar04"].Value.ToString();
					invTransfer.ChangeToWhse(invTransfer.InvTransferData);					
					dr["ToBinNum"] = ug.Rows[filteredRows[i].Index].Cells["UD100_ShortChar05"].Value.ToString();
					invTransfer.ChangeToBin(invTransfer.InvTransferData);
	
					invTransfer.PreCommitTransfer(invTransfer.InvTransferData, out requiresUserInput);
					
					invTransfer.CommitTransfer(out msg, out ptmsg);
					invTransfer.Dispose();
					dsInvTrans = null;

					
				}

In that case we’ll need some fancy work around to do this in the context of BPM. @Bart_Elia @Rich

I have fought at great lengths with gremlins within external BPM contexts in throwing PartBin, PartQty, and PartWhse tables out of sync.

These two little lines of code after each transfer should initiate the processing of the deferred items so that you can initiate another transaction with the same key.

Erp.Internal.Lib.DeferredUpdate libDeferredUpdate = new Erp.Internal.Lib.DeferredUpdate(Db);
libDeferredUpdate.UpdPQDemand();
4 Likes

Nice!

I will give this a try today and report back. Thanks!

Same message.

Here is where we are currently:

string msg = "";
string ptmsg = "";
bool reqUserInput = false; 


  foreach(var ttResultsRow in (from row in ttResults where row.RowMod == "U" select row))
      {

          using (var txScope = IceContext.CreateDefaultTransactionScope())
            {
            
                msg = "";
                ptmsg = "";
                Erp.Contracts.InvTransferSvcContract invTrans = null;
                invTrans = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.InvTransferSvcContract>(Db);
                var InvTransferDS = new Erp.Tablesets.InvTransferTableset();
                InvTransferDS = invTrans.GetTransferRecord(ttResultsRow.UD100_ShortChar01, ttResultsRow.UD100_ShortChar08);
                var ttInvTrans_Row = (from InvRow in InvTransferDS.InvTrans select InvRow).FirstOrDefault();
                
                this.PublishInfoMessage(ttInvTrans_Row.PartNum, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
                if(ttInvTrans_Row !=null)
                  {
                    ttInvTrans_Row.TransferQty = ttResultsRow.UD100_Number01; 
                    ttInvTrans_Row.TrackingQty = ttResultsRow.UD100_Number01; 
                    ttInvTrans_Row.FromWarehouseCode = ttResultsRow.UD100_ShortChar02; 
                    ttInvTrans_Row.FromBinNum = "";
                    ttInvTrans_Row.ToWarehouseCode = ttResultsRow.UD100_ShortChar04;
                    ttInvTrans_Row.FromBinNum = ttResultsRow.UD100_ShortChar03;
                    ttInvTrans_Row.TranReference = ttResultsRow.UD100_ShortChar06;         
                    ttInvTrans_Row.RowMod = "U"; 
                    invTrans.ChangeUOM(ref InvTransferDS); 
                    invTrans.ChangeFromWhse(ref InvTransferDS);
                    ttInvTrans_Row.FromBinNum = ttResultsRow.UD100_ShortChar03;    
                    invTrans.ChangeFromBin(ref InvTransferDS);        
                    invTrans.ChangeToWhse(ref InvTransferDS); 
                    ttInvTrans_Row.ToBinNum = ttResultsRow.UD100_ShortChar05; 
                    invTrans.ChangeToBin(ref InvTransferDS); 
                    invTrans.PreCommitTransfer(ref InvTransferDS, out reqUserInput);
                    ttInvTrans_Row.RowMod = "U"; 
                    invTrans.CommitTransfer(ref InvTransferDS, out msg, out ptmsg);
                    Erp.Internal.Lib.DeferredUpdate libDeferredUpdate = new Erp.Internal.Lib.DeferredUpdate(Db);
                    libDeferredUpdate.UpdPQDemand();
                  }
                invTrans.Dispose();
                InvTransferDS = null;
                txScope.Complete(); 



            }

      }

If I had to guess (which I do all the time) - I’d think you’d want your libdeferred update outside of the scope of the actual CommitTransfer.

2 Likes

That did the trick! I can’t thank you guys enough. It worked with two sets of duplicate parts without issue!

                InvTransferDS = null;
                txScope.Complete(); 
            }
            Erp.Internal.Lib.DeferredUpdate libDeferredUpdate = new Erp.Internal.Lib.DeferredUpdate(Db);
            libDeferredUpdate.UpdPQDemand();
2 Likes

Even a broken clock is right twice a day :slight_smile: Glad to help! @bfraseraepl

No problem! I’m glad @Chris_Conn pinged me on this one.

1 Like

@Chris_Conn @josephmoeller
Gentlemen,
Is this solution only for Method Directives? I tried this in a Data Directive and it appears an inherent Update transaction block may be stopping the deferred update from working? I run into the same initial issue, the first transaction processes, the second errors out with the PartTran message.

My scenario is I’m using UD07 for creating part UOM conversion requests for an outside warehouse (cases to each for example). When a new request ticket is created, the stock is moved from the assigned bin to a specific non-nettable bin created for this process. When the outside vendor flags that the ticket is complete, the quantity is adjusted to the new UOM via the SplitMergeUOM adapter and then transferred back to its original bin in its new configuration. If the quantity or UOM of an existing request ticket is modified, I transfer the original quantity/UOM from the non-nettable bin to the original bin, then the revised quantity/UOM is transferred to the non-nettable bin. Because these transactions occur back-to-back with the same part number, I am getting the PartTran error.

@BBussey, this will be a vague answer without testing or deeper insight, but it should work in different circumstances – you might need to play with the context that you’re passing your service instantiation Erp.Internal.Lib.DeferredUpdate(Db) vs Erp.Internal.Lib.DeferredUpdate() because they can refer to cached / non-cached data depending on the context. I’ve run into some issues with standard DT failing to use Db context, so I’d imagine you might need to test. Also, you want to make sure this is processing synchronously to wait for the update.

1 Like

I found the problem. The Invoke External Method was mistakenly set to fire asynchronously. Once the action was set to synchronously, the problem went away.

Great, thanks for following up!

Sorry for the delay, thought I already had responded.

@josephmoeller @Chris_Conn you guys are life savers with this. We’ve spent all day fighting with this thing!!!

3 Likes

Those two lines of code saves my night. I was struggling with this issue whole day yesterday. Thank you. I own you a beer.

1 Like