<?php
/*
Nombre del programador:         Cordourier Rojas Mathew
Ultima fecha de modificación:   [ 24 / Marzo / 2023 ]
Descripción:                    Controlador del submodulo Personal. Perteneciente al Módulo 13 - Gestion del Personal de Mantenimiento
*/

namespace App\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use stdClass;
use Throwable;

class EmployeeController extends Controller
{

    private $response_controller;
    private $encrypt_controller;
    private $documents_controller;

    public function __construct()
    {
        $this->response_controller = new ResponseController();
        $this->encrypt_controller = new EncryptionController();
        $this->documents_controller = new DocumentsController();

    }

    // Metodo para obtener datos del personal
    public function getConsultOfEmployees($line_number)
    {
        try {
            $employees = DB::table('S002V01TPERS')
                ->select(
                    'S002V01TPERS.PERS_IDPE as ID_EMPLOYEE',
                    DB::raw('CONCAT(S002V01TUSUA_P.USUA_NOMB, " " , S002V01TUSUA_P.USUA_APPA, " ",  S002V01TUSUA_P.USUA_APMA) as NAME'),
                    'S002V01TPERS.PERS_TICO as CONTRACT_TYPE',
                    'S002V01TPERS.PERS_ESPE as SPECIALITY',
                    'S002V01TPERS.PERS_FERE as REGISTER_DATE',
                    'S002V01TPERS.PERS_USRE as REGISTERED_BY_USER',
                    'S002V01TPERS.PERS_FEMO as UPDATE_DATE',
                    'S002V01TPERS.PERS_USMO as UPDATED_BY_USER',
                    'S002V01TPERS.PERS_ESTA as STATUS'
                )
                // ->where('S002V01TPERS.PERS_ESTA', '=', 'Activo')
                ->where('S002V01TPERS.PERS_NULI', '=', $line_number)
                ->where('S002V01TUSUA_P.USUA_NULI', '=', $line_number)
                ->join('S002V01TUSUA_P', 'S002V01TPERS.PERS_IDUS', '=', 'S002V01TUSUA_P.USUA_IDUS')
                ->get();

            // Verifica si el objeto esta vacio
            if (!isset($employees[0]) && empty($employees[0])) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG001: No se encontraron datos', $employees, 500);
            }

            $users = DB::table('S002V01TUSUA_P')
                ->select('USUA_IDUS as ID', DB::raw('CONCAT(USUA_NOMB, " " , USUA_APPA, " ",  USUA_APMA) as NAME'))
                ->where('USUA_NULI', '=', $line_number)
                ->get();

            // Verifica si el objeto esta vacio
            if (!isset($users[0]) && empty($users[0])) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_USUARIO_REG002: No se encontraron datos', $users, 500);
            }

            $workteams = DB::table('S002V01TEQMA')
                ->select('S002V01TEQMA.EQMA_NOMB as NAME', 'S002V01TPEEM.PEEM_IDPE as ID_EMPLOYEE')
                ->where('S002V01TEQMA.EQMA_NULI', '=', $line_number)
                ->where('S002V01TPEEM.PEEM_NULI', '=', $line_number)
                ->join('S002V01TPEEM', 'S002V01TEQMA.EQMA_IDEQ', '=', 'S002V01TPEEM.PEEM_IDEM')
                ->get();

