Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating a dimension "}ElementAttributes_example" switches an alias attribute into a text attribute #1202

Open
abetschenIBM opened this issue Nov 25, 2024 · 3 comments
Labels

Comments

@abetschenIBM
Copy link

Describe the bug
When updating a dimension (i.e. }ElementAttributes_example) using the code below, it converts an alias attribute into a text attribute wrecking havoc with websheets relying on these aliases.

To Reproduce
dimension_src = tm1_src.dimensions.get(dimension_name=sdim_name)
dimension_tgt = tm1_tgt.dimensions.get(dimension_name=sdim_name)
tm1_tgt.dimensions.update_or_create(dimension_src)

Expected behavior
I would expect that when updating a dimension, it would add the new attributes and keep the current attribute type as is.

Version
TM1py [2.0.4]
TM1 Server Version: [12.4.4]

Additional context
Add any other context about the problem here.

BR
Andre

@MariusWirtz
Copy link
Collaborator

Hi @abetschenIBM,

I recommend using the data frame functions like below instead.

With the attribute_suffix you can control if the attribute type is retrieved along with the attribute name. The update_or_create_hierarchy_from_dataframe will respect this accordingly. If no attribute type is provided, attributes are created as strings by default.

By default, existing attribute types are not changed. If you want TM1py to update existing attribute types, you must pass update_attribute_types=True. In this case, TM1py will delete attributes and recreate them with the new type when it detects attribute type changes.

from TM1py import TM1Service

v11_params = {...}

v12_params = {...}

with TM1Service(**v11_params) as tm1:
    df = tm1.elements.get_elements_dataframe(
        dimension_name="Global Account Reporting",
        hierarchy_name="Global Account Reporting",
        skip_consolidations=False,
        skip_parents=False,
        attribute_suffix=True,
        element_type_column="ElementType")

print(df.head(25).to_markdown())

with TM1Service(**v12_params) as tm1:
    tm1.hierarchies.update_or_create_hierarchy_from_dataframe(
        dimension_name="Global Account Reporting",
        hierarchy_name="Global Account Reporting",
        df=df)

@MariusWirtz MariusWirtz added question and removed bug labels Nov 26, 2024
@abetschenIBM
Copy link
Author

Hi Marius,

After a deeper look and analysis, I was able to reproduce the error and found other side effects. But 1st things 1st, here is what I did (hope this description will help other avoid similar issues; may be, it should have been clear to me, that what I did was not a good idea):

Case description: need to update the attribute of a dimension but not the content of the dimension (i.e. dimension content is different in Dev than in Test). Additionally a couple of the new attributes have specially configured to allow a date picker (https://community.ibm.com/community/user/businessanalytics/blogs/svetlana-pestsova/2022/06/10/tips-how-to-enable-the-calendar-picker-for-paw-cub) =>

  • "Start Date" attribute needs to be of typ: numeric (part of "}ElementAttributes_dim_name")
  • "Start Date" attribute needs a "Format" attribute that needs to be set to "c:mm/dd/yyyy"
  • "Format" is part of "}ElementAttributes}ElementAttributes_dim_name_"

So I performed the following to add the new attributes

sdim_name = "dim_name"
dimension_src = tm1_src.dimensions.get(dimension_name=sdim_name)
dimension_tgt = tm1_tgt.dimensions.get(dimension_name=sdim_name)
tm1_tgt.dimensions.update_or_create(dimension_src)

Since thee new attributes were the 1st one that needed the "Format" attribute, I performed the following, thinkin it would add the "Format" attribute

sdim_name = "_}ElementAttributes_dim_name_"
dimension_src = tm1_src.dimensions.get(dimension_name=sdim_name)
dimension_tgt = tm1_tgt.dimensions.get(dimension_name=sdim_name)
tm1_tgt.dimensions.update_or_create(dimension_src)

This last step, is the one that creates the issues. It did create the Format attribute but after that step the following changed:

  • in the dim "}ElementAttributes_dim_name" the aliases where converted to string
  • the cube "}ElementAttributes_dim_name" no longer behaves as an attribute cube
    • one can no longer enter numeric attributes on a C element
    • it aggregates these values at the C level
    • if you have any websheets in books that rely on aliases => book does not open in PAW and produces an error

Not sure if this is "normal behavior" after the tm1py scripts that I ran, but it certainly not what I expected. If it is not normal then I am not sure how to determine if the issue lies with TM1 REST API or tm1py. We are working on restoring the aliases and the cube "}ElementAttributes_dim_name".

If anyone has better deployment strategies and best practices or suggestions (PAasS on AWS / TM1v12), and is willing to share, that would be much appreciated.

@MariusWirtz We tried to use your suggestion but we encountered an error message. One of my colleague is looking into why.

@MariusWirtz
Copy link
Collaborator

I see.

Yes. }ElementAttribute_ dimension require special treatment in the REST API and TM1py. In TI you can treat them equal to normal dimensions, for the most part, but not so in the REST API and TM1py.

If you use the get / update_or_create approach that you described and combine it with synchronizing the attribute cube values you should be fine to sychronize dimensions with their attributes and attribute values.
But the attributes of attribute dimensions (}ElementAttributes_}ElementAttributes_) require special care.

To work with }ElementAttributes_}ElementAttributes_ dimensions maybe you can use the dedicated granular functions in tm1.elements.
Does this work?

from TM1py import TM1Service, ElementAttribute

tm1_params = {
    "address": "localhost",
    "port": 12354,
    "user": "admin",
    "password": "apple",
    "ssl": True
}
with TM1Service(**tm1_params) as tm1:
    tm1.elements.add_element_attributes(
        dimension_name="}ElementAttributes_Dimension",
        hierarchy_name="}ElementAttributes_Dimension",
        element_attributes=[
            ElementAttribute("New Alias Attribute", "Alias"),
            ElementAttribute("New Format Attribute", "String"),
            ElementAttribute("New Numeric Attribute", "Nummeric"),
        ]
    )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants