• 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 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();
        
Hi,

Something strange happened after I deployed 1 custom object and 1 visual flow from Sandbox to QA.

After opening the flow, I noticed the custom fields from my custom object do not show up in "Record Create" so I'm unable to match the flow fields with my object fields.

I checked the custom object but all the custom fields are there. I have no idea what could have happened.

What could be missing? I didn't have this issue in Sandbox.

Thanks for your help.

User-added image

User-added image

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 friends,
This query returns results when I run it developer console's Query Editor and the Workbench's Query Editor.
 
select Id, Name, Campaign_Name__c, RecordType.Name from Campaign__c where Campaign_Name__c LIKE '%\_%'


However, when I try to use it in Execute Anonymous it returns nothing. I've also tried using // instead of / . 

 

Has anybody else run into this?

Hello friends. I'm a junior developer and running into the following error: 
Uncaught Action failed: c:pdfDI_SelectTemplate2$controller$refresh [Maximum call stack size exceeded]
My project is to generate visualforce pdfs with these lightning components. So the main body of the component you see below is a picklist where the user will select the vfpage to be rendered as pdf. And the child component is just an inframe that will then display the selected pdf. All of that is working nicely but I noticed that if the record is edited then the pdf is not refreshed. So, I had a go with force:refreshview which gives me the error. I also found a suggestion for location.reload() but that refreshes the entire page. Hoping someone out there can help me solve this error.  Thanks!!
Here is my code:
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId,force:hasSObjectName,lightning:isUrlAddressable" 
                access="global" 
                controller="pdfDI_SelectTemplate2_Controller">
    
    <aura:attribute name="selectedTemplate" type="String"/>
    <aura:attribute name="templateOptions" type="List"/>
    <aura:attribute name="simpleRecord" type="Object"/> 
    <aura:attribute name="vfPage" type="String"/>
    <aura:handler event="force:refreshView" action="{!c.refresh}" />
 
    
    <force:recordData aura:id="recordLoader"
        recordId="{!v.recordId}"
        fields="Name, RecordTypeId"
        targetFields="{!v.simpleRecord}"
        recordUpdated="{!c.handleRecordUpdated}"  
    />
    
   
    <lightning:layout multipleRows="false">
        <lightning:layoutItem size="6">
        	<div class="row">
                <aura:if isTrue="{!v.templateOptions != null}">
                    <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>
                </aura:if>    
    		</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}" vfPage="{!v.vfPage}"/>
    </div>  
</aura:component>
 
