markTestSkipped('Flexible variant tables are missing.'); } } public function test_it_rewrites_sort_order_skus_from_option_value_labels(): void { [$product, $variant] = $this->seedVariant('REPAIR-WIG-001', 'REPAIR-WIG-001-1-1', 991900001); $variantId = (int) $variant->id; $this->artisan('products:repair-variant-skus', [ '--sku' => 'REPAIR-WIG-001', ])->assertSuccessful(); $fresh = ProductVariant::query()->find($variantId); $this->assertNotNull($fresh); $this->assertSame($variantId, (int) $fresh->id); $this->assertSame('REPAIR-WIG-001-12IN-1B', $fresh->sku); $this->assertSame('REPAIR-WIG-001', $product->fresh()->sku); } public function test_dry_run_does_not_write_skus(): void { [, $variant] = $this->seedVariant('REPAIR-WIG-002', 'REPAIR-WIG-002-1-1', 991900002); $this->artisan('products:repair-variant-skus', [ '--sku' => 'REPAIR-WIG-002', '--dry-run' => true, ])->assertSuccessful(); $this->assertSame('REPAIR-WIG-002-1-1', $variant->fresh()->sku); } public function test_it_leaves_products_that_were_not_migrated_from_asteria(): void { [, $variant] = $this->seedVariant('REPAIR-WIG-003', 'REPAIR-WIG-003-1-1', null); $this->artisan('products:repair-variant-skus', [ '--sku' => 'REPAIR-WIG-003', ])->assertSuccessful(); $this->assertSame('REPAIR-WIG-003-1-1', $variant->fresh()->sku); } public function test_it_rewrites_order_invoice_and_shipment_skus(): void { [$product, $variant] = $this->seedVariant('REPAIR-WIG-004', 'REPAIR-WIG-004-1-1', 991900004); $newSku = 'REPAIR-WIG-004-12IN-1B'; $now = now(); $orderId = DB::table('orders')->insertGetId([ 'increment_id' => 'REPAIR-ORD-004', 'status' => 'processing', 'is_guest' => 1, 'created_at' => $now, 'updated_at' => $now, ]); $nativeId = DB::table('order_items')->insertGetId([ 'order_id' => $orderId, 'product_id' => $product->id, 'sku' => 'REPAIR-WIG-004-1-1', 'name' => 'Wig', 'qty_ordered' => 1, 'additional' => json_encode([ 'variant_id' => $variant->id, 'variant_sku' => 'REPAIR-WIG-004-1-1', 'attributes' => [ 'hair_length' => [ 'attribute_name' => 'Hair Length', 'option_label' => 'Hair Length', 'value_label' => '12"', ], 'hair_color' => [ 'attribute_name' => 'Hair Color', 'option_label' => 'Hair Color', 'value_label' => 'Natural Black', ], ], ], JSON_UNESCAPED_UNICODE), 'created_at' => $now, 'updated_at' => $now, ]); $migratedId = DB::table('order_items')->insertGetId([ 'order_id' => $orderId, 'product_id' => $product->id, 'sku' => 'REPAIR-WIG-004', 'name' => 'Wig', 'qty_ordered' => 1, 'additional' => json_encode([ 'attributes' => [ ['attribute_name' => 'Hair Length', 'option_label' => '12"', 'attribute_type' => 'drop_down'], ['attribute_name' => 'Free Gift', 'option_label' => 'Yes', 'attribute_type' => 'drop_down'], ['attribute_name' => 'Hair Color', 'option_label' => 'Natural Black', 'attribute_type' => 'drop_down'], ], ], JSON_UNESCAPED_UNICODE), 'created_at' => $now, 'updated_at' => $now, ]); $invoiceId = DB::table('invoice_items')->insertGetId([ 'order_item_id' => $nativeId, 'sku' => 'REPAIR-WIG-004-1-1', 'name' => 'Wig', 'qty' => 1, 'created_at' => $now, 'updated_at' => $now, ]); $shipmentId = DB::table('shipment_items')->insertGetId([ 'shipment_id' => 1, 'order_item_id' => $migratedId, 'sku' => 'REPAIR-WIG-004', 'name' => 'Wig', 'qty' => 1, 'created_at' => $now, 'updated_at' => $now, ]); $this->artisan('products:repair-variant-skus', [ '--sku' => 'REPAIR-WIG-004', '--dry-run' => true, ])->assertSuccessful(); $this->assertSame('REPAIR-WIG-004-1-1', DB::table('order_items')->where('id', $nativeId)->value('sku')); $this->artisan('products:repair-variant-skus', [ '--sku' => 'REPAIR-WIG-004', ])->assertSuccessful(); $this->assertSame($newSku, $variant->fresh()->sku); $this->assertSame($newSku, DB::table('order_items')->where('id', $nativeId)->value('sku')); $this->assertSame($newSku, DB::table('order_items')->where('id', $migratedId)->value('sku')); $this->assertSame($newSku, DB::table('invoice_items')->where('id', $invoiceId)->value('sku')); $this->assertSame($newSku, DB::table('shipment_items')->where('id', $shipmentId)->value('sku')); $nativeAdditional = json_decode((string) DB::table('order_items')->where('id', $nativeId)->value('additional'), true); $this->assertSame($newSku, $nativeAdditional['variant_sku']); $migratedAdditional = json_decode((string) DB::table('order_items')->where('id', $migratedId)->value('additional'), true); $this->assertArrayNotHasKey('variant_sku', $migratedAdditional); } public function test_it_can_reuse_a_sku_held_by_a_variant_renamed_in_a_later_batch(): void { $now = now(); $product = new Product; $product->sku = 'SWAP'; $product->type = 'flexible_variant'; $product->migrated_from_asteria_id = 991900201; $product->save(); $option = ProductOption::query()->create([ 'label' => 'Length', 'type' => 'select', 'code' => 'swap_length', ]); DB::table('product_product_options')->insert([ 'product_id' => $product->id, 'product_option_id' => $option->id, 'position' => 0, 'is_required' => 1, 'created_at' => $now, 'updated_at' => $now, ]); $count = 201; $valueIds = []; for ($i = 0; $i < $count; $i++) { $valueIds[] = DB::table('product_option_values')->insertGetId([ 'product_option_id' => $option->id, 'label' => 'L'.$i, 'code' => 'N'.$i, 'position' => $i, 'created_at' => $now, 'updated_at' => $now, ]); } $variantIds = []; for ($i = 0; $i < $count; $i++) { $current = $i === $count - 1 ? 'SWAP-N0' : 'OLD-'.$i; $variantIds[] = DB::table('product_variants')->insertGetId([ 'product_id' => $product->id, 'sku' => $current, 'price' => 10, 'quantity' => 1, 'status' => 1, 'sort_order' => $i, 'created_at' => $now, 'updated_at' => $now, ]); } $pivots = []; foreach ($variantIds as $i => $variantId) { $pivots[] = [ 'product_variant_id' => $variantId, 'product_option_value_id' => $valueIds[$i], 'created_at' => $now, 'updated_at' => $now, ]; } DB::table('product_variant_option_values')->insert($pivots); $this->artisan('products:repair-variant-skus', [ '--sku' => 'SWAP', ])->assertSuccessful(); $this->assertSame('SWAP-N0', DB::table('product_variants')->where('id', $variantIds[0])->value('sku')); $this->assertSame('SWAP-N200', DB::table('product_variants')->where('id', $variantIds[$count - 1])->value('sku')); } /** * @return array{0: Product, 1: ProductVariant} */ private function seedVariant(string $parentSku, string $variantSku, ?int $asteriaId): array { $suffix = str_replace('-', '_', strtolower($parentSku)); $product = new Product; $product->sku = $parentSku; $product->type = 'flexible_variant'; $product->migrated_from_asteria_id = $asteriaId; $product->save(); $length = ProductOption::query()->create([ 'label' => 'Hair Length', 'type' => 'select', 'code' => $suffix.'_length', ]); $color = ProductOption::query()->create([ 'label' => 'Hair Color', 'type' => 'select', 'code' => $suffix.'_color', ]); $twelve = ProductOptionValue::query()->create([ 'product_option_id' => $length->id, 'label' => '12"', 'code' => '12IN', 'position' => 1, ]); $black = ProductOptionValue::query()->create([ 'product_option_id' => $color->id, 'label' => 'Natural Black', 'code' => '1B', 'position' => 1, ]); $now = now(); DB::table('product_product_options')->insert([ [ 'product_id' => $product->id, 'product_option_id' => $length->id, 'position' => 0, 'is_required' => 1, 'created_at' => $now, 'updated_at' => $now, ], [ 'product_id' => $product->id, 'product_option_id' => $color->id, 'position' => 1, 'is_required' => 1, 'created_at' => $now, 'updated_at' => $now, ], ]); $variant = ProductVariant::query()->create([ 'product_id' => $product->id, 'sku' => $variantSku, 'price' => 99, 'quantity' => 1, 'status' => 1, 'sort_order' => 0, ]); DB::table('product_variant_option_values')->insert([ [ 'product_variant_id' => $variant->id, 'product_option_value_id' => $twelve->id, 'created_at' => $now, 'updated_at' => $now, ], [ 'product_variant_id' => $variant->id, 'product_option_value_id' => $black->id, 'created_at' => $now, 'updated_at' => $now, ], ]); return [$product, $variant]; } }