# Overview

Saaster Documentation - Version 1.1

Welcome to the saaster documentation. Saaster is a web application written in CFML that offers all the basic functionality that you need for a SaaS project. With saaster you can save the development time (and costs) of programming these basic functions by yourself.

## Demo

Checkout our demo at [app.saaster.io](https://app.saaster.io)

**Login**\
User: *<demo@saaster.io>*\
Pass: *testtest*

#### Test credit cards

You need a credit card to activate plans or modules. Here are some credit cards with which you can test the payment processes:

> Insert three random digits for CVC and a future date for Date

| NUMBER           | BRAND            |
| ---------------- | ---------------- |
| 4242424242424242 | Visa             |
| 5555555555554444 | Mastercard       |
| 378282246310005  | American Express |

## License

Saaster is open source and bound to the [MIT licence](https://github.com/PAWECOGmbH/saaster/blob/main/LICENSE).

## Quick links

{% content-ref url="/pages/wmEc6m30KVmf3bANpSxQ" %}
[Target Audience](/introduction/target-audience)
{% endcontent-ref %}

{% content-ref url="/pages/qEosNNYccfI1hDk0Nnmk" %}
[Features](/introduction/features)
{% endcontent-ref %}

{% content-ref url="/pages/5SWiRIyjSaewdML6YMno" %}
[Local development](/development/local-development)
{% endcontent-ref %}

**Used open source projects:**

* <https://github.com/tabler/tabler/blob/main/LICENSE>
* <https://github.com/JeremyFagis/dropify/blob/master/LICENCE.md>
* <https://github.com/Alex-D/Trumbowyg/blob/develop/LICENSE>
* <https://github.com/twbs/bootstrap/blob/main/LICENSE>
* <https://github.com/Ortus-Solutions/MockDataCFC/blob/development/LICENSE>
* <https://fontawesome.com/v4/license/>
* <https://github.com/jquery/jquery/blob/main/LICENSE.txt>


# Target Audience

For developers by developers

Saaster is designed for companies and individuals who want to offer digital services on a subscription or fixed-price basis. Whether you're building a learning platform, an ERP interface, or something completely different, saaster has the flexibility and power to support your vision.&#x20;

To unlock the full potential of saaster, we recommend having a basic knowledge of programming, ideally in CFML. But even if you're not a programmer, saaster can be a great starting point for your project, and you can always hire an agency to add custom features. Saaster was created by developers, for developers, so the possibilities are endless.

<figure><img src="/files/9vVA3Yo5kh805Ia6s6Wk" alt=""><figcaption></figcaption></figure>

## Scenarios for using saaster

There are following scenarios in which saaster can be used:

### Develop your own SaaS offering using saaster as basic software

1. Develop your own offer within saaster (myApp)
2. Create modules and offer them together with your main app
3. Create only modules without main app (module-based offer)

<figure><img src="/files/CaFcLEZbwHs44aBJcJT0" alt=""><figcaption></figcaption></figure>

### Using saaster without any programming

a) Manage registrations and customers

b) Issue and send invoices

c) Making payments in various payment methods

d) Sell subscriptions

<figure><img src="/files/72nqaTVtSguAt5mn7JT6" alt=""><figcaption></figcaption></figure>

### Using saaster API to run your SaaS

With saaster's API, you can use an externally developed SaaS solution without much effort, such as creating plans and modules, receiving payments and charging credit cards again monthly/annually, and much more.

<figure><img src="/files/sKBKPwmlCLduEVDxfbRj" alt=""><figcaption></figcaption></figure>


# Features

All features at a glance

Saaster offers all the basic features you need to get your SaaS project started. The following list contains all this features.

### General features

* Registration process
* Authentication per email and password
* Password reset function
* API Capabilities

### Features for the customer

* Edit personal profile
  * Personal information
  * Avatar upload
  * Gravatar integration

* Password reset

* Edit company profile

  * Company information
  * Logo upload

* User and permission management

  * Invite new users
  * Edit users

* Tenant management and administration

  * Create and edit tenant
  * Assign users

* Manage invoices

  * View and/or print invoice
  * Pay invoice

* Plans

  * Book plan
  * Upgrade plan
  * Downgrade plan
  * Cancel plan
  * Withdraw cancellation

* Modules
  * Book modules
  * Cancel module
  * Withdraw cancellation

### Features for the provider (SysAdmin)

* System settings

  * Start of the invoice number
  * Prefix of the invoice number
  * VAT type default (incl., excl. or without)
  * VAT Pre-setting (net or gross)
  * Rounding factor for invoices (0.1 or 0.5)

* Customer settings

  * Generate variables with a default value
  * These variables can be called up system-wide via functions

* Languages

  * 1/n languages can be entered
  * Offer language for selection or not

* Currencies

  * 1/n currencies can be entered
  * Choice of default currency

* Countries

  * 250 countries incl. detailed data are already recorded in saaster
  * They can be activated as desired
  * Manual entry of new countries possible (probably not necessary)

* Mappings

  * Create beautiful URL (SEF)
  * Access management of content via mappings
  * Customised mappings
  * System mappings

* Translations

  * Customer-specific translations
  * System-wide translations
  * Mass translation via Deepl

* Widgets
  * Creating widgets for the dashboard
  * Determining the size
  * Assignment to plans and/or modules<br>

* Logfiles

  * GUI for all logs
  * Log types can be defined by the SysAdmin
  * Log levels such as Info, Warning and Error
  * Automatic dispatch by e-mail if desired
  * Log filters such as date, type or level


# System Requirements

Requirements to run saaster

The following list contains all the requirements that your system hast to fulfill to run saaster.\
For local development we strongly recommend the usage of the docker configuration that is provided by saaster.&#x20;

{% content-ref url="/pages/5SWiRIyjSaewdML6YMno" %}
[Local development](/development/local-development)
{% endcontent-ref %}

### CFML Engine

