Newer Version Available

This content describes an older version of this product. View Latest

TPM Account Plan LWC Reference

The tpm-account-plan LWC is a service component that loads a TPM account plan, exposing methods to update the account plan state, and events to keep all UI components of the account plan page in sync when the account plan state changes.

The content in this Consumer Goods Cloud Trade Promotion Management documentation is confidential and may be viewed only by customers or partners as authorized by Salesforce, and copying and further distribution is prohibited without prior written consent from Salesforce. The content is the highly confidential and proprietary information of Salesforce and is protected under the confidentiality obligations of your Agreement with Salesforce. Accordingly, the content may be used only as necessary in order to implement the Consumer Goods Cloud Trade Promotion Management functionality.

Important

Properties

account-plan-id: Id. Required. The ID of the account plan record to load.

Namespace

1cgcloud

Events

Here’s the event payload structure.

1{
2    detail : {
3        value: <<new value of the property>>,
4        property: <<property name>>,
5        recordId: <<promotionId>>
6    }
7}

onstatuschange

This event is triggered when the lifecycle state of the TPM account plan component changes. Status changes are triggered by lifecycle operations on the account plan record.

1{
2    detail : {
3        value: 'VALID',
4        property: 'status',
5        recordId: 'a2WTC0000000F772AE'
6    }
7}

The possible values are:

  • LOADING: The account plan is being loaded.
  • VALID: The account plan is loaded and can be interacted with.
  • SAVING: The account plan is being saved to the database.
  • ERROR: An irrecoverable error has occurred.

oncalculationstatuschange

This event is triggered when the account plan grids are calculated or recalculated.

1{
2    detail : {
3        value: 'LOADING',
4        property: 'calculationStatus',
5        recordId: 'a2WTC0000000F772AE'
6    }
7}

The possible values are:

  • LOADING: The calculations are being processed, or the engine is loading.
  • VALID: The calculations are completed, and values can be requested.
  • ERROR: An irrecoverable error has occurred.
  • DISABLED: The calculations engine is disabled for the account plan.

oncategoryfilterchange

This event is triggered when the account plan’s selected product category filter changes. The event contains the selected category product ID.

1{
2    detail : {
3        value: '01pXXXXXXXXXXXXXXX000',
4        property: 'categoryFilter',
5        recordId: 'a2WTC0000000F772AE'
6    }
7}

onkpisubsetsfilterchange

This event is triggered when the account plan subset filter changes. The event contains the selected category product ID.

1{
2    detail : {
3        value: 'BaselineManagement',
4        property: 'kpiSubsetFilter',
5        recordId: 'a2WTC0000000F772AE'
6    }
7}

Example Implementation

Here’s an example of how to use the tpm-account-plan component.

