fix(telegram): edit messages in-place during server switch flow

Server switch flow now edits the original message at each step
(progress, error, company list) instead of sending separate messages.
"Server schimbat" notice is folded into the company selection header.
Also adds budget debt breakdown to dashboard formatter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-02-23 09:18:59 +00:00
parent 30f55cf18b
commit aac49542e4
2 changed files with 90 additions and 11 deletions

View File

@@ -63,6 +63,21 @@ def format_dashboard_response(data: Dict[str, Any], company_name: str = None) ->
if tva_recup_cur > 0: if tva_recup_cur > 0:
text += f" - TVA de recuperat curent: {tva_recup_cur:,} RON\n" text += f" - TVA de recuperat curent: {tva_recup_cur:,} RON\n"
# Datorii la Buget - breakdown pe grupe (TVA / BASS / CAM), valori luna precedentă
budget_breakdown = data.get('budget_debt_breakdown', [])
if budget_breakdown:
grupe_cu_datorie = [
g for g in budget_breakdown
if round(float(g.get('precedent', 0))) > 0
]
if grupe_cu_datorie:
total_buget = sum(round(float(g.get('precedent', 0))) for g in grupe_cu_datorie)
text += "\n\n**Datorii la Buget:**\n"
for grupa in grupe_cu_datorie:
val = round(float(grupa.get('precedent', 0)))
text += f" - {grupa.get('label', '')}: {val:,} RON\n"
text += f" Total: {total_buget:,} RON\n"
return text return text

View File

