Dynamics365 Multiple ways to implement purchase receipt through X++

Dynamics365 Multiple ways to implement purchase receipt through X++

There are some way to purchase receipt in portal. I am summarize these various methods.


  1. Using purchFormLetter.update()

The simple way to purchase receipt. But the only one purchase order can be receipt.
    public void purchReceiptOnePO(PurchId _purchId, Num _packingSlipId)
    {
        PurchTable purchTable;

        purchTable = PurchTable::find(_purchId);

        PurchFormLetter                  purchFormLetter;
        
        purchFormLetter = purchFormLetter::construct(DocumentStatus::PackingSlip);
        purchFormLetter.showQueryForm(false);
        purchFormLetter.update(purchTable,
                _packingSlipId,
                purchTable.AccountingDate,
                PurchUpdate::All,
                AccountOrder::None,
                false,
                false);

    }        


2. Using SysQuery

You can purchase receipt to multiple purchase order simply. I hope you customize parameter section to your situation.
    public void purchReceiptUsingQuery(container _purchIdCon)
    {
        Query               query;
        SysQueryRun         queryRun;
        PurchFormLetter     purchFormLetter;
        PurchTable          purchTable;
        int                 i;

        // Set query
        query = new Query(queryStr(PurchUpdate));

        // Select purchase order
        for(i = 1 ; i <= conLen(_purchIdCon) ; i++)
        {
            query.dataSourceTable(tableNum(PurchTable)).addRange(fieldNum(PurchTable, PurchId)).value(conPeek(_purchIdCon, i));
        }
        queryRun = new SysQueryRun(query);

        // Post purchase receipt
        purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);
        purchFormLetter.chooseLinesQuery(queryRun);
        purchFormLetter.chooseLines();
        purchFormLetter.createParmUpdateFromParmUpdateRecord(purchFormLetter.purchParmUpdate());

        if(purchFormLetter.prompt())
        {
            purchFormLetter.run();
        }
    }        

3. Partial purchase receipt with item registration

In many articles, they wrote down various ways to do Purchase Receipt. However, I tried to make a standard code that could be done Purchase Receipt with registration to use PurchParmTable, and I was able to make the code as below.

First, you should create contract class. Because I standardize code to use List (Class types).

[DataContractAttribute]
internal final class HDGPurchReceipt_PurchReceiptContract
{
    private PurchId purchId;
    private TradeLineNumber lineNumber;
    private TransDate transDate;
    private Num num;
    private PurchQty receiveQty;
    private boolean register;
    private InventSiteId inventSiteId;
    private InventLocationId inventLocationId;
    private WMSLocationId wMSLocationId;

    [DataMemberAttribute("PurchId")]
    public PurchId PurchId(PurchId _purchId = purchId)
    {
        purchId = _purchId;
        return purchId;
    }

    [DataMemberAttribute("LineNumber")]
    public TradeLineNumber LineNumber(TradeLineNumber _lineNumber = lineNumber)
    {
        lineNumber = _lineNumber;
        return lineNumber;
    }

    [DataMemberAttribute("TransDate")]
    public TransDate TransDate(TransDate _transDate = transDate)
    {
        transDate = _transDate;
        return transDate;
    }

    [DataMemberAttribute("Num")]
    public Num Num(Num _num = num)
    {
        num = _num;
        return num;
    }

    [DataMemberAttribute("ReceiveQty")]
    public PurchQty ReceiveQty(PurchQty _receiveQty = receiveQty)
    {
        receiveQty = _receiveQty;
        return receiveQty;
    }

    [DataMemberAttribute('Register')]
    public boolean Register(boolean _register = register)
    {
        register = _register;
        return register;
    }

    [DataMemberAttribute('InventSiteId')]
    public InventSiteId InventSiteId(InventSiteId _inventSiteId = inventSiteId)
    {
        inventSiteId = _inventSiteId;
        return inventSiteId;
    }

    [DataMemberAttribute('InventLocationId')]
    public InventLocationId InventLocationId(InventLocationId _inventLocationId = inventLocationId)
    {
        inventLocationId = _inventLocationId;
        return inventLocationId;
    }

    [DataMemberAttribute('wMSLocationId')]
    public WMSLocationId wMSLocationId(WMSLocationId _wMSLocationId = wMSLocationId)
    {
        wMSLocationId = _wMSLocationId;
        return wMSLocationId;
    }

}        

After list is serialized, you can purchase receipt yo use below code.

internal final class HDGPurchReceipt_PurchReceiptPartialHelper
{
    PurchParmUpdate                  purchParmUpdate;

    private List gList;

    public List parmPurchReceiptList(List _list)
    {
        gList = _list;
        return gList;
    }

