Monday 27 July 2015

Filter N:N Subgrid in CRM 2013 using Javascript

Sometimes, you need to filter the N to N subgrid (not associated view) when you click the Add Existing button and you will see the inline lookup

image

To achieve it, you might need to modify the system ribbon. Well, This method is unsupported because it is not well-documented, but if just in case customers really demanding and want it, I just want to share the ‘how-to’.

Thanks to my friend with this blog post which can convince me that this is not possible to filter subgrid, this is a clue:

http://nycrmdev.blogspot.sg/2014/02/changing-default-view-of-inline-lookup.html

So, this is the common function:

//FUNCTION:AddExistingSubgrid
function filterSubgrid(gridTypeCode, gridControl, entityParentName, subgridName, viewId, entityRelatedName, viewDisplayName, fetchXML, layoutXML) {
    var AGS = window["AGS"] || {};

    AGS.AddExistingSubgrid = function (gridTypeCode, gridControl) {
        Mscrm.GridRibbonActions.addExistingFromSubGridAssociated(gridTypeCode, gridControl);
        if (Xrm.Page.data.entity.getEntityName() == entityParentName &&
            //gridTypeCode == 2 &&
            typeof gridControl['get_viewTitle'] == 'function') {
            var lookupExistingFieldName = 'lookup_' + subgridName + "_i";
            var inlineBehaviour = document.getElementById(lookupExistingFieldName).InlinePresenceLookupUIBehavior;
            setLookupCustomView(inlineBehaviour, viewId, entityRelatedName, viewDisplayName, fetchXML, layoutXML);
        }
    };

    this.AGS = AGS;
    //call this function;
    AGS.AddExistingSubgrid(gridTypeCode, gridControl);
}

// FUNCTION: setLookupCustomView
//must pass the lookup field control, not field name
//to add custom view to the subgrid (Add existing)
function setLookupCustomView(lookupFieldControl, viewId, entityRelatedName, viewDisplayName, fetchXML, layoutXML) {
    // add the Custom View to the primary contact lookup control      
    lookupFieldControl.AddCustomView(viewId, entityRelatedName, viewDisplayName, fetchXML, layoutXML, true);
}


And this is the example how to use that and wrap it in one specific function that would be called during ribbon action execution (clicked)

function filterTrainerProfile(gridTypeCode, gridControl) {
    var entityParentName = "primaryentityname";
   
    // use randomly generated GUID Id for our new view      
    var viewId = "{6fd72744-3676-41d4-8003-ae4cde9ac282}";
    var entityRelatedName = "relatedentityname"; 
    var viewDisplayName = "Filtered View Name";

    var subgridName = "subgrid_name";
   
    var fetchXml = getFetchXML(); //replace this to your own fetch xml

    // build Grid Layout     
    var layoutXml = getLayoutXML(); //replace this to your own layout example

    if (fetchXml != null) {
        filterSubgrid(gridTypeCode, gridControl, entityParentName, subgridName, viewId, entityRelatedName, viewDisplayName, fetchXml, layoutXml);
    }
}

*I used the filterTrainerProfile() function to filter the Trainer profile entity subgrid records (as related record) then I put the subgrid in the Class form entity.

So, the Trainer profile will be my related entity name, while Class is my entity Parent Name.

Then using our friendly tool here, we can modify the system ribbon

image

use number 1 if you want to filter subgrid based on 1:N relationship and use number 2 if you want to filter for N to N relationship (well in my example is N to N)

Then, after that, modify the command:

image

Here you go for the detail command

image

And you can see the result, it would filter my Trainer Profile records based on the xml I defined!

*Note: It can break the associated view, you might need to add try catch or conditional to make sure it works if you really need the associated view. In my case, users do not want to use associated view because we have subgrid already.

I hope this can help you, it seems becoming most requirement recently I found in the forum and also other projects.

Thanks.

Follow on Behalf Other users in CRM 2013

A quick post (just copy paste from my previous forum reply Smile
Just in case the users need to follow other users but he needs you as the Administrator to follow on behalf, you can do use this method:

https://community.dynamics.com/crm/f/117/t/151955

So, create a workflow here:


*You can make as ondemand and also oncreated as trigger point and put some condition, again up to you, here I use ondemand as well to execute it manually.

You can set as realtime workflow for CRM 2013 above as well, ok.

Then the most important thing is the Action step to Create a follow record.



Just put like my example, set the Owner to your VP of Sales.

Now let's see how it works.

At first, the VP has not followed CRM User 1



*Can see through the Follow button, okay.

Then I (as you as admin), run the workflow of this user (can select multiple users as well, but I have no enough sample here, so please use one of them first :))

okay then I run the workflow (before that you need to activate it first)



Then here is the result after that.

I login as VP then I can see that I have followed this user.



Without clicking that, my admin (you) already make me followed this user.

Thanks!

















Sunday 5 July 2015

Create Custom Ribbon in CRM Homepage Gridview

A quick tip for creating ribbon for subgrid

We can use Visual Ribbon Editor or RibbonWorkbench, they are two great tools!

Then, the most important thing is of course calling your Web Resources function.

And do not forget to pass the CRM Parameter : SelectedControlSelectedItemIds

image

Then to get the selected ID, you can use this function:

function acknowledge(selectedIds) {
    //check the status first
    debugger;
    if (selectedIds != null && selectedIds != "") {
        var strIds = selectedIds.toString();
        var arrayIds = strIds.split(",");
        for (var i = 0; i < arrayIds.length; i++) {
                //selected id = arrayIds[i]
            }
        }
    }   
}

