CluPilotCloud/app/Services/Billing/CatalogueSyncStatus.php

77 lines
2.8 KiB
PHP

<?php
namespace App\Services\Billing;
use App\Support\Settings;
use Illuminate\Support\Carbon;
/**
* What the last `stripe:sync-catalogue` run printed, and when.
*
* A settings row rather than a table, for the same reason InboundMailStatus is
* one: there is exactly one catalogue and exactly one last answer, and a table
* of one row is a table somebody has to prune.
*
* The OUTPUT is kept whole and unedited. Two of the things this command says
* are instructions rather than statuses — the refusal to touch a catalogue that
* belongs to the other Stripe account names the three places an operator has to
* clear, and the duplicate-product warning names an id only a person can
* resolve. Summarising either into "sync failed" would take away exactly the
* sentence that was worth reading, and send the operator back to the terminal
* this page exists to replace.
*/
class CatalogueSyncStatus
{
private const KEY = 'billing.catalogue_sync';
/**
* How much of the run's output is kept.
*
* Generous on purpose: a first run on a full catalogue prints a line per
* product and per price pair, and the interesting part of a long run is the
* end. Bounded all the same, because this is a settings row that gets read
* on every render of the page.
*/
private const MAX_OUTPUT = 20000;
public function record(bool $ok, bool $dryRun, string $output, string $by): void
{
Settings::set(self::KEY, [
'at' => Carbon::now()->toIso8601String(),
'ok' => $ok,
'dry_run' => $dryRun,
// Tail, not head: the summary line an operator is looking for
// ("N object(s) would be created", or the refusal) is the last
// thing printed, and a head-truncated log would cut off exactly it.
'output' => mb_strlen($output) > self::MAX_OUTPUT
? '…'.mb_substr($output, -self::MAX_OUTPUT)
: $output,
'by' => $by,
]);
}
/**
* The last run, or null if nobody has ever asked.
*
* @return array{at: Carbon, ok: bool, dry_run: bool, output: string, by: string}|null
*/
public function last(): ?array
{
$row = Settings::get(self::KEY);
if (! is_array($row) || ! isset($row['at'])) {
return null;
}
return [
// Parsed back into a Carbon so the view can put it on the wall
// clock (R19) rather than printing an ISO string at somebody.
'at' => Carbon::parse((string) $row['at']),
'ok' => (bool) ($row['ok'] ?? false),
'dry_run' => (bool) ($row['dry_run'] ?? false),
'output' => (string) ($row['output'] ?? ''),
'by' => (string) ($row['by'] ?? ''),
];
}
}