File manager - Edit - /var/www/html/homologBancodetalentos/app/Http/Controllers/Web/TalentBank/CandidateWebController.php
Back
<?php namespace App\Http\Controllers\Web\TalentBank; use App\Http\Controllers\Controller; use App\Http\Controllers\Web\TalentBank\Concerns\NotifiesResumeUpdates; use App\Http\Services\TalentBank\CandidateService; use App\Http\Services\TalentBank\Candidate\CourseService; use App\Http\Services\TalentBank\Candidate\EducationService; use App\Http\Services\TalentBank\Candidate\ExperienceService; use App\Http\Services\TalentBank\Candidate\SkillService; use App\Http\Services\UserService; use App\Models\TalentBank\AcademicDiscipline; use App\Models\TalentBank\BusinessLine; use App\Models\TalentBank\Candidate; use App\Models\TalentBank\Candidate\Course; use App\Models\TalentBank\Candidate\Education; use App\Models\TalentBank\Candidate\Experience; use App\Models\TalentBank\Candidate\Skill; use App\Models\TalentBank\EducationLevel; use App\Models\TalentBank\Ethnicity; use App\Models\TalentBank\Gender; use App\Models\TalentBank\Language; use App\Models\TalentBank\LanguageProficiency; use App\Models\TalentBank\MaritalStatus; use App\Models\TalentBank\Neighbourhood; use App\Models\TalentBank\Occupation; use Barryvdh\DomPDF\Facade\Pdf; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use Illuminate\View\View; class CandidateWebController extends Controller { use NotifiesResumeUpdates; private CandidateService $candidateService; public function __construct() { $this->candidateService = new CandidateService(); } public function profile(Request $request): View { $candidate = $this->resolveCandidate($request); $candidate->load(['applications.occupation']); $canUploadProfilePhoto = Schema::hasColumn('candidates', 'photo_path'); return view('pages.perfil', [ 'nomeUsuario' => $candidate->name, 'candidate' => $candidate, 'avatarUrl' => CandidateService::photoPublicUrl($candidate->photo_path) ?? 'https://via.placeholder.com/80', 'canUploadProfilePhoto' => $canUploadProfilePhoto, ]); } public function updatePhoto(Request $request): RedirectResponse { if (! Schema::hasColumn('candidates', 'photo_path')) { return redirect()->route('talent-bank.candidate.profile'); } $candidate = $this->resolveCandidate($request); $updated = $this->candidateService->updatePhoto($request, $candidate); session(['sso.profile_photo_path' => $updated->photo_path]); return redirect()->route('talent-bank.candidate.profile'); } public function curriculum(Request $request): View { $payload = $this->buildCurriculumPresentation($request); $lookups = $this->curriculumLookups(); return view('pages.curriculo', array_merge($payload, compact('lookups'))); } public function printCurriculum(Request $request): \Illuminate\View\View { $payload = $this->buildCurriculumPresentation($request); $photoDataUri = CandidateService::photoDataUri($payload['candidate']); return view('pages.curriculo-imprimir', array_merge($payload, compact('photoDataUri'))); } public function downloadCurriculumPdf(Request $request): Response { $payload = $this->buildCurriculumPresentation($request); $photoDataUri = CandidateService::photoDataUri($payload['candidate']); $slug = Str::slug(Str::limit($payload['candidate']->name ?? 'curriculo', 80, '')); $filename = ($slug !== '' ? $slug : 'curriculo').'-banco-de-talentos.pdf'; $pdf = Pdf::loadView('pdf.curriculum', array_merge($payload, compact('photoDataUri'))) ->setPaper('a4', 'portrait'); return $pdf->download($filename); } public function streamCurriculumPdf(Request $request): Response { $payload = $this->buildCurriculumPresentation($request); $photoDataUri = CandidateService::photoDataUri($payload['candidate']); $slug = Str::slug(Str::limit($payload['candidate']->name ?? 'curriculo', 80, '')); $filename = ($slug !== '' ? $slug : 'curriculo').'-banco-de-talentos.pdf'; $pdf = Pdf::loadView('pdf.curriculum', array_merge($payload, compact('photoDataUri'))) ->setPaper('a4', 'portrait'); return $pdf->stream($filename); } /** * @return array{usuario: object, experiencias: \Illuminate\Support\Collection, formacoes: \Illuminate\Support\Collection, conhecimentos: \Illuminate\Support\Collection, idiomas: \Illuminate\Support\Collection, habilidades: \Illuminate\Support\Collection, candidate: Candidate} */ private function buildCurriculumPresentation(Request $request): array { $candidate = $this->resolveCandidate($request); $canUploadProfilePhoto = Schema::hasColumn('candidates', 'photo_path'); $candidate->load([ 'gender', 'maritalStatus', 'ethnicity', 'occupation', 'neighbourhood', 'experiences.occupation', 'educations.educationLevel', 'educations.academicDiscipline', 'courses', 'skills', 'languages', 'wantedOccupations', ]); $levelPct = ['Basico' => 25, 'Intermediario' => 50, 'Avancado' => 75, 'Fluente' => 90, 'Nativo' => 100]; $usuario = (object) [ 'foto' => $canUploadProfilePhoto ? CandidateService::photoPublicUrl($candidate->photo_path) : null, 'nome' => $candidate->name, 'cargo' => optional($candidate->occupation)->name, 'occupation_id' => $candidate->occupation_id, 'perfil' => $candidate->cv_summary, 'data_nascimento' => $candidate->birth_date ? $candidate->birth_date->format('d/m/Y') : '', 'sexo' => optional($candidate->gender)->name, 'telefone' => $candidate->cellphone ?: $candidate->telephone, 'estado_civil' => optional($candidate->maritalStatus)->name, 'outro_campo' => optional($candidate->ethnicity)->name, 'status' => $candidate->special_needs ? 'PCD' : '', 'endereco' => $candidate->address, 'cep' => $candidate->zip_code, 'bairro' => optional($candidate->neighbourhood)->name, 'neighbourhood_id' => $candidate->neighbourhood_id, ]; $experiencias = $candidate->experiences->map(fn ($exp) => (object) [ 'id' => $exp->id, 'inicio' => $exp->date_start ? $exp->date_start->format('d/m/Y') : '', 'fim' => $exp->is_current ? 'Atual' : ($exp->date_end ? $exp->date_end->format('d/m/Y') : ''), 'date_start_raw' => $exp->date_start ? $exp->date_start->format('Y-m-d') : '', 'date_end_raw' => $exp->date_end ? $exp->date_end->format('Y-m-d') : '', 'is_current' => $exp->is_current, 'cargo' => optional($exp->occupation)->name ?? '', 'occupation_id' => $exp->occupation_id, 'empresa' => $exp->company ?? '', 'descricao' => $exp->description ?? '', 'business_line_id' => $exp->business_line_id, ]); $formacoes = $candidate->educations->map(fn ($edu) => (object) [ 'id' => $edu->id, 'inicio' => $edu->date_start ? $edu->date_start->format('d/m/Y') : '', 'fim' => $edu->date_end ? $edu->date_end->format('d/m/Y') : '', 'date_start_raw' => $edu->date_start ? $edu->date_start->format('Y-m-d') : '', 'date_end_raw' => $edu->date_end ? $edu->date_end->format('Y-m-d') : '', 'nivel' => optional($edu->educationLevel)->name ?? '', 'disciplina' => optional($edu->academicDiscipline)->name ?? '', 'education_level_id' => $edu->education_level_id, 'academic_discipline_id' => $edu->academic_discipline_id, 'instituicao' => $edu->institution ?? '', 'certificado' => $edu->specialization ?? '', ]); $conhecimentos = $candidate->courses->map(fn ($course) => (object) [ 'id' => $course->id, 'inicio' => $course->date_start ? $course->date_start->format('d/m/Y') : '', 'fim' => $course->date_end ? $course->date_end->format('d/m/Y') : '', 'date_start_raw' => $course->date_start ? $course->date_start->format('Y-m-d') : '', 'date_end_raw' => $course->date_end ? $course->date_end->format('Y-m-d') : '', 'titulo' => $course->name ?? '', 'instituicao' => $course->institution ?? '', 'carga' => $course->duration ?? '', ]); $idiomas = $candidate->languages->map(function ($lang) use ($levelPct) { $nivel = $lang->pivot->language_proficiency_id ? optional(LanguageProficiency::find($lang->pivot->language_proficiency_id))->name ?? '' : ''; return (object) [ 'id' => $lang->id, 'nome' => $lang->name ?? '', 'nivel' => $nivel, 'porcentagem' => $levelPct[$this->normalizeText($nivel)] ?? 0, ]; }); $habilidades = $candidate->skills->map(fn ($skill) => (object) [ 'id' => $skill->id, 'descricao' => $skill->name ?? '', ]); $areasInteresse = $candidate->wantedOccupations->map(fn ($occ) => (object) [ 'id' => $occ->id, 'nome' => $occ->name, ]); return compact('usuario', 'experiencias', 'formacoes', 'conhecimentos', 'idiomas', 'habilidades', 'candidate', 'areasInteresse'); } /** * @return array<string, \Illuminate\Support\Collection> */ private function curriculumLookups(): array { return [ 'ocupacoes' => Occupation::orderBy('name')->pluck('name', 'id'), 'areasNegocio' => BusinessLine::orderBy('name')->pluck('name', 'id'), 'niveisFormacao' => EducationLevel::orderBy('name')->pluck('name', 'id'), 'disciplinas' => AcademicDiscipline::orderBy('name')->pluck('name', 'id'), 'idiomas_lista' => Language::orderBy('name')->pluck('name', 'id'), 'proficiencias' => LanguageProficiency::orderBy('id')->pluck('name', 'id'), 'generos' => Gender::orderBy('name')->pluck('name', 'id'), 'estadosCivis' => MaritalStatus::orderBy('name')->pluck('name', 'id'), 'etnias' => Ethnicity::orderBy('name')->pluck('name', 'id'), 'bairros' => Neighbourhood::orderBy('name')->pluck('name', 'id'), ]; } public function editProfile(Request $request): View { $candidate = $this->resolveCandidate($request); $candidate->load(['gender', 'maritalStatus', 'ethnicity', 'occupation', 'neighbourhood', 'wantedOccupations']); $profileData = [ 'cpf' => $candidate->cpf, 'full_name' => $candidate->name, 'birth_date' => $candidate->birth_date ? $candidate->birth_date->format('Y-m-d') : '', 'gender' => optional($candidate->gender)->name, 'marital_status' => optional($candidate->maritalStatus)->name, 'ethnicity' => optional($candidate->ethnicity)->name, 'pcd' => $candidate->special_needs ? 1 : 0, 'desired_role' => optional($candidate->occupation)->name, 'address' => $candidate->address, 'cep' => $candidate->zip_code, 'neighborhood' => optional($candidate->neighbourhood)->name, 'phone_home' => $candidate->telephone, 'phone_cell' => $candidate->cellphone, 'last_salary' => $candidate->min_payment, 'expected_salary' => $candidate->desired_payment, 'resume' => $candidate->cv_summary, ]; $allOccupations = Occupation::orderBy('name')->get(['id', 'name']); $selectedOccupationIds = $candidate->wantedOccupations->pluck('id'); $options = $this->candidateService->getOptions(); return view('pages.alterar-cadastro', compact('candidate', 'profileData', 'allOccupations', 'selectedOccupationIds', 'options')); } public function updateProfile(Request $request): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); try { DB::beginTransaction(); $data = $request->all(); unset($data['cpf'], $data['_method'], $data['_token']); // Map form field names → model column names $fieldMap = [ 'full_name' => 'name', 'phone_home' => 'telephone', 'phone_cell' => 'cellphone', 'cep' => 'zip_code', 'last_salary' => 'min_payment', 'expected_salary' => 'desired_payment', 'resume' => 'cv_summary', ]; foreach ($fieldMap as $formKey => $modelKey) { if (array_key_exists($formKey, $data)) { $data[$modelKey] = $data[$formKey]; unset($data[$formKey]); } } if (array_key_exists('pcd', $data)) { $data['special_needs'] = (bool) $data['pcd']; unset($data['pcd']); } unset($data['desired_role']); foreach (['gender_id', 'marital_status_id', 'ethnicity_id', 'occupation_id', 'neighbourhood_id'] as $nullableFk) { if (array_key_exists($nullableFk, $data) && $data[$nullableFk] === '') { $data[$nullableFk] = null; } } if (array_key_exists('birth_date', $data) && $data['birth_date'] === '') { $data['birth_date'] = null; } $this->candidateService->update($data, $candidate); DB::commit(); } catch (\Exception $e) { DB::rollBack(); if ($request->wantsJson()) { return response()->json(['message' => $e->getMessage()], 422); } return back()->withErrors(['form' => $e->getMessage()])->withInput(); } if ($request->wantsJson()) { return response()->json(['ok' => true]); } return redirect()->route('talent-bank.candidate.edit') ->with('success', __('crud.message.update', ['model' => __('crud.model.talent_bank.candidate')])); } public function selfEdit(Request $request): RedirectResponse { $candidate = $this->resolveCandidate($request); try { DB::beginTransaction(); $userService = new UserService(); $ssoResponse = $userService->selfEdit($request); if ($ssoResponse->status() === 200) { $userData = data_get($ssoResponse->json(), 'data.user', []); $localData = array_filter([ 'name' => $userData['name'] ?? null, 'email' => $userData['email'] ?? null, ]); if ($localData) { $this->candidateService->update($localData, $candidate); } } DB::commit(); } catch (\Exception $e) { DB::rollBack(); return back()->withErrors(['form' => $e->getMessage()])->withInput(); } return redirect()->route('talent-bank.candidate.edit') ->with('success', __('crud.message.update', ['model' => __('crud.model.talent_bank.candidate')])); } public function storeSkill(Request $request): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); try { (new SkillService())->store($request, $candidate); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function updateSkill(Request $request, int $id): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $skill = Skill::where('candidate_id', $candidate->id)->findOrFail($id); try { (new SkillService())->update($request->all(), $skill); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function destroySkill(Request $request, int $id): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $skill = Skill::where('candidate_id', $candidate->id)->findOrFail($id); try { (new SkillService())->destroy($skill); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function storeEducation(Request $request): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); try { (new EducationService())->store($request, $candidate); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function updateEducation(Request $request, int $id): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $education = Education::where('candidate_id', $candidate->id)->findOrFail($id); try { (new EducationService())->update($request->all(), $education); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function destroyEducation(Request $request, int $id): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $education = Education::where('candidate_id', $candidate->id)->findOrFail($id); try { (new EducationService())->destroy($education); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function storeCourse(Request $request): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); try { (new CourseService())->store($request, $candidate); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function updateCourse(Request $request, int $id): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $course = Course::where('candidate_id', $candidate->id)->findOrFail($id); try { (new CourseService())->update($request->all(), $course); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function destroyCourse(Request $request, int $id): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $course = Course::where('candidate_id', $candidate->id)->findOrFail($id); try { (new CourseService())->destroy($course); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function storeExperience(Request $request): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $request->merge(['salary' => $this->sanitizeSalary($request->input('salary'))]); try { (new ExperienceService())->store($request, $candidate); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function updateExperience(Request $request, int $id): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $experience = Experience::where('candidate_id', $candidate->id)->findOrFail($id); $request->merge(['salary' => $this->sanitizeSalary($request->input('salary'))]); try { (new ExperienceService())->update($request->all(), $experience); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function destroyExperience(Request $request, int $id): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); $experience = Experience::where('candidate_id', $candidate->id)->findOrFail($id); try { (new ExperienceService())->destroy($experience); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function attachLanguage(Request $request): RedirectResponse|\Illuminate\Http\JsonResponse { $validator = Validator::make($request->all(), [ 'language_id' => 'required|integer|exists:languages,id', 'language_proficiency_id' => 'required|integer|exists:language_proficiencies,id', ]); if ($validator->fails()) { if ($request->wantsJson()) { return response()->json(['errors' => $validator->errors()], 422); } return back()->withErrors($validator)->withInput(); } $candidate = $this->resolveCandidate($request); try { $this->candidateService->attachLanguage($request, $candidate); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function detachLanguage(Request $request, int $languageId): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); try { $this->candidateService->detachLanguage($candidate, $languageId); } catch (\Exception $e) { return $this->jsonOrRedirectError($request, $e->getMessage()); } return $this->jsonOrRedirect($request, 'talent-bank.candidate.curriculum'); } public function attachWantedOccupation(Request $request): RedirectResponse|\Illuminate\Http\JsonResponse { $request->validate(['occupation_id' => 'required|integer|exists:occupations,id']); $candidate = $this->resolveCandidate($request); if ($candidate->wantedOccupations()->count() >= 3) { $message = 'Você já atingiu o limite de 3 áreas de interesse.'; return $request->wantsJson() ? response()->json(['message' => $message], 422) : back()->with('error', $message); } try { $this->candidateService->attachWantedOccupation($candidate, (int) $request->input('occupation_id')); } catch (\Exception $e) { return $request->wantsJson() ? response()->json(['message' => $e->getMessage()], 422) : back()->with('error', $e->getMessage()); } return $request->wantsJson() ? response()->json(['ok' => true]) : back()->with('success', 'Área de interesse adicionada.')->with('open_step', 6); } public function detachWantedOccupation(Request $request, int $occupationId): RedirectResponse|\Illuminate\Http\JsonResponse { $candidate = $this->resolveCandidate($request); try { $this->candidateService->detachWantedOccupation($candidate, $occupationId); } catch (\Exception $e) { return $request->wantsJson() ? response()->json(['message' => $e->getMessage()], 422) : back()->with('error', $e->getMessage()); } return $request->wantsJson() ? response()->json(['ok' => true]) : back()->with('success', 'Área de interesse removida.')->with('open_step', 6); } private function sanitizeSalary(mixed $value): ?float { if ($value === null || $value === '') { return null; } // Remove tudo exceto dígitos, ponto e vírgula; troca vírgula por ponto $clean = preg_replace('/[^\d,.]/', '', (string) $value); $clean = str_replace(',', '.', $clean); // Se houver mais de um ponto, mantém só o último como decimal $parts = explode('.', $clean); if (count($parts) > 2) { $clean = implode('', array_slice($parts, 0, -1)) . '.' . end($parts); } return is_numeric($clean) ? (float) $clean : null; } private function jsonOrRedirect(Request $request, string $route): RedirectResponse|\Illuminate\Http\JsonResponse { if ($route === 'talent-bank.candidate.curriculum') { $this->notifyResumeUpdatedIfApplied($this->resolveCandidate($request)); } if ($request->wantsJson()) { return response()->json(['ok' => true]); } return redirect()->route($route)->with('success', __('validation.success')); } private function jsonOrRedirectError(Request $request, string $message): RedirectResponse|\Illuminate\Http\JsonResponse { if ($request->wantsJson()) { return response()->json(['message' => $message], 422); } return back()->with('error', $message); } private function resolveCandidate(Request $request): Candidate { $user = $request->input('talentBankUser') ?? $request->talentBankUser ?? null; abort_if(! $user instanceof Candidate, 403); return $user; } private function normalizeText(string $value): string { $normalized = strtolower($value); $from = ['á', 'à', 'ã', 'â', 'é', 'ê', 'í', 'ó', 'ô', 'õ', 'ú', 'ç']; $to = ['a', 'a', 'a', 'a', 'e', 'e', 'i', 'o', 'o', 'o', 'u', 'c']; return str_replace($from, $to, $normalized); } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings