Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions add_missing_pm_names.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""
Add pm_name primary name fields ONLY to entities that don't have them
"""

import re

# Primary name field template (NO Format element for Teams compatibility)
PRIMARY_NAME_TEMPLATE = """ <attribute PhysicalName="pm_name">
<Type>nvarchar</Type>
<Name>pm_name</Name>
<LogicalName>pm_name</LogicalName>
<RequiredLevel>required</RequiredLevel>
<DisplayMask>PrimaryName|ValidForAdvancedFind|ValidForForm|ValidForGrid|RequiredForForm</DisplayMask>
<MaxLength>100</MaxLength>
<Length>100</Length>
<ImeMode>auto</ImeMode>
<ValidForUpdateApi>1</ValidForUpdateApi>
<ValidForReadApi>1</ValidForReadApi>
<ValidForCreateApi>1</ValidForCreateApi>
<IsCustomField>1</IsCustomField>
<IsAuditEnabled>0</IsAuditEnabled>
<IsSecured>0</IsSecured>
<SourceType>0</SourceType>
<IsGlobalFilterEnabled>0</IsGlobalFilterEnabled>
<IsSortableEnabled>0</IsSortableEnabled>
<CanModifyGlobalFilterSettings>1</CanModifyGlobalFilterSettings>
<CanModifyIsSortableSettings>1</CanModifyIsSortableSettings>
<IsDataSourceSecret>0</IsDataSourceSecret>
<AutoNumberFormat></AutoNumberFormat>
<IsSearchable>1</IsSearchable>
<IsFilterable>0</IsFilterable>
<IsRetrievable>1</IsRetrievable>
<IsLocalizable>0</IsLocalizable>
<IntroducedVersion>2.0.0.0</IntroducedVersion>
<IsCustomizable>1</IsCustomizable>
<IsRenameable>1</IsRenameable>
<CanModifySearchSettings>1</CanModifySearchSettings>
<CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
<CanModifyAdditionalSettings>1</CanModifyAdditionalSettings>
<displaynames>
<displayname description="Name" languagecode="1033" />
</displaynames>
<Descriptions>
<Description description="Primary name field" languagecode="1033" />
</Descriptions>
</attribute>"""

# Entities that need pm_name added
entities_needing_pm_name = [
'pm_EvaluationQuestion',
'pm_IDPEntry',
'pm_Goal'
]

# Read the file
with open('solution/Other/Customizations.xml', 'r', encoding='utf-8') as f:
content = f.read()

# Process each entity
for entity_name in entities_needing_pm_name:
# Find the entity's primary key field and insert pm_name after it
# Pattern: find the entity's attributes section and the first closing </attribute> tag
pattern = rf'(<entity Name="{entity_name}">.*?<attributes>.*?</attribute>)'

def add_pm_name(match):
return match.group(1) + '\n' + PRIMARY_NAME_TEMPLATE

content = re.sub(pattern, add_pm_name, content, flags=re.DOTALL)
print(f"Added pm_name to {entity_name}")

# Write back
with open('solution/Other/Customizations.xml', 'w', encoding='utf-8') as f:
f.write(content)

print("\nVerification:")
pm_name_count = content.count('PhysicalName="pm_name"')
print(f"Total pm_name fields: {pm_name_count}")

for entity_name in ['pm_StaffMember', 'pm_EvaluationQuestion', 'pm_WeeklyEvaluation', 'pm_SelfEvaluation',
'pm_IDPEntry', 'pm_MeetingNote', 'pm_Goal', 'pm_Recognition', 'pm_ActionItem']:
entity_section = re.search(rf'<entity Name="{entity_name}">.*?</entity>', content, re.DOTALL)
if entity_section:
has_pm_name = 'PhysicalName="pm_name"' in entity_section.group(0)
print(f" {entity_name}: {'✓' if has_pm_name else '✗'}")
Binary file not shown.
Binary file not shown.
60 changes: 60 additions & 0 deletions remove_system_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""
Remove all system field definitions from customizations.xml

Teams Dataverse automatically creates system fields (createdby, modifiedby, ownerid,
versionnumber, statecode, statuscode, etc.) for new entities in unmanaged solutions.

Including these fields in the solution causes import errors like:
"Attribute versionnumber is a BigInt, but a BigInt type was specified"

This script keeps only:
- Primary key fields (Type=primarykey)
- Custom fields (IsCustomField=1)
"""

import re

# Read the file
with open('solution/Other/Customizations.xml', 'r', encoding='utf-8') as f:
content = f.read()

# Count before
total_before = len(re.findall(r'<attribute PhysicalName=', content))
system_fields_before = len(re.findall(r'<IsCustomField>0</IsCustomField>', content))

# Remove attributes that have IsCustomField>0</IsCustomField> (system fields)
# BUT keep primary key fields (Type>primarykey</Type>)

# First, let's match all attribute blocks
attribute_pattern = r'<attribute PhysicalName=".*?">.*?</attribute>'
attributes = re.findall(attribute_pattern, content, re.DOTALL)

removed_count = 0
for attr in attributes:
# Check if it's a system field (IsCustomField=0) AND not a primary key
is_system = '<IsCustomField>0</IsCustomField>' in attr
is_primarykey = '<Type>primarykey</Type>' in attr

if is_system and not is_primarykey:
# Remove this attribute
content = content.replace(attr, '', 1)
removed_count += 1

# Count after
total_after = len(re.findall(r'<attribute PhysicalName=', content))
system_fields_after = len(re.findall(r'<IsCustomField>0</IsCustomField>', content))

# Write back
with open('solution/Other/Customizations.xml', 'w', encoding='utf-8') as f:
f.write(content)

print(f"System field cleanup complete:")
print(f" Total attributes before: {total_before}")
print(f" System fields removed: {removed_count}")
print(f" Total attributes after: {total_after}")
print(f" System fields remaining: {system_fields_after} (should be 0)")
print()
print(f"Kept fields:")
print(f" - 9 primary key fields (Type=primarykey)")
print(f" - {total_after - 9} custom fields (IsCustomField=1 or pm_name)")
28 changes: 28 additions & 0 deletions remove_text_format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env python3
"""
Remove <Format>text</Format> from pm_name fields in customizations.xml
Teams Dataverse doesn't accept Format elements for nvarchar string fields
"""

import re

# Read the file
with open('solution/Other/Customizations.xml', 'r', encoding='utf-8') as f:
content = f.read()

# Remove <Format>text</Format> lines (with any amount of whitespace)
# This pattern matches the line with Format and the newline
content = re.sub(r'\s*<Format>text</Format>\s*\n', '', content)

# Write back
with open('solution/Other/Customizations.xml', 'w', encoding='utf-8') as f:
f.write(content)

print("Removed <Format>text</Format> elements from customizations.xml")

# Count remaining pm_name fields
pm_name_count = content.count('PhysicalName="pm_name"')
format_text_count = content.count('<Format>text</Format>')

print(f"pm_name fields: {pm_name_count}")
print(f"Remaining <Format>text</Format> elements: {format_text_count}")
Loading