Owner notification webhook: Telegram re-point (#23)
Test backoffice (smb-crm) / test (push) Has been cancelled

Flask fires a fire-and-forget internal webhook (owner_notify.py, mirroring
mailer.py's background-thread queue) on booking create/cancel/reschedule,
carrying the same {booking, business_name, notify_channel} shape the old
EA-driven "Build booking row" node produced, plus an event field so the
Telegram message can say what actually happened. n8n/booking-sync.json gets
a new webhook + IF node feeding the existing Telegram node directly, so it
no longer needs EA's API to build the notification payload; channel routing
(only telegram sends for now) lives in that IF node.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-04 12:09:39 +02:00
parent 24d9aca812
commit a27ee59125
7 changed files with 336 additions and 6 deletions
+9 -3
View File
@@ -15,6 +15,7 @@ from flask import Blueprint, jsonify, request
import availability
import booking_db as bdb
import booking_mail
import owner_notify
bp = Blueprint("booking_api", __name__, url_prefix="/api/booking")
@@ -161,6 +162,7 @@ def create_booking_row(client_id, resource_id, service_id, start_time,
# owner manual-entry (#20) included -- calling bdb.create_booking()
# directly would bypass it.
booking_mail.send_booking_confirmation(client, booking, token)
owner_notify.notify(client, booking, "created") # #23
return booking, token
@@ -174,7 +176,9 @@ def cancel_booking_row(client_id, booking_id):
raise NotFound()
if existing["status"] == "cancelled":
raise AlreadyCancelled()
return bdb.update_booking(client_id, booking_id, status="cancelled")
updated = bdb.update_booking(client_id, booking_id, status="cancelled")
owner_notify.notify(bdb.get_client(client_id), updated, "cancelled") # #23
return updated
def reschedule_booking_row(client_id, booking_id, new_start):
@@ -203,10 +207,12 @@ def reschedule_booking_row(client_id, booking_id, new_start):
raise SlotUnavailable()
try:
return bdb.update_booking(client_id, booking_id, start_time=new_start,
end_time=new_end)
updated = bdb.update_booking(client_id, booking_id, start_time=new_start,
end_time=new_end)
except bdb.BookingConflict:
raise SlotTaken() from None
owner_notify.notify(client, updated, "rescheduled") # #23
return updated
class _BadDuration(ValueError):