Automating Fulfillment Workbench - Erp.OrderAlloc.GetLotBinOnHand() Error - "You need to select one demand record."

@gunny72 I ended up working in code as well. here is something to get you started. Note that this is an Epicor Function, not a BPM. There are may be small adjustments for a BPM. You could also create an Epicor Function and then call from BPM, as I do.

AllocateByLot

this.CallService<OrderAllocSvcContract>(orderAllocBO => {

    // get demands for given part
    OrderAllocTableset myOrderAllocTableset = this.EfxLib.InventoryAutomationLib.GenerateOrderAllocTablesetByPart(this.PartNum);
    int lineCount = myOrderAllocTableset.OrderAlloc.Count();
    
    // select the largest demand in the next month
    OrderAllocRow myOrderAllocRow = myOrderAllocTableset.OrderAlloc.First(); // add a Where() to select which demand
    myOrderAllocRow.SelectedForAction = true;
    myOrderAllocRow.ReleaseCount = lineCount; //should be the count of records in myOrderAllocTableset.OrderAlloc (I have inferred this from traces and it seems to work, doesn't make much sense to me tho. without, it fails)
    myOrderAllocRow.LineCount = lineCount;
    myOrderAllocRow.RowMod = "U";

    // get the on hand quantities
    string cMessageText = "";
    string oErrorText = "";
    string oDemandtype = "";
    bool lReleased = false;
    (myOrderAllocTableset, cMessageText, oErrorText, oDemandtype) = this.EfxLib.InventoryAutomationLib.GetOnHandQtys(myOrderAllocTableset); // get the current on hand quanitites

    // find the lot with matching LotNum Part 
    PartAllocLotRow myPartAllocLotRow = myOrderAllocTableset.PartAllocLot.First(); // add a Where() to select which lot
    int allocQty = 10; // put some calculation here
    
    // select the lot, allocate by lot
    myPartAllocLotRow.Allocate = true;
    myPartAllocLotRow.NewAllocatedQty = allocQty;
    
    orderAllocBO.AllocateByLotBin(ref myOrderAllocTableset, "", "All", out cMessageText, out lReleased); // perform the allocation
    orderAllocBO.GetFWBLimitedRefresh(out bool opFWBLimitedRefresh);
    orderAllocBO.GetFWBLimitedRefresh(out opFWBLimitedRefresh);
    libDeferredUpdate.UpdPQDemand(); // must process the deferred updates or the tables get de-synchronized (i think this code is Epicor Function specific, search the forum for the BPM variant)

});

GenerateOrderAllocTablesetByPart


this.CallService<OrderAllocSvcContract>(orderAllocBO => {
  this.CallService<PartAllocTemplateSvcContract>(partAllocTemplateBO => {
    OrderAllocListTableset orderAllocListTableset = orderAllocBO.GetListOfOrders("","","",$"OrderRel.PartNum = '{ PartNum }'","","","","","false","OrderHed.ReservePriorityCode , OrderRel.ReqDate","","",0,0, out bool morePages, "");
    this.orderAllocTableset = orderAllocBO.OrderAllocationGetRows(orderAllocListTableset, 0);
    PartAllocTemplateTableset partAllocTemplateTableset = partAllocTemplateBO.GetByID("YouTemplate");
    
    PartAllocTemplateRow partAllocTemplateRow = partAllocTemplateTableset.PartAllocTemplate.First();
    
    // Update orderAllocTableset.PartAllocTrans with template
    foreach (PartAllocTranRow partAllocTranRow in orderAllocTableset.PartAllocTran)
    {
      partAllocTranRow.AddHoc = false;
      partAllocTranRow.WarehouseCode = partAllocTemplateRow.WarehouseCode;
      partAllocTranRow.AllocTemplateID = partAllocTemplateRow.AllocTemplateID;
      partAllocTranRow.AllocTempDescAllocTemplateDesc = partAllocTemplateRow.AllocTemplateDesc;
      partAllocTranRow.RowMod = "U";
    }
        
  });
});

GetOnHandQtys

this.CallService<OrderAllocSvcContract>(orderAllocBO => {
  SlimOrderAllocTableset slimOrderAllocTableset = new SlimOrderAllocTableset();
  
  // transform orderAllocListTableset to SlimOrderAllocTableSet (there's probably a LINQ way to do this)
  foreach (OrderAllocRow orderAllocRow in inputOrderAllocTableset.OrderAlloc)
  {
      SlimOrderAllocRow slimOrderAllocRow = new SlimOrderAllocRow();
       
      slimOrderAllocRow.AssemblySeq = orderAllocRow.AssemblySeq;
      slimOrderAllocRow.Company = orderAllocRow.Company;
      slimOrderAllocRow.DemandType = orderAllocRow.DemandType;
      slimOrderAllocRow.FulfillmentSeq = orderAllocRow.FulfillmentSeq;
      slimOrderAllocRow.JobNum = orderAllocRow.JobNum;
      slimOrderAllocRow.MtlSeq = orderAllocRow.MtlSeq;
      slimOrderAllocRow.OrderLine = orderAllocRow.OrderLine;
      slimOrderAllocRow.OrderNum = orderAllocRow.OrderNum;
      slimOrderAllocRow.OrderRelNum = orderAllocRow.OrderRelNum;
      slimOrderAllocRow.SelectedForAction = orderAllocRow.SelectedForAction;
      slimOrderAllocRow.TFOrdLine = orderAllocRow.TFOrdLine;
      slimOrderAllocRow.TFOrdNum = orderAllocRow.TFOrdNum;
      slimOrderAllocRow.RowMod = "A";
      
      slimOrderAllocTableset.SlimOrderAlloc.Add(slimOrderAllocRow);
      
  }
  orderAllocBO.CheckDates(ref slimOrderAllocTableset, out string cMessageText);
  orderAllocBO.OneDemandType(ref inputOrderAllocTableset, out string oErrorText, out string oDemandType);
  orderAllocBO.GetLotBinOnHand(ref inputOrderAllocTableset);
  outputOrderAllocTableset = inputOrderAllocTableset;
});
5 Likes