Friday, February 17, 2023

Convert data type from/To Dot Net in D365FO X++

    /// Converts enum from .Net object. 

    public server static int convertEnumFromDotNet(System.Object _dotNetEnumValue)

    {

        int ret = CLRInterop::getAnyTypeForObject(_dotNetEnumValue);

        return ret;

    }


    /// Converts enum to .Net object.

    public server static CLRObject convertEnumToDotNet(EnumName _enumName, anytype _enumValue)

    {

        CLRObject ret = Microsoft.Dynamics365.Tax.Core.TaxEngineService::intToEnum(

            _enumName,

            enum2int(_enumValue));

       

        return ret;

    }


    /// Converts field from .Net object.

    public server static anytype convertFieldValueFromDotNet(System.Object _dotNetValue)

    {

        anytype     ret;


        if (_dotNetValue)

        {

            ERIEnumValue dotNetEREnumValue = _dotNetValue as ERIEnumValue;

            if (dotNetEREnumValue != null)

            {

                ret = new EREnumValueBase(

                    dotNetEREnumValue.getEnumName(),

                    dotNetEREnumValue.getTypeNamePrefix(),

                    dotNetEREnumValue.getName(),

                    dotNetEREnumValue.getLabel());

            }

            else

            {

                ret = CLRInterop::getAnyTypeForObject(_dotNetValue);

            }

        }


        return ret;

    }

Monday, January 30, 2023

Spliting Online store transaction in D365FO X++

//Online store transaction - Retail synchronize order

[ExtensionOf(classStr(RetailSyncOrdersSchedulerTask))]

final class RetailSyncOrdersSchedulerTaskCls_POL_Extension

{

    public void run()

    {

        Array             listOfCurTransactions, listOfTransactionsPostOrderSplit;


        listOfTransactionsPostOrderSplit= new Array(Types::Int64);

         listOfCurTransactions = Array::create(this.parmPackedTransactionRecIdList());


        listOfTransactionsPostOrderSplit= SANOrderSplit::splitOrders( listOfCurTransactions);

        this.parmPackedTransactionRecIdList(listOfTransactionsPostOrderSplit.pack());


        next run();

    }


}

Wednesday, January 25, 2023

Azure copy & move files from Blob storage in D635FO X++

 using Microsoft.Azure;

using Microsoft.WindowsAzure.Storage;

using Microsoft.WindowsAzure.Storage.Blob;


using Microsoft.WindowsAzure.Storage.Auth;

using Microsoft.Dynamics.AX.Framework.FileManagement;

using fileShareStorage = Microsoft.WindowsAzure.Storage.File;


class SANAzureBlobFileMove

{

    /// <summary>

    /// Runs the class with the specified arguments.

    /// </summary>

    /// <param name = "_args">The specified arguments.</param>

    public static void main(Args _args)

    {

        SAN_FileIntegrationParameters   fileParameters;

        str                             azureBlobFolderPath;

        CloudBlobClient                 blobClient;

        Filename                        folderPath ='DailyPortalOrder';

        Name                            containerReference = 'dp';

        str                             fileName;

        #File


        fileName = 'TestFile.Txt';

        fileParameters = SAN_FileIntegrationParameters::find();


        KeyVaultCertificateTable    certificateTable= KeyVaultCertificateTable::findByName(fileParameters.AuthorizationSecretName);

        str keyvaultValue   = KeyVaultCertificateHelper::getManualSecretValue(certificateTable.RecId);


        if (fileParameters.AuthorizationSecretName == "")

        {

            throw error("Key vault authorization secert must be specified");

        }


        try

        {

            System.Uri  uri = new System.Uri(keyvaultValue);

            blobClient = new CloudBlobClient(uri);

            if (folderPath)

            {

                azureBlobFolderPath = containerReference + #FilePathDelimiter + folderPath;

            }

            else

            {

                azureBlobFolderPath = containerReference;

            }

            

            CloudBlobContainer blobcontainer = blobClient.GetContainerReference(azureBlobFolderPath);

            CloudBlobContainer sourceBlobcontainer = blobClient.GetContainerReference(containerReference);

            CloudBlobContainer destBlobcontainer = blobClient.GetContainerReference(containerReference);

            /*

            CloudBlobDirectory  cloudBlobDirectory;

            Container  con;

            cloudBlobDirectory = blobcontainer.GetDirectoryReference("DailyPortalOrder");

            System.Collections.IEnumerable lstEnumarable = cloudBlobDirectory.ListBlobs(false, 0, null, null);

            System.Collections.IEnumerator lstEnumarator = lstEnumarable.GetEnumerator();

            List filenames = new List(Types::String);

            while(lstEnumarator.MoveNext())

            {

                IListBlobItem item = lstEnumarator.Current;

                if(item is CloudBlockBlob)

                {

                    CloudBlockBlob blob = item;

                    blob.FetchAttributes(null, null, null);

                    con = str2con(blob.name, "/");

                    filenames.addStart(conPeek(con,conlen(con)));

                    info(blob.name);

                    //System.IO.StreamReader  reader = new System.IO.StreamReader(blob.OpenRead(null, null, null));

                    //Info(reader.ReadToEnd());

                }

            }

            */


            System.Byte[] reportBytes = new System.Byte[0]();

            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();

            reportBytes = enc.GetBytes("SAN TEST TEXT");

            System.IO.MemoryStream stream = new System.IO.MemoryStream(reportBytes);

            CloudBlockBlob      blockBlob = blobcontainer.GetBlockBlobReference(fileName);

            blockBlob.UploadFromByteArray(stream.ToArray(),0,stream.ToArray().Length, null,null,null);


            info(strfmt("updloaded to file path %1 %2 %3", fileName, fileParameters.AzureStorageAccountName, azureBlobFolderPath));


            CloudBlobDirectory sourceCloudBlobDirectory = sourceBlobcontainer.GetDirectoryReference("DailyPortalOrder/");

            CloudBlobDirectory destinationCloudBlobDirectory = destBlobcontainer.GetDirectoryReference("DailyPortalOrder/archive");

            CloudBlockBlob SourceBlob = sourceCloudBlobDirectory.GetBlockBlobReference(fileName);

            CloudBlockBlob destinationBlob = destinationCloudBlobDirectory.GetBlockBlobReference(fileName);

            destinationBlob.UploadFromStream(blockBlob.OpenRead(null,null,null),null,null,null);

            blockBlob.Delete(0,null,null,null);

            

            CloudBlockBlob      blockBlob = blobcontainer.GetBlockBlobReference(_fileName);

            blockBlob.UploadFromByteArray(_memoryStream.ToArray(),0,_memoryStream.ToArray().Length, null,null,null);

        }

        catch(Exception::Error)

        {

            error("Error on file processing");

        }

    }


}


