Explorar o código

Actualización mantenimiento correctivo

Jose Brito hai 2 semanas
pai
achega
4498cd0848

+ 690 - 15
sistema-mantenimiento-back/app/Http/Controllers/CorrectiveMaintenanceController.php

@@ -337,7 +337,7 @@ class CorrectiveMaintenanceController extends Controller{
                 'FUNCION' => 'openCorrectiveWorkOrderDetails',
                 'PARAMETROS' => json_encode([$this->encryptionController->encrypt($orderID)])
             ], [
-                'BOTON' => 'Validar orden',
+                'BOTON' => 'Asignar orden',
                 'FUNCION' => 'validateCorrectiveWorkOrder',
                 'PARAMETROS' => json_encode([$this->encryptionController->encrypt($orderID)])
             ], [
@@ -520,6 +520,7 @@ class CorrectiveMaintenanceController extends Controller{
             'OTCO_CLAS AS CLASIFICACION',
             'OTCO_COME AS COMENTARIOS',
             'OTCO_GESE AS GERENCIA_SEGURIDAD',
+            'OTCO_HIES AS HISTORIAL_ESTATUS',
             'OTCO_CAEX AS CAMPOS_EXTRA',
             'OTCO_ESOR AS ESTADO',
             'OTCO_USRE AS USUREG',
@@ -1186,14 +1187,12 @@ class CorrectiveMaintenanceController extends Controller{
             $idOrder,
             'Correctivo'
         );
-        var_dump($audience);
-        exit;
 
         $now = $this->functionsController->now();
         $nowStr = $now->toDateTimeString();
 
         $statusHistoryArr = json_decode($order->OTCO_HIES, true);
-        $statusHistoryArr[] = ['USUARIO' => $idUser, 'ESTADO' => 'VA', 'FECHA' => $nowStr];
+        $statusHistoryArr[] = ['USUARIO' => $idUser, 'ESTADO' => 'VA', 'FECHA' => $nowStr, 'PERSONAL' => $audience];
         $statusHistoryStr = json_encode($statusHistoryArr);
 
         DB::table('S002V01TOTCO')->where([
@@ -1225,6 +1224,172 @@ class CorrectiveMaintenanceController extends Controller{
         return $this->responseController->makeResponse(false, 'EXITO.');
     }
 
+    public function updateApprovedWorkOrder(Request $request) {
+        DB::enableQueryLog();
+        $validator = Validator::make($request->all(), [
+            'id_user' => 'required|string',
+            'linea' => 'required|integer',
+            'id_order' => 'required|string',
+            'config' => 'required|json',
+        ]);
+ 
+        if($validator->fails()){
+            return $this->responseController->makeResponse(
+                true,
+                "Se encontraron uno o más errores.",
+                $this->responseController->makeErrors(
+                    $validator->errors()->messages()
+                ),
+                401
+            );
+        }
+
+        $form = $request->all();
+        $idUser = $this->encryptionController->decrypt($form['id_user']);
+        if(!$idUser){
+            return $this->responseController->makeResponse(true, 'El ID de usuario no fue encriptado correctamente.', [], 400);
+        }
+
+        $usr = DB::table('S002V01TUSUA')->where([
+            ['USUA_NULI', '=', $form['linea']],
+            ['USUA_IDUS', '=', $idUser]
+        ])->first();
+        
+        if(is_null($usr)){
+            return $this->responseController->makeResponse(true, 'El usuario que realizó la petición no existe.', [], 404);
+        }
+
+        $idOrder = $this->encryptionController->decrypt($form['id_order']);
+        if(!$idOrder){
+            return $this->responseController->makeResponse(true, 'El ID de la orden no fue encriptado correctamente.', [], 400);
+        }
+
+        $order = DB::table('S002V01TOTCO')->where([
+            ['OTCO_NULI', '=', $form['linea']],
+            ['OTCO_IDOT', '=', $idOrder]
+        ])->first();
+        
+        if(is_null($order)){
+            return $this->responseController->makeResponse(true, 'La orden solicitada no existe.', [], 404);
+        }else if($order->OTCO_ESOR == 'EL'){
+            return $this->responseController->makeResponse(true, 'La orden solicitada está eliminada.', [], 404);
+        }else if($order->OTCO_ESOR != 'VA'){
+            return $this->responseController->makeResponse(true, "La orden noo está validada.", [], 401);
+        }
+
+        $staffConfigArr = json_decode($form['config'], true);
+        $audience = [];
+        foreach($staffConfigArr as $key=>$val){
+            if(!array_key_exists('SPECIALTY', $val) || !array_key_exists('STAFF', $val)){
+                return $this->responseController->makeResponse(true, "El item $key del arreglo de configuración de operarios tiene un formato inválido.", [], 400);
+            }
+
+            $specialtyDec = $this->encryptionController->decrypt($val['SPECIALTY']);
+            if(!$specialtyDec){
+                return $this->responseController->makeResponse(true, "El identificador de la especialidad en el item $key del arreglo de configuración de operarios no fue encriptado correctamente.", [], 400);
+            }
+
+            if(gettype($val['STAFF']) != 'array'){
+                return $this->responseController->makeResponse(true, "El contenedor de oerarios en el item $key del arreglo de configuración de operarios es inválido-.", [], 400);
+            }
+
+            foreach($val['STAFF'] as $key0=>$val0){
+                if(!array_key_exists('ID', $val0) || !array_key_exists('TYPE', $val0)){
+                    return $this->responseController->makeResponse(true, "El item $key del arreglo de configuración de operarios tiene un formato inválido.", [], 400);
+                }
+
+                $idDec = $this->encryptionController->decrypt($val0['ID']);
+                $employee = DB::table('S002V01TPERS')->where([
+                    ['PERS_NULI', '=', $form['linea']],
+                    ['PERS_IDPE', '=', $idDec]
+                ])->first();
+
+                if(is_null($employee)){
+                    return $this->responseController->makeResponse(true, "El perario $key0 de la especialidad $specialtyDec del arreglo de configuración de operarios tiene un formato inválido.", [], 404);
+                }
+
+                $audience[] = $employee->PERS_IDUS;
+            }
+        }
+
+        $statusHistoryArr = json_decode($order->OTCO_HIES, true);
+        $statusApprovedFilt = array_filter($statusHistoryArr, function($v, $k) {
+            return $v['ESTADO'] == 'VA';
+        }, ARRAY_FILTER_USE_BOTH);
+
+        $keysFiltered = array_keys($statusApprovedFilt);
+        $approvedKey = end($keysFiltered);
+        $statusApproved = $statusApprovedFilt[$approvedKey];
+        $staff = $statusApproved['PERSONAL'];
+        $newAudience = [];
+
+        foreach($audience as $item){
+            if(!in_array($item, $staff)){
+                $newAudience[] = $item;
+                $staff[] = $item;
+            }
+        }
+
+        $statusApproved['PERSONAL'] = $staff;
+        $statusHistoryArr[$approvedKey] = $statusApproved;
+        $statusHistoryStr = json_encode($statusHistoryArr);
+
+        $this->notificationsController->emitNotification(
+            'S002V01M09GMCO',
+            "Orden de mantenimiento correctivo #$idOrder",
+            "Se ha generado la orden de mantenimiento correctivo #$idOrder y requiere su atención.",
+            [[
+                'BOTON' => 'Ver detalles',
+                'FUNCION' => 'openCorrectiveWorkOrderDetails',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt($idOrder)])
+            ], [
+                'BOTON' => 'Atender orden',
+                'FUNCION' => 'attendCorrectiveWorkOrder',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt($idOrder)])
+            ], [
+                'BOTON' => 'Ir al módulo',
+                'FUNCION' => 'openModule',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt('GMCO/ORTR/GEOP')])
+            ]],
+            $newAudience,
+            $idUser, 
+            $form['linea'],
+            $this->getSocketClient(),
+            $idOrder,
+            'Correctivo'
+        );
+
+        $now = $this->functionsController->now();
+        $nowStr = $now->toDateTimeString();
+        DB::table('S002V01TOTCO')->where([
+            ['OTCO_IDOT', '=', $idOrder],
+            ['OTCO_NULI', '=', $form['linea']]
+        ])->update([
+            'OTCO_ESOR' => 'VA',
+            'OTCO_HIES' => $statusHistoryStr,
+            'OTCO_USMO' => $idUser,
+            'OTCO_FEMO' => $nowStr,
+        ]);
+
+        $actions = DB::getQueryLog();
+        $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
+        
+        $idac = $this->functionsController->registerActivity(
+            $form['linea'],
+            'S002V01M09GMCO',
+            'S002V01F04GEOT',
+            'S002V01P01GEOT',
+            'Actualización',
+            "El usuario $name (" . $usr->USUA_IDUS . ") actualizó la orden de trabajo correctivo #$idOrder.",
+            $idUser,
+            $nowStr,
+            'S002V01S01ORTR'
+        );
+
+        $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $form['linea']);
+        return $this->responseController->makeResponse(false, 'EXITO.');
+    }
+
     public function startWorkOrder(Request $request) {
         DB::enableQueryLog();
         $validator = Validator::make($request->all(), [
@@ -1282,12 +1447,46 @@ class CorrectiveMaintenanceController extends Controller{
         }else if($order->OTCO_ESOR != 'VA'){
             $status = $orderStates[$order->OTCO_ESOR];
             return $this->responseController->makeResponse(true, "La orden está $status.", [], 401);
+        }else if($order->OTCO_IDUR != $idUser){
+            return $this->responseController->makeResponse(true, "El usuario que solicitó la acción no tiene los permisos necesarios.", [], 401);
         }
 
         $now = $this->functionsController->now();
         $nowStr = $now->toDateTimeString();
 
         $statusHistoryArr = json_decode($order->OTCO_HIES, true);
+        $validatedStatusFilt = array_filter($statusHistoryArr, function($v, $k) {
+            return $v['ESTADO'] == 'VA';
+        }, ARRAY_FILTER_USE_BOTH);
+
+        $validatedStatus = end($validatedStatusFilt);
+        $audience = [];
+
+        foreach($validatedStatus['ATENCION'] as $item){
+            if($item['RESPUESTA'] == 'A') $audience[] = $item['ID'];
+        }
+
+        $this->notificationsController->emitNotification(
+            'S002V01M09GMCO',
+            "Orden de mantenimiento correctivo #$idOrder",
+            "Inicio de la ejecución de la orden de mantenimiento #$idOrder.",
+            [[
+                'BOTON' => 'Ver detalles',
+                'FUNCION' => 'openCorrectiveWorkOrderDetails',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt($idOrder)])
+            ], [
+                'BOTON' => 'Ir al módulo',
+                'FUNCION' => 'openModule',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt('GMCO/ORTR/GEOP')])
+            ]],
+            $audience,
+            $idUser, 
+            $form['linea'],
+            $this->getSocketClient(),
+            $idOrder,
+            'Correctivo'
+        );
+
         $statusHistoryArr[] = ['USUARIO' => $idUser, 'ESTADO' => 'EP', 'FECHA' => $nowStr];
         $statusHistoryStr = json_encode($statusHistoryArr);
 
