Workflows
- It is imperative to ensure that the workflow contains connectors between the tasks. There should be a defined start and end point, or a connection to another workflow.
- When implementing branching logic within task connectors, it is essential to account for every potential outcome in your conditions, ensuring that each condition is mutually exclusive. Avoid overlapping logical conditions.
- Confirm that the object triggering the workflow is appropriately enabled. For instance, Level 1 templates must have workflows enabled and specific association workflows selected. Organizations are required to select specific company/contact workflows.
- It is not permissible to configure multiple workflows to be triggered by a single status.
- Verify that there is no malformed or incorrect syntax present within the task connectors or workflow routing (e.g., routing of an acknowledgment task).
Variable Processor
- Ensure that all variables referenced within the system are consistently encapsulated within double quotes.
- If certain syntax, such as [#(?object=)#], is malformed, it may result in a completely blank page being displayed.
- Ensure that there are no mismatched syntax tags, such as sslogic embedded within one another, or missing sslogic end tags. When embedding different syntax (e.g., sslogic, sscalculation, or system variables), it is crucial to understand the SmartSimple Order of Operations to configure these elements appropriately.
- Be cognizant of all possible return values for a variable. If a value has never been saved to a field, the variable syntax itself will be returned (i.e., @variable@). Additionally, a variable may return a blank empty string. The variable processor will also consider field formatting and, by default, return a field's configured format, such as currency or date format. This should be taken into account when manipulating the value.
Javascript & MySQL
- Javascript syntax is utilized in areas that are displayed to the user in the browser. Examples include custom field settings for Javascript Validation, Special Calculated Value custom fields, and Special Browser Script fields.
- MySQL syntax is employed in backend areas that are not visible to the user. Examples include Template Formulas, Submit Logic, and custom field Visibility Logic.
- The equality operator in Javascript is represented by a double equal sign (==), whereas in MySQL, it is represented by a single equal sign (=).
- String (text) values must be encapsulated within quotes (double quotes are the most secure), thus reinforcing the recommendation to always encapsulate Variable Processor calls within quotes.
When running conditional checks on Fields using SSLOGIC(), IF() or CASE statements from within either the variable syntax helper or from within Template/Type Formulas, how can I get the system to recognize NULL/Empty value?
if("@level1.fieldName.value@"="", 0, @level1.fieldName.value@)
is an example of how to return a "0" in the event the @level1.fieldName.value@ variable returns an empty result.
I'm attempting to calculate a set of scoring questions into a total score. The scoring questions are a radio button-single select. When trying to save the record without answering the scoring questions, the scores don't save.
We recommend creating a Level-1 Type Formula to perform these automated updates, using the following steps as a guide:
(1) Menu >> Tracking Applications >> [Edit] Submission Manager >> Application tab >> Types
(2) [Edit] your record Type that includes your scores
(3) Click the [Process] tab at the top
(4) Enter the following code into the [Application Formula], replacing the variables with the correct field names used within your environment:
@level1.TotalScoreField@=@level1.1stScore@+@level1.2ndScore@+@level1.3rdScore@
We want to add ~60 new budgets to the Budget Manager for different Branches - what is the best method to accomplish this?
We recommend using an Autoloader for this purpose; bulk uploading all of your budgets using a CSV file.
Can you please let me know how to delete the space between sentences within a Grant Invitation?
You can try replacing the <p> (paragraph) HTML tags with <br> (single line break). For example, navigating to Menu >> Tracking Applications >> [Edit] Submission Manager >> Grant tab >> Invitation Templates >> [Edit] Invite Collaborators >> Email Templates tab >> [Invitation Email Body]:
...
Your signature here,
<br>Administrator
We want to remove the "Pending Agreements" section within our Portal - how can we make this update?
In order to remove the 'Pending Agreements' from the Portal, you would want to perform the following navigation:
Menu >> Global Settings >> Users tab >> Portals >> [Edit] Common
From here you see all the active Portal Pages within your system. You will want to identify which Portal page, specific to your Roles, you are targeting. Once you have identified the correct Portal page you would click [Edit] next to its name, and finally click the [X] (Remove) button.
How can we attach a PDF into a confirmation email?
If you navigate to the Task within the Workflow that generates these confirmation emails, you will find the [File attachments] section within the configuration that allows us to attach a file (PDF) to the email:
Menu >> Workflows >> [Edit] WorkflowName >> Tasks (from the left menu) >> Click on the Email Acknowledgement Task >> Click on the [Message Template] tab at the top and scroll down to see the [File attachments] field at the bottom of the window
From here you may specify the custom field ID variable that houses your PDF, such :
@#123456789#@
We have setup OKTA SSO and have enabled the "create new user on no match" setting in OKTA. We are trying to setup SSO new user creation assertion. On the OKTA side, the client has added the new user assertion and when the new user gets created in the system, it is blank - meaning, it has no email address, first and last name.
Please ensure your OKTA Assertion Attributes are valid, especially the following as these would be important for your setup:
1. First name
2. Last name
3. Email
How can I automatically rename my Level-2 Activities? I want my Level-2 Name ("Subject" Standard Field) to be the same as its parent, Level-1 record name.
In order to set the L2 Activity standard field named "Subject" equal to the L1 standard field named "Application Name", the following syntax may be used within your Level-2 Template Formula found from Menu >> Tracking Applications >> [Edit] UTAname >> Activity (tab) >> [Formula]:
@level2.subject@=@level1.name@
How can I locate the internal ID of a Custom Field?
To locate a field ID value, you will want to navigate to:
Menu >> Tracking Applications >> [Edit] your UTA that stores these Activities
From here, you will want to click on either Standard Fields or Custom Fields depending on the type of field you are looking to identify the ID for. Within either of those windows, you will see a listing of all current fields with their respective ID listed on the very right of the screen.
How can we use our own unique CSS stylesheet within SmartSimple?
Customized CSS stylesheets may be uploaded by navigating as follows:
Menu --> Global Settings --> Branding tab --> Colors and Styles --> Classic tab --> [External Stylesheet Path] field at the bottom of the page.
I came across a workflow that makes use of "System Call Identifier," but I'm not sure what it is?
The System Call feature of SmartSimple provides you with the ability to execute pre-defined system functions on the server and in the process avoid the creation of client side scripting. The benefits of System Calls are as follows:
1. Better performance and security as the execution of the code takes place on the server not in the client browser.
2. More stable, as the System Calls are programmed by SmartSimple and optimized for the platform.
You don’t need to know JavaScript in order to use the feature. The System Call Identifier is the reference name used for the System Call to the workflow - these System Calls may be used from within a Browser Script custom field, with an example being:
<!--SysCall_function(@systemCallIdentifierName@)-->
What is the recommended approach to creating a City or Town Selection Custom Field that allows someone to select a City from a list of Cities?
We recommend utilizing a combination of a System Variable along with either a Lookup - Autocomplete Options Custom Field Type that includes the System Variable within its [Predefined Options].
1. Menu >> Global Settings >> System (tab) >> System Variables >> System Variables (tab) ; from here we would first want to create a new System Variable using the [New System Variable] button.
2. Name the new System Variable, such as cityList and place all selectable options within the [Value] box. All text string options must be separated by semi-colons, such as: City 1;City 2;City 3
3. Create a new Lookup - Autocomplete Options Custom Field within your UTA and desired Level and place the System Variable into the new field's [Predefined Options] using the following syntax: @system.cityList@
Best Practice: Correct Data Formats
When storing any information into any system, it's important to understand what type of information you're dealing with and to format it accordingly. The purpose of this is to store information in a meaningful way so that you can perform calculations or analysis on it. Take the example of someone's name; the easiest way to store this would be in a single field called 'name'.
However, problems occur later on if any manipulation or analysis of this name field is done. It cannot be separated into first/last name, meaning contacts cannot be sorted by last name if one so chooses. The name field cannot simply be parsed and separated by looking for an empty space between the names either because we cannot be sure of the format of the data contained within the field. Users may have entered their middle name as well, or perhaps their first name is composed of two separate words...etc. resulting in multiple space breaks in our name field. To correct this problem, multiple input fields need to be used for a name. These fields force the user to be specific and enter the data as such. This can be done by using separate fields for first name, middle name, last name, and even a title field for Jrs/Srs.
In order for information to be meaningful and useful, it must be formatted and stored correctly. It is unsafe to try to manipulate unstructured and unformatted data into another format.
Use the following steps to ensure that data is stored and represented correctly:
1) Design your architecture and schema in a meaningful way to begin with (i.e. using multiple fields to store a name in the example above).
2) Force the data input into a specific format of your choosing (i.e. using data validation and transformation techniques, validating that users can only enter alphabetic characters, apostrophes, and hyphens as their name input).
The main area to consider is the custom fields that you create and how you design them. Below are some specific examples using the validation and formatting option of a Single Line Text field:
1) Date/time: Date/time values should always be stored as a single Date/time value. The year, month, date, day as numbers or words, as well as the time, etc. can all be extracted from this.
Consider how the standard date input fields are broken up into a date, hour, and minute input but the system actually stores all this data as a single field. MySQL (and most other areas for easy sorting) uses the format "YYYY-MM-DD HH:MM:SS". By using the Date validation on a custom field, uniform date formatting is stored in the system regardless of how each individual user specifies the way they wish to view dates.
2) Numbers: Numbers always need to be entered accurately. Consider how you would store currency data. When you use the Numeric validation and Currency formatting on a custom field, the system actually stores the number value to the full number of decimals and without a currency symbol (i.e. "12.948576"). However, when the system displays this field, it is rounded to two decimals and with a currency symbol (i.e. "$12.95").
3) In General: It's important to have a specific format for any standard data. Take for example, the Canadian postal code which one could enter as "M5V 2H1" or "M5V2H1" (among other variants using lower/upper case letters). The best practice for this example would be to enforce that the user always enters one specific format with upper case letters. This can be done using the validation configuration of a custom field.
Correct Variable Processor Use
The Variable Processor is a functionality integrated into SmartSimple that facilitates the pre-processing and dynamic replacement of various values throughout the system, tailored to the context of the current user or the object being viewed. While the Variable Processor is an exceptionally powerful and beneficial tool, it is imperative to understand the fundamental principles governing its operation when configuring it.
Errors may easily occur, resulting in varying degrees of undesirable behavior, some of which may be subtle and difficult to detect. Fortunately, these issues can be readily avoided by adhering to the following best practices.
Generally, whenever a variable is retrieved for use in a calculation, evaluation, or assignment to another field, it is essential to encapsulate it within double quotes.
Template Formulae
Issue 1:
@level1.name@=@level1.owner.firstname@ @level1.owner.lastname@;
Explanation:
When assigning a string value to a custom field, the string must be enclosed in quotes. This example would result in a server error, and no data would be saved to @level1.name@.
Issue 2:
@level1.name@='@level1.owner.firstname@ @level1.owner.lastname@';
Explanation:
Names containing apostrophes will terminate the single-quoted string (for instance, if my name is Chin O'Brien), leading to a server error and preventing any data from being saved to @level1.name@.
Solution:
@level1.name@="@level1.owner.firstname@ @level1.owner.lastname@";
Always utilize double quotes around strings to ensure safety.
Browser Scripts
Issue 1:
frm.cf_@customfield.id@.value="";
Explanation:
In certain cases where the field value is null, the Variable Processor may not replace the variable with a blank value, resulting in the display of frm.cf_@customfield.id@.value on the page. This will disrupt this specific script and any subsequent script functions that follow.
Solution:
document.getElementById("cf_@customfield.id@");
Issue 2:
var oppid=@opportunityid@;
Explanation:
When the variable is nonexistent or blank, this script will fail, subsequently affecting all following scripts.
Solution:
var oppid="@opportunityid@";
Visibility Conditions
Issue 1:
@opportunityid@>0
Explanation:
When creating a new Level 1, it may appear that the condition is functioning correctly as the field is not visible; however, this will cause server errors since the @opportunityid@ is not replaced, as that value is not yet available for new Level 1s. An error will result in the visibility condition consistently failing, leading to undesirable behavior.
Solution:
"@opportunityid@"*1>0
Note: For this specific example, there is a checkbox setting within the custom field configuration that permits the hiding of fields on new objects until the object is saved at least once.
Everywhere Else
Issue 1:
@ReportProperty(12345,recordcount)@ + @custom number@
Explanation:
If either of the aforementioned values is blank or null, this will result in an error and will not function correctly.
Solution:
"@ReportProperty(12345,recordcount)@"*1 + "@custom number@"*1
The *1 is utilized to explicitly cast the result into a numeric value. This is necessary to ensure that if your @custom number@ includes an alphabetic character, the *1 will convert it to 0. If, for any reason, you use a @ReportProperty()@ that returns blank, then ""*1 will also convert to 0.
Issue 2:
Failing to use quotes within @sslogic()@ or @sscalculation()@ conditions will also produce errors, although these may not be immediately apparent since the @sslogic()@ does not display, potentially leading to incorrect assumptions in certain situations.
The following considerations should be taken into account:
1) The .inRole variable will always return boolean values of true or false, thus there is no necessity to encapsulate this within double quotes (e.g., @me.inRole(Organization Contact)@).
2) When the variable value being retrieved includes double quotes, these must be escaped, or the variable should be enclosed within single quotes if it is certain that the variable value does not contain single quotes.
Best Practice: Updates to a Field
Default Text
The most straightforward method for storing a value in a field is through the configuration available on the custom field settings page for open text input fields, such as Text - Single Line. This setting operates by pre-populating the input field on the form with the designated default value when the field does not already contain a stored value. It is necessary for the user to save the form in order to retain the field value.
Advantages:
- Simple and efficient
- Flexibility provided through custom field configuration (i.e., it can be utilized as a one-time storage option, preventing users from editing the default field value, and can be hidden or displayed on the page, or alternatively, permit users to modify the default field value)
- Visibility (i.e., users can view the field and confirm the default value prior to its actual saving and storage)
Calculated Value Field
This method allows for the updating of a field based on an expression executed upon page load. It is applicable solely to the Special - Calculated Value custom field type. This setting is configured using JavaScript syntax and functions by populating the input field on the form with the specified expression each time the form is loaded. Users must save the form to ensure that the field value is stored.
Advantages:
- Simple and efficient
- Complex calculations can be executed through JavaScript syntax
- Sequential processing (i.e., upon page load, each Calculated Value field is evaluated in the order of their display sequence)
- Visibility (i.e., users can view the field and confirm the default value before it is saved and stored)
Value Stores To
This method enables the duplication of a field value and its storage in another field. It is configured via the custom field settings page. This setting operates by duplicating a field value into another field whenever the first field is saved. Users must input a value into the first field for this process to occur.
Advantages:
- Simple and efficient
- Synchronization (i.e., this can be employed to synchronize values between multiple fields that represent the same data set)
- Transparency (i.e., operates behind the scenes)
Template Formula
This method allows for the updating of a field value behind the scenes. It is available in various sections and can be configured through the UTA settings page, User Roles, or Company Categories pages. This setting is implemented using MySQL syntax and functions by directly updating the stored value of a field. Users must save the form, and this operation occurs post-saving, thus referencing the most recent field values that have been saved.
Advantages:
- Capability to update different areas beyond the form the user is currently interacting with (i.e., an L2 formula can be used to update an L1 field)
- Server-side validity (i.e., can be utilized for date/time functions to reference server time at the precise moment of saving)
- Complex calculations can be conducted through MySQL syntax
- Sequential processing (i.e., saving an L3 results in the execution of L3 formulas, followed by L2 formulas, and subsequently L1 formulas in succession. Additionally, within a template formula block, each individual line is processed in order, allowing for the updating of a field value in one line and referencing the new field value in the subsequent line)
- Transparency (i.e., functions behind the scenes)
Workflow Task
This method provides a means to update a field value behind the scenes. It is configured as a task within a Workflow. The Workflow must be triggered against the object whose field requires updating.
Advantages:
- Ability to update different areas beyond the form the user is currently interacting with
- Server-side validity (i.e., can be utilized for date/time functions to reference server time at the exact moment of Workflow execution)
- Inherent audit trail detailing when the workflow was triggered and the individual who initiated it
- Sequential processing (i.e., the capability to process other Workflow tasks both before and after. Note: while Workflow tasks execute sequentially, the Workflows themselves operate asynchronously on the server)
- Transparency (i.e., operates behind the scenes)
SmartSimple's Order of Operations
It is imperative that all individuals possess a comprehensive understanding of the fundamental processes that occur and the sequence in which they take place when utilizing the system. A lack of understanding regarding this sequence may result in logical errors and, at times, unpredictable behavior (consider the significance of the mathematical order of operations).
As illustrated below, engaging in any scripting poses considerable risks, as any errors introduced through configuration could potentially disrupt a significant portion of the core system functionality. Let us examine the operation of a Level 3.
Initiating a Level-3
1) The Variable Processor executes over the entire page multiple times in the following order. This process occurs on the server side prior to the page reaching the user's browser. When anticipating a high user load, it is essential to carefully consider our utilization of the Variable Processor for performance optimization.
- The Variable Processor substitutes @System.@ variables
- The Variable Processor substitutes @me.@ variables
- The Variable Processor substitutes @rootcompany.@ variables
- The Variable Processor substitutes @ReportProperty()@ variables
- The Variable Processor substitutes prefixed @parent.@, @client.@, @owner.@, @branch.@, etc. variables
- The Variable Processor substitutes @standardfields@ and @customfields@ variables
- The Variable Processor substitutes @xml.customfield@ variables
- The Variable Processor substitutes [#(?object=)#] list view queries
- The Variable Processor substitutes @System2.@ variables
- The Variable Processor substitutes @sslogic and @sscalculation calculations
- The Variable Processor substitutes @ReportProperty2()@ variables
- The Variable Processor substitutes @ssencrypt, @ssescape, and @sstranslate variables
2) The page is subsequently dispatched to the end-user's browser.
3) The script - _showhideheader(); is executed, determining which title bars are displayed or hidden, along with dynamic control fields.
4) The script - onloadfunc(); is executed after all page elements have been fully loaded.
5) The script - SystemCall onload(); initializes and calls the script function here; however, the actual processing occurs asynchronously on the server side.
Saving a Level-3
6) The script - savefunc(); is executed upon saving a draft, saving, or submitting.
7) The script - sbfunc(); is executed upon saving or submitting.
8) The script - various system functions are executed, which include sanitizing and converting all dates/input values into appropriate formats for storage in the database.
9) The page is then submitted and posted to the server.
Post-Saving Processes for a Level-3
The following processes are executed discreetly in the background after all Level 3 fields have been saved and updated.
10) The script - SystemCall onsave(); was initialized and called prior to step (9), but the actual processing occurs and is executed on the server side at this point.
11) Submit Logic - this checks the conditions and custom field values based on the saved field values.
12) Template Formulas - template formulas are executed based on the saved field values in the following order:
- L3 global formula
- L3 type formula
- L2 global formula
- L2 type formula
- L1 global formula
- L1 type formula
13) Workflows - workflows based on status are subsequently triggered.
Calculate Difference Between Two Dates in Hours - Custom Fields
Datediff() can be used to calculate difference between two dates in hours.
datediff([startdatefieldname],[enddatefieldname],'H')
Trigger a save action from a 'Special - Browser Script' Custom Field
Update the ButtonID value within the following syntax:
document.getElementById('submitbutton_2947').click();
Conditional SmartCheck Validation - Date Check with Business Days
If the FiscalSupport field value is Yes, and if the EventDate date field is less than Today's Date + 45 Business Days then return the following alert, "Event Date must be at least 45 days away"
if(form.getStr("cf_FinancialSupport") == "Yes"){ if(ssConvertDate(form.getStr("cf_EventDate"),"@dateformat@","yyyy-mm-dd") < "<!--@sscalculation(SS_FUNC.addbusdays('@date(currentdate)@',45))-->") { result.isPassed=false; result.addMsg("cf_@EventDate.id@","Event Date must be at least 45 days away"); }}
Generate a Dynamic URL directing to a Level 1 or 2 Record
Level-1
https://alias.smartsimple.com/Apps/app_editevent.jsp?appid=xxxxxx&eventid=@opportunityid@
- Replace the appid=xxxxxx with your unique UTA ID housing the Level-1 record, found from System Administration (gear icon) >> Tracking Applications >> [Application ID] column.
Level-2
https://alias.smartsimple.com/Apps/app_editevent.jsp?appid=xxxxxx&eventid=@eventid@
- Replace the appid=xxxxxx with your unique UTA ID housing the Level-2 record, found from System Administration (gear icon) >> Tracking Applications >> [Application ID] column.
Retrieve the total sum of all Level-2 "Payment" Activity [Amount Paid] custom field values that have a status of "Paid" from within a Level-1 Record
[#(?object=activity::criteria=typeid=67382 && statusid=67400::groupfunction=sum)$amountPaid.value$#]
- Replace typeid=67382 with the ID value corresponding to your target Activity Type. In this example, the Level-2 "Payment" TypeID is 67382.
- Replace statusid=67400 with the ID value corresponding to your target Activity Status. In this example, the Level-2 "Paid" StatusID is 67400.
- Replace the $amountPaid$ variable with the target Level-2 Custom Field Name. In this example, the Level-2 [Amount Paid] Custom Field is named amountPaid.
- The .value suffix retrieves the stored value of the amountPaid field.