Monday, January 23, 2023

Sync D365FO/AX table to Commerce DB in D365FO


Subscribe to Event handler.

    [SubscribesTo(classStr(RetailCDXSeedDataBase), delegateStr(RetailCDXSeedDataBase, registerCDXSeedDataExtension))]

    public static void RetailCDXSeedDataBase_registerCDXSeedDataExtension(str originalCDXSeedDataResource, List resources)

    {

        if (originalCDXSeedDataResource == resourceStr(RetailCDXSeedDataAX7))

        {

            resources.addEnd(resourceStr(SAN_SalesOrderClassResource));

            resources.addEnd(resourceStr(smmBusRelSectorTableResource));

        }

    }


Create D365FO resource (SAN_SalesOrderClassResource) for new table.

Resource content: XML

<RetailCdxSeedData ChannelDBMajorVersion="7" ChannelDBSchema="ext" Name="AX7">

   <Subjobs>

       <Subjob Id="SAN_SalesOrderClass" TargetTableSchema="ext" AxTableName="SAN_SalesOrderClass">

           <ScheduledByJobs>

               <ScheduledByJob>1140</ScheduledByJob>

           </ScheduledByJobs>

           <AxFields>

              <Field Name="SALESORDERCLASS"/>

<Field Name="MAXQTY"/>

<Field Name="AVAILABLEFROM"/>

<Field Name="AVAILABLETO"/>

<Field Name="SOALLOCPRIORITY"/>

<Field Name="PAYMTERMID"/>

<Field Name="HOLDCODE"/>      

<Field Name="RECID"/>

    <Field Name="RECVERSION"/>

    <Field Name="PARTITION"/>

            </AxFields>

       </Subjob>

   </Subjobs>

</RetailCdxSeedData>


Tuesday, January 17, 2023

Embedded PDF stream to XML in D365FO X++

 

Embedded PDF stream to XML in D365FO X++


We can use either code 1 or code 2,


Code:1

Public System.Xml.XmlElement embed(

            System.Xml.XmlElement   _parentElement,

            Name                    _elementName,

            System.IO.Stream        _pdfStream)

    {

System.Xml.XmlDocument      document;

System.Xml.XmlElement       element;

System.Xml.XmlDocument      ownerDocument;


System.Byte[]               bytes;

    System.IO.BinaryReader      binaryReader;

    System.IO.Stream            baseStream;

    System.IO.StreamReader      streamReader;

    System.Object               streamObject;

    System.Object               bytesObject;

    System.Xml.XmlCDataSection  cdata;


int                         streamLength;

    int                         bytesLength;

    str                         base64data;


        element = document.CreateElement(_elementName);


        if (_pdfStream != null)

        {

            baseStream      = _pdfStream;

            streamObject    = baseStream.get_Length();

            streamLength    = streamObject;

            binaryReader    = new System.IO.BinaryReader(baseStream);

            bytes           = binaryReader.ReadBytes(streamLength);


            baseStream.Close();


            ownerDocument   = element.get_OwnerDocument();

            bytesObject     = bytes.get_Length();

            bytesLength     = bytesObject;

            base64data      = System.Convert::ToBase64String(bytes, 0, bytesLength);

            cdata           = ownerDocument.CreateCDataSection(base64data);


            element.AppendChild(cdata);

        }


        _parentElement.AppendChild(element);


        return element;

    }


