MS Dynamics CRM Form Field OnChange check for Existing Value in Entity - dynamics-crm

Unless someone can explain what I'm missing, CRM 2013 does not have any way to check for a duplicate WHILE entering a new Lead record. I want to check for a duplicate BEFORE the new record is saved. I can't seem to figure this one out.
Basically, when a user enters the Company Name on a new Lead record, I'd like JavaScript or something check for the existence of that value in all the other Lead records and return True or False. That way I can alert the user that the Company already exists BEFORE they save the new record.
Make sense? Am I just TOTALLY missing something here?
Thanks,
Scotty

Microsoft removed this functionality. But you can restore it using one of following articles:
http://a33ik.blogspot.com/2013/10/how-to-turn-on-duplicate-detection-for.html
http://jlattimer.blogspot.com/2013/10/are-you-missing-duplicate-detection-in.html

You can use below function to check duplicate records and set alert/field value depending upon result set :
CheckDuplicate: function (someIdentifier) {
var value = null;
var filter = "?$select=*&$filter=(new_Identifier eq '" + someIdentifier + "') and (new_someGuidField/Id eq guid'" + Xrm.Page.getAttribute("new_someGuidField").getValue()[0].id + "')";
retrieveMultipleSync("new_EntityNameSet", filter, function (data, textStatus, XmlHttpRequest) {
if (data != null && data.length > 0) {
value = data;
}
}, null);
return value;
}

Related

Update Dynamics form field when item is selected on another field

I have a Dynamics entity that has a relationship to another entity with a Main form in UX. I have a lookup control on the form to select that related entity. Doing so correctly writes the ID of that related entity record to the current record being edited. I need help grabbing the name value of that linked entity and writing it to the name value of the current record when the lookup selection changes. The form designer makes this so much more difficult than it needs to be! Is there a set of basic jscript libraries that I can add to my solution and call for such simple tasks?
After literally HOURS of hunting down bits and pieces, I finally got this to work!
function updateName(){
var name = "";
var lookupField = Xrm.Page.getAttribute("lookupentityproperty");
// Verify the field does exist on the form and has a selected value
if (lookupField != null && lookupField.getValue() != null && lookupField.getValue()[0] != null) {
name = lookupField.getValue()[0].name;
}
else { name = null; }
var nameField= Xrm.Page.getAttribute("nameproperty");
nameField.setValue(name);
}

Is there a way to make a field in Dynamics CRM as one time entry field?

