# Tasko

## Stakeholders

### at Tasko

- Lorenz
- Mark
- Jannik, Developer
- Ahmed, Developer, Oldenburg
- Joon, Developer, Canada

### at virtuetech

- Marcel, <marcel.malitz@virtuetech.de>
- Thomas Ries, <thomas.ries@virtuetech.de>
- Denis Shabanov, <denis.shabanov@virtuetech.de>

## Upgrade Laravel 11.x to 12.x

Currently tested by with a docker container for php 8.3.
In the Dockerfile, php7.4 packages have been modified to php8.3.

- Note: php-dom and php-json are now part of php8.3 core. No longer need explicit installation.

#### Steps to create php8.3 container:

Build docker image

    docker build -t tasko-backend-php83 -f Dockerfile  .

then

    cd [your tasko backend dir]
    docker run --name tasko-backend-php83 --mount type=bind,source=.,target=/opt -p 8000:8000 -it tasko-backend-php83:latest
    cd /opt/

if you exit and stop the container, you can resume with

    docker start tasko-backend-php83
    docker exec -it tasko-backend-php83 /bin/bash

To install dependencies from package-lock.json:

Note:

- when php composer.phar command conflicts with IDE try [Enable debugging of php](#Enable-debugging-of-php)
- composer.phar was updated from version 1.10.10 to 2.7.6 with `php composer.phar self-update --2` command. (Laravel v12.x requires composer-runtime-api ^2.2)

  php composer.phar install

When making changes to package.json, update package-lock.json dependencies by:

    php composer.phar update

#### List of upgraded dependencies:

- barryvdh/laravel-dompdf - From ^2.1 to ^3.1
- dompdf/dompdf - From ^2.0 to ^3.1
- nesbot/carbon - From ^2.39 to ^3.10.1

#### Modifications made to support Laravel 12.x:

- Fix task config on the config page becomes inaccessible from null dependency resolution, as now dependency injection container now respects the default value of class properties when resolving a class instance ([Container Class Dependency Resolution](https://laravel.com/docs/12.x/upgrade#container-class-dependency-resolution))
- Carbon 3 changes according to [Carbon 3 Migration Guide](https://carbon.nesbot.com/docs/#api-carbon-3)
  - Apply int type casting to `diffIn*` methods (E.g. diffInDays, diffInHours, etc) to maintain the same result as Carbon 2. Carbon 3 now returns float instead of positive integer
  - Apply strong typing for Carbon 3 methods, as now Carbon 3 will throw TypeError instead of warning

### Run various versions of PHP

We will install various versions of PHP on the server and the project will choose which PHP to run by using a setting
in the .htaccess.

#### Install PHP 8.3

Guides used:

- https://psujit775.medium.com/how-to-install-multiple-php-versions-with-apache-on-ubuntu-b37cd23d3019
- https://php.watch/articles/php-8.3-install-upgrade-on-debian-ubuntu#add-repo

First we need to add some PHP repositories as Ubuntu's repositories don't provide PHP 8.3 packages yet.

    sudo apt-get install software-properties-common
    sudo add-apt-repository ppa:ondrej/php
    sudo add-apt-repository ppa:ondrej/apache2
    sudo apt update
    sudo apt install php8.3 php8.3-fpm libapache2-mod-php8.3 php8.3-cgi php8.3-cli php8.3-gd php8.3-common php8.3-intl php8.3-mbstring php8.3-mysql php8.3-opcache php8.3-readline php8.3-xml php8.3-xsl php8.3-zip php8.3-redis php8.3-sqlite3 php8.3-curl php8.3-bcmath php8.3-xdebug php8.3-cgi php8.3-cli php8.3-gd php8.3-common php8.3-intl php8.3-mbstring php8.3-mysql php8.3-opcache php8.3-readline php8.3-xml php8.3-xsl php8.3-zip php8.3-redis php8.3-sqlite3 php8.3-curl php8.3-bcmath php8.3-xdebug php8.3-imap

#### Set default php back to 7.4

    sudo update-alternatives --config php

Then choose the default version manually and check the default version with the following command:

    php -v

#### Configure the project and Apache2 to use PHP 8.3

Check that PHP 8.3 and 7.4 are running:

    sudo systemctl status | grep php

Should return something like:

    │     ├─127325 grep --color=auto php
    ├─php8.3-fpm.service
    │ ├─126310 php-fpm: master process (/etc/php/8.3/fpm/php-fpm.conf)
    │ ├─126318 php-fpm: pool www
    │ └─126319 php-fpm: pool www
    ├─php7.4-fpm.service
    │ ├─ 984 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)
    │ ├─1592 php-fpm: pool www
    │ └─1593 php-fpm: pool www

Then install some modules:

    sudo a2enmod actions fcgid alias proxy_fcgi

If you get a result like the following everything should work fine

    Enabling module actions.
    ERROR: Module fcgid does not exist!
    Module alias already enabled
    Considering dependency proxy for proxy_fcgi:
    Module proxy already enabled
    Enabling module proxy_fcgi.
    To activate the new configuration, you need to run:
    systemctl restart apache2

Restart Apache 2

    sudo systemctl restart apache2

Make the project use the preferred PHP version and add the following code to the project's .htaccess file.
Replace the PHP version with the one the project shall use.

    <FilesMatch \.php>
        SetHandler "proxy:unix:/var/run/php/php8.3-fpm.sock|fcgi://localhost/"
    </FilesMatch>

## Git Hooks

To ensure that we have similar commit messages that contain ticket numbers and that we work on branches which follow
the git flow naming standards, we have some git hooks in the directory `.githooks`. These hooks will make sure, that you will
be informed if you are about to commit to a branch, which deviates from our conventions. Same for the commit messages.
To activate these git hooks, run the following command in your terminal.

    git config core.hooksPath .githooks

Now you are on the safe side.

## Test system

<https://ddemobad.mytasko.de>

credentials not put in here: ask the team.

## Search

For search in several fields maybe utilize
<https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html>
Might need special fulltext index on columns to be searched. Case sensitivity?

## SonarQube

###General prerequisites

Running Docker installation.

### Common steps

Install and launch SonarQube control panel by running

    docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:latest

Then open <http://localhost:9000> and log in with login and password `admin`.

### Scanning backend repo tasko

SonarQube supports PHP out of the box, so we don’t need any plugins, just the SonarQube scanner.

I have tried scanning the same repo with Java-based local scanner and
with Docker image scanner, and for some reason the Java one yielded much
less findings than the one inside Docker, so I recommend using it.

#### Step 0

If this is your first time scanning, you need to create a SonarQube
project. Just go to the dashboard at <http://localhost:9000>, then
Projects → Create project → Manually.

Select name and project key carefully, as changing them later is a bit
painful. Enter the correct name of the main branch (in our case, it is
master, not main). Click Next, use global setting for what is considered
new code, click Create project, then choose option Locally.

#### Step 1

After you have created project and obtained the token for scanning, move
to folder with the source code and run

    docker run \
        --rm \
        -e SONAR_HOST_URL="http://host.docker.internal:9000" \
        -e SONAR_SCANNER_OPTS="-Dsonar.projectKey=<YOUR_PROJECT_KEY>" \
        -e SONAR_TOKEN="<YOUR_AUTH_TOKEN>" \
        -v "<YOUR_REPO>:/usr/src" \
        sonarsource/sonar-scanner-cli

Substitute `YOUR_PROJECT_KEY` with the key of the project you created
(identical to project name by default), `YOUR_AUTH_TOKEN` with token that
you should have received on the previous step, `YOUR_REPO` with the path
to repo on your computer.

#### Step 2

Check the results of the scan at <http://localhost:9000>. Repeat Step 1
after code changes, SonarQube is smart enough to track the changes.

### Scanning application repo tasko_app2

Dart and Flutter are not supported by default, so we have to install the
plugin: <https://github.com/insideapp-oss/sonar-flutter>.

#### Step 0

The plugin has to be put on the SonarQube control panel. We have it
running in Docker, so we need to execute some commands inside the Docker
image to install it:

    docker exec sonarqube bash -c 'wget <PLUGIN_JAR_URL> -P "$SONARQUBE_HOME"/extensions/plugins/'

Replace `PLUGIN_JAR_URL` with the URL to .jar executable
of the plugin (can be found on the releases page:
<https://github.com/insideapp-oss/sonar-flutter/releases>
, as of today the newest .jar is at
<https://github.com/insideapp-oss/sonar-flutter/releases/download/0.5.0/sonar-flutter-plugin-0.5.0.jar>).

Then restart the SonarQube control panel with:

    docker restart sonarqube

The plugin should be installed. Then, create the project, if not already, as described earlier.

#### Step 1

Run the scan with

    docker run \
        --rm \
        -e SONAR_HOST_URL="http://host.docker.internal:9000" \
        -e SONAR_SCANNER_OPTS="-Dsonar.projectKey=<YOUR_PROJECT_KEY>" \
        -e SONAR_TOKEN="<YOUR_AUTH_TOKEN>" \
        -v "<YOUR_REPO>:/usr/src" \
        sonarsource/sonar-scanner-cli

Check the results in the Control Panel.

## Setup DB locally

    git checkout master_virtuetech

### php

-- php composer.phar self-update --2
php composer.phar install
or

    php composer.phar install --ignore-platform-reqs

to rollback to previous composer version

    composer self-update --rollback

### docker

for mariadb

    docker run -d --name tasko-mariadb --env MARIADB_USER=tasko --env MARIADB_PASSWORD=tasko --env MARIADB_ROOT_PASSWORD=root -p 3306:3306 mariadb:10.3.38

for running the backend once do

    docker build -t tasko-backend -f Dockerfile  .

if you want to retag manually

    docker image tag [image-sha] tasko-backend:latest

then

    cd [your tasko backend dir]
    docker run --name tasko-backend --mount type=bind,source=.,target=/opt -p 8000:8000 -it tasko-backend:latest
    cd /opt/

if you exit and stop the container, you can resume with

    docker start tasko-backend
    docker exec -it tasko-backend /bin/bash

Continue with the setup. Next step is only needed once or when updating dependencies do:

    php composer.phar install

create schema if necessary, see below.
You once need to generate an application encryption key:

    php artisan --env=local key:generate
    php artisan --env=local config:cache

Then to serve the application lookup your local ip with `ip a`

    php artisan serve --env=local --host [IP]

You can trace the backennd log file with

     tail -f storage/logs/laravel.log

connect with browser to <http://localhost:8000/>

optional to remove again

    docker rm -f tasko-mariadb
    docker rm -f tasko-backend

#### Enable debugging of php

Inside the docker container do

    find / -name xdebug.ini

This probably yields: `/etc/php/7.4/mods-available/xdebug.ini`

    vi /etc/php/7.4/mods-available/xdebug.ini

and change

    xdebug.client_host=docker.host.internal

to the the IP of your docker bridge, e.g.,

    xdebug.client_host=172.147.1.1

Make sure to start your IDE to listen for debugging connections. Then
continue with above `php artisan` command to serve your application.
If it seems to hang, it might be your debugger already got a connection
and by default paused on entry.

### start db

    cp .env.testing .env.local

in .env.local set
DB_HOST=[IP of you docker bridge, e.g. 172.17.0.1 or 172.147.0.1]
DB_DATABASE=taskolocaldb

connect with your db-tool to:
<jdbc:mariadb://localhost:3306/>

in mariadb create database `taskolocaldb` with charset `utf8` and collation `utf8_bin`.

creates migration info table

    ./artisan --env=local migrate:install

if you receive an error "Connection refused" you might need to execute

    ./artisan --env=local config:cache

show what would be migrated

    ./artisan --env=local  migrate:status

run migration to create/update to latest schema

    ./artisan --env=local  migrate

for some reason you might need to comment out the fulltext index creation in `database/migrations/2019_01_22_103524_fulltextindezes.php` for duplicate key name violations:

    //            $sql= "ALTER TABLE mbd_erg ADD FULLTEXT  INDEX volltext (erg_bemerkung)";
    //            $sql= "ALTER TABLE mbd_sak ADD FULLTEXT  INDEX volltext (sak_bemerkung)";

#### Enable query log for local development purposes

If one wants to see the queries that are executed on your MariaDB intsance, first set the log_output to file and table as follows:

    SET GLOBAL log_output = 'FILE,TABLE';

Run a query or click through the application, which then performs some queries. Next you will see the executed queries by performing the following query:

    select * from mysql.general_log order by event_time desc;

#### Enable slow query log

    SET GLOBAL slow_query_log=1;
    SET GLOBAL long_query_time=0.1; -- in seconds
    SET GLOBAL log_output='TABLE';

Restart `./artisan serve` as the setting only takes effect for new connections:

Check settings with:

    SHOW VARIABLES like 'long_query_time';
    SHOW VARIABLES like 'slow_query_log';
    SHOW VARIABLES like 'slow_query_log_file';
    SHOW VARIABLES like 'log_output';

Check slow queries:

    SELECT * FROM mysql.slow_log;

Some more information regarding slow queries can be found here https://ma.ttias.be/mysql-slow-query-log-without-restart/

#### Server configuration

On the 16th of August 2023 we activated the slow query log on server 8 for queries that take longer than three seconds.
In file `/etc/mysql/mariadb.conf.d/50-server.cnf` the following settings are responsible and will only take effect if
the server restarts which can be done by executing `sudo systemctl restart mysql`.

    slow_query_log
    long_query_time        = 3

#### Export dump

    mysqldump -uroot -proot --opt taskolocaldb > dump.sql

`--opt` is important to receive the `auto_increment` decarations for id
columns.

#### Import dump

create the taskolocaldb as described above, but do not create any tables yet. Then

    docker cp dump.sql tasko-mariadb:/
    docker exec -u 0 -it tasko-mariadb /bin/sh
    su - mysql
    mysql -uroot -proot taskolocaldb

at the mysql prompt do:

    SET autocommit=0;
    SET unique_checks=0;
    SET foreign_key_checks=0;

    source /dump.sql

    COMMIT;
    SET unique_checks=1;
    SET foreign_key_checks=1;

The additional steps apart from the actual data import with `source`
speed up the process significantly. For a big dump (like the 250MB dump
for stwh408) this takes about 2 minutes.

#### Look up version of MariaDB

    select version();

#### Does MariaDB's query optimizer consider statistics?

See https://mariadb.com/kb/en/engine-independent-table-statistics/

    show global variables like 'use_stat_tables';

## Send test emails

The file `.env.testing` contains some mailgun settings, which can be used to send some test emails. Either start the
server and trigger any application code that will send an email or send an email like as follows:

1. Start the artisan console `php artisan tinker`
2. Send an email from the command line like so `Mail::to('any@email.de')->send(new \App\Mail\TestMailable());`, where the
   send parameter accepts any instance of type Mailable. One can just search for classes, which implement the Mailable
   interface, create an instance and pass it on to the send method.
3. Make sure, that the email doesn't end up in your spam folder, which is likely to happen.

## Unit test

After `cd`ing to '/opt' in the container, run the tests with

    ./run_tests.sh

This will pickup the `phpunit.xml` in the tasko main dir mounted to
`/opt` inside the docker container.

### Test Coverage

php needs xdebug installed. The docker file for the tasko backend already
contains the appropriate package. If you want to check if you php has
support,run

    php -v

the output should contain a line referring to Xdebug

    PHP 7.4.33 (cli) (built: Jun  9 2023 07:38:14) ( NTS )
    Copyright (c) The PHP Group
    Zend Engine v3.4.0, Copyright (c) Zend Technologies
        with Zend OPcache v7.4.33, Copyright (c), by Zend Technologies
        with Xdebug v3.1.6, Copyright (c) 2002-2022, by Derick Rethans

To actually run the tests with coverage execute

    XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html='reports/coverage'

Unfortunately this currently produces

    PHP Fatal error:  Uncaught Error: Interface 'Illuminate\Auth\UserProviderInterface' not found in /opt/app/Extensions/TaskoAuthProvider.php:9

## JMeter test

Unfortunately, so far the installation of JMeter can only be done with GUI available (no complete CLI interface). If we ever need to run JMeter on a server with no GUI, there is this comprehensive guide: <https://sarkershantonu.github.io/2021/01/06/install-jmeter-plugins-cli/>

This little test connects to the testing environment <https://ibad.mytasko.de>, logins into it and searches for some user-defined word on the main page. The number of concurrent threads doing this is gradually getting bigger. Graphs showing average response time and current number of threads requesting the main page can then be viewed with the GUI (open respective Listener in the GUI, “Response Times Over Time” or Active Threads Over Time and load `jmeter/log.jtl` into it).

1. Download and unpack JMeter archive somewhere: <https://jmeter.apache.org/download_jmeter.cgi>. Add JMeter to your PATH variable.

2. Download Plugin Manager JAR: <https://jmeter-plugins.org/install/Install/> and put it into `lib/ext` directory, then restart JMeter if needed.

3. Launch GUI JMeter, and locate the Plugin Manager window (it's either in the right upper angle or in the menu Options -> Plugin Manager).

4. From UI, install plugins “Custom Thread Groups” and “3 Basic Graphs”.

5. Open `jmeter/test_prototype.jmx` and tweak it through GUI as you like.

6. To run the test, either just run it from GUI (if you're still tweaking and debugging it), or, if you are ready to run a serious load test with many threads, `cd` to `jmeter` and launch it from console:

   jmeter -n -t test_prototype.jmx -l log.jtl -Jlogin=${YOUR_LOGIN} -Jpassword=${YOUR_PASSWORD}

where `YOUR_LOGIN` and `YOUR_PASSWORD` should be replaced with your credentials to testing environment.

## ELK-Stack

Generate ssl certificate with:

    openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 1000 -out certificate.pem -subj "/C=DE/ST=Bremen/L=Bremen/CN=elk.virtuetech.de"
    openssl x509 -outform der -in certificate.pem -out certificate.crt

## Server monitoring with Elasticsearch, Kibana and Elastic Agents (ELK Stack)

> Denis Shabanov, <denis.shabanov@virtuetech.de>

A few words on the stack first — Elasticsearch is a powerful text searching engine, which we will use to parse and group multiple lines of system and MySQL logs that the server produces. Elasticsearch supports multiple nodes and it uses its own protocol for internode communications. Kibana is a convenient web-based interface for managing Elasticsearch and Elastic Agents. Elastic Agent is the end program that is installed on every monitored server and collects the logs immediately, then sending it to Elasticsearch. Elastic Agents can be managed by a Fleet Server, which itself is a special Elastic Agent, sending configuration files to remote Elastic Agents.

0. First of all, we will install Elasticsearch and Kibana on the same host; follow instructions here: https://www.elastic.co/guide/en/elastic-stack/current/installing-elastic-stack.html. It is advised to use the same versions of every component. As for choice of the platform, our current installation runs on Docker, but you can try and install it natively.

   After successful installation, try to log in to Kibana, it should be accessible at http://localhost:5601.

   Now, we should proceed with the installation of Fleet Server on the same host and Elastic Agents, that will be located on remote servers and they will access Elasticsearch through Internet. This requires us to expose Elasticsearch to Internet, which is HIGHLY NOT RECOMMENDED, even with security enabled. Maybe in the future I will add an intermediary Logstash layer, to avoid this.

1. In order to at least transfer data securely from Elastic Agents to Elasticsearch we need HTTPS, and that includes proper certificates. Automatically generated certificates are only set up to accept connections from localhost, that's why we need to regenerate the whole chain of certificates, starting with self-signed certificate a.k.a. certificate authority.

   Start with this guide: https://www.elastic.co/guide/en/elasticsearch/reference/current/update-node-certs-different.html. At the step when you are require to stop Elasticsearch/Kibana, just stop the Docker containers and manually edit config files with Docker Desktop UI.

2. After that, proceed with this guide: https://www.elastic.co/guide/en/fleet/current/secure-connections.html, in the step when they ask you to generate a CA just use CA you generated in the previous guide. Note: if installing Fleet Server in Docker and not natively, it is helpful to first just start Elastic Agent with no settings:

   docker run \
    --env FLEET_SERVER_ENABLE=true \

   and then copy-paste the command for installation generated by Kibana inside Docker container, just replace `install` with `enroll`.

## Enrolling server in the monitoring

> Denis Shabanov, <denis.shabanov@virtuetech.de>

Once you've done previous steps, head to Kibana, **Side Menu -> Management -> Fleet**, on the page **Agents** press **Add Agent** button. You need to choose agent policy first. Policy is simply a configuration file for Elastic Agent, which defines which integrations will be used and they parameters (e.g. paths to MySQL logs). You can create a new Agent Policy, and edit it later. Then choose **Enroll in Fleet** option and finally execute commands for Linux Tar on the end host with ONE addition: since we use custom certificate authority, add the `--certificate-authorities` option, like that:

    sudo ./elastic-agent install --url=https://elk.virtuetech.de:8220 \
        --enrollment-token=<ENROLLMENT_TOKEN> --certificate-authorities=/absolute/path/to/ca.crt

## Elasticsearch troubleshooting

> Denis Shabanov, <denis.shabanov@virtuetech.de>

- **Some indices have yellow health**
  Solution: in our case, since we only run one Elasticsearch node, it is probably because Elasticsearch is trying to put a replica of index and fails to do it. The rough solution is to execute this command in Elasticsearch console from time to time(**Side Menu -> Management -> Dev Tools**):
  PUT /.ds-\*/\_settings
  {
  "index.auto_expand_replicas": "0-5"
  }

# Description of Tables

Prefix `MBD` means `Mobile Daten`, everything related to smartphone clients.
Prefix `KDB` means `Kunden Datenbank`, ignore then for the moment.

| Table                     | Content                                                                                                                                |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| AGB_USR                   | Cross table between Aufgaben und User                                                                                                  |
| MAIL_SYSTEM               |                                                                                                                                        |
| CALENDAR_EVENTS           |                                                                                                                                        |
| COMPLAINT_CUSTOMER        |                                                                                                                                        |
| COMPLAINT_REPLY_TEMPLATES |                                                                                                                                        |
| DASH_ITEM                 |                                                                                                                                        |
| DOCUMENTS                 |                                                                                                                                        |
| FILE_PIVOT                |                                                                                                                                        |
| FILE_SYSTEM               |                                                                                                                                        |
| GROUP_USER                |                                                                                                                                        |
| GRP_CHILDRENS             | to be removed?                                                                                                                         |
| GRP_PARENTS               | to be removed?                                                                                                                         |
| MBD_AGB                   | Contains Aufgaben, the most important table                                                                                            |
| MBD_AUD                   | Audit log of adaptions of Ergebnisse von Aufgaben                                                                                      |
| MBD_BER                   | Bereiche, top level nodes, structures the tree and used as filter for queries.                                                         |
| MBD_CNT                   | counter, maybe old and to be removed                                                                                                   |
| MBD_DYA                   | _Dynamische Aspekte_, Ergebnisse von Aufgaben, wenn sie weiter geschaltet / delegiert werden                                           |
| MBD_EXT                   | _Externe Ergebnisse_, used for integrating data automatically for Aufgaben from external systems                                       |
| MBD_GRP                   | recursive tree structure                                                                                                               |
| MBD_JPKT                  | temp results for queries from iOS-App. Android app loads files for the same purpose, which get produced by the backend every n minutes |
| MBD_JSONLOGS              | DSVGO related data that needs to be cleared in shorter intervalls than other data                                                      |
| MBD_JSYNC                 | maybe old and to be removed?                                                                                                           |
| MBD_LOG                   | Results pushed from smartphones are written here first and later are moved to `JSON_RESULTS'                                           |
| MBD_MAIL                  | Emails                                                                                                                                 |
| MBD_MAILATT               | Email attachments                                                                                                                      |
| MBD_MCL                   | mobile clients, definition of smartphones in use                                                                                       |
| MBD_PAR                   | system parameters: licenses, settings, formats, ...                                                                                    |
| MBD_PKT                   | Definition of Unterpunkte for Aufgaben                                                                                                 |
| MBD_QAG                   | _Query Aufgaben_, which Ergebnisse go into which report                                                                                |
| MBD_SAK                   | Kommentare zu Aufgaben                                                                                                                 |
| MBD_STR                   | _Störungen_, maybe to be removed                                                                                                       |
| MBD_TAGS                  | for search?                                                                                                                            |
| MBD_TAGS_RESOURCES        | for search?                                                                                                                            |
| MBD_USG                   | User groups                                                                                                                            |
| MBD_USR                   | User                                                                                                                                   |
| MBD_WEP                   | _Wartung Ergebnisse (Unter-)Punkte_, which Punkt is connected to which Ergebnis and which `wep_value`                                  |
| MDB_PIC                   | Pictures, why MDB vs MBD?                                                                                                              |
| MONITOR_FILTERS           |                                                                                                                                        |
| MIGRATIONS                | Used by _Laravel_                                                                                                                      |
| NEXT_TASK_SCHEDULE        | Scheduling of Aufgaben                                                                                                                 |
| ORDER_NUMBERS             |                                                                                                                                        |
| PKT_DEF                   | Definition of Punkte for Aufgaben                                                                                                      |
| READ_LOGS                 | Did a user already see an Aufgabe                                                                                                      |
| TOKEN                     | Tokens for accessing the app / a query result?                                                                                         |
| UPDATE_TRACKER            | which Aufgaben did a User see when (difference to `READ_LOG`?)                                                                         |
| USER_BER                  | _User Bereiche_, which User see which Bereich                                                                                          |
| WEP_VALUES                | Values entered for Unterpunkte of Aufgaben                                                                                             |

## Deployment in PROD

Checkout github tasko `github.com:lorenzdonau/deploy.git` on a machine
used for managing the deployment. Install `capistrano` framework.

Under deploy there are shell scripts per server instance, that in turn
execute cap-skripts per tenant on that server instance. The per tenant
scripts are located under `config/deploy`.

The script pulls the configured branch from github (could also be
different per tenant, but not used at the moment).

The script copies the pulled version to the server and then remotely
configures the Apache-virtual-host directory per tenant by setting links
to the latest code and also to static content on the server.

To roll out a release to all instances this means executing all the per
server-scripts manually. Though usually there is no problem, still there
is no feedback, if everything worked as expected.

Additionally there are ansible scripts available to configure a new
server instance.

## JavaScript and deployment

> Marcel Malitz, <marcel.malitz@virtuetech.de>
> Denis Shabanov, <denis.shabanov@virtuetech.de>

Some parts of frontend are written with React .tsx templates and they
need to be regenerated in order to properly see your changes.

To test your changes:

1.  Some .tsx templates use **lingui** to support internationalization (those
    are `<Trans></Trans>` tags). You put a string identifier in this tag,
    and then it is matched to the corresponding translated line.

        To extract newly appeared identifiers and update occurences of old
        identifiers, run `npm run extract`. Then translate newly appeared
        identifiers in `resources/lang/[en|de|fr]/messages.po` and run
        `npm run compile`.

2.  Run `npm run dev`. Then launch PHP server and see your changes.

To push your changes:

1. Complete **lingui** steps described in “Test” section.

2. Run `npm run prod` and commit changed generated .js files.

If you encounter `code: 'ERR_OSSL_EVP_UNSUPPORTED'` then run
`NODE_OPTIONS=--openssl-legacy-provider npm run dev` or
`NODE_OPTIONS=--openssl-legacy-provider npm run prod` respectively.

# Known issues and how to tackle them

## Allowed memory size of 134217728 bytes exhausted ...

If you get an error like "Allowed memory size of 134217728 bytes exhausted (tried to allocate 118784 bytes)",
then you need to reconfigure PHP. You can check the value by opening https://ibad.mytasko.de/info.php, and then
you need to search for memory_limit. The default is 128M. I fixed that error on some servers by setting it to 256M.
You then need to change the entry memory_limit with this command:

    sudo vi /etc/php/8.3/fpm/php.ini

        <!!!! Set the value max_children in php/fpm/pool.d/www.conf to Memory GB / 2 -> 128 GB -> 64  !>

Look for the entry, change the value, save the change php.ini and restart PHP as follows:

    
    sudo apt install php-fpm
    sudo a2enmod proxy_fcgi setenvif
    sudo a2enconf php8.3-fpm   # adjust PHP version
    sudo systemctl restart php8.3-fpm.service
    sudo systemctl restart apache2

Check that the configuration is changed by calling the info.php file. It should show the just set value.

---

## Activating the Map Feature 🗺️

To enable the map functionality in this project, you must activate it via an environment variable.

1.  Find or create a `.env` file in the root directory of the project. If you don't have one, you can often copy it from an example file (e.g., `cp .env.example .env`).

2.  Add the following line to your `.env` file:

    ```env
    MAP_ENABLED=true
    ```

3.  **Restart your application** for the change to take effect. The system will now recognize that the map feature should be enabled.
