# Fields

todo

Fields are a super important configuration part of SCP. Materials Meta Data is stored in fields and therefore one of the first starting points for creating a suitable SCP configuration.

Filters are important

Don't forget to check out Filters as they are important for field configuration as well as for a lot of additional configuration options.

# Create your first field

SCP reads field configuration from the fields config key. Every field needs to have its own unique identifier which acts as the field name.

So let's assume we want to have a new field to contain the country ownership:

<?php

// CLIENT_CONFIG/config/fields.php

return [
    'country' => [
        'field' => [
            'label' => 'Country',
            'type' => 'select'
        ],
    ],
];

Looks good so far, it will render a new select field but obviously does not contain any values to pick from. So let's fix that:

<?php

// CLIENT_CONFIG/config/fields.php

return [
    'country' => [
        'field' => [
            'label' => 'Country',
            'type' => 'select'
        ],
        'values' => [
            [
                'filter' => [],
                'values' => [
                    'germany' => [
                        'name' => 'Germany',
                        'default' => true
                    ],
                    'switzerland' => [
                        'name' => 'Switzerland',
                        'default' => false
                    ]
                ]
            ]
        ],
    ],
];

You will now see that SCP will render a list of two Switzerland and Germany to pick from. But what exactly did happen here?

SCP allows you to add multiple Value Sets for select and tag fields – so you can choose by using Filter which Values SCP should present to the user as a pick list.

As you know from Filters empty arrays are always treated as a matching filter so the configured value set is always presented to the user.

The default flag tells SCP which value is defined as the default value – so be wise and just set one value as the default for a field 😄.

Order matters

Showcase Platform uses two techniques when it comes to filterable entries – merging and first match. For Value Sets SCP uses the first match strategy.

Let's create another field to host the language of the material:

<?php

// CLIENT_CONFIG/config/fields/language.php

return [
    'field' => [
        'label' => 'Language'
    ],
    'values' => [
        [
            'filter' => [],
            'values' => [
                'german' => [
                    'default' => true,
                    'name' => 'German',
                ],
                'french' => [
                    'default' => false,
                    'name' => 'French'
                ],
                'italian' => [
                    'default' => false,
                    'name' => 'Italian'
                ],
            ]
        ]
    ],
];

Cool, we now have two new Select-Fields for some Meta Data. Did you see that we've created the field inside a new space: config/fields/language.php and we have omitted the root key language.

As SCP maps down the file structure to configuration keys, the fields data is now set inside fields.language which is exactly what we want – we just did separate our config a little more to keep readability.

So we can now move on to dynamic fields.

# Dynamic Fields

The above configuration is good but a bit static. The language fields currently contains all possible languages relevant for our countries, but italian is not really relevant for Germany but for Switzerland. So what's about creating a dependency between those fields:

<?php

// CLIENT_CONFIG/config/fields/language.php

return [
    'language' => [
        'field' => [
            'label' => 'Language'
        ],
        'values' => [
            [
                'filter' => [
                    'country' => 'germany'
                ],
                'values' => [
                    'german' => [
                        'default' => true,
                        'name' => 'German',
                    ],
                ]
            ],
            [
                'filter' => [
                    'country' => 'switzerland'
                ],
                'values' => [
                    'german' => [
                        'default' => true,
                        'name' => 'French'
                    ],
                    'french' => [
                        'default' => false,
                        'name' => 'French'
                    ],
                    'italian' => [
                        'default' => false,
                        'name' => 'Italian'
                    ],
                ]
            ]
        ],
    ],
];

We have created a new Value set which is only valid for the material has the value switzerland stored inside the country field. When the user changes the country to Switzerland, SCP will rerender the possible language values to fit your Filter.

So let's add more magic to this field setup:

<?php

// CLIENT_CONFIG/config/fields/language.php

return [
    'language' => [
        'field' => [
            'label' => 'Language',
            'filter' => [
                'country' => 'switzerland'
            ],
        ],
        'values' => [
            [
                'filter' => [
                    'country' => 'switzerland'
                ],
                'values' => [
                    'german' => [
                        'default' => true,
                        'name' => 'French'
                    ],
                    'french' => [
                        'default' => false,
                        'name' => 'French'
                    ],
                    'italian' => [
                        'default' => false,
                        'name' => 'Italian'
                    ],
                ]
            ]
        ],
    ],
];

As german Materials are obviously in German, we decided to just show the language field only if it makes sense. To let SCP know when it has to reload the relationship between the current Material and the Fields configuration, you need to change the config for the country field just a little:

<?php

// CLIENT_CONFIG/config/fields.php

return [
    'country' => [
        'field' => [
            'label' => 'Country',
            'type' => 'select',
            'triggersFieldUpdate' => true,
        ],
        'values' => [
            // nothing changed here
        ],
    ],
];

Setting triggersFieldUpdate to true will instruct Showcase Platform to reload the configuration for fields once the value of the given field changes.

Field Defaults