1<!-- YourComponent.html -->
2<template>
3   <cgcloud-tpm-account-plan
4      account-plan-id={recordId} <!-- Id of the account plan record -->
5      <!-- Events -->
6      oncategoryfilterchange={onCategoryFilterChange}
7      oncalculationstatuschange={onCalculationStatusChange}
8   </cgcloud-tpm-account-plan>
9   
10   <!-- Your Component code -->
11</template>
1<!-- YourComponent.js-meta.xml -->
2<?xml version="1.0" encoding="UTF-8"?>
3<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
4    <apiVersion>55.0</apiVersion>
5    <isExposed>true</isExposed>
6    <targets>
7        <target>lightning__RecordPage</target>
8    </targets>
9    <targetConfigs>
10        <targetConfig targets="lightning__RecordPage">
11            <objects>
12                <object>cgcloud__Promotion__c</object>
13            </objects>
14        </targetConfig>
15    </targetConfigs>
16    <runtimeNamespace>cgcloud</runtimeNamespace>
17</LightningComponentBundle>
1import {
2    LightningElement,
3    api
4} from 'lwc';
5
6// Import the TPMManualInput class to create new instances
7import {
8    TPMManualInput
9} from 'c/tpmGenericUtils';
10
11export default class SampleAccountPlanTester extends LightningElement {
12    @api recordId; // Record Id provided by the LWC framework
13
14    currentCategoryId = '';
15    currentCalculationStatus = 'LOADING';
16
17    onCategoryFilterChange(event) {
18        // Store currently selected category
19        this.currentCategoryId = event.detail.value;
20    }
21
22    onCalculationStatusChange(event) {
23        // Store current status of calculation engine
24        this.currentCalculationStatus = event.detail.value;
25    }
26
27    // In this method, we will be adding a new manual input to the grid.
28    // This can, for instance, be executed in the click of a button or after
29    // some user interaction
30    async addNewManualInputs() {
31        const tpmAccountPlan = this.template.querySelector('cgcloud-tpm-account-plan');
32
33        // Extract the current manual inputs
34        const currentManualInputs = tpmAccountPlan.getProperty('manualInputs');
35
36        // You can read information from the current Manual Inputs:
37        currentManualInputs.forEach((mi) => {
38            console.log(mi.getKPICode()); // 'ALMD'
39            console.log(mi.getPeriodDateFrom()); // Date
40            console.log(mi.getPeriodDateThru()); // Date
41            console.log(mi.ProductId()); // '01qXXXXXXXXXXXXXXX'
42            console.log(mi.getValue()); // 133
43            console.log(mi.isObsolete()); // false
44        });
45
46        // Example: KPI Code to set the manual input to
47        const kpiCode = 'ABCD';
48
49        // Example: Product Id to set the manual input to. If null,
50        // the manual input will be applied to the "Total" for the KPI
51        // productId can be any level on the product hierarchy that is part of 
52        // the calculation (SubCategory, Brand, etc...)
53        const productId = '01tXXXXXXXXXXXXXXX';
54
55        // Methods used to extract data from Grid require the Grid to be in valid
56        // status. If trying to extract data from grid when not in the correct status
57        // an exception will be thrown
58        if (this.currentCalculationStatus !== 'VALID') {
59            throw new Error('Grid not in VALID status');
60        }
61
62        // Extract the periods information from the grid
63        const periods = await tpmAccountPlan.getPeriods();
64
65        // We find the period where we want to set the manual input.
66        // You can find periods by name or use the periods "dateFrom, "dateThru" and "periodtype"
67        // attributes to search for an specific period.
68        // In this example, we will set the manual input on the "Total" period
69        // that uses an specific label
70        const manualInputPeriod = periods.find((p) => p.periodtype === 'Total');
71
72        // Create the new instance
73        const newManualInput = new TPMManualInput({
74            kpiCode: kpiCode,
75            period: manualInputPeriod,
76            productId: productId,
77            value: 123 // Value to set
78        });
79
80        // Create a new array with our new manual input appended
81        const newManualInputArray = [currentManualInputs, newManualInput];
82
83        // Set the manual inputs
84        // If the array length is greater than the limit of 
85        // manual inputs, the "set" operation will throw an error
86        tpmAccountPlan.setManualInputs(newManualInputArray);
87
88        // After setting the new manual inputs, the Grid will be automatically
89        // reloaded and re-rendered with the new values in place.
90
91        // At this point, manual inputs are still not saved to SFDC database.
92        // the user must save & calculate the account plan
93    }
94}

TPM Account Plan Component Methods

Here are the methods supported by the tpm-account-plan LWC.

exportKPIs

This method returns a promise resolving to the values of the KPIs for the selected KPI subsets or names, levels, and period types.

API Version

58.0

Signature

exportKPIs(options)

Properties

Name Type Description Required or Optional
options.subsets List<String> List of loaded KPI subsets to retrieve data from.

You can get a list of loaded subsets using the getKPISubsets() method.

Provide either the KPI subsets or the KPI names.

Optional
options.kpis List<String> List of KPI names to retrieve data from.

You can get a list of loaded KPI names using the getKPIs() method.

Provide either the KPI subsets or the KPI names.

Optional
options.levels List<String> List of loaded levels to retrieve data from. 

You can get a list of loaded levels using the getLevelNames() method.

Optional
options.periods List<String> List of loaded period types to retrieve data.

You can get a list of loaded period types using the getPeriodTypes() method.

Optional
options.format List<String> Format in which the response is returned.