            // Verifica si el objeto esta vacio
            if (!isset($workteams[0]) && empty($workteams[0])) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_EQUIPO_TRABAJO_REG003: No se encontraron datos', $workteams, 500);
            }

            foreach ($employees as $employee) {

                // Introduce los equipos de trabajo a los que pertenece
                foreach ($workteams as $workteam) {
                    if ($employee->ID_EMPLOYEE == $workteam->ID_EMPLOYEE) {
                        $employee->WORKTEAMS[] = $workteam->NAME;
                    }
                }

                // Introduce la persona que lo registro
                foreach ($users as $user) {
                    if ($employee->REGISTERED_BY_USER == $user->ID) {
                        $employee->REGISTERED_BY_USER = $user->NAME;
                    }

                    // Si hubo actualización, introduce a la persona que lo actualizo
                    if ($employee->UPDATED_BY_USER != null) {
                        if ($employee->UPDATED_BY_USER == $user->ID) {
                            $employee->UPDATED_BY_USER = $user->NAME;
                        }
                    } else {
                        $employee->UPDATED_BY_USER = "-";
                    }
                }

                // Introduce la fecha en que se registro y actualizo al empleado (si hubo actualización)
                $employee->REGISTER_DATE = Carbon::create($employee->REGISTER_DATE)->format("d-m-Y h:i:s A");
                if ($employee->UPDATE_DATE != null) {
                    $employee->UPDATE_DATE = Carbon::create($employee->UPDATE_DATE)->format("d-m-Y h:i:s A");
                } else {
                    $employee->UPDATE_DATE = "-";
                }
            }

            return $this->response_controller
                ->makeResponse(FALSE, "Consulta exitosa", $employees);


        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG004: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

    // Metodo para ver el listado de documentos de un empleado
    public function getDocumentsByEmployee($id_employee, $line_number)
    {
        try {

            // Busca si existe el empleado
            $employee_found = DB::table('S002V01TPERS')
                ->select('PERS_IDPE')
                ->where('PERS_IDPE', '=', $id_employee)
                ->where('PERS_NULI', '=', $line_number)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($employee_found) && empty($employee_found)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG001: No se encontró al empleado', [], 500);
            }

            // Busca si el empleado tiene documentos
            $documents_by_employee = DB::table('S002V01TDOCU_P')
                ->select('DOCU_LIDO as DOCUMENT_LINK')
                ->where('DOCU_IDPE', '=', $id_employee)
                ->where('DOCU_NULI', '=', $line_number)
                ->get();

            // Verifica si el objeto esta vacio
            if (!isset($documents_by_employee[0]) && empty($documents_by_employee[0])) {
                return $this->response_controller
                    ->makeResponse(FALSE, 'El empleado no tiene documentos', []);
            }

            // Encripta la liga de cada documento
            foreach ($documents_by_employee as $doc) {

                $doc->DOCUMENT_NAME = $doc->DOCUMENT_LINK;
                $doc->DOCUMENT_LINK = Storage::disk('pdf')->url($doc->DOCUMENT_LINK);
                $doc->DOCUMENT_LINK = $this->encrypt_controller->encrypt($doc->DOCUMENT_LINK);
            }

            return $this->response_controller
                ->makeResponse(FALSE, "Consulta exitosa", $documents_by_employee);


        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG003: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

    // Metodo para obtener todas las intervenciones relacionadas a un empleado
    public function getInterventionsByEmployee($id_employee, $line_number)
    {
        try {

            // Verifica si el empleado existe
            $employee_exist = DB::table('S002V01TPERS')
                ->select('PERS_IDPE')
                ->where('PERS_IDPE', '=', $id_employee)
                ->where('PERS_NULI', '=', $line_number)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($employee_exist) && empty($employee_exist)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG001: No se encontró al empleado', [], 500);
            }

            // Obtiene las intervenciones del empleado
            $employee_interventions = DB::table('S002V01TPERS')
                ->select(
                    'S002V01TEQMA.EQMA_NOMB as WORKTEAM_NAME',
                    'S002V01TINTE_P.INTE_NOMB as INTERVENTION_NAME',
                    'S002V01TEQMA.EQMA_NOMB as WORKTEAM_NAME',
                    'S002V01TINTE_P.INTE_IDIN as INTERVENTION_ID',
                    'S002V01TINTE_P.INTE_DESC as INTERVENTION_DESCRIPTION',
                )
                ->where('S002V01TPERS.PERS_IDPE', '=', $id_employee)
                ->where('S002V01TPERS.PERS_NULI', '=', $line_number)
                ->where('S002V01TPEEM.PEEM_NULI', '=', $line_number)
                ->where('S002V01TEQMA.EQMA_NULI', '=', $line_number)
                ->where('S002V01TEMIN.EMIN_NULI', '=', $line_number)
                ->where('S002V01TINTE_P.INTE_NULI', '=', $line_number)
                ->join('S002V01TPEEM', 'S002V01TPERS.PERS_IDPE', '=', 'S002V01TPEEM.PEEM_IDPE')
                ->join('S002V01TEQMA', 'S002V01TPEEM.PEEM_IDEM', '=', 'S002V01TEQMA.EQMA_IDEQ')
                ->join('S002V01TEMIN', 'S002V01TEQMA.EQMA_IDEQ', '=', 'S002V01TEMIN.EMIN_IDEM')
                ->join('S002V01TINTE_P', 'S002V01TEMIN.EMIN_IDIN', '=', 'S002V01TINTE_P.INTE_IDIN')
                ->get();

            // Verifica si el objeto esta vacio
            if (!isset($employee_interventions[0]) && empty($employee_interventions[0])) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG002: El empleado no tiene intervenciones', [], 500);
            }

            return $this->response_controller
                ->makeResponse(FALSE, "Consulta exitosa", $employee_interventions);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG003: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

    // Metodo para la eliminación logica de un empleado
    public function updateToInactiveStatus(Request $request, $id_employee)
    {
        try {
            $request['SAVED_BY_USER'] = $this->encrypt_controller->decrypt($request->SAVED_BY_USER);
            $validator = Validator::make($request->all(), [
                "SAVED_BY_USER" => ['required', 'digits:10']
            ]);

            if ($validator->fails()) {
                return $this->response_controller->makeResponse(
                    TRUE,
                    'ERR_PERSONAL_REG001: Uno o más errores encontrados',
                    $this->response_controller->makeErrors($validator->errors()->messages()),
                    400
                );
            }

            // Busca si el empleado existe
            $search_employee = DB::table("S002V01TPERS")
                ->select("PERS_IDPE")
                ->where("PERS_IDPE", "=", $id_employee)
                ->where('PERS_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($search_employee) && empty($search_employee)) {
                return $this->response_controller
                    ->makeResponse(TRUE, "ERR_PERSONAL_REG002: No se encontró al empleado", $search_employee, 500);
            }

            $user_register = DB::table('S002V01TUSUA_P')
                ->select('USUA_IDUS as ID_USER')
                ->where('USUA_IDUS', '=', $request->SAVED_BY_USER)
                ->where('USUA_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($user_register) && empty($user_register)) {
                return $this->response_controller
                    ->makeResponse(TRUE, "ERR_USUARIO_REG003: Tu usuario no es válido para eliminar empleados", [], 500);
            }

            // Busca si el empleado tiene intervenciones activas
            $search_employee = DB::table("S002V01TPERS")
                ->select("S002V01TINTE_P.INTE_NOMB")
                ->where("S002V01TPERS.PERS_IDPE", "=", $id_employee)
                ->where("S002V01TINTE_P.INTE_ESTA", "=", "Activo")
                ->where("S002V01TEMIN.EMIN_ESTA", "=", "Activo")
                ->where("S002V01TPERS.PERS_NULI", "=", $request->LINE_NUMBER)
                ->where('S002V01TPEEM.PEEM_NULI', '=', $request->LINE_NUMBER)
                ->where('S002V01TEQMA.EQMA_NULI', '=', $request->LINE_NUMBER)
                ->where('S002V01TEMIN.EMIN_NULI', '=', $request->LINE_NUMBER)
                ->where('S002V01TINTE_P.INTE_NULI', '=', $request->LINE_NUMBER)
                ->groupBy('S002V01TINTE_P.INTE_NOMB')
                ->join("S002V01TPEEM", "S002V01TPERS.PERS_IDPE", "=", "S002V01TPEEM.PEEM_IDPE")
                ->join("S002V01TEQMA", "S002V01TPEEM.PEEM_IDEM", "=", "S002V01TEQMA.EQMA_IDEQ")
                ->join("S002V01TEMIN", "S002V01TEQMA.EQMA_IDEQ", "=", "S002V01TEMIN.EMIN_IDEM")
                ->join("S002V01TINTE_P", "S002V01TEMIN.EMIN_IDIN", "=", "S002V01TINTE_P.INTE_IDIN")
                ->get();


            // Verifica si el objeto contiene algo
            if (isset($search_employee[0]) && !empty($search_employee[0])) {
                return $this->response_controller
                    ->makeResponse(TRUE, "ERR_PERSONAL_REG004: Empleado ocupado con intervenciones", $search_employee, 500);
            } else {

                DB::beginTransaction(); # Para impedir que las actualizaciones queden incompletas

                $UPDATE_DATE = Carbon::now()->timezone('America/Mexico_City')->toDateTimeString();

                $delete_employee = DB::table('S002V01TPERS')
                    ->where('PERS_IDPE', $id_employee)
                    ->where('PERS_NULI', '=', $request->LINE_NUMBER)
                    ->update([
                        "PERS_ESTA" => "Inactivo",
                        "PERS_USMO" => trim($request->SAVED_BY_USER),
                        "PERS_FEMO" => $UPDATE_DATE,
                        "PERS_FEAR" => DB::raw('CURRENT_TIMESTAMP')
                    ]);

                // Verifica que la actualización fuera exitosa
                if ($delete_employee < 1) {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_PERSONAL_REG005: Algo salió mal, error eliminando al empleado', [], 500);
                }

                $delete_employee = DB::table('S002V01TPEEM')
                    ->where('PEEM_IDPE', $id_employee)
                    ->where('PEEM_NULI', '=', $request->LINE_NUMBER)
                    ->update([
                        "PEEM_ESTA" => "Inactivo",
                        "PEEM_USMO" => trim($request->SAVED_BY_USER),
                        "PEEM_FEMO" => $UPDATE_DATE,
                        "PEEM_FEAR" => DB::raw('CURRENT_TIMESTAMP')
                    ]);

                // Verifica que la actualización fuera exitosa
                if ($delete_employee < 1) {
                    DB::rollBack(); # Si no se logra eliminar al empleado en el equipo, se revierten los cambios previos
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_PERSONAL_REG006: Algo salió mal, error eliminando al empleado del equipo', [], 500);
                }
            }
            DB::commit(); # Para guardar los cambios en la base de datos
            return $this->response_controller->makeResponse(FALSE, "Eliminado exitoso");

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG007: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

    // Metodo para obtener a los usuarios que no son empleados
    public function getAvaibleUsers($line_number)
    {

        try {

            // Busca en la base si existe otro empleado con ese usuario
            $users = DB::table('S002V01TUSUA_P')
                ->select(
                    DB::raw('CONCAT(USUA_NOMB, " " , USUA_APPA, " ",  USUA_APMA) as NAME'),
                    "USUA_IDUS as ID_USER"
                )
                ->orderBy('NAME', 'asc')
                ->where('USUA_NULI', '=', $line_number)
                ->where('USUA_ESTA', '=', "Activo")
                ->get();

            // Verifica si el objeto contiene algo
            if (!isset($users) && empty($users)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_USUARIO_REG001: No se encontraron datos', [], 500);
            }

            // // Busca si el usuario existe
            // $employees = DB::table('S002V01TPERS')
            //     ->select("PERS_IDUS as ID_USER")
            //     ->where('PERS_NULI', '=', $line_number)
            //     ->get();

            // // Verifica si el objeto esta vacio
            // if (!isset($employees) && empty($employees)) {
            //     return $this->response_controller
            //         ->makeResponse(TRUE, 'ERR_PERSONAL_REG002: No se encontraron datos', [], 500);
            // }

            // $usersNotEmployees = [];

            // foreach ($users as $user) {
            //     foreach ($employees as $employee) {
            //         if ($user->ID_USER == $employee->ID_USER) {
            //             $user->ID_USER = "XXXX";
            //         }
            //     }
            //     if ($user->ID_USER != "XXXX") {
            //         $usersNotEmployees[] = $user;
            //     }
            // }

            // // Verifica si el objeto esta vacio
            // if (!isset($usersNotEmployees[0]) && empty($usersNotEmployees[0])) {
            //     return $this->response_controller
            //         ->makeResponse(TRUE, 'ERR_USUARIO_REG003: Todos los usuarios actuales son empleados', [], 500);
            // }

            return $this->response_controller->makeResponse(FALSE, 'Usuarios obtenidos', $users, 200);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG004: Error inesperado', strtoupper($th), 500);
        }
    }

    // Metodo para guardar un nuevo empleado
    public function storeEmployee(Request $request)
    {

        try {
            $REGISTER_DATE = Carbon::now()->timezone('America/Mexico_City')->toDateTimeString();
            $request['SAVED_BY_USER'] = $this->encrypt_controller->decrypt($request->SAVED_BY_USER);
            $request['CONTACT_NAME'] = $this->encrypt_controller->decrypt($request->CONTACT_NAME);
            $request['CONTACT_TELEPHONE'] = $this->encrypt_controller->decrypt($request->CONTACT_TELEPHONE);
            $request['CONTACT_ADDRESS'] = $this->encrypt_controller->decrypt($request->CONTACT_ADDRESS);

            $validator = Validator::make($request->all(), [
                "USER_ID" => ['required', 'digits:10'],
                "WORKTEAM_ID" => ['required', 'digits:10'],
                "CONTACT_NAME" => ['required', 'max:150'],
                "CONTACT_TELEPHONE" => ['required', 'max:11'],
                "CONTACT_ADDRESS" => ['required', 'max:100'],
                "CONTRACT_TYPE" => ['required'],
                "SPECIALITY" => ['required', 'max:75'],
                "SUBCONTRATIST_ID" => ['max:10'],
                "SAVED_BY_USER" => ['required', 'digits:10'],
                "LINE_NUMBER" => ['required', 'digits:1']
            ]);


            if ($validator->fails()) {
                return $this->response_controller->makeResponse(
                    TRUE,
                    'ERR_PERSONAL_REG001: Uno o más errores encontrados',
                    $this->response_controller->makeErrors($validator->errors()->messages()),
                    400
                );
            }

            // Busca en la base si existe otro empleado con ese usuario
            $uniq_user = DB::table('S002V01TPERS')
                ->select("PERS_IDPE")
                ->where('PERS_IDUS', '=', $request->USER_ID)
                ->where('PERS_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto contiene algo
            if (isset($uniq_user) && !empty($uniq_user)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG002: El usuario ya está registrado como empleado', [], 500);
            }

            // Busca si el usuario existe
            $user_exist = DB::table('S002V01TUSUA_P')
                ->select("USUA_IDUS")
                ->where('USUA_IDUS', '=', $request->USER_ID)
                ->where('USUA_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($user_exist) && empty($user_exist)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG003: No se encontró al usuario', [], 500);
            }

            // Busca si el equipo de trabajo existe
            $team_found = DB::table('S002V01TEQMA')
                ->select('EQMA_NOMB')
                ->where('EQMA_IDEQ', '=', $request->WORKTEAM_ID)
                ->where('EQMA_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($team_found) && empty($team_found)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_EQUIPO_TRABAJO_REG004: No se encontró al equipo de trabajo', [], 500);
            }

            $user_register = DB::table('S002V01TUSUA_P')
                ->select('USUA_IDUS as ID_USER')
                ->where('USUA_IDUS', '=', $request->SAVED_BY_USER)
                ->where('USUA_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($user_register) && empty($user_register)) {
                return $this->response_controller
                    ->makeResponse(TRUE, "ERR_USUARIO_REG005: Tu usuario no es válido para registrar empleados", [], 500);
            }

            DB::beginTransaction(); # Para impedir que las actualizaciones queden a incompletas

            $insert_employee = DB::table('S002V01TPERS')
                ->insert([
                    "PERS_IDUS" => $request->USER_ID,
                    "PERS_NOCE" => trim($request->CONTACT_NAME),
                    "PERS_NUTC" => $request->CONTACT_TELEPHONE,
                    "PERS_DICE" => trim($request->CONTACT_ADDRESS),
                    "PERS_TICO" => trim($request->CONTRACT_TYPE),
                    "PERS_ESPE" => trim($request->SPECIALITY),
                    "PERS_IDPS" => $request->SUBCONTRATIST_ID,
                    "PERS_NULI" => $request->LINE_NUMBER,
                    "PERS_ESTA" => "Activo",
                    "PERS_USRE" => $request->SAVED_BY_USER,
                    "PERS_FERE" => $REGISTER_DATE,
                    "PERS_FEAR" => DB::raw('CURRENT_TIMESTAMP')
                ]);

            // Verifica que la inserción del empleado se haya hecho correctamente
            if (!$insert_employee) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG006: Algo salió mal, error registrando al empleado', [], 500);
            }

            // Obtiene el ID del empleado registrado
            $employee_id = DB::table('S002V01TPERS')
                ->select('PERS_IDPE as EMPLOYEE_ID')
                ->where('PERS_IDUS', '=', $request->USER_ID)
                ->where('PERS_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Saca el ID del objeto
            $employee_id = $employee_id->EMPLOYEE_ID;

            $insert_employee_on_workteam = DB::table('S002V01TPEEM')
                ->insert([
                    "PEEM_IDPE" => $employee_id,
                    "PEEM_IDEM" => $request->WORKTEAM_ID,
                    "PEEM_NULI" => $request->LINE_NUMBER,
                    "PEEM_ESTA" => "Activo",
                    "PEEM_USRE" => $request->SAVED_BY_USER,
                    "PEEM_FERE" => $REGISTER_DATE,
                    "PEEM_FEAR" => DB::raw('CURRENT_TIMESTAMP'),
                ]);

            // Verifica que la inserción del empleado en el equipo de trabajo se haya hecho correctamente
            if (!$insert_employee_on_workteam) {
                DB::rollBack(); # Si no se logra insertar al equipo, se revierten los cambios previos
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_EQUIPO_TRABAJO_REG007: Algo salió mal, error registrando al empleado en el equipo', [], 500);
            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENTS_AUTHO) && !empty($request->DOCUMENTS_AUTHO)) {
                $doc = $request->DOCUMENTS_AUTHO;


                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $employee_id;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $name_document = $this->documents_controller->createDocument(
                    "GPRS",
                    "IN",
                    $final_part_name_document,
                    $employee_id,
                    'pdf',
                    $request->LINE_NUMBER,
                    $request->SAVED_BY_USER
                );

                // El documento es guardado en el storage
                $doc->storeAs('public/pdf_documents', $name_document);



            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENTS_AUTHO2) && !empty($request->DOCUMENTS_AUTHO2)) {
                $doc = $request->DOCUMENTS_AUTHO2;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $employee_id;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $name_document = $this->documents_controller->createDocument(
                    "GPRS",
                    "IN",
                    $final_part_name_document,
                    $employee_id,
                    'pdf',
                    $request->LINE_NUMBER,
                    $request->SAVED_BY_USER
                );

                // El documento es guardado en el storage
                $doc->storeAs('public/pdf_documents', $name_document);



            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENTS_CERT) && !empty($request->DOCUMENTS_CERT)) {
                $doc = $request->DOCUMENTS_CERT;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $employee_id;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $name_document = $this->documents_controller->createDocument(
                    "GPRS",
                    "CE",
                    $final_part_name_document,
                    $employee_id,
                    'pdf',
                    $request->LINE_NUMBER,
                    $request->SAVED_BY_USER
                );

                // El documento es guardado en el storage
                $doc->storeAs('public/pdf_documents', $name_document);



            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENTS_CERT2) && !empty($request->DOCUMENTS_CERT2)) {
                $doc = $request->DOCUMENTS_CERT2;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $employee_id;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $name_document = $this->documents_controller->createDocument(
                    "GPRS",
                    "CE",
                    $final_part_name_document,
                    $employee_id,
                    'pdf',
                    $request->LINE_NUMBER,
                    $request->SAVED_BY_USER
                );

                // El documento es guardado en el storage
                $doc->storeAs('public/pdf_documents', $name_document);



            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENT_OFFICE) && !empty($request->DOCUMENT_OFFICE)) {
                $doc = $request->DOCUMENT_OFFICE;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $employee_id;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $name_document = $this->documents_controller->createDocument(
                    "GPRS",
                    "CO",
                    $final_part_name_document,
                    $employee_id,
                    'pdf',
                    $request->LINE_NUMBER,
                    $request->SAVED_BY_USER
                );

                // El documento es guardado en el storage
                $doc->storeAs('public/pdf_documents', $name_document);

            }

            DB::commit(); # Para guardar los cambios en la base de datos
            return $this->response_controller->makeResponse(FALSE, 'Creación exitosa', 200);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG008: Error inesperado', strtoupper($th), 500);
        }
    }

    // Metodo para obtener un empleado por id con sus documentos (Pensado: 1 empleado solo tiene un equipo de trabajo)
    public function getEmployeeById($id_employee, $line_number)
    {
        try {

            $employee = DB::table('S002V01TPERS')
                ->select(
                    'S002V01TPERS.PERS_IDPE as ID_EMPLOYEE',
                    'S002V01TPERS.PERS_IDUS as USER_ID',
                    'S002V01TEQMA.EQMA_IDEQ as WORKTEAM_ID',
                    'S002V01TPERS.PERS_IDPS as SUBCONTRATIST_ID',
                    'S002V01TEQMA.EQMA_NOMB as WORKTEAM_NAME',
                    'S002V01TPERS.PERS_NOCE as CONTACT_NAME',
                    'S002V01TPERS.PERS_NUTC as CONTACT_TELEPHONE',
                    'S002V01TPERS.PERS_DICE as CONTACT_ADDRESS',
                    'S002V01TPERS.PERS_TICO as CONTRACT_TYPE',
                    'S002V01TPERS.PERS_ESPE as SPECIALITY',
                    'S002V01TPERS.PERS_NULI as LINE_NUMBER',
                    DB::raw('CONCAT(S002V01TUSUA_P.USUA_NOMB, " " , S002V01TUSUA_P.USUA_APPA, " ",  S002V01TUSUA_P.USUA_APMA) as EMPLOYEE_NAME')
                )
                ->where('S002V01TPERS.PERS_IDPE', '=', $id_employee)
                ->where('S002V01TPERS.PERS_NULI', '=', $line_number)
                ->where('s002v01TPEEM.PEEM_NULI', '=', $line_number)
                ->where('s002v01TEQMA.EQMA_NULI', '=', $line_number)
                ->where('s002v01TUSUA_P.USUA_NULI', '=', $line_number)
                ->join('S002V01TPEEM', 'S002V01TPERS.PERS_IDPE', '=', 'S002V01TPEEM.PEEM_IDPE')
                ->join('S002V01TEQMA', 'S002V01TPEEM.PEEM_IDEM', '=', 'S002V01TEQMA.EQMA_IDEQ')
                ->join('S002V01TUSUA_P', 'S002V01TPERS.PERS_IDUS', '=', 'S002V01TUSUA_P.USUA_IDUS')
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($employee) && empty($employee)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG001: No se encontró al empleado', [], 500);
            }

            $employee->CONTACT_NAME = $this->encrypt_controller->encrypt($employee->CONTACT_NAME);
            $employee->CONTACT_TELEPHONE = $this->encrypt_controller->encrypt($employee->CONTACT_TELEPHONE);
            $employee->CONTACT_ADDRESS = $this->encrypt_controller->encrypt($employee->CONTACT_ADDRESS);

            $employee->DOCUMENTS = [];

            // Obtiene los documentos de un empleado
            $documents_of_employee = DB::table('S002V01TDOCU_P')
                ->select('DOCU_LIDO as DOCUMENT')
                ->where('DOCU_IDPE', '=', $id_employee)
                ->where('DOCU_NULI', '=', $line_number)
                ->get();

            // Verifica si el objeto contiene algo
            if (isset($documents_of_employee[0]) && !empty($documents_of_employee[0])) {
                foreach ($documents_of_employee as $doc) {
                    $employee->DOCUMENTS[] = $this->encrypt_controller->encrypt($doc->DOCUMENT);
                }
            }

            return $this->response_controller
                ->makeResponse(FALSE, "Consulta exitosa", $employee);


        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG002: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

    // Metodo para obtener todos los empleados con sus documentos (Pensado: 1 empleado solo tiene un equipo de trabajo)
    public function getAllEmployees($line_number)
    {
        try {

            $employees = DB::table('S002V01TPERS')
                ->select(
                    'S002V01TPERS.PERS_IDPE as EMPLOYEE_ID',
                    'S002V01TPERS.PERS_IDUS as USER_ID',
                    'S002V01TEQMA.EQMA_IDEQ as WORKTEAM_ID',
                    'S002V01TPERS.PERS_NOCE as CONTACT_NAME',
                    'S002V01TPERS.PERS_NUTC as CONTACT_TELEPHONE',
                    'S002V01TPERS.PERS_DICE as CONTACT_ADDRESS',
                    'S002V01TPERS.PERS_TICO as CONTRACT_TYPE',
                    'S002V01TPERS.PERS_ESPE as SPECIALITY',
                )
                ->where('S002V01TPERS.PERS_NULI', '=', $line_number)
                ->where('S002V01TPEEM.PEEM_NULI', '=', $line_number)
                ->where('S002V01TEQMA.EQMA_NULI', '=', $line_number)
                ->join('S002V01TPEEM', 'S002V01TPERS.PERS_IDPE', '=', 'S002V01TPEEM.PEEM_IDPE')
                ->join('S002V01TEQMA', 'S002V01TPEEM.PEEM_IDEM', '=', 'S002V01TEQMA.EQMA_IDEQ')
                ->get();

            // Verifica si el objeto esta vacio
            if (!isset($employees[0]) && empty($employees[0])) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG001: No se encontraron datos', [], 500);
            }

            foreach ($employees as $employee) {
                $employee->CONTACT_NAME = $this->encrypt_controller->encrypt($employee->CONTACT_NAME);
                $employee->CONTACT_TELEPHONE = $this->encrypt_controller->encrypt($employee->CONTACT_TELEPHONE);
                $employee->CONTACT_ADDRESS = $this->encrypt_controller->encrypt($employee->CONTACT_ADDRESS);
                $employee->DOCUMENTS = [];
            }

            // Obtiene los documentos
            $documents_of_employees = DB::table('S002V01TDOCU_P')
                ->select('DOCU_LIDO as DOCUMENT', 'DOCU_IDPE as EMPLOYEE_ID')
                ->where('DOCU_NULI', '=', $line_number)
                ->get();

            // Verifica si el objeto esta vacio
            if (isset($documents_of_employees[0]) && !empty($documents_of_employees[0])) {

                // Asigna al empleado los documentos que le pertenezcan
                foreach ($employees as $employee) {
                    foreach ($documents_of_employees as $doc) {
                        if ($employee->EMPLOYEE_ID == $doc->EMPLOYEE_ID) {
                            $employee->DOCUMENTS[] = $this->encrypt_controller->encrypt($doc->DOCUMENT);
                        }
                    }
                }
            }

            return $this->response_controller
                ->makeResponse(FALSE, "Consulta exitosa", $employees);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG002: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

    // Metodo para actualizar un empleado
    public function updateEmployee(Request $request, $id_employee)
    {

        try {
            $save_option = $request->UPLOAD_NEW_DOCUMENTS != "N";
            $request['SAVED_BY_USER'] = $this->encrypt_controller->decrypt($request->SAVED_BY_USER);
            $UPDATE_DATE = Carbon::now()->timezone('America/Mexico_City')->toDateTimeString();
            $request['CONTACT_NAME'] = $this->encrypt_controller->decrypt($request->CONTACT_NAME);
            $request['CONTACT_TELEPHONE'] = $this->encrypt_controller->decrypt($request->CONTACT_TELEPHONE);
            $request['CONTACT_ADDRESS'] = $this->encrypt_controller->decrypt($request->CONTACT_ADDRESS);

            $validator = Validator::make($request->all(), [
                "USER_ID" => ['required', 'digits:10'],
                "WORKTEAM_ID" => ['required', 'digits:10'],
                "CONTACT_NAME" => ['required', 'max:150'],
                "CONTACT_TELEPHONE" => ['required', 'max:11'],
                "CONTACT_ADDRESS" => ['required', 'max:100'],
                "CONTRACT_TYPE" => ['required'],
                "SPECIALITY" => ['required', 'max:75'],
                "SUBCONTRATIST_ID" => ['max:10'],
                "SAVED_BY_USER" => ['required', 'digits:10'],
                "LINE_NUMBER" => ['required', 'digits:1']
            ]);

            if ($validator->fails()) {
                return $this->response_controller->makeResponse(
                    true,
                    'ERR_PERSONAL_REG001: Uno o más errores encontrados',
                    $this->response_controller->makeErrors($validator->errors()->messages()),
                    400
                );
            }

            // Busca al empleado si existe
            $employee_exist = DB::table('S002V01TPERS')
                ->select('PERS_IDPE')
                ->where('PERS_IDPE', '=', $id_employee)
                ->where('PERS_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($employee_exist) && empty($employee_exist)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG002: No se encontró al empleado', [], 500);
            }

            // Busca al equipo de trabajo si existe
            $team_found = DB::table('S002V01TEQMA')
                ->select('EQMA_NOMB')
                ->where('EQMA_IDEQ', '=', $request->WORKTEAM_ID)
                ->where('EQMA_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($team_found) && empty($team_found)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_EQUIPO_TRABAJO_REG003: No se encontró al equipo de trabajo', [], 500);
            }

            $user_register = DB::table('S002V01TUSUA_P')
                ->select('USUA_IDUS as ID_USER')
                ->where('USUA_IDUS', '=', $request->SAVED_BY_USER)
                ->where('USUA_NULI', '=', $request->LINE_NUMBER)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($user_register) && empty($user_register)) {
                return $this->response_controller
                    ->makeResponse(TRUE, "ERR_USUARIO_REG004: Tu usuario no es válido para actualizar empleados", [], 500);
            }

            DB::beginTransaction(); # Para impedir que las actualizaciones queden incompletas

            $update_employee = DB::table('S002V01TPERS')
                ->where('PERS_IDPE', '=', $id_employee)
                ->where('PERS_NULI', '=', $request->LINE_NUMBER)
                ->update([
                    "PERS_IDUS" => $request->USER_ID,
                    "PERS_NOCE" => trim($request->CONTACT_NAME),
                    "PERS_NUTC" => $request->CONTACT_TELEPHONE,
                    "PERS_DICE" => trim($request->CONTACT_ADDRESS),
                    "PERS_TICO" => trim($request->CONTRACT_TYPE),
                    "PERS_ESPE" => trim($request->SPECIALITY),
                    "PERS_IDPS" => $request->SUBCONTRATIST_ID,
                    "PERS_ESTA" => "Activo",
                    "PERS_USMO" => $request->SAVED_BY_USER,
                    "PERS_FEMO" => $UPDATE_DATE,
                    "PERS_FEAR" => DB::raw('CURRENT_TIMESTAMP')
                ]);

            // Verifica que la actualización del empleado haya sido satisfactoria
            if ($update_employee < 1) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG005: Algo salió mal, error actualizando al empleado', [], 500);
            }

            $update_employee_on_workteam = DB::table('S002V01TPEEM')
                ->where('PEEM_IDPE', '=', $id_employee)
                ->where('PEEM_NULI', '=', $request->LINE_NUMBER)
                ->update([
                    "PEEM_IDEM" => $request->WORKTEAM_ID,
                    "PEEM_ESTA" => "Activo",
                    "PEEM_USRE" => $request->SAVED_BY_USER,
                    "PEEM_FERE" => $UPDATE_DATE,
                    "PEEM_FEAR" => DB::raw('CURRENT_TIMESTAMP'),
                ]);

            // Verifica que la actualización del cambio de equipo del empleado haya sido satisfactoria
            if ($update_employee_on_workteam < 1) {
                DB::rollBack(); # Si no se logra actualizar el equipo, se revierten los cambios previos
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_EQUIPO_TRABAJO_REG006: Algo salió mal, error cambiando al empleado de equipo', [], 500);
            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENTS_AUTHO) && !empty($request->DOCUMENTS_AUTHO)) {
                $doc = $request->DOCUMENTS_AUTHO;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $id_employee;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $final_part_name_document = $this->documents_controller->deleteCodificationStructureName($final_part_name_document, "01", "GPRS");
                $old_documents_name = $this->documents_controller->getDocumentsWithSameName($final_part_name_document, "pdf");
                if ($old_documents_name != null) {

                    // Si no hay ningun cambio en el documento, se descarga la ultima versión
                    $old_documents_name = $this->documents_controller->sameDocumentsPdfOnRequest($doc, $old_documents_name);
                    if ($old_documents_name == null) {

                        // Crea el nombre del documento y lo almacena en la base de datos
                        $name_document = $this->documents_controller->createDocument(
                            "GPRS",
                            "IN",
                            $final_part_name_document,
                            $id_employee,
                            'pdf',
                            $request->LINE_NUMBER,
                            $request->SAVED_BY_USER,
                            $request->UPLOAD_NEW_DOCUMENTS
                        );

                        // El documento es guardado en el storage
                        $doc->storeAs('public/pdf_documents', $name_document);
                    }
                } else {
                    $name_document = $this->documents_controller->createDocument(
                        "GPRS",
                        "IN",
                        $final_part_name_document,
                        $id_employee,
                        'pdf',
                        $request->LINE_NUMBER,
                        $request->SAVED_BY_USER
                    );

                    // El documento es guardado en el storage
                    $doc->storeAs('public/pdf_documents', $name_document);
                }
                $request->UPLOAD_NEW_DOCUMENTS = "N";
            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENTS_AUTHO2) && !empty($request->DOCUMENTS_AUTHO2)) {
                $doc = $request->DOCUMENTS_AUTHO2;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $id_employee;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $final_part_name_document = $this->documents_controller->deleteCodificationStructureName($final_part_name_document, "01", "GPRS");
                $old_documents_name = $this->documents_controller->getDocumentsWithSameName($final_part_name_document, "pdf");
                if ($old_documents_name != null) {

                    // Si no hay ningun cambio en el documento, se descarga la ultima versión
                    $old_documents_name = $this->documents_controller->sameDocumentsPdfOnRequest($doc, $old_documents_name);
                    if ($old_documents_name == null) {

                        // Crea el nombre del documento y lo almacena en la base de datos
                        $name_document = $this->documents_controller->createDocument(
                            "GPRS",
                            "IN",
                            $final_part_name_document,
                            $id_employee,
                            'pdf',
                            $request->LINE_NUMBER,
                            $request->SAVED_BY_USER,
                            $request->UPLOAD_NEW_DOCUMENTS
                        );

                        // El documento es guardado en el storage
                        $doc->storeAs('public/pdf_documents', $name_document);
                    }
                } else {
                    $name_document = $this->documents_controller->createDocument(
                        "GPRS",
                        "IN",
                        $final_part_name_document,
                        $id_employee,
                        'pdf',
                        $request->LINE_NUMBER,
                        $request->SAVED_BY_USER
                    );

                    // El documento es guardado en el storage
                    $doc->storeAs('public/pdf_documents', $name_document);
                }

            }

            // Para llevar el control de la secuencia en los archivos, si el usuario desea no actualizar los nuevos, sino crear otros.s
            if ($save_option) {
                $request->UPLOAD_NEW_DOCUMENTS = "Y";
            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENTS_CERT) && !empty($request->DOCUMENTS_CERT)) {
                $doc = $request->DOCUMENTS_CERT;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $id_employee;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $final_part_name_document = $this->documents_controller->deleteCodificationStructureName($final_part_name_document, "01", "GPRS");
                $old_documents_name = $this->documents_controller->getDocumentsWithSameName($final_part_name_document, "pdf");
                if ($old_documents_name != null) {
                    // Si no hay ningun cambio en el documento, se descarga la ultima versión
                    $old_documents_name = $this->documents_controller->sameDocumentsPdfOnRequest($doc, $old_documents_name);
                    if ($old_documents_name == null) {

                        // Crea el nombre del documento y lo almacena en la base de datos
                        $name_document = $this->documents_controller->createDocument(
                            "GPRS",
                            "CE",
                            $final_part_name_document,
                            $id_employee,
                            'pdf',
                            $request->LINE_NUMBER,
                            $request->SAVED_BY_USER,
                            $request->UPLOAD_NEW_DOCUMENTS
                        );

                        // El documento es guardado en el storage
                        $doc->storeAs('public/pdf_documents', $name_document);
                    }
                } else {
                    $name_document = $this->documents_controller->createDocument(
                        "GPRS",
                        "CE",
                        $final_part_name_document,
                        $id_employee,
                        'pdf',
                        $request->LINE_NUMBER,
                        $request->SAVED_BY_USER
                    );

                    // El documento es guardado en el storage
                    $doc->storeAs('public/pdf_documents', $name_document);
                }

                $request->UPLOAD_NEW_DOCUMENTS = "N";
            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENTS_CERT2) && !empty($request->DOCUMENTS_CERT2)) {
                $doc = $request->DOCUMENTS_CERT2;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $id_employee;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $final_part_name_document = $this->documents_controller->deleteCodificationStructureName($final_part_name_document, "01", "GPRS");
                $old_documents_name = $this->documents_controller->getDocumentsWithSameName($final_part_name_document, "pdf");
                if ($old_documents_name != null) {
                    // Si no hay ningun cambio en el documento, se descarga la ultima versión
                    $old_documents_name = $this->documents_controller->sameDocumentsPdfOnRequest($doc, $old_documents_name);
                    if ($old_documents_name == null) {

                        // Crea el nombre del documento y lo almacena en la base de datos
                        $name_document = $this->documents_controller->createDocument(
                            "GPRS",
                            "CE",
                            $final_part_name_document,
                            $id_employee,
                            'pdf',
                            $request->LINE_NUMBER,
                            $request->SAVED_BY_USER,
                            $request->UPLOAD_NEW_DOCUMENTS
                        );

                        // El documento es guardado en el storage
                        $doc->storeAs('public/pdf_documents', $name_document);
                    }
                } else {
                    $name_document = $this->documents_controller->createDocument(
                        "GPRS",
                        "CE",
                        $final_part_name_document,
                        $id_employee,
                        'pdf',
                        $request->LINE_NUMBER,
                        $request->SAVED_BY_USER
                    );

                    // El documento es guardado en el storage
                    $doc->storeAs('public/pdf_documents', $name_document);
                }



            }

            if ($save_option) {
                $request->UPLOAD_NEW_DOCUMENTS = "Y";
            }

            // Verifica si el objeto esta vacio
            if (isset($request->DOCUMENT_OFFICE) && !empty($request->DOCUMENT_OFFICE)) {
                $doc = $request->DOCUMENT_OFFICE;

                // Se obtiene el nombre del archivo con su extensión
                $completeFileName = $doc->getClientOriginalName();
                // Se obtiene únicamente el nombre
                $fileNameOnly = pathinfo($completeFileName, PATHINFO_FILENAME) . '-' . $id_employee;

                // Se obtiene la extensión del archivo
                $extension = $doc->getClientOriginalExtension();
                if ($extension != "pdf") {
                    return $this->response_controller
                        ->makeResponse(TRUE, 'ERR_DOCUMENTO_REG007: Solo se permiten archivos PDF', [], 500);
                }

                // Se quitan los espacios y se concatena datos para ser guardado
                $final_part_name_document = str_replace(' ', '_', $fileNameOnly) . '.' . $extension;

                $final_part_name_document = $this->documents_controller->deleteCodificationStructureName($final_part_name_document, "01", "GPRS");
                $old_documents_name = $this->documents_controller->getDocumentsWithSameName($final_part_name_document, "pdf");
                if ($old_documents_name != null) {

                    // Si no hay ningun cambio en el documento, se descarga la ultima versión
                    $old_documents_name = $this->documents_controller->sameDocumentsPdfOnRequest($doc, $old_documents_name);
                    if ($old_documents_name == null) {

                        // Crea el nombre del documento y lo almacena en la base de datos
                        $name_document = $this->documents_controller->createDocument(
                            "GPRS",
                            "CO",
                            $final_part_name_document,
                            $id_employee,
                            'pdf',
                            $request->LINE_NUMBER,
                            $request->SAVED_BY_USER,
                            $request->UPLOAD_NEW_DOCUMENTS
                        );

                        // El documento es guardado en el storage
                        $doc->storeAs('public/pdf_documents', $name_document);
                    }
                } else {
                    $name_document = $this->documents_controller->createDocument(
                        "GPRS",
                        "CO",
                        $final_part_name_document,
                        $id_employee,
                        'pdf',
                        $request->LINE_NUMBER,
                        $request->SAVED_BY_USER
                    );

                    // El documento es guardado en el storage
                    $doc->storeAs('public/pdf_documents', $name_document);
                }



            }

            DB::commit(); # Para guardar los cambios en la base de datos
            return $this->response_controller->makeResponse(FALSE, 'Actualización exitosa', 200);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG008: Error inesperado', strtoupper($th), 500);
        }
    }

    // Metodo para obtener la cantidad de contratos otorgados a cada empleado
    public function getContractsOfEveryEmployee($line_number)
    {
        try {

            // Obtiene la cantidad de contratos que tiene cada empleado
            $contracts_by_employee = DB::table('S002V01TPERS')
                ->select(
                    'S002V01TPERS.PERS_IDPE as ID_EMPLOYEE',
                    DB::raw('CONCAT(S002V01TUSUA_P.USUA_NOMB, " " , S002V01TUSUA_P.USUA_APPA, " ", S002V01TUSUA_P.USUA_APMA) AS NAME'),
                    DB::raw(
                        'COUNT(S002V01TPECO.PECO_IDPE) AS CONTRACTS_COUNT',
                    )
                )
                ->where('S002V01TPERS.PERS_NULI', '=', $line_number)
                ->where('S002V01TUSUA_P.USUA_NULI', '=', $line_number)
                ->where('S002V01TPECO.PECO_NULI', '=', $line_number)
                ->where('S002V01TCONT.CONT_NULI', '=', $line_number)
                ->groupBy('S002V01TPERS.PERS_IDPE', 'NAME', 'S002V01TPECO.PECO_IDPE')
                ->join('S002V01TUSUA_P', 'S002V01TPERS.PERS_IDUS', '=', 'S002V01TUSUA_P.USUA_IDUS')
                ->join('S002V01TPECO', 'S002V01TPERS.PERS_IDPE', '=', 'S002V01TPECO.PECO_IDPE')
                ->join('S002V01TCONT', 'S002V01TPECO.PECO_IDCO', '=', 'S002V01TCONT.CONT_IDCO')
                ->get();

            // Verifica si el objeto esta vacio
            if (!isset($contracts_by_employee[0]) && empty($contracts_by_employee[0])) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_CONTRATO_REG001: No se encontraron datos', [], 500);
            }

            return $this->response_controller
                ->makeResponse(FALSE, "Consulta exitosa", $contracts_by_employee);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG002: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

    // Metodo para obtener detalles acerca de los contratos otorgados al empleado
    public function getDetailsOfContractsByEmployee($id_employee, $line_number)
    {
        try {

            // Busca al empleado si existe
            $employee_exist = DB::table('S002V01TPERS')
                ->select('PERS_IDPE')
                ->where('PERS_IDPE', '=', $id_employee)
                ->where('PERS_NULI', '=', $line_number)
                ->first();

            // Verifica si el objeto esta vacio
            if (!isset($employee_exist) && empty($employee_exist)) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_REG001: No se encontró al empleado', [], 500);
            }

            //Obtiene los contratos pertenecientes al subcontratista deseado
            $contracts_by_employee = DB::table('S002V01TPERS')
                ->orderBy("S002V01TCONT.CONT_FEIN", 'desc')
                ->where('S002V01TPERS.PERS_IDPE', '=', $id_employee)
                ->where('S002V01TPERS.PERS_NULI', '=', $line_number)
                ->where('S002V01TPECO.PECO_NULI', '=', $line_number)
                ->where('S002V01TCONT.CONT_NULI', '=', $line_number)
                ->select('S002V01TCONT.CONT_FEIN as START_DATE', 'S002V01TCONT.CONT_FEFI as END_DATE', 'S002V01TCONT.CONT_COST as CONTRACT_COST')
                ->join('S002V01TPECO', 'S002V01TPERS.PERS_IDPE', '=', 'S002V01TPECO.PECO_IDPE')
                ->join('S002V01TCONT', 'S002V01TPECO.PECO_IDCO', '=', 'S002V01TCONT.CONT_IDCO')
                ->get();

            // Verifica si el objeto esta vacio
            if (!isset($contracts_by_employee[0]) && empty($contracts_by_employee[0])) {
                return $this->response_controller
                    ->makeResponse(TRUE, 'ERR_PERSONAL_CONTRATO_REG002: Empleado sin contratos', $contracts_by_employee, 500);
            }

            foreach ($contracts_by_employee as $contract) {
                $contract->START_DATE = Carbon::create($contract->START_DATE)->format("d-m-Y h:i:s A");
                $contract->END_DATE = Carbon::create($contract->END_DATE)->format("d-m-Y h:i:s A");
                $contract->CONTRACT_COST = $this->encrypt_controller->encrypt($contract->CONTRACT_COST);
            }

            return $this->response_controller
                ->makeResponse(FALSE, "Consulta exitosa", $contracts_by_employee);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PERSONAL_REG003: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

    // Metodo para la descarga de archivo excel con los detalles del empleado
    public function downoloadEmployeeInfoOnExcel(Request $request)
    {

        try {
            $request['SAVED_BY_USER'] = $this->encrypt_controller->decrypt($request->SAVED_BY_USER);
            $employee_id = $request->EMPLOYEE['EMPLOYEE_ID'];

            $final_part_name_document = "Details_Of_Employee_" . $employee_id . ".xlsx";

            // Crea el documento con los datos del request
            $document = $this->createDocument($request);

            // Busca la ultima versión del documento que se haya insertado
            $old_document_name = $this->documents_controller->getDocumentsWithSameName($final_part_name_document, 'excel');

            if ($old_document_name != null) {

                // Obtiene el nombre del documento que tiene el mismo contenido
                $old_document_name = $this->documents_controller->sameDocumentsExcel($document, $old_document_name);

                // Si no hay ningun cambio en el documento, se descarga la ultima versión
                if ($old_document_name != null) {
                    return Storage::disk('excel')->url($old_document_name);
                }
            }

            // Guarda el documento creado en la variable
            $writer = IOFactory::createWriter($document, 'Xlsx');
            $content = tmpfile();
            $writer->save($content);

            // Inserta la nueva version del documento en la base de datos y en el storage            
            $name_document = $this->documents_controller->createDocument("GPRS", "IN", $final_part_name_document, $employee_id, "excel", $request->EMPLOYEE['LINE_NUMBER'], $request->SAVED_BY_USER);

            Storage::disk('excel')->put(
                $name_document,
                $content
            );

            return Storage::disk('excel')->url($name_document);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_EXCEL_REG001: Error inesperado', strtoupper($th), 500);
        }
    }

    // Metodo para la descarga de archivo pdf con los detalles del empleado
    public function downoloadEmployeeInfoOnPdf(Request $request)
    {

        try {
            $request['SAVED_BY_USER'] = $this->encrypt_controller->decrypt($request->SAVED_BY_USER);
            $employee_id = $request->EMPLOYEE['EMPLOYEE_ID'];

            $final_part_name_document = "Details_Of_Employee_" . $employee_id . ".pdf";

            // Crea el documento
            $document = $this->createDocument($request);
            $writer = IOFactory::createWriter($document, 'Mpdf');
            $content = tmpfile();

            // Busca la ultima versión del documento que se haya insertado
            $old_document_name = $this->documents_controller->getDocumentsWithSameName($final_part_name_document, 'pdf');

            $writer->save($content);
            if ($old_document_name != null) {

                // Obtiene el nombre del documento que tiene el mismo contenido
                $old_document_name = $this->documents_controller->sameDocumentsPdf($content, $old_document_name);

                // Si no hay ningun cambio en el documento, se descarga la ultima versión
                if ($old_document_name != null) {
                    return Storage::disk('pdf')->url($old_document_name);
                }
            }

            // Inserta la nueva version del documento en la base de datos y en el storage
            $name_document = $this->documents_controller->createDocument("GPRS", "IN", $final_part_name_document, $employee_id, "pdf", $request->EMPLOYEE['LINE_NUMBER'], $request->SAVED_BY_USER);
            Storage::disk('pdf')->put(
                $name_document,
                $content
            );

            return Storage::disk('pdf')->url($name_document);

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_PDF_REG001: Error inesperado', strtoupper($th), 500);
        }
    }

    // Metodo para la creación de archivo
    public function createDocument(Request $request)
    {
        try {
            $employee = $request->EMPLOYEE;
            $document = new Spreadsheet();

            // Propiedades del documento
            $document->getProperties()
                ->setCreator("ITTEC")
                ->setTitle("Detalles del empleado")
                ->setDescription("Detalles de solo un empleado.")
                ->setKeywords("Empleado Detalles")
                ->setCategory("Empleado Detalles Pdf");

            // Hace la escritura dentro del archivo
            $start_row = 2; # Indica desde que fila inicia la tabla
            $start_col = "B"; # Indica desde que columna inicia la tabla

            $col = $start_col;
            $row = $start_row;
            $col++;
            $second_col = $col;
            $col++;
            $third_col = $col;
            $col++;
            $fourth_col = $col;
            $col++;
            $fifth_col = $col;
            $col++;
            $sixth_col = $col;
            $col++;
            $seventh_col = $col;
            $col++;
            $eight_col = $col;
            $col = $start_col;
            $final_col = "";

            for ($i = 0; $i < 9; $i++) {
                $final_col = $col;
                $col++;
            }
            $col = $start_col;

            // Titulo del documento
            $document->getActiveSheet()->mergeCells($start_col . $row . ":" . $final_col . $row);
            $document->getActiveSheet()->setCellValue($start_col . $row, 'DETALLES DEL EMPLEADO')->getStyle($start_col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('FFCC88');
            $document->getActiveSheet()->getStyle($start_col . $row)->getFont()->setBold(true);
            $row++;

            //Cuerpo del documento
            $document->getActiveSheet()->setCellValue($col . $row, 'ID EMPLEADO')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, 'NOMBRE EMPLEADO')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, 'NOMBRE EQUIPO')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, 'NOMBRE CONTACTO DE EMERGENCIA')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, 'TELEFONO CONTACTO DE EMERGENCIA')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, 'DIRECCIÓN CONTACTO DE EMERGENCIA')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, 'TIPO DE CONTRATO')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, 'ESPECIALIDAD DEL EMPLEADO')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, 'LIGA DE DOCUMENTOS')->getStyle($col . $row)->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setRGB('38D9CE');

            $row++;
            $col = $start_col;

            $document->getActiveSheet()->setCellValue($col . $row, "#" . $employee['EMPLOYEE_ID']);
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, $employee['EMPLOYEE_NAME']);
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, $employee['WORKTEAM_NAME']);
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, $employee['CONTACT_NAME']);
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, $employee['CONTACT_TELEPHONE']);
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, $employee['CONTACT_ADDRESS']);
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, $employee['CONTRACT_TYPE']);
            $col++;

            $document->getActiveSheet()->setCellValue($col . $row, $employee['SPECIALITY']);
            $col++;

            // Verifica si el empleado tiene documentos
            if (isset($employee['DOCUMENTS'][0]) && !empty($employee['DOCUMENTS'][0])) {
                foreach ($employee['DOCUMENTS'] as $doc) {
                    $document->getActiveSheet()->setCellValue($col . $row, $this->encrypt_controller->decrypt($doc));
                    $row++;
                }
            } else {
                $document->getActiveSheet()->setCellValue($col . $row, 'SIN DOCUMENTOS...');
                $document->getActiveSheet()->getStyle($col . $row)->getFont()->setBold(true);
                $row++;
            }

            //Ajusta las celdas a su contenido y da estilo
            $document->getActiveSheet()->mergeCells($start_col . $start_row + 2 . ":" . $start_col . $row - 1);
            $document->getActiveSheet()->mergeCells($second_col . $start_row + 2 . ":" . $second_col . $row - 1);
            $document->getActiveSheet()->mergeCells($third_col . $start_row + 2 . ":" . $third_col . $row - 1);
            $document->getActiveSheet()->mergeCells($fourth_col . $start_row + 2 . ":" . $fourth_col . $row - 1);
            $document->getActiveSheet()->mergeCells($fifth_col . $start_row + 2 . ":" . $fifth_col . $row - 1);
            $document->getActiveSheet()->mergeCells($sixth_col . $start_row + 2 . ":" . $sixth_col . $row - 1);
            $document->getActiveSheet()->mergeCells($seventh_col . $start_row + 2 . ":" . $seventh_col . $row - 1);
            $document->getActiveSheet()->mergeCells($eight_col . $start_row + 2 . ":" . $eight_col . $row - 1);

            $col = $start_col;
            for ($i = 0; $i < 9; $i++) {
                $document->getActiveSheet()->getColumnDimension($col)->setAutoSize(true);
                $col++;
            }

            $document->getActiveSheet()->getStyle($start_col . $start_row . ':' . $final_col . $row)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
            $document->getActiveSheet()->getStyle($start_col . $start_row . ':' . $final_col . $row)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
            $document->getActiveSheet()->getStyle($start_col . $start_row . ':' . $final_col . $row - 1)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM);

            return $document;

        } catch (Throwable $th) {
            return $this->response_controller
                ->makeResponse(TRUE, 'ERR_CREACIÓN_DOCUMENTO_REG001: Error inesperado', strtoupper($th->getMessage()), 500);
        }
    }

}

/*
PENDIENTES:
3.1.2.1
VER TASA HORARIA (Otro modulo)
3.1.2.4 
TASA HORARIA (Otro modulo)
*/
