Mass quantity adjustment using PCIDs

Hello all,

I am looking into using PCID mainly in order to save time in the process of adjusting raw good and finished good quantities for jobs that use many different parts. Is there an option to perform quantity adjustment using a PCID that contains many different parts of varying amounts? And if not any suggestions for a different way to tackle this problem would be very helpful as well!

Think you could use DMT for this. We have a DMT for non PCID quantity adjustments but think PCID is just another field in the DMT.

1 Like

I think I made a dashboard for this. Remind me tomorrow.

1 Like

We are a little afraid of using DMT for this because we wanted to have it be a task all of our employees could perform. Most currently do not have access to DMT due to how powerful it is.

I found it, but it’s pretty tailored for us.
I’ll take a look at it and see if I can either share a generic version, or show how to diy.

Here is the dashboard and BAQ (One package)
Kev_PurchnvAdj.dbd (247.5 KB)

The heart of it is a UBAQ with Advanced BPM Update Only.
I left the criteria in on PartBin, you’ll have to edit that.
(It’s limited to WarehouseCode “RAW” & “SCRAP”)

This DB will let you make plus or minus adjustments, or set the qty and do the math for you.

Code below. (Go easy, code wrote a while ago :rofl:)

//UBAQ Update Code - Base - QtyAdjustment
//ref: Erp.Contracts.BO.InventoryQtyAdj
//using Ice.Assemblies;

  string retString = "";
  string nl = Environment.NewLine;
  bool DEBUG = false;
  //Reason for Adjustment:
  //string adjustmentRefReason = "ProdInvAdjDB";
  string adjustmentRefReason = ""; //Put your own here, or adjust the query so you can add it from the dashboard

  //Quantity Adjustment
  Action<string, string, string, string, string, decimal, decimal, string, Erp.Contracts.InventoryQtyAdjSvcContract> AdjustQty = (partNum, pcid, lotNum, binNum, ware, tranQty, originalTranQty, refReason, qtyAdj) =>
      Erp.Tablesets.InventoryQtyAdjTableset qtyTS = qtyAdj.GetInventoryQtyAdj(partNum, "");
      Erp.Tablesets.InventoryQtyAdjRow row = qtyTS.InventoryQtyAdj.FirstOrDefault();
      if (DEBUG)
          foreach (var r in qtyTS.InventoryQtyAdj)
              retString += $@"LotNum: {r.LotNum.ToString()}" + "\n";
              retString += $@"BinNum: {r.BinNum.ToString()}" + "\n";
              retString += $@"PCID: {r.PCID.ToString()}" + "\n";
              retString += $@"WareHseCode: {r.WareHseCode.ToString()}" + "\n";

      row.AdjustQuantity = tranQty - originalTranQty;
      row.LotNum = lotNum;
      row.BinNum = binNum;
      row.WareHseCode = ware;
      row.PCID = pcid;
      //row.AllowNegQty = (pcid == "" ? true : false);
      row.AllowNegQty = false;
      row.Reference = refReason;
      row.RowMod = "U";
      string tStr = "";
      qtyAdj.SetInventoryQtyAdj(ref qtyTS, out tStr);
      retString += tStr;

  var ttResultQuery = queryResultDataset.Results
      .Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P");

  Erp.Contracts.InventoryQtyAdjSvcContract qtyAdjBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.InventoryQtyAdjSvcContract>(Db);

  foreach (var ttResult in ttResultQuery)

          //Add To Onhand is the default and takes precedence if both fields are filled out.
          decimal origTQ  = 0;
          decimal tranQty = ttResult.Calculated_AddOnHand;
          if (ttResult.Calculated_AddOnHand == null){ttResult.Calculated_AddOnHand = 0;}
          if (ttResult.Calculated_AddOnHand == 0)
              //If the user chooses to "SET" the Qty, then use these values so the math comes out right.
              origTQ  = ttResult.PartBin_OnhandQty;
              tranQty = ttResult.Calculated_SetOnHand;
          AdjustQty(ttResult.PartBin_PartNum, (ttResult.PartBin_PCID == null ? "" : ttResult.PartBin_PCID), ttResult.PartBin_LotNum, ttResult.PartBin_BinNum, ttResult.PartBin_WarehouseCode, tranQty, origTQ, adjustmentRefReason, qtyAdjBO);
          if (origTQ == 0) //Add
              ttResult.PartBin_OnhandQty = ttResult.PartBin_OnhandQty + tranQty;
          else //Set
              ttResult.PartBin_OnhandQty = tranQty;

      catch (Exception ex)
          retString += ex.Message +nl;
          ttResult.Calculated_ReturnMessage = ex.Message;

      ttResult.RowMod = "P";

  if (DEBUG)
1 Like

I tried using the DMT to import our inventory from the old system and it does adjust the qty but it ignores the PCID# I have on the imported table.
For your code above, does the PCID have to already exist in Epicor?
Thanks again!


Not sure if you have found a solution to this or not, sorry for the Necropost. I do understand that if you void the PCID’s, you can assign a reason code to the inventory which in practice removes all of the stock in the PCID. I am not sure if this will be helpful for you or anyone who stumbles onto this post. The warehouse teams that I work with use PCID’s we fill with our expired parts on a weekly basis and adjust them out that way.