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.