All Collections
Ardoq Use Case Guides
Administrating Use Case Module
Migrate from IT Cost Management v1 to IT Cost Management v2
Migrate from IT Cost Management v1 to IT Cost Management v2

IT Cost Management Use Case Guide Migration Guide

Simon Wilkes avatar
Written by Simon Wilkes
Updated over a week ago

Table of Contents:

Why Migrate?

Keeping track of your IT spending can be challenging. Designing and implementing a cost management model with aggregations, dataflows, and information gathering is a major task.

The Ardoq IT Cost Management (ITCM) use case, which comes preconfigured, offers quick start-up and fast results.

To maximize realized value, Ardoq continually develops and refines its best practices. As a result of our feedback and iterative design process, we have extended the ITCM metamodel to further meet the needs of organizations.

The purpose of this document is to explain the differences between v1 and v2 of the ITCM metamodel and how you can migrate from v1 to v2.

Benefits of Migrating to v2:

Cost showbacks can be shown to departments and teams with the inclusion of Organizational Unit cost fields.

Before you begin:

  • It is assumed that you have the IT Cost Management Use Case deployed on your Ardoq instance.

  • Version 2 migration is optional, but recommended

  • There is no automated migration solution available at the moment, so manual migration is necessary

  • You have notified all parties who may be affected by this change

  • You need a team member in your organization who can modify Ardoq's configuration (metamodels, fields, broadcasts, and reports). Ardoq admins are typically responsible for this.

1. Changes to the Metamodel

In the screenshots below you can see how the two metamodels compare with each other. Fields that need to be modified are highlighted in the new metamodel.

Old

New

2. Changes to fields

Below you will find a list of field changes (workspaces & references) that need to be made, as well as links to the corresponding fields with gremlin code changes.

Field

Workspace &

Reference Types

New

Removed

Changed

Replacement

Gremlin code

Total Consumed Cost

All workspace types

Removed

Total Attributed Cost

Total Cost

All workspaces types

Changed. New gremlin

-

Total Consumption Percentage

  • Application workspace type

  • Server workspace type

Removed

Total Attributed Percentage

Cost Consumption Percent Data Quality

  • Application workspace type

Removed

Cost Attribution Percent Data Quality

Cost Consumption

All reference types

Removed

Cost Type Attribution

Cost Consumption Percentage

All references types

Removed

Cost Attribution Percentage

Total Attributed Percentage

  • Server workspace type

  • Org. Unit workspace type

New

Cost Attribution Percent Data Quality

  • Org. Unit workspace type

New

Cost Type Attribution

  • Is Realized By reference type

  • Owns reference type

  • Is Supported By reference type

New

Cost Attribution Percentage

  • Is Realized By reference type

  • Owns reference type

  • Is Supported By reference type

New

Total Attributed Cost

  • Business and Technical Capability workspace type

New

Budgeted CAPEX

Organization Workspace

New

Budgeted OPEX

Organization Workspace

New

Total Budgeted Cost

Organization Workspace

New

3. Changes to the presentation

ITCM - IT Cost Management Presentation needs to include v2 fields where v1 fields are shown (fields containing "Consumes"/"Consumption"/"Consumed"). As shown in the table above, they have been replaced by corresponding v2 fields.

4. Changes to reports

Green highlights indicate new reports that need to be configured. Each new report should be configured according to the screenshots below. For every Gremlin Graph Search report, the Gremlin code is provided.

ITCM DQ - Over allocated Org Units

ITCM DQ - Cost Type Attribution is Activated

fieldName = 'cost_type_attribution'

referenceTypesWithField =
g.E().
has(fieldName).
project('label', 'rootWorkspace').
by(label()).
by('rootWorkspace').
dedup().
fold().
next()

hasTypeWithField = {
referenceTypesWithField.any{ type ->
it.get().label() == type.label &&
it.get().value('rootWorkspace') == type.rootWorkspace
}
}

g.E().
filter(hasTypeWithField).
filter{ it.get().property(fieldName).orElse([]).size > 0 }/*.
count()*/

ITCM DQ - Org Units without Cost

ITCM - Showback

def toUSD = {
amount = String.format("%,.0f", (Double) it.get());
return "\$"+amount;
}

