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

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

PWA اپراتور CRM

کارکنان فروش و پشتیبانی با یک پنل ادمین دسکتاپ کار می‌کردند که فرضش این بود کاربر پشت میز نشسته است. اما کسی که واقعاً به آن نیاز داشت، ایستاده بود سر پیشخوان و روبه‌روی مشتری. از آن طرف، مشتری هم صفحه‌ی حسابی داشت که هیچ‌کدام از چیزهایی را که CRM درباره‌اش می‌دانست نشان نمی‌داد. حالا یک CRM ماژولار وردپرسی به هر دو طرف پیشخوان جواب می‌دهد: یک محیط کار اپراتور که برای پیشخوان ساخته شده، و یک هاب مشتری داخل ناحیه‌ی حساب کاربری WooCommerce.

مسئله تجاری

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

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

  • a2-crm-plugin؛ یک CRM ماژولار وردپرسی با تمرکز روی عملیات فروش حضوری، با صندوق ورودی اپراتور، جریان تخصیص، وضعیت خوانده‌نشده، تحویل کار به نفر بعد و دسترسی بر اساس نقش، تا هر پیگیری صاحب مشخصی داشته باشد نه اینکه مال همه باشد.
  • پروفایل مشتری که رفتار، سابقه‌ی گفت‌وگو، سفارش‌ها و وضعیت پیگیری را یک‌جا کنار هم می‌آورد، به‌اضافه‌ی گردش کار سرنخ، معامله و وظیفه برای پیگیری فروش و دید مدیریتی.
  • فرم سفارش حضوری با دراپ‌داون‌های پرداخت و منبع که از داخل خود مودال ویرایش می‌شوند، تا اضافه کردن یک روش پرداخت تازه کار توسعه‌دهنده نباشد؛ و امکان درج دستی محصول برای مواردی که کاتالوگ پوششان نمی‌دهد، که در فروشگاه جواهر بیشتر از چیزی که فکر کنید پیش می‌آید.
  • یک ماژول هاب مشتری که با شورت‌کد [customer_hub] رندر می‌شود و تب‌های داشبورد، سفارش‌ها، وفاداری، کیف پول، اخیراً دیده‌شده، پروفایل و آدرس‌ها را دارد؛ پشتش یک REST API زیر فضای نام customer-hub/v1 با مسیرهای خلاصه، سفارش‌ها، وفاداری، کیف پول و اخیراً دیده‌شده، به‌اضافه‌ی مسیرهای خواندن و نوشتن پروفایل و آدرس‌ها.
  • موتور امتیاز: هر سفارش پرداخت‌شده به‌ازای هر واحد مبلغ ثابت امتیاز می‌دهد و سطح‌ها — برنز، نقره، طلا و VIP — از امتیاز مادام‌العمر در آستانه‌های ۰، ۵۰۰، ۱۵۰۰ و ۵۰۰۰ تعیین می‌شوند. امتیاز و کیف پول هر کدام دفتر جداگانه دارند، به‌جای چپاندن موجودی توی متای کاربر. محصولات اخیراً دیده‌شده هم با سقف ۲۰ محصول برای هر مشتری و انقضای ۳۰ روزه ثبت می‌شوند.
  • داشبورد گزارش داخلی روی همان داده، تا عددی که مدیریت می‌بیند از چیزی بیاید که اپراتورها واقعاً ثبت کرده‌اند؛ در کنار لاگ ممیزی، خروجی CSV و مسیرهای پشتیبان‌گیری.
  • ماژول‌های آماده‌ی اتصال برای پیامک و اطلاعات تماس تلفنی، پشت آداپتورهای ارائه‌دهنده؛ پیکربندی در فایل config که در گیت نادیده گرفته می‌شود، و کلیدها ترجیحاً در متغیر محیطی یا ثابت‌های wp-config.