@@ -1400,20 +1599,25 @@ class CorrectiveMaintenanceController extends Controller{
             break;
         }
 
-        $message = '';
+        if($order->OTCO_ESOR == 'EP' && $status == 'CE'){
+            $status = 'CP';
+        }
+        
+        /*$message = '';
         if($status == 'CE' && is_null($order->OTCO_ANCO)){
             $status = 'CP';
             $message = 'La orden no puede cerrarse complentamente hasta asignar el análisis de costos.';
         }else{
             $message = 'Actualización correcta.';
-        }
+        }*/
 
         $now = $this->functionsController->now();
         $nowStr = $now->toDateTimeString();
 
         $ftin = null;
         $dtin = null;
-        if(($status == 'CE' || $status == 'CP') && is_null($order->OTCO_FTIN)){
+        //if(($status == 'CE' || $status == 'CP') && is_null($order->OTCO_FTIN)){
+        if($status == 'CP' && is_null($order->OTCO_FTIN)){
             $ftin = $nowStr;
             $startDate = new Carbon($order->OTCO_FIFA);
 
@@ -1426,6 +1630,46 @@ class CorrectiveMaintenanceController extends Controller{
         }
 
         $statusHistoryArr = json_decode($order->OTCO_HIES, true);
+        $validatedStatusFilt = array_filter($statusHistoryArr, function($v, $k) {
+            return $v['ESTADO'] == 'VA';
+        }, ARRAY_FILTER_USE_BOTH);
+
+        $validatedStatus = end($validatedStatusFilt);
+        $attendance = $validatedStatus['ATENCION'];
+        $enabledUsersToClose = [];
+
+        foreach($attendance as $item){
+            if($item['RESPUESTA'] == 'A') $enabledUsersToClose[] = $item['ID'];
+        }
+
+        if(!in_array($idUser, $enabledUsersToClose)){
+            return $this->responseController->makeResponse(true, 'El usuario que solicitó la acción no tiene los permisos necesarios.', [], 401);
+        }
+
+        $closeUserName = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
+        $audience = [$order->OTCO_IDUR];
+
+        $this->notificationsController->emitNotification(
+            'S002V01M09GMCO',
+            "Orden de mantenimiento correctivo #$idOrder",
+            "El usuario $closeUserName ($idUser) cerró la orden de mantenimiento #$idOrder con los siguientes comentarios: $form[comments].",
+            [[
+                'BOTON' => 'Ver detalles',
+                'FUNCION' => 'openCorrectiveWorkOrderDetails',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt($idOrder)])
+            ], [
+                'BOTON' => 'Ir al módulo',
+                'FUNCION' => 'openModule',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt('GMCO/ORTR/GEOP')])
+            ]],
+            $audience,
+            $idUser, 
+            $form['linea'],
+            $this->getSocketClient(),
+            $idOrder,
+            'Correctivo'
+        );
+
         $statusHistoryArr[] = ['USUARIO' => $idUser, 'ESTADO' => $status, 'FECHA' => $nowStr];
         $statusHistoryStr = json_encode($statusHistoryArr);
 
