# Common Codeunits

# CodeunitTranslator

# IntegrationFieldFixCPR

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Cleans up external data in CPR format, for use in a scheduled integration.

String are cleaned using the CPR translateInput method. Data will be cleaned before inserting without the use of this codeunit, but lookups and such might fail if the CPR is formatted poorly.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Insert value in field mapping:

Designer &gt; Integration &gt; Import sources &gt; \[integration\] &gt; \[fieldmapping\] &gt; Codeunit handler

```
dk.p2e.blanket.codeunit.common.IntegrationFieldFixCPR
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">None.</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitTranslator](https://docs.tsnocode.com/books/codeunit-reference/chapter/translator)</span>
- <span class="mw-headline">Security: None</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.IntegrationFieldFixCPR</span>

# IntegrationFieldFixDate

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Cleans up external data in date format, for use in a scheduled integration.

String are cleaned using the date translateInput method. Data will be cleaned before inserting without the use of this codeunit, but lookups and such might fail if the date is not formatted as YYYY-MM-DD.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Insert value in field mapping Designer &gt; Integration &gt; Import sources &gt; \[integration\] &gt; \[fieldmapping\] &gt; Codeunit handler

```
  dk.p2e.blanket.codeunit.common.IntegrationFieldFixDate
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">\[All possible configurations and where to edit them\]</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitTranslator](https://docs.tsnocode.com/books/codeunit-reference/chapter/translator)</span>
- <span class="mw-headline">Security: None</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.IntegrationFieldFixDate</span>

# IntegrationFieldLookupKey

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Looks up another value based on the string provided, for use in a scheduled integration.

A lookup will be executed substituting the @VALUE@ in the SQL expression passed to the codeunit.

Note that the @VALUE@ is SQL escaped for security reasons.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Insert value in field mapping Designer &gt; Integration &gt; Import sources &gt; \[intergration\] &gt; \[fieldmapping\] &gt; Codeunit handler

```
dk.p2e.blanket.codeunit.common.IntegrationFieldLookupKey
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

Insert an SQL expression in:

\[fieldmapping\] &gt; Configuration values

Example:

```
 SELECT Name FROM user WHERE Email = '@VALUE@';
```

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitTranslator](https://docs.tsnocode.com/books/codeunit-reference/chapter/translator)</span>
- <span class="mw-headline">Security: None</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.IntegrationFieldLookupKey</span>

# IntegrationFieldValueMap

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Looks up another value based on the string provided, for use in a scheduled integration.

Values will be swapped from a list provided to this codeunit.

An empty string will be returned if no match can be found.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Insert value in field mapping Designer &gt; Integration &gt; Import sources &gt; \[integration\] &gt; \[fieldmapping\] &gt; Codeunit handler

```
dk.p2e.blanket.codeunit.common.IntegrationFieldValueMap
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

Insert value maps seperated by "@" in:

\[fieldmapping\] &gt; Configuration values

Example:

