Files
voltcerto/tests/Feature/ContractPersistenceTest.php

131 lines
4.3 KiB
PHP

<?php
namespace Tests\Feature;
use App\Http\Requests\ContractRequest;
use App\Models\Contract;
use App\Services\ContractService;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Tests\Support\IsolatedDatabaseTestCase;
class ContractPersistenceTest extends IsolatedDatabaseTestCase
{
protected function setUp(): void
{
parent::setUp();
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
{
$user = $this->authenticate(financial: true);
$contract = Contract::create([
'client_id' => 1,
'contract_value' => 882.32,
'commission_value' => 588.92,
'profit_value' => 293.40,
'go_ki' => 1,
]);
$requestData = [
'contract_value' => 882.32,
'commission_value' => 588.92,
'chargeback_value' => -935.79,
'chargeback_date' => '2026-09-21',
'go_ki' => 1,
];
$request = $this->contractRequest($requestData, $user);
app(ContractService::class)->update($request, (string) $contract->id);
$this->assertDatabaseHas('contracts', [
'id' => $contract->id,
'chargeback' => true,
'chargeback_value' => -935.79,
'chargeback_date' => '2026-09-21',
'profit_value' => -642.39,
]);
}
public function test_update_reports_an_error_when_model_save_is_cancelled(): void
{
$user = $this->authenticate(financial: true);
$contract = Contract::create([
'client_id' => 1,
'contract_value' => 100,
'commission_value' => 10,
'profit_value' => 90,
'go_ki' => 1,
]);
Contract::saving(fn () => false);
$requestData = [
'contract_value' => 100,
'commission_value' => 10,
'chargeback' => false,
'go_ki' => 1,
'notes' => 'This save must be rejected',
];
$request = $this->contractRequest($requestData, $user);
try {
app(ContractService::class)->update($request, (string) $contract->id);
$this->fail('A cancelled contract save must be reported as an error.');
} catch (ValidationException $exception) {
$this->assertArrayHasKey('contract', $exception->errors());
}
$this->assertDatabaseMissing('contracts', [
'id' => $contract->id,
'notes' => 'This save must be rejected',
]);
}
private function contractRequest(array $data, object $user): ContractRequest
{
$request = ContractRequest::create('/contract/1/update', 'PUT', $data);
$request->setUserResolver(fn () => $user);
$prepareForValidation = new \ReflectionMethod(ContractRequest::class, 'prepareForValidation');
$prepareForValidation->invoke($request);
$requestData = $request->all();
$rules = array_fill_keys(array_keys($requestData), ['sometimes']);
$request->setValidator(app('validator')->make($requestData, $rules));
return $request;
}
}