Thursday, January 30, 2020

D365FO. Dynamics 365 fiance and operation. Get and update contract of batch job on Controller run method. ax 2012

set Batch id in contract if batch isInBatch check is true

in run method we will update the contract and set the batch id.


class BrFunctionalLocationRecordsController extends SysOperationServiceController
{
    protected void new()
    {
        super(classStr(BrFunctionalLocationRecordsService), methodStr(BrFunctionalLocationRecordsService, functionalLocationRecordsService), SysOperationExecutionMode::Synchronous);
    }

 
    public static BrFunctionalLocationRecordsController construct(SysOperationExecutionMode _executionMode = SysOperationExecutionMode::Synchronous)
    {
        BrFunctionalLocationRecordsController      controller;
        controller = new BrFunctionalLocationRecordsController();
        controller.parmExecutionMode(_executionMode);
        return controller;
    }

 
    public static void main(Args _args)
    {
        BrFunctionalLocationRecordsController controller;
        // to update contract value at main we can initialize contract here.
        //BrFunctionalLocationRecordsContract   brFunctionalLocationRecordsContract;

        controller = BrFunctionalLocationRecordsController::construct();
        //and can set contract values here
        //brFunctionalLocationRecordsContract = controller.getDataContractObject();
        controller.parmArgs(_args);
        controller.startOperation();
    }

 
    public ClassDescription defaultCaption()
    {
        return "@Br:FunctionalLocationRecords";
    }

   
    public void run()
    {
        BrFunctionalLocationRecordsContract brFunctionalLocationRecordsContract;

       //getting batch contract.
        brFunctionalLocationRecordsContract = this.getDataContractObject();
       
        Batch                                   batch;
        if (this.isInBatch())
        {
            //getting batch information;
            batch = this.currentBatch;
            //setting batch id in contract
            brFunctionalLocationRecordsContract.parmBatchHeader(batch.BatchJobId);
        }
        super();
    }

}

Monday, November 4, 2019

Upload Files To Azure BLOB From D365 FO


Uploading attachment file to Microsoft azure storage account blob.

  1.           Goto https://portal.azure.com
  2.             Goto Storage Account
  3. Click on Add 

  4. Fill details and click Review + Create
  5. Click on create. It will deploy the storage account.
  6. Go to newly created storage account go to access key .
    Key 1 and key 2 or connections strings will be used to access this storage account.
  7. Go to container and click Container
  8. Fill the name and click ok.
  9. Now we will create new runnable class in D365FO to upload file to newly created container.
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Blob;

    class UploadFileToAzureBlob
    {

        public static void main(Args _args)
        {
            DocuRef     docuref;
            /*const str connectionString =  "";*/
            const str containerName = "selflearningcontainer";
            str storageAccountName = "selflearningtest";
            str key = "”;

            System.IO.Stream attachmentStream = null;
            try
            {
    var storageCredentials = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(storageAccountName, key);
    CloudStorageAccount storageAccount = new Microsoft.WindowsAzure.Storage.CloudStorageAccount(storageCredentials, true);
            
                if(storageAccount)
                {
                    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
     CloudBlobContainer blobContainer = blobClient.GetContainerReference(containerName);
                    blobContainer.CreateIfNotExistsAsync();

                    changecompany('USMF')
                    {
                        SalesId salesId = '001835';
                        SalesTable SalesTable;
                        //SalesTable salesTable = SalesTable::find(salesId);
                        select SalesId from salestable where SalesTable.salesid == '001835';
                
        select firstonly docuref where docuref.RefTableid == salesTable.TableId
                        && docuref.RefRecid == salesTable.RecId;
                    }

                    if(docuref.isValueAttached())
                    {
                        docuValue = docuref.docuValue();

    CloudBlockBlob blockblob =    blobContainer.GetBlockBlobReference("testingblob");
                        if(blockblob && !blockblob.Exists(null, null))
                        {
                            var storageProvider = docuvalue.getStorageProvider();
                            if(storageProvider != null)
                            {
     var docContents = storageProvider.GetFile(docuValue.createLocation());
                                attachmentStream = docContents.Content;

                                if(attachmentStream)
                                {
                                    blockblob.UploadFromStreamAsync(attachmentStream).Wait();

                                    blockBlob.FetchAttributes(null,null,null);
                                    BlobProperties BlobProperties = blockblob.Properties;
                                    if(BlobProperties.Length == attachmentStream.Length)
                                    {
                                        info("file uploaded successfully");
                                    }
                                }

                            }
                        }
                        else
                        {
                            info("file already exists");
                        }
                    }
                }
                else
                {
                    error("unable to connect azure file storage with the provided credentials");
                }
            }
            catch(Exception::Error)
            {
                error("Operation cannot be completed");
            }
            
        }

    }

  10. Now we will run the class 


