Přeskočit na hlavní obsah

ESO9 Reporting Web Server

Webová verze Reporting Serveru, tj. tisk sestav je volatelný přes URL. Technicky řešeno jako ASP.NET Core API v C# a .NET 10. Načítá offline definici sestavy přímo z databáze ESO9, spouští její datové zdroje, renderuje Stimulsoft předlohu a:

  • vrací PDF přímo jako HTTP odpověď, nebo
  • uloží PDF do dokumentové databáze a založí dokument i vazbu v DMS ESO9.

Projekt nevolá původní Reporting Server, nelinkuje jeho VB zdroje a nepoužívá jeho binární knihovny. Stimulsoft engine je přímá NuGet závislost.

Konfigurace​

Pro lokální spuštění nastavte v appsettings.json nebo přes proměnné:

Eso9__ApplicationConnectionString
Eso9__MaxConcurrentReports
Stimulsoft__LicenseKey
ApiSecurity__ApiKey

Význam konfiguračních hodnot:

  • Stimulsoft__LicenseKey (Stimulsoft:LicenseKey) je licenční klíč pro Stimulsoft Reports. Je povinný pro korektní renderování sestav a získá se z licence Stimulsoft.
  • ApiSecurity__ApiKey (ApiSecurity:ApiKey) je sdílený klíč pro zabezpečení HTTP API. Pokud je nastaven, musí klient posílat stejnou hodnotu v hlavičce X-Api-Key u každého požadavku včetně GET /health. Pokud nastaven není, API není chráněno API klíčem.
  • Eso9__MaxConcurrentReports (Eso9:MaxConcurrentReports) určuje maximální počet sestav zpracovávaných současně v jedné instanci aplikace. Platí společně pro endpointy /api/reports/pdf a /api/reports/dms. Pokud jsou všechny dostupné sloty obsazené, další požadavky čekají na jejich uvolnění. Hodnota 1 znamená sériové zpracování jedné sestavy.

Connection string musí být ve formátu Microsoft.Data.SqlClient, například:

Server=sql01;Database=ESO9START;User ID=report_api;Password=...;Encrypt=True;TrustServerCertificate=True

Připojení k dokumentové databázi se odvodí automaticky ze stejného connection stringu přidáním _DOC k názvu aplikační databáze. Pro ESO9START se tedy použije ESO9START_DOC; server, přihlašovací údaje a ostatní parametry zůstanou beze změny. Položka Database nebo Initial Catalog je proto povinná.

Integrované Windows přihlášení není vhodné pro běžný Linux kontejner.

Volání API​

Základní URL služby při lokálním spuštění:

http://server

Pokud je v konfiguraci nastaven ApiSecurity:ApiKey, musí být u každého požadavku uvedena hlavička X-Api-Key.

Přehled endpointů​

MetodaURLPopis
GET/healthKontrola dostupnosti služby
POST/api/reports/pdfVygeneruje PDF a vrátí ho přímo v HTTP odpovědi
POST/api/reports/dmsVygeneruje PDF, uloží ho do DMS ESO9 a vrátí informace o dokumentu

Tělo požadavku​

Endpointy /api/reports/pdf a /api/reports/dms přijímají JSON tělo ve stejném formátu:

{
"offlineDefinitionId": 3,
"parameters": {
"IDHDOK": 36925,
"PRN_LANG": "CZ"
}
}

Hodnota offlineDefinitionId určuje offline definici sestavy v ESO9. Objekt parameters obsahuje parametry předané sestavě.

Kontrola dostupnosti služby​

GET http://server/health

Příklad pomocí PowerShellu:

Invoke-WebRequest `
-Uri "http://server/health" `
-Method Get

PDF jako odpověď​

POST http://server/api/reports/pdf
Content-Type: application/json
X-Api-Key: ...
{
"offlineDefinitionId": 3,
"parameters": {
"IDHDOK": 36925,
"PRN_LANG": "CZ"
}
}

Výsledek má Content-Type: application/pdf a PDF v těle odpovědi.

curl --fail-with-body \
-X POST http://server/api/reports/pdf \
-H "Content-Type: application/json" \
-H "X-Api-Key: $REPORTING_API_KEY" \
-d '{"offlineDefinitionId":3,"parameters":{"IDHDOK":36925,"PRN_LANG":"CZ"}}' \
--output faktura.pdf

Úspěšná odpověď má Content-Type: application/pdf a její tělo obsahuje vygenerovaný PDF soubor.

Uložení do DMS​

POST http://server/api/reports/dms
Content-Type: application/json
X-Api-Key: ...

Tělo požadavku je stejné jako pro endpoint /api/reports/pdf:

{
"offlineDefinitionId": 3,
"parameters": {
"IDHDOK": 36925,
"PRN_LANG": "CZ"
}
}

Příklad pomocí curl:

curl --fail-with-body \
-X POST http://server/api/reports/dms \
-H "Content-Type: application/json" \
-H "X-Api-Key: $REPORTING_API_KEY" \
-d '{"offlineDefinitionId":3,"parameters":{"IDHDOK":36925,"PRN_LANG":"CZ"}}'

Vazba DMS se vezme z IDTABLE, TABLENAME, IDTYPDOC a IDUZIVATEL vybrané offline definice. Výrazy jako %IDHDOK% se doplní z prvního řádku dat, UP parametrů nebo parametrů požadavku.

Úspěšná odpověď obsahuje JSON s informacemi o uloženém dokumentu, například:

{
"reportCode": "FAKTURA",
"offlineDefinitionId": 123,
"documentId": 98765,
"fileGuid": "30ad41aa-3180-44c6-8aac-49cbbfd70822",
"fileName": "FAKTURA.pdf"
}

