/ app / Http / Services / InboxFileService.php
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  }