fix(bot): refresh setup checklist after manual binds

This commit is contained in:
2026-03-11 11:23:33 +04:00
parent dd243d7edd
commit 4cd5622d63
5 changed files with 85 additions and 14 deletions

View File

@@ -810,11 +810,11 @@ describe('registerHouseholdSetupCommands', () => {
],
[
{
text: 'Create purchases',
text: 'Create purchases topic',
callback_data: 'setup_topic:create:purchase'
},
{
text: 'Bind purchases',
text: 'Bind purchases topic',
callback_data: 'setup_topic:bind:purchase'
}
]
@@ -1060,15 +1060,24 @@ describe('registerHouseholdSetupCommands', () => {
expect(await promptRepository.getPendingAction('-100123456', '123456')).toMatchObject({
action: 'setup_topic_binding',
payload: {
role: 'payments'
role: 'payments',
setupMessageId: 91
}
})
calls.length = 0
await bot.handleUpdate(topicMessageUpdate('hello from payments', 444) as never)
expect(calls).toHaveLength(2)
expect(calls).toHaveLength(3)
expect(calls[1]).toMatchObject({
method: 'editMessageText',
payload: {
chat_id: -100123456,
message_id: 91,
text: expect.stringContaining('- payments: bound to thread 444')
}
})
expect(calls[2]).toMatchObject({
method: 'sendMessage',
payload: {
chat_id: -100123456,

View File

@@ -321,12 +321,20 @@ function isHouseholdTopicRole(value: string): value is HouseholdTopicRole {
function parseSetupBindPayload(payload: Record<string, unknown>): {
role: HouseholdTopicRole
setupMessageId?: number
} | null {
return typeof payload.role === 'string' && isHouseholdTopicRole(payload.role)
? {
role: payload.role
}
: null
if (typeof payload.role !== 'string' || !isHouseholdTopicRole(payload.role)) {
return null
}
return {
role: payload.role,
...(typeof payload.setupMessageId === 'number' && Number.isInteger(payload.setupMessageId)
? {
setupMessageId: payload.setupMessageId
}
: {})
}
}
export function buildJoinMiniAppUrl(
@@ -527,6 +535,22 @@ export function registerHouseholdSetupCommands(options: {
return
}
if (payload.setupMessageId && options.householdConfigurationRepository) {
const reply = await buildSetupReplyForHousehold({
ctx,
locale,
household: result.household,
created: false
})
await ctx.api.editMessageText(
Number(telegramChatId),
payload.setupMessageId,
reply.text,
'reply_markup' in reply ? { reply_markup: reply.reply_markup } : {}
)
}
await ctx.reply(
bindTopicSuccessMessage(
locale,
@@ -1027,7 +1051,12 @@ export function registerHouseholdSetupCommands(options: {
telegramChatId,
action: SETUP_BIND_TOPIC_ACTION,
payload: {
role
role,
...(ctx.msg
? {
setupMessageId: ctx.msg.message_id
}
: {})
},
expiresAt: nowInstant().add({ milliseconds: SETUP_BIND_TOPIC_TTL_MS })
})

View File

@@ -60,8 +60,8 @@ export const enBotTranslations: BotTranslationCatalog = {
setupTopicsHeading: 'Topic setup:',
setupTopicBound: (role, topic) => `- ${role}: bound to ${topic}`,
setupTopicMissing: (role) => `- ${role}: not configured`,
setupTopicCreateButton: (role) => `Create ${role}`,
setupTopicBindButton: (role) => `Bind ${role}`,
setupTopicCreateButton: (role) => `Create ${role} topic`,
setupTopicBindButton: (role) => `Bind ${role} topic`,
setupTopicCreateFailed:
'I could not create that topic. Check bot admin permissions and forum settings.',
setupTopicCreateForbidden:
@@ -260,8 +260,20 @@ export const enBotTranslations: BotTranslationCatalog = {
payments: {
topicMissing:
'Payments topic is not configured for this household yet. Ask an admin to run /bind_payments_topic.',
proposal: (kind, amount, currency) =>
`I can record this ${kind === 'rent' ? 'rent' : 'utilities'} payment: ${amount} ${currency}. Confirm or cancel below.`,
clarification:
'I could not confirm this payment yet. Please clarify whether this was rent or utilities and include the amount/currency if needed.',
unsupportedCurrency:
'I can only record payments in the household settlement currency for this topic right now.',
noBalance: 'There is no payable balance for that payment type right now.',
confirmButton: 'Confirm payment',
cancelButton: 'Cancel',
recorded: (kind, amount, currency) =>
`Recorded ${kind === 'rent' ? 'rent' : 'utilities'} payment: ${amount} ${currency}`,
cancelled: 'Payment proposal cancelled.',
proposalUnavailable: 'This payment proposal is no longer available.',
notYourProposal: 'Only the original sender can confirm or cancel this payment.',
savedForReview: 'Saved this payment confirmation for review.',
duplicate: 'This payment confirmation was already processed.'
}

View File

@@ -62,8 +62,8 @@ export const ruBotTranslations: BotTranslationCatalog = {
setupTopicsHeading: 'Настройка топиков:',
setupTopicBound: (role, topic) => `- ${role}: привязан к ${topic}`,
setupTopicMissing: (role) => `- ${role}: не настроен`,
setupTopicCreateButton: (role) => `Создать ${role}`,
setupTopicBindButton: (role) => `Привязать ${role}`,
setupTopicCreateButton: (role) => `Создать топик для ${role}`,
setupTopicBindButton: (role) => `Привязать топик для ${role}`,
setupTopicCreateFailed:
'Не удалось создать этот топик. Проверьте права бота и включённые форум-топики в группе.',
setupTopicCreateForbidden:
@@ -263,8 +263,20 @@ export const ruBotTranslations: BotTranslationCatalog = {
payments: {
topicMissing:
'Для этого дома ещё не настроен топик оплат. Попросите админа выполнить /bind_payments_topic.',
proposal: (kind, amount, currency) =>
`Я могу записать эту оплату ${kind === 'rent' ? 'аренды' : 'коммуналки'}: ${amount} ${currency}. Подтвердите или отмените ниже.`,
clarification:
'Пока не могу подтвердить эту оплату. Уточните, это аренда или коммуналка, и при необходимости напишите сумму и валюту.',
unsupportedCurrency:
'Сейчас я могу записывать оплаты в этом топике только в валюте расчётов по дому.',
noBalance: 'Сейчас для этого типа оплаты нет суммы к подтверждению.',
confirmButton: 'Подтвердить оплату',
cancelButton: 'Отменить',
recorded: (kind, amount, currency) =>
`Оплата ${kind === 'rent' ? 'аренды' : 'коммуналки'} сохранена: ${amount} ${currency}`,
cancelled: 'Предложение оплаты отменено.',
proposalUnavailable: 'Это предложение оплаты уже недоступно.',
notYourProposal: 'Подтвердить или отменить эту оплату может только отправитель сообщения.',
savedForReview: 'Это подтверждение оплаты сохранено на проверку.',
duplicate: 'Это подтверждение оплаты уже было обработано.'
}

View File

@@ -249,6 +249,15 @@ export interface BotTranslationCatalog {
payments: {
topicMissing: string
recorded: (kind: 'rent' | 'utilities', amount: string, currency: string) => string
proposal: (kind: 'rent' | 'utilities', amount: string, currency: string) => string
clarification: string
unsupportedCurrency: string
noBalance: string
confirmButton: string
cancelButton: string
cancelled: string
proposalUnavailable: string
notYourProposal: string
savedForReview: string
duplicate: string
}