Files
ERP/bot/app/keyboards.py
T

84 lines
3.1 KiB
Python

"""Inline keyboard builders.
Bale keeps Telegram's 64-byte ``callback_data`` cap, so every callback is a
short op-code plus the 8-char draft prefix; the full state lives in bot_drafts
(or the in-memory pending-flow map) and is looked up on tap.
"""
def _kb(rows: list[list[dict]]) -> dict:
return {"inline_keyboard": rows}
def _btn(text: str, data: str) -> dict:
return {"text": text, "callback_data": data}
# callback scheme (≤64 bytes):
# q:ok:{d8} / q:no:{d8} / q:ok2:{d8} quote commit / cancel / commit-resolved-only
# s:ok:{d8} / s:no:{d8} supplier
# m:ok:{d8} / m:no:{d8} material
# pk:{d8}:{field}:{idx} pick candidate for a draft field
# qc:{idx} / ac:{op} / ar:{op} pending-flow buttons (accept/arrive)
def draft_actions(prefix: str, kind: str, has_partial_option: bool = False) -> list[list[dict]]:
op = {"quote": "q", "supplier": "s", "material": "m", "project": "p"}.get(kind, "q")
rows = [[_btn("✅ ثبت نهایی", f"{op}:ok:{prefix}"), _btn("❌ انصراف", f"{op}:no:{prefix}")]]
if has_partial_option:
rows.insert(0, [_btn("✅ ثبت فقط اقلام مشخص", f"{op}:ok2:{prefix}")])
return rows
def pick_buttons(prefix: str, field: str, names: list[str]) -> list[list[dict]]:
return [[_btn(name[:60], f"pk:{prefix}:{field}:{i}")] for i, name in enumerate(names)]
def quote_review_keyboard(
prefix: str,
pick_rows: list[list[dict]],
has_partial_option: bool = False,
wizard_url: str | None = None,
) -> dict:
rows = list(pick_rows)
if wizard_url:
rows.append([{"text": "🖥 بازبینی و تکمیل در ویزارد", "url": wizard_url}])
rows += draft_actions(prefix, "quote", has_partial_option=has_partial_option)
return _kb(rows)
def simple_review_keyboard(prefix: str, kind: str, pick_rows: list[list[dict]]) -> dict:
rows = list(pick_rows)
rows += draft_actions(prefix, kind)
return _kb(rows)
def quote_pick_keyboard(pairs: list[tuple[str, str]]) -> dict:
"""Pick among candidate quotes: pairs of (label, quote_id)."""
return _kb([[_btn(label[:60], f"qc:{i}")] for i, (label, _) in enumerate(pairs)])
def accept_keyboard(termsheet_labels: list[str]) -> dict:
rows = [[_btn(f"شرایط: {label[:40]}", f"ac:ts:{i}")] for i, label in enumerate(termsheet_labels)]
rows.append([_btn("✅ تأیید پذیرش", "ac:ok"), _btn("❌ انصراف", "ac:no")])
return _kb(rows)
def arrive_keyboard() -> dict:
return _kb([
[_btn("📦 تحویل کامل همه اقلام", "ar:full")],
[_btn("✅ ثبت مقادیر اعلام‌شده", "ar:ok"), _btn("❌ انصراف", "ar:no")],
])
def cancel_keyboard() -> dict:
return _kb([[_btn("❌ انصراف", "ac:no")]])
def ambiguity_keyboard(prefix: str, amb_id: str) -> dict:
"""Inline buttons for ambiguity sub-message (≤64 bytes callback_data)."""
return _kb([
[_btn("✅ تأیید و اعمال در پیش‌نویس", f"amb:ok:{prefix}:{amb_id}")],
[_btn("❌ تایید نمی‌شود", f"amb:no:{prefix}:{amb_id}")],
])