ImportDistrictsServiceTest.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. namespace Tests\Unit\Services\Dictionary;
  3. use App\Models\Dictionary\District;
  4. use App\Services\Import\ImportDistrictsService;
  5. use Illuminate\Foundation\Testing\RefreshDatabase;
  6. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  7. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  8. use Tests\TestCase;
  9. class ImportDistrictsServiceTest extends TestCase
  10. {
  11. use RefreshDatabase;
  12. protected $seed = true;
  13. private string $tempFilePath;
  14. protected function tearDown(): void
  15. {
  16. if (isset($this->tempFilePath) && file_exists($this->tempFilePath)) {
  17. unlink($this->tempFilePath);
  18. }
  19. parent::tearDown();
  20. }
  21. public function test_import_creates_new_districts(): void
  22. {
  23. $this->createTestFile([
  24. ['', 'НОВ', 'Новый округ'],
  25. ['', 'ТСТ', 'Тестовый округ'],
  26. ]);
  27. $service = new ImportDistrictsService($this->tempFilePath, 1);
  28. $result = $service->handle();
  29. $this->assertTrue($result['success']);
  30. $this->assertEquals(2, $result['imported']);
  31. $this->assertDatabaseHas('districts', ['shortname' => 'НОВ', 'name' => 'Новый округ']);
  32. $this->assertDatabaseHas('districts', ['shortname' => 'ТСТ', 'name' => 'Тестовый округ']);
  33. }
  34. public function test_import_updates_existing_districts_by_id(): void
  35. {
  36. $district = District::factory()->create(['shortname' => 'СТР', 'name' => 'Старый']);
  37. $this->createTestFile([
  38. [$district->id, 'НВ', 'Новое название'],
  39. ]);
  40. $service = new ImportDistrictsService($this->tempFilePath, 1);
  41. $result = $service->handle();
  42. $this->assertTrue($result['success']);
  43. $this->assertEquals(1, $result['updated']);
  44. $this->assertDatabaseHas('districts', [
  45. 'id' => $district->id,
  46. 'shortname' => 'НВ',
  47. 'name' => 'Новое название',
  48. ]);
  49. }
  50. public function test_import_updates_existing_districts_by_shortname(): void
  51. {
  52. // Удаляем существующий ЦАО из сидера если есть
  53. District::where('shortname', 'ТЕСТЦАО')->forceDelete();
  54. $district = District::factory()->create(['shortname' => 'ТЕСТЦАО', 'name' => 'Старое']);
  55. $this->createTestFile([
  56. ['', 'ТЕСТЦАО', 'Центральный административный округ'],
  57. ]);
  58. $service = new ImportDistrictsService($this->tempFilePath, 1);
  59. $result = $service->handle();
  60. $this->assertTrue($result['success']);
  61. $this->assertEquals(1, $result['updated']);
  62. $this->assertDatabaseHas('districts', [
  63. 'id' => $district->id,
  64. 'shortname' => 'ТЕСТЦАО',
  65. 'name' => 'Центральный административный округ',
  66. ]);
  67. }
  68. public function test_import_skips_empty_rows(): void
  69. {
  70. $this->createTestFile([
  71. ['', '', ''],
  72. ['', 'НОВТЕСТ', 'Новый округ тест'],
  73. ['', '', ''],
  74. ]);
  75. $service = new ImportDistrictsService($this->tempFilePath, 1);
  76. $result = $service->handle();
  77. $this->assertTrue($result['success']);
  78. $this->assertEquals(1, $result['imported']);
  79. $this->assertGreaterThanOrEqual(1, $result['skipped']);
  80. $this->assertDatabaseHas('districts', ['shortname' => 'НОВТЕСТ', 'name' => 'Новый округ тест']);
  81. }
  82. public function test_import_skips_rows_without_name(): void
  83. {
  84. $this->createTestFile([
  85. ['', 'НОВ', ''], // No name
  86. ['', 'ТСТ', 'Тестовый'],
  87. ]);
  88. $service = new ImportDistrictsService($this->tempFilePath, 1);
  89. $result = $service->handle();
  90. $this->assertTrue($result['success']);
  91. $this->assertEquals(1, $result['imported']);
  92. $this->assertEquals(1, $result['skipped']);
  93. }
  94. public function test_import_restores_soft_deleted_districts(): void
  95. {
  96. $district = District::factory()->create(['shortname' => 'УДЛ', 'name' => 'Удалённый']);
  97. $district->delete();
  98. $this->createTestFile([
  99. ['', 'УДЛ', 'Восстановленный'],
  100. ]);
  101. $service = new ImportDistrictsService($this->tempFilePath, 1);
  102. $result = $service->handle();
  103. $this->assertTrue($result['success']);
  104. $this->assertEquals(1, $result['updated']);
  105. $this->assertDatabaseHas('districts', [
  106. 'id' => $district->id,
  107. 'shortname' => 'УДЛ',
  108. 'name' => 'Восстановленный',
  109. 'deleted_at' => null,
  110. ]);
  111. }
  112. public function test_import_generates_shortname_if_missing(): void
  113. {
  114. $this->createTestFile([
  115. ['', '', 'Длинное название округа'],
  116. ]);
  117. $service = new ImportDistrictsService($this->tempFilePath, 1);
  118. $result = $service->handle();
  119. $this->assertTrue($result['success']);
  120. $this->assertEquals(1, $result['imported']);
  121. $this->assertDatabaseHas('districts', [
  122. 'shortname' => 'Длинное на',
  123. 'name' => 'Длинное название округа',
  124. ]);
  125. }
  126. public function test_import_returns_logs(): void
  127. {
  128. $this->createTestFile([
  129. ['', 'НОВ', 'Новый округ'],
  130. ]);
  131. $service = new ImportDistrictsService($this->tempFilePath, 1);
  132. $result = $service->handle();
  133. $this->assertArrayHasKey('logs', $result);
  134. $this->assertNotEmpty($result['logs']);
  135. }
  136. private function createTestFile(array $rows): void
  137. {
  138. $spreadsheet = new Spreadsheet();
  139. $sheet = $spreadsheet->getActiveSheet();
  140. // Headers
  141. $sheet->setCellValue('A1', 'ID');
  142. $sheet->setCellValue('B1', 'Сокращение');
  143. $sheet->setCellValue('C1', 'Название');
  144. // Data rows
  145. $rowNum = 2;
  146. foreach ($rows as $row) {
  147. $sheet->setCellValue('A' . $rowNum, $row[0] ?? '');
  148. $sheet->setCellValue('B' . $rowNum, $row[1] ?? '');
  149. $sheet->setCellValue('C' . $rowNum, $row[2] ?? '');
  150. $rowNum++;
  151. }
  152. $this->tempFilePath = sys_get_temp_dir() . '/test_districts_' . uniqid() . '.xlsx';
  153. $writer = new Xlsx($spreadsheet);
  154. $writer->save($this->tempFilePath);
  155. }
  156. }