@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\StoreInterestRequestRequest;
|
||||
use App\Jobs\NotifyInterestReceived;
|
||||
use App\Models\InterestRequest;
|
||||
use App\Models\Opportunity;
|
||||
use App\Services\IdempotencyConflict;
|
||||
use App\Services\InterestSubmission;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class InterestRequestController extends Controller
|
||||
{
|
||||
public function store(StoreInterestRequestRequest $request, InterestSubmission $submission): JsonResponse
|
||||
{
|
||||
$validated = $request->validated();
|
||||
$key = $request->header('Idempotency-Key');
|
||||
Validator::make(['idempotency_key' => $key], ['idempotency_key' => [$key === null ? 'nullable' : 'required', 'uuid']])->validate();
|
||||
|
||||
try {
|
||||
$interestRequest = $submission->receive($validated, $key, function () use ($request, $validated) {
|
||||
$opportunity = ! empty($validated['opportunityReference'])
|
||||
? Opportunity::published()->where('reference', $validated['opportunityReference'])->first()
|
||||
: null;
|
||||
if (! empty($validated['opportunityReference']) && ! $opportunity) {
|
||||
throw ValidationException::withMessages(['opportunityReference' => 'A oportunidade seleccionada já não está disponível.']);
|
||||
}
|
||||
|
||||
$interest = InterestRequest::create([
|
||||
'opportunity_id' => $opportunity?->id,
|
||||
'reference' => $this->generateReference(),
|
||||
'full_name' => trim($validated['fullName']),
|
||||
'email' => strtolower(trim($validated['email'])),
|
||||
'phone' => $validated['phone'] ?? null,
|
||||
'investor_type' => $validated['investorType'],
|
||||
'country' => $validated['country'],
|
||||
'sector_interest' => $validated['sectorInterest'],
|
||||
'opportunity_reference' => $validated['opportunityReference'] ?? null,
|
||||
'investment_range' => $validated['investmentRange'] ?? null,
|
||||
'message' => trim($validated['message']),
|
||||
'privacy_consent' => (bool) $validated['privacyConsent'],
|
||||
'consented_at' => now(),
|
||||
'status' => 'received',
|
||||
'source_page' => Str::limit($request->headers->get('referer', ''), 255, ''),
|
||||
'ip_address' => $request->ip(),
|
||||
'user_agent' => $request->userAgent(),
|
||||
]);
|
||||
if (config('portal.notifications_enabled')) {
|
||||
$connection = config('queue.connections.database.connection');
|
||||
if (config('queue.connections.database.after_commit') || ($connection && $connection !== config('database.default'))) {
|
||||
throw new \RuntimeException('Portal notifications require the transactional database queue.');
|
||||
}
|
||||
foreach (array_unique(config('portal.notification_recipients')) as $recipient) {
|
||||
if (filter_var($recipient, FILTER_VALIDATE_EMAIL)) {
|
||||
Queue::connection('database')->push(new NotifyInterestReceived($interest->id, $recipient));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $interest;
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Manifestação de interesse registada com sucesso.',
|
||||
'data' => [
|
||||
'reference' => $interestRequest->reference,
|
||||
'status' => 'received',
|
||||
],
|
||||
], 201);
|
||||
} catch (IdempotencyConflict) {
|
||||
return response()->json(['success' => false, 'message' => 'A chave de envio já foi usada com dados diferentes.'], 409);
|
||||
} catch (ValidationException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Throwable $exception) {
|
||||
Log::error('Erro ao registar manifestação de interesse', [
|
||||
'exception_type' => $exception::class,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Não foi possível registar o pedido. Tente novamente mais tarde.',
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
private function generateReference(): string
|
||||
{
|
||||
$year = now()->format('Y');
|
||||
|
||||
return 'IR-'.$year.'-'.Str::ulid();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user