Possible formats are:

  • JSON: The response is an array of JavaScript objects.
  • Serialized: The response is a JSON string of JavaScript objects.
  • CSV: The response is a CSV string.

The default format is JSON.

Optional

The returned data is a list of rows (JavaScript objects or CSV rows). Each row represents the value of the KPI for the determined level. Each row contains values for all the periods specified in the request.

Example Implementation

1const api = this.template.querySelector('cgcloud-tpm-promotion');
2
3// Export options, the possible values can be extracted using
4// the other described methods
5const exportOptions = {
6    subsets: ["Planning"], // Subsets to request data
7    periods: [
8        "Total",
9        "Week"
10    ],
11    levels: [
12        "Total",
13        "Category",
14        "Product"
15    ],
16    format: "json"
17};
18
19// Correct Scenario
20api.getProperty('calculationStatus'); // 'VALID'
21
22api.exportKPIs(exportOptions)
23    .then((data) => {
24        // Example response as CSV
25        //
26        // kpiName,Category,Product,AP_LBL_TOTAL,03/2022,04/2022
27        // SampleKPI1,,,246,123,123
28        // SampleKPI1,01tTC0000000001AAA,,246,123,123
29        // SampleKPI1,01tTC0000000001AAA,01tTC0000000002AAA,246,123,123
30        // SampleKPI2,,,1974,987,987
31        // SampleKPI2,01tTC0000000001AAA,,1974,987,987
32        // SampleKPI2,01tTC0000000001AAA,01tTC0000000002AAA,1974,987,987
33
34        // Example response as JSON
35        //
36        // [{
37        //    kpiName: "SampleKPI1",
38        //    Category: null,
39        //    Product: null,
40        //    AP_LBL_TOTAL: 246,
41        //    "03/2022": 123,
42        //    "04/2022": 123     
43        // }, {
44        //    kpiName: "SampleKPI1",
45        //    Category: "01tTC0000000001AAA",
46        //    Product: null,
47        //    AP_LBL_TOTAL: 246,
48        //    "03/2022": 123,
49        //    "04/2022": 123
50        // },{
51        //    kpiName: "SampleKPI1",
52        //    Category: "01tTC0000000001AAA",
53        //    Product: "01tTC0000000002AAA",
54        //    AP_LBL_TOTAL: 246,
55        //    "03/2022": 123,
56        //    "04/2022": 123
57        // },{
58        //    kpiName: "SampleKPI2",
59        //    Category: null,
60        //    Product: null,
61        //    AP_LBL_TOTAL: 1974,
62        //    "03/2022": 987,
63        //    "04/2022": 987
64        // },{
65        //    kpiName: "SampleKPI2",
66        //    Category: "01tTC0000000001AAA",
67        //    Product: null,
68        //    AP_LBL_TOTAL: 1974,
69        //    "03/2022": 987,
70        //    "04/2022": 987
71        // },{
72        //    kpiName: "SampleKPI2",
73        //    Category: "01tTC0000000001AAA",
74        //    Product: "01tTC0000000002AAA",
75        //    AP_LBL_TOTAL: 1974,
76        //    "03/2022": 987,
77        //    "04/2022": 987
78        // }]
79
80
81        // We can access the properties on the result:
82        const firstRecord = data[0];
83
84        console.log(firstRecord["kpiName"]); // "SampleKPI1"
85        // Since we request the total period, 
86        // we can read the total period value
87        console.log(firstRecord["AP_LBL_TOTAL"]); // 246
88        // We can also read specific periods information
89        console.log(firstRecord["03/2022"]); // 123
90        // We can also know which level the row references 
91        console.log(firstRecord["Category"]); // null
92        console.log(firstRecord["Product"]); // null
93        // Since Category is null, it means this data row 
94        // represents the total value for KPI "SampleKPI1" 
95
96        // For last record
97        const lastRecord = data[data.length - 1];
98
99        console.log(lastRecord["kpiName"]); // "SampleKPI2"
100        // Since we request the total period, 
101        // we can read the total period value
102        console.log(lastRecord["AP_LBL_TOTAL"]); // 1974
103        // We can also read specific periods information
104        console.log(lastRecord["03/2022"]); // 987
105        // We can also know which level the row references 
106        console.log(lastRecord["Category"]); // "01tTC0000000001AAA"
107        console.log(lastRecord["Product"]); // "01tTC0000000002AAA"
108        // Since Product is not null, it means this data row 
109        // represents the value for KPI "SampleKPI2" for that
110        // specific product
111    });
112
113// Error Scenario
114api.getProperty('calculationStatus'); // 'LOADING'
115
116api.exportKPIs(exportOptions)
117    .catch((error) => {
118        console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
119    });