({ 
    
    refresh : function(component, event, helper) {
		$A.get('e.force:refreshView').fire();
		//location.reload();
	},
    
    handleRecordUpdated: function(cmp, event, helper) {
        
        var eventParams = event.getParams();
        if(eventParams.changeType === "LOADED") {
        
            var actionVF = cmp.get("c.getVFPage");
            actionVF.setParams({
                sObjectName : cmp.get("v.sObjectName"),
                recordTypeId : cmp.get("v.simpleRecord.RecordTypeId")
            });
            actionVF.setCallback(this, function(response) {
           		
                var stateVF = response.getState();
            	if(stateVF == "SUCCESS") {
                	var vfpage;
                    vfpage = response.getReturnValue();
                    cmp.set("v.vfPage", vfpage);
            	}
            });
           // Send action off to be executed
           $A.enqueueAction(actionVF);
            
            //get template options
            var actionComp = cmp.get("c.getTemplateOptions");
            actionComp.setParams({ 
                sObjectName : cmp.get("v.sObjectName"),
                recordTypeId : cmp.get("v.simpleRecord.RecordTypeId")
            });
            // Add callback behavior for when response is received
            actionComp.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(actionComp);
            
        } else if(eventParams.changeType === "CHANGED") {
            
        } else if(eventParams.changeType === "REMOVED") {
            // record is deleted
        } else if(eventParams.changeType === "ERROR") {
            var errors = response.getError();
            console.log('errors '+errors);
        }
    },
    
    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.simpleRecord.Name");
        var pdfName = selectedTemplate;
        var vfPage = cmp.get("v.vfPage"); 
        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 Friends!

I have a server side class that needs the recordtype.developer name of the current record. I am trying to use lightning data service to get the developername. So, I have 2 <force:recordData> attributes. The first stores the current record and the second is for the recordType. So, my intention is get the recordTypeId from the current record and use the reloadRecord method to get LDS to populate the other fields I need. I can see that I am setting recordTypeId just fine but for some reason simpleRecordType remains null after the reloadRecord Command. Can anybody see what I am doing wrong?

 

({  
   
    handleRecordUpdated: function(cmp, event, helper) {
        
        var eventParams = event.getParams();
        if(eventParams.changeType === "LOADED" || eventParams.changeType === "CHANGED") {
      		// get the simpleRecord attribute from the component
      		var simpleRecordTypeId = cmp.get('v.simpleRecord.RecordTypeId');
            
            var recordTypeId = cmp.get('v.recordTypeId');
            // if this is the first time we're loading the record then 
            // populate the ownerid and load the record
            if(recordTypeId == null){
                // assign the base record's ownerid onto the attribute we've
                // attached to the second force:recordData's recordid value.
                cmp.set('v.recordTypeId', simpleRecordTypeId);
                // fire the component event to reload the record now
                // that we've given it a record id.
                cmp.find('recordType').reloadRecord(true);
            }

            var actionVF = cmp.get('c.getVFOptions');
            actionVF.setParams({
                sObjectName : cmp.get('v.sObjectName'),
                recordTypeName : cmp.get('v.simpleRecordType.DeveloperName')
            });
            actionVF.setCallback(this, function(response) {
                debugger;
                var stateVF = response.getState();
                if(stateVF == "SUCCESS") {
                    var vfOptions;
                    vfOptions = response.getReturnValue();
                    var custs = [];
                    var conts = vfOptions.cOpts;
                    for(key in conts) {
                        custs.push({value:conts[key], key:key});
                    } 
                    cmp.set('v.templateOptions', custs);   
                    
                    var vfPage;
                    vfPage = vfOptions.vfPage;
                    cmp.set('v.vfPage', vfPage);
                    
                }
            });
            // Send action off to be executed
            $A.enqueueAction(actionVF);

        } else if(eventParams.changeType === "CHANGED") {
           
        } else if(eventParams.changeType === "REMOVED") {
            // record is deleted
        } else if(eventParams.changeType === "ERROR") {
            var errors = response.getError();
            console.log('errors '+errors);
        }
    },
    
    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.simpleRecord.Name");
        var pdfName = selectedTemplate;
        var vfPage = cmp.get("v.vfPage"); 
        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);
    }
    
})
 
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId,force:hasSObjectName,lightning:isUrlAddressable" 
                access="global" 
                controller="pdfDI_SelectTemplate2_Controller">
    
    <aura:attribute name="selectedTemplate" type="String"/>
    <aura:attribute name="templateOptions" type="List"/>
    <aura:attribute name="simpleRecord" type="Object"/> 
    <aura:attribute name="vfPage" type="String"/>
     
    
    <force:recordData aura:id="recordLoader"
        recordId="{!v.recordId}"
        fields="Name, RecordTypeId"
        targetFields="{!v.simpleRecord}"
        recordUpdated="{!c.handleRecordUpdated}"               
    />
    
    <aura:attribute name="recordTypeId" type="Id"/> <!-- assigned in Javascript after record load -->
    <aura:attribute name="simpleRecordType" type="RecordType"/>
    <aura:attribute name="recordTypeError" type="String"/>
    <force:recordData aura:id="recordType"
        recordId="{!v.recordTypeId}"
        fields="Id, Name, DeveloperName"
        targetFields="{!v.simpleRecordType}"
        targetError="{!v.recordTypeError}"              
        recordUpdated="{!c.handleRecordUpdated}"              
    />
    
    <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}" vfPage="{!v.vfPage}"/>
    </div>  
</aura:component>

I have been using this as an example: https://github.com/aheber/ObjectAgnosticLightingComponent
Hello Friends.
I ran into problems querying a custom metadata object. I found the query was not working as expected when filtering on a picklist field. To test I then created a text field and put the same value as the picklist field. The query on the text field works.  Just wondering anybody else has ran into this. 


picklist field: Record_Type__c
text field: Record_Type2__c

non-working query:
select Id,
                      MasterLabel,
                      VF_Display_Name__c,
                      Component_Name__c,
                      PDF_Page_Factory__r.VF_Page__c,
                    PDF_Page_Factory__r.Object__c,
                    PDF_Page_Factory__r.Record_Type__c 
               from PDF_Component_Factory__mdt
             where  PDF_Page_Factory__r.Object__c = 'Quote'
