I'm trying this code for dynamic results but it's showing the error shown below. Kindly help me with this code.
System.QueryException: Only variable references are allowed in dynamic SOQL/SOSL.
boolean first = true;
string database_query = '';
List<Schema.FieldSetMember> userfields = SObjectType.Task__c.FieldSets.Search.getFields();
for(Schema.FieldSetMember f : userfields) {
if (!first) {
database_query += ', ';
}
first = false;
database_query += f.getFieldPath();
}
if(Search_value != '' && database_query != ''){
TaskList = Database.query('select ' + database_query +',SOE__c from task__c where SOE__c =: \''+selectSOE +'\' and '+ selectedfield + ' like \'%' + Search_value +'%\'');
}
Please try to replace the ':=' with just '=' in your query. Also have a look at the answer to this question, I think you have similar problem:
Query using string not working
Related
String query = 'SELECT id,CreatedById,Product.Id,POCGrades__c ,fm_pocname__c,product.Name ,Visit.placeId, fm_poccode__c, createdby.LastName,Visit.LastModifiedDate, createddate, ActualBooleanValue'
+ ' FROM retailvisitkpi'
+ ' WHERE createddate = last_month and '
+ ' ( Product.Id = \'01t5j000003tszWAAQ\''
+ ' OR Product.Id = \'01t5j000003tszWAAQ\''
+ ' OR Product.Id = \'01t5j000003tt5nAAA\''
+ ' OR Product.Id = \'01t5j000003tsznAAA\''
+ ' OR Product.Id = \'01t5j000003tt1zAAA\''
+ ' OR Product.Id = \'01t5j000003tt7AAAQ\''
+ ' )';
I am having trouble to removes duplicate records based on Visit.placeID, can anybody help me out with soql
Just use hashmaps with the resulting query?
Map<String, retailvisitkpi__c> mapOfItems = new Map<String, retailvisitkpi__c>();
That will remove all the duplicates based on the Visit Place ID
I'm Working through this challenge and appear to have run into an issue i have not found a solution to (nor does it appear that anyone has posted a question on this specifically.)
looking at the log is pretty painful as any System.debug() lines appear to be dropped due to the size of the log being >18MB but it appears there are 40000 rows to be added. Having caved and looked at some of the other code dumps out there i dont see that anyone else looks to have had this issue or made any special arrangements with batching and as far as i can see i haven't done anything drastically different to them (but the subtlety is clearly more than enough to cause an issue).
So if anyone could have a look over this and give me a hint as to where/why i have gone wrong it would be a great help. I'm not looking for a link to a working code set to copy i'm hoping for some understanding as to where my approach is incorrect/causing issues
With my trigger
trigger MaintenanceRequest on Case ( after update) {
List<Case> closedCases = new List<Case>();
for (Case c : Trigger.New){
System.debug('Type :' + c.Type );
System.debug('Equals Repair: ' +c.Type.equalsIgnoreCase('Repair'));
System.debug('Equals Routine Maintenance: ' +c.Type.equalsIgnoreCase('Routine Maintenance'));
if (
(c.Type.equalsIgnoreCase('Repair') || c.Type.equalsIgnoreCase('Routine Maintenance'))
&& c.isClosed == true )
{
closedCases.add(c);
}
}
System.debug(closedCases.size() + ' cases were closed');
if(closedCases.size() > 0){
MaintenanceRequestHelper.createScheduledMaintainance(closedCases);
}
}
and helper
public with sharing class MaintenanceRequestHelper {
public MaintenanceRequestHelper() {
}
public static Map<Id,Integer> getMainainanceCycleForCases(){
List<AggregateResult> maintainTimes = [SELECT Maintenance_Request__c, MIN(Equipment__r.Maintenance_Cycle__c)cycle
FROM Equipment_Maintenance_Item__c
GROUP BY Maintenance_Request__c
];
System.debug(maintainTimes);
Map<Id,Integer> maintinTimeMap = new Map<Id,Integer>();
for( AggregateResult e : maintainTimes ){
maintinTimeMap.put((Id)e.get('Maintenance_Request__c'), ((Double)e.get('cycle')).intValue());
}
System.debug(maintinTimeMap);
return maintinTimeMap;
}
public static Map<Id,List<Id>> getMaintainanceItems(List<Case> closedCases){
// map maintainance_Request_ID, Equipment_Maintenance_Item__c
List<Equipment_Maintenance_Item__c> equipmentMaintainanceList = [SELECT Maintenance_Request__c,
Equipment__r.Id
FROM Equipment_Maintenance_Item__c
Where Maintenance_Request__c IN :closedCases];
Map<Id,List<Id>> maintainance_equipmentMap = new Map<Id, List<Id>>();
for (Equipment_Maintenance_Item__c e:equipmentMaintainanceList){
System.debug('Putting : '+ e.Maintenance_Request__c + ' : ' + e.Equipment__r.Id);
if(maintainance_equipmentMap.containsKey(e.Maintenance_Request__c)){
maintainance_equipmentMap.get(e.Maintenance_Request__c).add(e.Equipment__r.Id);
}else{
maintainance_equipmentMap.put(e.Maintenance_Request__c,new List<id>{e.Equipment__r.Id});
}
System.debug('Map now : '+ maintainance_equipmentMap);
}
System.debug('Returning: ' +maintainance_equipmentMap);
return maintainance_equipmentMap;
}
public static void createScheduledMaintainance(List<Case> closedCaseList) {
System.debug(closedCaseList.size() + ' Cases to create');
Map<Id,Integer> maintainTimeMap = getMainainanceCycleForCases();
Map<Id,List<Id>> maintainanceItems = getMaintainanceItems(closedCaseList); // map maintainance_Request_ID, Equipment_Maintenance_Item__c
List<Case> createNewCases = new List<Case>();
for(Case c : closedCaseList){
Case newCase = new Case();
newCase.Type = 'Routine Maintenance';
newCase.Status = 'New';
newCase.Vehicle__c = c.Vehicle__c;
newCase.Subject = c.Subject;
newCase.Date_Reported__c = Date.today();
newCase.Date_Due__c = Date.today() + maintainTimeMap.get(c.Id);
newCase.ProductId = c.ProductId;
createNewCases.add(newCase);
}
System.debug(createNewCases.size() +' to insert');
list<Equipment_Maintenance_Item__c> itemsListToinsert= new list<Equipment_Maintenance_Item__c>();
if(createNewCases.size()>0){
insert createNewCases;
for(Case ca : createNewCases){
for(Id key: maintainanceItems.keySet()){
List<Id> equipment = maintainanceItems.get(key);
for (Id e : equipment){
Equipment_Maintenance_Item__c newitem = new Equipment_Maintenance_Item__c();
newitem.Equipment__c=e;
newitem.Maintenance_Request__c= ca.Id;
itemsListToinsert.add(newitem);
}
}
}
}
System.debug('itemsListToinsert Size: ' +itemsListToinsert.size());
if (itemsListToinsert.size() >0){
insert itemsListToinsert; //<<<< ERROR TRIGGERS HERE and has ~40000 rows <<<<<
}
}
}
So, It seems i was over complicating the issue to an extent.
Having taken a break and walking through the problem again something just didnt sit right with this block of code.
if(createNewCases.size()>0){
insert createNewCases;
for(Case ca : createNewCases){
for(Id key: maintainanceItems.keySet()){
List<Id> equipment = maintainanceItems.get(key);
for (Id e : equipment){
Equipment_Maintenance_Item__c newitem = new Equipment_Maintenance_Item__c();
newitem.Equipment__c=e;
newitem.Maintenance_Request__c= ca.Id;
itemsListToinsert.add(newitem);
}
}
}
}
For -> For -> For -> create new Equipment_Maintenance_Item__c
With 0 checks to see if this new Equipment_Maintenance_Item__c was needed.
I ended up partly re-writing the class but the main change was re-working the section of code above to
List<Equipment_Maintenance_Item__c> equipmentMaintainanceList = [SELECT Maintenance_Request__c,
Equipment__r.Id
FROM Equipment_Maintenance_Item__c
Where Maintenance_Request__c IN :closedCaseList];
List<Equipment_Maintenance_Item__c> updatedEquipment = new List<Equipment_Maintenance_Item__c>();
for(Case closed : closedCaseList){
for(Equipment_Maintenance_Item__c eqip : equipmentMaintainanceList){
if (eqip.Maintenance_Request__c == closed.Id){
Equipment_Maintenance_Item__c e = eqip.clone(false, false, false, false);
e.Maintenance_Request__c = oldToNewMap.get(closed.Id).Id;
updatedEquipment.add(e);
}
}
}
if (updatedEquipment.size() > 0 ){
insert updatedEquipment;
}
For me the lesson is be very mindful of nested for loops when the outcome is going to come up against some hard and fast governor limits.
I want to make it so that it would grab out certain information after certain words, and stop at certain words, for example
ss!submit | WIYISD: _____ | SHIWW: _____ | WDYWTA: _____ | SPN: _____
Collect arguements after the WIYISD:, SHIWW:, WDYWTA:, and SPN: and stop at the |'s after collecting each arguement.
I just don't know where to start.
I looked at what other people did, and I tried to pull it off myself but can't figure out how.
Edit: I'd like it based off of user input, and posts it in a channel, kind of similar to the bug-bot in discord testers.
Start by splitting at the vertical bars to get each portion of the string (String.split()). Then, iterate through the substrings ("Loops and iteration") and check the start of each (String.startsWith()), dealing with the resulting arguments however you want.
const str = 'ss!submit | WIYISD: hopefully | SHIWW: this code | WDYWTA: will | SPN: help you!';
const split = str.split(' | ').slice(1); // Also removing the command portion.
const args = {};
for (let i = 0; i < split.length; i++) {
const arg = split[i];
if (arg.startsWith('WIYISD: ')) args.WIYISD = arg.replace('WIYISD: ', '');
else if (arg.startsWith('SHIWW: ')) args.SHIWW = arg.replace('SHIWW: ', '');
else if (arg.startsWith('WDYWTA: ')) args.WDYWTA = arg.replace('WDYWTA: ', '');
else if (arg.startsWith('SPN: ')) args.SPN = arg.replace('SPN: ', '');
else {
console.error('Check your syntax.'); // Send an error message instead...
break; // ...and return (illegal in this context).
}
}
console.log(args); // The result in this example is an object, not an array.
Incorporating this into your message event...
// const bot = new Discord.Client();
const prefix = 'ss!';
bot.on('message', message => {
// Stop if the author is a bot or the message doesn't start with the prefix.
if (message.author.bot || !message.content.startsWith(prefix)) return;
// This is a very crude setup. Consider a command handler to keep the code organized.
if (message.content.startsWith(`${prefix}submit `)) {
const split = message.content.split(' | ').slice(1);
const args = {};
for (let i = 0; i < split.length; i++) {
const arg = split[i];
if (arg.startsWith('WIYISD: ')) args.WIYISD = arg.replace('WIYISD: ', '');
else if (arg.startsWith('SHIWW: ')) args.SHIWW = arg.replace('SHIWW: ', '');
else if (arg.startsWith('WDYWTA: ')) args.WDYWTA = arg.replace('WDYWTA: ', '');
else if (arg.startsWith('SPN: ')) args.SPN = arg.replace('SPN: ', '');
else {
return message.channel.send(':x: Invalid syntax.')
.catch(console.error); // Make sure the catch rejected promises.
}
}
// Use 'args' as you wish.
}
});
I am doing a fairly simple query for contact records using dynamic soql using the following method:
public PageReference contactSearch() {
contactResultSetSize = 0;
if(!String.isEmpty(firstname) || !String.isEmpty(lastname) || !String.isEmpty(company)) {
string soql = 'Select firstname, lastname, account.Name, account.BillingStreet, account.BillingCity, account.BillingState, account.BillingPostalCode From Contact';
String whereClause = '';
if(!String.isEmpty(firstname)) {
whereClause = ' Where firstname like \'%' + firstname + '%\'';
}
if(!String.isEmpty(lastname)) {
if(!String.isEmpty(firstname)) {
whereClause += ' AND lastname like \'%' + lastname + '%\'';
}
else {
whereClause = ' Where lastname like \'%' + lastname + '%\'';
}
}
if(!String.isEmpty(company)) {
if(!String.isEmpty(firstname) || !String.isEmpty(lastname)) {
whereClause += ' AND account.Name like \'%' + company + '%\'';
}
else {
whereClause = ' Where account.Name like \'%' + company + '%\'';
}
}
soql = soql + whereClause;
List<Contact> searchResults = Database.query(soql);
contactResultSetSize = searchResults.size();
if(contactLinesForPage == null) {
contactLinesForPage = new List<ContactWrapper>();
}
for(Contact c : searchResults) {
contactLinesForPage.add(new ContactWrapper(contactLinesForPage.size(), c, ''));
}
}
return null;
}
I am using a wrapper class and contactLinesForPage is a list of my wrapper object:
public List<ContactWrapper> contactLinesForPage {get; set;}
As a user does multiple searches, I don't want to re-add records to the searchResults list. How can I check if a record already exists in my object so I don't have duplicate records returned in the search?
Thanks for any help.
Or you could use a map. Add the ContactWrapper objects to the map. The key to the map is an id. If they add a duplicate contact it will simply overwrite the one already there. Your code would simply be
aMap.put(cw.id, cw); // one line eliminates duplicates.
When you want the list of ContactWrappers, simply return aMap.values();
If you want to abstract the behavior of maintaining the collection of Contacts, create a ContactCollection class and hide the implementation in there. This would provide something more reusable as well as a good pattern for similar situations.
Just add a check if contactLinesForPage allready contains this contact. Something like this:
for(Contact c : searchResults) {
Boolean toInsert = true;
for(ContactWrapper cw : contactLinesForPage){
if(cw.contact.Id == c.Id){
toInsert=false;
}
}
if(toInsert){
contactLinesForPage.add(new ContactWrapper(contactLinesForPage.size(), c, ''));
}
}
My company has an app that they got off of the app exchange(Note: before I started) that allowed you to follow or unfollow large number of cases/accounts/opportunities etc in salesforce.com. Supposedly it worked before and now it isn't working. I need an idea of what is wrong with the code for each button. If I can't fix them, any ideas for a replacement app? The app is no longer on the app exchange any more.
here's the code for the follow button:
{!REQUIRESCRIPT("/soap/ajax/18.0/connection.js")}
//EDIT THE FOLLOWING LINE TO ALTER THE CODE FOR OTHER OBJECTS. USE THE PICKLISTS ABOVE TO SELECT FIELD TYPE = $ObjectType AND THE OBJECT NAME THEN REPLACE "$ObjectType.Case" WITH YOUR NEW OBJECT NAME
var records = {!GETRECORDIDS( $ObjectType.Case)};
function LBox() {
var box = new parent.SimpleDialog("steve"+Math.random(), true);
parent.box = box;`
box.setTitle("Follow Records");
box.createDialog();
box.setWidth(220);
box.setContentInnerHTML("<img src='/img/loading32.gif' alt='' /> Running");
box.setupDefaultButtons();`
box.show();
}
function CBox(){
box.setContentInnerHTML("You are now following "+follow_count+" records<br /><br />Close");
}
if (records[0] == null) {
alert("Please select at least one record.");
}
else {
var follow_count = 0;
LBox();
for (var i = 0; i < records.length; i++){
var fol=new sforce.SObject("EntitySubscription");
fol.ParentId = records[i];
fol.SubscriberId = '{!User.Id}';
try{
sforce.connection.create([fol]);
follow_count++;
}
catch(e){
alert(e);
}
}
CBox();
}
here's the unfollow button:
{!REQUIRESCRIPT("/soap/ajax/18.0/connection.js")}
// EDIT THE FOLLOWING LINE TO ALTER THE CODE FOR OTHER OBJECTS. USE THE PICKLISTS ABOVE TO SELECT FIELD TYPE = $ObjectType AND THE OBJECT NAME THEN REPLACE "$ObjectType.Case" WITH YOUR NEW OBJECT NAME
var records = {!GETRECORDIDS( $ObjectType.Case)};
// display running message popup
function LBox() {
var box = new parent.SimpleDialog("steve"+Math.random(), true);
parent.box = box;`
box.setTitle("Unfollow Records");
box.createDialog();
box.setWidth(220);
box.setContentInnerHTML("<img src='/img/loading32.gif' alt='' /> Running");
box.setupDefaultButtons();
box.show();
}
// display output message
function CBox(){
if (unfollow_count < records.length)
box.setContentInnerHTML("You have now unfollowed "+unfollow_count+" records. You were not following the other selected records. <br /><br />Close");
else
box.setContentInnerHTML("You have now unfollowed "+unfollow_count+" records. <br /><br />Close");
}
if (records[0] == null) {
alert("Please select at least one record.");
}
else {
var unfollow_count = 0;`
LBox();
try {
// find following records
var searchstring = "SELECT Id FROM EntitySubscription WHERE (ParentId IN (";
for (var i = 0; i < records.length - 1; i++) {
searchstring += "'" + records[i] + "',";
}
searchstring += "'" + records[records.length - 1] + "') AND SubscriberId ='{!User.Id}')";
var resultRecords = sforce.connection.query(searchstring).getArray("records");
// delete following records
var recordIds = [];
for (var i = 0; i < resultRecords.length; i++) {
recordIds.push(resultRecords[i].Id);
unfollow_count++;
}
sforce.connection.deleteIds(recordIds);
} catch(e) {
alert(e);
}
CBox();
}
The first error message has to do with permissions, I don't get this error because I have admin rights, the second error is only on the account tab's button. I'm more worried about the permissions problem, is there anything there about permissions. Any help is great!
I think the issue is a throttle in SFDC, you are limited to following only a certain number of records per user. If this app was designed as you described to mass-follow records, it's possible your hitting that throttle, which is kind of the impression I get from the error your co-worker is receiving about at most 1000, also if it worked before, it would make sense that you have maxed out a limit for the org/user
Queries on EntitySubscription by users who aren't system admins must contain a LIMIT. If you change the query code in the button to the following it should work:
// find following records
var searchstring = "SELECT Id FROM EntitySubscription WHERE (ParentId IN (";
for (var i = 0; i < records.length - 1; i++) {
searchstring += "'" + records[i] + "',";
}
searchstring += "'" + records[records.length - 1] + "') AND SubscriberId ='{!User.Id}') LIMIT 1000";