CluPilotCloud/app/Livewire/Admin
nexxo 6d7c2bdf35
tests / pest (push) Failing after 8m35s Details
tests / assets (push) Successful in 22s Details
tests / release (push) Has been skipped Details
Ask whether they are a consumer, and let one change their mind
Three things the product owed its customers and did not have.

**Who is on the other side.** There was no consumer/business flag anywhere,
and `vat_id` was standing in for one — which it cannot: a business without a
VAT number is an ordinary small business, and a consumer with one does not
exist. It is asked at sign-up now, correctable in the portal, and NULL where
nobody has been asked. Unknown is read as CONSUMER everywhere it decides a
right, because that mistake costs us a refund while the other one takes a
statutory right away from somebody who has it.

Reverse charge asks the recorded type instead of the number: an explicit
consumer is charged the domestic rate whatever `vat_id` says — previously they
were not, and anyone could zero their own VAT by getting a number verified. An
unrecorded type still falls back to the verified number, so no contract that is
already running changes rate.

**The fourteen-day right of withdrawal** (FAGG, §312g BGB), for consumers only,
at every door: the window is stamped on the contract when it is concluded, the
customer exercises it from the portal, an operator records one that arrived by
telephone or post, and both go through one action that refuses a business
customer on the server rather than by hiding a card.

The money follows the paperwork rather than being computed beside it. The
invoice is cancelled by a Storno with its own gapless number — nothing is ever
edited or deleted — a new invoice states the pro-rata value of the service
actually delivered (FAGG §16, by days over the term paid for), and the refund
is exactly the difference between the two documents. Where the consumer never
expressly asked for the service to begin at once, they owe nothing and the whole
amount goes back. `StripeClient::refund()` is new, keyed so a retry cannot send
the money twice. The service ends through EndInstanceService and the
`cancellation_scheduled` machinery that was already there.

**The cancel button for modules.** BookAddon::cancelAtPeriodEnd() had no caller
in the interface at all, so a customer could book a recurring charge in two
clicks and had no way to stop it. It is on the module card now, with the date it
runs until and a way back while the cancellation is still pending — and putting
a module back settles nothing, because the term it was cancelled for was paid
for in advance.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 21:06:06 +02:00
..
Capacity.php Take the order, park it, and say when it will be delivered 2026-07-29 18:50:46 +02:00
ConfirmDeleteDatacenter.php fix(admin): authorize datacenter modal mounts; stale threshold uses step maxDuration 2026-07-25 18:23:44 +02:00
ConfirmDeleteIncident.php Let an incident be deleted, and start measuring whether the hosts answer 2026-07-29 15:16:48 +02:00
ConfirmDeletePlanDraft.php feat(admin): a console for creating, pricing and scheduling plans 2026-07-26 12:41:51 +02:00
ConfirmDeleteVpnPeer.php feat(vpn): ownership, a Developer role, and password-gated config retrieval 2026-07-25 22:31:54 +02:00
ConfirmDisableTwoFactor.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
ConfirmEndOtherSessions.php Show where an account is signed in, and let it sign the other places out 2026-07-28 23:38:17 +02:00
ConfirmForgetSecret.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
ConfirmReissueVpnPeer.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
ConfirmRemoveHost.php feat(admin): staff RBAC (spatie) + admin settings page 2026-07-25 15:47:42 +02:00
ConfirmRestartInstance.php Restart a machine, enforce the quota that was sold, end a route that ended 2026-07-29 18:28:28 +02:00
ConfirmSaveEnv.php Add a raw .env editor to the Integrations page, with a net under it 2026-07-29 01:51:27 +02:00
ConfirmSaveSecret.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
CustomerDetail.php Keep a register of what was sent, and answer the customer from here 2026-07-29 21:02:36 +02:00
Customers.php Ask whether they are a consumer, and let one change their mind 2026-07-29 21:06:06 +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
EditDatacenter.php Let a datacenter code be corrected while nothing depends on it, and say which building 2026-07-28 22:25:21 +02:00
EditExportTarget.php Let a destination say how it is laid out and how long anything stays 2026-07-29 03:08:27 +02:00
EditInvoiceSeries.php Give the console a Finance tab: company details, VAT rate, invoice series 2026-07-29 01:18:43 +02:00
EditPlanFamily.php Move each plan's marketing copy from the controller into the console 2026-07-29 14:31:44 +02:00
Finance.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
GrantPlan.php Grant a package or module from the customer's row in the console 2026-07-29 12:42:21 +02:00
HostCreate.php feat(admin): staff RBAC (spatie) + admin settings page 2026-07-25 15:47:42 +02:00
HostDetail.php feat(admin): staff RBAC (spatie) + admin settings page 2026-07-25 15:47:42 +02:00
Hosts.php Read VPN host state from the synced peer table, not a live hub call 2026-07-29 00:18:21 +02:00
Incidents.php Let an incident be deleted, and start measuring whether the hosts answer 2026-07-29 15:16:48 +02:00
InstanceAdminAccess.php Send an operator with an expired session to sign in, not a 500 2026-07-28 18:09:22 +02:00
Instances.php Deliver the storage a customer actually buys 2026-07-29 19:13:10 +02:00
Integrations.php Let the customer buy it themselves, and tab the integrations page 2026-07-29 19:42:28 +02:00
Invoices.php Take the invoice year off the storage clock too 2026-07-29 02:28:34 +02:00
Mail.php Merge credentials and infrastructure into one Integrations page 2026-07-29 01:49:39 +02:00
MailLog.php Keep a register of what was sent, and answer the customer from here 2026-07-29 21:02:36 +02:00
Maintenance.php Move the console's identity out of the customer table 2026-07-28 10:31:43 +02:00
NewInvoice.php Write an invoice for work that came off no price list 2026-07-29 20:12:26 +02:00
Overview.php Keep a register of what was sent, and answer the customer from here 2026-07-29 21:02:36 +02:00
PlanVersions.php Paketversionen: Verkauf wieder aufnehmen und saubere Übergabe 2026-07-29 14:58:11 +02:00
Plans.php Let the owner mark one plan as recommended, from the console 2026-07-29 14:22:22 +02:00
Provisioning.php fix(admin): authorize datacenter modal mounts; stale threshold uses step maxDuration 2026-07-25 18:23:44 +02:00
RecordWithdrawal.php Ask whether they are a consumer, and let one change their mind 2026-07-29 21:06:06 +02:00
Revenue.php Skip the invoice for a full gift, keep it out of revenue, hide its price 2026-07-29 12:41:32 +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 Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
TwoFactorSetup.php Quote what a person pays, and tab the settings page 2026-07-29 19:18:10 +02:00
Vpn.php Replace native confirm() dialogs with the app's own modal pattern 2026-07-28 19:34:27 +02:00
VpnConfigAccess.php Send an operator with an expired session to sign in, not a 500 2026-07-28 18:09:22 +02:00