Implement duplicate contract code validation with user confirmation
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Requests;
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use App\Models\Contract;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Validation\Validator;
|
use Illuminate\Validation\Validator;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
@@ -96,6 +97,31 @@ class ContractRequest extends FormRequest
|
|||||||
public function withValidator(Validator $validator)
|
public function withValidator(Validator $validator)
|
||||||
{
|
{
|
||||||
$validator->after(function ($validator) {
|
$validator->after(function ($validator) {
|
||||||
|
if ($this->filled('code') && $this->filled('supply_type')) {
|
||||||
|
$contractId = $this->route('id');
|
||||||
|
$existingContract = Contract::query()
|
||||||
|
->with('client:id,name')
|
||||||
|
->where('code', $this->input('code'))
|
||||||
|
->where('supply_type', $this->input('supply_type'))
|
||||||
|
->when($contractId, fn ($query) => $query->where('id', '!=', $contractId))
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($existingContract && ! $this->boolean('confirm_duplicate')) {
|
||||||
|
$supplyType = strtoupper($this->input('supply_type'));
|
||||||
|
$clientName = $existingContract->client?->name;
|
||||||
|
$message = "Já existe um contrato {$supplyType} com este código";
|
||||||
|
|
||||||
|
if ($clientName) {
|
||||||
|
$message .= " associado ao cliente {$clientName}";
|
||||||
|
}
|
||||||
|
|
||||||
|
$validator->errors()->add(
|
||||||
|
'duplicate_code',
|
||||||
|
$message . '. Confirme apenas se se trata de uma mudança de titularidade.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! $this->user()?->can('view_contract_summary')) {
|
if (! $this->user()?->can('view_contract_summary')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -635,5 +635,39 @@
|
|||||||
applyColor('previous_supplier_select');
|
applyColor('previous_supplier_select');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const duplicateCodeMessage = @json($errors->first('duplicate_code'));
|
||||||
|
if (duplicateCodeMessage) {
|
||||||
|
const form = document.querySelector('form');
|
||||||
|
const submitConfirmed = () => {
|
||||||
|
let confirmation = form.querySelector('input[name="confirm_duplicate"]');
|
||||||
|
if (!confirmation) {
|
||||||
|
confirmation = document.createElement('input');
|
||||||
|
confirmation.type = 'hidden';
|
||||||
|
confirmation.name = 'confirm_duplicate';
|
||||||
|
form.appendChild(confirmation);
|
||||||
|
}
|
||||||
|
confirmation.value = '1';
|
||||||
|
form.submit();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (window.Swal) {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'CPE/CUI já existente',
|
||||||
|
text: duplicateCodeMessage,
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Aceitar e gravar',
|
||||||
|
cancelButtonText: 'Cancelar',
|
||||||
|
reverseButtons: true
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
submitConfirmed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (window.confirm(`${duplicateCodeMessage}\n\nDeseja continuar?`)) {
|
||||||
|
submitConfirmed();
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use App\Models\Contract;
|
|||||||
use App\Services\ContractService;
|
use App\Services\ContractService;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Tests\Support\IsolatedDatabaseTestCase;
|
use Tests\Support\IsolatedDatabaseTestCase;
|
||||||
|
|
||||||
@@ -15,7 +16,38 @@ class ContractPersistenceTest extends IsolatedDatabaseTestCase
|
|||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
Schema::table('contracts', fn (Blueprint $table) => $table->decimal('go_ki')->nullable());
|
Schema::table('contracts', function (Blueprint $table) {
|
||||||
|
$table->decimal('go_ki')->nullable();
|
||||||
|
$table->string('code')->nullable();
|
||||||
|
$table->string('supply_type')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_duplicate_supply_code_requires_explicit_confirmation(): void
|
||||||
|
{
|
||||||
|
$user = $this->authenticate();
|
||||||
|
Contract::create([
|
||||||
|
'client_id' => 1,
|
||||||
|
'code' => 'CPE-123',
|
||||||
|
'supply_type' => 'cpe',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$request = ContractRequest::create('/contract', 'POST', [
|
||||||
|
'code' => 'CPE-123',
|
||||||
|
'supply_type' => 'cpe',
|
||||||
|
]);
|
||||||
|
$request->setUserResolver(fn () => $user);
|
||||||
|
$validator = Validator::make($request->all(), []);
|
||||||
|
$request->withValidator($validator);
|
||||||
|
|
||||||
|
$this->assertFalse($validator->passes());
|
||||||
|
$this->assertArrayHasKey('duplicate_code', $validator->errors()->messages());
|
||||||
|
|
||||||
|
$request->merge(['confirm_duplicate' => '1']);
|
||||||
|
$confirmedValidator = Validator::make($request->all(), []);
|
||||||
|
$request->withValidator($confirmedValidator);
|
||||||
|
|
||||||
|
$this->assertTrue($confirmedValidator->passes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_update_persists_chargeback_and_deducts_it_from_profit(): void
|
public function test_update_persists_chargeback_and_deducts_it_from_profit(): void
|
||||||
|
|||||||
Reference in New Issue
Block a user