x++ code to create custom service to reverse the work which is closed (work status)
Request Class:
[DataContractAttribute("BASMSReverseWorkRequestContract")]
class BASMSReverseWorkRequestContract
{
str workId;
str dataAreaId;
[DataMemberAttribute("WorkId")]
public str parmWHSWorkId(str _workId = workId)
{
workId = _workId;
return workId;
}
[DataMemberAttribute("dataAreaId")]
public str parmdataAreaId(str _dataAreaId = dataAreaId)
{
dataAreaId = _dataAreaId;
return dataAreaId;
}
}
Response Class:
[DataContractAttribute("BASMSReverseWorkResponseContract")]
class BASMSReverseWorkResponseContract
{
str workStatus;
List errorList;
[DataMember('WorkStatus')]
public str parmWorkStatus(str _workStatus = workStatus)
{
workStatus = _workStatus;
return workStatus;
}
[DataMember('ErrorList')]
public List parmErrorList(List _errorList = errorList)
{
errorList = _errorList;
return errorList;
}
private static BASMSReverseWorkResponseContract construct()
{
return new BASMSReverseWorkResponseContract();
}
public static BASMSReverseWorkResponseContract newFromTableRecord(str _workstatus,List _errorList)
{
BASMSReverseWorkResponseContract contract = BASMSReverseWorkResponseContract::construct();
contract.parmWorkStatus(_workstatus);
contract.parmErrorList(_errorList);
return contract;
}
}
Helper Class:
class BASMSReverseWorkHelper
{
Common common;
WHSReverseWorkMode mode;
WMSLocationId location;
WHSLoadTable loadTable;
WHSWaveTable waveTable;
str specifiedLocation;
str message,workStatus;
SysInfoLogEnumerator infoLogEnum;
SysInfologMessageStruct infoMessageStruct;
public void ok_clicked(
Common _common,
WHSReverseWorkMode _createPutaway,
InventLocationId _location)
{
WHSReverseSalesWork reverseSalesWork;
reverseSalesWork = WHSReverseSalesWork::newStandard(_common);
reverseSalesWork.reverseWork(_createPutaway, _location);
}
private static BASReverseWorkHelper construct()
{
return new BASReverseWorkHelper();
}
private void checkWorkHeaders()
{
WHSWorkLine workLine;
str loadIdList;
WHSWorkId prevWorkId;
WHSLoadTable tmpLoadTable;
WHSWorkLine tmpWHSWorkLine;
// Check for work headers associated with multiple loads if reversing by load
if (loadTable)
{
while select workLine
group by workLine.WorkId, workLine.LoadId
join LoadId from tmpLoadTable
where workLine.LoadId == tmpLoadTable.LoadId &&
workLine.LoadId != loadTable.LoadId &&
workLine.LoadId != ''
exists join tmpWHSWorkLine
where tmpWHSWorkLine.WorkId == workLine.WorkId &&
tmpWHSWorkLine.LoadId == loadTable.LoadId
{
if (prevWorkId == workLine.WorkId)
{
continue;
}
loadIdList += workLine.LoadId + ", ";
prevWorkId = workLine.WorkId;
}
if (loadIdList)
{
loadIdList = subStr(loadIdList, 1, strLen(loadIdList) - 2);
throw error(strFmt("@WAX2236", prevWorkId, loadTable.LoadId, loadIdList));
}
}
}
private void checkWorkLines()
{
//MoveToLocation and MoveUsingLocDirectives for a closed work creates a new open work. Order-committed reservation can't be set back in this case since reservation is on the work line.
if (mode == WHSReverseWorkMode::MoveToLocation ||
mode == WHSReverseWorkMode::MoveUsingLocDirectives)
{
WHSWorkLine workLine;
WHSWorkTable workTable;
select firstonly TableId from workTable
where (loadTable.LoadId && workTable.LoadId == loadTable.LoadId)
|| (waveTable.WaveId && workTable.WaveId == waveTable.WaveId)
&& (workTable.WorkStatus == WHSWorkStatus::InProcess
|| workTable.WorkStatus == WHSWorkStatus::Closed)
exists join workLine
where workLine.WorkId == workTable.WorkId
&& workLine.WorkStatus == WHSWorkStatus::Closed
&& workLine.WorkType == WHSWorkType::Pick
&& workLine.OrderCommittedInventDimId;
if (workTable)
{
throw error("@WAX:ReverseWorkOrderCommittedError");
}
}
}
private WHSWorkLine getWorkLineWithOnHandForWork(WHSWorkTable _workTable)
{
WHSWorkLine lastPutLine = WHSWorkTable::getLastClosedPutWorkLine(_workTable.WorkId);
WHSWorkLine nextPickLine = WHSWorkLine::getNextOppositeWorkLineFromWorkLine(lastPutLine);
WHSWorkLine workLineWithOnHand = nextPickLine ? nextPickLine : lastPutLine;
return workLineWithOnHand;
}
private boolean canCreateWorkToMoveItemsBack(WHSWorkTable _workTable)
{
return !this.isSerialNumberCaptured(_workTable);
}
private boolean isSerialNumberCaptured(WHSWorkTable _workTable)
{
InventTrans inventTrans;
InventTransOrigin inventTransOrigin;
InventDim inventDim;
while select itemId from inventTrans
exists join inventDim
where inventTrans.inventDimId == inventDim.inventDimId
&& inventDim.inventSerialId != ''
exists join inventTransOrigin
where inventTransOrigin.RecId == inventTrans.InventTransOrigin
&& inventTransOrigin.ItemId == inventTrans.itemId
&& inventTransOrigin.ReferenceCategory == InventTransType::WHSWork
&& inventTransOrigin.ReferenceId == _workTable.WorkId
{
switch (whsInventTable::captureSerial(inventTrans.ItemId))
{
case WHSRFWhenToCapture::Picking:
case WHSRFWhenToCapture::Packing:
info(strFmt("@SYP4881557", inventTrans.ItemId));
return true;
}
}
return false;
}
protected WHSWorkId createWorkToMoveItemsBack(WHSWorkTable _workTable, WHSWorkLine _workLineWithOnHand)
{
WHSWorkId workId;
InventDim inventDim = _workLineWithOnHand.inventDim();
inventDim.InventSiteId = _workTable.InventSiteId;
inventDim.InventLocationId = _workTable.InventLocationId;
inventDim.wMSLocationId = _workLineWithOnHand.WMSLocationId;
if (inventDim.wmsLocation().whsLocationIsLPControlled())
{
inventDim.LicensePlateId = _workTable.TargetLicensePlateId;
}
inventDim = InventDim::findOrCreate(inventDim);
switch (mode)
{
case WHSReverseWorkMode::MoveToLocation:
case WHSReverseWorkMode::MoveUsingLocDirectives:
WHSTmpMovementWork tmpMovementWork;
tmpMovementWork.InventDimId = inventDim.InventDimId;
tmpMovementWork.Qty = _workLineWithOnHand.InventQtyWork;
tmpMovementWork.UnitID = WHSCatchWeightHelper::inventHandlingUnitId(_workLineWithOnHand.ItemId);
WHSWorkCreateMovement workCreate = WHSWorkCreate::construct(tmpMovementWork);
workCreate.parmStartLocationId(_workLineWithOnHand.WMSLocationId);
workCreate.parmTargetLicensePlateId(_workTable.TargetLicensePlateId);
workId = workCreate.createWork();
break;
}
if (workId)
{
info(strFmt("@WAX3849", workId));
}
return workId;
}
private void unPick(SalesLine _salesLine, WHSInventQtyWork _inventQtyWork)
{
InventTrans inventTrans;
InventTransOrigin inventTransOrigin;
Qty quantityUnpicked;
ttsbegin;
while select InventDimId, Qty, PdsCWQty from inventTrans
exists join inventTransOrigin
where inventTrans.InventTransOrigin == inventTransOrigin.RecId
&& inventTransOrigin.InventTransId == _salesLine.InventTransId
&& inventTrans.StatusIssue == StatusIssue::Picked
&& inventTrans.StatusReceipt == StatusReceipt::None
{
WHSInvent::pickQuantities(_salesLine, inventTrans.InventDimId, inventTrans.Qty, inventTrans.PdsCWQty, null, UnknownNoYes::No /*No reserve*/);
// Subtract since inventTrans.Qty is negative for sales issues.
quantityUnpicked -= PdsGlobal::pdsIsCWItem(_salesLine.ItemId) ? inventTrans.PdsCWQty : inventTrans.Qty;
}
if (quantityUnpicked != _inventQtyWork)
{
throw error(strFmt("@SYP4881563", "@WAX2738"));
}
ttscommit;
}
private void reReserve(WHSLoadLine _loadLine, SalesLine _salesLine, Qty _handlingQty, WHSTransWeight _weight)
{
Qty qty;
PdsCWQty cwQty;
if (PdsGlobal::pdsIsCWItem(_salesLine.ItemId))
{
cwQty = _handlingQty;
qty = _weight;
// Reservation may attempt to update the movement buffer so this must be selected for update
_salesLine.selectForUpdate(true);
}
else
{
cwQty = 0;
qty = _handlingQty;
}
var movement = InventMovement::construct(_salesLine, InventMovSubType::None);
var reservation = InventUpd_Reservation::newMovement(movement, -qty, false, false, false, -cwQty);
reservation.updateNow();
}
private void unpickSalesLine(WHSLoadLine _loadLine, WHSInventQtyWork _inventQtyWork, WHSTransWeight _weight)
{
WHSLoadLine loadLine;
WHSWorkLine workLine;
SalesQty pickedInTotalHandlingUnit;
boolean pickedInTotal = false;
ttsbegin;
// Get the sales line
var salesLine = _loadLine.getOrderCommonFromLoadLine() as SalesLine;
// When reversing a wave prevent reversal if work is ship confirmed.
if (waveTable.WaveId && salesLine.deliveredInTotal() > 0)
{
// Do not undeliver qty.
throw error("@WAX:ReverseWorkForDeliveredSalesLineError");
}
select count(RecId) from loadLine
where loadLine.LoadId == _loadLine.LoadId
&& loadLine.InventTransId == _loadLine.InventTransId
&& loadLine.InventTransType == InventTransType::Sales;
pickedInTotalHandlingUnit = PdsGlobal::pdsIsCWItem(salesLine.ItemId) ? salesLine.pdsCWPickedInTotal() : salesLine.pickedInTotalInventUnit();
// Look at sales order details picked field and unpick
if (pickedInTotalHandlingUnit > 0)
{
if (loadLine.RecId > 1)
{
select sum(InventQtyWork) from workLine
group by InventTransId
where workLine.InventTransId == _loadLine.InventTransId
&& workLine.WorkStatus != WHSWorkStatus::Cancelled
&& workLine.WorkType == WHSWorkType::Pick;
this.unPick(salesLine, min(workLine.InventQtyWork, pickedInTotalHandlingUnit));
}
else
{
this.unPick(salesLine, _inventQtyWork);
}
pickedInTotal = true;
}
if (pickedInTotal || loadLine.RecId > 1)
{
_loadLine.PickedQty = max(0, _loadLine.PickedQty - _inventQtyWork);
_loadLine.PickedWeight = max(0, _loadLine.PickedWeight - _weight);
_loadLine.update();
this.reReserve(_loadLine, salesLine, _inventQtyWork, _weight);
}
// Inform the user if the serial number is associated with load's sales line
if (InventTable::find(salesLine.ItemId).isSalesProcessSerialActive()
&& WHSInventTable::captureSerial(salesLine.ItemId) != WHSRFWhenToCapture::None)
{
warning("@WAX:SerialNumbersExistOnSalesLine");
}
ttscommit;
}
public WHSCapturedWeight currentCapturedWeight()
{
return 0;
}
private void reverseWorkLines(WHSWorkTable _workTable)
{
WHSWorkLineLoadLineDetailsEnumerator enumerator = _workTable.getEnumerator();
while (enumerator.moveNext())
{
WHSLoadLine loadLine = enumerator.currentLoadLine();
if (loadLine)
{
this.unpickSalesLine(loadLine, enumerator.currentInventQtyWork(), 1);
loadLine.reread(); // Reread because we update the loadLine in above method
loadLine.WorkCreatedQty -= enumerator.currentInventQtyWork();
loadLine.update();
}
}
}
public void setCancelWorkStatus(WHSWorkId _workId)
{
WHSWorkTable workTable;
ttsbegin;
workTable = WHSWorkTable::find(_workId, true);
if (workTable)
{
workTable.WorkStatus = WHSWorkStatus::Cancelled;
workTable.WorkCancelledByUser = curUserId();
workTable.WorkCancelledUTCDateTime = DateTimeUtil::utcNow();
workTable.update();
}
ttscommit;
}
public void reverseWork(WHSReverseWorkMode _mode, str _location,str _loadid, str _waveid)
{
WHSWorkTable workTable;
WHSLoadLine loadLine;
if ((_mode == WHSReverseWorkMode::AutoMoveToLocation ||
_mode == WHSReverseWorkMode::MoveToLocation)
&& !_location)
{
throw error("@WAX2237");
}
// Set global values.
mode = WHSReverseWorkMode::MoveUsingLocDirectives;
ttsbegin;
this.checkWorkHeaders();
this.checkWorkLines();
// Go to the whs work load link table to find the work table records associated with the load
while select workTable
where workTable.LoadId == _loadid ||
workTable.WaveId == _waveid &&
workTable.WorkStatus != WHSWorkStatus::Cancelled
{
WHSWorkLine workLineWithOnHand;
switch (workTable.WorkStatus)
{
case WHSWorkStatus::Closed:
if (!workTable.isOriginForConsolidatedWork()) // We do not want to unpick lines from origin work - that's done through consolidated work
{
workLineWithOnHand = this.getWorkLineWithOnHandForWork(workTable);
this.reverseWorkLines(workTable);
if (this.canCreateWorkToMoveItemsBack(workTable))
{
this.createWorkToMoveItemsBack(workTable, workLineWithOnHand);
}
else
{
// Throw here if validation failed so that we roll back the reversal of work lines above.
throw error("@SYS18447");
}
}
this.setCancelWorkStatus(workTable.WorkId);
delete_from loadLine where loadLine.ShipmentId == workTable.ShipmentId;
break;
}
}
ttscommit;
}
public void completeReverseWork(str _loadid, str _waveid)
{
mode = WHSReverseWorkMode::MoveUsingLocDirectives;
location = '';
this.reverseWork(mode,location,_loadid,_waveid);
}
[AifCollectionTypeAttribute('return', Types::Class, classStr(BASMSReverseWorkResponseContract))]
public List getReverseWork(str _workId , str _dataAreaId)
{
str workId = _workId;
str dataAreaId = _dataAreaId;
List workOrderList = new List(Types::Class);
WHSLoadLine loadLine;
boolean workCompleted;
WHSWorkTable workTable;
changecompany(dataAreaId)
{
List errorList = new List(Types::String);
try
{
ttsbegin;
WHSWorkTable worktable1 = WHSWorkTable::find(workId);
if (workId == '')
{
workStatus = '';
message = strFmt("Please enter the workid");
errorList.addEnd(message);
}
else if (!worktable1)
{
workStatus = '';
message = strFmt("Workid %1 is invalid Please enter a valid workid",workId);
errorList.addEnd(message);
}
else if (worktable1.WorkStatus == WHSWorkStatus::Closed)
{
select firstonly workTable
where workTable.WorkId == workId;
this.completeReverseWork(workTable.LoadId,workTable.WaveId);
workStatus = 'Cancelled';
}
else if (worktable1.WorkStatus == WHSWorkStatus::Open)
{
workStatus = 'Open';
message = strFmt("You cannot Reverse the work %1 because it has a status of Open.",worktable1.WorkId);
errorList.addEnd(message);
}
else if (worktable1.WorkStatus == WHSWorkStatus::Cancelled)
{
workStatus = 'Cancelled';
message = strFmt("You cannot Reverse the work %1 because it has a status of Canceled.",worktable1.WorkId);
errorList.addEnd(message);
}
ttscommit;
}
catch(Exception::Error)
{
workCompleted = boolean::false;
infoLogEnum = SysInfoLogEnumerator::newData(infolog.infologData());
while(infoLogEnum.moveNext())
{
infoMessageStruct = SysInfologMessageStruct::construct(infoLogEnum.currentMessage());
str integrationMessage = infoMessageStruct.message();
errorList.addEnd(integrationMessage);
}
ttsabort;
}
BASMSReverseWorkResponseContract workOrderData = new BASMSReverseWorkResponseContract();
workOrderData = BASMSReverseWorkResponseContract::newFromTableRecord(workStatus,errorList);
workOrderList.addEnd(workOrderData);
return workOrderList;
}
}
}
Service Class :
class BASMSReverseWorkService
{
[AifCollectionTypeAttribute('return', Types::Class, classStr(BASMSReverseWorkResponseContract))] // name of the response contract class
// service method
public List completeReverseWork(BASMSReverseWorkRequestContract _contract) // name of the contract class
{
BASMSReverseWorkHelper workOrderData = new BASMSReverseWorkHelper();
str workId = _contract.parmWHSWorkId();
str dataAreaId = _contract.parmdataAreaId();
List workOrderList = new List(Types::Class);
workOrderList = workOrderData.getReverseWork(workId,dataAreaId);
return workOrderList;
}
[AifCollectionTypeAttribute('return', Types::Class, classStr(BASMSWorkHeaderCancellationResponseContract))] // name of the response contract class
// service method
public List getWorkHeaderCancellation(BASMSWorkHeaderCancellationRequestContract _contract) // name of the contract class
{
BASMSWorkHeaderCancellationHelper workOrderData = new BASMSWorkHeaderCancellationHelper();
str workId = _contract.parmWHSWorkId();
str dataAreaId = _contract.parmdataAreaId();
List workOrderList = new List(Types::Class);
workOrderList = workOrderData.getWorkHeaderCancellation(workId,dataAreaId);
return workOrderList;
}
}
Comments
Post a Comment