Balance sheet & filing
DE Sign in with Digi Soft Hub

Developer documentation

Structure, local development, tests and extension points of digisoft-bilanz (private repo digi-soft-ug/digisoft-bilanz).

Architecture

CSV --> Import\CsvTrialBalanceImporter --> Domain\TrialBalance (cents, debit +, credit -)
                                              |
                       Mapping\Skr03Mapper --> Engine\BalanceSheetBuilder --> BalanceSheet
                                              |                                   |
                                    Engine\Validator (Issues)        Render\BalanceSheetPdf / BalanceSheetXml
                                                                                  |
                                                         Submit\Submitter (ManualUploadExport)

Working locally

sh dev-test.sh      # composer install, phpcs (PSR-12), phpunit in Docker
docker compose up   # service on port 8080 (Traefik labels, host from .env DOMAIN)

Tests live in tests/; golden file: tests/golden/ug_first_year.csv (expected: asset B 550.00; liabilities A 400.00; liabilities C 150.00; result -600.00). OffenlegungSchemaTest validates against the official XSD once it is in specs/offenlegung/ (licence-gated, not in git; see specs/MANIFEST.md).

Hub login

Authentication belongs to the Digi Soft Hub. Flow: /login redirects to https://digi-soft.app/sso/bilanz; the Hub issues a 60-second JWT (HS256, secret HUB_SSO_SECRET) with sub, email, name, jti, aud=bilanz and redirects to /sso/callback?token=…. Auth::verify() requires aud=bilanz and redeems each jti only once. Only id, email, name are kept in the session.

Environment variables (server-side .env only, never in the repo): DOMAIN, HUB_URL, HUB_SSO_SECRET.

Extending

New importer

Write a class with import(string $content): array{TrialBalance, list<Issue>} (see CsvTrialBalanceImporter) and wire it into Draft::compute(). Report problems as Issue::error(); never drop rows silently.

New submitter

Implement Submit\Submitter (company register) or Submit\EBilanzSubmitter (tax office, deliberately separate). The default is ManualUploadExport, which sends nothing. Real submissions must default to test/dry-run mode and need explicit confirmation. Planned: BundesanzeigerMassenschnittstelle (after a contract with the publisher); NotImplementedEBilanzSubmitter is the M4 stub (ERiC only as a Docker service on Hetzner, certificates via secrets).

Chart of accounts

Mapping\Skr03Mapper holds the ranges (draft, unreviewed). SKR04 and per-client overrides are open.

Deployment

Hetzner, directory ~/digisoft-infra/projects/bilanz/, one stateless Apache/PHP container on network web, Traefik with Let's Encrypt (letsencrypt resolver, security-headers@file). Dockerfile changes need up -d --build; .env changes need --force-recreate.

Limits