diff --git a/src/Jobs/ImportSingleProductJob.php b/src/Jobs/ImportSingleProductJob.php index 660af70..2c23908 100644 --- a/src/Jobs/ImportSingleProductJob.php +++ b/src/Jobs/ImportSingleProductJob.php @@ -378,6 +378,7 @@ private function buildVariantFields(): string } } } + tracked }' : 'inventoryItem { measurement { @@ -387,6 +388,7 @@ private function buildVariantFields(): string } } requiresShipping + tracked }'; $contextualPricingFields = ''; @@ -571,7 +573,7 @@ private function importVariants(array $returnedVariants, string $product_slug, G 'product_slug' => $product_slug, 'title' => $variant['title'] === 'Default Title' ? 'Default' : $variant['title'], 'inventory_quantity' => $variant['inventoryQuantity'] ?? null, - 'inventory_policy' => $variant['inventoryPolicy'] ?? null, + 'inventory_policy' => Arr::get($variant, 'inventoryItem.tracked') ? ($variant['inventoryPolicy'] ?? null) : 'CONTINUE', 'inventory_management' => 'shopify', // @deprecated, left in for backwards JS compatibility 'price' => $variant['price'], 'compare_at_price' => $variant['compareAtPrice'], @@ -591,7 +593,7 @@ private function importVariants(array $returnedVariants, string $product_slug, G 'price' => $variant['price'], 'compare_at_price' => $variant['compareAtPrice'], 'inventory_quantity' => $variant['inventoryQuantity'] ?? null, - 'inventory_policy' => $variant['inventoryPolicy'] ?? null, + 'inventory_policy' => Arr::get($variant, 'inventoryItem.tracked') ? ($variant['inventoryPolicy'] ?? null) : 'CONTINUE', ]; $existingMultiStoreData = $entry->get('multi_store_data', []); diff --git a/tests/Unit/ImportSingleProductJobTest.php b/tests/Unit/ImportSingleProductJobTest.php index f5ba85d..f0d87e5 100644 --- a/tests/Unit/ImportSingleProductJobTest.php +++ b/tests/Unit/ImportSingleProductJobTest.php @@ -464,6 +464,48 @@ public function imports_product_when_in_sales_channel_and_filter_enabled() $this->assertSame($entry->product_id, '108828309'); } + #[Test] + public function uses_shopify_inventory_policy_when_variant_is_tracked() + { + Facades\Collection::make(config('shopify.collection_handle', 'products'))->save(); + Facades\Collection::make('variants')->save(); + Facades\Taxonomy::make()->handle('collections')->save(); + Facades\Taxonomy::make()->handle('tags')->save(); + Facades\Taxonomy::make()->handle('type')->save(); + Facades\Taxonomy::make()->handle('vendor')->save(); + + $this->mock(Graphql::class, function (MockInterface $mock) { + $mock->shouldReceive('query')->andReturn(new HttpResponse(status: 200, body: $this->getProductJson())); + }); + + Jobs\ImportSingleProductJob::dispatch(1); + + $variant = Facades\Entry::whereCollection('variants')->first(); + $this->assertSame('DENY', $variant->get('inventory_policy')); + } + + #[Test] + public function sets_inventory_policy_to_continue_when_variant_is_not_tracked() + { + Facades\Collection::make(config('shopify.collection_handle', 'products'))->save(); + Facades\Collection::make('variants')->save(); + Facades\Taxonomy::make()->handle('collections')->save(); + Facades\Taxonomy::make()->handle('tags')->save(); + Facades\Taxonomy::make()->handle('type')->save(); + Facades\Taxonomy::make()->handle('vendor')->save(); + + $json = str_replace('"tracked": true', '"tracked": false', $this->getProductJson()); + + $this->mock(Graphql::class, function (MockInterface $mock) use ($json) { + $mock->shouldReceive('query')->andReturn(new HttpResponse(status: 200, body: $json)); + }); + + Jobs\ImportSingleProductJob::dispatch(1); + + $variant = Facades\Entry::whereCollection('variants')->first(); + $this->assertSame('CONTINUE', $variant->get('inventory_policy')); + } + private function getProductJson(): string { return '{ @@ -602,7 +644,8 @@ private function getProductJson(): string "value": 0 } }, - "requiresShipping": true + "requiresShipping": true, + "tracked": true }, "inventoryPolicy": "DENY", "inventoryQuantity": 0,