Phase 3: invoice-first billing documents, company checkout and admin panel - #41
Merged
Merged
Conversation
…livery ledger Migrations 030-037 with a throwaway-Postgres test harness. Deploy order: 030, 031, 033-037, then the code, then 032 (revokes archive delete).
Invoices and reports for both billing modes, CEO archive with manifest and campus roll-up, legal gate on invoice mode, filtered CSV/Excel/PDF export over live and archived months, re-send without renumbering, and PDF rendering with bounded concurrency. Stops pruning the archive.
Documents page, settings tabs with per-tab save, grouped members with company paid ticks, filter bars and export dialog, like-for-like month comparison, and company checkout in the member flow.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
CLAUDE.md duplicated AGENTS.md and both had drifted from the product (billing ban, free tier, report location). Adds the staging/production migration rules.
The Supabase CLI applies pending migrations in order, so a post-deploy 032 could not be skipped while pre-deploy 033-037 were applied. The revoke returns as 039 once this code is live.
The SQL harness only ran locally. Migrations now carry a deploy phase tag so pre- and post-deploy changes cannot be mixed in one PR.
A preview wired to production data went unnoticed and failed with bare 500s. Non-production builds now refuse the production database, only email allowlisted addresses, and a missing migration is reported in German.
Staging migrates automatically for PRs that change migrations; production migrates only through an approved manual run that checks schema drift and then redeploys.
A database built from the migrations let the public key execute set_admin_pin and other server-only RPCs; production was only safe because of manual changes. 038 encodes production's posture. Migrations and drift checks now go through the Supabase Management API, so no database password lives in GitHub.
ITC1 found per-coffee rows unreadable. Documents now show one line per item and price; company emails list at most 15 people while the PDF adds each person's consumption and the Excel gains a per-person item sheet.
Every function crashed with ERR_REQUIRE_ESM once api/ imported runtime code from src/ (export.ts already did for csv). Shared modules now live in api/_lib and src re-exports them; a test forbids the pattern.
…only ITC1's administration gets key figures, the month against the previous one, the most-consumed items and warnings for silent gaps. The ZIP with every person's documents now goes only to the CEO.
src/ importing api/_lib/* broke vite dev (the /api proxy swallowed the module request). shared/ has its own CommonJS package.json so Vercel functions and the browser bundle can both load it.
Months without consumption no longer show a payable checkbox, company badges stop wrapping, settings describe the short email, detailed PDF and CEO-only archive, and shared accounts are not counted as active people.
ITC1, PBI and Level51 have named and unnamed rows on the paper sheet. checkout_mode 'both' keeps the name picker and adds a tile that books on the company's house account; the admin API only allows it for paying companies with a contact.
Staging mail to example.com addresses bounces and damages the sending domain's reputation. MAIL_SINK sends every allowed message to one test inbox and names the intended recipients in the subject; production ignores it.
…op contracts Logo now reads the theme context, so cards and designs wrap in KaffeelistenProvider. Declarations are generated with tsc so the design agent sees real props instead of empty contracts.
…ress Browser translation replaced the dialog's bare text nodes, so React crashed with removeChild when the confirmation switched to the result and the panel went blank. The emails had gone out.
arudaev
added a commit
that referenced
this pull request
Sep 17, 2026
040 is now the pre-deploy run-progress migration in #41; a post-deploy migration must come after every pre-deploy one.
ITC1: a paying company gets one invoice over the full amount. Who consumed what is a separate document for companies that asked for it. PDFs also stop ending in an empty page: print drops the email frame and flows the layout tables so content breaks across pages.
arudaev
added a commit
that referenced
this pull request
Sep 17, 2026
040 is now the pre-deploy run-progress migration in #41; a post-deploy migration must come after every pre-deploy one.
arudaev
added a commit
that referenced
this pull request
Sep 17, 2026
041 is now the pre-deploy Verzehrliste opt-in in #41.
MAIL_SINK redirected every allowed message, so a tester's own address could never receive staging mail. Exact addresses in MAIL_ALLOWLIST now get the email; example.com still goes to the sink.
A 429 counted the document as failed. Quota errors are not retried. Documents that production needs Resend Pro for a monthly run.
arudaev
added this pull request to stack #43
September 17, 2026 11:04
arudaev
removed this pull request from stack #43
September 17, 2026 11:05
arudaev
added a commit
that referenced
this pull request
Sep 25, 2026
040 is now the pre-deploy run-progress migration in #41; a post-deploy migration must come after every pre-deploy one.
arudaev
added a commit
that referenced
this pull request
Sep 25, 2026
041 is now the pre-deploy Verzehrliste opt-in in #41.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 3 for ITC1: billing documents for both payment models, shared company accounts at the iPad, a reworked admin panel, and a staging environment so previews never touch production. What was built and why:
docs/phase-3-billing.md. Environments and migrations:docs/environments.md.Documents (both billing modes kept equal)
invoice_mode_authorized+ note) and stays off in production.document_deliveries. Re-sending reuses the stored number.iPad
checkout_mode:member,company(4process: no name step),both(ITC1/PBI/Level51: Für die Firma buchen tile above the names).Admin
Data and security
038makes production's API privileges explicit. A database built from the migrations let the public key callset_admin_pinand other server-only functions.Environments
vercel devand local runs use the staging Supabase project (Vercel Preview/Development variables).MAIL_SINK. A non-production build pointed at production refuses to start.deploy: pre|posttags, numbering) and runs the SQL guards on a schema built without seeds.Database - staging(PRs),Database - production(on merge tomain). Both use the Supabase Management API.Deploy
docs/environments.md(SUPABASE_ACCESS_TOKEN,STAGING_PROJECT_REF, Environmentproduction). Without them the production migration job fails on merge instead of applying anything.Database - productionapplies030, 031, 033–039(alldeploy: pre) while Vercel buildsmain.040, post-deploy: archive DELETE revoke, anon company columns).Do not enable invoice mode in production without ITC1's written authority.
Test plan
vitest(270 tests),vite buildbothbooking on the shared account, verified in staging