    public void run()
    {
        HDGPurchReceipt_PurchReceiptPartialContract contract;

        PurchFormLetterParmData          purchFormLetterParmData;
        PurchParmTable                   purchParmTable, purchParmTableDuplicate;
        PurchParmLine                    purchParmLine;
        
        
        ListEnumerator listEnumerator = gList.getEnumerator();

        ttsbegin;

        purchFormLetterParmData = PurchFormletterParmData::newData(DocumentStatus::PackingSlip, VersioningUpdateType::Initial);

        purchFormLetterParmData.parmOnlyCreateParmUpdate(true);
        purchFormLetterParmData.createData(false);
        purchParmUpdate = purchFormLetterParmData.parmParmUpdate();

        while(listEnumerator.moveNext())
        {
            contract = listEnumerator.current();

            PurchLine purchLine = PurchLine::find(contract.PurchId(), contract.LineNumber());

            // Validate
            if(!purchLine)
            {
                throw error('Purchase order information is not valid.');
            }

            // If you need register before receipt, set Register to true
            if(contract.Register())
            {
                this.registerPurchLine(contract);
            }

            // Check there is already created proper parmtable
            select firstonly TableRefId, ParmId, RecId
                from purchParmTableDuplicate
                where purchParmTableDuplicate.ParmId == purchParmUpdate.ParmId
                && purchParmTableDuplicate.PurchId == contract.PurchId()
                && purchParmTableDuplicate.TransDate == contract.TransDate();

            // If no, create parmtable
            if(!purchParmTableDuplicate)
            {
                PurchTable purchTable = PurchTable::find(contract.PurchId());

                purchParmTable.clear();

                purchParmTable.TransDate                = contract.TransDate();
                purchParmTable.Ordering                 = DocumentStatus::PackingSlip;
                purchParmTable.ParmJobStatus            = ParmJobStatus::Waiting;
                purchParmTable.Num                      = contract.Num();
                purchParmTable.PurchId                  = purchTable.PurchId;
                purchParmTable.PurchName                = purchTable.PurchName;
                purchParmTable.OrderAccount             = purchTable.OrderAccount;
                purchParmTable.CurrencyCode             = purchTable.CurrencyCode;
                purchParmTable.InvoiceAccount           = purchTable.InvoiceAccount;
                purchParmTable.DeliveryName             = purchTable.DeliveryName;
                purchParmTable.DeliveryPostalAddress    = purchTable.DeliveryPostalAddress;
                purchParmTable.ParmId                   = purchParmUpdate.ParmId;

                purchParmTable.insert();
            }
            // If Yes, use created parmtable
            else
            {
                purchParmTable = PurchParmTable::findRecId(purchParmTableDuplicate.RecId);
            }
            
            // Create parmline
            purchParmLine.clear();

            purchParmLine.initFromPurchLine(purchLine);

            purchParmLine.ReceiveNow    = contract.ReceiveQty();
            purchParmLine.ParmId        = purchParmTable.ParmId;
            purchParmLine.TableRefId    = purchParmTable.TableRefId;
            purchParmLine.setQty(DocumentStatus::PackingSlip, false, true);
            purchParmLine.setLineAmount();
            
            if(contract.Register())
            {
                InventDim receivedInventDim;

                receivedInventDim.InventSiteId = contract.InventSiteId();
                receivedInventDim.InventLocationId = contract.InventLocationId();
                receivedInventDim.wMSLocationId = contract.wMSLocationId();

                purchParmLine.InventDimId = InventDim::findOrCreate(receivedInventDim).inventDimId;
            }

            purchParmLine.insert();
        }

        // Post purchase receipt
        this.postPurchReceipt();

        ttscommit;
    }

    private void registerPurchLine(HDGPurchReceipt_PurchReceiptPartialContract _contract)
    {
        PurchLine               purchLine;
        InventTrans             inventTranslocal;
        InventDim               inventDimlocal;

        purchLine = PurchLine::find(_contract.PurchId(), _contract.LineNumber());

        // Get original InventTransId, InventDim
        inventTranslocal = InventTrans::findTransId(purchLine.InventTransId, true);
        inventDimlocal   = inventTranslocal.inventDim();
 
        // Set InventDim to InventTrans record
        inventDimlocal.wMSLocationId    = _contract.wMSLocationId();
        inventDimlocal.InventLocationId = _contract.InventLocationId();
        inventDimlocal.InventSiteId     = _contract.InventSiteId();
        inventDimlocal                  = InventDim::findOrCreate(inventDimlocal);
        inventTranslocal.inventDimId    = inventDimlocal.inventDimId;

        // Create register data
        InventTransWMS_Register inventTransWMS_register;
        TmpInventTransWMS       tmpInventTransWMS;

        inventTransWMS_register         = inventTransWMS_register::newStandard(tmpInventTransWMS);

        tmpInventTransWMS.clear();
        tmpInventTransWMS.initFromInventTrans(inventTranslocal);
        tmpInventTransWMS.ItemId    = inventTranslocal.ItemId;
        tmpInventTransWMS.InventQty = _contract.ReceiveQty();
        tmpInventTransWMS.insert();

        inventTransWMS_register.writeTmpInventTransWMS(tmpInventTransWMS,
                                                       inventTranslocal,
                                                       inventDimlocal);
       
        inventTransWMS_register.updateInvent(inventTranslocal);
    }

    private void postPurchReceipt()
    {
        PurchFormLetter                  purchFormLetter;
        
        purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);
        purchFormLetter.transDate(DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone()));
        purchFormLetter.specQty(PurchUpdate::All);

        purchFormLetter.parmParmTableNum(purchParmUpdate.ParmId);
        purchFormLetter.parmId(purchParmUpdate.ParmId);
        purchFormLetter.purchParmUpdate(purchParmUpdate);
        purchFormLetter.run();
    }
}        

I write the comment on code, please refer that.

Also, you can check on GitHub too. (HDG_Dynamics365-Xpp-Samples/Purch_Receipt_MutipleWay/AxClass at main · ans1148/HDG_Dynamics365-Xpp-Samples (github.com))


Thanks for reading!

要查看或添加评论,请登录

DongGyun Ha的更多文章

社区洞察

其他会员也浏览了