InboxFileService.php
1 <?php 2 3 namespace App\Http\Services; 4 5 use App\Enums\InboxFileTypeEnum; 6 use App\Enums\ValidationRequirementResponseTypeEnum; 7 use App\Helpers\InboxFileSaver; 8 use App\Models\Document; 9 use App\Models\DocumentType; 10 use App\Models\Dossier; 11 use App\Models\InboxFile; 12 use App\Models\Stage; 13 use App\Models\User; 14 use App\Models\Validation; 15 use App\Models\ValidationRequirement; 16 use App\Models\ValidationRequirementResponse; 17 use App\Models\ValidationStatus; 18 use App\Models\ValidationType; 19 use App\Utils\InboxFileInterface; 20 use Carbon\Carbon; 21 use Illuminate\Database\Eloquent\Builder; 22 use Illuminate\Support\Facades\DB; 23 use Illuminate\Support\Facades\Storage; 24 use Throwable; 25 26 class InboxFileService 27 { 28 /** 29 * Search resources 30 * 31 * @param string $sortField 32 * @param string $sortDirection 33 * @param array|null $filters 34 * @return Builder 35 */ 36 public static function search(string $sortField, string $sortDirection, array $filters = []): Builder 37 { 38 return InboxFile::filter($sortField, $sortDirection, $filters); 39 } 40 41 /** 42 * @throws Throwable 43 */ 44 public static function create($user_id, $dossier_id, int $type, string $name, string $path, string $version = null): InboxFile 45 { 46 try { 47 DB::beginTransaction(); 48 $dossier = Dossier::find($dossier_id); 49 50 $needsValidation = match ($type) { 51 InboxFileTypeEnum::evaluation_request()->value => false, 52 InboxFileTypeEnum::OR()->value => false, 53 InboxFileTypeEnum::others()->value => false, 54 default => true, 55 }; 56 57 if ($dossier && $needsValidation) { 58 $validationType = $dossier->norm->validationTypes() 59 ->where('name', InboxFileTypeEnum::id2name($type)) 60 ->first(); 61 62 if ($validationType) { 63 $validation = ValidationService::createNewValidation($validationType, $dossier->id); 64 $validation->checkStatus(); 65 } 66 } 67 68 $reviewer = User::technicalManager(); 69 70 $file = new InboxFile(); 71 $file->type = $type; 72 $file->user_id = $user_id; 73 $file->dossier_id = $dossier_id; 74 $file->name = $name; 75 $file->path = $path; 76 $file->version = $version ?? 'v1'; 77 $file->validation_id = $validation->id ?? null; 78 $file->reviewer_id = $reviewer->id; 79 $file->document_id = null; 80 81 $file->save(); 82 DB::commit(); 83 84 return $file; 85 } catch (Throwable $e) { 86 DB::rollBack(); 87 logger()->error($e); 88 throw $e; 89 } 90 } 91 92 private static function incrementVersion(string $version): string 93 { 94 $versionNumber = (int) substr($version, 1); 95 return 'v' . ($versionNumber + 1); 96 } 97 98 /** 99 * @throws Throwable 100 */ 101 public static function newVersion(InboxFile $inboxFile, $user_id, string $name, string $path, string $version = null): InboxFile 102 { 103 try { 104 DB::beginTransaction(); 105 if ($inboxFile->validation) 106 $validation = ValidationService::copyValidation($inboxFile->validation); 107 108 $inboxFile->user_id = $user_id; 109 $inboxFile->name = $name; 110 $inboxFile->path = $path; 111 $inboxFile->version = $version ?? self::incrementVersion($inboxFile->version); 112 $inboxFile->validation_id = $validation->id ?? null; 113 114 $inboxFile->save(); 115 DB::commit(); 116 117 return $inboxFile; 118 } catch (Throwable $e) { 119 DB::rollBack(); 120 throw $e; 121 } 122 } 123 124 public static function finishValidation(InboxFileInterface $inboxFile, bool $isReview = false): InboxFileInterface 125 { 126 /** @var Validation $validation */ 127 $validation = $isReview ? $inboxFile->review : $inboxFile->validation; 128 $validation->validated_at = Carbon::now(); 129 $validation->save(); 130 131 /** @var ValidationStatus $status */ 132 $status = $validation->checkStatus(); 133 134 return $inboxFile; 135 } 136 137 public static function moveFile(InboxFile $inboxFile, int $userId, Document $existingDocument = null) 138 { 139 $dossier = $inboxFile->dossier; 140 141 // visibleFolder es la carpeta sobre la que irá visualmente 142 $dirTypeName = InboxFileTypeEnum::id2dirName($inboxFile->type); 143 $visibleFolder = self::getRootFolderId($dossier->id, $dirTypeName); 144 145 // Generamos para obtener un código 146 if (!$existingDocument) { 147 $document = self::newDocument($inboxFile, $inboxFile->path, $visibleFolder); 148 } else { 149 $document = $existingDocument; 150 151 $document->commit([ 152 'path' => $inboxFile->path, 153 'revision_name' => $inboxFile->name, 154 'description' => $inboxFile->name, 155 'created_by' => $userId, 156 ]); 157 $document->fresh(); 158 } 159 // Ahora que tenemos su codigo, podemos moverlo a la carpeta correcta 160 $document->head->moveToFilesystem(); 161 162 // Tambien se asocia el documento al inboxfile 163 $inboxFile->document_id = $document->id; 164 $inboxFile->path = $document->head->path; 165 $inboxFile->save(); 166 167 if ($inboxFile->type === InboxFileTypeEnum::certification_request()->value) { 168 $inboxFile->dossier->active = true; 169 $inboxFile->dossier->save(); 170 } 171 } 172 173 private static function getRootFolderId(int $dossierId, string $dirTypeName) 174 { 175 $folder = Dossier::find($dossierId) 176 ->folders() 177 ->where('name', $dirTypeName) 178 ->first(); 179 180 return $folder?->id; 181 } 182 183 public static function getPreviousNonConformities(InboxFileInterface $inboxFile) 184 { 185 $validations = []; 186 187 foreach ($inboxFile->versions as $version) { 188 if (isset($version->contents['validation_id'])) 189 $validations[] = $version->contents['validation_id']; 190 } 191 192 $requirements = ValidationRequirement::whereIn('validation_id', $validations) 193 ->whereNot('validation_id', $inboxFile->validation_id) 194 ->pluck('id'); 195 196 return ValidationRequirementResponse::with('requirement') 197 ->whereIn('validation_requirement_id', $requirements) 198 ->where('validation_requirement_response_type_id', ValidationRequirementResponseTypeEnum::nonconformity()->value) 199 ->get(); 200 } 201 202 private static function newDocument(InboxFile $inboxFile, string $path, int $folderId = null): Document 203 { 204 $name = basename($path); 205 $data = [ 206 'name' => $name, 207 'original_name' => $name, 208 'revision_name' => $name, 209 'hash' => md5_file(Storage::path($path)), 210 'size' => filesize(Storage::path($path)), 211 'isInternal' => 0, 212 'dossier_id' => $inboxFile->dossier_id, 213 'type_id' => DocumentType::where('code', 'EXT')->first()->id, 214 'created_by' => $inboxFile->user_id, 215 'from' => 'external', 216 'path' => $path, 217 'folder_id' => $folderId, 218 'active' => true, 219 'version' => 1, 220 'description' => '', 221 ]; 222 223 $doc = Document::create($data); 224 $doc->commit($data); 225 226 return $doc; 227 } 228 229 public static function isPartialReportType(string $name): bool|string 230 { 231 $partialReports = ['ASE', 'AGD', 'ALC', 'AVA', 'ATE', 'ADV']; //TODO: las clases que tenemos tendrían que obtenerse de algún lado?? 232 233 foreach ($partialReports as $partialReport) { 234 if (str_contains($name, $partialReport)) { 235 return $partialReport; 236 } 237 } 238 239 return false; 240 } 241 242 public static function evaluationRequestReceived(InboxFileSaver $saver) 243 { 244 logger()->info('Evaluation request received', ['dossier' => $saver->dossier->id]); 245 $userId = $saver->dossier->getNotifiableUser()->id; 246 TaskService::createEvaluationKickoffMeetingTask($userId, $saver->dossier); 247 TaskService::closeMilestone($saver->dossier, __('tasks.milestones.evaluation-request-received')); 248 } 249 250 public static function partialReportReceived(InboxFileSaver $saver, InboxFile $inboxFile) 251 { 252 $userId = $saver->dossier->getNotifiableUser()->id; 253 $partialClass = InboxFileService::isPartialReportType($saver->filename); 254 $task = TaskService::createValidatePartialReportTask($userId, $saver->dossier, $partialClass, $inboxFile->validation); 255 TaskService::createValidatePartialReportTaskMilestone(Stage::find($saver->dossier->current_stage_id), $partialClass, $task, $inboxFile->validation); 256 TaskService::createSendPartialReportTaskMilestone($saver->dossier->stage, $partialClass, $task, $inboxFile->validation); 257 } 258 259 public static function ETRReceived(InboxFileSaver $saver, InboxFile $inboxFile) 260 { 261 $userId = $saver->dossier->getNotifiableUser()->id; 262 $task = TaskService::createValidateETRTask($userId, $saver->dossier, $inboxFile->validation); 263 TaskService::createValidateETRTaskMilestone(Stage::find($saver->dossier->current_stage_id), $task, $inboxFile->validation); 264 TaskService::createSendETRTaskMilestone($saver->dossier->stage, $task, $inboxFile->validation); 265 } 266 267 public static function createValidation(InboxFile $inboxFile, int $validationTypeId) 268 { 269 $validationType = ValidationType::findOrFail($validationTypeId); 270 $validation = ValidationService::createNewValidation($validationType, $inboxFile->dossier->id); 271 $inboxFile->validation_id = $validation->id ?? null; 272 $inboxFile->save(); 273 } 274 }