• Andy Kallio 7
  • NEWBIE
  • 349 Points
  • Member since 2015

  • Chatter
    Feed
  • 2
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 45
    Questions
  • 70
    Replies

Hello friends. I have a method that creates records in custom metadata. It works as expected but now I am having a hard time figuring out how to get test coverage for it. 

Initially got an error on the line that enques the deployment via Metadata.Operations.enqueueDeployment which said that metadata cannot be deployed in a test context.

Then I found the suggestion of just skipping that line with a ternary operator, which is the version I have posted here. And that gives me 'Fake Job Id' is not a proper id. Strange that this seems to have worked for other people on that stackexchange post. 

 

At this point I need to seek some advice from those of you that are more experienced. Thanks!!

 

@future
    public static void createCustomMetaData(string acctName, string acctId) {

    string fullname = 'Product_Selection_Search_Parameter.'+acctName.replace(' ','_');    
    // Set up custom metadata to be created in the subscriber org. thanks to https://www.sfdcpanther.com/create-update-custom-metadata-using-apex/
    Metadata.CustomMetadata customMetadata =  new Metadata.CustomMetadata();
    customMetadata.fullName = fullname;
    customMetadata.label = acctName;

    Metadata.CustomMetadataValue typeField = new Metadata.CustomMetadataValue();
    typeField.field = 'Type__c';
    typeField.value = 'Top-Up';
	Metadata.CustomMetadataValue acctField = new Metadata.CustomMetadataValue();
    acctField.field = 'Value__c';
    acctField.value = acctId;

    customMetadata.values.add(typeField);
	customMetadata.values.add(acctField);

    Metadata.DeployContainer mdContainer = new Metadata.DeployContainer();
    mdContainer.addMetadata(customMetadata);

    // Setup deploy callback, MyDeployCallback implements
    // the Metadata.DeployCallback interface 
    CustomMetadataCallback callback = new CustomMetadataCallback();

    // Enqueue custom metadata deployment
    // jobId is the deployment ID
    Id jobId = Test.isRunningTest() ? 'Fake Job Id' : Metadata.Operations.enqueueDeployment(mdContainer, callback);
    }

Here is the test class
@isTest
public with sharing class di_PartnerCreation_Test {
    
    @TestSetup
    static void makeData(){
        TestData_Research_Director director = new TestData_Research_Director();
        director.Construct_Account(new TestData_Research(), true);
        director.Construct_NonStandardPBE(new TestData_Research(), true);
    }

    public static testMethod void testDIPartnerCreationMethods_Act() {
        Account act = [select Id, Name from Account limit 1];
        PriceBook2 pb = [select Id from PriceBook2 where IsStandard = false];

        map<string, string> pbTest = di_PartnerCreation_lcController.getPriceBookOptions(act, 'AUD');
        boolean exProds = di_PartnerCreation_lcController.hasExistingProducts(act.Id);
        di_PartnerCreation_lcController.createProducts(act, 'AUD');
        di_PartnerCreation_lcController.createPriceBookEntries(act, 'AUD', pb.Id);
    }

    public static testMethod void testDIPartnerCreationMethods_NoAct() {

        map<string, string> currencyMap = di_PartnerCreation_lcController.getCurrencies();

    }
}

 