Thursday, December 27, 2018

Trigger logic App from D365 Part 2







In this part we will see how to trigger logic app form D365FO (Dynamics 365 For operations)


For logic App details visit Part 1 

Create a class name :LogicAppHelper
with method : callPostWebAPI


class LogicAppHelper
{
    #define.ApplicationJson('application/json')

    public boolean callPostWebAPI(URL _serviceOperation, Comments _postData, str _header ='')
    {
        RetailWebRequest request;
        RetailWebResponse response;
       
        boolean ret;
        ListEnumerator  listEnmr;
        List dataList;
        RetailCommonWebAPI webApi = RetailCommonWebAPI::construct();
   
        try
        {
            response = webApi.makePostRequest(_serviceOperation, _postData, _header #ApplicationJson);

        }
        catch
        {
            ret = false;
        }
   
        return ret;
    }
}



Now we will create runable class (job)

class LogicAppConnectionJob
{        
    /// <summary>
    /// Runs the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {    
        LogicAppHelper  appHelper = new LogicAppHelper();
        container       conValues;
        AccountNum custAccount;
        str             callingparam ;
        ;
        
        custAccount = 'US-001';

        callingparam  = "{'CustomerAccount':'" + custAccount +" '}";

       //appHelper.callPostWebAPI(URL ,Comments,_header
       // URL : URL generated while creating logic for details see part 1
       // Comments: passing customer account to logic app as JSON Schema for details see part 1

        appHelper.callPostWebAPI('https://URL-Generated-By-Logic-App-Response-Receiver' ,callingparam);
    }

}

hopefully this will help you all...

Monday, December 24, 2018

Logic App For Dynamics 365 for operation (D365FO).Azure logic App (part 1)









Summary :
In this part we are going to create Logic App for Dynamics 365 For Operations.in this we will see how we will send email using logic app.
As we know right now there are no triggers for D365 FO, so we will achieve this using http response receive.
In this part we will discuss


a)      Login azure portal.
b)      Create Resource for logic app.
c)      Create basic logic app 
d)      And trigger logic using post man 

Part 2

  
Step 1:
Sign in azure portal



Step 2:
After log in, go to Create a resource à Web à Logic App



Step 3:
a. Enter logic app name e.g DemoLogicApp.
b. Select Subscription.
c. Check Create new in resource group.
d. Enter resource group name like DemoResourceGroup
e. Select location
f. Click on create.

Step 4:
Click All services
filter by Logic App



Step 5:

Click DemoLogicApp
It will open logic App Designer
Select Blank Logic App


It will look like 




 Step 6:
First we will add trigger to logic app(trigger is the point which define when to execute logic app)
 a)      Search for logic app trigger (When a Http Request is Recevied)

 b) Select When a Http Request is received 
  




 c) Now add Json Schema: 
Step 7:
a)  Now we will add action. Click next step


    b) Search for send email action
    c) Select Office 365 Outlook

   d)  Select send Email


 e)  Now we will sign in to office 365 Outlook.

  f)    Fill details
a.       Add to account
b.      Subject
c.       Body (you can add customer account which was define in jSon Schema.


Step 8:
Click on save
It will generate Https url
  Step 9:
        a)      Go to post man
        b)      Select post
        c)       Enter url
d      d)  Go to header tab add key and value 
    e) Go to body and define body (we defined json Schema in logic app)         


    f)  Click on send
    g)  Go to logic app àOverview à click refresh
We can see the status is succeeded which mean logic app got triggered and send email successfully 




in next part we will discuss how to connect D365 with logic apps 


Part 2 in this part we will discuss how to trigger Logic App From D365


Thursday, December 7, 2017

Creating Payment journal and posting Payment journal ax2012 /D365 ax7 x++

