From ce7c78bda9067109439407bbc76aafcc243a9a30 Mon Sep 17 00:00:00 2001 From: Maciej Pienczyn Date: Tue, 27 Jan 2026 14:22:44 +0100 Subject: [PATCH] feat(notifications): Add notifications for releases and announcements - notify_all_users_release(): Notify all users about new system version - notify_all_users_announcement(): Notify all users about new announcement - Auto-send notifications when admin publishes an announcement - New admin endpoint POST /admin/notify-release for manual release notifications - Category-specific icons for announcement notifications Co-Authored-By: Claude Opus 4.5 --- app.py | 37 +++++++++++++++- utils/__init__.py | 4 +- utils/notifications.py | 98 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 2 deletions(-) diff --git a/app.py b/app.py index aae911b..cf72f81 100644 --- a/app.py +++ b/app.py @@ -9610,6 +9610,32 @@ def release_notes(): return render_template('release_notes.html', releases=releases, stats=stats) +@app.route('/admin/notify-release', methods=['POST']) +@login_required +def admin_notify_release(): + """ + Send notifications to all users about a new release. + Called manually by admin after deploying a new version. + """ + if not current_user.is_admin: + return jsonify({'success': False, 'error': 'Brak uprawnień'}), 403 + + data = request.get_json() or {} + version = data.get('version') + highlights = data.get('highlights', []) + + if not version: + return jsonify({'success': False, 'error': 'Brak wersji'}), 400 + + from utils.notifications import notify_all_users_release + count = notify_all_users_release(version=version, highlights=highlights) + + return jsonify({ + 'success': True, + 'message': f'Wysłano {count} powiadomień o wersji {version}' + }) + + # ============================================================ # ZIELONY OKRĘG PRZEMYSŁOWY KASZUBIA (ZOPK) # ============================================================ @@ -13267,7 +13293,16 @@ def admin_announcements_publish(id): announcement.updated_at = datetime.now() db.commit() - return jsonify({'success': True, 'message': 'Ogłoszenie zostało opublikowane'}) + # Notify all users about new announcement + from utils.notifications import notify_all_users_announcement + notify_count = notify_all_users_announcement( + announcement_id=announcement.id, + title=announcement.title, + category=announcement.category + ) + logger.info(f"Sent {notify_count} notifications for announcement: {announcement.title}") + + return jsonify({'success': True, 'message': f'Ogłoszenie zostało opublikowane. Wysłano {notify_count} powiadomień.'}) except Exception as e: db.rollback() diff --git a/utils/__init__.py b/utils/__init__.py index 641c7fe..1bb3991 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -11,7 +11,9 @@ from .notifications import ( create_notification, create_news_notification, create_message_notification, - create_event_notification + create_event_notification, + notify_all_users_release, + notify_all_users_announcement ) from .analytics import ( get_or_create_analytics_session, diff --git a/utils/notifications.py b/utils/notifications.py index 0b9d229..abd2d73 100644 --- a/utils/notifications.py +++ b/utils/notifications.py @@ -121,3 +121,101 @@ def create_event_notification(user_id, event_title, event_id): related_id=event_id, action_url=f"/kalendarz/{event_id}" ) + + +def notify_all_users_release(version, highlights=None): + """ + Notify all active users about a new system release. + + Args: + version: Version string (e.g., 'v1.17.0') + highlights: Optional list of key changes to include in notification + + Returns: + Number of notifications created + """ + db = SessionLocal() + try: + # Get all active users + users = db.query(User).filter(User.is_active == True).all() + + message = f"Wersja {version} jest już dostępna." + if highlights: + # Include first 2 highlights + message += " Nowości: " + ", ".join(highlights[:2]) + if len(highlights) > 2: + message += f" (+{len(highlights) - 2} więcej)" + + count = 0 + for user in users: + result = create_notification( + user_id=user.id, + title=f"🚀 Nowa wersja systemu {version}", + message=message, + notification_type='system', + related_type='release', + related_id=None, + action_url='/release-notes' + ) + if result: + count += 1 + + logger.info(f"Created {count} release notifications for version {version}") + return count + + except Exception as e: + logger.error(f"Error creating release notifications: {e}") + return 0 + finally: + db.close() + + +def notify_all_users_announcement(announcement_id, title, category=None): + """ + Notify all active users about a new announcement. + + Args: + announcement_id: ID of the announcement + title: Title of the announcement + category: Optional category for context + + Returns: + Number of notifications created + """ + db = SessionLocal() + try: + # Get all active users + users = db.query(User).filter(User.is_active == True).all() + + # Category-specific icons + category_icons = { + 'general': '📢', + 'event': '📅', + 'business_opportunity': '💼', + 'member_news': '👥', + 'partnership': '🤝' + } + icon = category_icons.get(category, '📢') + + count = 0 + for user in users: + result = create_notification( + user_id=user.id, + title=f"{icon} Nowe ogłoszenie w Aktualnościach", + message=title[:100] + ('...' if len(title) > 100 else ''), + notification_type='news', + related_type='announcement', + related_id=announcement_id, + action_url=f'/ogloszenia/{announcement_id}' + ) + if result: + count += 1 + + logger.info(f"Created {count} announcement notifications for: {title[:50]}") + return count + + except Exception as e: + logger.error(f"Error creating announcement notifications: {e}") + return 0 + finally: + db.close()