diff --git a/app/Domains/Event/Actions/SendMissingPaymentMails/SendMissingPaymentMailsCommand.php b/app/Domains/Event/Actions/SendMissingPaymentMails/SendMissingPaymentMailsCommand.php new file mode 100644 index 0000000..6cb00c0 --- /dev/null +++ b/app/Domains/Event/Actions/SendMissingPaymentMails/SendMissingPaymentMailsCommand.php @@ -0,0 +1,37 @@ +request->eventParticipants->getParticipantsWithMissingPayments($this->request->event, $this->request->httpRequest) as $participant) { + $participantResource = $participant->toResource()->toArray($this->request->httpRequest); + if (!$participantResource['needs_payment']) { + continue; + } + + Mail::to($participant->email_1)->send(new ParticipantPaymentMissingPaymentMail( + participant: $participant, + )); + + if ($participant->email_2 !== null && $participant->email_2 !== $participant->email_1) { + Mail::to($participant->email_2)->send(new ParticipantPaymentMissingPaymentMail( + participant: $participant, + )); + } + + $response->remindedParticipants++; + } + + $response->success = true; + + return $response; + } +} diff --git a/app/Domains/Event/Actions/SendMissingPaymentMails/SendMissingPaymentMailsRequest.php b/app/Domains/Event/Actions/SendMissingPaymentMails/SendMissingPaymentMailsRequest.php new file mode 100644 index 0000000..d4e465a --- /dev/null +++ b/app/Domains/Event/Actions/SendMissingPaymentMails/SendMissingPaymentMailsRequest.php @@ -0,0 +1,16 @@ +events->getById($eventId); + public function __invoke(string $eventId) { + $event = $this->events->getByIdentifier($eventId); return new InertiaProvider('Event/Details', ['event' => $event])->render(); } diff --git a/app/Domains/Event/Controllers/PaymentReminderController.php b/app/Domains/Event/Controllers/PaymentReminderController.php new file mode 100644 index 0000000..f85b5f5 --- /dev/null +++ b/app/Domains/Event/Controllers/PaymentReminderController.php @@ -0,0 +1,33 @@ +events->getByIdentifier($eventIdentifier, true); + + $sendPaymentReminderMailsRequest = new SendMissingPaymentMailsRequest( + event: $event, + eventParticipants: $this->eventParticipants, + httpRequest: $request + ); + + $sendPaymentReminderMailsCommand = new SendMissingPaymentMailsCommand(request: $sendPaymentReminderMailsRequest); + $sendPaymentReminderResponse = $sendPaymentReminderMailsCommand->execute(); + + return response()->json([ + 'success' => $sendPaymentReminderResponse->success, + 'message' => $sendPaymentReminderResponse->success ? + sprintf('Es wurden %1$s Personen über fehlende Teilnahmebeiträge informiert', $sendPaymentReminderResponse->remindedParticipants) : + 'Beim Senden der Benachrichtigungen ist ein Fehler aufgetreten.', + + ]); + } +} diff --git a/app/Domains/Event/Routes/api.php b/app/Domains/Event/Routes/api.php index 8e9e817..8fbfd52 100644 --- a/app/Domains/Event/Routes/api.php +++ b/app/Domains/Event/Routes/api.php @@ -9,6 +9,7 @@ use App\Domains\Event\Controllers\ParticipantPaymentController; use App\Domains\Event\Controllers\ParticipantReSignOnController; use App\Domains\Event\Controllers\ParticipantSignOffController; use App\Domains\Event\Controllers\ParticipantUpdateController; +use App\Domains\Event\Controllers\PaymentReminderController; use App\Domains\Event\Controllers\SignupController; use App\Middleware\IdentifyTenant; use Illuminate\Support\Facades\Route; @@ -28,6 +29,8 @@ Route::prefix('api/v1') Route::post('/send', SendController::class); }); + Route::get('{eventIdentifier}/send-payment-reminder', PaymentReminderController::class); + Route::prefix('/details/{eventId}') ->group(function () { Route::get('/summary', [DetailsController::class, 'summary']); diff --git a/app/Domains/Event/Views/Create.vue b/app/Domains/Event/Views/Create.vue index 6d62896..2c3c359 100644 --- a/app/Domains/Event/Views/Create.vue +++ b/app/Domains/Event/Views/Create.vue @@ -161,17 +161,16 @@ }); if (data.status !== 'success') { - toas.error(data.message); + toast.error(data.message); return false; } else { - console.log(data.event); newEvent.value = data.event; showParticipationFees.value = true; } } async function finishCreation() { - window.location.href = '/event/details/' + newEvent.value.id; + window.location.href = '/event/details/' + newEvent.value.identifier; } diff --git a/app/Domains/Event/Views/Partials/MailCompose.vue b/app/Domains/Event/Views/Partials/MailCompose.vue index 6f56e03..cd8a2f0 100644 --- a/app/Domains/Event/Views/Partials/MailCompose.vue +++ b/app/Domains/Event/Views/Partials/MailCompose.vue @@ -4,6 +4,7 @@ import {useAjax} from "../../../../../resources/js/components/ajaxHandler.js"; import TextEditor from "../../../../Views/Components/TextEditor.vue"; import ErrorText from "../../../../Views/Components/ErrorText.vue"; import {toast} from "vue3-toastify"; +import InfoText from "../../../../Views/Components/InfoText.vue"; const { request } = useAjax(); @@ -37,6 +38,7 @@ onMounted(async () => { }); const errorMessage = ref(null) +const infoMessage = ref(null) const emit = defineEmits([ 'closeComposer', @@ -49,6 +51,10 @@ function close() { async function sendMail() { + document.getElementById('sendMessageButton').style.display = 'none'; + infoMessage.value = 'Die Rundmail wird nun gesendet. Dies kann einen Moment dauern. Bitte verlasse diese Seite nicht.' + + toast.info('Die Rundmail wird nun gesendet. Dies kann einen Moment dauern. Bitte verlasse diese Seite nicht.') const response = await request('/api/v1/event/' + props.event.identifier + '/mailing/send', { method: "POST", body: { @@ -59,10 +65,14 @@ async function sendMail() { }); if (response.success) { + infoMessage.value = null + document.getElementById('sendMessageButton').style.display = 'block'; close(); toast.success(response.message) } else { + infoMessage.value = null + document.getElementById('sendMessageButton').style.display = 'block'; errorMessage.value = response.message toast.error(response.message) } @@ -94,8 +104,8 @@ const form = reactive({ - - + + diff --git a/app/Domains/Event/Views/Partials/Overview.vue b/app/Domains/Event/Views/Partials/Overview.vue index 2811c17..22937a1 100644 --- a/app/Domains/Event/Views/Partials/Overview.vue +++ b/app/Domains/Event/Views/Partials/Overview.vue @@ -7,6 +7,7 @@ import Modal from "../../../../Views/Components/Modal.vue"; import MailCompose from "./MailCompose.vue"; import FullScreenModal from "../../../../Views/Components/FullScreenModal.vue"; + import {toast} from "vue3-toastify"; const props = defineProps({ data: Object, @@ -54,6 +55,17 @@ function mailToGroup() { mailCompose.value = true } + + async function sendPaymentReminder() { + toast.info("Die Nachrichten werden gesendet. Bitte verlasse diese Seite nicht."); + const response = await fetch("/api/v1/event/" + props.data.event.identifier + "/send-payment-reminder/" ); + const data = await response.json(); + if (data.success) { + toast.success(data.message) + } else { + toast.error(data.message) + } + }