"""Notification Blueprint: templates, logs, preferences. Prefix: /pos/api/notifications """ from flask import Blueprint, request, jsonify, g from middleware import require_auth from tenant_db import get_tenant_conn from services.notification_engine import ( get_templates, create_template, update_template, dispatch_notification, get_notification_logs, mark_as_read, notify_low_stock, notify_order_ready, notify_maintenance_due, notify_new_sale, notify_po_received, ) notification_bp = Blueprint('notifications', __name__, url_prefix='/pos/api/notifications') @notification_bp.route('/templates', methods=['GET']) @require_auth() def list_templates(): event_type = request.args.get('event_type') channel = request.args.get('channel') conn = get_tenant_conn(g.tenant_id) try: templates = get_templates(conn, g.tenant_id, event_type=event_type, channel=channel) return jsonify({'templates': templates}) finally: conn.close() @notification_bp.route('/templates', methods=['POST']) @require_auth() def create_new_template(): data = request.get_json() or {} required = ['event_type', 'channel', 'name', 'body_template'] for field in required: if not data.get(field): return jsonify({'error': f'{field} is required'}), 400 conn = get_tenant_conn(g.tenant_id) try: tid = create_template( conn, g.tenant_id, data['event_type'], data['channel'], data['name'], data['body_template'], subject_template=data.get('subject_template'), is_active=data.get('is_active', True), ) return jsonify({'id': tid, 'message': 'Template created'}), 201 finally: conn.close() @notification_bp.route('/templates/', methods=['PUT']) @require_auth() def update_existing_template(template_id): data = request.get_json() or {} conn = get_tenant_conn(g.tenant_id) try: ok = update_template(conn, template_id, data) if not ok: return jsonify({'error': 'No fields to update'}), 400 return jsonify({'message': 'Template updated'}) finally: conn.close() @notification_bp.route('/logs', methods=['GET']) @require_auth() def list_logs(): recipient_type = request.args.get('recipient_type') recipient_id = request.args.get('recipient_id', type=int) status = request.args.get('status') limit = min(int(request.args.get('limit', 50)), 200) conn = get_tenant_conn(g.tenant_id) try: logs = get_notification_logs( conn, g.tenant_id, recipient_type=recipient_type, recipient_id=recipient_id, status=status, limit=limit, ) return jsonify({'logs': logs}) finally: conn.close() @notification_bp.route('/logs//read', methods=['PUT']) @require_auth() def mark_log_read(log_id): conn = get_tenant_conn(g.tenant_id) try: mark_as_read(conn, log_id) return jsonify({'message': 'Marked as read'}) finally: conn.close() @notification_bp.route('/dispatch', methods=['POST']) @require_auth() def manual_dispatch(): """Manually dispatch a notification.""" data = request.get_json() or {} event_type = data.get('event_type') context = data.get('context', {}) if not event_type: return jsonify({'error': 'event_type is required'}), 400 conn = get_tenant_conn(g.tenant_id) try: log_ids = dispatch_notification( conn, g.tenant_id, event_type, context, recipient_type=data.get('recipient_type', 'owner'), recipient_id=data.get('recipient_id'), channels=data.get('channels'), ) return jsonify({'log_ids': log_ids, 'message': 'Notification dispatched'}) finally: conn.close() # ─── Convenience endpoints ───────────────────────────── @notification_bp.route('/test/low-stock', methods=['POST']) @require_auth() def test_low_stock(): data = request.get_json() or {} inventory_id = data.get('inventory_id') if not inventory_id: return jsonify({'error': 'inventory_id required'}), 400 conn = get_tenant_conn(g.tenant_id) try: log_ids = notify_low_stock( conn, g.tenant_id, inventory_id, stock=data.get('stock', 0), reorder_point=data.get('reorder_point', 5), ) return jsonify({'log_ids': log_ids, 'message': 'Low stock notification sent'}) finally: conn.close()