CluPilotCloud/lang/en
nexxo 6b8412f0c3
tests / pest (push) Failing after 8m11s Details
tests / assets (push) Successful in 20s Details
tests / release (push) Has been skipped Details
Write an invoice for work that came off no price list
Not everything we are paid for is a package. Somebody asks whether their
data can be moved into Nextcloud; we look at it, we say what it costs, we
do it. That is a real invoice with no order and no contract behind it,
and the only way to produce one was to write it somewhere else — which
puts it outside the series. A numbered series with a document missing
from it is worth nothing at an audit.

So it goes through the same door as every other invoice:
IssueInvoice::forService() draws from the same series and therefore the
same consecutive number, applies the same TaxTreatment (a verified
business in another member state gets its reverse charge and the note
that makes a zero-rated document lawful), freezes the same immutable
snapshot and dispatches the same archive jobs.

The page under Rechnungen writes what the operator typed and nothing
else. Amounts are in euro because it is a form — 12,95 becomes 1295 by
round(), not by a cast that would make it 1294 — and quantities go to a
thousandth because hours are billed in quarters. The total beside the
lines is the same InvoiceMath the document uses; a preview doing its own
arithmetic would be a second answer, and the first one anybody notices
differs is on a document that cannot be changed. There is no draft: a
"save as draft" that draws a number is an issued invoice with a friendlier
name.

The website's buy buttons go to the sign-in now, not to /order. Booking
belongs in the panel, where the account exists and its address has been
confirmed — which matters because that address is where the finished
cloud's credentials are sent. Sending an anonymous visitor at a page
behind auth worked, but only via a middleware bounce off a page they
never asked for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 20:12:26 +02:00
..
admin.php Take the order, park it, and say when it will be delivered 2026-07-29 18:50:46 +02:00
admin_incidents.php Let an incident be deleted, and start measuring whether the hosts answer 2026-07-29 15:16:48 +02:00
admin_settings.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
auth.php Give people a way back in, and put the URL in English 2026-07-29 16:50:29 +02:00
backups.php feat(portal): full sidebar — Cloud, Users, Backups, Invoices, Support 2026-07-25 08:08:33 +02:00
billing.php Deliver the storage a customer actually buys 2026-07-29 19:13:10 +02:00
capacity.php Take the order, park it, and say when it will be delivered 2026-07-29 18:50:46 +02:00
checkout.php Let the customer buy it themselves, and tab the integrations page 2026-07-29 19:42:28 +02:00
cloud.php Restart a machine, enforce the quota that was sold, end a route that ended 2026-07-29 18:28:28 +02:00
coming_soon.php Say EU, and stop promising to fix somebody else's deleted folder 2026-07-29 14:17: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 Let the customer buy it themselves, and tab the integrations page 2026-07-29 19:42:28 +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
delivery.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +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
domain.php Serve the custom domain, not just announce it 2026-07-29 16:44:52 +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 Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +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 Let the customer buy it themselves, and tab the integrations page 2026-07-29 19:42:28 +02:00
invoice.php Invoice every renewal, and tell Stripe when the package changes 2026-07-29 19:35:15 +02:00
invoice_mail.php Send the invoice with the invoice attached 2026-07-29 02:13:41 +02:00
invoices.php feat(portal): full sidebar — Cloud, Users, Backups, Invoices, Support 2026-07-25 08:08:33 +02:00
invoices_admin.php Write an invoice for work that came off no price list 2026-07-29 20:12:26 +02:00
mail.php Put customer instances on their own domain, and say which domains are ours 2026-07-29 16:03:13 +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
new_invoice.php Write an invoice for work that came off no price list 2026-07-29 20:12:26 +02:00
order.php Let the customer buy it themselves, and tab the integrations page 2026-07-29 19:42:28 +02:00
orders.php Keep the shop window off the portal's front door 2026-07-29 00:26:22 +02:00
plans.php Paketversionen: Verkauf wieder aufnehmen und saubere Übergabe 2026-07-29 14:58:11 +02:00
provisioning.php Deliver the storage a customer actually buys 2026-07-29 19:13:10 +02:00
reset_password.php Give people a way back in, and put the URL in English 2026-07-29 16:50:29 +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
security.php Put customer instances on their own domain, and say which domains are ours 2026-07-29 16:03:13 +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 Let an incident be deleted, and start measuring whether the hosts answer 2026-07-29 15:16:48 +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 Stop root workers breaking every page, and let the panel be closed 2026-07-29 15:43:54 +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