Example custom functions

Example 1: Making sure percentages add up in a Q&A

Clause9’s standard Q&A conditions functionality let you easily check whether a certain number-answer is in a certain range — e.g., higher than 40 and lower than 100. However, the standard conditions do not allow you to create conditions that combine various answers together.

For example, assume you are making an employment contract for situations where employees can divide their time between three different positions (e.g., sales, marketing and IT). Obviously, for a full-time position, the percentages need to add up to 100% — if not, then some warning needs to be shown.

Questions to create

  • Create three different questions with number (integer) answers. Assign those questions the identifiers f1, f2 and f3 respectively in their options.

  • Create a warning question with a content such as “Warning: the percentages do not add up to 100%”.

Clojure code

Insert the following Clojure code in the condition attached to the warning-question, so that the warning-question will only be shown when the result of the Clojure-code is true.

(defn value-or-0 [id] 
    (or (answer id) 0))

(not= 100 
      (+ (value-or-0 "f1") (value-or-0 "f2") (value-or-0 "f3")))

We first define a Clojure-function that fetches the answer of the question with the specified identifier. If that answer happens to be nil — which would be the case when the end-user has not yet filled in any value — we return 0, otherwise we return the answer.

We then add the three percentages, and check whether they add up to exactly 100. If so, the result will be false (so that the warning will not be shown); otherwise the result will be true, so that the warning will indeed be shown.

Improvement

When none of the three percentages is filled in, the warning is also shown. It is probably advisable to only start showing the warning when at least one of the three percentages if filled in.

A first way to solve this, is by adding a subgroup of non-Clojure subconditions:

A second way to solve it, is by adapting the Clojure-code as follows:

(defn value-or-0 [id] 
    (or (answer id) 0))

(and (or (answer "f1") (answer "f2") (answer "f3"))
     (not= 100 
       (+ (value-or-0 "f1") (value-or-0 "f2") (value-or-0 "f3"))))

This code specifies that two conditions must be met for the warning-question to be shown:

  1. at least one of the percentages-questions must have its answer filled in

  2. all three percentages together must not be equal to 100

Showing the current total

Instead of showing a static warning (“Warning: the percentages do not add up to 100%”), it is more helpful to show the current total amount.

(defn value-or-0 [id] 
    (or (answer id) 0))

(defn total []
    (+ (value-or-0 "f1") (value-or-0 "f2") (value-or-0 "f3")))

(assoc question :title 
       {:en (str "Warning: the percentages do not add up to 100% " 
                 "(current total: " (total) "%)")})

To change the title of the warning, we assoc a new value in var question. (This var is predefined by Clause9’s Clojure runtime when customising questions.)

If other languages besides English would be required, then the specified map should be extended — e.g. with a string for French (:fr) or Dutch (:nl).

By the way, because the function value-or-0 is now used both in this custom function and in the previous Clojure-code for calculating the warning’s visibility condition, it could be useful to move this function to the central repository, and replace the calls — e.g., instead of (value-or-0 "f1") we would get (call "value-or-0", "f1"). The contents of the central repository function can then simply be (or (answer $1) 0) — the $1 refers to the first parameter that gets passed into this function, which would be "f1" in the given example.


Example 2: Creating a custom interface for a question

Suppose you allow your end-users to choose the legal entity for which the contract is being composed. Besides changing the address, VAT number, etc. this would also change the logo in the header of the document.

While Clause9’s standard tools allow you to predefine a list of entities, and then insert the relevant logo into the document’s header, the logo will not be visible towards the end-users until the document is effectively exported to DOCX / PDF (because headers and footers are deliberately not shown within the browser).

Using a “custom block” question and some Clojure code, you can however easily show this logo within the list of questions.

Questions to create

  • Create a question with text-answers that has three predefines: “Microsoft”, “Google” and “Apple”. Assign identifier “entity” to this question.

  • Create a “custom block” question.

Clojure code

Insert the following code into the custom block’s code box:

(when-let [entity-name  (answer "entity")]
  [:img {:style {:padding "10px"}
         :width "200px"
         :src (case entity-name
                 "Microsoft" "https://bit.ly/2MhZegg"
                 "Google" "https://bit.ly/2TWJwvp"
                 "Apple" "https://apple.co/3gEE4XE")}])
  • This code only shows something on the screen when the answer to the question with identifier entity is set (i.e., when one of the three entities is chosen).

  • The code uses so-called “Hiccup-style” Clojure-code for creating user interfaces in a browser (see an in-depth introduction). It essentially creates:

    • an image HTML-component

    • with a 10px style padding and a fixed width of 200px

    • with a reference to a URL that depends on the entity-name chosen

The results is as follows:


Example 3: Changing other Q&A answers upon changing a specific answer

Through change sets, Clause9 allows you to change datafields, terms, styling, etc. that apply when certain answers are given. However, it is not possible for an answer to change some other answer. Clojure functions allow you to resolve this limitation.

Suppose you are creating a contract and you want to give the user the option to pre-fill answers in a single click. For example, suppose you want to give the users the option to choose between “neutral” and “aggressive” default answers.

Questions to create

  1. Create a text-question with title “Which style do you want?” with identifier “style” that contains two predefined answers: “neutral” and “aggressive”. Set the “Free answers?” option to “Not allowed”.

  2. Create a yes/no-question “Is recourse allowed?” with identifier “recourse”.

  3. Create a currency-question “Which liability cap applies?” with identifier “cap” that contains two predefined answers (200 EUR and 5000 EUR).

Clojure code

(defn action-fn [q a]
  (case a
    "neutral" (do (set-answer "recourse" true)
                  (set-answer "cap" (->CurrencyValue 50000000 :EUR)))
    "aggressive" (do (set-answer "recourse" false)
                  (set-answer "cap" (->CurrencyValue 2000000 :EUR)))
    nil))

(assoc question :action-fn action-fn)

This code extends the question var (which is assigned the current question by Clause9 upon initialization of the Clojure environment) with an action-function.

This action-function takes two arguments (the question and the answer-value). It then checks which answer was given, and sets the answer of the two other questions to the desired values.

Note that the currency-values are integers multiplied by 10000 to make room for potential decimals.

The result is as follows:

Last updated