﻿<?xml version="1.0" encoding="utf-8"?>
<configset name="LegalFeeSchedule" author="AVE">
  <comment>2026-09-04, AVE: v1</comment>
  <requirements>
    <version-requirement>6.8.0.20</version-requirement>
  </requirements>
  <update />
  <references />
  <objects>
    <object class="StringProperty" alias="StringProperty_tarifrechnerplus_api_key">
      <member name="propertyGroup">2</member>
      <member name="selectionType">None</member>
      <member name="scope">Global</member>
      <member name="propertyName">tarifrechnerplus_api_key</member>
      <member name="propertyCaption">Tarifrechnerplus API key</member>
      <member name="masked">false</member>
    </object>
    <object class="CustomField" alias="ZusatzfeldKlasse0">
      <member name="entryID">CustomfieldAmountInDispute</member>
      <member name="classes">Project</member>
      <member name="fieldName">cf_amount_in_dispute</member>
      <member name="designation">
        <mltext language="NV">Amount in dispute</mltext>
      </member>
      <member name="fieldType">Currency</member>
      <member name="hidden">true</member>
      <member name="orderIdx">60</member>
      <member name="selectionType">None</member>
    </object>
    <object class="CustomField" alias="ZusatzfeldKlasse1">
      <member name="entryID">CustomfieldOpposingParties</member>
      <member name="expression">"-", "1", "2", "3", "4",  "5", "6", "7", "8", "9+"</member>
      <member name="classes">Project</member>
      <member name="fieldName">cf_opposing_parties</member>
      <member name="designation">
        <mltext language="NV">Opposing parties</mltext>
      </member>
      <member name="fieldType">Multistring</member>
      <member name="hidden">true</member>
      <member name="orderIdx">160</member>
      <member name="selectionType">None</member>
    </object>
    <object class="CustomField" alias="ZusatzfeldKlasse2">
      <member name="entryID">CustomfieldRepresentedParties</member>
      <member name="expression">"-", "1", "2", "3", "4",  "5", "6", "7", "8", "9+"</member>
      <member name="classes">Project</member>
      <member name="fieldName">cf_represented_parties</member>
      <member name="designation">
        <mltext language="NV">Represented parties</mltext>
      </member>
      <member name="fieldType">Multistring</member>
      <member name="hidden">true</member>
      <member name="orderIdx">150</member>
      <member name="selectionType">None</member>
    </object>
    <object class="ClassSettings" alias="ClassSettings_Mandat6">
      <member name="entryID">ClasssettingsCaseRATG</member>
      <member name="remarks">Used for ConfigSet LegalFeeScheduleAT.</member>
      <member name="customPages">&lt;Page
    Name="RATG"
    LabelWidth="150"
    Header="{Translate 'RATG-Information'}"
    PlaceAfter="Project" &gt;

    &lt;TextBox Name="AmountInDispute" Label="{Translate 'Amount in dispute'}" ShowLabel="True" 
    ValueExpression="customfieldcurr('cf_amount_in_dispute')" 
    WidthFraction="0.5" ContentAlignment="Right" /&gt;
    
    &lt;AdditionalFieldComboBox Name="RepresentedParties" Label="{Translate 'Represented parties'}" 
    ValueExpression="customfieldint('cf_represented_parties')" 
    WidthFraction="0.5" /&gt;
    &lt;AdditionalFieldComboBox Name="OpposingParties" Label="{Translate 'Opposing parties'}" 
    ValueExpression="customfieldint('cf_opposing_parties')" 
    WidthFraction="0.5" /&gt;
&lt;/Page&gt;</member>
      <member name="class">Project</member>
    </object>
    <object class="ClassSettings" alias="ClassSettings_OpenService15">
      <member name="entryID">ClasssettingsOpenService</member>
      <member name="remarks">Used for ConfigSet LegalFeeScheduleAT.</member>
      <member name="class">OpenService</member>
      <member name="gridDefs">
        <object class="GridDef" alias="GridDef0">
          <member name="rowHeight">17</member>
          <member name="ghostrow">true</member>
          <member name="editing">true</member>
          <member name="class">OpenService</member>
          <member name="gridcols">
            <object class="GridColDef" alias="GridColDef0">
              <member name="alignment">0</member>
              <member name="orderIdx">0</member>
              <member name="controlName">cmbProject</member>
              <member name="totals">false</member>
              <member name="expression">project</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">Project</mltext>
              </member>
              <member name="tabstop">true</member>
              <member name="width">153</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef1">
              <member name="alignment">0</member>
              <member name="orderIdx">1</member>
              <member name="controlName">cmbPhase</member>
              <member name="totals">false</member>
              <member name="expression">phase</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">Phase</mltext>
              </member>
              <member name="tabstop">true</member>
              <member name="width">0</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef2">
              <member name="alignment">1</member>
              <member name="orderIdx">10</member>
              <member name="totals">true</member>
              <member name="expression">xfeeExt</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">External fees</mltext>
              </member>
              <member name="tabstop">true</member>
              <member name="width">80</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef3">
              <member name="alignment">0</member>
              <member name="orderIdx">2</member>
              <member name="totals">false</member>
              <member name="expression">entryDate</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">Date</mltext>
              </member>
              <member name="tabstop">false</member>
              <member name="width">70</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef4">
              <member name="alignment">0</member>
              <member name="orderIdx">3</member>
              <member name="controlName">cmbExpenditureUser</member>
              <member name="totals">false</member>
              <member name="expression">user</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">User</mltext>
              </member>
              <member name="tabstop">false</member>
              <member name="width">70</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef5">
              <member name="alignment">0</member>
              <member name="orderIdx">4</member>
              <member name="controlName">cmbServicetype</member>
              <member name="totals">false</member>
              <member name="expression">type</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">Service type</mltext>
              </member>
              <member name="tabstop">true</member>
              <member name="width">60</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef6">
              <member name="alignment">0</member>
              <member name="orderIdx">5</member>
              <member name="totals">false</member>
              <member name="expression">text</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">Text</mltext>
              </member>
              <member name="tabstop">true</member>
              <member name="width">180</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">true</member>
              <member name="spellCheckLanguageExpression">project.language</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef7">
              <member name="alignment">1</member>
              <member name="orderIdx">6</member>
              <member name="rendererName">rndMinute</member>
              <member name="totals">true</member>
              <member name="expression">minutesInt</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">Effort</mltext>
              </member>
              <member name="tabstop">true</member>
              <member name="width">64</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef8">
              <member name="alignment">1</member>
              <member name="orderIdx">7</member>
              <member name="rendererName">rndFeeRate</member>
              <member name="totals">false</member>
              <member name="expression">feeRateInt</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">Rate</mltext>
              </member>
              <member name="tabstop">false</member>
              <member name="width">64</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef9">
              <member name="alignment">1</member>
              <member name="orderIdx">8</member>
              <member name="rendererName">rndCostItemFee</member>
              <member name="totals">true</member>
              <member name="expression">feeInt</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="title">
                <mltext language="NV">Fee</mltext>
              </member>
              <member name="tabstop">false</member>
              <member name="width">64</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
            <object class="GridColDef" alias="GridColDef10">
              <member name="alignment">0</member>
              <member name="orderIdx">9</member>
              <member name="rendererName">renderer_legal_fee_schedule.ShowRatgButton</member>
              <member name="totals">false</member>
              <member name="readOnly">false</member>
              <member name="sortOrder">0</member>
              <member name="tabstop">true</member>
              <member name="width">22</member>
              <member name="isFixed">false</member>
              <member name="isDynamic">false</member>
              <member name="enableSpellCheck">false</member>
              <member name="griddef">
                <reference-object alias="GridDef0" />
              </member>
            </object>
          </member>
          <member name="classSettings">
            <reference-object alias="ClassSettings_OpenService15" />
          </member>
        </object>
      </member>
    </object>
    <object class="ClassSettings" alias="ClassSettings_Leistung1">
      <member name="entryID">ClasssettingsService</member>
      <member name="remarks">Used for ConfigSet LegalFeeScheduleAT.</member>
      <member name="customPages">&lt;!-- =============== Service: ServiceFurtherInfoPage =============== --&gt;
