@extends('layouts.dashboard') @section('title', 'PDF workflow | kView INVESTOR') @section('content') @php $statusTone = fn (?string $status) => match ($status) { \App\Models\RayDocImport::STATUS_COMPLETED, \App\Models\RayDocImport::STATUS_APPROVED => 'positive', \App\Models\RayDocImport::STATUS_REJECTED, \App\Models\RayDocImport::STATUS_FAILED => 'negative', \App\Models\RayDocImport::STATUS_PROCESSING, \App\Models\RayDocImport::STATUS_SENT_TO_RAYDOCS => 'primary', default => 'neutral', }; $jobStatusTone = fn (?string $status) => match ($status) { \App\Models\RayJob::STATUS_FAILED => 'negative', \App\Models\RayJob::STATUS_COMPLETED => 'positive', \App\Models\RayJob::STATUS_UPLOADING, \App\Models\RayJob::STATUS_PROCESSING, \App\Models\RayJob::STATUS_SENT => 'primary', default => 'neutral', }; $formatLabel = fn (?string $value) => $value ? ucfirst(str_replace('_', ' ', $value)) : '-'; $formatIdentifier = fn (?string $value) => $value ? str($value)->limit(18) : '-'; $formatBytes = function (?int $bytes): string { if ($bytes === null) { return '-'; } $units = ['B', 'KB', 'MB', 'GB']; $value = (float) $bytes; $unitIndex = 0; while ($value >= 1024 && $unitIndex < count($units) - 1) { $value /= 1024; $unitIndex++; } return number_format($value, $unitIndex === 0 ? 0 : 2).' '.$units[$unitIndex]; }; $metadata = collect($import->metadata ?? []); $latestJob = $import->latestJob; $completedJob = $import->jobs->first( fn ($job) => $job->status === \App\Models\RayJob::STATUS_COMPLETED && filled(data_get($job->response_payload, 'extraction.data')) ); $displayStatus = $completedJob ? \App\Models\RayDocImport::STATUS_COMPLETED : $import->status; $extractedData = data_get($completedJob?->response_payload, 'extraction.data'); $normalizedData = data_get($reviewTask?->extractedData?->data, 'normalized', []); $controlChecks = $reviewTask?->controlResults?->map(fn ($control) => [ 'code' => $control->control_type, 'status' => $control->status, 'message' => $control->message, 'details' => $control->data, ])->all() ?? []; $controlTone = fn (?string $status) => match ($status) { 'passed' => 'positive', 'warning' => 'warning', 'error' => 'negative', default => 'neutral', }; $canApprove = $reviewTask && $reviewTask->state === \App\Models\RayDocReviewTask::STATUS_READY && filled(data_get($reviewTask->data, 'resolution_validated_at')) && ! $reviewTask->controlResults->contains('status', 'error'); $isReviewTerminal = $reviewTask && in_array($reviewTask->state, [ \App\Models\RayDocReviewTask::STATUS_APPROVED, \App\Models\RayDocReviewTask::STATUS_REJECTED, ], true); $resolutionValidated = $reviewTask && $reviewTask->state === \App\Models\RayDocReviewTask::STATUS_READY && filled(data_get($reviewTask->data, 'resolution_validated_at')); $hasControlErrors = collect($controlChecks)->contains( fn (array $check): bool => ($check['status'] ?? null) === 'error' ); $duplicatePdfLinkAvailable = $duplicatePdfRecord !== null && collect($controlChecks)->contains( fn (array $check): bool => ($check['code'] ?? null) === 'duplicate' && ($check['status'] ?? null) === 'error' ); $rejectIsPrimary = $hasControlErrors && ! $duplicatePdfLinkAvailable; $investmentPairKeys = collect($investmentPairs)->map( fn (array $pair) => $pair['fund_id'].'|'.$pair['investor_id'] )->all(); @endphp
kView INVESTOR by kView

PDF workflow

{{ $import->original_filename }}

@csrf
Back
Status {{ $formatLabel($displayStatus) }}
Size {{ $formatBytes($import->file_size) }}
Storage {{ $fileExists ? 'OK' : 'Missing' }}
Disk {{ $import->storage_disk }}
Source
Uploaded by {{ $import->uploader?->name ?? '-' }}
Received {{ $import->received_at?->format('Y-m-d H:i') ?? '-' }}
MIME type {{ $import->mime_type ?: '-' }}

Stored document

Original PDF metadata captured before Raydocs processing.

Storage path {{ $import->storage_path }}
SHA-256 {{ $import->sha256 }}
Created {{ $import->created_at?->format('Y-m-d H:i:s') ?? '-' }}
Updated {{ $import->updated_at?->format('Y-m-d H:i:s') ?? '-' }}
@if ($completedJob)

