# API Zadań skryptowych

\
Platforma dostarcza możliwość tworzenia logiki zadań skryptowych handlerów z poziomu Eximee Designer. Projektant procesu musi jedynie napisać logikę handlera oraz podpiąć go w procesie.

## Tworzenie zadania skryptowego <a href="#zadanieskryptowe-tworzeniezadaniaskryptowego" id="zadanieskryptowe-tworzeniezadaniaskryptowego"></a>

Zadania skryptowe możemy tworzyć i edytować za pomocą aplikacji Eximee Designer. W tym celu należy w module **Biblioteka** wybrać zakładkę **Zadania skryptowe**:

<figure><img src="/files/3BAKEFmodOuWdQ03hovB" alt=""><figcaption><p><em><strong>Ilustracja 1.</strong> Okno zakładki zadań skryptowych</em></p></figcaption></figure>

Szczegółowy opis tworzenia skryptów dostępny jest w: [Zadania skryptowe](/budowanie-aplikacji/logika-biznesowa/scriptcode/zadanie-skryptowe-scripttask.md).

### API handlerów <a href="#zadanieskryptowe-apihandlerow" id="zadanieskryptowe-apihandlerow"></a>

```typescript
interface Task {
   getVariable(name): string;                                 // Pobieranie zmiennej procesu o identyfikatorze wskazanym w parametrze
   getAllVariables(): {[key: string]: string};                // Pobieranie wszystkich zmiennych w procesie
   getProcessIntanceId(): string;                             // Zwraca identyfikator instancji procesu
}
 
interface Context {
   complete(variables: [key: string]: string, modelChanges?: [key: string]: string): void; // Zakończenie zadania i przekazanie do procesu zmiennych wskazanych w parametrze oraz opcjonalnie zmian w modelu danych
   handleFailure(cause: string): void;                        // Zgłoszenie na zadaniu incydentu (np. błąd systemowy) wraz z określeniem powodu wskazanego w parametrze (proces zatrzymuje się do czasu interwencji)    
   handleBpmnError(errorCode: string, cause?: string): void;  // Zgłoszenie na zadaniu przewidzianego błędu biznesowego wraz z kodem błędu oraz powodem wskazanym w parametrze (uruchamiana jest ścieżka obsługi błędu w BPMN)
    
   // Deprected
   getModel(String processInstanceId, List<String> fieldsNames): Map<String, String> // Wywołanie modelu danych podając id instancji procesu oraz listę kluczy, których wartość chcemy pobrać.
                                                                                     // Metoda przestarzała. Należy używać api.model
}
 
interface Logger {
    info(message: string, ...args: any);                      // Logowanie na poziomie INFO                
    debug(message: string, ...args: any);                     // Logowanie na poziomie DEBUG
    warn(message: string, ...args: any);                      // Logowanie na poziomie WARN
    error(message: string, ...args: any);                     // Logowanie na poziomie ERROR
    trace(message: string, ...args: any);                     // Logowanie na poziomie TRACE
}
 
function nonsensitive(arg: any): String;
 
function handle(task: Task, context: Context): void {}


```

{% hint style="info" %}
Ustawienie listy grup, które będą miały dostęp do instancji procesu na liście spraw

[Operacje i dostęp do danych procesu](/budowanie-aplikacji/logika-biznesowa/scriptcode/skrypty-scriptservice/api-skryptow/operacje-i-dostep-do-danych-procesu.md)
{% endhint %}

### Przykładowe zadania skryptowe <a href="#zadanieskryptowe-przykladowezadaniaskryptowe" id="zadanieskryptowe-przykladowezadaniaskryptowe"></a>

Skrypt pobiera zmienną o identyfikatorze „testVariable”, mnoży ją przez samą siebie, a wynik przypisuje do nowej zmiennej „result”:

```javascript
function handle(task, context) {
    Logger.info("Rozpoczęcie zadania skryptowego nazwaSensytywna={}, nazwaNieSensytywna={}", 'TAJNE_DANE', nonsensitive('NIETAJNE_DANE'))
 
    const testVariableNumber = task.getVariable('testVariable');
    const testVariablePower = testVariableNumber * testVariableNumber;
     
    Logger.info("Zakończenie zadania skryptowego")
    context.complete({'result': testVariablePower});
 }
```