&lt;Page
    Override="ServiceFurtherInfo" &gt;
    &lt;TextBlock Name="RATG" Label="RATG" 
    ShowLabel="True"
    ValueExpression="keystring('ratg')" 
    VisibleExpression="keystring('ratg').length&gt;0" 
    Renderer= "renderer_legal_fee_schedule.RatgKeyOnPage"
    FitMode="Wrap" /&gt;
&lt;/Page&gt;</member>
      <member name="class">Service</member>
    </object>
    <object class="ClassSettings" alias="ClassSettings_Tätigkeit2">
      <member name="entryID">ClasssettingsServiceType</member>
      <member name="remarks">Used for ConfigSet LegalFeeScheduleAT.</member>
      <member name="customPages">&lt;!-- =============== Service: ServiceFurtherInfoPage =============== --&gt;
&lt;Page
    Override="FurtherInfo" &gt;
    &lt;TextBlock Name="RATG" Label="{Translate 'RATG setting'}" 
    ShowLabel="True"
    ValueExpression="keystring('ratg')" 
    VisibleExpression="keystring('ratg').length&gt;0" 
    Renderer= "renderer_legal_fee_schedule.RatgKeyOnPage"
    FitMode="Wrap" /&gt;
&lt;/Page&gt;</member>
      <member name="class">Servicetype</member>
    </object>
    <object class="Script" alias="Script_RATGTarifzuweisen12">
      <member name="entryID">ScriptAssignRatgFee</member>
      <member name="designation">RATG Assign fee</member>
      <member name="classes">OpenService,Servicetype</member>
      <member name="containerScript">false</member>
      <member name="condExpression">self-&gt;size=1</member>
      <member name="scriptText"># coding: windows-1252
#
# Designation: RATG Assign fee
# Show in Vertec menus: True
# Classes: OpenService, Servicetype
# Display condition: self-&gt;size=1
# Event script for: None
# Event classes: -
# Event fields: -
# Extended rights: True

# Calculates the RATG fee based on a service
# and assigns the value and the RATG parameter

# 2026-03-17 AVE: Script created 

from module_legal_fee_schedule import tarif_request

tarif_request(ratg_object = argobject)
 
</member>
      <member name="eventType">None</member>
      <member name="objectScript">false</member>
      <member name="extendedRights">true</member>
      <member name="selectedObjectsScript">true</member>
      <member name="platform">Python3</member>
    </object>
    <object class="Script" alias="Script_EventRATGparameterchanged14">
      <member name="entryID">ScriptEventRatgParameterChanged</member>
      <member name="designation">RATG Recalculate fee</member>
      <member name="classes">OpenService</member>
      <member name="containerScript">false</member>
      <member name="scriptText"># coding: windows-1252
#
# Designation: Recalculate services with RATG fee
# Show in Vertec menus:True
# Classes: OpenService
# Display condition: -
# Event script for: None
# Event classes: -
# Event fields: -
# Extended rights: False
#
# If RATG parameters on case has changed,
# the services with RATG can be recalculated
#
# 2026-08-17, AVE: Script created

from module_legal_fee_schedule import recalculate_ratg_fee_on_service, check_ratg_requirements

def main(selectedobjects):
    # recalulate services
    fees_old = 0.00
    fees_new = 0.00
    
    # Assign currency from frist open service, as in the current 
    # implementation of RATG we only accept one currency (Euro)
    currency = str(selectedobjects[0].project.currency)
    
    for service in selectedobjects:
        # We only process services with RATG parameters
        if not service.getkeystring('ratg'):
            continue
            
        # If one of the cases/projects of the selected open services does not
        # the requirements met, we stop the whole script as a long list of 
        # open services on different cases/projects were selected.
        if not check_ratg_requirements(service.project):
            return
            
        # RATG requirments ok, continue
        fees_old += service.xfeeext
        recalculate_ratg_fee_on_service(service)
        fees_new += service.xfeeext

    dlg_definition="""
    &lt;Dialog Title="{Translate 'RATG recalculation'}" Width="250" &gt;
        &lt;TextBlock Name="fees_old" Label="{Translate 'Total of old rates'}" ShowLabel="True"
         ContentAlignment="Right" /&gt;
        &lt;TextBlock Name="fees_new" Label="{Translate 'Total of new rates'}" ShowLabel="True"
         ContentAlignment="Right" /&gt;
        &lt;Dialog.Buttons&gt;
            &lt;Button Text="OK" IsAccept="True" Command="{Binding OkCommand}" /&gt;
        &lt;/Dialog.Buttons&gt;
    &lt;/Dialog&gt;
    """
    init_values = {}
    init_values["fees_old"] = "{} {}".format(vtcapp.formatnumber(fees_old), currency)
    init_values["fees_new"] = "{} {}".format(vtcapp.formatnumber(fees_new), currency)
    
    ok, values = vtcapp.showcustomdialog(dlg_definition, init_values)
    return


if selectedobjects and vtcapp.evalocl("TimSession.allInstances-&gt;first.hasGui"):
    main(selectedobjects)
 </member>
      <member name="eventType">None</member>
      <member name="objectScript">false</member>
      <member name="extendedRights">false</member>
      <member name="selectedObjectsScript">true</member>
      <member name="platform">Python3</member>
    </object>
    <object class="Script" alias="Script_EventServiceTypechanged13">
      <member name="entryID">ScriptEventServicetypeChanged</member>
      <member name="designation">Event ServiceType changed</member>
      <member name="eventMembers">type</member>
      <member name="eventClass">Service</member>
      <member name="containerScript">false</member>
      <member name="scriptText"># coding: windows-1252
#
# Designation: Event ServiceType changed
# Show in Vertec menus:False
# Classes: -
# Display condition: -
# Event script for: Changed
# Event classes: Service
# Event fields: type
# Extended rights: True

# Handles the calculation for RATG

# 2026-08-17, AVE: Script created

# we only catch here when the service type has changed
# we also check argobject for the case it was deleted

import json
from module_legal_fee_schedule import get_tariff, recalculate_ratg_fee_on_service, check_ratg_requirements

service = argobject

