Files
training-software/notifications/admin.py
Paperclip CTO 6384eac890
Some checks failed
CI / Tests (Python 3.12) (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / OpenAPI Schema (push) Has been cancelled
feat(TRA-245): Notification service with email and in-app delivery
- Notification model with idempotency_key dedup (unique per event+object+recipient)
- NotificationDelivery audit model (pending/sent/failed/delivered per channel)
- notify() service: creates notification idempotently, enqueues per-channel tasks
- deliver_notification_task Celery task: sends email via send_mail, marks in-app
  as sent without email; marks FAILED with error_detail on exception (autoretry x3)
- Event trigger helpers: notify_course_assigned, notify_attempt_limit_reached,
  notify_certificate_issued, notify_certificate_expiring (daily-reminder safe)
- send_course_due_reminders_task: periodic Celery Beat stub for due-date alerts
- REST API: list notifications (with ?unread=true filter), mark-read, mark-all-read
- Admin registrations with inline delivery audit view
- Initial migration (Notification + NotificationDelivery tables)
- Pytest test suite: idempotency, delivery dispatch, view auth/filtering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 09:34:24 +02:00

30 lines
997 B
Python

from django.contrib import admin
from .models import Notification, NotificationDelivery
class NotificationDeliveryInline(admin.TabularInline):
model = NotificationDelivery
extra = 0
readonly_fields = ["channel", "status", "sent_at", "error_detail", "created_at"]
@admin.register(Notification)
class NotificationAdmin(admin.ModelAdmin):
list_display = ["title", "event_type", "recipient", "is_read", "created_at"]
list_filter = ["event_type"]
search_fields = ["title", "recipient__email", "idempotency_key"]
readonly_fields = ["id", "idempotency_key", "created_at", "read_at"]
inlines = [NotificationDeliveryInline]
@admin.display(boolean=True)
def is_read(self, obj):
return obj.is_read
@admin.register(NotificationDelivery)
class NotificationDeliveryAdmin(admin.ModelAdmin):
list_display = ["notification", "channel", "status", "sent_at", "created_at"]
list_filter = ["channel", "status"]
readonly_fields = ["id", "created_at"]