Saaster requires the CFML engine [Lucee](http://lucee.org) 5.3.9+

### **Operating Systems**

Your Lucee engine can be installed on Linux, Mac or Windows.

### **Database Engines**

Saaster requires [MySQL 5.7](https://dev.mysql.com/downloads/mysql/5.7.html)

### Web Server

Saaster should run on all popular web servers. Saaster got tested with IIS and the [Tuckey servlet filter](http://tuckey.org/urlrewrite/). The chosen web server should support URL rewriting.

Example configuration:

{% tabs %}
{% tab title="IIS" %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                 <rule name="API" stopProcessing="true">
                    <match url="^/api/(.*)$" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="api/index.cfm/{R:1}" appendQueryString="true" />
                </rule>	
	        <rule name="SEF" stopProcessing="true">
                    <match url="^(.*)$" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="index.cfm/{R:1}" appendQueryString="true" />
                </rule>
            </rules>
        </rewrite>		
    </system.webServer>
</configuration>

```

{% endtab %}

{% tab title=" Tuckey" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<urlrewrite>
    <rule>
        <name>Rewrite API</name>
	<from>^/api/(.+)$</from>
        <condition type="request-filename" operator="notdir"/>
        <condition type="request-filename" operator="notfile"/>
        <to type="passthrough" qsappend="true" >/api/index.cfm/$1</to>
    </rule>

    <rule>
        <name>Rewrite Main</name>
	<from>^/(.+)$</from>
	<condition type="request-uri" operator="notequal">/lucee/admin/server.cfm</condition>
	<condition type="request-uri" operator="notequal">/lucee/admin/web.cfm</condition>
        <condition type="request-uri" operator="notequal">/api/</condition>
	<condition type="request-uri" operator="notequal">/(index.cfm|robots.txt|osd.xml|flex2gateway|cfide|cfformgateway|railo-context|lucee|admin-context|modules/contentbox-dsncreator|modules/contentbox-installer|modules/contentbox|files|images|js|javascripts|css|styles|config).*</condition>
        <condition type="request-uri" operator="notequal">\.(bmp|gif|jpe?g|png|css|js|txt|xls|ico|swf|woff|ttf|otf)$</condition>
        <condition type="request-filename" operator="notdir"/>
        <condition type="request-filename" operator="notfile"/>
        <to type="passthrough" qsappend="true" >/index.cfm/$1</to>
    </rule>
</urlrewrite>

```

{% endtab %}
{% endtabs %}


# Installation

Instructions for installing saaster

If you got familiar with saaster, and you would like to use it for a real life application, we recommend using a clean installation of saaster.&#x20;

First check if your host meets these [system requirements](/getting-started/system-requirements).

For developers there is a guide to setup a local development environment:

{% content-ref url="/pages/5SWiRIyjSaewdML6YMno" %}
[Local development](/development/local-development)
{% endcontent-ref %}

## Get saaster

Download the latest version from GitHub. Either get the official [latest release](https://github.com/PAWECOGmbH/saaster/releases) or clone the [repository](https://github.com/PAWECOGmbH/saaster/releases).

In the majority of cases we recommend to work with the official version because it is well documented and has undergone many error tests.

In this guide, we assume that you have downloaded the latest release. (.zip file)

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td>           Latest release (recommended)</td><td></td><td><a href="https://github.com/PAWECOGmbH/saaster/releases">https://github.com/PAWECOGmbH/saaster/releases</a></td></tr><tr><td></td><td>                              Repository</td><td></td><td><a href="https://github.com/PAWECOGmbH/saaster">https://github.com/PAWECOGmbH/saaster</a></td></tr></tbody></table>

## Configure website

Create a new website with your chosen web server and unpack all files into the root directory of this website. Running saaster in a subdirectory should in theory be possible, but is not officially tested.

Check out the example web server configurations under [system requirements](/getting-started/system-requirements#web-server).

When you created your new website and copied all files, you need to make some changes to the `config.cfm` file. You will find a template of this file in the `configs` folder. Please copy this file into the root directory and rename it to `config.cfm`.

Set these values accordingly to your website configuration:

```cfscript
// Environment
variables.environment = "prod";

// Enter the URL of your live project (incl. http:// or https://)
variables.mainURL = "https://www.your-domain.com";

// The name of your application.cfc
variables.applicationname = "YourProjectName";
```

## Create database

{% hint style="info" %}
For the datasource you must set "Allow multiple Queries" to *true*
{% endhint %}

Create a new MySQL database and add a new datasource in the Lucee Administrator. Following that task, execute the SQL scripts located in `/db/init/`. You can find more information about the database structure here.&#x20;

Also set the name of the newly created datasource in the `config.cfm` file:

```cfscript
variables.datasource = "database";
```

## Further configuration

These basic configurations should be enough to get saaster running. We recommend to set all other settings / values  in the `config.cfm` file to your liking. \
\
This guide will help you to complete the configuration of saaster.

{% content-ref url="/pages/aYHGt2fD8z6fNLJgsl4w" %}
[Configuration](/getting-started/configuration)
{% endcontent-ref %}

## Running the setup routine

After you finished the installation of saaster, we recommend running the setup routine of saaster.

{% content-ref url="/pages/Qj8bEtEBo0IPMFiayORx" %}
[Setup Routine](/getting-started/setup-routine)
{% endcontent-ref %}


# Configuration

Basic configuration of saaster in config.cfm

{% hint style="warning" %}
The Application.cfc must not be changed, otherwise the system can no longer be updated.
{% endhint %}

The `config.cfm` is **the first file you need to revise and modify**. You will find a template of this file in the `configs` folder. When not already done, copy this file into the root directory and rename it to `config.cfm`. Now you can adapt your data according to your needs.

## Available variables

This table shows the available variables and what they do:

<table><thead><tr><th width="232">Variables</th><th width="499.33333333333326">Description</th></tr></thead><tbody><tr><td>datasource</td><td>Name of datasource in Lucee</td></tr><tr><td>environment</td><td>Sets the environment where the application is currently running in. You can use "prod" or "dev".</td></tr><tr><td>mainURL</td><td>The full URL of your live project<br>(incl. http:// or https://)</td></tr><tr><td>schedulePassword</td><td>Password for scheduled tasks</td></tr><tr><td>applicationname</td><td>The name of your application.cfc</td></tr><tr><td>sessiontimeout</td><td>Set sessiontimout with "createTimespan()"</td></tr><tr><td>pdf_type</td><td>Set the pdf_type. You can use "modern" or "classic" for lucee pdf print</td></tr><tr><td>requesttimeout</td><td>RequestTimeout in seconds</td></tr><tr><td>imageFileTypes</td><td>Set allowed image file types</td></tr><tr><td>documentsFileTypes</td><td>Set allowed document file types</td></tr><tr><td>apiSecret</td><td>Secret, which is used to create the access tokens.</td></tr><tr><td>apiReloadPassword</td><td>Password that is used to reinit the API. (See taffy <a href="https://docs.taffy.io/#/3.5.0?id=reloadpassword">documentation</a>)</td></tr><tr><td>appName</td><td>Any name you like</td></tr><tr><td>appOwner</td><td>Enter the name of the operator (Your company)</td></tr><tr><td>fromEmail</td><td>Mail address from which the system should send mails from</td></tr><tr><td>toEmail</td><td>Enter the email address of the administrator</td></tr><tr><td>errorEmail</td><td>Enter an email address for error messages</td></tr><tr><td>usersIP<br><em>(Dev environment only)</em></td><td>To simulate a customer in local environment, enter a public IP address here</td></tr><tr><td>payrexxAPIurl</td><td>The basic URL to the Payrexx API</td></tr><tr><td>payrexxAPIinstance</td><td>Your personal Payrexx instance</td></tr><tr><td>payrexxAPIkey</td><td>Your API key from Payrexx</td></tr><tr><td>payrexxDesignID</td><td>Look and feel of your payment page <br>(id from Payrexx)</td></tr><tr><td>payrexxWebhookDev<br><em>(Dev environment only)</em></td><td>Webhook directory for developing environment</td></tr><tr><td>payrexxWebhookPassword</td><td>The webhook password that is specified in the url variable</td></tr><tr><td>payrexxPSPs</td><td>PSP IDs <br>(comma separated list without spaces)</td></tr><tr><td>footerText</td><td>The text in the footer of every page in Saaster (backend)</td></tr><tr><td>Email settings</td><td>Have a look to the config.cfm</td></tr></tbody></table>

## Payrexx related variables

Payrexx is a [Swiss Payment Service Provider](https://www.payrexx.com/?ref=paweco) and is subject to Swiss quality control. And anyone who knows Switzerland knows how important that is. Check out our documentation how to setup Payrexx in saaster:

{% content-ref url="/pages/tczI7BFngc2UrStSyILw" %}
[Payment Service Provider](/fundementals/payment-service-provider)
{% endcontent-ref %}


# Setup Routine

Setup routine for the basic configuration of saaster

{% hint style="danger" %}
After you have successfully run the setup routine, delete the setup folder from your production environment.
{% endhint %}

Our setup routine provides an easy way for the SaaS provider to configure saaster for first usage.\
If you not already have setup saaster on your production server follow this guide first:

{% content-ref url="/pages/QPT0YAYq0IqbnbbyLBkK" %}
[Installation](/getting-started/installation)
{% endcontent-ref %}

## Start setup routine

Once files and database are set up, you should be able to access the setup over following URL:\
\
`https://your-domain.com/setup`

If everything is configured as it should, you will be greeted with the beginning of our setup routine. Start the setup by clicking the according button.

<figure><img src="/files/z3obAu4B6eDz6fE9FUFE" alt=""><figcaption></figcaption></figure>

## Choose operation circle

Now you will be asked to choose between a worldwide or country based operation circle.\
Continue if you selected the desired option.

More information about this under [Country and time zone concept](/fundementals/countries-and-time-zones).

<figure><img src="/files/CKFXjhmyOh91aeCANaU5" alt=""><figcaption></figcaption></figure>

{% tabs %}
{% tab title="Worldwide setup " %}
Have you chosen to offer your project worldwide, you skip the country selection and immediately proceed to the next step. In this step, you choose the default language of your project. Note that you <mark style="color:red;">**CAN'T**</mark> change the default language later on!<br>

<figure><img src="/files/tQYzkHLHhNYIWq3EP9QV" alt=""><figcaption></figcaption></figure>

If your desired language is not available, you can add a new one. To do so, click "Add language".
{% endtab %}

{% tab title="Country based setup" %}
If you selected "country based" as your operation circle, selected the desired countries and proceed.

<figure><img src="/files/qsQZj7X9rEokUkVGVrZD" alt=""><figcaption></figcaption></figure>

Choose your default country and proceed. The default country can be changed later on.

<figure><img src="/files/0tROURXkl0WPvayYZHuF" alt=""><figcaption></figcaption></figure>

In this step, you choose the default language of your project. Note that you <mark style="color:red;">**CAN'T**</mark> change the default language later on!

<figure><img src="/files/fXDdOn651bL80fPYxYCB" alt=""><figcaption></figcaption></figure>

If your desired language is not available, you can add a new one. To do so, click "Add language".
{% endtab %}
{% endtabs %}

## Add new language

If your desired language is not available, you can add a new one.

<figure><img src="/files/nKGjFxeIxm1NVa0iXWDv" alt=""><figcaption></figcaption></figure>

<table data-header-hidden><thead><tr><th width="287"></th><th></th></tr></thead><tbody><tr><td><strong>Field</strong></td><td><strong>Description</strong></td></tr><tr><td><strong>Language (english)</strong></td><td>The language in the English language (e.g. French)</td></tr><tr><td><strong>Language (in its language)</strong></td><td>The language within the language that is captured<br>(e.g. François)</td></tr><tr><td><strong>ISO code</strong></td><td>The ISO code of the language in two digits (e.g. fr)</td></tr></tbody></table>

After you have decided your default language, save it, and go on.&#x20;

If you created a new language, you will be asked to translate all system translations manually or per bulk translate. The bulk translate uses the translation service from DeepL. Create an account [here ](https://www.deepl.com/pro-api?cta=header-pro-api)to get access to the API of DeepL.

<figure><img src="/files/1vM7VaHkxUMi3Z4nuP2J" alt=""><figcaption></figcaption></figure>

## Set default currency

Now select the currency you want to define as default. If your desired currency is not available, you can add it later. You can change the default currency at any time.

<figure><img src="/files/fRpQB2co0Sos8axXS8th" alt=""><figcaption></figcaption></figure>

Click the save button in order to finish the setup.

## Create SysAdmin account

After finishing the setup, you will be redirected to the register form. Provide the requested data and confirm your email address. As the first user that registers, you will receive the role of the SysAdmin.

<figure><img src="/files/pomUhZQgVbCBfI2bWvdB" alt=""><figcaption></figcaption></figure>

Now you should be able to login to saaster and start working on your SaaS project!

`https://your-domain.com/login`


# Roles

All roles in saaster

The role principle of saaster is most easily explained by means of the following sketch. There are three roles: Saaster developer, SaaS provider and SaaS customer.

<figure><img src="/files/beoyw1If9E10WNWeq488" alt=""><figcaption></figcaption></figure>

{% tabs %}
{% tab title="Saaster developer" %}
The saaster developer is responsible for the development and maintenance of saaster.

We appreciate any contribution to improve and expand saaster. The only thing you need are a GitHub Account and some basic CFML knowledge.

{% content-ref url="/pages/5SWiRIyjSaewdML6YMno" %}
[Local development](/development/local-development)
{% endcontent-ref %}
{% endtab %}

{% tab title="SaaS provider" %}
As a SaaS provider you use saaster as the base for your SaaS project. As a provider, you can either develop the software you want to offer by yourself or hand it over to an agency. The SaaS provider has the Sysadmin role in saaster.

{% content-ref url="/pages/QPT0YAYq0IqbnbbyLBkK" %}
[Installation](/getting-started/installation)
{% endcontent-ref %}

{% content-ref url="/pages/KGOKvqJ9BM47qGW79toD" %}
[Administration](/fundementals/administration)
{% endcontent-ref %}
{% endtab %}

{% tab title="SaaS customer" %}

Inside of saaster customers can have one of the three following roles:

* **User**

  * Can use the SaaS offer
  * Can edit his profile
  * Can change his password

* **Admin**

  * *Can additionally:*
  * Edit the company profile
  * View invoices
  * Enter/administer users
  * Manage plans or modules (make settings)

* **Super Admin**
  * *Can additionally:*
  * Enter/edit tenants
  * Buy/rent plans or modules

{% content-ref url="/pages/6EAHtjX6kyGzznUjNtPN" %}
[User guide](/fundementals/user-guide)
{% endcontent-ref %}
{% endtab %}
{% endtabs %}


# Countries and time zones

Country and time zone concept

We have built saaster in such a way that you can choose whether you want to provide your customers with the country choice or not. If you want to offer your software worldwide, the customer only chooses the time zone in which he is located. Saaster then takes the date and time from the time zone.

However, if you want to offer your software only in your own country or in a few countries, you can import the desired countries into the system and add the required data. If you choose a country-based software, the following settings are taken from the country:

* Time zone
* Language
* Currency

For the global solution, the language and locale are fetched from the browser, the time zone is fetched from the customers entry during registration and the currency is fetched from the basic settings. However, the customer can change the currency at any time.


# Scheduletask concept

The schedule tasks help to automate various tasks. This includes renewing subscriptions and other tasks.

You need to create a total of 21 tasks in Lucee. That may sound like a lot, but read this chapter to find out why.

You will find all the files for the schedule tasks in the "scheduletasks" folder.

### Task for subscriptions and other

The main task takes place every 2 hours. It has the following tasks to complete:

* Downgrade plans on waiting list
* Renewing plans
* Renewing modules
* Delete after cancellation
* Set status for expired plans
* Check open invoices (overdue)
* Delete logfiles older than 30 days

Please create a schedule task in Lucee that calls the file subscriptions.cfm **every 2 hours**:

```
https://yourdomain.com/scheduletasks/subscriptions.cfm?pass=xxx
```

You define the password xxx in the URL variable in **config.cfm**

### 20 parallel running tasks

The system is designed so that various tasks from the modules can take place for a large number of customers.

Example: You develop an interface to MailChimp and want all customers and their email addresses to be transferred to MailChimp on a periodic cycle. This should be carried out once every night, which should be done by a schedule task. You have created a file and want it to be executed for all customers who have purchased/subscribed to the module (i.e. the interface).

Now assume you have 1000 customers who have subscribed to the module. If you were to create just 1 schedule task to run the file once every night for all customers, this could possibly take a very long time, which could lead to the server being cancelled or even crashing.

The solution here is to process the tasks in parallel. The customers are distributed across 20 tables. The 20 schedule tasks now process the 1000 customers in parallel, so each task only has to process 50 customers instead of 1000 in serial mode.

So, please set up 20 schedule tasks, which are executed every 2 minutes:

```
https://yourdomain.com/frontend/core//tasks.cfm?task=01&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=02&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=03&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=04&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=05&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=06&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=07&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=08&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=09&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=10&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=11&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=12&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=13&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=14&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=15&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=16&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=17&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=18&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=19&pass=xxxx
https://yourdomain.com/scheduletasks/tasks.cfm?task=20&pass=xxxx
```

You define the password xxx in the URL variable in **config.cfm**


# Payment Service Provider

Payrexx

Saaster makes use of the payment service provider [Payrexx](https://www.payrexx.com/?ref=paweco). At the moment, integration of other payment provides is not planned.

Payrexx is a [Swiss Payment Service Provider](https://www.payrexx.com/?ref=paweco) and is subject to Swiss quality control. And anyone who knows Switzerland knows how important that is.

But this is not the only reason why we decided to work with [Payrexx](https://www.payrexx.com/?ref=paweco). Another reason is that [Payrexx ](https://www.payrexx.com/?ref=paweco)has already integrated tons of other payment service providers in the system, so that every SaaS provider can probably find their desired PSP in it.

<figure><img src="/files/6KmL76KfBxQYJC2LWUJA" alt=""><figcaption></figcaption></figure>

The following chapters will guide you through the configuration and integration of Payrexx in saaster.

## Create an account

First you need an account with Payrexx. [Click here to register](https://www.payrexx.com/?ref=paweco).\
Enter your company name or a part of it here:

<figure><img src="/files/HZZBBclyHxUnQR68MGBK" alt=""><figcaption></figcaption></figure>

After you have created your login, you will find yourself in the [Payrexx ](https://www.payrexx.com/?ref=paweco)account.

## Create an API key

Now you need to create an API key. To do this, navigate to **API & Plugins** on the left-hand side.

<figure><img src="/files/WIiRQDA4WmRn3M7IVUM1" alt=""><figcaption></figcaption></figure>

Click the button "Add API Key" and assign a meaningful name to the new key. It is best to choose the name of your project:

<figure><img src="/files/NBmhYrVG1os5E0ViBpMP" alt=""><figcaption></figcaption></figure>

Keep the API key you received safe. You will need this key in the further steps.

## Create a webhook

Now you create a webhook. This is used to store payment methods and to charge them repeatedly later. To do this, navigate to **Webhooks** on the left-hand side.

<figure><img src="/files/hj9cHlXzwPlGOo4wt6qZ" alt=""><figcaption></figcaption></figure>

You need two webhooks, one for the *development environment* and one for the *production environment*.

### Development environment

You will find a file called "payrexx\_webhook\_dev.cfm" in the saaster file structure in the "frontend" folder. You must now upload this file to any server that can be reached from the internet.&#x20;

*Example:*

`https://your-domain.com/frontend/core/handler/payrexx_webhook_dev.cfm`

This is also the path that you must enter as the webhook.\
Click "Add webhook". Give the webhook a unique name and write the path to the file you just uploaded in the field:

<figure><img src="/files/usU7mxkPuTjyyTJNrwpI" alt=""><figcaption></figcaption></figure>

Configure your webhook exactly as shown above.

### **Production environment**

For the productive environment you can add a webhook and specify the file "payrexx\_webhook.cfm" also in the folder "frontend". Everything else remains the same.

**Note: You must add a password defined in a url variable:**\
`https://your-domain.com/frontend/core/handler/payrexx_webhook.cfm?pass=xxx`

The password is defined in config.cfm

## Create a payment page design

To ensure that your payment page matches your design, you can create a corresponding design in [Payrexx](https://www.payrexx.com/?ref=paweco).

Click on "Settings" on the left, then on "Look & Feel":

<figure><img src="/files/KUfDZ8jE8ojo6yXLFjYD" alt=""><figcaption></figcaption></figure>

Click the green button "Add a new profile" at the top right and fill this form according to your wishes:

<figure><img src="/files/sfShKxx7skncewU86PfH" alt=""><figcaption></figcaption></figure>

Save the new profile at the bottom. You will now get a unique ID for your design.&#x20;

<figure><img src="/files/PmPyM9bRPckX0JWXQ6vq" alt=""><figcaption></figcaption></figure>

Please copy this ID into the config.cfm of your project. Read more about the configuration / config.cfm here:

{% content-ref url="/pages/QPT0YAYq0IqbnbbyLBkK" %}
[Installation](/getting-started/installation)
{% endcontent-ref %}

## Payment providers

In this menu you can configure your payment methods and choose the payment provider.

Please follow the instructions from [Payrexx](https://www.payrexx.com/?ref=paweco), as this configuration can be very extensive. You will also have to provide [Payrexx ](https://www.payrexx.com/?ref=paweco)with some confirmations in order to activate certain payment methods.

Docuementation related to [Payrexx ](https://www.payrexx.com/?ref=paweco)payment providers:

{% embed url="<https://docs.payrexx.com/merchant/payment-priovder/payrexx-direct>" %}

For more information about [Payrexx ](https://www.payrexx.com/?ref=paweco)we recommendreading the official documentation:

{% embed url="<https://docs.payrexx.com/merchant/>" %}


# Administration

Guide for the administration of saaster

When a system administrator logs in to saaster, a red bar appears at the top as an indicator. This shows that you are logged in as a SysAdmin. Also, an additional menu appears in the navigation.

<figure><img src="/files/r5u93h4pIrO7oj1dzf8s" alt=""><figcaption></figcaption></figure>

{% content-ref url="/pages/yfeWhoQrXWzRQ2bd2PhC" %}
[Sales](/fundementals/administration/sales)
{% endcontent-ref %}

{% content-ref url="/pages/HDJsKTnXtAVlngd2x3t5" %}
[System](/fundementals/administration/system)
{% endcontent-ref %}

####


# Sales


# Customers

Tool to manage customers in saaster

A comprehensive tool is available for system administrators to manage the customers:

* Data of customers
* Users of customers
* Invoices of customers
* Plans of customers
* Modules of customers

## Data of customers

Click the Edit button to edit the customer's data:

<figure><img src="/files/NlzLMRa3qBJF0CylcRKi" alt=""><figcaption></figcaption></figure>

For more details, click the company name:

<figure><img src="/files/szqke2a3x03PfoKR2lGS" alt=""><figcaption></figcaption></figure>

## Users of customers

When you opened the details of a company, click the register `Users` to view and edit a user:

<figure><img src="/files/7Db69c8r3eMTzpVdDs3t" alt=""><figcaption></figcaption></figure>

You can only edit the salutation, first name, surname and email address.&#x20;

{% hint style="info" %}
Changing an email address does not trigger a confirmation email. Users may not be able to log in if they are not aware of the change of address.
{% endhint %}

## Invoices of customers

Click the register `Invoices` to view and edit an invoice:

<figure><img src="/files/myDD3cjr8aSgD3AtA5Px" alt=""><figcaption></figcaption></figure>

You have more options by clicking to the button `Action`:

* Add a new invoice for this customer
* Edit an existing invoice
* Print an existing invoice
* Send the invoice to the customer by e-mail
* Delete an existing invoice

## Plans of customers

Click the register `plans` to view and edit the customer’s plan:

<figure><img src="/files/omiWa9GBUlRitHpdoKmJ" alt=""><figcaption></figcaption></figure>

In this tab you have the option to book, downgrade or upgrade a plan for the corresponding customer. Each available plan is displayed in a box. The button `Action` contains various options depending on the status of the plan:

#### **Activate now (free)**

The plan is activated immediately without charging an amount

#### **Activate the test time (xx days)**

Activate the plan with test time. Depending on how many test days you have given to the plan, the client can test for as long as they want.

#### **Make invoice for monthly cycle ($ xx)**

You can create an invoice for the customer first, which he then must pay. Only after the invoice is defined as "paid" the plan is activated.

#### **Make invoice for yearly cycle ($ xx)**

You can create an invoice for the customer first, which he then must pay. Only after the invoice is defined as "paid" the plan is activated.

#### **Edit period**

In the case of a plan that has already been booked, it is possible to change the term/period.

#### **Cancel at expiry date**

Cancel the booked plan at the expiry date.

#### **Withdraw plan**

Withdraw and delete the plan. Any credit balance will not be reimbursed and will also be deleted.

## Modules of customers

Click the register `modules` to view and edit the customer’s modules:

<figure><img src="/files/FvMSg9btC6uVYKryXXlB" alt=""><figcaption></figcaption></figure>

In contrast to the plans, the client may have activated several modules. Here you can manage the modules.

#### **Activate now (free)**

The module is activated immediately without charging an amount

#### **Activate the test time (xx days)**

Activate the module with test time. Depending on how many test days you have given to the module, the customer can test for as long as they want.

#### **Make invoice for monthly cycle ($ xx)**

You can create an invoice for the customer first, which he then must pay. Only after the invoice is defined as "paid" the module is activated.

#### **Make invoice for yearly cycle ($ xx)**

You can create an invoice for the customer first, which he then must pay. Only after the invoice is defined as "paid" the module is activated.

#### **Edit period**

In the case of a module that has already been booked, it is possible to change the term/period.

#### **Cancel at expiry date**

Cancel the booked module at the expiry date.

#### **Withdraw plan**

Withdraw and delete the module. Any credit balance will not be reimbursed and will also be deleted.


# Invoices

Tool to manage invoices in saaster

In this menu you can view and edit your customers' invoices or enter and send invoices. An invoice does not necessarily have to be related to a plan or a module, which is why this tool can also be used for other purposes.

<figure><img src="/files/s5xkJf8PHaJXGGZzjt5q" alt=""><figcaption></figcaption></figure>

## Invoice states

The following states for invoices exist in saaster:

<figure><img src="/files/CDBDvVZoz07MLV3YY4A8" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="156"></th><th>Description</th></tr></thead><tbody><tr><td>Draft</td><td>In draft mode, the invoice can still be modified. The invoice is not displayed to the customer while still in draft state</td></tr><tr><td>Open</td><td>The invoice is displayed to the customer and has not been paid yet</td></tr><tr><td>Paid</td><td>The invoice has been fully paid</td></tr><tr><td>Partial paid</td><td>The invoice is partially paid</td></tr><tr><td>Canceled</td><td>The invoice was cancelled by the system administrator</td></tr><tr><td>Overdue</td><td>The payment deadline for the invoice has been exceeded</td></tr></tbody></table>

## Create a new invoice

Click the `New invoice` button to create a new invoice. The following modal opens:

<div align="left"><figure><img src="/files/1vVuo1Q9j2fijboAfEmO" alt=""><figcaption></figcaption></figure></div>

1. In the `Search for customer` field, type in the first few letters of the customer for whom you want to create the invoice. Select the appropriate entry.
2. Assign a title to the invoice (optional).
3. Click `Save invoice`

You are now in the edit mode of the invoice. Now you need to add some items:

<figure><img src="/files/cVisx0f61rNYnRoiGKhX" alt=""><figcaption></figcaption></figure>

1. With the preview button you can view the invoice at any time
2. If you want to view the client, click the name.
3. Use this button to add positions to the invoice (see next image).
4. With the settings button you can edit the properties of the invoice.
5. The status icon provides information about the status of the invoice at any time.

## Add new position

The positions are not linked to the plans or modules. If you want to create an invoice to charge and link a plan or module, you must do this directly with the customer under `Customers` in the [Plans ](/fundementals/administration/sales/plans)or [Modules ](/fundementals/administration/sales/modules)tab.

<div align="left"><figure><img src="/files/7PS9nwEPcK6APZDqUy5i" alt=""><figcaption></figcaption></figure></div>

<table><thead><tr><th width="203">Field</th><th>Description</th></tr></thead><tbody><tr><td>Position title</td><td>The title of the position</td></tr><tr><td>Position description</td><td>The description of the position, which is displayed on the invoice.</td></tr><tr><td>Quantity</td><td>The quantity of the position</td></tr><tr><td>Single price</td><td>The unit price of the position</td></tr><tr><td>VAT (%)</td><td>Value added tax in percent</td></tr><tr><td>Unit</td><td>The unit (e.g. pcs, months, years)</td></tr><tr><td>Discount (%)</td><td>The discount of the position in percent</td></tr></tbody></table>

## Edit invoice

After you have added the first position, the following screen appears:

<figure><img src="/files/122RgImouQBJTN5NCu9y" alt=""><figcaption></figcaption></figure>

1. An arrow pointing upwards appears to the right of the status symbol. This means that the invoice is still in draft mode. If you click the arrow, the invoice is set to the status `open`.
2. With this symbol you can edit the position.
3. With this symbol you can delete the position.

As soon as the invoice reaches the status `open`, this screen is displayed:

<figure><img src="/files/BtEr5ScdtEapeyCNqecj" alt=""><figcaption></figcaption></figure>

1. This icon takes you to a window with which you can manage payments.
2. Click the arrow pointing downwards to return the invoice back to the draft mode.

## Manage payments

In the payment window, the payments of an invoice can be managed:

<figure><img src="/files/gqierbKqHJ5hYXlCghI2" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="252">Field</th><th>Description</th></tr></thead><tbody><tr><td>Date</td><td>The date on which the payment is posted</td></tr><tr><td>Payment type</td><td>The method used for the payment (e.g. PayPal or Visa)</td></tr><tr><td>Amount (Currency)</td><td>The amount paid in the corresponding currency</td></tr></tbody></table>

Once the invoice has been paid in full, the status of the invoice is changed to **PAID**:<br>

<figure><img src="/files/lcax69PN1y93TzVjQ8ZI" alt=""><figcaption></figcaption></figure>


# Plans

Creation and management of plans inside saaster

In this chapter we will look at creating and managing plans. You need to distinguish here how you want to use saaster. If you want to provide your SaaS offer worldwide, you only need one group, which you name *Pricing worldwide*, for example.\
\
Click the button `Settings` and select `Plan groups`:

<figure><img src="/files/amul7wCZwDLzO2LbeGEx" alt=""><figcaption></figcaption></figure>

## Add a group

Click the button `Add plan group`.

If you would like to offer your service worldwide and have not activated any countries, the window will appear as follows:

<div align="left"><figure><img src="/files/QvvH4QbhgjqaRnoOXrSd" alt=""><figcaption></figcaption></figure></div>

As you can see, you can't select countries here.\
However, if you only offer your software in some countries, the following window will appear:

<div align="left"><figure><img src="/files/iFqTjGDEzT86dczVwoR1" alt=""><figcaption></figcaption></figure></div>

Now enter a group for each country if the prices, currencies etc. are different.\
In our example we will show you how to proceed with a worldwide plan.

<figure><img src="/files/RPZhhwS4ApTdTt1sa9R8" alt=""><figcaption></figcaption></figure>

## Plan features

The features of the plans can be presented in a matrix. In this chapter you will learn how to capture and configure these features.

The features can be populated with feature categories as desired. Click `Add feature` to enter a category or feature:

<div align="left"><figure><img src="/files/53M0mtCfmai7wtXttulj" alt=""><figcaption></figcaption></figure></div>

<table><thead><tr><th width="179">Field</th><th>Description</th></tr></thead><tbody><tr><td>Feature name</td><td>The feature name can be a category or the feature itself.</td></tr><tr><td>Description</td><td>Enter a description of the feature. This text is displayed with the feature by means of a tooltip. This text has no effect on categories.</td></tr><tr><td>Category</td><td>If this settings is activated, the name changes to a category and is displayed slightly bolder.</td></tr><tr><td>Variable</td><td>With this variable you can access the value of the feature (see also edit features).</td></tr></tbody></table>

## Add new plan

Click the button `Add plan` to create a new plan. The following window appears:

<div align="left"><figure><img src="/files/zYzX3J2r301ODFOjX94p" alt=""><figcaption></figcaption></figure></div>

<table><thead><tr><th width="163">Field</th><th>Description</th></tr></thead><tbody><tr><td>Plan group</td><td>Choose under which group the new plan belongs</td></tr><tr><td>Plan name</td><td>Give the plan a name (e.g. Premium or Basic etc.)</td></tr></tbody></table>

After you have saved the plan, you are in edit mode.

## Edit a plan

{% hint style="info" %}
Don't forget to click the save button before switching tabs!
{% endhint %}

### Details

The editing mask for a plan looks like this:

<figure><img src="/files/BU5Ld3xuQeg9lanvyQVs" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="238">Field</th><th>Description</th></tr></thead><tbody><tr><td>Plan group</td><td>Choose under which group the plan belongs</td></tr><tr><td>Plan name</td><td>Give the plan a name (e.g. Premium or Basic etc.)</td></tr><tr><td>Short description</td><td>The short text is displayed in the box above the button</td></tr><tr><td>Description</td><td>The description is displayed in the box below the button</td></tr><tr><td>Button name (for not…)</td><td>The button text in non-registered status</td></tr><tr><td>Booking link</td><td>If the button should not link to the booking page, a specific link can be stored here (e.g. to a form)</td></tr><tr><td>Free plan</td><td>Define whether this plan is a free plan</td></tr><tr><td>Recommended</td><td>Mark the plan as "Recommended" with this setting</td></tr><tr><td>Number of test days</td><td>Determine the number of days the customer can test the plan</td></tr><tr><td>Maximum users</td><td>Enter here the maximum number of users intended for this plan</td></tr></tbody></table>

### Prices

<figure><img src="/files/2NIHhBxhtEpNim1CYOCM" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="237">Field</th><th>Description</th></tr></thead><tbody><tr><td>Price monthly</td><td>Specify the amount for monthly payment</td></tr><tr><td>Price yearly</td><td>Specify the amount for yearly payment (perhaps with discount)</td></tr><tr><td>Vat (%)</td><td>The value added tax in percent</td></tr><tr><td>Vat type</td><td>The type of VAT</td></tr><tr><td>Netto</td><td>Determine if net or gross prices</td></tr><tr><td>On request</td><td>If <code>On request</code> is activated, no price appears in the box and the specific link is used.</td></tr></tbody></table>

### Features

<figure><img src="/files/qeY4OHCmQhOHRBnh2M3K" alt=""><figcaption></figcaption></figure>

You can enter all the values contained in this plan one after the other.

{% hint style="info" %}
If the checkbox is activated, a green tick appears in the matrix. If there is a value in the text field, the value from the text field is displayed in the matrix. If the checkbox is activated AND there is a value in the text field, the value from the text field has priority.
{% endhint %}

### Modules

<figure><img src="/files/r2C7XmlBzlK00wmLPrlq" alt=""><figcaption></figcaption></figure>

You have the option of offering existing modules for each plan. When the customer books the plan, the module is also activated immediately without having to pay for it separately. If the customer cancels the plan, the module is also cancelled.

## Set a default plan

After you have created all your plans, you can select a plan to act as the `default` plan. This means that when a customer registers without directly booking a plan, the default plan is automatically activated.

{% hint style="info" %}
You need at least a free or a plan with test days.
{% endhint %}

<figure><img src="/files/qNIE5TIhVQAblxAV3m3U" alt=""><figcaption></figcaption></figure>


# Modules

Tool to manage modules in saaster

We first make sure that you know what we mean exactly by `module`. The term `module` might be a little confusing.

In saaster, a module is a small application that can be run alongside or together with a plan. You could also say "plugin" to the module, but not in the style of a WordPress plugin. With saaster, nothing is installed as with WordPress, but simply activated.

Just as with plans, a module can be given a price, a trial period or offered free of charge. It is also possible to link modules to a plan (see [Plans/Modules](/fundementals/administration/sales/plans#modules)).

{% hint style="info" %}
Don't forget to click the save button before switching tabs!
{% endhint %}

## Add a module

Add a new module by clicking on the button `Add module`. Give your module a name and save the module. You are now in the following screen:

<figure><img src="/files/2WCvDspAXOVDcBDdk9Qk" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="188">Field</th><th>Description</th></tr></thead><tbody><tr><td>Bookable</td><td>A module that cannot be booked is displayed to the customer but cannot be purchased.</td></tr><tr><td>Active</td><td>Activate or deactivate the module. A deactivated module is not displayed at the customer nor in the plans for linking.</td></tr><tr><td>Module name</td><td>The name of the module that is displayed in the box.</td></tr><tr><td>Short description</td><td>A small text that is displayed in the preview (box).</td></tr><tr><td>Description</td><td>A detailed text describing the module. Displayed using a modal.</td></tr><tr><td>Module settings</td><td>Please choose a short but meaningful name for the module. Make sure that the name does not contain any special characters. You will find further instructions right next to the mask or in the technical documentation.</td></tr><tr><td>Free module</td><td>If you want to capture the module as "free of charge", activate this checkbox. The tab "Prices" will then be deactivated.</td></tr><tr><td>Picture/Logo</td><td>Upload a logo or image for this module.</td></tr><tr><td>Number of test days</td><td>Allocate the number of days a customer may test the module before it must be purchased/booked.1</td></tr></tbody></table>

## Module prices

The following mask provides for editing the prices of a module. You can either define a fixed price or recurring prices.

<figure><img src="/files/4gbmFM7z4JgWZ75jlRVP" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="212">Field</th><th>Description</th></tr></thead><tbody><tr><td>One time pricing</td><td>If the module is sold with a fixed price (one-time), enter the amount in each currency. The recurring prices are thus ignored or set to 0.</td></tr><tr><td>Price monthly</td><td>If recurring amounts, specify the amount for monthly payment</td></tr><tr><td>Price yearly</td><td>If recurring amounts, specify the amount for yearly payment (perhaps with discount)</td></tr><tr><td>Vat (%)</td><td>The value added tax in percent</td></tr><tr><td>Vat type</td><td>The type of VAT</td></tr><tr><td>Netto</td><td>Determine if net or gross prices</td></tr></tbody></table>

### Module scheduletasks

In this tab you can add schedule tasks for the module. It is important to know that each schedule task can be executed at most every 2 minutes. 1-minute tasks are not possible. When saving, no direct schedule tasks are created in Lucee, but these are triggered by well-planned, system-wide schedule tasks.

You can read more about the schedule tasks here: [Scheduletask concept](/fundementals/scheduletask-concept)

<figure><img src="/files/hmPX2rfWQQmNr0f5Gkru" alt=""><figcaption></figcaption></figure>


# System


# System settings

System-wide settings for saaster

The system settings contain system-wide settings that you can make for your software.

## Invoice settings

<figure><img src="/files/sykZsxrpXzMcKyzH3uvd" alt=""><figcaption></figcaption></figure>

{% tabs %}
{% tab title="First setting" %}
**New invoice: At which invoice number should the system start?**

* Each invoice is numbered, while here you enter the starting number of the invoice you want to start with.
  {% endtab %}

{% tab title="Second setting" %}
**The rounding factor for invoice amounts**&#x20;

* For invoice amounts that receive an odd sum, the system can round up or down. Determine here which rounding factor is to be used for this.&#x20;
* Please note that at the moment only rounding to 5 cents (Switzerland) or to 1 cent can be used.
  {% endtab %}

{% tab title="Third setting" %}
**Invoices can be preceded by a short prefix**

* Each invoice number can be preceded by a prefix
* Example for the first invoice: INV-1000
* Or: RE-55200
* etc.
  {% endtab %}

{% tab title="Fourth setting" %}
**Which vat type should be set by default?**

You can choose between the following 3 VAT types:

* Incl. VAT
* Excl. VAT
* No VAT
  {% endtab %}

{% tab title="Fifth setting" %}
**Decide whether the invoices are issued "net" by default.**

Furthermore, it is possible to select the default value for gross and net:

* Netto
* Gross (brutto)
  {% endtab %}
  {% endtabs %}

## Layout settings

In this setting you can define the layout and color scheme of saaster. This setting will be applied globally for the whole application.

<figure><img src="/files/e0iNWZyOg45Fr8QGWPoQ" alt=""><figcaption></figcaption></figure>


# API Settings

All settings related to the API

You can easily create and manage your APIs in the API Settings section. Simply press the button in the left corner to create a new API

<figure><img src="/files/IqQcMdCuSJtILWTGaTjc" alt=""><figcaption></figcaption></figure>

A modal will open, allowing you to define the details of your API.

{% hint style="warning" %}
You will not be able to retrieve the API key after the API is created, so it is essential to copy the key before closing this window.
{% endhint %}

<figure><img src="/files/D2McBvFbtVOxKLT27zI4" alt=""><figcaption></figcaption></figure>

Once you have successfully created an API, you can utilize it in your application.

<figure><img src="/files/lDHTdTkDdacZrWCzPO2s" alt=""><figcaption></figcaption></figure>

Use this guide to kickstart your experience with the saaster API:

{% content-ref url="/pages/WBjIeC0z12b2VSqDPOki" %}
[API: Get started](/api/api-get-started)
{% endcontent-ref %}


# Languages

Settings related to languages in saaster

{% hint style="warning" %}
The *default language* must be set during the setup of the project. You cannot change the default language later!
{% endhint %}

## Adding a new language

Any number of languages can be added

<figure><img src="/files/3IqydTGtlNwmdtC4PLO7" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="254">Field</th><th>Description</th></tr></thead><tbody><tr><td>Language (english)</td><td>The language in the English language (e.g. French)</td></tr><tr><td>Language (in its language)</td><td>The language within the language that is captured (e.g. François)</td></tr><tr><td>ISO code</td><td>The ISO code of the language in two digits (e.g. fr)</td></tr><tr><td>Chooseable</td><td>Choose whether the language can be used by the customer</td></tr></tbody></table>

You can then translate the content in the menu [Translations](/fundementals/administration/system/translations).


# Currencies

Settings concerning currencies in saaster

The currencies are displayed with the plans and modules in order to define the prices manually.\
Any number of languages can be added

Note: There will be no automatic conversions. Prices are always defined manually, for each individual currency.

## Add new currency

<figure><img src="/files/tl1sV2MY8Ajzvz2TGYJX" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="270">Field</th><th>Description</th></tr></thead><tbody><tr><td>Currency (english)</td><td>The currency in the english language</td></tr><tr><td>Currency (own language)</td><td>The currency within the language that is captured</td></tr><tr><td>ISO code</td><td>The ISO code of the currency in three digits</td></tr><tr><td>Active</td><td>Choose whether the currency can be used by the customer</td></tr><tr><td>Sign</td><td>Enter the Sign of the curreny (e.g. $)</td></tr></tbody></table>


# Countries

Settings related to your operation circle

Whether you import countries or not affects the way saaster works. \
There are two ways to run saaster:

{% tabs %}
{% tab title="Worldwide" %}
If you want to provide your SaaS offer in all countries of the world, it is best **not to import** any countries. The system then searches for the correct time zone and currency via the customer’s IP.
{% endtab %}

{% tab title="Country-based" %}
If you only want to provide your SaaS offer in specific countries, **please import** the desired countries. The system then uses the time zone and the currency of the corresponding country.

We have already prepared **250 countries** in the database for you to import. Click "Import countries" to import the desired countries. Then add the few missing details.<br>

{% hint style="info" %}
At the moment countries are not translated yet. They only exist in English. It is therefore necessary that you translate all your desired countries into the other languages you offer in your project.
{% endhint %}
{% endtab %}
{% endtabs %}

## Import countries

Choose the desired countries and scroll to the bottom of the page and click the import button.

<figure><img src="/files/ZEzSThL31qFIxt9WmZ28" alt=""><figcaption></figcaption></figure>

## Edit country

Click the edit button on the country you want to edit. The following modal should open:

<figure><img src="/files/i2h0kVK4nwtYyVRO2fxU" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="308">Field</th><th>Description</th></tr></thead><tbody><tr><td>Country name (english)</td><td>Country name in English (default)</td></tr><tr><td>Language</td><td>Select the language (Only the countries added to saaster are shown here)</td></tr><tr><td>Locale</td><td>Locale of the country (e.g. en_US)</td></tr><tr><td>ISO 1</td><td>Two digit code (e.g. US)</td></tr><tr><td>ISO 2</td><td>Three digit code (e.g. USA)</td></tr><tr><td>Currency</td><td>ISO code of the used currency in the country</td></tr><tr><td>Region</td><td>Region of the country (e.g. Americas)</td></tr><tr><td>Subregion</td><td>Subregion of the country (e.g. North Americas)</td></tr><tr><td>Flag</td><td>Flag using flagcdn.com</td></tr><tr><td>Timezone</td><td>Time zone of the country (dropdown)</td></tr><tr><td>Prio</td><td>Prio is the order of the country</td></tr><tr><td>Default</td><td>Decide whether the country is to be defined as default</td></tr></tbody></table>


# Mappings

Settings regarding the mappings of saaster

The mappings are used to make the URL readable. At the same time, they are used for rights management and security measures.

They are divided into ***Custom mappings*** and ***System mappings***. Each mapping points to the corresponding path without showing the path in the URL.

## Custom mappings

Custom mappings are used by SaaS providers who develop an application using saaster. These mappings should never be touched by any updates.

### Add new mapping

<figure><img src="/files/rc1dG0vKE6mXpxZ2eicW" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="205">Field</th><th>Description</th></tr></thead><tbody><tr><td>Mapping</td><td>The desired display in the URL, beginning at the <code>root</code>.</td></tr><tr><td>Path</td><td>The file that must be called with the mapping, beginning at the <code>root</code>.</td></tr><tr><td>Users</td><td>If this flag is set, <em>users</em> and every following user can access this page.</td></tr><tr><td>Only Super Admins</td><td>If this flag is set, <em>Super Admins</em> and <em>Sys Admins</em> can access this page.</td></tr><tr><td>Only Sys Admins</td><td>If this flag is set, only <em>Sys Admins</em> can access this page.</td></tr></tbody></table>

## System Mappings

The system mappings are used by developers of the saaster project. Please never change these values, as these mappings are used directly in the code. If you change the system mappings, saaster may no longer run properly.&#x20;


# Translations

Settings and configuration of translations

The translations are also divided into two areas: ***Custom*** and ***System***.

These variables are used to use texts in the application that do not come from the database. Instead of writing the text directly into the code, so-called translation-variables are used.

You can show all the existing translations using this button:

<div align="left"><figure><img src="/files/YqyXpey1L23aiOXlPqKN" alt=""><figcaption></figcaption></figure></div>

## Custom translations

You can store your own language variables in this section and use them in the code.

### Add language variable

<figure><img src="/files/V2XZmVEk03e1Ryu7TM29" alt=""><figcaption></figcaption></figure>

In the field `Variable` you can add the desired variable as a string, e.g. *`txtPleaseAddName`,* which you then translate in all the languages you’ve added in saaster.

After you’ve added a variable, you can change the translation at any time.

## System translations

The system translations are added by saaster developers. As a SaaS provider that uses saaster you can use these translations, but cannot delete or add them.

To edit the translations, you can click on the small globe next to the translation. Make sure you display all translations&#x20;

<figure><img src="/files/46xiSE6dYyfRR1gX9x8w" alt=""><figcaption></figcaption></figure>

If you want to contribute to the translation of saaster, you can do this via [GitHub](https://github.com/PAWECOGmbH/saaster).

## Bulk translate

After adding a new language, you can use `Bulk translate` to translate all the content in the corresponding tables in one go. To archive this, saaster uses the DeepL API. Therefor, you also need an API key to use this feature.

You can decide whether you want a free account or the Pro one. Just follow this link and register:<br>

{% embed url="<https://www.deepl.com/pro-api>" %}

<figure><img src="/files/mfzLSkjfXb9hgmOCx75c" alt=""><figcaption></figcaption></figure>

Select the source language and the language into which you want to translate. You can also select what should get translated. Copy the API key received into the field and click the corresponding button, depending on which version of the API is available.


# Widgets

Settings regarding the widgets in saaster

Widgets are data displays that can be shown on the dashboard. Lastly, the customer is free to move or hide these boxes.

## Add new widget

<div align="left"><figure><img src="/files/F2R0oYP10D6XPPQsUsjy" alt=""><figcaption></figcaption></figure></div>

<table><thead><tr><th width="256">Field</th><th>Description</th></tr></thead><tbody><tr><td>Active</td><td>Activate and deactivate the widget</td></tr><tr><td>Widget name</td><td>Give the widget a name (for internal purposes only)</td></tr><tr><td>Widget ratio</td><td>Choose the size of the new widget</td></tr><tr><td>Path to the widget file</td><td>Enter the path to the file that contains the widget</td></tr><tr><td>Display permanently or…</td><td>Decide whether the widget should always be available for selection. If yes, the following boxes have no effect</td></tr><tr><td>Display only with plans</td><td>You can select the plans for which the widget has been developed</td></tr><tr><td>Display only with modules</td><td>You can select the modules for which the widget has been developed</td></tr></tbody></table>


# User guide

User interface guide for the customer


# Customer rights

All customer rights available in saaster

<table><thead><tr><th width="329">Function</th><th width="152" data-type="checkbox">Super Admin</th><th data-type="checkbox">Admin</th><th data-type="checkbox">User</th></tr></thead><tbody><tr><td>Edit own profile</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Reset own password</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Edit the profile of the company</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Add and manage users</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Add and manage tenants</td><td>true</td><td>true</td><td>false</td></tr><tr><td>View and print invoices</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Pay invoices</td><td>true</td><td>false</td><td>false</td></tr><tr><td>Add and manage payment methods</td><td>true</td><td>false</td><td>false</td></tr><tr><td>Book and change a plan</td><td>true</td><td>false</td><td>false</td></tr><tr><td>Book and change modules</td><td>true</td><td>false</td><td>false</td></tr></tbody></table>


# Customer Navigation

Guide for the customer navigation

Clicking the user's name in the top right-hand corner opens the user's menu.

<div align="left"><figure><img src="/files/wWpITBTdcfWzcyEzTVrC" alt=""><figcaption></figcaption></figure></div>

Click `Account settings` to see the various settings:

<figure><img src="/files/eKSjOVW3kyAnlTie1sAO" alt=""><figcaption></figcaption></figure>


# Edit profile

Change your profile information

<figure><img src="/files/gourzekkHbzW5NZp76NU" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="202">Field</th><th>Description</th></tr></thead><tbody><tr><td>My Photo</td><td>Upload your own profile picture. The most common formats are supported.</td></tr><tr><td>Salutation</td><td>The user's salutation such as Mr. or Mrs... Titles such as Dr. or Prof. can also be used.</td></tr><tr><td>First name</td><td>The first name of the user.</td></tr><tr><td>Name</td><td>The last name of the user.</td></tr><tr><td>Email Address</td><td>This email address is used for the login. If a change is made, the user will first receive an email with a confirmation link.</td></tr><tr><td>Phone</td><td>The landline telephone number of the user.</td></tr><tr><td>Mobile</td><td>The mobile phone number of the user.</td></tr><tr><td>Language</td><td>The default language of the user. The language of the Interface is taken from those settings every time the user logs in</td></tr></tbody></table>


# Reset password

Password reset form

{% hint style="info" %}
At least 8 characters must be entered. No other rules have been built in.
{% endhint %}

The password can be changed by typing it twice in this form:

<figure><img src="/files/1wlhPEddg6AOYugvNPHx" alt=""><figcaption></figcaption></figure>


# Edit company

Guide to edit your company details

An Admin or Super Admin can edit the company's details:

<figure><img src="/files/skBiDmypHun2Ov6mjVyy" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="244">Field</th><th>Description</th></tr></thead><tbody><tr><td>Logo</td><td>Upload the logo. The most common formats can be uploaded.</td></tr><tr><td>Company name</td><td>The company name of the customer</td></tr><tr><td>Contact person</td><td>The person responsible for opening the account. This entry is not linked to the user administration.</td></tr><tr><td>Address</td><td>The street and house number of the company.</td></tr><tr><td>Additional address</td><td>An additional indication of the street, if available.</td></tr><tr><td>ZIP</td><td>The Postcode.</td></tr><tr><td>City</td><td>The locality of the company.</td></tr><tr><td>Country *</td><td>The country must be selected from a dropdown.</td></tr><tr><td>Timezone *</td><td>The time zone must be selected from a dropdown.</td></tr><tr><td>Email address</td><td>This e-mail address belongs to the company and will not be used for any other purpose (except for invoices, if no invoice e-mail is defined).</td></tr><tr><td>Phone</td><td>The landline telephone number of the company.</td></tr><tr><td>Website</td><td>Website domain</td></tr></tbody></table>

\*Read more about the countries and the time zones at[ Country and time zone concept](/fundementals/countries-and-time-zones).

### Invoice settings

The following fields are specifically for printing on invoices. If these fields are empty, the fields from the company details will be used for invoices.

<table><thead><tr><th width="243">Field</th><th>Description</th></tr></thead><tbody><tr><td>Company name</td><td>The company name for invoices (invoice recipient)</td></tr><tr><td>Invoice email address</td><td>The email address to which invoices are sent.</td></tr><tr><td>Invoice address</td><td>The complete billing address including postcode and town.</td></tr><tr><td>Invoice information</td><td>This field can be used for general information to be printed on the invoice. E.g. the VAT number or a reference.</td></tr></tbody></table>


# Manage users

Tool to manage users

In saaster, 1/n users can be added as long as the current plan allows.

<figure><img src="/files/0xhTBLpNFzT7lGDumjLr" alt=""><figcaption></figcaption></figure>

### Add new user

<figure><img src="/files/m1UZbyfSQ23zQmf3Hoxd" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="209">Field</th><th>Description</th></tr></thead><tbody><tr><td>Active</td><td>Decide whether the user can login or not.</td></tr><tr><td>Administrator</td><td>Decide whether the user is an Admin. Read more about <a href="/pages/5JY0IJwpEVP0LPdkdeVQ">customer rights</a>.</td></tr><tr><td>Superadmin</td><td>Decide whether the user is a Super Admin. Read more about <a href="/pages/5JY0IJwpEVP0LPdkdeVQ">customer rights</a>.</td></tr><tr><td>Salutation</td><td>The user's salutation such as Mr. or Mrs... Titles such as Dr. or Prof. can also be used.</td></tr><tr><td>First name</td><td>The first name of the user.</td></tr><tr><td>Name</td><td>The last name of the user.</td></tr><tr><td>Email address</td><td>This e-mail address is used for the login.</td></tr><tr><td>Phone</td><td>The landline telephone number of the user.</td></tr><tr><td>Mobile</td><td>The mobile phone number of the user.</td></tr></tbody></table>

### Edit user

<figure><img src="/files/lzHSThSGcwZd7YcOGygM" alt=""><figcaption></figcaption></figure>

<table><thead><tr><th width="228">Field</th><th>Description</th></tr></thead><tbody><tr><td>Active</td><td>Deside whether the user can login or not.</td></tr><tr><td>Administrator</td><td>Deside whether the user is an Admin. Read more about <a href="/pages/5JY0IJwpEVP0LPdkdeVQ">customer rights</a>.</td></tr><tr><td>Superadmin</td><td>Deside whether the user is a Super Admin. Read more about <a href="/pages/5JY0IJwpEVP0LPdkdeVQ">customer rights</a>.</td></tr><tr><td>Salutation</td><td>The user's salutation such as Mr. or Mrs... Titles such as Dr. or Prof. can also be used.</td></tr><tr><td>First name</td><td>The first name of the user.</td></tr><tr><td>Name</td><td>The last name of the user.</td></tr><tr><td>Email address</td><td>This e-mail address is used for the login.</td></tr><tr><td>Phone</td><td>The landline telephone number of the user.</td></tr><tr><td>Mobile</td><td>The mobile phone number of the user.</td></tr></tbody></table>


# Manage tenants

Managemant tool for tenants

Since saaster is capable of multiple tenants, it is possible for each customer to create additional companies (tenants). The Super Admin is automatically also the Super Admin of the new tenant. He can then add further users and assign tenants. After a new tenant has been added, the tenant selection appears at the top in the header. This allows the Super Admin to switch between the tenants.

<figure><img src="/files/QcCDHQySEf67XnZNkzXu" alt=""><figcaption></figcaption></figure>

For the user, you can now select the desired tenants for which the user has access:

<figure><img src="/files/3j7Ucn8bWuBJgsa3bsc2" alt=""><figcaption></figcaption></figure>


# View invoices

View and manage your invoices

In the `Invoices` menu, all invoices issued for the customer can be viewed. It is also possible to save the invoice as a PDF file or to print it out.

<figure><img src="/files/5ZY4js6Kg5L5yu8R6Jj6" alt=""><figcaption></figcaption></figure>

### Pay invoice

It is possible for a SysAdmin to issue an invoice for the customer to activate a plan or module. After the customer has paid the invoice, the plan or module is activated.

Whatever a customer needs to be invoiced for, they can pay it here. You can recognise an open invoice by its status:

<figure><img src="/files/6pzct0iT9314hIIXfHNq" alt=""><figcaption></figcaption></figure>

The invoice in detail looks like this:

<figure><img src="/files/toX3ghmnCpleLm1WHEKM" alt=""><figcaption></figcaption></figure>

The customer now has the option to pay the invoice. Either he uses the deposited payment method, or he chooses another payment method.

* Pay with deposited payment method
  * An attempt is made to debit the standard payment method entered by the customer. If this does not work, the next stored payment method is used. If this does not work either, a message is displayed.<br>
* Choose other payment method
  * This feature opens the payment page directly from [Payrexx](https://www.payrexx.com/?ref=paweco). Once the amount has been successfully collected, the customer is redirected back to the invoice.


# Add payment method

Guide to add payment method

Click the `Add payment method` button to add a new payment method. The following window opens:<br>

<figure><img src="/files/TkDOiAHZd3t2hf1MpTE6" alt=""><figcaption></figcaption></figure>

In order to determine whether the selected payment method works, we need to "reserve" a small amount. The amount of 1.- in your currency will be displayed, but not debited. After you clicked `OK` you will be redirected to the payment service provider. Select the desired payment method:

<figure><img src="/files/qALUDnFXTihBKzKL4vz4" alt=""><figcaption></figcaption></figure>

Follow the on-screen instructions to complete the process. After you have added a payment method, it is displayed in saaster:

<figure><img src="/files/7HcSZpOVWgyxOU0F7ra9" alt=""><figcaption></figcaption></figure>

You now have the option to add more payment types. This is useful if the default payment method does not work.

<figure><img src="/files/LR5A1bAfLeM1nLDxlpp3" alt=""><figcaption></figcaption></figure>

Here you can decide which should be the default payment method or remove a payment method.


# Manage plans

Guide on how to manage and buy plans

If you haven't booked a plan yet, the booking button is displayed:

<figure><img src="/files/fno4B4bZoqhCDw6RzvSa" alt=""><figcaption></figcaption></figure>

After clicking, you will be redirected to the plans in the frontend, where you can choose your plan:

<figure><img src="/files/kdd0OL0fRlbGhcTcxJBv" alt=""><figcaption></figcaption></figure>

Depending on the settings, the desired plan is activated in test mode, or the amount is debited from a valid payment method.

The booked plan is shown as follows:

<figure><img src="/files/K1xOHVqiGBAE3KPGATJk" alt=""><figcaption></figcaption></figure>

You can now upgrade, downgrade or cancel the plan (according to your wishes) by clicking on `Plans`.

<figure><img src="/files/UuzPO3TsH0vWfUXzrJ0k" alt=""><figcaption></figcaption></figure>

The following image shows how the administration of the plans looks like:

<figure><img src="/files/GgllW9iSZGp5m9sL8aip" alt=""><figcaption></figcaption></figure>

Depending on the change you want, you will be shown the corresponding amount you have to pay for the upgrade or downgrade:

<figure><img src="/files/y1aXgsdH7gN89GwzR59p" alt=""><figcaption></figcaption></figure>


# Manage modules

Guide concerning the management of modules

The module overview shows all modules that you can activate or book. Each module is displayed according to the SysAdmin's settings:

<figure><img src="/files/xAXskEz0qHUfCieK6hdt" alt=""><figcaption></figcaption></figure>

A click on the info button shows more information of the module:

<figure><img src="/files/qo5N1LOLxfLzBzPr0EG2" alt=""><figcaption></figcaption></figure>

### Activate modules

<figure><img src="/files/yFiXoVgoGswGLhgiZm2b" alt=""><figcaption></figcaption></figure>

* The first module is a free module. It is activated immediately after clicking on the activation button.
* The second module is available on a monthly or yearly cycle. You can decide which cycle to book. Depending on the SysAdmin's settings, the module is activated in test mode or the amount is debited from the standard payment method.
* The third module in our example only has to be paid for once. Depending on the SysAdmin's settings, the module is activated in test mode or the amount is debited from the standard payment method.


# Notifications

Notifications in saaster

You can find your notifications in the top right corner next to the language selection:

<figure><img src="/files/z9BOCVcMsh68eNOon9tr" alt=""><figcaption></figcaption></figure>

You can click on the notification or show all notifications. As soon as you click on the notification, the state changes to read. The notification will have a button that links to a page related to the issue, in this case `Activate`.

<figure><img src="/files/5nx6HODN0lIBQAgKqeUW" alt=""><figcaption></figcaption></figure>

### Notification overview

In the notification overview, which you can access by clicking the `Show all notifcations` button in the user navigation, you will find all notifications. There is an additional functionality to change the status of several notifications at once or to delete them all together.

<figure><img src="/files/SicOmlE3RvGwKO6ZCDmP" alt=""><figcaption></figcaption></figure>


# Local development

Get a local saaster development environment running

Whether you're looking to contribute to saaster or build your own SaaS application, you'll need a development environment. We recommend using the dockerized development environment provided by saaster. The following guide will take you through the steps to set up your development environment and get you ready to start building.

## Prerequisites <a href="#prerequisites" id="prerequisites"></a>

**Windows:**

* [Docker Desktop](https://www.docker.com/products/docker-desktop/)
* [WSL2](https://docs.microsoft.com/en-us/windows/wsl/install) with any Distrobution for example: [Ubuntu](https://apps.microsoft.com/store/detail/ubuntu/9PDXGNCFSCZV?hl=en-en\&gl=EN)\
  In Docker Desktop enable WSL Integration with the distro you choosed.
* make (Install in WSL2 distro)

**Linux:**

* Docker
* Docker Compose
* make

**MacOS:**

* [Docker Desktop](https://www.docker.com/products/docker-desktop/)
* make (Install over xcode)

## Setup

### Clone the repository

```
git clone https://github.com/PAWECOGmbH/saaster
```

### Config files

You can find some example config files in the "configs" folder of the repository. Copy them to the root directory of the application and rename them as followed:

```
config/example.cfconfig.json   ->   /.cfconfig.json
config/example.env             ->   /.env
config/example.server.json     ->   /server.json
config/example.config.cfm      ->   /config.cfm
```

These files should work out of the box. You can obviously change the values of these configs to your liking.

### Start the application

Now you can start the application. Open any console\* in the root application directory and execute the following commands:

> \*On Windows you need to use the WSL distro to use make. The filesystem of Windows is normally mounted under /mnt on your WSL system.

```
make
```

This will output all possible commands:

```
Makefile commands:
dev                     -> creates the local development environment      
reinit                  -> reinites the database
seed                    -> seeds certain sql files
clean                   -> removes full application with all containers
url                     -> outputs all importent URL's of the application
```

Now enter `make dev` and let the application build.\
If everything worked out, then it should display the URL's:

```
------------------------------------------------------
Saaster: http://localhost/login
Mailslurper: http://localhost:9000
Lucee Admin: http://localhost/lucee/admin/server.cfm
------------------------------------------------------
```

## Seeding MySQL files

In the directory `db/dev` you find some SQL files. These files provide you with example data and basic configuration for saaster.

To execute these files, use the following make command:

```
make seed
```

Then enter the number of the sql file you would like to seed.

```
[1] create-plans.sql   
[2] create-widgets.sql 
[3] create-sysadmin.sql
[4] create-modules.sql 
Choose a number: 3
```

We recommend using this scripts in your local development environment. The `create-sysadmin` scripts adds an account with following credentials:

| User     | <admin@saaster.io> |
| -------- | ------------------ |
| Password | testtest           |

## Rebuild database

To completly rebuild the database, you can use the make target `reinit`. This command rebuilds the complete MySQL container and executes all the scripts in the `db/init` directory.

```
make reinit
```

## Mockdata

If you need some customers or invoices while developing, you can make use of the mockdata generator we implementet.

You can access it under `/setup/mockdata/index.cfm`

<figure><img src="/files/n7eH28OeIpXuyvaate6T" alt=""><figcaption></figcaption></figure>


# Folder structure

The folder structure of saaster

<table><thead><tr><th width="136">Main folder</th><th width="140">Sub folder</th><th width="143">Sub folder</th><th>Description</th></tr></thead><tbody><tr><td><strong>api</strong></td><td></td><td></td><td></td></tr><tr><td></td><td>jwt</td><td></td><td>JWT-CFML library</td></tr><tr><td></td><td>resources</td><td></td><td>All API resources</td></tr><tr><td></td><td>taffy</td><td></td><td>Taffy Framework files</td></tr><tr><td><strong>backend</strong></td><td></td><td></td><td></td></tr><tr><td></td><td><mark style="color:red;">core</mark></td><td></td><td>The core folder / never touch it</td></tr><tr><td></td><td></td><td><mark style="color:red;">com</mark></td><td>All .cfc files (models)</td></tr><tr><td></td><td></td><td><mark style="color:red;">handler</mark></td><td>The handler files (controller)</td></tr><tr><td></td><td></td><td><mark style="color:red;">views</mark></td><td>All cfm files (HTML views)</td></tr><tr><td></td><td><mark style="background-color:green;">modules</mark></td><td></td><td>Here you can develope your modules</td></tr><tr><td></td><td><mark style="background-color:green;">myapp</mark></td><td></td><td>Here you can develope your main app</td></tr><tr><td></td><td></td><td>widgets</td><td>Widgets for your app</td></tr><tr><td><strong>configs</strong></td><td> </td><td></td><td>Configuration files for Docker and the application (config.cfm)</td></tr><tr><td><strong>db</strong></td><td> </td><td></td><td>Database SQL files</td></tr><tr><td><strong>dist</strong></td><td> div.</td><td></td><td>Images, CSS, JS and fonts</td></tr><tr><td><strong>frontend</strong></td><td></td><td></td><td>Frontend files, all pages which do not require a login</td></tr><tr><td></td><td>core</td><td></td><td></td></tr><tr><td></td><td> </td><td>com</td><td>All .cfc files (models)</td></tr><tr><td></td><td></td><td>handler</td><td>The handler files (controller)</td></tr><tr><td></td><td></td><td>scheduletasks</td><td>All cfm files (HTML views)</td></tr><tr><td><strong>logs</strong></td><td> </td><td></td><td>Log files, split into monthly folders</td></tr><tr><td> <strong>setup</strong></td><td></td><td></td><td>This folder contains the routine needed for the very first setup on a live environment</td></tr><tr><td></td><td> mockdata</td><td></td><td>Contains scripts to create test data</td></tr><tr><td> </td><td></td><td></td><td></td></tr><tr><td><strong>userdata</strong></td><td></td><td></td><td>Files uploaded by the customer are stored in this folder</td></tr><tr><td></td><td>images</td><td></td><td>Stores images from usres</td></tr><tr><td> </td><td>logos</td><td></td><td>Stores logos from users</td></tr><tr><td> </td><td>modules</td><td></td><td>Pictures for the modules</td></tr><tr><td> </td><td>users</td><td></td><td>Stores profile pictures from users</td></tr></tbody></table>


# Application.cfc

Information regarding the Application.cfc in saaster

The Application.cfc must not be changed, otherwise the system can no longer be updated. If you want to write your own functions that are to be loaded in the application, please use the myApplication.cfc in the "myapp" folder.

To ensure that the application and session scopes are reloaded, we have configured the following URL variables. Simply use these variables in a URL call: `?reinit=x`<br>

1: for the application scope

2: for the translations (to load new languages)

3: for the session (deletes all sessions)

4: triggers 1 till 3 at the same time<br>

Example: <http://localhost/dashboard?reinit=1>


# Develop with saaster

Guide to help you get started developing with saaster

To know which plan or which modules the customer has booked, you can query a struct. This gives you all the relevant information you need to develop your software.

There are two session structs in saaster with which you can get this data:

* session.currentPlan
* session.currentModules

### The session variable "currentPlan"

With the session variable *session.currentPlan* you get all the data for a booked plan. \
This is how it looks like:

<div align="left"><figure><img src="/files/aPykBTBnfkrxlszT6VPO" alt=""><figcaption></figcaption></figure></div>

#### Explanation of the variables:

| **bookingID**       | The primary id from table *bookings*                              |
| ------------------- | ----------------------------------------------------------------- |
| **endDate**         | The end of the current subscription (*date*)                      |
| **invoiceID**       | The primary id from table *invoices,* which is joined to the plan |
| **maxUsers**        | The maximum number of users within this subscription              |
| **modulesIncluded** | An array with all modules included within this plan               |
| **nextPlan**        | A struct containing the data of the next plan if it’s another one |
| **planID**          | The primary id from table *plans*                                 |
| **planName**        | The name of the current plan                                      |
| **priceMonthly**    | The price paid monthly                                            |
| **recurring**       | <p>The current cycle of the plan; <br>ecurring and status</p>     |
| **startDate**       | The start of the current subscription (*date*)                    |
| **status**          | The status of the current subscription; Recurring and status      |

### The session variable "currentModules"

With the session variable *session.currentModules* you get all the data you need. \
This is how it looks like:

<div align="left"><figure><img src="/files/YFZItA0JXYL9CNT1xb4K" alt=""><figcaption></figcaption></figure></div>

#### Explanation of the variables:

| **includedInCurrentPlan**                                 | Whether the module is included within the current plan              |
| --------------------------------------------------------- | ------------------------------------------------------------------- |
| **invoiceID**                                             | The primary id from table *invoices,* which is joined to the module |
| **moduleData**                                            | All data of the corresponding module as a struct                    |
| **moduleID**                                              | The primary id from table *modules*                                 |
|                                                           |                                                                     |
| <mark style="color:blue;">**Struct moduleStatus:**</mark> |                                                                     |
|                                                           |                                                                     |
| **bookingID**                                             | The primary id from table *bookings*                                |
| **endDate**                                               | The end of the current subscription (*date*)                        |
| **fontColor**                                             | The font color is used to display a text in that color              |
| **recurring**                                             | The current cycle of the plan; Recurring and status                 |
| **startDate**                                             | The start of the current subscription (*date*)                      |
| **status**                                                | The status of the current subscription; Recurring and status        |
| **statusText**                                            | The status description to display to the customer                   |
| **statusTitle**                                           | The status title to display to the customer                         |

### Recurring and status

We work in saaster with the term "recurring" to save the cycle of the plan or module. These values are used:

| **test**    | The plan is in test mode and will not be automatically renewed |
| ----------- | -------------------------------------------------------------- |
| **monthly** | The plan is in a monthly cycle                                 |
| **yearly**  | The plan is in a yearly cycle                                  |

Furthermore, many different statuses exist to define plans and modules. These values are used as statuses:

| **test**     | The plan is in test mode                   |
| ------------ | ------------------------------------------ |
| **free**     | There is a free plan running               |
| **active**   | There is a paid plan running               |
| **payment**  | Waiting for payment from the customer      |
| **waiting**  | Waiting to start the plan (next plan)      |
| **canceled** | The plan has been canceled by the customer |
| **expired**  | The plan has expired                       |


# General services


# Mappings and rigths management

Explanation how to manage the rights regarding mappings and permissions

As you have already seen in chapter System Mappings, we use a mapping for the readable URLs, which runs through the database. Here you can find out how it is structured.

The relevant function for the mappings is the *getSEF()* function, which is called in application.cfc. In it, we resolve the URL and redirect the user to the right page.

<figure><img src="/files/WG8XhIJYUj2IbQR8akS8" alt=""><figcaption></figcaption></figure>

* strMapping is the url string in the browser
* strPath is the corresponding file which is loaded by saaster
* The three “admin” columns are for the right management

We currently only operate a small rights management system in saaster, which is reduced to the individual pages. Depending on the status of the logged-in user, the pages are blocked or can be accessed.

If all three boolean values are set to 0, a normal user can also call up the page


# Redirects

Summary on how redirects work in saaster

You can redirect to a specific page in saaster with URL variables after a specific action. The corresponding function triggers a session. Let's say you want to redirect the user to the dashboard after a certain action, then add the mapping to the URL:

* `?redirect=dashboard`

If you want to include a whole URL string as a redirect, it is best to put the URL in a *urlEncodedFormat* function:

* `"?redirect=" & urlEncodedFormat("account-settings/company?companyID=100");`

As already mentioned, the redirect creates a session. This session should be deleted again after the user has been successfully redirected. Delete the session as follows:

• `?del_redirect`


# Customer specific sessions

After a customer has logged in, he or she receives the following sessions:

| user\_id       | The users ID from table *users*                                   |
| -------------- | ----------------------------------------------------------------- |
| customer\_id   | The customer ID from the table *customers*                        |
| user\_name     | The users first and last name (John Doe)                          |
| user\_email    | The e-mail address of the user with which he/she logs in          |
| last\_login    | The date of the user's last login                                 |
| lng            | The current language displayed to the user                        |
| admin          | Whether the customer is an admin (boolean)                        |
| superadmin     | Whether the customer is a super admin (boolean)                   |
| sysadmin       | Whether the customer is a sys admin (boolean)                     |
| currentPlan    | The plan currently booked; The session variable currentPlan       |
| currentModules | The modules currently booked; The session variable currentModules |


# Global variable "getCustomerData"

With this Variable we get all the customer data of a customer we are looking for. The Variable has been implemented in application.cfc.

{% hint style="info" %}
You need a customer session to use this variable
{% endhint %}

The variable returns a struct with client data.


# Global functions

Functions that are globally available through the application

We use the following global functions in saaster, which have been implemented in application.cfc and can be called anywhere.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td>                            <strong>getTrans()</strong></td><td></td><td><a href="/pages/Ka5fCOfh5uO7nYFoiu52">/pages/Ka5fCOfh5uO7nYFoiu52</a></td></tr><tr><td></td><td>                         <strong>getAlert()</strong></td><td></td><td><a href="/pages/xVcqFFqZ44RRCgfP5YfK">/pages/xVcqFFqZ44RRCgfP5YfK</a></td></tr><tr><td></td><td>                            <strong>logWrite()</strong></td><td></td><td><a href="/pages/fijphnOkXQvgePBWdvOH">/pages/fijphnOkXQvgePBWdvOH</a></td></tr><tr><td></td><td>                           <strong>getTime()</strong></td><td></td><td><a href="/pages/PiCv7Iect1L6ExkHPB3j">/pages/PiCv7Iect1L6ExkHPB3j</a></td></tr></tbody></table>


# getTrans()

Global function getTrans()

To display the language variables from the table "system\_translations" as well as "custom\_translations", we use the function getTrans(). Let's assume you want to display the variable "txtActivateThisUser" in the corresponding language:

```cfscript
getTrans('txtActivateThisUser')
```


# getAlert()

Global function getAlert()

Messages can be displayed with the function `getAlert()`. Let's say you want to display the message "Your change has been successfully saved" in a green bar, then use the function as follows:

```cfscript
getAlert('Your change has been successfully saved')
```

You can also work with the language variables from the table "system\_translations" as well as "custom\_translations" here, or with your own sentences. If you want to use such a language variable, simply write:

```cfscript
getAlert('txtActivateThisUser')
```

You can also specify the color of the bar by adding one of the following attributes:

* info (<mark style="color:blue;">blue</mark>)
* warning (<mark style="color:orange;">orange</mark>)
* danger (<mark style="color:red;">red</mark>)
* success (default, <mark style="color:green;">green</mark>)

Example:

```cfscript
getAlert('alertErrorOccured', 'danger')
```

Without any attribute, green (success) is used by default.


# logWrite()

Global function logWrite()

Almost everything in saaster is logged. With this function you can also log your own applications.

The word combination *logWirte* may sound illogical at first; it would be better to use the name *writeLog*. The problem is, however, that the word combination *writeLog* is used directly by Lucee, which is why we simply wrote logWrite.

The function creates a text file in the folder "logs", separated with further folders, which are provided with the date (yyyy-mm). Within the respective folder, the text file is again named with today's date (day). There is a new text file for each day.

**Example 1**: */logs/2022-12/05.log*\
**Example 2**: */logs/2023-02/13.log*

<table><thead><tr><th width="221"></th><th></th></tr></thead><tbody><tr><td><strong>name</strong></td><td>the name of the given function to log</td></tr><tr><td><strong>severity</strong></td><td>"INFORMATION", "WARNING", "ERROR", "FATAL"</td></tr><tr><td><strong>message</strong></td><td>the given message such as an error message</td></tr><tr><td><strong>sendMail</strong></td><td>whether we should send an email to the administrator</td></tr></tbody></table>


# getTime()

Global function getTime()

Saaster offers a ready-to-use function for each user's correct time zone.

{% hint style="info" %}
Saaster sets the current time zone to UTC 0 by default. The getTime() function then converts the user's time based on their input or IP. This function is only available with a customer session.
{% endhint %}

Please always save your times to the database **using the Lucee function now()** and NOT with the SQL function NOW().

The component contains (among others) the following two functions:

* utc2local
* local2utc

If you now want to display the user's date and time (now) anywhere in the world, use this function:

```cfscript
lsDateFormat(getTime.utc2local(utcDate=now()));
lsTimeFormat(getTime.utc2local(utcDate=now()));
```

If you now want to display the date and time from a db entry, use this function:

```cfscript
lsDateFormat(getTime.utc2local(utcDate=qTable.theDate));
lsTimeFormat(getTime.utc2local(utcDate=qTable.theDate));
```

**Reminder:** The date and time in the database is stored in UTC 0.


# Developing the main application

Guide on how to develop your own main application inside saaster

We assume that by now you know what the scenarios are in saaster. If not, please read [this ](/introduction/target-audience)chapter.

You can create your own application in the "myapp" directory.

## myApplication.cfc

If you want to write functions that actually have to be processed in application.cfc, you can use the file myApplication.cfc.

If you want to write functions that actually have to be processed in application.cfc, you can use the file myApplication.cfc. It contains the following prepared functions:

* ownApplicationStart()
* ownSessionStart()
* ownRequestStart()
* ownRequest()

All these functions are called at the corresponding point in the application.cfc.

## Navigation

The file navigation.cfm is included in the main menu. You can add to it and use it as you wish.

## login\_include.cfm

If you want to run some functions or processes after a customer logs in, you can do this in the login\_include.cfm file. This file is called at the last position after the login.

## Folder "widgets"

On the dashboard you can place various widgets that are related to your software or modules.

A widget is always programmed in a single file and called up with the "Widgets" module. More about the module here: System: Widgets

You can also get ready-made code snippets from the framework "Tabler", which we use for saaster.

{% embed url="<https://preview.tabler.io>" %}

## Design template

You will find the file view\_template.cfm in the folder "views". This gives you a nice template for your content.


# Developing modules

Guide on how to develop modules for saaster

We assume that by now you know what the scenarios are in saaster. If not, please read [this ](/introduction/target-audience)chapter.

If you don’t know what a module is, please read this chapter: [Sales: Modules](/fundementals/administration/sales/modules)

We have already taken a few things off your hands when developing modules. Please first [add a module via the GUI](/fundementals/administration/sales/modules) so that all the necessary files are created.

After you have added the module, you will find a new folder in the "modules" folder with the name you have given it. It contains the following files:

* login\_include.cfm
* navigation.cfm
* settings.cfm

## login\_include.cfm

If you want to run some functions or processes after a customer logs in, you can do this in the login\_include.cfm file. This file is called at the last position after the login.

## navigation.cfm

The file navigation.cfm is included in the main menu. You can add to it and use it as you wish.

## Settings

In this file you develop the mask for all settings of the module that the customer can make. Those settings can be accessed by the customer via the navigation or the module overview.


# API: Get started

Get started using the saaster API

The API of saaster provides the oppurtunity to use the functionality of saaster in other application.\
To use the API of saaster you need to create one. Follow this guide for this process:

{% content-ref url="/pages/m86rrQNcZVu60Hu9ezXC" %}
[API Settings](/fundementals/administration/system/api-settings)
{% endcontent-ref %}

We have chosen to use custom headers for passing additional parameters like the customerID and language etc. This approach offers a number of benefits when compared to using path parameters or query parameters. By using headers, we can add new parameters to the API without modifying the endpoint itself, making it more flexible for different use cases. Additionally, custom headers are not visible in the URL, ensuring that sensitive information such as user IDs or authentication tokens can be passed securely without being exposed in the URL. This approach also keeps the URL clean and easy to read, making it easier to understand the purpose of the endpoint.

## First steps

In order to use the saaster API, you need to follow these steps:

1. Generate an access token. Example:<br>

   ```powershell
   curl -X GET \
      http://localhost/api/authenticate \
      -H 'Accept: application/json' \
      -H 'apiID: 1' \
      -H 'apiKey: 1c1932d0-81da-4ad0-93bd-5ca03002f17e' \
   ```
2. Use the access token to create a request to the saaster API. The example below fetches the current plan of a customer:<br>

   ```powershell
   curl -X GET \
      http://localhost/api/getPlanFeatureSetting \
      -H 'Accept: application/json' \
      -H 'Authorization: Bearer {access-token}' \
      -H 'customerID: 1' \
   ```

   > Make sure to replace `{access-token}` with the token you received in Step 1.

#### CFML example:

<pre class="language-cfscript"><code class="lang-cfscript">// Change values to your API
apiID = 1
<strong>apiKey = "YourOwnKey"
</strong>
// Authenticate with API and get token
cfhttp(method="get", charset="utf-8", url="http://localhost/api/authenticate", result="getToken") {
    cfhttpparam(name="Content-Type", type="header", value="application/json");
    
    // Custom saaster related header variables
    cfhttpparam(name="apiID", type="header", value="#apiID#");
    cfhttpparam(name="apiKey", type="header", value="#apiKey#");
}

token = DeserializeJSON(getToken.filecontent).token;

cfhttp(method="get", charset="utf-8", url="http://localhost/api/getPlanFeatureSetting", result="getPlanFeatureSettings") {
    
    cfhttpparam(name="Authorization", type="header", value="Bearer #token#");
    cfhttpparam(name="Content-Type", type="header", value="application/json");

    // Custom saaster related header variables
    cfhttpparam(name="settingVariable", type="header", value="YourVariableName");
    cfhttpparam(name="planID", type="header", value="1");
    cfhttpparam(name="language", type="header", value="en");
}

dump( var=getPlanFeatureSettings.filecontent, label="getPlanFeatureSettings");
</code></pre>


# Resources

Complete list of resources available in the saaster API


# authenticate

### Description

Authenticate users and issue valid tokens.

### Header parameters

<table><thead><tr><th>Name</th><th>Info</th><th data-type="checkbox">Required</th></tr></thead><tbody><tr><td>apiID</td><td>ID of the API</td><td>true</td></tr><tr><td>apiKey</td><td>Key of the API</td><td>true</td></tr></tbody></table>

### Response&#x20;

```json
struct { 
    "token": string 
}
```


# getCurrentModules

### Description

Retrieves all the modules that the customer has subscribed to.

### Header parameters

<table><thead><tr><th>Name</th><th>Info</th><th data-type="checkbox">Required</th></tr></thead><tbody><tr><td>customerID</td><td>ID of customer</td><td>true</td></tr><tr><td>language</td><td>Language in ISO standard</td><td>false</td></tr><tr><td>lngID</td><td>Language ID</td><td>false</td></tr><tr><td>currencyID</td><td>ID off currency</td><td>false</td></tr></tbody></table>

### Response&#x20;

```json
array [
    struct {
        "includedInCurrentPlan": boolean,
        "moduleData": struct {
            "itsFree": number,
            "vat_text_onetime": string,
            "bookingLinkY": string,
            "vatType": number,
            "priceYearly": number,
            "name": string,
            "includedInPlans": array [],
            "picture": string,
            "priceYearlyAfterVAT": string,
            "description": string,
            "priceMonthlyAfterVAT": string,
            "currencySign": string,
            "isNet": number,
            "shortdescription": string,
            "bookingLinkO": string,
            "vat_text_monthly": string,
            "vat_text_yearly": string,
            "bookingLinkM": string,
            "priceOnetime": number,
            "table_prefix": string,
            "moduleID": number,
            "testDays": number,
            "vat": number,
            "bookable": number,
            "priceMonthly": number,
            "active": number,
            "priceOneTimeAfterVAT": string,
            "settingPath": string,
            "currency": string,
            "currencyID": number
        },
        "invoiceID": string,
        "modulStatus": struct {
            "endDate": string,
            "recurring": string,
            "startDate": string,
            "statusText": string,
            "status": string,
            "bookingID": number,
            "statusTitle": string,
            "fontColor": string
        },
        "moduleID": number
    }
]
```


# getCurrentPlan

### Description

Retrieves the current plan that the customer has subscribed to.

### Header parameters

<table><thead><tr><th>Name</th><th>Info</th><th data-type="checkbox">Required</th></tr></thead><tbody><tr><td>customerID</td><td>ID of customer</td><td>true</td></tr><tr><td>language</td><td>Language in ISO standard</td><td>false</td></tr><tr><td>lngID</td><td>Language ID</td><td>false</td></tr><tr><td>currencyID</td><td>ID off currency</td><td>false</td></tr></tbody></table>

### Response&#x20;

```json
struct {
    "planID": number,
    "modulesIncluded": array [],
    "maxUsers": number,
    "invoiceID": string,
    "endDate": string,
    "recurring": string,
    "startDate": string,
    "status": status,
    "bookingID": number,
    "priceMonthly": number,
    "nextPlan": struct {},
    "planName": string
}
```


# getPlanFeatureSetting

### Description

Retrieves all the modules that the customer has subscribed to.

### Header parameters

<table><thead><tr><th>Name</th><th>Info</th><th data-type="checkbox">Required</th></tr></thead><tbody><tr><td>settingVariable</td><td>Feature setting variable</td><td>true</td></tr><tr><td>planID</td><td>ID of plan</td><td>true</td></tr><tr><td>language</td><td>Language in ISO format</td><td>false</td></tr></tbody></table>

### Response&#x20;

```json
string: "value"
```