if service.type and args.eventmember == "type":

    # Service type has changed. Check if there are RATG-parameters on type
    # and requirements for RATG are met?
    if service.type.getkeystring('ratg') != "" :
        if check_ratg_requirements(service.project):
            # There are ratg parameters defined on the 
            # service type, take it over for the service
            service.setkeyvalue('ratg', service.type.getkeystring('ratg'))
        else:
            # RATG requirements not fullfilled. We remove the servicetype from the service
            service.type = None
         
    else:
        # No service type with RATG: remove key
        service.setkeyvalue('ratg', None)
       
    if service.getkeystring('ratg') == "":
        # Nothing to do, no ratg parameters. But reset fixed priceflag (can be set before by RATG)
        service.fixedprice = False
    else: 
        # There are RATG-Parameters. Calculate the fees
        # Dict wit the parameters is stored as string in key, so we need to convert to python dict
        tp_parameters = json.loads(service.getkeystring('ratg'))
        
        # update parameters with such from case
        tp_parameters['Streitwert'] = service.project.cf_amount_in_dispute
        tp_parameters['VertretenePersonen'] = service.project.cf_represented_parties
        tp_parameters['Gegner'] = service.project.cf_opposing_parties
        tp_parameters['serviceDate'] = service.entrydate.strftime("%Y-%m-%d")

        # Calculate the RATG fees
        result, err = get_tariff("RATG", tp_parameters)
        if err:
           # Append error text on the beginning of existing text
           service.text = "{}{}{}".format(err['error']['message'], "\n" if service.text else "", service.text)
        else:
            # Save changed parameters as key
            service.setkeyvalue("ratg", json.dumps(tp_parameters))
            # Save new parameters
            recalculate_ratg_fee_on_service(service)
 </member>
      <member name="eventType">Changed</member>
      <member name="objectScript">false</member>
      <member name="extendedRights">true</member>
      <member name="selectedObjectsScript">false</member>
      <member name="platform">Python3</member>
    </object>
    <object class="Script" alias="Script_module_RATG0">
      <member name="entryID">ScriptModuleLegalfeeschedule</member>
      <member name="designation">module_legal_fee_schedule</member>
      <member name="containerScript">false</member>
      <member name="scriptText"># Designation: module_LegalFeeSchedule
# Show in Vertec menus: Y
# Classes: Services, serviceType
# Display condition: -
# Event script for: -
# Event classes: -
# Event fields: -
# Extended rights: -
  
# Gets RATG/GGG fees
# using the API from tarifrechnerplus.de

# 2026-08-17, AVE: Script created 


from module_tarifrechnerplus_api import TarifrechnerplusClient, get_input_types_static, get_form_schema, get_tariff
from datetime import datetime
import json

# ------------------------------------------------------------------
# Following methods are used to generate the form (python dialog)
# for the selected "tarifposten"
#
# Dialog XML builder
# ------------------------------------------------------------------
def build_dialog_xml(law, tp_id, date):
    """
    Generate Vertec custom dialog XML from visible field definitions and
    the corresponding init_values

    Field type mapping:
        'select' -&gt; IndexComboBox  (options rendered as 0-based ComboBoxItems)
        'number' -&gt; TextBox        (right-aligned, half-width)
        'checkbox' -&gt; CheckBox
        'date' -&gt; DatePicker
        'hidden' -&gt; TextBox        (not visible, no help, label not visible)
    """
    form_schema, err = get_form_schema(law, tp_id, date)

    if err:
        raise Exception(err)
 
    fields = form_schema.get('fields') 
    input_type = form_schema.get('inputType') 
    summary = input_type.get('reference')
    
    # Selection-Fields contain text as selections but return an index value in dialog.
    # We need therefore to store the texts as reference to hand over them to the API as parameter
    select_options = {}
    
    # Parts contains the xml(-parts) for the dialogue
    parts = []

    if summary:
        parts.append('&lt;TextBlock HorizontalAlignment="Left" Text="{}" Appearance="Info" FitMode="Wrap" Width="550" /&gt;'.format(_xmlchar(summary)))
        
    for field in fields:
        fid = field['id'] 

        label = _xmlchar(field.get('label', fid))
        ftype = field.get('type', 'text')
        ref = field.get('legalReference', '')
        help_attr = 'Help="{}"'.format(_xmlchar(ref)) if ref else ''
        required = field.get('requirement').lower() == "required"
        label_star = ('* ' + label) if required else label    

        if ftype == 'select':
            options = field.get('options') or []
            select_options[fid] = options
            parts.append('&lt;IndexComboBox Name="{}" Label="{}"  {}&gt;'
                         .format(fid, label_star, help_attr))
            parts.append('   &lt;IndexComboBox.ListItems&gt;')
            for idx, opt in enumerate(options):
                opt_text = _xmlchar(opt.get('label', ''))
                parts.append('     &lt;ComboBoxItem Value="{}" Text="{}"/&gt;'
                             .format(idx, opt_text))
            parts.append('    &lt;/IndexComboBox.ListItems&gt;')
            parts.append('&lt;/IndexComboBox&gt;')
        elif ftype == 'number':
            parts.append(
                ' &lt;TextBox Name="{}" Label="{}" ContentAlignment="Right"'
                '  WidthFraction="0.5" {}/&gt;'.format(fid, label_star, help_attr)
            )
        elif ftype == 'textarea':
            parts.append(
                ' &lt;TextArea Name="{}" Label="{}" '
                '  WidthFraction="1" Lines="1" {} MaxLength="65"/&gt;'.format(fid, label_star, help_attr)
            )     
        elif ftype == 'checkbox':
            parts.append('&lt;CheckBox Name="{}" Label="{}" ShowLabel="True" {}/&gt;'
                          .format(fid, label_star, help_attr)
            )
        elif ftype == 'date':
            parts.append('&lt;DatePicker Name="{}" Text="{}" ShowLabel="False" {}/&gt;'
                         .format(fid, label_star, help_attr)
            )   
        elif ftype == 'hidden':
            parts.append('&lt;TextBox Name="{}" Label="{}" ShowLabel="False" IsVisible="False" /&gt;'
                         .format(fid, label_star)
            )
        elif ftype == 'number_list':
            options = field.get('options') or []
            parts.append('&lt;IndexComboBox Name="{}" Label="{}" WidthFraction="0.8" {}&gt;'
                         .format(fid, label_star, help_attr))
            parts.append('   &lt;IndexComboBox.ListItems&gt;')
            for idx, opt in enumerate(options):
                opt_text = _xmlchar(opt.get('label', ''))
                parts.append('      &lt;ComboBoxItem Value="{}" Text="{}" /&gt;'
                             .format(idx, opt_text))
            parts.append('   &lt;/IndexComboBox.ListItems&gt;')
            parts.append('&lt;/IndexComboBox&gt;')
        else:
            vtcapp.msgbox("Invalid field definition: {}".format(ftype))
            
    # Add information about the meaning of the * in labels
    parts.append('&lt;Spacer Height="10" /&gt;'
                 '&lt;TextBlock Name="pflichtfeldinfo" ShowLabel="False" Text="{Translate \'* are mandatory fields\'}" /&gt;')           
    # Return xml for dialog and the corresponding init_values
    return '\n'.join(parts), build_init_values(fields, input_type), select_options

