Feat: Adding Backfill Skus to the Migrate Import Job
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Core\Catalog\Services;
|
||||||
|
|
||||||
|
use Lunar\Models\ProductVariant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a SKU for every ProductVariant missing one — extracted out of
|
||||||
|
* Command\BackfillMissingSkusCommand (which becomes a thin CLI wrapper
|
||||||
|
* around this, keeping --dry-run/progress-bar concerns out of the
|
||||||
|
* reusable logic) so MigrateImport\RunMigrateImportJob can also call it
|
||||||
|
* directly, right after a Shopify import, with no CLI concerns at all.
|
||||||
|
*
|
||||||
|
* Format is "SKU-P{product_id}-V{variant_id}": deterministic and
|
||||||
|
* guaranteed unique without a uniqueness check, since product_id/
|
||||||
|
* variant_id already are. Only variants with a null `sku` are touched —
|
||||||
|
* not an importer bug when one shows up after a Shopify import, the
|
||||||
|
* source CSV rows genuinely had no `Variant SKU` value (see
|
||||||
|
* MigrateImport\Shopify\ShopifyExportImporter).
|
||||||
|
*/
|
||||||
|
class SkuBackfillService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param ?callable(ProductVariant, string): void $onEach invoked
|
||||||
|
* once per variant with the sku about to be written (or, when
|
||||||
|
* $dryRun is true, that WOULD be written) — the command's own
|
||||||
|
* --dry-run listing and progress bar hook in here without this
|
||||||
|
* service knowing anything about console output.
|
||||||
|
* @return int the number of variants processed
|
||||||
|
*/
|
||||||
|
public function backfill(bool $dryRun = false, ?callable $onEach = null): int
|
||||||
|
{
|
||||||
|
$query = ProductVariant::query()->whereNull('sku');
|
||||||
|
$total = $query->count();
|
||||||
|
|
||||||
|
if ($total === 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query->chunkById(500, function ($variants) use ($dryRun, $onEach) {
|
||||||
|
foreach ($variants as $variant) {
|
||||||
|
$sku = "SKU-P{$variant->product_id}-V{$variant->id}";
|
||||||
|
|
||||||
|
if (! $dryRun) {
|
||||||
|
$variant->update(['sku' => $sku]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($onEach !== null) {
|
||||||
|
$onEach($variant, $sku);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,15 +4,13 @@ namespace Modules\Core\Command;
|
|||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Lunar\Models\ProductVariant;
|
use Lunar\Models\ProductVariant;
|
||||||
|
use Modules\Core\Catalog\Services\SkuBackfillService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One-off backfill for variants the Shopify import left with a blank SKU —
|
* CLI wrapper (--dry-run, a progress bar) around Catalog\Services\
|
||||||
* not an importer bug, the source CSV rows genuinely had no `Variant SKU`
|
* SkuBackfillService — see that class's own docblock for the actual
|
||||||
* value (see Modules\MigrateImport\Shopify\ShopifyExportImporter) — so
|
* backfill logic, also called automatically after a Shopify import (see
|
||||||
* this synthesizes one instead of re-running the import. Format is
|
* MigrateImport\RunMigrateImportJob).
|
||||||
* "SKU-P{product_id}-V{variant_id}": deterministic and guaranteed unique
|
|
||||||
* without a uniqueness check, since product_id/variant_id already are.
|
|
||||||
* Only variants with a null `sku` are touched.
|
|
||||||
*/
|
*/
|
||||||
class BackfillMissingSkusCommand extends Command
|
class BackfillMissingSkusCommand extends Command
|
||||||
{
|
{
|
||||||
@@ -20,12 +18,11 @@ class BackfillMissingSkusCommand extends Command
|
|||||||
|
|
||||||
protected $description = 'Generate a SKU for every product variant that is missing one';
|
protected $description = 'Generate a SKU for every product variant that is missing one';
|
||||||
|
|
||||||
public function handle(): void
|
public function handle(SkuBackfillService $backfill): void
|
||||||
{
|
{
|
||||||
$dryRun = (bool) $this->option('dry-run');
|
$dryRun = (bool) $this->option('dry-run');
|
||||||
|
|
||||||
$query = ProductVariant::query()->whereNull('sku');
|
$total = ProductVariant::query()->whereNull('sku')->count();
|
||||||
$total = $query->count();
|
|
||||||
|
|
||||||
if ($total === 0) {
|
if ($total === 0) {
|
||||||
$this->info('No variants are missing a SKU.');
|
$this->info('No variants are missing a SKU.');
|
||||||
@@ -38,19 +35,13 @@ class BackfillMissingSkusCommand extends Command
|
|||||||
$bar = $this->output->createProgressBar($total);
|
$bar = $this->output->createProgressBar($total);
|
||||||
$bar->start();
|
$bar->start();
|
||||||
|
|
||||||
$query->chunkById(500, function ($variants) use ($dryRun, $bar) {
|
$backfill->backfill($dryRun, function (ProductVariant $variant, string $sku) use ($dryRun, $bar) {
|
||||||
foreach ($variants as $variant) {
|
|
||||||
$sku = "SKU-P{$variant->product_id}-V{$variant->id}";
|
|
||||||
|
|
||||||
if ($dryRun) {
|
if ($dryRun) {
|
||||||
$this->newLine();
|
$this->newLine();
|
||||||
$this->line("Variant {$variant->id}: sku => {$sku}");
|
$this->line("Variant {$variant->id}: sku => {$sku}");
|
||||||
} else {
|
|
||||||
$variant->update(['sku' => $sku]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$bar->advance();
|
$bar->advance();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$bar->finish();
|
$bar->finish();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
|||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Modules\Core\Catalog\Services\SkuBackfillService;
|
||||||
|
|
||||||
class RunMigrateImportJob implements ShouldQueue
|
class RunMigrateImportJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
@@ -20,9 +21,19 @@ class RunMigrateImportJob implements ShouldQueue
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(): void
|
public function handle(SkuBackfillService $skuBackfill): void
|
||||||
{
|
{
|
||||||
$importer = ImporterFactory::make($this->spec);
|
$importer = ImporterFactory::make($this->spec);
|
||||||
$importer->import($this->spec);
|
$importer->import($this->spec);
|
||||||
|
|
||||||
|
// Only Shopify's importer creates ProductVariant rows at all (see
|
||||||
|
// Shopify\ShopifyExportImporter) — JudgeMe never touches products,
|
||||||
|
// so running this for that source would just be a guaranteed
|
||||||
|
// no-op query every time. Source CSV rows genuinely can have no
|
||||||
|
// `Variant SKU` value; see SkuBackfillService's own docblock for
|
||||||
|
// why that's synthesized rather than treated as an importer bug.
|
||||||
|
if ($this->spec->source === 'shopify') {
|
||||||
|
$skuBackfill->backfill();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user