163 lines
6.3 KiB
PHP
163 lines
6.3 KiB
PHP
<?php
|
|
|
|
use App\Models\Customer;
|
|
use App\Models\Department;
|
|
use App\Models\Feedback;
|
|
use App\Models\FeedbackChannel;
|
|
use App\Models\TicketTransferLog;
|
|
use App\Models\User;
|
|
use App\Services\TransferService;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
|
|
|
|
Permission::firstOrCreate(['name' => 'transfer-department']);
|
|
Permission::firstOrCreate(['name' => 'view-feedback']);
|
|
Permission::firstOrCreate(['name' => 'create-feedback']);
|
|
Permission::firstOrCreate(['name' => 'update-feedback']);
|
|
});
|
|
|
|
// ─── Scenario 3: Transfer Flow ──────────────────────────────────────
|
|
test('transfer creates log, updates department, and notifies manager', function () {
|
|
$managerRole = Role::create(['name' => 'manager']);
|
|
$managerRole->givePermissionTo(['transfer-department', 'view-feedback', 'create-feedback', 'update-feedback']);
|
|
|
|
\Illuminate\Support\Facades\Notification::fake();
|
|
|
|
$sender = User::factory()->create();
|
|
$sender->assignRole('manager');
|
|
|
|
$deptManager = User::factory()->create(['name' => 'Tech Manager']);
|
|
$deptManager->assignRole('manager');
|
|
|
|
$fromDept = Department::create(['name' => 'CSKH', 'manager_id' => null]);
|
|
$toDept = Department::create(['name' => 'Ky Thuat', 'manager_id' => $deptManager->id]);
|
|
|
|
$channel = FeedbackChannel::create(['name' => 'Email', 'slug' => 'email-transfer']);
|
|
$customer = Customer::create(['name' => 'Test Transfer', 'email' => 'transfer@test.com']);
|
|
|
|
$feedback = Feedback::create([
|
|
'customer_id' => $customer->id,
|
|
'feedback_channel_id' => $channel->id,
|
|
'title' => 'Transfer Test Ticket',
|
|
'content' => 'Test content',
|
|
'status' => 'pending',
|
|
'current_department_id' => $fromDept->id,
|
|
'assigned_to' => $sender->id,
|
|
]);
|
|
|
|
$this->actingAs($sender);
|
|
|
|
$transferService = app(TransferService::class);
|
|
$log = $transferService->transfer(
|
|
$feedback,
|
|
$toDept,
|
|
'Can chuyen sang phong ky thuat de kiem tra',
|
|
$sender,
|
|
);
|
|
|
|
// Assert log created
|
|
expect($log)->toBeInstanceOf(TicketTransferLog::class);
|
|
expect($log->from_department_id)->toBe($fromDept->id);
|
|
expect($log->to_department_id)->toBe($toDept->id);
|
|
expect($log->sender_id)->toBe($sender->id);
|
|
expect($log->reason)->toBe('Can chuyen sang phong ky thuat de kiem tra');
|
|
|
|
// Assert department updated
|
|
$feedback->refresh();
|
|
expect($feedback->current_department_id)->toBe($toDept->id);
|
|
expect($feedback->assignedTo->id)->toBe($deptManager->id);
|
|
|
|
// Assert notification sent to target department manager
|
|
\Illuminate\Support\Facades\Notification::assertSentTo(
|
|
$deptManager,
|
|
\App\Notifications\TicketTransferred::class,
|
|
function ($notification) use ($feedback, $sender) {
|
|
return $notification->feedback->id === $feedback->id
|
|
&& $notification->sender->id === $sender->id;
|
|
}
|
|
);
|
|
});
|
|
|
|
// ─── Transfer without reason should fail ────────────────────────────
|
|
test('transfer without reason throws validation error', function () {
|
|
$managerRole = Role::create(['name' => 'manager']);
|
|
$managerRole->givePermissionTo(['transfer-department', 'view-feedback', 'create-feedback', 'update-feedback']);
|
|
|
|
$sender = User::factory()->create();
|
|
$sender->assignRole('manager');
|
|
|
|
$fromDept = Department::create(['name' => 'CSKH']);
|
|
$toDept = Department::create(['name' => 'Ky Thuat']);
|
|
|
|
$channel = FeedbackChannel::create(['name' => 'Zalo', 'slug' => 'zalo-transfer']);
|
|
$customer = Customer::create(['name' => 'Test', 'email' => 'fail@test.com']);
|
|
|
|
$feedback = Feedback::create([
|
|
'customer_id' => $customer->id,
|
|
'feedback_channel_id' => $channel->id,
|
|
'title' => 'Fail Transfer',
|
|
'content' => 'Test',
|
|
'status' => 'pending',
|
|
'current_department_id' => $fromDept->id,
|
|
]);
|
|
|
|
$this->actingAs($sender);
|
|
|
|
$transferService = app(TransferService::class);
|
|
|
|
try {
|
|
$transferService->transfer($feedback, $toDept, ' ', $sender);
|
|
$this->fail('Expected ValidationException but none thrown.');
|
|
} catch (\Illuminate\Validation\ValidationException $e) {
|
|
expect($e->errors()['reason'][0])->toContain('Vui lòng nhập lý do chuyển tiếp');
|
|
}
|
|
|
|
expect(TicketTransferLog::count())->toBe(0);
|
|
});
|
|
|
|
// ─── Transfer to invalid handler should fail ─────────────────────────
|
|
test('transfer to handler not in target department throws validation error', function () {
|
|
$managerRole = Role::create(['name' => 'manager']);
|
|
$managerRole->givePermissionTo(['transfer-department', 'view-feedback', 'create-feedback', 'update-feedback']);
|
|
|
|
$sender = User::factory()->create();
|
|
$sender->assignRole('manager');
|
|
|
|
$fromDept = Department::create(['name' => 'CSKH']);
|
|
$toDept = Department::create(['name' => 'Ky Thuat']);
|
|
|
|
// Handler belongs to Finance department
|
|
$financeDept = Department::create(['name' => 'Tai Chinh']);
|
|
$handler = User::factory()->create(['department_id' => $financeDept->id]);
|
|
|
|
$channel = FeedbackChannel::create(['name' => 'Phone', 'slug' => 'phone-transfer']);
|
|
$customer = Customer::create(['name' => 'Test', 'email' => 't@test.com']);
|
|
|
|
$feedback = Feedback::create([
|
|
'customer_id' => $customer->id,
|
|
'feedback_channel_id' => $channel->id,
|
|
'title' => 'Transfer To Invalid Handler',
|
|
'content' => 'Test',
|
|
'status' => 'pending',
|
|
'current_department_id' => $fromDept->id,
|
|
]);
|
|
|
|
$this->actingAs($sender);
|
|
|
|
$transferService = app(TransferService::class);
|
|
|
|
try {
|
|
$transferService->transfer($feedback, $toDept, 'Chuyen sang kiem tra', $sender, $handler->id);
|
|
$this->fail('Expected ValidationException but none thrown.');
|
|
} catch (\Illuminate\Validation\ValidationException $e) {
|
|
expect($e->errors()['new_assignee_id'][0])->toContain('Người xử lý được chọn không thuộc phòng ban đích');
|
|
}
|
|
|
|
expect(TicketTransferLog::count())->toBe(0);
|
|
});
|