Replacing Financial Dimension in Ledger Dimension

Replacing a financial dimension in a Ledger dimension is not straight forward as the replacing of a dimension in Default dimensions. For default dimensions, we had a method serviceReplaceAttributeValue to replace one particular dimension. But for a ledger dimension, we need to do the following:

Get the target ledger dimension
Break it into its component parts (Main account and active dimensions)
Prepare the hash key array for each of them except main account (for only financial dimensions)
In this hash key array replace the hash key of the required financial dimension with the hash key of attribute value to be replaced
Find or create the DimensionAttributeValueSet table
Then use the “serviceCreateLedgerDimension” method of DimensionDefaultingService to get the new ledger dimension and use it
If anybody finds a better solution, please share.

Here is the job that does the steps explained above:

static void replaceLedgerDimensions(Args _args)
DimensionSHA1Hash hash; //To store the calculated hash for DimensionAttributeValueSet
HashKey valueKeyHashArray[]; //To store the has key of dimension in question
Map dimAttrIdx, dimAttrRecId; //to store the dimension index and backing entity type
DimensionAttributeSetItem dimAttrSetItem; // Contains the number of dimensions active for a account structure ledger
DimensionAttribute dimAttr; // Contains the financial dimensions records
DimensionAttributeValue dimAttrValue; // Contains used financial dimension values
DimensionAttributeValueSet dimAttrValueSet; //Contains default dimension records
DimensionAttributeValueSetItem dimAttrValueSetItem; //Contains individual records for default dimensions
DimAttributeHcmWorker dimAttrWorker; //Backing entity view for Employee type dimension
DimensionEnumeration dimensionSetId; //Record id for table that contains active dimensions for current ledger
LedgerDimensionAccount targetDimension = 5637145829; //Record Id DimensionAttributeValueCombination table in which attribute value is to be replaced
LedgerDimensionAccount ledgerDimension; // To hold the resultant DimensionAttributeValueCombination record id
LedgerDimensionAccount mainAccDimension; // Record id for LedgerDimension(DimensionAttributeValueCombination) containing default account for main account RecId
DimensionStorage dimensionStorage; // Class Dimension storage is used to store and manipulate the values of combination
DimensionStorageSegment segment; // Class DimensionStorageSegment will get specfic segments based on hierarchies

int segmentCount, segmentIndex;
int hierarchyCount, hierarchyIndex;
SysDim segmentValue, mainAccountValue;
int dimAttrCount, i;
int emplBackEntityType; //Stores the backing entity type for Employee type dimension
str valueStrArray[]; //To store the dimension attribute values
int64 valueKeyArray[]; //To store the record ids of DimensionAtrributeValue table
int backingEntityInstance;

//The employee backing entity will be the view DimAttributeHcmWorker
emplBackEntityType = tableNum(DimAttributeHcmWorker);

//Initialize the map to store the backing entity types
dimAttrIdx = new Map(Types::Integer, Types::Integer);
dimAttrRecId = new Map(Types::Integer, Types::Int64);

//Get the record Id (dimension set id) for current ledger to find active dimensions
dimensionSetId = DimensionCache::getDimensionAttributeSetForLedger();

//Find all the active dimensions for current ledger except main account and store there
//backing entity type in the map
while select * from dimAttr
order by Name
where dimAttr.Type != DimensionAttributeType::MainAccount
join RecId from dimAttrSetItem
where dimAttrSetItem.DimensionAttribute == dimAttr.RecId &&
dimAttrSetItem.DimensionAttributeSet == dimensionSetId
dimAttrIdx.insert(dimAttr.BackingEntityType, dimAttrCount);
dimAttrRecId.insert(dimAttr.BackingEntityType, dimAttr.RecId);

//initialize hash key array to null
for (i = 1; i<= dimAttrCount; i++)
valueKeyHashArray[i] = emptyGuid();
valueStrArray[i] = ”;
valueKeyArray[i] = 0;