and PDF_Page_Factory__r.Record_Type__c = 'Research'

working query:
select Id,
                      MasterLabel,
                      VF_Display_Name__c,
                   	 Component_Name__c,
                      PDF_Page_Factory__r.VF_Page__c,
                     PDF_Page_Factory__r.Object__c,
                     PDF_Page_Factory__r.Record_Type__c 
               from PDF_Component_Factory__mdt
             where  PDF_Page_Factory__r.Object__c = 'Quote'
and PDF_Page_Factory__r.Record_Type2__c = 'Research'

 

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 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];
       }}
}
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());

 

Hello

I have this class that is making the request body for an integration with netsuite. 
 

public class netsuite_CustomerMap implements INetsuiteMap{

	public map<string, object>  getNSMap(SObject sobj) {

		Account acc = (Account)sobj;
        string objectName = acc.getSObjectType().getDescribe().getName();
        netsuite_Service nsService = new netsuite_Service();
        map<string,map<string, Netsuite_Mapping__mdt>> ns_Map = nsService.getNSDefaultMap();
		map<string, object> objMap = new map<string, object>();

		objMap.put('companyname',acc.Name);
		objMap.put('externalid', acc.Id);
		objMap.put('recordtype', ns_Map.get('recordtype').get(objectName).Netsuite_Value__c);
		objMap.put('altPhone',acc.Phone);
		objMap.put('currency', ns_Map.get('currency').get(acc.CurrencyIsoCode).Netsuite_Value__c);
		objMap.put('customForm', ns_Map.get('customForm').get(objectName).Netsuite_Value__c);
		objMap.put('phone', acc.phone);
		objMap.put('isPerson', ns_Map.get('isPerson').get(objectName).Netsuite_Value__c);
		objMap.put('entityStatus',ns_Map.get('entityStatus').get(objectName).Netsuite_Value__c);*/

		
		return objMap;

	}
}

It works nicely but then I started thinking about what would happen if that request body needed to be changed. Perhaps a new field becsomes required by Netsuite, for example. This would require me to make edits to the class and deploying. So, I thought maybe I could put these map definitions into custom metadata, which would allow me to make any required changes by editing custom metdata inside production. I wound up with the following class:
 
public class netsuite_CustomerMap implements INetsuiteMap{

	public map<string, object>  getNSMap(SObject sobj) {

		Account acc = (Account)sobj;
        string objectName = acc.getSObjectType().getDescribe().getName();
        netsuite_Service nsService = new netsuite_Service();
        map<string,map<string, Netsuite_Mapping__mdt>> ns_Map = nsService.getNSDefaultMap();
		map<string, object> objMap = new map<string, object>();

		

		for(Netsuite_Master_Map_Definition__mdt mapSource : [select Id, 
																	 
 MasterLabel, 
																	Netsuite_Master_Map__c, 
																	Netsuite_Master_Map__r.MasterLabel, 
																	Netsuite_Field__c,  
																	Salesforce_Value__c 
															from Netsuite_Master_Map_Definition__mdt 
															where Netsuite_Master_Map__r.Apex_Class_Name__c = 'netsuite_CustomerMap']) {
			objMap.put(mapSource.Netsuite_Field__c, mapSource.Salesforce_Value__c);													
		}

		return objMap;

	}
}


And here is an example of what the 2 custom fields in Netsuite_Master_Map_Definition__mdt called Netsuite_Field__c and Salesforce_Value__c are storing:

Netsuite_Field__c = 'companyname'

Salesforce_Value__c = acc.Name

As an admin, what I didn't think through is that this would not work because these are text fields and therefore simply populates the objMap with literal text values like so "'companyname'" => "acc.Name".

So, at this point I'm not sure what to do and will probably just reconcile myself to the reality of updating the class anytime a change to request body is needed.....Unless someone out there has any good ideas.

Thanks!

 

Hello. I am playing around with rendering as PDF capability. I have created my first page and now I have other use cases for all of which I would like to use the same basic layout which is basically a two column layout with a footer. I have read the documentation on using <apex:composition>  <apex:insert> and <apex:define> but I am having a hard time seeing how to apply it to my template. 

 

So, here's hopin that someone out there sees this and has done it before and can give some pointers. 

 

Here's what my template would look like: 

 