If a field is not actively attached to a Material, the default value of the given field might not be set on its data. So be aware of this whenever you use the materials data anywhere in your configuration.

# Vault Fields

Getting values for your field directly from the "Vault"... easy.

We can use two different type of requests. We can get the data from a vql query or from the picklist.

# VQL

If the field has vault_field configuration it should execute the vql_query every time the cache expires and return results to your field values.










 
 
 
 
 
 
 
 
 
 
 




<?php

// CLIENT_CONFIG/config/fields.php

return [
    'product' => [
        'field' => [
            'label' => 'Product',
            'type' => 'select',
            'vault_field' => [
                [
                    'filter' => [],
                    'config' => [
                        'connection' => 'config.veeva_vault.prod',
                        'vql_query' => 'SELECT id, name__v FROM product__v',
                        'value' => 'id',
                        'label' => 'name__v'
                    ]
                ]
            ]
        ],
    ],
];

Result of the code above will be something like this, and it will be automatically assigned to your field values:




 
 
 



<?php

array (
    '00P000000000601' => ['default' => false, 'name' => '3FLEX'],
    '00P000000000G04' => ['default' => false, 'name' => 'SPECTRA'],
    '00P000000000J41' => ['default' => false, 'name' => 'ZACRTAN'],
    // ...
);

You can have multiple configurations for your field based on the different filters:











 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 





<?php

// CLIENT_CONFIG/config/fields.php

return [
    'product' => [
        'field' => [
            'label' => 'Product',
            'type' => 'select',
            'vault_field' => [
                [
                    'filter' => [
                        'vault_type' => 'com_vault'
                    ],
                    'config' => [
                        'connection' => 'config.com_vault.prod',
                        'vql_query' => 'SELECT id, name__v FROM product__v',
                        'value' => 'id',
                        'label' => 'name__v'
                    ]
                ],
                [
                    'filter' => [
                        'vault_type' => 'med_vault'
                    ],
                    'config' => [
                        'connection' => 'config.med_vault.prod',
                        'vql_query' => 'SELECT id, name__v FROM product__v',
                        'value' => 'id',
                        'label' => 'name__v'
                    ]
                ]
            ]
        ],
    ],
];

If you need some values filtering you can always use custom callable for your field values that will do the filtering for you, using material and cached data as parameters:
























 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 





<?php

// CLIENT_CONFIG/config/fields.php

return [
    'product' => [
        'field' => [
            'label' => 'Product',
            'type' => 'select',
            'vault_field' => [
                [
                    'filter' => [],
                    'config' => [
                        'connection' => 'config.veeva_vault.prod',
                        'vql_query' => 'SELECT product__cr.id, product__cr.name__v, country__cr.id FROM countryproduct__c'
                    ]
                ]
            ]
        ],

        'values' => [
            [
                'filter' => [],
                'values' => function (Material $material, array $data) {
                    $values = [];

                    $opu = $material->getField('opu')->getValue();
                    $countryCode = (string) Mapping::get('vault_opu_country', $opu);

                    foreach ($data as $product) {
                        if ($countryCode === $product['country__cr.id']) {
                            $values[$product['product__cr.id']] = [
                                'default' => false,
                                'name' => $product['product__cr.name__v']
                            ];
                        }
                    }

                    return $values;
                }
            ]
        ]
    ],
];

In this case you don't have to define value and name option because it will be set by your callable.

If you want to parse vault data that is being returned by vault response before it gets passed to the filtering callback as $dataFromVault, you can use vault_response_parser:


















 
 
 
 
 
 
 
 
 
 
 
 
 








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 





<?php

// CLIENT_CONFIG/config/fields.php

return [
    'product' => [
        'field' => [
            'label' => 'Product',
            'type' => 'select',
            'vault_field' => [
                [
                    'filter' => [
                        '!vault_type' => 'medicine_vault'
                    ],
                    'config' => [
                        'connection' => 'config.veeva_vault.prod',
                        'vql_query' => 'SELECT product__cr.id, product__cr.external_id__v, product__cr.name__v, country__cr.id FROM countryproduct__c',
                        'vault_response_parser' => function (array $dataFromVault): array {
                            $values = [];

                            foreach ($dataFromVault as $product) {
                                $id = $product['product__cr.id'];

                                $values[$id]['name'] = $product['product__cr.name__v'];
                                $values[$id]['external_id'] = $product['product__cr.external_id__v'];
                                $values[$id]['country_id'][] = $product['country__cr.id'];
                            }

                            return $values;
                        }
                    ]
                ]
            ]
        ],

        'values' => [
            [
                'filter' => [],
                'values' => function (Material $material, array $dataFromVault) {
                    $values = [];

                    $opu = $material->getField('opu')->getValue();
                    $countryCode = (string) Mapping::get('vault_opu_country', $opu);

                    foreach ($dataFromVault as $product) {
                        if (in_array($countryCode, $product['country_id'])) {
                            $values[$product['external_id']] = [
                                'default' => false,
                                'name' => $product['name']
                            ];
                        }
                    }

                    return $values;
                }
            ]
        ]
    ],
];