@@ -1292,16 +1292,37 @@ async def handle_text_message(update: Update, context: ContextTypes.DEFAULT_TYPE
except Exception as e: except Exception as e:
logger.warning(f"Could not delete password message: {e}") logger.warning(f"Could not delete password message: {e}")
# Șterge și mesajul prompt "Parolă:" (ForceReply)
prompt_msg_id = context.user_data.pop('pending_switch_prompt_message_id', None)
if prompt_msg_id:
try:
await context.bot.delete_message(
chat_id=update.effective_chat.id,
message_id=prompt_msg_id
)
except Exception:
pass
oracle_password = text oracle_password = text
jwt_token = context.user_data.pop('pending_switch_jwt_token', None) jwt_token = context.user_data.pop('pending_switch_jwt_token', None)
username = context.user_data.pop('pending_switch_username', None) username = context.user_data.pop('pending_switch_username', None)
context.user_data.pop('pending_switch_server_id', None) context.user_data.pop('pending_switch_server_id', None)
# Recuperează message_id-ul și chat_id-ul pentru editare in-place
switch_msg_id = context.user_data.get('pending_switch_message_id')
switch_chat_id = context.user_data.get('pending_switch_chat_id')
if not jwt_token or not username: if not jwt_token or not username:
await update.effective_chat.send_message("Sesiune expirată. Încearcă din nou.") await update.effective_chat.send_message("Sesiune expirată. Încearcă din nou.")
return return
await update.effective_chat.send_message("Se verifică parola și se schimbă serverul...") if switch_msg_id and switch_chat_id:
await context.bot.edit_message_text(
chat_id=switch_chat_id,
message_id=switch_msg_id,
text="Se verifică parola și se schimbă serverul..."
)
else:
await update.effective_chat.send_message("Se verifică parola și se schimbă serverul...")
client = get_backend_client() client = get_backend_client()
async with client: async with client:
@@ -1314,10 +1335,19 @@ async def handle_text_message(update: Update, context: ContextTypes.DEFAULT_TYPE
if not result.get('success'): if not result.get('success'):
from telegram import InlineKeyboardButton, InlineKeyboardMarkup from telegram import InlineKeyboardButton, InlineKeyboardMarkup
await update.effective_chat.send_message( error_text = f"{result.get('message', 'Eroare la schimbarea serverului')}\n\nReîncearcă cu /menu → Schimbă server."
f"{result.get('message', 'Eroare la schimbarea serverului')}\n\nReîncearcă cu /menu → Schimbă server.", error_markup = InlineKeyboardMarkup([[InlineKeyboardButton("« Meniu", callback_data="action:menu")]])
reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("« Meniu", callback_data="action:menu")]]) if switch_msg_id and switch_chat_id:
) context.user_data.pop('pending_switch_message_id', None)
context.user_data.pop('pending_switch_chat_id', None)
await context.bot.edit_message_text(
chat_id=switch_chat_id,
message_id=switch_msg_id,
text=error_text,
reply_markup=error_markup
)
else:
await update.effective_chat.send_message(error_text, reply_markup=error_markup)
return return
# Salvează noul JWT în SQLite # Salvează noul JWT în SQLite
@@ -1344,7 +1374,11 @@ async def handle_text_message(update: Update, context: ContextTypes.DEFAULT_TYPE
except Exception: except Exception:
srv_display = pending_server_id srv_display = pending_server_id
await update.effective_chat.send_message(f"✅ Server schimbat: **{srv_display}**\nSelectează firma...", parse_mode=ParseMode.MARKDOWN) edit_chat_id = switch_chat_id if (switch_msg_id and switch_chat_id) else None
edit_message_id = switch_msg_id if (switch_msg_id and switch_chat_id) else None
if switch_msg_id and switch_chat_id:
context.user_data.pop('pending_switch_message_id', None)
context.user_data.pop('pending_switch_chat_id', None)
await _handle_selectcompany_view( await _handle_selectcompany_view(
query_or_update=update, query_or_update=update,
@@ -1352,7 +1386,11 @@ async def handle_text_message(update: Update, context: ContextTypes.DEFAULT_TYPE
jwt_token=result['access_token'], jwt_token=result['access_token'],
is_callback=False, is_callback=False,
page=0, page=0,
search_term="" search_term="",
header=f"Server schimbat: **{srv_display}**\n\n",
bot=context.bot,
edit_chat_id=edit_chat_id,
edit_message_id=edit_message_id
) )
return return
@@ -2528,12 +2566,18 @@ async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
f"_(Mesajul cu parola va fi șters automat)_", f"_(Mesajul cu parola va fi șters automat)_",
parse_mode=ParseMode.MARKDOWN parse_mode=ParseMode.MARKDOWN
) )
# Salvează message_id-ul mesajului "🔐 Schimbare server" pentru editare ulterioară
context.user_data['pending_switch_message_id'] = query.message.message_id
context.user_data['pending_switch_chat_id'] = query.message.chat_id
# Trimite un mesaj separat cu ForceReply pentru a forța input-ul # Trimite un mesaj separat cu ForceReply pentru a forța input-ul
await context.bot.send_message( force_reply_msg = await context.bot.send_message(
chat_id=update.effective_chat.id, chat_id=update.effective_chat.id,
text="Parolă:", text="Parolă:",
reply_markup=ForceReply(selective=True, input_field_placeholder="Parola Oracle...") reply_markup=ForceReply(selective=True, input_field_placeholder="Parola Oracle...")
) )
# Salvează message_id-ul prompt-ului "Parolă:" pentru ștergere ulterioară
context.user_data['pending_switch_prompt_message_id'] = force_reply_msg.message_id
return return
# ========== LOGOUT CALLBACKS ========== # ========== LOGOUT CALLBACKS ==========
@@ -3075,7 +3119,11 @@ async def _handle_selectcompany_view(
jwt_token: str, jwt_token: str,
is_callback: bool = False, is_callback: bool = False,
page: int = 0, page: int = 0,
search_term: str = "" search_term: str = "",
header: str = "",
bot=None,
edit_chat_id: int = None,
edit_message_id: int = None
): ):
""" """
Common handler pentru company selection cu paginare. Common handler pentru company selection cu paginare.
@@ -3144,7 +3192,7 @@ async def _handle_selectcompany_view(
from backend.modules.telegram.bot.menus import create_main_menu, get_menu_message from backend.modules.telegram.bot.menus import create_main_menu, get_menu_message
keyboard = create_main_menu(company_name=company_name, company_cui=company_cui) keyboard = create_main_menu(company_name=company_name, company_cui=company_cui)
menu_text = f"Firmă selectată automat: **{company_name}**\n\n" + get_menu_message(company_name, company_cui) menu_text = header + f"Firma selectata automat: **{company_name}**\n\n" + get_menu_message(company_name, company_cui)
if is_callback: if is_callback:
await query_or_update.edit_message_text( await query_or_update.edit_message_text(
@@ -3152,6 +3200,14 @@ async def _handle_selectcompany_view(
reply_markup=keyboard, reply_markup=keyboard,
parse_mode=ParseMode.MARKDOWN parse_mode=ParseMode.MARKDOWN
) )
elif bot and edit_chat_id and edit_message_id:
await bot.edit_message_text(
chat_id=edit_chat_id,
message_id=edit_message_id,
text=menu_text,
reply_markup=keyboard,
parse_mode=ParseMode.MARKDOWN
)
else: else:
await query_or_update.message.reply_text( await query_or_update.message.reply_text(
menu_text, menu_text,
@@ -3163,7 +3219,7 @@ async def _handle_selectcompany_view(
from backend.modules.telegram.bot.helpers import create_company_selection_keyboard_paginated from backend.modules.telegram.bot.helpers import create_company_selection_keyboard_paginated
keyboard = create_company_selection_keyboard_paginated(companies, page=page) keyboard = create_company_selection_keyboard_paginated(companies, page=page)
message = f"**Selecteaza Compania**\n\n" message = header + f"**Selecteaza Compania**\n\n"
if search_term: if search_term:
message += f"Rezultate '{search_term}' ({len(companies)}):" message += f"Rezultate '{search_term}' ({len(companies)}):"
else: else:
@@ -3175,6 +3231,14 @@ async def _handle_selectcompany_view(
reply_markup=keyboard, reply_markup=keyboard,
parse_mode=ParseMode.MARKDOWN parse_mode=ParseMode.MARKDOWN
) )
elif bot and edit_chat_id and edit_message_id:
await bot.edit_message_text(
chat_id=edit_chat_id,
message_id=edit_message_id,
text=message,
reply_markup=keyboard,
parse_mode=ParseMode.MARKDOWN
)
else: else:
await query_or_update.message.reply_text( await query_or_update.message.reply_text(
message, message,