Prelegent widzi zadania i banery na sali
`PublicTaskOfferController` szukal tokenu wylacznie w `registrations`, a prelegent tam nie istnieje: nie przechodzi przez formularz zapisu i ma wlasny token w `webinar_speakers`. Kazdy endpoint sali odpowiadal mu 404. Objawialo sie to tym, ze prowadzacy **nie widzial wlasnych zadan**: panel pokazywal "Nie znaleziono zapisu" przy zadaniu ogloszonym minute wczesniej i widocznym w panelu prowadzenia. Tak samo znikaly banery i nie liczyly sie ich wyswietlenia. Zdarzylo sie to na zywo, w trakcie spotkania. Nowa metoda `TaskService.viewer` obsluguje oba rodzaje tokenu, wzorowana na `PublicInteractionController`, ktory robil to juz przy historii czatu. Przelaczone sa WYLACZNIE odczyty: lista zadan, banery i ich zdarzenia. Zapisy (zgloszenie do zadania, wyslanie oferty) zostaja przy `participant`, bo prelegent nie zapisuje sie na wlasne zadanie. `registrationId` rowne null jest tu poprawna wartoscia, nie brakiem danych: `listViews` przewidywalo to od poczatku, a `banner_events.registration_id` jest nullowalne wlasnie dla zdarzen od osob bez zapisu. Front: `TasksTab` dostaje tryb `readOnly`, wiec prowadzacy widzi zadania i liczbe zapisanych, ale bez przycisku zgloszenia. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+8
-4
@@ -67,7 +67,9 @@ public class PublicTaskOfferController {
|
||||
@GetMapping("/tasks")
|
||||
@Operation(summary = "Zadania webinaru i wlasne zgloszenia")
|
||||
public TasksView taskList(@PathVariable String token) {
|
||||
TaskService.ParticipantDetails participant = participant(token);
|
||||
// odczyt, wiec takze dla prelegenta: prowadzacy ma widziec zadania,
|
||||
// ktore sam oglosil
|
||||
TaskService.ParticipantDetails participant = tasks.viewer(token);
|
||||
return new TasksView(tasks.listViews(participant.webinarId(), participant.registrationId()));
|
||||
}
|
||||
|
||||
@@ -153,7 +155,7 @@ public class PublicTaskOfferController {
|
||||
@GetMapping("/banners")
|
||||
@Operation(summary = "Banery obowiazujace w tej chwili dla tego webinaru")
|
||||
public BannersView activeBanners(@PathVariable String token) {
|
||||
TaskService.ParticipantDetails participant = participant(token);
|
||||
TaskService.ParticipantDetails participant = tasks.viewer(token);
|
||||
return new BannersView(
|
||||
banners.activeFor(participant.webinarId()),
|
||||
banners.rotationSeconds());
|
||||
@@ -169,7 +171,9 @@ public class PublicTaskOfferController {
|
||||
@PostMapping("/banners/{bannerId}/impression")
|
||||
@Operation(summary = "Zapis wyswietlenia banera, raz na uczestnika")
|
||||
public void bannerImpression(@PathVariable String token, @PathVariable Long bannerId) {
|
||||
TaskService.ParticipantDetails participant = participant(token);
|
||||
// takze prelegent: `banner_events.registration_id` jest nullowalne
|
||||
// wlasnie po to, bo zdarzenie moze pochodzic od osoby bez zapisu
|
||||
TaskService.ParticipantDetails participant = tasks.viewer(token);
|
||||
banners.recordImpression(bannerId, participant.registrationId());
|
||||
}
|
||||
|
||||
@@ -177,7 +181,7 @@ public class PublicTaskOfferController {
|
||||
@PostMapping("/banners/{bannerId}/click")
|
||||
@Operation(summary = "Zapis klikniecia w baner")
|
||||
public void bannerClick(@PathVariable String token, @PathVariable Long bannerId) {
|
||||
TaskService.ParticipantDetails participant = participant(token);
|
||||
TaskService.ParticipantDetails participant = tasks.viewer(token);
|
||||
banners.recordClick(bannerId, participant.registrationId());
|
||||
}
|
||||
|
||||
|
||||
@@ -40,19 +40,22 @@ public class TaskService {
|
||||
private final WebinarRepository webinarRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final PlainTextSanitizer sanitizer;
|
||||
private final com.softspm.webinar.repository.WebinarSpeakerRepository speakerRepository;
|
||||
|
||||
public TaskService(TaskRepository taskRepository,
|
||||
InteractionRepository interactionRepository,
|
||||
RegistrationRepository registrationRepository,
|
||||
WebinarRepository webinarRepository,
|
||||
UserRepository userRepository,
|
||||
PlainTextSanitizer sanitizer) {
|
||||
PlainTextSanitizer sanitizer,
|
||||
com.softspm.webinar.repository.WebinarSpeakerRepository speakerRepository) {
|
||||
this.taskRepository = taskRepository;
|
||||
this.interactionRepository = interactionRepository;
|
||||
this.registrationRepository = registrationRepository;
|
||||
this.webinarRepository = webinarRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.sanitizer = sanitizer;
|
||||
this.speakerRepository = speakerRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -265,6 +268,43 @@ public class TaskService {
|
||||
* Odczyt jest w serwisie, a nie w kontrolerze: @Transactional na metodzie
|
||||
* wolanej z tej samej klasy nie dziala, bo samowywolanie omija proxy Springa.
|
||||
*/
|
||||
/**
|
||||
* Osoba na sali: uczestnik ALBO prelegent.
|
||||
*
|
||||
* DWA RODZAJE TOKENU, JEDNO WEJSCIE
|
||||
* -----------------------------------------------------------------------
|
||||
* Prelegent nie jest wierszem w `registrations`: nie przechodzi przez
|
||||
* formularz zapisu i ma wlasny token w `webinar_speakers`. Metoda
|
||||
* `participant` szuka wylacznie zapisu, wiec kazdy endpoint sali oparty
|
||||
* na niej odpowiadal prelegentowi bledem 404. Objawialo sie to tym, ze
|
||||
* prowadzacy **nie widzial wlasnych zadan** ani banerow, a panel pokazywal
|
||||
* "Nie znaleziono zapisu" przy poprawnie ogloszonym zadaniu.
|
||||
*
|
||||
* `registrationId` rowne null oznacza prelegenta i jest **poprawna
|
||||
* wartoscia**, nie brakiem danych: `listViews` traktuje go jako osobe bez
|
||||
* wlasnych zgloszen, bo prelegent nie zapisuje sie na wlasne zadanie.
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public ParticipantDetails viewer(String token) {
|
||||
return registrationRepository.findByConfirmationToken(token)
|
||||
.map(registration -> new ParticipantDetails(
|
||||
registration.getId(),
|
||||
registration.getWebinar().getId(),
|
||||
(registration.getFirstName() + " " + registration.getLastName()).trim(),
|
||||
registration.getEmail(),
|
||||
registration.getPhone(),
|
||||
registration.getCompany()))
|
||||
.orElseGet(() -> speakerRepository.findByAccessToken(token)
|
||||
.map(speaker -> new ParticipantDetails(
|
||||
null,
|
||||
speaker.getWebinar().getId(),
|
||||
speaker.getFullName(),
|
||||
speaker.getEmail(),
|
||||
null,
|
||||
null))
|
||||
.orElseThrow(() -> new NotFoundException("Nie znaleziono zapisu")));
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public ParticipantDetails participant(String confirmationToken) {
|
||||
Registration registration = registrationRepository.findByConfirmationToken(confirmationToken)
|
||||
|
||||
Reference in New Issue
Block a user