Standard Integrations

System integration options including REST services

Docusign Integration

Prereq

To set up DocuSign integration an account that meets one of the following criteria is needed.

To use the integration, the uploading user only needs a regular eSignature subscription.

The integration will initially be created in demo mode and has to be approved, before it can be moved to production.
Approval requires 20 consecutive successful uploads performed within the last 30 days.
After that, an account with the proper access permissions has to sign in and the integration will be transferred to their account.

Setup in DocuSign

First: Sign in with an admin account and create a new "Integration" under "Settings" -> "Integrations" -> "Apps and Keys". Give it a descriptive name. This name will be shown to all who upload documents via the integration.

Second: Add a "Secret Key", save it. This is needed for docuSignSecretKey.

Third: Under "Redirect URIs" provide a URL using the following syntax:
https://[domain]/[TS-app-name]/[docuSignAuthCallbackUrl]

URL Example: https://omega.tempusserva.dk/TempusServa/main?command=dk.tempusserva.signing.docusign.PageLoginCallback

Setup in TS

There are 11 parameters available. Seven of these (marked with an asterisk below) must be set for the integration to work:

The Field Type Component for which DocuSign upload should be available must be changed from "Files: Documents" to "Files: Documents with signing".

docuSignActive

To enable the DocuSign functionality, this has to be set to "true".

docuSignLog

This is used for debugging and should not be enabled in production.
It enables debuggin-logs on all uploads, both in TS and in DocuSign, thus breaking confidentiality, because all parameters will be saved to a log somewhere.

docuSignApiHost

This parameter is account-dependant.
It can be found on the "Apps and Keys" page in DocuSign, labeled "Account Base URI".

docuSignAuthHost

This parameter should always be "https://account-d.docusign.com/oauth/" when testing the integration and "https://account.docusign.com/oauth/", when the integration is in production.

docuSignHost

This parameter is account-dependant. It is used to redirect the user, after a successful upload.
It's value should be "https://appdemo.docusign.com" during testing.
The production value is found by signing in with an account, that will be using the integration, and then copying the URL from the browser. Remember to only copy from beginning to end of docusign.com, don't include the trailing /.

docuSignAccountId

This attribute is account-dependant.
It can be found on the "Apps and Keys" page in DocuSign, labeled "API Account ID".
It's a GUID, formatted like this: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

docuSignIntegrationKey

This parameter is integration-dependant.
It can be found on the "Apps and Keys" page in DocuSign, or when viewing the details about the integration.
It's a GUID, formatted like this: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

docuSignSecretKey

This parameter is integration-dependant.
It can be found when viewing the details about the integration, in DocuSign.
You will only have access to the entire key when creating it, but you can just add a new one if the key is lost. Remember to delete the old one.
It's a GUID, formatted like this: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

docuSignAuthCallbackUrl

This parameter I static and should always be
"main?command=dk.tempusserva.signing.docusign.PageLoginCallback".

docuSignEventCallbackUrl

This parameter is static and should always be
"docusign-event-callback".

docuSignBrandId

This parameter is optional.
In DocuSign it is possible to create "Brands" ("Settings" -> "Account" -> "Brands").
All brands have a unique ID, it doesn't have to be the owner of the integration that creates the brand.
To enable custom branding in email, the signing formula, etc., input the brandID here.
If this parameter is left is empty, the default DocuSign branding will be used.
It's a GUID, formatted like this: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

Moving to production

When moving the integration to production, the following should be taken into account.

Make sure to complete 20 successful uploads in a row within 30 days.
Uploads don't have to be full featured documents, empty ones will do, and they don't have to be different documents, you can upload the same document 20 times.

If the production account is different from the test account, the following parameters should be updated:

Make sure to change the following parameters:

If the TS Application for test and production are different (different base URL), remember to add the "Redirect URIs" in DocuSign. And make sure that docuSignLog is set to false.

E-Boks doc2mail


E-Boks doc2mail

Install components

Before you start ensure Java 8 is the default

Certificate

Ensure you have a valid certificate

sudo nano /mnt/sda/certs/doc2mail.pke

Copy paste contents of the certificate

sudo chmod 777 /mnt/sda/certs/doc2mail.pke

Binaries

Download OneTooX implementation

cd /mnt/sda/deploy
sudo wget https://www.tempusserva.dk/install/doc2mail/doc2mail.zip
unzip doc2mail.zip
sudo mv lib doc2mail
cd doc2mail
sudo chmod 777 *
E-Boks doc2mail

Test commandline setup

In this step you will configure and test the configuration for the commandline

Update the parameters below

Execute the following command