Public static boolean processPayment(BAModule BAModule)
{
ledgerJournalName  JournalName ;
ledgerJournalCheckPost JournalCheckPost;

ledgerJournalTable JournalTable;
ledgerJournalTrans JournalTrans;
JournalCheckPost JournalCheckPost;

Common common;
NumberSeq numberseq;
CustTrans custTrans;
CustTransOpen custTransOpen;
Specification specOffsetVoucher;

BAParameters parameters = BAParameters::find();
CustTable custTable = CustTable::find(BAModule.CustAccount);
boolean return = false;
InvoiceId invoiceId;
;

while select custTransOpen
where custTransOpen.RefRecIdCheck == BaModule.RecId &&
custTransOpen.UseRefRecId
{
custTrans = custTransOpen.custTrans();
invoiceId = custTrans.Invoice;

try
{
ttsbegin;

select firstonly JournalName
where JournalName .JournalName == parameters.JournalName Id &&
JournalName .JournalType == LedgerJournalType::CustPayment;

if(!JournalName .RecId)
throw error("@11250");

if(JournalName )
{
JournalTable.JournalName = JournalName .JournalName;
JournalTable.Name = JournalName .Name;
JournalTable.insert();

if(JournalTable)
{
numberseq = NumberSeq::NewGetVoucherFromCode(JournalName .VoucherSeries);
JournalTrans.JournalNum = JournalTable.JournalNum;
JournalTrans.Voucher = numberseq.voucher();
JournalTrans.TransDate = today();
JournalTrans.Txt = CustTable::find(JournalTrans.AccountNum).Name;
JournalTrans.OffsetAccountType = JournalName .OffsetAccountType;
JournalTrans.OffsetAccount = JournalName .OffsetAccount;
JournalTrans.Dimension = JournalName .Dimension;
JournalTrans.CurrencyCode = JournalTable.CurrencyCode;
JournalTrans.AccountType = LedgerJournalACType::Cust;

JournalTrans.TransactionType = LedgerTransType::Payment;
JournalTrans.PaymMode = parameters.PaymMode;
JournalTrans.SettleVoucher = SettlementType::SelectedTransact;
JournalTrans.AccountNum = custTable.AccountNum;
JournalTrans.AmountCurCredit = custTransOpen.AmountCur;
JournalTrans.ExchRate = ExchRates::find(JournalTable.CurrencyCode, datenull(), NoYes::No, NoYes::No).ExchRate;
JournalTrans.insert();

select custTransOpen
where custTransOpen.AccountNum == custTable.AccountNum &&
custTransOpen.RefRecId == CustTrans::findFromInvoice(invoiceId).RecId;

if(custTransOpen)
{
common = JournalTrans;
specOffsetVoucher = Specification_OffsetVoucher::newCommon(common, true);
if (!specOffsetVoucher.isMarked(custTransOpen.TableId, custTransOpen.RecId))
if (JournalTrans.RecId)
specOffsetVoucher.create(custTransOpen.TableId, custTransOpen.RecId, custTransOpen.AmountCur, JournalTable.CurrencyCode);
}

JournalCheckPost = JournalCheckPost::newJournalTable(JournalTable, NoYes::Yes);
JournalCheckPost.run();
return = true;
}
}
ttscommit;
}
catch
{
ttsabort;
return = false;
}
}
return return;
}

Friday, November 24, 2017

Creating a Valid Time State Table/Maintaining ValidTimeState Record


Maintaining Version of table record
Step 1)
Create Table Name: TableA and add fields to tha table

Note : You can change the ValidTimeStateFieldType to any value when the table contains no data. You can change the value to None even if the table contains data.

Step 2) go to table properties and set following properties          

Now Valid to valid from fields are added to your table automatically

Step 3 ) Create index and go to properties and set following properties

At least 3 fields will be added to index valid to, valid form and one other field (like accountNum as shown in table)

Note : You can change the ValidTimeStateMode property from Gap to NoGap only if the table contains no data. You can change from NoGapto Gap even if the table contains data.






Friday, March 10, 2017