Hello, I've made some lightning components and vfpage that will allow my users to select select, preview and save pdf templates from the Quote object. I now have the need to use the same functionality on other objects in my org. However, I don't quite see how I can do it without making new lightning components. The main challenge is in how to use the <force:recordData> dynamically....I think that is what I want to do. For example, if the component could recognize that it was on a Quote or an Invoice or some other custom object then my server side controller could get the appropriate template options and the rest will be easy. The part that I don't see is how to make force:recordData work with multiple objects. 

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" access="global" controller="pdfDI_SelectTemplate2_Controller">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="selectedTemplate" type="String"/>
    <aura:attribute name="templateOptions" type="List"/>
    <aura:attribute name="record_Q" type="Quote"/> 
    <force:recordData aura:id="recordLoader_Q"
        recordId="{!v.recordId}"
        fields="Name"
        targetFields="{!v.record_Q}"              
    />
    <lightning:layout multipleRows="false">
        <lightning:layoutItem size="6">
        	<div class="row">
        		<!--<p class="title">Select Template:</p>-->
    			<ui:inputSelect class="single" aura:id="InputSelectSingle" change="{!c.onSingleSelectChange}">
        			<option value="">...Select a Template...</option>
            		<aura:iteration items="{!v.templateOptions}" var="t_opt" indexVar="key">
                		<ui:inputSelectOption text="{!t_opt.value}" label="{!t_opt.key}"/>
            		</aura:iteration>
        		</ui:inputSelect>  
    		</div>
        </lightning:layoutItem>
    	<lightning:layoutItem size="6">
        <div class="slds-p-left_large">
    	 	<lightning:button label="Save PDF" title="Save PDF" onclick="{! c.savePDF }"/>
    	</div>
        </lightning:layoutItem>  
    </lightning:layout>
    
	<div class="slds-p-top_large">
        <p>PDF Preview:</p>
    	<c:pdfDI_DisplayTemplate selectedTemplate="{!v.selectedTemplate}" recordId2="{!v.recordId}"/>
    </div>  
</aura:component>
 
({
	
        // Load template options from Salesforce
    doInit: function(cmp, event, helper) {
        
        // Create the action
        var action = cmp.get("c.getTemplateOptions");
        // Add callback behavior for when response is received
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var custs = [];
                var conts = response.getReturnValue();
                for(var key in conts) {
                    custs.push({value:conts[key], key:key});
                }
                cmp.set("v.templateOptions",custs);
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
        // Send action off to be executed
        $A.enqueueAction(action);
    },
    
    onSingleSelectChange: function(cmp) {
        var selectCmp = cmp.find("InputSelectSingle");
        cmp.set("v.selectedTemplate", selectCmp.get("v.value"));
	},
    
    savePDF : function(cmp, event, helper) {
        var recordId = cmp.get("v.recordId");
        var selectedTemplate = cmp.get("v.selectedTemplate");
        var qName = cmp.get("v.record_Q.Name");
        var pdfName = selectedTemplate;
        var vfPage = '/apex/pdfDI_QuoteStandard2'; //really should pull this from child component.
        var action = cmp.get("c.savePDF_Quote");
        action.setParams({
            "vfPage": vfPage, 
            "recordId" : recordId, 
            "selectedTemplate" : selectedTemplate, 
            "pdfName" : qName
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                alert('Attachment saved successfully');
                
            }
            else if (state === "INCOMPLETE") {
                // do something
            }
                else if (state === "ERROR") {
                    var errors = response.getError();
                    if (errors) {
                        if (errors[0] && errors[0].message) {
                            console.log("Error message: " + 
                                        errors[0].message);
                        }
                    } else {
                        console.log("Unknown error");
                    }
                }
        });
        $A.enqueueAction(action);
    }
    
    
    
})
Hello All,

I'm brand new to this and I'm having trouble with generating JSON.  
I am getting an error like "Cannot start array, expecting field name"
Please help!!!!


Here is what I'm trying to emulate:


{
  "RatingZip": "",
  "YearsInBusiness": "",
  "NatureOfBusiness": "",
  "IsNonProfit": "",
  "Product": "", REQUIRED
  "IsIncumbantAgent": "",
  "ClassCodeList": [
    {
      "ClassCode": "", REQUIRED
      "ClassDescriptionCode": "",
      "LocState": "", REQUIRED
      "Payroll": "", REQUIRED
      "FullTimeEmployees": "",
      "PartTimeEmployees": ""
    }
  ],
  "GenerateProposal": "",
  "LegalEntity": "",
  "Fein": "",
  "Applicant": { REQUIRED
    "BusinessName": "", REQUIRED
    "BusinessAddress1": "", REQUIRED
    "BusinessCity": "", REQUIRED
    "BusinessState": "", REQUIRED
    "BusinessZip": "", REQUIRED
    "MailingAddress1": "",
    "MailingCity": "",
    "MailingState": "",
    "MailingZip": "",
    "ContactInformation": { REQUIRED
      "FirstName": "", REQUIRED
      "LastName": "", REQUIRED
      "Email": "", REQUIRED
      "Phone": "" REQUIRED
    }
  },
  "Salutation": "",
  "CompanyWebsiteAddress": "",
  "EffectiveDate": "", REQUIRED
  "ExpiredPremium": ""
}

