EFx for inventory transfer with serial numbers

How do you inject the serial number(s)* into the InvTransfer dataset?

[The * is because, for the REST integration that I am working on, I am planning to do only one serial number per transaction, if that makes this question any easier.]

You know me, I am trying to do this with widgets. And FYI, I got the function working fine already without serial numbers. Now I am trying to add the serial number bit.

@utaylor, have you done this with serial numbers?

When I do the trace, I don’t see a clear place where this magic happens. You can select serial numbers, but when do they get added to the actual dataset of the transfer?

Also, when I added in the GetSelectSerialNumbersParams method, I ran into this lovely error.

"The type 'SelectSerialNumbersParamsTableset' exists in both 'Erp.Contracts.BO.InvTransfer [...] and 'Erp.Contracts.BO.SelectedSerialNumbers"

error pic

image

I’m not sure if I need both references, really; I just added them because they were in the trace. I may need neither one at all.

Trace overview (my comments added):

First time the serial appears in the InvTransfer BO:

Also, I did read this post, but I don’t seem to have access to those methods via widgets:

So unfortunately Epicor put those SelectSerialNumbersParamsTableset in the same Package in different DLLs which causes all sorts of issues.
There isn’t an easy work-around for it

2 Likes

I have run into that before, and I’m hoping that today that error is actually a red herring due to my overzealous reference-adding.

On the off chance that I am right, any thoughts on the core question, of adding serial numbers to the InvTransfer dataset?

I see that it is a nested subset called <SelectedSerialNumbers>, and that never exists until I picked them. IRL when I did the trace I had added them at the end just before submitting, which I assume is why it shows there just before MasterInventoryBinTests.

Here’s some code which does an Inventory Transfer with Serial Numbers

private void TransferPart(string partNum, string UOM, int transferQty, string sourceBin, string stagingBin, IReadOnlyList serialNums, int OrderNum = 0, int OrderLine = 0) {
    using(var invTransfer = WCFServiceSupport.CreateImpl((Session) oTrans.Session, ImplBase.UriPath)) {
      var transDS = invTransfer.GetTransferRecord(partNum, "");
      transDS.InvTrans[0].FromOnHandUOM = UOM;
      transDS.InvTrans[0].ToOnHandUOM = UOM;
      transDS.InvTrans[0].TrackingUOM = UOM;
      transDS.InvTrans[0].TransferQtyUOM = UOM;
      invTransfer.ChangeUOM(transDS);
      transDS.InvTrans[0].FromBinNum = sourceBin;
      invTransfer.ChangeFromBin(transDS);
      transDS.InvTrans[0].ToBinNum = stagingBin;
      invTransfer.ChangeToBin(transDS);
      transDS.InvTrans[0].TransferQty = transferQty;
      if (transDS.InvTrans[0].TrackSerialnumbers)
        for (var i = 0; i < transferQty; i++) {
          invTransfer.GetSelectSerialNumbersParams(transDS);
          transDS.SelectedSerialNumbers.AddSelectedSerialNumbersRow(((Session)oTrans.Session).CompanyID, serialNums[i], false, "", false, "", "", "", partNum, "", "", Guid.Empty, "", false, false, "", "", 0, "", false, "", "", false, "", "A",true, Guid.Empty, transDS.InvTrans[0].RowMod);*/ } bool outBool; string outMsg; transDS.InvTrans[0].TranReference = string.Format("Order: {0}-{1} {2}=>{3} Serials: {4}", OrderNum, OrderLine, sourceBin, stagingBin, string.Join(", ", serialNums));
          invTransfer.PreCommitTransfer(transDS, out outBool);
          invTransfer.CommitTransfer(transDS, out outMsg, out outMsg);

        }
    }

You basically have to add / fill in the serialnumber rows inside the SelectedSerialNumber subtable before calling the Commit.

1 Like

Ugh missed that part, so try using the Fill Table Widget to fill in the SelectedSerialNumber subtable with the data you need right before the commit.

1 Like

No worries. By now, I always assume everyone would never dream of using widgets.

So, I’m trying to decipher your logic regardless.

I think at root (if using a single serial number), the part I need is the single line of code that I’ll summarize as:

transDS.SelectedSerialNumbers.AddSelectedSerialNumbersRow([lots of parameters]);

You’ve got a */ in there, just before the end of the for loop (before the bool outBool declaration), but that’s just a typo, right?

EDIT: Also, I was intrigued that you did use invTransfer.GetSelectSerialNumbersParams after all. Do you happen to recall why? Just mimicking the trace?

1 Like

Right that’s just a typo, I believe you can make that one line happen by using a FillByQuery widget.

1 Like

I wrote that code in 2017 so its just one of my many snippets, I have no earthly idea why haha but if I had to guess I’d say I was following the trace.

1 Like

Thanks for the snippets Jose!

I have not had to do inventory transfer with serials yet! @JasonMcD

@josecgomez Getting closer…

First the easy (for you) question: if I do this as code, it says I am missing a reference that would allow the method of AddSelectedSerialNumbersRow.

Do you know what that reference might be that I need? I tried ERP.BO.SelectedSerialNumbers, but then I get the conflict error again.

image

===================================

Next, the widget question. I tried the Fill Table By Query widget. The EFx compiles fine, but seems to ignore this widget. It says,

ttInvTrans record not found.\r\nThe number of serial numbers you have selected doesn’t match the number required. You have 0 serial numbers selected. You must select 1 serial numbers.

I think I mapped this right. One area I have concern is rows 26 and/or 27.

So, your code for this had 28 parameters and this wants 29. The extra one is one of these two Booleans. I think I tried all combinations of true and false here with no luck.

AddSelectedSeriaNumberRow is a method you just need to populate the SelectedSerialNumber table.

1 Like

Also, I may completely misunderstand the “fill table” widget, but does it work if there is no table?

My point is, I did another trace on a transfer with a part that is NOT serial-tracked, and the subtable of SelectedSerialNumber is not even there in the PreCommitTransfer method of the InvTransfer dataset, for example.

And @utaylor thanks for nothing lol.

The table needs to be there for that widget to work, but the SelectedRialNumber table should always be there it is part of the dataset./

1 Like

I don’t disagree, but the compiler won’t let me save the EFx with that.

image

image

You shouldn’t need that if you are using a widget. #ImConfused.

I’m attacking both ways. I can’t get custom code to work, and I can’t get the widget to work. (I’m only doing one OR the other.)

Sorry for the confusion.

OKay so with Custom Code you should be able to use just Add and that should return a row that you then have to fill in.

1 Like

I was just about to chime in, I have had to use a custom code widget to add a row to a table before I can use a fill widget or update widget, but I didn’t know what angle @JasonMcD was going at.

Something like this mind you this example is using CostAdjustmentRow in your case you’ll use SelectedSerialNumberRow

  CostAdjustmentRow r = new CostAdjustmentRow();
      r.AvgBurUnitCost=09;
      costDS.CostAdjustment.Add(r);
1 Like