# --------------
# Initial values
# --------------
def build_init_values(fields, input_type):
    """
    Build the init_values dict for showcustomdialog.

    select  -&gt; integer index matching the default option (0 if none)
    number  -&gt; string representation of defaultValue, or ''
    checkbox -&gt; bool
    date -&gt; date (converted from date string)
    hidden  -&gt; string representation of defaultValue, or ''
    """
    init = {}
    for field in fields:
        fid = field['id']
        ftype = field.get('type', 'text')
        default = field.get('defaultValue')

        if ftype == 'select':
            options = field.get('options') or []
            init[fid] = _option_default_index(options, default)

        elif ftype == 'number':
            init[fid] = '' if default is None else str(default)

        elif ftype == 'checkbox':
            init[fid] = bool(default) if default is not None else False
        
        elif ftype == 'date':
            init[fid] = '' if default is None else datetime.strptime(default, "%Y-%m-%d")
            
        elif ftype == 'textarea':
            init[fid] = '' if default is None else str(default)
            
        elif ftype == 'hidden':
            init[fid] = '' if default is None else str(default)

        elif ftype == 'number_list':
            options = field.get('options') or []
            init[fid] = _option_default_index(options, default)
    return init


# ----------
# XML helper
# ----------
def _xmlchar(text):
    """
    Escape text for use inside an XML attribute value (double-quoted).
    """
    return (str(text or '')
            .replace('&amp;', '&amp;amp;')
            .replace('&lt;', '&amp;lt;')
            .replace('&gt;', '&amp;gt;')
            .replace('"', '&amp;quot;'))


def _option_default_index(options, default_value):
    """ 
    Return 0-based index of the option whose 'value' matches default_value.
    """
    for i, opt in enumerate(options):
        if opt.get('value') == default_value:
            return i
    return 0


