bootTenant(); $csv = $this->makeCsv(CsvImportExport::CLIENT_COLUMNS, [ ['Ion Pop', '+37369000001', '', 'ion@example.com', '', 'individual', 'active', 'site', '', '0', '0', ''], ['SRL Auto', '+37322777888', '', '', 'SRL Auto', 'company', 'active', '', '', '5', '0', ''], ]); $r = app(CsvImportExport::class)->importClients($csv); @unlink($csv); $this->assertEquals(2, $r['imported']); $this->assertEquals(0, $r['skipped']); $this->assertEquals(2, Client::count()); $this->assertEquals('Ion Pop', Client::where('phone', '+37369000001')->first()->name); } public function test_import_clients_skips_duplicate_phone(): void { $this->bootTenant(); Client::create([ 'name' => 'Existing', 'phone' => '+37369000002', 'type' => 'individual', 'status' => 'active', ]); $csv = $this->makeCsv(CsvImportExport::CLIENT_COLUMNS, [ ['New Name', '+37369000002', '', '', '', 'individual', 'active', '', '', '0', '0', ''], ]); $r = app(CsvImportExport::class)->importClients($csv); @unlink($csv); $this->assertEquals(0, $r['imported']); $this->assertEquals(1, $r['skipped']); $this->assertEquals('Existing', Client::first()->name); } public function test_import_vehicles_uses_make_column_correctly(): void { // This guards a real bug: the service used to write `brand`, but the // vehicles table column is `make`. The import must persist `make`. $ctx = $this->bootTenant(); Client::create([ 'name' => 'Owner', 'phone' => '+37399100200', 'type' => 'individual', 'status' => 'active', ]); $csv = $this->makeCsv(CsvImportExport::VEHICLE_COLUMNS, [ // plate, vin, brand(=make), model, year, engine, gearbox, fuel, mileage, color, notes, client_phone ['ABC-001', 'VIN1234567890ABCD', 'BMW', 'X5', '2019', '3.0i', 'AT', 'Benzină', '85000', 'negru', '', '+37399100200'], ]); $r = app(CsvImportExport::class)->importVehicles($csv); @unlink($csv); $this->assertEquals(1, $r['imported'], 'one vehicle should be imported'); $v = Vehicle::first(); $this->assertNotNull($v, 'vehicle row exists'); $this->assertEquals('BMW', $v->make, 'make column populated from CSV brand header'); $this->assertEquals('X5', $v->model); $this->assertEquals(2019, $v->year); } public function test_export_vehicles_emits_make_value(): void { $this->bootTenant(); $client = Client::create([ 'name' => 'X', 'phone' => '+37377111222', 'type' => 'individual', 'status' => 'active', ]); Vehicle::create([ 'client_id' => $client->id, 'plate' => 'CSV-001', 'make' => 'BMW', 'model' => 'M3', ]); ob_start(); $resp = app(CsvImportExport::class)->exportVehicles(); $resp->sendContent(); $csv = ob_get_clean(); $this->assertStringContainsString('BMW', $csv, 'exported CSV must include the make value'); $this->assertStringContainsString('CSV-001', $csv); $this->assertStringContainsString('M3', $csv); } private function bootTenant(): array { $plan = Plan::firstOrCreate(['slug' => 'test'], ['name' => 'T', 'price' => 0, 'features' => []]); $company = Company::create([ 'plan_id' => $plan->id, 'slug' => 'csv-' . uniqid(), 'name' => 'CSV Co', 'status' => 'active', ]); app(TenantManager::class)->setCurrent($company); return compact('company'); } private function makeCsv(array $headers, array $rows): string { $path = tempnam(sys_get_temp_dir(), 'csv') . '.csv'; $fh = fopen($path, 'w'); fputs($fh, "\xEF\xBB\xBF"); // BOM fputcsv($fh, $headers); foreach ($rows as $row) fputcsv($fh, $row); fclose($fh); return $path; } }