Tutorial
...
Nue on Salesforce
Apex Global Methods and Services
45 min
apex global methods are special methods that are declared with the "global" access modifier these methods are part of apex classes and are accessible from any apex code in any organization, including triggers, classes, and flows, outside of nue on salesforce managed package nue provides a list of global services for salesforce admins to streamline and manage custom business processes salesforce admins can invoke these apex global services from apex triggers and flows invoke apex global services from salesforce flows here are the step to step instructions on how to invoke apex global methods from salesforce flows create an apex class first, you need to have an apex class that performs the desired functionality you want to invoke from the flow ensure that the class is properly designed to handle the input and output variables required for integration with the flow here's an example of a simple apex class that adds two numbers apexcopy codepublic class addnumbers { @invocablemethod(label='add numbers' description='adds two numbers') public static list\<integer> addtwonumbers(list\<integer> numbers) { integer num1 = numbers\[0]; integer num2 = numbers\[1]; integer sum = num1 + num2; return new list\<integer>{sum}; } } create a flow in your salesforce org, go to the flow builder and create a new flow (or use an existing one) add a new action in the flow inside the flow, add a new action element by dragging the "apex action" element from the palette onto the canvas select the apex class in the apex action properties, you'll need to select the apex class you want to invoke click on the "apex class" dropdown and find your desired class from the list map input and output variables if your apex class takes input parameters, you'll need to map those inputs to the appropriate flow variables similarly, if your apex class returns any output values, you'll need to map those outputs to flow variables as well configure fault handling (optional) you can also configure fault handling in case there are any errors when invoking the apex class this will allow you to define what should happen if an exception occurs during the apex execution save and activate the flow once you have configured the apex action and mapped the input/output variables, save and activate the flow now, when the flow runs, it will invoke the specified apex class, passing the input variables, and receive the output variables back to continue with the flow logic keep in mind that you need the appropriate permissions to create and invoke apex classes and flows in your salesforce org also, make sure the apex class logic is thoroughly tested before using it in a flow sample use case sample use case when a quote gets accepted by the customer, it will be finalized to an active order, then the subscriptions will be generated automatically the following is a list of step by step instructions to implement this use case step 1 create a class quotetoorderservice , and add a method with @invocablemethod annotation as below this method will call the global method nue on salesforce provided to finalize a list of quotes to active orders public class quotetoorderservice { @invocablemethod(label='finalize quote to order' description='finalize quote to order') public static void finalizedquotetoorder(list\<id> quoteids){ ruby globalquoteservice qs = new ruby globalquoteservice(); //parameters //quoteids a list of quote id need to be finalized //activateorders a boolean value indicates whether the generated orders will be activated qs generateorders(quoteids, true); } } step 2 create a flow on quote object named finalize accepted quotes to orders as below 1\ set the start condition status equals accepted 2\ add a new step to call the apex method quotetoorderservice finalizedquotetoorder created in above and set the input values to the triggering record id step 3 save and activate the flow step 4 now you can create a quote record, and change its status to 'accepted' step 5 after the quote is accepted, you can see an order is created and the subscriptions are generated automatically the subscription can be seen in the lifecycle manager global quote services the namespace of nue on salesforce managed package is ruby so please access all global apex methods with prefix ruby update start date of a quote or an order update the start date of a header level object—such as a quote, order, or line bucket this will trigger a recalculation of the end date for the header, along with adjustments to the start and end dates of its associated line items the newstartdate must be different from the current start date on the header object—whether it’s a quote, order, or line bucket //update the start date of a header object, including quote, order, or line bucket the end date of the header object will be recalculated, as well as the start date and end date of the line items global with sharing class globalheaderobjectservice {	 global void updatestartdate(id headerobjid, date newstartdate) { this headerobjectserviceinstance updatestartdate(headerobjid, newstartdate); } } recalculate a quote recalculate all prices for the given quote and its line items based on the quantity, subscription term, start date, end date and price tags already applied to each quote line item signature void ruby globalquoteservice recalculate(string quoteid); sample code id quoteid = '0q04w000002rzitca0'; new ruby globalquoteservice() recalculate(quoteid); re apply all price tags for a quote load currently applicable price tags for all line items of the quote according to the start date and end date of each line item, and recalculate all prices for the given quote and its line items based on the quantity, subscription term, start date, end date and price tags signature void ruby globalquoteservice reapplypricetags(string quoteid); sample code id quoteid = '0q04w000002rzitca0'; new ruby globalquoteservice() recalculate(quoteid); copy quote from template copy quote line items from a template quote to a target quote the target quote should not already have line items the price book of the target quote needs to be the same as the price book of the template quote signature void ruby globalquoteservice copyquotefromtemplate(string templatequoteid, string targetquoteid); sample code id targetquoteid = '0q04w000002rzitca0'; id templatequoteid = '0q04w000002rzitca1'; // copy quote line items from the template quote to the target quote note that the target quote should not already have line items new ruby globalquoteservice() copyquotefromtemplate(templatequoteid, targetquoteid); generate orders generate orders from a list of quotes with an option to activate the generated orders signature list\<orders> orders ruby globalquoteservice generateorders(list\<id> quoteids, boolean activateorders); sample code list\<id> quoteids = new list\<id>(); quoteids add('0q04w000002rzit'); quoteids add('0q04w000002rzmicac'); boolean activateorders = true; // generate orders for the list of quotes and activate the generated orders list\<orders> orders = new ruby globalquoteservice() generateorders(quoteids, activateorders); recalculate a list of quotes recalculate all prices for the given list of quotes and their line items based on the quantity, subscription term, start date, end date and price tags of each line item signature list\<quote> orders ruby globalquoteservice recalculate(list\<id> quoteids); sample code list\<id> quoteids = new list\<id>(); quoteids add('0q04w000002rzit'); quoteids add('0q04w000002rzmicac'); list\<quote> orders = new ruby globalquoteservice() recalculate(quoteids); re apply price tags for a list of quotes load currently applicable price tags for all line items of a list of quotes according to the start date and end date of each line item, and recalculate all prices for the given quotes and their line items based on the quantity, subscription term, start date, end date and price tags of each line item signature list\<order> orders ruby globalquoteservice reapplypricetags(list\<id> quoteids); sample code list\<id> quoteids = new list\<id>(); quoteids add('0q04w000002rzit'); quoteids add('0q04w000002rzmicac'); list\<order> orders = new ruby globalquoteservice() reapplypricetags(quoteids); synchronize primary quotes to opportunities nue provides two global methods for synchronizing primary quotes to their associated opportunities these methods ensure that only primary quotes are processed during synchronization synchronize a single primary quote signature boolean ruby globalquoteservice syncprimaryquotetoopportunity(id primaryquoteid); synchronizes a single primary quote with its associated opportunity behavior if the provided quote is marked as primary , it will be synchronized to the opportunity if the quote is not primary , an exception will be thrown synchronize a list of primary quotes signature boolean ruby globalquoteservice syncprimaryquotestoopportunities(list\<id> primaryquoteids); synchronizes a list of quotes , filtering and processing only those marked as primary behavior quotes that are not primary will be skipped if none of the quotes in the list are primary no exceptions will be thrown the method will return false if one or more primary quotes are found they will be synchronized to their associated opportunities the number of successfully synchronized quotes will be recorded in the debug logs sample code apex // synchronize a single primary quote to the opportunity id primaryquoteid = '0q0rk000000nw1f0aq'; id nonprimaryquoteid = '0q0rk000000oqwz0ae'; boolean result = new ruby globalquoteservice() syncprimaryquotetoopportunity(primaryquoteid); system debug('sync result ' + result); // synchronize a list of quotes to their associated opportunities list\<id> quoteids = new list\<id>(); quoteids add(primaryquoteid); quoteids add(nonprimaryquoteid); result = new ruby globalquoteservice() syncprimaryquotestoopportunities(quoteids); system debug('sync result ' + result); global order services the namespace of nue on salesforce managed package is ruby so please access all global apex methods with prefix ruby recalculate an order recalculate all prices for the given order and its line items based on the quantity, subscription term, start date, end date and price tags of each line item the order must be in draft status signature void ruby globalorderservice recalculate(string orderid); sample code id orderid = '8014w000008ln3kaag'; new ruby globalorderservice() recalculate(orderid); re apply all price tags for an order load currently applicable price tags for all line items of a given order according to the start date and end date of each line item, and recalculate all prices for the given order and their line items based on the quantity, subscription term, start date, end date and price tags of each line item the orders must be in draft status signature void ruby globalorderservice reapplypricetags(string orderid); sample code id orderid = '8014w000008lidxaa4'; new ruby globalorderservice() reapplypricetags(orderid); recalculate a list of order recalculate all prices for a list of orders and their line items based on the quantity, subscription term, start date, end date, and price tags of each line item the orders must all be in draft status signature void ruby globalorderservice recalculate(list\<id> orderids); sample code list\<id> orderids = new list\<id>(); orderids add('8014w000008lidxaa4'); // generate orders for the list of quotes and activate the generated orders new ruby globalorderservice() recalculate(orderids); re apply all price tags for an order load currently applicable price tags for all line items of a list of orders according to the start date and end date of each line item, and recalculate all prices for the given orders and their line items based on the quantity, subscription term, start date, end date and price tags of each line item the orders must be in draft status signature void ruby globalorderservice reapplypricetags(list\<id> orderids); sample code list\<id> orderids = new list\<id>(); orderids add('8014w000008lidxaa4'); // generate orders for the list of quotes and activate the generated orders new ruby globalorderservice() reapplypricetags(orderids); cancel a list of active orders cancel the given list of active orders please refer to this article for more details about order cancellation signature void ruby globalorderservice cancelactiveorders(list\<id> orderids); sample code list\<id> orderids = new list\<id>(); orderids add('8014w000008lidxaa4'); // generate orders for the list of quotes and activate the generated orders new ruby globalorderservice() cancelactiveorders(orderids); preview invoices for quotes and orders preview the invoices for a particular quote or order please refer to this article https //docs nue io/docs/tutorial/tutorial lifecycle manager/preview invoices/ for more details about invoice preview signature global class invoicepreviewservice { global static final integer option first invoice = 0; global static final integer option all invoices = 1; global static final integer option invoices with target date = 2; global static final string invoice status preview = 'preview'; / preview invoices for a quote or order the previewed invoices will be returned in a json representation @param objectid the quote, order, or account id @param objecttype quote, order, or account @param previewoption the preview options possible values are option first invoice, option all invoices, option invoices with target date @param targetdate if option invoices with target date is chosen, then this is the invoice target date @return invoices / global invoicespreviewapiresponse previewinvoices(id objectid, string objecttype, integer previewoption, date targetdate) {}; } sample code the following sample code previews invoices for a particular quote with an invoice target date ruby invoicepreviewservice previewservice = new ruby invoicepreviewservice(); // specify the object id and objecttype the object type can be quote or order string objecttype = 'quote'; id objectid = '0q08g0000006aobsam'; // the quote id date targetdate = date parse('1/1/2025'); ruby invoicepreviewservice invoicespreviewapiresponse response = previewservice previewinvoices( objectid, objecttype, ruby invoicepreviewservice option invoices with target date, targetdate); // optionally, save the previewed invoices list\<ruby invoice c> invoices = previewservice saveinvoicepreview(response); create and activate change quotes or orders nue provides a list of global services designed to create and activate change orders of various types these methods can be utilized by admin users to automate processes within salesforce the supported change types include renew this includes renewing to evergreen updateterm this includes updating the term to evergreen coterm co terming one or more subscriptions updatequantity adjusting the quantity of assets cancel cancelling assets evergreentocoterm switching from evergreen to co term evergreentoupdateterm switching from evergreen to update term bulksubscriptionrenewal handling bulk renewals of subscriptions adjustprice adjusting the prices of one or more subscriptions upgrade upgrading a product to another product, with or without the same uom downgrade downgrading a product to another pro, with or without the same uom swap swapping between 2 products, with or without the same uom the following is a code example //this class supports applying multiple changes with different types on assets ruby globalchangeorderservice //the following are the global change order requests ruby globalrenewrequest ruby globaladjustpricerequest ruby globalassetcancelrequest ruby globalassetchangerequest ruby globalreconfigurerequest ruby globalcotermrequest ruby globalupdatequantityrequest ruby globalupdatetermrequest ruby globalsubscriptionrenewalrequest ruby globalcotermforevergreenrequest ruby globalupdatetermforevergreenrequest ruby globalbulksubscriptionrenewalrequest sample code create a change quote containing multiple change requests the sample code below creates a new change quote that processes multiple change requests it also generates a new change opportunity, with the change quote set as the primary quote for that opportunity ruby globalchangeorderoptions options = new ruby globalchangeorderoptions(ruby globalchangeorderproceedoption createquote); options activateorder = false; options opportunityid = '006ea00000ofnxxiap'; //start to assemble a list of change requests list\<ruby globalassetchangerequest> changerequests = new list\<ruby globalassetchangerequest>(); //renew a subscription by 5 months ruby globalrenewrequest renewrequest = new ruby globalrenewrequest(); renewrequest assetnumber = 'sub 000055'; renewrequest renewalterm = 1; changerequests add(renewrequest); //update the quantity by adding 5 units, effective today ruby globalupdatequantityrequest updatequantityrequest = new ruby globalupdatequantityrequest(); updatequantityrequest assetnumber = 'sub 000055'; updatequantityrequest startdate = date today(); updatequantityrequest quantity = 5; changerequests add(updatequantityrequest); //execute the change order that includes all the above changes ruby globalchangeorderservice service = new ruby globalchangeorderservice(); ruby globalchangeorderresult result = service changeorder(new ruby globalchangeorder(options, changerequests)); create and activate a change order containing multiple change requests ruby globalchangeorderoptions options = new ruby globalchangeorderoptions(ruby globalchangeorderproceedoption createorder); options activateorder = true; //start to assemble a list of change requests list\<ruby globalassetchangerequest> changerequests = new list\<ruby globalassetchangerequest>(); //renew a subscription by 5 months ruby globalrenewrequest renewrequest = new ruby globalrenewrequest(); renewrequest assetnumber = 'sub 000014'; renewrequest renewalterm = 5; changerequests add(renewrequest); //update the quantity by adding 5 units, effective today ruby globalupdatequantityrequest updatequantityrequest = new ruby globalupdatequantityrequest(); updatequantityrequest assetnumber = 'sub 000014'; updatequantityrequest startdate = date today(); updatequantityrequest quantity = 5; changerequests add(updatequantityrequest); //adjust price to $4 per unit, for the following 5 months, effective today ruby globaladjustpricerequest adjustprice = new ruby globaladjustpricerequest(); adjustprice assetnumber = 'sub 000014'; adjustprice term = 5; adjustprice netsalesprice = 4; changerequests add(adjustprice); //execute the change order that includes all the above changes ruby globalchangeorderservice service = new ruby globalchangeorderservice(); ruby globalchangeorderresult result = service changeorder(new ruby globalchangeorder(options, changerequests)); // handle the result if (result success) { system debug('global change order executed successfully '); // process any informational or warning messages if (result messages != null && !result messages isempty()) { for (globalchangeorderresult message msg result messages) { system debug( 'message level ' + msg level + ' | message text ' + msg message ); } } // handle created or modified orders if (result orders != null && !result orders isempty()) { for (order ord result orders) { system debug('order created/modified id = ' + ord id + ', status = ' + ord status); // add any additional logic here, e g , link to opportunity, update custom fields, etc } } // handle created or modified orderitem (orderproducts) if (result orderproducts != null && !result orderproducts isempty()) { for (orderitem oi result orderproducts) { system debug('orderitem created/modified id = ' + oi id + ', pricebookentryid = ' + oi pricebookentryid); // for example, verify amounts, update related records, etc } } // handle created or modified subscription records if (result subscriptions != null && !result subscriptions isempty()) { for (subscription c sub result subscriptions) { system debug('subscription c created/modified id = ' + sub id + ', name = ' + sub name); // perform any post processing on the subscription (e g , set custom fields or trigger follow up logic) } } // handle created or modified assets if (result assets != null && !result assets isempty()) { for (asset ast result assets) { system debug('asset created/modified id = ' + ast id + ', name = ' + ast name); // update entitlement or support records as needed } } // handle created or modified entitlements if (result entitlements != null && !result entitlements isempty()) { for (entitlement c ent result entitlements) { system debug('entitlement c created/modified id = ' + ent id + ', name = ' + ent name); // link entitlements to customer support processes or sla tracking, etc } } } else { system debug('global change order failed '); // log all error messages if (result messages != null && !result messages isempty()) { for (globalchangeorderresult message msg result messages) { // you might want to throw an exception or add to an apexpages error here system debug( 'error level ' + msg level + ' | error message ' + msg message ); } } } create a change order including renewal & reconfigure of a bundle with dynamic product options ruby globalchangeorderservice changeorderservice = new ruby globalchangeorderservice(); ruby globalchangeorderoptions options = new ruby globalchangeorderoptions(ruby globalchangeorderproceedoption createorder); list\<ruby globalassetchangerequest> assetchanges = new list\<ruby globalassetchangerequest>(); ruby globalrenewrequest renewrequest = new ruby globalrenewrequest(); renewrequest assetnumber = 'sub 000003'; renewrequest renewalterm = 12; ruby globalreconfigurerequest reconfigrequest = new ruby globalreconfigurerequest(); reconfigrequest assetnumber = 'sub 000003'; reconfigrequest reconfigureeffectivedate = date today() addmonths(1); reconfigrequest addonchanges = new list\<ruby globalreconfigureproductoptionrequest>(); //set product option id and price book id to add dyanmic options into the subscription ruby globalreconfigurenewproductrequest n = new ruby globalreconfigurenewproductrequest('a0hrk00000bawfxyan', 7); n pricebookentryid = '01urk00000bokheyax'; reconfigrequest addonchanges add(n); assetchanges add(renewrequest); assetchanges add(reconfigrequest); ruby globalchangeorder globalchangeorder = new ruby globalchangeorder(options, assetchanges); ruby globalchangeorderresult result = changeorderservice changeorder(globalchangeorder); system debug(result); the following is additional sample code by use cases use case sample code renew ruby globalrenewrequest renewrequest = new ruby globalrenewrequest(); renewrequest assetnumber = 'sub 000013'; renewrequest switchtoevergreen = true; changerequests add(renewrequest); update term (evergreentoupdateterm) ruby globalupdatetermforevergreenrequest updatetermforevergreenrequest = new ruby globalupdatetermforevergreenrequest() updatetermforevergreenrequest assetnumber = 'sub 000012'; updatetermforevergreenrequest term = 0; changerequests add(updatetermforevergreenrequest); update term ruby globalupdatetermrequest updatetermrequest = new ruby globalupdatetermrequest(); updatetermrequest assetnumber = 'sub 000012'; updatetermrequest term = 6; changerequests add(updatetermrequest); update term to evergreen ruby globalupdatetermrequest updatetermrequest = new ruby globalupdatetermrequest(); updatetermrequest assetnumber = 'sub 000019'; updatetermrequest switchtoevergreen = true; changerequests add(updatetermrequest); cancel ruby globalassetcancelrequest cancelrequest = new ruby globalassetcancelrequest(); cancelrequest assetnumber = 'sub 000012'; cancelrequest cancellationdate = date valueof('2025 01 05'); changerequests add(cancelrequest); co term ruby globalcotermforevergreenrequest cotermforevergreenrequest = new ruby globalcotermforevergreenrequest(); cotermforevergreenrequest assetnumber = 'sub 000025'; cotermforevergreenrequest cotermdate = date valueof('2026 01 01'); changerequests add(cotermforevergreenrequest); ruby globalcotermrequest cotermrequest = new ruby globalcotermrequest(); cotermrequest assetnumber = 'sub 000026'; cotermrequest cotermdate = date valueof('2026 01 01'); changerequests add(cotermrequest); adjust price //adjust price to $4 per unit, for the following 5 months, effective today ruby globaladjustpricerequest adjustprice = new ruby globaladjustpricerequest(); adjustprice assetnumber = 'sub 000014'; adjustprice term = 5; adjustprice netsalesprice = 4; changerequests add(adjustprice); reconfigure //dynamic product options supported in 2505 ruby globalreconfigurerequest reconfigrequest = new ruby globalreconfigurerequest(); reconfigrequest assetnumber = 'sub 000003'; reconfigrequest reconfigureeffectivedate = date today() addmonths(1); reconfigrequest addonchanges = new list\<ruby globalreconfigureproductoptionrequest>(); //set product option id and price book id along with quantity to add dyanmic options into the subscription ruby globalreconfigurenewproductrequest n = new ruby globalreconfigurenewproductrequest('a0hrk00000bawfxyan', 7); n pricebookentryid = '01urk00000bokheyax'; reconfigrequest addonchanges add(n); changerequests add(reconfigrequest); upgrade // available in release 2504 // upgrade a subscription from product a to product b, specifying a product b's price book entry ruby globalproductchangerequest upgraderequest = new ruby globalproductchangerequest( ruby globalassetchangetype upgrade ); upgraderequest assetnumber = 'sub 000000'; upgraderequest startdate = date today() adddays(20); upgraderequest targetpricebookentryid = '01uql000007fzciya2'; downgrade // available in release 2504 // downgrade a subscription from product a to product b, specifying a product b's price book entry ruby globalproductchangerequest downgraderequest = new ruby globalproductchangerequest( ruby globalassetchangetype downgrade ); downgraderequest assetnumber = 'sub 000000'; downgraderequest startdate = date today() adddays(20); downgraderequest targetpricebookentryid = '01uql000007fzciya2'; swap // available in release 2504 // swap a subscription from product a to product b, specifying a product b's price book entry ruby globalproductchangerequest swaprequest = new ruby globalproductchangerequest( ruby globalassetchangetype swap ); swaprequest assetnumber = 'sub 000000'; swaprequest startdate = date today() adddays(20); swaprequest targetpricebookentryid = '01uql000007fzciya2'; swaprequest samepriceswap = true; bulk renew list bulksubscriptionlist = new list(); ruby globalrenewalrequest renewlrequest1 = new ruby globalrenewalrequest('sub 000025'); renewlrequest1 renewalterm = 12; ruby globalrenewalrequest renewlrequest2 = new ruby globalrenewalrequest('sub 000026'); renewlrequest2 renewalterm = 12; ruby globalrenewalrequest renewlrequest3 = new ruby globalrenewalrequest('sub 000027'); renewlrequest3 renewalterm = 12; bulksubscriptionlist add(renewlrequest1); bulksubscriptionlist add(renewlrequest2); bulksubscriptionlist add(renewlrequest3); ruby globalbulksubscriptionrenewalrequest bulkrenewalrequest = new ruby globalbulksubscriptionrenewalrequest(); bulkrenewalrequest subscriptionrenewalrequests = bulksubscriptionlist; bulkrenewalrequest generateopportunities = false; bulkrenewalrequest generatequotes = false; ruby globalchangeorderservice service = new ruby globalchangeorderservice(); service renewsubscriptions(bulkrenewalrequest);
🤔
Have a question?
Get answers fast with Nue’s intelligent AI, expert support team, and a growing community of users - all here to help you succeed.
To ask a question or participate in discussions, you'll need to authenticate first.