# -------------
# Tarif dialogs
# -------------
def tarif_request(case = None, law = 'RATG', ratg_object = None):
    """
    Dialogs to select and calculate the needed fee (tariff) position.
    case is optional; if provided its case data (dispute amount, parties) prefill the dialog.
    law is optional ('RATG' or 'GGG'). If not provided, RATG is used.
    ratg_object is optional; if it is an open service, its entrydate and project are used
    as date/case. If not provided, today's date is used.
    """
    if is_openservice(ratg_object):
        # Is an open service as of this date
        date = ratg_object.entrydate
        # Assign project/case from the open service 
        case = ratg_object.project
    else:
        date = vtcapp.currentdate()
    
    # Check if requirmentes to calculate RATG-tarif are met
    if not check_ratg_requirements(case):
        return 
        
    # input_types is a dict with an 'inputTypes' list (each item a dict) plus 'law' metadata
    input_types, err = get_input_types_static(law, date)
    if err:
        vtcapp.msgbox(vtcapp.translate("The following error occurred during data transmission:")
                      + "\nError: {}"
                      .format(err['error']['message']), 16)
        return
    
    # Dialog definitions
    # Top part of fee schedule dialog
    dlg_header = """
    &lt;Dialog Title="{}" Width="650"&gt;
    
        &lt;Group Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Stretch" &gt; 
            &lt;Group Orientation="Vertical" FlexWidth="6" LabelWidth="120"&gt; 
                &lt;TextBlock Name="title" Label="{{Translate 'Project'}}" 
                 ContentAlignment="Right" ShowLabel="True" IsBold="True" LabelWidth="80"/&gt;
                &lt;TextBlock Name="AmountInDisputeOnCase" Label="{{Translate 'Amount in dispute'}}" 
                  ContentAlignment="Right"  ShowLabel="True" IsBold="True" /&gt;
                &lt;TextBlock Name="RepresentedParties" Label="{{Translate 'Represented parties'}}" 
                 ShowLabel="True" IsBold="True" ContentAlignment="Right"/&gt;
                &lt;TextBlock Name="OpposingParties" Label="{{Translate 'Opposing parties'}}"  
                 ShowLabel="True" IsBold="True" ContentAlignment="Right"/&gt;
             &lt;/Group&gt;
             &lt;Spacer /&gt;
             &lt;Group Orientation="Vertical" FlexWidth="8" LabelWidth="60"&gt; 
                &lt;TextBlock Name="serviceDate" Label="{{Translate 'Date'}}" 
                 ShowLabel="True" /&gt;
                 &lt;TextBlock Name="quelle" Label="{{Translate 'Source'}}"  
                  ShowLabel="True" FitMode="Wrap" /&gt;
             &lt;/Group&gt;     
        &lt;/Group&gt; 
        
        &lt;ScrollableGroup Orientation="Vertical" HorizontalAlignment="Left" 
         LabelWidth="150" ShowVerticalScrollbar="True"
         Separator="Always" Width="600" MaxGroupHeight="600"&gt;
            &lt;TextBlock Name="selected_tp" ShowLabel="False" FitMode="Wrap" 
             LabelWidth="100" ContentAlignment="Left" IsBold="True" Appearance="Info"/&gt;
            &lt;TextBlock Name="inputTypeId" Visible="False" /&gt;
            &lt;Spacer Height="2"/&gt;
    """.format(law)
    
    # Lower part of fee dialog
    dlg_footer = """
        &lt;/ScrollableGroup&gt;
        &lt;Dialog.Buttons&gt;
            &lt;Button Name="back" Text="{Translate 'Back'}" 
            Command="{Binding CloseCommand}" /&gt;
            &lt;Button Name="next" 
            Command="{Binding CloseCommand}" IsAccept="True" /&gt;
        &lt;/Dialog.Buttons&gt;
    &lt;/Dialog&gt;
    """

    dlg_tarifposten_liste = """
        &lt;ListBox Name="tarifposten_liste"  Lines="20" /&gt;
    """

    # Initialize the init values
    tarifposten_liste = []
    for tp in input_types['inputTypes']:
        tarifposten_liste.append(tp['label'])
    
    init_values = {}
    init_values['title.Text'] = case.code if case else ""
    init_values['AmountInDisputeOnCase'] = vtcapp.formatnumber(case.cf_amount_in_dispute) if case else "0"
    init_values['RepresentedParties'] = str(case.cf_represented_parties) if case else "0"
    init_values['OpposingParties'] = str(case.cf_opposing_parties) if case else "0"
    init_values['quelle'] = "{} (Version: {})".format(input_types['law']['sourceLabel'],input_types['law']['version'])
    
    if is_servicetype(ratg_object):
        # If we just assign a RATG fee (tariff) to a servicetype, 'Streitwert'
        # and 'VertretenePersonen', 'Gegenpartei' are not needed as the will 
        # taken into account when a open service is created (as they are defined on project/case). Therefore: hide on service type
        init_values['title.Visible'] = False
        init_values['AmountInDisputeOnCase.Visible'] = False
        init_values['RepresentedParties.Visible'] = False
        init_values['OpposingParties.Visible'] = False
        # For the dummy calculation of the RATG fee on service type, we need default values 
        # that will be overwritten, when service type is assigned to the open service
        init_values['AmountInDisputeOnCase'] = "0.0"
        init_values['RepresentedParties'] = "1"
        init_values['OpposingParties'] = "1"
       
    # Dialog_nr is used to control, which dialog should be displayed. Used to navigate with forward/backward
    dialog_nr = 1
    selected_tp_from_list = 0
    tp_id = None 
   
    # Definitions done, here we start!
    # Outer while embedding the dialogs 
    while dialog_nr &gt; 0 :  
    
        if dialog_nr == 1:
            # Show first dialog till user selected a 'tarifposten' or pressed [cancel]
            init_values['back.Visible'] = False
            init_values['selected_tp'] = vtcapp.translate("Tariff positions")
            init_values['serviceDate'] = vtcapp.datetostr(date)
            init_values['next.Text'] =vtcapp.translate("Next") 
            init_values['tarifposten_liste'] = selected_tp_from_list
            init_values['tarifposten_liste.Items'] = tarifposten_liste
            # Dialog to select the needed 'Tarifposten'
            dlg_tarifposten = dlg_header + dlg_tarifposten_liste + dlg_footer 
            ok, values = vtcapp.showcustomdialog(dlg_tarifposten, init_values)
            if not ok:
                return

            # Store the value if we have to come back    
            selected_tp_from_list = values['tarifposten_liste'] 
            
            # Get the technical id that is needed to get the details for the form 
            # and to show in the following dialog
            tp_id = input_types['inputTypes'][values['tarifposten_liste']]['id']
            dialog_nr = 2

        elif dialog_nr == 2:
            # Detail dialog to enter the parameters for the selected tp
            # Get the Form (XML-Code) for the selected tp_id
            dlg_form, form_init_values, select_options = build_dialog_xml(law, tp_id, date)
            if values['back']:
                # Dialog is called again (with "back button"), so use the saved values
                init_values = dlg2_init_values
            else:
                # Is new dialog, add/overwrite 'Streitwert'
                # to the init_values of the form
                # we want to use our own init_value['Streitwert']
                form_init_values['Streitwert'] = init_values['AmountInDisputeOnCase']
                form_init_values['VertretenePersonen'] = init_values['RepresentedParties']
                form_init_values['Gegner'] = init_values['OpposingParties']
                init_values.update(form_init_values)
                
                if is_servicetype(ratg_object):
                    # If a the dialog is called on a service type, we do not show this fields
                    init_values['Streitwert.Visible'] = False
                    init_values['VertretenePersonen.Visible'] = False
                    init_values['Gegner.Visible'] = False
      
            init_values['back.Visible'] = True
            init_values['selected_tp'] = tp_id
            init_values['next.Text'] =vtcapp.translate("Next")
            # Just store the 'Tarifposten id' to use it later (hidden field)
            init_values['inputTypeId'] = tp_id

            dlg_tp_details =  dlg_header + dlg_form + dlg_footer 
            ok, values = vtcapp.showcustomdialog(dlg_tp_details, init_values)
            if not ok:
                return
                
            dlg2_init_values = {}
            # Store Init_values in case the dialog will be called again
            # using the [back] button
            for key in list(values.keys()):
                dlg2_init_values[key] = values[key]

            # Go to next or previous menu
            if values['next']:
                dialog_nr = 3 
            else:
                dialog_nr = 1   
            
        elif dialog_nr == 3:
            # Prepare values for fee calculation
            # We just have to send the values from the form (and inputTypeId, service date)
            tp_parameters = {}
            # Selected Tarifposten
            tp_parameters['inputTypeId'] = tp_id
            # Convert the string-date that is returned with the system specific format,
            # that convert it back to YYYY-mm-dd
            sd = vtcapp.strtodate(values['serviceDate'])
            tp_parameters['serviceDate'] = "{}-{:02d}-{:02d}".format(sd.year, sd.month, sd.day)
            
            for key in list(form_init_values.keys()):
                # Is this a value from a selection field?
                if key in select_options:
                    # get the text from the selection by the index value
                    tp_parameters[key] = select_options[key][values[key]]['label']
                else:
                    # get value but only if key in values exists
                    if key in values:
                        # Take over the value as they are
                         tp_parameters[key] = values[key]
                
            # Get the fee from the entered parameters
            result, err = get_tariff(law, tp_parameters)

            # For a servicetype we do not have to calculate the fee value.
            # We just need the parameters. Therefore we end the dialog here
            # if there is no error (dialog_nr not longer needed, therefore not
            # set here.)
            if is_servicetype(ratg_object) and not err:
                set_ratg_values_on_ratg_object(ratg_object, tp_parameters)
                return

            dlg_result = ""
            
            if err:
                # There is an error 
                dlg_result += """
                &lt;Table Width="550" ShowHeader="False" FillLastColumn="True" &gt;
                    &lt;Table.Columns&gt; &lt;TableColumn /&gt;&lt;/Table.Columns&gt;
                    &lt;TableRow&gt;
                        &lt;TableCell&gt;
                            &lt;TextBlock Name="errortext" Label="{{Translate 'Error'}}" 
                             LabelWidth="80" HorizontalAlignment="Left" ShowLabel="True" 
                             IsBold="True" Appearance="Error" FitMode="Wrap" Text="{}"/&gt;
                        &lt;/TableCell&gt;
                    &lt;/TableRow&gt;
                 &lt;/Table&gt;
                    """.format((err['error']['message']).replace('"', "'"))
                
                # Hide ok Button
                init_values['next.Visible'] = False
            else:
                # Result dialog part
                dlg_result =""" &lt;Group Orientation="Vertical" HorizontalAlignment="Left" &gt; """
                for breakdown in result['breakdown']:
                    dlg_result += """
                    &lt;TextBlock Name="{}" Label="{}" LabelWidth="150" ShowLabel="True" Text="{}" 
                     ContentAlignment="Right" /&gt;
                    """.format(breakdown['key'], breakdown['label'], 
                               vtcapp.formatnumber(float(breakdown['value'])))
    
                # Add total incl. currency
                dlg_result += """
                    &lt;Group Separator="Always" LabelWidth="150" &gt;
                        &lt;TextBlock Name="total" Label="{{Translate 'Total'}}" 
                         ShowLabel="True" Text="{} {}" IsBold="True" 
                         ContentAlignment="Right" /&gt;
                    &lt;/Group&gt;
                  &lt;/Group&gt;
                  """.format(result["amountText"][-3:], vtcapp.formatnumber(result['total']))
    
            # Show back button          
            init_values['back.Visible'] = True
            # This is the last dialog, so there is no "next", just "OK"
            init_values['next.Text'] = "OK"
            ok, values = vtcapp.showcustomdialog((dlg_header + dlg_result + dlg_footer), init_values)
            if not ok:
                return
            
            # End or go to previous menu
            if values['back']:
                dialog_nr = 2
            else:
                dialog_nr = 0
                # If an RATG object was used, then assign the parameters and fee
                if is_openservice(ratg_object):
                    set_ratg_values_on_ratg_object(ratg_object, tp_parameters, result['total'])
                    
    # End While dialog for dialogs  
    return
    
    
def is_servicetype(ratg_object):
    """
    Is object not None and ocl type of "Servicetype"?
    """
    return (ratg_object and ratg_object.evalocl("oclIsTypeOf(Servicetype)"))
    
    