@@ -1458,7 +1702,125 @@ class CorrectiveMaintenanceController extends Controller{
         );
 
         $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $form['linea']);
-        return $this->responseController->makeResponse(false, "EXITO: $message");
+        return $this->responseController->makeResponse(false, "EXITO");
+    }
+
+    public function closeWorkOrder(Request $request) {
+        DB::enableQueryLog();
+        $validator = Validator::make($request->all(), [
+            'id_user' => 'required|string',
+            'linea' => 'required|integer',
+            'id_order' => 'required|string',
+        ]);
+ 
+        if($validator->fails()){
+            return $this->responseController->makeResponse(
+                true,
+                "Se encontraron uno o más errores.",
+                $this->responseController->makeErrors(
+                    $validator->errors()->messages()
+                ),
+                401
+            );
+        }
+
+        $form = $request->all();
+        $idUser = $this->encryptionController->decrypt($form['id_user']);
+        if(!$idUser){
+            return $this->responseController->makeResponse(true, 'El ID de usuario no fue encriptado correctamente.', [], 400);
+        }
+
+        $usr = DB::table('S002V01TUSUA')->where([
+            ['USUA_NULI', '=', $form['linea']],
+            ['USUA_IDUS', '=', $idUser]
+        ])->first();
+        
+        if(is_null($usr)){
+            return $this->responseController->makeResponse(true, 'El usuario que realizó la petición no existe.', [], 404);
+        }
+
+        $idOrder = $this->encryptionController->decrypt($form['id_order']);
+        if(!$idOrder){
+            return $this->responseController->makeResponse(true, 'El ID de la orden no fue encriptado correctamente.', [], 400);
+        }
+
+        $order = DB::table('S002V01TOTCO')->where([
+            ['OTCO_NULI', '=', $form['linea']],
+            ['OTCO_IDOT', '=', $idOrder]
+        ])->first();
+        
+        $orderStates = [
+            'PE' => 'Pendiente',   'VA' => 'Validado', 'RE' => 'Rechazado', 
+            'EP' => 'En progreso', 'CE' => 'Cerrado',  'CP' => 'Cerrado pendiente',
+            'CA' => 'Cancelado',   'EL' => 'Eliminado'
+        ];
+        
+        if(is_null($order)){
+            return $this->responseController->makeResponse(true, 'La orden solicitada no existe.', [], 404);
+        }else if($order->OTCO_ESOR == 'EL'){
+            return $this->responseController->makeResponse(true, 'La orden solicitada está eliminada.', [], 404);
+        }else if($idUser != $order->OTCO_IDUR){
+            return $this->responseController->makeResponse(true, 'El usuario que solicitó la acción no tiene los permisos necesarios.', [], 401);
+        }
+        
+        $status = 'CE';
+        $now = $this->functionsController->now();
+        $nowStr = $now->toDateTimeString();
+
+        $closeUserName = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
+        $audience = [$order->OTCO_USRE];
+
+        $this->notificationsController->emitNotification(
+            'S002V01M09GMCO',
+            "Orden de mantenimiento correctivo #$idOrder",
+            "El usuario $closeUserName ($idUser) validó el cierre la orden de mantenimiento #$idOrder.",
+            [[
+                'BOTON' => 'Ver detalles',
+                'FUNCION' => 'openCorrectiveWorkOrderDetails',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt($idOrder)])
+            ], [
+                'BOTON' => 'Ir al módulo',
+                'FUNCION' => 'openModule',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt('GMCO/ORTR/GEOP')])
+            ]],
+            $audience,
+            $idUser, 
+            $form['linea'],
+            $this->getSocketClient(),
+            $idOrder,
+            'Correctivo'
+        );
+
+        $statusHistoryArr[] = ['USUARIO' => $idUser, 'ESTADO' => $status, 'FECHA' => $nowStr];
+        $statusHistoryStr = json_encode($statusHistoryArr);
+
+        DB::table('S002V01TOTCO')->where([
+            ['OTCO_IDOT', '=', $idOrder],
+            ['OTCO_NULI', '=', $form['linea']]
+        ])->update([
+            'OTCO_ESOR' => $status,
+            'OTCO_HIES' => $statusHistoryStr,
+            'OTCO_USMO' => $idUser,
+            'OTCO_FEMO' => $nowStr,
+        ]);
+
+        $actions = DB::getQueryLog();
+        $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
+        
+        $idac = $this->functionsController->registerActivity(
+            $form['linea'],
+            'S002V01M09GMCO',
+            'S002V01F04GEOT',
+            'S002V01P01GEOT',
+            'Actualización',
+            "El usuario $name (" . $usr->USUA_IDUS . ") actualizó el estado de la orden de trabajo correctivo #$idOrder.",
+            $idUser,
+            $nowStr,
+            'S002V01S01ORTR'
+        );
+
+        $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $form['linea']);
+        return $this->responseController->makeResponse(false, "EXITO");
     }
 
     public function getWorkOrderClasifications($idUser, $line) {
@@ -2516,8 +2878,10 @@ class CorrectiveMaintenanceController extends Controller{
                     ['PERS_IDPE', '=', $register->BLOQUEADO]
                 ])->join('S002V01TUSUA', 'USUA_IDUS', '=', 'PERS_IDUS')->first();
 
