+ Start a Discussion
EQ AdminEQ Admin 
for(Apttus_Billing__Invoice__c invoice:invoiceObjectList1) // loop over invoices
              {
                  List<InvoiceLineItems> listToStoreLineItems = new List<InvoiceLineItems>();
                  APTS_InvoiceJournalWrapper invoiceJournWrapper= new APTS_InvoiceJournalWrapper();
                   countHeader=0;
                   
                   count=count+1;
                  Decimal Sum=0;
                   
                                    invoiceJournWrapper.id=String.valueof(invoice.id);
                                    invoiceJournWrapper.HeaderKey=String.valueof(count);
                                    invoiceJournWrapper.ZCurrency=(invoice.CurrencyIsoCode!=null?invoice.CurrencyIsoCode:'USD');
                                    //invoiceJournWrapper.AccountingJournal='null';
                                    invoiceJournWrapper.AccountingJournalID=String.valueOf(invoice.Name + '_' +myDate);
                                    invoiceJournWrapper.JournalNumber=String.valueOf(invoice.Name + '_' +myDate);
                                    invoiceJournWrapper.ExternalReferenceID=String.valueOf(invoice.Name);                  
                                    invoiceJournWrapper.AccountingDate=String.valueof(Date.valueof(invoice.Apttus_Billing__InvoiceDate__c));
                  //-------------------
                  list<Apttus_Billing__InvoiceLineItem__c> invlineitems=[Select id,Apttus_Billing__AssetLineItemId__r.Apttus_Config2__ProductId__r.ProductCode,Apttus_Billing__AssetLineItemId__r.Apttus_Config2__OptionId__r.ProductCode,Apttus_Billing__InvoiceId__r.Name,Apttus_Billing__ProductId__r.Name,Apttus_Billing__InvoiceId__r.CurrencyIsoCode,
                                                                      Apttus_Billing__Type__c,Apttus_Billing__InvoiceId__c,Name,Apttus_Billing__Amount__c,Apttus_Billing__SoldToAccountId__r.EQ_ClientRef__c,Apttus_Billing__LocationId__c,
                                                                      Apttus_Billing__ProductId__r.EQ_FeeCode__c,Apttus_Billing__BillToAccountId__r.EQ_ClientRef__c,Apttus_Billing__ProductId__r.ProductCode,Apttus_Billing__InvoiceId__r.EQ_TotalInvoiceAmount__c 
                                                             from Apttus_Billing__InvoiceLineItem__c where Apttus_Billing__InvoiceId__c=:invoice.id and Apttus_Billing__Type__c='Contracted' and Apttus_Billing__Amount__c!=0];
                  //----
                  //
                  //-------------
                   InvoiceLineItems FirstInvItems= new InvoiceLineItems();
                            countHeader=countHeader+1;
                            FirstInvItems.LineKey=string.valueof(countHeader);

 
Best Answer chosen by EQ Admin
paul diracpaul dirac
I find some errors and the code does not compile (i mocked all of your custom object but anyway there might be some sintax errors).
Consider to split some "iterative tasks" in an helper (static) class, since your Rest service might grows in future, developers (you too ofc) may encounter difficulties to maintain that. For example, that part in which lineItems are collected and then modified can be delegated to the helper class to enhance code readability.
Further little optization can be done storing fixed numbers/strings in costants but I guess that there are not any improvements that significately reduce the execution time, I mean the optimization I will want to see here is in code readability first. Hope I helped you to solve your cancerns!
Chris760Chris760 
I have a regular old PDF file on my desktop, and that same PDF file is attached to a record in Salesforce.  Now, when I change the PDF's extension on my computer to ".txt", I can then open it and read the texttual data that makes up the file.  I need to extract some data at the beginning of the ".txt" version of the file that details how many pages the PDF consists of, but I need to do this for many PDF files that are already in Salesforce.

I discovered the "String pdf = System.EncodingUtil.base64Encode(a.Body)" method, which apparently converts the base64 blob representation of the file into an unencoded string... but when I looked at the actual output, I realized that it was totally different compared to the ".txt" version of the PDF on my desktop.  It seems that I'm not encoding/decoding the attachment Body blob to the correct format, but I'm totally clueless as to what to convert it to, or what method I would need to use to convert it.

Does anyone have any ideas as to how I would convert the PDF data to whatever format it gets converted to when I just change the extension on my computer and view it in notepad?

Thanks!


Best Answer chosen by Chris760
Ray GuyRay Guy
This isn't easy at all unfortunately.   What you're trying to do is view the bytes of the attachment coverted into displayable characters where possible.   What opening it in a text editor is doing for you is ignoring the binary characters that don't make sense as display characters.   Unfortunately if you try and get there using apex, salesforce will stop you short since there's no way to tell it to ignore binary values that aren't character display data.   Instead of ignoring them, it will give you an error instead when it encounters them.  For example, you could try and convert the Attachment's Body field to a String directly using:

String pdf = attachment.Body.toString();

but it's going to give you an error saying the BLOB (binary data) is "not a valid UTF-8 string".   What it means by this is some of the values it's coming across in the binary data don't match to any character it could put in a String (Salesforce uses "UTF-8" string encoding) - so it rejects the whole lot.   Your text editor on the other hand just replaces these with whitespace and lets you view the valid ones.

You can turn binary data into a form that can be shown in a String but that's what you have already, and as you've found, in order to turn all the binary data into valid display characters it encodes the whole thing making it unreadable for your purposes.

It would be great if you were able to step through the binary data in the Attachment Body one byte at a time, extract the ones that are normal characters and ignore the others.   But this isn't possible in apex.

The convoluted workaround that some have done involves turning the binary data into encoded base64 format (as you have).   But then hand-rolling a base64 decoder which will pick through the encoded string piece by piece and give you access to the individual decoded byte values.    You would then be able to add your own logic to determine if the byte is in the normal ascii character range (0 to 128)  (This appears to be how the values are stored in the first part of a PDF)

Here's a stackexchange question where the accepted answer delves into this a bit: http://salesforce.stackexchange.com/questions/860/mimic-mysql-aes-encrypt-in-apex/910#910
But it's pretty heavy code work I'm afraid and far from simple.

Ray
ForceClarity Ltd.
Anthony Wheeler 1Anthony Wheeler 1 
I'm wondering if this is just a glitch in Salesforce and if anyone has any workaround. I currently have a Trigger on ContentDocumentLink that sends an email to the owner of a custom object record when a File or Note is created and attached to that record. The trigger also attaches file information and the body of the Note if it's a ContentNote being inserted. The trigger handles the logic in differentiating Notes from other file types. The problem is when the user hits the button to create a new Note in classic or in the Console, an empty, untitled, new note record is inserted instantly firing my trigger before the user has time to add content to the body. In Lightning it at least allows the user to fill out the header of the note before saving, but saves before the note body is filled out. Cancelling out of creating the note still leaves the blank note saved and attached to the record. Any help in understanding why the note saves before the user hits the save button would be appreciated.
Best Answer chosen by Anthony Wheeler 1
Ryan GreeneRyan Greene
This is an annoying way SF setup the Content Notes. It does save every secord or so after the user starts typing. The only way I could figure out how to overcome this issue is to run batch Apex, but then you loose the real time notifications. Might need to try hooking it up Chatter somehow.
James Kacerguis 5James Kacerguis 5 
I currently have apex class in lightning component that is getting a specific Queue Id to assign as owner of the record the component is launched from.

This is the current  way I'm getting the id, but I'm guessing there is a better way to do this, any ideas?
Group marketingQueue = [SELECT id,Name FROM Group WHERE Type = 'Queue' and DeveloperNAME = 'MarketingProspectLeads'];
         	ID marketingQueueId = marketingQueue.id;
            //l.OwnerId = UserInfo.getUserId();
            system.debug('marketingQueue');
            l.OwnerId = marketingQueueId;

I just need to make sure this can't break so I'm assuming I should add some error checking or be doing this a different way.  Thanks in advance.  
Best Answer chosen by James Kacerguis 5
Sonali_takkeSonali_takke
Hi James,
If you don't require Name then you can modify your query as follows to reduce number of lines in code and add NULL check before assignment to avoid code break.
 
ID marketingQueueId = [SELECT id FROM Group WHERE Type = 'Queue' and DeveloperNAME = 'MarketingProspectLeads'].Id;

if(marketingQueueId != NULL) {
    l.OwnerId = marketingQueueId;
}

Kindly mark as resolved if you find this anser helpful. 
Matthew HofmannMatthew Hofmann 
Hello,

I'm creating an Apex class that creates a Salesforce File record and associates it with a parent record. I'm having a problem creating the association (ContentDocumentLink) record.

Here is what I'm doing:
  • Create a ContentVersion record. This creates a ContentDocument record automatically if you leave the ContentVersion.ContentDocumentId field blank. (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contentdocument.htm - "To create a document, create a new version via the ContentVersion object without setting the ContentDocumentId. This automatically creates a parent document record.")
  • Insert ContentVersion record
  • DEBUG: Confirm ContentVersion.ContentDocumentId is set (Here is where the problem is because it is NULL; however if I SOQL query ContentVersion after the Apex completes, ContentVersion.ContentDocumentId is set and the corresponding ContentDocument record exists)
  • Create ContentDocumentLink record (commented out because it fails because ContentDocumentLink.ContentDocumentId is a required field)
  • Insert ContentDocumentLink record (commented out because it fails because ContentDocumentLink.ContentDocumentId is a required field)
Here is the code:
public class FileController {
    
    @AuraEnabled
    public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType, Id contentDocumentId) { 
        base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');
        
        ContentVersion cv = new ContentVersion();
        cv.ContentLocation = 'S';
        cv.ContentDocumentId = contentDocumentId;
        cv.VersionData = EncodingUtil.base64Decode(base64Data);
        cv.Title = fileName;
        cv.PathOnClient = filename;
        
        insert cv;
        
        //***This DEBUG statement must return an Id for the rest of the code to work***
        System.debug('contentDocumentId='+cv.ContentDocumentId);               
        
        //ContentDocumentLink cdl = new ContentDocumentLink();
        //cdl.ContentDocumentId = cv.ContentDocumentId;
        //cdl.LinkedEntityId = parentId;
        //cdl.ShareType = 'I';
        
        //insert cdl;
        
        return cv.Id;
    }

    @AuraEnabled
    public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType) {         
        return saveTheFile(parentId, fileName, base64Data, contentType, NULL);
    }
}