```
Tesla Model S@Large car
Hummer@Large car
Toyota Corolla@Medium car
Suzuki Swift@Small car
```

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitTranslator](https://docs.tsnocode.com/books/codeunit-reference/chapter/translator)</span>
- <span class="mw-headline">Security: None</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.IntegrationFieldValueMap</span>

# StatusAction

# SignNemIdActionStatus

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

1. Send a document from a document field to signing with NemID.
2. The user will be notified via email containing a link for where to sign the document
3. When signing a document is generated including a NemID signature
4. After signing the documents saved in the same field carrying the postfix \_signed

## <span class="mw-headline" id="bkmrk-how-to-set-up-1">How to set up</span>

Add a status action and set the codeunit Classname to: **dk.tempusserva.signing.nemid.SignNemIdActionStatus**

Set the following entity configurations

- **Signer.FieldFil** Field NAME containing the file to be signed
- **Signer.FieldFilID** Field ID containing the file to be signed
- **Signer.FieldEmail** Field NAME containing the email of the signer
- **Signer.FieldCPR** Reserved for future use (specify any field)
- **Signer.ServerToken** Code to connect to the server (ask your TS contact)
- **Signer.StatusError** StatusID to set on the data if failed
- **Signer.StatusSigned** StatusID to set on the data if succes
- **Signer.EmailSubject** Header on the email sent to the signer
- **Signer.EmailBody** Content of the email sent to the signer

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitStatusaction](https://docs.tsnocode.com/books/codeunit-reference/chapter/statusaction)</span>
- <span class="mw-headline">Security: none</span>
- <span class="mw-headline">Classpath: dk.tempusserva.signing.nemid.SignNemIdActionStatus</span>

# SignNemIdActionStatusGenerator

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

1. Generates a document based on a defined template
2. Send a document from a document field to signing with NemID.
3. The user will be notified via email. The message contains a link to where to sign the document
4. When signing a document is generated including a NemID signature
5. After signing, the document is saved in the same field carrying the postfix \_signed

All steps after 1 are the same as [SignNemIdActionStatus](https://docs.tsnocode.com/books/common-codeunits/page/signnemidactionstatus "Codeunit/StatusAction/SignNemIdActionStatus")

## <span class="mw-headline" id="bkmrk-how-to-setup-1">How to setup</span>

Add a status action and set the codeunit Classname to: **dk.tempusserva.signing.nemid.SignNemIdActionStatusGenerator**

Set the following entity configurations (same as [SignNemIdActionStatus](https://docs.tsnocode.com/books/common-codeunits/page/signnemidactionstatus "Codeunit/StatusAction/SignNemIdActionStatus"))

- **Signer.FieldFil** Field NAME containing the file to be signed
- **Signer.FieldFilID** Field ID containing the file to be signed
- **Signer.FieldEmail** Field NAME containing the email of the signer
- **Signer.FieldCPR** Reserved for future use (specify any field)
- **Signer.ServerToken** Code to connect to the server (ask your TS contact)
- **Signer.StatusError** StatusID to set on the data if failed
- **Signer.StatusSigned** StatusID to set on the data if succes
- **Signer.EmailSubject** Header on the email sent to the signer
- **Signer.EmailBody** Content of the email sent to the signer

In addition the following entity configurations must be set

- **Signer.TemplateID** What template to use to generate the output
- **Signer.FieldID** Field to store the output in
- **Signer.FileName** Name of the output file (ex. "contract.docx")

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitStatusaction](https://docs.tsnocode.com/books/codeunit-reference/chapter/statusaction)</span>
- <span class="mw-headline">Security: none</span>
- <span class="mw-headline">Classpath: dk.tempusserva.signing.nemid.SignNemIdActionStatusGenerator</span>

# ChangeParentStatusAction

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Changes the status of a parent record, once all siblings are in a given state(status).</span>

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

Set the variables

- myParentField
- parentStatusID

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Add a status action that invokes this codeunit.</span>

### <span class="mw-headline">Options</span>

<span class="mw-headline">If the setup is unconventional you can overwrite the parent reference, using a config named "parentEntity" and you can include records in "hidden" states by setting "excludeHiddenStatus" to "false".</span>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

All configs for this codeunit support adding ".\[StatusID\]" add the end of the config name, to set a specific value, for that status. Otherwise the codeunit will fallback to the config without ".\[StatusID\]" at the end.

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitStatusaction](https://docs.tsnocode.com/books/codeunit-reference/chapter/statusaction)</span>
- <span class="mw-headline">Security: none</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.common.ChangeParentStatusAction</span>

# Set Date On Status

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Sets one or more fields to today's date when the codeunit is run.

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

Create a Configuration on the entity named "SetDateOnStatus.\[StatusID\]", which contains the system name(s) of the field(s) to be corrected.  
If multiple fields, separate with spaces.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Add the codeunit to a status action.</span>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">\[All possible configurations and where to edit them\]</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitStatusaction](https://docs.tsnocode.com/books/codeunit-reference/chapter/statusaction)</span>
- <span class="mw-headline">Security: access to the record</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.common.SetDateOnStatus</span>

# FormEvent

# BuildUserProfileFromRecord

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Creates a TS user from data in a record (name, email)

- Creates a user
- Assigns to a group
- Sends profile to user

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Set the codeunit on the entity to: **dk.p2e.blanket.codeunit.common.BuildUserProfileFromRecord**

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

Set the folowing configutations

- fieldUserLink
- fieldDataName
- fieldDataMail
- defaultGroupID
- requiredStatusID

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitFormevents](https://docs.tsnocode.com/books/codeunit-reference/chapter/formevents)</span>
- <span class="mw-headline">Security: None</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.BuildUserProfileFromRecord</span>

# Gantt Sync CodeUnit

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

This is a codeunit that syncs data from one entity to another.  
It also calculates start/end dates if a duration and only one of the dates are given.  
If all three are given, an error will be thrown.  
It was developed to sync data from a couple of entities to a single one, to display the data as a gantt chart.

#### <span class="mw-headline" id="bkmrk-notes-1">Notes</span>

If a duration field is set in the config, the following logic is used when calculating start and end dates.  
Default is to copy the dates.  
If one of the dates isn't given, then it is calculated based on duration (whole days) and the given date.

All statusIDs have to be set and it isn't possible to map from multiple states to a single state.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">\[Steps to enable codeunit\]</span>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<table id="bkmrk-configuration-descri"><tbody><tr><td>**Configuration**</td><td>**Description**</td></tr><tr><td>StructureMigrationCodeUnit.From.Field.Duration</td><td>Name of the column in the database containing the duration of the task (not required)</td></tr><tr><td>StructureMigrationCodeUnit.From.Field.EndDate</td><td>Name of the column in the database containing the enddate of the task</td></tr><tr><td>StructureMigrationCodeUnit.From.Field.Parent</td><td>Name of the column in the database containing the DataID of the parent task</td></tr><tr><td>StructureMigrationCodeUnit.From.Field.Progress</td><td>Name of the column in the database containing the percentage progress of the task</td></tr><tr><td>StructureMigrationCodeUnit.From.Field.Serial</td><td>Name of the column in the database containing the unique "code" of the task</td></tr><tr><td>StructureMigrationCodeUnit.From.Field.StartDate</td><td>Name of the column in the database containing the startdate of the task</td></tr><tr><td>StructureMigrationCodeUnit.From.Field.Title</td><td>Name of the column in the database containing the title of the task</td></tr><tr><td>StructureMigrationCodeUnit.To.Field.EndDate</td><td>Name of the column in the database where the end will be stored</td></tr><tr><td>StructureMigrationCodeUnit.To.Field.Parent</td><td>Name of the column in the database where the DataID of the parent task will be stored</td></tr><tr><td>StructureMigrationCodeUnit.To.Field.Progress</td><td>Name of the column in the database where the percentage progress of the task will be stored</td></tr><tr><td>StructureMigrationCodeUnit.To.Field.Serial</td><td>Name of the column in the database where the unique "code" of the task will be stored</td></tr><tr><td>StructureMigrationCodeUnit.To.Field.StartDate</td><td>Name of the column in the database where the startdate of the task will be stored</td></tr><tr><td>StructureMigrationCodeUnit.To.Field.Title</td><td>Name of the column in the database where the title of the task will be stored</td></tr><tr><td>StructureMigrationCodeUnit.To.Table</td><td>Name of the table in the database where all the tasks will be stored</td></tr><tr><td>StructureMigrationCodeUnit.Value.Parent</td><td>Static value. Use this to staticly set a DataID as parent task for all tasks synced (not required)</td></tr><tr><td>StructureMigrationCodeUnit.From.StatusID.Active</td><td>StatusID from source entity that should be converted to To.StatusID.Active</td></tr><tr><td>StructureMigrationCodeUnit.From.StatusID.Waiting</td><td>StatusID from source entity that should be converted to To.StatusID.Waiting</td></tr><tr><td>StructureMigrationCodeUnit.From.StatusID.Suspended</td><td>StatusID from source entity that should be converted to To.StatusID.Suspended</td></tr><tr><td>StructureMigrationCodeUnit.From.StatusID.Completed</td><td>StatusID from source entity that should be converted to To.StatusID.Completed</td></tr><tr><td>StructureMigrationCodeUnit.From.StatusID.Failed</td><td>StatusID from source entity that should be converted to To.StatusID.Failed</td></tr><tr><td>StructureMigrationCodeUnit.To.StatusID.Unknown</td><td>StatusID from the target entity. Given to tasks that have a status, that isn't defined in the config</td></tr><tr><td>StructureMigrationCodeUnit.To.StatusID.Active</td><td>StatusID from target entity that matches From.StatusID.Active</td></tr><tr><td>StructureMigrationCodeUnit.To.StatusID.Waiting</td><td>StatusID from target entity that matches From.StatusID.Waiting</td></tr><tr><td>StructureMigrationCodeUnit.To.StatusID.Suspended</td><td>StatusID from target entity that matches From.StatusID.Suspended</td></tr><tr><td>StructureMigrationCodeUnit.To.StatusID.Completed</td><td>StatusID from target entity that matches From.StatusID.Completed</td></tr><tr><td>StructureMigrationCodeUnit.To.StatusID.Failed</td><td>StatusID from target entity that matches From.StatusID.Failed</td></tr></tbody></table>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitFormevents](https://docs.tsnocode.com/books/codeunit-reference/chapter/formevents)</span>
- <span class="mw-headline">Security: Requires session</span>
- <span class="mw-headline">Classpath: dk.tempusserva.gantt.StructureMigrationCodeUnit</span>

# Recalculate Parent

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

A simple codeunit that allows you to force a complete re-calculation of an associated parent record.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Set the codeunit Classname of the entity to: **dk.tempusserva.codeunit.common.GenberegnParent**

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

Set the following entity configuration

- **GenberegnParent.ParentField** Field NAME containing the DataID of the associated record (eg. ParentReference or Lookup DataID)

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitFormevent](https://docs.tsnocode.com/books/codeunit-reference/chapter/formevents)</span>
- <span class="mw-headline">Security: none</span>
- <span class="mw-headline">Classpath: dk.tempusserva.codeunit.common.GenberegnParent</span>

# LoadInfoFromCVR

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

A codeunit that does a lookup via danish CVR register and updates the given fields of the record.

Only the configurations that are set will be updated, allowing for fetching of specific fields.

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

Add a status action and set the codeunit Classname to: **dk.tempusserva.codeunit.common.LoadInfoFromCVR**

Set the following entity configurations

- **LoadInfoFromCVR.LookupField** Field SYSTEMNAME containing the CVR to be looked up (required)
- **LoadInfoFromCVR.NameField** Field SYSTEMNAME for the field to be populated with the name of the company
- **LoadInfoFromCVR.AddressField** Field SYSTEMNAME for the field to be populated with the streetname and number of the company
- **LoadInfoFromCVR.PostalcodeField** Field SYSTEMNAME for the field to be populated with the zip/postal code of the company
- **LoadInfoFromCVR.CityField** Field SYSTEMNAME for the field to be populated with the cityname of the company
- **LoadInfoFromCVR.EmailField** Field SYSTEMNAME for the field to be populated with the email of the company
- **LoadInfoFromCVR.PhoneField** Field SYSTEMNAME for the field to be populated with the phonenumber of the company
- **LoadInfoFromCVR.FaxField** Field SYSTEMNAME for the field to be populated with the fax of the company
- **LoadInfoFromCVR.EmployeeCountField** Field SYSTEMNAME for the field to be populated with the employee count of the company
- **LoadInfoFromCVR.IndustryCodeField** Field SYSTEMNAME for the field to be populated with the industry code of the company
- **LoadInfoFromCVR.CompanyCodeField** Field SYSTEMNAME for the field to be populated with the company type code of the company

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">\[Steps to enable codeunit\]</span>

### <span class="mw-headline">Options</span>

<span class="mw-headline">\[Optional options, that can be set at runtime, eg. url-parameters\]</span>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">\[All possible configurations and where to edit them\]</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitFormevents](https://docs.tsnocode.com/books/codeunit-reference/chapter/formevents)</span>
- <span class="mw-headline">Security: \[eg. requires admin or session\]</span>
- <span class="mw-headline">Classpath: dk.tempusserva.codeunit.common.LoadInfoFromCVR</span>

# Http request on save

<span class="mw-headline">This Codeunit is not ready for use!</span>

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

This codeunit is capable of performing an HTTP-request with parameters from the updated item and update the item based on the result.

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

<span class="mw-headline">\[Optional, if extra config is required to get the codeunit working\]</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Add the codeunit `dk.tempusserva.codeunit.common.RequestFormevent` to the entity and add a configuration named `RequestFormevent.Setup` with content based on the following configuration.

It is possible to add both a "before-update" and an "after-update" action.

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<table class="wikitable" id="bkmrk-datapoint-%C2%A0-type-not"><tbody><tr><th>Datapoint</th><th> </th><th>Type</th><th>Notes</th></tr><tr><td>when</td><td>Required</td><td>String</td><td>Possible values: "after-update" or "before-update". Determines whether the call is executed before or after an item is updated.

</td></tr><tr><td>status</td><td>Optional</td><td>Array</td><td>An array of the StatusID's where the call should be executed. If "after-update", then this is if the item is in one of these status's after the update, likewise for "before-update".

If not given, then the call is executed every time.

</td></tr><tr><td>call</td><td>Required</td><td> </td><td>The actual configuration of the call.</td></tr><tr><td>call.url</td><td>Required</td><td>String</td><td>The url that is to be called. This supports input of parameters from the item.</td></tr><tr><td>call.method</td><td>Optional</td><td>String</td><td>The HTTP-method of the call, one of: "POST", "GET", "PUT" or "DELETE". Default: "GET".</td></tr><tr><td>call.type</td><td>Optional</td><td>String</td><td>The datatype of data returned, supported types: "json", "raw" or "XML". Default: "json".</td></tr><tr><td>call.headers</td><td>Optional</td><td>Map</td><td>A map of extra headers that should be set</td></tr><tr><td>call.params</td><td>Optional</td><td>Map</td><td>Path parameters that should be set and send.</td></tr><tr><td>call.body</td><td>Optional</td><td>String</td><td>A string that will be set and send. Not available for "GET".</td></tr><tr><td>call.update</td><td>Optional</td><td>Map</td><td>Fields that should be updated based on the data returned. If type is "raw", only the first item in this list will be updated, and it will be set to the entire response.

</td></tr></tbody></table>

### <span class="mw-headline" id="bkmrk-sample-1">Sample</span>

```json
[
    {
        "when": "before-update",
        "status": [69],
        "call": {
            "url": "https://acme.com/resource/[ID]",
            "method": "GET",
            "type": "json",
            "headers": {
                "Authorization": "Bearer XYZ"
            },
            "params": {
                "param": "[DATA]"
            },
            "body": "",
            "update": {
                "[LINK]": "info.link",
                "[NAME]": "info.name"
            }
        }
    }
]
```

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitFormevent](https://docs.tsnocode.com/books/codeunit-reference/chapter/formevents)</span>
- <span class="mw-headline">Security: requires session</span>
- <span class="mw-headline">Classpath: dk.tempusserva.codeunit.common.RequestFormevent</span>

# Public Pages

# Hello World

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Displays "Hello World" in a seperate page. Purpose is learning and testing.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Make a http request:

```
 .../main?command=<strong>dk.p2e.blanket.codeunit.common.PagePublicHelloWorld</strong>
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">None</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontentPublic](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontentpublic)</span>
- <span class="mw-headline">Security: Public access</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.PagePublicHelloWorld</span>

# PublicTokenBuilder

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Usage example: Lets external users resend tokens for data they should have access to.

Builds a token for accessing records using configuration options and dynamic parameters. It requires a record that has a reference to an email, to whom the token will be sent.

Multimode operation based on supplied parameters

1. Email as parameter: Execute silently
2. No email supplied: 
    - Display form with email
    - Execute normally

The DataID of the record is collected by making a lookup on the email supplied (see: LookupSolution, LookupFieldName).

An email is then sent to the user with a token for the record in question

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Make a http request:

```
main?command=dk.p2e.blanket.codeunit.common.PagePublicTokenBuilder
```

### <span class="mw-headline">Options</span>


The name of the following parameters are optional and configurable

- AltToken
- EmailMatch

```
main?command=dk.p2e.blanket.codeunit.common.PagePublicTokenBuilder&AltToken=0
```

```
main?command=dk.p2e.blanket.codeunit.common.PagePublicTokenBuilder&EmailMatch=foo@bar.com
```

```
main?command=dk.p2e.blanket.codeunit.common.PagePublicTokenBuilder&AltToken=0&EmailMatch=foo@bar.com
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

If no interface (**TokenInterface**) is specified the codeunit will allways exit without doing anything.

The codeunit has the following options

### <span class="mw-headline" id="bkmrk-options-for-the-emai-1">Options for the email input form</span>

These options are required

- FormHeader: HTML before the form and resulting message
- FormFooter: HTML after the form and resulting message
- FormIntroduction: Help text displayed above the form
- FormSubmitButton: Text on submit button
- FormReponseSuccess: Message to user if email is sent succesfully
- FormReponseFailure: Message to user if email failed

### <span class="mw-headline" id="bkmrk-options-for-building-1">Options for building the token</span>

These options are required

- EmailMatch: Name of http parameter for setting the email
- TokenInterface: Interface to build the token for
- LookupSolution: System name of the solution which the token is built for
- LookupFieldName: Field in solution where email of the user can be found

These options are optional

- AltToken: Name of http parameter for selecting the alternative interface
- TokenInterfaceAlt: Interface used if the parameter **AltToken** is set to **1**

### <span class="mw-headline" id="bkmrk-options-for-the-emai-3">Options for the email message</span>

These options are required

- EmailHeader: Subject content
- EmailContent: Body of email

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontentPublic](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontentpublic)</span>
- <span class="mw-headline">Security: Public accces (with some model restrictions)</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.PagePublicTokenBuilder</span>

# MigrateFilesToChildren

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Helps migrate from a [Files: Documents](https://docs.tsnocode.com/books/field-type-reference/page/documents) field to a related entity, with a Files: Documents field in single-file mode.</span>

<span class="mw-headline">Introduced in version 11879.</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Make a http request:</span>

```
.../main?command=com.tsnocode.codeunit.common.MigrateFilesToChildren
```

### <span class="mw-headline">Options</span>

Required parameters:

<table border="1" id="bkmrk-name-description-fro" style="border-collapse: collapse; width: 100%; height: 178.781px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">**Name**</td><td style="height: 29.7969px;">**Description**</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">From</td><td style="height: 29.7969px;">Entity migrating files from</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">FromDocument</td><td style="height: 29.7969px;">Field to migrate files from in "From" entity</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">To</td><td style="height: 29.7969px;">Entity to migrate files to</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">ToParent</td><td style="height: 29.7969px;">Field that references "From" entity</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">ToDocument</td><td style="height: 29.7969px;">Field to migrate files to in "To" entity</td></tr></tbody></table>

Optional parameters:

<table border="1" id="bkmrk-dontkeepmetadata-don" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr><td>DontKeepMetadata</td><td>Don't set CreatedAt and CreatedBy based on when and who uploaded the original file</td></tr><tr><td>TEST</td><td>Limit to first 10 records in "From" entity</td></tr></tbody></table>

All entity and field names are system names.

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontentPublic](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontentpublic)</span>
- <span class="mw-headline">Security: requires admin</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.common.MigrateFilesToChildren</span>

# Pages

# Clone System

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Clones the entire webapp to another server.

Only works on linux.

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

1. Generate an SSH key for the tomcat-user on the source server `sudo -u tomcat ssh-keygen`
2. Add the public key to a user on the target server that has sudo-access
3. Connect from the source server, as tomcat, to the target server and accept the certificate
4. Add configurations

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Invoke the codeunit, as an admin. eg.

`[SERVER]/main?command=common.CloneSystem`

### <span class="mw-headline" id="bkmrk-options-1">Options</span>

Control the behavior with the following url-parameters.

<table class="wikitable" id="bkmrk-parameter-desctiptio"><tbody><tr><th>Parameter</th><th>Desctiption</th></tr><tr><td>with-users</td><td>Also clones the users and their groups</td></tr><tr><td>with-files</td><td>Also clones the files uploaded</td></tr><tr><td>dont-backup-target</td><td>Does not create a copy of the database on the target server with the name `_backupyyyyMMddHHmm`</td></tr><tr><td>dont-clean</td><td>Does not remove the sql files on both systems</td></tr></tbody></table>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<table class="wikitable" id="bkmrk-config-default-descr"><tbody><tr><th>Config</th><th>Default</th><th>Description</th></tr><tr><td>CloneSystem.targetServer</td><td> </td><td>IP or domain of target server</td></tr><tr><td>CloneSystem.targetUser</td><td>ec2-user</td><td>Name of the user that is being used on the target server</td></tr><tr><td>CloneSystem.targetBasePath</td><td>Policy:applicationBasePath</td><td>Webapps, folder on target server</td></tr><tr><td>CloneSystem.targetApp</td><td>Policy:applicationName</td><td>Application name on target server</td></tr><tr><td>CloneSystem.targetDb</td><td>DbLive-name</td><td>Name of live server on target server</td></tr></tbody></table>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)
- Security: Requires session
- Classpath: com.tsnocode.codeunit.common.CloneSystem

# Copy Structure

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Will copy all fields except files and pictures, but all sub child entities (1 level, non recursive).

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

The page is called with the command: **dk.tempusserva.codeunit.common.PageCopyStructure**

Takes the following parameters

- SagID
- DataID

The user activating the function must have the group specified in "AllowCloneGroup"

Example of usage:

```
main?command=dk.tempusserva.codeunit.common.PageCopyStructure&SagID=10&DataID=100
```

Button for the function can be created using a "Action button: Button: Parameterized URL"

Example of URL pattern

```
main?command=dk.tempusserva.codeunit.common.PageCopyStructure&SagID=10&DataID=[DataID]
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">\[All possible configurations and where to edit them\]</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: \[eg. requires admin or session\]</span>
- <span class="mw-headline">Classpath: dk.tempusserva.codeunit.common.PageCopyStructure</span>

# Clone records

## <span class="mw-headline" id="bkmrk-usage-1">Usage</span>

This function will copy a single record

## <span class="mw-headline" id="bkmrk-configuration-guide-1">Configuration guide</span>

Add a button with parameterized URL using:

```
main?command=com.tsnocode.codeunit.common.CloneRecord&SagID=[SagID]&DataID=[DataID]
```

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: \[eg. requires admin or session\]</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.common.CloneRecord</span>

# Static Content

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Displays configurable static HTML code.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Make a http request:

```
main?command=dk.p2e.blanket.codeunit.common.PageStaticContent
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

Set up HTML:

Designer &gt; Modules &gt; Static content &gt; **StaticPageContent**

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: Requires session</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.PageStaticContent</span>

# Users By Group

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Displays list of active users in the system.

Multi mode function

- User normal: No filters
- User exclusive group: Filters users/groups that active user belongs to

You can navigate through the pages

1. Lists exclusive groups + none
2. Lists users in *selected* exclusive group (1)
3. Lists groups for *selected* user (2)

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Make a http request:

```
 main?command=<strong>dk.p2e.blanket.codeunit.common.PageUsersByGroup</strong>
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">None</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: Requires UderEditor or Admin</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.PageUsersByGroup</span>

# Users Online

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span><span class="mw-headline" id="bkmrk-first-setup-1"></span>

Displays a list of users with a session on the current server

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Make a http request:

```
main?command=common.PageUsersOnline
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">None</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: Requires admin</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.PageUsersOnline</span>

# Website Iframe

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Displays a configurable webpage in an IFrame.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Make a http request:

```
main?command=dk.p2e.blanket.codeunit.common.PageWebsiteIframe
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

Set up IFrame options:

Designer &gt; Modules &gt; Static content

- WebsiteIframeURL
- WebsiteIframeWidth
- WebsiteIframeHeight

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: Requires session</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.PageWebsiteIframe</span>

# Solution Structure View

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Lists the components (fields, status etc.) in the current solution.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Make a http request including a valid SagID:

```
main?SagID=[SagID]&command=common.SolutionStructureView
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">None</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: Requires session</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.SolutionStructureView</span>

# Gantt Diagram

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

The platform has a build-in gantt chart generator.  
It supports zooming, nesting and relations.

The datastructure has to be a single entity.  
If your data isn't contained in a single entity use [Gantt Sync CodeUnit](https://docs.tsnocode.com/books/common-codeunits/page/gantt-sync-codeunit).

**Sample**

[![image.png](https://docs.tsnocode.com/uploads/images/gallery/2025-04/scaled-1680-/LfOEnDLWW4ebPf31-image.png)](https://docs.tsnocode.com/uploads/images/gallery/2025-04/LfOEnDLWW4ebPf31-image.png)

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

To view the gantt chart, access: main?command=dk.tempusserva.gantt.DhtmlXGanttPage&amp;SagID=\[SagID\]

### <span class="mw-headline">Options</span>

#### <span class="mw-headline" id="bkmrk-basic-setup-1">Basic setup</span>

To view a gantt chart, first access the page main?command=dk.tempusserva.gantt.DhtmlXGanttPage to generate the required **static configurations**.  
Six fields are required in the table, that the data is being read from:  
Code, Title, Group, Start date, End date and Progress.

Code and Title have to be single-line text inputs.  
Progress has to be an integer input, it represents how far along the task is, in percent.  
Start and End date have to be dates.  
Group should store the DataID of the parent-task. Here a database-lookup is used, executing query: SELECT DataID, Resume FROM data\_ganttdata and displaying field Resume.

Also at least 5 statuses:  
Active, Suspended, Completed, Failed and Waiting.  
All other statuses will be marked as Undefined.

**<span class="mw-headline" id="bkmrk-sample-2">Sample</span>**

[![image.png](https://docs.tsnocode.com/uploads/images/gallery/2025-04/scaled-1680-/TSzxf2mIiBWgF175-image.png)](https://docs.tsnocode.com/uploads/images/gallery/2025-04/TSzxf2mIiBWgF175-image.png)

#### <span class="mw-headline" id="bkmrk-relations-1">Relations</span>

To view relations between tasks, create another table.  
Two fields are required:  
From and To.  
A third field Type can be added, but isn't required.

From and To have to store the DataID of the tasks that should be linked via a relation. This setup is the same as Group.  
Type has to have value of 1 or 0, any other value is overwritten to 0. This defines whether the relation is drawn from the beginning (1) or end (0) of the From-task.

To view the gantt chart, access: main?command=dk.tempusserva.gantt.DhtmlXGanttPage&amp;SagID=\[SagID\]&amp;LinkSagID=\[RelationSagID\]

**Sample**

[![image.png](https://docs.tsnocode.com/uploads/images/gallery/2025-04/scaled-1680-/4eGRssSGib9yPau5-image.png)](https://docs.tsnocode.com/uploads/images/gallery/2025-04/4eGRssSGib9yPau5-image.png)

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<table id="bkmrk-static-config-defaul"><tbody><tr><td>**Static config**</td><td>**Default value**</td><td>**Description**</td></tr><tr><td>Gantt.Field.Group</td><td>GROUP\_VALUE</td><td>Name of the column that contains the DataID of parent-task</td></tr><tr><td>Gantt.Field.StartDate</td><td>STARTDATE</td><td>Name of the column that contains the task-start date</td></tr><tr><td>Gantt.Field.EndDate</td><td>ENDDATE</td><td>Name of the column that contains the task-end date</td></tr><tr><td>Gantt.Field.Code</td><td>CODE</td><td>Name of the column that contains the task-code</td></tr><tr><td>Gantt.Field.Title</td><td>TITLE</td><td>Name of the column that contains the task-title</td></tr><tr><td>Gantt.Field.Progress</td><td>PROGRESS</td><td>Name of the column that contains the task-progress</td></tr><tr><td>Gantt.Filter.Field</td><td>TASKTYPE</td><td>Name of a column that contains a value that should be filtered to match Gantt.Filter.Value</td></tr><tr><td>Gantt.Filter.Value</td><td>249</td><td>Value that task have to equal in column Gantt.Filter.Field</td></tr><tr><td>Gantt.Field.Link.From</td><td>FROM</td><td>Name of column that contains DataID of source-task in a relation</td></tr><tr><td>Gantt.Field.Link.To</td><td>TO</td><td>Name of column that contains DataID of target-task in a relation</td></tr><tr><td>Gantt.Field.Link.Type</td><td> </td><td>Name of column that contains type of relation, not required</td></tr><tr><td>Gantt.StatusID.Active</td><td>1</td><td>ID of status that marks a task as Active</td></tr><tr><td>Gantt.StatusID.Waiting</td><td>2</td><td>ID of status that marks a task as Waiting</td></tr><tr><td>Gantt.StatusID.Suspended</td><td>3</td><td>ID of status that marks a task as Suspended</td></tr><tr><td>Gantt.StatusID.Completed</td><td>4</td><td>ID of status that marks a task as Completed</td></tr><tr><td>Gantt.StatusID.Failed</td><td>5</td><td>ID of status that marks a task as Failed</td></tr><tr><td>Gantt.StatusColor.Undefined</td><td>\#858586</td><td>CSS-color of tasks with status Undefined</td></tr><tr><td>Gantt.StatusColor.Active</td><td>\#76C0F1</td><td>CSS-color of tasks with status Active</td></tr><tr><td>Gantt.StatusColor.Waiting</td><td>\#F6BF5F</td><td>CSS-color of tasks with status Waiting</td></tr><tr><td>Gantt.StatusColor.Suspended</td><td>\#F28F42</td><td>CSS-color of tasks with status Suspended</td></tr><tr><td>Gantt.StatusColor.Completed</td><td>\#4DBE6C</td><td>CSS-color of tasks with status Completed</td></tr><tr><td>Gantt.StatusColor.Failed</td><td>\#E70015</td><td>CSS-color of tasks with status Failed</td></tr></tbody></table>

### <span class="mw-headline" id="bkmrk-advanced-usage-1">Advanced usage</span>

It's possible to override the static content.  
To do so, add the desired value to the url.  
Example:  
To override the field used for Title, add *&amp;Gantt.Field.Title=\[field-name\]* to the url

### <span class="mw-headline" id="bkmrk-exporting-1">Exporting</span>

The chart supports exporting to Excel and iCal formats.

It's possible to overwrite the export, be declaring a javascript function named `customExportToExcel` or `customExportToICal`. Either takes one argument: the gantt object.

Heres an example that removes html markup from the gantt titles before export.

```javascript
function customExportToExcel(gantt) {
  var data = gantt.getDatastore("task").getVisibleItems();
  var rtn = [];
  for (var i = 0; i < data.length; i++) {
    var d = new Date(data[i].start_date);
    rtn[i] = {
      color: data[i].color,
      duration: data[i].duration,
      id: data[i].id,
      open: data[i].open,
      parent: (data[i].parent == "0" || data[i].parent == 0 ? "" : data[i].parent),
      progress: data[i].progress,
      start_date: d.getFullYear() + "-" + ("0"+(d.getMonth()+1)).slice(-2) + "-" + ("0" + d.getDate()).slice(-2) + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2),
      text: $(data[i].text).text(),
    };
  }
  console.log(rtn);
  viewGantt({data: rtn, links: []});
  setTimeout(function() {
    gantt.exportToExcel();
  }, 5);
  setTimeout(loadGantt, 100);
}
```

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: Requires session</span>
- <span class="mw-headline">Classpath: dk.tempusserva.gantt.DhtmlXGanttPage</span>

# Move a File

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

Moves a file from one document-field to another, on the same entity.

Works between document-fields with and without signing.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Add the following snippet to the entity scripts. This enables movement between all document-fields on the entity.

It adds another column to the file-lists, with a "Move" link. When clicked it opens a popup, with a dropdown where the new field can be selected.

```javascript
const moveFile = (id, to) => {
  const params = new URLSearchParams(window.location.search)
  $.ajax({
    url: "main",
    method: "GET",
    data: {
      "command": "dk.tempusserva.codeunit.common.MoveFile",
      "SagID": params.get("SagID"),
      "DataID": params.get("DataID"),
      "FileID": id.split("_")[2],
      "FieldFrom": id.split("_")[1],
      "FieldTo": to,
    },
    success: (data) => {
      if (data == "File moved") {
        $(`#${id}`).find("td").last().html("Moved")
      } else {
        alert(data)
      }
    },
  })
}

$(() => {
  const moveFileAction = () => {
    console.log("yay")
    moveFile($("#modeFileFrom").val(), $("#moveFileTo").val())
    $("#moveFilePopup").remove()
  }
  $(() => {
    $(".tableFiles").each((i,e) => {
      let t = $(e)
      t.find("thead").find("tr").each((i,e) => { $(e).append("<th></th>") })
      t.find("tbody").find("tr").each((i,e) => { $(e).append(`<td><a href="#" class="moveFile">Move</a></td>`) })
    })
    $(".moveFile").on("click", (e) => {
      e.preventDefault()
      let t = $(e.currentTarget)
      let id = t.parent().parent().attr("id")
      let r = `<select class="form-control" id="moveFileTo">`
      r += `<option value="">Select a field</option>`;
      $(".uploadFiles").each((i,e) => {
        let p = $(e).parent().attr("id").replace("VB_DATA_", "")
        if (id.split("_")[1] != p) {
          let x = $(e).parent().parent().parent().find(`#NB_DATA_${p}`).html()
          r += `<option value="${p}">${x}</option>`
        }
      })
      r += "</select>"
      $("#TempusServaPage").append(`
        <div id="moveFilePopup" style="display: none;">
          <label>Move file to:</label>
          ${r}
          <input type="hidden" id="modeFileFrom" value="${id}"/>
          <a href="javascript:moveFileAction();" class="moveFileAction">Move</a>
        </div>
      `)
      createJqueryDialog("moveFilePopup")
    })
  })
})
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">None</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent) (raw)</span>
- <span class="mw-headline">Security: Requires session</span>
- <span class="mw-headline">Classpath: dk.tempusserva.codeunit.common.MoveFile</span>

# Convert database to UTF-8

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline" id="bkmrk-special-characters-c-1">Special characters causing errors</span><span class="mw-headline" id="bkmrk-"></span>

The default support for UTF8 is 3 byte.

Using 4 byte UTF content in text areas, can cause errors, that looks like

```
java.sql.SQLException: Incorrect string value: '\xC2\x96 Z. ...' for column 'NOTES' at row 1
```

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Update the database to full UTF8 support using the following command

```
main?command=dk.p2e.blanket.codeunit.common.PageConvertDatabaseToUTF8
```

Note an administration profile is needed to complete the operation.

You might also have to update the tomcat server.xml file.  
You have to add `useBodyEncodingForURI="true"` to the connectors.

Note that this codeunit has build in protection against being excuted multiple times at once, and should be executed every time a new field or entity has been added to the database.

### Issue before version 11315 on MariaDB

Due to a difference in how MySQL and MariaDB stores "DEFALUT NULL", when executing this codeunit on a MariaDB server, all columns with the default value of null would be updated to have a default value of 'NULL' (the string NULL, not the empty value null).

To find the affected columns and generate all the required sql to fix the issue, run the following query.  
Remember to reaplce `[LIVE DB]` with the name of the live database of your instance!

```mysql
SELECT a.TABLE_NAME, a.COLUMN_NAME, CONCAT('ALTER TABLE ', a.TABLE_NAME, ' ALTER ', a.COLUMN_NAME, ' SET DEFAULT NULL;') AS upd
FROM information_schema.columns AS a
INNER JOIN INFORMATION_SCHEMA.TABLES b ON 
	a.TABLE_CATALOG = b.TABLE_CATALOG AND 
	a.TABLE_SCHEMA = b.TABLE_SCHEMA AND 
	a.TABLE_NAME = b.TABLE_NAME AND
	LOWER(b.table_type) != 'view'
WHERE a.COLUMN_DEFAULT = '\'NULL\'' AND 
a.TABLE_SCHEMA = '[LIVE DB]'
```

This should create one row for every column in the database that has a default value of the string 'NULL'.

Take the output of the third column, copy all rows and execute them against the database.  
Should look something like this:

```mysql
ALTER TABLE form ALTER SagNavnI18N SET DEFAULT NULL;
ALTER TABLE form ALTER EntityIcon SET DEFAULT NULL;
ALTER TABLE form ALTER Description SET DEFAULT NULL;
ALTER TABLE form ALTER DescriptionI18N SET DEFAULT NULL;
ALTER TABLE form ALTER MailDomains SET DEFAULT NULL;
ALTER TABLE form ALTER MailSecurity SET DEFAULT NULL;
ALTER TABLE form ALTER Codeunit SET DEFAULT NULL;
ALTER TABLE form ALTER Instructions SET DEFAULT NULL;
```

Go back and execute the first query, it now should return 0 rows.

### <span class="mw-headline">Options</span>

<span class="mw-headline">None.</span>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">None.</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: Requires administrator</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.PageConvertDatabaseToUTF8</span>

# Bulk importing files

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

This page describes how to setup the bulk-import codeunit, to import a lot of files at once and generate a separate record in an entity, for each file.

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

First, setup an entity with at least two fields: A [text-field](https://docs.tsnocode.com/books/field-type-reference/page/text "FieldText") for the filename and a [document field](https://docs.tsnocode.com/books/field-type-reference/page/documents "FieldFiles") for the document.  
Second, create or edit the following 5 "Static content".

1. BulkImport.SagID, the SagID of the entity that is the target of the import
2. BulkImport.UserGroupID, The GroupID of the usergroup that is allowed to access the bulk-import system
3. BulkImport.FileTitleField, The systemname of the field where the name of the file should be stored
4. BulkImport.FileFieldID, The FieldID of the field where the uploaded document should be stored
5. BulkImport.StatusID, The StatusID that uploaded documents should have

Third, edit the url on the site and access *main?command=dk.tempusserva.codeunit.bulkimport.ImportPage*  
Fourth, upload the files.

Next step could be to index all the files, allowing the content of the files to be searched and queried, maybe through ChatGPT.

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">\[Steps to enable codeunit\]</span>

### <span class="mw-headline">Options</span>

<span class="mw-headline">\[Optional options, that can be set at runtime, eg. url-parameters\]</span>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">\[All possible configurations and where to edit them\]</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: \[eg. requires admin or session\]</span>
- <span class="mw-headline">Classpath: dk.tempusserva.codeunit.bulkimport.ImportPage</span>

# Update resume for entire entity

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Updates the resume for all records in a given entity</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

The page is called with the command: **com.tsnocode.codeunit.backend.UpdateEntityResumes**

Requires the following parameter

- SagID

Example of usage:

```
main?command=com.tsnocode.codeunit.backend.UpdateEntityResumes&SagID=10&RecordLimit=10000
```

### <span class="mw-headline">Options</span>

Takes the following parameters

- RecordLimit (default 1000)
- BatchSize (default 100)

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: requires admin</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.backend.UpdateEntityResumes</span>

# Cleanup Inactive Model Parts

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Removes all states in an entity, that have no records and are marked as inaktive.</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Call the codeunit, with the SagID to clean.</span>

```
main?command=com.tsnocode.codeunit.backend.CleanupInactiveModelParts&SagID=[SagID]
```

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: administrator</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.backend.CleanupInactiveModelParts</span>

# Fix Docx Tags

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Tries to fix templating tags in a docx template.</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Call the codeunit, along with a TemplateID

```
main?command=com.tsnocode.codeunit.backend.FixDocxTags&TemplateID=[TemplateID]
```

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: administrator</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.backend.FixDocxTags</span>

# Reinvite Users

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Resets passwords and sends out welcome messages, to all of the listed emails.</span>

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

<span class="mw-headline">Setup the configuration "ReinviteUsersGroupID".</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Call the page</span>

```
main?command=com.tsnocode.codeunit.backend.ReinviteUsers
```

Input the emails that should be reset and re-invited, one email pr line, and submit the form.

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">ReinviteUsersGroupID</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: administrator and specific group</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.backend.ReinviteUsers</span>

# Generate Video Thumbnails

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Generates missing thumbnails for files in an entity.</span>

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

<span class="mw-headline">Make sure the application is using filesystem storage ([filesystemStorageActive](https://docs.tsnocode.com/books/policy-reference/page/filesystem))</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

Call the page

```
main?command=com.tsnocode.codeunit.common.GenerateVideoThumbnails&SagID=[SagID]
```

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">You can adjust the thumbnail size via the policy [uploadPictureSizeThumbnail](https://docs.tsnocode.com/books/policy-reference/page/filesystem)</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: administrator</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.common.GenerateVideoThumbnails</span>

# Export Template To WebDav

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Exports a template, saves it to the record, and opens it via webdav.</span>

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

<span class="mw-headline">Add an action button with the correct parameters</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Call the page, e.g. via an action button</span>

```
main?command=com.tsnocode.codeunit.common.SaveTemplateToWebDav&SagID=[SagID]&DataID=[DataID]&TemplateID=[TemplateID]&Filename=[Filename]&Field=[Field]
```

### <span class="mw-headline">Options</span>

- <span class="mw-headline">SagID</span>
- <span class="mw-headline">DataID</span>
- <span class="mw-headline">TemplateID</span>
- <span class="mw-headline">Filename, Name of the generated file</span>
- <span class="mw-headline">Field, Field systemname to save the generated file to</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: session</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.common.SaveTemplateToWebDav</span>

# Bulk import files

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Imports files and creates a record for each of them.</span>

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

<span class="mw-headline">\[Optional, if extra config is required to get the codeunit working\]</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Open the page</span>

```
main?command=com.tsnocode.codeunit.system.bulkimport.ImportPage
```

### <span class="mw-headline">Options</span>

<span class="mw-headline">\[Optional options, that can be set at runtime, eg. url-parameters\]</span>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">\[All possible configurations and where to edit them\]</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: admin, datahandler, or specific group</span>
- <span class="mw-headline">Classpath: com.tsnocode.codeunit.system.bulkimport.ImportPage</span>

# Dynamically change users exclusive group

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Gives the user a list of exclusive groups defined in the application. The user can select one and will have their exclusive group set to that value untill they sign out.</span>

<span class="mw-headline">Also supports changing the users exclusive group, if the already have one.</span>

<span class="mw-headline">Does not support advanced security with multiple exclusive groups.</span>

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

<span class="mw-headline">Enable the policy [securityExclusiveGroupSet](https://docs.tsnocode.com/books/policy-reference/page/security).</span>

<span class="mw-headline">If the option to change groups is required, enable the policy [securityExclusiveGroupChange](https://docs.tsnocode.com/books/policy-reference/page/security).</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Add a button that links to this codeunit</span>

```
main?command=dk.p2e.blanket.codeunit.common.PageSetExclusiveGroup
```

### <span class="mw-headline">Options</span>

<span class="mw-headline">None</span>

## <span class="mw-headline" id="bkmrk-configuration-1">Configuration</span>

<span class="mw-headline">None</span>

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: [CodeunitPagecontent](https://docs.tsnocode.com/books/codeunit-reference/chapter/pagecontent)</span>
- <span class="mw-headline">Security: Session</span>
- <span class="mw-headline">Classpath: dk.p2e.blanket.codeunit.common.PageSetExclusiveGroup</span>

# Is Date weekend/holiday

## <span class="mw-headline" id="bkmrk-what-it-does-1">What it does</span>

<span class="mw-headline">Tests wether a date is a weekend date and/or a holiday (based on those that are input via the designer).</span>

<span class="mw-headline">Available from version 11968.</span>

## <span class="mw-headline" id="bkmrk-first-setup-1">First setup</span>

<span class="mw-headline">Just make sure that you maintain the list of holidays (in the designer).</span>

## <span class="mw-headline" id="bkmrk-how-to-invoke-1">How to invoke</span>

<span class="mw-headline">Make an http request to  
</span>

```
main?command=com.tsnocode.codeunit.frontend.TestDate&Date=[DATE]
```

<span class="mw-headline">This will return a json object.</span>

```json
{
  "date": "2026-05-14",
  "isHoliday": true,
  "isWeekend": false,
  "error": false,
  "holidayName": "Kristihimmelfart"
}
```

If `error` is true, then a message (`msg`) will also be available.  
If `isHoliday` is true, then a `holidayName` should also be returned. (As of version 12007)

## <span class="mw-headline" id="bkmrk-developer-info-1">Developer info</span>

- <span class="mw-headline">Type: \[Type+link\]</span>
- <span class="mw-headline">Security: \[eg. requires admin or session\]</span>
- <span class="mw-headline">Classpath: \[full class path\]</span>