"""Add-supplier flow: name + one of the 8 fixed Persian categories (required).""" import logging from app import drafts as draft_store from app.api.client import ApiError from app.drafts import ( KIND_SUPPLIER, merge_supplier_patch, new_supplier_payload, supplier_missing, ) from app.keyboards import pick_buttons, simple_review_keyboard from app.resolve import safe_resolve from app.texts import ERR_GENERIC, esc, supplier_committed_report, supplier_review_text logger = logging.getLogger("bot.supplier") async def handle_entities(ctx, chat_id, user, patch: dict, source: str | None) -> None: draft = await draft_store.get_active(chat_id, KIND_SUPPLIER) if draft is not None: payload = draft.payload merge_supplier_patch(payload, patch) else: payload = new_supplier_payload() merge_supplier_patch(payload, patch) draft = await draft_store.create(chat_id, KIND_SUPPLIER, payload, source=source) await resolve_payload(ctx, payload) await draft_store.save_payload(draft, missing={"fields": supplier_missing(payload)}) await render(ctx, chat_id, draft, fresh=draft.review_message_id is None) async def resolve_payload(ctx, payload: dict) -> None: options = payload.setdefault("options", {}) if not payload.get("category_id") and payload.get("category_name"): res = await safe_resolve(ctx.resolver, "category", payload["category_name"]) if res.resolved: payload["category_id"] = res.candidates[0].id payload["category_name"] = res.candidates[0].name options.pop("cat", None) elif res.candidates: options["cat"] = [{"id": c.id, "name": c.name} for c in res.candidates] else: options.pop("cat", None) async def apply_pick(ctx, chat_id, user, draft, field: str, choice: dict) -> None: if field == "cat": draft.payload["category_id"] = choice["id"] draft.payload["category_name"] = choice["name"] draft.payload.setdefault("options", {}).pop("cat", None) await draft_store.save_payload(draft, missing={"fields": supplier_missing(draft.payload)}) await render(ctx, chat_id, draft, fresh=False) def _keyboard(payload: dict, draft_id: str) -> dict: rows: list[list[dict]] = [] options = (payload.get("options") or {}).get("cat") or [] if options: rows += pick_buttons(draft_id, "cat", [o["name"] for o in options[:6]]) return simple_review_keyboard(draft_id, KIND_SUPPLIER, rows) async def render(ctx, chat_id, draft, fresh: bool = True) -> None: payload = draft.payload missing = supplier_missing(payload) text = supplier_review_text(payload, missing) keyboard = _keyboard(payload, draft.id) if fresh: message = await ctx.send(chat_id, text, reply_markup=keyboard) draft.review_message_id = (message or {}).get("message_id") await draft_store.save_payload(draft, missing={"fields": missing}, review_message_id=draft.review_message_id) else: await ctx.edit(chat_id, draft.review_message_id, text, reply_markup=keyboard) await draft_store.save_payload(draft, missing={"fields": missing}) async def commit(ctx, chat_id, user, draft) -> None: payload = draft.payload await resolve_payload(ctx, payload) missing = {m["key"]: m["ok"] for m in supplier_missing(payload)} problems = [label for key, label, ok in [ ("name", "نام تأمین‌کننده", missing.get("name")), ("category", "دسته‌بندی", missing.get("category")), ] if not ok] if problems: await ctx.send(chat_id, "ثبت ممکن نیست؛ اول این‌ها را مشخص کن:\n" + "\n".join(f"❌ {esc(p)}" for p in problems)) return body = { "name": payload["name"], "category_id": payload["category_id"], "phone": payload.get("phone"), "location": payload.get("location"), "contact_person": payload.get("contact_person"), } body = {k: v for k, v in body.items() if v} try: created = await ctx.api.create_supplier(body, actor_id=user.actor_id) except ApiError as exc: await ctx.send(chat_id, ERR_GENERIC.format(detail=esc(exc.message))) return await draft_store.set_status(draft.id, "committed") ctx.resolver.invalidate("suppliers") await ctx.send(chat_id, supplier_committed_report(created))