Code 2:

System.Xml.XmlElement embed(

            System.Xml.XmlElement   _parentElement,

            Name                    _elementName,

            System.IO.Stream        _pdfStream)

    {

        element = document.CreateElement(_elementName);


        if (_pdfStream != null)

        {

            using (System.IO.Stream fileStream = _pdfStream)

            {

                using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())

                {

                    fileStream.CopyTo(memoryStream);

                    base64data =  ERConversionUtils::StreamToBase64(memoryStream);

                    ownerDocument   = element.get_OwnerDocument();

                    cdata           = ownerDocument.CreateCDataSection(base64data);

                    element.AppendChild(cdata);

                }

            }

        }


        _parentElement.AppendChild(element);


        return element;

    }

Friday, January 6, 2023

SQL Query to fetch Related information based on transaction type from TaxTrans in D365FO

//Query to Fetch Related information based on transaction type and tagged Masters (Customer/Vendor) from 

Posted Sales Tax

1. Type (Customer or vendor or ledger)

2. Identification (Customer or vendor account name or Voucher entries text)

//These columns also be converted to Computed column (T-SQL) in view.


Query:

 CAST

                 ((SELECT TOP (1) CAST((CASE WHEN tt.Voucher =

                                   (SELECT TOP (1) ct.Voucher

                                   FROM    CUSTTRANS AS ct

                                   WHERE ct.VOUCHER = tt.VOUCHER AND ct.TRANSDATE = tt.TRANSDATE AND ct.DATAAREAID = tt.DATAAREAID) THEN 'Customer' ELSE CASE WHEN tt.Voucher =

                                   (SELECT TOP (1) vt.Voucher

                                   FROM    VendTrans AS vt

                                   WHERE vt.VOUCHER = tt.VOUCHER AND vt.TRANSDATE = tt.TRANSDATE AND vt.DATAAREAID = tt.DATAAREAID) THEN 'Vendor' ELSE 'Ledger' END END) AS NVARCHAR(10)) AS Expr1

                  FROM    dbo.TAXTRANS AS tt

                  WHERE (RECID = T1.RECID)) AS NVARCHAR(60)) AS TYPE,


 

CAST

                 ((SELECT TOP (1) dpt.NAME

                  FROM    dbo.CUSTTRANS AS ct INNER JOIN

                               dbo.CUSTTABLE AS ctab ON ctab.ACCOUNTNUM = ct.ACCOUNTNUM AND ct.DATAAREAID = ctab.DATAAREAID INNER JOIN

                               dbo.DIRPARTYTABLE AS dpt ON dpt.RECID = ctab.PARTY

                  WHERE (ct.VOUCHER = T1.VOUCHER) AND (ct.TRANSDATE = T1.TRANSDATE) AND (ct.DATAAREAID = T1.DATAAREAID)

                  UNION ALL

                  SELECT TOP (1) dpt.NAME

                  FROM   dbo.VENDTRANS AS vt INNER JOIN

                               dbo.VENDTABLE AS vtab ON vtab.ACCOUNTNUM = vt.ACCOUNTNUM AND vt.DATAAREAID = vtab.DATAAREAID INNER JOIN

                               dbo.DIRPARTYTABLE AS dpt ON dpt.RECID = vtab.PARTY

                  WHERE (vt.VOUCHER = T1.VOUCHER) AND (vt.TRANSDATE = T1.TRANSDATE) AND (vt.DATAAREAID = T1.DATAAREAID)

                  UNION ALL

                  SELECT TOP (1) gjae.TEXT

                  FROM   dbo.GENERALJOURNALENTRY AS gje INNER JOIN

                               dbo.GENERALJOURNALACCOUNTENTRY AS gjae ON gjae.GENERALJOURNALENTRY = gje.RECID

                  WHERE (NOT EXISTS

                                   (SELECT TOP (1) VOUCHER

                                   FROM    dbo.CUSTTRANS AS ct2

                                   WHERE (VOUCHER = T1.VOUCHER) AND (TRANSDATE = T1.TRANSDATE) AND (DATAAREAID = T1.DATAAREAID))) AND (NOT EXISTS

                                   (SELECT TOP (1) VOUCHER

                                   FROM    dbo.VENDTRANS AS vt2

                                   WHERE (VOUCHER = T1.VOUCHER) AND (TRANSDATE = T1.TRANSDATE) AND (DATAAREAID = T1.DATAAREAID))) AND (gje.SUBLEDGERVOUCHER = T1.VOUCHER) AND (gje.ACCOUNTINGDATE = T1.TRANSDATE) AND 

                               (gje.SUBLEDGERVOUCHERDATAAREAID = T1.DATAAREAID)) AS NVARCHAR(100)) AS IDENTIFICATION 

FROM   dbo.TAXTRANS AS T1

