Amirali Yaghoutiمهندس ارشد نرم‌افزار

مطالعه موردی مهندسی

بات مدیریت و گزارش شبانهٔ مالک

مالک یک فروشگاه نباید عددهای روزش را از شش گروه و دو داشبورد جمع کند. برای یک فروشگاه ساعت و جواهر، لایهٔ مدیریت را یک‌پارچه ساختم: یک دستیار Telegram که کارت سفارش‌ها را زنده نگه می‌دارد و به سؤال مالی جواب می‌دهد، هر شب یک گزارش، و یک PWA که همان عددها را روی گوشی نشان می‌دهد، حتی بدون اینترنت.

مسئله تجاری

مالک، کسب‌وکارش را تکه‌تکه می‌گرفت: اعلان سفارش در یک گروه، کارت مدیر عصرها، دستیار فروش هوشمند که یادداشت روزانهٔ خودش را می‌فرستاد، و گزارش کار کارکنان جایی دیگر. هر ارسال زمان‌بندی خودش و کوئری خودش را داشت؛ یک سؤال، بسته به اینکه کجا پرسیده می‌شد، می‌توانست جواب متفاوتی بگیرد.

زیر همهٔ این‌ها، خود عددها یک نقص بی‌صدا داشتند. بیکنِ رویدادهای اختصاصی سایت از سه گیت مستقل عبور می‌کرد و سقف پیش‌فرض سه رویداد برای هر بازدیدکننده در هر پنج دقیقه بود. بیکن حتی وقتی رویداد دور ریخته می‌شد جواب «موفق» می‌داد؛ پس هیچ داشبوردی چیزی غیرعادی نشان نداد، در حالی که یک ماه تمام ضربه‌های تماس و شبکه‌های اجتماعی دور ریخته می‌شدند.

آنچه تحویل دادم

  • یک بات دستیار Telegram که هر سفارش پرداخت‌شده را به یک کارت زنده با تصویر محصول و تاریخ شمسی تبدیل می‌کند و با هر تغییر سفارش همان پیام را در جا ویرایش می‌کند: وضعیت، تعویض محصول، اصلاح قیمت، پرداخت الباقی، تفکیک تخفیف. بدون سیل پیام‌های پاسخ.
  • یک منوی مدیریتی روی همان بات: فروش امروز، هفته، ماه و سال؛ انتخاب ماه شمسی با سهم هر درگاه؛ گزارش‌های مدیریتی (نمای کلی، روند، میانگین سبد، نرخ رهاشدن، محصولات برتر، استان‌ها، موفقیت درگاه‌ها)؛ خروجی CSV؛ جست‌وجوی سفارش؛ کارت مشتری از CRM؛ و یک کارت مالی که به سؤال کمیسیون جواب می‌دهد.
  • یک گزارش چندبخشی برای مالک، درست پیش از نیمه‌شب: پنل امروز، کارت اپراتور CRM، اقدام‌های شیفت و صف سرنخ‌ها، عملیات، بات‌ها با خلاصهٔ دستیار فروش، و عملکرد تیم. این گزارش جای ارسال‌های پراکندهٔ قدیمی را گرفت: کارت عصرگاهی گروه غیرفعال شد، پست روزانهٔ خودِ دستیار فروش خاموش شد، و گروه کاری حالا فقط گزارش کارکنان را جمع می‌کند و نمره می‌دهد.
  • یک PWA نصب‌شدنی برای مالک با هشت تب (امروز، فروش، محصولات، مشتریان و باشگاه، ترافیک، عملیات، سلامت سایت، کارکنان) به‌علاوهٔ کارت‌های حال‌وهوای مشتری، موجودی ویترین در برابر انبار شرکت، الگوهای پیامک و سلامت بات‌ها؛ همه روی بازه‌های شمسی و با نمودار. بدون اینترنت، آخرین عددها را زیر یک نوار «قدیمی» نشان می‌دهد.
  • ثبت رویداد اختصاصی: جدول رویداد خودِ فروشگاه (بازدید صفحه، نمایش و ارسال پاپ‌آپ، ضربه‌های تماس و شبکه‌های اجتماعی، سبد، پرداخت، خرید) با ستون‌های UTM که روزانه برای داشبورد جمع‌بندی می‌شود. رویدادهای قصد حالا سطل محدودیت خودشان را دارند.
  • یک حلقهٔ «DNA مشتری» از دستیار فروش هوشمند: هر گفت‌وگو به یک پروفایل رفتاری برای هر نفر تبدیل می‌شود، روزانه به مخاطبان CRM همگام می‌شود، کارت اپراتور و تب بات‌های PWA آن را می‌خوانند، و فروشِ پس از گفت‌وگو با بات به آن نسبت داده می‌شود. تب بات‌ها همگام‌سازی قدیمی‌تر از ۴۸ ساعت را علامت می‌زند.