<apex:page >
            
    
    
    <apex:stylesheet value="{!$Resource.ppPDFStyles}"/>

    <!-- All Pages Footer -->
   
    <c:pdfHeaderFooter type="footer" position="left" >
        <apex:image url="{!URLFOR($Resource.ppLogos,'/ppLogo3/Pureprofile-logo-horizontal-RGB.png')}" width="121" height="29" styleClass="columnFooterLeft"/>
        <apex:outputLabel value="Pureprofile" styleClass="footerBold columnFooterLeft"/> 
        <apex:outputLabel value="ABN 37 167 522" styleClass="footerLight columnFooterLeft"/> 
        <apex:outputLabel value="www.pureprofile.com" styleClass="footerLight columnFooterLeft"/> 
        <apex:outputLabel value="info@pureprofile.com" styleClass="footerLight columnFooterLeft"/> 
    </c:pdfHeaderFooter>
    <c:pdfHeaderFooter type="footer" position="center" >
            <apex:outputLabel value="Sydney" styleClass="footerBold columnFooterCenter" /> 
            <apex:outputLabel value="Melbourne" styleClass="footerBold columnFooterCenter"/>  
            <apex:outputLabel value="London" styleClass="footerBold columnFooterCenter" />  
            <apex:outputLabel value="New York" styleClass="footerBold columnFooterCenter" />  
            <apex:outputLabel value="Thessaloniki" styleClass="footerBold columnFooterCenter"/>  
            <apex:outputLabel value="Mumbai" styleClass="footerBold columnFooterCenter"/> 
    </c:pdfHeaderFooter>
    <c:pdfHeaderFooter type="footer" position="right" showPageNumbers="true" />
    
    <table width="100%">
        <tr width="100%">
            <td class="columnleft column"> 
                <apex:image url="{!URLFOR($Resource.ppLogos,'ppLogo3/pp-line-dot2.png')}" style="padding-top: 9px"/>
            </td>
            <td class="columnright column">
               
                
                        
            </td>
        </tr>
        
    </table>
   
    
</apex:page>
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 trying to use the salesforce extensions for vscode and cannot seem to run the replay debugger. I am working org based as opposed to with scratch orgs and everything has been working fine until the replay debugger....I have a project and I have pushed changes made back to the org. I can turn the replay debugger on and then I generate a log and download it. All that is just to say that it seems that most commands are working. I have breakpoints set on the class that I want to debug. When I right click on the dowloaded log and choose the SFDX: Launch Apex Replay Debugger nothing happens. There are no messages in the output to go on. So then my next step was to try running the replay debugger manually by opening the debugger console in the left hand margin and then clicking that green play button at the top. Here I get the following message: command 'extension.replay-debugger.getLogFileName' not found and a button that offers to open the launch.json file. I have setup launch.json this file exactly as the documentation suggests, which I provide here:
 
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Apex Replay Debugger",
            "type": "apex-replay",
            "request": "launch",
            "logFile": "${command:AskForLogFileName}",
            "stopOnEntry": true,
            "trace": true
        }
    ]    

    
}

I have also learned that salesforce extension requires jdk 8. So, I have that installed, and I have also pointed my user settings to it.
"salesforcedx-vscode-apex.java.home": "/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home"

I have uninstalled and reinstalled the salesforce cli. I have unistalled all of the jdks and reinstalled jdk8. I'm not sure whate else I can do. Thanks for any suggestions!
Hello. I am trying to learn my way around the CLI. It is properly installed. I cannot seem to authenticate with any org. 

Using the command 
sfdx force:auth:web:login
The browers will open a login page at the default login.salesforce.com. I enter the credentials and the get the following messages.

On my browser I get: 'local host did not send any data'

On the terminal I get: 
ERROR:  Command failed with response.
 - security: SecKeychainItemCreateFromContent (<default>): The user name or passphrase you entered is not correct.
. 

Try this:
Determine why this command failed to set an encryption key for user andykallio: [/usr/bin/security add-generic-password -a local -s sfdx -w 7e91f8815b82c8172111410fa91dc6a8].


I have tried this with my production, and sanbox orgs and I am definitely entering the right username and password. 

 

I have uninstalled/reinstalled the cli. 

My IT guy says there are not any IP restrictions that he is impossing. 

Any ideas would be really appreciated. Thanks!