java -cp .:/mnt/sda/deploy/doc2mail/* dk.doc2mail.client.FileUploaderClient --address "https://privat.doc2mail.dk/delivery/FileUploader.asmx" --certificate "/mnt/sda/certs/doc2mail.pke" -i "/tmp/eboks_test.pdf" --title "Oplysningsskemaet" -d ebokskmdprint -u "domainX\userY" -t "tempus serva" --ss "Oplysningsskema" --testmode 3 -r 1234561234 --rt CPR

A success message will look something like

 <uploadStatus>
   <deliveryInformation>
       <destination>5</destination>
       <errorCode>0</errorCode>
       <id>148069122</id>
       <mailPriority>B</mailPriority>
       <responseInfo>No response</responseInfo>
       <status>OK</status>
       <succeeded>true</succeeded>
   </deliveryInformation>
   <message>OK</message>
   <success>true</success>
   3379
 </uploadStatus>
E-Boks doc2mail

Server configuration: Linux

In this step you will deploy the commandline configuration

Make the following substitutions

The connection string should look something like

java -cp .:/mnt/sda/deploy/doc2mail/* dk.doc2mail.client.FileUploaderClient --address "https://privat.doc2mail.dk/delivery/FileUploader.asmx" --certificate "/mnt/sda/certs/doc2mail.pke" -i "$DOCUMENT" --title "$TITLE" -d ebokskmdprint -u "domainX\userY" -t "tempus serva" --ss "Oplysningsskema" --testmode 0 -r $CPR --rt CPR

Create execution script

cd /mnt/sda/deploy/doc2mail
sudo nano send.sh

Paste the execution script (above)

DOCUMENT=$1
CPR=$2
TITLE="$3 $4 $5 $6 $7"
java -cp .:/mnt/sda/deploy/doc2mail/* dk.doc2mail.client.FileUploaderClient --address "https://privat.doc2mail.dk/delivery/FileUploader.asmx" --certificate "/mnt/sda/certs/doc2mail.pke" -i "$DOCUMENT" --title "$TITLE" -d ebokskmdprint -u "domainX\userY" -t "tempus serva" --ss "Oplysningsskema" --testmode 0 -r $CPR --rt CPR

The set up permissions for the script

sudo chmod 777 send.sh

Copy the value to the server configuration parameter

  1. Modules > Static content > Add
  2. Set title = eboksIntegrationTemplate
/mnt/sda/deploy/doc2mail/send.sh @@DOCUMENT@@ @@CPR@@ @@TITLE@@

Set doc2mail as ebox provider

  1. Edit the setting eboksProvider (url: ServerSettingSingle.do?PolicyName=eboksProvider&DataType=3)
  2. Set the value to: doc2mail

Activate token rewrites

  1. Edit the setting interfaceTokenRewrite (url: ServerSettingSingle.do?PolicyName=interfaceTokenRewrite&DataType=1)
  2. Set the value to true
  3. Edit the setting interfaceTokenRewriteUrl (url: ServerSettingSingle.do?PolicyName=interfaceTokenRewriteUrl&DataType=3)
  4. Set the value to https://svar.link/FOOBAR/
    • FOOBAR is the name of your application as registered in svar.link

Reboot the server

E-Boks doc2mail

Server configuration : Windows

In this step you will deploy the commandline configuration

Make the following substitutions

The connection string should look something like

java -cp .:/mnt/sda/deploy/doc2mail/* dk.doc2mail.client.FileUploaderClient --address "https://privat.doc2mail.dk/delivery/FileUploader.asmx" --certificate "/mnt/sda/certs/doc2mail.pke" -i "@@DOCUMENT@@" --title "@@TITLE@@" -d ebokskmdprint -u "domainX\userY" -t "tempus serva" --ss "Oplysningsskema" --testmode 0 -r @@CPR@@ --rt CPR

Copy the value to the server configuration parameter

  1. Modules > Static content > Add
  2. Set title = eboksIntegrationTemplate
  3. Set value the string above

Set doc2mail as ebox provider

  1. Edit the setting eboksProvider (url: ServerSettingSingle.do?PolicyName=eboksProvider&DataType=3)
  2. Set the value to: doc2mail

Activate token rewrites

  1. Edit the setting interfaceTokenRewrite (url: ServerSettingSingle.do?PolicyName=interfaceTokenRewrite&DataType=1)
  2. Set the value to true
  3. Edit the setting interfaceTokenRewriteUrl (url: ServerSettingSingle.do?PolicyName=interfaceTokenRewriteUrl&DataType=3)
  4. Set the value to https://svar.link/FOOBAR/
    • FOOBAR is the name of your application as registered in svar.link

Finally reboot the server

Sending emails

Preparations

Get the information of the outbound server

Note that the SMTP server may be the same as the IMAP or POP server

Setup in Tempus Serva backend

Go to: Designer > Modules > Configuration

Policy_reference#Mail_server

Alias Empty Meaning Example
smtpServer No URL for the outgoing SMTP server send.one.com
smtpSystemEmail No Sender address on email sent from the server noreply@acme.com
smtpUsername Yes Account name for sending emails noreply@acme.com
smtpPassword Yes Password for the above account secret1234

Communication with the SMTP server can be tweaked using

Alias Meaning Example
smtpUseTLS Use TLS communication true
smtpMailDelay Throtling between each mail (seconds) 500
smtpSendRetries Number of attemts to send each mail 3


In order to test applications a testmode can be activated

Alias Meaning Example
smtpTestMode Activates the test mode true
smtpTestEmail Email that receives all emails when in testmode someone@acme.com

Embed TS in other sites

To embed the output of a public codeunit, on another website, the following code can be used.

<div id="tsContent"></div>
<script type="text/javascript">
    $.ajax({
        url: 'https://[SYSTEM-DOMAIN]/[APP-NAME]/mainpublic?command=[CODEUNIT-NAME]]',
        success: function(data) {
            $('#tsContent').html($(data).find(".mainContent").html());
        },
    });
</script>

It requires jQuery to be loaded beforehand.

MitID Integration

What it does

We have a generic integration to Criipto (a MitID, and other eID, broker) and an account, allowing for sign in and document signing with MitID/nemID.

Sign in

Sign in can be setup as a webinterface or as SSO from the login-page (not fully supported yet), the authentication method isn't available in the dropdown for the webinterface, as of writing, it has to be set through the database (the live database).

UPDATE forminterface SET AuthenticationType = 5 WHERE InterfaceID = [ID];

Document signing

One or multiple documents can be send for signature, one or more people can sign the batch and it is possible to enforce CVR or CPR. This process can be initiated from a StatusAction or be accessing a url.

A page is appended to the signed documents showing who signed it and when, in the order they signed it.

Prereq

To setup this an "Application" has to be set up in Criipto, one for sign in and one for signatures, and a CNAME dns-record has to be created.

The ID's and secrets created here will be needed later.

Setup in Criipto

First, a domain has to be added.

Haed to the Criipto Dashboard, select "Domains" in the menu, make sure that you are in "Production", click "Add production domain".

Name it [customer]-eid.tsnocode.com and head to CloudFlare and add a CNAME record that points to idp.criipto.id.

Once the domain is active you can progress.

Sign in

Coming

Document signing

Requires version 7336 or newer.

Head to "Application" in the Criipto menu, click "Add signatures application" (if it exits), otherwise click "Add login application" and add ?tags=signatures to the end of the url.

Name the application [customer] eSign, select their domain and check the eID's that should be available, select java as technology.

A secret might pop up or be shown, take note. It is possible to add more after the fact and re-issue them.

Setup in TS

There are a lot of parameters available. Some of these must be set for the integration to work, depending on the integration.

Sign in

Coming

Policies

Document signing

To start the signing process, setup the configuration and execute a Status Action that executes the codeunit dk.tempusserva.signing.criipto.CriiptoStatusAction or dk.tempusserva.signing.criipto.CriiptoStatusActionGenerator or dk.tempusserva.signing.criipto.CriiptoStatusActionGeneratorAlt or access a url with command=dk.tempusserva.signing.criipto.CriiptoPage&SagID=[SagID]&DataID=[DataID] (not ready).

This will try to lookup and send the document(s) out for signing.

Configurations

Configuration Description
Signer.MultipleSigners Whether multiple signers is allowed (true/false)
Signer.MaximumSigners How many signatures are needed. Defaults to "COUNT", which counts the number of signers, when using MultipleSigners, otherwise 1. Can otherwise be set to a number.
Signer.ExpiresInDays Number of days the recipient has to sign the document. Default is 30.
Signer.FieldMaximum Not implemented
Signer.FieldFil * System name for the field with documents that should be send, all documents found here will be send. Defaults to "FILES". Also used to store generated files.
Signer.FieldCPR System name for the field with a CPR, that the signer has to have to sign the document. Also used with MultipleSigners.
Signer.FieldCVR System name for the field with a CVR, that the signer has to have to sign the document. Also used with MultipleSigners.
Signer.FieldEmail * System name for the field with an email, that will be notified about the signature request. Also used with MultipleSigners. Defaults to "EMAIL".
Signer.FieldSigners System name for a list-of-children-field. All records found here will be required to sign the document. Required when using MultipleSigners.
Signer.StatusError Status that the record should enter if the signature request failed (was rejected or timed out). Defaults to 0.
Signer.StatusSigned Status that the record should enter when all signatures are collected. Defaults to 0.
Signer.StatusUploaded Status that the record should enter when it has been uploaded to signing service. Defaults to 0.
Signer.StatusDisableCodeunits Whether codeunits should be executed or not, when the signing completes or fails. Defaults to false (do execute).
Signer.EmailSubject The subject of the email send to the signer. Defaults to "Dokument til signering".
Signer.EmailBody The email-body of the email send to the signer. Defaults to "Du kan underskrive her: {LINK}".
Signer.NotificationSubject The subject of the email send to EmailWarner, when all signatures have been collected. Defaults to "Dokument til signering er blevet underskrevet"
Signer.NotificationBody The body of the email send to EmailWarner, when all signatures have been collected.

Defaults to "Alle parter har nu underskrevet dokumentet. {LINK}". Links to the record.

Signer.NotificationBodyExt The body of the email send to all signers of a document, when all have signed.

Defaults to "Alle parter har nu underskrevet dokumentet. Du kan downloade det underskrevne dokument her: {LINK}". Links to the signed document at Criipto.

Signer.EmailWarner Can be an email or the system name of a field containing an email.

The email found here will be notified when a signature fails and completes. If an email is not found, the email of the current user will be used, if not a status action. Required for status action.

Signer.WarningSubject The subject of the email send to EmailWarner, when a signature request fails. Defaults to "Dokument til signering blev afvist".
Signer.WarningBody The body of the email send to EmailWarner, when a signature request fails. Defaults to "En underskrift blev afvist. {LINK}". Links to the record.
Signer.CriiptoClientID * The client ID from Criipto application.
Signer.CriiptoClientSecret * The client secret from Criipto application.
Signer.OverwriteOnReupload true/false, default false. If enabled the system allows re-sending a record for signing, overwriting the old one.
Signer.FileName Name of generated file, defaults to kontrakt.docx, used by CriiptoStatusActionGenerator
Signer.TemplateID ID of template to be rendered and saved before sending it of to be signed, used by CriiptoStatusActionGenerator
Signer.FileNameAlt Name of generated file, defaults to kontrakt.docx, used by CriiptoStatusActionGeneratorAlt
Signer.TemplateIDAlt ID of template to be rendered and saved before sending it of to be signed, used by CriiptoStatusActionGeneratorAlt

OLAP

OLAP

OLAP example

We have a solution

The solution contains the following lookup fields

It also has some decimal values

In our reporting we want to see distributions by

Setting up the cube

A new OLAP cube is set up in: "Integration" > "OLAP cubes" > "Add"

Basic information

Cube definition ("Cube Schema XML")

For further help to designing schemas please refer to the following ressources

<Cube name="sample1cube">
  <Table name="data_changemanagement"/>
  <Dimension name="Scope" foreignKey="TASKTYPE">
    <Hierarchy hasAll="true" primaryKey="LookupID">
    <Table name="formfieldlookup"/>
      <Level name="Type" column="Value" uniqueMembers="true"/>
    </Hierarchy>
  </Dimension>
  <Dimension name="Type" foreignKey="TYPE">
    <Hierarchy hasAll="true" primaryKey="LookupID">
    <Table name="formfieldlookup"/>
      <Level name="Type" column="Value" uniqueMembers="true"/>
    </Hierarchy>
  </Dimension>
  <Dimension name="Status" foreignKey="StatusID">
    <Hierarchy hasAll="true" primaryKey="StatusID">
    <Table name="formstatus"/>
      <Level name="Type" column="Status" uniqueMembers="true"/>
    </Hierarchy>
  </Dimension>
  <Dimension name="Period" type="TimeDimension">
    <Hierarchy name="Periode" hasAll="true" allMemberName="All period">
      <Table name="data_changemanagement"/>
      <Level name="Aar" levelType="TimeYears" uniqueMembers="true">
        <KeyExpression>
          <SQL dialect="mysql">Year(CreatedAt)</SQL>
          <SQL dialect="generic">YEAR</SQL>
        </KeyExpression>
      </Level>
      <Level name="Kvartal" uniqueMembers="false" levelType="TimeQuarters">
        <KeyExpression>
          <SQL dialect="mysql">Quarter(CreatedAt)</SQL>
          <SQL dialect="generic">Quarter</SQL>
        </KeyExpression>
      </Level>
      <Level name="Maaned" uniqueMembers="false" levelType="TimeMonths">
        <KeyExpression>
          <SQL dialect="mysql">Month(CreatedAt)</SQL>
          <SQL dialect="generic">Month</SQL>
        </KeyExpression>
      </Level>
    </Hierarchy>
  </Dimension>
  <Measure name="Revision" column="Revision" aggregator="sum" formatString="Standard"/>   
  <Measure name="Estimate" column="ESTIMATTIMER" aggregator="sum" formatString="Standard"/>   
  <Measure name="Realized" column="REALISERETTIMER" aggregator="sum" formatString="Standard"/>   
</Cube>

MDX query ("Cube Query MDX")

For further help to designing queries please refer to the following ressources

SELECT
  NON EMPTY {([Measures].[Estimate],[Measures].[Realized])} ON COLUMNS,
  NON EMPTY {([Period],[Type],[Status])} ON ROWS
FROM [sample1cube]

Results

The cube is acccesed via this URL (or press "test" form the OLAP overview) http://YOUR_DOMAIN/TempusServa/olapview.jsp?query=sample1

image.png

image.png

OLAP

Schema cheatsheet

Introduction

The below paragraphs contains sample snippets for your OLAP schema.

Precise documentation on how to define a schema, can be found at: http://mondrian.pentaho.com/documentation/schema.php

Schema structure overview

Defining dimensions for related values

Standard lookup value

The cube schema below only needs adjustment for the system name of the lookup field.

Structure

Solution as displayed "Sample solution" : "Category" = xxx
Solution system names sample : CATEGORY = xxx
Database table names data_sample : CATEGORY = xxx

Data model

Cube schema

...
<Dimension name="Example" foreignKey="CATEGORY">
   <Hierarchy hasAll="true" primaryKey="LookupID">
      <Level name="Category" column="Value" uniqueMembers="true" />
   </Hierarchy>
</Dimension>
...

Simple choice value

The cube schema below only needs adjustment for the system name of the lookup field.

Structure

Solution as displayed "Sample solution" : "My choice" = xxx
Solution system names sample : CHOICE = xxx
Database table names data_sample : CHOICE = xxx

Data model

Cube schema

...
<Dimension name="Example" foreignKey="CHOICE">
   <Hierarchy hasAll="true" primaryKey="ChoiceID">
      <Level name="Answer" column="Value" uniqueMembers="true" />
   </Hierarchy>
</Dimension>
...

Standard record Status

The cube schema below can be copied directly without modification: The status properties and tablenames are allways the same.

Structure

Solution as displayed "Sample solution" : "Status" = xxx
Solution system names sample : "StatusID" = xxx
Database table names data_sample "StatusID" = xxx

Data model

Cube schema

...
<Dimension name="Example" foreignKey="StatusID">
   <Hierarchy hasAll="true" primaryKey="StatusID">
      <Level name="Status" column="Status" uniqueMembers="true" />
   </Hierarchy>
</Dimension>
...

Defining dimensions for related records

Structure

Solutions as displayed "Some child" : "Parent" -> "Father or mother"
Solution system names child : PARENT -> parent
Database table names data_child : PARENT -> data_parent

Data model

Cube schema

...
<Dimension name="Example" foreignKey="PARENT">
   <Hierarchy hasAll="true" primaryKey="DataID" primaryKeyTable="data_parent">
      <Level name="Parent" column="PARENTNAME" uniqueMembers="true" />
   </Hierarchy>
</Dimension>
...

Note that the schemas for multi join tables are written from "inside out", that might seem counterintuitive i relation to what you want to display in the cube later.

Structure

Solutions as displayed "Some child" : "Parent" -> "Father or mother"  : "Grand parent" -> "Grandma and Grandpa's"
Solution system names child : PARENT -> parent : GRANDPARENT -> grandparent
Database table names data_child : PARENT -> data_parent : GRANDPARENT -> data_grandparent

Data model

Cube schema

...
<Dimension name="Example" foreignKey="PARENT">
   <Hierarchy hasAll="true" primaryKey="DataID" primaryKeyTable="data_parent">
      <Join leftKey="GRANDPARENT" rightKey="DataID" />
      <Level name="Grandparent" table="data_grandparent" column="GRANDPARENTNAME" uniqueMembers="true" />
      <Level name="Parent" table="data_parent" column="PARENTNAME" uniqueMembers="true" />
   </Hierarchy>
</Dimension>
...

Defining dimensions for inline values

Text values

Cube schema

 ...
 <Dimension name="Category">
     <Hierarchy hasAll="true">
         <Level name="Name" column="NAME" uniqueMembers="true"/>
     </Hierarchy>
 </Dimension>
 ...

Year/integer values

Cube schema

 ...
 <Dimension name="Period" type="TimeDimension">
     <Hierarchy hasAll="true">
         <Level name="Aar" column="YEAR" type="Numeric" uniqueMembers="false" levelType="TimeYears"/>
     </Hierarchy>
 </Dimension>
 ...

Date / datetime values

Cube schema

...
<Dimension name="Period" type="TimeDimension">
   <Hierarchy name="Periode" hasAll="true" allMemberName="All period">
      <Level name="Aar" levelType="TimeYears" uniqueMembers="true">
         <KeyExpression>
            <SQL dialect="mysql">Year(CreatedAt)</SQL>
            <SQL dialect="generic">YEAR</SQL>
         </KeyExpression>
      </Level>
      <Level name="Maaned" uniqueMembers="false" levelType="TimeMonths">
         <KeyExpression>
            <SQL dialect="mysql">Month(CreatedAt)</SQL>
            <SQL dialect="generic">Month</SQL>
         </KeyExpression>
      </Level>
   </Hierarchy>
</Dimension>
...


Enumeration values

Cube schema

 ...
 <Dimension name="Severity">
     <Hierarchy hasAll="true" primaryKey="SEVERITY">
         <InlineTable alias="enumeration">
         <ColumnDefs>
             <ColumnDef name="id" type="Numeric"/>
             <ColumnDef name="desc" type="String"/>
         </ColumnDefs>
         <Rows>
             <Row>
                 <Value column="id">1</Value>
                 <Value column="desc">High</Value>
             </Row>
             <Row>
                 <Value column="id">2</Value>
                 <Value column="desc">Medium</Value>
             </Row>
             ... more values ...
        </Rows>
     </InlineTable>
     <Level name="Severity" column="id" nameColumn="desc" uniqueMembers="true"/>
 </Hierarchy>
 </Dimension>
 ...

Defining measures

Normal values

Measures are allways numeric values, that can be agggated to higher levels (the levels in the dimensions)

Type Aggregator Examples
Sums SUM Time spent, costs
Average AVG Process time


Cube schema

Calculated values

OLAP

Analyse Activity

User activity will display an OLAP cube for changes and updates to certain solutions.

Changes are defined by updates to the underlying record.

How to activate this feature

OLAP

Analyse Flowsteps

User activity will display an OLAP cube for flow in each process step for certain solutions.

The total flow time is defined as the time span between entry and exit point in time for each flow step (status).

Furthermore each status can have targets for good performance defined:

How to activate this feature

OLAP

Analyse Flowtotal

User activity will display an OLAP cube for total flow time to certain solutions.

The total flow time is defined as the time span between creation and point in time where a final status i reached.

Furthermore each solution can have targets for good performance defined:

How to activate this feature

WebDAV

About our WebDAV implementation

Supported document types: Word, Excel, Powerpoint.

The implementation does not require SSL to be enabled on the server, but it is recommended.


Sometimes the action of saving a file, that was opened using WebDAV will fail, but only the fist time, if it happens at all.

To fix this, you just have to save the document again, and the issue will be gone for you, until you re-sign-in.

How to enable

Toggle the policy webdavSupport and webdavSessionTokens to true.

image.png

When WebDAV is enabled, the files-field, will add tiny pencils next to the supported file-types.

Clicking on the file icon will prompt the file to be opened in the associated application. Clicking on the filename, will prompt a download of the file.


You can control how long the auth-tokens are valid for, using policy webdavSessionLifetime.
You can control whether a token should automatically be re-validated if it times out using policy webdavSessionTokensRevalidate.

Testing WebDAV

Upload a word or excel file to a file field and save the record.
Re-open the record and click the type icon with the pencil next to the file name.
If the appropriate program opens, edit the file and save it.
Close the program.
Open the file again (either download it or re-open it via WebDAV), if your changes are still there, WebDAV is working.

Common config issues

The following policies have to be set up correctly, otherwise the WebDAV feature will not work.

applicationServer
applicationIsBehindAReverseProxy
applicationName
applicationBasePath
securitySslPages

Map WebDAV as a drive

Add a network location with the address https://[domain]/[app]/webdav/drive/.

On linux, replace the protocol with davs.

Enabling basic auth to your server

Office has stopped officially supporting Basic-auth, which is the backup authentication for our implementation.

To allow Office to connect to your server, and authenticate using Basic-auth, execute the following command, as admin, from the commandline.

REG ADD HKEY_CURRENT_USER\Software\Policies\Microsoft\Office\16.0\Common\Identity /t REG_EXPAND_SZ /v basichostallowlist /d "HOSTNAME"

Where HOSTNAME is the domain of your server, eg. wiki.tsnocode.com.

How to enable support in LibreOffice on Debian

Run the following commands

xdg-mime default libreoffice-writer.desktop  x-scheme-handler/ms-word
xdg-mime default libreoffice-calc.desktop  x-scheme-handler/ms-excel
xdg-mime default libreoffice-impress.desktop  x-scheme-handler/ms-powerpoint

LDAP

Basic configuration is the name of the LDAP server and domain that is binded to the application

All configuration options are found in: Policy#Active directory

Synchronization options

Different options for LDAP integration exists

  1. Validate credentials: Check username/password against LDAP
  2. Maintain groups: Add missing groups as defined in the LDAP
  3. Create missing users: Create users with correct LDAP credentials

Credential validation (1) is mandatory, while group synchronization (2) and automatic user creation (3) is optional.

  1. ldapAuthentication
  2. ldapMaintainGroupsOnLogon
  3. ldapCreateUsers

Groups and usersd in Tempus Serva will be marked with the LDAP path of the object. This path is also editable, so that groups or users can be mapped to other names in Tempus Serva than in the LDAP.

Failover mechanism

In case the LDAP is not responding the server can be allowed to use local application credentials:

The server will initially try to validate against the LDAP, after which the validation is done against the local user table. In order to allow this operation, an encrypted copy of the user password is stored on every successfull LDAP authentication. Note this behaviour is only active if the fallback authentication is enabled.

LDAP service account

In order to communicate with the LDAP server, the Tempus Serva application will need its own acount to carry out many of the synchronization operations:

No permissions except lookup rights are required for this role.

Jobnet

Jobnet

Jobnet v1

It's possible to upload jobs to JobNet using the tsJobnet servlet.
This site documents the interface.

Usage

Send a POST or GET-request to the servlet-endpoint "/addJob" with the required parameters as url-parameters.
If a parameter is missing, the servlet will return HTTP-CODE 403 and a message in the body, telling you what was wrong.

All fields

Parameter Type Default Required Description
ApplicationDetails.ApplicationMethods.ApplyByEmail String (email)   No  
ApplicationDetails.ApplicationMethods.ApplyByLetter Boolean false No  
ApplicationDetails.ApplicationMethods.ApplyByTelephone String (phone-number)   No  
ApplicationDetails.ApplicationMethods.ApplyOnline String (url)   No  
ApplicationDetails.Description String   No A short description of the job, not the full description, that is JobDetails.Description
ApplicationDetails.JobContactList.JobContactType.Email String (email)   Yes  
ApplicationDetails.JobContactList.JobContactType.PersonNameStructure.PersonGivenName String   Yes  
ApplicationDetails.JobContactList.JobContactType.PersonNameStructure.PersonSurnameName String   Yes  
ApplicationDetails.JobContactList.JobContactType.Title String   Yes  
ApplicationDetails.JobContactList.JobContactType.HidePhoneNumbers Boolean true Yes  
ApplicationDetails.JobContactList.JobContactType.TelephoneNumberStructure.MobileNumber String (phone-number)   No  
ApplicationDetails.JobContactList.JobContactType.TelephoneNumberStructure.PrimaryNumber String (phone-number)   No  
ApplicationDetails.JobContactList.JobContactType.TelephoneNumberStructure.SecondaryNumber String (phone-number)   No  
ApplicationDetails.JobContactList.JobContactType.TelephoneNumberStructure.Telefax String (phone-number)   No  
ApplicationDetails.Referral String   No  
HiringOrganizationDetails.AddressStructure.CountryCode String   Yes  
HiringOrganizationDetails.AddressStructure.FloorIdentifier String   No  
HiringOrganizationDetails.AddressStructure.MunicipalityId Integer   Yes  
HiringOrganizationDetails.AddressStructure.MunicipalityName String   Yes  
HiringOrganizationDetails.AddressStructure.PostalCity String   Yes  
HiringOrganizationDetails.AddressStructure.PostalCode String   Yes  
HiringOrganizationDetails.AddressStructure.StreetBuildingIdentifier String   Yes  
HiringOrganizationDetails.AddressStructure.StreetName String   Yes  
HiringOrganizationDetails.AddressStructure.SuiteIdentifier String   No  
HiringOrganizationDetails.BranchCode Integer   Yes  
HiringOrganizationDetails.BranchDescription String   Yes  
HiringOrganizationDetails.Contact.Email String (email)   No  
HiringOrganizationDetails.Contact.PersonNameStructure.PersonGivenName String   Yes  
HiringOrganizationDetails.Contact.PersonNameStructure.PersonSurnameName String   Yes  
HiringOrganizationDetails.Contact.Title String   No  
HiringOrganizationDetails.Contact.PrimaryNumber String (phone-number)   No  
HiringOrganizationDetails.Contact.SecondaryNumber String (phone-number)   No  
HiringOrganizationDetails.Contact.Telefax String (phone-number)   No  
HiringOrganizationDetails.CvrNumber String   No  
HiringOrganizationDetails.Name String   Yes  
HiringOrganizationDetails.PNumber String   No  
HiringOrganizationDetails.Url String   No  
JobAdDetails.JobPublishDates.LastModifiedDate String   No  
JobAdDetails.JobPublishDates.PublishEndDate String   Yes Has to be after PublishStartDate, but at the longest 8 weeks after
JobAdDetails.JobPublishDates.PublishStartDate String   Yes Has to be today or after
JobAdDetails.Logo String (base64)   No max. 200x135px / 100KB
JobAdDetails.PostedBy.Email String (email)   No  
JobAdDetails.PostedBy.PersonNameStructure.PersonGivenName String   Yes  
JobAdDetails.PostedBy.PersonNameStructure.PersonSurnameName String   Yes  
JobAdDetails.PostedBy.Title String   No  
JobAdDetails.PostedBy.ContactGuid String   No  
JobAdDetails.PostedBy.PrimaryNumber String (phone-number)   No  
JobAdDetails.PostedBy.Telefax String   No  
JobAdDetails.PostedBy.UserRid String   No  
JobAdDetails.Type String Normal No Has to be one of "WageSubsidy", "HotJob", "Normal", "SpringStone", "Flexjob", "EarlyRetirement", "JobRotation", "EarlyRetiree", "CompanyInternship", "NormalAndEarlyRetiree", or"NormalAndEarlyRetireeWithHotJob"
JobDetails.AuthorityId Integer 0 No  
JobDetails.AuthorityPhoneNumber String (phone-number)   No  
JobDetails.Classification.EmploymentType String PermanentJob No Has to be "PermanentJob" or "LimitedPeriod"
JobDetails.Classification.IsEuresJob Boolean false No  
JobDetails.Classification.IsPublicSectorJob Boolean false No  
JobDetails.Classification.IsWorkInDenmarkJob Boolean false No  
JobDetails.Description String   Yes The description of the job. If it contains html (subset) it has to be wrapped in <![CDATA[]]>
JobDetails.DriversLicences Comma-List   No Required drivers licenses to apply for the job. Can be any combination of A1, A, B, BE, C, CE, D, DE, A10, AMa, AMb, A2, C1, D1, C1E, D1E, Taxi, Traktor, Truck, BusErhverv, DigitalFartskriver, EUGodsErhverv and EUBusErhverv, seperated by a comma
JobDetails.HidePhonenumbers Boolean false No  
JobDetails.IsAnonymousEmployer Boolean false No  
JobDetails.IsDisabilityFriendly Boolean false No  
JobDetails.JobDates.ApplicationDeadlineDate String (date)   Yes  
JobDetails.JobDates.EmploymentDate String (date)   No  
JobDetails.JobDates.StartAsSoonAsPossible Boolean false No  
JobDetails.JobLocation.Address.CountryCode String   Yes  
JobDetails.JobLocation.Address.FloorIdentifier String   No  
JobDetails.JobLocation.Address.MunicipalityId Integer   Yes  
JobDetails.JobLocation.Address.MunicipalityName String   Yes  
JobDetails.JobLocation.Address.PostalCity String   Yes  
JobDetails.JobLocation.Address.PostalCode String   Yes  
JobDetails.JobLocation.Address.StreetBuildingIdentifier String   Yes  
JobDetails.JobLocation.Address.StreetName String   Yes  
JobDetails.JobLocation.Address.SuiteIdentifier String   No  
JobDetails.JobLocation.NoLocalBusinessAddress Boolean false No  
JobDetails.NumberOfPositions Integer 1 No  
JobDetails.OccupationConceptUri String (JobnetConceptUri)   Yes  
JobDetails.Schedule.DailyWorkTime.Day Boolean false No  
JobDetails.Schedule.DailyWorkTime.Evening Boolean false No  
JobDetails.Schedule.DailyWorkTime.Night Boolean false No  
JobDetails.Schedule.DailyWorkTime.Weekend Boolean false No  
JobDetails.Schedule.WeeklyWorkTimeTypes String FullTime No Has to be PartTime or FullTime
JobDetails.Schedule.WorkHour.Max Integer   No Expected maximum of hours of work, a week, if PartTime
JobDetails.Schedule.WorkHour.Min Integer   No Expected minimum of hours of work, a week, if PartTime
JobDetails.Title String   Yes The title being hired for

Notes

At least one application method (ApplicationDetails.ApplicationMethods) has to be set.
At least one phonenumber has to be set for job-contact (ApplicationDetails.JobContactList.JobContactType.TelephoneNumberStructure).
If schedule (JobDetails.Schedule.WeeklyWorkTimeTypes) equals "FullTime", workhours (JobDetails.Schedule.WorkHour.Min and JobDetails.Schedule.WorkHour.Max) can't be set.
JobDetails.Schedule.WorkHour.Min has to be lower than JobDetails.Schedule.WorkHour.Max and between 0 and 36.
JobDetails.Schedule.WorkHour.Max has to be greater than JobDetails.Schedule.WorkHour.Min and between 1 and 36.
If schedule (JobDetails.Schedule.WeeklyWorkTimeTypes) Equals "PartTime", workhours (JobDetails.Schedule.WorkHour.Min and JobDetails.Schedule.WorkHour.Max) have to be set.

Jobnet

JobnetConceptUri

Jobs uploadet to JobNet require the parameter JobDetails.JobLocation.OccupationConceptUri to be set to a valid OccupationConceptUri.
A wrapper has been made for this, it is part of the JobNet servlet.

Usage

Send a POST or GET-request to the servlet-endpoint "/getOccupations".
If an error occurs, the servlet will return HTTP-CODE 403 or 500 and a message in the body, telling you what was wrong.
If the request is successful a JSONArray wil be returned.
Invalid OccupationConceptUri's will be returned, because of backwards-compatibility. Filter these via the "valid" attribute.

Sample

[
    {
        "valid": false,
        "description": "Borearbejdere (sten) betjener boremaskinen, der borer huller i stenblokke. De behandler granit, sandsten, marmor og skifer i overensstemmelse med specifikationerne.",
        "label": "borearbejder - sten",
        "uri": "http://data.star.dk/esco/occupation/2fbdc3fa-aeab-4e45-bccf-9421b84c687f"
    },
    ...
]

Link to QR codes

You can use our online QR coder to convert links to mobile phone QR codes.

Example:

https://omega.tempusserva.dk/qr/encode?https://docs.tsnocode.com/books/standard-integrations/page/link-to-qr-codes

As of version 11524 this servlet is now built into the platform and can be used like this:

qr?https://docs.tsnocode.com/books/standard-integrations/page/link-to-qr-codes

Transforming access tokens to QR codes

Assuming you allready have an interface for a solution, you can add a button to build QR codes containing the tokens for selected elements.

First create a field of the type Button: Script execution.

Then set up the JS to handle open a window with a code:

let url = "main?command=dk.p2e.blanket.codeunit.common.PagePublicTokenBuilderQR&interface=foobar&SagID=257&DataID=" + DataID;
window.open(url, "QR code", "width=300,height=300,menubar=no,resizable=no,toolbar=no,location=no");

In the above you will need to change

Oauth2 authentication

Oauth2 authentication

Understanding Oauth 2

Oauth authentication will put icons on the login page for fast and easy SSO wth multiple vendors.

The user will be authenticated if the email matches between the provider and the Tempus Serva user.

The following providers are supported.

From version 6191 it is possible to setup TS to create a new account, if a user signed in with oauth/sso and wasn't found among the existing users.

To do this enable the configuration oauthCreateNewUsersAllow and set their initial GroupID in the configuration oauthNewUserGroup.

Oauth2 authentication

Setting up SingleSignon

Before going into the detailed configuration please make sure https/SSL is enabled.

Set the following configurations to true

Next activate service icons on the login page

Google Oauth

Using an existing Google account , go to the [credentials section].

Navigate to "Credentials" in the left menu.

First setup Oauth messages in the Oauth conscent section

Next setup setup credentials

  1. Navigate back to credentials
  2. Click Create credentials
  3. Fill out the information
  4. Credentials are generated
  5. Copy credentials to your Tempus Serva configuration
    • oauthGoogleClient = [Client ID]
    • oauthGoogleSecret = [Client secret]
  6. Finally
    • oauthGoogleAllow = true


LinkedIn Oauth

Follow the guide

Copy credentials to

Enable

Callback URL

Facebook Oauth

Follow the guide

Copy credentials to

Enable

Callback URL

Azure Oauth

Follow the guide

Copy credentials to

Enable

Callback URL

ADFS Oauth

Follow the guide

Copy credentials to

Enable

Callback URL

WordPress

  1. Install and activate the plugin
  2. Enable the Oauth-server (Oath Server -> Settings -> Enable Oauth Server)
  3. Create a new client (Oauth Server -> Clients -> Add New Client)
    1. Give it a descriptive name
    2. Add the Redirect URI (Should be something like: https://[ts-hostname]/[ts-instance]/SignInWP)
    3. Assign it admin rights
    4. Save it
  4. Copy credentials to Configurations
    • oauthWPClient
    • oauthWPSecret
  5. Input wordpress domain/link to Configuration (no trailing /)
    • oauthWPHost
  6. Enable Configuration
    • oauthWPAllow

Outlook calendar

Exporting data items as calendar entrys

How to display an export to calendar on each data item

  1. Create a button: Parametrized URL
  2. Build an URL using the following parameters
    • title [field]
    • SagID [value]
    • DataID [value]
    • OPTION A
      • from [field]
      • minutes [field or value]
    • OPTION B
      • from [field]
      • to [field]
    • OPTIONAL
      • content [field]
      • hidelink [value]

Note that

Example configuration

 exportcard?SagID=1&DataID=[DataID]&title=COMPANY&content=AGENDA&from=MEETINGDATE&minutes=MINUTES
 exportcard?SagID=1&DataID=[DataID]&title=COMPANY&from=MEETINGDATE&minutes=60

Pentaho

Pentaho

Installing Pentaho CE

https://www.hitachivantara.com/en-us/pdfd/white-paper/pentaho-community-edition-installation-guide-for-windows-whitepaper.pdf

https://sourceforge.net/projects/pentaho/

Pentaho

Setting up Mondrian

https://rpbouman.blogspot.com/2016/03/need-mondrian-war-checkout-xmondrian.html

https://github.com/rpbouman/xmondrian

NOT https://sourceforge.net/projects/mondrian/

Pentaho

Connecting Mondrian to TS

Pentaho

Connecting Pentaho to Mondrian