To get the value of the selected record, you need to query using the ID using odata or fetchxml

Then you can also show hide, this time, i use my custom rule:


image

Or you can use your own rule or available CRM Rules, but you cannot use valueRule as I know since this only take the value rule from formCommand context.

Then here is the result:

image

If you want to validate that only if selected then show the ribbon, you can use another Enable Rule, that is the selectioncountrule

http://nishantrana.me/2011/08/24/enabling-button-in-subgrid-on-selection-of-record-selectioncountrule-in-crm-2011/

https://msdn.microsoft.com/en-us/library/gg309316.aspx

image

Then here is the result

image

If I select 1 or 2

image

And if I select more than 2

image

And here is when you click and you get selected IDs

image

Hope this helps.

Thanks.

Utilizing CRM Custom Action for Transaction Rollback Purposes

Introduction

In CRM 2013, we have a new feature, so-called Custom Action.

Well, I have posted about this feature long ago.


That time I was rarely using that because got problem in deploying the Custom Action which I believed has been fixed and now my colleague’s opening again my mind to re-consider using this feature.

Custom Action Features

Do you know that beside its great features such as:

1.  For replacing Configuration entity
2. Or even to validate something that need server side code which you are no longer need plugin again since its capacity to be called without triggering it by creating or changing field value like what plugin does,
3. Or to call this using javascript,
4. Plus even new amusing feature in CRM 2015 Update 1 to call it through Workflow,
5. Again, you can add more action as well as what workflow has been doing for you the whole time.

What I want to emphasize and spot in this post is its capability to do rollback.

Example or Scenario

Imagine, in daily transaction, in CRM, you have Header and Detail, Parent and Child, and Main and Line Item, Transaction and Transaction Detail.

Then also for major impact transactions, such as Bank Account, posting to Finance, Order and Order Detail, you need to secure that all of records must be done properly and 100% success rate, otherwise fail it! You cannot deliver an Order to customer if not all the details were created successfully and also very common situation you need to flag a record that you have updated in other entity, you need to make sure both are success, you cannot just in halfway, success in one transaction while fail to another, you need BOTH of them SUCCESS and EITHER one is FAIL, ALL must be stated FAIL and roll it back as the original one. This table is very important because it is Financial record, a –finance-related means A Money related, so both must be in sync, one fail, both must fail.

Well, CRM also gives good example in term of reciprocal and must done transaction, that is fund transferring:

“The classic example is transferring funds between two bank accounts. If you withdraw funds from one account you must deposit them in the other. If either fails, both must fail.”

The Research and The Implementation

I think what you all are waiting for is the real example in term of coding or implementation

Now, let’s say I have two entities, Entity A and B.

If Entity A is fail created and I need to make sure B also fail and vice versa.

I have 5 Entity A records and 5 Entity B records.
1 of them is failed then I must fail them.

*All of the example is within the CRM DB Context, not other system (external) involved that can be rolled-back, okay.

Standard CRM Transaction CRUD Request

There is no rollback for this standard CRUD Request because it’s processing one by one record.

Execute Multiple Request CRM

Well, now let’s move little bit to more advance, what will happen if we use the Execute Multiple Request, will it be rolled-back?

The answer is no..It will stop you to the next action if you use the skip or ignore error parameter to No, but in fact, it does not roll back the previous made transaction.

Custom Action

This is what I want to emphasize.
Assuming, I have this Action:

image

*For creating an action you can refer to my blog posts or other good example through the internet and good explanation from Power Object:

Then, inside the Custom Action code, I have the Create Record like I did in the Code-1 but I put in the CRM Action by parsing the EntityCollection as input

image

*Inside the collapsed region:

image

This one if you enable, means “no error” so that it won’t enable roll-ed back because assuming this action never throw an error, so you might need to re-think when you implement this.

For roll-back purposes, do not catch error for each single transaction.

You can do that in lump sum then just throw it all!

Okay, now, so what happened to my record after I trigger this action through executing it programmatically?

Well, it throw me error and there is no record at all!

*First entity
image

*Second Entity

image

*Well, as we can see here is, one fail, make the others also fail.

Other Research

Now, to make it lively, I increase the number of record to 800.
Then I make the failure in 789th row.
image
See what happened when I keep refreshing… then in fact I failed in almost the last row.
*First Refresh
image
*as you can see we have 130 records here
Then..
keep refreshing
*Second Refresh…
image

208 records here..

*Third time..

image

667 records here..

And until my code was stopped..

image

Yeah, it does stop in the record no 789.

And now..

I try to refresh again the advanced find..

And guess what…

All records….It’s gone..

image

So, it has the concept, once one is failed, then the other must failed as well!

What if I disable the Roll-Back

To ensure my curiosity and my doubt about the rollback function (well even for such example I still have doubt little bit but annoying) then I try to disable the rollback checkbox to ensure this usage.
image
And here is the result when I turn it off.
image

*As you can see here is the record is created anyway, no rollback same as what CRM Normal CRUD or Execute Multiple did before.

This does stop the transaction, but not rollback the previous committed transaction, so it proves the concept of rollback that Custom Action has.

So, hopefully this article is not so long for you to read and you can get advantage by reading it.

I intend to document it because in case I forgot it will become our e-memory and to encourage anyone to keep using this feature for your important couple of transactions that needs rollback each other.

Thanks and have a nice day!