Hello,
I'm an admin that has just written my first integration. The code makes a call to an external service, receives some json, and then parses it and places it into a custom object. The json could either contain new records or update an existing record from a previous run...this is being done with upsert dml statement.  This process runs on a schedule. 

My question is regarding testing. There are no problems with testing the insert of new records. There is a test method that sets up all of the needed test data and a json string that makes use of that test data. The method returns that string and is used as a mockHTTPResponse. This tests everything except for the branch of code that updates existing records. This is where I'm challenged...I don't see how I can make another json string that uses first set of test data. 

So, I'm hoping that someone out there has been through this before and can offers some suggestions. 

Hi all. I'm using a lightning based app that has just started throwing 'System.SObjectException: Illegal assignment from String to Decimal' in one of its apex controllers, but only for certain profiles. That seems very strange to me and I can't find a difference between the profiles that would account for it. The reason I think the problem is related to the profile is because I have logged in as different users with different profiles and for some it works as expected and for others I get this error. 

I have already logged an issue on the app's github page, but thought I would try to see if there are any suggestions/ideas here. Thanks!

Hello,
I made this really simple lightning component simply to have a better layout of the fields than what could be achieved with standard page layouts. All of the fields in it are roll-up summary fields of child objects. The component is going to sit above those child related lists on the page layout. 

My challenge is that when those child records are updated the changes are not reflected in the lightning component....have to refresh the page to see them. 

So, my question is on event handling. More specifically what event should I be listening for? Is the update to the roll-up summary fields? Is that even possible? If not then I have to listen for the update to the child record. Can I get a little advice on how that is done?

 

<aura:component implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global">
    
    <force:recordData recordId="{!v.recordId}" layoutType="FULL" recordUpdated="{!c.itemsChange}"/>
    
    
    <lightning:card>
        <lightning:recordViewForm recordId="{!v.recordId}" objectApiName="Project__c">
            
            <div class="slds-grid">
                <div class="slds-col slds-size_1-of-3">
                    <div class="demo-only" style="padding: 10px; background: rgb(43,168,166);  margin-right: 150px;">
                    	<div class="slds-text-heading_medium slds-text-color_inverse">Estimation for Invoiced</div>
                    </div>    
                    <lightning:outputField fieldName="Invoiced_Amount__c" />
                    <lightning:outputField fieldName="Estimated_Expense_of_Invoiced__c"/>
                    <lightning:outputField fieldName="Estimated_Profit_for_Invoiced__c" />
                    <lightning:outputField fieldName="Estimated_Margin_for_Invoiced__c" />
                </div>
                <div class="slds-col slds-size_1-of-3">
                    <div class="demo-only" style="padding: 10px; background: rgb(43,168,166); margin-right: 100px;">
                    	<div class="slds-text-heading_medium slds-text-color_inverse">Estimation for Entire Project</div>
                    </div>    
                    <lightning:outputField fieldName="Expected_Invoice_Amount__c" />
                    <lightning:outputField fieldName="Total_Estimated_Expense__c"/>
                    <lightning:outputField fieldName="Estimated_Total_Profit__c" />
                    <lightning:outputField fieldName="Estimated_Total_Margin__c" />
                </div>
                <div class="slds-col slds-size_1-of-3">
                    <div class="demo-only" style="padding: 10px; background: rgb(43,168,166); margin-right: 150px;">
                    	<div class="slds-text-heading_medium slds-text-color_inverse">Actual</div>
                    </div>    
                    <lightning:outputField fieldName="Invoiced_Amount__c" />
                    <lightning:outputField fieldName="Actual_Expense3__c"/>
                    <lightning:outputField fieldName="Actual_Profit__c" />
                    <lightning:outputField fieldName="Actual_Gross_Margin__c" />
                </div>
            </div>
        </lightning:recordViewForm>
    </lightning:card>
</aura:component>
 

Thanks!!

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'm an admin just trying to adapt examples I've found on blogs into something for my use case. I am trying to create a data table that can be edited. It's almost working but there is one problem. The columns that I have tagged to be 'editable' do not display any data until they have been clicked on. Here is a screenshot to demonstrate. Hoping someone out there has run into this before. Thanks!!
 User-added image