// Default hash key array with required dimension value
// Get dimension storage
dimensionStorage = DimensionStorage::findById(targetDimension);
if (dimensionStorage == null)
throw error("@SYS83964");

// Get hierarchy count
hierarchyCount = dimensionStorage.hierarchyCount();
//Loop through hierarchies to get individual segments
for(hierarchyIndex = 1; hierarchyIndex <= hierarchyCount; hierarchyIndex++)
//Get segment count for hierarchy
segmentCount = dimensionStorage.segmentCountForHierarchy(hierarchyIndex);

//Loop through segments and display required values
for (segmentIndex = 1; segmentIndex <= segmentCount; segmentIndex++)
// Get segment
segment = dimensionStorage.getSegmentForHierarchy(hierarchyIndex, segmentIndex);

// Get the segment information
if (segment.parmDimensionAttributeValueId() != 0)
//Get the backing entity type;
backingEntityInstance = DimensionAttribute::find(DimensionAttributeValue::find(segment.parmDimensionAttributeValueId()).DimensionAttribute).BackingEntityType;

if (backingEntityInstance == tableNum(DimAttributeMainAccount))
mainAccountValue = segment.parmDisplayValue();

//Default the required arrays
if (dimAttrIdx.exists(backingEntityInstance))
i = dimAttrIdx.lookup(backingEntityInstance);
valueKeyHashArray[i] = segment.parmHashKey();
valueKeyArray[i] = segment.parmDimensionAttributeValueId();
valueStrArray[i] = segment.parmDisplayValue();

//Find the Dimension attribute record for the dimension to work on, in our case it is HcmWorker
dimAttr = DimensionAttribute::find(dimAttrRecId.lookup(emplBackEntityType));

//Get the backing entity type for the dimension value to process
select firstOnly dimAttrWorker
where dimAttrWorker.Value == "51011";

//Find the required Dimension Attribute Value record
//Create if necessary
dimAttrValue = DimensionAttributeValue::findByDimensionAttributeAndEntityInst(dimAttr.RecId, dimAttrWorker.RecId, false, true);

//Replace the required combination hash keys and other value arrays
i = dimAttrIdx.lookup(emplBackEntityType);
valueKeyHashArray[i] = dimAttrValue.HashKey;
valueStrArray[i] = dimAttrWorker.Value;
valueKeyArray[i] = dimAttrValue.RecId;

//Calculate the hash for the current values
hash = DimensionAttributeValueSetStorage::getHashFromArray(valueKeyHashArray, dimAttrCount);

//Null hash indicates no values exist, which may occur if the user entered an invalid value for one dimension attribute
if (hash == conNull())
throw error("Wrong value for Employee Dimension");

// Search for existing value set
dimAttrValueSet = DimensionAttributeValueSet::findByHash(hash);

// This value set does not exist, so it must be persisted
if (!dimAttrValueSet)

// Insert the value set with appropriate hash
dimAttrValueSet.Hash = hash;

// Insert only specified set items use this
for (i = 1; i <= dimAttrCount; i++)
if (valueKeyArray[i] != 0)
dimAttrValueSetItem.DimensionAttributeValueSet = dimAttrValueSet.RecId;
dimAttrValueSetItem.DimensionAttributeValue = valueKeyArray[i];
dimAttrValueSetItem.DisplayValue = valueStrArray[i];


// Get the default account for main account
mainAccDimension = DimensionStorage::getDefaultAccountForMainAccountNum(mainAccountValue);

//Find or create the LedgerDimension record for required combination
ledgerDimension = DimensionDefaultingService::serviceCreateLedgerDimension(

info(strFmt("Original %1: %2", targetDimension, DimensionAttributeValueCombination::find(targetDimension).DisplayValue));
info(strFmt("Replaced %1: %2", ledgerDimension, DimensionAttributeValueCombination::find(ledgerDimension).DisplayValue));


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.