Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
509 lines
23 KiB
Java
509 lines
23 KiB
Java
package de.oaa.xxx.gruppe;
|
|
|
|
import de.oaa.xxx.gruppe.dto.*;
|
|
import de.oaa.xxx.gruppe.entity.*;
|
|
import de.oaa.xxx.gruppe.repository.*;
|
|
import de.oaa.xxx.social.entity.KommentarEntity;
|
|
import de.oaa.xxx.social.repository.KommentarRepository;
|
|
import de.oaa.xxx.user.UserEntity;
|
|
import de.oaa.xxx.user.UserRepository;
|
|
import de.oaa.xxx.user.UserService;
|
|
import de.oaa.xxx.util.BaseController;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
import java.security.Principal;
|
|
import java.time.LocalDateTime;
|
|
import java.util.*;
|
|
|
|
@RestController
|
|
@RequestMapping("/gruppen")
|
|
public class GruppeController extends BaseController {
|
|
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(GruppeController.class);
|
|
|
|
private final GruppeRepository gruppeRepository;
|
|
private final GruppenmitgliedRepository mitgliedRepository;
|
|
private final BeitrittsanfrageRepository anfrageRepository;
|
|
private final GruppenbeitragRepository beitragRepository;
|
|
private final UmfrageOptionRepository optionRepository;
|
|
private final UmfrageStimmeRepository stimmeRepository;
|
|
private final GruppenbeitragLikeRepository likeRepository;
|
|
private final BeitragMeldungRepository meldungRepository;
|
|
private final KommentarRepository kommentarRepository;
|
|
private final UserRepository userRepository;
|
|
|
|
public GruppeController(GruppeRepository gruppeRepository,
|
|
GruppenmitgliedRepository mitgliedRepository,
|
|
BeitrittsanfrageRepository anfrageRepository,
|
|
GruppenbeitragRepository beitragRepository,
|
|
UmfrageOptionRepository optionRepository,
|
|
UmfrageStimmeRepository stimmeRepository,
|
|
GruppenbeitragLikeRepository likeRepository,
|
|
BeitragMeldungRepository meldungRepository,
|
|
KommentarRepository kommentarRepository,
|
|
UserRepository userRepository,
|
|
UserService userService) {
|
|
super(userService);
|
|
this.gruppeRepository = gruppeRepository;
|
|
this.mitgliedRepository = mitgliedRepository;
|
|
this.anfrageRepository = anfrageRepository;
|
|
this.beitragRepository = beitragRepository;
|
|
this.optionRepository = optionRepository;
|
|
this.stimmeRepository = stimmeRepository;
|
|
this.likeRepository = likeRepository;
|
|
this.meldungRepository = meldungRepository;
|
|
this.kommentarRepository = kommentarRepository;
|
|
this.userRepository = userRepository;
|
|
}
|
|
|
|
record CreateGruppeRequest(String name, String beschreibung, String bild, boolean isPrivate) {}
|
|
record JoinRequest(String nachricht) {}
|
|
record UpdateGruppeRequest(String name, String beschreibung, String bild, Boolean isPrivate) {}
|
|
|
|
// ── GET /gruppe/search?q= ──
|
|
|
|
@GetMapping("/search")
|
|
public ResponseEntity<List<GruppeDto>> search(@RequestParam String q, Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
List<GruppeEntity> gruppen = gruppeRepository.findByNameContainingIgnoreCase(q)
|
|
.stream().limit(30).toList();
|
|
List<UUID> gruppeIds = gruppen.stream().map(GruppeEntity::getGruppeId).toList();
|
|
Map<UUID, LocalDateTime> latestActivity = buildLatestActivityMap(gruppeIds);
|
|
List<GruppeDto> result = gruppen.stream()
|
|
.map(g -> toDto(g, myId))
|
|
.sorted((a, b) -> {
|
|
LocalDateTime la = latestActivity.getOrDefault(a.gruppeId(), a.createdAt());
|
|
LocalDateTime lb = latestActivity.getOrDefault(b.gruppeId(), b.createdAt());
|
|
return lb.compareTo(la);
|
|
})
|
|
.toList();
|
|
return ResponseEntity.ok(result);
|
|
}
|
|
|
|
// ── GET /gruppe/mine ──
|
|
|
|
@GetMapping("/mine")
|
|
public ResponseEntity<List<GruppeDto>> mine(Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
List<GruppeEntity> gruppen = mitgliedRepository.findByUserId(myId)
|
|
.stream()
|
|
.map(m -> gruppeRepository.findById(m.getGruppeId()).orElse(null))
|
|
.filter(Objects::nonNull)
|
|
.toList();
|
|
List<UUID> gruppeIds = gruppen.stream().map(GruppeEntity::getGruppeId).toList();
|
|
Map<UUID, LocalDateTime> latestActivity = buildLatestActivityMap(gruppeIds);
|
|
List<GruppeDto> result = gruppen.stream()
|
|
.map(g -> toDto(g, myId))
|
|
.sorted((a, b) -> {
|
|
LocalDateTime la = latestActivity.getOrDefault(a.gruppeId(), a.createdAt());
|
|
LocalDateTime lb = latestActivity.getOrDefault(b.gruppeId(), b.createdAt());
|
|
return lb.compareTo(la);
|
|
})
|
|
.toList();
|
|
return ResponseEntity.ok(result);
|
|
}
|
|
|
|
// ── GET /gruppe/{id} ──
|
|
|
|
@GetMapping("/{id}")
|
|
public ResponseEntity<GruppeDto> getGruppe(@PathVariable("id") UUID id, Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
return gruppeRepository.findById(id)
|
|
.map(g -> ResponseEntity.ok(toDto(g, myId)))
|
|
.orElse(ResponseEntity.notFound().build());
|
|
}
|
|
|
|
// ── POST /gruppe ──
|
|
|
|
@PostMapping
|
|
public ResponseEntity<GruppeDto> createGruppe(@RequestBody CreateGruppeRequest req, Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
if (req.name() == null || req.name().isBlank()) return ResponseEntity.badRequest().build();
|
|
|
|
GruppeEntity gruppe = new GruppeEntity();
|
|
gruppe.setGruppeId(UUID.randomUUID());
|
|
gruppe.setName(req.name().trim());
|
|
gruppe.setBeschreibung(req.beschreibung());
|
|
gruppe.setBild(req.bild());
|
|
gruppe.setPrivate(req.isPrivate());
|
|
gruppe.setCreatedAt(LocalDateTime.now());
|
|
gruppe.setCreatedByUserId(myId);
|
|
gruppeRepository.save(gruppe);
|
|
|
|
GruppenmitgliedEntity admin = new GruppenmitgliedEntity();
|
|
admin.setMitgliedId(UUID.randomUUID());
|
|
admin.setGruppeId(gruppe.getGruppeId());
|
|
admin.setUserId(myId);
|
|
admin.setRolle(GruppenRolle.ADMIN);
|
|
admin.setJoinedAt(LocalDateTime.now());
|
|
mitgliedRepository.save(admin);
|
|
LOGGER.info("User {} hat Gruppe '{}' ({}) erstellt", myId, gruppe.getName(), gruppe.getGruppeId());
|
|
|
|
return ResponseEntity.status(201).body(toDto(gruppe, myId));
|
|
}
|
|
|
|
// ── PUT /gruppe/{id} ──
|
|
|
|
@PutMapping("/{id}")
|
|
public ResponseEntity<GruppeDto> updateGruppe(@PathVariable("id") UUID id,
|
|
@RequestBody UpdateGruppeRequest req,
|
|
Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
var gruppeOpt = gruppeRepository.findById(id);
|
|
if (gruppeOpt.isEmpty()) return ResponseEntity.notFound().build();
|
|
GruppeEntity gruppe = gruppeOpt.get();
|
|
|
|
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
|
|
|
if (req.name() != null && !req.name().isBlank()) gruppe.setName(req.name().trim());
|
|
if (req.beschreibung() != null) gruppe.setBeschreibung(req.beschreibung());
|
|
if (req.bild() != null) gruppe.setBild(req.bild());
|
|
if (req.isPrivate() != null) gruppe.setPrivate(req.isPrivate());
|
|
gruppeRepository.save(gruppe);
|
|
LOGGER.debug("User {} hat Gruppe {} aktualisiert", myId, id);
|
|
|
|
return ResponseEntity.ok(toDto(gruppe, myId));
|
|
}
|
|
|
|
// ── DELETE /gruppe/{id} ──
|
|
|
|
@DeleteMapping("/{id}")
|
|
public ResponseEntity<Void> deleteGruppe(@PathVariable("id") UUID id, Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
var gruppeOpt = gruppeRepository.findById(id);
|
|
if (gruppeOpt.isEmpty()) return ResponseEntity.notFound().build();
|
|
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
|
|
|
// Cascade delete
|
|
List<GruppenbeitragEntity> beitraege = beitragRepository.findByGruppeIdOrderByCreatedAtDesc(id);
|
|
for (GruppenbeitragEntity b : beitraege) {
|
|
UUID bid = b.getBeitragId();
|
|
meldungRepository.deleteByBeitragId(bid);
|
|
stimmeRepository.deleteByBeitragId(bid);
|
|
optionRepository.deleteByBeitragId(bid);
|
|
likeRepository.deleteByBeitragId(bid);
|
|
// Kommentare on GROUP_POST
|
|
List<KommentarEntity> kommentare = kommentarRepository
|
|
.findByTargetTypeAndTargetIdOrderByCreatedAtAsc("GROUP_POST", bid);
|
|
for (KommentarEntity k : kommentare) {
|
|
kommentarRepository.delete(k);
|
|
}
|
|
}
|
|
beitragRepository.deleteByGruppeId(id);
|
|
anfrageRepository.deleteByGruppeId(id);
|
|
mitgliedRepository.deleteByGruppeId(id);
|
|
gruppeRepository.deleteById(id);
|
|
LOGGER.info("User {} hat Gruppe {} gelöscht", myId, id);
|
|
|
|
return ResponseEntity.noContent().build();
|
|
}
|
|
|
|
// ── POST /gruppe/{id}/join ──
|
|
|
|
@PostMapping("/{id}/join")
|
|
public ResponseEntity<Void> join(@PathVariable("id") UUID id,
|
|
@RequestBody(required = false) JoinRequest req,
|
|
Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
var gruppeOpt = gruppeRepository.findById(id);
|
|
if (gruppeOpt.isEmpty()) return ResponseEntity.notFound().build();
|
|
GruppeEntity gruppe = gruppeOpt.get();
|
|
|
|
if (mitgliedRepository.findFirstByGruppeIdAndUserId(id, myId).isPresent())
|
|
return ResponseEntity.status(409).build();
|
|
|
|
if (gruppe.isPrivate()) {
|
|
// Check no pending request already
|
|
var existingReq = anfrageRepository.findByGruppeIdAndUserId(id, myId);
|
|
if (existingReq.isPresent() && existingReq.get().getStatus() == AnfrageStatus.AUSSTEHEND)
|
|
return ResponseEntity.status(409).build();
|
|
|
|
BeitrittsanfrageEntity anfrage = new BeitrittsanfrageEntity();
|
|
anfrage.setAnfrageId(UUID.randomUUID());
|
|
anfrage.setGruppeId(id);
|
|
anfrage.setUserId(myId);
|
|
anfrage.setNachricht(req != null ? req.nachricht() : null);
|
|
anfrage.setAngefragtAt(LocalDateTime.now());
|
|
anfrage.setStatus(AnfrageStatus.AUSSTEHEND);
|
|
anfrageRepository.save(anfrage);
|
|
LOGGER.info("User {} hat Beitrittsanfrage für private Gruppe {} gestellt", myId, id);
|
|
return ResponseEntity.status(201).build();
|
|
} else {
|
|
GruppenmitgliedEntity mitglied = new GruppenmitgliedEntity();
|
|
mitglied.setMitgliedId(UUID.randomUUID());
|
|
mitglied.setGruppeId(id);
|
|
mitglied.setUserId(myId);
|
|
mitglied.setRolle(GruppenRolle.MITGLIED);
|
|
mitglied.setJoinedAt(LocalDateTime.now());
|
|
mitgliedRepository.save(mitglied);
|
|
LOGGER.info("User {} ist Gruppe {} beigetreten", myId, id);
|
|
return ResponseEntity.status(201).build();
|
|
}
|
|
}
|
|
|
|
// ── DELETE /gruppe/{id}/leave ──
|
|
|
|
@DeleteMapping("/{id}/leave")
|
|
public ResponseEntity<Void> leave(@PathVariable("id") UUID id, Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
mitgliedRepository.deleteByGruppeIdAndUserId(id, myId);
|
|
LOGGER.info("User {} hat Gruppe {} verlassen", myId, id);
|
|
return ResponseEntity.noContent().build();
|
|
}
|
|
|
|
// ── GET /gruppe/{id}/members ──
|
|
|
|
@GetMapping("/{id}/members")
|
|
public ResponseEntity<List<Map<String, Object>>> getMembers(@PathVariable("id") UUID id, Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
if (mitgliedRepository.findFirstByGruppeIdAndUserId(id, myId).isEmpty())
|
|
return ResponseEntity.status(403).build();
|
|
|
|
List<Map<String, Object>> result = mitgliedRepository.findByGruppeId(id).stream()
|
|
.map(m -> {
|
|
Map<String, Object> map = new LinkedHashMap<>();
|
|
map.put("mitgliedId", m.getMitgliedId());
|
|
map.put("userId", m.getUserId());
|
|
map.put("rolle", m.getRolle().name());
|
|
map.put("joinedAt", m.getJoinedAt());
|
|
userRepository.findById(m.getUserId()).ifPresent(u -> {
|
|
map.put("userName", u.getName());
|
|
map.put("userPicture", u.getProfilePicture());
|
|
});
|
|
return map;
|
|
})
|
|
.toList();
|
|
return ResponseEntity.ok(result);
|
|
}
|
|
|
|
// ── DELETE /gruppe/{id}/members/{userId} ──
|
|
|
|
@DeleteMapping("/{id}/members/{userId}")
|
|
public ResponseEntity<Void> removeMember(@PathVariable("id") UUID id,
|
|
@PathVariable("userId") UUID userId,
|
|
Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
|
|
|
mitgliedRepository.deleteByGruppeIdAndUserId(id, userId);
|
|
LOGGER.warn("Admin {} hat User {} aus Gruppe {} entfernt", myId, userId, id);
|
|
return ResponseEntity.noContent().build();
|
|
}
|
|
|
|
// ── POST /gruppe/{id}/members/{userId}/promote ──
|
|
|
|
@PostMapping("/{id}/members/{userId}/promote")
|
|
public ResponseEntity<Void> promote(@PathVariable("id") UUID id,
|
|
@PathVariable("userId") UUID userId,
|
|
Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
|
|
|
var m = mitgliedRepository.findFirstByGruppeIdAndUserId(id, userId);
|
|
if (m.isEmpty()) return ResponseEntity.notFound().build();
|
|
m.get().setRolle(GruppenRolle.ADMIN);
|
|
mitgliedRepository.save(m.get());
|
|
LOGGER.info("Admin {} hat User {} in Gruppe {} zum Admin befördert", myId, userId, id);
|
|
return ResponseEntity.ok().build();
|
|
}
|
|
|
|
// ── GET /gruppe/{id}/requests ──
|
|
|
|
@GetMapping("/{id}/requests")
|
|
public ResponseEntity<List<BeitrittsanfrageDto>> getRequests(@PathVariable("id") UUID id, Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
|
|
|
List<BeitrittsanfrageDto> dtos = anfrageRepository
|
|
.findByGruppeIdAndStatus(id, AnfrageStatus.AUSSTEHEND)
|
|
.stream()
|
|
.map(a -> {
|
|
UserEntity u = userRepository.findById(a.getUserId()).orElse(null);
|
|
return new BeitrittsanfrageDto(a.getAnfrageId(), a.getGruppeId(), a.getUserId(),
|
|
u != null ? u.getName() : "Unbekannt",
|
|
u != null ? u.getProfilePicture() : null,
|
|
a.getNachricht(), a.getAngefragtAt());
|
|
})
|
|
.toList();
|
|
return ResponseEntity.ok(dtos);
|
|
}
|
|
|
|
// ── POST /gruppe/{id}/requests/{reqId}/approve ──
|
|
|
|
@PostMapping("/{id}/requests/{reqId}/approve")
|
|
public ResponseEntity<Void> approveRequest(@PathVariable("id") UUID id,
|
|
@PathVariable("reqId") UUID reqId,
|
|
Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
|
|
|
var anfOpt = anfrageRepository.findById(reqId);
|
|
if (anfOpt.isEmpty()) return ResponseEntity.notFound().build();
|
|
BeitrittsanfrageEntity anfrage = anfOpt.get();
|
|
anfrage.setStatus(AnfrageStatus.GENEHMIGT);
|
|
anfrageRepository.save(anfrage);
|
|
LOGGER.info("Admin {} hat Beitrittsanfrage {} (User: {}) für Gruppe {} genehmigt", myId, reqId, anfrage.getUserId(), id);
|
|
|
|
if (mitgliedRepository.findFirstByGruppeIdAndUserId(id, anfrage.getUserId()).isEmpty()) {
|
|
GruppenmitgliedEntity mitglied = new GruppenmitgliedEntity();
|
|
mitglied.setMitgliedId(UUID.randomUUID());
|
|
mitglied.setGruppeId(id);
|
|
mitglied.setUserId(anfrage.getUserId());
|
|
mitglied.setRolle(GruppenRolle.MITGLIED);
|
|
mitglied.setJoinedAt(LocalDateTime.now());
|
|
mitgliedRepository.save(mitglied);
|
|
}
|
|
|
|
return ResponseEntity.ok().build();
|
|
}
|
|
|
|
// ── DELETE /gruppe/{id}/requests/{reqId} ──
|
|
|
|
@DeleteMapping("/{id}/requests/{reqId}")
|
|
public ResponseEntity<Void> rejectRequest(@PathVariable("id") UUID id,
|
|
@PathVariable("reqId") UUID reqId,
|
|
Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
if (!isAdmin(id, myId)) return ResponseEntity.status(403).build();
|
|
|
|
var anfOpt = anfrageRepository.findById(reqId);
|
|
if (anfOpt.isEmpty()) return ResponseEntity.notFound().build();
|
|
BeitrittsanfrageEntity anfrage = anfOpt.get();
|
|
anfrage.setStatus(AnfrageStatus.ABGELEHNT);
|
|
anfrageRepository.save(anfrage);
|
|
LOGGER.debug("Admin {} hat Beitrittsanfrage {} für Gruppe {} abgelehnt", myId, reqId, id);
|
|
return ResponseEntity.noContent().build();
|
|
}
|
|
|
|
// ── GET /gruppen/reports/pending/count ──
|
|
|
|
@GetMapping("/reports/pending/count")
|
|
public ResponseEntity<Long> pendingReportsCount(Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
long count = mitgliedRepository.findByUserId(myId).stream()
|
|
.filter(m -> m.getRolle() == GruppenRolle.ADMIN)
|
|
.mapToLong(m -> {
|
|
List<GruppenbeitragEntity> beitraege = beitragRepository.findByGruppeIdOrderByCreatedAtDesc(m.getGruppeId());
|
|
List<UUID> ids = beitraege.stream().map(GruppenbeitragEntity::getBeitragId).toList();
|
|
return ids.isEmpty() ? 0L : meldungRepository.findByBeitragIdIn(ids).size();
|
|
})
|
|
.sum();
|
|
return ResponseEntity.ok(count);
|
|
}
|
|
|
|
// ── GET /gruppen/requests/pending/count ──
|
|
|
|
@GetMapping("/requests/pending/count")
|
|
public ResponseEntity<Long> pendingRequestCount(Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
long count = mitgliedRepository.findByUserId(myId).stream()
|
|
.filter(m -> m.getRolle() == GruppenRolle.ADMIN)
|
|
.mapToLong(m -> anfrageRepository.findByGruppeIdAndStatus(m.getGruppeId(), AnfrageStatus.AUSSTEHEND).size())
|
|
.sum();
|
|
return ResponseEntity.ok(count);
|
|
}
|
|
|
|
// ── GET /gruppe/requests/mine ──
|
|
|
|
@GetMapping("/requests/mine")
|
|
public ResponseEntity<List<Map<String, Object>>> myRequests(Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
List<Map<String, Object>> result = anfrageRepository.findByUserIdAndStatus(myId, AnfrageStatus.AUSSTEHEND)
|
|
.stream()
|
|
.map(a -> {
|
|
Map<String, Object> map = new LinkedHashMap<>();
|
|
map.put("anfrageId", a.getAnfrageId());
|
|
map.put("gruppeId", a.getGruppeId());
|
|
map.put("nachricht", a.getNachricht());
|
|
map.put("angefragtAt", a.getAngefragtAt());
|
|
gruppeRepository.findById(a.getGruppeId()).ifPresent(g -> map.put("gruppeName", g.getName()));
|
|
return map;
|
|
})
|
|
.toList();
|
|
return ResponseEntity.ok(result);
|
|
}
|
|
|
|
// ── DELETE /gruppe/{id}/requests/mine (withdraw own request) ──
|
|
|
|
@DeleteMapping("/{id}/requests/mine")
|
|
public ResponseEntity<Void> withdrawRequest(@PathVariable("id") UUID id, Principal principal) {
|
|
UUID myId = resolveMyId(principal);
|
|
if (myId == null) return ResponseEntity.status(401).build();
|
|
|
|
anfrageRepository.findByGruppeIdAndUserId(id, myId).ifPresent(a -> {
|
|
if (a.getStatus() == AnfrageStatus.AUSSTEHEND) {
|
|
anfrageRepository.delete(a);
|
|
LOGGER.debug("User {} hat eigene Beitrittsanfrage für Gruppe {} zurückgezogen", myId, id);
|
|
}
|
|
});
|
|
return ResponseEntity.noContent().build();
|
|
}
|
|
|
|
// ── Helpers ──
|
|
|
|
private Map<UUID, LocalDateTime> buildLatestActivityMap(List<UUID> gruppeIds) {
|
|
if (gruppeIds.isEmpty()) return Map.of();
|
|
Map<UUID, LocalDateTime> map = new HashMap<>();
|
|
beitragRepository.findLatestCreatedAtByGruppeIds(gruppeIds).forEach(row -> {
|
|
UUID gId = (UUID) row[0];
|
|
LocalDateTime latest = (LocalDateTime) row[1];
|
|
map.put(gId, latest);
|
|
});
|
|
return map;
|
|
}
|
|
|
|
|
|
private boolean isAdmin(UUID gruppeId, UUID userId) {
|
|
return mitgliedRepository.findFirstByGruppeIdAndUserId(gruppeId, userId)
|
|
.map(m -> m.getRolle() == GruppenRolle.ADMIN)
|
|
.orElse(false);
|
|
}
|
|
|
|
GruppeDto toDto(GruppeEntity g, UUID myId) {
|
|
long memberCount = mitgliedRepository.countByGruppeId(g.getGruppeId());
|
|
long postCount = beitragRepository.findByGruppeIdOrderByCreatedAtDesc(g.getGruppeId()).size();
|
|
String myRole = mitgliedRepository.findFirstByGruppeIdAndUserId(g.getGruppeId(), myId)
|
|
.map(m -> m.getRolle().name())
|
|
.orElse(null);
|
|
String myRequestStatus = null;
|
|
if (myRole == null) {
|
|
myRequestStatus = anfrageRepository.findByGruppeIdAndUserId(g.getGruppeId(), myId)
|
|
.filter(a -> a.getStatus() == AnfrageStatus.AUSSTEHEND)
|
|
.map(a -> a.getStatus().name())
|
|
.orElse(null);
|
|
}
|
|
return new GruppeDto(g.getGruppeId(), g.getName(), g.getBeschreibung(), g.getBild(),
|
|
g.isPrivate(), g.getCreatedAt(), memberCount, postCount, myRole, myRequestStatus);
|
|
}
|
|
}
|