alerts: Teams webhook fan-out (contract 0.14.0) + printedparts detail revision column

send_webhook(title,text) posts alerts to an optional webhook (Teams Incoming
Webhook / Workflow, or generic JSON) via alert_webhook_url + alert_webhook_format
settings; send_alert fans out to it alongside email; exposed on shopdb.api
(0.13.0->0.14.0, PLUGIN-HOOKS synced); low-stock posts on its custom-recipient
path too. Also: recent-transactions table shows the consumed print-file revision.
This commit is contained in:
cproudlock
2026-07-22 10:21:42 -04:00
parent d141fef203
commit 38c7ec347b
9 changed files with 162 additions and 11 deletions

View File

@@ -0,0 +1,42 @@
"""Alert webhook (Teams etc.): payload formats + send_alert fan-out."""
from unittest.mock import patch
from shopdb.utils.mailer import _webhook_payload, send_webhook, send_alert
CFG = {'url': 'https://teams.example/webhook', 'format': 'teams'}
def test_payload_formats():
teams = _webhook_payload('teams', 'Title', 'Body')
assert teams['@type'] == 'MessageCard' and teams['title'] == 'Title'
card = _webhook_payload('adaptivecard', 'T', 'B')
assert card['attachments'][0]['contentType'].endswith('card.adaptive')
assert _webhook_payload('json', 'T', 'B') == {'title': 'T', 'text': 'B'}
def test_noop_when_unset(app):
with app.app_context():
with patch('shopdb.utils.mailer.get_webhook_config',
return_value={'url': '', 'format': 'teams'}):
ok, err = send_webhook('t', 'b')
assert ok is False and err is None
def test_posts_when_configured(app):
with app.app_context():
with patch('shopdb.utils.mailer.get_webhook_config', return_value=CFG), \
patch('shopdb.utils.mailer.requests') as mock_requests:
mock_requests.post.return_value.status_code = 200
ok, err = send_webhook('Low stock', 'x down')
assert ok is True and err is None
assert mock_requests.post.call_args[0][0] == CFG['url']
assert mock_requests.post.call_args[1]['json']['@type'] == 'MessageCard'
def test_send_alert_fans_out_to_webhook(app):
with app.app_context():
with patch('shopdb.utils.mailer.get_webhook_config', return_value=CFG), \
patch('shopdb.utils.mailer.requests') as mock_requests:
mock_requests.post.return_value.status_code = 200
send_alert('Subject', '<p>Body</p>')
assert mock_requests.post.called # webhook fired even with no email recipients