alerts: per-support-team webhook; printedparts routes low-stock to a chosen team
Support teams gain a webhookurl (migration 7d29 + API + settings-page field), so a team is a notification target. send_webhook(url=) lets a caller override the site default with a team's webhook. Printedparts gains a 'alert support team' setting (printedparts_alert_supportteamid) + selector on its settings page; low-stock alerts post to that team's webhook, falling back to the site alert_webhook_url. Email leg unchanged. Same pattern extends to other alerting plugins (printers low-toner next).
This commit is contained in:
@@ -330,7 +330,7 @@ def _send_lowstock_alert(item):
|
||||
Recipients: Setting printedparts_alert_email (comma-separated), falling
|
||||
back to the site's alert_recipients. Never fails the transaction - the
|
||||
ledger write already committed."""
|
||||
from shopdb.api import send_email, send_alert, send_webhook, Setting
|
||||
from shopdb.api import send_email, send_webhook, Setting
|
||||
code = item.gagelabtag or item.itemcode
|
||||
subject = (f'Low stock: {item.itemname} ({code}) - '
|
||||
f'{item.quantityonhand} left')
|
||||
@@ -350,20 +350,43 @@ def _send_lowstock_alert(item):
|
||||
f'Bin: {item.binlocation or "-"}.'
|
||||
+ (f' [View]({item_url})' if item_url else ''))
|
||||
try:
|
||||
recipients = _alert_recipients()
|
||||
# Webhook: the selected support team's own webhook, else the site
|
||||
# default (send_webhook falls back to alert_webhook_url when url=None).
|
||||
send_webhook(subject, webhook_text, url=_alert_team_webhook())
|
||||
# Email: this plugin's recipients, else the site's alert_recipients.
|
||||
recipients = _alert_recipients() or _site_alert_recipients()
|
||||
if recipients:
|
||||
# send_email does not fan to the webhook, so post it explicitly.
|
||||
send_webhook(subject, webhook_text)
|
||||
send_email(recipients, subject, html)
|
||||
else:
|
||||
# send_alert already fans out to email + webhook.
|
||||
send_alert(subject, html)
|
||||
except Exception:
|
||||
import logging
|
||||
logging.getLogger(__name__).exception(
|
||||
'Low-stock alert failed for %s', item.itemcode)
|
||||
|
||||
|
||||
def _site_alert_recipients():
|
||||
"""Site-wide alert_recipients setting as a clean list (email fallback)."""
|
||||
from shopdb.api import Setting
|
||||
raw = Setting.get('alert_recipients') or ''
|
||||
return [r.strip() for r in raw.replace(';', ',').split(',') if r.strip()]
|
||||
|
||||
|
||||
def _alert_team_webhook():
|
||||
"""Webhook URL of the support team chosen for printedparts alerts, or None.
|
||||
|
||||
printedparts_alert_supportteamid selects a SupportTeam; alerts route to that
|
||||
team's webhook. None -> send_webhook uses the site-wide default."""
|
||||
from shopdb.api import Setting
|
||||
team_id = Setting.get('printedparts_alert_supportteamid')
|
||||
if not team_id:
|
||||
return None
|
||||
try:
|
||||
from shopdb.core.models import SupportTeam
|
||||
team = db.session.get(SupportTeam, int(team_id))
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
return (team.webhookurl or None) if team else None
|
||||
|
||||
|
||||
@printedparts_bp.route('/items/<int:item_id>/restock', methods=['POST'])
|
||||
@jwt_required()
|
||||
@require_permission('printedparts.restock')
|
||||
|
||||
Reference in New Issue
Block a user