multiflexi-pohoda-raiffeisenbank

multiflexi-pohoda-raiffeisenbank

Raiffeisen Bank statement tools for MultiFlexi

desktop applicationUtility
Instalace
apt install multiflexi-pohoda-raiffeisenbank
Popis

Allow use of Raiffeisen Bank statement tools in MultiFlexi environment

🌐 Domovská stránka🐛 Chyby📋 Detail balíčku

Raiffeisenbank for Stormware Pohoda

License: MIT Packaging: deb

It downloads PDF and XML statements from the Raiffeisen Premium API for a specified period and uploads both to SharePoint.

It parses the XML statements and imports the bank movements into Stormware Pohoda via mServer.

After importing all items, document liquidation is initiated and they are automatically matched.

After uploading to SharePoint, links to the PDF statements are attached to all imported bank movements in Pohoda via a direct SQL insert into the DOC table (requires a SQLServer credential with access to the Pohoda database).

wakatime

Requirements

  • php 8.1+
  • Pohoda + mServer
  • Sharepoint User or Application Account

Setup command

Check certificate presence yet.

The low-privilege runtime DB account used for DB_USERNAME (by pohodaSQL-raiffeisenbank-statements-sharepoint.php and pohoda-sharepoint-link-fixer.php) needs write access to the DOC table so attachSharepointUrl() can attach/repair the SharePoint link on bank records - most Pohoda MSSQL setups otherwise leave this account read-only. Grant it once per database, connected as an account with GRANT rights (e.g. sa):

USE StwPh_12345678_2026;

GRANT INSERT ON dbo.DOC TO pohodaSQLuser;
GRANT UPDATE ON dbo.DOC TO pohodaSQLuser;
GRANT DELETE ON dbo.DOC TO pohodaSQLuser;

pohoda-raiffeisenbank-setup can also run this for you: set DB_* to an admin-capable connection and GRANT_INSERT_TO to the low-privilege runtime username (see .env.example).

Transactions tool

Import Bank movements from RaiffeisenBank (using getTransactionList as source) to Pohoda using mServer

Transactions

Configuration

Configuration is stored in .env file in the working directory. You can use .env.example as template. When the configuration file is missing, the application will try to use environment variables.

EASE_LOGGER=syslog|console
CERT_FILE='RAIFF_CERT.p12'
CERT_PASS=CertPass
XIBMCLIENTID=PwX4bOQLWGiuoErv6I
ACCOUNT_NUMBER=666666666
ACCOUNT_CURRENCY=CZK

IMPORT_SCOPE=last_two_months
IMPORT_SCOPE=yesterday

API_DEBUG=True
APP_DEBUG=True
STATEMENT_LINE=ADDITIONAL
STATEMENT_SAVE_DIR=/tmp/rb

CNB_CACHE=http://localhost/cnb-cache/
RATE_OFFSET=today
FIXED_RATE=25.1
FIXED_RATE_AMOUNT=1


POHODA_ICO=12345678
POHODA_URL=http://10.11.25.25:10010
POHODA_USERNAME=mServerXXX
POHODA_PASSWORD=mServerXXX
POHODA_TIMEOUT=60
POHODA_COMPRESS=false
POHODA_DEBUG=true
POHODA_BANK_IDS=RB

Import Scopes

  • today
  • yesterday
  • last_week
  • last_month
  • last_two_months
  • previous_month
  • two_months_ago
  • this_year (statements only)
  • January (statements only)
  • February (statements only)
  • March (statements only)
  • April (statements only)
  • May (statements only)
  • June (statements only)
  • July (statements only)
  • August (statements only)
  • September (statements only)
  • October (statements only)
  • November (statements only)
  • December (statements only)
  • auto
  • 2024-08-05>2024-08-11 - custom scope
  • 2024-10-11 - only specific day

Foregin Currency Transactions

If you have transactions in foreign currency, you can use FIXED_RATE to convert them to CZK using preconfigured fixed rate. (for some currencies eg. 💴 you can use FIXED_RATE_AMOUNT=100)

Otherwise you can use CNB_CACHE to get actual rate from CNB. In this case you can also need to specify RATE_OFFSET=yesterday to get rate for previous day.

