درس ~6 دقیقه

جدا کردن فلوی پروفایل از فلوی رویدادی

چرا ویژگی‌های پایدارِ شخص را در یک فلوی مستقلِ تکرارپذیر جمع‌آوری کنیم و تصمیم‌های وابسته به رویداد را در فلوی جداگانه.

تفاوت دو نوع داده

هر چیزی که از کاربر می‌پرسیم در یکی از دو دستهٔ زیر می‌گنجد:

  • دادهٔ پایدارِ شخص: ویژگی‌هایی که به خود فرد چسبیده‌اند و کم تغییر می‌کنند — مثل «طلبه است؟»، «همکار مدرسه است؟»، «شغل»، «مدرک تحصیلی». اینها مستقل از سال تحصیلی و رویدادهای جاری‌اند.
  • تصمیم وابسته به رویداد: مقادیری که فقط در زمینهٔ یک رویداد خاص معنی می‌دهند — مثل «تخفیف امسال»، «ثبت‌نام در سال ۱۴۰۵»، «حضور در اردوی تابستان».
خلط این دو، باگ‌های پنهانی می‌سازد: اگر «طلبه است؟» را در یک کالکشن رویدادی ذخیره کنیم، در سال بعد دوباره از کاربر پرسیده می‌شود، چون هیچ ردیفی برای سال جدید وجود ندارد.

محل ذخیرهٔ درست

دادهٔ پایدار را روی کالکشنِ خودِ شخص (مثل «اشخاص» / persons) در یک فیلد اختصاصی ذخیره می‌کنیم. تصمیم‌های رویدادی را در کالکشن مخصوص رویداد (مثل «ثبت‌نام‌ها» / enrollments) با ارجاع به سال یا رویداد.

الگوی دو فلوی مستقل

  1. فلوی پروفایل (تکرارپذیر، بدون skipIfSet): کاربر هر زمان می‌تواند پروفایل خود را به‌روز کند. سؤال‌ها هر بار پرسیده می‌شوند تا اجازهٔ ویرایش بدهند. خروجی فقط روی کالکشن شخص می‌نشیند.
  2. فلوی رویدادی (با skipIfSet=true): همان سؤال‌ها را در صورت نیاز می‌پرسد ولی اگر مقدار قبلاً از طریق فلوی پروفایل (یا اجرای قبلی همین فلو) ذخیره شده، رد می‌شود و به منطق ساخت رکورد رویداد می‌رود.
نیازی نیست فلوی رویدادی صریحاً «call_flow» به فلوی پروفایل بزند. کافی است سؤال‌ها در هر دو فلو روی همان فیلدِ کالکشنِ شخص ذخیره کنند؛ skipIfSet خودش از تکرار جلوگیری می‌کند و وابستگی متقابل بین دو فلو ساخته نمی‌شود.

مثال واقعی: تخفیف والدین

در بازوی چمرانی‌ها، فلوی «به‌روزرسانی اطلاعات والدین» (code=40) دو فیلد is_seminarian و is_school_collaborator را برای پدر و مادر روی کالکشن «اشخاص» می‌نویسد. فلوی «ثبت‌نام و تخفیف فرزندان» (code=36) در زمان ثبت‌نام دیگر سؤالی نمی‌پرسد و رکورد جانبی هم نمی‌سازد؛ هنگام نمایش پیام خلاصهٔ ثبت‌نام خانواده، با خواندن همین پرچم‌ها به‌علاوهٔ تعداد فرزندان ثبت‌نامی و طرح تقسیط خانواده، درصد تخفیف را محاسبه و از کل شهریه کسر می‌کند.

نکات داخلی برای توسعه‌دهندگان

وقتی سؤالی روی رکورد شخص دیگری (نه خود bot_user) می‌نویسد، فیلد recordIdVar را به متغیری مانند fathers.0.id یا mothers.0.id ست کنید. موتور فلو در این حالت:

  • skipIfSet مقدار را از همان رکورد هدف می‌خواند (نه از رکورد bot_user) — برای فلوهای multi-person حیاتی است.
  • نوشتنِ مقدار، کش ctx.vars.user[slug] را فقط زمانی به‌روز می‌کند که هدف، رکورد خودِ bot_user باشد — تا داده‌های یک والد روی متغیرهای والد دیگر سرریز نکند.

ارجاع: recipe «جدا کردن فلوی پروفایل از فلوی رویدادی» در راهنمای نود «پرسش».