g.V().hasLabel('Organizational Unit').filter(__.out('Consumes').hasLabel('Application').values('name')).
project('name', 'Consumption Cost', 'Consuming Applications').
by('name').
by(
__.out('Consumes').hasLabel('Application').
as('totalCost', 'numberOfConsumesApplications').
math('totalCost / numberOfConsumesApplications').
by(coalesce(values('total_cost'), constant(0))).
by(__.in('Consumes').hasLabel('Organizational Unit').count()).
sum().map({ it.get().toFloat() }).map(toUSD)
).
by(__.out('Consumes').hasLabel('Application').values('name').fold().dedup())

ITCM - Total Cost of Organizational Units

g.V().hasLabel('Organizational Unit').project('name', 'Total Cost').
by('name').
by(values('total_direct_cost', 'total_attributed_cost').sum().map{ (it.get() as Double).round(0) })

ITCM - Attributed Cost of Organization Units

g.V().hasLabel('Organizational Unit').values('total_attributed_cost').sum()

5. Changes to Gremlin Graph Searches

To see what needs to be changed, please refer to the field table

New versions:

Total Attributed Cost

This contains the Gremlin Code that aggregates the underlying components' costs to calculate the target component's Total Attributed Cost. By checking the Cost Type Attribution field, the code only aggregates the cost types that are not selected. In addition, the code takes into account the specific weighting of the Cost Attribution Percentage.

def defaultFieldNames = ['total_attributed_cost', 'total_direct_cost']

def toAPIFieldName = {
if (it.get() == 'No Attributed Cost Flow') return 'total_attributed_cost';
if (it.get() == 'No Direct Cost Flow') return 'total_direct_cost';
return '';
}

def getCostTypeAttributionFieldNames = {
values('cost_type_attribution').
unfold().
map(toAPIFieldName).
fold().
map{
fieldNamesToExclude = it.get()
defaultFieldNames.findAll{ defaultFieldName ->
!fieldNamesToExclude.contains(defaultFieldName)
}
}
}

def hasCostTypeAttribution = {
getCostTypeAttributionFieldNames().unfold().count().is(gt(0))
}

g.V(ids).
project('id', 'name', 'value').
by(id).
by('name').
by(
coalesce(
outE().filter(__.not(hasLabel('ardoq_parent'))).filter(hasCostTypeAttribution()).as('reference').
filter(hasCostTypeAttribution()).
map(
map(getCostTypeAttributionFieldNames()).unfold().as('fieldName').
project('percentage', 'totalCost').
by(
select('reference').
choose(
has('cost_attribution_percentage'),
values('cost_attribution_percentage'),
inV().
inE().as('otherReference').
project('fieldNamesOnOtherReference', 'fieldName').
by(getCostTypeAttributionFieldNames()).
by(select('fieldName')).
filter{ it.get().fieldNamesOnOtherReference.contains(it.get().fieldName) }.select('otherReference').outV().
where(eq('reference')).
by(label).
by(outV().label()).
count().
map{ 100 / it.get() }
)
).
by(
select('reference').
project('fieldName', 'component').
by(select('fieldName')).
by(inV()).
map{ it.get().component.property(it.get().fieldName).orElse(0) }
).
math('percentage * totalCost / 100').
sum()
).
sum(),
constant(0)
)
)

Total Direct Cost

The Total Direct Cost Gremlin Code sums up the values of CAPEX and OPEX.

g.V(ids).
project('id', 'name', 'value').
by(id).
by('name').
by(project('capex','opex').
by(coalesce(values('capex'), constant(0))).
by(coalesce(values('opex'), constant(0))).
math('capex + opex'))

Total Cost

The Total Cost Gremlin Code sums up the value of Total Attributed Cost and Total Direct Cost of the current Component Type and all it’s children.

g.V(ids).
project('id', 'name', 'value').
by(id).
by('name').
by(emit().repeat(
__.in('ardoq_parent')).
values('total_direct_cost', 'total_attributed_cost').unfold().sum().map{ (it.get() as Double).round(0) })

Total Attribution Percentage

This Gremlin Code calculated the sum of a component's total Cost Attribution Percentages to other components. The cost allocation is divided into the target Component Type. For example, if an Application has specific weights on references to both Business and Technical Capabilities. Then the Gremlin Code will calculate the sum of Cost Attribution Percentages to Business and Technical Capabilities separately. A result could, for example, be “Technical Capability: 110%, Business Capability: 70%

