Found by an end-to-end run against a live Gotify container:
- action_code / NotificationLink.action_code were SlugField, which rejects
dots. Every documented action_code (billboard.approved, escrow.timeout,
...) is dotted, so any real request using the catalog got a 400 before
this fix -- only click_url ever worked. Switched both to CharField with
a validator that keeps slug's charset but allows ".".
- send_push_notification set push_message.state instead of .stats after a
successful send, so PushMessage.stats stayed stuck at INIT forever
regardless of delivery outcome. Fixed the attribute name and scoped the
save with update_fields.
Verified live: POST with a dotted action_code now resolves through
NotificationLink and lands in Gotify with the correct click.url, and the
PushMessage row flips to DONE.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Not every notification is clickable, so click_url is optional end to end
(null/blank on the model, required=False on the serializer). When set, it's
merged into Gotify's own client::notification.click.url extras convention
without disturbing any other extras a producer already sends, so official
Gotify clients can open it on tap. Wired through both message-creation
paths: the single-push REST API and the bulk Excel upload. Also fixes a
pre-existing NameError in the bulk path (json.loads(extras) referenced an
undefined name instead of extras_str).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>