رویکرد فنی

  • بات هر جا که Telegram در دسترس باشد زندگی می‌کند و فروشگاه را صرفاً یک منبع داده روی REST می‌بیند: API ووکامرس به‌علاوهٔ دو namespace اختصاصی، هدر توکن و فهرست مجاز IP. در همان ماه، کلید SSH روتِ سرور بات به سایت را باطل کردم؛ یک بات گزارش‌گیر دلیلی ندارد چنین کلیدی داشته باشد.
  • PWA سریع است چون اجازهٔ کمتری دارد. درخواست‌های پنل با افزونه‌های غیرفعال اجرا می‌شوند و کف زمان از ۱٫۸ ثانیه به ۱٫۰ ثانیه رسید؛ هر تب برای هر بازه سی دقیقه کش می‌شود و یک کرون پانزده‌دقیقه‌ای بازهٔ پیش‌فرض را گرم نگه می‌دارد. شمارش محصول به تفکیک برند یک JOIN داشت که برای فروشگاهی با ۲۵ هزار محصول ۱۹۳ هزار ردیف برمی‌گرداند؛ یک sub-select آن را از ۹٫۸ ثانیه به ۱٫۹ ثانیه رساند. بازه‌های بلندتر از ۴۵ روز به‌جای رویدادهای خام از یک جدول جمع‌بندی روزانه می‌خوانند.
  • تاریخ جایی است که این سایت گاز می‌گیرد. wp_date اینجا شمسی برمی‌گرداند و این دو بار بازنویسی هزینه داشت تا برای پنل یک کمکی تاریخِ SQL بدون بومی‌سازی نوشتم؛ جدول رویداد UTC است در حالی که همهٔ جدول‌های دیگر به وقت تهران‌اند؛ و بات زمان محلی را از یک منبع بیرونی می‌گیرد تا کار شبانه حتی وقتی ساعت میزبان جابه‌جا شده درست اجرا شود.
  • اصلاح محدودیت «سقف را بالا ببر» نبود. رویدادهای قصد سطل خودشان را گرفتند: چهل در هر پنج دقیقه؛ ضربه‌های صفحهٔ لینک همان سهمیه را با کلید کوکی بازدیدکننده می‌گیرند تا یک NAT کامل اپراتور موبایل در یک سطل شریک نشود. بازدید صفحه هم از نمونهٔ ده‌درصدی به ثبت کامل رسید، با سهمیهٔ خودش: سی در هر پنج دقیقه.
  • زمان‌بند وظایف Windows درس‌های خودش را داد. وظیفه‌ها با کاربر SYSTEM و بدون python در PATH اجرا می‌شوند؛ پس یک فایل bat که python را خالی صدا می‌زند هر بار شکست می‌خورد ولی با دوبار کلیک کار می‌کند. همگام‌سازی DNA هم چهار روز مُرد چون وظیفه‌اش به ورود تعاملی نیاز داشت و هیچ‌چیز خبر نداد. عقب‌ماندگی جبران شد و PWA حالا هر همگام‌سازی قدیمی‌تر از ۴۸ ساعت را علامت می‌زند.

نتیجه و شواهد