Basically, what I want is that the user should be able to select the dropdown and not be able to change it after making and saving the selection. So it will be a one-time entry field.
Below is a screenshot of the field I want to apply this property.
So this field has a Yes or No selection. And to make the business logic from failing I have to make it a one-time entry field only.
I looked up the form editor for possible things but couldn't find anything that would let me achieve this.
UPDATE #1
Below is my onload function:
function Form_onload() {
var formType = Xrm.Page.ui.getFormType();
var p = Xrm.Page.getAttribute("opportunityid");
--------------NEW CODE--------------------------------
if(formType ==2){ //form type 2 means the form is a saved form. form type 1 is new form.
alert(formType);
var myattribute = Xrm.Page.getAttribute("var_internal");
var myname = myattribute.getName();
if (Xrm.Page.getControl(myname) != null) {
//alert(myname);
Xrm.Page.getControl(myname).setDisabled(true);
}
}
--------------NEW CODE---------------------------
if (formType == 1 && p != null && p.getValue() != null) {
alert('Child Opportunities can only be created by clicking the Create Child Opportunity button in the Opportunity ribbon.');
window.top.close();
}
}
No code solution: I think you could use an Option set with a Yes/No option and a default of Unassigned Value. Then add that field to Field Level Security with "Allow Update" set to No.
When updating the FLS field permissions, be sure that the profile is associated with the organization "team" so that all users can see the field:
Arun already gave you an hint how to proceed, I just tried this req on one of my instance.
Create one extra field (dummy field) in my case I call it new_hasfieldbeenchanged1
This field will hold data when field is changed. Lock this field (always) and keep this field on form (but visibile =false)
Now you need 2 trigger Onload and OnSave. Below function will do your work. Let me know if this helps.
function onLoad(executionContext) {
debugger;
var formContext;
if (executionContext && executionContext.getFormContext()) {
formContext = executionContext.getFormContext();
//executionContext.getEventSource()
if (formContext.getAttribute("new_hasfieldbeenchanged1") && formContext.getAttribute("new_hasfieldbeenchanged1").getValue()!=null) {
if (formContext.getControl("new_twooptionfield")) {
formContext.getControl("new_twooptionfield").setDisabled(true);
}
}
}
}
function onSave(executionContext) {
debugger;
var formContext;
if (executionContext && executionContext.getFormContext()) {
formContext = executionContext.getFormContext();
//executionContext.getEventSource()
if(formContext.getAttribute("new_hasfieldbeenchanged1") && formContext.getAttribute("new_twooptionfield") && formContext.getAttribute("new_twooptionfield").getIsDirty()){
formContext.getAttribute("new_hasfieldbeenchanged1").setValue((new Date()).toString());
if (formContext.getControl("new_twooptionfield")) {
formContext.getControl("new_twooptionfield").setDisabled(true);
}
}
}
}
Due to environment-specific settings in my DEV, I was not able to reproduce what was suggested by #Eccountable. Although, his solution worked in other environments.
#AnkUser has a good answer as well but I was looking to shorten the code and make things as simple as possible.
My solution
I was able to handle this using Javascript on client-side. using the XRM toolbox.
In the XRM toolbox, I located the javascript for the opportunity and observed field changes in formType when the Opportunity was New and when the Opportunity was Existing. This variable (formType) was =1 when the Opportunity was New and =2 when it was Existing/Saved.
Using this piece of information I was able to leverage my Javascript as follows in Form_onload()
function Form_onload() {
if (formType == 2) {
var myattribute = Xrm.Page.getAttribute("internal");
var myname = myattribute.getName();
if (Xrm.Page.getControl(myname) != null) {
Xrm.Page.getControl(myname).setDisabled(true);
}
}
}
There’s no OOB configuration for such custom requirements, but we can apply some script logic.
Assuming this is a picklist with default null and not a two-option bool field, we can use onLoad form script to check if it has value & lock it. No need to have onChange function.
If it’s a bool field, then it’s hard to achieve. You have to track the initial value & changes made to implement the logic you want. Or through some unsupported code.

sys_id arrays to is one of not displaying records on my report

I am not able to display records on my report.
Report Source: Group Approval(sysapproval_group) table
Condition:Sys Id - is one of - javascript: new GetMyGroupApprovals().getSysIds();
Script Include : MyGroupApproval
Note : Active is checked, Accesible is all application score & Client callable unchecked
var GetMyGroupApprovals = Class.create();
GetMyGroupApprovals.prototype = {
initialize: function() {
},
getSysIds : function getMyGroupMembers(){
var ga = new GlideRecord('sysapproval_group');
ga.addQuery('parent.sys_class_name', '=', 'change_request');
ga.query();
gs.log("TotalRecords1 Before:: " + ga.getRowCount());
var sysIdArray = [];
while(ga.next()){
sysIdArray.push(ga.sys_id);
}
return sysIdArray;
},
type: 'GetMyGroupApprovals'
};
Kindly note that I have to achieve with script approach. I am not able to get records on my report.
This line is probably causing unexpected behavior:
sysIdArray.push(ga.sys_id);
ga.sys_id returns a GlideElement object, which changes for each of the iterations in the GlideRecord, so the contents of sysIdArray will just be an instance of the same object for each row in the result set, but the value will just be the last row in the set.
You need to make sure you push a string to the array by using one of the following methods:
sysIdArray.push(ga.sys_id+''); // implicitly call toString
sysIdArray.push(ga.getValue('sys_id')); // return string value
Quick suggestion, you can use the following to get sys_ids as well:
sysIdArray.push(ga.getUniqueValue());

Using afterDelete trigger to modify a lot of users

