پرش به مطلب اصلی

نوشتن یک قاعده کسب‌وکار

هدف​

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

پیش‌نیازها​

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

قاعده کسب‌وکار چیست و چه نیست​

قاعده کسب‌وکار در مرورگر و روی فرم اجرا می‌شود و رفتار فرم را تغییر می‌دهد. چهار کار می‌کند: نشان دادن یا پنهان کردن یک فیلد، فعال یا غیرفعال کردن آن، اجباری کردن یا نکردن آن، و تعیین یک مقدار.

اما تعیین نمی‌کند چه چیزی قابل ذخیره است. کاربر می‌تواند قاعده را خاموش کند، از صفحه دیگری استفاده کند یا مستقیم API را صدا بزند و رکورد باز هم ذخیره می‌شود. هر چیزی که باید درباره داده درست باشد به یک افزونه سمت سرور تعلق دارد که فارغ از رفتار مرورگر اجرا می‌شود. از قاعده کسب‌وکار برای خوشایند کردن فرم استفاده کنید و از افزونه سمت سرور برای واقعی کردن یک قانون. خواستن هر دو طبیعی است و عمداً جدا نوشته می‌شوند.

گام‌ها​

  1. فرمی را که قاعده برای آن است باز کنید — جدول، سپس فرم‌ها، سپس همان فرم — و در نوار ابزارش رویدادها را بزنید. فهرست، هر قاعده‌ای را که روی این فرم اجرا می‌شود نشان می‌دهد، از جمله قواعدی که به همه فرم‌های جدول بسته شده‌اند.

  2. جدید را بزنید تا طراح قاعده باز شود.

  3. نام نمایشی را بنویسید. نام منطقی خودکار و با پیشوند ناشر شما پر می‌شود و پس از ذخیره تغییرناپذیر است.

  4. فرم را وارسی کنید. از پیش همان فرمی است که از آن آمده‌اید و تقریباً همیشه درست است — قاعده دربارهٔ فیلدها حرف می‌زند و فیلدهایی که از آن‌ها حرف می‌زند همان‌هایی‌اند که پیش روی شماست. برای چیزی که باید هر جا جدول نشان داده می‌شود برقرار باشد — مثل «تا تأیید نشده پنهان بماند» — آن را به همه فرم‌ها تغییر دهید. قاعده‌ای که به همه فرم‌ها بسته شده باز هم در فهرست رویدادهای هر فرم، با همین نشانه، دیده می‌شود.

  5. زمان اجرا را انتخاب کنید — هر قاعده یک رویداد:

    • هنگام باز شدن فرم، قاعده را همزمان با نمایش رکورد اعمال می‌کند.
    • هنگام تغییر یک فیلد، انتخابگر فیلد را نشان می‌دهد. فیلدی را انتخاب کنید تا به شکل یک برچسب اضافه شود؛ هر تعداد که لازم است اضافه کنید و با ✕ روی هر برچسب حذفش کنید.
    • هنگام ذخیرهٔ فرم، قاعده را میان فشردن دکمه و نوشتن رکورد اجرا می‌کند؛ پس می‌تواند مقداری را پر کند — یا با cancelSave (پایین‌تر) جلوی ذخیره را بگیرد.

    قاعده‌ای بدون رویداد هرگز اجرا نمی‌شود، پس دکمه ذخیره تا وقتی قاعدهٔ تغییر فیلد دست‌کم یک فیلد نداشته باشد غیرفعال می‌ماند.

    یک رویداد برای هر قاعده عمدی است. وقتی یک کار باید در دو لحظه انجام شود — حالت رایج، مثل «این را وقتی وضعیت رد شده است نشان بده» که هم هنگام باز شدن فرم و هم با هر تغییر وضعیت باید درست باشد — دو قاعده بنویسید که یک اسکریپت راه‌حل را وارد می‌کنند، هرکدام دو سطر. منطق یک‌بار نوشته می‌شود؛ و آنجا که دو لحظه واقعاً فرق دارند، خودِ اسکریپت eventType() را می‌پرسد و تصمیم می‌گیرد. چند رویداد روی یک قاعده، این تصمیم را جایی نمی‌گذارد: هیچ‌چیز روی صفحه نمی‌گوید کدام نیمهٔ اسکریپت به کدام رویداد تعلق دارد.

  6. اسکریپت را در ویرایشگر بنویسید. هنگام تایپ اشتباه‌ها را زیرخط می‌کشد، توابع پلتفرم را تکمیل می‌کند و با باز کردن پرانتز، آرگومان‌های هر تابع را نشان می‌دهد. دکمهٔ چشم در گوشهٔ بالای ویرایشگر، توابع در دسترس اسکریپت را روی کد باز می‌کند.

  7. تیک فعال را نگه دارید، یا بردارید تا قاعده بماند ولی اجرا نشود.

  8. ذخیره را بزنید.

