diff --git a/handlers/business_updates.py b/handlers/business_updates.py
index 4a5f8ee..7ff4092 100644
--- a/handlers/business_updates.py
+++ b/handlers/business_updates.py
@@ -268,8 +268,6 @@ def _notify_incoming(bcid: str, customer_chat_id: int, text: str) -> None:
# =============================================================================
def on_edited_business_message(message) -> None:
# Informational only: do NOT generate a new reply (prevents edit loops).
- if not database.get_bool("monitoring_mode"):
- return
bcid = getattr(message, "business_connection_id", None)
if not bcid:
return
@@ -278,11 +276,24 @@ def on_edited_business_message(message) -> None:
sender = getattr(message, "from_user", None)
if sender and owner_user_id and sender.id == owner_user_id:
return # owner edited their own message
+ invalidated = database.invalidate_approvals_for_messages(
+ bcid, message.chat.id, [message.message_id]
+ )
+ log.info(
+ "customer edited message chat=%s (invalidated %d approvals)",
+ utils.mask_id(message.chat.id), invalidated,
+ )
+ if not database.get_bool("monitoring_mode"):
+ return
name = business_service.customer_display_name(bcid, message.chat.id)
text = (getattr(message, "text", None) or getattr(message, "caption", None) or "").strip()
+ cancellation = (
+ "\nThe pending approval for the earlier version was cancelled."
+ if invalidated else ""
+ )
handlers.notify_owner(
f"✏️ {utils.escape(name)} edited a message: "
- f"{utils.escape(text[:300])}"
+ f"{utils.escape(text[:300])}{cancellation}"
)
diff --git a/tests/unit/handlers/test_business_updates.py b/tests/unit/handlers/test_business_updates.py
index 8f35d0f..f1b53b2 100644
--- a/tests/unit/handlers/test_business_updates.py
+++ b/tests/unit/handlers/test_business_updates.py
@@ -196,7 +196,55 @@ def test_deliver_auto_warns_when_delivery_is_unconfirmed(
assert db.get_recent_memory("bc1", 5, 10) == []
-# --- deleted messages --------------------------------------------------------
+# --- edited / deleted messages ----------------------------------------------
+def test_edited_customer_message_invalidates_approval(penv, make_message, mocker):
+ aid = penv.db.insert_pending_approval("bc1", 5, 22, "before", "reply")
+ notify = mocker.patch("handlers.notify_owner")
+
+ bu.on_edited_business_message(
+ make_message(
+ business_connection_id="bc1", chat_id=5, message_id=22, text="after"
+ )
+ )
+
+ assert penv.db.get_approval(aid)["status"] == "invalidated"
+ assert "pending approval for the earlier version was cancelled" in notify.call_args.args[0]
+
+
+def test_edited_customer_message_invalidates_with_monitoring_off(
+ penv, make_message, mocker
+):
+ penv.db.set_setting("monitoring_mode", False)
+ aid = penv.db.insert_pending_approval("bc1", 5, 22, "before", "reply")
+ notify = mocker.patch("handlers.notify_owner")
+
+ bu.on_edited_business_message(
+ make_message(
+ business_connection_id="bc1", chat_id=5, message_id=22, text="after"
+ )
+ )
+
+ assert penv.db.get_approval(aid)["status"] == "invalidated"
+ notify.assert_not_called()
+
+
+def test_edited_owner_message_does_not_invalidate_customer_approval(
+ penv, make_message, mocker
+):
+ aid = penv.db.insert_pending_approval("bc1", 5, 22, "customer", "reply")
+ notify = mocker.patch("handlers.notify_owner")
+
+ bu.on_edited_business_message(
+ make_message(
+ business_connection_id="bc1", user_id=999, chat_id=5,
+ message_id=22, text="owner edit",
+ )
+ )
+
+ assert penv.db.get_approval(aid)["status"] == "pending"
+ notify.assert_not_called()
+
+
def test_deleted_invalidates_approval(penv):
aid = penv.db.insert_pending_approval("bc1", 5, 22, "c", "r")
deleted = SimpleNamespace(business_connection_id="bc1",