And here is my code:

JSONGenerator gen = JSON.createGenerator(true);   
        gen.writeStartObject();
        gen.writeStringField('RatingZip', '');
        gen.writeNumberField('YearsInBusiness', 0);
        gen.writeStringField('NatureOfBusiness', '');
        gen.writeBooleanField('IsNonProfit', false);
        gen.writeStringField('Product', 'WC');
        gen.writeBooleanField('IsIncumbantAgent', false);
        gen.writeStringField('ClassCodeList', '');
        gen.writeStartArray();
        gen.writeStringField('ClassCode', i.Class_Code__c);
        gen.writeStringField('ClassDescriptionCode', '');
        gen.writeStringField('LocState', '');
        gen.writeStringField('Payroll', i.Payroll__c);
        gen.writeStringField('FullTimeEmployees', '');
        gen.writeStringField('PartTimeEmployees', '');
        gen.writeEndArray();
        gen.writeBooleanField('GenerateProposal', true);
        gen.writeNumberField('LegalEntity', 0);
        gen.writeStringField('Fein', '');
        gen.writeObjectField('Applicant', '');
        gen.writeStartObject();
        gen.writeStringField('BusinessName', i.Business_Name__c);
        gen.writeStringField('BusinessAddress1', i.Business_Address__c);
        gen.writeStringField('BusinessCity', i.Business_City__c);
        gen.writeStringField('BusinessState', i.Business_State__c);
        gen.writeStringField('BusinessZip', i.Business_Zip__c);
        gen.writeStringField('MailingAddress1', '');
        gen.writeStringField('MailingCity', '');
        gen.writeStringField('MailingState', '');
        gen.writeStringField('MailingZip', '');
        gen.writeStartObject();
        gen.writeObjectField('ContactInformation', '');
        gen.writeStringField('FirstName', i.First_Name__c);
        gen.writeStringField('LastName', i.Last_Name__c);
        gen.writeStringField('Email', i.Email__c);
        gen.writeStringField('Phone', i.Phone__c);
        gen.writeEndObject();
        gen.writeEndObject();
        gen.writeStringField('Salutation', '');
        gen.writeStringField('CompanyWebsiteAddress', '');
        gen.writeStringField('EffectiveDate', i.Effective_Date__c);
        gen.writeNumberField('ExpiredPremium', 0);
        gen.writeEndObject();
        

Hello friends!

I cannot get this visualforce component to save. After trying a lot of different things in setting the properties i still get the error: Unknown property 'SObject.' on line 0.

Any guidance is greatly appreciated.

 

<apex:component controller="pdf_QLineItemGrouped2">

	<apex:attribute name="qlis" required="true" type="QuoteLineItem[]" assignTo="{!qli}" description="List of quote line items to be displayed."/>
    <apex:attribute name="totalPrice" required="true" type="Decimal" description="Quotes total sales price"/>
     <section >
         <b></b>
         <table class="qitable">
             <tr>
                 <th class="row-name label" >Product</th>
                 <th class="row-date label">Description</th>
                 <th class="row-date label">Quantity</th>
                 <th class="row-status label">CPI</th>
                 <th class="row-status label">Total</th>
             </tr>
             
             <apex:repeat var="qli" value="{!groupedQLIs}">
                 
                 <tr>
                     <td class="row-name detail" >{!qli.['Family']}</td>
                     <td class="row-name detail" >{!qli['Quantity']}</td>
                     <td class="row-date detail">
                         <apex:outputText value="{0, number,currency}">
                             <apex:param value="{!qli.['Amount']}"/>
                         </apex:outputText>
                     </td>
                     <td class="row-date detail">
                         <apex:outputText value="{0, number,currency}">
                             <apex:param value="{!qli.TotalPrice}"/>
                         </apex:outputText>
                     </td>
                 </tr>
             </apex:repeat> 
             <tr class="label">
                 <td colspan="4" class="alignRight">Total:</td>
                 <td>
                     <apex:outputText value="{0, number,currency}">
                         <apex:param value="{!totalPrice}"/>
                     </apex:outputText>
                 </td>
             </tr>
         </table>
         <p style="page-break-after: always">Please note that prices do not include GST.</p>
    </section>

