CluPilotCloud/app/Observers/OrderObserver.php

58 lines
2.3 KiB
PHP

<?php
namespace App\Observers;
use App\Actions\ApplyPlanChange;
use App\Models\Order;
use Illuminate\Support\Facades\Log;
use Throwable;
/**
* The moment a bought upgrade becomes a bigger machine.
*
* StartCustomerProvisioning turns a paid order into work from the webhook that
* announced the payment. An upgrade has no such webhook: there is no checkout in
* this application yet, payment is mocked repo-wide, and the order sits in the
* cart at `pending` until something marks it paid. So the trigger is hung on the
* fact itself — the order becoming paid — rather than on whichever call site
* happens to exist today. A real Stripe checkout, an operator settling a
* purchase by hand and a seeder all end at the same `status = paid`, and all
* three have to result in the customer getting what they bought.
*
* Only an UPDATE, never a create. Every order in this codebase is created either
* already-paid by provisioning (a first purchase, which opens a contract rather
* than changing one) or pending by the shop; an upgrade that goes straight in as
* paid is not a state this application produces, and firing on create would make
* every fixture that builds one start a provisioning run.
*
* A downgrade is deliberately not here. It costs nothing, is never paid, and
* lands at the end of the term — clupilot:apply-due-plan-changes carries those.
*/
class OrderObserver
{
public function updated(Order $order): void
{
if (! $order->wasChanged('status') || $order->status !== 'paid') {
return;
}
if ($order->type !== 'upgrade') {
return;
}
try {
app(ApplyPlanChange::class)->forOrder($order);
} catch (Throwable $e) {
// Never allowed to fail the write that marked the order paid. That
// write is the record that money changed hands, and undoing it over
// a plan change would erase the payment and leave nothing to retry
// from. A change that did not land is loud in its own right: the
// order stays unconsumed and the contract still says the old
// package, both of which somebody can see.
Log::error('Failed to apply the plan change a paid order bought.', [
'order_id' => $order->id, 'plan' => $order->plan, 'error' => $e->getMessage(),
]);
}
}
}