From afd378712c9176f32a705fb3a10d2d56ed6c8ba2 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Wed, 8 Oct 2025 13:51:27 -0300 Subject: [PATCH] =?UTF-8?q?Feat:=20PS1=20A=C3=B1adido=20-=20Fix:=20Elimina?= =?UTF-8?q?ci=C3=B3n=20de=20Equipos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/Controllers/EquiposController.cs | 6 +- .../net9.0/Inventario.API.AssemblyInfo.cs | 2 +- .../src/components/ModalDetallesEquipo.tsx | 14 +- getDatosPost.ps1 | 248 ++++++++++++++++++ 4 files changed, 264 insertions(+), 6 deletions(-) create mode 100644 getDatosPost.ps1 diff --git a/backend/Controllers/EquiposController.cs b/backend/Controllers/EquiposController.cs index 4a4c546..94a66f7 100644 --- a/backend/Controllers/EquiposController.cs +++ b/backend/Controllers/EquiposController.cs @@ -189,15 +189,13 @@ namespace Inventario.API.Controllers [HttpDelete("{id}")] public async Task Borrar(int id) { - var query = "DELETE FROM dbo.equipos WHERE Id = @Id AND Origen = 'manual';"; + var query = "DELETE FROM dbo.equipos WHERE Id = @Id;"; using (var connection = _context.CreateConnection()) { var filasAfectadas = await connection.ExecuteAsync(query, new { Id = id }); if (filasAfectadas == 0) { - // Puede que no se haya borrado porque no existe o porque es automático. - // Damos un mensaje de error genérico pero informativo. - return NotFound("Equipo no encontrado o no se puede eliminar porque fue generado automáticamente."); + return NotFound("Equipo no encontrado."); } return NoContent(); } diff --git a/backend/obj/Debug/net9.0/Inventario.API.AssemblyInfo.cs b/backend/obj/Debug/net9.0/Inventario.API.AssemblyInfo.cs index e2a04d9..2551edc 100644 --- a/backend/obj/Debug/net9.0/Inventario.API.AssemblyInfo.cs +++ b/backend/obj/Debug/net9.0/Inventario.API.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Inventario.API")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+177ad5596221b094cc62c04b38044cc9f09a107e")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+268c1c2bf99b66ab7fb5c6dd1a2d1134d636839e")] [assembly: System.Reflection.AssemblyProductAttribute("Inventario.API")] [assembly: System.Reflection.AssemblyTitleAttribute("Inventario.API")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/frontend/src/components/ModalDetallesEquipo.tsx b/frontend/src/components/ModalDetallesEquipo.tsx index fca7a84..6775598 100644 --- a/frontend/src/components/ModalDetallesEquipo.tsx +++ b/frontend/src/components/ModalDetallesEquipo.tsx @@ -226,7 +226,19 @@ const ModalDetallesEquipo: React.FC = ({ -
Eliminar Equipo:{equipo.origen === 'manual' ? 'Eliminar equipo permanentemente' : 'No se puede eliminar un equipo cargado automáticamente'}
+
+ Eliminar Equipo: + + + Eliminar este equipo permanentemente del inventario + +
diff --git a/getDatosPost.ps1 b/getDatosPost.ps1 new file mode 100644 index 0000000..242be88 --- /dev/null +++ b/getDatosPost.ps1 @@ -0,0 +1,248 @@ +# ================================================================================= +# SCRIPT DE INVENTARIO AUTOMÁTICO PARA INVENTARIO-IT +# +# Descripción: +# Este script recopila información de hardware y software del equipo y la envía +# a la API del sistema de inventario. Es compatible con Windows 7 y versiones +# superiores (Windows 10, 11, Server 2012+). +# ================================================================================= + +# --- CONFIGURACIÓN --- +# Host/IP del servidor de API. +$baseUrl = "http://equipos.eldia.net" +# --------------------- + + +# --- DETECCIÓN DE VERSIÓN DE WINDOWS Y FUNCIONES AUXILIARES --- + +$osInfo = Get-WmiObject Win32_OperatingSystem +$isWindows7 = [version]$osInfo.Version -lt [version]"6.2" + +if ($isWindows7) { + Write-Host "Ejecutando en modo de compatibilidad para Windows 7 (PowerShell 2.0)..." + + # Función de conversión a JSON para PowerShell 2.0 + function ConvertTo-BasicJson { + param($InputObject) + if ($null -eq $InputObject) { return "null" } + if ($InputObject -is [array]) { + $json = @() + foreach ($item in $InputObject) { $json += ConvertTo-BasicJson -InputObject $item } + return "[$($json -join ',')]" + } + elseif ($InputObject -is [System.Collections.IDictionary]) { + $props = @() + foreach ($key in $InputObject.Keys) { $props += "`"$key`":$(ConvertTo-BasicJson -InputObject $InputObject[$key])" } + return "{$($props -join ',')}" + } + elseif ($InputObject -is [string]) { + return "`"$($InputObject.ToString().Replace('\', '\\').Replace('"', '\"'))`"" + } + elseif ($InputObject -is [bool]) { + return $InputObject.ToString().ToLower() + } + else { # Números y otros tipos + return $InputObject.ToString() + } + } + + # Función de envío de datos para PowerShell 2.0 + function Send-Data { + param($Url, $Method, $Body) + try { + $webClient = New-Object System.Net.WebClient + $webClient.Headers.Add("Content-Type", "application/json") + return $webClient.UploadString($Url, $Method, $Body) + } catch { + Write-Host "Error en el envío a $Url: $($_.Exception.Message)" + return $null + } + } +} else { + Write-Host "Ejecutando en modo estándar (PowerShell 5+)..." +} + + +# --- RECOPILACIÓN DE DATOS --- + +Write-Host "Recopilando información del sistema..." + +if ($isWindows7) { + # --- Lógica para Windows 7 --- + $hostname = $env:COMPUTERNAME + $username = $env:USERNAME + + $activeInterface = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true -and $_.DefaultIPGateway -ne $null } | Sort-Object InterfaceIndex | Select-Object -First 1 + $ip = if ($activeInterface) { $activeInterface.IPAddress[0] } else { "N/A" } + $mac = if ($activeInterface) { $activeInterface.MACAddress } else { "N/A" } + + $cpu = (Get-WmiObject Win32_Processor).Name + $motherboard = (Get-WmiObject Win32_BaseBoard).Product + $ramSlots = (Get-WmiObject Win32_PhysicalMemoryArray).MemoryDevices + $osName = $osInfo.Caption + $osArchitecture = $osInfo.OSArchitecture + + # Discos (WMI) + $disks = @(Get-WmiObject Win32_DiskDrive | Where-Object { $_.MediaType -like "*hard disk*" } | ForEach-Object { + [PSCustomObject]@{ + mediatype = if ((Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='$($_.DeviceID)'} WHERE AssocClass=Win32_DiskDriveToDiskPartition" | Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='$($_.DeviceID)'} WHERE AssocClass=Win32_LogicalDiskToPartition" | Select-Object -First 1).Description -like "*SSD*") { "SSD" } else { "HDD" } + size = [math]::Round($_.Size / 1GB, 0) + } + }) + + # Módulos de RAM (WMI) - ¡NUEVO! + $ramModules = @(Get-WmiObject Win32_PhysicalMemory | ForEach-Object { + [PSCustomObject]@{ + partNumber = $_.PartNumber.Trim() + fabricante = $_.Manufacturer.Trim() + tamano = [math]::Round($_.Capacity / 1GB, 0) + velocidad = $_.Speed + slot = $_.DeviceLocator.Trim() + } + }) + $installedRAMGB = ($ramModules | Measure-Object -Property tamano -Sum).Sum + +} else { + # --- Lógica para Windows moderno --- + $hostname = $env:COMPUTERNAME + $username = $env:USERNAME + + $activeInterface = Get-NetIPConfiguration | Where-Object { $_.IPv4DefaultGateway -ne $null -and $_.NetAdapter.Status -eq 'Up' } | Sort-Object InterfaceMetric | Select-Object -First 1 + $ip = if ($activeInterface) { $activeInterface.IPv4Address.IPAddress } else { "N/A" } + $mac = if ($activeInterface) { $activeInterface.NetAdapter.MacAddress } else { "N/A" } + + $cpu = (Get-CimInstance Win32_Processor).Name + $motherboard = (Get-CimInstance Win32_BaseBoard).Product + $ramSlots = (Get-CimInstance Win32_PhysicalMemoryArray).MemoryDevices + $os = Get-CimInstance Win32_OperatingSystem + $osName = $os.Caption + $osArchitecture = $os.OSArchitecture + + # Discos (CIM) + $disks = @(Get-PhysicalDisk | Where-Object {$_.MediaType -ne "Unspecified"} | ForEach-Object { + [PSCustomObject]@{ + mediatype = $_.MediaType.ToString() + size = [math]::Round($_.Size / 1GB, 0) + } + }) + + # Módulos de RAM (CIM) - ¡NUEVO! + $ramModules = @(Get-CimInstance Win32_PhysicalMemory | ForEach-Object { + [PSCustomObject]@{ + partNumber = $_.PartNumber.Trim() + fabricante = $_.Manufacturer.Trim() + tamano = [math]::Round($_.Capacity / 1GB, 0) + velocidad = $_.Speed + slot = $_.DeviceLocator.Trim() + } + }) + $installedRAMGB = ($ramModules | Measure-Object -Property tamano -Sum).Sum +} + + +# --- CONSTRUCCIÓN DE PAYLOADS JSON --- + +$equipoPayload = @{ + hostname = $hostname + ip = $ip + mac = $mac + cpu = if ($cpu -is [array]) { $cpu -join ', ' } else { $cpu } + motherboard = $motherboard + ram_installed = $installedRAMGB + ram_slots = $ramSlots + os = $osName + architecture = $osArchitecture +} + +$usuarioPayload = @{ + username = $username +} + +# La API espera una lista de discos +$discosPayload = $disks + +# La API espera una lista de módulos de RAM +$ramModulesPayload = $ramModules + + +# --- CONVERSIÓN A JSON --- + +if ($isWindows7) { + $jsonEquipo = ConvertTo-BasicJson -InputObject $equipoPayload + $jsonUsuario = ConvertTo-BasicJson -InputObject $usuarioPayload + $jsonDiscos = ConvertTo-BasicJson -InputObject $discosPayload + $jsonRamModules = ConvertTo-BasicJson -InputObject $ramModulesPayload +} else { + $jsonEquipo = $equipoPayload | ConvertTo-Json -Depth 5 -Compress + $jsonUsuario = $usuarioPayload | ConvertTo-Json -Compress + $jsonDiscos = $discosPayload | ConvertTo-Json -Depth 5 -Compress + $jsonRamModules = $ramModulesPayload | ConvertTo-Json -Depth 5 -Compress +} + + +# --- ENVÍO DE DATOS A LA API --- + +Write-Host "Enviando datos a la API en $baseUrl..." + +# Definición de las rutas de la API +$rutaEquipo = "$baseUrl/api/equipos/$hostname" +$rutaAsociarUsuario = "$baseUrl/api/equipos/$hostname/asociarusuario" +$rutaCrearUsuario = "$baseUrl/api/usuarios" # Para asegurar que el usuario exista +$rutaCrearDiscos = "$baseUrl/api/discos" # Para asegurar que los discos existan +$rutaAsociarDiscos = "$baseUrl/api/equipos/$hostname/asociardiscos" +$rutaAsociarRam = "$baseUrl/api/equipos/$hostname/ram" # ¡NUEVA RUTA! + +try { + if ($isWindows7) { + # Lógica de envío para Windows 7 + Write-Host "Enviando datos de equipo..." + Send-Data -Url $rutaEquipo -Method "POST" -Body $jsonEquipo + + Write-Host "Creando/actualizando usuario maestro..." + Send-Data -Url $rutaCrearUsuario -Method "POST" -Body $jsonUsuario + + Write-Host "Asociando usuario al equipo..." + Send-Data -Url $rutaAsociarUsuario -Method "POST" -Body $jsonUsuario + + Write-Host "Creando discos maestros..." + Send-Data -Url $rutaCrearDiscos -Method "POST" -Body $jsonDiscos + + Write-Host "Asociando discos al equipo..." + Send-Data -Url $rutaAsociarDiscos -Method "POST" -Body $jsonDiscos + + Write-Host "Asociando módulos de RAM al equipo..." + Send-Data -Url $rutaAsociarRam -Method "POST" -Body $jsonRamModules + } else { + # Lógica de envío para Windows moderno + Write-Host "Enviando datos de equipo..." + Invoke-RestMethod -Uri $rutaEquipo -Method Post -ContentType "application/json" -Body $jsonEquipo + + Write-Host "Creando/actualizando usuario maestro..." + Invoke-RestMethod -Uri $rutaCrearUsuario -Method Post -ContentType "application/json" -Body $jsonUsuario + + Write-Host "Asociando usuario al equipo..." + Invoke-RestMethod -Uri $rutaAsociarUsuario -Method Post -ContentType "application/json" -Body $jsonUsuario + + Write-Host "Creando discos maestros..." + Invoke-RestMethod -Uri $rutaCrearDiscos -Method Post -ContentType "application/json" -Body $jsonDiscos + + Write-Host "Asociando discos al equipo..." + Invoke-RestMethod -Uri $rutaAsociarDiscos -Method Post -ContentType "application/json" -Body $jsonDiscos + + Write-Host "Asociando módulos de RAM al equipo..." + Invoke-RestMethod -Uri $rutaAsociarRam -Method Post -ContentType "application/json" -Body $jsonRamModules + } + + Write-Host "`n-------------------------------------------" + Write-Host "¡Proceso de inventario completado con éxito!" + Write-Host "-------------------------------------------" + +} catch { + Write-Host "`n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + Write-Host "ERROR: Ocurrió un error durante el envío de datos." + Write-Host "Detalle del error: $($_.Exception.Message)" + Write-Host "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" +} + +# Pausa opcional para ver el resultado en una ventana de consola +# Read-Host "Presiona Enter para salir" \ No newline at end of file