</apex:component>
 
public class pdf_QLineItemGrouped2 {
	
    public pdf_QLineItemGrouped2(){}
   public list<QuoteLineItem> qli {get; set;}
   set<Id> qlids = (new Map<Id, QuoteLineItem>(qli)).keySet(); 
   public list<SObject> groupedQLIs {
       get {return groupedQLIs;} 
       private set{
           groupedQLIs = [SELECT 
                       PricebookEntry.Product2.Family Family, 
                       SUM(Quantity) Quantity, 
                       SUM(CG_Total_Price__c) Amount
                       FROM QuoteLineItem
                       WHERE Id IN :qlids AND UnitPrice > 0
                       GROUP BY PricebookEntry.Product2.Family
                       ORDER BY PricebookEntry.Product2.Family ASC];
       }}
}
I am a little green to Salesforce so I apologise in advance if this is a simple hack that I did not know. 

Scenario: I would like to email client's weekly with the status of their milestones of a project. Each Project has multiple milestones. The additional layer of complexity is that some milestones are internal (and we have a checkbox called Publicly Tracked to filter for the external facing milestones). How do I create a template that show the related milestones for a project where Publicly Tracked = Yes

I have been following the tutorial on https://www.vandeveldejan.com/tips/for-admins/15-the-not-so-scary-visualforce-email-template-as-order-confirmation-email
Hello friends. 
My requirement is to develop a few different visualforce pdfs that the user is to select based on their particular need. In other words, the user wants to be able to present a quote in different ways depending on the client. 

So, I could simply stack up a bunch of links on the page layout that would call each of these visualforce pages. I would like to provide them with a select list on the screen, though. So, the idea is that they could make a selection and then the pdf would be saved to the record and perhaps opened in a new tab. 

My question here is about how to provide that select list. We are pretty much entirely on lightning. So, I have been thinking about the following 3 options.
  1. Use a flow to call an invocable apex method. I think this option is not going to work because the invocable method cannot return a pagereference that would open the pdf. 
  2. Use a visualforce page. Here I get confused...do I then have to embed that page in a lightning component since we're on lightning?
  3. Use a lightning component. If have to embed the visualforce page then wouldn't it be better to just make a lightning component?
Any opinions on these or new ideas is greatly appreciated. Thanks!
Hello friends. I am playing around with generating a nested json string to send to netsuite. It seems like there are two options: use the JSONGenerator or use JSON.serialize() and use it seralize a class that has properties that are the same as netsuite's. 

I have Generator working in the snippet below. This is my first time doing this kind of thing. So, I'm just wondering if there are any opinions on these two approaches  or maybe something I haven't considered. 
 
JSONGenerator gen = JSON.createGenerator(true);
Invoicing__c invs = [select Id, 
                           		  Name, 
                                  Invoice_Name__c, 
                                  Expected_Invoice_Date__c,
                                  Primary_Billing_Contact_Email_id__c,
                                  Project__r.Subsidiary_Usage__r.Netsuite_Subsidiary_Id__c,
                                  Project__r.Project_Consultant__r.Netsuite_Id__c,
                                  Project__r.Owner_Netsuite_Id__c,
                                  Status__c,
                                  Project__r.Netsuite_Id__c,
                                  (select Id, Quantity__c, Sales_Price__c, Product__r.Netsuite_Product_Code__c from Invoice_Line_Items__r)
                          from Invoicing__c limit 1];
system.debug(invs.Name);

gen.writeStartObject();
gen.writeStringField('recordType', 'invoice');
gen.writeStringField('isDynamic', 'false');
gen.writeFieldName('columns');
gen.writeStartObject();
gen.writeObjectField('tranid', invs.Name);
gen.writeObjectField('companyid', invs.Project__r.Netsuite_Id__c);
gen.writeObjectField('trandate', invs.Expected_Invoice_Date__c);
gen.writeEndObject();

