Backoffice stage 2: chats (support + concierge, files)

- ChatThread per client/provider and channel; messages get files, internal notes,
  source (bot/mini app) and delivery errors; reply templates. Migration moves old
  concierge messages into threads.
- Routing: subscribers write to the concierge, others to support; /support and
  /concierge in the client bot; staff can take, transfer, close and move threads.
- Telegram: photos/documents from clients and providers, replies with the channel
  header, files sent from storage, notifications only to the assignee or the
  channel's staff, "Reply" into a specific thread.
- New admin: /chats with list, conversation, notes, files, templates, client panel;
  "Message" button on the client card; dashboard counts threads awaiting reply.
- Client mini app: in-app chat screen sharing the same conversation.
- Old admin keeps working on the same data (notes hidden there).
- Tests for routing, notes, assign/close/move, lists, recipients; separate test DB
  via TEST_DB_NAME; dev:chats-demo script.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zabudko-ruandClaude Opus 5.5 committed 2026-10-21 01:50:37 +04:00
1 parent d452824c62
commit 23ffb2bf1d
46 files changed
+4176 -144

No files matched your search

+30 -4
View File
@@ -442,7 +442,9 @@
"PROVIDER_NOT_LINKED": "El profesional aún no ha abierto el bot con la invitación: no hay dónde escribirle.",
"CARD_EXPIRED": "El QR caducó o no es válido: pide al cliente que vuelva a abrir la tarjeta.",
"OFFER_NOT_AVAILABLE": "Esta oferta no está disponible en el nivel del cliente.",
"OFFER_LIMIT_REACHED": "Ya se agotó el límite de esta oferta."
"OFFER_LIMIT_REACHED": "Ya se agotó el límite de esta oferta.",
"CONCIERGE_SUBSCRIBERS_ONLY": "El conserje personal es para miembros de Barev+ y Barev Elite. De momento, escribe a soporte: también te ayudaremos.",
"ASSIGNEE_NO_ACCESS": "Esta persona del equipo no tiene acceso a este canal."
},
"client": {
"nav": {
@@ -654,6 +656,20 @@
"used_ONCE": "ya usado",
"used_WEEK": "de nuevo la próxima semana",
"used_MONTH": "de nuevo el próximo mes"
},
"chat": {
"title": "Chat con Barev Club",
"support": "Soporte",
"concierge": "Conserje personal",
"hint": "Es la misma conversación que en el chat del bot: la respuesta llegará aquí y a Telegram.",
"empty": "Cuéntanos en qué podemos ayudarte: te responderemos aquí.",
"placeholder": "Mensaje…",
"send": "Enviar",
"attach": "Adjuntar foto o archivo",
"conciergeOnly": "El conserje personal está incluido en Barev+ y Barev Elite",
"team": "Barev Club",
"fileTooBig": "El archivo supera los 10 MB",
"file": "Archivo"
}
},
"pro": {
@@ -815,7 +831,12 @@
"cmdHelp": "Ayuda",
"webRequestOrdered": "Solicitud n.º {{request}} recibida y registrada como pedido n.º {{order}} para el {{date}}. El estado está en la app.",
"webRequestLinked": "Solicitud n.º {{request}} recibida. Un operador te contactará para confirmar la hora.",
"conciergeReceived": "Lo hemos pasado al conserje: te responderemos aquí, en este chat."
"conciergeReceived": "Lo hemos pasado al conserje: te responderemos aquí, en este chat.",
"supportReceived": "Lo hemos pasado a soporte: te responderemos aquí, en este chat.",
"channelSupport": "Ahora escribes a soporte. Envía un mensaje, una foto o un archivo.",
"channelConcierge": "Ahora escribes a tu conserje personal. Envía un mensaje, una foto o un archivo.",
"cmdSupport": "Escribir a soporte",
"cmdConcierge": "Escribir al conserje (Barev+)"
},
"pro": {
"notLinked": "Este bot es para los especialistas de Barev Club. Pide al operador un enlace de invitación.",
@@ -844,7 +865,11 @@
"newRequest": "Solicitud de la app n.º {{number}}",
"newWebRequest": "Solicitud de la web n.º {{number}}",
"loginOk": "Inicio de sesión confirmado: vuelve al navegador.",
"loginExpired": "El enlace de acceso ha caducado: recarga la página de administración."
"loginExpired": "El enlace de acceso ha caducado: recarga la página de administración.",
"channelSupport": "Soporte",
"channelConcierge": "Conserje",
"file": "archivo",
"chatAssigned": "{{by}} te ha pasado una conversación: {{name}}"
},
"partner": {
"valid": "{{name}} — {{level}}, tarjeta válida",
@@ -948,7 +973,8 @@
"openPlan": "Abrir la app",
"concierge": "Conserje de Barev Club",
"subscriptionActivated": "{{plan}} activo hasta el {{date}}. Los descuentos ya están en los precios.",
"operator": "Operador de Barev Club"
"operator": "Operador de Barev Club",
"support": "Soporte de Barev Club"
},
"admin": {
"nav": {