Browse Source

modal para visualización de detalles de orden preventiva - falta agregarle prioridad con su formateo

EmilianoOrtiz 1 week ago
parent
commit
e0346ef64f

+ 2 - 0
src/app/app.module.ts

@@ -469,6 +469,7 @@ import { CommentsViewComponent } from './components/template/notification-dialog
 import { AgreeOrderComponent } from './components/template/notification-dialog/agree-order/agree-order.component';
 import { SignaturePadComponent } from './components/template/notification-dialog/signature-pad/signature-pad.component';
 import { ValidateApplicationsModalComponent } from './components/template/notification-dialog/validate-applications-modal/validate-applications-modal.component';
+import { PreventiveOrderDetailsComponent } from './components/preventive-maintenance/preventive-order-details/preventive-order-details.component';
 import { SignaturePadModule } from 'angular-signature-pad-v2';
 import { MultipleSerialNumbersComponent } from './components/resources/multiple-serial-numbers/multiple-serial-numbers.component';
 import { HelpDialogComponent } from './components/template/help-dialog/help-dialog.component';
@@ -873,6 +874,7 @@ import { HelpDialogComponent } from './components/template/help-dialog/help-dial
     MultipleSerialNumbersComponent,
     HelpDialogComponent,
     ValidateApplicationsModalComponent,