-                $employeeName = $this->functionsController->joinName($employee->USUA_NOMB, $employee->USUA_APPA, $employee->USUA_APMA);
-                $register->BLOQUEADO = $employeeName . " (" . $register->BLOQUEADO . ")";
+                if(!is_null($employee)){
+                    $employeeName = $this->functionsController->joinName($employee->USUA_NOMB, $employee->USUA_APPA, $employee->USUA_APMA);
+                    $register->BLOQUEADO = $employeeName . " (" . $register->BLOQUEADO . ")";
+                }
             }
 
             $usrReg = DB::table('S002V01TUSUA')->where([
@@ -2525,8 +2889,10 @@ class CorrectiveMaintenanceController extends Controller{
                 ['USUA_IDUS', '=', $register->USUREG]
             ])->first();
 
-            $usrRegName = $this->functionsController->joinName($usrReg->USUA_NOMB, $usrReg->USUA_APPA, $usrReg->USUA_APMA);
-            $register->USUREG = $usrRegName . " (" . $register->USUREG . ")";
+            if(!is_null($usrReg)){
+                $usrRegName = $this->functionsController->joinName($usrReg->USUA_NOMB, $usrReg->USUA_APPA, $usrReg->USUA_APMA);
+                $register->USUREG = $usrRegName . " (" . $register->USUREG . ")";
+            }
 
             if(!is_null($register->USUMOD)){
                 $usrMod = DB::table('S002V01TUSUA')->where([
@@ -2534,8 +2900,10 @@ class CorrectiveMaintenanceController extends Controller{
                     ['USUA_IDUS', '=', $register->USUMOD]
                 ])->first();
 
-                $usrModName = $this->functionsController->joinName($usrMod->USUA_NOMB, $usrMod->USUA_APPA, $usrMod->USUA_APMA);
-                $register->USUMOD = $usrModName . " (" . $register->USUMOD . ")";
+                if(!is_null($usrMod)){
+                    $usrModName = $this->functionsController->joinName($usrMod->USUA_NOMB, $usrMod->USUA_APPA, $usrMod->USUA_APMA);
+                    $register->USUMOD = $usrModName . " (" . $register->USUMOD . ")";
+                }
             }
 
             $blockRegisters[$key] = $register;
@@ -5822,6 +6190,313 @@ class CorrectiveMaintenanceController extends Controller{
             $staffArrFn[$key] = $item;
         }
 
-        return $this->responseController->makeResponse(false, 'EXITO', $staffArrFn);
+        return $this->responseController->makeResponse(false, 'EXITO', $staffArr);
+    }
+
+    public function getWorkOrderAttendance($idOrder, $idUser, $line) {
+        DB::enableQueryLog();
+
+        $idUser = $this->encryptionController->decrypt($idUser);
+        if(!$idUser){
+            return $this->responseController->makeResponse(true, 'El ID del usuario que realizó la solicitud no está encriptado correctamente', [], 400);
+        }
+
+        $usr = DB::table('S002V01TUSUA')->where([
+            ['USUA_NULI', '=', $line],
+            ['USUA_IDUS', '=', $idUser],
+        ])->first();
+
+        if(is_null($usr)){
+            return $this->responseController->makeResponse(true, 'El usuario que realizó la consulta no está registrado.', [], 404);
+        }
+
+        $idOrder = $this->encryptionController->decrypt($idOrder);
+        if(!$idOrder){
+            return $this->responseController->makeResponse(true, 'El ID de la orden relacionada no está encriptado correctamente', [], 400);
+        }
+
+        $workOrder = DB::table('S002V01TOTCO')->where([
+            ['OTCO_NULI', '=', $line],
+            ['OTCO_IDOT', '=', $idOrder]
+        ])->first();
+
+        if(is_null($workOrder)){
+            return $this->responseController->makeResponse(true, 'La orden relacionada no está registrada.', [], 404);
+        }
+
+        $statusHistory = json_decode($workOrder->OTCO_HIES, true);
+        $validatedHistoryFilt = array_filter($statusHistory, function($v, $k) {
+            return $v['ESTADO'] == 'VA';
+        }, ARRAY_FILTER_USE_BOTH);
+
+        if(empty($validatedHistoryFilt)){
+            return $this->responseController->makeResponse(true, 'La orden relacionada no está en el estado de validación', [], 404);
+        }
+
+        $validatedHistory = end($validatedHistoryFilt);
+        $attendance = array_key_exists('ATENCION', $validatedHistory) ? $validatedHistory['ATENCION'] : [];
+        $attendanceAux = [];
+
+        foreach($attendance as $item){
+            if($item['RESPUESTA'] == 'A'){
+                $attendanceAux[] = $item;
+            }
+        }
+
+        return $this->responseController->makeResponse(false, 'EXITO', $attendanceAux);
+    }
+
+    public function setWorkOrderAttendance(Request $request) {
+        DB::enableQueryLog();
+        $validator = Validator::make($request->all(), [
+            'id_user' => 'required|string',
+            'linea' => 'required|integer',
+            'id_order' => 'required|string',
+            'attendance' => 'required|string|in:A,R',
+            'data' => 'required|string'
+        ]);
+ 
+        if($validator->fails()){
+            return $this->responseController->makeResponse(
+                true,
+                "Se encontraron uno o más errores.",
+                $this->responseController->makeErrors(
+                    $validator->errors()->messages()
+                ),
+                401
+            );
+        }
+
+        $form = $request->all();
+        $idUser = $this->encryptionController->decrypt($form['id_user']);
+        if(!$idUser){
+            return $this->responseController->makeResponse(true, 'El ID de usuario no fue encriptado correctamente.', [], 400);
+        }
+
+        $usr = DB::table('S002V01TUSUA')->where([
+            ['USUA_NULI', '=', $form['linea']],
+            ['USUA_IDUS', '=', $idUser]
+        ])->first();
+        
+        if(is_null($usr)){
+            return $this->responseController->makeResponse(true, 'El usuario que realizó la petición no existe.', [], 404);
+        }
+
+        $idOrder = $this->encryptionController->decrypt($form['id_order']);
+        if(!$idOrder){
+            return $this->responseController->makeResponse(true, 'El ID de la solicitud seleccionada no fue encriptado correctamente.', [], 400);
+        }
+
+        $order = DB::table('S002V01TOTCO')->where([
+            ['OTCO_NULI', '=', $form['linea']],
+            ['OTCO_IDOT', '=', $idOrder]
+        ])->first();
+        
+        if(is_null($order)){
+            return $this->responseController->makeResponse(true, 'La orden que desea actualizar no existe.', [], 404);
+        }else if($order->OTCO_ESOR != 'VA'){
+            return $this->responseController->makeResponse(true, 'La solicitud seleccionada no está validada.', [], 401);
+        }
+
+        if($form['attendance'] == 'A' && !str_contains($form['data'], 'data:image/png')){
+            return $this->responseController->makeResponse(true, 'El archivo de la firma capturada es inválido.', [], 400);
+        }else if($form['attendance'] == 'R' && strlen($form['data']) < 10){
+            return $this->responseController->makeResponse(true, 'La cadena de comentarios tiene una longitud menor a 10 caracteres.', [], 400);
+        }
+
+        $userAttendance = ["ID" => $idUser, "RESPUESTA" => $form['attendance']];
+        $signature = null;
+        $comments = null;
+
+        if($form['attendance'] == 'A'){
+            $filesPath = str_replace("app\\Http\\Controllers", "storage\\app\\files", __DIR__);
+            if(!file_exists($filesPath)){
+                return $this->responseController->makeResponse(true, 'No se encontró la ubicación de almacenamiento de archivos.', [], 400);
+            }
+
+            generateSignatureFileName:
+            $signatureFileName = $this->generateSignatureImageName();
+            $signatureFileDir = $filesPath . "\\" . $signatureFileName;
+            $signatureFileExists = file_exists($signatureFileDir);
+
+            if($signatureFileExists) goto generateSignatureFileName;
+
+            $signatureFileData = str_replace("data:image/png;base64,", "", $form['data']);
+            file_put_contents($signatureFileDir, base64_decode($signatureFileData));
+
+            $now = $this->functionsController->now();
+            $year = $now->year;
+            $month = $now->month < 10 ? "0{$now->month}" : "0{$now->month}";
+            $day = $now->day < 10 ? "0{$now->day}" : "{$now->day}";
+            $fecr = substr("$year", -2) . $month . $day;
+            $sec = DB::table('S002V01TAFAL')->where([
+                ['AFAL_COMO', '=', "GMCO"],
+                ['AFAL_CLDO', '=', "FO"],
+                ['AFAL_NULI', '=', $form['linea']],
+            ])->orderBy('AFAL_NUSE', 'desc')->first();
+
+            $nuse = 1;
+            if(!is_null($sec)){
+                $nuse = intval($sec->AFAL_NUSE) + 1;
+            }
+
+            $noar = "firma_conformidad_" . $idUser;
+            $exte = "png";
+            $ver = DB::table('S002V01TAFAL')->where([
+                ['AFAL_NULI', '=', $form['linea']],
+                ['AFAL_COMO', '=', "GMCO"],
+                ['AFAL_CLDO', '=', "FO"],
+                ['AFAL_NOAR', '=', $noar],
+                ['AFAL_EXTE', '=', $exte],
+            ])->orderBy('AFAL_NUVE', 'desc')->first();
+
+            $nuve = 1;
+            if(!is_null($ver)){
+                $nuve = intval($sec->AFAL_NUVE) + 1;
+            }
+
+            $tama = filesize($signatureFileDir);
+            $code = intval($form['linea']) < 10 ? "0$form[linea]" : "$form[linea]";
+            $code .= "-GMCO-FO-$fecr-";
+
+            for($i = strlen($nuse); $i < 6; $i++){
+                $code .= "0";
+            }
+
+            $code .= "$nuse=";
+            $code .= $nuve < 10 ? "0$nuve=" : "$nuve=";
+            $code .= "$noar.$exte";
+
+            $usac = json_encode([$idUser]);
+            $nowStr = $now->toDateTimeString();
+            DB::table('S002V01TAFAL')->insert([
+                'AFAL_NULI' => $form['linea'],
+                'AFAL_COMO' => "GMCO",
+                'AFAL_CLDO' => "FO",
+                'AFAL_FECR' => $fecr,
+                'AFAL_NUSE' => $nuse,
+                'AFAL_NUVE' => $nuve,
+                'AFAL_NOAR' => $noar,
+                'AFAL_EXTE' => $exte,
+                'AFAL_TAMA' => $tama,
+                'AFAL_UBIC' => $signatureFileDir,
+                'AFAL_USAC' => $usac,
+                'AFAL_USRE' => $idUser,
+                'AFAL_FERE' => $nowStr
+            ]);
+
+            $signature = $code;
+        }else if($form['attendance'] == 'R'){
+            $comments = $form['data'];
+        }
+
+        if(!is_null($signature) || !is_null($comments)){
+            $userAttendance['FIRMA'] = $signature;
+            $userAttendance['COMENTARIOS'] = $comments;
+            $statusHistoryArr = json_decode($order->OTCO_HIES, true);
+            $validatedHistoryFilt = array_filter($statusHistoryArr, function($v, $k) {
+                return $v['ESTADO'] == 'VA';
+            }, ARRAY_FILTER_USE_BOTH);
+
+            if(!empty($validatedHistoryFilt)){
+                $validatedHistory = end($validatedHistoryFilt);
+                $validatedHistoryKeys = array_keys($validatedHistoryFilt);
+                $validatedHistoryKey = end($validatedHistoryKeys);
+                $attendance = array_key_exists('ATENCION', $validatedHistory) ? $validatedHistory['ATENCION'] : [];
+                
+                $attendance[] = $userAttendance;
+                $validatedHistory['ATENCION'] = $attendance;
+                $statusHistoryArr[$validatedHistoryKey] = $validatedHistory;
+            }
+
+            $statusHistoryStr = json_encode($statusHistoryArr);
+            $now = $this->functionsController->now();
+            $nowStr = $now->toDateTimeString();
+
+            DB::table('S002V01TOTCO')->where([
+                ['OTCO_NULI', '=', $form['linea']],
+                ['OTCO_IDOT', '=', $idOrder]
+            ])->update([
+                "OTCO_HIES" => $statusHistoryStr,
+                "OTCO_USMO" => $idUser,
+                "OTCO_FEMO" => $nowStr,
+            ]);
+        }
+
+        $userName = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
+        $action = $form['attendance'] == 'A' ? 'aceptó' : 'rechazó';
+        $notificationActions = [];
+        if($form['attendance'] == 'A'){
+            $notificationActions[] = [
+                'BOTON' => 'Revisar firma',
+                'FUNCION' => 'reviewSignatureInCorrectiveWorkOrder',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt($idOrder), $this->encryptionController->encrypt($idUser)])
+            ];
+        }else if($form['attendance'] == 'R'){
+            $notificationActions[] = [
+                'BOTON' => 'Revisar comentarios',
+                'FUNCION' => 'reviewCommentsInCorrectiveWorkOrder',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt($idOrder), $this->encryptionController->encrypt($idUser)])
+            ];
+
+            $notificationActions[] = [
+                'BOTON' => 'Reasignar orden',
+                'FUNCION' => 'revalidateCorrectiveWorkOrder',
+                'PARAMETROS' => json_encode([$this->encryptionController->encrypt($idOrder)])
+            ];
+        }
+        
+        $notificationActions[] = [
+            'BOTON' => 'Ir al módulo',
+            'FUNCION' => 'openModule',
+            'PARAMETROS' => json_encode([$this->encryptionController->encrypt('GMCO/ORTR/GEOP')])
+        ]; 
+        
+        $this->notificationsController->emitNotification(
+            'S002V01M09GMCO',
+            "Orden de mantenimiento correctivo #$idOrder",
+            "El usuario $userName ($idUser) $action atender la orden de mantenimiento #$idOrder.",
+            $notificationActions,
+            [$order->OTCO_IDUR],
+            $idUser, 
+            $form['linea'],
+            $this->getSocketClient(),
+            $idOrder,
+            'Correctivo'
+        );
+
+        return $this->responseController->makeResponse(false, 'EXITO');
+    }
+
+    private function generateSignatureImageName(){
+        $upperLetters = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
+        $lowerLetters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
+        $numbers = ["0","1","2","3","4","5","6","7","8","9"];
+        $fileName = "";
+
+        for($i = 0; $i < 40; $i++){
+            $charTypeSelector = rand(0, 2);
+            $selectedChar = "";
+
+            switch($charTypeSelector){
+                case 0:
+                    $charSelector = rand(0, count($upperLetters) - 1);
+                    $selectedChar = $upperLetters[$charSelector];
+                break;
+                case 1:
+                    $charSelector = rand(0, count($lowerLetters) - 1);
+                    $selectedChar = $lowerLetters[$charSelector];
+                break;
+                case 2:
+                    $charSelector = rand(0, count($numbers) - 1);
+                    $selectedChar = $numbers[$charSelector];
+                break;
+            }
+
+            $selectedChar = empty($selectedChar) ? 'A' : $selectedChar;
+            $fileName .= $selectedChar;
+        }
+
+        return $fileName . '.png';
     }
 }