4

I am new to Salesforce development. I made a trigger that creates a new asset record and autofills some of the fields on said record. What I want ultimately would be a button that I can put on the "Products" related list on the opportunity page that does what my trigger does. From what I understand, I can't just call my trigger on the button click, and I have to create a VF page or an Apex class that uses the trigger's logic. Does anyone know how I would go about doing this? Here's my code:

trigger ConvertOpportunitiesToAssets on Opportunity (after update) {

    List<Asset> a = new List<Asset>();
    OpportunityLineItem oli = new OpportunityLineItem();

    for(Opportunity o: Trigger.new)
    {          
        a.add( new Asset(
            PSI_Supplier__c = o.Supplier__c,
            PSI_Opportunity__c = oli.Product2Id,
            AccountId = o.Accountid,
            Name = oli.Product2Id,
            Product2Id = oli.Product2Id,
            Product_Name__c = oli.Product_Name__c
            ));       
    }
    insert a;
}

Thanks in advance!

UPDATE So I tried making the trigger into a class and button (thanks sfdcfox!), but now it won't work. Here's what I've got:

    global class OpportunityWS{
    webservice static void createAsset(Id opportunityId)
    {
        List<Asset> a = new List<Asset>();
        Opportunity o = new Opportunity();
        OpportunityLineItem oli = new OpportunityLineItem();

        a.add( new Asset(
            PSI_Supplier__c = o.Supplier__c,
            PSI_Opportunity__c = oli.Product2Id,
            AccountId = o.Accountid,
            Name = oli.Product2Id,
            Product2Id = oli.Product2Id,
            Product_Name__c = oli.Product_Name__c
            ));       

        insert a;

    }
}

{!RequireScript("/soap/ajax/34.0/connection.js")}
{!RequireScript("/soap/ajax/34.0/apex.js")}
function success() {
var alertString="Success!"; 
alert(alertString); 
}
function error() {
var alertString="Error!"; 
alert(alertString); 
}
sforce.connection.sessionId = "{!$Api.Session_ID}";
sforce.apex.execute("OpportunityWS", "createAsset", { opportunityId: "{!Opportunity.Id}" }, { onSuccess: success, onFailure: error });

I can't tell if it's something wrong with the class or the button. I think it must be the class.

UPDATE(AGAIN) Alright so I followed Doug's advice and tried to use the opportunityId to query the opportunity and opportunityLineItem sobjects, was able to compile without errors. But now I'm getting the error message that I made in the button thrown and the asset isn't being created. Unfortunately, I haven't been able to track down the issue. Here's the OpportunityWS apex class that I've updated since last edit:

global class OpportunityWS{
webservice static void createAsset(Id opportunityId)
{
    List<Asset> a = new List<Asset>();
    List<Opportunity> o = [SELECT Supplier__c, Accountid FROM Opportunity WHERE Id = :opportunityId];
    List<OpportunityLineItem> oli = [SELECT Product2Id, Product_Name__c FROM OpportunityLineItem WHERE Id = :opportunityId];

    a.add( new Asset(
        PSI_Supplier__c = o[0].Supplier__c,
        PSI_Opportunity__c = oli[0].Product2Id,
        AccountId = o[1].Accountid,
        Name = oli[0].Product2Id,
        Product2Id = oli[0].Product2Id,
        Product_Name__c = oli[1].Product_Name__c
        ));       

    insert a;
}

}

  • 1
    In your updated webservice class you are passing in the Opportunity Id, but aren't doing anything with it. You are instantiating new Opportunity and OpportunityLineItem records, but as they are new they have no values and won't populate your asset. What you want to do is use the OpportunityId to query your Opportunity record, and your OpportunityLineItem record. Then you can populate your Asset with the values from the queried record. – dBeltowski Jun 22 '15 at 17:36
8

First, make your trigger into a static webservice function:

global class OpportunityWS {
    webservice static void createAsset(Id opportunityId) {
    // Do logic here
    }
}

Then, create a custom JS button or link on the opportunity:

{!RequireScript("/soap/ajax/34.0/connection.js")}
{!RequireScript("/soap/ajax/34.0/apex.js")}
function success() {
    // Indicate success
}
function error() {
    // Indicate failure
}
sforce.connection.sessionId = "{!$Api.Session_ID}";
sforce.apex.execute("OpportunityWS", "createAsset", { opportunityId: "{!Opportunity.Id}" }, { onSuccess: success, onFailure: error });

I've left a few placeholders here for you to figure out, but that's basically it.

For more information, see the AJAX Toolkit documentation on using Apex from JS.

You might also choose to make a list view version, in which case you'd want to accept a List of Id values instead. Don't forget to query any data you need.

| improve this answer | |
  • Is it necessary to have the Id opportunityId in the webservice function heading? I don't really see what I need to use it for. – Matt Mc Jun 23 '15 at 16:09
  • @MattMc If you use this technique, the webservice function needs to know what record you're operating on. We provide this by the way of a parameter. Without it, it has no idea what you're trying to do, because, unlike a Visualforce page, trigger, or flow, it isn't associated with the record in any way. – sfdcfox Jun 23 '15 at 17:38
  • Ah, I see. I forgot that the apex classes aren't automatically associated with their intended records as it is with triggers. Thanks for clearing that up! – Matt Mc Jun 23 '15 at 17:53
3

One way to achieve this would be to have a button call a flow and have the flow generate the asset items.
enter image description here

| improve this answer | |
1

Whenever opportunity is updated, your trigger will fire. So you can have a details page button to update some field in the backend.

You can find a different sample in below link

Detail Page Button with JavaScript on Opportunity Record

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.