توابع در دسترس اسکریپت​

فراخوانیکاری که می‌کند
getValue(field)مقدار فعلی فیلد روی فرم.
setValue(field, value)مقدار یک فیلد را تعیین می‌کند.
setVisible(field, visible)فیلد را نشان می‌دهد یا پنهان می‌کند.
setDisabled(field, disabled)فیلد را فقط‌خواندنی می‌کند یا نمی‌کند.
setRequired(field, required)فیلد را اجباری می‌کند یا نمی‌کند.
eventType()"OnLoad"، "OnChange" یا "OnSave" — رویدادی که در حال اجراست.
changedField()فیلدی که تغییرش OnChange را اجرا کرده، وگرنه "".
isNewRecord()تا وقتی رکورد یک بار ذخیره نشده true است. برای قفل کردن فیلدی که یک بار انتخاب می‌شود و دیگر تغییر نمی‌کند، مثل نوع یک فعالیت.
cancelSave(message)فقط هنگام ذخیره: جلوی ذخیرهٔ همین فرم را می‌گیرد و پیام را نشان می‌دهد.
isEmpty(value)آیا مقدار پر نشده است. متن سفید و «هیچ» خالی‌اند؛ 0 و false مقادیری‌اند که کسی انتخاب کرده.

فیلد با نام منطقی (par_amount) نامیده می‌شود، نه با نام نمایشی.

فیلدی که چیزی در آن نیست، متنِ خالی خوانده می‌شود، پس getValue("par_currency") == "" همان بررسی «هنوز پر نشده» است — نمونهٔ واحد پول پایین‌تر دقیقاً همین‌طور کار می‌کند. برای عدد، تاریخ یا لوکاپ متن خالی‌ای برای مقایسه وجود ندارد؛ آنجا isEmpty(getValue("par_due")) را بپرسید. همان تعریفی از «خالی» را به کار می‌برد که بررسی اجباری‌بودنِ خودِ فرم — و به همین دلیل قاعده نمی‌تواند فیلدی را پیش‌فرض کند که فرم همین حالا آن را پرشده پذیرفته است.

getValue و setValue دقیقاً همان‌طور که در افزونه سمت سرور نوشته می‌شوند و کار می‌کنند اینجا هم هستند، تا منطقی که یک بار درمی‌آورید در هر دو طرف یکسان خوانده شود.

یک فیلد عددی به‌صورت عدد خوانده می‌شود — ۱۲۰۰٫۵، نه «۱۲۰۰٫۵» — حتی هنگام تایپ، و فیلد پرنشده همچنان خالی خوانده می‌شود. این نکته درست از لحظه‌ای اهمیت پیدا می‌کند که تابعی از خودتان بنویسید: func needsApproval(amount: number) متن را نمی‌پذیرد و خطا به‌جای آنکه دربارهٔ نوع‌ها باشد Function overload for needsApproval not found. است. پس مبلغ را number اعلام کنید، نه int — ستون Decimal مقدار ۱۲۰۰٫۵۰ را نگه می‌دارد و پارامتر عدد صحیح آن را رد می‌کند — و پیش از هر محاسبه‌ای برای جعبهٔ خالی صفر بگذارید:

func claimAmount(): number {
var raw = getValue("par_amount");
if (isEmpty(raw)) { return 0; }
return raw;
}

…و هرچه یک اسکریپت راه‌حل صادر کرده باشد. وقتی چند سطر یکسان در چند قانون پیدا شد، آن‌ها را به یک اسکریپت راه‌حل ببرید و با نوشتن import 'par_expense_helpers'; در بالای قاعده واردش کنید — ویرایشگر نام را تکمیل می‌کند و از آن پس می‌داند آن ماژول چه چیزی صادر کرده است.

گزینه‌ها، و نشان دادن یک بخش برای یکی از آن‌ها​

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

if (getValue("pw_type") == 110000001) { setVisible("pw_to", true); }

پیش از این، گزینه‌ای که تازه انتخاب شده بود به‌صورت متن ("110000001") خوانده می‌شد و مقایسهٔ بالا پس از اولین انتخاب بی‌صدا از کار می‌افتاد. قاعده‌ای که با متنِ داخل گیومه مقایسه می‌کرد باید گیومه‌ها را بردارد.

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

