Work Pick and Put in Code without using Warehouse App - arp6333/xplusplus GitHub Wiki
Execution order of the regular Warehouse app process with equivalent code (full code at bottom).
App Process would be:
- Login to Warehouse app (action:WHSWorkExecute in browser)
- Transloading
- Move and print label
- Enter Loc/LP and Item, click ok
- Enter batch, click ok
- Enter Qty / Weight
Relevant forms:
action:WHSWorkExecute - Open and use WH app in browser
WHSLicensePlateLabel - Created license plate labels
WHSWorkTable - Work and work lines
InventOnhandItem - Show available items / batches, filter by:
- Location = Pick location
- Warehouse = Warehouse to run in
- Available physical = At least 1
WHSWorkExecuteDisplayMovementByTemplate
Instantiate code:
WHSTmpMovementWork tmpMovementWork;
InventDim inventDim;
WhsWorkCreate workCreate;
WhsWorkExecute workExecute;
WHSWorkBuildId workBuildId;
WHSWorkLine workLine;
workExecute = WhsWorkExecute::construct();
Line 452 - if (complete): gets called after ok is hit the first time (before entering To info !!!)
- fullLP = False
- changingStatuses = True if invent status changes (ex going from 'BAG' into 'BOX')
- isCWItem = false : No quarantineInventDim then
- menuItemTable = 'Move and Print' (not needed for custom code)
Created / found InventDim from WH app
- InventBatchId = Entered batch
- InventLocationId = Warehouse user is running in
- InventStatusId = To InventStatus
- InventSiteId = Warehouse SiteId (ex 'GLOBAL')
- LicensePlateId = '' blank!
Custom code:
inventDim.inventBatchId = batch;
inventDim.inventLocationId = warehouse;
inventDim.wMSLocationId = pickLocation; // Use pick Location
inventDim.InventStatusId = toInventStatus; // Use put InventStatus
inventDim.InventSiteId = InventLocation::find(warehouse).inventSiteId;
inventDim = InventDim::findOrCreate(inventDim);
tmpMovementWork() from WH app
- InventDimId = Same as created InventDim above
- InventTransId = Null
- ItemId = Item entered
- Qty = Total quantity entered
- UnitId = Unit of measure to use
Custom code:
tmpMovementWork.InventDimId = inventDim.InventDimId;
tmpMovementWork.ItemId = itemId;
tmpMovementWork.Qty = netWeight;
tmpMovementWork.UnitID = unitId;
workCreate() from WH app
- parmInventStatusId('BAG') - To status
- parmCreatedBy(UserId) - Warehouse user
- parmStartLocationId(FromLocation) - From location
- parmWorkTemplateCode('Move and Print') - Not needed
- parmLocDirHintCode('') - Blank, not needed
- parmTargetLicensePlateId('') - Blank
- parmCreateWorkInventTransWithTargetLP(fullLP (which is false here))
- parmFromInventStatusId('BOX') - From status, only needed IF it is not the same as to status
Then createWork() is called.
createWork() is not called again from WHSWorkExecuteDisplayByTemplate.
Custom code:
ttsbegin;
workCreate = WHSWorkCreate::construct(tmpMovementWork);
workCreate.parmInventStatusId(toInventStatus);
workCreate.parmFromInventStatusId(fromInventStatus);
workCreate.parmCreatedBy(userWH);
workCreate.parmStartLocationId(pickLocation);
workCreate.parmCreateWorkInventTransWithTargetLP(false);
workBuildId = workCreate.createWork();
ttscommit;
Note: Any entered user / userId field should match the warehouse username, NOT the D365 user. This is needed to utilize the intermediary table that is used between the pick/put function. If getting 'Invalid location.' error it may be because it cannot find this intermediary table that must be the same name as the WH username. You may also need to login once if the user has just been created.
WHSWorkExecuteDisplay
Click ok to confirm pick:
- Line 9265, case (Pick): Second page ok click, before choosing put location
- workLine = workExecute.getFirstOpenLine(pass.lookup(#WorkId), userId); Add this to our code!
- Line 9501 executed
- assignSerial() returns false
- Line 9517 executed
- Line 9539, completePickStep(): Not applicable, only for UI changes
Pick custom code:
workLine = WHSWorkTable::getFirstWorkLineByWorkBuildId(workBuildId, userWH);
licensePlate = this.generateLicensePlateId(itemId, unitId);
workLine = workExecute.pickNonLicensePlateCheckDigitQuantities(
workLine.WorkId,
workLine.LineNum,
workLine.ItemId,
workLine.QtyRemain,
0,
workLine.UnitId,
userWH,
inventDim,
licensePlate,
false
);
WHSWorkTable::addTargetLicensePlate(workLine.WorkId, licensePlate);
Changing put location
- Line 9940: Create work exception; NOT needed in my case since we don't care about override exceptions
- LineNum = 3
- WorkException = 'Location override'
- WMSLocationId = OLD location, not new one yet
- Line 9725: Get location id passing in new location
- Line 9782: Update work line location; then workLine.reread()
Change put location custom code:
WMSLocationId locationId = WMSLocation::whsGetLocationId(putLocation, warehouse);
if (!locationId)
{
throw error("@WAX755"); // 'Invalid location.'
}
workExecute.updateWorkLineLocation(workLine.WorkId, 3, putLocation, userWH); // 3 = workLine put line
workLine.reread();
Click ok to confirm put
- Line 9615 processPutWorkLine()
- Line 17390 executed
- sourceLP = '' blank
- targetLP = generated LP
- targetLPNotExist = true
- newLP = same as targetLP
- workFlowPut = 0
- Line 17548 processPutAwayToLocation()
- Line 17550 executed
- isDeferredPutContainerFeature = false
- isAllowUseOfDeferredPut = true
- Line 17568 executed
- putOperationParameters:
- handleByLP = false
- lineNum = 3
- putWMSLocationId = put location
- sourceLP = '' blank
- targetLP = generated LP
- userId = user
- workID = pulled from line
- workPutFlow = 0
- Line 10931 executed
- WHSContainerTable::determineContainerClose(workLine.WorkId);
- workExecute.putAwayToLocationConsiderDeferredPut(putOperationParameters, isAllowUseOfDeferredPut);
InventStatus changes
WHSWorkExecuteDisplay isInventoryStatusBeingChanged() - Method can check if true
Otherwise, just make sure:
inventDim.InventStatusId = toInventStatus;
... // and:
workCreate.parmInventStatusId(toInventStatus);
workCreate.parmFromInventStatusId(fromInventStatus);
License plate label creation
Line 9671: LineNum = 2 (the label line (1 = pick, 3 = put))
Do any custom steps to the LP label here that need to be done before printing; it will be printed from labelBuild.buildLicensePlateLabels().
License plate label creation custom code:
WHSLicensePlateLabelBuild labelBuild = new WHSLicensePlateLabelBuild(workLine.WorkId, WHSWorkLine::find((workLine.WorkId), 2), '', userWH);
labelBuild.buildLicensePlateLabels();
workLine = workExecute.confirmCustomWork(workLine.WorkId, 2, userWH);
Full code
try
{
// Get your work info here, including warehouse, pick location, put location, etc.
WHSTmpMovementWork tmpMovementWork;
InventDim inventDim;
WhsWorkCreate workCreate;
WhsWorkExecute workExecute;
WHSWorkBuildId workBuildId;
WHSWorkLine workLine;
workExecute = WhsWorkExecute::construct();
// Find or create the InventDim
inventDim.inventBatchId = batch;
inventDim.inventLocationId = warehouse;
inventDim.wMSLocationId = pickLocation;
inventDim.InventStatusId = toInventStatus;
inventDim.InventSiteId = InventLocation::find(warehouse).inventSiteId;
inventDim = InventDim::findOrCreate(inventDim);
// Create the work
tmpMovementWork.clear();
tmpMovementWork.InventDimId = inventDim.InventDimId;
tmpMovementWork.ItemId = itemId;
tmpMovementWork.Qty = netWeight;
tmpMovementWork.UnitID = unitId;
ttsbegin;
workCreate = WHSWorkCreate::construct(tmpMovementWork);
workCreate.parmInventStatusId(toInventStatus);
workCreate.parmFromInventStatusId(fromInventStatus);
workCreate.parmCreatedBy(userWH);
workCreate.parmStartLocationId(pickLocation);
workCreate.parmCreateWorkInventTransWithTargetLP(false);
workBuildId = workCreate.createWork();
ttscommit;
// Pick
workLine = WHSWorkTable::getFirstWorkLineByWorkBuildId(workBuildId, userWH);
licensePlate = this.generateLicensePlateId(itemId, unitId);
workLine = workExecute.pickNonLicensePlateCheckDigitQuantities(
workLine.WorkId,
workLine.LineNum,
workLine.ItemId,
workLine.QtyRemain,
0,
workLine.UnitId,
userWH,
inventDim,
licensePlate,
false
);
WHSWorkTable::addTargetLicensePlate(workLine.WorkId, licensePlate);
// Set Put location
WMSLocationId locationId = WMSLocation::whsGetLocationId(putLocation, warehouse);
if (!locationId)
{
throw error("@WAX755");
}
workExecute.updateWorkLineLocation(workLine.WorkId, 3, putLocation, userWH);
workLine.reread();
// Put
WHSContainerTable::determineContainerClose(workLine.WorkId);
workLine = workExecute.putAwayToLocation(
workLine.WorkId,
3,
putLocation,
0,
userWH,
'',
licensePlate,
false
);
// Create the license plate label
WHSLicensePlateLabelBuild labelBuild = new WHSLicensePlateLabelBuild(workLine.WorkId, WHSWorkLine::find((workLine.WorkId), 2), '', userWH);
labelBuild.buildLicensePlateLabels();
workLine = workExecute.confirmCustomWork(workLine.WorkId, 2, userWH);
}
catch
{
// Get errors here
}
finally
{
// Do any post processing here
}