testFilePath))) { Storage::disk('upload')->put( 'test_orders_import.xlsx', file_get_contents(base_path($this->testFilePath)) ); } } protected function tearDown(): void { Storage::disk('upload')->delete('test_orders_import.xlsx'); parent::tearDown(); } private function createReferenceData(): array { $district = District::factory()->create(['name' => 'ЦАО', 'shortname' => 'ЦАО']); $area = Area::factory()->create(['name' => 'Тверской', 'district_id' => $district->id]); $user = User::factory()->create(['name' => 'Тест Менеджер']); $objectType = ObjectType::factory()->create(['name' => 'Детская площадка']); $orderStatus = OrderStatus::firstOrCreate(['name' => 'Новый']); return compact('district', 'area', 'user', 'objectType', 'orderStatus'); } private function hasTestFile(): bool { return file_exists(base_path($this->testFilePath)); } // ==================== Constants ==================== public function test_service_has_headers_mapping(): void { $this->assertIsArray(ImportOrdersService::HEADERS); $this->assertArrayHasKey('Округ', ImportOrdersService::HEADERS); $this->assertArrayHasKey('Район', ImportOrdersService::HEADERS); $this->assertArrayHasKey('Адрес объекта', ImportOrdersService::HEADERS); $this->assertArrayHasKey('Артикул', ImportOrdersService::HEADERS); $this->assertArrayHasKey('Год установки', ImportOrdersService::HEADERS); } public function test_headers_mapping_contains_required_fields(): void { $headers = ImportOrdersService::HEADERS; // Order fields $this->assertEquals('orders.name', $headers['Название площадки']); $this->assertEquals('orders.object_address', $headers['Адрес объекта']); $this->assertEquals('orders.year', $headers['Год установки']); // Product fields $this->assertEquals('products.article', $headers['Артикул']); $this->assertEquals('products.nomenclature_number', $headers['Номер номенклатуры']); // References $this->assertEquals('districts.name', $headers['Округ']); $this->assertEquals('areas.name', $headers['Район']); $this->assertEquals('users.name', $headers['Менеджер']); } // ==================== Service instantiation ==================== public function test_service_can_be_instantiated(): void { $import = Import::factory()->create(); $service = new ImportOrdersService($import); $this->assertInstanceOf(ImportOrdersService::class, $service); } // ==================== Handle method (requires Excel file) ==================== public function test_handle_returns_false_when_file_not_found(): void { $import = Import::factory()->create([ 'filename' => 'non_existent_file.xlsx', 'status' => 'PENDING', ]); $service = new ImportOrdersService($import); $result = $service->handle(); $this->assertFalse($result); $import->refresh(); $this->assertEquals('ERROR', $import->status); } // ==================== Integration tests ==================== public function test_import_creates_order_from_valid_row(): void { if (!$this->hasTestFile()) { $this->markTestSkipped('Requires valid Excel test file at ' . $this->testFilePath); } $this->createReferenceData(); $import = Import::factory()->create([ 'filename' => 'test_orders_import.xlsx', 'status' => 'PENDING', ]); $initialOrderCount = Order::withoutGlobalScopes()->count(); $initialProductCount = Product::withoutGlobalScopes()->count(); $service = new ImportOrdersService($import); $result = $service->handle(); $this->assertTrue($result); $import->refresh(); $this->assertEquals('DONE', $import->status); // Should create 2 orders (rows 1,2 same address; row 5 different address; row 3 skipped; row 4 duplicate) $this->assertGreaterThan($initialOrderCount, Order::withoutGlobalScopes()->count()); // Should create products $this->assertGreaterThan($initialProductCount, Product::withoutGlobalScopes()->count()); // Verify order created with correct address $this->assertDatabaseHas('orders', [ 'object_address' => 'ул. Тестовая, д. 1', 'year' => 2025, ]); } public function test_import_creates_product_when_not_exists(): void { if (!$this->hasTestFile()) { $this->markTestSkipped('Requires valid Excel test file at ' . $this->testFilePath); } $this->createReferenceData(); $import = Import::factory()->create([ 'filename' => 'test_orders_import.xlsx', 'status' => 'PENDING', ]); // Verify no products with test nomenclature exist $this->assertDatabaseMissing('products', ['nomenclature_number' => 'NOM-001']); $service = new ImportOrdersService($import); $service->handle(); // Verify product was created $this->assertDatabaseHas('products', [ 'nomenclature_number' => 'NOM-001', 'article' => 'ART-001', 'year' => 2025, ]); } public function test_import_skips_row_when_district_not_found(): void { if (!$this->hasTestFile()) { $this->markTestSkipped('Requires valid Excel test file at ' . $this->testFilePath); } $this->createReferenceData(); $import = Import::factory()->create([ 'filename' => 'test_orders_import.xlsx', 'status' => 'PENDING', ]); $service = new ImportOrdersService($import); $service->handle(); // Row 3 has invalid district "НЕСУЩЕСТВУЮЩИЙ_ОКРУГ" - should be skipped $this->assertDatabaseMissing('orders', [ 'object_address' => 'ул. Ошибочная, д. 999', ]); } public function test_import_increments_maf_order_quantity(): void { if (!$this->hasTestFile()) { $this->markTestSkipped('Requires valid Excel test file at ' . $this->testFilePath); } $this->createReferenceData(); $import = Import::factory()->create([ 'filename' => 'test_orders_import.xlsx', 'status' => 'PENDING', ]); $service = new ImportOrdersService($import); $service->handle(); // Rows 1 and 2 have same MAF order number "MAF-001" // Should create one maf_order with quantity = 2 $mafOrder = MafOrder::withoutGlobalScopes() ->where('order_number', 'MAF-001') ->where('year', 2025) ->first(); $this->assertNotNull($mafOrder); $this->assertEquals(2, $mafOrder->quantity); } public function test_import_skips_duplicate_product_sku(): void { if (!$this->hasTestFile()) { $this->markTestSkipped('Requires valid Excel test file at ' . $this->testFilePath); } $this->createReferenceData(); $import = Import::factory()->create([ 'filename' => 'test_orders_import.xlsx', 'status' => 'PENDING', ]); $service = new ImportOrdersService($import); $service->handle(); // Row 4 is duplicate of Row 1 (same RFID, product, order, maf, factory_number, etc.) // Should only have 1 SKU with RFID-001 $skuCount = ProductSKU::withoutGlobalScopes() ->where('rfid', 'RFID-001') ->where('year', 2025) ->count(); $this->assertEquals(1, $skuCount); } public function test_import_creates_product_sku_without_maf(): void { if (!$this->hasTestFile()) { $this->markTestSkipped('Requires valid Excel test file at ' . $this->testFilePath); } $this->createReferenceData(); $import = Import::factory()->create([ 'filename' => 'test_orders_import.xlsx', 'status' => 'PENDING', ]); $service = new ImportOrdersService($import); $service->handle(); // Row 5 has no MAF order - should create SKU with status "требуется" $sku = ProductSKU::withoutGlobalScopes() ->where('rfid', 'RFID-004') ->where('year', 2025) ->first(); $this->assertNotNull($sku); $this->assertNull($sku->maf_order_id); $this->assertEquals('требуется', $sku->status); } }