# Vault field config parameters

Parameter Description Mandatory
connection Connection that will be used on Vault API side true
vql_query Query to execute on Vault API side true
value Value that will be used for field value false
label Label that will be used as field value label false
cache_duration Cache duration, default is 30 days false
vault_response_parser Callback for parsing vault response data false

# Picklist

Working with Picklists is almost the same as when working with VQL. It's also not necessary to have a vault_response_parser. But If you want to parse vault data that is being returned by vault response before it gets passed to the filtering callback as $dataFromVault, you can use vault_response_parser:










 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 




<?php

// CLIENT_CONFIG/config/fields.php

return [
    'crm_org' => [
        'field' => [
            'label'       => 'CRM Org',
            'type'        => 'select',
            'vault_field' => [
                [
                    'filter' => [],
                    'config' => [
                        'connection'            => 'config.veeva_vault.prod',
                        'picklist'              => 'crm_org__c',
                        'vault_response_parser' => static function (array $dataFromVault): array {
                            $values = [];

                            if (!empty($dataFromVault['picklistValues'])) {
                                foreach ($dataFromVault['picklistValues'] as $value) {
                                    $values[$value['label']] = $value;
                                }
                            }

                            return $values;
                        }
                    ]
                ]
            ]
        ]
    ]
];

The result of the code above will look like this, after it got parsed:







 
 
 
 
 
 
 
 
 
 
 
 





<?php

[

    // ...

    'americas__c' => [
        'name'  => 'americas__c',
        'label' => 'Americas'
    ],
    'eu__c'       => [
        'name'  => 'eu__c',
        'label' => 'EU'
    ],
    'apac__c'     => [
        'name'  => 'apac__c',
        'label' => 'APAC'
    ],

    // ...

];

You can have multiple configurations for your field based on the different filters. Please note that the requested object does not always exist. Also note that not every field is in vault. You can use mixed configuration like this:































 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 



<?php

// CLIENT_CONFIG/config/fields.php

return [
    'crm_org' => [
        'field'  => [
            'label'       => 'CRM Org',
            'type'        => 'select',
            'vault_field' => [
                [
                    'filter' => [],
                    'config' => [
                        'connection'            => 'config.veeva_vault.prod',
                        'picklist'              => 'crm_org__c',
                        'vault_response_parser' => static function (array $dataFromVault): array {
                            $values = [];

                            if (!empty($dataFromVault['picklistValues'])) {
                                foreach ($dataFromVault['picklistValues'] as $value) {
                                    $values[$value['label']] = $value;
                                }
                            }

                            return $values;
                        }
                    ]
                ]
            ]
        ],
        'values' => [
            [
                'filter' => [
                    'opu' => 'global'
                ],
                'values' => [
                    'na' => ['default' => true, 'name' => 'N/A'],
                ]
            ],
            [
                'filter' => [
                    'opu' => [
                        'argentina',
                        'bolivia',
                        'brazil',
                        // ...
                    ]
                ],
                'values' => static function (Material $material, array $dataFromVault): array {
                    $values = [];

                    foreach ($dataFromVault as $crmOrg) {
                        if ($crmOrg['label'] === 'Americas') {
                            $values[$crmOrg['name']] = [
                                'default' => true,
                                'name'    => $crmOrg['label']
                            ];
                        }
                    }

                    return $values;
                }
            ],

            // ...

        ]
    ]
];

Vault field config parameters

Parameter Description Mandatory
connection Connection that will be used on Vault API side true
picklist Picklist_name which get requested from the vault true
value Value that will be used for field value false
label Label that will be used as field value label false
cache_duration Cache duration, default is 30 days false
vault_response_parser Callback for parsing vault response data false

# Field Validations

Fields are managed by users and validation and rules can help to keep your Metadata as clean as possible. We have a handy example for you:

<?php

// CLIENT_CONFIG/config/fields.php

return [
    'name' => [
        'field' => [
            'conditions' => [
                [
                    'rules' => [
                        'max' => 100,
                    ],
                    'message' => 'Material Name must not have more than 100 characters'
                ]
            ]
        ]
    ],
];

So what happens here? As you can see we did not create a new fields as we are just extending one of the Default Fields here. Instead of creating the full configuration, we've only defined that part of the configuration we want to modify.

We did create a new condition which uses the max rule to allow a maximum of 100 characters for the field and a custom message to let the user know what happens when he ran into this condition.

Check out the reference for fields for details

# Default Fields

SCP defines a few default fields which are relevant for system use and are commonly used.

Field Description
id Contains the Material ID and is used for internal reference.
name The name of the Material used for easier finding of materials.
description The description for the given material.
created_at The date of creation for the material.
status A materials status (e.g. deployed, in progress, etc.) is handled via this field.
materialType A special field containing the reference to the Material Type.
created_by Stores the id of the user who has created the Material.
updated_by Stores the id of the user who has updated the Material recently.