getProperty

Imperatively retrieve the account plan state properties.

API Version

59.0

Signature

getProperty(propName)

The available properties to retrieve are:

  • status
  • calculationStatus
  • manualInputs
  • kpiSubsetFilter
  • categoryFilter

getLevelNames

This method returns a promise resolving to the list of levels that are currently loaded in the calculation engine. If the calculation status isn’t valid, the method returns an error.

API Version

59.0

Signature

getLevelNames()

Example Implementation

1const api = this.template.querySelector('cgcloud-tpm-account-plan');
2
3// Correct Scenario
4api.getProperty('calculationStatus'); // 'VALID'
5
6api.getLevelNames()
7    .then((levels) => {
8        console.log(levels); // [ "Brand", "Product"]
9    });
10
11// Error Scenario
12api.getProperty('calculationStatus'); // 'LOADING'
13
14api.getLevelNames()
15    .catch((error) => {
16        console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
17    });

getKPISubsets

This method returns a promise resolving to the list of KPI subsets that are currently loaded in the calculation engine. If the calculation status isn’t valid, the method returns an error.

API Version

59.0

Signature

getKPISubsets()

Example Implementation

1const api = this.template.querySelector('cgcloud-tpm-account-plan');
2
3// Correct Scenario
4api.getProperty('calculationStatus'); // 'VALID'
5
6api.getKPISubsets()
7    .then((subsets) => {
8        console.log(subsets); // ["Planning", ...
9    });
10
11// Error Scenario
12api.getProperty('calculationStatus'); // 'LOADING'
13
14api.getKPISubsets()
15    .catch((error) => {
16        console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
17    });

getKPIs

This method returns a promise resolving to the list of KPIs that are currently loaded in the calculation engine. If the calculation status isn’t valid, the method returns an error.

API Version

59.0

Signature

getKPIs()

Example Implementation

1const api = this.template.querySelector('cgcloud-tpm-account-plan');
2
3// Correct Scenario
4api.getProperty('calculationStatus'); // 'VALID'
5
6api.getKPIs()
7    .then((kpis) => {
8        // 0 
9        console.log(kpis[0].id); // "0"
10        console.log(kpis[0].name); // "BasePrice"
11        console.log(kpis[0].kpitype); // "account"
12        console.log(kpis[0].skipped); // ["Tactic"]
13        console.log(kpis[0].type); // "read"
14        console.log(kpis[0].valuetype); // "Price"
15    });
16
17// Error Scenario
18api.getProperty('calculationStatus'); // 'LOADING'
19
20api.getKPIs()
21    .catch((error) => {
22        console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
23    });

getPeriods

This method returns a promise resolving to the list of periods that are currently loaded in the calculation engine. If the calculation status isn’t valid, the method returns an error.

API Version

59.0

Signature

getPeriods()

Example Implementation

1const api = this.template.querySelector('cgcloud-tpm-account-plan');
2
3// Correct Scenario
4api.getProperty('calculationStatus'); // 'VALID'
5
6api.getPeriods()
7    .then((periods) => {
8        // 0 
9        console.log(periods[0].id); // "0"
10        console.log(periods[0].name); // "AP_LBL_TOTAL" (label of the period)
11        console.log(periods[0].periodtype); // "Total"
12        console.log(periods[0].dateFrom); // null
13        console.log(periods[0].dateThru); // null
14        // 1 
15        console.log(periods[1].id); // 1
16        console.log(periods[1].name); // "36/2022" // label in case of label is specified alternativly it returns the ....
17        console.log(periods[1].periodtype); // "Week"
18        console.log(periods[1].dateFrom); // 1661731200000 timestamp
19        console.log(periods[1].dateThru); // 1662249600000 timestamp
20    });
21
22// Error Scenario
23api.getProperty('calculationStatus'); // 'LOADING'
24
25api.getPeriods()
26    .catch((error) => {
27        console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
28    });