def is_openservice(ratg_object):
    """
    Is object not None and ocl type of "Open service"?
    """
    return (ratg_object and ratg_object.evalocl("oclIsTypeOf(OpenService)"))
    
    
def set_ratg_values_on_ratg_object(ratg_object, tp_parameters, total="0.0"):
    """
    Calculates the RATG fee (tariff) based on the parameters
    and sets the corresponding values on service
    total is only used on openservice
    """
    
    if is_openservice(ratg_object):
        # Set values on service, we do not want to trigger the event
        # as this function is also used in an event script!
        ratg_object.fixedprice = True
        ratg_object.extfixed = True
        ratg_object.isunitservice = True
        ratg_object.quantity = 1
        ratg_object.feerateext = float(total)
        # Store parameters under the 'ratg' key
        ratg_object.setkeyvalue('ratg', json.dumps(tp_parameters))
        
    elif is_servicetype(ratg_object):
         # Streitwert, represented and counter parties we do not store on
         # servicetype as these come from the case/project
         tp_parameters.pop('Streitwert', None)
         tp_parameters.pop('VertretenePersonen', None)
         tp_parameters.pop('Gegner', None)

         ratg_object.code = tp_parameters['inputTypeId']
         # Append RATG-Tariff in front of existing text
         ratg_object.text =  "(RATG: {}){}{}".format(tp_parameters['inputTypeId'],
                              "\n" if ratg_object.text else "", ratg_object.text)
         # Store parameters under the 'ratg' key
         ratg_object.setkeyvalue('ratg', json.dumps(tp_parameters))
    return


def recalculate_ratg_fee_on_service(open_service):
    """
    Recalculates the RATG fee (tariff) for an open service
    Ex. needed if 'Streitwert' has changed
    """
    # Does the service have RATG parameters?
    if len(open_service.getkeystring("ratg"))&gt;0:
        try:
            tp_parameters = json.loads(open_service.getkeystring("ratg"))
        except Exception:
            vtcapp.msgbox("Invalid RATG definition on service {}".format(open_service))
            return
        # Take over the parameters that are defined on the case / project
        tp_parameters['Streitwert'] = open_service.project.cf_amount_in_dispute
        tp_parameters['VertretenePersonen'] = open_service.project.cf_represented_parties
        tp_parameters['Gegner'] = open_service.project.cf_opposing_parties
        tp_parameters['serviceDate'] = open_service.entrydate.strftime("%Y-%m-%d")
        result, err = get_tariff("RATG", tp_parameters)
        if err:
            raise Exception(err)
        try:
            total = result['total']
        except Exception:
            total = "0.0"
        set_ratg_values_on_ratg_object(open_service, tp_parameters, total)
        return
    
    
def check_ratg_requirements(case):
    """
    Checks if the requirements for a RATG calculation are given
    Result is also true if case is None, as this fuction is also 
    called for service types where no case/project is assigned
    """
    error_list = []
    if not case:
        # If no mandate is provided we assign RATG parameters on a 
        # service type, so the requirments are always ok
        return True
        
    # RATG requires EUR as currency
    if (case.currency.designation != "EUR") :
        error_list.append(vtcapp.translate("RATG only supports EUR as curreny."))

    # Amount in dispute must not be none
    if (case.cf_amount_in_dispute is None):
        error_list.append(vtcapp.translate("Field amount in dispute must not be empty."))

    # Represented and opposing parties must be defined
    if (case.cf_represented_parties==0) or (case.cf_opposing_parties==0):
        error_list.append(vtcapp.translate("Represented and opposing parties must be defined."))
        
    error_text = "\n".join(error_list)
    
    if error_text and vtcapp.evalocl("TimSession.allInstances-&gt;first.hasGui"):
                vtcapp.msgbox(error_text, 0, "RATG" )
    
    return not error_list
</member>
      <member name="eventType">None</member>
      <member name="objectScript">false</member>
      <member name="extendedRights">true</member>
      <member name="selectedObjectsScript">false</member>
      <member name="platform">Python3</member>
    </object>
    <object class="Script" alias="Script_module_tarifrechnerplus_api24">
      <member name="entryID">ScriptModuleTarifrechnerplusApi</member>
      <member name="designation">module_tarifrechnerplus_api</member>
      <member name="containerScript">false</member>
      <member name="scriptText"># coding: windows-1252
#
# Designation: module_tarifrechnerplus_api
# Show in Vertec menus:False
# Classes: -
# Display condition: -
# Event script for: None
# Event classes: -
# Event fields: -
# Extended rights: False

# 2026-08-17, AVE:Script created

import vtcapp
import json
import requests


# Debug on tarifrechnerplus.de
DEBUG = True

API_KEY = vtcapp.getpropertyvalue("tarifrechnerplus_api_key")
# API-URL for RATG
BASE_URL_RATG = "https://tarifrechnerplus.de/api/laws/ratg"
# GGG not yet implemented
BASE_URL_GGG = "https://tarifrechnerplus.de/api/laws/ggg"


# ---------------------
# BasicAPI definition
# ---------------------  
class TarifrechnerplusClient(object):
    """
    Basic API class with core functions.
    """
    def __init__(self,law):
        """
        Initializes the client.
        """
        self.logging = False
        
        if law.upper() == 'RATG':
            base_url = BASE_URL_RATG
        elif law.upper() == 'GGG':
            base_url = BASE_URL_GGG
        else:
            raise Exception("Wrong law selected: {}".format(law))

        self.base_url = base_url.rstrip("/")
        self.session = self._create_session()
        self.Log("API new session opened")
        return
    
    def Log(self, message):
        """ helper method for logging """
        if self.logging:
            print("[Log]: {}".format(message))
    
    def _create_session(self):
        """
        Creates a Requests session with standard headers.
        """
        session = requests.Session()
        session.headers.update({
            "Content-Type": "application/json",
            "Accept": "application/json",
            "Authorization": "Bearer " + API_KEY,
            "X-API-Sprache": "de",
            "X-RATG-Debug": str(DEBUG)
        })
        session.verify = True
        return session
    
    
    def _build_url(self, path):
        """Builds complete URL from path."""
        if not path.startswith("/"):
            path = "/" + path
        return self.base_url + path
    
    
    def _check_response(self, resp):
        """Checks HTTP status and returns the error payload (or None on success); does not raise."""
        err = None
        if not (200 &lt;= resp.status_code &lt; 300):
            try:
                err = resp.json()
            except ValueError:
                err = resp.text
        return err
    
    def _safe_json(self, resp):
        """Safe JSON parsing with fallback."""
        try:
            return resp.json()
        except ValueError:
            self.Log("error on _safe_json")
            return resp.text

    def close_session(self):
        """ Close current session """
        self.session.close()
        self.session = None
        self.Log("API session closed")
    
    # ------------------------------------------------------
    # Core API functions. We only need GET and POST
    # ------------------------------------------------------
    def get(self, path, params=None):
        """Generic GET request."""
        url = self._build_url(path)
        resp = self.session.get(url, params=params, timeout=10)
        self.Log("GET {} params: {}".format(url, params))
        err = self._check_response(resp)
        return self._safe_json(resp), err
    
    
    def post(self, path, data=None):
        """Generic POST request."""
        url = self._build_url(path)
        resp = self.session.post(url, data=data, timeout=10)
        self.Log("POST {} data: {}".format(url, data))
        err = self._check_response(resp)
        return self._safe_json(resp), err
    
    
