Depoda toplanan ürünün yerine geri koyulmasını ve sevkiyatının iptal edilmesini kodla nasıl yaparız?
Bu yazıda Dynamics 365 Finance and Operations içinde depo yönetimi modülünde toplanan bir ürünün kodla yerine koyulması ve sevkiyatın iptal edilmesinin nasıl yapılacağını anlatacağım.
Aslında bu işlemi ekran üzerinden tek tek yapabiliyoruz. Load Line formunu açıp Reduce picked quantity’ye tıklıyoruz.
Resim-1
Açılan formda miktarı ayarlayıp Ok dediğimizde aslında bu işlemi yapmış oluyoruz.
Resim-2
Benim burada yapacağım bu işlemi toplu yapmak için bir kod yamak olacak. Bir sebepten otomatik toplanan bazı siparişlerin iptali gerektiğinde elle tek tek yapmak çok uzun süreceğinden böyle bir koda ihtiyaç oldu. Öncelikle Ax2012’de bu işlem için Güven arkadaşım şu makaleyi yazmış. Benim işimi tam çözmüyor. Ben bir dosyadan beri okuyup D365 te bu işlemi yapmak istiyorum.
Öncelikle WhsUnShip sınıfından bir Extension sınıfı oluşturmam gerekti. BuildTmpTable aslında Ax2012 olan bir metottu ama D365 te kullanamıyoruz.
[ExtensionOf(classStr(WhsUnShip))]
final class WhsUnShip_Extension
{
public WHSTmpLoadLineInventory dmrBuildTmpTable(WHSLoadLine _loadLine = loadLine)
{
WHSTmpLoadLineInventory tmpLoadLineInv;
WHSWorkLine workLine;
WHSWorkLine putWorkLine;
WHSWorkTable workTable;
WHSDimTracking dimTracking;
InventDim inventDim;
Qty closedContainerQty;
InventDim inventDimId;
SalesLine salesLine;
InventTransferLine transferLine;
InventDim loadLineInventDim;
boolean putIsPackingStation;
WHSWorkId lastWHSWorkId;
WMSLocation wmsLocation;
boolean hasDimTracking;
// Set LoadLine if specified.
loadLine = _loadLine;
loadLineInventDim = loadLine.inventDim();
switch (loadLine.InventTransType)
{
case InventTransType::Sales:
salesLine = loadLine.getOrderCommonFromLoadLine() as SalesLine;
break;
case InventTransType::TransferOrderShip:
transferLine = loadLine.getOrderCommonFromLoadLine() as InventTransferLine;
break;
}
while select InventQtyWork, ItemId, LineNum, WorkId, ContainerId from workLine
order by workLine.WorkId
where workLine.LoadLineRefRecId == loadLine.RecId &&
workLine.WorkStatus == WHSWorkStatus::Closed
join WorkId, TargetLicensePlateId, InventLocationId from workTable
where workTable.WorkId == workLine.WorkId &&
workTable.WorkStatus == WHSWorkStatus::Closed
{
if (lastWHSWorkId != workLine.WorkId)
{
select firstonly wmsLocationId from putWorkLine
order by putWorkLine.LineNum desc
where putWorkLine.WorkId == workTable.WorkId &&
putWorkLine.WorkStatus == WHSWorkStatus::Closed &&
putWorkLine.WorkType == WHSWorkType::Put
join LocProfileId from wmsLocation
where wmsLocation.wMSLocationId == putWorkLine.wmsLocationId &&
wmsLocation.InventLocationId == workTable.InventLocationId;
putIsPackingStation = wmsLocation.LocProfileId == parameters.PackingLocType;
lastWHSWorkId = workLine.WorkId;
}
hasDimTracking = false;
// If the workLine uses dim tracking we must use those values.
while select InventDimId, Qty from dimTracking
where dimTracking.WorkId == workLine.WorkId
&& dimTracking.LineNum == workLine.LineNum
{
hasDimTracking = true;
inventDim = InventDim::find(dimTracking.InventDimId);
inventDim.wmsLocationId = putWorkLine.wmsLocationId;
if (WMSLocation::find(inventDim.wmsLocationId, inventDim.InventLocationId).whsLocationIsLPControlled())
{
inventDim.LicensePlateId = workTable.TargetLicensePlateId;
}
inventDim = InventDim::findOrCreate(inventDim);
// If put location is a packing station, then we need to look for closed containers that may have moved inventory.
if (putIsPackingStation)
{
InventDimParm inventDimParm;
InventDim joinInventDim;
InventDim inventDimMethod;
WHSContainerLine containerLine;
WHSContainerTable containerTable;
inventDimParm.initFromInventDim(inventDim);
// Loop over container lines for closed containers
while select containerLine
where containerLine.LoadLine == loadLine.RecId
join InventDimId, ContainerId from containerTable
where containerTable.ContainerId == containerLine.ContainerId
&& containerTable.ContainerStatus == WHSContainerStatus::Closed
#InventDimExistsJoin(containerLine.inventDimId, joinInventDim, inventDim, inventDimParm)
{
tmpLoadLineInv.InventQty = InventTableModule::unitConvert(containerLine.ItemId, ModuleInventPurchSales::Invent, containerLine.UnitId, containerLine.Qty);
inventDimMethod = containerLine.mergedClosedInventDim();
tmpLoadLineInv.InventDimId = inventDimMethod.InventDimId;
tmpLoadLineInv.RefRecId = loadLine.RecId;
tmpLoadLineInv.ContainerId = containerTable.ContainerId;
tmpLoadLineInv.insert();
closedContainerQty += tmpLoadLineInv.InventQty;
}
}
if (dimTracking.Qty > closedContainerQty)
{
tmpLoadLineInv.clear();
tmpLoadLineInv.InventQty = dimTracking.Qty – closedContainerQty;
tmpLoadLineInv.InventDimId = inventDim.InventDimId;
tmpLoadLineInv.RefRecId = loadLine.RecId;
tmpLoadLineInv.ContainerId = workLine.ContainerId;
tmpLoadLineInv.insert();
}
}
if (!hasDimTracking)
{
inventDim.clear();
inventDim.initFromInventDim(loadLineInventDim);
inventDim.wmsLocationId = putWorkLine.wmsLocationId;
if (WMSLocation::find(inventDim.wmsLocationId, inventDim.InventLocationId).whsLocationIsLPControlled())
{
inventDim.LicensePlateId = workTable.TargetLicensePlateId;
}
inventDim = InventDim::findOrCreate(inventDim);
// If put location is a packing station, then we need to look for closed containers that may have moved inventory.
if (putIsPackingStation)
{
InventDimParm inventDimParm;
InventDim joinInventDim;
InventDim inventDimMethod;
WHSContainerLine containerLine;
WHSContainerTable containerTable;
inventDimParm.initFromInventDim(inventDim);
// Loop over container lines for closed containers
while select containerLine
where containerLine.LoadLine == loadLine.RecId
join InventDimId, ContainerId from containerTable
where containerTable.ContainerId == containerLine.ContainerId
&& containerTable.ContainerStatus == WHSContainerStatus::Closed
#InventDimExistsJoin(containerLine.inventDimId, joinInventDim, inventDim, inventDimParm)
{
tmpLoadLineInv.InventQty = InventTableModule::unitConvert(containerLine.ItemId, ModuleInventPurchSales::Invent, containerLine.UnitId, containerLine.Qty);
inventDimMethod = containerLine.mergedClosedInventDim();
tmpLoadLineInv.InventDimId = inventDimMethod.InventDimId;
tmpLoadLineInv.RefRecId = loadLine.RecId;
tmpLoadLineInv.ContainerId = containerTable.ContainerId;
tmpLoadLineInv.insert();
closedContainerQty += tmpLoadLineInv.InventQty;
}
}
if (workLine.InventQtyWork > closedContainerQty)
{
tmpLoadLineInv.clear();
tmpLoadLineInv.InventQty = workLine.InventQtyWork – closedContainerQty;
tmpLoadLineInv.InventDimId = inventDim.InventDimId;
tmpLoadLineInv.RefRecId = loadLine.RecId;
tmpLoadLineInv.ContainerId = workLine.ContainerId;
tmpLoadLineInv.insert();
}
}
}
return tmpLoadLineInv;
}
public WHSLoadLine parmLoadLine(WHSLoadLine _loadLine = loadLine)
{
loadLine = _loadLine;
return loadLine;
}
}
Sonrasında asıl işi yapan sınıfı yazdım. Burada bir csv dosyasından veri okuyup ilgili kaydı bulup iptal işlemini yapan kod var.
class DmrUnsipLoadCsv
{
public static void main(Args _args)
{
DmrUnsipLoadCsv DmrUnsipLoadCsv;
DmrUnsipLoadCsv = new DmrUnsipLoadCsv();
DmrUnsipLoadCsv.run();
}
void run()
{
whsworkid whsworkid;
container rec;
Array fileLines;
Counter counter = 0;
AsciiStreamIo file;
InventTable inventTable;
FileUploadTemporaryStorageResult fileUpload;
#OCCRetryCount
//conPeek(rec, 3);
try
{
fileUpload = File::GetFileFromUser() as FileUploadTemporaryStorageResult;
file = AsciiStreamIo::constructForRead(fileUpload.openResult());
if (file)
{
if (file.status())
{
throw error(“@SYS52680″);
}
file.inFieldDelimiter(“;”);
file.inRecordDelimiter(“\r\n”);
}
while (!file.status())
{
counter++;
rec = file.read();
if (conLen(rec))
{
whsworkid = conPeek(rec, 1);
ttsbegin;
this.unship(whsworkid);
ttscommit;
//info(strFmt(“%1″,conPeek(rec, 1)));
} }
// info(“Aktarım tamamlandı.”);
}
catch (Exception::Deadlock)
{
retry;
}
catch (Exception::UpdateConflict)
{
if (appl.ttsLevel() == 0)
{
if (xSession::currentRetryCount() >= #RetryNum)
{
throw Exception::UpdateConflictNotRecovered;
}
else
{
retry;
} }
else
{
throw Exception::UpdateConflict;
}
}
}
void unship(whsworkid _whsworkid )
{
WHSWorkLine WHSWorkLine;
WHSWorkLine WHSWorkLineLocation;
WHSUnShip WHSUnShip;
WHSTmpLoadLineInventory tmpLoadLineInv;
WHSLoadLine WHSLoadLine;
;
while select WHSWorkLine
group by LoadLineRefRecId
where WHSWorkLine.WorkId == _whsworkid
&& WHSWorkLine.WorkType == WHSWorkType::Pick
&& WHSWorkLine.WorkStatus == WHSWorkStatus::Closed
{
WHSLoadLine = WHSLoadLine::findbyRecId(WHSWorkLine.LoadLineRefRecId);
WHSUnShip = null;
WHSUnShip = new WHSUnShip();
tmpLoadLineInv = null;
tmpLoadLineInv = WHSUnShip.dmrbuildTmpTable(WHSLoadLine);
while select tmpLoadLineInv
{
select WHSWorkLineLocation
where WHSWorkLineLocation.LoadLineRefRecId == WHSLoadLine.RecId;
WHSUnShip.parmMoveToLocation(WMSLocation::find(WHSWorkLineLocation.WMSLocationId,InventDim::find(WHSWorkLineLocation.inventDimId).inventLocationId));
WHSUnShip.parmDecrementLoadLine(true);
WHSUnShip.unShip(
InventDim::find(tmpLoadLineInv.InventDimId),
tmpLoadLineInv.InventQty, // qty to reduce
WHSLoadLine,
tmpLoadLineInv.ContainerId,
tmpLoadLineInv.InventQty);
}
//info(_whsworkid);
}
info(_whsworkid);
}
}
Bu kodları kullanacaksanız mutlaka canlıdan önce bir ortamda test etmelisiniz. Her kurulum farklı olabilir verilerinizde sorun oluşturma ihtimali olabilir dikkatli olmak lazım. Biz baya test ettik sonunda işimizi gördüğünü düşündük ve canlı ortamda çalıştırdık. Umarım sizin de işinize yarar.
Selamlar.
www.fatihdemirci.net
TAGs: Microsoft Life Cycle Services, LCS, Azure, Azure DevOps, WmsUnShip, Microsoft Dynamics 365, MsDyn365FO, MsDyn365CE, MsDyn365, Segmented Entry, Power Automate, Power Apss, Power Virtual Agents, Dynamics 365 nedir, Dynamics 365 ERP, Dynamics 365 CRM