Does anyone know what I'm doing wrong, not considering, etc?
Appreciate any thoughts and input!
Best Answer chosen by Matthew Hofmann
VineetKumarVineetKumar
Interesting..

Well the culprit in your code is the null value and way you are using it to assign the value to ContentDocumentLink.contentDocumentId.
You should query the content version object again to get the contentDocumentId (which is generated after the parent document is inserted by default because of you passing of null value).
Something like below :
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = [SELECT Id, ContentDocumentId FROM ContentVersion WHERE Id =: cv.Id].ContentDocumentId;
cdl.LinkedEntityId = '00590000000a6dP';
cdl.ShareType = 'V';
insert cdl;

As per the salesforce documentation lines higlighted by you, "To create a document, create a new version via the ContentVersion object without setting the ContentDocumentId. This automatically creates a parent document record." it does create the parent document record as expected, but the contentDocumentId is still null in above initialised object. Id doesn't get updated automatically to the object instance. Infact you will have to pull out the corresponding Id as done in the above snippet.

Let me know if this helps.
Rodolfo CalvoRodolfo Calvo 
Hello team, 
I have this code
String soql = 'SELECT id, firstName, lastName, accountId FROM Contact';
I need to call all contacts from one simple account. 
I tried this: 
 
SELECT firstName, lastName, accountId FROM Contact WHERE accountid = '00000000000000'

