Properties
account-plan-id: Id. Required. The ID of the account plan record to load.
Namespace
cgcloud
Events
Here’s the event payload structure.
{
detail : {
value: <<new value of the property>>,
property: <<property name>>,
recordId: <<promotionId>>
}
}
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.
{
detail : {
value: 'VALID',
property: 'status',
recordId: 'a2WTC0000000F772AE'
}
}
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.
{
detail : {
value: 'LOADING',
property: 'calculationStatus',
recordId: 'a2WTC0000000F772AE'
}
}
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.
{
detail : {
value: '01pXXXXXXXXXXXXXXX000',
property: 'categoryFilter',
recordId: 'a2WTC0000000F772AE'
}
}
onkpisubsetsfilterchange
This event is triggered when the account plan subset filter changes. The event contains the selected category product ID.
{
detail : {
value: 'BaselineManagement',
property: 'kpiSubsetFilter',
recordId: 'a2WTC0000000F772AE'
}
}
Example Implementation
Here’s an example of how to use the tpm-account-plan component.
<!-- YourComponent.html -->
<template>
<cgcloud-tpm-account-plan
account-plan-id={recordId} <!-- Id of the account plan record -->
<!-- Events -->
oncategoryfilterchange={onCategoryFilterChange}
oncalculationstatuschange={onCalculationStatusChange}
</cgcloud-tpm-account-plan>
<!-- Your Component code -->
</template>
<!-- YourComponent.js-meta.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>55.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<objects>
<object>cgcloud__Promotion__c</object>
</objects>
</targetConfig>
</targetConfigs>
<runtimeNamespace>cgcloud</runtimeNamespace>
</LightningComponentBundle>
import {
LightningElement,
api
} from 'lwc';
// Import the TPMManualInput class to create new instances
import {
TPMManualInput
} from 'c/tpmGenericUtils';
export default class SampleAccountPlanTester extends LightningElement {
@api recordId; // Record Id provided by the LWC framework
currentCategoryId = '';
currentCalculationStatus = 'LOADING';
onCategoryFilterChange(event) {
// Store currently selected category
this.currentCategoryId = event.detail.value;
}
onCalculationStatusChange(event) {
// Store current status of calculation engine
this.currentCalculationStatus = event.detail.value;
}
// In this method, we will be adding a new manual input to the grid.
// This can, for instance, be executed in the click of a button or after
// some user interaction
async addNewManualInputs() {
const tpmAccountPlan = this.template.querySelector('cgcloud-tpm-account-plan');
// Extract the current manual inputs
const currentManualInputs = tpmAccountPlan.getProperty('manualInputs');
// You can read information from the current Manual Inputs:
currentManualInputs.forEach((mi) => {
console.log(mi.getKPICode()); // 'ALMD'
console.log(mi.getPeriodDateFrom()); // Date
console.log(mi.getPeriodDateThru()); // Date
console.log(mi.ProductId()); // '01qXXXXXXXXXXXXXXX'
console.log(mi.getValue()); // 133
console.log(mi.isObsolete()); // false
});
// Example: KPI Code to set the manual input to
const kpiCode = 'ABCD';
// Example: Product Id to set the manual input to. If null,
// the manual input will be applied to the "Total" for the KPI
// productId can be any level on the product hierarchy that is part of
// the calculation (SubCategory, Brand, etc...)
const productId = '01tXXXXXXXXXXXXXXX';
// Methods used to extract data from Grid require the Grid to be in valid
// status. If trying to extract data from grid when not in the correct status
// an exception will be thrown
if (this.currentCalculationStatus !== 'VALID') {
throw new Error('Grid not in VALID status');
}
// Extract the periods information from the grid
const periods = await tpmAccountPlan.getPeriods();
// We find the period where we want to set the manual input.
// You can find periods by name or use the periods "dateFrom, "dateThru" and "periodtype"
// attributes to search for an specific period.
// In this example, we will set the manual input on the "Total" period
// that uses an specific label
const manualInputPeriod = periods.find((p) => p.periodtype === 'Total');
// Create the new instance
const newManualInput = new TPMManualInput({
kpiCode: kpiCode,
period: manualInputPeriod,
productId: productId,
value: 123 // Value to set
});
// Create a new array with our new manual input appended
const newManualInputArray = [currentManualInputs, newManualInput];
// Set the manual inputs
// If the array length is greater than the limit of
// manual inputs, the "set" operation will throw an error
tpmAccountPlan.setManualInputs(newManualInputArray);
// After setting the new manual inputs, the Grid will be automatically
// reloaded and re-rendered with the new values in place.
// At this point, manual inputs are still not saved to SFDC database.
// the user must save & calculate the account plan
}
}
TPM Account Plan Component Methods
Here are the methods supported by the tpm-account-plan LWC.
exportKPIs
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:
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
const api = this.template.querySelector('cgcloud-tpm-promotion');
// Export options, the possible values can be extracted using
// the other described methods
const exportOptions = {
subsets: ["Planning"], // Subsets to request data
periods: [
"Total",
"Week"
],
levels: [
"Total",
"Category",
"Product"
],
format: "json"
};
// Correct Scenario
api.getProperty('calculationStatus'); // 'VALID'
api.exportKPIs(exportOptions)
.then((data) => {
// Example response as CSV
//
// kpiName,Category,Product,AP_LBL_TOTAL,03/2022,04/2022
// SampleKPI1,,,246,123,123
// SampleKPI1,01tTC0000000001AAA,,246,123,123
// SampleKPI1,01tTC0000000001AAA,01tTC0000000002AAA,246,123,123
// SampleKPI2,,,1974,987,987
// SampleKPI2,01tTC0000000001AAA,,1974,987,987
// SampleKPI2,01tTC0000000001AAA,01tTC0000000002AAA,1974,987,987
// Example response as JSON
//
// [{
// kpiName: "SampleKPI1",
// Category: null,
// Product: null,
// AP_LBL_TOTAL: 246,
// "03/2022": 123,
// "04/2022": 123
// }, {
// kpiName: "SampleKPI1",
// Category: "01tTC0000000001AAA",
// Product: null,
// AP_LBL_TOTAL: 246,
// "03/2022": 123,
// "04/2022": 123
// },{
// kpiName: "SampleKPI1",
// Category: "01tTC0000000001AAA",
// Product: "01tTC0000000002AAA",
// AP_LBL_TOTAL: 246,
// "03/2022": 123,
// "04/2022": 123
// },{
// kpiName: "SampleKPI2",
// Category: null,
// Product: null,
// AP_LBL_TOTAL: 1974,
// "03/2022": 987,
// "04/2022": 987
// },{
// kpiName: "SampleKPI2",
// Category: "01tTC0000000001AAA",
// Product: null,
// AP_LBL_TOTAL: 1974,
// "03/2022": 987,
// "04/2022": 987
// },{
// kpiName: "SampleKPI2",
// Category: "01tTC0000000001AAA",
// Product: "01tTC0000000002AAA",
// AP_LBL_TOTAL: 1974,
// "03/2022": 987,
// "04/2022": 987
// }]
// We can access the properties on the result:
const firstRecord = data[0];
console.log(firstRecord["kpiName"]); // "SampleKPI1"
// Since we request the total period,
// we can read the total period value
console.log(firstRecord["AP_LBL_TOTAL"]); // 246
// We can also read specific periods information
console.log(firstRecord["03/2022"]); // 123
// We can also know which level the row references
console.log(firstRecord["Category"]); // null
console.log(firstRecord["Product"]); // null
// Since Category is null, it means this data row
// represents the total value for KPI "SampleKPI1"
// For last record
const lastRecord = data[data.length - 1];
console.log(lastRecord["kpiName"]); // "SampleKPI2"
// Since we request the total period,
// we can read the total period value
console.log(lastRecord["AP_LBL_TOTAL"]); // 1974
// We can also read specific periods information
console.log(lastRecord["03/2022"]); // 987
// We can also know which level the row references
console.log(lastRecord["Category"]); // "01tTC0000000001AAA"
console.log(lastRecord["Product"]); // "01tTC0000000002AAA"
// Since Product is not null, it means this data row
// represents the value for KPI "SampleKPI2" for that
// specific product
});
// Error Scenario
api.getProperty('calculationStatus'); // 'LOADING'
api.exportKPIs(exportOptions)
.catch((error) => {
console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
});
getProperty
API Version
59.0
Signature
getProperty(propName)
The available properties to retrieve are:
- status
- calculationStatus
- manualInputs
- kpiSubsetFilter
- categoryFilter
getLevelNames
API Version
59.0
Signature
getLevelNames()
Example Implementation
const api = this.template.querySelector('cgcloud-tpm-account-plan');
// Correct Scenario
api.getProperty('calculationStatus'); // 'VALID'
api.getLevelNames()
.then((levels) => {
console.log(levels); // [ "Brand", "Product"]
});
// Error Scenario
api.getProperty('calculationStatus'); // 'LOADING'
api.getLevelNames()
.catch((error) => {
console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
});
getKPISubsets
API Version
59.0
Signature
getKPISubsets()
Example Implementation
const api = this.template.querySelector('cgcloud-tpm-account-plan');
// Correct Scenario
api.getProperty('calculationStatus'); // 'VALID'
api.getKPISubsets()
.then((subsets) => {
console.log(subsets); // ["Planning", ...
});
// Error Scenario
api.getProperty('calculationStatus'); // 'LOADING'
api.getKPISubsets()
.catch((error) => {
console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
});
getKPIs
API Version
59.0
Signature
getKPIs()
Example Implementation
const api = this.template.querySelector('cgcloud-tpm-account-plan');
// Correct Scenario
api.getProperty('calculationStatus'); // 'VALID'
api.getKPIs()
.then((kpis) => {
// 0
console.log(kpis[0].id); // "0"
console.log(kpis[0].name); // "BasePrice"
console.log(kpis[0].kpitype); // "account"
console.log(kpis[0].skipped); // ["Tactic"]
console.log(kpis[0].type); // "read"
console.log(kpis[0].valuetype); // "Price"
});
// Error Scenario
api.getProperty('calculationStatus'); // 'LOADING'
api.getKPIs()
.catch((error) => {
console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
});
getPeriods
API Version
59.0
Signature
getPeriods()
Example Implementation
const api = this.template.querySelector('cgcloud-tpm-account-plan');
// Correct Scenario
api.getProperty('calculationStatus'); // 'VALID'
api.getPeriods()
.then((periods) => {
// 0
console.log(periods[0].id); // "0"
console.log(periods[0].name); // "AP_LBL_TOTAL" (label of the period)
console.log(periods[0].periodtype); // "Total"
console.log(periods[0].dateFrom); // null
console.log(periods[0].dateThru); // null
// 1
console.log(periods[1].id); // 1
console.log(periods[1].name); // "36/2022" // label in case of label is specified alternativly it returns the ....
console.log(periods[1].periodtype); // "Week"
console.log(periods[1].dateFrom); // 1661731200000 timestamp
console.log(periods[1].dateThru); // 1662249600000 timestamp
});
// Error Scenario
api.getProperty('calculationStatus'); // 'LOADING'
api.getPeriods()
.catch((error) => {
console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
});
getPeriodTypes
API Version
59.0
Signature
getPeriodTypes()
Example Implementation
const api = this.template.querySelector('cgcloud-tpm-account-plan');
// Correct Scenario
api.getProperty('calculationStatus'); // 'VALID'
api.getPeriodTypes()
.then((periodTypes) => {
console.log(periodTypes); // ["Total", "Week"]
});
// Error Scenario
api.getProperty('calculationStatus'); // 'LOADING'
api.getPeriodTypes()
.catch((error) => {
console.log(error.message); // CalculationStatus is not "VALID". Current Status "LOADING"
});
setManualInputs
Manual grid edits are an array of TPMManualInput instances. You can add new entries or remove entries from the existing array of elements.
API Version
60.0
Signature
setManualInputs(manualInputs)
Example Implementation
// Import the TPMManualInput class to create new instances
import {
TPMManualInput
} from 'cgcloud/tpmGenericUtils';
// In this method, we will be adding a new manual input to the grid.
// This can, for instance, be executed in the click of a button or after
// some user interaction
async addNewManualInputs() {
const tpmAccountPlan = this.template.querySelector('cgcloud-tpm-account-plan');
// Extract the current manual inputs
const currentManualInputs = tpmAccountPlan.getProperty('manualInputs');
// You can read information from the current Manual Inputs:
currentManualInputs.forEach((mi) => {
console.log(mi.getKPICode()); // 'ALMN'
console.log(mi.getPeriodDateFrom()); // Date
console.log(mi.getPeriodDateThru()); // Date
console.log(mi.ProductId()); // '03sXXXXXXXXXXXXXXX'
console.log(mi.getValue()); // 133
});
// Example: KPI code to set the manual input to
const kpiCode = 'ABCD';
// Example: Product Id to set the manual input to. If null,
// the manual input will be applied to the "Total" for the KPI
// productId can be any level on the product hierarchy that is part of
// the calculation (SubCategory, Brand, etc)
const productId = '01tXXXXXXXXXXXXXXX';
// Methods used to extract data from Grid require the Grid to be in valid
// status. If trying to extract data from grid when not in the correct status
// an exception will be thrown
if (tpmAccountPlan.getProperty('calculationStatus') !== 'VALID') {
throw new Error('Grid not in VALID status');
}
// Extract the periods information from the grid
const periods = await tpmAccountPlan.getPeriods();
// We find the period where we want to set the manual input.
// You can find periods by name or use the periods "dateFrom, "dateThru" and "periodtype"
// attributes to search for an specific period.
// In this example, we will set the manual input on the "Total" period
// that uses an specific label
const manualInputPeriod = periods.find((p) => p.periodtype === 'Total');
// Create the new instance
const newManualInput = new TPMManualInput({
kpiCode: kpiCode,
period: manualInputPeriod,
productId: productId,
value: 123 // Value to set
});
// Create a new array with our new manual input appended
const newManualInputArray = [currentManualInputs, newManualInput];
// Set the manual inputs
tpmAccountPlan.setManualInputs(newManualInputArray);
// After setting the new manual inputs, the grids will be automatically
// reloaded and re-rendered with the new values in place.
// At this point, manual inputs are still not saved to SFDC database.
// the user must save the account plan
}