Pokud není nastaven ApiSecurity:ApiKey, hlavička X-Api-Key není povinná.

Příklad volání z SQL databáze​

/*
Odeslání dokladu do Web RS
*/
DECLARE @IDHDOK int
DECLARE @headers nvarchar(4000) =
N'<Headers><Accept>*/*</Accept><X-Api-Key>123456</X-Api-Key><Content-Type>application/json</Content-Type></Headers>';

DECLARE @Data nvarchar(max) =
CONCAT(
N'{',
N'"offlineDefinitionId":3,',
N'"parameters":{',
N'"IDHDOK":', CONVERT(nvarchar(20), @IDHDOK), N',',
N'"PRN_LANG":"CZ"',
N'}}'
);

DECLARE @Response nvarchar(max);

SET @IDHDOK = 36925; -- ID dokladu, který chcete vytisknout

EXEC [dbo].[DownloadURL]
'http://10.20.30.36:5099/api/reports/dms',
'POST',
@headers,
@Data,
@Response OUT;

SELECT @Response AS Response;

Žurnál tisku​

Každý úspěšně vyrenderovaný tisk do PDF i DMS se zapisuje do HISSTIOFFLINE. U DMS obsahuje žurnál SESTAVAGUID i FILENAME; u PDF je SESTAVAGUID prázdný a FILENAME obsahuje název vráceného PDF souboru.

Zpracování parametrů​

Hodnoty se skládají v pořadí:

  1. výchozí hodnoty QGSPARAM,
  2. hodnoty offline definice STIOFFLINE_PAR,
  3. hodnoty z HTTP požadavku.

Parametr PRN_LANG z HTTP požadavku má tedy přednost před hodnotou offline definice i před uživatelským parametrem LEGISLATIVA. Hodnota se zapíše také do UP_params.PRN_LANG a před renderováním se podle ní použijí překlady uložené ve GlobalizationStrings Stimulsoft šablony. Pro systémové texty Stimulsoftu jsou přibaleny lokalizace CZ, DE, EN, HU, IT, PL a SK. Pokud PRN_LANG není zadán, použije se LEGISLATIVA, případně CZ.

Placeholdery %PARAM% v ROOTVIEWSQL jsou převáděny na SqlParameter. Fungují původní zápisy %PARAM% i '%PARAM%'; HTTP hodnota se nevkládá přímo jako SQL text. Chybějící parametr vede k HTTP 400.

Datové zdroje typu akce (VLTYPDZSESTAVY=1) se provedou před renderem. Sloupce obsahující FILEGUID, firemní logo a razítko se načtou z ESO9DOC.

Sestavení​

dotnet restore
dotnet build --configuration Release
dotnet run

Docker​

Čisté sestavení Docker image bez použití cache:

docker build --no-cache -t eso9-reporting-web-server-net10:latest .

Uložení sestavené image do TAR souboru pro přenos na jiný Docker nebo Portainer server:

docker save -o eso9-reporting-web-server-net10-latest.tar eso9-reporting-web-server-net10:latest

Na cílovém serveru lze image načíst příkazem:

docker load -i eso9-reporting-web-server-net10-latest.tar

Po načtení bude image dostupná pod názvem eso9-reporting-web-server-net10:latest.

Vytvořte .env mimo verzování:

ESO9_APPLICATION_CONNECTION_STRING=Server=...;Database=...;User ID=...;Password=...
STIMULSOFT_LICENSE_KEY=...
REPORTING_API_KEY=...

Potom:

docker compose up -d

API bude dostupné na http://localhost:5099.

Kontejner obsahuje základní DejaVu fonty a vlastní TTF fonty ze složky Fonts. Vlastní fonty se při startu registrují také přímo do StiFontCollection a při exportu PDF se explicitně vkládají do výsledného dokumentu. Po přidání nebo změně TTF souborů je nutné aplikaci znovu sestavit a vytvořit novou Docker image.

Diagnostika chyb a traceId​

Klient při chybě dostane standardní ProblemDetails odpověď s bezpečnou zprávou a položkou traceId. Stejná hodnota je uvedena v hranatých závorkách u všech logů daného požadavku. Neočekávaná chyba je v logu zapsána včetně úplného stack trace a vnitřních výjimek.

Logy se zapisují současně na konzoli a do rotujících souborů:

logs/eso9-reporting-YYYYMMDD.log

Soubor se rotuje denně nebo po 50 MB a uchovává se nejvýše 30 souborů. Cestu a ostatní parametry lze změnit standardním přepsáním sekce Serilog konfigurace.

Lokální dohledání v PowerShellu:

Select-String -Path .\logs\eso9-reporting-*.log -Pattern '0HNNE6AAQS2NB:00000003' -Context 0,30

Dohledání v Docker Compose:

docker compose exec eso9-reporting-web-server \
grep -n -A 30 '0HNNE6AAQS2NB:00000003' /app/logs/eso9-reporting-*.log

Compose používá persistentní volume report-logs, takže soubory přežijí restart nebo nahrazení kontejneru. Protože obsahují podrobné technické chyby, musí mít přístup k volume pouze administrátoři služby.

DMS konzistence​

PDF, záznam dokumentu a jeho vazbu na tabulku ESO9 zakládá stored procedura spDokument_Zalozeni. Volání procedury a zápis žurnálu HISSTIOFFLINE proběhnou v jedné transakci aplikační databáze. API vrací idDokument z výstupního parametru procedury a fileGuid načtený ze založeného záznamu DOKUMENT.