This query worked fine, but my issue is calling all contact list from calling the account name: 
For example: I have Account_1, what I only have is the name, we imagine we do not have the ID, how could make this query by calling the name of the account?
I also tried this but there was no succeed.
String soql = 'SELECT id, firstName, lastName, accountId FROM Contact WHERE account.id;
How could I make this query correct? 
Thanks in advance
 
Best Answer chosen by Rodolfo Calvo
Arun GoelArun Goel
If you directly run the query in Developer c
SELECT id, firstName, lastName, accountId FROM Contact WHERE Account.name =  'Master Account'

onsole try this
Nidhi MeshramNidhi Meshram 
Trigger having all the events so in handler there are two methods which i not able to cover how to cover this methods:-

public void afterDelete(SObject so) {
    }
    
    public void afterUndelete(SObject so) {
    }
Best Answer chosen by Nidhi Meshram
Steve Schreiner 4Steve Schreiner 4
Remove the unused events from the trigger. Why have them if never used?
Carrie Nunemaker 10Carrie Nunemaker 10 
I am completely new to Apex and could really use some help with what seems to be a simple task.  I have a formula on the contact, Persona_True__c, that returns a 1 if the custom field "persona" is populated and a 0 if it is blank.

I would like to have a roll-up summary that sums this field at the account level in a field called Related_Personas__c.  