For CNB currency rates you need to have running CNB cache server!

Sharepoint Integration

Login based auth

OFFICE365_USERNAME=me@company.tld
OFFICE365_PASSWORD=xxxxxxxxxxxxxx

ClientID based auth

OFFICE365_CLIENTID=78842b49-651d-516e-0f2g-f979956aa620
OFFICE365_SECRET=09f04vbd-cfbc-5d78-afb7-2dfbebc4c385
OFFICE365_CLSECRET=8FR8Q~3Rab4-5o8dVd~1vDRId9oYiqEtMJB.Ucb2

Destination options

OFFICE365_TENANT=yourcomapny
OFFICE365_SITE=YourSite
OFFICE365_PATH='Shared documents/statements'

Into configuration file .env please put ClientID OR Login/Password values.

Permanent sharing links (ClientID auth only): by default, the URL stored for an uploaded statement is a permanent SharePoint sharing link (Microsoft Graph createLink), which keeps working even if the file is later moved or renamed. Set SHAREPOINT_PERMANENT_LINK=false to instead use the upload response's webUrl, which is path-based and goes stale on move/rename.

SHAREPOINT_PERMANENT_LINK=true
SHAREPOINT_LINK_TYPE=view
SHAREPOINT_LINK_SCOPE=organization
  • SHAREPOINT_LINK_TYPE - view (read-only) or edit
  • SHAREPOINT_LINK_SCOPE - anonymous, organization (default, only people in your org), or users (only people already granted access)

This only applies to the Graph (client-id/secret) app-only path - the legacy Login/Password flow still goes through classic SharePoint REST and is unaffected.

Controlling XML statement uploads (pohodaSQL-raiffeisenbank-statements-sharepoint only): by default, both PDF and XML statements are uploaded to SharePoint into OFFICE365_PATH. Set SHAREPOINT_UPLOAD_XML=false to keep XML statements local only - the PDF upload and the Pohoda import via mServer are unaffected. Set OFFICE365_PATH_XML to upload XML statements into a different SharePoint folder than PDFs. OFFICE365_PATH_XML is also read by pohoda-sharepoint-link-fixer, which relocates any already-uploaded XML statements it finds sitting in OFFICE365_PATH to this folder - see its section below.

SHAREPOINT_UPLOAD_XML=true
OFFICE365_PATH_XML='Shared documents/statements-xml'

Archiving old years (pohoda-sharepoint-year-archiver only): by default the working folder (OFFICE365_PATH) accumulates every year's statements indefinitely. Run this tool at year-end to sort anything not from the current year into a <year> subfolder, so the working folder only ever contains the current year - older years stay available, grouped by year, for occasional audit lookups. See its section below.

OFFICE365_ARCHIVE_PATH='Shared documents/statements'
CURRENT_YEAR=2026
ARCHIVE_APPLY=false

Error Handling

All scripts perform certificate validation before attempting API calls. If the certificate cannot be read or validated, a detailed error report is generated including:

  • Certificate file path
  • File existence status
  • File readability status
  • File permissions (if file exists)
  • File owner and group (if file exists)

ExitCodes

  • 0 - Success, all operations completed without errors
  • 1 - Generic API error (when no specific error code is available)
  • 2 - Certificate validation failed (file not found, not readable, or invalid password)
  • 3 - Error accessing Pohoda mServer
  • 4 - Cannot link to Sharepoint
  • 145 - API authentication error (HTTP 401 Unauthorized - typically certificate blocked or invalid)
  • 254 - Another exception without numeric code occurred

mServer availability (exit code 3): before importing, pohodasql-raiffeisenbank-statements-sharepoint probes POHODA_URL via isOnline(). If that check fails, PohodaBankClient::describeMServerOfflineReason() turns the raw curl/HTTP state into a specific message instead of a bare mServer error: line, e.g.:

  • mServer at http://SE-APP01:40016 is unreachable: Connection timed out after 30001 milliseconds - transport-level failure (connection refused, timeout, DNS)
  • mServer at http://SE-APP01:40016 responded with HTTP 500 and an empty body (mServer may be restarting, overloaded, or crashed) - mServer process itself is unhealthy
  • mServer at http://SE-APP01:40016 returned HTTP 200 without the expected "Response from POHODA mServer" marker (got: ...) - something else is answering on that port/URL This message is written both to the status log and to the JSON report's pohoda.error/message fields.