### Wywołanie usług Rest w zadaniu skryptowym <a href="#zadanieskryptowe-wywolanieuslugrestwzadaniuskryptowym" id="zadanieskryptowe-wywolanieuslugrestwzadaniuskryptowym"></a>

Dokumentacja wywołania: [\[Rest\] Wołanie zewnętrznych usług RESTowych (ScriptCode)](/budowanie-aplikacji/logika-biznesowa/scriptcode/restapi-integracje-z-zewnetrznymi-systemami.md)

{% hint style="danger" %}
Jedyną zmianą co do powyższej dokumentacji jest plik konfiguracyjny.

Ten dla ScriptCode Handler nazywa się **script-handler-api.xml** i znajduję się w katalogu **`/etc/eximee/webforms/script-handler-config`**
{% endhint %}

Przykład zadania skryptowego z wywołaniem zewnętrznej usługi REST:

```typescript
function handle(task, context) {
    // Pobranie zmiennej procesowej o kluczu "testVariable"
    const value = task.getVariable('testVariable');
     
    // Pobranie zmiennej procesowej o kluczu "result"
    const result = task.getVariable('result');
 
    if (value == null || isNaN(value)) {
        // Zgłoszenie na zadaniu błędu wraz z kodem błędu "errorCode"
         context.handleBpmnError("errorCode", "Brak wartości dla zmiennej procesowej o kluczu testVariable");
    }
 
    value = value * 5
    result = result * 5
    Logger.info("Passed: [value={}, result={}]", value, result);
          
    try {
        let response = api.rest.v1.get("questionnaire", {}, {});
 
        Logger.info("Task ended successfully");
        context.complete({'variable1': value, 'variable2': result, 'Questionnaires': response.body});
    }
    catch(e) {
        Logger.warn("Exception occured: {}", e.message);
        context.handleFailure("Failed to retrieve questionnaire list " + e.message);
    }      
}
```

### Pobieranie konfiguracji aplikacji biznesowej <a href="#zadanieskryptowe-pobieraniekonfiguracjiaplikacjibiznesowej" id="zadanieskryptowe-pobieraniekonfiguracjiaplikacjibiznesowej"></a>

