You need to sign in to do that
Don't have an account?
Haseeb Ahmad 9
Adding attachments in apex, convert the code to add Files
Hi Everyone,
I have this Apex class which creates SOW and attached to "Notes & Attachments" and I want to change that so when we generate SOW it attach to files instead.
This is Apex class which generate and attached SOW, how can change this to it be attached to Files. Thank you for your help.
I have this Apex class which creates SOW and attached to "Notes & Attachments" and I want to change that so when we generate SOW it attach to files instead.
/** * This controller will generate a Quote PDF and attach it to the Quote's parent Opportunity. */ global class ZuoraDocumentGenerator { @testVisible private static final string noAmountResponse = 'Please add ACV to the opportunity before generating an SOW'; @testVisible private static final string noOpportunitiesResponse = 'No opportunities found.'; @testVisible private static final string notCorrectStage= 'You cannot generate an SOW before Stage 4, please fill out the required integration fields and move your Opportunity to Stage 4 to continue generating the SOW.'; @testVisible private static final string oppOverThresholdResponse = 'Please chatter <a href="/_ui/core/chatter/groups/GroupProfilePage?g=0F90d0000008YEA" target="_blank">@Professional Services</a> in order to get an SOW generated'; @testVisible private static final string noTemplateFoundResponse = 'No SOW templates are setup.'; @testVisible private static final string errorContactingZuoraResponse = 'Error contacting Zuora'; @testVisible private static integer testStatusCode; @testVisible private static string testSuccessMessage; // Generates PDF and attaches to Quote's parent Opportunity Object. @AuraEnabled webservice static String generateSOW(Id quoteId, String docType) { // query for quote to pull opportunity ID System.debug('** quoteid: '+ quoteId); System.debug('** doctype = '+ docType); List<zqu__quote__c> quotes = [select zqu__opportunity__c from zqu__quote__c where id = :quoteId limit 1]; if (quotes.isEmpty()) { return 'No quotes found.'; } // query for opp to pull licenses cost List<Opportunity> opps = [select name,Custom_SOW__c,Number_of_Seats__c, StageName, Record_Type_Name__c, sales_engineer__r.email, bundles__c,SOWException__c, account.billingCountry,rvpe__RVAccount__r.Name, Use_Case__c from opportunity where id = :quotes[0].zqu__opportunity__c limit 1]; if (opps.isEmpty()) { return noOpportunitiesResponse; } if (opps[0].Custom_SOW__c == true) { return 'Unable to process Autogen request due to Custom SOW already generated. Please send a Chatter message to @proserv for assistance.'; } //if the opportunity stage is not at least stage 4 throw this error. List<String> stageList = new List<String>{'Stage 4-Shortlist', 'Stage 5-Verbal', 'Stage 6-Legal / Contracting','Stage 7-Closed Won','Stage 8-Closed Won: Finance'}; if ((!stageList.contains(opps[0].StageName)) && opps[0].Record_Type_Name__c =='New Business'){ return notCorrectStage; } // if there is no amount return error if (opps[0].Number_of_Seats__c == null) { return noAmountResponse; } // get template name based on amount and bundles; if no template is returned, it is above the threshold --> return over threshold response String templateName = getTemplateName(opps[0]); if (templateName == null) { return oppOverThresholdResponse; } // query for template using name, get the ID List<zqu__Quote_Template__c> quoteTemplateList = [select zqu__Template_Id__c from zqu__Quote_Template__c where name = :templateName limit 1]; if (quoteTemplateList.isEmpty()) { return noTemplateFoundResponse; } // make HTTP call to zuora to generate the document HttpResponse res = generateSOW(quoteTemplateList, quoteId, docType); if (res.getStatusCode() != 200) { return errorContactingZuoraResponse; } String zuoraResponse = res.getBody(); if(Test.isRunningTest()){ zuoraResponse = testSuccessMessage != null ? testSuccessMessage : 'Quote PDF document has been successfully AttachmentID: 10101'; } // if response is successful, update the attachment name and response for SOW template String successMessage = 'document has been successfully'; // list of objects to update (opp and attachment) List<sObject> recordsForUpdate = new List<sObject>(); // keep track of any dml errors String dmlErrors = ''; if (zuoraResponse.contains(successMessage)) { // replace 'Quote' with 'SOW' zuoraResponse = zuoraResponse.replace('Quote', 'SOW'); // update opportunity with 'SOW Generated' = true recordsForUpdate.add(updateOpportunity(opps[0])); // update attachment name Attachment attachment = updateAttachment(zuoraResponse, opps[0], docType); if (attachment != null) { recordsForUpdate.add(attachment); } else { dmlErrors += 'No attachment found for update.'; } // send email to solution engineer notifySolutionEngineer(opps[0]); } if (!recordsForUpdate.isEmpty()) { List<Database.saveResult> results = Utils.saveRecords(recordsForUpdate, 'Update'); dmlErrors += Utils.getResultErrorString(results); } // if there were DML errors, send email to admin if (String.isNotBlank(dmlErrors)) { String subject = 'Error(s) in ZuoraDocumentGenerator ' + Date.today(); Utils.sendEmailToAdmin(subject, dmlErrors); } return zuoraResponse; } private static String getTemplateName(Opportunity opp) { String results = null; Account account = [select id, billingCountry from Account where id =:opp.AccountId]; if (opp.Number_of_Seats__c > 50 ) { return results; } Set<String>useCase = new Set<String>(); useCase.addAll(opp.Use_Case__c.split(';')); boolean isSales = false; boolean isSupport = false; for(String st : useCase){ System.debug('*** st ='+st); if(useCase.contains('Sales')){ isSales = true; } if(useCase.contains('Support')){ isSupport = true; } } if(opp.rvpe__RVAccount__r.Name !=null && opp.rvpe__RVAccount__r.Name.contains('Mitel')){ if (opp.Use_Case__c == 'Sales'|| (isSales && isSupport)) { if (opp.Number_of_Seats__c > 15) { results = 'SOW 2'; } else if (opp.Number_of_Seats__c <= 14) { results = 'SOW 1'; } else{ results = 'SOW 1'; } } } if(account.billingCountry == 'United States' || account.billingCountry == 'USA' || account.billingCountry == 'US' || account.billingCountry == 'United States of America' || account.billingCountry == 'Canada' || account.billingCountry == 'CAN'){ // Sales use case if (opp.Use_Case__c == 'Sales'|| (isSales && isSupport)) { if (opp.Number_of_Seats__c > 15) { results = 'PPT SOW 2'; } else if (opp.Number_of_Seats__c <= 14) { results = 'PPT SOW 1'; } else{ results = 'PPT SOW 2'; } } // Support use case else if(opp.Use_Case__c == 'Support') { if (opp.Number_of_Seats__c > 15) { results = 'PPT SOW 2'; } else if (opp.Number_of_Seats__c <= 14) { results = 'PPT SOW 1'; } else{ results = 'PPT SOW 1'; } } }//this will be called if the billing country is not the US or Canada else{ if (opp.Use_Case__c == 'Sales'|| (isSales && isSupport)) { if (opp.Number_of_Seats__c > 15) { results = 'SOW 2'; } else if (opp.Number_of_Seats__c <= 14) { results = 'SOW 1'; } else{ results = 'SOW 1'; } } // Support use case else if(opp.Use_Case__c == 'Support') { if (opp.Number_of_Seats__c > 15) { results = 'SOW 2'; } else if (opp.Number_of_Seats__c <= 14) { results = 'SOW 1'; } else{ results = 'SOW 1'; } } } return results; } public class SessionId { public String sessionId; } private static String getUserSessionId() { SessionId sessionJson = new SessionId(); if(!Test.isRunningTest()) { sessionJson = (SessionId)JSON.deserialize(Page.ZuoraGenerateSOW.getContent().toString(), SessionId.class); } return sessionJson.sessionId; } private static HttpResponse generateSOW(List<zqu__Quote_Template__c> quoteTemplateList, Id quoteId, String docType) { // Generate Quote and attach to Opportunity Map<String,Object> zuoraConfigInfo = zqu.zQuoteUtil.getZuoraConfigInformation(); Zuora.ZApi zApi = new Zuora.ZApi(); Zuora.ZApi.LoginResult loginResult = new Zuora.ZApi.LoginResult(); if(!Test.isRunningTest()){ loginResult = zApi.zLogin(); } else { loginResult.serverUrl = 'apisandbox'; } String quoteServletUrl = loginResult.serverUrl.contains('apisandbox') ? 'https://apisandbox.zuora.com/apps/servlet/GenerateQuote' : 'https://zuora.com/apps/servlet/GenerateQuote'; String sessionId = UserInfo.getSessionId(); String sfdcUrl = URL.getSalesforceBaseUrl().toExternalForm() + '/services/Soap/u/10.0/' + UserInfo.getOrganizationId(); PageReference generatePage = new PageReference(quoteServletUrl); generatePage.getParameters().put('templateId', quoteTemplateList[0].zqu__Template_Id__c); generatePage.getParameters().put('serverUrl', sfdcUrl); generatePage.getParameters().put('sessionId', getUserSessionId()); generatePage.getParameters().put('quoteId', quoteId); generatePage.getParameters().put('attachToOpportunity', 'true'); generatePage.getParameters().put('format', docType); generatePage.getParameters().put('ZSession', loginResult.session); generatePage.getParameters().put('useSFDCLocale', '1'); generatePage.getParameters().put('locale', UserInfo.getLocale()); // Zuora handles the attaching it to the opportunity through the https callout. Http h = new Http(); HttpRequest req = new HttpRequest(); req.setEndpoint(generatePage.getUrl()); req.setMethod('GET'); req.setTimeout(30000); if (!Test.isRunningTest()) { HttpResponse response = h.send(req); System.debug('response>>>' + response); return response; } else { HttpResponse res = new HttpResponse(); Integer statusCode = testStatusCode != null ? testStatusCode : 200; res.setStatusCode(statusCode); return res; } } private static Opportunity updateOpportunity(Opportunity opportunity) { // update boolean on opportunity to indicate an SOW was generated opportunity.SOW_Generated__c = true; opportunity.Bypass_Opportunity_Validation__c = true; return opportunity; } private static Attachment updateAttachment(String zuoraResponse, Opportunity opportunity, String docType) { String errorMessage = ''; String attachmentId = zuoraResponse.split('AttachmentID:', 0)[1].normalizeSpace(); List<Attachment> attachments = [select id, name from attachment where id = :attachmentId limit 1]; if (!attachments.isEmpty()) { attachments[0].name = 'SOW for ' + opportunity.name + '.' + docType; return attachments[0]; } else { return null; } } private static void notifySolutionEngineer(Opportunity opportunity) { List<String> toAddresses = new List<String>(); if (opportunity.Sales_Engineer__c != null) { toAddresses.add(opportunity.Sales_Engineer__r.email); } else { toAddresses.add(); toAddresses.add(); } String subject = 'An SOW has been generated for ' + opportunity.name; String baseURL = URL.getSalesforceBaseUrl().toExternalForm(); String body = subject + '.\n\nHere is a link to the opportunity: ' + baseURL + '/' + opportunity.id; Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage(); message.setToAddresses(toAddresses); message.setSubject(subject); message.setPlainTextBody(body); message.setSaveAsActivity(false); EmailUtils.sendEmails(new List<Messaging.SingleEmailMessage>{message}, false); } }
This is Apex class which generate and attached SOW, how can change this to it be attached to Files. Thank you for your help.
I get this to work with this code but now I have SOW getting links to files and attachments. how can delete the attachment from here? Where I can make that adjustment?
I only need to keep files and other copy from attachments can be deleted, how can I achieve that?
All Answers
Though not exact for your requirement, the below links explain how you can code to add Files (ContentDocument in Lightning experience) so you can get started
https://www.biswajeetsamal.com/blog/convert-attachment-to-file-in-salesforce-using-apex/
https://salesforce.stackexchange.com/questions/234575/adding-attachments-in-apex-convert-the-code-to-add-files
Hope this helps you. Please mark this answer as best so that others facing the same issue will find this information useful. Thank you
Thank you for your help.
I have made the following changes as you mentioned but the attachment is still linking to Note&attachements. I have made changes to updateAttachemnt method.
Can you please check thank you.
I get this to work with this code but now I have SOW getting links to files and attachments. how can delete the attachment from here? Where I can make that adjustment?
I only need to keep files and other copy from attachments can be deleted, how can I achieve that?