Skip to content

Commit b885bf9

Browse files
committed
fix: #212 confirm unsubscribe and skip already completed enrollments
1 parent 5f5f681 commit b885bf9

5 files changed

Lines changed: 30 additions & 4 deletions

File tree

django_email_learning/jobs/deliver_contents_job.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,16 @@ def run(self) -> None:
4646
job_execution.finished_at = timezone.now()
4747
job_execution.save()
4848
else:
49-
self.process_delivery(delivery_schedule)
49+
try:
50+
self.process_delivery(delivery_schedule)
51+
except Exception as e:
52+
# Unhandled exception during delivery processing should not crash the job.
53+
# We log the error and mark the delivery as blocked to prevent further attempts until manual intervention.
54+
delivery_schedule.status = DeliveryStatus.BLOCKED
55+
delivery_schedule.save()
56+
logger.exception(
57+
f"Error processing delivery schedule: {str(e)}. Continuing with next task."
58+
)
5059

5160
def get_delivery_queue(self) -> DeliveryQueueProtocol:
5261
try:

django_email_learning/personalised/views.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,16 @@ def get(self, request, *args, **kwargs) -> HttpResponse: # type: ignore[no-unty
184184
decoded_token = self.get_decoded_token(request)
185185
if isinstance(decoded_token, HttpResponse):
186186
return decoded_token # Return error response if token is invalid
187+
if request.GET.get("confirm") != "true":
188+
return self.render_to_response(
189+
context={
190+
"page_title": _("Confirm Unsubscription"),
191+
"confirmation_message": _(
192+
"Are you sure you want to unsubscribe from our mailing list?"
193+
),
194+
"confirm_url": f"{request.path}?token={request.GET.get('token')}&confirm=true",
195+
}
196+
)
187197
command = UnsubscribeCommand(
188198
email=decoded_token["email"],
189199
course_slug=decoded_token["course_slug"],

django_email_learning/services/command_models/unsubscribe_command.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def execute(self) -> None:
4747
return
4848

4949
enrollments = Enrollment.objects.filter(learner=learner, course=course).exclude(
50-
status=EnrollmentStatus.DEACTIVATED
50+
status__in=[EnrollmentStatus.DEACTIVATED, EnrollmentStatus.COMPLETED]
5151
)
5252
if not enrollments.exists():
5353
self.logger.warning(

django_email_learning/templates/personalised/command_result.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
{% block head_script %}
55
<script>
66
const success_message = "{{ success_message|escapejs }}";
7+
const confirmation_message = "{{ confirmation_message|escapejs }}";
8+
const confirm_url = "{{ confirm_url|escapejs }}";
9+
const localeMessages = {
10+
"Confirm": "{% translate 'Confirm' %}",
11+
}
712
</script>
813
{% vite_asset 'personalised/command_result/CommandResult.jsx' %}
914
{% endblock %}

frontend/personalised/command_result/CommandResult.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
import { Alert, Box } from '@mui/material';
1+
import { Alert, Box, Button } from '@mui/material';
22
import render from '../../src/render.jsx';
33
import Layout from '../../public/components/Layout.jsx';
44

55

66
const CommandResult = () => {
77
return <Layout>
8-
{ !error_message ?<Alert severity='success' sx={{ maxWidth: 800, margin: '0 auto', backgroundColor: "background.light" }}>
8+
{ !error_message && !confirmation_message ?<Alert severity='success' sx={{ maxWidth: 800, margin: '0 auto', backgroundColor: "background.light" }}>
99
{success_message}
10+
</Alert> : confirmation_message ? <Alert severity="warning" sx={{ maxWidth: 800, margin: '20px auto' }}>
11+
{confirmation_message}<Box mt={2}><Button href={confirm_url} variant='contained' mt={2}>{localeMessages["Confirm"]}</Button></Box>
1012
</Alert> : <Alert severity="error" sx={{ maxWidth: 800, margin: '20px auto' }}>
1113
{error_message} (ref: {ref})
1214
</Alert>}

0 commit comments

Comments
 (0)