|
|
@@ -2231,6 +2231,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(false, 'EXITO.', $programmedWorkOrders);
|
|
|
}
|
|
|
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function newUnprogrammedOrder(Request $request)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -2379,6 +2380,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(false, 'EXITO.');
|
|
|
}
|
|
|
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function getUnprogrammedVisits($idUser, $line)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -2403,19 +2405,22 @@ class PreventiveMaintenanceController extends Controller
|
|
|
'EQUI_TIPO AS TIPO_EQUIPAMIENTO',
|
|
|
'EQUI_MODE AS MODELO_EQUIPAMIENTO',
|
|
|
'EQUI_IDEQ AS ID_EQUIPAMIENTO',
|
|
|
- 'RVTN_ESTA AS ESTATUS',
|
|
|
+ 'RVTN_ESTA AS ESTADO',
|
|
|
'RVTN_USRE AS USRREG',
|
|
|
'RVTN_FERE AS FECREG',
|
|
|
- 'RVTN_UARE AS USAURE',
|
|
|
- 'RVTN_FARE AS FEAURE',
|
|
|
- 'RVTN_USCA AS USRCAN',
|
|
|
- 'RVTN_FECA AS FECCAN',
|
|
|
- 'RVTN_USFI AS USRFIN',
|
|
|
- 'RVTN_FEFI AS FECFIN',
|
|
|
- 'RVTN_USMO AS USRMOD',
|
|
|
'RVTN_FEMO AS FECMOD',
|
|
|
+ 'RVTN_PRIO AS PRIORIDAD',
|
|
|
+ 'RVTN_DEIN AS DESCRIPCION',
|
|
|
+ 'RVTN_TIAC AS TIPO_ACTIVACION',
|
|
|
+ 'usrReg.USUA_NOMB AS USRREG_NOMB',
|
|
|
+ 'usrReg.USUA_APPA AS USRREG_APPA',
|
|
|
+ 'usrReg.USUA_APMA AS USRREG_APMA'
|
|
|
])->where('RVTN_NULI', '=', $line)
|
|
|
->join('S002V01TEQUI', 'EQUI_COEQ', '=', 'RVTN_EQRE')
|
|
|
+ ->leftJoin('S002V01TUSUA as usrReg', function ($join) {
|
|
|
+ $join->on('usrReg.USUA_IDUS', '=', 'S002V01TRVTN.RVTN_USRE')
|
|
|
+ ->on('usrReg.USUA_NULI', '=', 'S002V01TRVTN.RVTN_NULI');
|
|
|
+ })
|
|
|
->orderBy('RVTN_IDVI', 'desc')->get()->all();
|
|
|
|
|
|
foreach ($visits as $visit) {
|
|
|
@@ -2423,19 +2428,12 @@ class PreventiveMaintenanceController extends Controller
|
|
|
$visit->EQUIPAMIENTO = $this->encryptionController->encrypt($visit->EQUIPAMIENTO);
|
|
|
$visit->ID_EQUIPAMIENTO = $this->encryptionController->encrypt($visit->ID_EQUIPAMIENTO);
|
|
|
|
|
|
- switch ($visit->ESTATUS) {
|
|
|
- case 'P':
|
|
|
- $usrReg = DB::table('S002V01TUSUA')->where([
|
|
|
- ['USUA_NULI', '=', $line],
|
|
|
- ['USUA_IDUS', '=', $visit->USRREG]
|
|
|
- ])->first();
|
|
|
-
|
|
|
- $nameReg = $this->functionsController->joinName($usrReg->USUA_NOMB, $usrReg->USUA_APPA, $usrReg->USUA_APMA);
|
|
|
- $nameReg .= " (" . $visit->USRREG . ")";
|
|
|
-
|
|
|
- $visit->USRREG = $nameReg;
|
|
|
- break;
|
|
|
+ $nameReg = $this->functionsController->joinName($visit->USRREG_NOMB, $visit->USRREG_APPA, $visit->USRREG_APMA);
|
|
|
+ if (!empty($nameReg)) {
|
|
|
+ $visit->USRREG = trim((string) $nameReg) . " (" . $visit->USRREG . ")";
|
|
|
}
|
|
|
+
|
|
|
+ unset($visit->USRREG_NOMB, $visit->USRREG_APPA, $visit->USRREG_APMA);
|
|
|
}
|
|
|
|
|
|
$now = $this->functionsController->now();
|
|
|
@@ -2459,6 +2457,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(false, 'EXITO.', $visits);
|
|
|
}
|
|
|
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function getUnprogrammedVisit($idVisit, $idUser, $line)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -2616,16 +2615,21 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(false, 'EXITO.', $visit);
|
|
|
}
|
|
|
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function updateVisitStatus(Request $request)
|
|
|
{
|
|
|
+ Log::info($request->all());
|
|
|
DB::enableQueryLog();
|
|
|
|
|
|
+ // RVTN_ESTA enum: 'VA','EP','CP','CE','P','C','R','A','F'
|
|
|
+ // VA, EP, CP, CE: Solo para RVTN_TIAC='A' (Automática)
|
|
|
+ // P, C, R, A, F: Solo para RVTN_TIAC='M' (Manual)
|
|
|
$validator = Validator::make($request->all(), [
|
|
|
'id_user' => 'required|string',
|
|
|
'linea' => 'required|integer',
|
|
|
'id_visit' => 'required|string',
|
|
|
'comments' => 'required|string|min:35',
|
|
|
- 'status' => 'required|string|in:C,R,A,F'
|
|
|
+ 'status' => 'required|string|in:VA,EP,CP,CE,P,C,R,A,F'
|
|
|
]);
|
|
|
|
|
|
if ($validator->fails()) {
|
|
|
@@ -2664,6 +2668,18 @@ class PreventiveMaintenanceController extends Controller
|
|
|
['RVTN_IDVI', '=', $idVisit],
|
|
|
])->first();
|
|
|
|
|
|
+ // Validar que el estado solicitado corresponda al tipo de activación
|
|
|
+ $automaticStates = ['VA', 'EP', 'CP', 'CE'];
|
|
|
+ $manualStates = ['P', 'C', 'R', 'A', 'F'];
|
|
|
+ $isRequestedStateAutomatic = in_array($form['status'], $automaticStates);
|
|
|
+ $isRequestedStateManual = in_array($form['status'], $manualStates);
|
|
|
+
|
|
|
+ if (($visit->RVTN_TIAC === 'A' && !$isRequestedStateAutomatic) ||
|
|
|
+ ($visit->RVTN_TIAC === 'M' && !$isRequestedStateManual)
|
|
|
+ ) {
|
|
|
+ return $this->responseController->makeResponse(true, "El estado {$form['status']} no corresponde al tipo de activación de la visita.", [], 400);
|
|
|
+ }
|
|
|
+
|
|
|
$commentsArr = json_decode($visit->RVTN_COME, true);
|
|
|
$commentsArr["C$form[status]"] = $form['comments'];
|
|
|
$commentsStr = json_encode($commentsArr);
|
|
|
@@ -2678,19 +2694,24 @@ class PreventiveMaintenanceController extends Controller
|
|
|
'RVTN_FEMO' => $nowStr,
|
|
|
];
|
|
|
|
|
|
- if ($form['status'] == 'A' || $form['status'] == 'R') {
|
|
|
+ // Estados automáticos: VA, EP, CP, CE
|
|
|
+ if (in_array($form['status'], ['VA', 'EP', 'CP', 'CE'])) {
|
|
|
$updateArr['RVTN_UARE'] = $idUser;
|
|
|
$updateArr['RVTN_FARE'] = $nowStr;
|
|
|
}
|
|
|
|
|
|
- if ($form['status'] == 'F') {
|
|
|
- $updateArr['RVTN_USFI'] = $idUser;
|
|
|
- $updateArr['RVTN_FEFI'] = $nowStr;
|
|
|
- }
|
|
|
-
|
|
|
- if ($form['status'] == 'C') {
|
|
|
+ // Estados manuales
|
|
|
+ if ($form['status'] == 'P') {
|
|
|
+ // Pendiente - Ya registrado en creación
|
|
|
+ } elseif ($form['status'] == 'C') {
|
|
|
$updateArr['RVTN_USCA'] = $idUser;
|
|
|
$updateArr['RVTN_FECA'] = $nowStr;
|
|
|
+ } elseif ($form['status'] == 'R' || $form['status'] == 'A') {
|
|
|
+ $updateArr['RVTN_UARE'] = $idUser;
|
|
|
+ $updateArr['RVTN_FARE'] = $nowStr;
|
|
|
+ } elseif ($form['status'] == 'F') {
|
|
|
+ $updateArr['RVTN_USFI'] = $idUser;
|
|
|
+ $updateArr['RVTN_FEFI'] = $nowStr;
|
|
|
}
|
|
|
|
|
|
DB::table('S002V01TRVTN')->where([
|
|
|
@@ -4786,6 +4807,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
$this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $line);
|
|
|
return $this->responseController->makeResponse(false, 'EXITO.', $workOrders);
|
|
|
}
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function getVisit($idVisit, $idUser, $line)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -4918,12 +4940,19 @@ class PreventiveMaintenanceController extends Controller
|
|
|
$activationTypes = ['M' => 'Manual', 'A' => 'Automática'];
|
|
|
$visit->TIPO_ACTIVACION = $activationTypes[$visit->TIPO_ACTIVACION];
|
|
|
|
|
|
- // Mapear ESTADO
|
|
|
+ // Mapear ESTADO (RVTN_ESTA enum: 'VA','EP','CP','CE','P','C','R','A','F')
|
|
|
+ // VA, EP, CP, CE: Solo para RVTN_TIAC='A' (Automática)
|
|
|
+ // P, C, R, A, F: Solo para RVTN_TIAC='M' (Manual)
|
|
|
$orderStates = [
|
|
|
- 'VA' => 'Validado',
|
|
|
- 'EP' => 'En progreso',
|
|
|
- 'CP' => 'Cerrado pendiente',
|
|
|
- 'CE' => 'Cerrado',
|
|
|
+ 'VA' => 'Validado', // Automática
|
|
|
+ 'EP' => 'En progreso', // Automática
|
|
|
+ 'CP' => 'Cerrado pendiente', // Automática
|
|
|
+ 'CE' => 'Cerrado', // Automática
|
|
|
+ 'P' => 'Pendiente', // Manual
|
|
|
+ 'C' => 'Cancelado', // Manual
|
|
|
+ 'R' => 'Rechazado', // Manual
|
|
|
+ 'A' => 'Aprobado', // Manual
|
|
|
+ 'F' => 'Finalizado', // Manual
|
|
|
];
|
|
|
$visit->ESTADO = $orderStates[$visit->ESTADO];
|
|
|
|
|
|
@@ -4957,6 +4986,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(false, 'EXITO.', $visit);
|
|
|
}
|
|
|
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function assignOperariosToPreventiveVisit(Request $request)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -5044,6 +5074,49 @@ class PreventiveMaintenanceController extends Controller
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Validación de cupo global (basado en RVTN_PEIN)
|
|
|
+ $planilla = json_decode($visit->RVTN_PEIN, true);
|
|
|
+ $cupoRequerido = 0;
|
|
|
+ if (!empty($planilla) && is_array($planilla)) {
|
|
|
+ foreach ($planilla as $pe) {
|
|
|
+ $cupoRequerido += intval($pe['CANT'] ?? 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Obtener último VA
|
|
|
+ $statusHistoryArr = json_decode($visit->RVTN_HIES, true);
|
|
|
+ $vaObj = null;
|
|
|
+ if (!empty($statusHistoryArr)) {
|
|
|
+ for ($i = count($statusHistoryArr) - 1; $i >= 0; $i--) {
|
|
|
+ if ($statusHistoryArr[$i]['ESTADO'] == 'VA') {
|
|
|
+ $vaObj = $statusHistoryArr[$i];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $atencionActual = $vaObj && array_key_exists('ATENCION', $vaObj) ? $vaObj['ATENCION'] : [];
|
|
|
+ $aceptadosActual = 0;
|
|
|
+ foreach ($atencionActual as $itm) {
|
|
|
+ if (($itm['RESPUESTA'] ?? '') === 'A') $aceptadosActual++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($cupoRequerido > 0 && $aceptadosActual >= $cupoRequerido) {
|
|
|
+ return $this->responseController->makeResponse(true, 'La planilla ya está completa. No se pueden asignar más operarios.', [], 401);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Evitar invitación duplicada al mismo operario (ya invitado o ya respondió)
|
|
|
+ $yaInvitados = [];
|
|
|
+ foreach ($atencionActual as $itm) {
|
|
|
+ $yaInvitados[$itm['ID']] = $itm['RESPUESTA'] ?? '';
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach ($audience as $opId) {
|
|
|
+ if (array_key_exists($opId, $yaInvitados)) {
|
|
|
+ return $this->responseController->makeResponse(true, "El operario $opId ya fue invitado o respondió anteriormente.", [], 401);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// Iniciar transacción
|
|
|
DB::beginTransaction();
|
|
|
|
|
|
@@ -5087,6 +5160,26 @@ class PreventiveMaintenanceController extends Controller
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Revalidar cupo justo antes de insertar (concurrencia)
|
|
|
+ $vaObjRef = null;
|
|
|
+ if (!empty($statusHistoryArr)) {
|
|
|
+ for ($i = count($statusHistoryArr) - 1; $i >= 0; $i--) {
|
|
|
+ if ($statusHistoryArr[$i]['ESTADO'] == 'VA') {
|
|
|
+ $vaObjRef = $statusHistoryArr[$i];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $atencionRef = $vaObjRef && array_key_exists('ATENCION', $vaObjRef) ? $vaObjRef['ATENCION'] : [];
|
|
|
+ $aceptadosRef = 0;
|
|
|
+ foreach ($atencionRef as $itm) {
|
|
|
+ if (($itm['RESPUESTA'] ?? '') === 'A') $aceptadosRef++;
|
|
|
+ }
|
|
|
+ if ($cupoRequerido > 0 && $aceptadosRef >= $cupoRequerido) {
|
|
|
+ DB::rollBack();
|
|
|
+ return $this->responseController->makeResponse(true, 'La planilla ya está completa. No se pueden asignar más operarios.', [], 401);
|
|
|
+ }
|
|
|
+
|
|
|
// Crear nuevas invitaciones
|
|
|
$newInvitations = [];
|
|
|
foreach ($audience as $operarioId) {
|
|
|
@@ -5171,6 +5264,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function getVisitAttendance($idVisit, $idUser, $line)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -5225,6 +5319,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(false, 'EXITO', $attendanceAux);
|
|
|
}
|
|
|
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function getVisitStaff($idVisit, $idUser, $line)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -5331,6 +5426,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
|
|
|
return $this->responseController->makeResponse(false, 'EXITO', $staffArr);
|
|
|
}
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function getVisitStatusHistory($idOrder, $idUser, $line)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -5365,15 +5461,19 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(true, 'La visita solicitada no está registrada.', [], 404);
|
|
|
}
|
|
|
|
|
|
+ // RVTN_ESTA enum: 'VA','EP','CP','CE','P','C','R','A','F'
|
|
|
+ // VA, EP, CP, CE: Solo para RVTN_TIAC='A' (Automática)
|
|
|
+ // P, C, R, A, F: Solo para RVTN_TIAC='M' (Manual)
|
|
|
$visitStates = [
|
|
|
- 'PE' => 'Pendiente',
|
|
|
- 'VA' => 'Validado',
|
|
|
- 'RE' => 'Rechazado',
|
|
|
- 'EP' => 'En progreso',
|
|
|
- 'CE' => 'Cerrado',
|
|
|
- 'CP' => 'Cerrado pendiente',
|
|
|
- 'CA' => 'Cancelado',
|
|
|
- 'EL' => 'Eliminado'
|
|
|
+ 'VA' => 'Validado', // Automática
|
|
|
+ 'EP' => 'En progreso', // Automática
|
|
|
+ 'CP' => 'Cerrado pendiente', // Automática
|
|
|
+ 'CE' => 'Cerrado', // Automática
|
|
|
+ 'P' => 'Pendiente', // Manual
|
|
|
+ 'C' => 'Cancelado', // Manual
|
|
|
+ 'R' => 'Rechazado', // Manual
|
|
|
+ 'A' => 'Aprobado', // Manual
|
|
|
+ 'F' => 'Finalizado', // Manual
|
|
|
];
|
|
|
|
|
|
$statusHistoryArr = json_decode($visit->HISTORIAL, true);
|
|
|
@@ -5415,6 +5515,7 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(false, 'EXITO.', $statusHistoryArr);
|
|
|
}
|
|
|
|
|
|
+ // Visitas técnicas no programadas (Preventivas)
|
|
|
public function attendPreventiveVisit(Request $request)
|
|
|
{
|
|
|
DB::enableQueryLog();
|
|
|
@@ -5475,6 +5576,15 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(true, 'La cadena de comentarios tiene una longitud menor a 10 caracteres.', [], 400);
|
|
|
}
|
|
|
|
|
|
+ // Cupo global requerido (RVTN_PEIN)
|
|
|
+ $planilla = json_decode($visit->RVTN_PEIN, true);
|
|
|
+ $cupoRequerido = 0;
|
|
|
+ if (!empty($planilla) && is_array($planilla)) {
|
|
|
+ foreach ($planilla as $pe) {
|
|
|
+ $cupoRequerido += intval($pe['CANT'] ?? 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// Obtener historial de estados
|
|
|
$statusHistoryArr = json_decode($visit->RVTN_HIES, true);
|
|
|
|
|
|
@@ -5511,6 +5621,15 @@ class PreventiveMaintenanceController extends Controller
|
|
|
return $this->responseController->makeResponse(true, "Ya ha $respuestaAnterior esta invitación.", [], 401);
|
|
|
}
|
|
|
|
|
|
+ // Bloquear aceptación si la planilla ya está completa (con base en aceptados actuales)
|
|
|
+ $aceptadosActual = 0;
|
|
|
+ foreach ($atencionArr as $itm) {
|
|
|
+ if (($itm['RESPUESTA'] ?? '') === 'A') $aceptadosActual++;
|
|
|
+ }
|
|
|
+ if ($form['attendance'] == 'A' && $cupoRequerido > 0 && $aceptadosActual >= $cupoRequerido) {
|
|
|
+ return $this->responseController->makeResponse(true, 'La planilla ya está completa. No es posible aceptar esta invitación.', [], 401);
|
|
|
+ }
|
|
|
+
|
|
|
// Iniciar transacción
|
|
|
DB::beginTransaction();
|
|
|
|
|
|
@@ -5602,6 +5721,30 @@ class PreventiveMaintenanceController extends Controller
|
|
|
$comments = $form['data'];
|
|
|
}
|
|
|
|
|
|
+ // Última verificación de cupo (concurrencia) antes de confirmar respuesta
|
|
|
+ $statusHistoryCheck = json_decode(DB::table('S002V01TRVTN')->where([
|
|
|
+ ['RVTN_NULI', '=', $form['linea']],
|
|
|
+ ['RVTN_IDVI', '=', $idVisit]
|
|
|
+ ])->value('RVTN_HIES'), true);
|
|
|
+ $vaObjChk = null;
|
|
|
+ if (!empty($statusHistoryCheck)) {
|
|
|
+ for ($i = count($statusHistoryCheck) - 1; $i >= 0; $i--) {
|
|
|
+ if ($statusHistoryCheck[$i]['ESTADO'] == 'VA') {
|
|
|
+ $vaObjChk = $statusHistoryCheck[$i];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $aceptadosChk = 0;
|
|
|
+ $atencionChk = $vaObjChk && array_key_exists('ATENCION', $vaObjChk) ? $vaObjChk['ATENCION'] : [];
|
|
|
+ foreach ($atencionChk as $itm) {
|
|
|
+ if (($itm['RESPUESTA'] ?? '') === 'A') $aceptadosChk++;
|
|
|
+ }
|
|
|
+ if ($form['attendance'] == 'A' && $cupoRequerido > 0 && $aceptadosChk >= $cupoRequerido) {
|
|
|
+ DB::rollBack();
|
|
|
+ return $this->responseController->makeResponse(true, 'La planilla ya está completa. No es posible aceptar esta invitación.', [], 401);
|
|
|
+ }
|
|
|
+
|
|
|
// Actualizar el objeto en ATENCION
|
|
|
$statusHistoryArr[$vaStatusIndex]['ATENCION'][$operatorIndex]['RESPUESTA'] = $form['attendance'];
|
|
|
$statusHistoryArr[$vaStatusIndex]['ATENCION'][$operatorIndex]['FIRMA'] = $signature;
|