gen.writeFieldName('lines');
gen.writeStartObject();
gen.writeStringField('sublistId', 'item');
gen.writeFieldName('lineItems');
gen.writeStartArray();
for(Invoice_Line_Item__c ili : invs.Invoice_Line_Items__r) {
	gen.writeStartObject();
	gen.writeObjectField('quantity', ili.Quantity__c);
	gen.writeObjectField('rate', ili.Sales_Price__c);
	gen.writeObjectField('accout', ili.Product__r.Netsuite_Product_Code__c);
	gen.writeEndObject();
}    
gen.writeEndArray();
gen.writeEndObject();
gen.writeEndObject();
    
system.debug(gen.getAsString());

 
Hi there,

In Lightning Flow, I want to open case record detail page after finish my screen Flow.

To solve this, I added Lightning Component to Last Screen of my Flow.
Is it good idea to implement it or not?
Is there other ways to do this, please let me share.
<aura:component implements="lightning:availableForFlowScreens,lightning:availableForFlowActions">
    <aura:attribute name="recordId" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>    
</aura:component>
 
({    
    doInit: function(component, event, helper) {
        // Get the record ID attribute
        var record = component.get("v.recordId");
        
        // Get the Lightning event that opens a record in a new tab
        var redirect = $A.get("e.force:navigateToSObject");
        
        // Pass the record ID to the event
        redirect.setParams({
            "recordId": record
        });
        
        // Open the record
        redirect.fire();
    }
})

Regards,
LinThaw
Hi there,

I am getting this kind of warning when saving Lightning Flow (Spring'19 ver).
Is there any way to clear it?

This screen includes screen components that require Lightning runtime.

User-added image

Regards,
LinThaw
Hello. I am trying to use the invocableMethod annotation to pass some ids from a flow to the method that will return a list of custom Sobjects.

For some reason the soql is only finding the first record, and I don't see why. Posted here is the class and a debug log. Thanks for any help!!
 
public with sharing class getCampaigns_Flow {
    
    @invocableMethod
    public static list<list<Campaign__c>> getCampaigns(list<string> campaignIds) {
        system.debug('campaignIds: '+campaignIds);
        list<list<Campaign__c>> varCamps = new list<list<Campaign__c>>();
        List<string> varIds = campaignIds[0].split(';');
        system.debug('varIds: '+varIds);
        list<Campaign__c> camps = [select Id,
                                    Target_Audience__c,
                                    Geographic_Targeting__c,
                                    Search_Keywords__c,
                                    Creative_Versions_Per_Flight__c
                                    from Campaign__c
                                    where Id In :varIds];
        varCamps.add(camps);
        system.debug('camps: '+camps);
        system.debug('varCamps: '+varCamps);
        return varCamps;
    }
}
User-added image
 
Hi everyone,
I'm an admin that just made their first succesfull http callout. In this case, to netsuite. Authentication was acheived by setting the header with NLAuth details. I would like for my next step to be to Authenticate with OAuth, which I think Netsuite refers to as token based authentication. 

There are few examples out there that I was able to find in blogs on how to do basic authentication, but nothing on OAuth. 

So, I am just wondering if there is anybody out there who has done it that might be willing to answer some further questions. 
Hello
I am working on a flow and one of the things it needs to do is query PriceBookEntry. For some reason the fast lookup is not finding any records, but when I test the same query with soql executed on workbench the record is found. I'm a bit stumped on what to do next. So hopfully someone out there has some ideas. 

Here is excerpt from the debug email that shows what the fast lookup is doing:
FAST LOOKUP: Get_Standard_PBE_PP
Find all PricebookEntry records where:
Platform__c Equals {!Pureprofile} (Pureprofile)
Pricebook2Id Equals {!varQuote.Pricebook2Id} (01s90000004YFPxAAO)
CurrencyIsoCode Equals {!varQuote.CurrencyIsoCode} (AUD)
Incidence_Rate__c Equals {!formulaIncidenceRate} (10.00)
Length_of_Interview__c Equals {!Length_of_Interview2} (20)
Assign those records to {!sovPBEM}.
Save these field values in the variable: Id
Result
Failed to find records.

And here is the soql that actually finds the record
SELECT 
    Id, 
    name, 
    currencyisocode 
FROM PricebookEntry 
where 
    Length_of_Interview__c = 20 and 
    Incidence_Rate__c = 10.00 and 
    Platform__c = 'Pureprofile' and 
    Pricebook2id = '01s90000004YFPxAAO' and 
    CurrencyIsoCode = 'AUD'