feat(offers): implement phase four private details and confidentiality in QA
This commit is contained in:
@@ -6,15 +6,84 @@ use App\Models\Opportunity;
|
||||
use App\Services\OpportunityCanonicalContract;
|
||||
use App\Services\OpportunityManagement;
|
||||
use App\Services\OpportunityProfileWorkflow;
|
||||
use App\Services\OpportunityResources;
|
||||
use App\Services\PortalProfileAccess;
|
||||
use App\Services\PrivateOfferConfidentiality;
|
||||
use App\Services\PrivateOfferPreparation;
|
||||
use App\Services\VerifiedDocumentBinary;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Inertia\Inertia;
|
||||
use Inertia\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
|
||||
final class PrivateOfferPreparationController extends Controller
|
||||
{
|
||||
public function resources(Request $request, PrivateOfferPreparation $service, int $id): JsonResponse
|
||||
{
|
||||
$record = $service->record($request->user(), $id);
|
||||
$resources = [];
|
||||
foreach (['images', 'documents'] as $kind) {
|
||||
$resources[$kind] = array_map(fn ($row) => ['id' => $row->id, 'version' => $row->version, 'deleted' => $row->deleted_at !== null,
|
||||
'caption' => $row->payload['caption'] ?? null, 'digitally_edited' => $row->payload['digitally_edited'] ?? null,
|
||||
'edit_description' => $row->payload['edit_description'] ?? null,
|
||||
'scan' => $row->file->malware_scan_status ?? 'pending'], app(OpportunityResources::class)->listing($id, $kind));
|
||||
}
|
||||
|
||||
return response()->json(['resources' => $resources, 'etag' => app(OpportunityManagement::class)->etag($record),
|
||||
'internalProofAccess' => app(PrivateOfferConfidentiality::class)->internal($request->user(), $record)]);
|
||||
}
|
||||
|
||||
public function attachment(Request $request, PrivateOfferPreparation $service, int $id, string $kind, string $resourceId): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
$record = $service->record($request->user(), $id);
|
||||
abort_unless(in_array($kind, ['documents', 'images'], true), 404);
|
||||
$link = DB::table('opportunity_'.$kind)->where('opportunity_id', $id)->where('id', $resourceId)->whereNull('deleted_at')->first();
|
||||
abort_unless($link !== null, 404);
|
||||
$document = DB::table('documents')->where('id', $link->document_id)->whereNull('deleted_at')->first();
|
||||
abort_unless($document !== null, 404);
|
||||
|
||||
return app(VerifiedDocumentBinary::class)->respond($document);
|
||||
}
|
||||
|
||||
public function confidentiality(Request $request, PrivateOfferConfidentiality $privacy, int $id): JsonResponse|Response
|
||||
{
|
||||
$overview = $privacy->overview($request->user(), $id);
|
||||
|
||||
return $request->expectsJson() ? response()->json($overview) : Inertia::render('offers/confidentiality', ['offerId' => $id]);
|
||||
}
|
||||
|
||||
public function confidentialityAction(Request $request, PrivateOfferConfidentiality $privacy, int $id): JsonResponse
|
||||
{
|
||||
return response()->json($privacy->act($request->user(), $id, $request->all()));
|
||||
}
|
||||
|
||||
public function confidentialRead(Request $request, PrivateOfferConfidentiality $privacy, int $id): JsonResponse
|
||||
{
|
||||
try {
|
||||
$result = $privacy->read($request->user(), $id);
|
||||
} catch (HttpExceptionInterface $error) {
|
||||
app(PortalProfileAccess::class)->audit($request->user(), 'offer_confidential_denied', ['record_id' => $id, 'http_status' => $error->getStatusCode()]);
|
||||
throw $error;
|
||||
}
|
||||
abort_if(isset($result['denied']), 403, 'É necessária aceitação do NDA e autorização expressa do vendedor para esta versão.');
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
|
||||
public function nda(Request $request, PrivateOfferConfidentiality $privacy, int $id): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
$overview = $privacy->overview($request->user(), $id);
|
||||
abort_unless($overview['nda'], 409, 'O NDA aprovado ainda não foi disponibilizado.');
|
||||
app(PortalProfileAccess::class)->audit($request->user(), 'offer_nda_access', ['record_id' => $id, 'version_hash' => $overview['version_hash'], 'nda' => $overview['nda']]);
|
||||
|
||||
$document = DB::table('documents')->where('id', $overview['nda']['document_id'])->firstOrFail();
|
||||
abort_unless((int) $document->version_no === $overview['nda']['version'] && hash_equals(trim($document->sha256), $overview['nda']['sha256']), 409, 'O exemplar do NDA mudou; actualize antes de continuar.');
|
||||
|
||||
return app(VerifiedDocumentBinary::class)->respond($document);
|
||||
}
|
||||
|
||||
public function index(Request $request, PortalProfileAccess $access): Response
|
||||
{
|
||||
$filters = $request->validate(['state' => 'nullable|in:draft,submitted,in_review,needs_information,rejected,approved']);
|
||||
@@ -40,7 +109,9 @@ final class PrivateOfferPreparationController extends Controller
|
||||
$options = app(OpportunityCanonicalContract::class)->options($request->user(), $record);
|
||||
|
||||
return Inertia::render('offers/preparation', ['record' => $presentation, 'contexts' => $contexts,
|
||||
'contacts' => $options['contacts'], 'contactInvestors' => $options['contactInvestors']]);
|
||||
'contacts' => $options['contacts'], 'contactInvestors' => $options['contactInvestors'],
|
||||
'sectors' => DB::table('sectors')->where('is_active', true)->orderBy('name')->get(['id', 'name']),
|
||||
'propertyTypes' => array_values(array_filter($options['definitions']['realEstatePatch']['properties']['property_type']['enum'], fn ($type) => is_string($type)))]);
|
||||
}
|
||||
|
||||
public function save(Request $request, PrivateOfferPreparation $service, ?int $id = null): JsonResponse
|
||||
|
||||
Reference in New Issue
Block a user