Guard Paddle sync mapping
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-02 21:47:14 +01:00
parent 77b7af13d4
commit 8b445ae998
3 changed files with 85 additions and 2 deletions

View File

@@ -15,6 +15,7 @@ class PaddleSyncPackages extends Command
{--package=* : Limit sync to the given package IDs or slugs}
{--dry-run : Generate payload snapshots without calling Paddle}
{--pull : Fetch remote Paddle state instead of pushing local changes}
{--allow-unmapped : Allow sync when packages are missing Paddle product/price IDs}
{--queue : Dispatch jobs onto the queue instead of running synchronously}';
protected $description = 'Synchronise local packages with Paddle products and prices.';
@@ -32,6 +33,13 @@ class PaddleSyncPackages extends Command
$dryRun = (bool) $this->option('dry-run');
$pull = (bool) $this->option('pull');
$queue = (bool) $this->option('queue');
$allowUnmapped = (bool) $this->option('allow-unmapped');
if (! $pull && ! $allowUnmapped && ! $this->hasPackageFilter()) {
if (! $this->guardUnmappedPackages($packages)) {
return self::FAILURE;
}
}
$packages->each(function (Package $package) use ($dryRun, $pull, $queue) {
if ($pull) {
@@ -82,6 +90,42 @@ class PaddleSyncPackages extends Command
return $query->orderByDesc('id')->get();
}
protected function hasPackageFilter(): bool
{
return collect((array) $this->option('package'))->filter()->isNotEmpty();
}
protected function guardUnmappedPackages(Collection $packages): bool
{
$unmapped = $packages->filter(fn (Package $package) => blank($package->paddle_product_id) || blank($package->paddle_price_id));
if ($unmapped->isEmpty()) {
return true;
}
$this->error('Unmapped Paddle package IDs detected. Resolve legacy mappings or pass --allow-unmapped.');
$this->table(
['ID', 'Slug', 'Missing'],
$unmapped->map(function (Package $package): array {
$missing = [];
if (blank($package->paddle_product_id)) {
$missing[] = 'product_id';
}
if (blank($package->paddle_price_id)) {
$missing[] = 'price_id';
}
return [
$package->id,
$package->slug,
implode(', ', $missing),
];
})->values()->all()
);
return false;
}
protected function dispatchSyncJob(Package $package, bool $dryRun, bool $queue): void
{
$context = [