You need to sign in to do that
Don't have an account?
Developer.mikie.Apex.Student
validation Trigger Please help
Hi there,
I was helped wih this brilliant trigger by a scotty McClung, but correspondence recently died down. He had a brilliant idea, where I used my current business model to create a validation rule. It works, but it is not finished just yet.
Basically I have account, account has a child service__c. A user will add a service to an account, to do so they will select the picklist service_name__c and service_type__c, which will use a trigger that has an soql querry which finds the record from destiny_product_and_services__c and therefore will autofill formula fields on the service record.
I have added another field called macimum records to the destiny_products_and_service__c database. The trigger checks to see if the services attached to the account is greater than the number set in maximum records and if so will error.
This all works properly, except it only runs off service_name__c rather than both service_name__c and service_type__c. I was wondering if someone would give me a hand on either making it so that it will find the exact record through service_name__c and service_type__c or run by the actual record name field.
If it helps, in the database object - the name of the record is basically service_name__c (service_type__c).
E.g. A record with service_name__c = advantage program and service_type__c = new client would be:
Advantage Program (new client).
Thank you in advance for your time
To further explain, Destiny_rpoducts_and_services and service_c have two same fields which is two picklist service_name__c and service_type__c on service__c and the same but texts fields on Destiny_products_and_services. A trigger is used to take the picklist options and autofill the correct lookup.
This is my code:
I was helped wih this brilliant trigger by a scotty McClung, but correspondence recently died down. He had a brilliant idea, where I used my current business model to create a validation rule. It works, but it is not finished just yet.
Basically I have account, account has a child service__c. A user will add a service to an account, to do so they will select the picklist service_name__c and service_type__c, which will use a trigger that has an soql querry which finds the record from destiny_product_and_services__c and therefore will autofill formula fields on the service record.
I have added another field called macimum records to the destiny_products_and_service__c database. The trigger checks to see if the services attached to the account is greater than the number set in maximum records and if so will error.
This all works properly, except it only runs off service_name__c rather than both service_name__c and service_type__c. I was wondering if someone would give me a hand on either making it so that it will find the exact record through service_name__c and service_type__c or run by the actual record name field.
If it helps, in the database object - the name of the record is basically service_name__c (service_type__c).
E.g. A record with service_name__c = advantage program and service_type__c = new client would be:
Advantage Program (new client).
Thank you in advance for your time
To further explain, Destiny_rpoducts_and_services and service_c have two same fields which is two picklist service_name__c and service_type__c on service__c and the same but texts fields on Destiny_products_and_services. A trigger is used to take the picklist options and autofill the correct lookup.
This is my code:
Trigger ServiceValidation2 on Service__c (before insert) { //Populate a map of the ServiceRules object using the service name as the key Map<String, Destiny_Products_and_Services__c> mapServiceRules = new Map<String, Destiny_Products_and_Services__c>(); for(Destiny_Products_and_Services__c objRule : [SELECT Name, MaximumRecords__c FROM Destiny_Products_and_Services__c]) { mapServiceRules.put(objRule.Name, objRule); } //Populate a set of account_ids to use in your SOQL query Set<Id> setAccountIds = new Set<Id>(); for(Service__c objService : trigger.new) { setAccountIds.add(objService.Account__c); } //Populate a map of the aggregate query results Map<String, Map<String, Decimal>> mapResults = new Map<String, Map<String, Decimal>>(); AggregateResult[] groupedResult = [SELECT Account__c, service_name__c, Service_type__c, Count(Id) countOfRecords FROM Service__c WHERE Account__c IN :setAccountIds GROUP BY Account__c, Service_name__c, Service_type__c]; for(AggregateResult ar : groupedResult) { if(!mapResults.containsKey((String)ar.get('Account__c'))) { mapResults.put((String)ar.get('Account__c'), new Map<String, Decimal>()); } mapResults.get((String)ar.get('Account__c')).put((String)ar.get('Service_Name__c'), (Decimal)ar.get('countOfRecords')); } //Iterate through your list of Service__c records and generate an error for any //that have a matching Account__c in the map for(Service__c objService : trigger.new) { if(mapServiceRules.containsKey(objService.Service_Name__c) && mapServiceRules.get(objService.Service_Name__c).MaximumRecords__c != null) { //If there is no rule set ignore the record if(mapResults.containsKey(objService.Account__c)) { if(mapResults.get(objService.Account__c).containsKey(objService.Service_Name__c)) { if(mapResults.get(objService.Account__c).get(objService.Service_Name__c) >= mapServiceRules.get(objService.Service_Name__c).MaximumRecords__c) { objService.addError('This service has already been added the maximum number of times'); } } } } } }
Few questions here,
Is name field of Destiny_Products_and_Services__c is same as service type of service object?
As you are creating map mapServiceRules which contains key as name and value as count. And retriving values from map using service type of service object.
When we do group by 3 fields we get result like below
Account__c Service Name Service Type Count
1 A Type 1 21
1 A Type 2 13
1 B Type 1 2
1 B Type 2 5
2 A Type 1 6
You can store value in map of map of map i.e. you will require to use map 3 level deep. So your map should be Map<String,Map<String,Map<String,Decimal>>>
You can populate map as shown below:
Map<String, Map<String,Map<String, Decimal>>> mapResults = new Map<String, Map<String,Map<String, Decimal>>>();
for(AggregateResult ar : groupedResult) {
String account = (String)ar.get('Account__c');
String serviceName = (String)ar.get('Service_Name__c');
String serviceType = (String)ar.get('Service_type__c');
Decimal countofRecords = (Decimal)ar.get('countOfRecords');
if(!mapResults.containsKey(account)) {
Map<String,Map<String,Decimal>> serviceNameMap = New Map<String,Map<String,Decimal>>();
serviceNameMap.put(serviceName, new Map<String,Decimal>{ serviceType => countofRecords});
mapResults.put(account, serviceNameMap);
}
else{
Map<String,Map<String,Decimal>> serviceNameMap = mapResults.get(account);
if(!serviceNameMap.containsKey(serviceName)){
Map<String,Decimal> serviceTypeMap = New Map<String,Decimal>{ serviceType => countofRecords };
mapResults.get(account).put(serviceName,serviceTypeMap);
}
else{
mapResults.get(account).get(serviceName).put(serviceType,countofRecords);
}
}
}
And when you want to check, you will need to get value from map as below:
if(mapResults.containsKey(objService.Account__c)) {
if(mapResults.get(objService.Account__c).containsKey(objService.Service_Name__c)) {
if(mapResults.get(objService.Account__c).get(objService.Service_Name__c).containsKey(objService.Service_Type__c)){
if(mapResults.get(objService.Account__c).get(objService.Service_Name__c).get(objService.Service_Type__c) >=
mapServiceRules.get(objService.Service_Name__c).MaximumRecords__c) {
objService.addError('This service has already been added the maximum number of times');
}
}
}
}
All Answers
Few questions here,
Is name field of Destiny_Products_and_Services__c is same as service type of service object?
As you are creating map mapServiceRules which contains key as name and value as count. And retriving values from map using service type of service object.
When we do group by 3 fields we get result like below
Account__c Service Name Service Type Count
1 A Type 1 21
1 A Type 2 13
1 B Type 1 2
1 B Type 2 5
2 A Type 1 6
You can store value in map of map of map i.e. you will require to use map 3 level deep. So your map should be Map<String,Map<String,Map<String,Decimal>>>
You can populate map as shown below:
Map<String, Map<String,Map<String, Decimal>>> mapResults = new Map<String, Map<String,Map<String, Decimal>>>();
for(AggregateResult ar : groupedResult) {
String account = (String)ar.get('Account__c');
String serviceName = (String)ar.get('Service_Name__c');
String serviceType = (String)ar.get('Service_type__c');
Decimal countofRecords = (Decimal)ar.get('countOfRecords');
if(!mapResults.containsKey(account)) {
Map<String,Map<String,Decimal>> serviceNameMap = New Map<String,Map<String,Decimal>>();
serviceNameMap.put(serviceName, new Map<String,Decimal>{ serviceType => countofRecords});
mapResults.put(account, serviceNameMap);
}
else{
Map<String,Map<String,Decimal>> serviceNameMap = mapResults.get(account);
if(!serviceNameMap.containsKey(serviceName)){
Map<String,Decimal> serviceTypeMap = New Map<String,Decimal>{ serviceType => countofRecords };
mapResults.get(account).put(serviceName,serviceTypeMap);
}
else{
mapResults.get(account).get(serviceName).put(serviceType,countofRecords);
}
}
}
And when you want to check, you will need to get value from map as below:
if(mapResults.containsKey(objService.Account__c)) {
if(mapResults.get(objService.Account__c).containsKey(objService.Service_Name__c)) {
if(mapResults.get(objService.Account__c).get(objService.Service_Name__c).containsKey(objService.Service_Type__c)){
if(mapResults.get(objService.Account__c).get(objService.Service_Name__c).get(objService.Service_Type__c) >=
mapServiceRules.get(objService.Service_Name__c).MaximumRecords__c) {
objService.addError('This service has already been added the maximum number of times');
}
}
}
}