getPeriodTypes

This method returns a promise resolving to the list of period types that are currently loaded in the calculation engine. If the calculation status isn’t valid, the method returns an error.

API Version

59.0

Signature

getPeriodTypes()

Example Implementation

1const api = this.template.querySelector('cgcloud-tpm-account-plan');
2
3// Correct Scenario
4api.getProperty('calculationStatus'); // 'VALID'
5
6api.getPeriodTypes()
7    .then((periodTypes) => {
8        console.log(periodTypes); // ["Total", "Week"]
9    });
10
11// Error Scenario
12api.getProperty('calculationStatus'); // 'LOADING'
13
14api.getPeriodTypes()
15    .catch((error) => {
16        console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
17    });

setManualInputs

This method sets an array of manual inputs in the account plan service component.

API Version

Manual grid edits are an array of TPMManualInput instances. You can add new entries or remove entries from the existing array of elements.

60.0

Signature

setManualInputs(manualInputs)

Example Implementation

1// Import the TPMManualInput class to create new instances
2import {
3    TPMManualInput
4} from 'cgcloud/tpmGenericUtils';
5
6
7// In this method, we will be adding a new manual input to the grid.
8// This can, for instance, be executed in the click of a button or after
9// some user interaction
10async addNewManualInputs() {
11    const tpmAccountPlan = this.template.querySelector('cgcloud-tpm-account-plan');
12
13    // Extract the current manual inputs
14    const currentManualInputs = tpmAccountPlan.getProperty('manualInputs');
15
16    // You can read information from the current Manual Inputs:
17    currentManualInputs.forEach((mi) => {
18        console.log(mi.getKPICode()); // 'ALMN'
19        console.log(mi.getPeriodDateFrom()); // Date
20        console.log(mi.getPeriodDateThru()); // Date
21        console.log(mi.ProductId()); // '03sXXXXXXXXXXXXXXX'
22        console.log(mi.getValue()); // 133
23    });
24
25    // Example: KPI code to set the manual input to
26    const kpiCode = 'ABCD';
27
28    // Example: Product Id to set the manual input to. If null,
29    // the manual input will be applied to the "Total" for the KPI
30    // productId can be any level on the product hierarchy that is part of 
31    // the calculation (SubCategory, Brand, etc)
32    const productId = '01tXXXXXXXXXXXXXXX';
33
34    // Methods used to extract data from Grid require the Grid to be in valid
35    // status. If trying to extract data from grid when not in the correct status
36    // an exception will be thrown
37    if (tpmAccountPlan.getProperty('calculationStatus') !== 'VALID') {
38        throw new Error('Grid not in VALID status');
39    }
40
41    // Extract the periods information from the grid
42    const periods = await tpmAccountPlan.getPeriods();
43
44    // We find the period where we want to set the manual input.
45    // You can find periods by name or use the periods "dateFrom, "dateThru" and "periodtype"
46    // attributes to search for an specific period.
47    // In this example, we will set the manual input on the "Total" period
48    // that uses an specific label
49    const manualInputPeriod = periods.find((p) => p.periodtype === 'Total');
50
51    // Create the new instance
52    const newManualInput = new TPMManualInput({
53        kpiCode: kpiCode,
54        period: manualInputPeriod,
55        productId: productId,
56        value: 123 // Value to set
57    });
58
59    // Create a new array with our new manual input appended
60    const newManualInputArray = [currentManualInputs, newManualInput];
61
62    // Set the manual inputs
63    tpmAccountPlan.setManualInputs(newManualInputArray);
64
65    // After setting the new manual inputs, the grids will be automatically
66    // reloaded and re-rendered with the new values in place.
67
68    // At this point, manual inputs are still not saved to SFDC database.
69    // the user must save the account plan
70}