Component:
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="leadGen_Inv_LEXController" >
	
    <aura:attribute name="data" type="Object"/>
    <aura:attribute name="columns" type="List"/>
    <aura:attribute name="recordId" type="String"/>
    <!-- This attribute will hold the update records from data table-->
    <aura:attribute name="updatedRecord" type="Object[]" />

    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>

    <!-- You must define keyField as 'Id' to save the record back in Salesforce
	'onsave' attribute will executed when user clicks on save button -->
    <lightning:card title="Account Editable Datatable">
        <lightning:datatable
                             aura:id="iliDataTable"
                             columns="{! v.columns }"
                             data="{! v.data }"
                             keyField="Id"
                             onsave ="{!c.onSave}"
                             hideCheckboxColumn="true"
                             onrowaction="{! c.handleRowAction }" />
    </lightning:card>
</aura:component>
js controller
({
    /*
     * This function defined column header
     * and calls getAccounts helper method for column data
     * editable:'true' will make the column editable
     * */
doInit : function(component, event, helper) {        
        component.set('v.columns', [
            {label: 'Name', fieldName: 'Name', type: 'String'},
            {label: 'Description', fieldName: 'Line_Item_Description__c', editable:'true', type: 'String'},
            {label: 'Quantity', fieldName: 'Quantity__c', editable:'true', type: 'Integer'},
            {label: 'Sales Price', fieldName: 'Sub_Total__c', editable:'true', type: 'Integer'}
        ]);        
        helper.getILIs(component, helper);
    },

    /*
     * This function is calling saveDataTable helper function
     * to save modified records
     * */
    onSave : function (component, event, helper) {
        helper.saveDataTable(component, event, helper);
    }
})


js helper
({
    getILIs : function(component, event, helper) {
        var invoiceId = component.get("v.recordId");
        var action = component.get("c.getILIs");
        action.setParams({ "invoiceId" : invoiceId });
        action.setCallback(this,function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.data", response.getReturnValue());
            }
        });
        $A.enqueueAction(action);
    },

    /*
     * This function gets called when user clicks on Save button
     * user can get all modified records
     * and pass them back to server side controller
     * */
    saveDataTable : function(component, event, helper) {
        var editedRecords =  component.find("iliDataTable").get("v.draftValues");
        var totalRecordEdited = editedRecords.length;
        var action = component.get("c.updateILIs");
        action.setParams({
            'editedILIList' : editedRecords
        });
        action.setCallback(this,function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                //if update is successful
                if(response.getReturnValue() === true){
                    helper.showToast({
                        "title": "Record Update",
                        "type": "success",
                        "message": totalRecordEdited+" Account Records Updated"
                    });
                    helper.reloadDataTable();
                } else{ //if update got failed
                    helper.showToast({
                        "title": "Error!!",
                        "type": "error",
                        "message": "Error in update"
                    });
                }
            }
        });
        $A.enqueueAction(action);
    },

    /*
     * Show toast with provided params
     * */
    showToast : function(params){
        var toastEvent = $A.get("e.force:showToast");
        if(toastEvent){
            toastEvent.setParams(params);
            toastEvent.fire();
        } else{
            alert(params.message);
        }
    },

    /*
     * reload data table
     * */
    reloadDataTable : function(){
    var refreshEvent = $A.get("e.force:refreshView");
        if(refreshEvent){
            refreshEvent.fire();
        }
    },
})

apex controller
public class leadGen_Inv_LEXController {
@AuraEnabled
    public static List<Invoice_Line_Item__c> getILIs(Id invoiceId){
        return [SELECT
               		Id 
               		,Name
                	,Line_Item_Description__c
                	,Quantity__c
                	,Sub_Total__c
               FROM Invoice_Line_Item__c 
               where Invoicing__c = :invoiceId];
    }

    @AuraEnabled
    public static boolean updateILIs(List<Invoice_Line_Item__c> editedILIList){
        try{
            update editedILIList;
            return true;
        } catch(Exception e){
            return false;
        }
    }
}

 

Hi. 

My goal is to have a flow end on the Edit All Quote Line Items modal. The ideal would be a url that i could simply send the user to at the end of the flow. This was very easy to do in classic with this: /quoteitm/multilinelitem.jsp?quoteId=XXX  but seems to be quite difficult to do in lightning. I think that I will have to create a lightning component to use in the flow that will be a recreation of the existing modal. 

 

Someone else is also asking this question on SE: https://salesforce.stackexchange.com/questions/204965/access-standard-lightning-quote-line-item-dialogs-from-lightning-component-or-vi

 

And here is a picture of what the modal looks like. 

 

User-added image

 

Thanks for any help!

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'