Relocations and requests in the new admin; star rating in the client bot

Orders section gets tabs: Orders / Relocations / Requests (concierge sees the
last two). Relocation list with statuses, plan progress and current step;
relocation card with per-client steps (status, client comment, rename, add,
remove), documents, quiz answers, team note, write/call. Requests: website
cleaning requests and app requests (membership, call back) with notes,
create order, turn on membership. Dashboard links point here instead of the
old admin.

Fix: leads with an unanswered 'already moved?' (NULL) were skipped by
'moved not true' filters — plan sync and linking to the app client.

Client bot: after an order is done, asks for 1-5 stars; low rating asks what
went wrong, the reply is saved as the rating comment and goes to the team chat.

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 04:17:21 +04:00
1 parent bbb25d3d0d
commit dcba7c200c
19 files changed
+1422 -22

No files matched your search

+5 -2
View File
@@ -878,7 +878,9 @@
"channelSupport": "You are now writing to support. Just send a message, photo or file.",
"channelConcierge": "You are now writing to your personal concierge. Just send a message, photo or file.",
"cmdSupport": "Write to support",
"cmdConcierge": "Write to the concierge (Barev+)"
"cmdConcierge": "Write to the concierge (Barev+)",
"rated": "Thanks for your rating! {{stars}}",
"ratedLow": "Sorry it didn’t go well. Tell us here what happened — the team will sort it out."
},
"pro": {
"notLinked": "This bot is for Barev Club specialists. Ask the operator for an invite link.",
@@ -1019,7 +1021,8 @@
"concierge": "Barev Club concierge",
"subscriptionActivated": "{{plan}} is on until {{date}}. Discounts are already in service prices.",
"operator": "Barev Club operator",
"support": "Barev Club support"
"support": "Barev Club support",
"rateAsk": "How did it go? Please rate — it takes a second:"
},
"admin": {
"nav": {
+5 -2
View File
@@ -878,7 +878,9 @@
"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+)"
"cmdConcierge": "Escribir al conserje (Barev+)",
"rated": "¡Gracias por tu valoración! {{stars}}",
"ratedLow": "Lamentamos que no fuera bien. Cuéntanos aquí qué pasó y el equipo lo resolverá."
},
"pro": {
"notLinked": "Este bot es para los especialistas de Barev Club. Pide al operador un enlace de invitación.",
@@ -1019,7 +1021,8 @@
"concierge": "Conserje de Barev Club",
"subscriptionActivated": "{{plan}} activo hasta el {{date}}. Los descuentos ya están en los precios.",
"operator": "Operador de Barev Club",
"support": "Soporte de Barev Club"
"support": "Soporte de Barev Club",
"rateAsk": "¿Qué tal fue? Valóralo, por favor, es un segundo:"
},
"admin": {
"nav": {
+5 -2
View File
@@ -878,7 +878,9 @@
"channelSupport": "Այժմ գրում եք աջակցությանը։ Պարզապես ուղարկեք հաղորդագրություն, լուսանկար կամ ֆայլ։",
"channelConcierge": "Այժմ գրում եք ձեր անձնական կոնսիերժին։ Պարզապես ուղարկեք հաղորդագրություն, լուսանկար կամ ֆայլ։",
"cmdSupport": "Գրել աջակցությանը",
"cmdConcierge": "Գրել կոնսիերժին (Barev+)"
"cmdConcierge": "Գրել կոնսիերժին (Barev+)",
"rated": "Շնորհակալություն գնահատականի համար։ {{stars}}",
"ratedLow": "Ափսոս, որ ամեն ինչ լավ չանցավ։ Գրիր այստեղ, թե ինչ է պատահել, թիմը կզբաղվի։"
},
"pro": {
"notLinked": "Այս բոտը Barev Club-ի կատարողների համար է։ Խնդրեք օպերատորից հրավերի հղում։",
@@ -1019,7 +1021,8 @@
"concierge": "Barev Club կոնսիերժ",
"subscriptionActivated": "{{plan}}-ը միացված է մինչև {{date}}։ Զեղչերն արդեն ծառայությունների գներում են։",
"operator": "Barev Club օպերատոր",
"support": "Barev Club աջակցություն"
"support": "Barev Club աջակցություն",
"rateAsk": "Ինչպե՞ս անցավ։ Խնդրում ենք գնահատել՝ մեկ վայրկյան է։"
},
"admin": {
"nav": {
+5 -2
View File
@@ -878,7 +878,9 @@
"channelSupport": "Теперь вы пишете в поддержку. Просто отправьте сообщение, фото или файл.",
"channelConcierge": "Теперь вы пишете личному консьержу. Просто отправьте сообщение, фото или файл.",
"cmdSupport": "Написать в поддержку",
"cmdConcierge": "Написать консьержу (Barev+)"
"cmdConcierge": "Написать консьержу (Barev+)",
"rated": "Спасибо за оценку! {{stars}}",
"ratedLow": "Жаль, что не всё прошло хорошо. Напиши здесь, что случилось, — команда разберётся."
},
"pro": {
"notLinked": "Этот бот — для исполнителей Barev Club. Попроси у оператора ссылку-приглашение.",
@@ -1019,7 +1021,8 @@
"concierge": "Консьерж Barev Club",
"subscriptionActivated": "{{plan}} включён до {{date}}. Скидки уже в ценах услуг.",
"operator": "Оператор Barev Club",
"support": "Поддержка Barev Club"
"support": "Поддержка Barev Club",
"rateAsk": "Как всё прошло? Оцени, пожалуйста, — это займёт секунду:"
},
"admin": {
"nav": {
+5 -2
View File
@@ -878,7 +878,9 @@
"channelSupport": "现在你在给客服写信。直接发送消息、照片或文件即可。",
"channelConcierge": "现在你在给专属礼宾写信。直接发送消息、照片或文件即可。",
"cmdSupport": "联系客服",
"cmdConcierge": "联系礼宾(Barev+)"
"cmdConcierge": "联系礼宾(Barev+)",
"rated": "感谢您的评价!{{stars}}",
"ratedLow": "很抱歉服务不够好。请在这里告诉我们发生了什么,团队会处理。"
},
"pro": {
"notLinked": "此机器人供 Barev Club 服务人员使用。请向客服索取邀请链接。",
@@ -1019,7 +1021,8 @@
"concierge": "Barev Club 礼宾",
"subscriptionActivated": "{{plan}} 已开通,有效期至 {{date}}。服务价格已含折扣。",
"operator": "Barev Club 客服",
"support": "Barev Club 客服支持"
"support": "Barev Club 客服支持",
"rateAsk": "服务体验如何?请花一秒钟评价一下:"
},
"admin": {
"nav": {
+1 -1
View File
@@ -101,7 +101,7 @@ export async function updateLead(ctx: Ctx, input: UpdateLeadInput) {
/** Для админки: свежие сверху */
export async function listLeads(ctx: Ctx, input: { status?: LeadStatus }) {
// заявки, отправленные до появления шаблонов, получают план и документы при первом показе
const bare = await ctx.db.lead.findMany({ where: { submittedAt: { not: null }, moved: { not: true }, package: { not: null }, docs: { none: {} } } });
const bare = await ctx.db.lead.findMany({ where: { submittedAt: { not: null }, OR: [{ moved: null }, { moved: false }], package: { not: null }, docs: { none: {} } } });
for (const l of bare) {
await syncLeadSteps(ctx.db, l);
await ensureLeadDocs(ctx.db, l.id);
+1 -1
View File
@@ -72,7 +72,7 @@ export async function clientRelocation(ctx: Ctx, clientId: string) {
const username = client.user.username;
if (!username) return null;
const site = await ctx.db.lead.findFirst({
where: { clientId: null, contactType: 'TELEGRAM', contact: { equals: `@${username}`, mode: 'insensitive' }, moved: { not: true } },
where: { clientId: null, contactType: 'TELEGRAM', contact: { equals: `@${username}`, mode: 'insensitive' }, OR: [{ moved: null }, { moved: false }] },
orderBy: { createdAt: 'desc' },
});
if (!site) return null;