Capture all Error logs trace in D365FO

    [SubscribesTo(classStr(Info), delegateStr(Info, onInfoLogMessageAdd))]

    public static void Info_onInfoLogMessageAdd(InfoLogMessageAddEventArgs _eventArgs)

    {

        SANPOCDebugTable    sanPOCDebugTable; (Enable with CreatedDateTime)

        boolean                      iscallStackUserEnabled;

            iscallStackUserEnabled = true;//Added custom checkbox on custom user setting

                   if(_eventArgs.exception == Exception::Info || 

                           _eventArgs.exception == Exception::Warning)

                    {

                        //If want to skip validation
                    }

                  else

                {

                sanPOCDebugTable.clear();

                sanPOCDebugTable.initValue();

                sanPOCDebugTable.RunByuserId = curuserid();

                sanPOCDebugTable.Exception = _eventArgs.exception;

                sanPOCDebugTable.InfologStr = _eventArgs.message;

                sanPOCDebugTable.CallStack = xSession::xppCallStack();

                sanPOCDebugTable.insert();

                }

}

//Create new form and add table on it -> Add button to import log information

//To Clean up -> Create batch run -> run to clean up data for past 90 days

//To add this new log form -> generic to all form UI. (To review logs)

Ref: Blog on Microsoft Dynamics AX/ D365: To add dynamics default controls on UI in D365FO (sangeethwiki.blogspot.com)

Tuesday, December 27, 2022

Posting Invoice/Product Receipt/Packing Slip - D365FO X++

Posting Vendor invoice based on Product receipt

public void postPurchaseInvoiceJournal()

    {

        VendPackingSlipJour             vendPackingSlipJour;

        VendPackingSlipTrans            vendPackingSlipTrans;

        TmpFrmVirtual                   tmpFrmVirtual;

        boolean                         isValidToProcess = false;

        container                       conTmpFrmVirtual;

        SysQueryRun                     chooseLinesQuery;

        SysQueryRun                     chooseLinesPendingInvoiceQuery;


        select firstonly vendPackingSlipJour

            order by RecId desc

            where vendPackingSlipJour.PackingSlipId == shipmentId;


        if(vendPackingSlipJour)

        {

            isValidToProcess = true;

        }


        chooseLinesQuery = new SysQueryRun(queryStr(PurchUpdate));

       

        List packingSlipList = new List(Types::Record);

        while select OrigPurchId from vendPackingSlipTrans

            group by OrigPurchId

            where vendPackingSlipTrans.PackingSlipId == vendPackingSlipJour.PackingSlipId

        {

            tmpFrmVirtual.clear();

            tmpFrmVirtual.TableNum      = tableNum(VendPackingSlipJour);

            tmpFrmVirtual.RecordNo      = vendPackingSlipJour.RecId;

            tmpFrmVirtual.NoYes         = NoYes::Yes;

            tmpFrmVirtual.Id            = vendPackingSlipTrans.OrigPurchId;

            tmpFrmVirtual.insert();


            packingSlipList.addEnd(tmpFrmVirtual);

            conTmpFrmVirtual            = packingSlipList.pack();


            chooseLinesQuery.query().dataSourceTable(tableNum(PurchTable)).addRange(fieldNum(PurchTable, PurchId)).value(queryValue(vendPackingSlipTrans.OrigPurchid));

        }


        chooseLinesQuery.query().interactive (false);

        chooseLinesQuery.saveUserSetup (false);

        chooseLinesQuery.query().addDataSource(tableNum(VendInvoiceInfoTable)).enabled(false);


        chooseLinesPendingInvoiceQuery = new SysQueryRun(queryStr(PurchUpdatePendingInvoice));

        chooseLinesPendingInvoiceQuery.query().dataSourceTable(tableNum(PurchTable)).addRange(fieldNum(PurchTable,PurchId)).value(queryValue(''));


        TransDate postingDate = getTodayDate;


        PurchFormLetter_Invoice purchFormLetter;

        purchFormLetter = PurchFormLetter::construct(DocumentStatus::Invoice);

        purchFormLetter.chooseLinesQuery (chooseLinesQuery);

        purchFormLetter.parmQueryChooseLinesPendingInvoice(chooseLinesPendingInvoiceQuery);

        purchFormLetter.transDate (postingDate);

        purchFormLetter.parmParmTableNum(shipmentId);

        purchFormLetter.printFormLetter (NoYes::No);

        purchFormLetter.sumBy (AccountOrder::Account);

        purchFormLetter.specQty (PurchUpdate::PackingSlip);

        purchFormLetter.selectFromJournal(conTmpFrmVirtual);

        purchFormLetter.reArrangeNow(true);         

        purchFormLetter.runOperation();


        if(purchFormLetter.parmJournalRecord())

        {            

            VendInvoiceJour                 invoiceJour;

            

            invoiceJour = VendInvoiceJour::findRecId(purchFormLetter.parmJournalRecord().RecId);

            if(invoiceJour)

            {

//Successful posting

            }

        }

    }


Process Customer invoice based on PackingSlip

--> Normal Sales order/ Direct delivery sales order

