feat(servers): permitir tipos vindos do banco

- remove enums fixos de tipo, aplicação e dbType
- atualiza DTOs, controller e repositório para lidar com strings normalizadas
- normaliza e registra tipos durante criação e importação em massa
master
Artur Oliveira 2025-12-16 18:09:40 -03:00
parent bba78772db
commit a43fc58ff7
8 changed files with 89 additions and 80 deletions

View File

@ -3,9 +3,6 @@ package com.hitcommunications.servermanager.controllers;
import com.hitcommunications.servermanager.model.dtos.BulkServerImportResponse;
import com.hitcommunications.servermanager.model.dtos.NewServerDTO;
import com.hitcommunications.servermanager.model.dtos.ServerDTO;
import com.hitcommunications.servermanager.model.enums.Applications;
import com.hitcommunications.servermanager.model.enums.DatabaseType;
import com.hitcommunications.servermanager.model.enums.ServersType;
import com.hitcommunications.servermanager.services.ServersService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@ -72,14 +69,14 @@ public class ServersController {
@GetMapping("/type/{type}")
@Operation(summary = "Lista servidores por tipo.")
@ApiResponse(responseCode = "200", description = "Lista retornada.")
public ResponseEntity<List<ServerDTO>> getByType(@PathVariable ServersType type) {
public ResponseEntity<List<ServerDTO>> getByType(@PathVariable String type) {
return ResponseEntity.ok().body(serversService.getByType(type));
}
@GetMapping("/type")
@Operation(summary = "Conta servidores agrupando por tipo.")
@ApiResponse(responseCode = "200", description = "Mapa retornado.")
public ResponseEntity<Map<ServersType, Integer>> countAllByType() {
public ResponseEntity<Map<String, Integer>> countAllByType() {
return ResponseEntity.ok().body(serversService.countAllByType());
}
@ -96,7 +93,7 @@ public class ServersController {
@GetMapping("/application/{application}")
@Operation(summary = "Lista servidores por aplicação.")
@ApiResponse(responseCode = "200", description = "Lista retornada.")
public ResponseEntity<List<ServerDTO>> getByApplication(@PathVariable Applications application) {
public ResponseEntity<List<ServerDTO>> getByApplication(@PathVariable String application) {
return ResponseEntity.ok().body(serversService.getByApplication(application));
}
@ -105,9 +102,9 @@ public class ServersController {
@ApiResponse(responseCode = "200", description = "Resultados retornados.")
public ResponseEntity<List<ServerDTO>> getAll(
@RequestParam(value = "query", required = false) String query,
@RequestParam(value = "type", required = false) ServersType type,
@RequestParam(value = "application", required = false) Applications application,
@RequestParam(value = "dbType", required = false) DatabaseType dbType
@RequestParam(value = "type", required = false) String type,
@RequestParam(value = "application", required = false) String application,
@RequestParam(value = "dbType", required = false) String dbType
) {
return ResponseEntity.ok().body(serversService.search(query, type, application, dbType));
}

View File

@ -1,8 +1,5 @@
package com.hitcommunications.servermanager.model.dtos;
import com.hitcommunications.servermanager.model.enums.Applications;
import com.hitcommunications.servermanager.model.enums.DatabaseType;
import com.hitcommunications.servermanager.model.enums.ServersType;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
@ -12,9 +9,8 @@ public record NewServerDTO(
@NotNull Integer port,
@NotBlank String user,
@NotBlank String password,
@NotNull ServersType type,
@NotNull Applications application,
@NotNull DatabaseType dbType
@NotBlank String type,
@NotBlank String application,
@NotBlank String dbType
) {
}

View File

@ -1,9 +1,5 @@
package com.hitcommunications.servermanager.model.dtos;
import com.hitcommunications.servermanager.model.enums.Applications;
import com.hitcommunications.servermanager.model.enums.DatabaseType;
import com.hitcommunications.servermanager.model.enums.ServersType;
import java.sql.Timestamp;
public record ServerDTO(
@ -13,9 +9,9 @@ public record ServerDTO(
Integer port,
String user,
String password,
ServersType type,
Applications application,
DatabaseType dbType,
String type,
String application,
String dbType,
Timestamp createdAt,
Timestamp updatedAt
) {

View File

@ -1,12 +0,0 @@
package com.hitcommunications.servermanager.model.enums;
public enum Applications {
ASTERISK,
HITMANAGER,
HITMANAGER_V2,
OMNIHIT,
HITPHONE,
CDR,
FUNCIONALIDADE,
VOICEMAIL
}

View File

@ -1,12 +0,0 @@
package com.hitcommunications.servermanager.model.enums;
public enum DatabaseType {
MYSQL,
POSTGRESQL,
SQLSERVER,
ORACLE,
REDIS,
MONGODB,
MARIADB,
NONE
}

View File

@ -1,7 +0,0 @@
package com.hitcommunications.servermanager.model.enums;
public enum ServersType {
PRODUCTION,
HOMOLOGATION,
DATABASE
}

View File

@ -8,16 +8,12 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.hitcommunications.servermanager.model.Servers;
import com.hitcommunications.servermanager.model.enums.Applications;
import com.hitcommunications.servermanager.model.enums.DatabaseType;
import com.hitcommunications.servermanager.model.enums.ServersType;
public interface ServersRepository extends JpaRepository<Servers, String> {
Optional<Servers> findByName(String name);
List<Servers> findByType(ServersType type);
List<Servers> findByApplication(Applications application);
List<Servers> findByType(String type);
List<Servers> findByApplication(String application);
Optional<Servers> findByIpAndPort(String ip, Integer port);
Integer countAllByType(ServersType type);
Integer countAllByType(String type);
@Query(value = """
select s.* from "server-manager".tab_servers s

View File

@ -6,10 +6,10 @@ import com.hitcommunications.servermanager.model.dtos.BulkServerImportResponse;
import com.hitcommunications.servermanager.model.dtos.BulkServerImportResponse.FailedRow;
import com.hitcommunications.servermanager.model.dtos.NewServerDTO;
import com.hitcommunications.servermanager.model.dtos.ServerDTO;
import com.hitcommunications.servermanager.model.enums.Applications;
import com.hitcommunications.servermanager.model.enums.DatabaseType;
import com.hitcommunications.servermanager.model.enums.ServersType;
import com.hitcommunications.servermanager.model.enums.TypeCategory;
import com.hitcommunications.servermanager.repositories.ServersRepository;
import com.hitcommunications.servermanager.services.TypeOptionService;
import com.hitcommunications.servermanager.utils.TypeNormalizer;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@ -18,18 +18,20 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@Service
@RequiredArgsConstructor
public class ServersService {
private final ServersMapper mapper;
private final ServersRepository repo;
private final TypeOptionService typeOptionService;
public ServerDTO create(NewServerDTO createDTO) {
Servers entity = mapper.toEntity(createDTO);
applyNormalizedTypeData(entity, createDTO);
entity = repo.save(entity);
return mapper.toDTO(entity);
}
@ -46,25 +48,34 @@ public class ServersService {
.orElseThrow(() -> new RuntimeException("Server not found with name: " + name));
}
public List<ServerDTO> getByType(ServersType type) {
return repo.findByType(type)
public List<ServerDTO> getByType(String type) {
String normalized = normalizeFilter(type, TypeCategory.SERVER_TYPE);
return repo.findByType(normalized)
.stream()
.map(mapper::toDTO)
.toList();
}
public Map<ServersType, Integer> countAllByType() {
Map<ServersType, Integer> response = new HashMap<>();
public Map<String, Integer> countAllByType() {
Map<String, Integer> response = new LinkedHashMap<>();
for(ServersType type : ServersType.values()) {
typeOptionService.list(TypeCategory.SERVER_TYPE).forEach(type -> {
response.put(type, repo.countAllByType(type));
}
});
// Garantir que valores existentes, mas não registrados, também apareçam
repo.findAll().stream()
.map(Servers::getType)
.filter(type -> type != null && !response.containsKey(type))
.distinct()
.forEach(type -> response.put(type, repo.countAllByType(type)));
return response;
}
public List<ServerDTO> getByApplication(Applications application) {
return repo.findByApplication(application)
public List<ServerDTO> getByApplication(String application) {
String normalized = normalizeFilter(application, TypeCategory.APPLICATION);
return repo.findByApplication(normalized)
.stream()
.map(mapper::toDTO)
.toList();
@ -91,6 +102,7 @@ public class ServersService {
processed++;
try {
registerTypeOptionsFromRow(columns);
NewServerDTO dto = toNewServerDTO(columns);
create(dto);
succeeded++;
@ -125,13 +137,29 @@ public class ServersService {
Integer port = Integer.parseInt(columns[2]);
String user = columns[3];
String password = columns[4];
ServersType type = ServersType.valueOf(columns[5].toUpperCase());
Applications application = Applications.valueOf(columns[6].toUpperCase());
DatabaseType dbType = DatabaseType.valueOf(columns[7].toUpperCase());
String type = columns[5];
String application = columns[6];
String dbType = columns[7];
return new NewServerDTO(name, ip, port, user, password, type, application, dbType);
}
private void registerTypeOptionsFromRow(String[] columns) {
if (columns.length < 8) {
return;
}
registerTypeOption(TypeCategory.SERVER_TYPE, columns[5]);
registerTypeOption(TypeCategory.APPLICATION, columns[6]);
registerTypeOption(TypeCategory.DATABASE, columns[7]);
}
private void registerTypeOption(TypeCategory category, String value) {
if (value == null || value.isBlank()) {
return;
}
typeOptionService.register(category, value);
}
private boolean isHeaderRow(String[] columns) {
if (columns.length < 8) {
return false;
@ -148,11 +176,11 @@ public class ServersService {
.toList();
}
public List<ServerDTO> search(String query, ServersType type, Applications application, DatabaseType dbType) {
public List<ServerDTO> search(String query, String type, String application, String dbType) {
String normalizedQuery = (query == null || query.isBlank()) ? null : query.trim();
String typeFilter = type != null ? type.name() : null;
String applicationFilter = application != null ? application.name() : null;
String dbTypeFilter = dbType != null ? dbType.name() : null;
String typeFilter = normalizeFilter(type, TypeCategory.SERVER_TYPE);
String applicationFilter = normalizeFilter(application, TypeCategory.APPLICATION);
String dbTypeFilter = normalizeFilter(dbType, TypeCategory.DATABASE);
return repo.search(normalizedQuery, typeFilter, applicationFilter, dbTypeFilter)
.stream()
@ -165,6 +193,7 @@ public class ServersService {
.orElseThrow(() -> new RuntimeException("Server not found with id: " + id));
mapper.partialUpdate(updateDTO, entity);
applyNormalizedTypeData(entity, updateDTO);
entity = repo.save(entity);
return mapper.toDTO(entity);
}
@ -176,4 +205,30 @@ public class ServersService {
repo.deleteById(id);
}
private void applyNormalizedTypeData(Servers entity, NewServerDTO dto) {
entity.setType(normalizeAndRegister(TypeCategory.SERVER_TYPE, dto.type()));
entity.setApplication(normalizeAndRegister(TypeCategory.APPLICATION, dto.application()));
entity.setDbType(normalizeAndRegister(TypeCategory.DATABASE, dto.dbType()));
}
private String normalizeFilter(String value, TypeCategory category) {
if (value == null || value.isBlank()) {
return null;
}
String normalized = TypeNormalizer.normalize(value);
if (normalized == null) {
return null;
}
typeOptionService.register(category, normalized);
return normalized;
}
private String normalizeAndRegister(TypeCategory category, String value) {
String normalized = TypeNormalizer.normalize(value);
if (normalized == null) {
throw new IllegalArgumentException("Valor inválido para " + category.name());
}
typeOptionService.register(category, normalized);
return normalized;
}
}