CluPilotCloud/lang/en
nexxo cd54212b34
tests / pest (push) Failing after 7m32s Details
tests / assets (push) Successful in 25s Details
tests / release (push) Has been skipped Details
Issue an invoice from what somebody bought, and freeze it there
One invoice per purchase rather than per order: a customer who buys a plan and
two add-ons in one go has bought once, and three invoices for one purchase is
three times the paperwork for the same money. Each order becomes a line, which
is also how the add-ons get listed individually.

Everything the document says is copied into the snapshot at the moment the
number is assigned — issuer, recipient, lines, rate, the reason for the rate.
A test changes the company name and the customer name afterwards and asserts
the invoice still says what it said. That is the whole reason no PDF is stored.

The number and the invoice commit in one transaction. A number taken and then
lost to a failure is a gap in a series that must not have one, and the refusal
test asserts that a rejected invoice leaves the counter where it was.

It refuses outright until the company details are complete. An invoice without
a registered name, an address or a VAT number is not a valid invoice here, and
issuing one consumes a number that can never be handed out again.

VAT comes from TaxTreatment, which already existed and already handles a
verified EU VAT ID correctly — including the reverse-charge note, without which
a zero-rated invoice says nothing about why no VAT was charged.

The billing address is carried as the lines it was written as. It is one
free-text field today, and guessing which line is the postcode would put it
where the street belongs, on a document nobody can correct afterwards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 02:09:05 +02:00
..
admin.php Merge credentials and infrastructure into one Integrations page 2026-07-29 01:49:39 +02:00
admin_settings.php Update only to a released version, never to whatever landed on main 2026-07-28 22:32:44 +02:00
auth.php Give the console a front door of its own 2026-07-28 11:45:22 +02:00
backups.php feat(portal): full sidebar — Cloud, Users, Backups, Invoices, Support 2026-07-25 08:08:33 +02:00
billing.php Measure availability, and let a customer move down again 2026-07-27 16:41:15 +02:00
cloud.php Measure availability, and let a customer move down again 2026-07-27 16:41:15 +02:00
coming_soon.php Dress the placeholder page, and record why the obvious VPN fix cannot work 2026-07-27 09:19:30 +02:00
common.php Recover silently from an expired session, and show a connection banner when offline 2026-07-28 21:36:21 +02:00
dashboard.php Stop mailing the initial admin password, hold it in the panel until noted 2026-07-28 23:19:20 +02:00
datacenters.php Let a datacenter code be corrected while nothing depends on it, and say which building 2026-07-28 22:25:21 +02:00
devices.php Recognise the devices an account signs in from, and warn about a new one 2026-07-28 23:28:34 +02:00
errors.php Refuse a portal login for an address that already belongs to an operator 2026-07-28 14:42:16 +02:00
finance.php Give the console a Finance tab: company details, VAT rate, invoice series 2026-07-29 01:18:43 +02:00
hosts.php Show WireGuard tunnel state per host in the hosts list 2026-07-29 00:10:15 +02:00
impersonate.php feat(admin): impersonate customer portal — session login + return banner 2026-07-25 13:46:48 +02:00
instances.php Pin the sidebar header and footer so only the nav list scrolls, and shorten two action labels that wrapped 2026-07-28 20:52:12 +02:00
integrations.php Add a raw .env editor to the Integrations page, with a net under it 2026-07-29 01:51:27 +02:00
invoice.php Issue an invoice from what somebody bought, and freeze it there 2026-07-29 02:09:05 +02:00
invoices.php feat(portal): full sidebar — Cloud, Users, Backups, Invoices, Support 2026-07-25 08:08:33 +02:00
mail.php Recognise the devices an account signs in from, and warn about a new one 2026-07-28 23:28:34 +02:00
mail_settings.php Bound the mail test-send and real send to a timeout instead of hanging 2026-07-28 16:36:14 +02:00
maintenance.php Put every mail in one design, and confirm an order when the money arrives 2026-07-29 00:14:04 +02:00
orders.php Keep the shop window off the portal's front door 2026-07-29 00:26:22 +02:00
plans.php Make the console's access list reach the proxy, price in euros, and answer errors 2026-07-27 06:51:05 +02:00
provisioning.php Keep the shop window off the portal's front door 2026-07-29 00:26:22 +02:00
secrets.php Add the SSH identity to the vault, and give deployment config a console page 2026-07-29 00:52:44 +02:00
sessions.php Show where an account is signed in, and let it sign the other places out 2026-07-28 23:38:17 +02:00
settings.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
status.php Make the console's access list reach the proxy, price in euros, and answer errors 2026-07-27 06:51:05 +02:00
support.php Editing in modals, an update button that is not gated on a stale reading, and a support page that is real 2026-07-27 17:55:49 +02:00
two_factor_setup.php Let a half-finished two-factor enrolment be cancelled, and rework the setup page 2026-07-28 22:25:27 +02:00
updating.php feat(ops): update page, automatic 419 recovery, CI workflow 2026-07-26 00:58:27 +02:00
users.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
verify_email.php Require a confirmed address before an account can use anything 2026-07-28 23:43:20 +02:00
vpn.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00