برای اینکه فیلدی فقط یک بار انتخاب شود، وقتی رکورد جدید نیست آن را غیرفعال کنید:

setDisabled("pw_type", !isNewRecord());

وقتی رکورد جدیدی ذخیره می‌شود، قاعده‌هایی که هنگام باز شدن اجرا می‌شوند دوباره اجرا می‌شوند، پس فیلد بلافاصله قفل می‌شود. این هم مثل هر قاعدهٔ دیگری فقط جلوی فرم را می‌گیرد. برای اینکه API یا ورود داده هم نتواند فیلد را تغییر دهد، یک مرحلهٔ افزونهٔ سمت سرور هم بنویسید.

جلوگیری از ذخیره​

قاعده‌ای که هنگام ذخیرهٔ فرم اجرا می‌شود می‌تواند جلوی ذخیره را بگیرد:

if (getValue("par_status") == "rejected" && getValue("par_reason") == "") {
cancelSave("پیش از رد کردن این درخواست، دلیلش را بنویسید.");
}

ذخیره متوقف می‌شود، پیام شما بالای فرم می‌آید و هیچ چیزی از دست نمی‌رود — فرم با هرچه تایپ کرده‌اید باز می‌ماند.

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

یک نمونه​

فیلد مدیر را فقط برای هزینه‌های بالای ۱۰۰ نشان بده و اجباری کن — هنگام باز شدن فرم و هر بار که مبلغ تغییر می‌کند:

var over = getValue("par_amount") > 100;
setVisible("par_manager", over);
setRequired("par_manager", over);

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

دو قاعده روی یک فرم​

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

هیچ قاعده‌ای نمی‌تواند بی‌پایان اجرا شود​

هر قاعده با یک بودجه اجرا می‌شود و قاعده‌ای که از آن بگذرد متوقف و به نام خودش گزارش می‌شود. سه حد وجود دارد و هرکدام اشتباه متفاوتی را می‌گیرد:

متوقف می‌کندوقتی
حلقه‌ای که تمام نمی‌شودwhile (true)، یا شرطی که هیچ‌گاه کاملاً برقرار نمی‌شود
قاعده‌ای که ساده‌تر بگوییم زیادی کار می‌کندبعد از نیم ثانیه هنوز در حال اجراست
تابعی که بی‌پایان خودش را صدا می‌زندصد فراخوانی عمیق شده و پایانی در کار نیست

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

به‌طور تصادفی به این حد نمی‌رسید: بزرگ‌ترین قاعده در نمونه‌ها کمتر از یک‌صدم سهمیه را مصرف می‌کند. اگر رسیدید، قاعده ایراد دارد — بیشتر اوقات while‌ای که بدنه‌اش شرط را تغییر نمی‌دهد.

نکته‌ای دربارهٔ مقایسهٔ مقادیر. == درون یک نوع مقایسه می‌کند: دو عدد، دو متن، دو مقدار درست/نادرست. دو نوع متفاوت هرگز برابر نیستند — 1 == "1" نادرست است — و «هیچ» با «هیچ» برابر است، پس فیلد پرنشده با "" برابر نیست. به همین دلیل فیلدی که مقداری ندارد متنِ خالی خوانده می‌شود و به همین دلیل isEmpty() برای عددها و تاریخ‌ها وجود دارد.

عیب‌یابی​

  • قاعده‌ای که انگار هرگز اجرا نمی‌شود. بررسی کنید فعال باشد، فرمی که به آن بسته شده همان فرمی باشد که می‌بینید، و رویدادش شامل فیلدی باشد که تغییر می‌دهید.
  • «BS Lang script is invalid: …» هنگام ذخیره — اسکریپت تجزیه نمی‌شود. ویرایشگر همان اشتباه را زیرخط می‌کشد و پیام شماره خط را می‌گوید.
  • «Form '…' was not found on '…'.» — قاعده به فرمی بسته شده که جدول ندارد. یکی از فهرست را انتخاب کنید یا به همه فرم‌ها ببندید.
  • پیام قرمز بالای فرم در برنامه با نام یک قاعده. قاعده هنگام اجرا خطا داده است. فرم به کار خود ادامه می‌دهد و قاعده در همان نقطه متوقف شده است.
  • زیرخط زیر getValue — ویرایشگر دیگر توابع خود پلتفرم را ناشناخته گزارش نمی‌کند. اگر چنین چیزی دیدید، اسکریپت چیزی را صدا می‌زند که در فهرست بالا نیست.

سناریوهای مرتبط​