Dokumentacja wywołania: [Skrypty (scriptService)#Pobieraniekonfiguracjiaplikacji](/budowanie-aplikacji/logika-biznesowa/scriptcode/skrypty-scriptservice/api-skryptow.md#skrypty-scriptservice-pobieraniekonfiguracjiaplikacji)

Przykład zadania skryptowego z pobraniem konfiguracji:

```javascript
function handle(task, context) {
    // Pobranie zmiennych z konfiguracji
    const skipTask = api.config.v1.get("script.task.skip.task")
    const titleName = api.config.v1.getOrDefault("script.task.title.name", "Domyślny tytuł")
     
    // Zakończenie zadania i przekazanie zmiennych (skipTask, titleName) do procesu
    context.complete({'skipTask': skipTask, 'titleName': titleName});
}
```

### Wywołanie Eximee Status w ScriptCode Handlerze <a href="#zadanieskryptowe-wywolanieeximeestatuswscriptcodehandlerze" id="zadanieskryptowe-wywolanieeximeestatuswscriptcodehandlerze"></a>

{% hint style="danger" %}
Aby wywołanie działało poprawnie należy uzupełnić parametr EXIMEE\_STATUS\_URL wskazujący na api eximee-status.

Metody wywołujące eximee-status wymagają zmiennej procesowej **statusId**, która powinna zawierać numer wniosku, dla którego ma zajść wskazana aktualizacja.
{% endhint %}

#### Status API <a href="#zadanieskryptowe-statusapi" id="zadanieskryptowe-statusapi"></a>

```typescript
interface EximeeStatusClient {
   updateStatus(statusName: string, statusDescription: string): void;   // Aktualizacja nazwy oraz opisu statusu
   updateMetadata(metadata: string): void;                               // Aktualizacja metadanych wniosku
   getMetadata(): Object;                                               // Pobranie metadanych wniosku
   getClientFormsBasicInfo(): Object;                                   // Pobranie listy statusów wniosków dla klienta zalogowanego (Metoda dostępna od wersji 4.154.0. Klient musi być zalogowany, aby funkcjonalność działała.)
 }
```

Przykład ScriptCodeHandler z wywołaniem eximee-status:

```javascript
function handle(task, context) {
    try {
        api.status.v1.updateStatus("NEW_STATUS", "STATUS_DESC");
 
        Logger.info("Task ended successfully");
        context.complete({});
    }
    catch(e) {
        Logger.warn("Exception occured: {}", e.message);
        context.handleFailure("Failed to retrieve questionnaire list " + e.message);
    }      
}
```

### Pobieranie zawartości Treści <a href="#zadanieskryptowe-pobieraniezawartoscitresci" id="zadanieskryptowe-pobieraniezawartoscitresci"></a>

{% hint style="info" %}
Funkcjonalność dostępna od wersji platformy: **3.332.0**
{% endhint %}

Z poziomu zadania skryptowego można pobrać zawartość artefaktu **Treść** (textContent) utworzonego w **Eximee Designer**, wykorzystując do tego funkcję: `api.repository.v1.textContent`. Funkcja ta zwraca obiekt, który posiada treści dla każdego ze zdefiniowanych tłumaczeń. By pobrać treść dla danego tłumaczenia używamy funkcji `language`. Przykład użycia:

```javascript
const nazwaArtefaktu = "stopka";
const wersjaArtefakut = "*";
const język = "pl";
  
const artefaktTresci = api.repository.v1.textContent(nazwaArtefaktu, wersjaArtefaktu);
const stopkaPl = artefaktTresci.language(jezyk).text();
```

{% hint style="danger" %}

1. Funkcja **`textContent`** rzuca wyjątek jeśli nie znajdzie artefaktu o podanych parametrach.
2. Funkcja **`language`** rzuca wyjątek jeśli nie znajdzie tłumaczenia w podanym języku.
   {% endhint %}

Jeśli nie mamy pewności, że podane przez nas parametry są prawidłowe, możemy obsłużyć wyjątki używając **try catch**:

```javascript
const nazwaArtefaktu = "stopka";
const wersjaArtefaktu = "*";
const jezyk = "pl";
  
let artefaktTresci;
try {
    artefaktTresci = api.repository.v1.textContent(nazwaArtefaktu, wersjaArtefaktu);
} catch (error) {
    context.handleFailure("Brak artefaktu o nazwie: " + nazwaArtefaktu + " i wersji: " + wersjaArtefaktu);
    return;
}
  
let stopkaPl;  
try {
    stopkaPl = artefaktTresci.language(jezyk).text(); 
} catch (error) {
    context.handleFailure("W artefakcie nie znaleziono tłumaczenia dla języka: " + jezyk);
    return;
}
 
context.complete({'output': stopkaPl});
```

### Model danych

Więcej informacji w [API modelu danych](/budowanie-aplikacji/model-danych/wykorzystanie-modelu-danych/api-modelu-danych.md)

### Zapisanie danych w modelu danych

W zadaniach skryptowych możemy zapisać dane do modelu za pomocą metody 'complete', pierwszy parametr zapisuje dane do procesu, a drugi parametr zapisuje dane do modelu:

{% hint style="warning" %}
Klucz modelu musi istnieć w modelu danych żeby poprawnie zostało zapisane
{% endhint %}

```js
function handle(task, context) {
    const branchId = task.getVariable('branchId');
    const isDocumentChangedRequired = task.getVariable('isDocumentChangedRequired');
    const documentsNotes = task.getVariable('documentsNotes');
 
    let modelUpdate = { "Ugoda.Adres.Oddzial": branchId, "Ugoda.CzyWymaganaZmianaTresciUmowy": isDocumentChangedRequired }
 
    if (isDocumentChangedRequired == "true") {
        modelUpdate['Ugoda.Uwagi'] = documentsNotes
    }
    context.complete({}, modelUpdate);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.eximee.com/budowanie-aplikacji/logika-biznesowa/scriptcode/zadanie-skryptowe-scripttask/api-zadan-skryptowych.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