When a specific object is deleted, I need to use an afterDelete trigger to remove references to the object that was just deleted. Specifically, the User class has a column that is a pointer to an object of the type that was just deleted. Therefore I need to unset that column for users who had that set to the object that was just deleted. To do this I am querying for the users, looping over the results of the query, unseting the attribute, then calling saveAll. My worry is that the results of the query may return a lot of users, and I need to ensure all of them are updated.
My question is, do Cloud Code triggers have the 1000 max query limit? Is there a better way to unset this pointer once that object is deleted? Is there no automatic removal of pointers to this deleted object?
Parse.Cloud.afterDelete("Book", function(request) {
Parse.Cloud.useMasterKey();
var book = request.object;
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo("Favorite_Book", book);
userQuery.limit(1000);
userQuery.find( {
success:function(users){
for (var i = 0; i < users.length; i++) {
users[i].unset("Favorite_Book");
}
Parse.Object.saveAll(users, {
success: function(users) {},
error: function(users, error) {
console.error("Failed to update users: " + error.code + ": " + error.message);
}
});
}, error: function(error) {
console.error("Failed to fetch users: " + error.code + ": " + error.message);
}
});
});
There are mainly two issue you need to know:
Parse query returns only maximum of 1000 records. To process more records, you need paginate the results using skip method on your query object. You can use Promises in Series to process all your records in batches of 1000 records.
On Parse free plan, you are limited to make only 1800 requests per minute. This means that you cannot save/update a large number of records over a short time span.

Knockout validation issues

I have the following issues with my knockout model validations and not sure how to resolve them. Following is my model first of all, with the validation rules:
var Data = function (data) {
this.Val = data;
}
function ViewModel(item) {
var parse = JSON.parse(item.d);
var self = this;
this.Name = ko.observable(parse.Name);
this.UserType = ko.observable(parse.UserType);
this.ID = ko.observable(parse.ID).extend({ required: { params: true, message: "ID is required" }, decimal: { params: 2, message: "Should be decimal"} });
this.Username = ko.observable(parsed.Username).extend({ required: {
onlyIf: function () {
return self.UserType() > 1;
}
}
});
this.WeeklyData = ko.observableArray([]);
var records = $.map(parse.WeeklyData, function (data) { return new Data(data) });
this.WeeklyData(records);
this.WeeklyData2 = ko.observableArray([]);
var records = $.map(parse.WeeklyData2, function (data) { return new Data(data) });
this.WeeklyData2(records);
}
ko.extenders.numeric = function (target, precision) {
var result = ko.dependentObservable({
read: function () {
return target().toFixed(precision);
},
write: target
});
result.raw = target;
return result;
};
Here are my problems:
1) with the ID() observable, I want to restrict it to two decimal points, so I've created the validation extender 'numeric' but it's not working. Is there anything wrong with how I'm using it and how to correct it?
2) Also, if I want to restrict an observable to whole numbers, how can I do that?
3) when I define a rule with a condition, (i.e. Username()), how do I define a custom message for that? I was able to do it for default rules, but with the conditional rules, it's not working
4) I have two observable arrays WeeklyData1 and WeeklyData2 both of which contains Data() objects. I want to have separate min/max rules for these two, for example, min/max - 1,7 for WeeklyData1 and min/max - 1,150 for WeeklyData2. How can I get it done?
4) Right now my error messages appear right next to the data field, but I want all those to appear in a single validation summary, while displaying '*' against the field. I've been told to use Validation-bindings, but I'm not sure how to use it, can someone please give an example?
It's a lot of questions, I know, but I appreciate if someone could help.
Thanks in advance
Instead of diving in your code i have created a small-small demonstrations for your questions. Ok so here we go,
1) with the ID() observable, I want to restrict it to two decimal points.... and 2) Also, if I want to restrict an observable to whole numbers....
Your 1 and 2 question are pretty similar so i covered both of this in a single fiddle. Check this fiddle.
3) when I define a rule with a condition, (i.e. Username()), how do I define a custom message ....
You can use message property to set custom messages, Check this fiddle.
4) I have two observable arrays WeeklyData1 and WeeklyData2 both of which contains Data() objects
I am not clear which this question, what type of data both of these array contains and for what you want to set min/max rule ( array length or other ). So please clear this, than i will try to help on this.
5) Right now my error messages appear right next to the data field.....
This questions answer i already given in your how to? with knockout js validations question (Check update).
Let me know if it helps!

Resources