Flow
ServicesAccounting Service

Accounting app

The accounting UI deploys to dev as its own release and calls the public accounting, leases, and billing hosts.

The accounting app is the Next.js UI in frontend/accounting-app. It deploys as one Helm release, accounting-app, from frontend/accounting-app/.azure/azure-pipelines.yml. A merge to develop deploys to dev. There is no prod stage.

The container listens on port 3000. The dev host and replica count are in frontend/accounting-app/.azure/k8s/values/dev.yaml.

The browser calls accounting, leases, and billing at their public dev hosts. Those URLs are in frontend/accounting-app/.azure/env/config.dev.yaml and are compiled into the image. Locally the same settings fall back to localhost.

The browser calls those APIs on another host, so each service lists this app in ALLOWED_ORIGINS. In dev that value is https://accounting-app.dev.apps-and-services.com. The browser sends its Cloudflare Access cookie with the request, and each API checks that token the same way the other browser-facing services do. A verified person is recorded as staff, which is what a read requires. Locally the APIs run with DEV_AUTH=1, the app sends X-Dev-Actor instead of an Access token, and the APIs answer the preflight themselves. Deployed processes do not set DEV_AUTH, and they refuse to start when it is 1 outside local.

Accounting periods

The /accounting-periods screen selects an active legal entity and a calendar year. Both selections are kept in the URL. It reads the entity's Open month, timezone and books start from accounting, together with its recorded closures; the browser's local timezone does not choose the Open month. Reads refresh every minute and when the window regains focus, except while a confirmation form is open. The calendar and history stay visible during refreshes for the same entity and history page. Close and reopen buttons wait for the refreshed calendar before becoming available.

An unconfigured calendar links to Legal entities, where selecting the entity's name opens its settings. Set up calendar collects an explicit IANA timezone and books-start month. Initial setup suggests a timezone when every property assigned to the entity has a valid Locations timezone and they resolve to the same zone. Missing or conflicting data leaves manual selection available. The user can change the suggestion; later property responses do not overwrite an edited or cleared field. Configured calendars keep their saved timezone. Setup still requires an explicit save, and the server validates the values and any existing closures. Configured entities offer Correct timezone and Correct books start in their settings. Both require a reason. Books-start corrections cannot exclude existing postings or break the sequence of closed months; conflicting months must be reopened first. Timezone corrections preserve books start. Setup and correction require controller or platform-admin access. The forms retain their idempotency key when retrying an unchanged request and refresh the calendar after saving.

The books-start correction API requires a why object in its request contract. A blank why.detail is rejected with reason_required.

The screen offers Hard-close only for the earliest unclosed past month. Reopen requires a reason and explains that later hard-closed months reopen too. Accounting checks permissions and current period state when the command executes. The form keeps its idempotency key when retrying the same request and refreshes the calendar after success.

The accounting periods screen also shows paginated close/reopen history for the selected entity across all years. Controllers and platform admins can read it; other users see a restricted-history message. Records show the affected month, action, actor FID, timestamp in the entity timezone, and stated reason. Successful close/reopen actions refresh history and return it to the newest page.

Tests

These are local only. The Docker image build and the Azure pipeline do not run them. The steps are in frontend/accounting-app/README.md.

From frontend/accounting-app, pnpm test runs the Vitest unit tests. They import TypeScript modules in Node and replace fetch. They do not start the app or the APIs.

pnpm test:e2e runs the Playwright browser tests. The first time, install Chromium with pnpm exec playwright install chromium. Playwright starts pnpm dev on port 3600 when that port is free. The suite checks that each route shows its page title. It does not need the accounting, leases, or billing processes, and it does not create records.

The config files are frontend/accounting-app/vitest.config.mts and frontend/accounting-app/playwright.config.ts.

On this page