mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 00:48:49 +00:00
implementado el soft-delete
This commit is contained in:
@ -13,6 +13,7 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -33,6 +34,7 @@ import com.imprimelibros.erp.datatables.DataTable;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@ -66,18 +68,17 @@ public class UserController {
|
||||
public String list(Model model, Authentication authentication, Locale locale) {
|
||||
|
||||
List<String> keys = List.of(
|
||||
"usuarios.delete.title",
|
||||
"usuarios.delete.text",
|
||||
"usuarios.eliminar",
|
||||
"usuarios.delete.button",
|
||||
"app.yes",
|
||||
"app.cancelar",
|
||||
"usuarios.delete.ok.title",
|
||||
"usuarios.delete.ok.text"
|
||||
);
|
||||
"usuarios.delete.title",
|
||||
"usuarios.delete.text",
|
||||
"usuarios.eliminar",
|
||||
"usuarios.delete.button",
|
||||
"app.yes",
|
||||
"app.cancelar",
|
||||
"usuarios.delete.ok.title",
|
||||
"usuarios.delete.ok.text");
|
||||
|
||||
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
||||
model.addAttribute("languageBundle", translations);
|
||||
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
||||
model.addAttribute("languageBundle", translations);
|
||||
|
||||
return "imprimelibros/users/users-list";
|
||||
}
|
||||
@ -86,7 +87,8 @@ public class UserController {
|
||||
// método con @ResponseBody.
|
||||
@GetMapping(value = "/datatable", produces = "application/json")
|
||||
@ResponseBody
|
||||
public DataTablesResponse<Map<String, Object>> datatable(HttpServletRequest request, Locale locale) {
|
||||
public DataTablesResponse<Map<String, Object>> datatable(HttpServletRequest request, Authentication authentication,
|
||||
Locale locale) {
|
||||
|
||||
DataTablesRequest dt = DataTablesParser.from(request); //
|
||||
|
||||
@ -94,8 +96,9 @@ public class UserController {
|
||||
// Si 'role' es relación, sácalo de aquí:
|
||||
List<String> searchable = List.of("fullName", "userName", "enabled", "rolesConcat"); // <- busca por roles de
|
||||
// verdad
|
||||
List<String> orderable = List.of("id", "fullName", "userName", "enabled", "roleRank"); // <- permite ordenar por estas
|
||||
// columnas
|
||||
List<String> orderable = List.of("id", "fullName", "userName", "enabled", "roleRank"); // <- permite ordenar por
|
||||
// estas
|
||||
// columnas
|
||||
|
||||
Specification<User> base = (root, query, cb) -> cb.conjunction();
|
||||
long total = repo.count();
|
||||
@ -121,12 +124,27 @@ public class UserController {
|
||||
messageSource.getMessage("usuarios.rol." + rol, null, locale) + "</span>")
|
||||
.collect(Collectors.joining(" ")))
|
||||
.add("actions", (user) -> {
|
||||
return "<div class=\"hstack gap-3 flex-wrap\">\n" +
|
||||
" <a href=\"javascript:void(0);\" data-id=\"" + user.getId()
|
||||
+ "\" class=\"link-success btn-edit-user fs-15\"><i class=\"ri-edit-2-line\"></i></a>\n" +
|
||||
" <a href=\"javascript:void(0);\" data-id=\"" + user.getId()
|
||||
+ "\" class=\"link-danger btn-delete-user fs-15\"><i class=\"user-delete ri-delete-bin-line\"></i></a>\n" +
|
||||
" </div>";
|
||||
|
||||
boolean isSuperAdmin = authentication.getAuthorities().stream()
|
||||
.anyMatch(a -> a.getAuthority().equals("ROLE_SUPERADMIN"));
|
||||
|
||||
if (!isSuperAdmin) {
|
||||
return "<div class=\"hstack gap-3 flex-wrap\">\n" +
|
||||
" <a href=\"javascript:void(0);\" data-id=\"" + user.getId()
|
||||
+ "\" class=\"link-success btn-edit-user fs-15\"><i class=\"ri-edit-2-line\"></i></a>\n"
|
||||
+
|
||||
" </div>";
|
||||
} else {
|
||||
// Admin editando otro admin o usuario normal: puede editarse y eliminarse
|
||||
return "<div class=\"hstack gap-3 flex-wrap\">\n" +
|
||||
" <a href=\"javascript:void(0);\" data-id=\"" + user.getId()
|
||||
+ "\" class=\"link-success btn-edit-user fs-15\"><i class=\"ri-edit-2-line\"></i></a>\n"
|
||||
+
|
||||
" <a href=\"javascript:void(0);\" data-id=\"" + user.getId()
|
||||
+ "\" class=\"link-danger btn-delete-user fs-15\"><i class=\"user-delete ri-delete-bin-line\"></i></a>\n"
|
||||
+
|
||||
" </div>";
|
||||
}
|
||||
})
|
||||
.where(base)
|
||||
// Filtros custom:
|
||||
@ -295,28 +313,38 @@ public class UserController {
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<?> delete(@PathVariable Long id, Authentication authentication, Locale locale) {
|
||||
@Transactional
|
||||
public ResponseEntity<?> delete(@PathVariable Long id, Authentication auth, Locale locale) {
|
||||
return repo.findById(id).map(u -> {
|
||||
|
||||
if (authentication != null && u.getUserName().equalsIgnoreCase(authentication.getName())) {
|
||||
if (auth != null && u.getUserName().equalsIgnoreCase(auth.getName())) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN)
|
||||
.body(Map.of("message", messageSource.getMessage("usuarios.error.delete-self", null, locale)));
|
||||
}
|
||||
try {
|
||||
repo.delete(u);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(
|
||||
Map.of("message", messageSource.getMessage("usuarios.exito.eliminado", null, locale))
|
||||
);
|
||||
} catch (DataIntegrityViolationException dive) {
|
||||
// Restricción FK / dependencias
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT)
|
||||
.body(Map.of("message", messageSource.getMessage("usuarios.error.delete-relational-data", null, locale)));
|
||||
Long currentUserId = null;
|
||||
if (auth != null && auth.getPrincipal() instanceof UserDetailsImpl udi) {
|
||||
currentUserId = udi.getId();
|
||||
} else if (auth != null) {
|
||||
currentUserId = repo.findIdByUserNameIgnoreCase(auth.getName()).orElse(null); // fallback
|
||||
}
|
||||
|
||||
u.setDeleted(true);
|
||||
u.setDeletedAt(LocalDateTime.now());
|
||||
u.setDeletedBy(currentUserId);
|
||||
|
||||
// Soft-delete de los vínculos (si usas cascade REMOVE + @SQLDelete en UserRole,
|
||||
// podrías omitir este foreach y dejar que JPA lo haga)
|
||||
u.getRolesLink().forEach(UserRole::softDelete);
|
||||
|
||||
repo.save(u); // ← NO delete(); guardamos el soft delete con deleted_by relleno
|
||||
return ResponseEntity.ok(Map.of("message",
|
||||
messageSource.getMessage("usuarios.exito.eliminado", null, locale)));
|
||||
} catch (Exception ex) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(Map.of("message", messageSource.getMessage("usuarios.error.delete-internal-error", null, locale)));
|
||||
.body(Map.of("message",
|
||||
messageSource.getMessage("usuarios.error.delete-internal-error", null, locale)));
|
||||
}
|
||||
}).orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body(Map.of("message", messageSource.getMessage("usuarios.error.delete-not-found", null, locale))));
|
||||
.body(Map.of("message", messageSource.getMessage("usuarios.error.not-found", null, locale))));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user