Because we can't roll-up from contact to account I'm reading that this type of action needs to be a trigger, but I don't even know where to start.  Does anyone have any thoughts or expertise they can share to help me out? 
Best Answer chosen by Carrie Nunemaker 10
Anthony McDougaldAnthony McDougald
Good Evening Carrie,
Hope that your day is off to an amazing start. We've constructed a trigger to your specifications. Please test and report back if anything. Hope this helps and may God bless you abundantly.
trigger ContactSumTrigger on Contact (after delete, after insert, after undelete, after update) {

Contact[] cons;
    if (Trigger.isDelete){ 
    cons = Trigger.old;
    }
    else{
    cons = Trigger.new;
    }
Set<ID> acctIds = new Set<ID>();
for (Contact con : cons) {
   acctIds.add(con.AccountId);
}

Map<ID, Contact> contactsForAccounts = new Map<ID, Contact>([SELECT Id, AccountId, Persona_True__c FROM Contact WHERE AccountId IN :acctIds]);

Map<ID, Account> acctsToUpdate = new Map<ID, Account>([SELECT Id, Related_Personas__c FROM Account WHERE Id IN :acctIds]);

for (Account acct : acctsToUpdate.values()) {
Set<Id> conIds = new Set<Id>();
Decimal totalValue = 0;
for (Contact con : contactsForAccounts.values()) {
    if (con.AccountId == acct.Id && con.Persona_True__c != NULL) {
        totalValue += con.Persona_True__c; 
    }
}
acct.Related_Personas__c = totalValue;
}
if(acctsToUpdate.values().size() > 0) {
    update acctsToUpdate.values();
}
}


Best Regards,
Anthony McDougald
iKnowSFDCiKnowSFDC 

I have a list I need to sort by a primary key as well as a secondary key - I tried ORDER BY fieldName AND fieldNAME as well as ORDER BY fieldName AND BY fieldName - neither one compiled on save. 

 

Any ideas? 

 

Thanks!

 

JoAnn

Best Answer chosen by Admin (Salesforce Developers) 
craigmhcraigmh

Order By fieldName1, fieldName2

csbaacsbaa 

Hello Helper

 

I want to export   from an org a package  containing  custom objects,  Custom fields , classes,  custom buttons......

 

I created a package.xml  file where I included  the Metadata  types  I want to export

 

I can not  specify  Custom button Metadata  type

Looking into the salesforce docs it seems to me that is is  considered as weblink

 

I tried  something like  below

 

.....

<types>
<members>Account.CustomButton_1</members>
<members>Account.CustomButton_1</members>
<name>webLinks</name>
</types>

 

 

 

but it does not work

 

any suggestion?

 

 

Thanks in advance

Csaba

 

 

 

 

Best Answer chosen by csbaa
David CheungDavid Cheung
@csaba, meta data name for custom button is WebLink - in the singular form, you had it as WebLinks.
@Admin why was @Vinita_SFDC chosen as the best answer?