CluPilotCloud/app/Services/Billing
nexxo 40f7818757 Fix round 1: give the frozen-booking test real teeth
Two Important findings from review, both against the plan's own text.

The frozen-booking test could not fail for a defect this diff introduces.
Digging into why turned up two problems, not one. The two assertions the
review named were never exercised: sync-catalogue never writes
subscription_addons.stripe_price_id, and the orphan planted for the new
figure sits at a different amount than the booking's own price, so
archiveSuperseded's net_cents scoping was never going to reach it either.
Underneath that, the test's own orphan was inert regardless of any of that:
with no StripeAddonPrice row seeded first, AddonPrices::product() minted its
own Stripe Product instead of reusing 'prod_support', so the competing
orphan planted under that literal id sat on a product nothing ever asked
about. Fixed both — seeded the product the way the first two tests in this
file already do, added the three assertions the review specified, and a
comment on what the two original assertions do and do not prove.

Verified the fix actually bites, since a test whose teeth are asserted but
never demonstrated is what produced this finding in the first place. With
just the amount check in AdoptStripePrice disabled, the booking still
survived: the `claimed` callback this diff wires into AddonPrices::ensure()
caught it as a second, independent guard. Only disabling both together
reproduced the failure — the honest demonstration, not the single-line
sabotage first suggested, which this diff's own defense-in-depth absorbs.

The remember() comment credited a unique index stripe_addon_prices does not
have — that index sits on stripe_plan_prices, the plan side. Reworded to
name what actually keeps two rows off one Price id today (the `claimed`
callback), what 2026_07_31_210000_one_row_per_stripe_price adds as a net
under it, and why two rows sharing one Price is dangerous: archiving one —
the ordinary response to a superseded figure — would withdraw the very
Price the other row is still selling.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 11:45:50 +02:00
..
AddonCatalogue.php Ask whether they are a consumer, and let one change their mind 2026-07-29 21:06:06 +02:00
AddonPrices.php Fix round 1: give the frozen-booking test real teeth 2026-07-30 11:45:50 +02:00
AdoptStripePrice.php Make the money gate compare the whole recurrence 2026-07-30 11:15:16 +02:00
CustomDomainAccess.php Serve the custom domain, not just announce it 2026-07-29 16:44:52 +02:00
DowngradeCheck.php Deliver the storage a customer actually buys 2026-07-29 19:13:10 +02:00
InvoiceArchive.php Leave the archive readable by whoever collects from it 2026-07-29 03:48:03 +02:00
InvoiceDocument.php Say the same thing to the customer, the register and the bank 2026-07-30 01:30:24 +02:00
InvoiceMath.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00
InvoiceNumbers.php Lay the foundation for self-issued invoices: series, numbers, frozen documents 2026-07-29 00:57:06 +02:00
InvoiceRenderer.php Say the same thing to the customer, the register and the bank 2026-07-30 01:30:24 +02:00
IssueInvoice.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
PlanCatalogue.php Paketversionen: Verkauf wieder aufnehmen und saubere Übergabe 2026-07-29 14:58:11 +02:00
PlanChange.php Book a downgrade for a date that cannot move, and sell a module once 2026-07-29 17:51:37 +02:00
PlanPrices.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
SampleInvoice.php Print every line at full price and take the discount off once, in euros 2026-07-29 01:59:56 +02:00
SetupFee.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
StorageAllowance.php Deliver the storage a customer actually buys 2026-07-29 19:13:10 +02:00
StripeInvoiceLines.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
TaxTreatment.php Stop charging VAT to the customers who owe us none 2026-07-30 02:15:41 +02:00
WithdrawalRight.php Charge the price the website shows, and hand a withdrawal back in full 2026-07-29 22:42:02 +02:00