Raydocs review

Resolve the parties, verify the controls, and approve the Call / Distribution record.

@if ($reviewTask)
Extracted key figures
Document type {{ $formatLabel($normalizedData['document_type'] ?? null) }}
Fund {{ $normalizedData['fund_name'] ?? '-' }}
Investor {{ $normalizedData['investor_name'] ?? '-' }}
Due date {{ $normalizedData['due_date'] ?? '-' }}
Call amount {{ $normalizedData['call_amount'] ?? '-' }} {{ $normalizedData['currency'] ?? '' }}
Distribution amount {{ $normalizedData['distribution_amount'] ?? '-' }} {{ $normalizedData['currency'] ?? '' }}
@if ($fileExists) Open PDF @else

The stored PDF is unavailable.

@endif
Fund and investor resolution
@if ($isReviewTerminal)
Fund {{ $reviewTask->extractedData?->fund?->full_name ?: $reviewTask->extractedData?->fund?->name ?: '-' }}
Investor {{ $reviewTask->extractedData?->investor?->full_name ?: $reviewTask->extractedData?->investor?->name ?: '-' }}
Review {{ $formatLabel($reviewTask->approval_status) }}
@if ($reviewTask->approved_record_type === 'call_distrib' && $reviewTask->approved_record_id)
Created record View Call / Distribution
@endif @if ($reviewTask->rejection_reason)
Rejection reason {{ $reviewTask->rejection_reason }}
@endif
@else
Fund {{ $reviewTask->extractedData?->fund?->full_name ?: $reviewTask->extractedData?->fund?->name ?: 'Not selected' }}
Investor {{ $reviewTask->extractedData?->investor?->full_name ?: $reviewTask->extractedData?->investor?->name ?: 'Not selected' }}
@endif
@if ($resolutionValidated || $isReviewTerminal)
Automatic controls
@forelse ($controlChecks as $check)
{{ $formatLabel($check['status'] ?? null) }}
{{ $formatLabel($check['code'] ?? null) }}

{{ $check['message'] ?? '-' }}

@if (($check['code'] ?? null) === 'duplicate' && $duplicatePdfLinkAvailable)

The existing Call / Distribution has no PDF reference.

@endif
@empty

No controls are available.

@endforelse
@endif @if (! $isReviewTerminal && $resolutionValidated)
@if ($duplicatePdfLinkAvailable)
@csrf
@endif
@csrf
@csrf
@csrf
@endif @if (! $isReviewTerminal && ! $resolutionValidated)
@csrf
Resolve Fund and investor
Fund Create a new fund
Investor Create a new investor
@if ($errors->any())

{{ $errors->first() }}

@endif
@endif @else

The completed extraction has not produced a review task yet.

@endif

Completed extraction JSON

Parsed data returned by Raydocs for result {{ $completedJob->raydocs_result_id }}.

{{ json_encode(
                                $extractedData,
                                JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
                            ) }}
@endif

Raydocs processing

Raydocs upload, extraction session, and result identifiers.

@if ($latestJob)
Status {{ $formatLabel($latestJob->status) }}
Workspace {{ $latestJob->raydocs_workspace_id ?: '-' }}
Template {{ $latestJob->raydocs_template_id ?: '-' }}
Session {{ $latestJob->raydocs_session_id ?: '-' }}
Document {{ $latestJob->raydocs_document_id ?: '-' }}
Result {{ $latestJob->raydocs_result_id ?: '-' }}
Raydocs job {{ $latestJob->raydocs_job_id ?: '-' }}
S3 upload key {{ $latestJob->upload_key ?: '-' }}
Started {{ $latestJob->started_at?->format('Y-m-d H:i:s') ?? '-' }}
@if ($latestJob->error)
Error {{ $latestJob->error }}
@endif
@endif @if ($import->jobs->isNotEmpty())
@foreach ($import->jobs as $job) @endforeach
Created Status Session Document Result Error
{{ $job->created_at?->format('Y-m-d H:i') ?? '-' }} {{ $formatLabel($job->status) }} {{ $job->raydocs_session_id ?: '-' }} {{ $job->raydocs_document_id ?: '-' }} {{ $job->raydocs_result_id ?: '-' }} {{ $job->error ?: '-' }}
@endif

Metadata

Additional import details captured from upload or email intake.

@if ($metadata->isNotEmpty())
@foreach ($metadata as $key => $value)
{{ $formatLabel((string) $key) }} {{ is_scalar($value) || $value === null ? ($value ?? '-') : json_encode($value) }}
@endforeach
@else

No additional metadata recorded.

@endif
@if (! $isReviewTerminal && ! $resolutionValidated) @endif @endsection