| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- <?php
- namespace Tests\Feature;
- use App\Models\Dictionary\Area;
- use App\Models\Dictionary\District;
- use App\Models\File;
- use App\Models\MafOrder;
- use App\Models\ObjectType;
- use App\Models\Order;
- use App\Models\OrderStatus;
- use App\Models\Product;
- use App\Models\ProductSKU;
- use App\Models\Role;
- use App\Models\User;
- use Illuminate\Foundation\Testing\RefreshDatabase;
- use Illuminate\Http\UploadedFile;
- use Illuminate\Support\Facades\Storage;
- use Tests\TestCase;
- class OrderControllerTest extends TestCase
- {
- use RefreshDatabase;
- protected $seed = true;
- private User $adminUser;
- private User $managerUser;
- private User $brigadierUser;
- protected function setUp(): void
- {
- parent::setUp();
- $this->adminUser = User::factory()->create(['role' => Role::ADMIN]);
- $this->managerUser = User::factory()->create(['role' => Role::MANAGER]);
- $this->brigadierUser = User::factory()->create(['role' => Role::BRIGADIER]);
- }
- // ==================== Authentication ====================
- public function test_guest_cannot_access_orders_index(): void
- {
- $response = $this->get(route('order.index'));
- $response->assertRedirect(route('login'));
- }
- public function test_authenticated_user_can_access_orders_index(): void
- {
- $response = $this->actingAs($this->managerUser)
- ->get(route('order.index'));
- $response->assertStatus(200);
- $response->assertViewIs('orders.index');
- }
- // ==================== Index ====================
- public function test_orders_index_displays_orders(): void
- {
- $order = Order::factory()->create();
- $response = $this->actingAs($this->managerUser)
- ->get(route('order.index'));
- $response->assertStatus(200);
- $response->assertSee($order->object_address);
- }
- public function test_brigadier_sees_only_assigned_orders(): void
- {
- $assignedOrder = Order::factory()->create([
- 'brigadier_id' => $this->brigadierUser->id,
- ]);
- $otherOrder = Order::factory()->create([
- 'brigadier_id' => User::factory()->create(['role' => Role::BRIGADIER])->id,
- ]);
- $response = $this->actingAs($this->brigadierUser)
- ->get(route('order.index'));
- $response->assertStatus(200);
- $response->assertSee($assignedOrder->object_address);
- $response->assertDontSee($otherOrder->object_address);
- }
- // ==================== Create ====================
- public function test_can_view_create_order_form(): void
- {
- $response = $this->actingAs($this->adminUser)
- ->get(route('order.create'));
- $response->assertStatus(200);
- $response->assertViewIs('orders.edit');
- }
- // ==================== Store ====================
- public function test_can_create_new_order(): void
- {
- $district = District::factory()->create();
- $area = Area::factory()->create();
- $objectType = ObjectType::factory()->create();
- $response = $this->actingAs($this->managerUser)
- ->post(route('order.store'), [
- 'name' => 'Тестовый заказ',
- 'user_id' => $this->managerUser->id,
- 'district_id' => $district->id,
- 'area_id' => $area->id,
- 'object_address' => 'ул. Тестовая, д. 1',
- 'object_type_id' => $objectType->id,
- 'comment' => 'Тестовый комментарий',
- ]);
- $response->assertRedirect();
- $this->assertDatabaseHas('orders', [
- 'object_address' => 'ул. Тестовая, д. 1',
- 'order_status_id' => Order::STATUS_NEW,
- ]);
- }
- public function test_creating_order_sets_tg_group_name(): void
- {
- $district = District::factory()->create(['shortname' => 'ЦАО']);
- $area = Area::factory()->create(['name' => 'Тверской']);
- $objectType = ObjectType::factory()->create();
- $this->actingAs($this->managerUser)
- ->post(route('order.store'), [
- 'name' => 'Тестовый заказ',
- 'user_id' => $this->managerUser->id,
- 'district_id' => $district->id,
- 'area_id' => $area->id,
- 'object_address' => 'ул. Пушкина',
- 'object_type_id' => $objectType->id,
- ]);
- $order = Order::where('object_address', 'ул. Пушкина')->first();
- $this->assertStringContainsString('ЦАО', $order->tg_group_name);
- $this->assertStringContainsString('Тверской', $order->tg_group_name);
- }
- public function test_can_update_existing_order(): void
- {
- $order = Order::factory()->create([
- 'object_address' => 'Старый адрес',
- ]);
- $response = $this->actingAs($this->managerUser)
- ->post(route('order.store'), [
- 'id' => $order->id,
- 'name' => $order->name,
- 'user_id' => $order->user_id,
- 'district_id' => $order->district_id,
- 'area_id' => $order->area_id,
- 'object_address' => 'Новый адрес',
- 'object_type_id' => $order->object_type_id,
- ]);
- $response->assertRedirect();
- $this->assertDatabaseHas('orders', [
- 'id' => $order->id,
- 'object_address' => 'Новый адрес',
- ]);
- }
- // ==================== Show ====================
- public function test_can_view_order_details(): void
- {
- $order = Order::factory()->create();
- $response = $this->actingAs($this->managerUser)
- ->get(route('order.show', $order));
- $response->assertStatus(200);
- $response->assertViewIs('orders.show');
- $response->assertSee($order->object_address);
- }
- // ==================== Edit ====================
- public function test_can_view_edit_order_form(): void
- {
- $order = Order::factory()->create();
- $response = $this->actingAs($this->managerUser)
- ->get(route('order.edit', $order));
- $response->assertStatus(200);
- $response->assertViewIs('orders.edit');
- }
- // ==================== Destroy ====================
- public function test_can_delete_order(): void
- {
- $order = Order::factory()->create();
- $orderId = $order->id;
- $response = $this->actingAs($this->adminUser)
- ->delete(route('order.destroy', $order));
- $response->assertRedirect(route('order.index'));
- // Order uses SoftDeletes, so check deleted_at is set
- $this->assertSoftDeleted('orders', ['id' => $orderId]);
- }
- public function test_deleting_order_removes_related_product_skus(): void
- {
- $order = Order::factory()->create();
- $product = Product::factory()->create();
- $sku = ProductSKU::factory()->create([
- 'order_id' => $order->id,
- 'product_id' => $product->id,
- ]);
- $this->actingAs($this->adminUser)
- ->delete(route('order.destroy', $order));
- // ProductSKU uses SoftDeletes, so check deleted_at is set
- $this->assertSoftDeleted('products_sku', ['id' => $sku->id]);
- }
- // ==================== Search ====================
- public function test_search_returns_matching_orders(): void
- {
- $order = Order::factory()->create([
- 'object_address' => 'ул. Уникальная Тестовая, д. 999',
- ]);
- $otherOrder = Order::factory()->create([
- 'object_address' => 'ул. Другая, д. 1',
- ]);
- $response = $this->actingAs($this->managerUser)
- ->get(route('order.index', ['s' => 'Уникальная Тестовая']));
- $response->assertStatus(200);
- $response->assertSee($order->object_address);
- $response->assertDontSee($otherOrder->object_address);
- }
- // ==================== MAF Operations ====================
- public function test_get_maf_to_order_assigns_available_maf(): void
- {
- $product = Product::factory()->create();
- $order = Order::factory()->create();
- $productSku = ProductSKU::factory()->create([
- 'order_id' => $order->id,
- 'product_id' => $product->id,
- 'maf_order_id' => null,
- 'status' => 'требуется',
- ]);
- $mafOrder = MafOrder::factory()->create([
- 'product_id' => $product->id,
- 'in_stock' => 5,
- ]);
- // This route requires admin role
- $response = $this->actingAs($this->adminUser)
- ->get(route('order.get-maf', $order));
- $response->assertRedirect(route('order.show', $order));
- $productSku->refresh();
- $this->assertEquals($mafOrder->id, $productSku->maf_order_id);
- $this->assertEquals('отгружен', $productSku->status);
- $mafOrder->refresh();
- $this->assertEquals(4, $mafOrder->in_stock);
- }
- public function test_revert_maf_returns_maf_to_stock(): void
- {
- $product = Product::factory()->create();
- $order = Order::factory()->create();
- $mafOrder = MafOrder::factory()->create([
- 'product_id' => $product->id,
- 'in_stock' => 3,
- ]);
- $productSku = ProductSKU::factory()->create([
- 'order_id' => $order->id,
- 'product_id' => $product->id,
- 'maf_order_id' => $mafOrder->id,
- 'status' => 'отгружен',
- ]);
- // This route requires admin role
- $response = $this->actingAs($this->adminUser)
- ->get(route('order.revert-maf', $order));
- $response->assertRedirect(route('order.show', $order));
- $productSku->refresh();
- $this->assertNull($productSku->maf_order_id);
- $this->assertEquals('требуется', $productSku->status);
- $mafOrder->refresh();
- $this->assertEquals(4, $mafOrder->in_stock);
- }
- public function test_move_maf_transfers_sku_to_another_order(): void
- {
- $product = Product::factory()->create();
- $order1 = Order::factory()->create();
- $order2 = Order::factory()->create();
- $productSku = ProductSKU::factory()->create([
- 'order_id' => $order1->id,
- 'product_id' => $product->id,
- ]);
- // This route requires admin role
- $response = $this->actingAs($this->adminUser)
- ->post(route('order.move-maf'), [
- 'new_order_id' => $order2->id,
- 'ids' => json_encode([$productSku->id]),
- ]);
- $response->assertStatus(200);
- $response->assertJson(['success' => true]);
- $productSku->refresh();
- $this->assertEquals($order2->id, $productSku->order_id);
- }
- // ==================== Photo Management ====================
- public function test_can_upload_photo_to_order(): void
- {
- Storage::fake('public');
- $order = Order::factory()->create();
- // Use create() instead of image() to avoid GD extension requirement
- $photo = UploadedFile::fake()->create('photo.jpg', 100, 'image/jpeg');
- $response = $this->actingAs($this->managerUser)
- ->post(route('order.upload-photo', $order), [
- 'photo' => [$photo],
- ]);
- $response->assertRedirect(route('order.show', $order));
- $this->assertCount(1, $order->fresh()->photos);
- }
- public function test_can_delete_photo_from_order(): void
- {
- Storage::fake('public');
- $order = Order::factory()->create();
- $file = File::factory()->create();
- $order->photos()->attach($file);
- // This route requires admin role
- $response = $this->actingAs($this->adminUser)
- ->delete(route('order.delete-photo', [$order, $file]));
- $response->assertRedirect(route('order.show', $order));
- $this->assertCount(0, $order->fresh()->photos);
- }
- public function test_can_delete_all_photos_from_order(): void
- {
- Storage::fake('public');
- $order = Order::factory()->create();
- $files = File::factory()->count(3)->create();
- $order->photos()->attach($files->pluck('id'));
- // This route requires admin role
- $response = $this->actingAs($this->adminUser)
- ->delete(route('order.delete-all-photos', $order));
- $response->assertRedirect(route('order.show', $order));
- $this->assertCount(0, $order->fresh()->photos);
- }
- // ==================== Document Management ====================
- public function test_can_upload_document_to_order(): void
- {
- Storage::fake('public');
- $order = Order::factory()->create();
- $document = UploadedFile::fake()->create('document.pdf', 100);
- $response = $this->actingAs($this->managerUser)
- ->post(route('order.upload-document', $order), [
- 'document' => [$document],
- ]);
- $response->assertRedirect(route('order.show', $order));
- $this->assertCount(1, $order->fresh()->documents);
- }
- public function test_upload_document_limits_to_5_files(): void
- {
- Storage::fake('public');
- $order = Order::factory()->create();
- $documents = [];
- for ($i = 0; $i < 7; $i++) {
- $documents[] = UploadedFile::fake()->create("document{$i}.pdf", 100);
- }
- $this->actingAs($this->managerUser)
- ->post(route('order.upload-document', $order), [
- 'document' => $documents,
- ]);
- $this->assertCount(5, $order->fresh()->documents);
- }
- // ==================== Generation ====================
- public function test_generate_installation_pack_requires_correct_status(): void
- {
- $order = Order::factory()->create([
- 'order_status_id' => Order::STATUS_NEW,
- ]);
- $response = $this->actingAs($this->managerUser)
- ->get(route('order.generate-installation-pack', $order));
- $response->assertRedirect(route('order.show', $order));
- $response->assertSessionHas('danger');
- }
- public function test_generate_installation_pack_succeeds_with_correct_status(): void
- {
- $product = Product::factory()->create();
- $mafOrder = MafOrder::factory()->create(['product_id' => $product->id]);
- $order = Order::factory()->create([
- 'order_status_id' => Order::STATUS_READY_TO_MOUNT,
- ]);
- // Create SKU with MAF assigned
- ProductSKU::factory()->create([
- 'order_id' => $order->id,
- 'product_id' => $product->id,
- 'maf_order_id' => $mafOrder->id,
- ]);
- $response = $this->actingAs($this->managerUser)
- ->get(route('order.generate-installation-pack', $order));
- $response->assertRedirect(route('order.show', $order));
- $response->assertSessionHas('success');
- }
- // ==================== Export ====================
- public function test_can_export_orders(): void
- {
- Order::factory()->count(3)->create();
- // This route requires admin role
- $response = $this->actingAs($this->adminUser)
- ->post(route('order.export'));
- $response->assertRedirect(route('order.index'));
- $response->assertSessionHas('success');
- }
- public function test_can_export_single_order(): void
- {
- $order = Order::factory()->create();
- // This route requires admin role
- $response = $this->actingAs($this->adminUser)
- ->post(route('order.export-one', $order));
- $response->assertRedirect(route('order.show', $order));
- $response->assertSessionHas('success');
- }
- }
|