MARK AND UNMARK DYNAMICS TREE NODE CHECK BOX (IF NO CHECK BOX IS MARK THEN TAKE TWO CLICK TO MARK FIRST CHECK BOX AND THEN ONE CLICK ON EACH NODE TO MARK CHECK AND REFRSH GRID.IF NO CHECKBOX THEN JUST REFRESH RESPECTIVE GRID) AND SET/REMOVE TREE NODE IDX TO TMP TABLE

MARK AND UNMARK DYNAMICS TREE NODE CHECK BOX (IF NO CHECK BOX IS MARK THEN TAKE TWO CLICK TO MARK FIRST CHECK BOX AND THEN ONE CLICK ON EACH NODE TO MARK CHECK AND REFRSH GRID.IF NO CHECKBOX THEN JUST REFRESH RESPECTIVE GRID) AND SET/REMOVE TREE NODE IDX TO TMP TABLE

public class FormRun extends ObjectRun
{
TreeSearchingTmp      setTreeSearchItemID;
}
public int mouseDown(int _x, int _y, int _button, boolean _Ctrl, boolean _Shift)
{
    ImageRes     stateImage;
    int idx,f;
    int ret;

    FormTreeItem formTreeItem ;//= PlanningObjectClinicsTree.getItem(PlanningObjectClinicsTree.getSelection());
    FormTreeItem        parentNode;
     #FormTreeControl
    [idx,f]      = this.hitTest(_x,_y);

    FormTreeItem = this.getItem(idx);
    ret = super(_x, _y, _button, _Ctrl, _Shift);
    select *from setTreeSearchItemID;
    if(!setTreeSearchItemID)
    {
        if(element.getNode()==idx)
        {
            if (FormTreeItem)

            {
                switch(formTreeItem.stateImage())
                {
                        case imageListAppl_checkbox.image(#ImageCheckNone):
                            stateImage = imageListAppl_checkbox.image(#ImageCheckAll);
                            formTreeItem.stateImage(stateImage);
                            this.setItem(formTreeItem);
                            element.setTreeSearchItemID(idx,formTreeItem.data());
                            break;
                        case imageListAppl_checkbox.image(#ImageCheckAll):
                            stateImage = imageListAppl_checkbox.image(#ImageCheckNone);
                            formTreeItem.stateImage(stateImage);
                            this.setItem(formTreeItem);
                            element.removePlanningOjectTreeSearch(idx);
                            break;
                }

                element.refreshGrid();
                element.resetControls();
            }
        }
        else if(!setTreeSearchItemID )
        {
            {
                RefreshResourceGroupTree = false;
                element.setnode(idx);
            }

        }
        else
        {
            RefreshResourceGroupTree = false;
            element.setnode(idx);
        }
    }
    else
    {

        if(setTreeSearchItemID)
        {
            if (FormTreeItem)

                {
                    switch(formTreeItem.stateImage())
                    {
                            case imageListAppl_checkbox.image(#ImageCheckNone):
                                stateImage = imageListAppl_checkbox.image(#ImageCheckAll);
                                formTreeItem.stateImage(stateImage);
                                this.setItem(formTreeItem);
                                element.setTreeSearchItemID(idx,formTreeItem.data());
                                break;
                            case imageListAppl_checkbox.image(#ImageCheckAll):
                                stateImage = imageListAppl_checkbox.image(#ImageCheckNone);
                                formTreeItem.stateImage(stateImage);
                                this.setItem(formTreeItem);
                                element.removePlanningOjectTreeSearch(idx);
                                break;
                    }

                    element.refreshGrid();
                    element.resetControls();
                }
        }

    }
    return ret;
}
Public void removePlanningOjectTreeSearch(int _idx)
{

    while select *from setTreeSearchItemID where setTreeSearchItemID.ItemIdx == _idx
    {
        setTreeSearchItemID.delete();

    }
}
public HMTreeSearchingTmp setTreeSearchItemID(int64 idx = 0 ,Description _data ='')
{

    if(idx)
    {
        setTreeSearchItemID.ItemIdx= idx;
        setTreeSearchItemID.Description = _data;
        setTreeSearchItemID.insert();
        return setTreeSearchItemID;
    }
    else
    {
        return setTreeSearchItemID;
    }



}


D365FO. Dynamics 365 fiance and operation. Get and update contract of batch job on Controller run method. ax 2012

set Batch id in contract if batch isInBatch check is true in run method we will update the contract and set the batch id. class BrFunc...