Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions app/Http/Controllers/ChamadoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ public function storePessoa(Request $request, Chamado $chamado)

$request->validate(
[
'codpes' => ['required', 'regex:/^((codpes|id)-)?\d+$/'],
'codpes' => User::identificadorRules,
'papel' => 'required|in:' . implode(',', Chamado::pessoaPapeis()),
Comment on lines 540 to 543
]
);
Expand All @@ -552,15 +552,7 @@ public function storePessoa(Request $request, Chamado $chamado)
$this->authorize('atendente');
}

if (is_numeric($codpesField)) {
$user = User::obterOuCriarPorCodpes((int) $codpesField);
} else {
[$searchField, $valueField] = explode('-', $codpesField, 2);

$user = $searchField === 'codpes'
? User::obterOuCriarPorCodpes((int) $valueField)
: User::find((int) $valueField);
}
$user = User::obterOuCriarPorIdentificador($codpesField);

if (empty($user)) {
return back()->withErrors(['codpes' => 'Usuário não encontrado.'])->withInput();
Expand Down
16 changes: 12 additions & 4 deletions app/Http/Controllers/FilaController.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,19 @@ public function storePessoa(Request $request, Fila $fila)
{
$this->authorize('filas.update', $fila);

[$searchField, $valueField] = explode('-', $request->codpes_id);
// codpes era o nome usado por clientes antigos; o formulário atual usa codpes_id.
$identificador = $request->input('codpes_id', $request->input('codpes'));
$request->merge(['codpes_id' => $identificador]);
$request->validate([
'codpes_id' => User::identificadorRules,
'funcao' => 'required|in:Gerente,Atendente',
]);

$user = User::obterOuCriarPorIdentificador($identificador);
if (empty($user)) {
return back()->withErrors(['codpes_id' => 'Usuário não encontrado.'])->withInput();
}

$user = $searchField === 'codpes' ?
User::obterOuCriarPorCodpes($valueField) :
User::find($valueField);
$fila->users()->detach($user->id);
$fila->users()->attach($user->id, ['funcao' => $request->funcao]);

Expand Down
10 changes: 9 additions & 1 deletion app/Http/Controllers/SetorController.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,15 @@ public function storePessoa(Request $request, Setor $setor)
{
$this->authorize('setores.view', $setor);

$user = User::obterOuCriarPorCodpes($request->codpes);
$request->validate([
'codpes' => User::identificadorRules,
]);

$user = User::obterOuCriarPorIdentificador($request->codpes);
if (empty($user)) {
return back()->withErrors(['codpes' => 'Usuário não encontrado.'])->withInput();
}

Setor::vincularPessoa($setor, $user, 'Gerente');

$request->session()->flash('alert-info', 'Pessoa adicionada com sucesso');
Expand Down
11 changes: 10 additions & 1 deletion app/Http/Controllers/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,16 @@ public function create()
public function store(Request $request)
{
$this->authorize('admin');
User::obterOuCriarPorCodpes($request->codpes);

$request->validate([
'codpes' => User::identificadorRules,
]);

$user = User::obterOuCriarPorIdentificador($request->codpes);
if (empty($user)) {
return back()->withErrors(['codpes' => 'Usuário não encontrado.'])->withInput();
}

$request->session()->flash('alert-info', 'Atendente adicionado com sucesso');
return redirect('/users');
}
Expand Down
35 changes: 35 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class User extends Authenticatable
'telefone' => '',
];

public const identificadorRules = [
'required',
'regex:/^((codpes|id)-)?\d+$/',
];

protected const fields = [
[
'name' => 'codpes',
Expand Down Expand Up @@ -106,6 +111,7 @@ public static function getFields()

public static function criarPorCodpes($codpes)
{
$codpes = (int) $codpes;
$user = new User;
$user->codpes = $codpes;
if (config('chamados.usar_replicado')) {
Expand All @@ -131,6 +137,35 @@ public static function obterPorCodpes($codpes)
return User::where('codpes', $codpes)->first();
}

/**
* Resolve um identificador vindo da busca de pessoas.
*
* Identificadores codpes-* apontam para uma pessoa do Replicado e
* identificadores id-* apontam para um usuário já existente na base local.
* Números sem prefixo são aceitos para compatibilidade com chamadas antigas.
*
* @param string|int|null $identificador
* @return User|null
*/
public static function obterOuCriarPorIdentificador($identificador)
{
$identificador = (string) $identificador;

if (ctype_digit($identificador)) {
return self::obterOuCriarPorCodpes((int) $identificador);
}

if (!preg_match('/^(codpes|id)-(\d+)$/', $identificador, $matches)) {
return null;
}

$valor = (int) $matches[2];

return $matches[1] === 'codpes'
? self::obterOuCriarPorCodpes($valor)
: self::find($valor);
}

/**
* Obtém se já existir ou cria um novo objeto de usuário
*
Expand Down
232 changes: 232 additions & 0 deletions tests/Unit/UserIdentifierTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
<?php

namespace Tests\Unit;

use App\Models\Chamado;
use App\Models\Fila;
use App\Models\Setor;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;

class UserIdentifierTest extends TestCase
{
use RefreshDatabase;

protected function setUp(): void
{
parent::setUp();

// Os testes não devem depender do Replicado real.
config(['chamados.usar_replicado' => false]);
}

public function test_it_resolves_a_replication_person_by_prefixed_codpes(): void
{
$user = User::factory()->create(['codpes' => 17971882]);

$resolved = User::obterOuCriarPorIdentificador('codpes-17971882');

$this->assertTrue($resolved->is($user));
}

public function test_it_resolves_a_local_user_by_prefixed_id(): void
{
$user = User::factory()->create(['codpes' => null, 'local' => true]);

$resolved = User::obterOuCriarPorIdentificador('id-' . $user->id);

$this->assertTrue($resolved->is($user));
}

public function test_it_creates_a_user_with_a_prefixed_codpes_identifier(): void
{
$user = User::obterOuCriarPorIdentificador('codpes-17971882');

$this->assertSame(17971882, (int) $user->codpes);
$this->assertDatabaseHas('users', ['codpes' => 17971882]);
}

public function test_it_passes_an_integer_codpes_to_the_replication_client(): void
{
$pessoa = \Mockery::mock('alias:Uspdev\\Replicado\\Pessoa');
$pessoa->shouldReceive('email')->once()->with(17971882)->andReturn('pessoa@example.com');
$pessoa->shouldReceive('dump')->once()->with(17971882)->andReturn([
'nompesttd' => 'Pessoa do Replicado',
]);
$pessoa->shouldReceive('obterRamalUsp')->once()->with(17971882)->andReturn(false);
$pessoa->shouldReceive('email')->once()->with(17971883)->andReturn('outra-pessoa@example.com');
$pessoa->shouldReceive('dump')->once()->with(17971883)->andReturn([
'nompesttd' => 'Outra pessoa do Replicado',
]);
$pessoa->shouldReceive('obterRamalUsp')->once()->with(17971883)->andReturn(false);

config(['chamados.usar_replicado' => true]);

$user = User::obterOuCriarPorIdentificador('codpes-17971882');
$legacyUser = User::obterOuCriarPorCodpes('17971883');

$this->assertSame(17971882, (int) $user->codpes);
$this->assertSame(17971883, (int) $legacyUser->codpes);
}

public function test_it_adds_a_replication_person_as_a_sector_manager(): void
{
$admin = User::factory()->create(['is_admin' => true]);
$target = User::factory()->create(['codpes' => 17971882]);
$setor = Setor::factory()->create();

$response = $this->withSession(['perfil' => 'admin'])
->actingAs($admin)
->post('/setores/' . $setor->id . '/pessoas', [
'codpes' => 'codpes-17971882',
]);

$response->assertRedirect();
$this->assertDatabaseHas('user_setor', [
'user_id' => $target->id,
'setor_id' => $setor->id,
'funcao' => 'Gerente',
]);
$this->assertDatabaseCount('users', 2);
}

public function test_it_adds_a_local_user_as_a_sector_manager(): void
{
$admin = User::factory()->create(['is_admin' => true]);
$localUser = User::factory()->create(['codpes' => null, 'local' => true]);
$setor = Setor::factory()->create();

$response = $this->withSession(['perfil' => 'admin'])
->actingAs($admin)
->post('/setores/' . $setor->id . '/pessoas', [
'codpes' => 'id-' . $localUser->id,
]);

$response->assertRedirect();
$this->assertDatabaseHas('user_setor', [
'user_id' => $localUser->id,
'setor_id' => $setor->id,
'funcao' => 'Gerente',
]);
$this->assertDatabaseCount('users', 2);
}

public function test_it_rejects_an_invalid_sector_user_identifier(): void
{
$admin = User::factory()->create(['is_admin' => true]);
$setor = Setor::factory()->create();

$response = $this->withSession(['perfil' => 'admin'])
->actingAs($admin)
->post('/setores/' . $setor->id . '/pessoas', [
'codpes' => 'id-999999',
]);

$response->assertSessionHasErrors('codpes');
}

public function test_it_adds_a_local_user_to_a_queue(): void
{
$admin = User::factory()->create(['is_admin' => true]);
$localUser = User::factory()->create(['codpes' => null, 'local' => true]);
$setor = Setor::factory()->create();
$fila = Fila::factory()->create(['setor_id' => $setor->id]);

$response = $this->withSession(['perfil' => 'admin'])
->actingAs($admin)
->post('/filas/' . $fila->id . '/pessoas', [
'codpes_id' => 'id-' . $localUser->id,
'funcao' => 'Gerente',
]);

$response->assertRedirect();
$this->assertDatabaseHas('user_fila', [
'user_id' => $localUser->id,
'fila_id' => $fila->id,
'funcao' => 'Gerente',
]);
}

public function test_it_keeps_supporting_the_legacy_queue_codpes_field(): void
{
$admin = User::factory()->create(['is_admin' => true]);
$target = User::factory()->create(['codpes' => 17971882]);
$setor = Setor::factory()->create();
$fila = Fila::factory()->create(['setor_id' => $setor->id]);

$response = $this->withSession(['perfil' => 'admin'])
->actingAs($admin)
->post('/filas/' . $fila->id . '/pessoas', [
'codpes' => (string) $target->codpes,
'funcao' => 'Atendente',
]);

$response->assertRedirect();
$this->assertDatabaseHas('user_fila', [
'user_id' => $target->id,
'fila_id' => $fila->id,
'funcao' => 'Atendente',
]);
}

public function test_it_rejects_an_unknown_local_user_in_a_queue(): void
{
$admin = User::factory()->create(['is_admin' => true]);
$setor = Setor::factory()->create();
$fila = Fila::factory()->create(['setor_id' => $setor->id]);

$response = $this->withSession(['perfil' => 'admin'])
->actingAs($admin)
->post('/filas/' . $fila->id . '/pessoas', [
'codpes_id' => 'id-999999',
'funcao' => 'Gerente',
]);

$response->assertSessionHasErrors('codpes_id');
}

public function test_it_adds_a_local_user_to_a_ticket(): void
{
$admin = User::factory()->create(['is_admin' => true]);
$localUser = User::factory()->create(['codpes' => null, 'local' => true]);
$setor = Setor::factory()->create();
$fila = Fila::factory()->create(['setor_id' => $setor->id]);
$chamado = Chamado::withoutEvents(function () use ($fila) {
return Chamado::factory()->create([
'fila_id' => $fila->id,
'status' => 'Triagem',
]);
});
Mail::fake();

$response = $this->withSession(['perfil' => 'admin'])
->actingAs($admin)
->post('/chamados/' . $chamado->id . '/pessoas', [
'codpes' => 'id-' . $localUser->id,
'papel' => 'Observador',
]);

$response->assertRedirect();
$this->assertDatabaseHas('user_chamado', [
'user_id' => $localUser->id,
'chamado_id' => $chamado->id,
'papel' => 'Observador',
]);
}

public function test_it_adds_a_replication_person_from_the_users_screen(): void
{
$admin = User::factory()->create(['is_admin' => true]);
$target = User::factory()->create(['codpes' => 17971882]);

$response = $this->actingAs($admin)->post('/users', [
'codpes' => 'codpes-17971882',
]);

$response->assertRedirect('/users');
$this->assertDatabaseHas('users', ['id' => $target->id]);
$this->assertDatabaseCount('users', 2);
}
}
Loading