feat: Add A-Z filter for clients/suppliers in Telegram bot

- Add A-Z alphabetical filter keyboard for clients and suppliers lists
  (same pattern as company selection, without emoji)
- Increase clients/suppliers list pagination from 10 to 20 items per page
- Remove emoji from company A-Z filter button for consistency
- Add 6 new callback handlers: clients_alpha_menu, clients_alpha:LETTER,
  clients_alpha_page:PAGE:LETTER, and supplier equivalents
- Dashboard service and models updates
- Telegram bot: email handlers, auth, DB operations, internal API improvements
- Frontend: dashboard cards updates (CashFlow, Clienti, Furnizori, Treasury)
- Frontend: SolduriCompactCard and CollapsibleCard improvements
- DashboardView enhancements
- start.sh and run-with-restart.sh script updates
- IIS web.config and service worker updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-02-21 14:34:15 +00:00
parent 1366dbc11c
commit 30f55cf18b
28 changed files with 1671 additions and 520 deletions

View File

@@ -169,7 +169,10 @@ def create_company_selection_keyboard(
def create_company_selection_keyboard_paginated(
companies: List[Dict[str, Any]],
page: int = 0,
per_page: int = 10
per_page: int = 20,
back_callback: str = "action:menu",
page_callback_prefix: str = "select_company_page",
page_callback_suffix: str = ""
) -> InlineKeyboardMarkup:
"""
Create paginated inline keyboard for company selection.
@@ -180,7 +183,10 @@ def create_company_selection_keyboard_paginated(
Args:
companies: Full list of company dicts (with id, nume_firma, cui)
page: Current page number (0-indexed)
per_page: Number of companies per page (default: 10)
per_page: Number of companies per page (default: 20)
back_callback: Callback data for the back button (default: "action:menu")
page_callback_prefix: Prefix for pagination callbacks (default: "select_company_page")
page_callback_suffix: Suffix appended after page number in pagination callbacks
Returns:
InlineKeyboardMarkup with company buttons and pagination controls
@@ -221,8 +227,9 @@ def create_company_selection_keyboard_paginated(
# Previous button
if page > 0:
prev_cb = f"{page_callback_prefix}:{page-1}{page_callback_suffix}"
nav_buttons.append(
InlineKeyboardButton("< Anterior", callback_data=f"select_company_page:{page-1}")
InlineKeyboardButton("< Anterior", callback_data=prev_cb)
)
# Page indicator (non-clickable)
@@ -232,20 +239,76 @@ def create_company_selection_keyboard_paginated(
# Next button
if page < total_pages - 1:
next_cb = f"{page_callback_prefix}:{page+1}{page_callback_suffix}"
nav_buttons.append(
InlineKeyboardButton("Urmator >", callback_data=f"select_company_page:{page+1}")
InlineKeyboardButton("Urmator >", callback_data=next_cb)
)
keyboard.append(nav_buttons)
# Back to menu button
# A-Z filter + back button
keyboard.append([
InlineKeyboardButton("< Inapoi la Meniu", callback_data="action:menu")
InlineKeyboardButton("Filtrare A-Z", callback_data="select_company_alpha_menu")
])
keyboard.append([
InlineKeyboardButton("« Înapoi", callback_data=back_callback)
])
return InlineKeyboardMarkup(keyboard)
def create_alpha_filter_keyboard() -> InlineKeyboardMarkup:
"""
Create inline keyboard with AZ letter buttons for filtering companies.
Displays 26 letter buttons in rows of 6, plus a 'Toată lista' button
that shows all companies without filtering.
Returns:
InlineKeyboardMarkup with letter buttons and navigation
"""
letters = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
keyboard = []
row_size = 6
for i in range(0, len(letters), row_size):
row = [
InlineKeyboardButton(l, callback_data=f"select_company_alpha:{l}")
for l in letters[i:i + row_size]
]
keyboard.append(row)
keyboard.append([
InlineKeyboardButton("Toată lista", callback_data="select_company_alpha:ALL"),
InlineKeyboardButton("« Meniu", callback_data="action:menu")
])
return InlineKeyboardMarkup(keyboard)
def create_alpha_filter_keyboard_partner(partner_type: str) -> InlineKeyboardMarkup:
"""
Create inline keyboard with AZ letter buttons for filtering clients or suppliers.
Args:
partner_type: "clients" or "suppliers"
Returns:
InlineKeyboardMarkup with letter buttons and navigation
"""
letters = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
keyboard = []
row_size = 6
for i in range(0, len(letters), row_size):
row = [
InlineKeyboardButton(l, callback_data=f"{partner_type}_alpha:{l}")
for l in letters[i:i + row_size]
]
keyboard.append(row)
keyboard.append([
InlineKeyboardButton("Toata lista", callback_data=f"{partner_type}_alpha:ALL"),
InlineKeyboardButton("« Meniu", callback_data="action:menu")
])
return InlineKeyboardMarkup(keyboard)
def format_company_context_footer(company_name: str) -> str:
"""
Format discrete footer with company context.