Note on Exit Codes: Unix/Linux exit codes are limited to 0-255. When an HTTP error code like 401 (Unauthorized) is used as an exit code, it may be truncated by the shell to its modulo 256 value. For example:

  • HTTP 401 → Unix exit code 145 (401 % 256 = 145)
  • The full HTTP status code and error details are always available in the JSON report's message field

Important: Exit code 0 is only returned when the entire script completes successfully. Any error during execution (API failures, certificate issues, etc.) will result in a non-zero exit code.

Powered by

See also

MultiFlexi

Pohoda RaiffeisenBank is ready for run as MultiFlexi application. See the full list of ready-to-run applications within the MultiFlexi platform on the application list page.

MultiFlexi App

Debian/Ubuntu installation

Please use the .deb packages. The repository is availble:

   echo "deb http://repo.vitexsoftware.com $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/vitexsoftware.list
   sudo wget -O /etc/apt/trusted.gpg.d/vitexsoftware.gpg http://repo.vitexsoftware.com/keyring.gpg
   sudo apt update
   sudo apt install pohoda-raiffeisenbank

Po instalaci balíku jsou v systému k dispozici tyto nové příkazy:

  • pohoda-raiffeisenbank-setup - check and/or prepare Bank account setup in Pohoda

  • pohoda-raiffeisenbank-transactions - Import transactions. From latest imported or within the given scope

  • pohoda-raiffeisenbank-statements - Import transactions from Account Statements.

  • pohoda-raiffeisenbank-offline-statement-importer - Import transactions from XML Statements file.

  • pohoda-raiffeisenbank-xml-statement - Import transactions from XML Statements file.

  • pohodasql-raiffeisenbank-statements-sharepoint - Download PDF+XML statements, upload both to SharePoint, import into Pohoda via mServer, attach SharePoint PDF link to each bank record via direct SQL (DOC table)

  • pohoda-sharepoint-link-fixer - Validate and repair SharePoint PDF links on Pohoda bank records for a given period: attach missing links and repoint links that were cross-attached to another bank account's statement. Scoped to the configured bank account; supports IMPORT_SCOPE; dry-run by default (LINK_FIX_APPLY).

  • pohoda-sharepoint-year-archiver - Sort statement PDF/XML files out of the SharePoint working folder into per-year subfolders (<year>), based on the date in each filename, so only the current year's statements remain in the working folder. Dry-run by default (ARCHIVE_APPLY).

  • pohoda-bank-transaction-report - Generate a JSON report of Pohoda bank transactions for a specified period. The output format matches the RaiffeisenBank statement reporter, including totals and transaction breakdowns.

pohodasql-raiffeisenbank-statements-sharepoint

Statements SharePoint Logo

Executes the following pipeline in order:

  1. Download PDF statements from Raiffeisen Bank
  2. Download XML statements from Raiffeisen Bank
  3. Upload PDF and XML statements to SharePoint
  4. Import XML statements into Pohoda via mServer
  5. Attach SharePoint PDF link to each imported bank record (direct SQL — DOC table, requires SQLServer credential)
  6. Write JSON report to RESULT_FILE

The JSON report contains the result of every stage:

{
  "certificate_valid": true,
  "raiffeisenbank": {
    "pdf": ["/tmp/147_2026_5230011111_4243005_CZK_2026-05-27.pdf"],
    "xml": ["/tmp/147_2026_5230011111_4243005_CZK_2026-05-27.xml"]
  },
  "sharepoint": {
    "pdf": {
      "147_2026_5230011111_4243005_CZK_2026-05-27.pdf": "https://tenant.sharepoint.com/..."
    },
    "xml": {
      "147_2026_5230011111_4243005_CZK_2026-05-27.xml": "https://tenant.sharepoint.com/..."
    }
  },
  "pohoda": {
    "1779931074_9022160411": {"success": true, "message": "..."}
  },
  "pohodaSQL": {
    "30850": {"status": "success", "linkedTo": 12345}
  },
  "messages": [],
  "exitcode": 0
}

