Skip to content

Change State

kevinn-veeva edited this page Feb 4, 2019 · 7 revisions

Business Requirement

In the vSDK Country Brand Penetration workflow, if a user determines a "Product is marketed in the country" as shown below, the workflow changes the vSDK Country Brand record to an "Active" state. When this happens, the parent vSDK Product record should be set to "In Use" state automatically.

When a product's vSDK Country Brand records are all in "Terminated" or "Not Applicable" state, the vSDK Product record should be set to "Off Market" state.

Trigger Logic

The CountryBrandLifeCycleUserActions class in the project contains code to address this requirement.

Key Concepts

  • When a workflow is completed and the state is changed to "Active", "Terminated", or "Not Applicable", an AFTER_UPDATE event is triggered on the vSDK Country Brand record.

  • To trigger a state change on the associated vSDK Product, the configured User Action to change state must be invoked via the JobService, e.g. "Change State To In Use" on the "Pending" state or "Change State to Off Market" on the "In Use" state.

  • First, initialize the JobService and JobParameter objects. The JobParameter object can only be created against the record_user_action__v value.

     JobService jobService = ServiceLocator.locate(JobService.class);
     JobParameters jobParameters = jobService.newJobParameters("record_user_action__v");
    
  • Next, the JobParameter object has two required parameters that must be set: the records and user_action_name parameters.

    • For records, add each new vSDK Country Brand record to a List and use it as the input.

      jobParameters.setValue("records", records);

    • For user_action_name, use the name of the object user action:

      jobParameters.setValue("user_action_name", "change_state_to_in_use_useraction__c");

      • The user action name is derived from the user action label, in lower case with "_useraction__c" appended to it.
      • Note: there are cases where the user action name (including the _useraction suffix) is truncated to 39 characters before the final namespace "__c". If you get an error telling you the user action name is not found, use the REST API on Objectlifecycle to find out the exact name. Endpoint: /api/{{version}}/configuration/Objectlifecycle
  • Run the Job.

  • If "Product is marketed in this country", then the vSDK Product's state will be set to "In Use".

  • If all vSDK Country Brand records for a vSDK Product are marked as "Product is not applicable" or "Terminated", then the vSDK Product's state will be set to "Off Market".

To disable the automatic initialization of the workflow and state changes, set UserDefinedUtils.example_type = NO_WORKFLOW.

Sample code is shown below:

@RecordTriggerInfo(object = "vsdk_country_brand__c", name="vsdk_country_brand_lc_user_actions__c", events = {RecordEvent.AFTER_INSERT, RecordEvent.AFTER_UPDATE})
public class CountryBrandLifeCycleUserActions implements RecordTrigger {**

     //Get an instance of Job for invoking user actions, such as changing state and starting workflow
     JobService jobService = ServiceLocator.locate(JobService.class);
     JobParameters jobParameters = jobService.newJobParameters("record_user_action__v");
...

     if (UserDefinedUtils.example_type.equals(UserDefinedUtils.ALL)){

...

           else if (recordEvent.toString().equals("AFTER_UPDATE")) {
    
                //Before Country Brand is updated, update parent Product record to:
                //    From "Pending" to "In Use" state if any Country Brand record becomes "Active"
                //    From "In Use" to "Off Market" state if all Country Brand records become "Terminated" or "Not Applicable"
    
...
    
                    //If the vSDK Country Brand record becomes "Active", the parent Product record should change to "In Use".
                    if (state != null && state.equals("active_state__c")) {
    
                        if (parentState != null && !parentState.equals("in_use_state__c")) {
                            //Run job to invoke user action to change parent Product record state
                            jobParameters.setValue("user_action_name", "change_state_to_in_use_useraction__c");
                            jobParameters.setValue("records", parentProductRecords);
                            jobService.run(jobParameters);
                        }
    
                    } else if (state != null && (state.equals("terminated_state__c") || state.equals("not_applicable_state__c"))) {
    
                        //Query all Country Brand records for the same parent Product record
                        QueryService queryService = ServiceLocator.locate(QueryService.class);
                        String queryCountryBrand = "select id, state__v from vsdk_country_brand__c where vsdk_product__cr.id=" + "\'" + parentProductId + "\'" + "and id !=" + "\'" + id + "\'";
                        QueryResponse queryResponse = queryService.query(queryCountryBrand);
                        Iterator<QueryResult> iterator = queryResponse.streamResults().iterator();
    
                        //Check vSDK Country Brand records retrieved are all "Terminated" or "Not Applicable".
                        boolean allTerminated = true;
                        while (iterator.hasNext()) {
                            QueryResult qr = (QueryResult) iterator.next();
                            String nextChildState = qr.getValue("state__v", ValueType.STRING);
                            if (nextChildState != null && !nextChildState.equals("terminated_state__c") && !nextChildState.equals("not_applicable_state__c")) {
                                allTerminated = false;
                                break;
                            }
                        }
    
                        //If all vSDK Country Brand records for the parent vSDK Product record are terminated, update parent vSDK Product record to "Off Market".
                        if (allTerminated && (parentState != null && !parentState.equals("pending_state__c") && !parentState.equals("off_market_state__c"))) {
                            jobParameters.setValue("user_action_name", "change_state_to_off_market_useraction__c");
                            jobParameters.setValue("records", parentProductRecords);
                            jobService.run(jobParameters);
                        }
    
                    }
                });
            }
...