نتیجه‌ای که برایم مهم است، هم‌خوانی است. جمع یک ماه در PWA با صفحهٔ کمیسیون تطبیق داده شد و کارت مالی بات همان عدد را می‌دهد؛ پس مالک چه از صفحه بپرسد، چه از اپ، چه از بات، یک جواب می‌گیرد. باگ محدودیت بخش صادقانهٔ ماجراست: ضربه‌های تماس حدود ده برابر افت کرده بود در حالی که بازدید چهل درصد پایین آمده بود، و هر روند قصد در آن ماه تا ده برابر کم است. دیده نشد چون بیکن «موفق» گزارش می‌داد؛ با یک سطل اختصاصی اصلاح شد و آن بازه علامت خورده تا کسی روی آن روند نگیرد. و ارسال‌های پراکنده رفته‌اند: مالک حالا هر شب یک گزارش می‌گیرد و پیام‌های مدیر قدیمی بسته شده‌اند.

اهمیت برای کارفرما

مالکی که مجبور است سه منبع را با هم تطبیق دهد، خواندن هر سه را کنار می‌گذارد. یک گزارش در شب، اپی روی گوشی که بدون اتصال هم عدد نشان می‌دهد، و باتی که به سؤال مالی همان عدد صفحهٔ کمیسیون را می‌دهد؛ این چیزی است که باعث می‌شود عددها واقعاً استفاده شوند. درس محدودیت هم به هر تحلیل اختصاصی منتقل می‌شود: بیکنی که «موفق» می‌گوید و رویداد را دور می‌ریزد از نداشتن بیکن بدتر است، چون دلیل بررسی کردن را از بین می‌برد.

خلاصه-اجرایی-پروژه

خلاصه اجرایی خوانا

خلاصه_اجرایی {
  پروژه: "بات مدیریت و گزارش شبانهٔ مالک"
  کارفرما: "یک فروشگاه ساعت و جواهر"
  بات: "python-telegram-bot؛ REST ووکامرس + دو namespace اختصاصی،
        هدر توکن، فهرست مجاز IP؛ SQLite نگاشت سفارش <-> پیام کارت؛
        کپشن‌ها در جا ویرایش می‌شوند"
  گزارش: "یک ارسال چندبخشی درست پیش از نیمه‌شب: امروز،
          کارت اپراتور CRM، اقدام‌های شیفت + صف سرنخ، عملیات،
          بات‌ها (خلاصهٔ دستیار فروش)، عملکرد تیم"
  PWA: "هشت تب، بازه‌های شمسی، Chart.js؛ کش ۳۰ دقیقه‌ای هر تب،
        کرون گرم‌کنندهٔ ۱۵ دقیقه‌ای؛ آفلاین = آخرین عددها + نوار قدیمی"
  رویدادها: "جدول اختصاصی، UTC، ستون‌های UTM؛ سه گیت محدودیت؛
            سطل قصد ۴۰ در ۵ دقیقه، بازید صفحه ۳۰ در ۵ دقیقه"
  DNA: "گفت‌وگو -> پروفایل هر نفر -> همگام‌سازی روزانه -> مخاطب CRM؛
        PWA همگام‌سازی قدیمی‌تر از ۴۸ ساعت را علامت می‌زند"
  درس: "بیکنی که «موفق» جواب می‌دهد و رویداد را دور می‌ریزد،
        یک ماه ضربهٔ قصد را پنهان کرد"
}

ارزش حرفه‌ای این پروژه

باگ محدودیت همان چیزی است که دوست دارم بازبین بخواند. هیچ‌چیز خراب نبود، هر درخواست «موفق» برمی‌گشت، و داشبوردها یک ماه با اطمینان اشتباه بودند. اصلاحش به شکل یک سطل جدا، و علامت زدن آن بازه به‌جای پر کردن بی‌صدایش، فرق بین تحلیلی است که می‌شود به آن اعتماد کرد و تحلیلی که فقط خوب به نظر می‌رسد.

جایگزین کردن چهار ارسال با یک گزارش شبیه نظافت به نظر می‌رسد؛ در واقع یک تصمیم داده‌ای است. وقتی گزارش مالک، اپ و بات از یک عدد می‌خوانند، ناهم‌خوانی می‌شود باگی که باید درست شود، نه بحثی سر اینکه کدام گروه را باور کنیم.