g.V(ids).
project('id', 'name', 'value').
by(id).
by('name').
by(
inE().has('cost_attribution_percentage').
group().
by(otherV().label()).
by(values('cost_attribution_percentage').sum()).
map{ it.get().keySet().collect{ key -> "${key}: ${it.get().get(key)}%" }.join(', ') })

Cost Attribution Percent Data Quality

This code checks if the sum of the Cost Attribution Percentage from one given component to another Component Type exceeds 100%. If it does, the checkbox named Cost Attribution Percent Data Quality is set to ‘checked’.

g.V(ids).
project('id', 'name', 'value').
by(id).
by('name').
by(
inE().has('cost_attribution_percentage').
group().
by(otherV().label()).
by(values('cost_attribution_percentage').sum()).
map{ it.get().values().any{percentage -> percentage > 100} })

Total Budgeted Cost

Equivalent to Total Cost, just for budgets. X = budget capex+budget opex

g.V(ids).
project('id', 'name', 'value').
by(id).
by('name').
by(values('budget_capex', 'budget_opex').unfold().sum().map{ (it.get() as Double).round(0) })

Old versions:

Total Consumed Cost

This contains the Gremlin Code that aggregates the underlying components cost to the target component Total Consumed Cost. The code checks the field Cost Consumption, and only aggregates cost if it is checked. The code also takes into account the specific weighting in Cost Consumption Percentage.

g.V(ids).

project('id', 'name', 'value').

by(id).

by('name').

by(

coalesce(

emit().repeat(__.in('ardoq_parent')).

outE().has('cost_consumption', true).as('percentage').inV().as('totalCost').

math('percentage * totalCost / 100').

by(choose(

has('cost_consumption_percentage'),

values('cost_consumption_percentage'),

__.as('reference').inV().

inE().has('cost_consumption', true).outV().

where(eq('reference')).

by(label).

by(outV().label()).

count().

map{ 100 / it.get() }).math('floor _ ')).

by(values('total_attributed_cost', 'total_direct_cost').sum()).

sum(),

constant(0)

)

)

Total Cost:

The Total Cost Gremlin Code sums up the value of Total Consumed Cost and Total Direct Cost.

totaldirectcost = 'total_direct_cost'

totalconsumedcost = 'total_consumed_cost'

def calculateTotalCost(it) {

a=it.get().values(totaldirectcost)[0] as Double

b=it.get().values(totalconsumedcost)[0] as Double

return (a + b).round(2)

}

g.V(ids)

.and(

has(totaldirectcost),

has(totalconsumedcost))

.project('id', 'name', 'value').

by(id).

by('name').

by(map{calculateTotalCost(it)})

Total Consumption Percentage:

This Gremlin Code calculated the sum of a component's total Cost Consumption Percentages to other components. The cost allocation is divided into the target Component Type. For example if an Application has specific weights on references to both Business and Technical Capabilities. Then the Gremlin Code will calculate the sum of Cost Consumption Percentages to Business and Technical Capabilities separately. A result could, for example, be “Technical Capability: 110%, Business Capability: 70%”

g.V(ids).

project('id', 'name', 'value').

by(id).

by('name').

by(

inE().has('cost_consumption_percentage').

group().

by(otherV().label()).

by(values('cost_consumption_percentage').sum()).

map{ it.get().keySet().collect{ key -> "${key}: ${it.get().get(key)}%" }.join(', ') }

)

Cost Consumption Percent Data Quality:

The code checks if the sum of the Cost Consumption Percentage from one component to another component type exceeds 100%. The checkbox titled Cost Consumption Percent Data Quality is set to 'checked' when it does.

g.V(ids).

project('id', 'name', 'value').

by(id).

by('name').

by(

inE().has('cost_consumption_percentage').

group().

by(otherV().label()).

by(values('cost_consumption_percentage').sum()).

map{ it.get().values().any{percentage -> percentage > 100} }

)

6. Support

Whether you are a new or an experienced customer, our technical support team will be available to help you overcome any knowledge or technical hurdles throughout the migration process. In Ardoq, select 'Chat with us'.

Did this answer your question?