markTestSkipped('Run php artisan migrate to add Asteria order columns.'); } $this->seedRequiredData(); Cache::forget('migrate_asteria_orders_last_id'); $this->sqlitePath = sys_get_temp_dir().'/asteria_order_cmd_'.uniqid('', true).'.sqlite'; touch($this->sqlitePath); config()->set('database.connections.'.$this->connection, [ 'driver' => 'sqlite', 'database' => $this->sqlitePath, 'prefix' => '', 'foreign_key_constraints' => false, ]); DB::purge($this->connection); MagentoSchema::create($this->connection); } public function tearDown(): void { DB::purge($this->connection); if (isset($this->sqlitePath) && is_file($this->sqlitePath)) { @unlink($this->sqlitePath); } parent::tearDown(); } public function test_it_migrates_an_order_with_items_addresses_and_payment(): void { $customer = $this->createCustomer([ 'email' => 'jane@example.com', 'first_name' => 'Jane', 'last_name' => 'Doe', 'migrated_from_asteria_id' => 10, ]); $product = $this->createSimpleProduct('WIG-001'); $this->seedCompleteMagentoOrder(); $this->artisan('orders:migrate-asteria', [ '--connection' => $this->connection, '--reset-progress' => true, ])->assertSuccessful(); $order = Order::query()->where('increment_id', '100000010')->first(); $this->assertNotNull($order); $this->assertSame(10, (int) $order->migrated_from_asteria_id); $this->assertSame(Order::STATUS_COMPLETED, $order->status); $this->assertSame((int) $customer->id, (int) $order->customer_id); $this->assertSame(0, (int) $order->is_guest); $this->assertSame('jane@example.com', $order->customer_email); $this->assertEquals(110, (float) $order->grand_total); $this->assertEquals(100, (float) $order->sub_total); $this->assertEquals(10, (float) $order->shipping_amount); $this->assertSame('2021-06-01 12:00:00', $order->created_at?->format('Y-m-d H:i:s')); $item = OrderItem::query()->where('order_id', $order->id)->first(); $this->assertNotNull($item); $this->assertSame('WIG-001', $item->sku); $this->assertSame('Lace Wig', $item->name); $this->assertSame((int) $product->id, (int) $item->product_id); $this->assertSame('simple', $item->type); $this->assertEquals(100, (float) $item->price); $this->assertSame(101, (int) ($item->additional['asteria_item_id'] ?? 0)); $billing = OrderAddress::query() ->where('order_id', $order->id) ->where('address_type', OrderAddress::ADDRESS_TYPE_BILLING) ->first(); $this->assertNotNull($billing); $this->assertSame('123 Main St, Apt 4', $billing->address); $this->assertSame('Austin', $billing->city); $this->assertSame('US', $billing->country); $shipping = OrderAddress::query() ->where('order_id', $order->id) ->where('address_type', OrderAddress::ADDRESS_TYPE_SHIPPING) ->first(); $this->assertNotNull($shipping); $this->assertSame('9 Oak Rd', $shipping->address); $payment = OrderPayment::query()->where('order_id', $order->id)->first(); $this->assertNotNull($payment); $this->assertSame('paypal_standard', $payment->method); $this->assertSame('paypal_express', $payment->additional['magento_method'] ?? null); $this->assertSame('ABC123', $payment->additional['last_trans_id'] ?? null); } public function test_dry_run_does_not_write_orders(): void { MagentoSchema::seedOrder($this->connection, [ 'entity_id' => 10, 'increment_id' => '100000010', 'customer_email' => 'dry-run@example.com', ]); $before = Order::query()->count(); $this->artisan('orders:migrate-asteria', [ '--connection' => $this->connection, '--dry-run' => true, '--reset-progress' => true, ])->assertSuccessful(); $this->assertSame($before, Order::query()->count()); $this->assertNull(Order::query()->where('increment_id', '100000010')->first()); } public function test_it_is_idempotent_on_a_second_run(): void { MagentoSchema::seedOrder($this->connection, [ 'entity_id' => 80, 'increment_id' => '100000080', 'customer_email' => 'once@example.com', 'items' => [ ['item_id' => 801, 'sku' => 'ONCE-1', 'name' => 'Once'], ], 'addresses' => [ ['entity_id' => 802, 'address_type' => 'billing'], ], 'payment' => [ 'entity_id' => 803, 'method' => 'checkmo', ], ]); $options = [ '--connection' => $this->connection, '--reset-progress' => true, ]; $this->artisan('orders:migrate-asteria', $options)->assertSuccessful(); $this->artisan('orders:migrate-asteria', $options)->assertSuccessful(); $this->assertSame(1, Order::query()->where('increment_id', '100000080')->count()); $order = Order::query()->where('increment_id', '100000080')->first(); $this->assertSame(1, OrderItem::query()->where('order_id', $order->id)->count()); $this->assertSame(1, OrderAddress::query()->where('order_id', $order->id)->count()); $this->assertSame(1, OrderPayment::query()->where('order_id', $order->id)->count()); $this->assertSame('moneytransfer', $order->payment->method); } public function test_it_links_a_customer_by_asteria_id(): void { $customer = $this->createCustomer([ 'email' => 'linked@example.com', 'migrated_from_asteria_id' => 44, ]); MagentoSchema::seedOrder($this->connection, [ 'entity_id' => 90, 'increment_id' => '100000090', 'customer_id' => 44, 'customer_email' => 'other-address@example.com', 'items' => [ ['item_id' => 901, 'sku' => 'LINK-1'], ], 'payment' => ['entity_id' => 903, 'method' => 'paypal_standard'], ]); $this->artisan('orders:migrate-asteria', [ '--connection' => $this->connection, '--reset-progress' => true, ])->assertSuccessful(); $order = Order::query()->where('increment_id', '100000090')->first(); $this->assertNotNull($order); $this->assertSame((int) $customer->id, (int) $order->customer_id); $this->assertSame(0, (int) $order->is_guest); } public function test_it_creates_a_guest_order_when_the_customer_is_missing(): void { MagentoSchema::seedOrder($this->connection, [ 'entity_id' => 91, 'increment_id' => '100000091', 'customer_id' => 9999, 'customer_email' => 'nobody@example.com', 'customer_firstname' => 'Guest', 'customer_lastname' => 'Buyer', 'customer_is_guest' => 1, 'items' => [ ['item_id' => 911, 'sku' => 'GUEST-1'], ], 'payment' => ['entity_id' => 913, 'method' => 'cashondelivery'], ]); $this->artisan('orders:migrate-asteria', [ '--connection' => $this->connection, '--reset-progress' => true, ])->assertSuccessful(); $order = Order::query()->where('increment_id', '100000091')->first(); $this->assertNotNull($order); $this->assertNull($order->customer_id); $this->assertSame(1, (int) $order->is_guest); $this->assertSame('nobody@example.com', $order->customer_email); $this->assertSame('Guest', $order->customer_first_name); $this->assertSame('cashondelivery', $order->payment->method); } public function test_it_imports_unmatched_sku_items_without_a_product_id(): void { MagentoSchema::seedOrder($this->connection, [ 'entity_id' => 92, 'increment_id' => '100000092', 'items' => [ [ 'item_id' => 921, 'sku' => 'MISSING-SKU', 'name' => 'Retired Product', 'product_type' => 'simple', ], ], 'payment' => ['entity_id' => 923, 'method' => 'checkmo'], ]); $this->artisan('orders:migrate-asteria', [ '--connection' => $this->connection, '--reset-progress' => true, ])->assertSuccessful(); $order = Order::query()->where('increment_id', '100000092')->first(); $this->assertNotNull($order); $item = OrderItem::query()->where('order_id', $order->id)->first(); $this->assertSame('MISSING-SKU', $item->sku); $this->assertSame('Retired Product', $item->name); $this->assertNull($item->product_id); $this->assertNull($item->product_type); $this->assertSame('simple', $item->type); } public function test_it_skips_when_increment_id_already_exists(): void { $channel = Channel::query()->first(); Order::factory()->create([ 'increment_id' => '100000099', 'channel_id' => $channel?->id, 'channel_type' => Channel::class, 'customer_id' => null, 'is_guest' => 1, 'customer_email'=> 'native@example.com', ]); MagentoSchema::seedOrder($this->connection, [ 'entity_id' => 99, 'increment_id' => '100000099', 'customer_email' => 'asteria@example.com', 'items' => [ ['item_id' => 991, 'sku' => 'SKIP-1'], ], 'payment' => ['entity_id' => 993, 'method' => 'checkmo'], ]); $this->artisan('orders:migrate-asteria', [ '--connection' => $this->connection, '--reset-progress' => true, ])->assertSuccessful(); $this->assertSame(1, Order::query()->where('increment_id', '100000099')->count()); $existing = Order::query()->where('increment_id', '100000099')->first(); $this->assertNull($existing->migrated_from_asteria_id); $this->assertSame('native@example.com', $existing->customer_email); } private function seedCompleteMagentoOrder(): void { MagentoSchema::seedOrder($this->connection, [ 'entity_id' => 10, 'increment_id' => '100000010', 'customer_id' => 10, 'customer_email' => 'jane@example.com', 'customer_firstname' => 'Jane', 'customer_lastname' => 'Doe', 'status' => 'complete', 'state' => 'complete', 'grand_total' => 110, 'subtotal' => 100, 'shipping_amount' => 10, 'created_at' => '2021-06-01 12:00:00', 'items' => [ [ 'item_id' => 101, 'sku' => 'WIG-001', 'name' => 'Lace Wig', 'qty_ordered'=> 1, 'price' => 100, 'row_total' => 100, ], ], 'addresses' => [ [ 'entity_id' => 201, 'address_type' => 'billing', 'firstname' => 'Jane', 'lastname' => 'Doe', 'street' => "123 Main St\nApt 4", 'city' => 'Austin', 'country_id' => 'US', ], [ 'entity_id' => 202, 'address_type' => 'shipping', 'firstname' => 'Jane', 'lastname' => 'Doe', 'street' => '9 Oak Rd', 'city' => 'Dallas', 'country_id' => 'US', ], ], 'payment' => [ 'entity_id' => 301, 'method' => 'paypal_express', 'last_trans_id' => 'ABC123', ], ]); } private function createSimpleProduct(string $sku): Product { $attributeFamilyId = (int) (DB::table('attribute_families')->value('id') ?? 1); return Product::factory()->create([ 'sku' => $sku, 'type' => 'simple', 'attribute_family_id' => $attributeFamilyId, ]); } }