# ---------------------
# Basic Tariff methods 
# ---------------------
def get_input_types_static(law, date):
    """
    Fetches tariffs including source info for a specific date
    returns a json
    """
    parameters = {}
    parameters['serviceDate'] = date.strftime("%Y-%m-%d") 
    tariff_client = TarifrechnerplusClient(law)
    input_types, err = tariff_client.get("/input-types-static", params=parameters)
    tariff_client.close_session()
    return input_types, err
    
    
def get_form_schema(law, input_type_id, date):
    """
    Fetches tariff details for the needed inputs 
    """
    parameters = {}
    parameters['inputTypeId'] = input_type_id 
    parameters['serviceDate'] = date.strftime("%Y-%m-%d") 
    tariff_client = TarifrechnerplusClient(law)
    form_schema, err = tariff_client.get("/form-schema", params=parameters)
    tariff_client.close_session()
    return form_schema, err

def get_tariff(law, tp_parameters):
    """
    Get the tariff for the entered data
    """ 
    tariff_client = TarifrechnerplusClient(law)
    calculated_tariff, err = tariff_client.post("/calculate-static", 
                                         data=json.dumps(tp_parameters))
    tariff_client.close_session()

    return calculated_tariff, err
    
    
# -------------
# Usage example
# -------------
def main():
    # get the list of the available 'Tarifposten'
    date = vtcapp.currentdate()
    input_types, err  = get_input_types_static('RATG', date)
    for typ in input_types['inputTypes']:
        print(typ['group'], " ", typ['label'])

    # get the form schema for one of the types
    print(get_form_schema('RATG', input_types['inputTypes'][40]['id'], date))
        
if __name__ == "__main__":
    main()
 </member>
      <member name="eventType">None</member>
      <member name="objectScript">false</member>
      <member name="extendedRights">false</member>
      <member name="selectedObjectsScript">false</member>
      <member name="platform">Python3</member>
    </object>
    <object class="Script" alias="Script_RATG-Vertec5">
      <member name="entryID">ScriptRatgFeeInformation</member>
      <member name="designation">RATG fee information</member>
      <member name="classes">Project</member>
      <member name="containerScript">false</member>
      <member name="condExpression">self-&gt;size=1</member>
      <member name="scriptText"># coding: windows-1252
#
# Designation: RATG fee information
# Show in Vertec menus:True
# Classes: Project
# Display condition: -
# Event script for: None
# Event classes: -
# Event fields: -
# Extended rights: False
# 
# Gets a RATG fee
# 2026-08-17, AVE: Script created


from module_legal_fee_schedule import tarif_request

tarif_request(argobject)
</member>
      <member name="eventType">None</member>
      <member name="objectScript">false</member>
      <member name="extendedRights">false</member>
      <member name="selectedObjectsScript">true</member>
      <member name="platform">Python3</member>
    </object>
    <object class="Script" alias="Script_CustomRendererRATG11">
      <member name="entryID">ScriptRendererLegalfeeschedule</member>
      <member name="designation">renderer_legal_fee_schedule</member>
      <member name="containerScript">false</member>
      <member name="scriptText"># coding: windows-1252
#
# Designation: renderer_legal_fee_schedule
# Show in Vertec menus: N
# Classes: - 
# Display condition: - 
# Event script for: - 
# Event classes: - 
# Event fields: - 
# Extended rights: 

# Custom renderer for services related to RATG

# 2026-08-17, AVE: Script created 

import json

class ShowRatgButton():
    """
    Renderer defintions to display a button and the
    corresponding actions
    """
    display_type = "button"
    # No text beside button
    value = ""
    
    def get_buttoniconid(self, rowobj, expression, subscriber):
            return 'calculate'

    def get_buttontooltip(self,rowobj, expression, subscriber):
        return "RATG"

    def get_background_color(self, rowobj, expression, subscriber):
        # Are there already RATG parameters?
        if self.evalocl("keystring('ratg')&lt;&gt;''",rowobj):
            return "clAqua"
        else: 
            return ""

    def button_clicked(self, rowobj, expression):
        """ 
        Calls the RATG dialog to assign a fee
        """
        script_text = self.evalocl("scripteintrag-&gt;select(entryid='ScriptAssignRatgFee')-&gt;first.scripttext")
        return vtcapp.scriptexecute(script_text, rowobj)


class RatgKeyOnPage():
    """
    Displays the RATG key (dict) on a service or service type nice
    """

    def get_value(self, rowobj, expression, subscriber):
        nice_string = ""
        # get key as dict. key 'ratg' must be a dict stored as string!  
        try:
            ratg = json.loads(self.evalocl("keystring('ratg')", rowobj))
            if ratg:
                for key in sorted(ratg.keys()):
                    nice_string += "{}: {}\n".format(key, ratg[key])
        except Exception:
            pass
        return nice_string
 