رویکرد فنی

  • ساختار ماژولار به‌جای یک فایل بزرگ افزونه. CRM مدام فیچر جمع می‌کند و فیچر تازه نباید مجبورت کند به کدی که کار می‌کند دست بزنی.
  • روی لایه‌ی دیتابیس و سیستم دسترسی خود وردپرس کار می‌کند و مدل احراز هویت موازی نمی‌آورد؛ کنترل دسترسی همان است که سایت از قبل دارد. هر جا هسته مدلی ندارد جدول اختصاصی هست، و هر جا دارد از هوک هسته استفاده می‌شود.
  • فرانت‌اند با جاوااسکریپت خالص. CRMای که سر پیشخوان و روی اینترنت بی‌ثبات استفاده می‌شود جای بار یک فریم‌ورک نیست.
  • مقادیر دراپ‌داون به‌شکل داده ذخیره می‌شوند، نه تعریف‌شده در کد؛ همین است که تغییرات عادی عملیاتی را از مسیر دیپلوی بیرون نگه می‌دارد.
  • امتیاز روی woocommerce_order_status_changed اعمال می‌شود، وقتی سفارش به یکی از وضعیت‌های پرداخت‌شده برسد؛ و روی لغو، بازپرداخت، ناموفق یا حذف، خودش برمی‌گردد. هر نوشتن امتیاز از یک بررسی idempotency رد می‌شود (a2_ch_points_entry_exists) تا تغییر وضعیتِ بازپخش‌شده نتواند دوبار به مشتری امتیاز بدهد.
  • بازدید محصول روی template_redirect و فقط برای کاربر واردشده ثبت می‌شود، و یک روال پاک‌سازی مرتب هرسش می‌کند تا جدول بی‌حدومرز بزرگ نشود.
  • تب‌های هاب پیکربندی‌اند و در یک آپشن ذخیره می‌شوند. تیکت، دانلود و لیست علاقه‌مندی را از فهرست برداشتم چون مسیر REST‌شان هنوز ساخته نشده بود؛ تب همیشه خالی بدتر از تب نداشته است.
  • گزارش‌های مدیریتی را از صفحه‌های روزمره‌ی اپراتور جدا کردم تا هر گروه چیزی را که لازم دارد ببیند بدون اینکه کار دیگری را شلوغ کند؛ ممیزی و خروجی‌گیری هم اضافه شد چون یک ابزار داخلی مدت‌ها بعد از تحویل هم باید قابل توضیح بماند.
  • هیچ کلید و رمزی وارد مخزن نمی‌شود: نمونه‌ی config کامیت می‌شود و نسخه‌ی واقعی نادیده گرفته می‌شود.

نتیجه و شواهد

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

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

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

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

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

خلاصه_اجرایی {
  پروژه: "CRM Operator PWA"
  افزونه: "a2-crm-plugin، CRM ماژولار وردپرسی"
  پشته: "PHP (وردپرس + WooCommerce)، جاوااسکریپت خالص، MySQL"
  تمرکز: "عملیات فروشگاه حضوری، سر پیشخوان"
  سمت_اپراتور: "صندوق ورودی، تخصیص، وضعیت خوانده‌نشده، پروفایل مشتری،
                گردش‌کار سرنخ/معامله/وظیفه، فرم سفارش حضوری،
                درج دستی محصول، گزارش، لاگ ممیزی"
  پیکربندی_اپراتور: "دراپ‌داون پرداخت و منبع از داخل مودال
                     قابل ویرایش، ذخیره‌شده به‌شکل داده"
  هاب_مشتری: "شورت‌کد [customer_hub]؛ customer-hub/v1 ← خلاصه،
              سفارش‌ها، وفاداری، کیف پول، اخیراً دیده‌شده،
              پروفایل، آدرس‌ها"
  وفاداری: "سطح برنز/نقره/طلا/VIP در ۰/۵۰۰/۱۵۰۰/۵۰۰۰ امتیاز؛
            دفتر جداگانه برای امتیاز و کیف پول"
  هوک‌ها: "woocommerce_order_status_changed ← اعمال/برگشت امتیاز
           template_redirect ← ثبت بازدید"
  احراز_هویت: "دسترسی‌های وردپرس؛ بدون مدل موازی"
  رازها: "config.php در گیت نادیده؛ محیط یا wp-config"
  وضعیت: "روی پروداکشن و در حالت نگهداری؛ بدون اندازه‌گیری
          رسمی قبل و بعد"
}

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

افزونه‌ای که در حالت نگهداری است و هنوز استفاده‌ی روزانه شکلش می‌دهد، بیشتر از هر فهرست فیچری حرف می‌زند. این همان جور سیستم داخلی است که به کار درآمدزا نزدیک است: نه چند صفحه و داشبورد، بلکه ابزاری که تیم فروش و پشتیبانی هر روز بازش می‌کنند.

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