public void processSalesInvoiceDataToPost(str  _salesPackingSlipId)

    {

        salesFormletterParmData     salesFormLetterParmData;

        SalesParmUpdate             salesParmUpdate;

        SalesTable                  salesTable;

        SalesParmTable              salesParmTable;

        CustPackingSlipJour         custPackingSlipJour;

        CustPackingSlipTrans        custPackingSliptrans;

        SalesLine                   salesLine;


        TransDate postingDate = getToday;


        select firstonly custPackingSlipJour

            where custPackingSlipJour.PackingSlipId == _salesPackingSlipId;


        salesFormLetterParmData = salesFormletterParmData::newData(DocumentStatus::Invoice, VersioningUpdateType::Initial);

       

        salesFormLetterParmData.parmOnlyCreateParmUpdate(true);

        salesFormLetterParmData.parmProforma(this.parmIsProformaProcess());

        salesFormLetterParmData.createData(false);

        salesParmUpdate = salesFormLetterParmData.parmParmUpdate();


        InventTransOrigin       inventTransOrigin;

        InventTrans             inventTrans;


        if(_salesPackingSlipId)

        {

            salesTable  = salesTable::find(custPackingSlipJour.SalesId);

            salesParmTable.clear();

            salesParmTable.TransDate                = transportInvoiceTable.InvoiceDate;

            salesParmTable.Ordering                 = DocumentStatus::Invoice;

            salesParmTable.ParmJobStatus            = ParmJobStatus::Waiting;

            salesParmTable.salesId                  = salesTable.salesId;

            salesParmTable.salesName                = salesTable.salesName;

            salesParmTable.DeliveryName             = salesTable.DeliveryName;

            salesParmTable.DeliveryPostalAddress    = salesTable.DeliveryPostalAddress;

            salesParmTable.CustAccount              = salesTable.CustAccount;

            salesParmTable.CurrencyCode             = salesTable.CurrencyCode;

            salesParmTable.InvoiceAccount           = salesTable.InvoiceAccount;

            salesParmTable.ParmId                   = salesParmUpdate.ParmId;

            salesParmTable.insert();

       

            while select custPackingSliptrans group by OrigSalesId

                where custPackingSliptrans.PackingSlipId == custPackingSlipJour.PackingSlipId

                    && custPackingSliptrans.OrigSalesId != custPackingSlipJour.SalesId

            {

                this.processSalesParmSubTableData(salesParmTable, SalesTable::find(custPackingSliptrans.OrigSalesId));

            }

       

            custPackingSliptrans.clear();

            while select custPackingSliptrans

                where custPackingSliptrans.PackingSlipId == custPackingSlipJour.PackingSlipId

                    join salesLine

                        where salesLine.InventTransId == custPackingSliptrans.InventTransId

            {

                this.processSalesParmLinesTableData(salesParmTable, salesLine, custPackingSliptrans);

            }

        }

        else 

        {

            //Update reference on salesParmUpdate

            if(salesParmUpdate)

            {

                ttsbegin;

                salesParmUpdate.selectForUpdate(true);

                salesParmUpdate.SpecQty        = SalesUpdate::PickingList;

                salesParmUpdate.update();

                ttscommit;

            }

        SalesFormLetter_Invoice salesFormLetter = salesFormLetter::construct(DocumentStatus::Invoice);

        salesFormLetter.transDate(postingDate);

        salesFormLetter.proforma(this.parmIsProformaProcess()); 

         salesFormLetter.specQty(salesUpdate::PackingSlip); 

        salesFormLetter.salesTable(salesTable);

        salesFormLetter.parmId(salesParmTable.ParmId);

        salesFormLetter.salesParmUpdate(salesFormLetterParmData.parmParmUpdate());

        if(//Need print destination setting)

        {

            SRSPrintDestinationSettings     printSettings = new SRSPrintDestinationSettings();

            PrintSetupOriginalCopy          printSetupOriginalCopy;


            printSetupOriginalCopy = this.parmIsProformaProcess() ? PrintSetupOriginalCopy::Copy : PrintSetupOriginalCopy::Original;

            printSettings = new SRSPrintDestinationSettings(salesFormLetter.printerSettingsFormletter(printSetupOriginalCopy));

            printSettings.printMediumType(PrintMediumType::Printer);

            //printSettings.DestinationSettings(printSettings);

            salesFormLetter.updatePrinterSettingsFormLetter(printSettings.pack());

        }

//To open FORM, User will click post

        salesFormLetter.startOperation();// process operation to post invoice

//To Direct POST without UI FORM open

        salesFormLetter.runOperation();// process operation to post invoice


        if (salesFormLetter.parmJournalRecord().RecId )

        {

// Success posting

        }

    }


    /// <summary>

    /// Process sales update parm history sub table data for posting invoice

    /// </summary>

    /// <param name = "_salesParmTable">current salesParmTable</param>

    /// <param name = "_SalesTable">current sales id to process</param>

    public void processSalesParmSubTableData(SalesParmTable     _salesParmTable, SalesTable     _SalesTable)

    {

        SalesParmSubTable       parmSubTable;


        parmSubTable.clear();

        parmSubTable.initValue();

        parmSubTable.InitFromSalesParmTable(_salesParmTable);

        parmSubTable.initFromSalesTable(_SalesTable);

        parmSubTable.insert();

    }


    /// <summary>

    /// Process sales update parm history sub line table data for posting invoice

    /// </summary>

    /// <param name = "_salesParmTable">current salesParmTable</param>

    /// <param name = "_salesLine">current salesLine</param>

    /// <param name = "_custPackingSliptrans">current custPackingslipTrans</param>

    /// <param name = "_qty">current trasnprot line qty</param>

    public void processSalesParmLinesTableData(SalesParmTable       _salesParmTable, SalesLine      _salesLine, CustPackingSlipTrans    _custPackingSliptrans, Qty      _qty = 0)

    {

        SalesParmLine       salesParmLine;

        SalesParmSubLine    salesParmSubLine;


        salesParmLine.clear();

        salesParmLine.initValue();

        salesParmLine.InitFromsalesLine(_salesLine);

        salesParmLine.DeliverNow    = _qty ? _qty : _custPackingSliptrans.Qty;  

        salesParmLine.ParmId        = _salesParmTable.ParmId;

        salesParmLine.TableRefId    = _salesParmTable.TableRefId;

        salesParmLine.setQty(DocumentStatus::Invoice, false, true);

        salesParmLine.setLineAmount(_salesLine);

        salesParmLine.insert();


        salesParmSubLine.clear();

        salesParmSubLine.initValue();

        salesParmSubLine.initFromCustPackingSlipTrans(_custPackingSliptrans);

        salesParmSubLine.initFromSalesParmLine(salesParmLine);

        if(_custPackingSliptrans    == null) 

        {

            salesParmSubLine.InventNow              = _qty;

            salesParmSubLine.DeliverNow             = _qty;

        }

        salesParmSubLine.insert();

    }


    public void processMultipleSOInvoice()

    {

        SalesFormLetter_invoice salesFormLetter;

        CustPackingSlipJour custPackingSlipJour;

        TmpFrmVirtual tmpFrmVirtual;

        salesFormletterParmData     salesFormLetterParmData;

        SalesParmLine   salesParmLine;

        SalesParmUpdate             salesParmUpdate;

        List selectedList = new List(Types::Record);


        tmpFrmVirtual.setTmp();     

        while select from custPackingSlipJour

            where custPackingSlipJour.ReferenceId== 'ReferenceId' //Reference Id custom field

        {          


            tmpFrmVirtual.clear();

            tmpFrmVirtual.TableNum = custPackingSlipJour.TableId;

            tmpFrmVirtual.RecordNo = custPackingSlipJour.RecId;

            tmpFrmVirtual.NoYes = NoYes::Yes;

            tmpFrmVirtual.Id = custPackingSlipJour.SalesId;

            tmpFrmVirtual.insert();

            if (!salesParmUpdate)

            {

                salesFormLetterParmData = salesFormletterParmData::newData(DocumentStatus::Invoice, VersioningUpdateType::Initial);

       

                salesFormLetterParmData.parmOnlyCreateParmUpdate(true);

                salesFormLetterParmData.parmProforma(this.parmIsProformaProcess());//Added code bug fix 410277

                salesFormLetterParmData.createData(false);

                salesParmUpdate = salesFormLetterParmData.parmParmUpdate();

            }

            this.processMultipleSalesInvoiceParmData(custPackingSlipJour,salesParmUpdate);

        }


        while select tmpFrmVirtual

        {

            selectedList.addEnd(tmpFrmVirtual);

        }


     

        // Construct form letter

        salesFormLetter = salesFormLetter::construct(DocumentStatus::Invoice);

        // Add the packing slips to the sales form letter

        salesFormLetter.selectFromJournal(selectedList.pack());

        select firstonly salesParmLine

               where salesParmLine.ParmId == salesParmUpdate.ParmId;

       

        if(salesParmLine)

       

        {

            salesFormLetter.salesParmUpdate(salesParmUpdate);

        }

        // Reorganize as desired

        salesFormLetter.specQty(SalesUpdate::PackingSlip);

        salesFormLetter.sumBy(AccountOrder::Auto);

        salesFormLetter.transDate(transportInvoiceTable.InvoiceDate);

   


        salesFormLetter.reArrangeNow(true);

        salesFormLetter.parmId(salesParmUpdate.ParmId);

        salesFormLetter.startOperation();

     

    }


    public void processMultipleSalesInvoiceParmData(CustPackingSlipJour _custPackingSlipJour,

                                            SalesParmUpdate     _salesParmUpdate)

    {

        SalesParmUpdate             salesParmUpdate = _salesParmUpdate;

        SalesTable                  salesTable;

        SalesParmTable              salesParmTable;

        CustPackingSlipJour         custPackingSlipJour = _custPackingSlipJour;

        CustPackingSlipTrans        custPackingSliptrans;

        SalesLine                   salesLine;


        TransDate postingDate = getToday;


        if(_custPackingSlipJour.PackingSlipId)

        {

            salesTable  = salesTable::find(custPackingSlipJour.SalesId);

            salesParmTable.clear();

            salesParmTable.TransDate                = transportInvoiceTable.InvoiceDate;

            salesParmTable.Ordering                 = DocumentStatus::Invoice;

            salesParmTable.ParmJobStatus            = ParmJobStatus::Waiting;

            salesParmTable.salesId                  = salesTable.salesId;

            salesParmTable.salesName                = salesTable.salesName;

            salesParmTable.DeliveryName             = salesTable.DeliveryName;

            salesParmTable.DeliveryPostalAddress    = salesTable.DeliveryPostalAddress;

            salesParmTable.CustAccount              = salesTable.CustAccount;

            salesParmTable.CurrencyCode             = salesTable.CurrencyCode;

            salesParmTable.InvoiceAccount           = salesTable.InvoiceAccount;

            salesParmTable.ParmId                   = salesParmUpdate.ParmId;

            salesParmTable.insert();

       

            while select custPackingSliptrans group by OrigSalesId

                where custPackingSliptrans.PackingSlipId == custPackingSlipJour.PackingSlipId

                    && custPackingSliptrans.OrigSalesId != custPackingSlipJour.SalesId

            {

                this.processSalesParmSubTableData(salesParmTable, SalesTable::find(custPackingSliptrans.OrigSalesId));

            }

       

            custPackingSliptrans.clear();

            while select custPackingSliptrans

                where custPackingSliptrans.PackingSlipId == custPackingSlipJour.PackingSlipId

                    join salesLine

                        where salesLine.InventTransId == custPackingSliptrans.InventTransId

            {

                this.processSalesParmLinesTableData(salesParmTable, salesLine, custPackingSliptrans);

            }

        }

       

    }


Process Purchase product receipt - Post

public void postProductReceiptJournal()

    {

        PurchFormLetter             purchFormLetter;

        PurchFormletterParmData     purchFormLetterParmData;

        PurchParmUpdate             purchParmUpdate;

        PurchParmTable              purchParmTable;       

        SanJournalTrans   jourTrans; //Custom table

        PurchTable                  purchTable;

        PurchLine                   purchLine;

        PurchId                     purchId;

        container                   conPurchList;

        Num                         packingSlipId = purchInvoiceHeaderInbound.InvoiceId;


        purchFormLetterParmData = PurchFormletterParmData::newData(

        DocumentStatus::PackingSlip,

        VersioningUpdateType::Initial);


        select firstonly jourTrans

            where jourTrans.JournalId == this.journalId;

        purchId = jourTrans.PurchId;


        purchTable = PurchTable::find(purchId, false);

    

        purchFormLetterParmData.parmOnlyCreateParmUpdate(true);

        purchFormLetterParmData.createData(false);

        purchParmUpdate = purchFormLetterParmData.parmParmUpdate();


        // Set PurchParmTable table

        purchParmTable.clear();

        purchParmTable.TransDate                = SystemDateGet();

        purchParmTable.Ordering                 = DocumentStatus::PackingSlip;

        purchParmTable.ParmJobStatus            = ParmJobStatus::Waiting;

        purchParmTable.Num                      = packingSlipId;

        purchParmTable.PurchId                  = purchTable.PurchId;

        purchParmTable.PurchName                = purchTable.PurchName;

        purchParmTable.DeliveryName             = purchTable.DeliveryName;

        purchParmTable.DeliveryPostalAddress    = purchTable.DeliveryPostalAddress;

        purchParmTable.OrderAccount             = purchTable.OrderAccount;

        purchParmTable.CurrencyCode             = purchTable.CurrencyCode;

        purchParmTable.InvoiceAccount           = purchTable.InvoiceAccount;

        purchParmTable.ParmId                   = purchParmUpdate.ParmId;

        purchParmTable.insert();


        if(purchTable)

        {

            conPurchList += [purchTable.PurchId];

        }


        // Set PurchParmLine table

        jourTrans.clear();

        while select jourTrans

            where jourTrans.JournalId == this.journalId

                && jourTrans.purchId && jourTrans.SourceLineNumber

            join purchLine

                where purchLine.PurchId == jourTrans.purchId

                && purchLine.POL_OriginalLotID == jourTrans.SourceLineNumber

        {

            if(!conFind(conPurchList, purchTable.PurchId))

            {

                conPurchList += [jourTrans.PurchId];

                this.processPurchParmSubTable(purchParmTable,jourTrans.PurchId );

            }

            this.processPurchParmLine(purchLine, purchParmTable, jourTrans.Quantity);

        }


        purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);

        purchFormLetter.transDate(systemDateGet());

        purchFormLetter.proforma(false);

        purchFormLetter.specQty(PurchUpdate::All);

        purchFormLetter.purchTable(purchTable);

        purchFormLetter.parmParmTableNum(purchParmTable.ParmId);

        purchFormLetter.parmId(purchParmTable.ParmId);

        purchFormLetter.purchParmUpdate(purchFormLetterParmData.parmParmUpdate());

        purchFormLetter.runOperation();

        if(purchFormLetter.parmJournalRecord())

        {

            shipmentId = '';//Can get here posted number

        }

    }


    private void processPurchParmLine(PurchLine _purchLine, PurchParmTable  _purchParmTable, Qty        _curQty)

    {

        PurchParmLine               purchParmLine;


        purchParmLine.InitFromPurchLine(_purchLine);

        purchParmLine.ReceiveNow    = _curQty;

        purchParmLine.ParmId        = _purchParmTable.ParmId;

        purchParmLine.TableRefId    = _purchParmTable.TableRefId;

        purchParmLine.setQty(DocumentStatus::PackingSlip, false, true);

        purchParmLine.setLineAmount();

        purchParmLine.insert();

        this.processPurchParmSubLine(purchParmLine);

    }


    private void processPurchParmSubLine(PurchParmLine  _purchParmLine)

    {

        PurchParmSubLine               purchParmSubLine;


        purchParmSubLine.ParmId               = _purchParmLine.ParmId;

        purchParmSubLine.LineRefRecId         = _purchParmLine.RecId;

        purchParmSubLine.ReceiveNow           = _purchParmLine.ReceiveNow;

        purchParmSubLine.JournalRefRecId      = _purchParmLine.RecId;

        purchParmSubLine.JournalRefTableId    = _purchParmLine.TableId;

        purchParmSubLine.insert();

    }


    private void processPurchParmSubTable(PurchParmTable  _purchParmTable, PurchId  _origPurchId)

    {

        PurchParmSubTable       purchParmSubTable;

        PurchTable              purchTable = PurchTable::find(_origPurchId,false);


        purchParmSubTable.OrigPurchId   = _origPurchId;

        purchParmSubTable.ParmId        = _purchParmTable.ParmId;

        purchParmSubTable.TableRefId    = _purchParmTable.TableRefId;

        purchParmSubTable.PurchName     = purchTable.PurchName;

        AccountingEvent accountingEvent;

        select firstonly accountingEvent

            order by CreatedDateTime desc

            where accountingEvent.SourceDocumentHeader == purchTable.SourceDocumentHeader

                && accountingEvent.Type != AccountingEventType::PeriodClose;


        purchParmSubTable.SourceAccountingEvent   = accountingEvent.RecId;

        purchParmSubTable.insert();

    }


Process Sales packing slip - Post

In Progress

Tuesday, December 20, 2022

ADF expression - Sample & examples

ForEach loop,

@Item()

GetMetaData

@Item().Name

FileFormat -> yyMMdd_HHmmss

FormatDateTime:

@formatDateTime(utcnow(),'yyyy-MM-dd HH:mm:ss')

Date to integer to string

concat(Column_2,'_',toString(toDate(Column_3, 'MM/dd/yyyy','en-US'), 'yyyyMMdd')) 

Str upper ->  upper('test')

concat ->  concat('test-1','_','test-2')

Data Flow: SinkDataset ( enable -> optimize ->  Single partition)


If expression (Data flow)

iif(GROUPNAME == 'WG', 'Y', 'N')

Compare -> 

Ex

 iif((compare(TABLENAME,"VENDTABLE")>0),iif(isNull(sendVendorId), concat(ACCOUNTNUM,'_',PARTY,'_',PARTNERDATAAREAID),ACCOUNTNUM ),concat(ACCOUNTNUM,'_',PARTY,'_',PARTNERDATAAREAID))

iif((compare(TABLENAME,"VENDTABLE")>0),"SUPPLIER","CUSTOMER")

iif((compare(TABLENAME,"PurchLine")>0),"0",toString(round(toDecimal(EXTENDEDPRICE),2)))

iif((compare(TABLENAME,"PurchLine")>0),"SO","PO")

Agreegate: first('fieldname')

Filter On: TABLENAME == "VendTable"

Address street (3 fields)
Derived column1:
Address1-> split(STREET, "\n")

Derived column2:
Address1 ->
replace(iif(length(STREET) > 100, substring(STREET,1, 100), Address1[1]),'\n',' ')

Address2 ->replace(iif(length(STREET) > 100, substring(STREET,101, 100), iif(size(Address1) > 1,Address1[2], '')),'\n',' ')

Address3 ->replace(iif(length(STREET) > 200, substring(STREET,201, 100), iif(size(Address1 ) > 2,Address1 [3], '')),'\n',' ')

substring: (replace .csv to .zip)
@concat(
    substring(
        dataset().p_fileName,
        0,
        sub(
            length(dataset().p_fileName)
            ,4)
    ),'.zip'
)
Replace -> replace(toString(DATE,'YYYY-MM-DD'),'00:00:00','')

Dataset:
UTF-8 (format by D365FO DMF)

Friday, December 2, 2022

Auto Approve purchTable X++ in D365FO

 VersioningPurchaseOrder versioningPurchaseOrder;


        if (_PurchTable.ChangeRequestRequired)

        {

            versioningPurchaseOrder = VersioningPurchaseOrder::newPurchaseOrder(_PurchTable);

            versioningPurchaseOrder.submitChangeRequest();

            versioningPurchaseOrder.approveChangeRequest();

        }

WMS Mobile app flow - Adding Detour fields for Process guided framework custom implementation

 WMS Mobile app flow => Adding Detour fields for Process guided framework custom implementation Before fix: Adding code fix to get thos r...