+    PreventiveOrderDetailsComponent,
   ],
   imports: [
     SocketIoModule.forRoot(config),

+ 1 - 0
src/app/components/preventive-maintenance/preventive-order-details/preventive-order-details.component.css

@@ -0,0 +1 @@
+/* Styles identical to corrective order details */

+ 87 - 0
src/app/components/preventive-maintenance/preventive-order-details/preventive-order-details.component.html

@@ -0,0 +1,87 @@
+<h1 mat-dialog-title class="prevent-select">Detalles orden de mantenimiento preventivo</h1>
+<div mat-dialog-content class="prevent-select">
+  @if (isLoading) {
+    <div class="is-loading animated fadeIn fast">
+      <mat-spinner align="center"></mat-spinner>
+      <h3>Cargando datos ...</h3>
+    </div>
+  }
+  @if (!isLoading && hasError) {
+    <div class="has-error animated fadeIn pt-64">
+      <mat-icon class="red_primary_font">error</mat-icon>
+      <h2>{{ errorStr }}</h2>
+    </div>
+  }
+  @if (!isLoading && !hasError) {
+    <div class="dialog_details_column animated fadeIn">
+      <p><b>Orden de mantenimiento preventivo #{{ workOrder!.ID_ORDEN }}</b></p>
+      <p><b>Usuario encargado de atender la solicitud: </b>{{ workOrder!.ID_RESPONSABLE }} - {{ workOrder!.TIPO_RESPONSABLE }}</p>
+      <p><b>Descripción: </b>{{ workOrder!.DESCRIPCION || '-' }}</p>
+      <p><b>Equipamiento: </b>{{ workOrder!.TIPO_EQUIPAMIENTO }} - {{ workOrder!.MODELO_EQUIPAMIENTO }}</p>
+      <p><b>Fecha de inicio: </b>{{ workOrder!.FECHA_INICIO }}</p>
+      <p><b>Tiempo de solución estimado: </b>{{ workOrder!.TIEMPO_ESTIMADO || '-' }}h</p>
+      <p><b>Contador relacionado: </b>#{{ workOrder!.CONTADOR || '-' }}</p>
+      <p class="m-0"><b>Medida reportada al registro de la orden:</b></p>
+      <ul class="m-0">
+        @if (workOrder!.MEDIDAS_OBJ) {
+          <li><b>ID medida: </b>{{ workOrder!.MEDIDAS_OBJ!.ID_MEDIDA }}</li>
+          <li><b>Valor: </b>{{ workOrder!.MEDIDAS_OBJ!.VALOR }}</li>
+          <li><b>Servicio web: </b>{{ workOrder!.MEDIDAS_OBJ!.URL_SERVICIO_WEB }}</li>
+          <li><b>Fecha y hora de registro: </b>{{ workOrder!.MEDIDAS_OBJ!.HORA_REGISTRO }}</li>
+        } @else {
+          <li><b>Sin medidas</b></li>
+        }
+      </ul>
+      <p class="mt-12"><b>Fecha de finalización: </b>{{ workOrder!.FECHA_FINAL || '-' }}</p>
+      <p><b>Duración total: </b>{{ workOrder!.DURACION_TOTAL ? workOrder!.DURACION_TOTAL + 'h' : '-' }}</p>
+      <p class="m-0"><b>Recursos requeridos:</b></p>
+      <ul class="m-0">
+        @if (workOrder!.RECURSOS_ARR && workOrder!.RECURSOS_ARR.length > 0) {
+          @for (item of workOrder!.RECURSOS_ARR; track $index) {
+            <li>
+              {{ item }}
+            </li>
+          }
+        } @else {
+          <li><b>Sin recursos</b></li>
+        }
+      </ul>
+      <div style="width: 100%;" class="mt-12"></div>
+      <p class="m-0"><b>Personal requerido:</b></p>
+      <ul class="m-0">
+        @if (workOrder!.PERSONAL_ARR && workOrder!.PERSONAL_ARR.length > 0) {
+          @for (item of workOrder!.PERSONAL_ARR; track $index) {
+            <li>
+              {{ item.NAME }} - {{ item.CANT }} operario(s) requerido(s).
+            </li>
+          }
+        } @else {
+          <li><b>Sin personal</b></li>
+        }
+      </ul>
+      <p class="mt-12"><b>Tipo de activación: </b>{{ workOrder!.TIPO_ACTIVACION || '-' }}</p>
+      <p class="m-0"><b>Documentos relacionados:</b></p>
+      <ul class="m-0">
+        @if (workOrder!.DOCUMENTOS_RELACIONADOS_ARR && workOrder!.DOCUMENTOS_RELACIONADOS_ARR.length > 0) {
+          @for (item of workOrder!.DOCUMENTOS_RELACIONADOS_ARR; track $index) {
+            <li>
+              {{ item.name }} - {{ item.size }}
+            </li>
+          }
+        } @else {
+          <li><b>Sin documentos</b></li>
+        }
+      </ul>
+      <p class="mt-12"><b>Clasificación: </b>{{ workOrder!.CLASIFICACION || '-' }}</p>
+      <p><b>Comentarios: </b>{{ workOrder!.COMENTARIOS || '-' }}</p>
+      <p><b>Estado: </b>{{ workOrder!.ESTADO || '-' }}</p>
+      <p><b>Usuario que realizó el registro: </b>{{ workOrder!.USUREG || '-' }}</p>
+      <p><b>Fecha de registro: </b>{{ workOrder!.FECREG || '-' }}</p>
+      <p><b>Usuario que modificó: </b>{{ workOrder!.USUMOD || '-' }}</p>
+      <p><b>Fecha de modificación: </b>{{ workOrder!.FECMOD || '-' }}</p>
+    </div>
+  }
+</div>
+<div mat-dialog-actions align="end">
+  <button mat-button mat-dialog-close>Cerrar</button>
+</div>

+ 196 - 0
src/app/components/preventive-maintenance/preventive-order-details/preventive-order-details.component.ts

@@ -0,0 +1,196 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { PreventiveMaintenanceService } from '../../../services/preventive-maintenance.service';
+import { EncService } from '../../../services/enc.service';
+import { FunctionsService } from '../../../services/functions.service';
+import { ResourcesService } from '../../../services/resources.service';
+import { lastValueFrom } from 'rxjs';
+import {
+  PreventiveVisitDetailsResponse,
+  PreventiveVisitDetails,
+} from '../../../interfaces/preventive-maintenance.interface';
+
+@Component({
+  selector: 'app-preventive-order-details',
+  templateUrl: './preventive-order-details.component.html',
+  styleUrl: './preventive-order-details.component.css',
+  standalone: false,
+})
+export class PreventiveOrderDetailsComponent implements OnInit {
+  idOrder: string;
+  isLoading: boolean;
+  hasError: boolean;
+  errorStr: string;
+
+
+
+  workOrder: PreventiveVisitDetails | null;
+
+  constructor(
+    @Inject(MAT_DIALOG_DATA) private _data: any,
+    private _preventiveMaintenanceService: PreventiveMaintenanceService,
+    private _encService: EncService,
+    private _functionsService: FunctionsService,
+    private _resourcesService: ResourcesService,
+
+  ) {
+    this.idOrder = '';
+    this.isLoading = true;
+    this.hasError = false;
+    this.errorStr = '';
+
+
+
+    this.workOrder = null;
+  }
+
+  ngOnInit(): void {
+    this.getOrderDetails();
+  }
+
+  async getOrderDetails() {
+    try {
+      let idUser = localStorage.getItem('idusuario')!;
+      let order: PreventiveVisitDetailsResponse = await lastValueFrom(
+        this._preventiveMaintenanceService.getVisit(
+          this._data.idOrder,
+          idUser,
+          1
+        )
+      );
+
+      this.hasError = order.error;
+      this.errorStr = order.msg;
+
+      if (!this.hasError) {
+        // Decrypt encrypted fields
+        order.response.ID_ORDEN = await this._encService.decrypt(
+          order.response.ID_ORDEN
+        );
+        order.response.CONTADOR = await this._encService.decrypt(
+          order.response.CONTADOR
+        );
+
+        let codeDec = await this._encService.decrypt(
+          order.response.CODIGO_EQUIPAMIENTO
+        );
+        order.response.TIPO_EQUIPAMIENTO = `${codeDec} - ${order.response.TIPO_EQUIPAMIENTO}`;
+
+        let idEquipmentDec = await this._encService.decrypt(
+          order.response.ID_EQUIPAMIENTO
+        );
+        order.response.MODELO_EQUIPAMIENTO = `${order.response.MODELO_EQUIPAMIENTO} (${idEquipmentDec})`;
+
+        // Handle MEDIDAS_OBJ if exists
+        if (order.response.MEDIDAS_OBJ) {
+          order.response.MEDIDAS_OBJ.ID_MEDIDA = await this._encService.decrypt(
+            order.response.MEDIDAS_OBJ.ID_MEDIDA
+          );
+          order.response.MEDIDAS_OBJ.CONTADOR = await this._encService.decrypt(
+            order.response.MEDIDAS_OBJ.CONTADOR
+          );
+          order.response.MEDIDAS_OBJ.ID_SERVICIO_WEB =
+            await this._encService.decrypt(
+              order.response.MEDIDAS_OBJ.ID_SERVICIO_WEB
+            );
+          order.response.MEDIDAS_OBJ.HORA_REGISTRO =
+            this._functionsService.orderDate(
+              order.response.MEDIDAS_OBJ.HORA_REGISTRO
+            )!;
+        }
+
+        // Process resources - handle both formats
+        if (order.response.RECURSOS_ARR) {
+          // Already comes as array
+        } else {
+          // Parse from RECURSOS string
+          order.response.RECURSOS_ARR = JSON.parse(order.response.RECURSOS || '[]');
+        }
+
+        // Process personal if exists
+        if (order.response.PERSONAL) {
+          let staffArr = JSON.parse(order.response.PERSONAL);
+          let staffArrFn: any[] = [];
+          for (const item of staffArr) {
+            staffArrFn.push({
+              ID: item.ID,
+              NAME: item.NAME,
+              CANT: item.CANT,
+            });
+          }
+          order.response.PERSONAL_ARR = staffArrFn;
+        } else {
+          order.response.PERSONAL_ARR = [];
+        }
+
+        // Process documents - handle different format
+        if (
+          order.response.DOCUMENTOS_RELACIONADOS_ARR &&
+          order.response.DOCUMENTOS_RELACIONADOS_ARR.length > 0
+        ) {
+          // Already processed
+        } else {
+          let documentsArr = JSON.parse(
+            order.response.DOCUMENTOS_RELACIONADOS || '[]'
+          );
+          let documentsArrFn: any[] = [];
+          for (const document of documentsArr) {
+            if (typeof document === 'string') {
+              let parts = document.split('=');
+              documentsArrFn.push({
+                name: parts[2] || document,
+                size: '-',
+              });
+            }
+          }
+          order.response.DOCUMENTOS_RELACIONADOS_ARR = documentsArrFn;
+        }
+
+        // Format dates
+        order.response.FECREG = this._functionsService.orderDate(
+          order.response.FECREG
+        )!;
+
+        // Handle optional fields with null checks
+        if (order.response.FECHA_FINAL) {
+          order.response.FECHA_FINAL = this._functionsService.orderDate(
+            order.response.FECHA_FINAL
+          )!;
+        }
+
+        if (order.response.FECMOD) {
+          order.response.FECMOD = this._functionsService.orderDate(
+            order.response.FECMOD
+          )!;
+        }
+
+        // Handle comments - parse if it's JSON array
+        if (order.response.COMENTARIOS && order.response.COMENTARIOS !== '[]') {
+          try {
+            let comments = JSON.parse(order.response.COMENTARIOS);
+            order.response.COMENTARIOS =
+              comments.length > 0 ? comments.join(', ') : null;
+          } catch {
+            // Keep as string if not JSON
+          }
+        } else {
+          order.response.COMENTARIOS = '';
+        }
+
+        // Set default values for missing fields
+        order.response.ID_RESPONSABLE = order.response.ID_RESPONSABLE || '-';
+        order.response.TIPO_RESPONSABLE =
+          order.response.TIPO_RESPONSABLE || '-';
+        order.response.FECHA_INICIO = order.response.FECHA_INICIO || '-';
+
+        this.workOrder = order.response;
+      }
+
+      this.isLoading = false;
+    } catch (error: any) {
+      this.errorStr = error?.error?.msg || 'Ocurrió un error inesperado.';
+      this.hasError = true;
+      this.isLoading = false;
+    }
+  }
+}

+ 51 - 0
src/app/interfaces/preventive-maintenance.interface.ts

@@ -0,0 +1,51 @@
+export interface PreventiveVisitDetailsResponse {
+  error: boolean;
+  msg: string;
+  response: PreventiveVisitDetails;
+}
+
+export interface PreventiveVisitDetails {
+  ID_ORDEN: string;
+  DESCRIPCION: string;
+  CODIGO_EQUIPAMIENTO: string;
+  TIPO_EQUIPAMIENTO: string;
+  MODELO_EQUIPAMIENTO: string;
+  ID_EQUIPAMIENTO: string;
+  TIEMPO_ESTIMADO: number;
+  CONTADOR: string;
+  PRIORIDAD: string;
+  RECURSOS: string;
+  TIPO_ACTIVACION: string;
+  DOCUMENTOS_RELACIONADOS: string;
+  CLASIFICACION: string;
+  COMENTARIOS: string;
+  ESTADO: string;
+  USUREG: string;
+  FECREG: string;
+  ID_RESPONSABLE?: string;
+  TIPO_RESPONSABLE?: string;
+  PERSONAL?: string;
+  MEDIDAS_OBJ?: PreventiveMeasureDetails;
+  DOCUMENTOS_RELACIONADOS_ARR?: PreventiveDocumentInfo[];
+  RECURSOS_ARR?: string[];
+  PERSONAL_ARR?: any[];
+  FECHA_INICIO?: string;
+  FECHA_FINAL?: string;
+  DURACION_TOTAL?: number;
+  FECMOD?: string;
+  USUMOD?: string;
+}
+
+export interface PreventiveMeasureDetails {
+  VALOR: number;
+  CONTADOR: string;
+  ID_MEDIDA: string;
+  HORA_REGISTRO: string;
+  ID_SERVICIO_WEB: string;
+  URL_SERVICIO_WEB: string;
+}
+
+export interface PreventiveDocumentInfo {
+  name: string;
+  size: number;
+}

+ 4 - 0
src/app/services/preventive-maintenance.service.ts

@@ -86,6 +86,10 @@ export class PreventiveMaintenanceService {
     return this.getQuery(`get-work-orders-by-equipment/${equipmentCode}/${idUser}/${line}`).pipe(map((data: any) => data))
   }
 
+  getVisit(id: string, idUser: string, line: number){
+    return this.getQuery(`get-visit/${id}/${idUser}/${line}`).pipe(map((data: any) => data))
+  }
+
   registerWorkOrder(body: any){
     return this.postQuery("register-work-order", body).pipe(map((data: any) => data))
   }