| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- <?php
- namespace Tests\Unit\Services\Import;
- use App\Models\SparePart;
- use App\Models\SparePartOrder;
- use App\Services\Import\ImportSparePartOrdersService;
- use Illuminate\Foundation\Testing\RefreshDatabase;
- use PhpOffice\PhpSpreadsheet\Spreadsheet;
- use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
- use Tests\TestCase;
- class ImportSparePartOrdersServiceTest extends TestCase
- {
- use RefreshDatabase;
- protected $seed = true;
- private string $tempFilePath;
- private SparePart $sparePart1;
- private SparePart $sparePart2;
- protected function setUp(): void
- {
- parent::setUp();
- $this->sparePart1 = SparePart::factory()->create(['article' => 'TEST.0001']);
- $this->sparePart2 = SparePart::factory()->create(['article' => 'TEST.0002']);
- }
- protected function tearDown(): void
- {
- if (isset($this->tempFilePath) && file_exists($this->tempFilePath)) {
- unlink($this->tempFilePath);
- }
- parent::tearDown();
- }
- public function test_import_creates_spare_part_orders(): void
- {
- $this->createTestFile([
- ['TEST.0001', 10, 'Да', '55/5224', 'На складе'],
- ['TEST.0002', 5, 'Нет', '1554-55453', 'Заказано'],
- ]);
- $service = new ImportSparePartOrdersService($this->tempFilePath, 1);
- $result = $service->handle();
- $this->assertTrue($result['success']);
- $this->assertEquals(2, $result['imported']);
- $this->assertEquals(0, $result['errors']);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $this->sparePart1->id,
- 'ordered_quantity' => 10,
- 'available_qty' => 10,
- 'with_documents' => true,
- 'order_number' => '55/5224',
- 'status' => SparePartOrder::STATUS_IN_STOCK,
- ]);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $this->sparePart2->id,
- 'ordered_quantity' => 5,
- 'available_qty' => 5,
- 'with_documents' => false,
- 'order_number' => '1554-55453',
- 'status' => SparePartOrder::STATUS_ORDERED,
- ]);
- }
- public function test_import_reports_error_for_unknown_article(): void
- {
- $this->createTestFile([
- ['UNKNOWN.ARTICLE', 10, 'Да', '55/5224', 'На складе'],
- ['TEST.0001', 5, 'Да', '55/5224', 'На складе'],
- ]);
- $service = new ImportSparePartOrdersService($this->tempFilePath, 1);
- $result = $service->handle();
- $this->assertFalse($result['success']);
- $this->assertEquals(1, $result['imported']);
- $this->assertEquals(1, $result['errors']);
- $hasErrorLog = false;
- foreach ($result['logs'] as $log) {
- if (str_contains($log, 'UNKNOWN.ARTICLE') && str_contains($log, 'не найдена')) {
- $hasErrorLog = true;
- break;
- }
- }
- $this->assertTrue($hasErrorLog, 'Should log error for unknown article');
- }
- public function test_import_reports_error_for_unknown_status(): void
- {
- $this->createTestFile([
- ['TEST.0001', 10, 'Да', '55/5224', 'Неизвестный статус'],
- ]);
- $service = new ImportSparePartOrdersService($this->tempFilePath, 1);
- $result = $service->handle();
- $this->assertFalse($result['success']);
- $this->assertEquals(0, $result['imported']);
- $this->assertEquals(1, $result['errors']);
- }
- public function test_import_skips_empty_rows(): void
- {
- $this->createTestFile([
- ['', '', '', '', ''],
- ['TEST.0001', 10, 'Да', '55/5224', 'На складе'],
- ]);
- $service = new ImportSparePartOrdersService($this->tempFilePath, 1);
- $result = $service->handle();
- $this->assertTrue($result['success']);
- $this->assertEquals(1, $result['imported']);
- $this->assertEquals(1, $result['skipped']);
- }
- public function test_import_parses_with_documents_correctly(): void
- {
- $sparePart3 = SparePart::factory()->create(['article' => 'TEST.0003']);
- $sparePart4 = SparePart::factory()->create(['article' => 'TEST.0004']);
- $this->createTestFile([
- ['TEST.0001', 1, 'Да', 'order1', 'На складе'],
- ['TEST.0002', 1, 'да', 'order2', 'На складе'],
- ['TEST.0003', 1, 'Нет', 'order3', 'На складе'],
- ['TEST.0004', 1, 'нет', 'order4', 'На складе'],
- ]);
- $service = new ImportSparePartOrdersService($this->tempFilePath, 1);
- $result = $service->handle();
- $this->assertTrue($result['success']);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $this->sparePart1->id,
- 'with_documents' => true,
- ]);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $this->sparePart2->id,
- 'with_documents' => true,
- ]);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $sparePart3->id,
- 'with_documents' => false,
- ]);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $sparePart4->id,
- 'with_documents' => false,
- ]);
- }
- public function test_import_parses_status_correctly(): void
- {
- $sparePart3 = SparePart::factory()->create(['article' => 'TEST.0003']);
- $this->createTestFile([
- ['TEST.0001', 1, 'Да', 'order1', 'На складе'],
- ['TEST.0002', 1, 'Да', 'order2', 'Заказано'],
- ['TEST.0003', 1, 'Да', 'order3', 'Отгружено'],
- ]);
- $service = new ImportSparePartOrdersService($this->tempFilePath, 1);
- $result = $service->handle();
- $this->assertTrue($result['success']);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $this->sparePart1->id,
- 'status' => SparePartOrder::STATUS_IN_STOCK,
- ]);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $this->sparePart2->id,
- 'status' => SparePartOrder::STATUS_ORDERED,
- ]);
- $this->assertDatabaseHas('spare_part_orders', [
- 'spare_part_id' => $sparePart3->id,
- 'status' => SparePartOrder::STATUS_SHIPPED,
- ]);
- }
- public function test_import_returns_summary(): void
- {
- $this->createTestFile([
- ['TEST.0001', 10, 'Да', '55/5224', 'На складе'],
- ['UNKNOWN', 5, 'Да', '55/5224', 'На складе'],
- [' ', '', '', '', ''], // пробел в артикуле, после trim станет пустым
- ]);
- $service = new ImportSparePartOrdersService($this->tempFilePath, 1);
- $result = $service->handle();
- $this->assertArrayHasKey('imported', $result);
- $this->assertArrayHasKey('skipped', $result);
- $this->assertArrayHasKey('errors', $result);
- $this->assertArrayHasKey('logs', $result);
- $this->assertEquals(1, $result['imported']);
- $this->assertEquals(1, $result['skipped']); // строка с пробелом в артикуле
- $this->assertEquals(1, $result['errors']); // UNKNOWN артикул
- // Check summary in logs
- $hasSummary = false;
- foreach ($result['logs'] as $log) {
- if (str_contains($log, 'РЕЗЮМЕ')) {
- $hasSummary = true;
- break;
- }
- }
- $this->assertTrue($hasSummary, 'Should include summary in logs');
- }
- private function createTestFile(array $rows): void
- {
- $spreadsheet = new Spreadsheet();
- $sheet = $spreadsheet->getActiveSheet();
- // Headers
- $sheet->setCellValue('A1', 'Артикул детали');
- $sheet->setCellValue('B1', 'кол-во');
- $sheet->setCellValue('C1', 'С документами?');
- $sheet->setCellValue('D1', 'Номер заказа');
- $sheet->setCellValue('E1', 'Статус');
- // Data rows
- $rowNum = 2;
- foreach ($rows as $row) {
- $sheet->setCellValue('A' . $rowNum, $row[0] ?? '');
- $sheet->setCellValue('B' . $rowNum, $row[1] ?? '');
- $sheet->setCellValue('C' . $rowNum, $row[2] ?? '');
- $sheet->setCellValue('D' . $rowNum, $row[3] ?? '');
- $sheet->setCellValue('E' . $rowNum, $row[4] ?? '');
- $rowNum++;
- }
- $this->tempFilePath = sys_get_temp_dir() . '/test_spare_part_orders_' . uniqid() . '.xlsx';
- $writer = new Xlsx($spreadsheet);
- $writer->save($this->tempFilePath);
- }
- }
|