Thursday, February 13, 2025

X++ Code for Estimating Work Order Costs in Production

 public static estimateWorkOrder(ProdTable _prodTable)

{

                ProdMultiCostEstimation prodMultiCostEstimation;

                prodMultiCostEstimation =  ProdMultiCostEstimation::construct(new Args());

                RunBaseMultiParm::initParm(prodMultiCostEstimation);

                prodMultiCostEstimation.insert(_prodTable, prodMultiCostEstimation.defaultParmBuffer());

                prodMultiCostEstimation.runOperation();

This X++ code is for estimating a work order based on a given production order (referred to as ProdTable _prodTable). Here's a step-by-step breakdown of what the code does:

  1. Define the variable prodMultiCostEstimation:
    • A variable prodMultiCostEstimation of type ProdMultiCostEstimation is declared. This class is responsible for calculating and estimating the multi-cost for a production order.
  2. Initialize prodMultiCostEstimation:
    • prodMultiCostEstimation is instantiated using the static method construct of the ProdMultiCostEstimation class. The Args() constructor is passed, likely to initialize arguments or context for the cost estimation process.
  3. Initialize Parameters (RunBaseMultiParm::initParm):
    • The static method RunBaseMultiParm::initParm(prodMultiCostEstimation) initializes the parameters for the prodMultiCostEstimation. RunBaseMultiParm is a helper class used to manage and initialize parameters in operations that involve multi-step or multi-parameter operations.
  4. Insert production table data:
    • prodMultiCostEstimation.insert(_prodTable, prodMultiCostEstimation.defaultParmBuffer()); inserts the provided production order (_prodTable) into the cost estimation process. It passes the default parameters from prodMultiCostEstimation.defaultParmBuffer(), which likely sets up necessary default configuration for the estimation.
  5. Execute the cost estimation operation:
    • Finally, prodMultiCostEstimation.runOperation() runs the cost estimation operation. This likely calculates the estimated costs based on the provided production order and the parameters set earlier.

Summary:

  • This code is performing cost estimation for a production order (ProdTable _prodTable).
  • It creates an instance of the ProdMultiCostEstimation class, sets it up with default parameters, inserts the production order data, and runs the operation to estimate the costs associated with the production order.

This could be part of a manufacturing or production planning system where the goal is to estimate the cost of producing a specific product or batch of products.

Wednesday, July 29, 2020

Create Movement Journal using X++


    InventJournalId                journalNum;
    JournalCheckPost           journalCheckPost;
    InventDim                      inventDim;
    InventJournalTrans          journalTrans;
    InventJournalTable          inventJournal;
    JournalTableData            journalTableData;
    Counter                          lineNum;
    InventLocation               inventLocation;

public void createJournal()
{
    this.createHeader();
    this.createLine();
    this.postJournal()
}

public void createHeader()
{
        InventJournalName   inventJournalName;
        NumberSeq num;
        num = NumberSeq::newGetNum(InventParameters::numRefInventJournalId());
        journalNum = num.num();
        inventJournalName = InventJournalName::find("JournalName");
        inventJournal.initFromInventJournalName(inventJournalName);
        inventJournal.JournalId     = journalNum;
        inventJournal.JournalType   = InventJournalType::Movement;
        inventJournal.Description = "Description";
        inventJournal.insert();            
        journalTableData = JournalTableData::newTable(inventJournal);
        lineNum++;
}

public void createLine()
{
            inventDim.clear();
            inventDim.initValue();        
            inventDim.InventSiteId  = inventLocation.InventSiteId;
            inventDim.InventLocationId = inventLocation.InventLocationId;
            inventDim.wMSLocationId = inventLocation.WMSlocationIdDefaultIssue;
            inventDim = InventDim::findOrCreate(inventDim);
            journalTrans.clear();
            journalTrans.initValue();
            journalTrans.initFromInventJournalTable(inventJournal);
            journalTrans.JournalType = inventJournal.JournalType;
            journalTrans.TransDate      = "Trans_Date";
            journalTrans.ItemId         = "ItemId";
            journalTrans.InventDimId    = inventDim.InventDimId;
            journalTrans.initFromInventTable(InventTable::find("ItemId")); 
            journalTrans.LineNum        = lineNum;
            journalTrans.Qty            = "Quantity";
            journalTrans.CostAmount     = journalTrans.Qty * journalTrans.CostPrice;
            journalTrans.insert(false);
            lineNum++;
}

public void postJournal()
{
            inventJournal.selectForUpdate(true);
            inventJournal.SystemBlocked = true;
            inventJournal.update();
            journalCheckPost =                     InventJournalCheckPost::newJournalCheckPost(JournalCheckPostType::Post, inventJournal);
            journalCheckPost.run();

}

Monday, July 27, 2020

How to read csv data from SFTP location through Microsoft Flow and Import into Dynamics 365 Finance and Operations

File based integration with Dynamics 365 Finance and Operation using Power Automate

Step 1: Login to Power Automate
Step 2: Create New Flow Connector


Step 3: Add Trigger Point SFTP Folder 'When a file is added or modified'

(This operation triggers a flow when a file is added or modified in a folder. The trigger will fetch both the file metadata as well as the content of the file. The trigger relies on the last modified time of a file. If a file is being created by a third-party client, the preservation of the last modified time should be disabled in the client. Files larger than 50 megabytes are skipped by the trigger)

Step 4: Create SFTP connection and select the folder.
Step 5: Add new Action step 'Get file content'
Step 6: Add new Action step 'Dynamics 365 FO' with in 'Apply to each' action.

Create Purchase Order using X++

PurchTable                        purchTable;
PurchLine                         purchLine;
PurchId                             purchId;
LogisticsPostalAddress    logisticsPostalAddress;

//Create purchase order
public void createPO()
{
    ttsbegin;
    
    this.createHeader();
    this.createLine();
    if(purchId)
    {
            this.postConfirmation();
     }
    ttscommit;
}

//Create purchase order header
public void createHeader()
{
        purchId = NumberSeq::newGetNum(PurchParameters::numRefPurchId()).num();
        purchTable.clear();
        purchTable.PurchId = purchId;
        purchTable.initValue();
        purchTable.initFromVendTable(VendTable::find("VendAccount"));
        purchTable.PurchStatus = PurchStatus::Backorder;
        purchTable.DocumentState = VersioningDocumentState::Approved;
        purchTable.InventSiteId = InventLocation::find("ToWarehouse").InventSiteId;
        purchTable.InventLocationId = "ToWarehouse";
        purchTable.ChangeRequestRequired = NoYes::no;
        purchTable.MCRDropShipment = NoYes::Yes;
        logisticsPostalAddress = InventLocation::find("ToWarehouse").logisticsPostalAddress();
        purchTable.DeliveryName = Logisticslocation::find(logisticsPostalAddress.location).description;
        purchTable.DeliveryPostalAddress = logisticsPostalAddress.RecId;
        purchTable.VendorRef  = "Vendor reference"; //Optional
        purchTable.Requester = "HCMWorkerRecId";
        purchTable.WorkerPurchPlacer = this.getWorkerPurchPlacer();
        purchTable.insert();
}

//Create purchase order line
public void createLine()
{
        purchLine.clear();
        purchLine.PurchId = purchId;
        purchLine.ItemId = "ItemId";
        purchLine.itemIdChanged();
        purchLine.PurchQty = "Quantity";
        purchLine.DeliveryType = TradeLineDlvType::DropShip;
        inventDimfind.InventSiteId = purchTable.InventSiteId;
        inventDimfind.InventLocationId = purchTable.InventLocationId;
        inventDimfind.wMSLocationId = InventLocation::find(purchTable.InventLocationId).WMSLocationIdDefaultReceipt;
        inventDimLines = InventDim::findOrCreate(inventDimfind);
        purchLine.createLine(true, true, true, false, true, true);
        purchLine.selectForUpdate(true);
        purchLine.InventDimId = inventDimLines.inventDimId;
        purchLine.doUpdate();
}

//Post purchase order confirmation
public void postConfirmation()
{
        PurchFormLetter     purchFormLetter;
        purchformletter = PurchFormLetter::construct(documentstatus::PurchaseOrder);
        purchformletter.update(purchtable,
                                strfmt("inv_%1", purchId), systemDateGet(), PurchUpdate::All, 
                                AccountOrder::None,
                                NoYes::No,
                                true,
                                true);
}

public RefRecId getWorkerPurchPlacer ()
{
        UserInfo userInfo;
        RefRecId refRecId;
        select name from userInfo where userInfo.id == curUserId();

        if(userInfo.id != '')
        {        
            refRecId = HcmWorker::findByPerson(DirPerson::find(DirPartyTable::findByName(                                                userInfo.name).RecId).RecId).RecId;
        }
        return refRecId;
}

Sunday, July 26, 2020

Create Transfer Order using X++.


InventTransferTable                 inventTransferTable;

InventTransferLine                  inventTransferLine;

InventTransferId                      inventTransferId;


public void createTransferOrder()

{

     ttsBegin;

     createHeader();

        createLine()

    ttsCommit;

}

Sample code to create header of the Transfer Order

public void createHeader()

{        

        //create the transfer order id.

        inventTransferId = InventTransferTable::numberSeq().num(); 

        inventTransferTable.clear();

        inventTransferTable.initValue();

        inventTransferTable.TransferId = inventTransferId; // assign the transfer order id

        inventTransferTable.InventLocationIdFrom = “FromWarehouse”;  // assign the from warehouse

        inventTransferTable.InventLocationIdTo = “ToWarehouse”; // assign the to warehouse

        inventTransferTable.TransferStatus = InventTransferStatus::Created; // assign the transfer status

        inventTransferTable.DlvModeId = “ShipMethod”; 

        inventTransferTable.ShipDate = “ShipDate”; // assign the ship date

        inventTransferTable.ReceiveDate = “ReceiveDate”; // assign the receive date

        inventTransferTable.AutoReservation = NoYes::No;

        inventTransferTable.initToAddress();

        inventTransferTable.initFromAddress();

        inventTransferTable.InventLocationIdTransit = InventLocation::find(“FromWarehouse”).InventLocationIdTransit;

        inventTransferTable.validateWrite();

        inventTransferTable.insert();

   

Sample code to create line of the Transfer Order

    public void createLine()

    {

        InventDim                   inventDim;

        inventDim.clear();

        inventTransferLine.clear();

        inventDim = inventTransferLine.inventDim();

        inventDim.InventSiteId = InventLocation::find(inventTransferTable.InventLocationIdFrom).InventSiteId;

        inventDim.InventLocationId = inventTransferTable.InventLocationIdFrom;             

        inventTransferLine.initFromInventTransferTable(inventTransferTable,NoYes::Yes);

        inventTransferLine.ItemId = “ItemId”;

        inventTransferLine.LineNum = inventTransferLine::lastLineNum(inventTransferTable.TransferId) + 1;

        inventTransferLine.initFromInventTable(InventTable::find(“ItemId”));

        inventTransferLine.QtyTransfer = “Quantity”;

        inventTransferLine.QtyRemainReceive = “Quantity”;

        inventTransferLine.QtyRemainShip = “Quantity”;

        inventTransferLine.QtyShipNow = 0;

        inventTransferLine.QtyReceiveNow = 0;

        inventTransferLine.RemainStatus = InventTransferRemainStatus::Shipping;

        inventTransferLine.AutoReservation  = NoYes::No;

        inventTransferLine.InventDimId = InventDim::findOrCreate(inventDim).inventDimId;;

        inventTransferLine.insert();      

    }


Wednesday, July 31, 2019

Write csv file on Azure Blob

##How to write csv file on Azure Blob from Dynamics 365 FO using X++?

This blog will explain how and why export data from dynamics 365 using X++ without data entity. There are some scenarios where we can not use directly the data entity to export data from dynamics 365 FO like incremental export. In this situation, we can use following way to export data in CSV/Excel format.
 
 public void WriteCSVFileOnBlob()
 {     
        System.Byte[]                       byteArray;
        System.Text.Encoding                encodingUTF8;
        str                                 accountName ="<<AccountNameOfBlob>>";
        str                                 accountKey ="<<AccountKeyofBlob>>";
str     blobName ="<<BlobName>>";
        str                                 fileName;
        str                                 strRowData;
        boolean                             isColumnsAdded=false;
        LogTable     logTable;
               
     

            if(logTable)
            {
                fileName="inputfilename.csv";

                Microsoft.WindowsAzure.Storage.Auth.StorageCredentials storageCredentials = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(accountName, accountKey);

                Microsoft.WindowsAzure.Storage.CloudStorageAccount storageAccount = new Microsoft.WindowsAzure.Storage.CloudStorageAccount(storageCredentials, true);

                var blobcli = storageAccount.CreateCloudBlobClient();

                Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer cont = blobcli.GetContainerReference(blobName);

                CloudBlockBlob cloudBlockBlob = cont.GetBlockBlobReference(fileName);

                using (Microsoft.WindowsAzure.Storage.Blob.CloudBlobStream x = cloudBlockBlob.OpenWriteAsync().Result)
                {
                    while select logTable where logTable.InputfileName==fileName
                    {
                        if(logTable.RecId>0)
                        {
                            if(!isColumnsAdded)
                            {
                                isColumnsAdded=true;

                                strRowData= strFmt("%1,%2,%3,%4,%5,%6,%7,%8,%9","ItemCode","DocumentNumber","DocumentReference","WarehouseCode","ProcessName","DateTime","InputFileName","ErrorMessage","\r\n");

                                encodingUTF8 = System.Text.Encoding::get_UTF8();
                                byteArray = encodingUTF8.GetBytes(strRowData);
                                x.Write(byteArray,0,byteArray.Length);
                            }


                            strRowData=strFmt("%1,%2,%3,%4,%5,%6,%7,%8,%9",logTable.ItemCode,logTable.DocumentNumber,logTable.DocumentReference,logTable.WarehouseCode,enum2Str(ProcessType),logTable.Datetime,inputfilename,strReplace(logTable.Errormessage,",",";"),"\r\n");

                            encodingUTF8 = System.Text.Encoding::get_UTF8();
                            byteArray = encodingUTF8.GetBytes(strRowData);
                            x.Write(byteArray,0,byteArray.Length);

                        }

                    }

                    if(isColumnsAdded)
                    {
                        x.Flush();
                        x.Close();
                    }

                }
            }

    }