On upload failure, the value is {"error": "exception message"} instead of the URL.

pohoda-sharepoint-link-fixer

Link Fixer Logo

Validates and repairs the SharePoint PDF links on Pohoda bank records. Use when records were imported without the SharePoint URL attachment, or when an earlier un-scoped import cross-attached statements between the several bank accounts of one Pohoda company (so a record for one account links to another account's statement).

Executes the following pipeline in order:

  1. List PDF statement files in SharePoint for the configured period, filtered by ACCOUNT_NUMBER
  2. Query Pohoda MSSQL for bank records (BV) in the period together with their current URL attachment, filtered by POHODA_BANK_IDS when set
  3. For each record decide and (when applying) perform:
    • missing link → attach the account's statement PDF (fixed)
    • link pointing to another account, or pointing to the right file but in the stale URL format (see below) → repoint to the current link (corrected, with reason set to wrong_account or format_upgrade), or remove it when no correct PDF exists (removed)
    • already-correct link (right account, current URL format) → leave untouched (ok)
    • missing link with no PDF for that date → leave (skipped)

Permanent link upgrades (Graph/ClientID auth only): like the uploaders, this tool respects SHAREPOINT_PERMANENT_LINK (default true), SHAREPOINT_LINK_TYPE, SHAREPOINT_LINK_SCOPE — see "Permanent sharing links" under the ClientID authentication section above. Since it re-resolves each SharePoint file's current link on every run, running it with LINK_FIX_APPLY=true also upgrades records still holding an old-format webUrl link to the current permanent share link, not just records with a missing or cross-attached link. This does not apply to the legacy Login/Password flow, which has no permanent-link concept.

Dry-run by default: with LINK_FIX_APPLY unset/false the tool only reports what it would change and writes nothing. Set LINK_FIX_APPLY=true to apply. Always dry-run and review first.

Relocating XML statements: when OFFICE365_PATH_XML is set to a folder different from OFFICE365_PATH, any XML statement belonging to ACCOUNT_NUMBER found alongside the PDFs in OFFICE365_PATH (for example, uploaded before OFFICE365_PATH_XML was configured, or from before that feature existed) is moved there - listed in the report's xml_moved. This runs independently of LINK_FIX_APPLY's dry-run for Pohoda records: with LINK_FIX_APPLY unset it's also a dry-run (nothing moved, just reported); set it to actually move the files. Use pohoda-raiffeisenbank-setup first if OFFICE365_PATH_XML doesn't exist yet in SharePoint (see "Setup command" above).

Date range is resolved by IMPORT_SCOPE (default: last_month). DATE_FROM / DATE_TO override IMPORT_SCOPE when explicitly set.

Multi-bank behaviour: When POHODA_BANK_IDS is set (e.g. RB), only records belonging to that bank account are processed. Because one Pohoda company can hold several bank accounts, run the tool once per account (each with its own ACCOUNT_NUMBER + POHODA_BANK_IDS + SharePoint folder). SharePoint files and existing links are matched by ACCOUNT_NUMBER embedded in the filename to detect and prevent cross-account attachment.

Example JSON report (account numbers below are fictional):

{
  "account": "1234567890/0100",
  "bank_ids": "RB",
  "since": "2026-05-01",
  "until": "2026-05-31",
  "apply": false,
  "sharepoint_files": ["2026-05-31"],
  "bank_records_checked": 3,
  "ok": 1,
  "fixed": [
    {"pohodaId": 12345, "cislo": "VBÚ001", "date": "2026-05-31", "filename": "001_1234567890_0100_9999999_CZK_2026-05-31.pdf", "url": "https://tenant.sharepoint.com/..."}
  ],
  "corrected": [
    {"pohodaId": 12346, "docId": 555, "date": "2026-05-31", "from": "001_9999999999_0100_9999999_CZK_2026-05-31.pdf", "to": "001_1234567890_0100_9999999_CZK_2026-05-31.pdf", "url": "https://tenant.sharepoint.com/..."}
  ],
  "removed": [],
  "skipped": [],
  "xml_moved": ["001_1234567890_0100_9999999_CZK_2026-05-31.xml"],
  "errors": [],
  "exitcode": 0
}

pohoda-sharepoint-year-archiver

Archiver Logo

Sorts bank statement PDF/XML files out of the SharePoint working folder (OFFICE365_PATH) into per-year subfolders, based on the YYYY-MM-DD date embedded in each filename. Run this at year-end so accounting staff only see the current year's statements in the working folder, while older years stay reachable - grouped by year - for the occasional audit lookup, instead of accumulating indefinitely in one flat folder.

Executes the following pipeline in order:

  1. List files in OFFICE365_PATH
  2. For each file matching ..._YYYY-MM-DD.pdf or ..._YYYY-MM-DD.xml, skip it if its year equals CURRENT_YEAR (default: the current calendar year); otherwise group it under its own year
  3. For each year found, ensure <archive prefix>/<year> exists (creating it if needed) and move that year's files into it

Archive location: files are moved to <OFFICE365_ARCHIVE_PATH>/<year>. OFFICE365_ARCHIVE_PATH defaults to OFFICE365_PATH itself (subfolders created directly under the working folder), but can be set to a different SharePoint path/library if archived years should live elsewhere entirely.

Sorted by each file's own year: a first run can encounter several backlogged years at once (e.g. 2023, 2024, 2025 all sitting in the working folder) - each file is moved into the subfolder matching its own filename's year, not dumped into one generic "archive" bucket.

Dry-run by default: with ARCHIVE_APPLY unset/false the tool only reports which files would move and where, without creating folders or moving anything. Set ARCHIVE_APPLY=true to apply. Always dry-run and review first.

Not account-scoped: unlike pohoda-sharepoint-link-fixer, this tool doesn't filter by ACCOUNT_NUMBER - it sorts every dated statement file in the folder regardless of which bank account it belongs to.

Side effect on other tools: raiffeisenbank-statements-sharepoint-checker and pohoda-sharepoint-link-fixer only look at the top-level OFFICE365_PATH, so once a year is archived away they will no longer see (or be able to fix links against) that year's statements. This is expected, not a bug - just keep it in mind if link-fixing or checking an archived year is ever needed again (point OFFICE365_PATH at the archive subfolder for that one run).

Example JSON report:

{
  "path": "Sdilene dokumenty/Banky/",
  "archive_path": "Sdilene dokumenty/Banky",
  "current_year": "2026",
  "apply": false,
  "years_created": ["2024", "2025"],
  "moved": [
    {"filename": "001_1234567890_0100_9999999_CZK_2025-12-31.pdf", "year": "2025", "from": "Sdilene dokumenty/Banky/", "to": "Sdilene dokumenty/Banky/2025"},
    {"filename": "001_1234567890_0100_9999999_CZK_2024-11-30.pdf", "year": "2024", "from": "Sdilene dokumenty/Banky/", "to": "Sdilene dokumenty/Banky/2024"}
  ],
  "skipped": [],
  "errors": [],
  "exitcode": 0
}

pohoda-bank-transaction-report

Transaction Report Logo

This tool generates a JSON report of bank transactions imported in Pohoda for a given period.

Usage:

pohoda-bank-transaction-report --scope="last_month" --output="report.json"

Options:

  • --scope Specify the period (e.g. yesterday, last_month, custom range)
  • --output Output file (default: stdout)
  • --environment Path to .env file (default: ../.env)

The report includes:

  • Incoming and outgoing transactions
  • Totals and sums
  • IBAN and account info (if available)
  • Date range

Example output:

{
  "source": "Statementor",
  "account": "666666666",
  "status": "statement 2024-07-01_666666666_CZK_2024-07-01.xml",
  "in": {"2024-07-01": 1000.00},
  "out": {"2024-07-02": 500.00},
  "in_total": 1,
  "out_total": 1,
  "in_sum_total": 1000.00,
  "out_sum_total": 500.00,
  "from": "2024-07-01",
  "to": "2024-07-31",
  "iban": "CZ1234567890123456789012"
}

Exit Codes

Applications in this package use the following exit codes:

  • 0: Success
  • 1: General error
  • 2: Misuse of shell command
  • 3: Application-specific error
  • 4: Application-specific error
  • 401: Unauthorized - authentication failed
Databáze balíčků je dočasně nedostupná.