</member>
      <member name="eventType">None</member>
      <member name="objectScript">false</member>
      <member name="extendedRights">true</member>
      <member name="selectedObjectsScript">false</member>
      <member name="platform">Python3</member>
    </object>
    <object class="TranslationItem" alias="TranslationStreitwert">
      <member name="entryID">TranslationAmountInDispute</member>
      <member name="text">
        <mltext language="DE">Streitwert</mltext>
        <mltext language="EN">Amount in dispute</mltext>
        <mltext language="FR">Montant du litige</mltext>
        <mltext language="IT">Valore della controversia</mltext>
        <mltext language="DD">Streitwert</mltext>
        <mltext language="NL">Geschilwaarde</mltext>
        <mltext language="NV">Amount in dispute</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationSindPflichtfelder">
      <member name="entryID">TranslationAreMandatoryFields</member>
      <member name="text">
        <mltext language="DE">* sind Pflichtfelder</mltext>
        <mltext language="EN">* are mandatory fields</mltext>
        <mltext language="FR">* sont des champs obligatoires</mltext>
        <mltext language="IT">* sono campi obbligatori</mltext>
        <mltext language="DD">* sind Pflichtfelder</mltext>
        <mltext language="NL">* zijn verplichte velden</mltext>
        <mltext language="NV">* are mandatory fields</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationRatgTarifZuweisen">
      <member name="entryID">TranslationAssignRatgFee</member>
      <member name="text">
        <mltext language="DE">RATG Tarif zuweisen</mltext>
        <mltext language="EN">RATG Assign fee</mltext>
        <mltext language="FR">RATG Attribuer le tarif </mltext>
        <mltext language="IT">RATG Assegnare la tariffa </mltext>
        <mltext language="DD">RATG Tarif zuweisen</mltext>
        <mltext language="NL">RATG tarief toewijzen</mltext>
        <mltext language="NV">RATG Assign fee</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationFieldAmountInDisputeMustNotBeEmpty">
      <member name="entryID">TranslationFieldAmountInDisputeMustNotBeEmpty</member>
      <member name="text">
        <mltext language="DE">Das Feld Streitbetrag darf nicht leer sein.</mltext>
        <mltext language="EN">Field amount in dispute must not be empty.</mltext>
        <mltext language="FR">Le champ montant du litige ne doit pas être vide.</mltext>
        <mltext language="IT">Il campo valore della controversia non deve essere vuoto.</mltext>
        <mltext language="DD">Das Feld Streitbetrag darf nicht leer sein.</mltext>
        <mltext language="NL">Bedrag in geschilwaarde mag niet leeg zijn.</mltext>
        <mltext language="NV">Field amount in dispute must not be empty.</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationTarifauskunftRatg">
      <member name="entryID">TranslationRatgFeeInformation</member>
      <member name="text">
        <mltext language="DE">RATG Tarifauskunft</mltext>
        <mltext language="EN">RATG fee information</mltext>
        <mltext language="FR">RATG Informations tarifs</mltext>
        <mltext language="IT">RATG Informazioni sulle tariffa</mltext>
        <mltext language="DD">RATG Tarifauskunft</mltext>
        <mltext language="NL">RATG Tariefinformatie</mltext>
        <mltext language="NV">RATG fee information</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationRatgOnlySupportsEurAsCurreny">
      <member name="entryID">TranslationRatgOnlySupportsEurAsCurreny</member>
      <member name="text">
        <mltext language="DE">RATG unterstützt nur EUR als Währung.</mltext>
        <mltext language="EN">RATG only supports EUR as curreny.</mltext>
        <mltext language="FR">RATG ne prend en charge que l’EUR en tant que devise.</mltext>
        <mltext language="IT">RATG sostiene solo l’euro come valuta.</mltext>
        <mltext language="DD">RATG unterstützt nur EUR als Währung.</mltext>
        <mltext language="NL">RATG ondersteunt alleen de euro als valuta.</mltext>
        <mltext language="NV">RATG only supports EUR as curreny.</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationLeistungenMitRatgTarifNeuBerechnen">
      <member name="entryID">TranslationRatgRecalculateFee</member>
      <member name="text">
        <mltext language="DE">RATG Tarif neu berechnen</mltext>
        <mltext language="EN">RATG Recalculate fee</mltext>
        <mltext language="FR">RATG Recalculer le tarif </mltext>
        <mltext language="IT">RATG Ricalcolare la tariffa</mltext>
        <mltext language="DD">RATG Tarif neu berechnen</mltext>
        <mltext language="NL">RATG Tarief opnieuw berekenen</mltext>
        <mltext language="NV">RATG Recalculate fee</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationNeukalkulationRatg">
      <member name="entryID">TranslationRatgRecalculation</member>
      <member name="remarks">Recalculation RATG</member>
      <member name="text">
        <mltext language="DE">Neukalkulation RATG</mltext>
        <mltext language="EN">RATG recalculation</mltext>
        <mltext language="FR">Recalcul RATG</mltext>
        <mltext language="IT">Ricalcolo RATG</mltext>
        <mltext language="DD">Neukalkulation RATG</mltext>
        <mltext language="NL">Herberekening RATG</mltext>
        <mltext language="NV">RATG recalculation</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationRatgSetting">
      <member name="entryID">TranslationRatgSetting</member>
      <member name="text">
        <mltext language="DE">RATG Vorgabe</mltext>
        <mltext language="EN">RATG setting</mltext>
        <mltext language="FR">Réglage RATG</mltext>
        <mltext language="IT">Impostazione RATG</mltext>
        <mltext language="DD">RATG Vorgabe</mltext>
        <mltext language="NL">RATG-instelling</mltext>
        <mltext language="NV">RATG setting</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationRepresentedAndOpposingPartiesMustBeDefined">
      <member name="entryID">TranslationRepresentedAndOpposingPartiesMustBeDefined</member>
      <member name="text">
        <mltext language="DE">Die vertretenen und die gegnerischen Parteien müssen definiert sein.</mltext>
        <mltext language="EN">Represented and opposing parties must be defined.</mltext>
        <mltext language="FR">Les parties représentées et opposées doivent être définies.</mltext>
        <mltext language="IT">Occorre definire le parti rappresentate e quelle opposte.</mltext>
        <mltext language="DD">Die vertretenen und die gegnerischen Parteien müssen definiert sein.</mltext>
        <mltext language="NL">Vertegenwoordigde partijen en opposanten moeten worden gedefinieerd.</mltext>
        <mltext language="NV">Represented and opposing parties must be defined.</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationStreitgenossen">
      <member name="entryID">TranslationRepresentedParties</member>
      <member name="text">
        <mltext language="DE">Vertretene Parteien</mltext>
        <mltext language="EN">Represented parties</mltext>
        <mltext language="FR">Parties représentées</mltext>
        <mltext language="IT">Parti rappresentate</mltext>
        <mltext language="DD">Vertretene Parteien</mltext>
        <mltext language="NL">Vertegenwoordigde partijen</mltext>
        <mltext language="NV">Represented parties</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationQuelle">
      <member name="entryID">TranslationSource</member>
      <member name="text">
        <mltext language="DE">Quelle</mltext>
        <mltext language="EN">Source</mltext>
        <mltext language="FR">Source</mltext>
        <mltext language="IT">Fonte</mltext>
        <mltext language="DD">Quelle</mltext>
        <mltext language="NL">Bron</mltext>
        <mltext language="NV">Source</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationTarifposten">
      <member name="entryID">TranslationTariffPositions</member>
      <member name="text">
        <mltext language="DE">Tarifpositionen</mltext>
        <mltext language="EN">Tariff positions</mltext>
        <mltext language="FR">Positions tarifaires</mltext>
        <mltext language="IT">Voci tariffarie</mltext>
        <mltext language="DD">Tarifpositionen</mltext>
        <mltext language="NL">Tariefposten</mltext>
        <mltext language="NV">Tariff positions</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationSummeNeueTarife">
      <member name="entryID">TranslationTotalOfNewRates</member>
      <member name="text">
        <mltext language="DE">Summe neue Tarife</mltext>
        <mltext language="EN">Total of new rates</mltext>
        <mltext language="FR">Total des nouveaux tarif</mltext>
        <mltext language="IT">Totale nuova tariffa</mltext>
        <mltext language="DD">Summe neue Tarife</mltext>
        <mltext language="NL">Totaal nieuwe tarieven</mltext>
        <mltext language="NV">Total of new rates</mltext>
      </member>
    </object>
    <object class="TranslationItem" alias="TranslationSummeAlterTarife">
      <member name="entryID">TranslationTotalOfOldRates</member>
      <member name="text">
        <mltext language="DE">Summe alte Tarife</mltext>
        <mltext language="EN">Total of old rates</mltext>
        <mltext language="FR">Total des anciens tarif</mltext>
        <mltext language="IT">Totale delle vecchie tariffe</mltext>
        <mltext language="DD">Summe alte Tarife</mltext>
        <mltext language="NL">Totaal oude tarieven</mltext>
        <mltext language="NV">Total of old rates</mltext>
      </member>
    </object>
  </objects>
  <settings />
</configset>